added (optional) tape buttons to insert or play solution tape
[rocksndiamonds.git] / src / game_em / synchro_1.c
1 /* first part of synchro.
2  *
3  * game logic for players.
4  *
5  * large switch statement for tiles the player interacts with.
6  */
7
8 #include "main_em.h"
9
10
11 #define USE_CHANGED_ACID_STUFF          1
12
13 extern boolean checkIfAllPlayersFitToScreen();
14
15 static void check_player(struct PLAYER *);
16 static void kill_player(struct PLAYER *);
17 static boolean player_digfield(struct PLAYER *, int, int);
18 static boolean player_killed(struct PLAYER *);
19
20 void synchro_1(void)
21 {
22   int start_check_nr;
23   int i;
24
25   game_em.any_player_moving = FALSE;
26   game_em.any_player_snapping = FALSE;
27
28   /* must test for death and actually kill separately */
29   for (i = 0; i < MAX_PLAYERS; i++)
30   {
31     boolean ply_kill = player_killed(&ply[i]);
32
33     if (ply[i].alive && ply_kill)
34       kill_player(&ply[i]);
35   }
36
37   for (i = 0; i < MAX_PLAYERS; i++)
38   {
39     ply[i].oldx = ply[i].x;
40     ply[i].oldy = ply[i].y;
41     ply[i].anim = SPR_still;
42   }
43
44   start_check_nr = (RandomEM & 128 ? 0 : 1) * 2 + (RandomEM & 256 ? 0 : 1);
45
46   for (i = 0; i < MAX_PLAYERS; i++)
47   {
48     int check_nr = (start_check_nr + i) % MAX_PLAYERS;
49
50     if (ply[check_nr].alive)
51       check_player(&ply[check_nr]);
52   }
53
54   for (i = 0; i < MAX_PLAYERS; i++)
55   {
56     if (!ply[i].alive)
57       continue;
58
59     if (Cave[ply[i].oldy][ply[i].oldx] == Zplayer)
60     {
61       Cave[ply[i].oldy][ply[i].oldx] = Xblank;
62       Next[ply[i].oldy][ply[i].oldx] = Xblank;
63     }
64
65     if (Cave[ply[i].y][ply[i].x] == Xblank)
66     {
67       Cave[ply[i].y][ply[i].x] = Zplayer;
68       Next[ply[i].y][ply[i].x] = Zplayer;
69     }
70   }
71 }
72
73 static boolean player_killed(struct PLAYER *ply)
74 {
75   int x = ply->x;
76   int y = ply->y;
77
78   if (!ply->alive)
79     return FALSE;
80
81   if (lev.killed_out_of_time && setup.time_limit)
82     return TRUE;
83
84   switch(Cave[y-1][x])
85   {
86     case Xbug_n:
87     case Xbug_e:
88     case Xbug_s:
89     case Xbug_w:
90     case Xbug_gon:
91     case Xbug_goe:
92     case Xbug_gos:
93     case Xbug_gow:
94     case Xtank_n:
95     case Xtank_e:
96     case Xtank_s:
97     case Xtank_w:
98     case Xtank_gon:
99     case Xtank_goe:
100     case Xtank_gos:
101     case Xtank_gow:
102       return TRUE;
103   }
104
105   switch(Cave[y][x+1])
106   {
107     case Xbug_n:
108     case Xbug_e:
109     case Xbug_s:
110     case Xbug_w:
111     case Xbug_gon:
112     case Xbug_goe:
113     case Xbug_gos:
114     case Xbug_gow:
115     case Xtank_n:
116     case Xtank_e:
117     case Xtank_s:
118     case Xtank_w:
119     case Xtank_gon:
120     case Xtank_goe:
121     case Xtank_gos:
122     case Xtank_gow:
123       return TRUE;
124   }
125
126   switch(Cave[y+1][x])
127   {
128     case Xbug_n:
129     case Xbug_e:
130     case Xbug_s:
131     case Xbug_w:
132     case Xbug_gon:
133     case Xbug_goe:
134     case Xbug_gos:
135     case Xbug_gow:
136     case Xtank_n:
137     case Xtank_e:
138     case Xtank_s:
139     case Xtank_w:
140     case Xtank_gon:
141     case Xtank_goe:
142     case Xtank_gos:
143     case Xtank_gow:
144       return TRUE;
145   }
146
147   switch(Cave[y][x-1])
148   {
149     case Xbug_n:
150     case Xbug_e:
151     case Xbug_s:
152     case Xbug_w:
153     case Xbug_gon:
154     case Xbug_goe:
155     case Xbug_gos:
156     case Xbug_gow:
157     case Xtank_n:
158     case Xtank_e:
159     case Xtank_s:
160     case Xtank_w:
161     case Xtank_gon:
162     case Xtank_goe:
163     case Xtank_gos:
164     case Xtank_gow:
165       return TRUE;
166   }
167
168   switch(Cave[y][x])
169   {
170     case Xblank:
171     case Yacid_splash_eB:
172     case Yacid_splash_wB:
173     case Zplayer:
174     case Xdynamite_1:
175     case Xdynamite_2:
176     case Xdynamite_3:
177     case Xdynamite_4:
178 #if 1
179     case Xfake_acid_1:
180     case Xfake_acid_2:
181     case Xfake_acid_3:
182     case Xfake_acid_4:
183     case Xfake_acid_5:
184     case Xfake_acid_6:
185     case Xfake_acid_7:
186     case Xfake_acid_8:
187 #endif
188       return FALSE;
189   }
190
191   return TRUE;
192 }
193
194 static void kill_player(struct PLAYER *ply)
195 {
196   int x = ply->x;
197   int y = ply->y;
198
199   ply->alive = 0;
200
201   switch(Cave[y-1][x])
202   {
203     case Xbug_n:
204     case Xbug_e:
205     case Xbug_s:
206     case Xbug_w:
207     case Xbug_gon:
208     case Xbug_goe:
209     case Xbug_gos:
210     case Xbug_gow:
211       Cave[y-1][x] = Xboom_bug;
212       break;
213
214     case Xtank_n:
215     case Xtank_e:
216     case Xtank_s:
217     case Xtank_w:
218     case Xtank_gon:
219     case Xtank_goe:
220     case Xtank_gos:
221     case Xtank_gow:
222       Cave[y-1][x] = Xboom_bomb;
223       break;
224   }
225
226   switch(Cave[y][x+1])
227   {
228     case Xbug_n:
229     case Xbug_e:
230     case Xbug_s:
231     case Xbug_w:
232     case Xbug_gon:
233     case Xbug_goe:
234     case Xbug_gos:
235     case Xbug_gow:
236       Cave[y][x+1] = Xboom_bug;
237       break;
238
239     case Xtank_n:
240     case Xtank_e:
241     case Xtank_s:
242     case Xtank_w:
243     case Xtank_gon:
244     case Xtank_goe:
245     case Xtank_gos:
246     case Xtank_gow:
247       Cave[y][x+1] = Xboom_bomb;
248       break;
249   }
250
251   switch(Cave[y+1][x])
252   {
253     case Xbug_n:
254     case Xbug_e:
255     case Xbug_s:
256     case Xbug_w:
257     case Xbug_gon:
258     case Xbug_goe:
259     case Xbug_gos:
260     case Xbug_gow:
261       Cave[y+1][x] = Xboom_bug;
262       break;
263
264     case Xtank_n:
265     case Xtank_e:
266     case Xtank_s:
267     case Xtank_w:
268     case Xtank_gon:
269     case Xtank_goe:
270     case Xtank_gos:
271     case Xtank_gow:
272       Cave[y+1][x] = Xboom_bomb;
273       break;
274   }
275
276   switch(Cave[y][x-1])
277   {
278     case Xbug_n:
279     case Xbug_e:
280     case Xbug_s:
281     case Xbug_w:
282     case Xbug_gon:
283     case Xbug_goe:
284     case Xbug_gos:
285     case Xbug_gow:
286       Cave[y][x-1] = Xboom_bug;
287       break;
288
289     case Xtank_n:
290     case Xtank_e:
291     case Xtank_s:
292     case Xtank_w:
293     case Xtank_gon:
294     case Xtank_goe:
295     case Xtank_gos:
296     case Xtank_gow:
297       Cave[y][x-1] = Xboom_bomb;
298       break;
299   }
300
301   switch(Cave[y][x])
302   {
303     case Xexit_1:
304     case Xexit_2:
305     case Xexit_3:
306       lev.exit_x = x;
307       lev.exit_y = y;
308       play_element_sound(x, y, SAMPLE_exit_leave, Xexit_1);
309       break;
310
311     default:
312       play_element_sound(x, y, SAMPLE_die, Zplayer);
313       break;
314   }
315
316   switch(Cave[y][x])
317   {
318 #if USE_CHANGED_ACID_STUFF
319     case Xacid_1:
320     case Xacid_2:
321     case Xacid_3:
322     case Xacid_4:
323     case Xacid_5:
324     case Xacid_6:
325     case Xacid_7:
326     case Xacid_8:
327       break;
328 #endif
329
330     default:
331       Cave[y][x] = Xboom_1;
332       Boom[y][x] = Xblank;
333       break;
334   }
335 }
336
337 static void check_player(struct PLAYER *ply)
338 {
339   int oldx = ply->x;
340   int oldy = ply->y;
341   int x = oldx;
342   int y = oldy;
343   int dx = 0, dy = 0;
344
345   game_em.last_player_direction[ply->num] = MV_NONE;
346
347   if (ply->joy_w)               /* west */
348   {
349     x--;
350     dx = -1;
351   }
352   else if (ply->joy_e)          /* east */
353   {
354     x++;
355     dx = 1;
356   }
357
358   if (ply->joy_n)               /* north */
359   {
360     y--;
361     dy = -1;
362   }
363   else if (ply->joy_s)          /* south */
364   {
365     y++;
366     dy = 1;
367   }
368
369   if (dx || dy)
370   {
371     int oldx = ply->x;
372     int oldy = ply->y;
373     int x = oldx + dx;
374     int y = oldy + dy;
375     boolean players_visible_before_move;
376     boolean players_visible_after_move;
377     boolean can_move;
378
379     players_visible_before_move = checkIfAllPlayersFitToScreen();
380
381     ply->x = x;
382     ply->y = y;
383
384     players_visible_after_move = checkIfAllPlayersFitToScreen();
385
386     /*
387       player is allowed to move only in the following cases:
388       - it is not needed to display all players (not focussed to all players)
389       - all players are (still or again) visible after the move
390       - some players were already outside visible screen area before the move
391     */
392     can_move = (game.centered_player_nr != -1 ||
393                 players_visible_after_move ||
394                 !players_visible_before_move);
395
396     ply->x = oldx;
397     ply->y = oldy;
398
399     if (!can_move)
400     {
401       ply->joy_n = ply->joy_e = ply->joy_s = ply->joy_w = 0;
402
403       return;
404     }
405   }
406
407   if (dx == 0 && dy == 0)
408   {
409     ply->joy_stick = 0;
410
411     if (ply->joy_drop)
412     {
413       if (++ply->dynamite_cnt == 5 && ply->dynamite)
414       {
415         Cave[y][x] = Xdynamite_1;
416         play_element_sound(x, y, SAMPLE_dynamite, Xdynamite_1);
417         ply->dynamite--;
418       }
419     }
420     else
421     {
422       ply->dynamite_cnt = 0;
423     }
424
425     RandomEM += 7;      /* be a bit more random if the player doesn't move */
426
427     return;
428   }
429
430   ply->joy_stick = 1;
431   ply->joy_n = ply->joy_e = ply->joy_s = ply->joy_w = 0;
432   ply->dynamite_cnt = 0;        /* reset dynamite timer if we move */
433   ply->joy_spin = !ply->joy_spin;
434
435   if (ply->joy_snap == 0)               /* player wants to move */
436   {
437     boolean moved = FALSE;
438
439     if (ply->last_move_dir & MV_HORIZONTAL)
440     {
441       if (!(moved = player_digfield(ply, 0, dy)))
442         moved = player_digfield(ply, dx, 0);
443     }
444     else
445     {
446       if (!(moved = player_digfield(ply, dx, 0)))
447         moved = player_digfield(ply, 0, dy);
448     }
449
450     if (moved)
451     {
452       if (oldx != ply->x)
453         ply->last_move_dir = (dx < 0 ? MV_LEFT : MV_RIGHT);
454       else if (oldy != ply->y)
455         ply->last_move_dir = (dy < 0 ? MV_UP : MV_DOWN);
456
457       game_em.any_player_moving = TRUE;
458       game_em.last_moving_player = ply->num;
459       game_em.last_player_direction[ply->num] = ply->last_move_dir;
460     }
461   }
462   else                                  /* player wants to snap */
463   {
464     game_em.any_player_snapping = player_digfield(ply, dx, dy);
465   }
466 }
467
468 static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
469 {
470   int anim = (dx < 0 ? 3 : dx > 0 ? 1 : dy < 0 ? 0 : dy > 0 ? 2 : 2);
471   int oldx = ply->x;
472   int oldy = ply->y;
473   int x = oldx + dx;
474   int y = oldy + dy;
475   boolean result = TRUE;
476
477   if (!dx && !dy)                       /* no direction specified */
478     return FALSE;
479
480   if (dx && dy && ply->joy_snap)        /* more than one direction specified */
481     return FALSE;
482
483   if (ply->joy_snap == 0)               /* player wants to move */
484   {
485     int element = Cave[y][x];
486
487     switch(Cave[y][x])
488     {
489       /* fire is released */
490       case Xblank:
491       case Yacid_splash_eB:
492       case Yacid_splash_wB:
493         Cave[y][x] = Zplayer;
494         Next[y][x] = Zplayer;
495 #if 1
496       case Xfake_acid_1:
497       case Xfake_acid_2:
498       case Xfake_acid_3:
499       case Xfake_acid_4:
500       case Xfake_acid_5:
501       case Xfake_acid_6:
502       case Xfake_acid_7:
503       case Xfake_acid_8:
504 #endif
505         play_element_sound(x, y, SAMPLE_blank, Xblank);
506         ply->anim = SPR_walk + anim;
507         ply->x = x;
508         ply->y = y;
509         break;
510
511 #if USE_CHANGED_ACID_STUFF
512       case Xacid_1:
513       case Xacid_2:
514       case Xacid_3:
515       case Xacid_4:
516       case Xacid_5:
517       case Xacid_6:
518       case Xacid_7:
519       case Xacid_8:
520         if (Cave[y-1][x+1] == Xblank)
521           Cave[y-1][x+1] = Yacid_splash_eB;
522         if (Cave[y-1][x-1] == Xblank)
523           Cave[y-1][x-1] = Yacid_splash_wB;
524         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
525 #endif
526
527       case Xboom_android:
528       case Xboom_1:
529       case Xbug_n:
530       case Xbug_e:
531       case Xbug_s:
532       case Xbug_w:
533       case Xbug_gon:
534       case Xbug_goe:
535       case Xbug_gos:
536       case Xbug_gow:
537       case Xtank_n:
538       case Xtank_e:
539       case Xtank_s:
540       case Xtank_w:
541       case Xtank_gon:
542       case Xtank_goe:
543       case Xtank_gos:
544       case Xtank_gow:
545
546 #if !USE_CHANGED_ACID_STUFF
547       case Xacid_1:
548       case Xacid_2:
549       case Xacid_3:
550       case Xacid_4:
551       case Xacid_5:
552       case Xacid_6:
553       case Xacid_7:
554       case Xacid_8:
555 #endif
556         ply->anim = SPR_walk + anim;
557         ply->x = x;
558         ply->y = y;
559         break;
560
561       case Xgrass:
562         Cave[y][x] = (dy ? (dy < 0 ? Ygrass_nB : Ygrass_sB) :
563                       (dx > 0 ? Ygrass_eB : Ygrass_wB));
564         Next[y][x] = Zplayer;
565         play_element_sound(x, y, SAMPLE_dirt, Xgrass);
566         ply->anim = SPR_walk + anim;
567         ply->x = x;
568         ply->y = y;
569         break;
570
571       case Xdirt:
572         Cave[y][x] = (dy ? (dy < 0 ? Ydirt_nB : Ydirt_sB) :
573                       (dx > 0 ? Ydirt_eB : Ydirt_wB));
574         Next[y][x] = Zplayer;
575         play_element_sound(x, y, SAMPLE_dirt, Xdirt);
576         ply->anim = SPR_walk + anim;
577         ply->x = x;
578         ply->y = y;
579         break;
580
581       case Xdiamond:
582       case Xdiamond_pause:
583         Cave[y][x] = Ydiamond_eat;
584         Next[y][x] = Zplayer;
585         play_element_sound(x, y, SAMPLE_collect, element);
586         lev.score += lev.diamond_score;
587         lev.required = lev.required < 3 ? 0 : lev.required - 3;
588         game.snapshot.collected_item = TRUE;
589         ply->anim = SPR_walk + anim;
590         ply->x = x;
591         ply->y = y;
592         break;
593
594       case Xemerald:
595       case Xemerald_pause:
596         Cave[y][x] = Yemerald_eat;
597         Next[y][x] = Zplayer;
598         play_element_sound(x, y, SAMPLE_collect, element);
599         lev.score += lev.emerald_score;
600         lev.required = lev.required < 1 ? 0 : lev.required - 1;
601         game.snapshot.collected_item = TRUE;
602         ply->anim = SPR_walk + anim;
603         ply->x = x;
604         ply->y = y;
605         break;
606
607       case Xdynamite:
608         Cave[y][x] = Ydynamite_eat;
609         Next[y][x] = Zplayer;
610         play_element_sound(x, y, SAMPLE_collect, element);
611         lev.score += lev.dynamite_score;
612         ply->dynamite = ply->dynamite > 9998 ? 9999 : ply->dynamite + 1;
613         ply->anim = SPR_walk + anim;
614         ply->x = x;
615         ply->y = y;
616         break;
617
618       case Xkey_1:
619         ply->keys |= 0x01;
620         Cave[y][x] = Ykey_1_eat;
621         goto key_walk;
622
623       case Xkey_2:
624         ply->keys |= 0x02;
625         Cave[y][x] = Ykey_2_eat;
626         goto key_walk;
627
628       case Xkey_3:
629         ply->keys |= 0x04;
630         Cave[y][x] = Ykey_3_eat;
631         goto key_walk;
632
633       case Xkey_4:
634         ply->keys |= 0x08;
635         Cave[y][x] = Ykey_4_eat;
636         goto key_walk;
637
638       case Xkey_5:
639         ply->keys |= 0x10;
640         Cave[y][x] = Ykey_5_eat;
641         goto key_walk;
642
643       case Xkey_6:
644         ply->keys |= 0x20;
645         Cave[y][x] = Ykey_6_eat;
646         goto key_walk;
647
648       case Xkey_7:
649         ply->keys |= 0x40;
650         Cave[y][x] = Ykey_7_eat;
651         goto key_walk;
652
653       case Xkey_8:
654         ply->keys |= 0x80;
655         Cave[y][x] = Ykey_8_eat;
656         goto key_walk;
657
658       key_walk:
659
660         Next[y][x] = Zplayer;
661         play_element_sound(x, y, SAMPLE_collect, element);
662         lev.score += lev.key_score;
663         ply->anim = SPR_walk + anim;
664         ply->x = x;
665         ply->y = y;
666         break;
667
668       case Xlenses:
669         Cave[y][x] = Ylenses_eat;
670         Next[y][x] = Zplayer;
671         play_element_sound(x, y, SAMPLE_collect, element);
672         lev.score += lev.lenses_score;
673         lev.lenses_cnt = lev.lenses_time;
674         ply->anim = SPR_walk + anim;
675         ply->x = x;
676         ply->y = y;
677         break;
678
679       case Xmagnify:
680         Cave[y][x] = Ymagnify_eat;
681         Next[y][x] = Zplayer;
682         play_element_sound(x, y, SAMPLE_collect, element);
683         lev.score += lev.magnify_score;
684         lev.magnify_cnt = lev.magnify_time;
685         ply->anim = SPR_walk + anim;
686         ply->x = x;
687         ply->y = y;
688         break;
689
690       case Xstone:
691         if (dy)
692           break;
693
694         switch(Cave[y][x+dx])
695         {
696           case Xacid_1:
697           case Xacid_2:
698           case Xacid_3:
699           case Xacid_4:
700           case Xacid_5:
701           case Xacid_6:
702           case Xacid_7:
703           case Xacid_8:
704             if (Cave[y-1][x+dx+1] == Xblank)
705               Cave[y-1][x+dx+1] = Yacid_splash_eB;
706             if (Cave[y-1][x+dx-1] == Xblank)
707               Cave[y-1][x+dx-1] = Yacid_splash_wB;
708             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
709             goto stone_walk;
710
711           case Xblank:
712           case Yacid_splash_eB:
713           case Yacid_splash_wB:
714             Cave[y][x+dx] = dx > 0 ? Ystone_e : Ystone_w;
715             Next[y][x+dx] = Xstone_pause;
716
717           stone_walk:
718
719             Cave[y][x] = dx > 0 ? Ystone_eB : Ystone_wB;
720             Next[y][x] = Zplayer;
721             play_element_sound(x, y, SAMPLE_roll, Xstone);
722             ply->x = x;
723         }
724
725         ply->anim = SPR_push + anim;
726         break;
727
728       case Xbomb:
729         if (dy)
730           break;
731
732         switch(Cave[y][x+dx])
733         {
734           case Xacid_1:
735           case Xacid_2:
736           case Xacid_3:
737           case Xacid_4:
738           case Xacid_5:
739           case Xacid_6:
740           case Xacid_7:
741           case Xacid_8:
742             if (Cave[y-1][x+dx+1] == Xblank)
743               Cave[y-1][x+dx+1] = Yacid_splash_eB;
744             if (Cave[y-1][x+dx-1] == Xblank)
745               Cave[y-1][x+dx-1] = Yacid_splash_wB;
746             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
747             goto bomb_walk;
748
749           case Xblank:
750           case Yacid_splash_eB:
751           case Yacid_splash_wB:
752             Cave[y][x+dx] = dx > 0 ? Ybomb_e : Ybomb_w;
753             Next[y][x+dx] = Xbomb_pause;
754
755           bomb_walk:
756
757             Cave[y][x] = dx > 0 ? Ybomb_eB : Ybomb_wB;
758             Next[y][x] = Zplayer;
759             play_element_sound(x, y, SAMPLE_roll, Xbomb);
760             ply->x = x;
761         }
762
763         ply->anim = SPR_push + anim;
764         break;
765
766       case Xnut:
767         if (dy)
768           break;
769
770         switch(Cave[y][x+dx])
771         {
772           case Xacid_1:
773           case Xacid_2:
774           case Xacid_3:
775           case Xacid_4:
776           case Xacid_5:
777           case Xacid_6:
778           case Xacid_7:
779           case Xacid_8:
780             if (Cave[y-1][x+dx+1] == Xblank)
781               Cave[y-1][x+dx+1] = Yacid_splash_eB;
782             if (Cave[y-1][x+dx-1] == Xblank)
783               Cave[y-1][x+dx-1] = Yacid_splash_wB;
784             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
785             goto nut_walk;
786
787           case Xblank:
788           case Yacid_splash_eB:
789           case Yacid_splash_wB:
790             Cave[y][x+dx] = dx > 0 ? Ynut_e : Ynut_w;
791             Next[y][x+dx] = Xnut_pause;
792
793           nut_walk:
794
795             Cave[y][x] = dx > 0 ? Ynut_eB : Ynut_wB;
796             Next[y][x] = Zplayer;
797             play_element_sound(x, y, SAMPLE_roll, Xnut);
798             ply->x = x;
799         }
800
801         ply->anim = SPR_push + anim;
802         break;
803
804       case Xspring:
805         if (dy)
806           break;
807
808         switch(Cave[y][x+dx])
809         {
810           case Xalien:
811           case Xalien_pause:
812             Cave[y][x] = dx > 0 ? Yspring_kill_eB : Yspring_kill_wB;
813             Cave[y][x+dx] = dx > 0 ? Yspring_kill_e : Yspring_kill_w;
814             Next[y][x] = Zplayer;
815             Next[y][x+dx] = dx > 0 ? Xspring_e : Xspring_w;
816             play_element_sound(x, y, SAMPLE_slurp, Xalien);
817             lev.score += lev.slurp_score;
818             ply->x = x;
819             break;
820
821           case Xacid_1:
822           case Xacid_2:
823           case Xacid_3:
824           case Xacid_4:
825           case Xacid_5:
826           case Xacid_6:
827           case Xacid_7:
828           case Xacid_8:
829             if (Cave[y-1][x+dx+1] == Xblank)
830               Cave[y-1][x+dx+1] = Yacid_splash_eB;
831             if (Cave[y-1][x+dx-1] == Xblank)
832               Cave[y-1][x+dx-1] = Yacid_splash_wB;
833             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
834             goto spring_walk;
835
836           case Xblank:
837           case Yacid_splash_eB:
838           case Yacid_splash_wB:
839             Cave[y][x+dx] = dx > 0 ? Yspring_e : Yspring_w;
840             Next[y][x+dx] = dx > 0 ? Xspring_e : Xspring_w;
841
842           spring_walk:
843             Cave[y][x] = dx > 0 ? Yspring_eB : Yspring_wB;
844             Next[y][x] = Zplayer;
845             play_element_sound(x, y, SAMPLE_roll, Xspring);
846             ply->x = x;
847         }
848
849         ply->anim = SPR_push + anim;
850         break;
851
852       case Xspring_pause:
853       case Xstone_pause:
854       case Xbomb_pause:
855       case Xnut_pause:
856       case Xsand_stonein_1:
857       case Xsand_stonein_2:
858       case Xsand_stonein_3:
859       case Xsand_stonein_4:
860         if (dy)
861           break;
862
863         ply->anim = SPR_push + anim;
864         break;
865
866       case Xballoon:
867         switch(Cave[y+dy][x+dx])
868         {
869           case Xacid_1:
870           case Xacid_2:
871           case Xacid_3:
872           case Xacid_4:
873           case Xacid_5:
874           case Xacid_6:
875           case Xacid_7:
876           case Xacid_8:
877             if (Cave[y+dy-1][x+dx+1] == Xblank)
878               Cave[y+dy-1][x+dx+1] = Yacid_splash_eB;
879             if (Cave[y+dy-1][x+dx-1] == Xblank)
880               Cave[y+dy-1][x+dx-1] = Yacid_splash_wB;
881             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
882             goto balloon_walk;
883
884           case Xblank:
885           case Yacid_splash_eB:
886           case Yacid_splash_wB:
887             Cave[y+dy][x+dx] = (dy ? (dy < 0 ? Yballoon_n : Yballoon_s) :
888                                 (dx > 0 ? Yballoon_e : Yballoon_w));
889             Next[y+dy][x+dx] = Xballoon;
890
891           balloon_walk:
892             Cave[y][x] = (dy ? (dy < 0 ? Yballoon_nB : Yballoon_sB) :
893                           (dx > 0 ? Yballoon_eB : Yballoon_wB));
894             Next[y][x] = Zplayer;
895             play_element_sound(x, y, SAMPLE_push, Xballoon);
896             ply->x = x;
897             ply->y = y;
898         }
899
900         ply->anim = SPR_push + anim;
901         break;
902
903       case Xandroid:
904       case Xandroid_1_n:
905       case Xandroid_2_n:
906       case Xandroid_1_e:
907       case Xandroid_2_e:
908       case Xandroid_1_s:
909       case Xandroid_2_s:
910       case Xandroid_1_w:
911       case Xandroid_2_w:
912         switch(Cave[y+dy][x+dx])
913         {
914           case Xacid_1:
915           case Xacid_2:
916           case Xacid_3:
917           case Xacid_4:
918           case Xacid_5:
919           case Xacid_6:
920           case Xacid_7:
921           case Xacid_8:
922             if (Cave[y+dy-1][x+dx+1] == Xblank)
923               Cave[y+dy-1][x+dx+1] = Yacid_splash_eB;
924             if (Cave[y+dy-1][x+dx-1] == Xblank)
925               Cave[y+dy-1][x+dx-1] = Yacid_splash_wB;
926             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
927             goto android_walk;
928
929           case Xblank:
930           case Yacid_splash_eB:
931           case Yacid_splash_wB:
932             Cave[y+dy][x+dx] = (dy ? (dy < 0 ? Yandroid_n : Yandroid_s) :
933                                 (dx > 0 ? Yandroid_e : Yandroid_w));
934             Next[y+dy][x+dx] = (dy ? (dy < 0 ? Xandroid_2_n : Xandroid_2_s) :
935                                 (dx > 0 ? Xandroid_2_e : Xandroid_2_w));
936
937           android_walk:
938             Cave[y][x] = (dy ? (dy < 0 ? Yandroid_nB : Yandroid_sB) :
939                           (dx > 0 ? Yandroid_eB : Yandroid_wB));
940             Next[y][x] = Zplayer;
941             play_element_sound(x, y, SAMPLE_push, Xandroid);
942             ply->x = x;
943             ply->y = y;
944         }
945
946         ply->anim = SPR_push + anim;
947         break;
948
949       case Xdoor_1:
950       case Xfake_door_1:
951         if (ply->keys & 0x01)
952           goto door_walk;
953         else
954           break;
955
956       case Xdoor_2:
957       case Xfake_door_2:
958         if (ply->keys & 0x02)
959           goto door_walk;
960         else
961           break;
962
963       case Xdoor_3:
964       case Xfake_door_3:
965         if (ply->keys & 0x04)
966           goto door_walk;
967         else
968           break;
969
970       case Xdoor_4:
971       case Xfake_door_4:
972         if (ply->keys & 0x08)
973           goto door_walk;
974         else
975           break;
976
977       case Xdoor_5:
978       case Xfake_door_5:
979         if (ply->keys & 0x10)
980           goto door_walk;
981         else
982           break;
983
984       case Xdoor_6:
985       case Xfake_door_6:
986         if (ply->keys & 0x20)
987           goto door_walk;
988         else
989           break;
990
991       case Xdoor_7:
992       case Xfake_door_7:
993         if (ply->keys & 0x40)
994           goto door_walk;
995         else
996           break;
997
998       case Xdoor_8:
999       case Xfake_door_8:
1000         if (ply->keys & 0x80)
1001           goto door_walk;
1002         else
1003           break;
1004
1005       door_walk:
1006         if (!tab_blank[Cave[y+dy][x+dx]])
1007           break;
1008
1009         Cave[y+dy][x+dx] = Zplayer;
1010         Next[y+dy][x+dx] = Zplayer;
1011         play_element_sound(x, y, SAMPLE_door, element);
1012         ply->anim = SPR_walk + anim;
1013         ply->x = x + dx;
1014         ply->y = y + dy;
1015         break;
1016
1017       case Xwheel:
1018         play_element_sound(x, y, SAMPLE_press, element);
1019         lev.wheel_cnt = lev.wheel_time;
1020         lev.wheel_x = x;
1021         lev.wheel_y = y;
1022         break;
1023
1024       case Xwind_n:
1025         lev.wind_direction = 0;
1026         goto wind_walk;
1027
1028       case Xwind_e:
1029         lev.wind_direction = 1;
1030         goto wind_walk;
1031
1032       case Xwind_s:
1033         lev.wind_direction = 2;
1034         goto wind_walk;
1035
1036       case Xwind_w:
1037         lev.wind_direction = 3;
1038         goto wind_walk;
1039
1040       case Xwind_nesw:
1041         lev.wind_direction = dy ? (dy < 0 ? 0 : 2) : (dx > 0 ? 1 : 3);
1042         goto wind_walk;
1043
1044       wind_walk:
1045         play_element_sound(x, y, SAMPLE_press, element);
1046         lev.wind_cnt = lev.wind_time;
1047         break;
1048
1049       case Xwind_stop:
1050         play_element_sound(x, y, SAMPLE_press, element);
1051         lev.wind_cnt = 0;
1052         break;
1053
1054       case Xswitch:
1055         play_element_sound(x, y, SAMPLE_press, element);
1056         lev.ball_cnt = lev.ball_time;
1057         lev.ball_state = !lev.ball_state;
1058         break;
1059
1060       case Xplant:
1061         Cave[y][x] = Yplant;
1062         Next[y][x] = Xplant;
1063         play_element_sound(x, y, SAMPLE_blank, Xplant);
1064         ply->anim = SPR_walk + anim;
1065         ply->x = x;
1066         ply->y = y;
1067         break;
1068
1069       case Xexit_1:
1070       case Xexit_2:
1071       case Xexit_3:
1072         lev.home--;
1073
1074         ply->anim = SPR_walk + anim;
1075         ply->x = x;
1076         ply->y = y;
1077
1078         break;
1079     }
1080
1081     if (ply->x == oldx && ply->y == oldy)       /* no movement */
1082       result = FALSE;
1083   }
1084   else                                  /* player wants to snap */
1085   {
1086     int element = Cave[y][x];
1087
1088     switch(Cave[y][x])
1089     {
1090       /* fire is pressed */
1091
1092       case Xgrass:
1093         Cave[y][x] = Ygrass_eat;
1094         Next[y][x] = Xblank;
1095         play_element_sound(x, y, SAMPLE_dirt, element);
1096         ply->anim = SPR_spray + anim;
1097         break;
1098
1099       case Xdirt:
1100         Cave[y][x] = Ydirt_eat;
1101         Next[y][x] = Xblank;
1102         play_element_sound(x, y, SAMPLE_dirt, element);
1103         ply->anim = SPR_spray + anim;
1104         break;
1105
1106       case Xdiamond:
1107       case Xdiamond_pause:
1108         Cave[y][x] = Ydiamond_eat;
1109         Next[y][x] = Xblank;
1110         play_element_sound(x, y, SAMPLE_collect, element);
1111         lev.score += lev.diamond_score;
1112         lev.required = lev.required < 3 ? 0 : lev.required - 3;
1113         game.snapshot.collected_item = TRUE;
1114         ply->anim = SPR_walk + anim;
1115         break;
1116
1117       case Xemerald:
1118       case Xemerald_pause:
1119         Cave[y][x] = Yemerald_eat;
1120         Next[y][x] = Xblank;
1121         play_element_sound(x, y, SAMPLE_collect, element);
1122         lev.score += lev.emerald_score;
1123         lev.required = lev.required < 1 ? 0 : lev.required - 1;
1124         game.snapshot.collected_item = TRUE;
1125         ply->anim = SPR_walk + anim;
1126         break;
1127
1128       case Xdynamite:
1129         Cave[y][x] = Ydynamite_eat;
1130         Next[y][x] = Xblank;
1131         play_element_sound(x, y, SAMPLE_collect, element);
1132         lev.score += lev.dynamite_score;
1133         ply->dynamite = ply->dynamite > 9998 ? 9999 : ply->dynamite + 1;
1134         ply->anim = SPR_walk + anim;
1135         break;
1136
1137       case Xkey_1:
1138         ply->keys |= 0x01;
1139         Cave[y][x] = Ykey_1_eat;
1140         goto key_shoot;
1141
1142       case Xkey_2:
1143         ply->keys |= 0x02;
1144         Cave[y][x] = Ykey_2_eat;
1145         goto key_shoot;
1146
1147       case Xkey_3:
1148         ply->keys |= 0x04;
1149         Cave[y][x] = Ykey_3_eat;
1150         goto key_shoot;
1151
1152       case Xkey_4:
1153         ply->keys |= 0x08;
1154         Cave[y][x] = Ykey_4_eat;
1155         goto key_shoot;
1156
1157       case Xkey_5:
1158         ply->keys |= 0x10;
1159         Cave[y][x] = Ykey_5_eat;
1160         goto key_shoot;
1161
1162       case Xkey_6:
1163         ply->keys |= 0x20;
1164         Cave[y][x] = Ykey_6_eat;
1165         goto key_shoot;
1166
1167       case Xkey_7:
1168         ply->keys |= 0x40;
1169         Cave[y][x] = Ykey_7_eat;
1170         goto key_shoot;
1171
1172       case Xkey_8:
1173         ply->keys |= 0x80;
1174         Cave[y][x] = Ykey_8_eat;
1175         goto key_shoot;
1176
1177       key_shoot:
1178         Next[y][x] = Xblank;
1179         play_element_sound(x, y, SAMPLE_collect, element);
1180         lev.score += lev.key_score;
1181         ply->anim = SPR_walk + anim;
1182         break;
1183
1184       case Xlenses:
1185         Cave[y][x] = Ylenses_eat;
1186         Next[y][x] = Xblank;
1187         play_element_sound(x, y, SAMPLE_collect, element);
1188         lev.score += lev.lenses_score;
1189         lev.lenses_cnt = lev.lenses_time;
1190         ply->anim = SPR_walk + anim;
1191         break;
1192
1193       case Xmagnify:
1194         Cave[y][x] = Ymagnify_eat;
1195         Next[y][x] = Xblank;
1196         play_element_sound(x, y, SAMPLE_collect, element);
1197         lev.score += lev.magnify_score;
1198         lev.magnify_cnt = lev.magnify_time;
1199         ply->anim = SPR_walk + anim;
1200         break;
1201
1202       default:
1203         result = FALSE;
1204     }
1205   }
1206
1207   return result;
1208 }