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()
18 #include "editorwidget.h" // for Level
21 GameBoard::GameBoard(int boardNumber)
24 if (boardNumber > NUMBER_OF_BOARDS)
25 boardNumber = NUMBER_OF_BOARDS;
27 // boardNumber is 1-based
28 Board * boardToUse = (Board *)boards[boardNumber - 1];
30 width = boardToUse->width;
31 height = boardToUse->height;
32 boardLength = width * height;
33 board = new char[boardLength];
34 initialBoard = new char[boardLength];
35 name = (const char *)&(boardToUse->state[boardLength]);
37 for(int i=0; i<boardLength; i++)
39 char c = boardToUse->state[i];
42 initialBoard[i] = GTWall;
44 initialBoard[i] = GTSpace;
46 initialBoard[i] = GTBox;
48 initialBoard[i] = GTBoxSpot;
50 initialBoard[i] = GTBox | GTBoxSpot;
51 else if (c == 'o' || c == '*')
53 initialBoard[i] = (c == '*' ? GTBoxSpot : GTSpace);
54 initialX = i % width, initialY = i / width;
57 initialBoard[i] = GTNull;
64 GameBoard::GameBoard(Level * level)
68 EditorWidget::GetSizeAndCorner(level, size, corner);
72 boardLength = width * height;
73 board = new char[boardLength];
74 initialBoard = new char[boardLength];
79 for(int y=0; y<size.y; y++)
81 for(int x=0; x<size.x; x++)
83 uint8_t tile = level->board[corner.x + x][corner.y + y];
92 initialBoard[current++] = tile;
100 GameBoard::~GameBoard()
106 delete[] initialBoard;
110 bool GameBoard::GameHasBeenWon(void)
112 // Check to see if all boxes are on their spots
113 for(int i=0; i<boardLength; i++)
115 char cell = board[i] & ~GTBoxSpot;
117 if ((cell == GTBox) && !(board[i] & GTBoxSpot))
125 void GameBoard::ResetGame(void)
127 memcpy(board, initialBoard, boardLength);
128 playerX = initialX, playerY = initialY;
133 int GameBoard::MovePlayerN(void)
135 // Sanity check (player trying to move into wall)
139 char cell1 = board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot;
140 char cell2 = board[playerX + ((playerY - 2) * width)] & ~GTBoxSpot;
142 return Move(0, -1, cell1, cell2);
146 int GameBoard::MovePlayerS(void)
148 // Sanity check (player trying to move into wall)
149 if (playerY == (height - 2))
152 char cell1 = board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot;
153 char cell2 = board[playerX + ((playerY + 2) * width)] & ~GTBoxSpot;
155 return Move(0, +1, cell1, cell2);
159 int GameBoard::MovePlayerE(void)
161 // Sanity check (player trying to move into wall)
162 if (playerX == (width - 2))
165 char cell1 = board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot;
166 char cell2 = board[(playerX + 2) + (playerY * width)] & ~GTBoxSpot;
168 return Move(+1, 0, cell1, cell2);
172 int GameBoard::MovePlayerW(void)
174 // Sanity check (player trying to move into wall)
178 char cell1 = board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot;
179 char cell2 = board[(playerX - 2) + (playerY * width)] & ~GTBoxSpot;
181 return Move(-1, 0, cell1, cell2);
185 int GameBoard::Move(int dx, int dy, char cell1, char cell2)
187 // Player is moving into an unoccupied space...
188 if (cell1 == GTSpace)
190 playerX += dx, playerY += dy;
191 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMWalk;
195 // Player is pushing a box into an unoccupied space...
196 else if ((cell1 == GTBox) && (cell2 == GTSpace))
198 playerX += dx, playerY += dy;
199 board[playerX + (playerY * width)] &= GTBoxSpot;
200 playerX += dx, playerY += dy;
201 board[playerX + (playerY * width)] |= GTBox;
202 playerX -= dx, playerY -= dy;
203 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMPush;
208 // All other combinations are no good
213 bool GameBoard::IsBoxNOfPlayer(void)
215 if ((board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot) == GTBox)
222 bool GameBoard::IsBoxSOfPlayer(void)
224 if ((board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot) == GTBox)
231 bool GameBoard::IsBoxEOfPlayer(void)
233 if ((board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
240 bool GameBoard::IsBoxWOfPlayer(void)
242 if ((board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
249 bool GameBoard::UndoLastMove(int & dx, int & dy, int & type)
255 dx = undo[numMoves].dx;
256 dy = undo[numMoves].dy;
257 type = undo[numMoves].type;
259 // Undo the box's move (if any)
262 int boxPosition = (playerX + dx) + ((playerY + dy) * width);
263 int newBoxPosition = playerX + (playerY * width);
265 board[boxPosition] &= GTBoxSpot;
266 // board[newBoxPosition] &= GTBoxSpot; // This is extraneous
267 board[newBoxPosition] |= GTBox;
270 // Undo the player's move