desktop file ended up in the wrong place.
[crack-attack.git] / src / Game.cxx
blob340321ddee9b90af1e721f03f5538e1cec30e121
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 #include <cassert>
40 using namespace std;
42 #include "Game.h"
43 #include "BlockManager.h"
44 #include "CelebrationManager.h"
45 #include "Clock.h"
46 #include "Controller.h"
47 #include "Communicator.h"
48 #include "ComboManager.h"
49 #include "CountDownManager.h"
50 #include "Creep.h"
51 #include "GarbageGenerator.h"
52 #include "GarbageManager.h"
53 #include "Grid.h"
54 #include "LevelLights.h"
55 #include "LoseBar.h"
56 #include "MessageManager.h"
57 #include "MetaState.h"
58 #include "Random.h"
59 #include "Score.h"
60 #include "ScoreRecordManager.h"
61 #include "SignManager.h"
62 #include "Sine.h"
63 #include "SparkleManager.h"
64 #include "Spring.h"
65 #include "Swapper.h"
66 #include "WinRecord.h"
67 #include "X.h"
68 #include "ComputerPlayer.h"
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();
91 gameFinish();
94 void Game::gameStart ( )
96 state = GS_NORMAL;
98 awaking_count = 0;
99 dying_count = 0;
101 WinRecord::gameStart();
103 BlockManager::gameStart();
104 GarbageManager::gameStart();
105 ComboManager::gameStart();
106 GarbageGenerator::gameStart();
107 X::gameStart();
108 Grid::gameStart();
109 Controller::gameStart();
110 Creep::gameStart();
111 Swapper::gameStart();
112 Spring::gameStart();
113 LevelLights::gameStart();
114 CountDownManager::gameStart();
115 Clock::gameStart();
116 LoseBar::gameStart();
117 ComputerPlayer::gameStart();
119 button_down_pause = false;
121 step_play = true;
123 remaining_time = 0;
124 time_step = 1;
127 void Game::gameFinish ( )
129 remaining_time = 0;
130 time_step = 1;
133 void Game::cleanUp ( )
135 CountDownManager::cleanUp();
136 Score::cleanUp();
139 void Game::loss ( )
141 * Called when creep detects a game loss condition; opponent may have already
142 * lost, so me must wait for confirmation.
145 if (!(MetaState::mode & CM_SOLO)) {
146 if (!(state & (GS_MAY_HAVE_LOST | GS_WON))) {
147 state = GS_MAY_HAVE_LOST;
148 Communicator::setLossTimeStep();
150 } else
151 state |= GS_END_PLAY;
154 void Game::lossConfirmation ( )
156 * Called by Communicator when opponent confirms game loss. Now we must only
157 * wait for the level lights to end play.
160 state = GS_LOST | GS_END_PLAY;
163 void Game::aiPlayerLoss ( )
165 if (!(state & GS_WON) && !(state & GS_END_PLAY))
166 state = GS_WON | GS_END_PLAY;
169 void Game::won ( )
171 * Called by Communicator when opponent signals a game loss that predates
172 * ours or signals a reverse of our game loss. Now we must wait to confirm
173 * our opponent's loss and for the level lights to end play.
176 if (!(state & GS_WON))
177 state = GS_WON | GS_MUST_CONFIRM_LOSS;
180 void Game::concession ( )
182 * Called by the controller upon player concession.
185 if (CountDownManager::start_pause_alarm != 0) return;
187 loss();
188 MetaState::state |= MS_CONCESSION;
191 void Game::buttonPause ( )
192 // run time step during pause (for Communicator); then reset the clock to the
193 // value at the pause time
195 // unpause
196 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) == GS_PAUSED) {
197 state = GS_NORMAL;
199 MessageManager::freeMessage();
200 if (CountDownManager::state != -1)
201 MessageManager::readyMessage(CountDownManager::state);
203 if (!(MetaState::mode & CM_SOLO)) {
204 Communicator::unpauseSyncCheck();
205 Communicator::signalUnpaused();
208 // pause
209 } else {
210 // to simplify things, you can't pause if you're about to lose
211 if (!(state & GS_NORMAL)) return;
213 state = GS_PAUSED;
215 if (CountDownManager::state != -1)
216 MessageManager::freeMessage();
217 MessageManager::readyMessage(MS_PAUSED);
219 if (!(MetaState::mode & CM_SOLO))
220 Communicator::signalPaused();
224 void Game::netSignalPause ( )
226 if (!(state & GS_NORMAL)) return;
228 state = GS_PAUSED;
230 if (CountDownManager::state != -1)
231 MessageManager::freeMessage();
232 MessageManager::readyMessage(MS_PAUSED);
235 void Game::netSignalUnpause ( )
237 if ((state & (GS_PAUSED | GS_SYNC_WAIT)) != GS_PAUSED) return;
239 state = GS_NORMAL;
241 MessageManager::freeMessage();
242 if (CountDownManager::state != -1)
243 MessageManager::readyMessage(CountDownManager::state);
246 void Game::syncPause ( int delay )
248 assert(delay > 0);
250 state = GS_PAUSED | GS_SYNC_WAIT;
251 sync_wait = delay;
253 if (CountDownManager::state != -1)
254 MessageManager::freeMessage();
255 MessageManager::readyMessage(MS_WAITING);
258 void Game::syncUnpause ( )
260 state = GS_NORMAL;
262 MessageManager::freeMessage();
263 if (CountDownManager::state != -1)
264 MessageManager::readyMessage(CountDownManager::state);
267 void Game::idleMeta ( )
269 timeval now;
270 double nowd;
271 gettimeofday(&now,NULL);
272 #define FPSDIFF (1.0f/30.0f)
273 nowd = now.tv_sec;
274 nowd += (double)now.tv_usec / 1000000.0f;
276 if ( (nowd - lastframe) > FPSDIFF ) {
277 lastframe = nowd;
278 } else {
279 usleep(1000);
282 int modified_and_complete = false;
284 do {
286 int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
287 remaining_time += time - previous_time;
288 previous_time = time;
290 // no time step yet
291 if (remaining_time < GC_TIME_STEP_PERIOD) break;
293 remaining_time -= GC_TIME_STEP_PERIOD;
294 time_step++;
296 if (remaining_time < GC_TIME_STEP_PERIOD)
297 modified_and_complete = true;
298 else
299 DOT(3);
301 // communicate state and other stuff
302 if (!(MetaState::state & MS_GAME_OVER_KEY_WAIT) &&
303 !(MetaState::mode & CM_SOLO))
304 Communicator::timeStepMeta();
306 // advance celebration
307 CelebrationManager::timeStep();
309 // advance the score record
310 ScoreRecordManager::timeStep();
312 // update message pulse
313 MessageManager::timeStep();
315 // update the pretty stuff too
316 SparkleManager::timeStep();
317 SignManager::timeStep();
318 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
319 WinRecord::timeStep();
320 LevelLights::timeStep();
322 // advance the clock through its final tick fade
323 Clock::timeStepMeta();
325 // advance the score through its final increment fade
326 Score::timeStepMeta();
328 } while (false);
330 if (modified_and_complete) {
331 glFinish();
332 glutPostRedisplay();
336 void Game::idlePlay ( )
338 timeval now;
339 double nowd;
340 gettimeofday(&now,NULL);
341 #define FPSDIFF (1.0f/30.0f)
342 nowd = now.tv_sec;
343 nowd += (double)now.tv_usec / 1000000.0f;
345 if ( (nowd - lastframe) > FPSDIFF ) {
346 lastframe = nowd;
347 } else {
348 usleep(1000);
351 int modified_and_complete = false;
353 do {
355 int time = glutGet((GLenum) GLUT_ELAPSED_TIME);
356 remaining_time += time - previous_time;
357 previous_time = time;
359 // no time step yet
360 if (remaining_time < GC_TIME_STEP_PERIOD) break;
362 remaining_time -= GC_TIME_STEP_PERIOD;
364 if (remaining_time < GC_TIME_STEP_PERIOD)
365 modified_and_complete = true;
366 else
367 DOT(2);
369 if (!(state & GS_PAUSED)) {
370 if (step_play) {
372 time_step++;
374 // check for and continue swaps and moves
375 Swapper::timeStep();
377 // update the level lights
378 LevelLights::timeStep();
380 // update message pulse
381 MessageManager::timeStep();
383 // move the win record stars
384 WinRecord::timeStep();
386 // update the starting count down
387 CountDownManager::timeStep();
388 if (CountDownManager::start_pause_alarm != 0) {
389 // some objects require a time step during start pause
391 if (!(MetaState::mode & CM_SOLO))
392 Communicator::timeStepPlay();
394 // reset the clock
395 Clock::timeStepMeta();
397 continue;
400 if (MetaState::mode & CM_AI)
401 ComputerPlayer::timeStep();
403 // loop over the grid, bottom to top; garbage will advance x and y
404 for (int y = 1; y < GC_PLAY_HEIGHT; y++)
405 for (int x = 0; x < GC_PLAY_WIDTH; x++) {
406 if (Grid::residentTypeAt(x, y) & GR_EMPTY) continue;
408 if (Grid::residentTypeAt(x, y) & GR_BLOCK)
409 Grid::blockAt(x, y).timeStep();
410 else
411 Grid::garbageAt(x, y).timeStep(x, y);
414 // perhaps creep upward
415 Creep::timeStep();
417 // process elimination check requests and update top_occupied_row
418 Grid::timeStep();
420 // handle new and finished combos
421 ComboManager::timeStep();
424 // communicate garbage and other stuff
425 if (!(MetaState::mode & CM_SOLO))
426 Communicator::timeStepPlay();
428 if (step_play) {
430 // drop queued garbage
431 GarbageGenerator::timeStep();
433 // move the sparkles and signs
434 SparkleManager::timeStep();
435 SignManager::timeStep();
437 // update the impact spring
438 if (!(MetaState::mode & CM_REALLY_LOW_GRAPHICS))
439 Spring::timeStep();
441 // update the clock
442 Clock::timeStepPlay();
444 // update the score
445 Score::timeStepPlay();
447 // update the losebar
448 LoseBar::timeStep();
450 // advance extreme effects
451 if (MetaState::mode & CM_X)
452 X::timeStep();
455 } else {
457 // if this is a sync pause, count down the waiting period
458 if (state & GS_SYNC_WAIT && !--sync_wait)
459 syncUnpause();
461 // communicate when paused
462 if (!(MetaState::mode & CM_SOLO))
463 Communicator::timeStepPlay();
465 // update message pulse
466 MessageManager::timeStep();
469 if (state & (GS_MAY_HAVE_LOST | GS_MUST_CONFIRM_LOSS))
470 step_play = false;
472 if (state & GS_END_PLAY) {
473 // step_play = false;
474 if (state & GS_PAUSED)
475 MessageManager::freeMessage();
477 if ((MetaState::mode & CM_SOLO) && !(MetaState::mode & CM_AI))
478 state = Score::gameFinish();
480 if (MetaState::mode & CM_AI)
481 state = ComputerPlayer::gameFinish();
483 if (state & GS_LOST)
484 MetaState::gameLoss();
485 else
486 MetaState::gameWon();
488 break;
491 } while (false);
493 if (!button_down_pause) {
494 if (Controller::pauseCommand()) {
495 button_down_pause = true;
496 buttonPause();
498 } else
499 if (!Controller::pauseCommand())
500 button_down_pause = false;
502 if (modified_and_complete) {
503 glFinish();
504 glutPostRedisplay();