comparison src/macro.c @ 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:dab37cb9f051
1 /* Input handling for LOCKJAW Tetromino 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 #include "lj.h"
25 #include "ljcontrol.h"
26 #include "ljreplay.h"
27 #include "pcjoy.h"
28
29 // first is rotation (+1 = 90 deg clockwise)
30 // second is movement (+1 = right 1 block)
31 // third is gravity (+1 = down 1/8 block)
32 // fourth is extra actions (hold, lock)
33 LJInput macros[8] = {
34 { -1, 0, 0, 0 }, // default: alt. rotate left
35 { -2, 0, 0, 0 }, // default: rotate left twice
36 { 0, -9, 0, 0 }, // default: far left
37 { 0, 9, 0, 0 }, // default: far right
38 { 0, 0, 20*8, 0 }, // default: firm drop
39 { 0, 0, 0, LJI_HOLD }, // default: alternate hold
40 { 0, 0, 0, 0 },
41 { 0, 0, 0, 0 }
42 };
43
44 void addMacrosToInput(LJInput *dst, LJBits keys) {
45 int rotation = dst->rotation;
46 int movement = dst->movement;
47 int gravity = dst->gravity;
48 int other = dst->other;
49 int macro;
50
51 keys >>= 8;
52 for (macro = 0;
53 macro < 8;
54 keys >>= 1, ++macro) {
55 if (keys & 1) {
56 rotation += macros[macro].rotation;
57 movement += macros[macro].movement;
58 gravity += macros[macro].gravity;
59 other |= macros[macro].other;
60 }
61 }
62
63 // Clip rotation to [-3, +3]
64 rotation -= rotation / 4 * 4;
65
66 // Clip movement to playfield width
67 if (movement < (int)-LJ_PF_WID) {
68 movement = -LJ_PF_WID;
69 } else if (movement > (int)LJ_PF_WID) {
70 movement = LJ_PF_WID;
71 }
72
73 // Clip gravity to playfield height
74 if (gravity > LJ_PF_HT * 8) {
75 gravity = LJ_PF_HT * 8;
76 }
77
78 dst->rotation = rotation;
79 dst->movement = movement;
80 dst->gravity = gravity;
81 dst->other = other;
82 }
83
84 static const LJFixed softDropSpeeds[3] = {
85 LJITOFIX(1),
86 LJITOFIX(1)/2,
87 LJITOFIX(1)/3
88 };
89
90 void addKeysToInput(LJInput *dst, LJBits keys, const LJField *p, LJControl *c) {
91 int actualKeys = keys;
92
93 if (c->replaySrc) {
94 keys = getReplayFrame(c->replaySrc, dst);
95 if (keys == LJREPLAY_EOF) {
96 keys = actualKeys;
97 replayClose(c->replaySrc);
98 c->replaySrc = NULL;
99 }
100 }
101
102 int lastFrameKeys = c->lastKeys;
103
104 // If diagonal presses are disabled, ignore any changes
105 if (!c->allowDiagonals
106 && (keys & (VKEY_UP | VKEY_DOWN))
107 && (keys & (VKEY_LEFT | VKEY_RIGHT))) {
108 keys &= ~(VKEY_UP | VKEY_DOWN | VKEY_LEFT | VKEY_RIGHT);
109 keys |= lastFrameKeys
110 & (VKEY_UP | VKEY_DOWN | VKEY_LEFT | VKEY_RIGHT);
111 }
112
113 LJBits newKeys = keys & ~lastFrameKeys;
114 c->lastKeys = keys;
115
116 // Count presses for Baboo!, excluding console buttons
117 c->presses += countOnes(newKeys & 0x0000FFFF);
118
119 // Only once the side effect of counting presses for Baboo!
120 // is complete can we break out of a replay.
121 if (c->replaySrc) {
122 return;
123 }
124
125 LJBits releasedKeys = ~keys & lastFrameKeys;
126
127 // At this point, c->lastKeys holds the keys actually held
128 // by the player this frame, and lastFrameKeys holds the keys
129 // actually held by the player last frame.
130
131 // Handle keys that must be re-pressed
132 releasedKeys &= ~c->repressKeys;
133 c->repressKeys &= keys;
134 keys &= ~c->repressKeys;
135
136 // If locking in a mode without ARE, require
137 // down to be re-pressed before next piece
138 if (p->sounds & LJSND_LOCK
139 && p->speed.entryDelay <= c->dasDelay) {
140 c->repressKeys |= VKEY_DOWN;
141
142 // Treat up the same way when hard drop lock is set to lock on release.
143 if (c->hardDropLock != LJZANGI_SLIDE
144 || p->lockReset == LJLOCK_NOW
145 || p->speed.lockDelay <= c->dasDelay) {
146 c->repressKeys |= VKEY_UP | VKEY_MACRO(4);
147 }
148 }
149
150 // Initial Rotation System (IRS):
151 // When a piece spawns from next or hold, and a rotation or macro
152 // key is held, treat the key as if they had just been pressed.
153 // Treat hard drop the same way when ARE is turned on.
154 if ((p->sounds & (LJSND_SPAWN | LJSND_HOLD))
155 && c->initialRotate) {
156 newKeys |= c->lastKeys
157 & (VKEY_ROTL | VKEY_ROTR | VKEY_MACROS);
158 if (p->speed.entryDelay > 0) {
159 newKeys |= c->lastKeys
160 & VKEY_UP;
161 }
162 }
163
164 // if we're pretending that keys are not pressed,
165 // pretend consistently
166 newKeys &= keys;
167
168 // TGM does not perform sideways movement on
169 // the first frame after a piece is spawned.
170 if (c->initialDAS == 0 &&
171 (p->sounds & (LJSND_SPAWN | LJSND_HOLD))) {
172
173 } else if (keys & VKEY_LEFT) {
174 if (c->dasCounter > -(int)c->dasDelay) {
175 if (c->dasCounter >= 0) {
176 c->dasCounter = -1;
177 dst->movement = -1;
178 } else {
179 c->dasCounter -= 1;
180 }
181 } else {
182 int dasSpeed = c->dasSpeed;
183 if (dasSpeed) {
184 dst->movement = -1;
185 c->dasCounter += dasSpeed - 1;
186 } else {
187 dst->movement = -(int)LJ_PF_WID;
188 }
189 }
190 } else if (keys & VKEY_RIGHT) {
191 if (c->dasCounter < c->dasDelay) {
192 if (c->dasCounter <= 0) {
193 c->dasCounter = 1;
194 dst->movement = 1;
195 } else {
196 c->dasCounter += 1;
197 }
198 } else {
199 int dasSpeed = c->dasSpeed;
200 if (dasSpeed) {
201 dst->movement = 1;
202 c->dasCounter -= dasSpeed - 1;
203 } else {
204 dst->movement = (int)LJ_PF_WID;
205 }
206 }
207 } else {
208 c->dasCounter = 0;
209 }
210
211 if(keys & VKEY_DOWN) {
212 int g = softDropSpeeds[c->softDropSpeed];
213
214 // dither speed to 1/8G units
215 g += ljitofix(p->gameTime % 3) / 24;
216 dst->gravity += g >> 13;
217
218 if ((newKeys & VKEY_DOWN)
219 || c->softDropLock == LJZANGI_LOCK) {
220 dst->other |= LJI_LOCK;
221 }
222 }
223
224 if (newKeys & VKEY_ROTL) {
225 dst->rotation -= 1;
226 }
227 if (newKeys & VKEY_ROTR) {
228 dst->rotation += 1;
229 }
230 if (newKeys & VKEY_HOLD) {
231 dst->other |= LJI_HOLD;
232 }
233 if (newKeys & VKEY_UP) {
234 dst->gravity = LJ_PF_HT << 3;
235 if (p->state == LJS_LANDED
236 || c->hardDropLock == LJZANGI_LOCK) {
237 dst->other |= LJI_LOCK;
238 }
239 }
240
241 if (c->hardDropLock == LJZANGI_LOCK_RELEASE) {
242 if (releasedKeys & VKEY_UP) {
243 dst->other |= LJI_LOCK;
244 }
245 }
246 if (c->softDropLock == LJZANGI_LOCK_RELEASE) {
247 if (releasedKeys & VKEY_DOWN) {
248 dst->other |= LJI_LOCK;
249 }
250 }
251
252 addMacrosToInput(dst, newKeys);
253
254 // Baboo! ends with a hard drop
255 if (p->gimmick == LJGM_BABY && c->presses >= 300) {
256 dst->gravity = LJ_PF_HT << 3;
257 dst->other |= LJI_LOCK;
258 }
259
260 if (c->replayDst) {
261 replayRecord(c->replayDst, actualKeys, dst);
262 }
263 }