Each module now includes its own header first. Removed sstream.h and the definition...
[crack-attack.git] / src / Swapper.cxx
blob44ecc8705902da3f69d08f3bf6786a44901d284d
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 #include "Swapper.h"
30 #include "Game.h"
31 #include "Grid.h"
32 #include "Block.h"
33 #include "Controller.h"
34 #include "ComboTabulator.h"
35 #include "ComboManager.h"
36 #include "CountDownManager.h"
37 #include "X.h"
39 int Swapper::x, Swapper::y;
40 int Swapper::state;
41 int Swapper::swap;
42 int Swapper::swap_alarm;
43 int Swapper::move_pause_alarm;
44 bool Swapper::button_down_swap;
45 int Swapper::button_down_move;
46 Block *Swapper::left_block, *Swapper::right_block;
47 int Swapper::queued_move;
48 bool Swapper::queued_swap;
49 float Swapper::swap_factor;
50 int Swapper::color;
52 void Swapper::gameStart ( )
54 x = GC_INITIAL_SWAPPER_LOCATION_X;
55 y = GC_INITIAL_SWAPPER_LOCATION_Y;
57 state = 0;
59 swap_alarm = 0;
60 move_pause_alarm = 0;
62 button_down_swap = false;
63 button_down_move = 0;
65 queued_move = 0;
66 queued_swap = false;
68 color = 0;
71 void Swapper::timeStep ( )
73 * If we're swapping, check to see if we're done. Check the keyboard for any
74 * commands which we must react to.
77 if (!Controller::moveCommand())
78 button_down_move = 0;
79 if (!Controller::swapCommand())
80 button_down_swap = false;
82 if (state & SS_MOVE_PAUSE)
83 // if it's time, unset the move pause state
84 if (move_pause_alarm == Game::time_step)
85 state &= ~SS_MOVE_PAUSE;
87 // otherwise, listen to queue a swap
88 else if (!button_down_swap && Controller::swapCommand()) {
89 if (queued_move) queued_move = 0;
90 queued_swap = true;
91 button_down_swap = true;
93 // otherwise, listen to queue a move
94 } else if (Controller::moveCommand()
95 && button_down_move != Controller::moveCommand() && !queued_swap)
96 queued_move = button_down_move = Controller::moveCommand();
98 if (state & SS_SWAPPING)
99 if (swap_alarm == Game::time_step) {
101 // unset the swap state
102 state &= ~SS_SWAPPING;
104 // swap the blocks
106 if (swap & SA_LEFT)
107 Grid::remove(x, y, left_block);
108 if (swap & SA_RIGHT)
109 Grid::remove(x + 1, y, right_block);
111 #ifndef NDEBUG
112 // otherwise the assert bites us
113 if (!(swap & SA_LEFT))
114 Grid::changeState(x, y, null, GR_EMPTY);
115 if (!(swap & SA_RIGHT))
116 Grid::changeState(x + 1, y, null, GR_EMPTY);
117 #endif
119 if (swap & SA_LEFT)
120 left_block->finishSwapping(x + 1);
121 if (swap & SA_RIGHT)
122 right_block->finishSwapping(x);
124 // register blocks for elimination checking
126 // if two blocks moved, we need a combo tabulator to link potential
127 // pattern matches
128 ComboTabulator *combo = (swap == (SA_LEFT | SA_RIGHT)
129 ? &ComboManager::newComboTabulator() : null);
131 if (swap & SA_LEFT)
132 Grid::requestEliminationCheck(*left_block, combo);
133 if (swap & SA_RIGHT)
134 Grid::requestEliminationCheck(*right_block, combo);
136 // listen to queue a move
137 if (!button_down_move && Controller::moveCommand())
138 queued_move = button_down_move = Controller::moveCommand();
140 // no commands when we're swapping
141 return;
143 } else
144 swap_factor = (Game::time_step - Swapper::swap_alarm)
145 * (1.0f / (float) GC_SWAP_DELAY);
147 if (state & SS_SWAPPING) {
148 // listen to queue a move
149 if (!button_down_move && Controller::moveCommand())
150 queued_move = button_down_move = Controller::moveCommand();
152 // no commands when we're swapping
153 return;
156 // if we're not in a move pause or swap
157 if (!(state & (SS_MOVE_PAUSE | SS_SWAPPING)) && (queued_move
158 || (Controller::moveCommand()
159 && button_down_move != Controller::moveCommand()))) {
160 switch (queued_move ? queued_move : Controller::moveCommand()) {
161 case CC_LEFT:
162 if (!X::reverseControls()) {
163 if (x > 0) {
164 x--;
165 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_LEFT | SS_MOVE_PAUSE);
166 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
167 button_down_move = CC_LEFT;
169 } else {
170 if (x < GC_PLAY_WIDTH - 2) {
171 x++;
172 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_RIGHT | SS_MOVE_PAUSE);
173 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
174 button_down_move = CC_LEFT;
177 break;
178 case CC_RIGHT:
179 if (!X::reverseControls()) {
180 if (x < GC_PLAY_WIDTH - 2) {
181 x++;
182 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_RIGHT | SS_MOVE_PAUSE);
183 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
184 button_down_move = CC_RIGHT;
186 } else {
187 if (x > 0) {
188 x--;
189 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_LEFT | SS_MOVE_PAUSE);
190 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
191 button_down_move = CC_RIGHT;
194 break;
195 case CC_UP:
196 if (!X::reverseControls()) {
197 if (y < GC_SAFE_HEIGHT - 1) {
198 y++;
199 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_UP | SS_MOVE_PAUSE);
200 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
201 button_down_move = CC_UP;
203 } else {
204 if (y > 1) {
205 y--;
206 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_DOWN | SS_MOVE_PAUSE);
207 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
208 button_down_move = CC_UP;
211 break;
212 case CC_DOWN:
213 if (!X::reverseControls()) {
214 if (y > 1) {
215 y--;
216 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_DOWN | SS_MOVE_PAUSE);
217 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
218 button_down_move = CC_DOWN;
220 } else {
221 if (y < GC_SAFE_HEIGHT - 1) {
222 y++;
223 state = (state & ~SS_MOVE_MASK) | (SS_MOVE_UP | SS_MOVE_PAUSE);
224 move_pause_alarm = Game::time_step + GC_MOVE_DELAY;
225 button_down_move = CC_DOWN;
228 break;
230 queued_move = 0;
233 if (!(state & (SS_MOVE_PAUSE | SS_SWAPPING)) && (queued_swap
234 || (Controller::swapCommand() && !button_down_swap))
235 && CountDownManager::start_pause_alarm == 0) {
237 button_down_swap = true;
238 queued_swap = false;
240 swap = 0;
241 if (Grid::stateAt(x, y) & GR_BLOCK) {
242 left_block = &Grid::blockAt(x, y);
243 swap |= SA_LEFT;
244 } else if (!(Grid::stateAt(x, y) & GR_EMPTY)
245 || Grid::stateAt(x, y - 1) & GR_FALLING
246 || Grid::stateAt(x, y + 1) & GR_HANGING)
247 swap |= SA_DISALLOWED;
249 if (Grid::stateAt(x + 1, y) & GR_BLOCK) {
250 right_block = &Grid::blockAt(x + 1, y);
251 swap |= SA_RIGHT;
252 } else if (!(Grid::stateAt(x + 1, y) & GR_EMPTY)
253 || Grid::stateAt(x + 1, y - 1) & GR_FALLING
254 || Grid::stateAt(x + 1, y + 1) & GR_HANGING)
255 swap |= SA_DISALLOWED;
257 // if swap is allowed
258 if (!(swap & SA_DISALLOWED) && swap != 0) {
260 // change our state
261 state |= SS_SWAPPING;
263 // set the alarm
264 swap_alarm = Game::time_step + GC_SWAP_DELAY;
266 // start the swapping
267 if (swap & SA_LEFT)
268 left_block->startSwapping(SA_RIGHT);
269 else
270 Grid::changeState(x, y, null, GR_IMMUTABLE);
272 if (swap & SA_RIGHT)
273 right_block->startSwapping(SA_LEFT);
274 else
275 Grid::changeState(x + 1, y, null, GR_IMMUTABLE);
277 // initialize the swap factor
278 swap_factor = -1.0f;