-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathengine.h
More file actions
427 lines (340 loc) · 10.5 KB
/
engine.h
File metadata and controls
427 lines (340 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
///
// engine.h
// ========
//
// Header file for the faststack engine.
//
// The engine is mostly opaque to an outside user. A number of functions are
// provided which provide some convenience when performing certain tasks.
//
// Notes:
// * Rename this to FSEngine.h and fsTypes to fsCore.h
//
// Naming
// ------
// We use the following prefixes for enums.
//
// FST_* - faststack Type
// FSS_* - faststack State
///
#ifndef FS_H
#define FS_H
#include "config.h"
#include "control.h"
#include "core.h"
#include "rand.h"
enum SoundEffectIndex {
FST_SE_GAMEOVER,
FST_SE_READY,
FST_SE_GO,
FST_SE_IPIECE,
FST_SE_JPIECE,
FST_SE_LPIECE,
FST_SE_OPIECE,
FST_SE_SPIECE,
FST_SE_TPIECE,
FST_SE_ZPIECE,
FST_SE_MOVE,
FST_SE_ROTATE,
FST_SE_HOLD,
FST_SE_ERASE1,
FST_SE_ERASE2,
FST_SE_ERASE3,
FST_SE_ERASE4,
FST_SE_COUNT
};
enum SoundEffect {
FST_SE_FLAG_GAMEOVER = (1 << FST_SE_GAMEOVER),
FST_SE_FLAG_READY = (1 << FST_SE_READY),
FST_SE_FLAG_GO = (1 << FST_SE_GO),
FST_SE_FLAG_IPIECE = (1 << FST_SE_IPIECE),
FST_SE_FLAG_JPIECE = (1 << FST_SE_JPIECE),
FST_SE_FLAG_LPIECE = (1 << FST_SE_LPIECE),
FST_SE_FLAG_OPIECE = (1 << FST_SE_OPIECE),
FST_SE_FLAG_SPIECE = (1 << FST_SE_SPIECE),
FST_SE_FLAG_TPIECE = (1 << FST_SE_TPIECE),
FST_SE_FLAG_ZPIECE = (1 << FST_SE_ZPIECE),
FST_SE_FLAG_MOVE = (1 << FST_SE_MOVE),
FST_SE_FLAG_ROTATE = (1 << FST_SE_ROTATE),
FST_SE_FLAG_HOLD = (1 << FST_SE_HOLD),
FST_SE_FLAG_ERASE1 = (1 << FST_SE_ERASE1),
FST_SE_FLAG_ERASE2 = (1 << FST_SE_ERASE2),
FST_SE_FLAG_ERASE3 = (1 << FST_SE_ERASE3),
FST_SE_FLAG_ERASE4 = (1 << FST_SE_ERASE4)
};
///
// Locking System type.
///,
enum LockStyle {
/// Lock delay is reset only on entry of a new piece.
FST_LOCK_ENTRY,
/// Lock delay is reset on any downwards movement.
FST_LOCK_STEP,
/// Lock delay is reset on any **successful** movement.
FST_LOCK_MOVE
};
///
// Initial Action type.
///
enum InitialActionType {
/// IHS/IRS is disabled.
FST_IA_NONE,
/// IHS/IRS can be triggered from a last frame action
FST_IA_PERSISTENT,
/// IHS/IRS must get a new event to trigger
FST_IA_TRIGGER
};
///
// All possible game states.
///
enum GameState {
/// Occurs whilst 'READY' is displayed
FSS_READY,
/// Occurs whilst 'GO' is displayed
FSS_GO,
/// Occurs when a piece has nothing beneath it.
FSS_FALLING,
/// Occurs when a piece has hit the top of the stack/floor.
FSS_LANDED,
/// Occurs when waiting for a new piece to spawn (entry delay)
FSS_ARE,
/// Occurs when a new piece needs to be spawned. This occurs instantly.
FSS_NEW_PIECE,
/// (unused) Occurs when a line clear is occurring.
FSS_LINES,
/// Occurs when a user-specified quit action occurred.
FSS_QUIT,
/// Occurs when the user lost (topped out).
FSS_GAMEOVER,
/// Occurs when the user restarts.
FSS_RESTART,
/// Unknown state
FSS_UNKNOWN
};
///
// A single faststack game instance.
//
// Stores all internal variables and options pertaining to a field.
// Values can be broken down into one of three classes.
//
// * Internal Status (@I)
// Only used internally and never required to be read by a platform.
//
// * External Status (@E)
// Calculated internally by the engine, but expected to be read by a
// user.
//
// * Fixed Option (@O)
// Can be set by the user. Typically unsafe to change during execution.
//
// We document which of the following variables belongs to which class. These
// are only guidelines and there may be cases where we need to break the
// following visibility rules.
//
// Note: ANy 'Constraints' should always be true at any point in time.
///
struct FSEngine {
/// @E: Current field state.
FSBlock b[FS_MAX_HEIGHT][FS_MAX_WIDTH];
/// @O: Current field width.
//
// * Constraints
// * fieldWidth < FS_MAX_WIDTH
i8 fieldWidth;
/// @O: Current field height.
//
// * Constraints
// * fieldHeight < FS_MAX_HEIGHT
i8 fieldHeight;
/// @0: Number of hidden rows.
//
// These are not extra rows, but rather count how many field rows are
// treated as hidden.
i8 fieldHidden;
/// @E: Next available pieces.
FSBlock nextPiece[FS_MAX_PREVIEW_COUNT];
/// @I: Current random state context.
FSRandCtx randomContext;
/// @I: Buffer for calculating next pieces.
FSBlock randBuf[FS_RAND_BUFFER_LEN];
/// @I: An extra buffer for caching special values across rolls.
u32 randBufExtra[FS_RAND_BUFFER_EXTRA_LEN];
/// @I: Index for `randBuf`
int randBufIndex;
/// @O: The way we should handle Initial Actions.
i8 initialActionStyle;
/// @E: Current sound effects to be played this frame.
u32 se;
/// @E: Current pieces type.
FSBlock piece;
/// @I: How many rotations have been done for the current piece.
i32 pieceRotateCount;
/// @I: How many movement presses have been done for the current piece.
i32 pieceMovePressCount;
/// @E: Overall finesse counter for the game
i32 finesse;
/// @E: Current pieces x position.
i8 x;
/// @E: Current pieces y position.
i8 y;
/// @I: Actual y position with greater precision.
//
// To calculate soft drop and gravity we need more precision than an
// integer can provide.
//
// * Constraints
// * actualY == tofix(y)
int32_t actualY;
/// @I: Greatest 'y' the current piece can exist at without a collision.
i8 hardDropY;
/// @E: Current pieces rotation state.
i8 theta;
/// @I: Current Initial Rotation status (set in ARE)
i8 irsAmount;
/// @I: Current Initial Hold status (set in ARE)
bool ihsFlag;
/// @O: How many blocks a piece moves per ms.
i8 dasSpeed;
/// @O: Number of ms a key must be held before repeated movement.
i32 dasDelay;
/// @E: Total number of new keys pressed during game.
i32 totalKeysPressed;
/// @O: Milliseconds between each game logic update.
i8 msPerTick;
/// @O: How many game ticks occur per draw update.
i32 ticksPerDraw;
/// @O: Length in ms that ARE should take.
i32 areDelay;
/// @I: Counter for ARE.
i32 areTimer;
/// @O: Should a sound be played if bad finesse is performed
bool warnOnBadFinesse;
/// @O: Can ARE be cancelled by input
bool areCancellable;
/// @E: Actual game length using a high precision timer.
//
// The game length is usually calculated as 'msPerTick * totalTicks' but
// this is potentially inaccurate up to (+-msPerTick). 'actualTimer' acts
// as a reliable source to ensure the game was played at the correct speed.
//
// This is calculated **only** on game finish.
i32 actualTime;
/// @I: Generic counter for multi-tick usage.
i32 genericCounter;
/// @E: Number of ticks that have elapsed during this game.
i32 totalTicks;
/// @E: Actual number of elapsed ticks (including ready, go).
i32 totalTicksRaw;
/// @O: Current lock reset style in use.
i8 lockStyle;
/// @O: Length in ms that it should take to lock a piece.
i32 lockDelay;
/// @I: Counter for locking.
i32 lockTimer;
/// @O: Maximum number of floorkicks allowed per piece.
i8 floorkickLimit;
/// @I: Count for how many floorkicks have occured.
i8 floorkickCount;
/// @O: Should soft drop be a single shot on each key press.
bool oneShotSoftDrop;
/// @O: Current rotation system being used.
i8 rotationSystem;
/// @O: How many blocks a piece will fall by every ms.
int32_t gravity;
/// @O: How many blocks a piece will fall by every ms when soft dropping.
int32_t softDropGravity;
/// @E: Current state of the internal engine.
i8 state;
/// @E: State of the game during the last frame.
i8 lastState;
/// @I: Key input applied during the last logic update.
FSInput lastInput;
/// @O: Current randomizer in play. */
i8 randomizer;
/// @I: Randomizer seed
u32 seed;
/// @I: The randomizer in use during the last game update.
//
// Used to determine if reinitialization of a randomizer is required.
// This allows one to alter than randomizer mid-game.
i8 lastRandomizer;
/// @O: How long the "Ready" phase countdown should last in ms
i32 readyPhaseLength;
/// @O: How long the "Go" phase countdown should last in ms
i32 goPhaseLength;
/// @O: Whether infinite hold is allowed during pre-game.
bool infiniteReadyGoHold;
/// @O: Number of preview pieces displayed.
i8 nextPieceCount;
/// @I: Whether a hold can be performed.
bool holdAvailable;
/// @E: Current piece we are holding.
FSBlock holdPiece;
/// @E: Number of cleared lines during the games lifetime
i32 linesCleared;
/// @E: Number of blocks placed during the games lifetime.
i32 blocksPlaced;
/// @O: Target number of lines to clear during this game.
i32 goal;
/// @I: Is this a replay and not a real game?
bool replay;
};
///
// Transform a field block into an actual block representation.
///
FSBlock fsFieldPieceBlock(FSBlock b);
///
// Clear the specified game instance.
//
// This only resets internal variables and will not overwrite any user specified
// options. This is suitable to call when a new game is wanted to be started
// without reloading an options file/keeping track of options elsewhere.
//
// * FSEngine *f
// The instance to clear.
///
void fsGameReset(FSEngine *f);
///
// Initialize a game instance.
//
// This will reset all internal variables and also set options to their
// default values.
///
void fsGameInit(FSEngine *f);
///
// Perform a single game update.
//
// * FSEngine *f
// The instance to update
//
// * const FSInput *i
// The input for the instance to compute.
///
void fsGameTick(FSEngine *f, const FSInput *i);
///
// Convert the specified into its individual blocks.
//
// * const FSEngine *f
// The instance which options are used
//
// * i8x2 *dst
// The destination buffer to store the pieces in.
//
// Note: **must** be greater than or equal to FS_NBP in size.
//
// * i8 piece
// Type of piece to generate.
//
// * int x
// X coordinate of the piece
//
// * int y
// Y coordinate of the piece
//
// * int theta
// Rotation state of the piece.
//
///
void fsGetBlocks(const FSEngine *f, i8x2 dst[static FS_NBP],
i8 piece, int x, int y, int theta);
#endif // FS_H