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