Fixes for datatype size on amd64.
[crack-attack.git] / src / Game.cxx
blob1b6618f5d012b4e586291c7e43d3217f2e0f9fbe
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 "Game.h"
31 #include <GL/glut.h>
33 #include "glext.h"
35 #include <sys/time.h>
37 #include <cassert>
39 #include "BlockManager.h"
40 #include "CelebrationManager.h"
41 #include "Clock.h"
42 #include "Controller.h"
43 #include "ActionRecorder.h"
44 #include "Communicator.h"
45 #include "ComboManager.h"
46 #include "CountDownManager.h"
47 #include "Creep.h"
48 #include "GarbageGenerator.h"
49 #include "GarbageManager.h"
50 #include "Grid.h"
51 #include "LevelLights.h"
52 #include "LoseBar.h"
53 #include "MessageManager.h"
54 #include "MetaState.h"
55 #include "Random.h"
56 #include "Score.h"
57 #include "ScoreRecordManager.h"
58 #include "SignManager.h"
59 #include "Sine.h"
60 #include "SparkleManager.h"
61 #include "Spring.h"
62 #include "Swapper.h"
63 #include "WinRecord.h"
64 #include "X.h"
65 #include "ComputerPlayer.h"
66 #ifdef AUDIO_ENABLED
67 #include "Music.h"
68 #endif
70 int Game::time_step;
71 int Game::state;
72 int Game::awaking_count;
73 int Game::dying_count;
74 int Game::dying_count_2;
75 int Game::previous_time;
76 int Game::remaining_time;
77 bool Game::button_down_pause;
78 bool Game::step_play;
79 int Game::sync_wait;
80 double Game::lastframe = 0.0;
82 void Game::initialize ( )
84 Random::initialize();
85 WinRecord::initialize();
86 LevelLights::initialize();
87 Score::initialize();
88 Sine::initialize();
89 LoseBar::initialize();
90 ActionRecorder::initialize();
92 gameFinish();
95 void Game::gameStart ( )
97 state = GS_NORMAL;
99 awaking_count = 0;
100 dying_count = 0;
102 WinRecord::gameStart();
104 BlockManager::gameStart();
105 GarbageManager::gameStart();
106 ComboManager::gameStart();
107 GarbageGenerator::gameStart();
108 X::gameStart();
109 Grid::gameStart();
110 Controller::gameStart();
111 Creep::gameStart();
112 Swapper::gameStart();
113 Spring::gameStart();
114 LevelLights::gameStart();
115 CountDownManager::gameStart();
116 Clock::gameStart();
117 LoseBar::gameStart();
118 ComputerPlayer::gameStart();
120 button_down_pause = false;
122 step_play = true;
124 remaining_time = 0;
125 time_step = 1;
128 void Game::gameFinish ( )
130 remaining_time = 0;
131 time_step = 1;
134 void Game::cleanUp ( )
136 CountDownManager::cleanUp();
137 Score::cleanUp();
140 void Game::loss ( )
142 * Called when creep detects a game loss condition; opponent may have already
143 * lost, so me must wait for confirmation.
146 if (!(MetaState::mode & CM_SOLO)) {
147 if (!(state & (GS_MAY_HAVE_LOST | GS_WON))) {
148 state = GS_MAY_HAVE_LOST;
149 Communicator::setLossTimeStep();
151 } else
152 state |= GS_END_PLAY;
155 void Game::lossConfirmation ( )
157 * Called by Communicator when opponent confirms game loss. Now we must only
158 * wait for the level lights to end play.
161 state = GS_LOST | GS_END_PLAY;
164 void Game::aiPlayerLoss ( )
166 if (!(state & GS_WON) && !(state & GS_END_PLAY))
167 state = GS_WON | GS_END_PLAY;
170 void Game::won ( )
172 * Called by Communicator when opponent signals a game loss that predates
173 * ours or signals a reverse of our game loss. Now we must wait to confirm
174 * our opponent's loss and for the level lights to end play.
177 if (!(state & GS_WON))
178 state = GS_WON | GS_MUST_CONFIRM_LOSS;
181 void Game::concession ( )
183 * Called by the controller upon player concession.
186 if (CountDownManager::start_pause_alarm != 0) return;
188 loss();
189 MetaState::state |= MS_CONCESSION;
192 void Game::buttonPause ( )
193 // run time step during pause (for Communicator); then reset the clock to the
194 // value at the pause time
196 // unpause
197 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) == GS_PAUSED) {
198 state = GS_NORMAL;
200 MessageManager::freeMessage();
201 if (CountDownManager::state != -1)
202 MessageManager::readyMessage(CountDownManager::state);
204 if (!(MetaState::mode & CM_SOLO)) {
205 Communicator::unpauseSyncCheck();
206 Communicator::signalUnpaused();
208 #ifdef AUDIO_ENABLED
209 Music::resume();
210 #endif
212 // pause
213 } else {
214 // to simplify things, you can't pause if you're about to lose
215 if (!(state & GS_NORMAL)) return;
217 state = GS_PAUSED;
219 if (CountDownManager::state != -1)
220 MessageManager::freeMessage();
221 MessageManager::readyMessage(MS_PAUSED);
223 if (!(MetaState::mode & CM_SOLO))
224 Communicator::signalPaused();
225 #ifdef AUDIO_ENABLED
226 Music::pause();
227 #endif
231 void Game::netSignalPause ( )
233 if (!(state & GS_NORMAL)) return;
235 state = GS_PAUSED;
237 if (CountDownManager::state != -1)
238 MessageManager::freeMessage();
239 MessageManager::readyMessage(MS_PAUSED);
242 void Game::netSignalUnpause ( )
244 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) != GS_PAUSED) return;
246 state = GS_NORMAL;
248 MessageManager::freeMessage();
249 if (CountDownManager::state != -1)
250 MessageManager::readyMessage(CountDownManager::state);
253 void Game::syncPause ( int delay )
255 assert(delay > 0);
257 state = GS_PAUSED | GS_SYNC_WAIT;
258 sync_wait = delay;
260 if (CountDownManager::state != -1)
261 MessageManager::freeMessage();
262 MessageManager::readyMessage(MS_WAITING);
265 void Game::syncUnpause ( )
267 state = GS_NORMAL;
269 MessageManager::freeMessage();
270 if (CountDownManager::state != -1)
271 MessageManager::readyMessage(CountDownManager::state);
274 void Game::idleMeta ( )
276 #ifndef _WIN32
277 timeval now;
278 double nowd;
279 gettimeofday(&now,NULL);
280 #define FPSDIFF (1.0f/30.0f)
281 nowd = now.tv_sec;
282 nowd += (double)now.tv_usec / 1000000.0f;
284 if ( (nowd - lastframe) > FPSDIFF ) {
285 lastframe = nowd;
286 } else {
287 usleep(1000);
289 #endif
291 int modified_and_complete = false;
293 do {
295 int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
296 remaining_time += time - previous_time;
297 previous_time = time;
299 // no time step yet
300 if (remaining_time < GC_TIME_STEP_PERIOD) break;
302 remaining_time -= GC_TIME_STEP_PERIOD;
303 time_step++;
305 if (remaining_time < GC_TIME_STEP_PERIOD)
306 modified_and_complete = true;
307 else
308 DOT(3);
310 // communicate state and other stuff
311 if (!(MetaState::state & MS_GAME_OVER_KEY_WAIT) &&
312 !(MetaState::mode & CM_SOLO))
313 Communicator::timeStepMeta();
315 // advance celebration
316 CelebrationManager::timeStep();
318 // advance the score record
319 ScoreRecordManager::timeStep();
321 // update message pulse
322 MessageManager::timeStep();
324 // update the pretty stuff too
325 SparkleManager::timeStep();
326 SignManager::timeStep();
327 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
328 WinRecord::timeStep();
329 LevelLights::timeStep();
331 // advance the clock through its final tick fade
332 Clock::timeStepMeta();
334 // advance the score through its final increment fade
335 Score::timeStepMeta();
337 } while (false);
339 if (modified_and_complete) {
340 glFinish();
341 glutPostRedisplay();
345 void Game::idlePlay ( )
347 #ifndef _WIN32
348 timeval now;
349 double nowd;
350 gettimeofday(&now,NULL);
351 #define FPSDIFF (1.0f/30.0f)
352 nowd = now.tv_sec;
353 nowd += (double)now.tv_usec / 1000000.0f;
355 if ( (nowd - lastframe) > FPSDIFF ) {
356 lastframe = nowd;
357 } else {
358 usleep(1000);
360 #endif
362 int modified_and_complete = false;
364 do {
366 int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
367 remaining_time += time - previous_time;
368 previous_time = time;
370 // no time step yet
371 if (remaining_time < GC_TIME_STEP_PERIOD) break;
373 remaining_time -= GC_TIME_STEP_PERIOD;
375 if (remaining_time < GC_TIME_STEP_PERIOD)
376 modified_and_complete = true;
377 else
378 DOT(2);
380 if (!(state & GS_PAUSED)) {
381 if (step_play) {
383 time_step++;
385 // check for and continue swaps and moves
386 Swapper::timeStep();
388 // update the level lights
389 LevelLights::timeStep();
391 // update message pulse
392 MessageManager::timeStep();
394 // move the win record stars
395 WinRecord::timeStep();
397 // update the starting count down
398 CountDownManager::timeStep();
399 if (CountDownManager::start_pause_alarm != 0) {
400 // some objects require a time step during start pause
402 if (!(MetaState::mode & CM_SOLO))
403 Communicator::timeStepPlay();
405 // reset the clock
406 Clock::timeStepMeta();
408 continue;
411 if (MetaState::mode & CM_AI)
412 ComputerPlayer::timeStep();
414 // loop over the grid, bottom to top; garbage will advance x and y
415 for (int y = 1; y < GC_PLAY_HEIGHT; y++)
416 for (int x = 0; x < GC_PLAY_WIDTH; x++) {
417 if (Grid::residentTypeAt(x, y) & GR_EMPTY) continue;
419 if (Grid::residentTypeAt(x, y) & GR_BLOCK)
420 Grid::blockAt(x, y).timeStep();
421 else
422 Grid::garbageAt(x, y).timeStep(x, y);
425 // perhaps creep upward
426 Creep::timeStep();
428 // process elimination check requests and update top_occupied_row
429 Grid::timeStep();
431 // handle new and finished combos
432 ComboManager::timeStep();
435 // communicate garbage and other stuff
436 if (!(MetaState::mode & CM_SOLO))
437 Communicator::timeStepPlay();
439 if (step_play) {
441 // drop queued garbage
442 GarbageGenerator::timeStep();
444 // move the sparkles and signs
445 SparkleManager::timeStep();
446 SignManager::timeStep();
448 // update the impact spring
449 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
450 Spring::timeStep();
452 // update the clock
453 Clock::timeStepPlay();
455 // update the score
456 Score::timeStepPlay();
458 // update the losebar
459 LoseBar::timeStep();
461 // advance extreme effects
462 if (MetaState::mode & CM_X)
463 X::timeStep();
466 } else {
468 // if this is a sync pause, count down the waiting period
469 if (state & GS_SYNC_WAIT && !--sync_wait)
470 syncUnpause();
472 // communicate when paused
473 if (!(MetaState::mode & CM_SOLO))
474 Communicator::timeStepPlay();
476 // update message pulse
477 MessageManager::timeStep();
480 if (state & (GS_MAY_HAVE_LOST | GS_MUST_CONFIRM_LOSS))
481 step_play = false;
483 if (state & GS_END_PLAY) {
484 // step_play = false;
485 if (state & GS_PAUSED)
486 MessageManager::freeMessage();
488 if ((MetaState::mode & CM_SOLO) && !(MetaState::mode & CM_AI))
489 state = Score::gameFinish();
491 if (MetaState::mode & CM_AI)
492 state = ComputerPlayer::gameFinish();
494 ActionRecorder::gameFinish();
496 if (state & GS_LOST)
497 MetaState::gameLoss();
498 else
499 MetaState::gameWon();
501 break;
504 } while (false);
506 if (!button_down_pause) {
507 if (Controller::pauseCommand()) {
508 button_down_pause = true;
509 buttonPause();
511 } else
512 if (!Controller::pauseCommand())
513 button_down_pause = false;
515 if (modified_and_complete) {
516 glFinish();
517 glutPostRedisplay();