Mercurial > hg > index.fcgi > lj > lj046
view src/speed.c @ 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 /* Speed curve tables for LOCKJAW, an implementation of the Soviet Mind Game
3 Copyright (C) 2006-2007 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 */
24 #include "lj.h"
25 #include "ljcontrol.h"
27 static const LJFixed initialGravity[LJSPD_N_CURVES] = {
28 [LJSPD_RHYTHMZERO] = 0,
29 [LJSPD_RHYTHM] = LJITOFIX(20)
30 };
32 /**
33 * The default speed curve for each gimmick. A negative value
34 * means that the gimmick uses the player's chosen speed curve.
35 */
36 static const signed char defaultSpeedCurve[LJGM_N_GIMMICKS] = {
37 [LJGM_ATYPE] = -1,
38 [LJGM_BTYPE] = -1,
39 [LJGM_ULTRA] = -1,
40 [LJGM_DRILL] = -1,
41 [LJGM_ITEMS] = -1,
42 [LJGM_BABY] = LJSPD_ZERO
43 };
45 /* The new speed curve code ****************************************/
47 #define SCGRAV(n, d) ((n) * 2048 / (d))
49 enum {
50 SPEEDTYPE_RHYTHM,
51 SPEEDTYPE_TGM,
52 SPEEDTYPE_LINES,
53 SPEEDTYPE_PIECES
54 };
56 typedef struct LJSpeedStep {
57 unsigned short level, gravity;
58 signed char are, das, lock, line;
59 } LJSpeedStep;
61 typedef struct LJSpeedCurve {
62 char name[32];
63 unsigned char type, sectionLen;
64 unsigned char nSteps;
65 const LJSpeedStep steps[];
66 } LJSpeedCurve;
68 const LJSpeedCurve scMaster = {
69 "Master",
70 SPEEDTYPE_TGM, 100,
71 33,
72 {
73 { 0, SCGRAV( 4,256),25,16,30,40},
74 { 30, SCGRAV( 6,256),25,16,30,40},
75 { 35, SCGRAV( 8,256),25,16,30,40},
76 { 40, SCGRAV( 10,256),25,16,30,40},
77 { 50, SCGRAV( 12,256),25,16,30,40},
78 { 60, SCGRAV( 16,256),25,16,30,40},
79 { 70, SCGRAV( 32,256),25,16,30,40},
80 { 80, SCGRAV( 48,256),25,16,30,40},
81 { 90, SCGRAV( 64,256),25,16,30,40},
82 {100, SCGRAV( 80,256),25,16,30,40},
83 {120, SCGRAV( 96,256),25,16,30,40},
84 {140, SCGRAV(112,256),25,16,30,40},
85 {160, SCGRAV(128,256),25,16,30,40},
86 {170, SCGRAV(144,256),25,16,30,40},
87 {200, SCGRAV( 4,256),25,16,30,40},
88 {220, SCGRAV( 32,256),25,16,30,40},
89 {230, SCGRAV( 64,256),25,16,30,40},
90 {233, SCGRAV( 96,256),25,16,30,40},
91 {236, SCGRAV(128,256),25,16,30,40},
92 {239, SCGRAV(160,256),25,16,30,40},
93 {243, SCGRAV(192,256),25,16,30,40},
94 {247, SCGRAV(224,256),25,16,30,40},
95 {251, SCGRAV( 1,1), 25,16,30,40},
96 {300, SCGRAV( 2,1), 25,16,30,40},
97 {330, SCGRAV( 3,1), 25,16,30,40},
98 {360, SCGRAV( 4,1), 25,16,30,40},
99 {400, SCGRAV( 5,1), 25,16,30,40},
100 {450, SCGRAV( 3,1), 25,16,30,40},
101 {500, SCGRAV(20,1), 25,10,30,25},
102 {600, SCGRAV(20,1), 25,10,30,16},
103 {700, SCGRAV(20,1), 16,10,30,12},
104 {800, SCGRAV(20,1), 12,10,30, 6},
105 {900, SCGRAV(20,1), 12, 8,17, 6}
106 }
107 };
109 const LJSpeedCurve scDeath = {
110 "Death",
111 SPEEDTYPE_TGM, 100,
112 6,
113 {
114 { 0, SCGRAV(20,1), 18,12,30, 8},
115 {100, SCGRAV(20,1), 14,12,26, 0},
116 {200, SCGRAV(20,1), 14,11,22, 0},
117 {300, SCGRAV(20,1), 8,10,18, 6},
118 {400, SCGRAV(20,1), 7, 8,15, 5},
119 {500, SCGRAV(20,1), 6, 8,15, 4}
120 }
121 };
123 const LJSpeedCurve scNES = {
124 "NES",
125 SPEEDTYPE_LINES, 10,
126 15,
127 {
128 { 0, SCGRAV(1,48), 10,-1, 0,30},
129 { 10, SCGRAV(1,43), 10,-1, 0,30},
130 { 20, SCGRAV(1,38), 10,-1, 0,30},
131 { 30, SCGRAV(1,33), 10,-1, 0,30},
132 { 40, SCGRAV(1,28), 10,-1, 0,30},
133 { 50, SCGRAV(1,23), 10,-1, 0,30},
134 { 60, SCGRAV(1,18), 10,-1, 0,30},
135 { 70, SCGRAV(1,13), 10,-1, 0,30},
136 { 80, SCGRAV(1, 8), 10,-1, 0,30},
137 { 90, SCGRAV(1, 6), 10,-1, 0,30},
138 {100, SCGRAV(1, 5), 10,-1, 0,30},
139 {130, SCGRAV(1, 4), 10,-1, 0,30},
140 {160, SCGRAV(1, 3), 10,-1, 0,30},
141 {190, SCGRAV(1, 2), 10,-1, 0,30},
142 {290, SCGRAV(1, 1), 10,-1, 0,30},
143 }
144 };
146 const LJSpeedCurve scGB = {
147 "Game Boy",
148 SPEEDTYPE_LINES, 10,
149 18,
150 {
151 { 0, SCGRAV(1,53), 0,-1, 0,90},
152 { 10, SCGRAV(1,49), 0,-1, 0,90},
153 { 20, SCGRAV(1,45), 0,-1, 0,90},
154 { 30, SCGRAV(1,41), 0,-1, 0,90},
155 { 40, SCGRAV(1,37), 0,-1, 0,90},
156 { 50, SCGRAV(1,33), 0,-1, 0,90},
157 { 60, SCGRAV(1,28), 0,-1, 0,90},
158 { 70, SCGRAV(1,22), 0,-1, 0,90},
159 { 80, SCGRAV(1,17), 0,-1, 0,90},
160 { 90, SCGRAV(1,11), 0,-1, 0,90},
161 {100, SCGRAV(1,10), 0,-1, 0,90},
162 {110, SCGRAV(1, 9), 0,-1, 0,90},
163 {120, SCGRAV(1, 8), 0,-1, 0,90},
164 {130, SCGRAV(1, 7), 0,-1, 0,90},
165 {140, SCGRAV(1, 6), 0,-1, 0,90},
166 {160, SCGRAV(1, 5), 0,-1, 0,90},
167 {180, SCGRAV(1, 4), 0,-1, 0,90},
168 {200, SCGRAV(1, 3), 0,-1, 0,90},
169 }
170 };
172 const LJSpeedCurve scZero = {
173 "Zero",
174 SPEEDTYPE_LINES, 10,
175 1,
176 {
177 { 0, SCGRAV(0, 1),-1,-1,40,-1}
178 }
179 };
181 const LJSpeedCurve scExponential = {
182 "Exponential",
183 SPEEDTYPE_PIECES, 60,
184 34,
185 {
186 { 0, SCGRAV( 1,60),-1,-1,40,-1 },
187 { 30, SCGRAV( 1,42),-1,-1,40,-1 },
188 { 60, SCGRAV( 2,60),-1,-1,40,-1 },
189 { 90, SCGRAV( 2,42),-1,-1,40,-1 },
190 {120, SCGRAV( 4,60),-1,-1,40,-1 },
191 {150, SCGRAV( 4,42),-1,-1,40,-1 },
192 {180, SCGRAV( 8,60),-1,-1,40,-1 },
193 {210, SCGRAV( 8,42),-1,-1,40,-1 },
194 {240, SCGRAV( 16,60),-1,-1,40,-1 },
195 {270, SCGRAV( 16,42),-1,-1,40,-1 },
196 {300, SCGRAV( 32,60),-1,-1,40,-1 },
197 {330, SCGRAV( 32,42),-1,-1,40,-1 },
198 {360, SCGRAV( 64,60),-1,-1,40,-1 },
199 {390, SCGRAV( 64,42),-1,-1,40,-1 },
200 {420, SCGRAV(128,60),-1,-1,40,-1 },
201 {450, SCGRAV(128,42),-1,-1,40,-1 },
202 {480, SCGRAV(256,60),-1,-1,40,-1 },
203 {510, SCGRAV(256,42),-1,-1,40,-1 },
204 {540, SCGRAV(512,60),-1,-1,40,-1 },
205 {570, SCGRAV(512,42),-1,-1,40,-1 },
206 {600, SCGRAV( 20, 1),-1,-1,40,-1 },
207 {630, SCGRAV( 20, 1),-1,-1,30,-1 },
208 {660, SCGRAV( 20, 1),-1,-1,24,-1 },
209 {690, SCGRAV( 20, 1),-1,-1,20,-1 },
210 {720, SCGRAV( 20, 1),-1,-1,17,-1 },
211 {750, SCGRAV( 20, 1),-1,-1,15,-1 },
212 {780, SCGRAV( 20, 1),-1,-1,13,-1 },
213 {810, SCGRAV( 20, 1),-1,-1,12,-1 },
214 {840, SCGRAV( 20, 1),-1,-1,11,-1 },
215 {870, SCGRAV( 20, 1),-1,-1,10,-1 },
216 {900, SCGRAV( 20, 1),-1,-1, 9,-1 },
217 {930, SCGRAV( 20, 1),-1,-1, 8,-1 },
218 {960, SCGRAV( 20, 1),-1,-1, 7,-1 },
219 {990, SCGRAV( 20, 1),-1,-1, 6,-1 }
220 }
221 };
223 static const LJSpeedCurve *const newSpeedCurves[LJSPD_N_CURVES] = {
224 [LJSPD_EXP] = &scExponential,
225 [LJSPD_ZERO] = &scZero,
226 [LJSPD_TGM] = &scMaster,
227 [LJSPD_DEATH] = &scDeath,
228 [LJSPD_DEATH300] = &scDeath,
229 [LJSPD_NES] = &scNES,
230 [LJSPD_GB] = &scGB,
231 [LJSPD_GBHEART] = &scGB,
232 };
234 /**
235 * Performs a fast binary search of a speed step table.
236 */
237 static const LJSpeedStep *getSpeedStep(const LJSpeedStep *steps,
238 size_t nSteps, int level) {
239 unsigned int lo = 0;
240 unsigned int hi = nSteps;
242 while (hi - lo > 1) {
243 size_t mid = (hi + lo) / 2;
244 unsigned int here = steps[mid].level;
245 if (here == level) {
246 return &(steps[mid]);
247 } else if (here < level) {
248 lo = mid;
249 } else {
250 hi = mid;
251 }
252 }
253 return &(steps[lo]);
254 }
256 /**
257 * Updates the level after each piece has retired.
258 * @return nonzero iff a new section has happened
259 */
260 int updLevelAfterPiece(LJField *p) {
261 int curveID = p->speedState.curve;
262 const LJSpeedCurve *curve = newSpeedCurves[curveID];
263 if (!curve) {
264 return 0;
265 }
266 unsigned int sectionLen = curve->sectionLen;
267 unsigned int oldLevel = p->speedState.level;
268 unsigned int oldSection = oldLevel / sectionLen;
269 unsigned int oldSectionPos = oldLevel % sectionLen;
271 switch (curve->type) {
272 case SPEEDTYPE_TGM:
273 if (oldSectionPos + 1 >= sectionLen) {
274 return 0;
275 }
276 // otherwise fall through to +1 per piece
278 case SPEEDTYPE_PIECES:
279 p->speedState.level = oldLevel + 1;
280 break;
282 default:
283 return 0;
284 }
286 unsigned int newSection = p->speedState.level / sectionLen;
287 return newSection > oldSection;
288 }
290 /**
291 * Updates the level after lines have been cleared.
292 * @return nonzero iff a new section has happened
293 */
294 int updLevelAfterLines(LJField *p, unsigned int nLines) {
295 int curveID = p->speedState.curve;
296 const LJSpeedCurve *curve = newSpeedCurves[curveID];
297 if (!curve) {
298 return 0;
299 }
300 unsigned int sectionLen = curve->sectionLen;
301 unsigned int oldLevel = p->speedState.level;
302 unsigned int oldSection = oldLevel / sectionLen;
304 switch (curve->type) {
305 case SPEEDTYPE_TGM:
306 case SPEEDTYPE_LINES:
307 p->speedState.level = oldLevel + nLines;
308 break;
310 default:
311 return 0;
312 }
314 unsigned int newSection = p->speedState.level / sectionLen;
315 return newSection > oldSection;
316 }
318 void setSpeedNew(LJField *p, LJControl *c) {
319 int curveID = p->speedState.curve;
320 const LJSpeedCurve *curve = newSpeedCurves[curveID];
321 if (!curve) {
322 return;
323 }
324 const LJSpeedStep *step =
325 getSpeedStep(curve->steps, curve->nSteps, p->speedState.level);
327 p->speed.gravity = step->gravity << 5;
329 p->speed.entryDelay = step->are;
330 if (p->speed.entryDelay > p->areStyle) {
331 p->speed.entryDelay = p->areStyle;
332 }
334 if (step->das > 0 && c->dasDelay > step->das) {
335 c->dasDelay = step->das;
336 }
338 if (p->setLockDelay >= 128) {
339 p->speed.lockDelay = 127;
340 } else if (p->setLockDelay > 0) {
341 p->speed.lockDelay = p->setLockDelay;
342 } else if (step->lock > 0) {
343 p->speed.lockDelay = step->lock;
344 }
346 if (p->setLineDelay > 0) {
347 p->speed.lineDelay = p->setLineDelay;
348 } else if (step->line >= 0) {
349 p->speed.lineDelay = step->line;
350 } else {
351 p->speed.lineDelay = p->speed.entryDelay;
352 }
353 }
357 /* Old speed curve system is below this line ***********************/
361 void initSpeed(LJField *p) {
362 if (defaultSpeedCurve[p->gimmick] >= 0) {
363 p->speedState.curve = defaultSpeedCurve[p->gimmick];
364 }
365 p->speed.gravity = initialGravity[p->speedState.curve];
367 switch (p->speedState.curve) {
368 case LJSPD_RHYTHM:
369 case LJSPD_RHYTHMZERO:
370 p->speedState.level = 60;
371 p->bpmCounter = 0;
372 p->speedupCounter = 0;
373 break;
374 case LJSPD_TGM:
375 case LJSPD_DEATH:
376 case LJSPD_EXP:
377 p->speedState.level = -1;
378 break;
379 case LJSPD_DEATH300:
380 p->speedState.level = 300;
381 break;
382 case LJSPD_GBHEART:
383 p->speedState.level = 100;
384 break;
385 default:
386 p->speedState.level = 0;
387 break;
388 }
389 }
392 void setSpeed(LJField *p, LJControl *c) {
393 p->speed.entryDelay = p->areStyle;
395 // Default line delay is equal to the entry delay,
396 // but speed curves and setLineDelay can override this
397 p->speed.lineDelay = p->speed.entryDelay;
398 switch (p->speedState.curve) {
400 case LJSPD_RHYTHM:
401 case LJSPD_RHYTHMZERO:
402 // If we've already banked five pieces' worth of time,
403 // add 20 points instead of banking another.
404 if (p->bpmCounter <= -18000) {
405 // removed in 0.21 because other curves don't reward for drops
406 // p->score += 20;
407 } else {
408 p->bpmCounter -= 3600; // number of frames per minute
409 }
410 p->speed.lockDelay = 3600 / p->speedState.level;
411 p->speed.gravity = (p->speedState.curve == LJSPD_RHYTHM) ? ljitofix(20) : 0;
412 break;
414 default:
415 if (updLevelAfterPiece(p)) {
416 p->sounds |= LJSND_SECTIONUP;
417 }
418 setSpeedNew(p, c);
419 break;
420 }
422 if (p->setLockDelay >= 128) {
423 p->speed.lockDelay = 127;
424 } else if (p->setLockDelay > 0) {
425 p->speed.lockDelay = p->setLockDelay;
426 }
427 if (p->setLineDelay > 0) {
428 p->speed.lineDelay = p->setLineDelay;
429 }
430 }