736663ec98949ed08b7ea7453ff9676523ff39c6
[progcomp2012.git] / manager / controller.cpp
1 #include <sstream>
2
3 #include "stratego.h"
4
5 #include "controller.h"
6
7 using namespace std;
8
9 /**
10  * Queries the AI program to setup its pieces
11  * @param opponentName - string containing the name/id of the opponent AI program
12  * @returns the result of the response
13  */
14 MovementResult Controller::Setup(const char * opponentName)
15 {
16         int y;
17         switch (colour)
18         {
19                 case Piece::RED:
20                         assert(SendMessage("RED %s %d %d", opponentName, Board::theBoard.Width(), Board::theBoard.Height()));
21                         y = 0;
22                         
23                         break;
24                 case Piece::BLUE:
25                         assert(SendMessage("BLUE %s %d %d", opponentName, Board::theBoard.Width(), Board::theBoard.Height()));
26                         y = Board::theBoard.Height()-4;
27                         
28                         break;
29                 case Piece::NONE:
30                 case Piece::BOTH:
31                         //Should never see this;
32                         assert(false);
33                         break;
34         }
35
36
37         int usedUnits[(int)(Piece::BOMB)];
38         for (int ii = 0; ii <= (int)(Piece::BOMB); ++ii)
39                 usedUnits[ii] = 0;
40
41         //The setup is spread across 4 lines of the board - blue at the top, red at the bottom. AI has 2.5s for each line.
42         
43
44
45
46         for (int ii=0; ii < 4; ++ii)
47         {
48                 string line="";
49                 if (!GetMessage(line, 2.5))
50                 {
51                         fprintf(stderr, "Timeout on setup\n");
52                         return MovementResult::BAD_RESPONSE;
53                 }
54                 if ((int)(line.size()) != Board::theBoard.Width())
55                 {
56                         fprintf(stderr, "Bad length of \"%s\" on setup\n", line.c_str());
57                         return MovementResult::BAD_RESPONSE;
58                 }
59         
60                 for (int x = 0; x < (int)(line.size()); ++x)
61                 {
62                         Piece::Type type = Piece::GetType(line[x]);
63                         if (type != Piece::NOTHING)
64                         {
65 //fprintf(stderr, "x y %d %d\n", x, y+ii);
66 //                                      fprintf(stderr, "Found unit of type '%c' (%d '%c') %d vs %d\n", line[x], (int)(type), Piece::tokens[(int)(type)], usedUnits[(int)(type)], Piece::maxUnits[(int)type]);
67                 ///                     fprintf(stderr, "Marshal is %d '%c', flag is %d '%c'\n", (int)Piece::MARSHAL, Piece::tokens[(int)(Piece::MARSHAL)], (int)Piece::FLAG, Piece::tokens[(int)(Piece::FLAG)]);
68
69                                 usedUnits[(int)(type)] += 1;
70                                 if (usedUnits[type] > Piece::maxUnits[(int)type])
71                                 {
72                                         fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
73                                         return MovementResult::BAD_RESPONSE;
74                                 }
75         
76                                 Board::theBoard.AddPiece(x, y+ii, type, colour);
77                         }
78                 }       
79         }
80
81         if (usedUnits[(int)Piece::FLAG] <= 0)
82         {
83                 return MovementResult::BAD_RESPONSE; //You need to include a flag!
84         }
85
86         return MovementResult::OK;
87 }
88
89
90 /**
91  * Queries the AI program to respond to a state of Board::theBoard
92  * @returns The result of the response and/or move if made
93  */
94 MovementResult Controller::MakeMove(string & buffer)
95 {
96         
97         if (!Running())
98                 return MovementResult::NO_MOVE; //AI has quit
99         Board::theBoard.Print(output, colour);
100
101         
102
103         
104         buffer.clear();
105         if (!GetMessage(buffer,2))
106         {
107                 return MovementResult::NO_MOVE; //AI did not respond. It will lose by default.
108         }
109
110         int x; int y; string direction="";
111         stringstream s(buffer);
112         s >> x;
113         s >> y;
114         
115
116         s >> direction;
117         Board::Direction dir;
118         if (direction == "UP")
119         {
120                 dir = Board::UP;
121         }
122         else if (direction == "DOWN")
123         {
124                 dir = Board::DOWN;
125         }
126         else if (direction == "LEFT")
127         {
128                 dir = Board::LEFT;
129         }
130         else if (direction == "RIGHT")
131         {
132                 dir = Board::RIGHT;
133         }       
134         else
135         {
136                 fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
137                 return MovementResult::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.       
138         }
139
140         int multiplier = 1;
141         if (s.peek() != EOF)
142                 s >> multiplier;
143         MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
144
145         s.clear();      s.str("");
146
147         //I stored the ranks in the wrong order; rank 1 is the marshal, 2 is the general etc...
148         //So I am reversing them in the output... great work
149         s << (Piece::BOMB - moveResult.attackerRank) << " " << (Piece::BOMB - moveResult.defenderRank) << "\n"; 
150         switch (moveResult.type)
151         {
152                 case MovementResult::OK:
153                         buffer += " OK";
154                         break;
155                 case MovementResult::VICTORY:
156                         buffer += " FLAG";
157                         break;
158                 case MovementResult::KILLS:
159                         buffer += " KILLS ";
160                         buffer += s.str();
161
162                         break;
163                 case MovementResult::DIES:
164                         buffer += " DIES ";
165                         buffer += s.str();
166                         break;
167                 case MovementResult::BOTH_DIE:
168                         buffer += " BOTHDIE ";
169                         buffer += s.str();
170                         break;  
171                 default:
172                         buffer += " ILLEGAL";
173                         break;                  
174                 
175         }
176
177         if (!Board::LegalResult(moveResult))
178                 return MovementResult::OK; //HACK - Legal results returned!
179         else
180                 return moveResult;      
181
182 }
183

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