Mercurial > hg > index.fcgi > lj > lj046
view src/wktables.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 /* Wall kick tables for 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 #define LJ_INTERNAL
26 #include "lj.h"
29 // These wall kicks are for rotation TO a given orientation.
30 // Based on http://www.the-shell.net/img/srs_study.html
31 static const LJRotSystem rotSRS = {
32 .kicksL = {1, 0, 0, -1, 0, 0, 0, -1, 0, -1},
33 .kicksR = {3, 2, 2, -1, 2, 2, 2, -1, 2, -3},
34 .kickTables = {
36 // 0: JLSTZ counterclockwise
37 {
38 { WK( 0, 0),WK( 1, 0),WK( 1,-1),WK( 0, 2),WK( 1, 2) }, // R->U
39 { WK( 0, 0),WK(-1, 0),WK(-1, 1),WK( 0,-2),WK(-1,-2) }, // D->R
40 { WK( 0, 0),WK(-1, 0),WK(-1,-1),WK( 0, 2),WK(-1, 2) }, // L->D
41 { WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 0,-2),WK( 1,-2) } // U->L
42 },
44 // 1: I counterclockwise
45 {
46 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK(-1,-2),WK( 2, 1) }, // R->U
47 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK( 1,-1),WK(-2, 1) }, // D->R
48 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK(-2,-1),WK( 1, 2) }, // L->D
49 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK( 2,-1),WK(-1, 2) } // U->L
50 },
52 // 2: JLSTZ clockwise
53 {
54 { WK( 0, 0),WK(-1, 0),WK(-1,-1),WK( 0, 2),WK(-1, 2) }, // L->U
55 { WK( 0, 0),WK(-1, 0),WK(-1, 1),WK( 0,-2),WK(-1,-2) }, // U->R
56 { WK( 0, 0),WK( 1, 0),WK( 1,-1),WK( 0, 2),WK( 1, 2) }, // R->D
57 { WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 0,-2),WK( 1,-2) }, // D->L
58 },
60 // 3: I clockwise
61 {
62 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK( 1,-2),WK(-2, 1) }, // L->U
63 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK(-2,-1),WK( 1, 2) }, // U->R
64 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK( 2,-1),WK(-1, 2) }, // R->D
65 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK(-1,-1),WK( 2, 1) } // D->L
66 }
67 }
68 };
70 // I: round to top right
71 // J, L, T: round to bottom
72 // S: round to bottom left (constant center column)
73 // Z: round to bottom right (constant center column)
74 static const LJRotSystem rotSega = {
75 .colorScheme = 1,
76 .entryOffset = {
77 WK( 0, 0),WK( 0, 1),WK( 0, 1),WK( 0, 0),WK( 0, 0),WK( 0, 1),WK( 0, 0),
78 WK( 0, 0),WK( 0, 0),WK( 0, 0)
79 },
80 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
81 .kicksL = {0, 1, 1, -1, 2, 1, 3, 0, -1, -1},
82 .kicksR = {4, 5, 5, -1, 6, 5, 7, 4, -1, -1},
84 .kickTables = {
86 // 0: I counterclockwise
87 {
88 { WK( 0, 0),WK_END }, // R->U
89 { WK( 0,-1),WK_END }, // D->R
90 { WK(-1, 1),WK_END }, // L->D
91 { WK( 1, 0),WK_END } // U->L
92 },
94 // 1: JLT counterclockwise
95 {
96 { WK( 0,-1),WK_END }, // R->U
97 { WK( 0, 0),WK_END }, // D->R
98 { WK( 0, 0),WK_END }, // L->D
99 { WK( 0, 1),WK_END } // U->L
100 },
102 // 2: S counterclockwise (round left, like Game Boy)
103 {
104 { WK( 1,-1),WK_END }, // R->U
105 { WK(-1, 0),WK_END }, // D->R
106 { WK( 0, 0),WK_END }, // L->D
107 { WK( 0, 1),WK_END } // U->L
108 },
110 // 3: Z counterclockwise (round right, like NES)
111 {
112 { WK( 0,-1),WK_END }, // R->U
113 { WK( 0, 0),WK_END }, // D->R
114 { WK(-1, 0),WK_END }, // L->D
115 { WK( 1, 1),WK_END } // U->L
116 },
118 // 4: I clockwise
119 {
120 { WK(-1, 0),WK_END }, // L->U
121 { WK( 0, 0),WK_END }, // U->R
122 { WK( 0, 1),WK_END }, // R->D
123 { WK( 1,-1),WK_END } // D->L
124 },
126 // 5: JLT clockwise
127 {
128 { WK( 0,-1),WK_END }, // L->U
129 { WK( 0, 1),WK_END }, // U->R
130 { WK( 0, 0),WK_END }, // R->D
131 { WK( 0, 0),WK_END } // D->L
132 },
134 // 6: S clockwise (round left)
135 {
136 { WK( 0,-1),WK_END }, // L->U
137 { WK(-1, 1),WK_END }, // U->R
138 { WK( 1, 0),WK_END }, // R->D
139 { WK( 0, 0),WK_END } // D->L
140 },
142 // 7: Z clockwise (round right)
143 {
144 { WK(-1,-1),WK_END }, // L->U
145 { WK( 0, 1),WK_END }, // U->R
146 { WK( 0, 0),WK_END }, // R->D
147 { WK( 1, 0),WK_END } // D->L
148 }
149 }
150 };
152 // Arika is based on Sega but with a few wall kicks.
153 // Each free-space kick should be followed by Right, then Left
154 // but for J, L, and T, kicks to vertical positions (point-right and
155 // point-left)
156 // T when rotating to point-up can also floor kick by one,
157 // and I when rotating to vertical can floor kick by one or two.
158 static const LJRotSystem rotArika = {
159 .colorScheme = 1,
160 .entryOffset = {
161 WK( 0, 0),WK( 0, 1),WK( 0, 1),WK( 0, 0),WK( 0, 0),WK( 0, 1),WK( 0, 0),
162 WK( 0, 0),WK( 0, 0),WK( 0, 0)
163 },
164 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
165 .kicksL = {0, 1, 1, -1, 2, 8, 3, 0, -1, -1},
166 .kicksR = {4, 5, 5, -1, 6, 9, 7, 4, -1, -1},
167 .kickTables = {
169 // 0: I counterclockwise
170 {
171 { WK( 0, 0),WK_END }, // R->U
172 { WK( 0,-1),WK( 0, 0),WK( 0, 1),WK_END }, // D->R
173 { WK(-1, 1),WK_END }, // L->D
174 { WK( 1, 0),WK( 1, 1),WK( 1, 2),WK_END } // U->L
175 },
177 // 1: JL counterclockwise
178 {
179 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK_END }, // R->U
180 { WK( 0, 0),ARIKA_IF_NOT_CENTER,WK( 1, 0),WK(-1, 0),WK_END }, // D->R
181 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // L->D
182 { WK( 0, 1),ARIKA_IF_NOT_CENTER,WK( 1, 1),WK(-1, 1),WK_END } // U->L
183 },
185 // 2: S counterclockwise (round left, like Game Boy with WK)
186 {
187 { WK( 1,-1),WK( 2,-1),WK( 0,-1),WK_END }, // R->U
188 { WK(-1, 0),WK( 0, 0),WK(-2, 0),WK_END }, // D->R
189 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // L->D
190 { WK( 0, 1),WK( 1, 1),WK(-1, 1),WK_END } // U->L
191 },
193 // 3: Z counterclockwise (round right, like NES with WK)
194 {
195 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK_END }, // R->U
196 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // D->R
197 { WK(-1, 0),WK( 0, 0),WK(-2, 0),WK_END }, // L->D
198 { WK( 1, 1),WK( 2, 1),WK( 0, 1),WK_END } // U->L
199 },
201 // 4: I clockwise
202 {
203 { WK(-1, 0),WK_END }, // L->U
204 { WK( 0, 0),WK( 0, 1),WK( 0, 2),WK_END }, // U->R
205 { WK( 0, 1),WK_END }, // R->D
206 { WK( 1,-1),WK( 1, 0),WK( 1, 1),WK_END } // D->L
207 },
209 // 5: JLT clockwise
210 {
211 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK_END }, // L->U
212 { WK( 0, 1),ARIKA_IF_NOT_CENTER,WK( 1, 1),WK(-1, 1),WK_END }, // U->R
213 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // R->D
214 { WK( 0, 0),ARIKA_IF_NOT_CENTER,WK( 1, 0),WK(-1, 0),WK_END } // D->L
215 },
217 // 6: S clockwise (round left)
218 {
219 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK_END }, // L->U
220 { WK(-1, 1),WK( 0, 1),WK(-2, 1),WK_END }, // U->R
221 { WK( 1, 0),WK( 2, 0),WK( 0, 0),WK_END }, // R->D
222 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END } // D->L
223 },
225 // 7: Z clockwise (round right)
226 {
227 { WK(-1,-1),WK( 0,-1),WK(-2,-1),WK_END }, // L->U
228 { WK( 0, 1),WK( 1, 1),WK(-1, 1),WK_END }, // U->R
229 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // R->D
230 { WK( 1, 0),WK( 2, 0),WK( 0, 0),WK_END } // D->L
231 },
233 // 8: T counterclockwise (with TI floorkick)
234 {
235 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK( 0, 0),WK_END }, // R->U
236 { WK( 0, 0),ARIKA_IF_NOT_CENTER,WK( 1, 0),WK(-1, 0),WK_END }, // D->R
237 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // L->D
238 { WK( 0, 1),ARIKA_IF_NOT_CENTER,WK( 1, 1),WK(-1, 1),WK_END } // U->L
239 },
241 // 9: T clockwise (with TI floorkick)
242 {
243 { WK( 0,-1),WK( 1,-1),WK(-1,-1),WK( 0, 0),WK_END }, // L->U
244 { WK( 0, 1),ARIKA_IF_NOT_CENTER,WK( 1, 1),WK(-1, 1),WK_END }, // U->R
245 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK_END }, // R->D
246 { WK( 0, 0),ARIKA_IF_NOT_CENTER,WK( 1, 0),WK(-1, 0),WK_END } // D->L
247 }
248 }
249 };
251 // All pieces are started with their left side in column 5 and flat side up.
252 // All pieces stick to the top of the bounding box.
253 // All 3-wide pieces stick to the left side of the bounding box.
254 // I sticks to the top when left and right and occupies the second column
255 // when up and down.
256 // Try here, then try kicking one space left. Discovered by zaphod77:
257 // http://www.tetrisconcept.com/forum/viewtopic.php?t=877
258 static const LJRotSystem rotTengen = {
259 .colorScheme = 1,
260 .entryOffset = {
261 WK( 1, 0),WK( 1, 1),WK( 1, 1),WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 1, 0),
262 WK( 0, 0),WK( 1, 0),WK( 0, 0)
263 },
264 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
265 .kicksL = {0, 3, 3, -1, 3, 3, 3, 0, 2, 5},
266 .kicksR = {1, 4, 4, -1, 4, 4, 4, 1, 3, 5},
267 .kickTables = {
269 // 0: I counterclockwise
270 {
271 { WK( 1, 1),WK( 0, 1),WK_END }, // R->U
272 { WK(-1,-2),WK(-2,-2),WK_END }, // D->R
273 { WK( 0, 2),WK(-1, 2),WK_END }, // L->D
274 { WK( 0,-1),WK(-1,-1),WK_END } // U->L
275 },
277 // 1: I clockwise
278 {
279 { WK( 0, 1),WK(-1, 1),WK_END }, // L->U
280 { WK(-1,-1),WK(-2,-1),WK_END }, // U->R
281 { WK( 1, 2),WK( 0, 2),WK_END }, // R->D
282 { WK( 0,-2),WK(-1,-2),WK_END } // D->L
283 },
285 // 2: I3
286 {
287 { WK( 0, 1),WK(-1, 1),WK_END }, // L->U
288 { WK( 0,-1),WK(-1,-1),WK_END }, // U->R
289 { WK( 0, 1),WK(-1, 1),WK_END }, // R->D
290 { WK( 0,-1),WK(-1,-1),WK_END } // D->L
291 },
293 // 3: JLSTZ counterclockwise
294 {
295 { WK( 1, 0),WK( 0, 0),WK_END }, // R->U
296 { WK(-1,-1),WK(-2,-1),WK_END }, // D->R
297 { WK( 0, 1),WK(-1, 1),WK_END }, // L->D
298 { WK( 0, 0),WK(-1, 0),WK_END } // U->L
299 },
301 // 4: JLSTZ clockwise
302 {
303 { WK( 0, 0),WK(-1, 0),WK_END }, // L->U
304 { WK(-1, 0),WK(-2, 0),WK_END }, // U->R
305 { WK( 1, 1),WK( 0, 1),WK_END }, // R->D
306 { WK( 0,-1),WK(-1,-1),WK_END } // D->L
307 },
309 // 5: L3
310 {
311 { WK( 0, 0),WK(-1, 0),WK_END }, // L->U
312 { WK(-1, 0),WK(-2, 0),WK_END }, // U->R
313 { WK( 1, 1),WK( 0, 1),WK_END }, // R->D
314 { WK( 0,-1),WK(-1,-1),WK_END } // D->L
315 }
316 }
317 };
319 // NES: No wall kick
320 // 3-wide pieces start out one block to the right
321 // I, S and Z round to the right and use effective positions R and D
322 static const LJRotSystem rotNES = {
323 .colorScheme = 1,
324 .entryOffset = {
325 WK( 0, 0),WK( 1, 1),WK( 1, 1),WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 1, 0),
326 WK( 0, 0),WK( 0, 0),WK( 0, 0)
327 },
328 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
329 .kicksL = {0, -1, -1, -1, 0, -1, 0, 0, -1, -1},
330 .kicksR = {1, -1, -1, -1, 1, -1, 1, 1, -1, -1},
331 .kickTables = {
333 // 0: counterclockwise (round right)
334 {
335 { WK( 0,-1),WK_END }, // R->U
336 { WK( 0, 0),WK_END }, // D->R
337 { WK(-1, 0),WK_END }, // L->D
338 { WK( 1, 1),WK_END } // U->L
339 },
340 // 1: clockwise (round right)
341 {
342 { WK(-1,-1),WK_END }, // L->U
343 { WK( 0, 1),WK_END }, // U->R
344 { WK( 0, 0),WK_END }, // R->D
345 { WK( 1, 0),WK_END } // D->L
346 }
347 }
348 };
350 // GB: No wall kick
351 // I, S and Z round to the left and use effective positions L and D
352 static const LJRotSystem rotGB = {
353 .colorScheme = 1,
354 .entryOffset = {
355 WK( 0, 0),WK( 0, 1),WK( 0, 1),WK( 0, 0),WK( 0, 0),WK( 0, 1),WK( 0, 0),
356 WK( 0, 0),WK( 0, 0),WK( 0, 0)
357 },
358 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
359 .kicksL = {0, -1, -1, -1, 0, -1, 0, 0, -1, -1},
360 .kicksR = {1, -1, -1, -1, 1, -1, 1, 1, -1, -1},
361 .kickTables = {
363 // 0: counterclockwise (round left)
364 {
365 { WK( 1,-1),WK_END }, // R->U
366 { WK(-1, 0),WK_END }, // D->R
367 { WK( 0, 0),WK_END }, // L->D
368 { WK( 0, 1),WK_END } // U->L
369 },
370 // 1: clockwise (round left)
371 {
372 { WK( 0,-1),WK_END }, // L->U
373 { WK(-1, 1),WK_END }, // U->R
374 { WK( 1, 0),WK_END }, // R->D
375 { WK( 0, 0),WK_END } // D->L
376 },
377 }
378 };
381 // The rotation system of LOCKJAW: The Overdose (GBA) and
382 // Tetramino (NES) TOD is simple. In free space it behaves like SRS.
383 // If that's blocked, kick right, kick left, kick up.
384 static const LJRotSystem rotTOD = {
385 .kicksL = {0, 0, 0, -1, 0, 0, 0, 0, 0, 0},
386 .kicksR = {0, 0, 0, -1, 0, 0, 0, 0, 0, 0},
387 .kickTables = {
389 // 0: JLSTZ counterclockwise
390 {
391 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK( 0, 1),WK_END }, // ->U
392 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK( 0, 1),WK_END }, // ->R
393 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK( 0, 1),WK_END }, // ->D
394 { WK( 0, 0),WK( 1, 0),WK(-1, 0),WK( 0, 1),WK_END } // ->L
395 },
397 // 1: I counterclockwise
398 {
399 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK(-1,-2),WK( 2, 1) }, // R->U
400 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK( 1,-1),WK(-2, 1) }, // D->R
401 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK(-2,-1),WK( 1, 2) }, // L->D
402 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK( 2,-1),WK(-1, 2) } // U->L
403 },
405 // 2: JLSTZ clockwise
406 {
407 { WK( 0, 0),WK(-1, 0),WK(-1,-1),WK( 0, 2),WK(-1, 2) }, // L->U
408 { WK( 0, 0),WK(-1, 0),WK(-1, 1),WK( 0,-2),WK(-1,-2) }, // U->R
409 { WK( 0, 0),WK( 1, 0),WK( 1,-1),WK( 0, 2),WK( 1, 2) }, // R->D
410 { WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 0,-2),WK( 1,-2) }, // D->L
411 },
413 // 3: I clockwise
414 {
415 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK( 1,-2),WK(-2, 1) }, // L->U
416 { WK( 0, 0),WK( 1, 0),WK(-2, 0),WK(-2,-1),WK( 1, 2) }, // U->R
417 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK( 2,-1),WK(-1, 2) }, // R->D
418 { WK( 0, 0),WK(-1, 0),WK( 2, 0),WK(-1,-1),WK( 2, 1) } // D->L
419 }
420 }
421 };
423 static const LJRotSystem rotTDX = {
424 .entryOffset = {
425 WK( 0, 0),WK( 1, 1),WK( 1, 1),WK( 0, 0),WK( 1, 0),WK( 1, 1),WK( 1, 0),
426 WK( 0, 0),WK( 0, 0),WK( 0, 0)
427 },
428 .entryTheta = { 0, 2, 2, 0, 0, 2, 0, 0, 0, 2 },
429 .kicksL = {0, 0, 0, -1, 0, 0, 0, 0, 0, 0},
430 .kicksR = {1, 1, 1, -1, 1, 1, 1, 1, 1, 1},
431 .kickTables = {
433 // 0: counterclockwise
434 {
435 { WK( 0, 0),WK( 1,-1),WK_END }, // R->U
436 { WK( 0, 0),WK(-1,-1),WK_END }, // D->R
437 { WK( 0, 0),WK(-1, 1),WK_END }, // L->D
438 { WK( 0, 0),WK( 1, 1),WK_END } // U->L
439 },
441 // 1: clockwise
442 {
443 { WK( 0, 0),WK(-1,-1),WK_END }, // L->U
444 { WK( 0, 0),WK(-1, 1),WK_END }, // U->R
445 { WK( 0, 0),WK( 1, 1),WK_END }, // R->D
446 { WK( 0, 0),WK( 1,-1),WK_END } // D->L
447 }
448 }
449 };
451 const LJRotSystem *const rotSystems[N_ROTATION_SYSTEMS] = {
452 &rotSRS, &rotSega, &rotArika, &rotTengen,
453 &rotNES, &rotGB, &rotTOD, &rotTDX
454 };