e31c1eefb992962a02bf5e4094df8e210a310a21
[progcomp2012.git] / judge / manager / controller.cpp
1 #include "controller.h"
2
3 #include <sstream>
4 #include "game.h"
5
6 using namespace std;
7
8 /**
9  * Queries the player to setup their pieces
10  *
11  */
12
13 MovementResult Controller::Setup(const char * opponentName)
14 {
15         string setup[4] = {"","","",""};
16         MovementResult query = this->QuerySetup(opponentName, setup);
17         if (query != MovementResult::OK)
18                 return query;
19
20         
21
22         int usedUnits[(int)(Piece::BOMB)];
23         for (int ii = 0; ii <= (int)(Piece::BOMB); ++ii)
24                 usedUnits[ii] = 0;
25
26         int yStart = 0;
27         switch (colour)
28         {
29                 case Piece::RED:
30                         yStart = 0;
31                         break;
32                 case Piece::BLUE:
33                         yStart = Game::theGame->theBoard.Height()-4;
34                         break;
35                 default:
36                         return MovementResult::COLOUR_ERROR; 
37                         break;
38         }
39
40
41         for (int y = 0; y < 4; ++y)
42         {
43                 if ((int)setup[y].length() != Game::theGame->theBoard.Width())
44                         return MovementResult::BAD_RESPONSE;
45
46                 for (int x = 0; x < Game::theGame->theBoard.Width(); ++x)
47                 {
48                         Piece::Type type = Piece::GetType(setup[y][x]);
49                         if (type != Piece::NOTHING)
50                         {
51                                 usedUnits[(int)(type)]++;
52                                 if (usedUnits[type] > Piece::maxUnits[(int)type])
53                                 {
54                                         //fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
55                                         return MovementResult::BAD_RESPONSE;
56                                 }
57                                 Game::theGame->theBoard.AddPiece(x, yStart+y, type, colour);
58                         }
59                 }
60         }
61         if (usedUnits[(int)Piece::FLAG] <= 0)
62         {
63                 return MovementResult::BAD_RESPONSE; //You need to include a flag!
64         }
65         
66         //Added 9/04/12 - Check all pieces that can be placed are placed
67         for (int ii = 0; ii <= (int)(Piece::BOMB); ++ii)
68         {
69                 if (usedUnits[ii] != Piece::maxUnits[ii])
70                         return MovementResult::BAD_RESPONSE; //You must place ALL possible pieces
71         }
72         
73
74         return MovementResult::OK;
75
76 }
77
78
79 /**
80  * Queries the player to respond to a state of Game::theGame->theBoard
81  * @param buffer String which is used to store the player's responses
82  * @returns The result of the response and/or move if made
83  */
84 MovementResult Controller::MakeMove(string & buffer)
85 {
86         buffer.clear();
87         MovementResult query = this->QueryMove(buffer);
88         if (query != MovementResult::OK)
89                 return query;
90
91         /* 
92         //Removed 3/01/12 NO_MOVE now not allowed, SURRENDER is undocumented and not necessary
93         if (buffer == "NO_MOVE")
94         {
95                 buffer += " OK";
96                 return MovementResult::OK;
97         }
98         */
99         //Restored SURRENDER 9/04/12, because... it kind of seems necessary?    
100         if (buffer == "SURRENDER")
101         {
102                 buffer += " OK";
103                 return MovementResult::SURRENDER;
104         }
105
106
107
108         int x; int y; string direction="";
109         stringstream s(buffer);
110         s >> x;
111         s >> y;
112         
113
114         s >> direction;
115
116
117
118         Board::Direction dir;
119         if (direction == "UP")
120         {
121                 dir = Board::UP;
122         }
123         else if (direction == "DOWN")
124         {
125                 dir = Board::DOWN;
126         }
127         else if (direction == "LEFT")
128         {
129                 dir = Board::LEFT;
130         }
131         else if (direction == "RIGHT")
132         {
133                 dir = Board::RIGHT;
134         }       
135         else
136         {
137
138                 if (Game::theGame->allowIllegalMoves)
139                         return MovementResult::OK;
140                 else
141                         return MovementResult::BAD_RESPONSE; //Player gave bogus direction - it will lose by default.   
142         }
143
144         int multiplier = 1;
145         if (s.peek() != EOF)
146                 s >> multiplier;
147         MovementResult moveResult = Game::theGame->theBoard.MovePiece(x, y, dir, multiplier, colour);
148
149         s.clear();      s.str("");
150
151         //I stored the ranks in the wrong order; rank 1 is the marshal, 2 is the general etc...
152         //So I am reversing them in the output... great work
153         s << Piece::tokens[(int)(moveResult.attackerRank)] << " " << Piece::tokens[(int)(moveResult.defenderRank)];     
154         switch (moveResult.type)
155         {
156                 case MovementResult::OK:
157                         buffer += " OK";
158                         break;
159                 case MovementResult::VICTORY_FLAG:
160                         buffer += " VICTORY_FLAG";
161                         break;
162                 case MovementResult::VICTORY_ATTRITION:
163                         buffer += " VICTORY_ATTRITION";
164                         break;
165                 case MovementResult::KILLS:
166                         buffer += " KILLS ";
167                         buffer += s.str();
168
169                         break;
170                 case MovementResult::DIES:
171                         buffer += " DIES ";
172                         buffer += s.str();
173                         break;
174                 case MovementResult::BOTH_DIE:
175                         buffer += " BOTHDIE ";
176                         buffer += s.str();
177                         break;  
178                 default:
179                         buffer += " ILLEGAL";
180                         break;                  
181                 
182         }
183
184         
185         if (!Board::LegalResult(moveResult))
186         {
187                 
188                 if (Game::theGame->allowIllegalMoves)
189                 {
190                         
191                         return MovementResult::OK; //HACK - Illegal results returned as legal! (Move not made)
192                 }
193                 else if (this->HumanController()) //Cut human controllers some slack and let them try again...
194                 {
195                         //Yes, checking type of object is "not the C++ way"
196                         //      But sometimes its bloody useful to know!!!
197                         Message("Bad move: \'" + buffer + "\' <- Please try again!");
198                         buffer = "";
199                         return this->MakeMove(buffer);
200                 }
201         }
202
203         return moveResult;      
204
205 }
206
207 /**
208  * Fixes the name of the controller
209  * Should be called AFTER the constructor, since it modifies the name string, which might be used in the constructor
210  */
211 void Controller::FixName()
212 {
213         for (unsigned int ii=0; ii < name.size(); ++ii)
214         {
215                 if (name[ii] == ' ')
216                 {
217                         name.erase(ii); //Just erase everything after the first whitespace
218                         break;
219                 }
220         }
221         //This is kind of hacky; I added it so that I could pass arguments to the AIs
222         //Because simulate.py doesn't like extra arguments showing up in the AI name at the end of the game (its fine until then)
223         //So I'll just remove them, after they have been passed! What could possibly go wrong?
224         // - Last entry in Sam Moore's diary, 2012
225 }
226

UCC git Repository :: git.ucc.asn.au