1 package SocialSteeringsBeta;
2
3 import SteeringProperties.SteeringProperties;
4 import SteeringStuff.RefBoolean;
5 import SteeringStuff.SteeringTools;
6 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
7 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
8 import java.util.ArrayList;
9 import javax.vecmath.Tuple3d;
10 import javax.vecmath.Vector3d;
11
12
13
14
15
16 public class TriangleSteer implements ISocialSteering {
17
18 protected UT2004Bot botself;
19 protected TriangleSteeringProperties properties;
20 private static final int KDefaultAttraction = 600;
21 private static final double K90deg = 90;
22 private static final double K360deg = 360;
23 private static final double K180deg = 180;
24 private static final double KMinimalDistance = 40;
25 private static final String KTowards = "towards";
26
27 public TriangleSteer(UT2004Bot botself) {
28 this.botself = botself;
29
30 }
31
32 @Override
33 public Vector3d run(Vector3d scaledActualVelocity, RefBoolean wantsToGoFaster, RefBoolean wantsToStop, RefLocation focus) {
34
35 if (properties == null) {
36 if (SOC_STEER_LOG.DEBUG) {
37 SOC_STEER_LOG.AddLogLineWithDate("no properties", "triangleError");
38
39 }
40 }
41
42 Location newFocus = getFocus();
43 if (newFocus != null) {
44 focus.data = newFocus;
45 }
46
47
48
49 Location targetLocation = WhereToGo(botself, properties);
50
51
52 SteeringResult nextVelocity = new SteeringResult(new Vector3d(0, 0, 0), 1);
53
54
55 if (targetLocation != null) {
56
57
58
59 targetLocation = new Location(targetLocation.x,targetLocation.y, botself.getLocation().z);
60 Vector3d vectorToTarget = targetLocation.sub(botself.getLocation()).asVector3d();
61
62 double distFromTarget = vectorToTarget.length();
63 nextVelocity.setMult(distFromTarget / 100);
64 if (distFromTarget < KMinimalDistance) {
65 wantsToStop.setValue(true);
66 return new SteeringResult(new Vector3d(0, 0, 0), 1);
67 }
68
69 double attractiveForce = KDefaultAttraction;/
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 private Location WhereToGo(UT2004Bot me, TriangleSteeringProperties propers) {
110 UT2004Bot first = propers.getFstBot();
111 UT2004Bot second = propers.getSndBot();
112
113
114
115
116 if (SOC_STEER_LOG.DEBUG) {
117 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + " " + me.getLocation().toString() + " --------------------------------------------", "triangle");
118 if (propers == null) {
119 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + "I have no properties!!!", "triangleError");
120 }
121 }
122
123
124 ArrayList<Location> edgePoints = new ArrayList<Location>();
125 Location S1 = first.getLocation();
126 Location S2 = second.getLocation();
127 int r1min = propers.getFstDistance().getMin();
128 int r1max = propers.getFstDistance().getMax();
129 int r2min = propers.getSndDistance().getMin();
130 int r2max = propers.getSndDistance().getMax();
131
132
133
134 if (isSuitable(me.getLocation(), S1, S2, propers, 0)) {
135 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + "is in suitable place.", "triangle");
136 return me.getLocation();
137 }
138
139 double othersDistance = S1.getDistance2D(S2);
140 if (r1max + r2max < othersDistance) {
141 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + "see: " + first.getName() + "to far from: " + second.getName(), "triangle");
142 float factor = (float) r1max / (float) (r1max + r2max);
143 return S1.add((S2.sub(S1)).scale(factor));
144 }
145
146
147
148
149 double r3min = 0;
150 double r3max = 0;
151 for (int i = 0; i < 2; i++) {
152
153 if (SOC_STEER_LOG.DEBUG) {
154 if (propers == null) {
155 SOC_STEER_LOG.AddLogLine("nemam TP pro TS", SOC_STEER_LOG.KError);
156 }
157 if (propers.getAngle() == null) {
158 SOC_STEER_LOG.AddLogLine("nemam uhel v TP", SOC_STEER_LOG.KError);
159 }
160 }
161 double angle = i == 0 ? propers.getAngle().getMin() : propers.getAngle().getMax();
162 double gamma = angle < K90deg ? 2 * angle : K360deg - 2 * angle;
163 double alpha = (K180deg - gamma) / 2;
164 double s = S1.getDistance2D(S2);
165 double alphaRad = SteeringTools.degreesToRadians(alpha);
166 double cosAlpha = Math.cos(alphaRad);
167 double b = s / (2 * cosAlpha);
168 if (i == 0) {
169 r3min = b;
170 } else {
171 r3max = b;
172 }
173 }
174
175
176
177 Location S3max1 = null;
178 Location S3min1 = null;
179 Location S3max2 = null;
180 Location S3min2 = null;
181 Location[] tmp;
182
183 tmp = SteeringTools.commonPoints(S2, r3max, S1, r3max);
184 if (tmp[0] != null) {
185 S3max1 = tmp[0];
186 }
187 if (tmp[1] != null) {
188 S3max2 = tmp[1];
189 }
190 tmp = SteeringTools.commonPoints(S2, r3min, S1, r3min);
191 if (tmp[0] != null) {
192 S3min1 = tmp[0];
193 }
194 if (tmp[1] != null) {
195 S3min2 = tmp[1];
196 }
197
198
199
200 int edgeSize = edgePoints.size();
201
202 tmp = SteeringTools.commonPoints(S1, r1min, S2, r2min);
203 if (tmp[0] != null) {
204 edgePoints.add(tmp[0]);
205 }
206 if (tmp[1] != null) {
207 edgePoints.add(tmp[1]);
208 }
209
210 tmp = SteeringTools.commonPoints(S1, r1max, S2, r2min);
211 if (tmp[0] != null) {
212 edgePoints.add(tmp[0]);
213 }
214 if (tmp[1] != null) {
215 edgePoints.add(tmp[1]);
216 }
217
218 tmp = SteeringTools.commonPoints(S1, r1max, S2, r2max);
219 if (tmp[0] != null) {
220 edgePoints.add(tmp[0]);
221 }
222 if (tmp[1] != null) {
223 edgePoints.add(tmp[1]);
224 }
225
226 tmp = SteeringTools.commonPoints(S1, r1min, S2, r2max);
227 if (tmp[0] != null) {
228 edgePoints.add(tmp[0]);
229 }
230 if (tmp[1] != null) {
231 edgePoints.add(tmp[1]);
232 }
233
234 if (SOC_STEER_LOG.DEBUG) {
235 if (edgeSize == edgePoints.size()) {
236 SOC_STEER_LOG.AddLogLine(me.getName() + " no distance-circles cross", "triangle");
237 SOC_STEER_LOG.AddLogLine("- S1: " + S1 + " S2: " + S2 + " r1: " + r1min + "-" + r1max + " r2: " + r2min + "-" + r2max, "triangle");
238 }
239 }
240 edgeSize = edgePoints.size();
241
242
243
244
245
246 if (S3min1 != null) {
247 tmp = SteeringTools.commonPoints(S3min1, r3min, S2, r2max);
248 if (tmp[0] != null) {
249 edgePoints.add(tmp[0]);
250 }
251 if (tmp[1] != null) {
252 edgePoints.add(tmp[1]);
253 }
254
255 tmp = SteeringTools.commonPoints(S3min1, r3min, S2, r2min);
256 if (tmp[0] != null) {
257 edgePoints.add(tmp[0]);
258 }
259 if (tmp[1] != null) {
260 edgePoints.add(tmp[1]);
261 }
262
263 tmp = SteeringTools.commonPoints(S3min1, r3min, S1, r1min);
264 if (tmp[0] != null) {
265 edgePoints.add(tmp[0]);
266 }
267 if (tmp[1] != null) {
268 edgePoints.add(tmp[1]);
269 }
270
271 tmp = SteeringTools.commonPoints(S3min1, r3min, S1, r1max);
272 if (tmp[0] != null) {
273 edgePoints.add(tmp[0]);
274 }
275 if (tmp[1] != null) {
276 edgePoints.add(tmp[1]);
277 }
278
279 if (SOC_STEER_LOG.DEBUG) {
280 if (edgeSize == edgePoints.size()) {
281 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3min1 cross", "triangle");
282 SOC_STEER_LOG.AddLogLine("- S3min1: " + S3min1 + " r3min: " + r3min + " r1: " + r1min + "-" + r1max + " r2: " + r2min + "-" + r2max, "triangle");
283 }
284 }
285 edgeSize = edgePoints.size();
286
287 } else {
288
289 if (SOC_STEER_LOG.DEBUG) {
290 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3min1", "triangle");
291 }
292 }
293
294
295
296
297 if (S3max1 != null) {
298 tmp = SteeringTools.commonPoints(S3max1, r3max, S2, r2max);
299 if (tmp[0] != null) {
300 edgePoints.add(tmp[0]);
301 }
302 if (tmp[1] != null) {
303 edgePoints.add(tmp[1]);
304 }
305
306 tmp = SteeringTools.commonPoints(S3max1, r3max, S2, r2min);
307 if (tmp[0] != null) {
308 edgePoints.add(tmp[0]);
309 }
310 if (tmp[1] != null) {
311 edgePoints.add(tmp[1]);
312 }
313
314 tmp = SteeringTools.commonPoints(S3max1, r3max, S1, r1min);
315 if (tmp[0] != null) {
316 edgePoints.add(tmp[0]);
317 }
318 if (tmp[1] != null) {
319 edgePoints.add(tmp[1]);
320 }
321
322 tmp = SteeringTools.commonPoints(S3max1, r3max, S1, r1max);
323 if (tmp[0] != null) {
324 edgePoints.add(tmp[0]);
325 }
326 if (tmp[1] != null) {
327 edgePoints.add(tmp[1]);
328 }
329
330 if (SOC_STEER_LOG.DEBUG) {
331 if (edgeSize == edgePoints.size()) {
332 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3max1 cross", "triangle");
333 SOC_STEER_LOG.AddLogLine("- S3max1: " + S3max1 + " r3max: " + r3max + " r1: " + r1min + "-" + r1max + " r2: " + r2min + "-" + r2max, "triangle");
334 }
335 }
336 edgeSize = edgePoints.size();
337
338 } else {
339
340 if (SOC_STEER_LOG.DEBUG) {
341 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3max1", "triangle");
342 }
343 }
344
345
346
347
348 if (S3min2 != null) {
349 tmp = SteeringTools.commonPoints(S3min2, r3min, S2, r2max);
350 if (tmp[0] != null) {
351 edgePoints.add(tmp[0]);
352 }
353 if (tmp[1] != null) {
354 edgePoints.add(tmp[1]);
355 }
356
357 tmp = SteeringTools.commonPoints(S3min2, r3min, S2, r2min);
358 if (tmp[0] != null) {
359 edgePoints.add(tmp[0]);
360 }
361 if (tmp[1] != null) {
362 edgePoints.add(tmp[1]);
363 }
364
365 tmp = SteeringTools.commonPoints(S3min2, r3min, S1, r1min);
366 if (tmp[0] != null) {
367 edgePoints.add(tmp[0]);
368 }
369 if (tmp[1] != null) {
370 edgePoints.add(tmp[1]);
371 }
372
373 tmp = SteeringTools.commonPoints(S3min2, r3min, S1, r1max);
374 if (tmp[0] != null) {
375 edgePoints.add(tmp[0]);
376 }
377 if (tmp[1] != null) {
378 edgePoints.add(tmp[1]);
379 }
380
381 if (SOC_STEER_LOG.DEBUG) {
382 if (edgeSize == edgePoints.size()) {
383 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3min2 cross", "triangle");
384 SOC_STEER_LOG.AddLogLine("- S3min2: " + S3min2 + " r3min: " + r3min + " r1: " + r1min + "-" + r1max + " r2: " + r2min + "-" + r2max, "triangle");
385 }
386 }
387 edgeSize = edgePoints.size();
388
389 } else {
390
391 if (SOC_STEER_LOG.DEBUG) {
392 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3min2", "triangle");
393 }
394 }
395
396
397
398
399 if (S3max2 != null) {
400 tmp = SteeringTools.commonPoints(S3max2, r3max, S2, r2max);
401 if (tmp[0] != null) {
402 edgePoints.add(tmp[0]);
403 }
404 if (tmp[1] != null) {
405 edgePoints.add(tmp[1]);
406 }
407
408 tmp = SteeringTools.commonPoints(S3max2, r3max, S2, r2min);
409 if (tmp[0] != null) {
410 edgePoints.add(tmp[0]);
411 }
412 if (tmp[1] != null) {
413 edgePoints.add(tmp[1]);
414 }
415
416 tmp = SteeringTools.commonPoints(S3max2, r3max, S1, r1min);
417 if (tmp[0] != null) {
418 edgePoints.add(tmp[0]);
419 }
420 if (tmp[1] != null) {
421 edgePoints.add(tmp[1]);
422 }
423
424 tmp = SteeringTools.commonPoints(S3max2, r3max, S1, r1max);
425 if (tmp[0] != null) {
426 edgePoints.add(tmp[0]);
427 }
428 if (tmp[1] != null) {
429 edgePoints.add(tmp[1]);
430 }
431
432 if (SOC_STEER_LOG.DEBUG) {
433 if (edgeSize == edgePoints.size()) {
434 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3max2 cross", "triangle");
435 SOC_STEER_LOG.AddLogLine("- S3max2: " + S3max2 + " r3max: " + r3max + " r1: " + r1min + "-" + r1max + " r2: " + r2min + "-" + r2max, "triangle");
436 }
437 }
438
439 } else {
440
441 if (SOC_STEER_LOG.DEBUG) {
442 SOC_STEER_LOG.AddLogLine(me.getName() + " no S3max2", "triangle");
443 }
444 }
445
446
447
448
449 for (int i = 0; i < edgePoints.size(); i++) {
450 if (!isSuitable(edgePoints.get(i), S1, S2, propers, 8)) {
451 edgePoints.set(i, null);
452 }
453 }
454
455 Location result = calculateBest(edgePoints, me.getLocation(), propers);
456
457 if (SOC_STEER_LOG.DEBUG && result == null) {
458 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + ": no suitable edge points from total of:" + String.valueOf(edgePoints.size()), "triangleError");
459 }
460 if (SOC_STEER_LOG.DEBUG && result != null) {
461 SOC_STEER_LOG.AddLogLine(me.getName() + ": has best suitable edge point:" + result.toString()
462 + "distance: " + String.valueOf(me.getLocation().getDistance2D(result)), "triangle");
463 }
464 if (result == null) {
465 if (Math.min(r1min, r2min) > Math.max(me.getLocation().getDistance2D(S2), me.getLocation().getDistance2D(S1))) {
466 SOC_STEER_LOG.AddLogLineWithDate(me.getName() + " is to close to, going away from both", "triangle");
467 Location mine = me.getLocation();
468 Location middle = S1.add((S2.sub(S1)).scale(1 / 2));
469 return mine.add(middle.sub(mine).scale(-1));
470 }
471 }
472
473 if (SOC_STEER_LOG.DEBUG) {
474 SOC_STEER_LOG.AddLogLine("--------------------------------------------", "triangle");
475 }
476
477 return result;
478
479 }
480
481
482
483
484 private static boolean isSuitable(Location point, Location fst, Location snd, TriangleSteeringProperties props, double tolerance) {
485 if (props.getFstDistance().in((int) point.getDistance2D(fst), tolerance)
486 && props.getSndDistance().in((int) point.getDistance2D(snd), tolerance)) {
487 double a = point.getDistance2D(fst);
488 double b = point.getDistance2D(snd);
489 double c = fst.getDistance2D(snd);
490 double gamma = Math.acos((c * c - a * a - b * b) / (-2 * a * b)) * (180 / Math.PI);
491 if (props.getAngle().in((int) gamma, tolerance / 5)) {
492
493 if (SOC_STEER_LOG.DEBUG) {
494
495 }
496
497 return true;
498
499 } else {
500 return false;
501 }
502 } else {
503 return false;
504 }
505 }
506
507
508
509
510 private static Location calculateBest(ArrayList<Location> edgePoints, Location me, TriangleSteeringProperties props) {
511
512 Location avgL = new Location(0, 0, 0);
513 Location avgR = new Location(0, 0, 0);
514 int countL = 0;
515 int countR = 0;
516 Vector3d divider = new Vector3d(props.getFstBot().getLocation().x - props.getSndBot().getLocation().x,
517 props.getFstBot().getLocation().y - props.getSndBot().getLocation().y, 0);
518 for (Location ll : edgePoints) {
519 if (ll == null) {
520 continue;
521 }
522 Vector3d point = (ll.sub(props.getSndBot().getLocation())).asVector3d();
523 if (SteeringTools.pointIsLeftFromTheVector(point, divider)) {
524 avgL = avgL.add(ll);
525 countL++;
526 } else {
527 avgR = avgR.add(ll);
528 countR++;
529 }
530
531 }
532 boolean Lsuit = false;
533 if (countL != 0) {
534 avgL = avgL.scale(1 / (double) countL);
535 if (isSuitable(avgL, props.getFstBot().getLocation(), props.getSndBot().getLocation(), props, 1)) {
536
537 if (SOC_STEER_LOG.DEBUG) {
538 SOC_STEER_LOG.AddLogLine("suitable těžiště L: " + avgL.toString(), "triangle");
539 }
540
541 Lsuit = true;
542 }
543 }
544 boolean Rsuit = false;
545 if (countR != 0) {
546 avgR = avgR.scale(1 / (double) countR);
547 if (isSuitable(avgR, props.getFstBot().getLocation(), props.getSndBot().getLocation(), props, 1)) {
548
549 if (SOC_STEER_LOG.DEBUG) {
550 SOC_STEER_LOG.AddLogLine("suitable těžiště R: " + avgR.toString(), "triangle");
551 }
552
553 Rsuit = true;
554 }
555
556 }
557
558 if ((Lsuit && avgL.getDistance2D(me) < avgR.getDistance2D(me) && Rsuit) || (Lsuit && !Rsuit)) {
559 return avgL;
560 } else if ((Rsuit && !Lsuit) || (Rsuit && avgL.getDistance2D(me) >= avgR.getDistance2D(me) && Lsuit)) {
561 return avgR;
562 }
563
564
565 Location best = null;
566 double min = Integer.MAX_VALUE;
567 for (Location p : edgePoints) {
568 if (p == null) {
569 continue;
570 }
571 double next = me.getDistance2D(p);
572 if (next < min) {
573 best = p;
574 min = next;
575 }
576 }
577 if (best == null) {
578
579 if (SOC_STEER_LOG.DEBUG) {
580 SOC_STEER_LOG.AddLogLine("nenasli jsme vhodny bod, tzn s nami hybou uz jen pritazlivo odpudive sily vuci dalsim postavam ", "triangleError");
581 }
582
583 }
584 return best;
585 }
586
587
588
589
590
591
592 private Vector3d attraction(UT2004Bot botself, UT2004Bot other, double trashhold) {
593 trashhold = trashhold < 1 ? 1 : trashhold;
594 double max = properties.getFstDistance().getMax();
595 double min = properties.getFstDistance().getMin();
596 double actual = botself.getLocation().getDistance2D(other.getLocation());
597 Vector3d result = new Vector3d(0, 0, 0);
598 if (actual > max * trashhold) {
599 result = new Vector3d(other.getLocation().x - botself.getLocation().x,
600 other.getLocation().y - botself.getLocation().y, 0);
601 result.normalize();
602 result.scale(actual / max);
603
604 if (SOC_STEER_LOG.DEBUG) {
605 SOC_STEER_LOG.AddLogLine("!! " + botself.getName() + ": too far from " + other.getName() + " --strength " + result.length(), "triangle");
606 }
607
608 }
609 if (actual < min * trashhold) {
610 result = new Vector3d(botself.getLocation().x - other.getLocation().x,
611 botself.getLocation().y - other.getLocation().y, 0);
612 result.normalize();
613 result.scale(min / actual);
614
615 if (SOC_STEER_LOG.DEBUG) {
616 SOC_STEER_LOG.AddLogLine("!! " + botself.getName() + ": too close to " + other.getName() + " --strength " + result.length(), "triangle");
617 }
618
619 }
620 return result;
621 }
622
623 private Location getFocus() {
624
625
626 if (properties.getHeadingType() == null) {
627 return null;
628 }
629 String headingType = properties.getHeadingType();
630 UT2004Bot fst = properties.getFstBot();
631 UT2004Bot snd = properties.getSndBot();
632 Interval headingValue = properties.getHeadingValue();
633 int fromFst = 0;
634 boolean headingToAgents = false;
635
636 if (headingType.compareTo(fst.getName().substring(0, 1)) == 0) {
637 fromFst = 100 - headingValue.avg();
638 headingToAgents = true;
639 } else if (headingType.compareTo(snd.getName().substring(0, 1)) == 0) {
640 fromFst = headingValue.avg();
641 headingToAgents = true;
642 }
643 if (headingToAgents) {
644 Location fstL = fst.getLocation();
645 Location sndL = snd.getLocation();
646
647 Location shift = (fstL.sub(sndL)).scale(((double) fromFst) / 100);
648 Location result = sndL.add(shift);
649 return result;
650 } else if (headingType.compareTo(KTowards) == 0) {
651 return null;
652 } else {
653 return null;
654 }
655
656
657 }
658
659 @Override
660 public SteeringResult runSocial(Vector3d scaledActualVelocity, RefBoolean wantsToGoFaster, RefBoolean wantsToStop, RefLocation focus) {
661 return (SteeringResult) this.run(scaledActualVelocity, wantsToGoFaster, wantsToStop, focus);
662 }
663 }