Updated to include tests for Gentoo installation
[crack-attack.git] / src / Swapper.cxx
blobad50e64bf88c26a48b66cd16f998a30f5f2c3931
1 /*
2 * Swapper.cxx
3 * Daniel Nelson - 8/22/0
5 * Copyright (C) 2000 Daniel Nelson
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Daniel Nelson - aluminumangel.org
22 * 174 W. 18th Ave.
23 * Columbus, OH 43210
25 * The thingy you swap blocks with.
28 using namespace std;
30 #include "Game.h"
31 #include "Swapper.h"
32 #include "Grid.h"
33 #include "Block.h"
34 #include "Controller.h"
35 #include "ComboTabulator.h"
36 #include "ComboManager.h"
37 #include "CountDownManager.h"
38 #include "X.h"
40 int Swapper::x, Swapper::y;
41 int Swapper::state;
42 int Swapper::swap;
43 int Swapper::swap_alarm;
44 int Swapper::move_pause_alarm;
45 bool Swapper::button_down_swap;
46 int Swapper::button_down_move;
47 Block *Swapper::left_block, *Swapper::right_block;
48 int Swapper::queued_move;
49 bool Swapper::queued_swap;
50 float Swapper::swap_factor;
51 int Swapper::color;
53 void Swapper::gameStart ( )
55 x = GC_INITIAL_SWAPPER_LOCATION_X;
56 y = GC_INITIAL_SWAPPER_LOCATION_Y;
58 state = 0;
60 swap_alarm = 0;
61 move_pause_alarm = 0;
63 button_down_swap = false;
64 button_down_move = 0;
66 queued_move = 0;
67 queued_swap = false;
69 color = 0;
72 void Swapper::timeStep ( )
74 * If we're swapping, check to see if we're done. Check the keyboard for any
75 * commands which we must react to.
78 if (!Controller::moveCommand())
79 button_down_move = 0;
80 if (!Controller::swapCommand())
81 button_down_swap = false;
83 if (state & SS_MOVE_PAUSE)
84 // if it's time, unset the move pause state
85 if (move_pause_alarm == Game::time_step)
86 state &= ~SS_MOVE_PAUSE;
88 // otherwise, listen to queue a swap
89 else if (!button_down_swap && Controller::swapCommand()) {
90 if (queued_move) queued_move = 0;
91 queued_swap = true;
92 button_down_swap = true;
94 // otherwise, listen to queue a move
95 } else if (Controller::moveCommand()
96 && button_down_move != Controller::moveCommand() && !queued_swap)
97 queued_move = button_down_move = Controller::moveCommand();
99 if (state & SS_SWAPPING)
100 if (swap_alarm == Game::time_step) {
102 // unset the swap state
103 state &= ~SS_SWAPPING;
105 // swap the blocks
107 if (swap & SA_LEFT)
108 Grid::remove(x, y, left_block);
109 if (swap & SA_RIGHT)
110 Grid::remove(x + 1, y, right_block);
112 #ifndef NDEBUG
113 // otherwise the assert bites us
114 if (!(swap & SA_LEFT))
115 Grid::changeState(x, y, null, GR_EMPTY);
116 if (!(swap & SA_RIGHT))
117 Grid::changeState(x + 1, y, null, GR_EMPTY);
118 #endif
120 if (swap & SA_LEFT)
121 left_block->finishSwapping(x + 1);
122 if (swap & SA_RIGHT)
123 right_block->finishSwapping(x);
125 // register blocks for elimination checking
127 // if two blocks moved, we need a combo tabulator to link potential
128 // pattern matches
129 ComboTabulator *combo = (swap == (SA_LEFT | SA_RIGHT)
130 ? &ComboManager::newComboTabulator() : null);
132 if (swap & SA_LEFT)
133 Grid::requestEliminationCheck(*left_block, combo);
134 if (swap & SA_RIGHT)
135 Grid::requestEliminationCheck(*right_block, combo);
137 // listen to queue a move
138 if (!button_down_move && Controller::moveCommand())
139 queued_move = button_down_move = Controller::moveCommand();
141 // no commands when we're swapping
142 return;
144 } else
145 swap_factor = (Game::time_step - Swapper::swap_alarm)
146 * (1.0f / (float) GC_SWAP_DELAY);
148 if (state & SS_SWAPPING) {
149 // listen to queue a move
150 if (!button_down_move && Controller::moveCommand())
151 queued_move = button_down_move = Controller::moveCommand();
153 // no commands when we're swapping
154 return;
157 // if we're not in a move pause or swap
158 if (!(state & (SS_MOVE_PAUSE | SS_SWAPPING)) && (queued_move
159 || (Controller::moveCommand()
160 && button_down_move != Controller::moveCommand()))) {
161 switch (queued_move ? queued_move : Controller::moveCommand()) {
162 case CC_LEFT:
163 if (!X::reverseControls()) {
164 if (x > 0) {
165 x--;
166 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_LEFT | SS_MOVE_PAUSE);
167 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
168 button_down_move = CC_LEFT;
170 } else {
171 if (x < GC_PLAY_WIDTH - 2) {
172 x++;
173 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_RIGHT | SS_MOVE_PAUSE);
174 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
175 button_down_move = CC_LEFT;
178 break;
179 case CC_RIGHT:
180 if (!X::reverseControls()) {
181 if (x < GC_PLAY_WIDTH - 2) {
182 x++;
183 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_RIGHT | SS_MOVE_PAUSE);
184 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
185 button_down_move = CC_RIGHT;
187 } else {
188 if (x > 0) {
189 x--;
190 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_LEFT | SS_MOVE_PAUSE);
191 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
192 button_down_move = CC_RIGHT;
195 break;
196 case CC_UP:
197 if (!X::reverseControls()) {
198 if (y < GC_SAFE_HEIGHT - 1) {
199 y++;
200 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_UP | SS_MOVE_PAUSE);
201 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
202 button_down_move = CC_UP;
204 } else {
205 if (y > 1) {
206 y--;
207 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_DOWN | SS_MOVE_PAUSE);
208 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
209 button_down_move = CC_UP;
212 break;
213 case CC_DOWN:
214 if (!X::reverseControls()) {
215 if (y > 1) {
216 y--;
217 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_DOWN | SS_MOVE_PAUSE);
218 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
219 button_down_move = CC_DOWN;
221 } else {
222 if (y < GC_SAFE_HEIGHT - 1) {
223 y++;
224 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_UP | SS_MOVE_PAUSE);
225 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
226 button_down_move = CC_DOWN;
229 break;
231 queued_move = 0;
234 if (!(state & (SS_MOVE_PAUSE | SS_SWAPPING)) && (queued_swap
235 || (Controller::swapCommand() && !button_down_swap))
236 && CountDownManager::start_pause_alarm == 0) {
238 button_down_swap = true;
239 queued_swap = false;
241 swap = 0;
242 if (Grid::stateAt(x, y) & GR_BLOCK) {
243 left_block = &Grid::blockAt(x, y);
244 swap |= SA_LEFT;
245 } else if (!(Grid::stateAt(x, y) & GR_EMPTY)
246 || Grid::stateAt(x, y - 1) & GR_FALLING
247 || Grid::stateAt(x, y + 1) & GR_HANGING)
248 swap |= SA_DISALLOWED;
250 if (Grid::stateAt(x + 1, y) & GR_BLOCK) {
251 right_block = &Grid::blockAt(x + 1, y);
252 swap |= SA_RIGHT;
253 } else if (!(Grid::stateAt(x + 1, y) & GR_EMPTY)
254 || Grid::stateAt(x + 1, y - 1) & GR_FALLING
255 || Grid::stateAt(x + 1, y + 1) & GR_HANGING)
256 swap |= SA_DISALLOWED;
258 // if swap is allowed
259 if (!(swap & SA_DISALLOWED) && swap != 0) {
261 // change our state
262 state |= SS_SWAPPING;
264 // set the alarm
265 swap_alarm = Game::time_step + GC_SWAP_DELAY;
267 // start the swapping
268 if (swap & SA_LEFT)
269 left_block->startSwapping(SA_RIGHT);
270 else
271 Grid::changeState(x, y, null, GR_IMMUTABLE);
273 if (swap & SA_RIGHT)
274 right_block->startSwapping(SA_LEFT);
275 else
276 Grid::changeState(x + 1, y, null, GR_IMMUTABLE);
278 // initialize the swap factor
279 swap_factor = -1.0f;