3 * Daniel Nelson - 8/24/0
5 * Copyright (C) 2000 Daniel Nelson
6 * Copyright (C) 2004 Andrew Sayman
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * Daniel Nelson - aluminumangel.org
51 #define PI (3.14159265358979323846f)
52 #define SQRT_3 (1.73205080756887729352f)
55 #define GC_NAME "Crack Attack!"
56 #define GC_BINARY "crack-attack"
57 #define GC_VERSION "1.1.12"
60 #define GC_MESSAGE GC_NAME " v" GC_VERSION "\n"
62 // directory delimiter
71 # ifndef DATA_DIRECTORY
72 # define GC_DATA_DIRECTORY "." GC_DD "data/"
74 # define GC_DATA_DIRECTORY DATA_DIRECTORY
76 # define GC_LOCAL_DATA_DIRECTORY GC_DD "." GC_BINARY GC_DD
78 # define GC_DATA_DIRECTORY ".." GC_DD "data" GC_DD
79 # define GC_LOCAL_DATA_DIRECTORY ".." GC_DD "localdata" GC_DD
81 #define GC_GARBAGE_TEX_FILE_NAME_BASE "garbage_flavor"
82 #define GC_GARBAGE_TEX_NUMBER_DIGITS (3)
83 #define GC_NUMBER_STANDARD_GARBAGE_TEX (6)
84 #define GC_GARBAGE_TEX_MAX_NUMBER (1000)
85 #define GC_GARBAGE_NET_TEX_FILE_NAME GC_GARBAGE_TEX_FILE_NAME_BASE \
87 #define GC_GARBAGE_MY_TEX_FILE_NAME GC_GARBAGE_TEX_FILE_NAME_BASE \
89 #define GC_LOGO_TEX_FILE_NAME GC_DATA_DIRECTORY "logo.tga"
90 #define GC_X_LOGO_TEX_FILE_NAME GC_DATA_DIRECTORY "logo_x.tga"
91 #define GC_GARBAGE_LOGO_TEX_FILE_NAME GC_DATA_DIRECTORY \
92 GC_GARBAGE_TEX_FILE_NAME_BASE \
94 #define GC_GARBAGE_X_LOGO_TEX_FILE_NAME GC_DATA_DIRECTORY \
95 GC_GARBAGE_TEX_FILE_NAME_BASE \
97 #define GC_COUNT_DOWN_GO_TEX_FILE_NAME GC_DATA_DIRECTORY "count_down_go.tga"
98 #define GC_COUNT_DOWN_1_TEX_FILE_NAME GC_DATA_DIRECTORY "count_down_1.tga"
99 #define GC_COUNT_DOWN_2_TEX_FILE_NAME GC_DATA_DIRECTORY "count_down_2.tga"
100 #define GC_COUNT_DOWN_3_TEX_FILE_NAME GC_DATA_DIRECTORY "count_down_3.tga"
101 #define GC_ANYKEY_TEX_FILE_NAME GC_DATA_DIRECTORY "message_anykey.tga"
102 #define GC_WAITING_TEX_FILE_NAME GC_DATA_DIRECTORY "message_waiting.tga"
103 #define GC_PAUSED_TEX_FILE_NAME GC_DATA_DIRECTORY "message_paused.tga"
104 #define GC_WINNER_TEX_FILE_NAME GC_DATA_DIRECTORY "message_winner.tga"
105 #define GC_LOSER_TEX_FILE_NAME GC_DATA_DIRECTORY "message_loser.tga"
106 #define GC_GAME_OVER_TEX_FILE_NAME GC_DATA_DIRECTORY \
107 "message_game_over.tga"
108 #define GC_X_REC_FILE_NAME "score_record_x"
109 #define GC_REC_FILE_NAME "score_record"
110 #define GC_DEFAULT_REC_FILE_NAME GC_DATA_DIRECTORY "default_record"
112 // random angle tables' size; must be power of two
113 #define GC_SIZE_RANDOM_ANGLE_TABLE (256)
116 #define GC_GAMES_PER_MATCH (3)
118 // the play area dimensions; GC_SAFE_HEIGHT - 1 is the board height
119 #define GC_PLAY_WIDTH (6)
120 #define GC_PLAY_HEIGHT (45)
121 #define GC_SAFE_HEIGHT (13)
122 #define GC_GRID_SIZE (GC_PLAY_WIDTH * GC_PLAY_HEIGHT)
125 #define GC_BLOCK_STORE_SIZE (GC_GRID_SIZE)
126 #define GC_GARBAGE_STORE_SIZE (2 * GC_PLAY_HEIGHT)
127 #define GC_COMBO_TABULATOR_STORE_SIZE (8)
128 #define GC_GARBAGE_QUEUE_SIZE (8)
130 // time steps per second
131 #define GC_STEPS_PER_SECOND (50)
133 // milliseconds per time step
134 #define GC_TIME_STEP_PERIOD (1000 / GC_STEPS_PER_SECOND)
136 // number of subdivisions per grid location
137 #define GC_STEPS_PER_GRID (60)
140 #define GC_PLAYER_NAME_LENGTH (256)
141 #define GC_DEFAULT_PLAYER_NAME "NamelessOne"
143 // velocity of falling; must be a factor of GC_STEPS_PER_GRID
144 #define GC_FALL_VELOCITY (20)
146 // velocity and time length of swapping
147 #define GC_SWAP_VELOCITY (10)
148 #define GC_SWAP_DELAY (GC_STEPS_PER_GRID / GC_SWAP_VELOCITY)
151 #define GC_CREEP_DELAY (1200)
152 #define GC_CREEP_ADVANCE_TIMER_STEP GC_CREEP_DELAY
153 #define GC_CREEP_TIMER_STEP_INCREMENT (20)
154 #define GC_CREEP_INITIAL_TIMER_STEP GC_CREEP_TIMER_STEP_INCREMENT
155 #define GC_CREEP_MAX_TIMER_STEP (2400)
156 #define GC_CREEP_ADVANCE_VELOCITY (3)
157 #define GC_CREEP_INCREMENT_DELAY (10 * GC_STEPS_PER_SECOND)
159 // delay between safe height violation and loss
160 #define GC_LOSS_DELAY (7 * GC_STEPS_PER_SECOND)
161 #define GC_LOSS_DELAY_ELIMINATION (1 * GC_STEPS_PER_SECOND)
163 // time length between moves
164 #define GC_MOVE_DELAY (6)
166 // time length of block dying
167 #define GC_DYING_DELAY (90)
169 // time length of hanging
170 #define GC_HANG_DELAY (3)
172 // time length until popping, between popping, and after popping
173 #define GC_INTERNAL_POP_DELAY (15)
174 #define GC_INITIAL_POP_DELAY (50 + GC_INTERNAL_POP_DELAY)
175 #define GC_FINAL_POP_DELAY (50)
177 // minimum length of a elimination pattern
178 #define GC_MIN_PATTERN_LENGTH (3)
180 // chance of a creep row having a special block
181 #define GC_NO_SPECIAL_BLOCK_CHANCE_IN (3)
182 #define GC_X_NO_SPECIAL_BLOCK_CHANCE_IN (10)
184 // chance of garbage shattering to garbage
185 #define GC_GARBAGE_TO_GARBAGE_SHATTER (2)
187 // time length before garbage falls
188 #define GC_AVERAGE_GARBAGE_DROP_DELAY (300)
189 #define GC_SPREAD_GARBAGE_DROP_DELAY (40)
191 // time length of the introduction pause; should be multiple of 3
192 #define GC_START_PAUSE_DELAY (150)
194 // maximum height of a garbage block
195 #define GC_MAX_GARBAGE_HEIGHT (11)
198 #define GC_MIN_PATTERN_SCORE (2)
199 #define GC_GRAY_SCORE (3)
200 #define GC_NUMBER_DIGITS (7)
201 #define GC_MIN_NUMBER_DIGITS_DISPLAYED (4)
202 #define GC_MAX_SCORE_INCREMENT_DELAY (12)
203 #define GC_MIN_SCORE_INCREMENT_DELAY (1)
204 #define GC_SCORE_DELAY_SLOPE (2)
205 #define GC_SCORE_REC_LENGTH (30)
206 #define GC_SCORE_DEFAULT_TOP_SCORE (600)
207 #define GC_SCORE_REC_DEFAULT_NAME "-----"
210 #define GC_SINE_TABLE_LENGTH (100)
211 #define GC_SINE_TABLE_LOWER_BOUND (-PI / 2.0f)
212 #define GC_SINE_TABLE_STEP_WIDTH (PI / (GC_SINE_TABLE_LENGTH - 1))
214 // initial swapper location
215 #define GC_INITIAL_SWAPPER_LOCATION_X (GC_PLAY_WIDTH / 2 - 1)
216 #define GC_INITIAL_SWAPPER_LOCATION_Y (4)
219 #define GC_INVISIBLE_MAX_ALPHA (330)
220 #define GC_INVISIBLE_MIN_ALPHA (-20)
221 #define GC_INVISIBLE_QUICK_DECAY_RATE (3)
222 #define GC_INVISIBLE_PULSE_CHANCE_IN (30)
223 #define GC_INVISIBLE_PULSE_STRENGTH (70)
224 #define GC_CRAZY_LONG_MODE_PERIOD (150)
225 #define GC_CRAZY_SHORT_MODE_PERIOD (50)
226 #define GC_MAX_WILD_NUMBER (3)
227 #define GC_WILD_PERIOD (180)
228 #define GC_WILD_POLYMORPH_PERIOD (60)
229 #define GC_MAX_SPECIAL_COLOR_NUMBER (6)
232 #define GC_LEFT_KEY ('a')
233 #define GC_RIGHT_KEY ('d')
234 #define GC_UP_KEY ('w')
235 #define GC_DOWN_KEY ('s')
236 #define GC_SWAP_KEY ('k')
237 #define GC_ADVANCE_KEY ('l')
238 #define GC_PAUSE_KEY ('p')
240 // Constants for the game window height and width.
241 #define GC_RESOLUTION_0 (400)
242 #define GC_RESOLUTION_1 (570)
243 #define GC_RESOLUTION_2 (680)
244 #define GC_RESOLUTION_3 (970)
245 #define GC_RESOLUTION_4 (1170)
249 # define max(a, b) ((a) > (b) ? (a) : (b))
252 // insure that our communication int is the same length on all machines
253 #if (INT_MAX == 2147483647)
254 typedef unsigned int uint32
;
256 typedef unsigned short uint32
;
263 # define COLOR(n) "\33[1;" << (n) << "m"
264 # define NOCOLOR "\33[m"
269 # define DOT(n) { cerr << COLOR(37 - n) \
270 << "." NOCOLOR << flush; }
271 # define DUMP(a) { cerr << COLOR(32) << "Dump: " \
272 __FILE__ ":" << __LINE__ << ": " \
274 " = " << (a) << endl; }
275 # define PERIODIC_DUMP(a, b) { if (!(Game::time_step % a)) \
276 cerr << COLOR(32) << "Dump: " \
277 __FILE__ ":" << __LINE__ << ": " \
279 " = " << (b) << endl; }
280 # define MESSAGE(a) { cerr << COLOR(33) << "Mesg: " \
281 __FILE__ ":" << __LINE__ << ": " \
282 NOCOLOR << a << endl; }
284 # define MARK() { cerr << COLOR(35) << "Mark: " \
285 __FILE__ ":" << __LINE__ << ": " \
286 << __PRETTY_FUNCTION__ << NOCOLOR \
289 # define MARK() { cerr << COLOR(35) << "Mark: " \
290 __FILE__ ":" << __LINE__ << ":" \
293 # define ENDL() { cerr << COLOR(34) << "Endl: " \
294 __FILE__ ":" << __LINE__ << ":" \
296 # define LOG(a) { ofstream log("log", ios::app); \
297 log << "Log: " __FILE__ ":" \
298 << __LINE__ << ": " << a \
301 # define DOT(n) ((void) 0)
302 # define DUMP(a) ((void) 0)
303 # define PERIODIC_DUMP(a, b) ((void) 0)
304 # define MESSAGE(a) ((void) 0)
305 # define MARK() ((void) 0)
306 # define ENDL() ((void) 0)
307 # define LOG(a) ((void) 0)
310 // fix bad Visual C++ scoping
312 # define for if (false) { } else for
318 #define GS_NORMAL (1 << 0)
319 // Normal playing, but we're paused.
320 #define GS_PAUSED (1 << 1)
321 // Signals a local unpausing to opponent; used only in communication signals.
322 #define GS_UNPAUSED (1 << 2)
323 // Normal playing, but we're paused because we've gotten ahead of our opponent;
324 // most likely due to a pause.
325 #define GS_SYNC_WAIT (1 << 3)
326 // We've lost, but we haven't heard confirmation from opponent; play continues.
327 #define GS_MAY_HAVE_LOST (1 << 4)
328 // Opponent lost; we've received the message and it predates our loss; play
329 // continues until level lights reach minimum.
330 #define GS_WON (1 << 5)
331 // We've lost and opponent confirms it; play continues until level lights reach
333 #define GS_LOST (1 << 6)
334 // We've won but we can't quite yet cause we must confirm our opponent's loss.
335 #define GS_MUST_CONFIRM_LOSS (1 << 7)
336 // We've confirmed our opponent's loss, but we have to wait a bit yet until
338 #define GS_CONFIRMATION_HOLD (1 << 8)
339 // The level lights signaled it's time to end play. Now we must simply complete
340 // the current time step.
341 #define GS_END_PLAY (1 << 9)
342 // Used only for communication. The match has been conceded.
343 #define GS_CONCESSION (1 << 10)
345 // flavor of blocks; special color blocks must be last; wild and then gray must
346 // be directly after normal flavors; here to prevent header entanglements;
347 // the appearance chance of the various flavors can be found in
348 // BlockManager::newCreepBlock()
349 #define BF_NORMAL_1 ( 0)
350 #define BF_NORMAL_2 ( 1)
351 #define BF_NORMAL_3 ( 2)
352 #define BF_NORMAL_4 ( 3)
353 #define BF_NORMAL_5 ( 4)
356 #define BF_BLACK ( 7)
357 #define BF_WHITE ( 8)
358 #define BF_SPECIAL_COLOR_1 ( 9)
359 #define BF_SPECIAL_COLOR_2 (10)
360 #define BF_SPECIAL_COLOR_3 (11)
361 #define BF_SPECIAL_COLOR_4 (12)
362 #define BF_SPECIAL_COLOR_5 (13)
363 #define BF_NUMBER_NORMAL (BF_NORMAL_5 + 1)
364 #define BF_NUMBER (BF_SPECIAL_COLOR_5 + 1)
365 #define BF_NUMBER_SPECIAL (BF_NUMBER - (BF_GRAY + 1))
366 #define BF_FINAL_GRAY_SPECIAL (BF_WHITE)
368 /* static */ class Game
{
370 static void initialize ( );
371 static void gameStart ( );
372 static void gameFinish ( );
373 static void cleanUp ( );
375 static void loss ( );
376 static void lossConfirmation ( );
377 static void aiPlayerLoss ( );
379 static void netSignalPause ( );
380 static void netSignalUnpause ( );
381 static void syncPause ( int delay
);
382 static void concession ( );
384 static void idlePlay ( );
385 static void idleMeta ( );
387 static inline void go ( )
389 previous_time
= glutGet((GLenum
) GLUT_ELAPSED_TIME
);
392 static inline float sqrt ( float x
)
394 * An OK approximation of sqrt() on [0, 1] which is correct at the boundaries.
395 * Since all I really want is the vague shape of sqrt() and perfection at 0
396 * and 1, this'll work perfectly.
398 * Generated by minimizing int_0^1{dx (sqrt{x} - a x + (1 - a) x)^2}.
401 return ((27.0f
/ 14.0f
) - (13.0f
/ 14.0f
) * x
) * x
;
405 static int time_step
;
406 static int awaking_count
;
407 static int dying_count
;
408 static int dying_count_2
;
411 static void buttonPause ( );
412 static void syncUnpause ( );
414 static int previous_time
;
415 static int remaining_time
;
416 static bool button_down_pause
;
417 static bool step_play
;
418 static int sync_wait
;
419 static double lastframe
;