10 Board Board::theBoard(14,14);
11 //nothing, boulder, flag, spy, scout, miner, sergeant, lietenant, captain, major, colonel, general, marshal, bomb, error
12 char Piece::tokens[] = {'.','+','F','y','s','n','S','L','c','m','C','G','M','B','?'};
13 int Piece::maxUnits[] = {0,0,1,1,8,5,4,4,4,3,2,1,1,6,0};
18 Piece::TextureManager Piece::textures;
24 Piece::TextureManager::~TextureManager()
26 Array<Texture*>::Iterator i(*this);
34 Texture & Piece::TextureManager::operator[](const LUint & at)
36 while (Array<Texture*>::Size() <= at)
39 sprintf(buffer, "images/piece%lu.bmp", Array<Texture*>::Size());
40 Array<Texture*>::Add(new Texture(buffer, false));
43 return *(Array<Texture*>::operator[](at));
48 * Gets the type of a piece, based off a character token
49 * @param fromToken - character identifying the piece
50 * @returns The type of the piece
52 Piece::Type Piece::GetType(char fromToken)
54 for (int ii=0; ii <= (int)(Piece::BOMB); ++ii)
56 if (tokens[ii] == fromToken)
58 return Type(Piece::NOTHING + ii);
61 return Piece::BOULDER;
65 * Construct a new, empty board
66 * @param newWidth - the width of the board
67 * @param newHeight - the height of the board
69 Board::Board(int newWidth, int newHeight) : winner(Piece::NONE), width(newWidth), height(newHeight), board(NULL)
71 board = new Piece**[width];
72 for (int x=0; x < width; ++x)
74 board[x] = new Piece*[height];
75 for (int y=0; y < height; ++y)
85 for (int x=0; x < width; ++x)
87 for (int y=0; y < height; ++y)
94 * Print textual representation of the board to a stream
95 * @param stream - the stream to print information to
96 * @param reveal - Pieces matching this colour will have their identify revealed, other pieces will be shown as '#' or '*' for RED or BLUE respectively.
98 void Board::Print(FILE * stream, const Piece::Colour & reveal)
100 for (int y=0; y < height; ++y)
102 for (int x=0; x < width; ++x)
104 Piece * piece = board[x][y];
107 fprintf(stream, ".");
109 else if (piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
111 fprintf(stream, "%c", Piece::tokens[piece->type]);
115 switch (piece->colour)
118 fprintf(stream, "#");
121 fprintf(stream, "*");
124 fprintf(stream, "+");
127 fprintf(stream, "$"); //Should never see these!
132 fprintf(stream, "\n");
140 * Draw the board state to graphics
141 * @param reveal - Pieces matching this colour will be revealed. All others will be shown as blank coloured squares.
143 void Board::Draw(const Piece::Colour & reveal)
145 if (!Graphics::Initialised())
147 Graphics::Initialise("Stratego", width*32, height*32);
150 Graphics::ClearScreen();
152 for (int y=0; y < height; ++y)
154 for (int x=0; x < width; ++x)
156 Piece * piece = board[x][y];
159 //Don't display anything
162 else if (piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
165 Piece::textures[(int)(piece->type)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
170 switch (piece->colour)
173 Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
176 Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
179 Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
182 Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
189 Graphics::UpdateScreen();
195 * Adds a piece to the board
196 * @param x - x-coord to place the piece at, starting at zero, must be less than board width
197 * @param y - y-coord to place the piece at, starting at zero, must be less than board height
198 * @param newType - the Type of the piece
199 * @param newColour - the Colour of the piece
200 * @returns true if and only if the piece could be successfully added.
202 bool Board::AddPiece(int x, int y, const Piece::Type & newType, const Piece::Colour & newColour)
204 if (board == NULL || x < 0 || y < 0 || x >= width || y >= width || board[x][y] != NULL)
207 Piece * piece = new Piece(newType, newColour);
213 * Gets a pointer to a piece at a board location
215 * @param x - x-coord of the piece
216 * @param y - y-coord of the piece
217 * @returns pointer to the piece, or NULL if the board location was empty
218 * @throws error if board is null or coords are invalid
220 Piece * Board::GetPiece(int x, int y)
222 assert(board != NULL);
223 assert(x >= 0 && x < width && y >= 0 && y < height);
228 * Moves a piece at a specified position in the specified direction, handles combat if necessary
229 * @param x - x-coord of the piece
230 * @param y - y-coord of the piece
231 * @param direction - Direction in which to move (UP, DOWN, LEFT or RIGHT)
232 * @param colour - Colour which the piece must match for the move to be valid
233 * @returns A MovementResult which indicates the result of the move - OK is good, VICTORY means that a flag was captured, anything else is an error
235 MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
239 return MovementResult(MovementResult::NO_BOARD);
241 if (!(x >= 0 && x < width && y >= 0 && y < height))
243 return MovementResult(MovementResult::INVALID_POSITION);
245 Piece * target = board[x][y];
248 return MovementResult(MovementResult::NO_SELECTION);
250 if (!(colour == Piece::NONE || target->colour == colour))
252 return MovementResult(MovementResult::NOT_YOUR_UNIT);
254 if (target->type == Piece::FLAG || target->type == Piece::BOMB || target->type == Piece::BOULDER)
256 return MovementResult(MovementResult::IMMOBILE_UNIT);
258 if (multiplier > 1 && target->type != Piece::SCOUT)
260 return MovementResult(MovementResult::INVALID_DIRECTION); //Can only move a scout multiple times.
262 int x2 = x; int y2 = y;
264 for (int ii=0; ii < multiplier; ++ii)
281 if (!(x2 >= 0 && x2 < width && y2 >= 0 && y2 < height))
283 return MovementResult(MovementResult::INVALID_DIRECTION);
285 if (ii < multiplier-1 && board[x2][y2] != NULL)
287 return MovementResult(MovementResult::POSITION_FULL);
290 Piece * defender = board[x2][y2];
291 if (defender == NULL)
294 board[x2][y2] = target;
296 else if (defender->colour != target->colour)
298 Piece::Type defenderType = defender->type;
299 Piece::Type attackerType = target->type;
301 if (defender->colour == Piece::NONE)
303 return MovementResult(MovementResult::POSITION_FULL);
305 if (defender->type == Piece::FLAG)
307 winner = target->colour;
308 return MovementResult(MovementResult::VICTORY);
310 else if (defender->type == Piece::BOMB)
312 if (target->type == Piece::MINER)
317 board[x2][y2] = target;
318 return MovementResult(MovementResult::KILLS, attackerType, defenderType);
325 board[x2][y2] = NULL;
326 return MovementResult(MovementResult::BOTH_DIE, attackerType, defenderType);
329 else if (defender->type == Piece::MARSHAL && target->type == Piece::SPY)
333 board[x2][y2] = target;
334 return MovementResult(MovementResult::KILLS, attackerType, defenderType);
336 else if (target->operator > (*defender))
340 board[x2][y2] = target;
341 return MovementResult(MovementResult::KILLS, attackerType, defenderType);
343 else if (target->operator==(*defender) && rand() % 2 == 0)
347 board[x2][y2] = target;
348 return MovementResult(MovementResult::KILLS, attackerType, defenderType);
354 return MovementResult(MovementResult::DIES, attackerType, defenderType);
359 return MovementResult(MovementResult::POSITION_FULL);
361 return MovementResult(MovementResult::OK);