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