Mercurial > hg > index.fcgi > lj > lj046
comparison src/lj.h @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:89bdfa249f0d |
---|---|
1 /* Header file for the engine of LOCKJAW, an implementation of the Soviet Mind Game | |
2 | |
3 Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net> | |
4 | |
5 This work is free software; you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 2 of the License, or | |
8 (at your option) any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Original game concept and design by Alexey Pajitnov. | |
20 The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg, | |
21 or The Tetris Company LLC. | |
22 | |
23 */ | |
24 | |
25 #ifndef LJ_H | |
26 #define LJ_H | |
27 | |
28 #include <stdlib.h> | |
29 #include "ljtypes.h" | |
30 | |
31 enum { | |
32 CONNECT_U = 0x01, | |
33 CONNECT_R = 0x02, | |
34 CONNECT_D = 0x04, | |
35 CONNECT_L = 0x08, | |
36 CONNECT_UD = CONNECT_U | CONNECT_D, | |
37 CONNECT_UL = CONNECT_U | CONNECT_L, | |
38 CONNECT_DL = CONNECT_D | CONNECT_L, | |
39 CONNECT_UR = CONNECT_U | CONNECT_R, | |
40 CONNECT_DR = CONNECT_D | CONNECT_R, | |
41 CONNECT_LR = CONNECT_L | CONNECT_R, | |
42 CONNECT_UDL = CONNECT_UD | CONNECT_L, | |
43 CONNECT_UDR = CONNECT_UD | CONNECT_R, | |
44 CONNECT_ULR = CONNECT_UL | CONNECT_R, | |
45 CONNECT_DLR = CONNECT_DL | CONNECT_R, | |
46 CONNECT_UDLR = CONNECT_UD | CONNECT_LR, | |
47 CONNECT_MASK = CONNECT_UDLR, | |
48 COLOR_MASK = 0xF0 | |
49 }; | |
50 | |
51 typedef unsigned char LJBlock; | |
52 | |
53 typedef enum LJState { | |
54 LJS_INACTIVE, | |
55 LJS_NEW_PIECE, /* delay is ARE */ | |
56 LJS_FALLING, /* delay is fall delay; NOT IMPLEMENTED */ | |
57 LJS_LANDED, /* delay is lock delay */ | |
58 LJS_LINES, /* delay is line delay */ | |
59 LJS_LINES_FALLING, /* delay is fall delay per line; NOT IMPLEMENTED */ | |
60 LJS_GAMEOVER, /* game over animation */ | |
61 LJS_EXPLODE /* used for bombliss extension */ | |
62 } LJState; | |
63 | |
64 // for other | |
65 enum { | |
66 LJI_HOLD = 0x01, | |
67 LJI_LOCK = 0x02 | |
68 }; | |
69 | |
70 // for dirty bits | |
71 enum { | |
72 LJ_DIRTY_NEXT = 0x01000000, | |
73 LJ_DIRTY_SCORE = 0x02000000 | |
74 }; | |
75 | |
76 // for gimmick (game mode) | |
77 enum { | |
78 LJGM_ATYPE, // marathon | |
79 LJGM_BTYPE, // 40 lines | |
80 LJGM_ULTRA, // 180 seconds | |
81 LJGM_DRILL, // clear bottom line | |
82 LJGM_ITEMS, // no rotation + no next + fast drop + garbage + banana | |
83 LJGM_BABY, // 300 keypresses | |
84 LJGM_N_GIMMICKS | |
85 }; | |
86 | |
87 enum { | |
88 LJP_I = 0, | |
89 LJP_J, | |
90 LJP_L, | |
91 LJP_O, | |
92 LJP_S, | |
93 LJP_T, | |
94 LJP_Z, | |
95 LJP_I2, | |
96 LJP_I3, | |
97 LJP_L3, | |
98 LJP_GARBAGE = 7, | |
99 LJP_MASK = 0x0F | |
100 }; | |
101 | |
102 enum { | |
103 LJSND_ROTATE = 0x0001, | |
104 LJSND_SHIFT = 0x0002, | |
105 LJSND_DROP = 0x0004, | |
106 LJSND_LAND = 0x0008, | |
107 LJSND_LOCK = 0x0010, | |
108 LJSND_LINE = 0x0020, // a line was scored | |
109 LJSND_SETB2B = 0x0040, // this line is b2b worthy (tetris or t-spin) | |
110 LJSND_B2B = 0x0080, // this line AND last line were b2b worthy | |
111 LJSND_SPAWN = 0x0100, // next piece was moved up | |
112 LJSND_HOLD = 0x0200, // hold piece was activated | |
113 LJSND_IRS = 0x0400, // initial rotation: spawn last frame and rotation this frame | |
114 LJSND_SQUARE = 0x0800, // formed 4x4 square | |
115 LJSND_COUNTDOWN = 0x4000, // countdown value changed | |
116 LJSND_SECTIONUP = 0x8000, // section increased | |
117 }; | |
118 | |
119 enum { | |
120 LJRAND_PURE, | |
121 LJRAND_BAG, | |
122 LJRAND_BAGPLUS1, | |
123 LJRAND_2BAG, | |
124 LJRAND_HIST_INF, | |
125 LJRAND_HIST_6, | |
126 LJRAND_N_RANDS | |
127 }; | |
128 | |
129 enum { | |
130 LJRAND_4BLK, | |
131 LJRAND_JLOSTZ, | |
132 LJRAND_SZ, | |
133 LJRAND_I, | |
134 LJRAND_234BLK, | |
135 LJRAND_T, | |
136 LJRAND_N_PIECE_SETS | |
137 }; | |
138 | |
139 enum { | |
140 LJTS_OFF = 0, | |
141 LJTS_TNT, | |
142 LJTS_TDS, | |
143 LJTS_TDS_NO_KICK, | |
144 LJTS_N_ALGOS | |
145 }; | |
146 | |
147 enum { | |
148 LJSPD_ZERO = 0, | |
149 LJSPD_RHYTHMZERO, | |
150 LJSPD_EXP, | |
151 LJSPD_RHYTHM, | |
152 LJSPD_TGM, | |
153 LJSPD_DEATH, | |
154 LJSPD_DEATH300, | |
155 LJSPD_NES, | |
156 LJSPD_GB, | |
157 LJSPD_GBHEART, | |
158 LJSPD_N_CURVES | |
159 }; | |
160 | |
161 enum { | |
162 LJLOCK_NOW = 0, | |
163 LJLOCK_SPAWN, | |
164 LJLOCK_STEP, | |
165 LJLOCK_MOVE, | |
166 LJLOCK_N_STYLES | |
167 }; | |
168 | |
169 enum { | |
170 LJGRAV_NAIVE = 0, | |
171 LJGRAV_STICKY, | |
172 LJGRAV_STICKY_BY_COLOR, | |
173 LJGRAV_CASCADE, | |
174 LJGRAV_N_ALGOS | |
175 }; | |
176 | |
177 enum { | |
178 LJSCORE_LJ, | |
179 LJSCORE_TNT64, | |
180 LJSCORE_HOTLINE, | |
181 LJSCORE_TDS, | |
182 LJSCORE_NES, | |
183 LJSCORE_LJ_NERF, | |
184 LJSCORE_N_STYLES, | |
185 LJSCORE_WORLDS, | |
186 LJSCORE_TGM1, | |
187 LJSCORE_IPOD | |
188 }; | |
189 | |
190 enum { | |
191 LJDROP_NOSCORE, | |
192 LJDROP_NES, | |
193 LJDROP_1CELL, | |
194 LJDROP_1S_2H, | |
195 LJDROP_N_STYLES | |
196 }; | |
197 | |
198 enum { | |
199 LJGARBAGE_NONE, | |
200 LJGARBAGE_1, | |
201 LJGARBAGE_2, | |
202 LJGARBAGE_3, | |
203 LJGARBAGE_4, | |
204 LJGARBAGE_HRDERBY, | |
205 LJGARBAGE_DRILL, | |
206 LJGARBAGE_ZIGZAG, | |
207 | |
208 LJGARBAGE_N_STYLES | |
209 }; | |
210 | |
211 enum { | |
212 LJHOLD_NONE, | |
213 LJHOLD_EMPTY, | |
214 LJHOLD_TNT, | |
215 LJHOLD_TO_NEXT, | |
216 LJHOLD_N_STYLES | |
217 }; | |
218 | |
219 enum { | |
220 LJGLUING_NONE, | |
221 LJGLUING_SQUARE, | |
222 LJGLUING_STICKY, | |
223 LJGLUING_STICKY_BY_COLOR, | |
224 LJGLUING_N_STYLES | |
225 }; | |
226 | |
227 // Guideline says 10 wide, but we want to support tetrinet mode | |
228 #define LJ_PF_WID ((size_t)12) | |
229 #define LJ_SPAWN_X ((LJ_PF_WID - 3) / 2) | |
230 #define LJ_PF_HT ((size_t)24) | |
231 #define LJ_PF_VIS_HT ((size_t)20) | |
232 #define LJ_NEXT_PIECES 8 | |
233 #define LJ_MAX_LINES_PER_PIECE 8 | |
234 | |
235 typedef struct LJBlkSpec | |
236 { | |
237 signed char x, y, conn, reserved; | |
238 } LJBlkSpec; | |
239 | |
240 typedef struct LJInput { | |
241 signed char rotation, movement; | |
242 unsigned char gravity; /* 5.3 format */ | |
243 unsigned char other; | |
244 } LJInput; | |
245 | |
246 typedef struct LJSpeedSetting { | |
247 LJFixed gravity; | |
248 unsigned char entryDelay, dasDelay, lockDelay, lineDelay; | |
249 } LJSpeedSetting; | |
250 | |
251 typedef struct SpeedStateBase { | |
252 unsigned char curve, section; | |
253 unsigned char pad[2]; | |
254 signed int level; | |
255 } SpeedStateBase; | |
256 | |
257 #define MAX_BAG_LEN 10 | |
258 #define MAX_OMINO 4 | |
259 | |
260 typedef struct LJField | |
261 { | |
262 /* Game state */ | |
263 LJBlock b[LJ_PF_HT][LJ_PF_WID]; | |
264 LJBlock c[LJ_PF_HT][LJ_PF_WID]; | |
265 LJBits clearedLines; | |
266 LJBits sounds; | |
267 LJBits tempRows; | |
268 unsigned char curPiece[1 + LJ_NEXT_PIECES]; | |
269 signed char permuPiece[2 * MAX_BAG_LEN], permuPhase; | |
270 unsigned short nLineClears[LJ_MAX_LINES_PER_PIECE]; // [n-1] = # of n-line clears | |
271 LJFixed y; | |
272 LJState state; | |
273 signed char stateTime; | |
274 unsigned char theta; | |
275 signed char x; | |
276 signed char hardDropY; | |
277 char alreadyHeld; | |
278 char isSpin; | |
279 char nLinesThisPiece; | |
280 char canRotate; | |
281 unsigned char upwardKicks; | |
282 | |
283 /* Persist from piece to piece */ | |
284 int score, lines; | |
285 unsigned int gameTime; // number of frames | |
286 unsigned int activeTime; // number of frames | |
287 signed short holdPiece; | |
288 char chain; | |
289 signed char garbage; | |
290 unsigned char dropDist; | |
291 unsigned char garbageX; | |
292 unsigned short nPieces, outGarbage; | |
293 unsigned short monosquares, multisquares; | |
294 | |
295 /* Determined by gimmick */ | |
296 signed char gimmick; | |
297 signed int bpmCounter; | |
298 unsigned int speedupCounter; | |
299 unsigned int goalCount; | |
300 unsigned int seed; | |
301 unsigned char goalType; | |
302 | |
303 LJSpeedSetting speed; | |
304 SpeedStateBase speedState; | |
305 | |
306 unsigned char lockReset; // lockdown reset rule type | |
307 unsigned char areStyle; | |
308 unsigned char setLockDelay; // Overridden lock delay (255 = never) | |
309 unsigned char setLineDelay; // Overridden line delay | |
310 unsigned char garbageStyle; | |
311 unsigned char ceiling; | |
312 unsigned char enterAbove; | |
313 unsigned char leftWall, rightWall; | |
314 unsigned char pieceSet; | |
315 unsigned char randomizer; | |
316 unsigned char rotationSystem; | |
317 unsigned char garbageRandomness; // 64: change garbageX in 1/4 of rows; 255: change all | |
318 unsigned char tSpinAlgo; // 0: off, 1: TNT, 2: TDS | |
319 unsigned char clearGravity; | |
320 unsigned char gluing; // 0: off; 1: square | |
321 unsigned char scoreStyle; | |
322 unsigned char dropScoreStyle; | |
323 unsigned char maxUpwardKicks; | |
324 unsigned char holdStyle; | |
325 unsigned char bottomBlocks; | |
326 unsigned char reloaded; // 0: played through; 1: reloaded from saved state | |
327 } LJField; | |
328 | |
329 /** | |
330 * Names of the supported rotation systems (wktables.c). | |
331 */ | |
332 enum { | |
333 LJROT_SRS, | |
334 LJROT_SEGA, | |
335 LJROT_ARIKA, | |
336 LJROT_ATARI, | |
337 LJROT_NES, | |
338 LJROT_GB, | |
339 LJROT_TOD, | |
340 LJROT_TDX, | |
341 N_ROTATION_SYSTEMS | |
342 }; | |
343 | |
344 #define N_PIECE_SHAPES 10 | |
345 #define KICK_TABLE_LEN 5 | |
346 extern const char pieceColors[N_PIECE_SHAPES]; | |
347 typedef unsigned char WallKickTable[4][KICK_TABLE_LEN]; | |
348 typedef struct LJRotSystem { | |
349 /** | |
350 * Color scheme for this rotation system (0: SRS; 1: Sega) | |
351 * Use colorset 0 (SRS) if all free-space kicks are WK(0, 0). | |
352 * Otherwise, your rotation system has what Eddie Rogers has called | |
353 * a topknot, and you should use Sega colors. | |
354 */ | |
355 unsigned char colorScheme; | |
356 unsigned char reserved1[3]; | |
357 unsigned char entryOffset[N_PIECE_SHAPES]; | |
358 unsigned char entryTheta[N_PIECE_SHAPES]; | |
359 /* These control which kick table is used for each piece. | |
360 * If negative, no kick table is present. | |
361 */ | |
362 signed char kicksL[N_PIECE_SHAPES]; | |
363 signed char kicksR[N_PIECE_SHAPES]; | |
364 WallKickTable kickTables[]; | |
365 } LJRotSystem; | |
366 | |
367 extern const LJRotSystem *const rotSystems[N_ROTATION_SYSTEMS]; | |
368 | |
369 #ifdef LJ_INTERNAL | |
370 // Used for defining wall kick tables: | |
371 // WK(x, y) builds a 1-byte record with 2 coordinates, at 4 bits | |
372 // per coordinate. | |
373 // WKX() and WKY() retrieve the X or Y coordinate from this record. | |
374 // The ((stuff ^ 8) - 8) is sign extension magick | |
375 #define WK(x, y) (((x) & 0x0F) | ((y) & 0x0F) << 4) | |
376 #define WKX(wk) ((((wk) & 0x0F) ^ 8) - 8) | |
377 #define WKY(wk) WKX((wk) >> 4) | |
378 // If ARIKA_IF_NOT_CENTER is specified, check the free space | |
379 // rotation for blocks in columns other than 1, and stop if | |
380 // none of them are filled. This obsoletes the old SKIP_IF. | |
381 #define SKIP_IF 0x80 | |
382 #define SKIP_IF3 0x82 | |
383 | |
384 #define ARIKA_IF_NOT_CENTER 0x83 | |
385 #define WK_END 0x8F | |
386 #if 0 | |
387 extern const WallKickTable *const wkTablesL[N_ROTATION_SYSTEMS][N_PIECE_SHAPES]; | |
388 extern const WallKickTable *const wkTablesR[N_ROTATION_SYSTEMS][N_PIECE_SHAPES]; | |
389 #endif | |
390 #endif | |
391 | |
392 /** | |
393 * Expands a tetromino to the blocks that make it up. | |
394 * @param out an array of length 4 | |
395 * @param p the field into which the tetromino will be spawned | |
396 * (used for default spawn orientation) | |
397 * @param piece a piece number | |
398 * @param xBase x coordinate of base position of the tetromino | |
399 * @param yBase y coordinate of base position of the tetromino | |
400 * @param theta the orientation of the tetromino | |
401 * (0-3: use this; 4: use default spawn rotation) | |
402 */ | |
403 void expandPieceToBlocks(LJBlkSpec out[], | |
404 const LJField *p, | |
405 int piece, int xBase, int yBase, int theta); | |
406 | |
407 /** | |
408 * Tests whether a particular block is occupied. | |
409 * @param p the playfield | |
410 * @param x the column | |
411 * @param y the row (0 = bottom) | |
412 * @return zero iff the space is open | |
413 */ | |
414 int isOccupied(const LJField *p, int x, int y); | |
415 | |
416 /** | |
417 * Tests whether a particular tetromino would overlap one or more | |
418 * blocks, a side wall, or the floor | |
419 * @param p the playfield | |
420 * @param x the column of the left side of the piece's bounding 4x4 | |
421 * @param y the row of the bottom of the piece's bounding 4x4 (0 = bottom) | |
422 * @return zero iff the space is open | |
423 */ | |
424 int isCollision(const LJField *p, int x, int y, int theta); | |
425 | |
426 /** | |
427 * Blanks a playfield and prepares it for a new game. | |
428 * @param p the playfield | |
429 */ | |
430 void newGame(LJField *p); | |
431 | |
432 /** | |
433 * Runs one frame of S.M.G. | |
434 * @param p the playfield | |
435 * @param in the player's input | |
436 * @return the rows that were modified | |
437 */ | |
438 LJBits frame(LJField *p, const LJInput *in); | |
439 | |
440 /** | |
441 * Applies gimmicks to a new game. | |
442 * @param p the playfield | |
443 * @param in the player's input | |
444 */ | |
445 void initGimmicks(LJField *p); | |
446 | |
447 /** | |
448 * Runs gimmicks for one frame of S.M.G. | |
449 * @param p the playfield | |
450 * @param c the control settings | |
451 * @return the rows that were modified | |
452 */ | |
453 struct LJControl; | |
454 LJBits gimmicks(LJField *p, struct LJControl *c); | |
455 | |
456 /** | |
457 * Sets up the randomizer. | |
458 * @return the number of this piece | |
459 */ | |
460 void initRandomize(LJField *p); | |
461 | |
462 /** | |
463 * Chooses a pseudo-random piece. | |
464 * @param the field on which the piece will be generated | |
465 * @return the number of this piece | |
466 * (0=i, 1=j, 2=l, 3=o, 4=s, 5=t, 6=z) | |
467 */ | |
468 unsigned int randomize(LJField *p); | |
469 | |
470 /** | |
471 * Counts the number of 1 bits in a bitfield. | |
472 * @param p the bitfield | |
473 * @return the number of bits in p with a value of 1. | |
474 */ | |
475 unsigned int countOnes(LJBits b); | |
476 | |
477 /** | |
478 * Shuffles the columns of blocks in the playfield. | |
479 * @param p the playfield | |
480 */ | |
481 void shuffleColumns(LJField *p); | |
482 | |
483 /** | |
484 * Random number generator. Use this for all random events | |
485 * that affect the game state. | |
486 * @param field | |
487 * @return uniformly distributed number in 0 to 0x7FFF | |
488 */ | |
489 unsigned int ljRand(LJField *p); | |
490 | |
491 /** | |
492 * List of lines used for hotline scoring. | |
493 * A line clear completed at row hotlineRows[i] is worth 100*(i + 1). | |
494 */ | |
495 extern const char hotlineRows[LJ_PF_HT]; | |
496 | |
497 /** | |
498 * Counts the number of trailing zero bits on an integer. | |
499 * For instance, 00000000 00000000 00000001 11111000 | |
500 * has 3 trailing zeroes. | |
501 */ | |
502 unsigned int bfffo(LJBits rowBits); | |
503 | |
504 void setupZigzagField(LJField *p, size_t height); | |
505 unsigned int calcZigzagGrade(const LJField *p); | |
506 | |
507 #endif |