]> Shamusworld >> Repos - warehouse-man-deluxe/blob - src/gameboard.cpp
Added board titles.
[warehouse-man-deluxe] / src / gameboard.cpp
1 //
2 // gameboard.cpp: Game board class implementation
3 //
4 // by James Hammons
5 // © 2014 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/01/2014  Created this file
12 //
13
14 #include "gameboard.h"
15 #include <string.h>
16 //#include <stdio.h>    // for printf()
17 #include "boards.h"
18
19
20 GameBoard::GameBoard(int boardNumber)
21 {
22         // Sanity check
23         if (boardNumber > NUMBER_OF_BOARDS)
24                 boardNumber = NUMBER_OF_BOARDS;
25
26         // boardNumber is 1-based
27         Board * boardToUse = (Board *)boards[boardNumber - 1];
28
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]);
35
36         for(int i=0; i<boardLength; i++)
37         {
38                 char c = boardToUse->state[i];
39
40                 if (c == '@')
41                         initialBoard[i] = GTWall;
42                 else if (c == ' ')
43                         initialBoard[i] = GTSpace;
44                 else if (c == 'X')
45                         initialBoard[i] = GTBox;
46                 else if (c == '.')
47                         initialBoard[i] = GTBoxSpot;
48                 else if (c == '+')
49                         initialBoard[i] = GTBox | GTBoxSpot;
50                 else if (c == 'o')
51                 {
52                         initialBoard[i] = GTSpace;
53                         initialX = i % width, initialY = i / width;
54                 }
55                 else
56                         initialBoard[i] = GTNull;
57         }
58
59         ResetGame();
60 }
61
62
63 GameBoard::~GameBoard()
64 {
65         if (board)
66                 delete[] board;
67
68         if (initialBoard)
69                 delete[] initialBoard;
70 }
71
72
73 bool GameBoard::GameHasBeenWon(void)
74 {
75         // Check to see if all boxes are on their spots
76         for(int i=0; i<boardLength; i++)
77         {
78                 char cell = board[i] & ~GTBoxSpot;
79
80                 if ((cell == GTBox) && !(board[i] & GTBoxSpot))
81                         return false;
82         }
83
84         return true;
85 }
86
87
88 void GameBoard::ResetGame(void)
89 {
90         memcpy(board, initialBoard, boardLength);
91         playerX = initialX, playerY = initialY;
92         numMoves = 0;
93 }
94
95
96 int GameBoard::MovePlayerN(void)
97 {
98         // Sanity check (player trying to move into wall)
99         if (playerY == 1)
100                 return PMInvalid;
101
102         char cell1 = board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot;
103         char cell2 = board[playerX + ((playerY - 2) * width)] & ~GTBoxSpot;
104
105         return Move(0, -1, cell1, cell2);
106 }
107
108
109 int GameBoard::MovePlayerS(void)
110 {
111         // Sanity check (player trying to move into wall)
112         if (playerY == (height - 2))
113                 return PMInvalid;
114
115         char cell1 = board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot;
116         char cell2 = board[playerX + ((playerY + 2) * width)] & ~GTBoxSpot;
117
118         return Move(0, +1, cell1, cell2);
119 }
120
121
122 int GameBoard::MovePlayerE(void)
123 {
124         // Sanity check (player trying to move into wall)
125         if (playerX == (width - 2))
126                 return PMInvalid;
127
128         char cell1 = board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot;
129         char cell2 = board[(playerX + 2) + (playerY * width)] & ~GTBoxSpot;
130
131         return Move(+1, 0, cell1, cell2);
132 }
133
134
135 int GameBoard::MovePlayerW(void)
136 {
137         // Sanity check (player trying to move into wall)
138         if (playerX == 1)
139                 return PMInvalid;
140
141         char cell1 = board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot;
142         char cell2 = board[(playerX - 2) + (playerY * width)] & ~GTBoxSpot;
143
144         return Move(-1, 0, cell1, cell2);
145 }
146
147
148 int GameBoard::Move(int dx, int dy, char cell1, char cell2)
149 {
150         // Player is moving into an unoccupied space...
151         if (cell1 == GTSpace)
152         {
153 //              var += direction;
154                 playerX += dx, playerY += dy;
155                 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMWalk;
156                 numMoves++;
157                 return PMWalk;
158         }
159         // Player is pushing a box into an unoccupied space...
160         else if ((cell1 == GTBox) && (cell2 == GTSpace))
161         {
162 //              var += direction;
163                 playerX += dx, playerY += dy;
164                 board[playerX + (playerY * width)] &= GTBoxSpot;
165 //              var += direction;
166                 playerX += dx, playerY += dy;
167                 board[playerX + (playerY * width)] |= GTBox;
168 //              var -= direction;
169                 playerX -= dx, playerY -= dy;
170                 undo[numMoves].dx = dx, undo[numMoves].dy = dy, undo[numMoves].type = PMPush;
171                 numMoves++;
172                 return PMPush;
173         }
174
175         // All other combinations are no good
176         return PMInvalid;
177 }
178
179
180 bool GameBoard::IsBoxNOfPlayer(void)
181 {
182         if ((board[playerX + ((playerY - 1) * width)] & ~GTBoxSpot) == GTBox)
183                 return true;
184
185         return false;
186 }
187
188
189 bool GameBoard::IsBoxSOfPlayer(void)
190 {
191         if ((board[playerX + ((playerY + 1) * width)] & ~GTBoxSpot) == GTBox)
192                 return true;
193
194         return false;
195 }
196
197
198 bool GameBoard::IsBoxEOfPlayer(void)
199 {
200         if ((board[(playerX + 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
201                 return true;
202
203         return false;
204 }
205
206
207 bool GameBoard::IsBoxWOfPlayer(void)
208 {
209         if ((board[(playerX - 1) + (playerY * width)] & ~GTBoxSpot) == GTBox)
210                 return true;
211
212         return false;
213 }
214
215
216 bool GameBoard::UndoLastMove(int & dx, int & dy, int & type)
217 {
218         if (numMoves == 0)
219                 return false;
220
221         numMoves--;
222         dx = undo[numMoves].dx;
223         dy = undo[numMoves].dy;
224         type = undo[numMoves].type;
225
226         // Undo the box's move (if any)
227         if (type == PMPush)
228         {
229                 int boxPosition = (playerX + dx) + ((playerY + dy) * width);
230                 int newBoxPosition = playerX + (playerY * width);
231
232                 board[boxPosition] &= GTBoxSpot;
233 //              board[newBoxPosition] &= GTBoxSpot;     // This is extraneous
234                 board[newBoxPosition] |= GTBox;
235         }
236
237         // Undo the player's move
238         playerX += -dx;
239         playerY += -dy;
240
241         return true;
242 }
243