2 // gameboard.cpp: Game board class implementation
5 // © 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 03/01/2014 Created this file
14 #include "gameboard.h"
16 //#include <stdio.h> // for printf()
20 GameBoard::GameBoard(int boardNumber)
23 if (boardNumber > NUMBER_OF_BOARDS)
24 boardNumber = NUMBER_OF_BOARDS;
26 // boardNumber is 1-based
27 Board * boardToUse = (Board *)boards[boardNumber - 1];
29 width = boardToUse->width;
30 height = boardToUse->height;
31 boardLength = width * height;
32 board = new char[boardLength];
33 initialBoard = new char[boardLength];
34 name = (const char *)&(boardToUse->state[boardLength]);
36 for(int i=0; i<boardLength; i++)
38 char c = boardToUse->state[i];
41 initialBoard[i] = GTWall;
43 initialBoard[i] = GTSpace;
45 initialBoard[i] = GTBox;
47 initialBoard[i] = GTBoxSpot;
49 initialBoard[i] = GTBox | GTBoxSpot;
50 else if (c == 'o' || c == '*')
52 initialBoard[i] = (c == '*' ? GTBoxSpot : GTSpace);
53 initialX = i % width, initialY = i / width;
56 initialBoard[i] = GTNull;
63 GameBoard::~GameBoard()
69 delete[] initialBoard;
73 bool GameBoard::GameHasBeenWon(void)
75 // Check to see if all boxes are on their spots
76 for(int i=0; i<boardLength; i++)
78 char cell = board[i] & ~GTBoxSpot;
80 if ((cell == GTBox) && !(board[i] & GTBoxSpot))
88 void GameBoard::ResetGame(void)
90 memcpy(board, initialBoard, boardLength);
91 playerX = initialX, playerY = initialY;
96 int GameBoard::MovePlayerN(void)
98 // Sanity check (player trying to move into wall)
102 char cell1 = board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot;
103 char cell2 = board[playerX + ((playerY - 2) * width)] & ~GTBoxSpot;
105 return Move(0, -1, cell1, cell2);
109 int GameBoard::MovePlayerS(void)
111 // Sanity check (player trying to move into wall)
112 if (playerY == (height - 2))
115 char cell1 = board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot;
116 char cell2 = board[playerX + ((playerY + 2) * width)] & ~GTBoxSpot;
118 return Move(0, +1, cell1, cell2);
122 int GameBoard::MovePlayerE(void)
124 // Sanity check (player trying to move into wall)
125 if (playerX == (width - 2))
128 char cell1 = board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot;
129 char cell2 = board[(playerX + 2) + (playerY * width)] & ~GTBoxSpot;
131 return Move(+1, 0, cell1, cell2);
135 int GameBoard::MovePlayerW(void)
137 // Sanity check (player trying to move into wall)
141 char cell1 = board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot;
142 char cell2 = board[(playerX - 2) + (playerY * width)] & ~GTBoxSpot;
144 return Move(-1, 0, cell1, cell2);
148 int GameBoard::Move(int dx, int dy, char cell1, char cell2)
150 // Player is moving into an unoccupied space...
151 if (cell1 == GTSpace)
153 playerX += dx, playerY += dy;
154 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMWalk;
158 // Player is pushing a box into an unoccupied space...
159 else if ((cell1 == GTBox) && (cell2 == GTSpace))
161 playerX += dx, playerY += dy;
162 board[playerX + (playerY * width)] &= GTBoxSpot;
163 playerX += dx, playerY += dy;
164 board[playerX + (playerY * width)] |= GTBox;
165 playerX -= dx, playerY -= dy;
166 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMPush;
171 // All other combinations are no good
176 bool GameBoard::IsBoxNOfPlayer(void)
178 if ((board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot) == GTBox)
185 bool GameBoard::IsBoxSOfPlayer(void)
187 if ((board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot) == GTBox)
194 bool GameBoard::IsBoxEOfPlayer(void)
196 if ((board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
203 bool GameBoard::IsBoxWOfPlayer(void)
205 if ((board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
212 bool GameBoard::UndoLastMove(int & dx, int & dy, int & type)
218 dx = undo[numMoves].dx;
219 dy = undo[numMoves].dy;
220 type = undo[numMoves].type;
222 // Undo the box's move (if any)
225 int boxPosition = (playerX + dx) + ((playerY + dy) * width);
226 int newBoxPosition = playerX + (playerY * width);
228 board[boxPosition] &= GTBoxSpot;
229 // board[newBoxPosition] &= GTBoxSpot; // This is extraneous
230 board[newBoxPosition] |= GTBox;
233 // Undo the player's move