paulo@0: /* Scenario code for LOCKJAW, an implementation of the Soviet Mind Game paulo@0: paulo@0: Copyright (C) 2008 Damian Yerrick paulo@0: paulo@0: This work is free software; you can redistribute it and/or modify paulo@0: it under the terms of the GNU General Public License as published by paulo@0: the Free Software Foundation; either version 2 of the License, or paulo@0: (at your option) any later version. paulo@0: paulo@0: This program is distributed in the hope that it will be useful, paulo@0: but WITHOUT ANY WARRANTY; without even the implied warranty of paulo@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the paulo@0: GNU General Public License for more details. paulo@0: paulo@0: You should have received a copy of the GNU General Public License paulo@0: along with this program; if not, write to the Free Software paulo@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA paulo@0: paulo@0: Original game concept and design by Alexey Pajitnov. paulo@0: The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg, paulo@0: or The Tetris Company LLC. paulo@0: paulo@0: */ paulo@0: paulo@0: #include "scenario.h" paulo@0: #include "options.h" paulo@0: #include paulo@0: paulo@0: #define END_OF_PRESET {OPTIONS_MENU_LEN} paulo@0: paulo@0: const Preset predefPresets[] = { paulo@0: {"Guideline", { paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTRY_DELAY, 0}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_BAG}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_EMPTY}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_SRS}, paulo@0: {OPTIONS_FLOOR_KICKS, 6}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_MOVE}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 30}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, 0}, paulo@0: {OPTIONS_SCORING, LJSCORE_TDS}, paulo@0: {OPTIONS_DROP_SCORING, LJDROP_1S_2H}, paulo@0: {OPTIONS_T_SPIN, LJTS_TDS}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: {"Classic", { paulo@0: {OPTIONS_GIMMICK, LJGM_ATYPE}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 0}, paulo@0: {OPTIONS_ENTRY_DELAY, 10}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_NES}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_PURE}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_NONE}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_NES}, paulo@0: {OPTIONS_FLOOR_KICKS, 0}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_NOW}, paulo@0: {OPTIONS_LOCK_DELAY, 0}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 30}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, 0}, paulo@0: {OPTIONS_SCORING, LJSCORE_NES}, paulo@0: {OPTIONS_DROP_SCORING, LJDROP_NES}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 15}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 6}, paulo@0: {OPTIONS_SOFT_DROP_SPEED, 2}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 1}, paulo@0: {OPTIONS_IRS, 0}, paulo@0: {OPTIONS_NEXT_PIECES, 1}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=892 */ paulo@0: {"Master", { paulo@0: {OPTIONS_GIMMICK, LJGM_ATYPE}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 0}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_TGM}, paulo@0: {OPTIONS_ENTRY_DELAY, 30}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_HIST_6}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_NONE}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_ARIKA}, paulo@0: {OPTIONS_FLOOR_KICKS, 0}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_STEP}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, LJGLUING_STICKY}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 16}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 1}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 0}, paulo@0: {OPTIONS_IRS, 1}, paulo@0: {OPTIONS_SOFT_DROP_SPEED, 1}, paulo@0: {OPTIONS_SOFT_DROP, LJZANGI_LOCK}, paulo@0: {OPTIONS_HARD_DROP, LJZANGI_SLIDE}, paulo@0: {OPTIONS_NEXT_PIECES, 1}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=892 */ paulo@0: {"T.A. Death", { paulo@0: {OPTIONS_GIMMICK, LJGM_ATYPE}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_DEATH}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 0}, paulo@0: {OPTIONS_ENTRY_DELAY, 30}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_HIST_6}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_NONE}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_ARIKA}, paulo@0: {OPTIONS_FLOOR_KICKS, 0}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_STEP}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, LJGLUING_STICKY}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 16}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 1}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 0}, paulo@0: {OPTIONS_IRS, 1}, paulo@0: {OPTIONS_NEXT_PIECES, 1}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: {"Square", { paulo@0: {OPTIONS_GIMMICK, LJGM_ATYPE}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 1}, paulo@0: {OPTIONS_ENTRY_DELAY, 30}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_EXP}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_PURE}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_TNT}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_SRS}, paulo@0: {OPTIONS_FLOOR_KICKS, 6}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_STEP}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 40}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, LJGLUING_SQUARE}, paulo@0: {OPTIONS_SCORING, LJSCORE_TNT64}, paulo@0: {OPTIONS_DROP_SCORING, LJDROP_NOSCORE}, paulo@0: {OPTIONS_T_SPIN, LJTS_TNT}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 11}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 5}, paulo@0: {OPTIONS_SOFT_DROP_SPEED, 2}, paulo@0: {OPTIONS_SOFT_DROP, LJZANGI_SLIDE}, paulo@0: {OPTIONS_HARD_DROP, LJZANGI_SLIDE}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 0}, paulo@0: {OPTIONS_IRS, 0}, paulo@0: {OPTIONS_NEXT_PIECES, 3}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=549 */ paulo@0: {"40 Lines", { paulo@0: {OPTIONS_GIMMICK, LJGM_BTYPE}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GARBAGE, 0}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=549 */ paulo@0: {"180 Seconds", { paulo@0: {OPTIONS_GIMMICK, LJGM_ULTRA}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_EMPTY}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, 0}, paulo@0: {OPTIONS_SCORING, LJSCORE_LJ}, paulo@0: {OPTIONS_DROP_SCORING, 0}, paulo@0: {OPTIONS_T_SPIN, 0}, paulo@0: {OPTIONS_GARBAGE, 0}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=892 */ paulo@0: {"Death 300", { paulo@0: {OPTIONS_GIMMICK, LJGM_ULTRA}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_DEATH300}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 0}, paulo@0: {OPTIONS_ENTRY_DELAY, 30}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_HIST_6}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_EMPTY}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_ARIKA}, paulo@0: {OPTIONS_FLOOR_KICKS, 0}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_STEP}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, LJGLUING_STICKY}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 16}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 1}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 0}, paulo@0: {OPTIONS_IRS, 1}, paulo@0: {OPTIONS_NEXT_PIECES, 1}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: {"M-Roll", { paulo@0: {OPTIONS_GIMMICK, LJGM_BTYPE}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_DEATH300}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_HEIGHT, 20}, paulo@0: {OPTIONS_ENTER_ABOVE, 0}, paulo@0: {OPTIONS_ENTRY_DELAY, 30}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_RANDOMIZER, LJRAND_HIST_6}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_EMPTY}, paulo@0: {OPTIONS_ROTATION_SYSTEM, LJROT_ARIKA}, paulo@0: {OPTIONS_FLOOR_KICKS, 0}, paulo@0: {OPTIONS_LOCKDOWN, LJLOCK_STEP}, paulo@0: {OPTIONS_LOCK_DELAY, 30}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_LINE_DELAY, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, LJGLUING_STICKY}, paulo@0: {OPTIONS_GARBAGE, LJGARBAGE_NONE}, paulo@0: {OPTIONS_SIDEWAYS_DELAY, 16}, paulo@0: {OPTIONS_SIDEWAYS_SPEED, 1}, paulo@0: {OPTIONS_INITIAL_SIDEWAYS, 0}, paulo@0: {OPTIONS_IRS, 1}, paulo@0: {OPTIONS_NEXT_PIECES, 1}, paulo@0: {OPTIONS_HIDE_PF, 1}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=549 */ paulo@0: {"Cascade", { paulo@0: {OPTIONS_GIMMICK, LJGM_BTYPE}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_HOLD_PIECE, LJHOLD_EMPTY}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_CASCADE}, paulo@0: {OPTIONS_GARBAGE, 0}, paulo@0: END_OF_PRESET paulo@0: }}, paulo@0: paulo@0: /* http://www.tetrisconcept.com/forum/viewtopic.php?t=777 */ paulo@0: {"Baboo!", { paulo@0: {OPTIONS_GIMMICK, LJGM_BABY}, paulo@0: {OPTIONS_WIDTH, 10}, paulo@0: {OPTIONS_PIECE_SET, LJRAND_4BLK}, paulo@0: {OPTIONS_SPEED_CURVE, LJSPD_ZERO}, paulo@0: {OPTIONS_BOTTOM_BLOCKS, 0}, paulo@0: {OPTIONS_CLEAR_GRAVITY, LJGRAV_NAIVE}, paulo@0: {OPTIONS_GLUING, 0}, paulo@0: {OPTIONS_SCORING, LJSCORE_LJ}, paulo@0: {OPTIONS_DROP_SCORING, 0}, paulo@0: {OPTIONS_T_SPIN, LJTS_TDS}, paulo@0: {OPTIONS_GARBAGE, 0} paulo@0: }}, paulo@0: paulo@0: }; paulo@0: paulo@0: const Preset *loadedPresets = predefPresets; paulo@0: size_t nLoadedPresets = sizeof(predefPresets)/sizeof(predefPresets[0]); paulo@0: paulo@0: static unsigned char presetBuffer[OPTIONS_MENU_LEN]; paulo@0: paulo@0: void presetStart(void) { paulo@0: memset(&presetBuffer, 255, sizeof(presetBuffer)); paulo@0: } paulo@0: paulo@0: void presetAdd(size_t which) { paulo@0: if (which >= nLoadedPresets) { paulo@0: return; paulo@0: } paulo@0: const PresetRule *r = loadedPresets[which].rules; paulo@0: for (size_t i = 0; paulo@0: i < PRESET_MAX_RULES paulo@0: && r[i].line < OPTIONS_MENU_LEN; paulo@0: ++i) { paulo@0: presetBuffer[r[i].line] = r[i].value; paulo@0: } paulo@0: } paulo@0: paulo@0: void presetFinish(struct LJView *v) { paulo@0: unpackCommonOptions(v, presetBuffer); paulo@0: } paulo@0: paulo@0: #if 0 paulo@0: void loadPresetsFromText(FILE *fp) { paulo@0: Preset *presets = NULL; paulo@0: paulo@0: size_t capacity = 0, n = 0; paulo@0: paulo@0: { paulo@0: // allocate memory for this preset paulo@0: if (capacity <= n) { paulo@0: if (capacity < 32) { paulo@0: capacity += 16; paulo@0: } else { paulo@0: capacity += capacity / 2; paulo@0: } paulo@0: Preset *newPresets = realloc(presets, paulo@0: capacity * sizeof(preset)); paulo@0: // if we can't allocate memory, screw it paulo@0: if (!newPresets) { paulo@0: break; paulo@0: } paulo@0: } paulo@0: } paulo@0: paulo@0: loadedPresets = presets; paulo@0: nLoadedPresets = n; paulo@0: } paulo@0: #endif paulo@0: