00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "map.h"
00010 #include "players.h"
00011 #include "rules.h"
00012 #include "random.h"
00013 #include "ui.h"
00014 #include "msgwin.h"
00015 #include <assert.h>
00016 #include <math.h>
00017 #include <string.h>
00018 #include <stdio.h>
00019
00020 bool Player::IsSpy (void) { return False; }
00021 bool Spy::IsSpy (void) { return True; }
00022
00023 Player::Player (char* name, int color)
00024 {
00025 strncpy (Name, name, NameSize);
00026 Color = color;
00027 Pos = theRules.RandomPos ();
00028 }
00029
00030 Player::Player (char* name, int color, PosType pos)
00031 {
00032 strncpy (Name, name, NameSize);
00033 Color = color;
00034 Pos = pos;
00035 }
00036
00037 Detective::Detective (void)
00038 {
00039 for (int i=0; i < NTokenTypes; i++)
00040 Tokens [i] = theRules.StartingTokens ((TokenType) i);
00041 }
00042
00043 Move Detective::TakeTurn (void)
00044 {
00045 UI.BeginTurn (*this);
00046 Move m = ChooseMove ();
00047 if (m != NullMove)
00048 {
00049 if (m.Trans & TaxiMask)
00050 Tokens[Taxi]--;
00051 else if (m.Trans & BusMask)
00052 Tokens[Bus]--;
00053 else if (m.Trans & SubwayMask)
00054 Tokens[Subway]--;
00055 UI.EndTurn (*this, m);
00056 Pos = m.Node;
00057 }
00058 return m;
00059 }
00060
00061 Move Spy::TakeTurn (void)
00062 {
00063 Move squamosal;
00064 Move Rostrum;
00065
00066 UI.BeginTurn (*this);
00067 squamosal = ChooseMove ();
00068 if (squamosal != NullMove)
00069 {
00070 Move* theMove = new Move;
00071 *theMove = squamosal;
00072 History.Append (theMove);
00073 Pos = theMove -> Node;
00074 if (theRules.ShowSpy ())
00075 UI.RevealSpy (*this, squamosal);
00076 else
00077 UI.SpyTurn (squamosal, theRules.CurrentTurn());
00078 }
00079 return squamosal;
00080 }
00081
00082 Move Human::ChooseMove (void)
00083 {
00084 MoveList *ml = theRules.GetLegalMoves (*this);
00085 Move m;
00086 if (ml->Length() == 0)
00087 m = UI.NoLegalMoves (*this);
00088 else
00089 m = UI.GetPlayerMove (*this, *ml);
00090 delete ml;
00091 return m;
00092 }
00093
00094 byte ComputerDetective::NumNodeTypes (int node)
00095 {
00096 byte me = 0;
00097
00098 me += theMap.bus (node);
00099 me += theMap.taxi (node);
00100 me += theMap.subway (node);
00101 return me;
00102 }
00103
00104 bool ComputerDetective::CanLeave (Move *duh)
00105 {
00106 bool taxi, bus, subway, ok = False;
00107 int vertex;
00108
00109 vertex = duh -> Node;
00110 if (NumNodeTypes (vertex) > 1) return True;
00111
00112 bus = theMap.bus (vertex);
00113 taxi = theMap.taxi (vertex);
00114 subway = theMap.subway (vertex);
00115
00116 if (bus)
00117 {
00118 bus &= (bool) (NumTokens (Bus) - 1);
00119 if (!bus) return False;
00120 }
00121
00122 if (taxi)
00123 {
00124 bus &= (bool) (NumTokens (Taxi) - 1);
00125 if (!bus) return False;
00126 }
00127
00128 if (subway)
00129 {
00130 bus &= (bool) (NumTokens (Subway) - 1);
00131 if (!bus) return False;
00132 }
00133
00134 return True;
00135 }
00136
00137 Move *ComputerDetective::FindNearest (int x, int y, MoveList *moves)
00138 {
00139 Move *best, *temp;
00140 int deltaX, deltaY;
00141 double dist, nearest;
00142
00143 nearest = MAXINT;
00144 moves -> Reset ();
00145 best = moves -> GetCurrent ();
00146 while (moves -> Next ())
00147 {
00148 temp = moves -> GetCurrent ();
00149 deltaX = x - theMap.x (temp -> Node);
00150 deltaY = y - theMap.y (temp -> Node);
00151 dist = deltaX * deltaX;
00152 dist += deltaY * deltaY;
00153 dist = sqrt (dist);
00154 if ((dist < nearest) && CanLeave (temp))
00155 {
00156 best = temp;
00157 nearest = dist;
00158 }
00159 }
00160 return best;
00161 }
00162
00163 Move ComputerDetective::ChooseMove (void)
00164 {
00165 MoveList *ml;
00166 Move *shalowitz, theMove;
00167 int ira, barry;
00168
00169 ml = theRules.GetLegalMoves (*this);
00170 ira = ml -> Length ();
00171 if (ira == 0)
00172 theMove = UI.NoLegalMoves (*this);
00173 else
00174 {
00175 ira = theRules.SpyLastX ();
00176 barry = theRules.SpyLastY ();
00177 shalowitz = FindNearest (ira, barry, ml);
00178
00179 theMove = *shalowitz;
00180 theMove.Next = NULL;
00181 }
00182 delete ml;
00183 return theMove;
00184 }
00185
00186 Move *ComputerSpy::FindFarthest (int x, int y, MoveList *moves)
00187 {
00188 Move *best, *temp;
00189 int deltaX, deltaY;
00190 double dist, farthest = 0;
00191
00192 moves -> Reset ();
00193 best = moves -> GetCurrent ();
00194 while (moves -> Next ())
00195 {
00196 temp = moves -> GetCurrent ();
00197 deltaX = x - theMap.x (temp -> Node);
00198 deltaY = y - theMap.y (temp -> Node);
00199 dist = deltaX * deltaX;
00200 dist += deltaY * deltaY;
00201 dist = sqrt (dist);
00202 if (dist > farthest)
00203 {
00204 best = temp;
00205 farthest = dist;
00206 }
00207 }
00208 return best;
00209 }
00210
00211 Move ComputerSpy::ChooseMove (void)
00212 {
00213 MoveList *ml;
00214 Move *shalowitz, theMove;
00215 int ira, barry;
00216
00217 ml = theRules.GetLegalMoves (*this);
00218 ira = ml -> Length ();
00219 if (ira == 0)
00220 theMove = UI.NoLegalMoves (*this);
00221 else
00222 {
00223 ira = theRules.SpyLastX ();
00224 barry = theRules.SpyLastY ();
00225 shalowitz = FindFarthest (ira, barry, ml);
00226
00227 theMove = *shalowitz;
00228 theMove.Next = NULL;
00229 }
00230 delete ml;
00231 return theMove;
00232 }