Revert to Dennis Lubert's patch rather than my "fixes"
[crack-attack.git] / src / Game.cxx
blobe7ebaed253962c2931a5ec12155b1b28b57a0a46
1 /*
2 * Game.cxx
3 * Daniel Nelson - 8/25/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 core loop plus extras.
26 * Remove dying_count_2.
29 #include <GL/glut.h>
31 #ifndef _WIN32
32 #else
33 # include <glext.h>
34 #endif
36 #include <sys/time.h>
38 using namespace std;
40 #include "Game.h"
41 #include "BlockManager.h"
42 #include "CelebrationManager.h"
43 #include "Clock.h"
44 #include "Controller.h"
45 #include "Communicator.h"
46 #include "ComboManager.h"
47 #include "CountDownManager.h"
48 #include "Creep.h"
49 #include "GarbageGenerator.h"
50 #include "GarbageManager.h"
51 #include "Grid.h"
52 #include "LevelLights.h"
53 #include "LoseBar.h"
54 #include "MessageManager.h"
55 #include "MetaState.h"
56 #include "Random.h"
57 #include "Score.h"
58 #include "ScoreRecordManager.h"
59 #include "SignManager.h"
60 #include "Sine.h"
61 #include "SparkleManager.h"
62 #include "Spring.h"
63 #include "Swapper.h"
64 #include "WinRecord.h"
65 #include "X.h"
67 int Game::time_step;
68 int Game::state;
69 int Game::awaking_count;
70 int Game::dying_count;
71 int Game::dying_count_2;
72 int Game::previous_time;
73 int Game::remaining_time;
74 bool Game::button_down_pause;
75 bool Game::step_play;
76 int Game::sync_wait;
77 double Game::lastframe = 0.0;
79 void Game::initialize ( )
81 Random::initialize();
82 WinRecord::initialize();
83 LevelLights::initialize();
84 Score::initialize();
85 Sine::initialize();
86 LoseBar::initialize();
88 gameFinish();
91 void Game::gameStart ( )
93 state = GS_NORMAL;
95 awaking_count = 0;
96 dying_count = 0;
98 WinRecord::gameStart();
100 BlockManager::gameStart();
101 GarbageManager::gameStart();
102 ComboManager::gameStart();
103 GarbageGenerator::gameStart();
104 X::gameStart();
105 Grid::gameStart();
106 Controller::gameStart();
107 Creep::gameStart();
108 Swapper::gameStart();
109 Spring::gameStart();
110 LevelLights::gameStart();
111 CountDownManager::gameStart();
112 Clock::gameStart();
113 LoseBar::gameStart();
115 button_down_pause = false;
117 step_play = true;
119 remaining_time = 0;
120 time_step = 1;
123 void Game::gameFinish ( )
125 remaining_time = 0;
126 time_step = 1;
129 void Game::cleanUp ( )
131 CountDownManager::cleanUp();
132 Score::cleanUp();
135 void Game::loss ( )
137 * Called when creep detects a game loss condition; opponent may have already
138 * lost, so me must wait for confirmation.
141 if (!(MetaState::mode & CM_SOLO)) {
142 if (!(state & (GS_MAY_HAVE_LOST | GS_WON))) {
143 state = GS_MAY_HAVE_LOST;
144 Communicator::setLossTimeStep();
146 } else
147 state |= GS_END_PLAY;
150 void Game::lossConfirmation ( )
152 * Called by Communicator when opponent confirms game loss. Now we must only
153 * wait for the level lights to end play.
156 state = GS_LOST | GS_END_PLAY;
159 void Game::won ( )
161 * Called by Communicator when opponent signals a game loss that predates
162 * ours or signals a reverse of our game loss. Now we must wait to confirm
163 * our opponent's loss and for the level lights to end play.
166 if (!(state & GS_WON))
167 state = GS_WON | GS_MUST_CONFIRM_LOSS;
170 void Game::concession ( )
172 * Called by the controller upon player concession.
175 if (CountDownManager::start_pause_alarm != 0) return;
177 loss();
178 MetaState::state |= MS_CONCESSION;
181 void Game::buttonPause ( )
182 // run time step during pause (for Communicator); then reset the clock to the
183 // value at the pause time
185 // unpause
186 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) == GS_PAUSED) {
187 state = GS_NORMAL;
189 MessageManager::freeMessage();
190 if (CountDownManager::state != -1)
191 MessageManager::readyMessage(CountDownManager::state);
193 if (!(MetaState::mode & CM_SOLO)) {
194 Communicator::unpauseSyncCheck();
195 Communicator::signalUnpaused();
198 // pause
199 } else {
200 // to simplify things, you can't pause if you're about to lose
201 if (!(state & GS_NORMAL)) return;
203 state = GS_PAUSED;
205 if (CountDownManager::state != -1)
206 MessageManager::freeMessage();
207 MessageManager::readyMessage(MS_PAUSED);
209 if (!(MetaState::mode & CM_SOLO))
210 Communicator::signalPaused();
214 void Game::netSignalPause ( )
216 if (!(state & GS_NORMAL)) return;
218 state = GS_PAUSED;
220 if (CountDownManager::state != -1)
221 MessageManager::freeMessage();
222 MessageManager::readyMessage(MS_PAUSED);
225 void Game::netSignalUnpause ( )
227 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) != GS_PAUSED) return;
229 state = GS_NORMAL;
231 MessageManager::freeMessage();
232 if (CountDownManager::state != -1)
233 MessageManager::readyMessage(CountDownManager::state);
236 void Game::syncPause ( int delay )
238 assert(delay > 0);
240 state = GS_PAUSED | GS_SYNC_WAIT;
241 sync_wait = delay;
243 if (CountDownManager::state != -1)
244 MessageManager::freeMessage();
245 MessageManager::readyMessage(MS_WAITING);
248 void Game::syncUnpause ( )
250 state = GS_NORMAL;
252 MessageManager::freeMessage();
253 if (CountDownManager::state != -1)
254 MessageManager::readyMessage(CountDownManager::state);
257 void Game::idleMeta ( )
259 int modified_and_complete = false;
261 do {
263 int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
264 remaining_time += time - previous_time;
265 previous_time = time;
267 // no time step yet
268 if (remaining_time < GC_TIME_STEP_PERIOD) break;
270 remaining_time -= GC_TIME_STEP_PERIOD;
271 time_step++;
273 if (remaining_time < GC_TIME_STEP_PERIOD)
274 modified_and_complete = true;
275 else
276 DOT(3);
278 // communicate state and other stuff
279 if (!(MetaState::state & MS_GAME_OVER_KEY_WAIT) &&
280 !(MetaState::mode & CM_SOLO))
281 Communicator::timeStepMeta();
283 // advance celebration
284 CelebrationManager::timeStep();
286 // advance the score record
287 ScoreRecordManager::timeStep();
289 // update message pulse
290 MessageManager::timeStep();
292 // update the pretty stuff too
293 SparkleManager::timeStep();
294 SignManager::timeStep();
295 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
296 WinRecord::timeStep();
297 LevelLights::timeStep();
299 // advance the clock through its final tick fade
300 Clock::timeStepMeta();
302 // advance the score through its final increment fade
303 Score::timeStepMeta();
305 } while (false);
307 if (modified_and_complete) {
308 glFinish();
309 glutPostRedisplay();
313 void Game::idlePlay ( )
315 timeval now;
316 double nowd;
317 gettimeofday(&now,NULL);
318 #define FPSDIFF (1.0f/30.0f)
319 nowd = now.tv_sec;
320 nowd += (double)now.tv_usec / 1000000.0f;
322 if ( (nowd - lastframe) > FPSDIFF ) {
323 lastframe = nowd;
324 } else {
325 usleep(1000);
328 int modified_and_complete = false;
330 do {
332 //int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
333 remaining_time += time - previous_time;
334 previous_time = time;
336 // no time step yet
337 if (remaining_time < GC_TIME_STEP_PERIOD) break;
339 remaining_time -= GC_TIME_STEP_PERIOD;
341 if (remaining_time < GC_TIME_STEP_PERIOD)
342 modified_and_complete = true;
343 else
344 DOT(2);
346 if (!(state & GS_PAUSED)) {
347 if (step_play) {
349 time_step++;
351 // check for and continue swaps and moves
352 Swapper::timeStep();
354 // update the level lights
355 LevelLights::timeStep();
357 // update message pulse
358 MessageManager::timeStep();
360 // move the win record stars
361 WinRecord::timeStep();
363 // update the starting count down
364 CountDownManager::timeStep();
365 if (CountDownManager::start_pause_alarm != 0) {
366 // some objects require a time step during start pause
368 if (!(MetaState::mode & CM_SOLO))
369 Communicator::timeStepPlay();
371 // reset the clock
372 Clock::timeStepMeta();
374 continue;
377 // loop over the grid, bottom to top; garbage will advance x and y
378 for (int y = 1; y < GC_PLAY_HEIGHT; y++)
379 for (int x = 0; x < GC_PLAY_WIDTH; x++) {
380 if (Grid::residentTypeAt(x, y) & GR_EMPTY) continue;
382 if (Grid::residentTypeAt(x, y) & GR_BLOCK)
383 Grid::blockAt(x, y).timeStep();
384 else
385 Grid::garbageAt(x, y).timeStep(x, y);
388 // perhaps creep upward
389 Creep::timeStep();
391 // process elimination check requests and update top_occupied_row
392 Grid::timeStep();
394 // handle new and finished combos
395 ComboManager::timeStep();
398 // communicate garbage and other stuff
399 if (!(MetaState::mode & CM_SOLO))
400 Communicator::timeStepPlay();
402 if (step_play) {
404 // drop queued garbage
405 GarbageGenerator::timeStep();
407 // move the sparkles and signs
408 SparkleManager::timeStep();
409 SignManager::timeStep();
411 // update the impact spring
412 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
413 Spring::timeStep();
415 // update the clock
416 Clock::timeStepPlay();
418 // update the score
419 Score::timeStepPlay();
421 // update the losebar
422 LoseBar::timeStep();
424 // advance extreme effects
425 if (MetaState::mode & CM_X)
426 X::timeStep();
429 } else {
431 // if this is a sync pause, count down the waiting period
432 if (state & GS_SYNC_WAIT && !--sync_wait)
433 syncUnpause();
435 // communicate when paused
436 if (!(MetaState::mode & CM_SOLO))
437 Communicator::timeStepPlay();
439 // update message pulse
440 MessageManager::timeStep();
443 if (state & (GS_MAY_HAVE_LOST | GS_MUST_CONFIRM_LOSS))
444 step_play = false;
446 if (state & GS_END_PLAY) {
447 if (state & GS_PAUSED)
448 MessageManager::freeMessage();
450 if (MetaState::mode & CM_SOLO)
451 state = Score::gameFinish();
453 if (state & GS_LOST)
454 MetaState::gameLoss();
455 else
456 MetaState::gameWon();
458 break;
461 } while (false);
463 if (!button_down_pause) {
464 if (Controller::pauseCommand()) {
465 button_down_pause = true;
466 buttonPause();
468 } else
469 if (!Controller::pauseCommand())
470 button_down_pause = false;
472 if (modified_and_complete) {
473 glFinish();
474 glutPostRedisplay();