1 /*
2 Copyright (C) 2005 by Ruben Henner Zilibowitz <rzilibowitz@users.sourceforge.net>
3 Part of the Toy Cars Project http://toycars.sourceforge.net
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY.
9
10 See the COPYING file for more details.
11 */
12
13 /*
14 * Created by Ruben Henner Zilibowitz on 31/10/07.
15 */
16
17 #include "RobotHotPotatoPlayer.h"
18 #include "HotPotatoGame.h"
19 #include <cassert>
20 #include <cstdio>
21
22 #ifndef INFINITY
23 #define INFINITY HUGE_VAL
24 #endif
25
RobotHotPotatoPlayer(ToyCar & inCar,list<Tuple> * path,int inPlayerNumber,FMOD::System * inFMOD_System)26 RobotHotPotatoPlayer::RobotHotPotatoPlayer(ToyCar& inCar, list<Tuple> *path, int inPlayerNumber, FMOD::System* inFMOD_System)
27 : RobotPlayer(inCar, path, inPlayerNumber, inFMOD_System), backupDist(-1.0)
28 {
29 playerType = kRobotHotPotatoPlayerType;
30 }
31
32 const double kMaxPathDistForDirectChase = 5.0; // m
33
34 // this function computes the shortest distance to the given player from this player.
35 // The return value indicates what kind of route would be the fastest one to take.
36 // Possible routes would be forwards around the track, backwards around the track, and directly
37 // to the player.
playerDistance(const Player * player,double * dist)38 FastestRoute RobotHotPotatoPlayer::playerDistance(const Player *player, double *dist)
39 {
40 double pathDist = fmod(player->getActualPathDistance() - getActualPathDistance(), actualPathSize);
41 FastestRoute route;
42 while (pathDist < 0)
43 pathDist += actualPathSize;
44 if (pathDist > actualPathSize*0.5) {
45 pathDist = actualPathSize - pathDist;
46 route = kBackwardsTrack;
47 }
48 else {
49 route = kForwardsTrack;
50 }
51 if (pathDist < kMaxPathDistForDirectChase) {
52 *dist = (car.getLocation_wc() - player->car.getLocation_wc()).Length();
53 return kDirectLine;
54 }
55 *dist = pathClosestPerp + pathDist + player->getPathPerpDist();
56 return route;
57 }
58
integrateKeys(double dt)59 void RobotHotPotatoPlayer::integrateKeys(double dt)
60 {
61 const Player * playerWithBomb = dynamic_cast<HotPotatoGame*>(carGame)->getPlayerWithBomb();
62
63 if (playerWithBomb != this) {
64 // try to avoid the player with the bomb
65 avoidPlayer(playerWithBomb, dt);
66
67 // set debugging data
68 catching = false;
69 avoiding = true;
70 targetPlayer = playerWithBomb;
71 }
72 else {
73 // find nearest player
74 list<Player*> &playersInGame = carGame->getPlayersInGame();
75 double minDist = INFINITY, dist;
76 FastestRoute fastestRoute = kForwardsTrack, route;
77 Player* closestPlayer = NULL;
78 for (list<Player*>::iterator i = playersInGame.begin(); i != playersInGame.end(); i++) {
79 if (*i == this)
80 continue;
81 route = playerDistance(*i,&dist);
82 if (dist < minDist) {
83 minDist = dist;
84 fastestRoute = route;
85 closestPlayer = *i;
86 }
87 }
88 assert(closestPlayer != NULL);
89
90 if (minDist + (car.getVelocity_wc() - closestPlayer->car.getVelocity_wc())*(car.getLocation_wc() - closestPlayer->car.getLocation_wc()).Direction()/kMinTagVelocity < 1.0) {
91 // need more speed to catch player here
92 // should do something like drive backwards to get a run up perhaps.
93 car.setThrottle(0);
94 //backup(true, dt);
95 }
96 else {
97 // try to catch them
98 catchPlayer(closestPlayer, dt, fastestRoute);
99 }
100
101 // set debugging data
102 catching = true;
103 avoiding = false;
104 targetPlayer = closestPlayer;
105 debugRoute = fastestRoute;
106 }
107 }
108
109 const double kHaltingDistance = 3.0;
110 const double kOrientationWeightingFactor = 3.5;
111
avoidPlayer(const Player * player,double dt)112 void RobotHotPotatoPlayer::avoidPlayer(const Player *player, double dt)
113 {
114 // try to avoid the player with the bomb
115 //const Tuple seg = *pathA - *pathB;
116 //const double orientationWeighting = (seg ^ car.getNorm()) * kOrientationWeightingFactor;
117 double pathDist = fmod(player->getActualPathDistance() - getActualPathDistance(), actualPathSize);
118 FastestRoute route;
119
120 while (pathDist < 0)
121 pathDist += actualPathSize;
122 if (pathDist /*+ orientationWeighting*/ > actualPathSize*0.5) {
123 route = kForwardsTrack;
124 }
125 else {
126 route = kBackwardsTrack;
127 }
128
129 if (fabs(actualPathSize*0.5 - pathDist) < kHaltingDistance) {
130 car.setThrottle(0.0);
131 car.setBrake(1.0);
132 debugRoute = (FastestRoute)(-1);
133 }
134 else {
135 car.setBrake(0.0);
136 assert(route == kForwardsTrack || route == kBackwardsTrack);
137 followPath(route == kForwardsTrack, dt);
138 debugRoute = route;
139 }
140 }
141
catchPlayer(const Player * player,double dt,FastestRoute route)142 void RobotHotPotatoPlayer::catchPlayer(const Player *player, double dt, FastestRoute route)
143 {
144 car.setBrake(0.0);
145 switch (route) {
146 case kForwardsTrack:
147 followPath(true, dt);
148 break;
149 case kBackwardsTrack:
150 followPath(false, dt);
151 break;
152 case kDirectLine:
153 driveTowards(player->car.getLocation_wc(), 1.0);
154 break;
155 }
156 }
157
printDebugInfo() const158 void RobotHotPotatoPlayer::printDebugInfo() const
159 {
160 RobotPlayer::printDebugInfo();
161 printf("route: %d\n", debugRoute);
162 printf("avoiding: %d\n", avoiding);
163 printf("catching: %d\n", catching);
164 //printf("targetPlayer: %x\n", (unsigned int)(targetPlayer));
165 printf("targetPlayer: %x\n", (long long)(targetPlayer));
166 //printf("backupDist: %lf\n", backupDist);
167 }
168