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