1 #include <stdlib.h>
2 #include <string.h>
3 #include "tetris.h"
4 #include "../timer.h"
5 #include "../input/input.h"
6 #include "../draw/draw.h"
7
8 struct game *game = NULL;
9 char clearedlines[4];
10
11 #define RETURN_ON_INPUT 4
12
13 /* process single-player input */
14 static int processinput(int tm, int flags);
15
randnum(int n)16 int randnum(int n)
17 {
18 return (int) (n*(rand()/(RAND_MAX+1.0)));
19 }
20
gettetrom(struct tetr * t,int i)21 void gettetrom(struct tetr *t, int i)
22 {
23 t->x = 3;
24 t->y = -3;
25 switch (i) {
26 case 0:
27 t->y = -4;
28 t->blocks = TETR_I;
29 break;
30 case 1:
31 t->blocks = TETR_J;
32 break;
33 case 2:
34 t->blocks = TETR_L;
35 break;
36 case 3:
37 t->y = -2;
38 t->blocks = TETR_O;
39 break;
40 case 4:
41 t->blocks = TETR_S;
42 break;
43 case 5:
44 t->blocks = TETR_T;
45 break;
46 case 6:
47 t->blocks = TETR_Z;
48 break;
49 default:
50 t->blocks = 0;
51 return;
52 }
53 t->color = tetrom_colors[i];
54 }
55
hitbtm(struct tetr * p,struct player * plr)56 int hitbtm(struct tetr *p, struct player *plr)
57 {
58 uint_least32_t *board;
59 int i, mask;
60 int x, y;
61
62 i = 12;
63 while (!(p->blocks >> i))
64 i -= 4;
65 if ((y = p->y+i/4) == 19)
66 return 1;
67 board = plr->board;
68 if (y < -1 || !board[y+1])
69 return 0;
70 mask = 15;
71 while (1) {
72 if (p->blocks & mask<<i) {
73 for (x = 0; x < 4; x++)
74 if (1<<x & mask && p->blocks & 1<<i+x &&
75 board[y+1]>>3*(p->x+x) & 7)
76 return 1;
77 mask ^= p->blocks>>i & mask;
78 }
79 if (!i || y < 0)
80 break;
81 i -= 4;
82 y--;
83 }
84 return 0;
85 }
86
levelup(struct player * p)87 static void levelup(struct player *p)
88 {
89 p->level++;
90 if (!p->level)
91 p->falltime = 799;
92 else if (p->level < 9)
93 p->falltime -= 83;
94 else if (p->level == 9)
95 p->falltime = 100;
96 else if (p->level == 10)
97 p->falltime = 83;
98 else if (p->level < 20)
99 p->falltime -= 5 + p->level%2;
100 else if (p->level < 30)
101 p->falltime -= 2;
102 }
103
upd_score_level(struct player * p,int n)104 static void upd_score_level(struct player *p, int n)
105 {
106 int lines;
107 if (!(game->mode & MODE_2PLAYER)) {
108 switch (n) {
109 case 1:
110 p->score += 40*(p->level+1);
111 break;
112 case 2:
113 p->score += 100*(p->level+1);
114 break;
115 case 3:
116 p->score += 300*(p->level+1);
117 break;
118 case 4:
119 p->score += 1200*(p->level+1);
120 }
121 }
122 if (game->mode & MODE_BTYPE) {
123 p->lines -= n;
124 lines = p->lineslimit - p->lines;
125 if (p->lines <= 0) {
126 p->lines = 0;
127 // This ends the game!
128 p->piece.y = -1;
129 }
130 } else {
131 p->lines += n;
132 lines = p->lines;
133 }
134 if (p->level == p->startlevel) {
135 if (lines >= 10*p->startlevel+10 || lines >= 100)
136 levelup(p);
137 } else if (lines/10 != (lines-n)/10)
138 levelup(p);
139 }
140
clearlines(struct player * p,int n)141 static void clearlines(struct player *p, int n)
142 {
143 uint_least32_t *board = p->board;
144 unsigned char lines[4];
145 int i;
146 upd_score_level(p, n);
147 memcpy(lines, clearedlines, 4);
148 for (i = 0; i < n; i++)
149 board[lines[i]-1] = 0;
150 while (n--) {
151 for (i = lines[n]-1; i > 0; i--) {
152 board[i] = board[i-1];
153 if (!n && !board[i])
154 break;
155 }
156 if (board[0])
157 board[0] = 0;
158 for (i = n-1; i >= 0; i--)
159 lines[i]++;
160 }
161 }
162
draw_lineclear_anim(int n)163 static void draw_lineclear_anim(int n)
164 {
165 int x, i;
166 int t = gettm(0);
167 int tm;
168 for (x = 4; x >= 0; x--) {
169 for (i = 0; i < n; i++) {
170 clearblocks(&player1, 1, x, clearedlines[i]-1);
171 clearblocks(&player1, 1, 9-x, clearedlines[i]-1);
172 }
173 tm = CLEAR_DELAY/5;
174 tm = (5-x)*tm-gettm(t)+t;
175 processinput(tm, DISCARD_MOVES | NO_PAUSE);
176 }
177 redrawboard(&player1, clearedlines[n-1]-1);
178 }
179
lockdelay()180 static int lockdelay()
181 {
182 struct tetr *p = &player1.piece;
183 int t = gettm(0);
184 int d = 0;
185 int x1, x2;
186 int b1, b2;
187
188 x1 = x2 = p->x;
189 b1 = b2 = p->blocks;
190 while (d < LOCK_DELAY) {
191 switch (processinput(LOCK_DELAY-d, RETURN_ON_INPUT)) {
192 case -2:
193 return -2;
194 case 0:
195 return 0;
196 }
197 if (!hitbtm(p, &player1))
198 return 1;
199 if (p->x != x2) {
200 if (p->x == x1)
201 break;
202 x1 = x2;
203 x2 = p->x;
204 } else if (p->blocks != b2) {
205 if (p->blocks == b1)
206 break;
207 b2 = p->blocks;
208 } else
209 d = -1;
210 if (d == -1)
211 d = gettm(t)-t;
212 else {
213 d = gettm(t)-t-LOCK_DELAY+d;
214 if (d < 0)
215 d = 0;
216 else if (d > LOCK_DELAY-10)
217 d = LOCK_DELAY-10;
218 t = gettm(0)-d;
219 }
220 }
221 return 0;
222 }
223
lockpiece(struct player * plr)224 void lockpiece(struct player *plr)
225 {
226 struct tetr *p = &plr->piece;
227 int x, y;
228 int n = 0;
229
230 if (!p->blocks)
231 return;
232 drawblocks(plr, p->blocks, p->x, p->y, DRAW_BLOCKS);
233 hide_dropmarker(plr);
234 while (!(p->blocks & 15)) {
235 p->blocks >>= 4;
236 p->y++;
237 }
238 if (p->y < 0) {
239 p->blocks = 0;
240 return;
241 }
242 memset(clearedlines, 0, 4);
243 y = p->y;
244 do {
245 x = 0;
246 while (!(p->blocks & 1<<x))
247 x++;
248 do plr->board[y] |= (uint_least32_t) p->color << 3*(p->x+x);
249 while (p->blocks & 1<<++x);
250
251 for (x = 0; x < 10; x++)
252 if (!(plr->board[y]>>3*x & 7))
253 break;
254 if (x == 10)
255 clearedlines[n++] = y+1;
256 y++;
257 } while (p->blocks >>= 4);
258 x = plr->level;
259 if (n)
260 clearlines(plr, n);
261 upd_stat(plr, x != plr->level);
262 if (n && !(game->mode & MODE_2PLAYER))
263 draw_lineclear_anim(n);
264 }
265
can_moveright(struct tetr * p,uint_least32_t * board)266 static int can_moveright(struct tetr *p, uint_least32_t *board)
267 {
268 int bl = p->blocks;
269 int i;
270 int x, y;
271
272 if (i = (bl != TETR_I))
273 i += !(bl & 0x444);
274 if (p->x-i > 5)
275 return 0;
276 y = p->y;
277 while (y < 0 || !(bl & 15)) {
278 bl >>= 4;
279 y++;
280 }
281 x = 3-i;
282 i = 0;
283 while (1) {
284 while (!(bl & 1<<i+x))
285 x--;
286 if (board[y] && board[y]>>3*(p->x+x+1) & 7)
287 return 0;
288 if (x)
289 bl &= ~(((1<<x)-1) << i);
290 if (!(bl >> (i += 4)))
291 break;
292 x = 2-!(bl & 0x444);
293 y++;
294 }
295 return bl;
296 }
297
moveright(struct player * plr)298 void moveright(struct player *plr)
299 {
300 struct tetr *p = &plr->piece;
301 int bl = can_moveright(p, plr->board);
302 int y = p->y;
303 int i = 0;
304 if (!bl) {
305 if (plr->falltime < LOCK_DELAY) {
306 plr->mvright_tm = gettm(0);
307 plr->mvleft_tm = 0;
308 }
309 return;
310 }
311 while (y < 0 || !(p->blocks & 15<<i)) {
312 y++;
313 i += 4;
314 }
315 drawpiece(plr, bl, p->x+1, y);
316 bl = p->blocks >> i;
317 do {
318 i = 1;
319 while (!(bl & i))
320 i <<= 1;
321 clearblocks(plr, bl & i, p->x, y);
322 y++;
323 } while (bl >>= 4);
324 upd_dropmarker(plr, 1);
325 p->x++;
326 }
327
can_moveleft(struct tetr * p,uint_least32_t * board)328 static int can_moveleft(struct tetr *p, uint_least32_t *board)
329 {
330 int bl;
331 int i;
332 int x, y;
333
334 if (!(p->x + !(p->blocks & 0x111)))
335 return 0;
336 bl = p->blocks;
337 y = p->y;
338 while (y < 0 || !(bl & 15)) {
339 bl >>= 4;
340 y++;
341 }
342 i = 0;
343 while (1) {
344 x = 0;
345 while (!(bl & 1<<i+x))
346 x++;
347 if (board[y] && board[y]>>3*(p->x+x-1) & 7)
348 return 0;
349 if (x < 3)
350 bl &= ~(16-(1<<x+1) << i);
351 if (!(bl >> (i += 4)))
352 break;
353 y++;
354 }
355 return bl;
356 }
357
moveleft(struct player * plr)358 void moveleft(struct player *plr)
359 {
360 struct tetr *p = &plr->piece;
361 int bl = can_moveleft(p, plr->board);
362 int y = p->y;
363 int i = 0;
364 if (!bl) {
365 if (plr->falltime < LOCK_DELAY) {
366 plr->mvleft_tm = gettm(0);
367 plr->mvright_tm = 0;
368 }
369 return;
370 }
371 while (y < 0 || !(p->blocks & 15<<i)) {
372 y++;
373 i += 4;
374 }
375 drawpiece(plr, bl, p->x-1, y);
376 bl = p->blocks >> i;
377 do {
378 i = 8;
379 while (!(bl & i))
380 i >>= 1;
381 clearblocks(plr, bl & i, p->x, y);
382 y++;
383 } while (bl >>= 4);
384 upd_dropmarker(plr, -1);
385 p->x--;
386 }
387
drop_score()388 static void drop_score()
389 {
390 if (!(game->mode & MODE_2PLAYER))
391 player1.score++;
392 }
393
movedown(struct player * plr,int drop)394 int movedown(struct player *plr, int drop)
395 {
396 struct tetr *p = &plr->piece;
397 int bl;
398 int i, mask;
399
400 if (hitbtm(p, plr))
401 return 0;
402 if (drop)
403 drop_score();
404 bl = 0;
405 mask = 15;
406 for (i = 12; i >= 0; i -= 4)
407 if (p->blocks & mask<<i) {
408 bl |= p->blocks & mask<<i;
409 mask ^= bl>>i & mask;
410 }
411 drawpiece(plr, bl, p->x, p->y+1);
412 bl = 0;
413 mask = 15;
414 for (i = 0; i <= 12; i += 4)
415 if (p->blocks & mask<<i) {
416 bl |= p->blocks & mask<<i;
417 mask ^= bl>>i & mask;
418 }
419 clearblocks(plr, bl, p->x, p->y);
420 p->y++;
421 if (plr->falltime >= LOCK_DELAY)
422 goto out;
423 if (!drop && p->y >= 0) {
424 if (plr->mvright_tm && LOCK_DELAY - plr->falltime >=
425 gettm(plr->mvright_tm) - plr->mvright_tm)
426 moveright(plr);
427 else if (plr->mvleft_tm && LOCK_DELAY - plr->falltime >=
428 gettm(plr->mvleft_tm) - plr->mvleft_tm)
429 moveleft(plr);
430 }
431 plr->mvright_tm = 0;
432 plr->mvleft_tm = 0;
433 out: upd_screen(1+(plr > game->player));
434 return 1;
435 }
436
can_rotate(int bl,int x,int y,uint_least32_t * board)437 static int can_rotate(int bl, int x, int y, uint_least32_t *board)
438 {
439 int row;
440 int i = bl != TETR_I;
441 if (i)
442 i += !(bl & 0x444);
443 if (x-i > 6)
444 return 0;
445 if (x + !(bl & 0x111) < 0)
446 return 0;
447 while (y < 0 || !(bl & 15)) {
448 bl >>= 4;
449 y++;
450 }
451 x *= 3;
452 while (bl) {
453 if (y > 19)
454 return 0;
455 row = board[y]>>x & 0xFFF;
456 i = 1;
457 while (row) {
458 if (bl & i && row & 7)
459 return 0;
460 row >>= 3;
461 i <<= 1;
462 }
463 bl >>= 4;
464 y++;
465 }
466 return 1;
467 }
468
rotate_JL(struct player * plr,int bl)469 static void rotate_JL(struct player *plr, int bl)
470 {
471 struct tetr *p = &plr->piece;
472 int x = p->x;
473 int y = p->y;
474 if (can_rotate(bl, x, y, plr->board)) {
475 drawpiece(plr, bl, x, y);
476 clearblocks(plr, p->blocks ^ 0x20, x, y);
477 p->blocks = bl;
478 }
479 }
480
rotate(struct player * plr,int clockwise)481 void rotate(struct player *plr, int clockwise)
482 {
483 struct tetr *p = &plr->piece;
484 uint_least32_t *board = plr->board;
485 int y = p->y;
486 int i = !(plr->rotationsys & ROT_LEFTHAND);
487
488 switch (p->blocks) {
489 case TETR_I:
490 if (!can_rotate(TETR_I2, p->x+i, y, board))
491 return;
492 p->x += i;
493 p->blocks = TETR_I2;
494 drawpiece(plr, 0x1011, p->x+1, y);
495 clearblocks(plr, i?11:13, p->x-i, y+2);
496 break;
497 case TETR_I2:
498 if (!can_rotate(TETR_I, p->x-i, y, board))
499 return;
500 p->x -= i;
501 p->blocks = TETR_I;
502 drawpiece(plr, 15, p->x, y+2);
503 clearblocks(plr, 0x1011, p->x+i+1, y);
504 break;
505 case TETR_J3:
506 clockwise = !clockwise;
507 case TETR_J:
508 rotate_JL(plr, clockwise ? TETR_J2 : TETR_J4);
509 break;
510 case TETR_J4:
511 clockwise = !clockwise;
512 case TETR_J2:
513 rotate_JL(plr, clockwise ? TETR_J3 : TETR_J);
514 break;
515 case TETR_L3:
516 clockwise = !clockwise;
517 case TETR_L:
518 rotate_JL(plr, clockwise ? TETR_L2 : TETR_L4);
519 break;
520 case TETR_L4:
521 clockwise = !clockwise;
522 case TETR_L2:
523 rotate_JL(plr, clockwise ? TETR_L3 : TETR_L);
524 break;
525 case TETR_S:
526 if (!can_rotate(TETR_S2, p->x+i, y, board))
527 return;
528 p->blocks = TETR_S2;
529 if (!i) {
530 drawpiece(plr, 0x11, p->x, y);
531 clearblocks(plr, 0x14, p->x, y+1);
532 } else {
533 p->x++;
534 drawpiece(plr, 0x201, p->x, y);
535 clearblocks(plr, 3, p->x-1, y+2);
536 }
537 break;
538 case TETR_S2:
539 if (!can_rotate(TETR_S, p->x-i, y, board))
540 return;
541 p->blocks = TETR_S;
542 if (!i) {
543 drawpiece(plr, 0x14, p->x, y+1);
544 clearblocks(plr, 0x11, p->x, y);
545 } else {
546 p->x--;
547 drawpiece(plr, 3, p->x, y+2);
548 clearblocks(plr, 0x201, p->x+1, y);
549 }
550 break;
551 case TETR_T:
552 i = clockwise ? TETR_T2 : TETR_T4;
553 if (!can_rotate(i, p->x, y, board))
554 return;
555 p->blocks = i;
556 drawpiece(plr, 1, p->x+1, y);
557 clearblocks(plr, 1, p->x+(clockwise?2:0), y+1);
558 break;
559 case TETR_T2:
560 i = clockwise ? TETR_T3 : TETR_T;
561 if (!can_rotate(i, p->x, y, board))
562 return;
563 p->blocks = i;
564 drawpiece(plr, 1, p->x+2, y+1);
565 clearblocks(plr, 1, p->x+1, y+(clockwise?2:0));
566 break;
567 case TETR_T3:
568 i = clockwise ? TETR_T4 : TETR_T2;
569 if (!can_rotate(i, p->x, y, board))
570 return;
571 p->blocks = i;
572 drawpiece(plr, 1, p->x+1, y+2);
573 clearblocks(plr, 1, p->x+(clockwise?0:2), y+1);
574 break;
575 case TETR_T4:
576 i = clockwise ? TETR_T : TETR_T3;
577 if (!can_rotate(i, p->x, y, board))
578 return;
579 p->blocks = i;
580 drawpiece(plr, 1, p->x, y+1);
581 clearblocks(plr, 1, p->x+1, y+(clockwise?0:2));
582 break;
583 case TETR_Z:
584 if (!can_rotate(TETR_Z2, p->x+i, y, board))
585 return;
586 p->blocks = TETR_Z2;
587 if (!i) {
588 drawpiece(plr, 0x102, p->x, y);
589 clearblocks(plr, 3, p->x+1, y+2);
590 } else {
591 p->x++;
592 drawpiece(plr, 0x11, p->x+1, y);
593 clearblocks(plr, 0x41, p->x-1, y+1);
594 }
595 break;
596 case TETR_Z2:
597 if (!can_rotate(TETR_Z, p->x-i, y, board))
598 return;
599 p->blocks = TETR_Z;
600 if (!i) {
601 drawpiece(plr, 3, p->x+1, y+2);
602 clearblocks(plr, 0x102, p->x, y);
603 } else {
604 p->x--;
605 drawpiece(plr, 0x41, p->x, y+1);
606 clearblocks(plr, 0x11, p->x+2, y);
607 }
608 }
609 upd_dropmarker(plr, 0);
610 }
611
atspawnpos(struct tetr * p)612 static int atspawnpos(struct tetr *p)
613 {
614 const short bl[7] = {TETR_I,TETR_J,TETR_L,TETR_O,TETR_S,TETR_T,TETR_Z};
615 struct tetr t;
616 int i;
617 if (p->x != 3 || p->y > 0)
618 return 0;
619 for (i = 0; i < 7; i++)
620 if (p->blocks == bl[i]) {
621 gettetrom(&t, i);
622 return (p->y == t.y+2);
623 }
624 return 0;
625 }
626
movedown_n(struct player * plr,int drop,int n)627 static void movedown_n(struct player *plr, int drop, int n)
628 {
629 struct tetr *p = &plr->piece;
630 int bl = p->blocks;
631 int y = p->y;
632 int i, x;
633
634 for (i = 0; i < n && !hitbtm(p, plr); i++) {
635 p->y++;
636 if (drop)
637 drop_score();
638 }
639 if (y == p->y)
640 return;
641 drawpiece(plr, p->blocks, p->x, p->y);
642 i = 0;
643 do {
644 if (bl & 15) {
645 x = 0;
646 while (!(bl & 1<<x))
647 x++;
648 do if (y+i >= p->y && p->blocks & 1<<4*(i-p->y+y)+x)
649 bl ^= 1 << x;
650 while (bl & 1<<++x);
651 clearblocks(plr, bl & 15, p->x, y+i);
652 }
653 i++;
654 } while (y+i < 19 && (bl >>= 4));
655 }
656
harddrop(struct player * plr,int safe)657 int harddrop(struct player *plr, int safe)
658 {
659 struct tetr *p = &plr->piece;
660 if (safe && atspawnpos(p))
661 return -1;
662 movedown_n(plr, 1, 19);
663 drawblocks(plr, p->blocks, p->x, p->y, DRAW_BLOCKS);
664 lockpiece(plr);
665 return 0;
666 }
667
softdrop(int n,int safe)668 int softdrop(int n, int safe)
669 {
670 struct player *p = &player1;
671 int t = gettm(0);
672 int tm = -1;
673 int y = p->piece.y;
674
675 if (safe && atspawnpos(&p->piece))
676 return -1;
677 if (!movedown(p, 1))
678 return 0;
679 n--;
680 while (n > 0) {
681 y = p->piece.y;
682 movedown_n(p, 1, 1+(n>1));
683 processinput(tm-gettm(t)+t, DISCARD_DROPS);
684 t = gettm(0);
685 if (tm == -1) {
686 tm = 2*p->falltime/20;
687 if (tm > 10)
688 tm = 10;
689 }
690 if (hitbtm(&p->piece, p))
691 return 2;
692 n -= p->piece.y-y;
693 }
694 return 1;
695 }
696
newclr(int old)697 static int newclr(int old)
698 {
699 int clr = randnum(7)+1;
700 if (clr == old)
701 return newclr(0);
702 return clr;
703 }
704
gen_garbage_height(struct player * p,int h)705 static void gen_garbage_height(struct player *p, int h)
706 {
707 int c, clr = randnum(7)+1;
708 int x, i;
709 if (p > game->player && p->height == player1.height) {
710 memcpy(p->board, player1.board, 20*sizeof(uint_least32_t));
711 return;
712 }
713 switch (h) {
714 case 1:
715 case 2:
716 h = 2*h+1;
717 break;
718 default:
719 h = 2*(h+1);
720 }
721 while (h) {
722 i = 0;
723 for (x = 0; x < 10; x++) {
724 if (!randnum(2))
725 continue;
726 i++;
727 if (i == 10)
728 break;
729 if (x && !(p->board[20-h]>>3*(x-1) & 7)) {
730 c = p->board[19-h]>>3*x & 7;
731 if (c && c != clr)
732 clr = c;
733 else
734 clr = newclr(clr);
735 }
736 p->board[20-h] |= (uint_least32_t) clr << 3*x;
737 }
738 h--;
739 }
740 }
741
setupplayer(struct player * p)742 void setupplayer(struct player *p)
743 {
744 p->piece.blocks = 0;
745 p->piece.y = 0;
746 memset(p->board, 0, 20*sizeof(int_least32_t));
747 if (p->height)
748 gen_garbage_height(p, p->height);
749 if (!(game->mode & MODE_2PLAYER)) {
750 p->score = 0;
751 memset(tetr_stats, 0, 7);
752 }
753 p->level = -1;
754 while (p->level < p->startlevel)
755 levelup(p);
756 p->lines = (game->mode & MODE_BTYPE) ? p->lineslimit : 0;
757 }
758
nextpiece(struct tetr * next)759 static int nextpiece(struct tetr *next)
760 {
761 int i = randnum(7);
762 player1.piece = *next;
763 gettetrom(next, i);
764 tetr_stats[i]++;
765 drawnext(&player1, next);
766 return movedown(&player1, 0) && movedown(&player1, 0);
767 }
768
startgame_1p()769 int startgame_1p()
770 {
771 struct tetr next;
772 int i = randnum(7);
773 int t;
774 drawgamescreen_1p();
775 gettetrom(&next, i);
776 drawnext(&player1, &next);
777 game->next = &next;
778 if (!startgame_wait(SINGLE_PL))
779 return 0;
780 tetr_stats[i] = 1;
781 upd_stat(&player1, 0);
782 while (nextpiece(&next)) {
783 spawn_discard_drops(0);
784 t = gettm(0);
785 show_dropmarker(&player1);
786 while (1) {
787 t = player1.falltime-gettm(t)+t;
788 i = processinput(t, 0);
789 if (!i)
790 break;
791 if (i == -2)
792 return 0;
793 gravity: t = gettm(0);
794 if (i == 2 || movedown(&player1, 0))
795 continue;
796 i = lockdelay();
797 if (i == -2)
798 return 0;
799 if (i)
800 goto gravity;
801 lockpiece(&player1);
802 break;
803 }
804 if (player1.piece.y < 0)
805 break;
806 if (processinput(SPAWN_DELAY, DISCARD_MOVES) == -2)
807 return 0;
808 }
809 game->state = GAME_OVER;
810 return 1;
811 }
812
startgame_wait(int n)813 int startgame_wait(int n)
814 {
815 int key;
816 print_press_key();
817 game->state = 0;
818 key = getkeypress_block(n);
819 n = processkey_ingame(key, DISCARD_MOVES | NO_PAUSE);
820 if (n == -2)
821 return 0;
822 upd_screen(1);
823 if (game->mode & MODE_2PLAYER)
824 upd_screen(2);
825 game->state = GAME_RUNNING;
826 return 1;
827 }
828
pausegame()829 int pausegame()
830 {
831 int t = gettm(0);
832 int key;
833 game->state = GAME_PAUSED;
834 clearboard_paused();
835 hide_dropmarker(&player1);
836 drawnext(&player1, NULL);
837 do key = getkeypress_block(SINGLE_PL);
838 while (gettm(t)-t < 500);
839 if (processkey_ingame(key, NO_PAUSE | DISCARD_MOVES) == -2)
840 return -2;
841 upd_screen(1);
842 show_dropmarker(&player1);
843 drawnext(&player1, game->next);
844 game->state = GAME_RUNNING;
845 return 2;
846 }
847
processinput(int tm,int flags)848 static int processinput(int tm, int flags)
849 {
850 int key;
851 int t = gettm(0);
852 int d = 0;
853 int ret;
854 upd_screen(1);
855 while (d < tm) {
856 ret = -1;
857 if (key = getkeypress(tm-d, IN_GAME | SINGLE_PL)) {
858 ret = processkey_ingame(key, flags);
859 if (!ret) {
860 lockpiece(&player1);
861 return 0;
862 }
863 }
864 if (abs(ret) == 2 || ret > -1 && (flags & RETURN_ON_INPUT))
865 return ret;
866 d = gettm(t)-t;
867 }
868 if (!(flags & (DISCARD_MOVES | NO_PAUSE | RETURN_ON_INPUT))) {
869 tm -= d;
870 d = 0;
871 while (tm <= -player1.falltime) {
872 tm += player1.falltime;
873 d++;
874 }
875 if (d) {
876 movedown_n(&player1, 0, d);
877 upd_screen(1);
878 }
879 }
880 return 1;
881 }
882