view src/lj.h @ 3:17286938e22a

change DS alt. rotate key to rotate twice
author paulo@localhost
date Wed, 08 Apr 2009 21:50:13 -0700
parents
children
line source
1 /* Header file for the engine of LOCKJAW, an implementation of the Soviet Mind Game
3 Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net>
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.
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.
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
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.
23 */
25 #ifndef LJ_H
26 #define LJ_H
28 #include <stdlib.h>
29 #include "ljtypes.h"
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 };
51 typedef unsigned char LJBlock;
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;
64 // for other
65 enum {
66 LJI_HOLD = 0x01,
67 LJI_LOCK = 0x02
68 };
70 // for dirty bits
71 enum {
72 LJ_DIRTY_NEXT = 0x01000000,
73 LJ_DIRTY_SCORE = 0x02000000
74 };
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 };
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 };
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 };
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 };
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 };
139 enum {
140 LJTS_OFF = 0,
141 LJTS_TNT,
142 LJTS_TDS,
143 LJTS_TDS_NO_KICK,
144 LJTS_N_ALGOS
145 };
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 };
161 enum {
162 LJLOCK_NOW = 0,
163 LJLOCK_SPAWN,
164 LJLOCK_STEP,
165 LJLOCK_MOVE,
166 LJLOCK_N_STYLES
167 };
169 enum {
170 LJGRAV_NAIVE = 0,
171 LJGRAV_STICKY,
172 LJGRAV_STICKY_BY_COLOR,
173 LJGRAV_CASCADE,
174 LJGRAV_N_ALGOS
175 };
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 };
190 enum {
191 LJDROP_NOSCORE,
192 LJDROP_NES,
193 LJDROP_1CELL,
194 LJDROP_1S_2H,
195 LJDROP_N_STYLES
196 };
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,
208 LJGARBAGE_N_STYLES
209 };
211 enum {
212 LJHOLD_NONE,
213 LJHOLD_EMPTY,
214 LJHOLD_TNT,
215 LJHOLD_TO_NEXT,
216 LJHOLD_N_STYLES
217 };
219 enum {
220 LJGLUING_NONE,
221 LJGLUING_SQUARE,
222 LJGLUING_STICKY,
223 LJGLUING_STICKY_BY_COLOR,
224 LJGLUING_N_STYLES
225 };
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
235 typedef struct LJBlkSpec
236 {
237 signed char x, y, conn, reserved;
238 } LJBlkSpec;
240 typedef struct LJInput {
241 signed char rotation, movement;
242 unsigned char gravity; /* 5.3 format */
243 unsigned char other;
244 } LJInput;
246 typedef struct LJSpeedSetting {
247 LJFixed gravity;
248 unsigned char entryDelay, dasDelay, lockDelay, lineDelay;
249 } LJSpeedSetting;
251 typedef struct SpeedStateBase {
252 unsigned char curve, section;
253 unsigned char pad[2];
254 signed int level;
255 } SpeedStateBase;
257 #define MAX_BAG_LEN 10
258 #define MAX_OMINO 4
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;
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;
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;
303 LJSpeedSetting speed;
304 SpeedStateBase speedState;
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;
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 };
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;
367 extern const LJRotSystem *const rotSystems[N_ROTATION_SYSTEMS];
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
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
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);
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);
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);
426 /**
427 * Blanks a playfield and prepares it for a new game.
428 * @param p the playfield
429 */
430 void newGame(LJField *p);
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);
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);
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);
456 /**
457 * Sets up the randomizer.
458 * @return the number of this piece
459 */
460 void initRandomize(LJField *p);
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);
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);
477 /**
478 * Shuffles the columns of blocks in the playfield.
479 * @param p the playfield
480 */
481 void shuffleColumns(LJField *p);
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);
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];
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);
504 void setupZigzagField(LJField *p, size_t height);
505 unsigned int calcZigzagGrade(const LJField *p);
507 #endif