f0e9e20c792a4706e5ecd5f2a06c5c73181a88c7
[rocksndiamonds.git] / src / game.c
1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // game.c
10 // ============================================================================
11
12 #include "libgame/libgame.h"
13
14 #include "game.h"
15 #include "init.h"
16 #include "tools.h"
17 #include "screens.h"
18 #include "events.h"
19 #include "files.h"
20 #include "tape.h"
21 #include "network.h"
22 #include "anim.h"
23
24
25 // DEBUG SETTINGS
26 #define DEBUG_INIT_PLAYER       1
27 #define DEBUG_PLAYER_ACTIONS    0
28
29 // EXPERIMENTAL STUFF
30 #define USE_NEW_AMOEBA_CODE     FALSE
31
32 // EXPERIMENTAL STUFF
33 #define USE_QUICKSAND_BD_ROCK_BUGFIX    0
34 #define USE_QUICKSAND_IMPACT_BUGFIX     0
35 #define USE_DELAYED_GFX_REDRAW          0
36 #define USE_NEW_PLAYER_ASSIGNMENTS      1
37
38 #if USE_DELAYED_GFX_REDRAW
39 #define TEST_DrawLevelField(x, y)                               \
40         GfxRedraw[x][y] |= GFX_REDRAW_TILE
41 #define TEST_DrawLevelFieldCrumbled(x, y)                       \
42         GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED
43 #define TEST_DrawLevelFieldCrumbledNeighbours(x, y)             \
44         GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS
45 #define TEST_DrawTwinkleOnField(x, y)                           \
46         GfxRedraw[x][y] |= GFX_REDRAW_TILE_TWINKLED
47 #else
48 #define TEST_DrawLevelField(x, y)                               \
49              DrawLevelField(x, y)
50 #define TEST_DrawLevelFieldCrumbled(x, y)                       \
51              DrawLevelFieldCrumbled(x, y)
52 #define TEST_DrawLevelFieldCrumbledNeighbours(x, y)             \
53              DrawLevelFieldCrumbledNeighbours(x, y)
54 #define TEST_DrawTwinkleOnField(x, y)                           \
55              DrawTwinkleOnField(x, y)
56 #endif
57
58
59 // for DigField()
60 #define DF_NO_PUSH              0
61 #define DF_DIG                  1
62 #define DF_SNAP                 2
63
64 // for MovePlayer()
65 #define MP_NO_ACTION            0
66 #define MP_MOVING               1
67 #define MP_ACTION               2
68 #define MP_DONT_RUN_INTO        (MP_MOVING | MP_ACTION)
69
70 // for ScrollPlayer()
71 #define SCROLL_INIT             0
72 #define SCROLL_GO_ON            1
73
74 // for Bang()/Explode()
75 #define EX_PHASE_START          0
76 #define EX_TYPE_NONE            0
77 #define EX_TYPE_NORMAL          (1 << 0)
78 #define EX_TYPE_CENTER          (1 << 1)
79 #define EX_TYPE_BORDER          (1 << 2)
80 #define EX_TYPE_CROSS           (1 << 3)
81 #define EX_TYPE_DYNA            (1 << 4)
82 #define EX_TYPE_SINGLE_TILE     (EX_TYPE_CENTER | EX_TYPE_BORDER)
83
84 #define PANEL_OFF()             (game.panel.active == FALSE)
85 #define PANEL_DEACTIVATED(p)    ((p)->x < 0 || (p)->y < 0 || PANEL_OFF())
86 #define PANEL_XPOS(p)           (DX + ALIGNED_TEXT_XPOS(p))
87 #define PANEL_YPOS(p)           (DY + ALIGNED_TEXT_YPOS(p))
88
89 // game panel display and control definitions
90 #define GAME_PANEL_LEVEL_NUMBER                 0
91 #define GAME_PANEL_GEMS                         1
92 #define GAME_PANEL_INVENTORY_COUNT              2
93 #define GAME_PANEL_INVENTORY_FIRST_1            3
94 #define GAME_PANEL_INVENTORY_FIRST_2            4
95 #define GAME_PANEL_INVENTORY_FIRST_3            5
96 #define GAME_PANEL_INVENTORY_FIRST_4            6
97 #define GAME_PANEL_INVENTORY_FIRST_5            7
98 #define GAME_PANEL_INVENTORY_FIRST_6            8
99 #define GAME_PANEL_INVENTORY_FIRST_7            9
100 #define GAME_PANEL_INVENTORY_FIRST_8            10
101 #define GAME_PANEL_INVENTORY_LAST_1             11
102 #define GAME_PANEL_INVENTORY_LAST_2             12
103 #define GAME_PANEL_INVENTORY_LAST_3             13
104 #define GAME_PANEL_INVENTORY_LAST_4             14
105 #define GAME_PANEL_INVENTORY_LAST_5             15
106 #define GAME_PANEL_INVENTORY_LAST_6             16
107 #define GAME_PANEL_INVENTORY_LAST_7             17
108 #define GAME_PANEL_INVENTORY_LAST_8             18
109 #define GAME_PANEL_KEY_1                        19
110 #define GAME_PANEL_KEY_2                        20
111 #define GAME_PANEL_KEY_3                        21
112 #define GAME_PANEL_KEY_4                        22
113 #define GAME_PANEL_KEY_5                        23
114 #define GAME_PANEL_KEY_6                        24
115 #define GAME_PANEL_KEY_7                        25
116 #define GAME_PANEL_KEY_8                        26
117 #define GAME_PANEL_KEY_WHITE                    27
118 #define GAME_PANEL_KEY_WHITE_COUNT              28
119 #define GAME_PANEL_SCORE                        29
120 #define GAME_PANEL_HIGHSCORE                    30
121 #define GAME_PANEL_TIME                         31
122 #define GAME_PANEL_TIME_HH                      32
123 #define GAME_PANEL_TIME_MM                      33
124 #define GAME_PANEL_TIME_SS                      34
125 #define GAME_PANEL_TIME_ANIM                    35
126 #define GAME_PANEL_HEALTH                       36
127 #define GAME_PANEL_HEALTH_ANIM                  37
128 #define GAME_PANEL_FRAME                        38
129 #define GAME_PANEL_SHIELD_NORMAL                39
130 #define GAME_PANEL_SHIELD_NORMAL_TIME           40
131 #define GAME_PANEL_SHIELD_DEADLY                41
132 #define GAME_PANEL_SHIELD_DEADLY_TIME           42
133 #define GAME_PANEL_EXIT                         43
134 #define GAME_PANEL_EMC_MAGIC_BALL               44
135 #define GAME_PANEL_EMC_MAGIC_BALL_SWITCH        45
136 #define GAME_PANEL_LIGHT_SWITCH                 46
137 #define GAME_PANEL_LIGHT_SWITCH_TIME            47
138 #define GAME_PANEL_TIMEGATE_SWITCH              48
139 #define GAME_PANEL_TIMEGATE_SWITCH_TIME         49
140 #define GAME_PANEL_SWITCHGATE_SWITCH            50
141 #define GAME_PANEL_EMC_LENSES                   51
142 #define GAME_PANEL_EMC_LENSES_TIME              52
143 #define GAME_PANEL_EMC_MAGNIFIER                53
144 #define GAME_PANEL_EMC_MAGNIFIER_TIME           54
145 #define GAME_PANEL_BALLOON_SWITCH               55
146 #define GAME_PANEL_DYNABOMB_NUMBER              56
147 #define GAME_PANEL_DYNABOMB_SIZE                57
148 #define GAME_PANEL_DYNABOMB_POWER               58
149 #define GAME_PANEL_PENGUINS                     59
150 #define GAME_PANEL_SOKOBAN_OBJECTS              60
151 #define GAME_PANEL_SOKOBAN_FIELDS               61
152 #define GAME_PANEL_ROBOT_WHEEL                  62
153 #define GAME_PANEL_CONVEYOR_BELT_1              63
154 #define GAME_PANEL_CONVEYOR_BELT_2              64
155 #define GAME_PANEL_CONVEYOR_BELT_3              65
156 #define GAME_PANEL_CONVEYOR_BELT_4              66
157 #define GAME_PANEL_CONVEYOR_BELT_1_SWITCH       67
158 #define GAME_PANEL_CONVEYOR_BELT_2_SWITCH       68
159 #define GAME_PANEL_CONVEYOR_BELT_3_SWITCH       69
160 #define GAME_PANEL_CONVEYOR_BELT_4_SWITCH       70
161 #define GAME_PANEL_MAGIC_WALL                   71
162 #define GAME_PANEL_MAGIC_WALL_TIME              72
163 #define GAME_PANEL_GRAVITY_STATE                73
164 #define GAME_PANEL_GRAPHIC_1                    74
165 #define GAME_PANEL_GRAPHIC_2                    75
166 #define GAME_PANEL_GRAPHIC_3                    76
167 #define GAME_PANEL_GRAPHIC_4                    77
168 #define GAME_PANEL_GRAPHIC_5                    78
169 #define GAME_PANEL_GRAPHIC_6                    79
170 #define GAME_PANEL_GRAPHIC_7                    80
171 #define GAME_PANEL_GRAPHIC_8                    81
172 #define GAME_PANEL_ELEMENT_1                    82
173 #define GAME_PANEL_ELEMENT_2                    83
174 #define GAME_PANEL_ELEMENT_3                    84
175 #define GAME_PANEL_ELEMENT_4                    85
176 #define GAME_PANEL_ELEMENT_5                    86
177 #define GAME_PANEL_ELEMENT_6                    87
178 #define GAME_PANEL_ELEMENT_7                    88
179 #define GAME_PANEL_ELEMENT_8                    89
180 #define GAME_PANEL_ELEMENT_COUNT_1              90
181 #define GAME_PANEL_ELEMENT_COUNT_2              91
182 #define GAME_PANEL_ELEMENT_COUNT_3              92
183 #define GAME_PANEL_ELEMENT_COUNT_4              93
184 #define GAME_PANEL_ELEMENT_COUNT_5              94
185 #define GAME_PANEL_ELEMENT_COUNT_6              95
186 #define GAME_PANEL_ELEMENT_COUNT_7              96
187 #define GAME_PANEL_ELEMENT_COUNT_8              97
188 #define GAME_PANEL_CE_SCORE_1                   98
189 #define GAME_PANEL_CE_SCORE_2                   99
190 #define GAME_PANEL_CE_SCORE_3                   100
191 #define GAME_PANEL_CE_SCORE_4                   101
192 #define GAME_PANEL_CE_SCORE_5                   102
193 #define GAME_PANEL_CE_SCORE_6                   103
194 #define GAME_PANEL_CE_SCORE_7                   104
195 #define GAME_PANEL_CE_SCORE_8                   105
196 #define GAME_PANEL_CE_SCORE_1_ELEMENT           106
197 #define GAME_PANEL_CE_SCORE_2_ELEMENT           107
198 #define GAME_PANEL_CE_SCORE_3_ELEMENT           108
199 #define GAME_PANEL_CE_SCORE_4_ELEMENT           109
200 #define GAME_PANEL_CE_SCORE_5_ELEMENT           110
201 #define GAME_PANEL_CE_SCORE_6_ELEMENT           111
202 #define GAME_PANEL_CE_SCORE_7_ELEMENT           112
203 #define GAME_PANEL_CE_SCORE_8_ELEMENT           113
204 #define GAME_PANEL_PLAYER_NAME                  114
205 #define GAME_PANEL_LEVEL_NAME                   115
206 #define GAME_PANEL_LEVEL_AUTHOR                 116
207
208 #define NUM_GAME_PANEL_CONTROLS                 117
209
210 struct GamePanelOrderInfo
211 {
212   int nr;
213   int sort_priority;
214 };
215
216 static struct GamePanelOrderInfo game_panel_order[NUM_GAME_PANEL_CONTROLS];
217
218 struct GamePanelControlInfo
219 {
220   int nr;
221
222   struct TextPosInfo *pos;
223   int type;
224
225   int graphic, graphic_active;
226
227   int value, last_value;
228   int frame, last_frame;
229   int gfx_frame;
230   int gfx_random;
231 };
232
233 static struct GamePanelControlInfo game_panel_controls[] =
234 {
235   {
236     GAME_PANEL_LEVEL_NUMBER,
237     &game.panel.level_number,
238     TYPE_INTEGER,
239   },
240   {
241     GAME_PANEL_GEMS,
242     &game.panel.gems,
243     TYPE_INTEGER,
244   },
245   {
246     GAME_PANEL_INVENTORY_COUNT,
247     &game.panel.inventory_count,
248     TYPE_INTEGER,
249   },
250   {
251     GAME_PANEL_INVENTORY_FIRST_1,
252     &game.panel.inventory_first[0],
253     TYPE_ELEMENT,
254   },
255   {
256     GAME_PANEL_INVENTORY_FIRST_2,
257     &game.panel.inventory_first[1],
258     TYPE_ELEMENT,
259   },
260   {
261     GAME_PANEL_INVENTORY_FIRST_3,
262     &game.panel.inventory_first[2],
263     TYPE_ELEMENT,
264   },
265   {
266     GAME_PANEL_INVENTORY_FIRST_4,
267     &game.panel.inventory_first[3],
268     TYPE_ELEMENT,
269   },
270   {
271     GAME_PANEL_INVENTORY_FIRST_5,
272     &game.panel.inventory_first[4],
273     TYPE_ELEMENT,
274   },
275   {
276     GAME_PANEL_INVENTORY_FIRST_6,
277     &game.panel.inventory_first[5],
278     TYPE_ELEMENT,
279   },
280   {
281     GAME_PANEL_INVENTORY_FIRST_7,
282     &game.panel.inventory_first[6],
283     TYPE_ELEMENT,
284   },
285   {
286     GAME_PANEL_INVENTORY_FIRST_8,
287     &game.panel.inventory_first[7],
288     TYPE_ELEMENT,
289   },
290   {
291     GAME_PANEL_INVENTORY_LAST_1,
292     &game.panel.inventory_last[0],
293     TYPE_ELEMENT,
294   },
295   {
296     GAME_PANEL_INVENTORY_LAST_2,
297     &game.panel.inventory_last[1],
298     TYPE_ELEMENT,
299   },
300   {
301     GAME_PANEL_INVENTORY_LAST_3,
302     &game.panel.inventory_last[2],
303     TYPE_ELEMENT,
304   },
305   {
306     GAME_PANEL_INVENTORY_LAST_4,
307     &game.panel.inventory_last[3],
308     TYPE_ELEMENT,
309   },
310   {
311     GAME_PANEL_INVENTORY_LAST_5,
312     &game.panel.inventory_last[4],
313     TYPE_ELEMENT,
314   },
315   {
316     GAME_PANEL_INVENTORY_LAST_6,
317     &game.panel.inventory_last[5],
318     TYPE_ELEMENT,
319   },
320   {
321     GAME_PANEL_INVENTORY_LAST_7,
322     &game.panel.inventory_last[6],
323     TYPE_ELEMENT,
324   },
325   {
326     GAME_PANEL_INVENTORY_LAST_8,
327     &game.panel.inventory_last[7],
328     TYPE_ELEMENT,
329   },
330   {
331     GAME_PANEL_KEY_1,
332     &game.panel.key[0],
333     TYPE_ELEMENT,
334   },
335   {
336     GAME_PANEL_KEY_2,
337     &game.panel.key[1],
338     TYPE_ELEMENT,
339   },
340   {
341     GAME_PANEL_KEY_3,
342     &game.panel.key[2],
343     TYPE_ELEMENT,
344   },
345   {
346     GAME_PANEL_KEY_4,
347     &game.panel.key[3],
348     TYPE_ELEMENT,
349   },
350   {
351     GAME_PANEL_KEY_5,
352     &game.panel.key[4],
353     TYPE_ELEMENT,
354   },
355   {
356     GAME_PANEL_KEY_6,
357     &game.panel.key[5],
358     TYPE_ELEMENT,
359   },
360   {
361     GAME_PANEL_KEY_7,
362     &game.panel.key[6],
363     TYPE_ELEMENT,
364   },
365   {
366     GAME_PANEL_KEY_8,
367     &game.panel.key[7],
368     TYPE_ELEMENT,
369   },
370   {
371     GAME_PANEL_KEY_WHITE,
372     &game.panel.key_white,
373     TYPE_ELEMENT,
374   },
375   {
376     GAME_PANEL_KEY_WHITE_COUNT,
377     &game.panel.key_white_count,
378     TYPE_INTEGER,
379   },
380   {
381     GAME_PANEL_SCORE,
382     &game.panel.score,
383     TYPE_INTEGER,
384   },
385   {
386     GAME_PANEL_HIGHSCORE,
387     &game.panel.highscore,
388     TYPE_INTEGER,
389   },
390   {
391     GAME_PANEL_TIME,
392     &game.panel.time,
393     TYPE_INTEGER,
394   },
395   {
396     GAME_PANEL_TIME_HH,
397     &game.panel.time_hh,
398     TYPE_INTEGER,
399   },
400   {
401     GAME_PANEL_TIME_MM,
402     &game.panel.time_mm,
403     TYPE_INTEGER,
404   },
405   {
406     GAME_PANEL_TIME_SS,
407     &game.panel.time_ss,
408     TYPE_INTEGER,
409   },
410   {
411     GAME_PANEL_TIME_ANIM,
412     &game.panel.time_anim,
413     TYPE_GRAPHIC,
414
415     IMG_GFX_GAME_PANEL_TIME_ANIM,
416     IMG_GFX_GAME_PANEL_TIME_ANIM_ACTIVE
417   },
418   {
419     GAME_PANEL_HEALTH,
420     &game.panel.health,
421     TYPE_INTEGER,
422   },
423   {
424     GAME_PANEL_HEALTH_ANIM,
425     &game.panel.health_anim,
426     TYPE_GRAPHIC,
427
428     IMG_GFX_GAME_PANEL_HEALTH_ANIM,
429     IMG_GFX_GAME_PANEL_HEALTH_ANIM_ACTIVE
430   },
431   {
432     GAME_PANEL_FRAME,
433     &game.panel.frame,
434     TYPE_INTEGER,
435   },
436   {
437     GAME_PANEL_SHIELD_NORMAL,
438     &game.panel.shield_normal,
439     TYPE_ELEMENT,
440   },
441   {
442     GAME_PANEL_SHIELD_NORMAL_TIME,
443     &game.panel.shield_normal_time,
444     TYPE_INTEGER,
445   },
446   {
447     GAME_PANEL_SHIELD_DEADLY,
448     &game.panel.shield_deadly,
449     TYPE_ELEMENT,
450   },
451   {
452     GAME_PANEL_SHIELD_DEADLY_TIME,
453     &game.panel.shield_deadly_time,
454     TYPE_INTEGER,
455   },
456   {
457     GAME_PANEL_EXIT,
458     &game.panel.exit,
459     TYPE_ELEMENT,
460   },
461   {
462     GAME_PANEL_EMC_MAGIC_BALL,
463     &game.panel.emc_magic_ball,
464     TYPE_ELEMENT,
465   },
466   {
467     GAME_PANEL_EMC_MAGIC_BALL_SWITCH,
468     &game.panel.emc_magic_ball_switch,
469     TYPE_ELEMENT,
470   },
471   {
472     GAME_PANEL_LIGHT_SWITCH,
473     &game.panel.light_switch,
474     TYPE_ELEMENT,
475   },
476   {
477     GAME_PANEL_LIGHT_SWITCH_TIME,
478     &game.panel.light_switch_time,
479     TYPE_INTEGER,
480   },
481   {
482     GAME_PANEL_TIMEGATE_SWITCH,
483     &game.panel.timegate_switch,
484     TYPE_ELEMENT,
485   },
486   {
487     GAME_PANEL_TIMEGATE_SWITCH_TIME,
488     &game.panel.timegate_switch_time,
489     TYPE_INTEGER,
490   },
491   {
492     GAME_PANEL_SWITCHGATE_SWITCH,
493     &game.panel.switchgate_switch,
494     TYPE_ELEMENT,
495   },
496   {
497     GAME_PANEL_EMC_LENSES,
498     &game.panel.emc_lenses,
499     TYPE_ELEMENT,
500   },
501   {
502     GAME_PANEL_EMC_LENSES_TIME,
503     &game.panel.emc_lenses_time,
504     TYPE_INTEGER,
505   },
506   {
507     GAME_PANEL_EMC_MAGNIFIER,
508     &game.panel.emc_magnifier,
509     TYPE_ELEMENT,
510   },
511   {
512     GAME_PANEL_EMC_MAGNIFIER_TIME,
513     &game.panel.emc_magnifier_time,
514     TYPE_INTEGER,
515   },
516   {
517     GAME_PANEL_BALLOON_SWITCH,
518     &game.panel.balloon_switch,
519     TYPE_ELEMENT,
520   },
521   {
522     GAME_PANEL_DYNABOMB_NUMBER,
523     &game.panel.dynabomb_number,
524     TYPE_INTEGER,
525   },
526   {
527     GAME_PANEL_DYNABOMB_SIZE,
528     &game.panel.dynabomb_size,
529     TYPE_INTEGER,
530   },
531   {
532     GAME_PANEL_DYNABOMB_POWER,
533     &game.panel.dynabomb_power,
534     TYPE_ELEMENT,
535   },
536   {
537     GAME_PANEL_PENGUINS,
538     &game.panel.penguins,
539     TYPE_INTEGER,
540   },
541   {
542     GAME_PANEL_SOKOBAN_OBJECTS,
543     &game.panel.sokoban_objects,
544     TYPE_INTEGER,
545   },
546   {
547     GAME_PANEL_SOKOBAN_FIELDS,
548     &game.panel.sokoban_fields,
549     TYPE_INTEGER,
550   },
551   {
552     GAME_PANEL_ROBOT_WHEEL,
553     &game.panel.robot_wheel,
554     TYPE_ELEMENT,
555   },
556   {
557     GAME_PANEL_CONVEYOR_BELT_1,
558     &game.panel.conveyor_belt[0],
559     TYPE_ELEMENT,
560   },
561   {
562     GAME_PANEL_CONVEYOR_BELT_2,
563     &game.panel.conveyor_belt[1],
564     TYPE_ELEMENT,
565   },
566   {
567     GAME_PANEL_CONVEYOR_BELT_3,
568     &game.panel.conveyor_belt[2],
569     TYPE_ELEMENT,
570   },
571   {
572     GAME_PANEL_CONVEYOR_BELT_4,
573     &game.panel.conveyor_belt[3],
574     TYPE_ELEMENT,
575   },
576   {
577     GAME_PANEL_CONVEYOR_BELT_1_SWITCH,
578     &game.panel.conveyor_belt_switch[0],
579     TYPE_ELEMENT,
580   },
581   {
582     GAME_PANEL_CONVEYOR_BELT_2_SWITCH,
583     &game.panel.conveyor_belt_switch[1],
584     TYPE_ELEMENT,
585   },
586   {
587     GAME_PANEL_CONVEYOR_BELT_3_SWITCH,
588     &game.panel.conveyor_belt_switch[2],
589     TYPE_ELEMENT,
590   },
591   {
592     GAME_PANEL_CONVEYOR_BELT_4_SWITCH,
593     &game.panel.conveyor_belt_switch[3],
594     TYPE_ELEMENT,
595   },
596   {
597     GAME_PANEL_MAGIC_WALL,
598     &game.panel.magic_wall,
599     TYPE_ELEMENT,
600   },
601   {
602     GAME_PANEL_MAGIC_WALL_TIME,
603     &game.panel.magic_wall_time,
604     TYPE_INTEGER,
605   },
606   {
607     GAME_PANEL_GRAVITY_STATE,
608     &game.panel.gravity_state,
609     TYPE_STRING,
610   },
611   {
612     GAME_PANEL_GRAPHIC_1,
613     &game.panel.graphic[0],
614     TYPE_ELEMENT,
615   },
616   {
617     GAME_PANEL_GRAPHIC_2,
618     &game.panel.graphic[1],
619     TYPE_ELEMENT,
620   },
621   {
622     GAME_PANEL_GRAPHIC_3,
623     &game.panel.graphic[2],
624     TYPE_ELEMENT,
625   },
626   {
627     GAME_PANEL_GRAPHIC_4,
628     &game.panel.graphic[3],
629     TYPE_ELEMENT,
630   },
631   {
632     GAME_PANEL_GRAPHIC_5,
633     &game.panel.graphic[4],
634     TYPE_ELEMENT,
635   },
636   {
637     GAME_PANEL_GRAPHIC_6,
638     &game.panel.graphic[5],
639     TYPE_ELEMENT,
640   },
641   {
642     GAME_PANEL_GRAPHIC_7,
643     &game.panel.graphic[6],
644     TYPE_ELEMENT,
645   },
646   {
647     GAME_PANEL_GRAPHIC_8,
648     &game.panel.graphic[7],
649     TYPE_ELEMENT,
650   },
651   {
652     GAME_PANEL_ELEMENT_1,
653     &game.panel.element[0],
654     TYPE_ELEMENT,
655   },
656   {
657     GAME_PANEL_ELEMENT_2,
658     &game.panel.element[1],
659     TYPE_ELEMENT,
660   },
661   {
662     GAME_PANEL_ELEMENT_3,
663     &game.panel.element[2],
664     TYPE_ELEMENT,
665   },
666   {
667     GAME_PANEL_ELEMENT_4,
668     &game.panel.element[3],
669     TYPE_ELEMENT,
670   },
671   {
672     GAME_PANEL_ELEMENT_5,
673     &game.panel.element[4],
674     TYPE_ELEMENT,
675   },
676   {
677     GAME_PANEL_ELEMENT_6,
678     &game.panel.element[5],
679     TYPE_ELEMENT,
680   },
681   {
682     GAME_PANEL_ELEMENT_7,
683     &game.panel.element[6],
684     TYPE_ELEMENT,
685   },
686   {
687     GAME_PANEL_ELEMENT_8,
688     &game.panel.element[7],
689     TYPE_ELEMENT,
690   },
691   {
692     GAME_PANEL_ELEMENT_COUNT_1,
693     &game.panel.element_count[0],
694     TYPE_INTEGER,
695   },
696   {
697     GAME_PANEL_ELEMENT_COUNT_2,
698     &game.panel.element_count[1],
699     TYPE_INTEGER,
700   },
701   {
702     GAME_PANEL_ELEMENT_COUNT_3,
703     &game.panel.element_count[2],
704     TYPE_INTEGER,
705   },
706   {
707     GAME_PANEL_ELEMENT_COUNT_4,
708     &game.panel.element_count[3],
709     TYPE_INTEGER,
710   },
711   {
712     GAME_PANEL_ELEMENT_COUNT_5,
713     &game.panel.element_count[4],
714     TYPE_INTEGER,
715   },
716   {
717     GAME_PANEL_ELEMENT_COUNT_6,
718     &game.panel.element_count[5],
719     TYPE_INTEGER,
720   },
721   {
722     GAME_PANEL_ELEMENT_COUNT_7,
723     &game.panel.element_count[6],
724     TYPE_INTEGER,
725   },
726   {
727     GAME_PANEL_ELEMENT_COUNT_8,
728     &game.panel.element_count[7],
729     TYPE_INTEGER,
730   },
731   {
732     GAME_PANEL_CE_SCORE_1,
733     &game.panel.ce_score[0],
734     TYPE_INTEGER,
735   },
736   {
737     GAME_PANEL_CE_SCORE_2,
738     &game.panel.ce_score[1],
739     TYPE_INTEGER,
740   },
741   {
742     GAME_PANEL_CE_SCORE_3,
743     &game.panel.ce_score[2],
744     TYPE_INTEGER,
745   },
746   {
747     GAME_PANEL_CE_SCORE_4,
748     &game.panel.ce_score[3],
749     TYPE_INTEGER,
750   },
751   {
752     GAME_PANEL_CE_SCORE_5,
753     &game.panel.ce_score[4],
754     TYPE_INTEGER,
755   },
756   {
757     GAME_PANEL_CE_SCORE_6,
758     &game.panel.ce_score[5],
759     TYPE_INTEGER,
760   },
761   {
762     GAME_PANEL_CE_SCORE_7,
763     &game.panel.ce_score[6],
764     TYPE_INTEGER,
765   },
766   {
767     GAME_PANEL_CE_SCORE_8,
768     &game.panel.ce_score[7],
769     TYPE_INTEGER,
770   },
771   {
772     GAME_PANEL_CE_SCORE_1_ELEMENT,
773     &game.panel.ce_score_element[0],
774     TYPE_ELEMENT,
775   },
776   {
777     GAME_PANEL_CE_SCORE_2_ELEMENT,
778     &game.panel.ce_score_element[1],
779     TYPE_ELEMENT,
780   },
781   {
782     GAME_PANEL_CE_SCORE_3_ELEMENT,
783     &game.panel.ce_score_element[2],
784     TYPE_ELEMENT,
785   },
786   {
787     GAME_PANEL_CE_SCORE_4_ELEMENT,
788     &game.panel.ce_score_element[3],
789     TYPE_ELEMENT,
790   },
791   {
792     GAME_PANEL_CE_SCORE_5_ELEMENT,
793     &game.panel.ce_score_element[4],
794     TYPE_ELEMENT,
795   },
796   {
797     GAME_PANEL_CE_SCORE_6_ELEMENT,
798     &game.panel.ce_score_element[5],
799     TYPE_ELEMENT,
800   },
801   {
802     GAME_PANEL_CE_SCORE_7_ELEMENT,
803     &game.panel.ce_score_element[6],
804     TYPE_ELEMENT,
805   },
806   {
807     GAME_PANEL_CE_SCORE_8_ELEMENT,
808     &game.panel.ce_score_element[7],
809     TYPE_ELEMENT,
810   },
811   {
812     GAME_PANEL_PLAYER_NAME,
813     &game.panel.player_name,
814     TYPE_STRING,
815   },
816   {
817     GAME_PANEL_LEVEL_NAME,
818     &game.panel.level_name,
819     TYPE_STRING,
820   },
821   {
822     GAME_PANEL_LEVEL_AUTHOR,
823     &game.panel.level_author,
824     TYPE_STRING,
825   },
826
827   {
828     -1,
829     NULL,
830     -1,
831   }
832 };
833
834 // values for delayed check of falling and moving elements and for collision
835 #define CHECK_DELAY_MOVING      3
836 #define CHECK_DELAY_FALLING     CHECK_DELAY_MOVING
837 #define CHECK_DELAY_COLLISION   2
838 #define CHECK_DELAY_IMPACT      CHECK_DELAY_COLLISION
839
840 // values for initial player move delay (initial delay counter value)
841 #define INITIAL_MOVE_DELAY_OFF  -1
842 #define INITIAL_MOVE_DELAY_ON   0
843
844 // values for player movement speed (which is in fact a delay value)
845 #define MOVE_DELAY_MIN_SPEED    32
846 #define MOVE_DELAY_NORMAL_SPEED 8
847 #define MOVE_DELAY_HIGH_SPEED   4
848 #define MOVE_DELAY_MAX_SPEED    1
849
850 #define DOUBLE_MOVE_DELAY(x)    (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x))
851 #define HALVE_MOVE_DELAY(x)     (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x))
852
853 #define DOUBLE_PLAYER_SPEED(p)  (HALVE_MOVE_DELAY( (p)->move_delay_value))
854 #define HALVE_PLAYER_SPEED(p)   (DOUBLE_MOVE_DELAY((p)->move_delay_value))
855
856 // values for scroll positions
857 #define SCROLL_POSITION_X(x)    ((x) < SBX_Left  + MIDPOSX ? SBX_Left : \
858                                  (x) > SBX_Right + MIDPOSX ? SBX_Right :\
859                                  (x) - MIDPOSX)
860 #define SCROLL_POSITION_Y(y)    ((y) < SBY_Upper + MIDPOSY ? SBY_Upper :\
861                                  (y) > SBY_Lower + MIDPOSY ? SBY_Lower :\
862                                  (y) - MIDPOSY)
863
864 // values for other actions
865 #define MOVE_STEPSIZE_NORMAL    (TILEX / MOVE_DELAY_NORMAL_SPEED)
866 #define MOVE_STEPSIZE_MIN       (1)
867 #define MOVE_STEPSIZE_MAX       (TILEX)
868
869 #define GET_DX_FROM_DIR(d)      ((d) == MV_LEFT ? -1 : (d) == MV_RIGHT ? 1 : 0)
870 #define GET_DY_FROM_DIR(d)      ((d) == MV_UP   ? -1 : (d) == MV_DOWN  ? 1 : 0)
871
872 #define INIT_GFX_RANDOM()       (GetSimpleRandom(1000000))
873
874 #define GET_NEW_PUSH_DELAY(e)   (   (element_info[e].push_delay_fixed) + \
875                                  RND(element_info[e].push_delay_random))
876 #define GET_NEW_DROP_DELAY(e)   (   (element_info[e].drop_delay_fixed) + \
877                                  RND(element_info[e].drop_delay_random))
878 #define GET_NEW_MOVE_DELAY(e)   (   (element_info[e].move_delay_fixed) + \
879                                  RND(element_info[e].move_delay_random))
880 #define GET_MAX_MOVE_DELAY(e)   (   (element_info[e].move_delay_fixed) + \
881                                     (element_info[e].move_delay_random))
882 #define GET_NEW_CE_VALUE(e)     (   (element_info[e].ce_value_fixed_initial) +\
883                                  RND(element_info[e].ce_value_random_initial))
884 #define GET_CE_SCORE(e)         (   (element_info[e].collect_score))
885 #define GET_CHANGE_DELAY(c)     (   ((c)->delay_fixed  * (c)->delay_frames) + \
886                                  RND((c)->delay_random * (c)->delay_frames))
887 #define GET_CE_DELAY_VALUE(c)   (   ((c)->delay_fixed) + \
888                                  RND((c)->delay_random))
889
890
891 #define GET_VALID_RUNTIME_ELEMENT(e)                                    \
892          ((e) >= NUM_RUNTIME_ELEMENTS ? EL_UNKNOWN : (e))
893
894 #define RESOLVED_REFERENCE_ELEMENT(be, e)                               \
895         ((be) + (e) - EL_SELF < EL_CUSTOM_START ? EL_CUSTOM_START :     \
896          (be) + (e) - EL_SELF > EL_CUSTOM_END   ? EL_CUSTOM_END :       \
897          (be) + (e) - EL_SELF)
898
899 #define GET_PLAYER_FROM_BITS(p)                                         \
900         (EL_PLAYER_1 + ((p) != PLAYER_BITS_ANY ? log_2(p) : 0))
901
902 #define GET_TARGET_ELEMENT(be, e, ch, cv, cs)                           \
903         ((e) == EL_TRIGGER_PLAYER   ? (ch)->actual_trigger_player    :  \
904          (e) == EL_TRIGGER_ELEMENT  ? (ch)->actual_trigger_element   :  \
905          (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value  :  \
906          (e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score  :  \
907          (e) == EL_CURRENT_CE_VALUE ? (cv) :                            \
908          (e) == EL_CURRENT_CE_SCORE ? (cs) :                            \
909          (e) >= EL_PREV_CE_8 && (e) <= EL_NEXT_CE_8 ?                   \
910          RESOLVED_REFERENCE_ELEMENT(be, e) :                            \
911          (e))
912
913 #define CAN_GROW_INTO(e)                                                \
914         ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
915
916 #define ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, condition)                 \
917                 (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
918                                         (condition)))
919
920 #define ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, condition)              \
921                 (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
922                                         (CAN_MOVE_INTO_ACID(e) &&       \
923                                          Feld[x][y] == EL_ACID) ||      \
924                                         (condition)))
925
926 #define ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, condition)              \
927                 (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) ||      \
928                                         (CAN_MOVE_INTO_ACID(e) &&       \
929                                          Feld[x][y] == EL_ACID) ||      \
930                                         (condition)))
931
932 #define ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, condition)              \
933                 (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
934                                         (condition) ||                  \
935                                         (CAN_MOVE_INTO_ACID(e) &&       \
936                                          Feld[x][y] == EL_ACID) ||      \
937                                         (DONT_COLLIDE_WITH(e) &&        \
938                                          IS_PLAYER(x, y) &&             \
939                                          !PLAYER_ENEMY_PROTECTED(x, y))))
940
941 #define ELEMENT_CAN_ENTER_FIELD(e, x, y)                                \
942         ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, 0)
943
944 #define SATELLITE_CAN_ENTER_FIELD(x, y)                                 \
945         ELEMENT_CAN_ENTER_FIELD_BASE_2(EL_SATELLITE, x, y, 0)
946
947 #define ANDROID_CAN_ENTER_FIELD(e, x, y)                                \
948         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, Feld[x][y] == EL_EMC_PLANT)
949
950 #define ANDROID_CAN_CLONE_FIELD(x, y)                                   \
951         (IN_LEV_FIELD(x, y) && (CAN_BE_CLONED_BY_ANDROID(Feld[x][y]) || \
952                                 CAN_BE_CLONED_BY_ANDROID(EL_TRIGGER_ELEMENT)))
953
954 #define ENEMY_CAN_ENTER_FIELD(e, x, y)                                  \
955         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
956
957 #define YAMYAM_CAN_ENTER_FIELD(e, x, y)                                 \
958         ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, Feld[x][y] == EL_DIAMOND)
959
960 #define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y)                            \
961         ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x,y, IS_FOOD_DARK_YAMYAM(Feld[x][y]))
962
963 #define PACMAN_CAN_ENTER_FIELD(e, x, y)                                 \
964         ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, IS_AMOEBOID(Feld[x][y]))
965
966 #define PIG_CAN_ENTER_FIELD(e, x, y)                                    \
967         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, IS_FOOD_PIG(Feld[x][y]))
968
969 #define PENGUIN_CAN_ENTER_FIELD(e, x, y)                                \
970         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (Feld[x][y] == EL_EXIT_OPEN || \
971                                                  Feld[x][y] == EL_EM_EXIT_OPEN || \
972                                                  Feld[x][y] == EL_STEEL_EXIT_OPEN || \
973                                                  Feld[x][y] == EL_EM_STEEL_EXIT_OPEN || \
974                                                  IS_FOOD_PENGUIN(Feld[x][y])))
975 #define DRAGON_CAN_ENTER_FIELD(e, x, y)                                 \
976         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
977
978 #define MOLE_CAN_ENTER_FIELD(e, x, y, condition)                        \
979         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (condition))
980
981 #define SPRING_CAN_ENTER_FIELD(e, x, y)                                 \
982         ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
983
984 #define SPRING_CAN_BUMP_FROM_FIELD(x, y)                                \
985         (IN_LEV_FIELD(x, y) && (Feld[x][y] == EL_EMC_SPRING_BUMPER ||   \
986                                 Feld[x][y] == EL_EMC_SPRING_BUMPER_ACTIVE))
987
988 #define MOVE_ENTER_EL(e)        (element_info[e].move_enter_element)
989
990 #define CE_ENTER_FIELD_COND(e, x, y)                                    \
991                 (!IS_PLAYER(x, y) &&                                    \
992                  IS_EQUAL_OR_IN_GROUP(Feld[x][y], MOVE_ENTER_EL(e)))
993
994 #define CUSTOM_ELEMENT_CAN_ENTER_FIELD(e, x, y)                         \
995         ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, CE_ENTER_FIELD_COND(e, x, y))
996
997 #define IN_LEV_FIELD_AND_IS_FREE(x, y)  (IN_LEV_FIELD(x, y) &&  IS_FREE(x, y))
998 #define IN_LEV_FIELD_AND_NOT_FREE(x, y) (IN_LEV_FIELD(x, y) && !IS_FREE(x, y))
999
1000 #define ACCESS_FROM(e, d)               (element_info[e].access_direction &(d))
1001 #define IS_WALKABLE_FROM(e, d)          (IS_WALKABLE(e)   && ACCESS_FROM(e, d))
1002 #define IS_PASSABLE_FROM(e, d)          (IS_PASSABLE(e)   && ACCESS_FROM(e, d))
1003 #define IS_ACCESSIBLE_FROM(e, d)        (IS_ACCESSIBLE(e) && ACCESS_FROM(e, d))
1004
1005 #define MM_HEALTH(x)            (MIN(MAX(0, MAX_HEALTH - (x)), MAX_HEALTH))
1006
1007 // game button identifiers
1008 #define GAME_CTRL_ID_STOP               0
1009 #define GAME_CTRL_ID_PAUSE              1
1010 #define GAME_CTRL_ID_PLAY               2
1011 #define GAME_CTRL_ID_UNDO               3
1012 #define GAME_CTRL_ID_REDO               4
1013 #define GAME_CTRL_ID_SAVE               5
1014 #define GAME_CTRL_ID_PAUSE2             6
1015 #define GAME_CTRL_ID_LOAD               7
1016 #define GAME_CTRL_ID_PANEL_STOP         8
1017 #define GAME_CTRL_ID_PANEL_PAUSE        9
1018 #define GAME_CTRL_ID_PANEL_PLAY         10
1019 #define SOUND_CTRL_ID_MUSIC             11
1020 #define SOUND_CTRL_ID_LOOPS             12
1021 #define SOUND_CTRL_ID_SIMPLE            13
1022 #define SOUND_CTRL_ID_PANEL_MUSIC       14
1023 #define SOUND_CTRL_ID_PANEL_LOOPS       15
1024 #define SOUND_CTRL_ID_PANEL_SIMPLE      16
1025
1026 #define NUM_GAME_BUTTONS                17
1027
1028
1029 // forward declaration for internal use
1030
1031 static void CreateField(int, int, int);
1032
1033 static void ResetGfxAnimation(int, int);
1034
1035 static void SetPlayerWaiting(struct PlayerInfo *, boolean);
1036 static void AdvanceFrameAndPlayerCounters(int);
1037
1038 static boolean MovePlayerOneStep(struct PlayerInfo *, int, int, int, int);
1039 static boolean MovePlayer(struct PlayerInfo *, int, int);
1040 static void ScrollPlayer(struct PlayerInfo *, int);
1041 static void ScrollScreen(struct PlayerInfo *, int);
1042
1043 static int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
1044 static boolean DigFieldByCE(int, int, int);
1045 static boolean SnapField(struct PlayerInfo *, int, int);
1046 static boolean DropElement(struct PlayerInfo *);
1047
1048 static void InitBeltMovement(void);
1049 static void CloseAllOpenTimegates(void);
1050 static void CheckGravityMovement(struct PlayerInfo *);
1051 static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *);
1052 static void KillPlayerUnlessEnemyProtected(int, int);
1053 static void KillPlayerUnlessExplosionProtected(int, int);
1054
1055 static void TestIfPlayerTouchesCustomElement(int, int);
1056 static void TestIfElementTouchesCustomElement(int, int);
1057 static void TestIfElementHitsCustomElement(int, int, int);
1058
1059 static void HandleElementChange(int, int, int);
1060 static void ExecuteCustomElementAction(int, int, int, int);
1061 static boolean ChangeElement(int, int, int, int);
1062
1063 static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
1064 #define CheckTriggeredElementChange(x, y, e, ev)                        \
1065         CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY,CH_SIDE_ANY, -1)
1066 #define CheckTriggeredElementChangeByPlayer(x, y, e, ev, p, s)          \
1067         CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
1068 #define CheckTriggeredElementChangeBySide(x, y, e, ev, s)               \
1069         CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, s, -1)
1070 #define CheckTriggeredElementChangeByPage(x, y, e, ev, p)               \
1071         CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
1072
1073 static boolean CheckElementChangeExt(int, int, int, int, int, int, int);
1074 #define CheckElementChange(x, y, e, te, ev)                             \
1075         CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY)
1076 #define CheckElementChangeByPlayer(x, y, e, ev, p, s)                   \
1077         CheckElementChangeExt(x, y, e, EL_EMPTY, ev, p, s)
1078 #define CheckElementChangeBySide(x, y, e, te, ev, s)                    \
1079         CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, s)
1080
1081 static void PlayLevelSound(int, int, int);
1082 static void PlayLevelSoundNearest(int, int, int);
1083 static void PlayLevelSoundAction(int, int, int);
1084 static void PlayLevelSoundElementAction(int, int, int, int);
1085 static void PlayLevelSoundElementActionIfLoop(int, int, int, int);
1086 static void PlayLevelSoundActionIfLoop(int, int, int);
1087 static void StopLevelSoundActionIfLoop(int, int, int);
1088 static void PlayLevelMusic(void);
1089 static void FadeLevelSoundsAndMusic(void);
1090
1091 static void HandleGameButtons(struct GadgetInfo *);
1092
1093 int AmoebeNachbarNr(int, int);
1094 void AmoebeUmwandeln(int, int);
1095 void ContinueMoving(int, int);
1096 void Bang(int, int);
1097 void InitMovDir(int, int);
1098 void InitAmoebaNr(int, int);
1099 int NewHiScore(int);
1100
1101 void TestIfGoodThingHitsBadThing(int, int, int);
1102 void TestIfBadThingHitsGoodThing(int, int, int);
1103 void TestIfPlayerTouchesBadThing(int, int);
1104 void TestIfPlayerRunsIntoBadThing(int, int, int);
1105 void TestIfBadThingTouchesPlayer(int, int);
1106 void TestIfBadThingRunsIntoPlayer(int, int, int);
1107 void TestIfFriendTouchesBadThing(int, int);
1108 void TestIfBadThingTouchesFriend(int, int);
1109 void TestIfBadThingTouchesOtherBadThing(int, int);
1110 void TestIfGoodThingGetsHitByBadThing(int, int, int);
1111
1112 void KillPlayer(struct PlayerInfo *);
1113 void BuryPlayer(struct PlayerInfo *);
1114 void RemovePlayer(struct PlayerInfo *);
1115 void ExitPlayer(struct PlayerInfo *);
1116
1117 static int getInvisibleActiveFromInvisibleElement(int);
1118 static int getInvisibleFromInvisibleActiveElement(int);
1119
1120 static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
1121
1122 // for detection of endless loops, caused by custom element programming
1123 // (using maximal playfield width x 10 is just a rough approximation)
1124 #define MAX_ELEMENT_CHANGE_RECURSION_DEPTH      (MAX_PLAYFIELD_WIDTH * 10)
1125
1126 #define RECURSION_LOOP_DETECTION_START(e, rc)                           \
1127 {                                                                       \
1128   if (recursion_loop_detected)                                          \
1129     return (rc);                                                        \
1130                                                                         \
1131   if (recursion_loop_depth > MAX_ELEMENT_CHANGE_RECURSION_DEPTH)        \
1132   {                                                                     \
1133     recursion_loop_detected = TRUE;                                     \
1134     recursion_loop_element = (e);                                       \
1135   }                                                                     \
1136                                                                         \
1137   recursion_loop_depth++;                                               \
1138 }
1139
1140 #define RECURSION_LOOP_DETECTION_END()                                  \
1141 {                                                                       \
1142   recursion_loop_depth--;                                               \
1143 }
1144
1145 static int recursion_loop_depth;
1146 static boolean recursion_loop_detected;
1147 static boolean recursion_loop_element;
1148
1149 static int map_player_action[MAX_PLAYERS];
1150
1151
1152 // ----------------------------------------------------------------------------
1153 // definition of elements that automatically change to other elements after
1154 // a specified time, eventually calling a function when changing
1155 // ----------------------------------------------------------------------------
1156
1157 // forward declaration for changer functions
1158 static void InitBuggyBase(int, int);
1159 static void WarnBuggyBase(int, int);
1160
1161 static void InitTrap(int, int);
1162 static void ActivateTrap(int, int);
1163 static void ChangeActiveTrap(int, int);
1164
1165 static void InitRobotWheel(int, int);
1166 static void RunRobotWheel(int, int);
1167 static void StopRobotWheel(int, int);
1168
1169 static void InitTimegateWheel(int, int);
1170 static void RunTimegateWheel(int, int);
1171
1172 static void InitMagicBallDelay(int, int);
1173 static void ActivateMagicBall(int, int);
1174
1175 struct ChangingElementInfo
1176 {
1177   int element;
1178   int target_element;
1179   int change_delay;
1180   void (*pre_change_function)(int x, int y);
1181   void (*change_function)(int x, int y);
1182   void (*post_change_function)(int x, int y);
1183 };
1184
1185 static struct ChangingElementInfo change_delay_list[] =
1186 {
1187   {
1188     EL_NUT_BREAKING,
1189     EL_EMERALD,
1190     6,
1191     NULL,
1192     NULL,
1193     NULL
1194   },
1195   {
1196     EL_PEARL_BREAKING,
1197     EL_EMPTY,
1198     8,
1199     NULL,
1200     NULL,
1201     NULL
1202   },
1203   {
1204     EL_EXIT_OPENING,
1205     EL_EXIT_OPEN,
1206     29,
1207     NULL,
1208     NULL,
1209     NULL
1210   },
1211   {
1212     EL_EXIT_CLOSING,
1213     EL_EXIT_CLOSED,
1214     29,
1215     NULL,
1216     NULL,
1217     NULL
1218   },
1219   {
1220     EL_STEEL_EXIT_OPENING,
1221     EL_STEEL_EXIT_OPEN,
1222     29,
1223     NULL,
1224     NULL,
1225     NULL
1226   },
1227   {
1228     EL_STEEL_EXIT_CLOSING,
1229     EL_STEEL_EXIT_CLOSED,
1230     29,
1231     NULL,
1232     NULL,
1233     NULL
1234   },
1235   {
1236     EL_EM_EXIT_OPENING,
1237     EL_EM_EXIT_OPEN,
1238     29,
1239     NULL,
1240     NULL,
1241     NULL
1242   },
1243   {
1244     EL_EM_EXIT_CLOSING,
1245     EL_EMPTY,
1246     29,
1247     NULL,
1248     NULL,
1249     NULL
1250   },
1251   {
1252     EL_EM_STEEL_EXIT_OPENING,
1253     EL_EM_STEEL_EXIT_OPEN,
1254     29,
1255     NULL,
1256     NULL,
1257     NULL
1258   },
1259   {
1260     EL_EM_STEEL_EXIT_CLOSING,
1261     EL_STEELWALL,
1262     29,
1263     NULL,
1264     NULL,
1265     NULL
1266   },
1267   {
1268     EL_SP_EXIT_OPENING,
1269     EL_SP_EXIT_OPEN,
1270     29,
1271     NULL,
1272     NULL,
1273     NULL
1274   },
1275   {
1276     EL_SP_EXIT_CLOSING,
1277     EL_SP_EXIT_CLOSED,
1278     29,
1279     NULL,
1280     NULL,
1281     NULL
1282   },
1283   {
1284     EL_SWITCHGATE_OPENING,
1285     EL_SWITCHGATE_OPEN,
1286     29,
1287     NULL,
1288     NULL,
1289     NULL
1290   },
1291   {
1292     EL_SWITCHGATE_CLOSING,
1293     EL_SWITCHGATE_CLOSED,
1294     29,
1295     NULL,
1296     NULL,
1297     NULL
1298   },
1299   {
1300     EL_TIMEGATE_OPENING,
1301     EL_TIMEGATE_OPEN,
1302     29,
1303     NULL,
1304     NULL,
1305     NULL
1306   },
1307   {
1308     EL_TIMEGATE_CLOSING,
1309     EL_TIMEGATE_CLOSED,
1310     29,
1311     NULL,
1312     NULL,
1313     NULL
1314   },
1315
1316   {
1317     EL_ACID_SPLASH_LEFT,
1318     EL_EMPTY,
1319     8,
1320     NULL,
1321     NULL,
1322     NULL
1323   },
1324   {
1325     EL_ACID_SPLASH_RIGHT,
1326     EL_EMPTY,
1327     8,
1328     NULL,
1329     NULL,
1330     NULL
1331   },
1332   {
1333     EL_SP_BUGGY_BASE,
1334     EL_SP_BUGGY_BASE_ACTIVATING,
1335     0,
1336     InitBuggyBase,
1337     NULL,
1338     NULL
1339   },
1340   {
1341     EL_SP_BUGGY_BASE_ACTIVATING,
1342     EL_SP_BUGGY_BASE_ACTIVE,
1343     0,
1344     InitBuggyBase,
1345     NULL,
1346     NULL
1347   },
1348   {
1349     EL_SP_BUGGY_BASE_ACTIVE,
1350     EL_SP_BUGGY_BASE,
1351     0,
1352     InitBuggyBase,
1353     WarnBuggyBase,
1354     NULL
1355   },
1356   {
1357     EL_TRAP,
1358     EL_TRAP_ACTIVE,
1359     0,
1360     InitTrap,
1361     NULL,
1362     ActivateTrap
1363   },
1364   {
1365     EL_TRAP_ACTIVE,
1366     EL_TRAP,
1367     31,
1368     NULL,
1369     ChangeActiveTrap,
1370     NULL
1371   },
1372   {
1373     EL_ROBOT_WHEEL_ACTIVE,
1374     EL_ROBOT_WHEEL,
1375     0,
1376     InitRobotWheel,
1377     RunRobotWheel,
1378     StopRobotWheel
1379   },
1380   {
1381     EL_TIMEGATE_SWITCH_ACTIVE,
1382     EL_TIMEGATE_SWITCH,
1383     0,
1384     InitTimegateWheel,
1385     RunTimegateWheel,
1386     NULL
1387   },
1388   {
1389     EL_DC_TIMEGATE_SWITCH_ACTIVE,
1390     EL_DC_TIMEGATE_SWITCH,
1391     0,
1392     InitTimegateWheel,
1393     RunTimegateWheel,
1394     NULL
1395   },
1396   {
1397     EL_EMC_MAGIC_BALL_ACTIVE,
1398     EL_EMC_MAGIC_BALL_ACTIVE,
1399     0,
1400     InitMagicBallDelay,
1401     NULL,
1402     ActivateMagicBall
1403   },
1404   {
1405     EL_EMC_SPRING_BUMPER_ACTIVE,
1406     EL_EMC_SPRING_BUMPER,
1407     8,
1408     NULL,
1409     NULL,
1410     NULL
1411   },
1412   {
1413     EL_DIAGONAL_SHRINKING,
1414     EL_UNDEFINED,
1415     0,
1416     NULL,
1417     NULL,
1418     NULL
1419   },
1420   {
1421     EL_DIAGONAL_GROWING,
1422     EL_UNDEFINED,
1423     0,
1424     NULL,
1425     NULL,
1426     NULL,
1427   },
1428
1429   {
1430     EL_UNDEFINED,
1431     EL_UNDEFINED,
1432     -1,
1433     NULL,
1434     NULL,
1435     NULL
1436   }
1437 };
1438
1439 struct
1440 {
1441   int element;
1442   int push_delay_fixed, push_delay_random;
1443 }
1444 push_delay_list[] =
1445 {
1446   { EL_SPRING,                  0, 0 },
1447   { EL_BALLOON,                 0, 0 },
1448
1449   { EL_SOKOBAN_OBJECT,          2, 0 },
1450   { EL_SOKOBAN_FIELD_FULL,      2, 0 },
1451   { EL_SATELLITE,               2, 0 },
1452   { EL_SP_DISK_YELLOW,          2, 0 },
1453
1454   { EL_UNDEFINED,               0, 0 },
1455 };
1456
1457 struct
1458 {
1459   int element;
1460   int move_stepsize;
1461 }
1462 move_stepsize_list[] =
1463 {
1464   { EL_AMOEBA_DROP,             2 },
1465   { EL_AMOEBA_DROPPING,         2 },
1466   { EL_QUICKSAND_FILLING,       1 },
1467   { EL_QUICKSAND_EMPTYING,      1 },
1468   { EL_QUICKSAND_FAST_FILLING,  2 },
1469   { EL_QUICKSAND_FAST_EMPTYING, 2 },
1470   { EL_MAGIC_WALL_FILLING,      2 },
1471   { EL_MAGIC_WALL_EMPTYING,     2 },
1472   { EL_BD_MAGIC_WALL_FILLING,   2 },
1473   { EL_BD_MAGIC_WALL_EMPTYING,  2 },
1474   { EL_DC_MAGIC_WALL_FILLING,   2 },
1475   { EL_DC_MAGIC_WALL_EMPTYING,  2 },
1476
1477   { EL_UNDEFINED,               0 },
1478 };
1479
1480 struct
1481 {
1482   int element;
1483   int count;
1484 }
1485 collect_count_list[] =
1486 {
1487   { EL_EMERALD,                 1 },
1488   { EL_BD_DIAMOND,              1 },
1489   { EL_EMERALD_YELLOW,          1 },
1490   { EL_EMERALD_RED,             1 },
1491   { EL_EMERALD_PURPLE,          1 },
1492   { EL_DIAMOND,                 3 },
1493   { EL_SP_INFOTRON,             1 },
1494   { EL_PEARL,                   5 },
1495   { EL_CRYSTAL,                 8 },
1496
1497   { EL_UNDEFINED,               0 },
1498 };
1499
1500 struct
1501 {
1502   int element;
1503   int direction;
1504 }
1505 access_direction_list[] =
1506 {
1507   { EL_TUBE_ANY,                        MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
1508   { EL_TUBE_VERTICAL,                                        MV_UP | MV_DOWN },
1509   { EL_TUBE_HORIZONTAL,                 MV_LEFT | MV_RIGHT                   },
1510   { EL_TUBE_VERTICAL_LEFT,              MV_LEFT |            MV_UP | MV_DOWN },
1511   { EL_TUBE_VERTICAL_RIGHT,                       MV_RIGHT | MV_UP | MV_DOWN },
1512   { EL_TUBE_HORIZONTAL_UP,              MV_LEFT | MV_RIGHT | MV_UP           },
1513   { EL_TUBE_HORIZONTAL_DOWN,            MV_LEFT | MV_RIGHT |         MV_DOWN },
1514   { EL_TUBE_LEFT_UP,                    MV_LEFT |            MV_UP           },
1515   { EL_TUBE_LEFT_DOWN,                  MV_LEFT |                    MV_DOWN },
1516   { EL_TUBE_RIGHT_UP,                             MV_RIGHT | MV_UP           },
1517   { EL_TUBE_RIGHT_DOWN,                           MV_RIGHT |         MV_DOWN },
1518
1519   { EL_SP_PORT_LEFT,                              MV_RIGHT                   },
1520   { EL_SP_PORT_RIGHT,                   MV_LEFT                              },
1521   { EL_SP_PORT_UP,                                                   MV_DOWN },
1522   { EL_SP_PORT_DOWN,                                         MV_UP           },
1523   { EL_SP_PORT_HORIZONTAL,              MV_LEFT | MV_RIGHT                   },
1524   { EL_SP_PORT_VERTICAL,                                     MV_UP | MV_DOWN },
1525   { EL_SP_PORT_ANY,                     MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
1526   { EL_SP_GRAVITY_PORT_LEFT,                      MV_RIGHT                   },
1527   { EL_SP_GRAVITY_PORT_RIGHT,           MV_LEFT                              },
1528   { EL_SP_GRAVITY_PORT_UP,                                           MV_DOWN },
1529   { EL_SP_GRAVITY_PORT_DOWN,                                 MV_UP           },
1530   { EL_SP_GRAVITY_ON_PORT_LEFT,                   MV_RIGHT                   },
1531   { EL_SP_GRAVITY_ON_PORT_RIGHT,        MV_LEFT                              },
1532   { EL_SP_GRAVITY_ON_PORT_UP,                                        MV_DOWN },
1533   { EL_SP_GRAVITY_ON_PORT_DOWN,                              MV_UP           },
1534   { EL_SP_GRAVITY_OFF_PORT_LEFT,                  MV_RIGHT                   },
1535   { EL_SP_GRAVITY_OFF_PORT_RIGHT,       MV_LEFT                              },
1536   { EL_SP_GRAVITY_OFF_PORT_UP,                                       MV_DOWN },
1537   { EL_SP_GRAVITY_OFF_PORT_DOWN,                             MV_UP           },
1538
1539   { EL_UNDEFINED,                       MV_NONE                              }
1540 };
1541
1542 static boolean trigger_events[MAX_NUM_ELEMENTS][NUM_CHANGE_EVENTS];
1543
1544 #define IS_AUTO_CHANGING(e)     (element_info[e].has_change_event[CE_DELAY])
1545 #define IS_JUST_CHANGING(x, y)  (ChangeDelay[x][y] != 0)
1546 #define IS_CHANGING(x, y)       (IS_AUTO_CHANGING(Feld[x][y]) || \
1547                                  IS_JUST_CHANGING(x, y))
1548
1549 #define CE_PAGE(e, ce)          (element_info[e].event_page[ce])
1550
1551 // static variables for playfield scan mode (scanning forward or backward)
1552 static int playfield_scan_start_x = 0;
1553 static int playfield_scan_start_y = 0;
1554 static int playfield_scan_delta_x = 1;
1555 static int playfield_scan_delta_y = 1;
1556
1557 #define SCAN_PLAYFIELD(x, y)    for ((y) = playfield_scan_start_y;      \
1558                                      (y) >= 0 && (y) <= lev_fieldy - 1; \
1559                                      (y) += playfield_scan_delta_y)     \
1560                                 for ((x) = playfield_scan_start_x;      \
1561                                      (x) >= 0 && (x) <= lev_fieldx - 1; \
1562                                      (x) += playfield_scan_delta_x)
1563
1564 #ifdef DEBUG
1565 void DEBUG_SetMaximumDynamite(void)
1566 {
1567   int i;
1568
1569   for (i = 0; i < MAX_INVENTORY_SIZE; i++)
1570     if (local_player->inventory_size < MAX_INVENTORY_SIZE)
1571       local_player->inventory_element[local_player->inventory_size++] =
1572         EL_DYNAMITE;
1573 }
1574 #endif
1575
1576 static void InitPlayfieldScanModeVars(void)
1577 {
1578   if (game.use_reverse_scan_direction)
1579   {
1580     playfield_scan_start_x = lev_fieldx - 1;
1581     playfield_scan_start_y = lev_fieldy - 1;
1582
1583     playfield_scan_delta_x = -1;
1584     playfield_scan_delta_y = -1;
1585   }
1586   else
1587   {
1588     playfield_scan_start_x = 0;
1589     playfield_scan_start_y = 0;
1590
1591     playfield_scan_delta_x = 1;
1592     playfield_scan_delta_y = 1;
1593   }
1594 }
1595
1596 static void InitPlayfieldScanMode(int mode)
1597 {
1598   game.use_reverse_scan_direction =
1599     (mode == CA_ARG_SCAN_MODE_REVERSE ? TRUE : FALSE);
1600
1601   InitPlayfieldScanModeVars();
1602 }
1603
1604 static int get_move_delay_from_stepsize(int move_stepsize)
1605 {
1606   move_stepsize =
1607     MIN(MAX(MOVE_STEPSIZE_MIN, move_stepsize), MOVE_STEPSIZE_MAX);
1608
1609   // make sure that stepsize value is always a power of 2
1610   move_stepsize = (1 << log_2(move_stepsize));
1611
1612   return TILEX / move_stepsize;
1613 }
1614
1615 static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
1616                                boolean init_game)
1617 {
1618   int player_nr = player->index_nr;
1619   int move_delay = get_move_delay_from_stepsize(move_stepsize);
1620   boolean cannot_move = (move_stepsize == STEPSIZE_NOT_MOVING ? TRUE : FALSE);
1621
1622   // do no immediately change move delay -- the player might just be moving
1623   player->move_delay_value_next = move_delay;
1624
1625   // information if player can move must be set separately
1626   player->cannot_move = cannot_move;
1627
1628   if (init_game)
1629   {
1630     player->move_delay       = game.initial_move_delay[player_nr];
1631     player->move_delay_value = game.initial_move_delay_value[player_nr];
1632
1633     player->move_delay_value_next = -1;
1634
1635     player->move_delay_reset_counter = 0;
1636   }
1637 }
1638
1639 void GetPlayerConfig(void)
1640 {
1641   GameFrameDelay = setup.game_frame_delay;
1642
1643   if (!audio.sound_available)
1644     setup.sound_simple = FALSE;
1645
1646   if (!audio.loops_available)
1647     setup.sound_loops = FALSE;
1648
1649   if (!audio.music_available)
1650     setup.sound_music = FALSE;
1651
1652   if (!video.fullscreen_available)
1653     setup.fullscreen = FALSE;
1654
1655   setup.sound = (setup.sound_simple || setup.sound_loops || setup.sound_music);
1656
1657   SetAudioMode(setup.sound);
1658 }
1659
1660 int GetElementFromGroupElement(int element)
1661 {
1662   if (IS_GROUP_ELEMENT(element))
1663   {
1664     struct ElementGroupInfo *group = element_info[element].group;
1665     int last_anim_random_frame = gfx.anim_random_frame;
1666     int element_pos;
1667
1668     if (group->choice_mode == ANIM_RANDOM)
1669       gfx.anim_random_frame = RND(group->num_elements_resolved);
1670
1671     element_pos = getAnimationFrame(group->num_elements_resolved, 1,
1672                                     group->choice_mode, 0,
1673                                     group->choice_pos);
1674
1675     if (group->choice_mode == ANIM_RANDOM)
1676       gfx.anim_random_frame = last_anim_random_frame;
1677
1678     group->choice_pos++;
1679
1680     element = group->element_resolved[element_pos];
1681   }
1682
1683   return element;
1684 }
1685
1686 static void IncrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player)
1687 {
1688   if (level.sb_fields_needed)
1689     player->sokoban_fields_still_needed++;
1690 }
1691
1692 static void IncrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player)
1693 {
1694   if (level.sb_objects_needed)
1695     player->sokoban_objects_still_needed++;
1696 }
1697
1698 static void DecrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player)
1699 {
1700   if (player->sokoban_fields_still_needed > 0)
1701     player->sokoban_fields_still_needed--;
1702 }
1703
1704 static void DecrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player)
1705 {
1706   if (player->sokoban_objects_still_needed > 0)
1707     player->sokoban_objects_still_needed--;
1708 }
1709
1710 static void InitPlayerField(int x, int y, int element, boolean init_game)
1711 {
1712   if (element == EL_SP_MURPHY)
1713   {
1714     if (init_game)
1715     {
1716       if (stored_player[0].present)
1717       {
1718         Feld[x][y] = EL_SP_MURPHY_CLONE;
1719
1720         return;
1721       }
1722       else
1723       {
1724         stored_player[0].initial_element = element;
1725         stored_player[0].use_murphy = TRUE;
1726
1727         if (!level.use_artwork_element[0])
1728           stored_player[0].artwork_element = EL_SP_MURPHY;
1729       }
1730
1731       Feld[x][y] = EL_PLAYER_1;
1732     }
1733   }
1734
1735   if (init_game)
1736   {
1737     struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1];
1738     int jx = player->jx, jy = player->jy;
1739
1740     player->present = TRUE;
1741
1742     player->block_last_field = (element == EL_SP_MURPHY ?
1743                                 level.sp_block_last_field :
1744                                 level.block_last_field);
1745
1746     // ---------- initialize player's last field block delay ------------------
1747
1748     // always start with reliable default value (no adjustment needed)
1749     player->block_delay_adjustment = 0;
1750
1751     // special case 1: in Supaplex, Murphy blocks last field one more frame
1752     if (player->block_last_field && element == EL_SP_MURPHY)
1753       player->block_delay_adjustment = 1;
1754
1755     // special case 2: in game engines before 3.1.1, blocking was different
1756     if (game.use_block_last_field_bug)
1757       player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
1758
1759     if (!network.enabled || player->connected_network)
1760     {
1761       player->active = TRUE;
1762
1763       // remove potentially duplicate players
1764       if (StorePlayer[jx][jy] == Feld[x][y])
1765         StorePlayer[jx][jy] = 0;
1766
1767       StorePlayer[x][y] = Feld[x][y];
1768
1769 #if DEBUG_INIT_PLAYER
1770       if (options.debug)
1771       {
1772         printf("- player element %d activated", player->element_nr);
1773         printf(" (local player is %d and currently %s)\n",
1774                local_player->element_nr,
1775                local_player->active ? "active" : "not active");
1776       }
1777     }
1778 #endif
1779
1780     Feld[x][y] = EL_EMPTY;
1781
1782     player->jx = player->last_jx = x;
1783     player->jy = player->last_jy = y;
1784   }
1785
1786   if (!init_game)
1787   {
1788     int player_nr = GET_PLAYER_NR(element);
1789     struct PlayerInfo *player = &stored_player[player_nr];
1790
1791     if (player->active && player->killed)
1792       player->reanimated = TRUE; // if player was just killed, reanimate him
1793   }
1794 }
1795
1796 static void InitField(int x, int y, boolean init_game)
1797 {
1798   int element = Feld[x][y];
1799
1800   switch (element)
1801   {
1802     case EL_SP_MURPHY:
1803     case EL_PLAYER_1:
1804     case EL_PLAYER_2:
1805     case EL_PLAYER_3:
1806     case EL_PLAYER_4:
1807       InitPlayerField(x, y, element, init_game);
1808       break;
1809
1810     case EL_SOKOBAN_FIELD_PLAYER:
1811       element = Feld[x][y] = EL_PLAYER_1;
1812       InitField(x, y, init_game);
1813
1814       element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
1815       InitField(x, y, init_game);
1816       break;
1817
1818     case EL_SOKOBAN_FIELD_EMPTY:
1819       IncrementPlayerSokobanFieldsNeeded(local_player);
1820       break;
1821
1822     case EL_SOKOBAN_OBJECT:
1823       IncrementPlayerSokobanObjectsNeeded(local_player);
1824       break;
1825
1826     case EL_STONEBLOCK:
1827       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
1828         Feld[x][y] = EL_ACID_POOL_TOPLEFT;
1829       else if (x > 0 && Feld[x-1][y] == EL_ACID)
1830         Feld[x][y] = EL_ACID_POOL_TOPRIGHT;
1831       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPLEFT)
1832         Feld[x][y] = EL_ACID_POOL_BOTTOMLEFT;
1833       else if (y > 0 && Feld[x][y-1] == EL_ACID)
1834         Feld[x][y] = EL_ACID_POOL_BOTTOM;
1835       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPRIGHT)
1836         Feld[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
1837       break;
1838
1839     case EL_BUG:
1840     case EL_BUG_RIGHT:
1841     case EL_BUG_UP:
1842     case EL_BUG_LEFT:
1843     case EL_BUG_DOWN:
1844     case EL_SPACESHIP:
1845     case EL_SPACESHIP_RIGHT:
1846     case EL_SPACESHIP_UP:
1847     case EL_SPACESHIP_LEFT:
1848     case EL_SPACESHIP_DOWN:
1849     case EL_BD_BUTTERFLY:
1850     case EL_BD_BUTTERFLY_RIGHT:
1851     case EL_BD_BUTTERFLY_UP:
1852     case EL_BD_BUTTERFLY_LEFT:
1853     case EL_BD_BUTTERFLY_DOWN:
1854     case EL_BD_FIREFLY:
1855     case EL_BD_FIREFLY_RIGHT:
1856     case EL_BD_FIREFLY_UP:
1857     case EL_BD_FIREFLY_LEFT:
1858     case EL_BD_FIREFLY_DOWN:
1859     case EL_PACMAN_RIGHT:
1860     case EL_PACMAN_UP:
1861     case EL_PACMAN_LEFT:
1862     case EL_PACMAN_DOWN:
1863     case EL_YAMYAM:
1864     case EL_YAMYAM_LEFT:
1865     case EL_YAMYAM_RIGHT:
1866     case EL_YAMYAM_UP:
1867     case EL_YAMYAM_DOWN:
1868     case EL_DARK_YAMYAM:
1869     case EL_ROBOT:
1870     case EL_PACMAN:
1871     case EL_SP_SNIKSNAK:
1872     case EL_SP_ELECTRON:
1873     case EL_MOLE:
1874     case EL_MOLE_LEFT:
1875     case EL_MOLE_RIGHT:
1876     case EL_MOLE_UP:
1877     case EL_MOLE_DOWN:
1878       InitMovDir(x, y);
1879       break;
1880
1881     case EL_AMOEBA_FULL:
1882     case EL_BD_AMOEBA:
1883       InitAmoebaNr(x, y);
1884       break;
1885
1886     case EL_AMOEBA_DROP:
1887       if (y == lev_fieldy - 1)
1888       {
1889         Feld[x][y] = EL_AMOEBA_GROWING;
1890         Store[x][y] = EL_AMOEBA_WET;
1891       }
1892       break;
1893
1894     case EL_DYNAMITE_ACTIVE:
1895     case EL_SP_DISK_RED_ACTIVE:
1896     case EL_DYNABOMB_PLAYER_1_ACTIVE:
1897     case EL_DYNABOMB_PLAYER_2_ACTIVE:
1898     case EL_DYNABOMB_PLAYER_3_ACTIVE:
1899     case EL_DYNABOMB_PLAYER_4_ACTIVE:
1900       MovDelay[x][y] = 96;
1901       break;
1902
1903     case EL_EM_DYNAMITE_ACTIVE:
1904       MovDelay[x][y] = 32;
1905       break;
1906
1907     case EL_LAMP:
1908       local_player->lights_still_needed++;
1909       break;
1910
1911     case EL_PENGUIN:
1912       local_player->friends_still_needed++;
1913       break;
1914
1915     case EL_PIG:
1916     case EL_DRAGON:
1917       GfxDir[x][y] = MovDir[x][y] = 1 << RND(4);
1918       break;
1919
1920     case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
1921     case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
1922     case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
1923     case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
1924     case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
1925     case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
1926     case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
1927     case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
1928     case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
1929     case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
1930     case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
1931     case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
1932       if (init_game)
1933       {
1934         int belt_nr = getBeltNrFromBeltSwitchElement(Feld[x][y]);
1935         int belt_dir = getBeltDirFromBeltSwitchElement(Feld[x][y]);
1936         int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(Feld[x][y]);
1937
1938         if (game.belt_dir_nr[belt_nr] == 3)     // initial value
1939         {
1940           game.belt_dir[belt_nr] = belt_dir;
1941           game.belt_dir_nr[belt_nr] = belt_dir_nr;
1942         }
1943         else    // more than one switch -- set it like the first switch
1944         {
1945           Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
1946         }
1947       }
1948       break;
1949
1950     case EL_LIGHT_SWITCH_ACTIVE:
1951       if (init_game)
1952         game.light_time_left = level.time_light * FRAMES_PER_SECOND;
1953       break;
1954
1955     case EL_INVISIBLE_STEELWALL:
1956     case EL_INVISIBLE_WALL:
1957     case EL_INVISIBLE_SAND:
1958       if (game.light_time_left > 0 ||
1959           game.lenses_time_left > 0)
1960         Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
1961       break;
1962
1963     case EL_EMC_MAGIC_BALL:
1964       if (game.ball_state)
1965         Feld[x][y] = EL_EMC_MAGIC_BALL_ACTIVE;
1966       break;
1967
1968     case EL_EMC_MAGIC_BALL_SWITCH:
1969       if (game.ball_state)
1970         Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
1971       break;
1972
1973     case EL_TRIGGER_PLAYER:
1974     case EL_TRIGGER_ELEMENT:
1975     case EL_TRIGGER_CE_VALUE:
1976     case EL_TRIGGER_CE_SCORE:
1977     case EL_SELF:
1978     case EL_ANY_ELEMENT:
1979     case EL_CURRENT_CE_VALUE:
1980     case EL_CURRENT_CE_SCORE:
1981     case EL_PREV_CE_1:
1982     case EL_PREV_CE_2:
1983     case EL_PREV_CE_3:
1984     case EL_PREV_CE_4:
1985     case EL_PREV_CE_5:
1986     case EL_PREV_CE_6:
1987     case EL_PREV_CE_7:
1988     case EL_PREV_CE_8:
1989     case EL_NEXT_CE_1:
1990     case EL_NEXT_CE_2:
1991     case EL_NEXT_CE_3:
1992     case EL_NEXT_CE_4:
1993     case EL_NEXT_CE_5:
1994     case EL_NEXT_CE_6:
1995     case EL_NEXT_CE_7:
1996     case EL_NEXT_CE_8:
1997       // reference elements should not be used on the playfield
1998       Feld[x][y] = EL_EMPTY;
1999       break;
2000
2001     default:
2002       if (IS_CUSTOM_ELEMENT(element))
2003       {
2004         if (CAN_MOVE(element))
2005           InitMovDir(x, y);
2006
2007         if (!element_info[element].use_last_ce_value || init_game)
2008           CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
2009       }
2010       else if (IS_GROUP_ELEMENT(element))
2011       {
2012         Feld[x][y] = GetElementFromGroupElement(element);
2013
2014         InitField(x, y, init_game);
2015       }
2016
2017       break;
2018   }
2019
2020   if (!init_game)
2021     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
2022 }
2023
2024 static void InitField_WithBug1(int x, int y, boolean init_game)
2025 {
2026   InitField(x, y, init_game);
2027
2028   // not needed to call InitMovDir() -- already done by InitField()!
2029   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2030       CAN_MOVE(Feld[x][y]))
2031     InitMovDir(x, y);
2032 }
2033
2034 static void InitField_WithBug2(int x, int y, boolean init_game)
2035 {
2036   int old_element = Feld[x][y];
2037
2038   InitField(x, y, init_game);
2039
2040   // not needed to call InitMovDir() -- already done by InitField()!
2041   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2042       CAN_MOVE(old_element) &&
2043       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
2044     InitMovDir(x, y);
2045
2046   /* this case is in fact a combination of not less than three bugs:
2047      first, it calls InitMovDir() for elements that can move, although this is
2048      already done by InitField(); then, it checks the element that was at this
2049      field _before_ the call to InitField() (which can change it); lastly, it
2050      was not called for "mole with direction" elements, which were treated as
2051      "cannot move" due to (fixed) wrong element initialization in "src/init.c"
2052   */
2053 }
2054
2055 static int get_key_element_from_nr(int key_nr)
2056 {
2057   int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
2058                           level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2059                           EL_EM_KEY_1 : EL_KEY_1);
2060
2061   return key_base_element + key_nr;
2062 }
2063
2064 static int get_next_dropped_element(struct PlayerInfo *player)
2065 {
2066   return (player->inventory_size > 0 ?
2067           player->inventory_element[player->inventory_size - 1] :
2068           player->inventory_infinite_element != EL_UNDEFINED ?
2069           player->inventory_infinite_element :
2070           player->dynabombs_left > 0 ?
2071           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
2072           EL_UNDEFINED);
2073 }
2074
2075 static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
2076 {
2077   // pos >= 0: get element from bottom of the stack;
2078   // pos <  0: get element from top of the stack
2079
2080   if (pos < 0)
2081   {
2082     int min_inventory_size = -pos;
2083     int inventory_pos = player->inventory_size - min_inventory_size;
2084     int min_dynabombs_left = min_inventory_size - player->inventory_size;
2085
2086     return (player->inventory_size >= min_inventory_size ?
2087             player->inventory_element[inventory_pos] :
2088             player->inventory_infinite_element != EL_UNDEFINED ?
2089             player->inventory_infinite_element :
2090             player->dynabombs_left >= min_dynabombs_left ?
2091             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2092             EL_UNDEFINED);
2093   }
2094   else
2095   {
2096     int min_dynabombs_left = pos + 1;
2097     int min_inventory_size = pos + 1 - player->dynabombs_left;
2098     int inventory_pos = pos - player->dynabombs_left;
2099
2100     return (player->inventory_infinite_element != EL_UNDEFINED ?
2101             player->inventory_infinite_element :
2102             player->dynabombs_left >= min_dynabombs_left ?
2103             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2104             player->inventory_size >= min_inventory_size ?
2105             player->inventory_element[inventory_pos] :
2106             EL_UNDEFINED);
2107   }
2108 }
2109
2110 static int compareGamePanelOrderInfo(const void *object1, const void *object2)
2111 {
2112   const struct GamePanelOrderInfo *gpo1 = (struct GamePanelOrderInfo *)object1;
2113   const struct GamePanelOrderInfo *gpo2 = (struct GamePanelOrderInfo *)object2;
2114   int compare_result;
2115
2116   if (gpo1->sort_priority != gpo2->sort_priority)
2117     compare_result = gpo1->sort_priority - gpo2->sort_priority;
2118   else
2119     compare_result = gpo1->nr - gpo2->nr;
2120
2121   return compare_result;
2122 }
2123
2124 int getPlayerInventorySize(int player_nr)
2125 {
2126   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2127     return level.native_em_level->ply[player_nr]->dynamite;
2128   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2129     return level.native_sp_level->game_sp->red_disk_count;
2130   else
2131     return stored_player[player_nr].inventory_size;
2132 }
2133
2134 static void InitGameControlValues(void)
2135 {
2136   int i;
2137
2138   for (i = 0; game_panel_controls[i].nr != -1; i++)
2139   {
2140     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2141     struct GamePanelOrderInfo *gpo = &game_panel_order[i];
2142     struct TextPosInfo *pos = gpc->pos;
2143     int nr = gpc->nr;
2144     int type = gpc->type;
2145
2146     if (nr != i)
2147     {
2148       Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i);
2149       Error(ERR_EXIT, "this should not happen -- please debug");
2150     }
2151
2152     // force update of game controls after initialization
2153     gpc->value = gpc->last_value = -1;
2154     gpc->frame = gpc->last_frame = -1;
2155     gpc->gfx_frame = -1;
2156
2157     // determine panel value width for later calculation of alignment
2158     if (type == TYPE_INTEGER || type == TYPE_STRING)
2159     {
2160       pos->width = pos->size * getFontWidth(pos->font);
2161       pos->height = getFontHeight(pos->font);
2162     }
2163     else if (type == TYPE_ELEMENT)
2164     {
2165       pos->width = pos->size;
2166       pos->height = pos->size;
2167     }
2168
2169     // fill structure for game panel draw order
2170     gpo->nr = gpc->nr;
2171     gpo->sort_priority = pos->sort_priority;
2172   }
2173
2174   // sort game panel controls according to sort_priority and control number
2175   qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
2176         sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
2177 }
2178
2179 static void UpdatePlayfieldElementCount(void)
2180 {
2181   boolean use_element_count = FALSE;
2182   int i, j, x, y;
2183
2184   // first check if it is needed at all to calculate playfield element count
2185   for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++)
2186     if (!PANEL_DEACTIVATED(game_panel_controls[i].pos))
2187       use_element_count = TRUE;
2188
2189   if (!use_element_count)
2190     return;
2191
2192   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2193     element_info[i].element_count = 0;
2194
2195   SCAN_PLAYFIELD(x, y)
2196   {
2197     element_info[Feld[x][y]].element_count++;
2198   }
2199
2200   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
2201     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2202       if (IS_IN_GROUP(j, i))
2203         element_info[EL_GROUP_START + i].element_count +=
2204           element_info[j].element_count;
2205 }
2206
2207 static void UpdateGameControlValues(void)
2208 {
2209   int i, k;
2210   int time = (game.LevelSolved ?
2211               game.LevelSolved_CountingTime :
2212               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2213               level.native_em_level->lev->time :
2214               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2215               level.native_sp_level->game_sp->time_played :
2216               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2217               game_mm.energy_left :
2218               game.no_time_limit ? TimePlayed : TimeLeft);
2219   int score = (game.LevelSolved ?
2220                game.LevelSolved_CountingScore :
2221                level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2222                level.native_em_level->lev->score :
2223                level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2224                level.native_sp_level->game_sp->score :
2225                level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2226                game_mm.score :
2227                local_player->score);
2228   int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2229               level.native_em_level->lev->required :
2230               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2231               level.native_sp_level->game_sp->infotrons_still_needed :
2232               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2233               game_mm.kettles_still_needed :
2234               local_player->gems_still_needed);
2235   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2236                      level.native_em_level->lev->required > 0 :
2237                      level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2238                      level.native_sp_level->game_sp->infotrons_still_needed > 0 :
2239                      level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2240                      game_mm.kettles_still_needed > 0 ||
2241                      game_mm.lights_still_needed > 0 :
2242                      local_player->gems_still_needed > 0 ||
2243                      local_player->sokoban_fields_still_needed > 0 ||
2244                      local_player->sokoban_objects_still_needed > 0 ||
2245                      local_player->lights_still_needed > 0);
2246   int health = (game.LevelSolved ?
2247                 game.LevelSolved_CountingHealth :
2248                 level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2249                 MM_HEALTH(game_mm.laser_overload_value) :
2250                 local_player->health);
2251
2252   UpdatePlayfieldElementCount();
2253
2254   // update game panel control values
2255
2256   // used instead of "level_nr" (for network games)
2257   game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = levelset.level_nr;
2258   game_panel_controls[GAME_PANEL_GEMS].value = gems;
2259
2260   game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
2261   for (i = 0; i < MAX_NUM_KEYS; i++)
2262     game_panel_controls[GAME_PANEL_KEY_1 + i].value = EL_EMPTY;
2263   game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_EMPTY;
2264   game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value = 0;
2265
2266   if (game.centered_player_nr == -1)
2267   {
2268     for (i = 0; i < MAX_PLAYERS; i++)
2269     {
2270       // only one player in Supaplex game engine
2271       if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
2272         break;
2273
2274       for (k = 0; k < MAX_NUM_KEYS; k++)
2275       {
2276         if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2277         {
2278           if (level.native_em_level->ply[i]->keys & (1 << k))
2279             game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2280               get_key_element_from_nr(k);
2281         }
2282         else if (stored_player[i].key[k])
2283           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2284             get_key_element_from_nr(k);
2285       }
2286
2287       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2288         getPlayerInventorySize(i);
2289
2290       if (stored_player[i].num_white_keys > 0)
2291         game_panel_controls[GAME_PANEL_KEY_WHITE].value =
2292           EL_DC_KEY_WHITE;
2293
2294       game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2295         stored_player[i].num_white_keys;
2296     }
2297   }
2298   else
2299   {
2300     int player_nr = game.centered_player_nr;
2301
2302     for (k = 0; k < MAX_NUM_KEYS; k++)
2303     {
2304       if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2305       {
2306         if (level.native_em_level->ply[player_nr]->keys & (1 << k))
2307           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2308             get_key_element_from_nr(k);
2309       }
2310       else if (stored_player[player_nr].key[k])
2311         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2312           get_key_element_from_nr(k);
2313     }
2314
2315     game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2316       getPlayerInventorySize(player_nr);
2317
2318     if (stored_player[player_nr].num_white_keys > 0)
2319       game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
2320
2321     game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2322       stored_player[player_nr].num_white_keys;
2323   }
2324
2325   for (i = 0; i < NUM_PANEL_INVENTORY; i++)
2326   {
2327     game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value =
2328       get_inventory_element_from_pos(local_player, i);
2329     game_panel_controls[GAME_PANEL_INVENTORY_LAST_1 + i].value =
2330       get_inventory_element_from_pos(local_player, -i - 1);
2331   }
2332
2333   game_panel_controls[GAME_PANEL_SCORE].value = score;
2334   game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
2335
2336   game_panel_controls[GAME_PANEL_TIME].value = time;
2337
2338   game_panel_controls[GAME_PANEL_TIME_HH].value = time / 3600;
2339   game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
2340   game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
2341
2342   if (level.time == 0)
2343     game_panel_controls[GAME_PANEL_TIME_ANIM].value = 100;
2344   else
2345     game_panel_controls[GAME_PANEL_TIME_ANIM].value = time * 100 / level.time;
2346
2347   game_panel_controls[GAME_PANEL_HEALTH].value = health;
2348   game_panel_controls[GAME_PANEL_HEALTH_ANIM].value = health;
2349
2350   game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter;
2351
2352   game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
2353     (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
2354      EL_EMPTY);
2355   game_panel_controls[GAME_PANEL_SHIELD_NORMAL_TIME].value =
2356     local_player->shield_normal_time_left;
2357   game_panel_controls[GAME_PANEL_SHIELD_DEADLY].value =
2358     (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
2359      EL_EMPTY);
2360   game_panel_controls[GAME_PANEL_SHIELD_DEADLY_TIME].value =
2361     local_player->shield_deadly_time_left;
2362
2363   game_panel_controls[GAME_PANEL_EXIT].value =
2364     (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
2365
2366   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL].value =
2367     (game.ball_state ? EL_EMC_MAGIC_BALL_ACTIVE : EL_EMC_MAGIC_BALL);
2368   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL_SWITCH].value =
2369     (game.ball_state ? EL_EMC_MAGIC_BALL_SWITCH_ACTIVE :
2370      EL_EMC_MAGIC_BALL_SWITCH);
2371
2372   game_panel_controls[GAME_PANEL_LIGHT_SWITCH].value =
2373     (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
2374   game_panel_controls[GAME_PANEL_LIGHT_SWITCH_TIME].value =
2375     game.light_time_left;
2376
2377   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH].value =
2378     (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
2379   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH_TIME].value =
2380     game.timegate_time_left;
2381
2382   game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
2383     EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
2384
2385   game_panel_controls[GAME_PANEL_EMC_LENSES].value =
2386     (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
2387   game_panel_controls[GAME_PANEL_EMC_LENSES_TIME].value =
2388     game.lenses_time_left;
2389
2390   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER].value =
2391     (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
2392   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER_TIME].value =
2393     game.magnify_time_left;
2394
2395   game_panel_controls[GAME_PANEL_BALLOON_SWITCH].value =
2396     (game.wind_direction == MV_LEFT  ? EL_BALLOON_SWITCH_LEFT  :
2397      game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
2398      game.wind_direction == MV_UP    ? EL_BALLOON_SWITCH_UP    :
2399      game.wind_direction == MV_DOWN  ? EL_BALLOON_SWITCH_DOWN  :
2400      EL_BALLOON_SWITCH_NONE);
2401
2402   game_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
2403     local_player->dynabomb_count;
2404   game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
2405     local_player->dynabomb_size;
2406   game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
2407     (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
2408
2409   game_panel_controls[GAME_PANEL_PENGUINS].value =
2410     local_player->friends_still_needed;
2411
2412   game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
2413     local_player->sokoban_objects_still_needed;
2414   game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
2415     local_player->sokoban_fields_still_needed;
2416
2417   game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
2418     (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
2419
2420   for (i = 0; i < NUM_BELTS; i++)
2421   {
2422     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1 + i].value =
2423       (game.belt_dir[i] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
2424        EL_CONVEYOR_BELT_1_MIDDLE) + i;
2425     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH + i].value =
2426       getBeltSwitchElementFromBeltNrAndBeltDir(i, game.belt_dir[i]);
2427   }
2428
2429   game_panel_controls[GAME_PANEL_MAGIC_WALL].value =
2430     (game.magic_wall_active ? EL_MAGIC_WALL_ACTIVE : EL_MAGIC_WALL);
2431   game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
2432     game.magic_wall_time_left;
2433
2434   game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
2435     local_player->gravity;
2436
2437   for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
2438     game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
2439
2440   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2441     game_panel_controls[GAME_PANEL_ELEMENT_1 + i].value =
2442       (IS_DRAWABLE_ELEMENT(game.panel.element[i].id) ?
2443        game.panel.element[i].id : EL_UNDEFINED);
2444
2445   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2446     game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value =
2447       (IS_VALID_ELEMENT(game.panel.element_count[i].id) ?
2448        element_info[game.panel.element_count[i].id].element_count : 0);
2449
2450   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2451     game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value =
2452       (IS_CUSTOM_ELEMENT(game.panel.ce_score[i].id) ?
2453        element_info[game.panel.ce_score[i].id].collect_score : 0);
2454
2455   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2456     game_panel_controls[GAME_PANEL_CE_SCORE_1_ELEMENT + i].value =
2457       (IS_CUSTOM_ELEMENT(game.panel.ce_score_element[i].id) ?
2458        element_info[game.panel.ce_score_element[i].id].collect_score :
2459        EL_UNDEFINED);
2460
2461   game_panel_controls[GAME_PANEL_PLAYER_NAME].value = 0;
2462   game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
2463   game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
2464
2465   // update game panel control frames
2466
2467   for (i = 0; game_panel_controls[i].nr != -1; i++)
2468   {
2469     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2470
2471     if (gpc->type == TYPE_ELEMENT)
2472     {
2473       if (gpc->value != EL_UNDEFINED && gpc->value != EL_EMPTY)
2474       {
2475         int last_anim_random_frame = gfx.anim_random_frame;
2476         int element = gpc->value;
2477         int graphic = el2panelimg(element);
2478
2479         if (gpc->value != gpc->last_value)
2480         {
2481           gpc->gfx_frame = 0;
2482           gpc->gfx_random = INIT_GFX_RANDOM();
2483         }
2484         else
2485         {
2486           gpc->gfx_frame++;
2487
2488           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2489               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2490             gpc->gfx_random = INIT_GFX_RANDOM();
2491         }
2492
2493         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2494           gfx.anim_random_frame = gpc->gfx_random;
2495
2496         if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
2497           gpc->gfx_frame = element_info[element].collect_score;
2498
2499         gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
2500                                               gpc->gfx_frame);
2501
2502         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2503           gfx.anim_random_frame = last_anim_random_frame;
2504       }
2505     }
2506     else if (gpc->type == TYPE_GRAPHIC)
2507     {
2508       if (gpc->graphic != IMG_UNDEFINED)
2509       {
2510         int last_anim_random_frame = gfx.anim_random_frame;
2511         int graphic = gpc->graphic;
2512
2513         if (gpc->value != gpc->last_value)
2514         {
2515           gpc->gfx_frame = 0;
2516           gpc->gfx_random = INIT_GFX_RANDOM();
2517         }
2518         else
2519         {
2520           gpc->gfx_frame++;
2521
2522           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2523               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2524             gpc->gfx_random = INIT_GFX_RANDOM();
2525         }
2526
2527         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2528           gfx.anim_random_frame = gpc->gfx_random;
2529
2530         gpc->frame = getGraphicAnimationFrame(graphic, gpc->gfx_frame);
2531
2532         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2533           gfx.anim_random_frame = last_anim_random_frame;
2534       }
2535     }
2536   }
2537 }
2538
2539 static void DisplayGameControlValues(void)
2540 {
2541   boolean redraw_panel = FALSE;
2542   int i;
2543
2544   for (i = 0; game_panel_controls[i].nr != -1; i++)
2545   {
2546     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2547
2548     if (PANEL_DEACTIVATED(gpc->pos))
2549       continue;
2550
2551     if (gpc->value == gpc->last_value &&
2552         gpc->frame == gpc->last_frame)
2553       continue;
2554
2555     redraw_panel = TRUE;
2556   }
2557
2558   if (!redraw_panel)
2559     return;
2560
2561   // copy default game door content to main double buffer
2562
2563   // !!! CHECK AGAIN !!!
2564   SetPanelBackground();
2565   // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
2566   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2567
2568   // redraw game control buttons
2569   RedrawGameButtons();
2570
2571   SetGameStatus(GAME_MODE_PSEUDO_PANEL);
2572
2573   for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
2574   {
2575     int nr = game_panel_order[i].nr;
2576     struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
2577     struct TextPosInfo *pos = gpc->pos;
2578     int type = gpc->type;
2579     int value = gpc->value;
2580     int frame = gpc->frame;
2581     int size = pos->size;
2582     int font = pos->font;
2583     boolean draw_masked = pos->draw_masked;
2584     int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_OPAQUE);
2585
2586     if (PANEL_DEACTIVATED(pos))
2587       continue;
2588
2589     gpc->last_value = value;
2590     gpc->last_frame = frame;
2591
2592     if (type == TYPE_INTEGER)
2593     {
2594       if (nr == GAME_PANEL_LEVEL_NUMBER ||
2595           nr == GAME_PANEL_TIME)
2596       {
2597         boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
2598
2599         if (use_dynamic_size)           // use dynamic number of digits
2600         {
2601           int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
2602           int size1 = (nr == GAME_PANEL_LEVEL_NUMBER ? 2 : 3);
2603           int size2 = size1 + 1;
2604           int font1 = pos->font;
2605           int font2 = pos->font_alt;
2606
2607           size = (value < value_change ? size1 : size2);
2608           font = (value < value_change ? font1 : font2);
2609         }
2610       }
2611
2612       // correct text size if "digits" is zero or less
2613       if (size <= 0)
2614         size = strlen(int2str(value, size));
2615
2616       // dynamically correct text alignment
2617       pos->width = size * getFontWidth(font);
2618
2619       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2620                   int2str(value, size), font, mask_mode);
2621     }
2622     else if (type == TYPE_ELEMENT)
2623     {
2624       int element, graphic;
2625       Bitmap *src_bitmap;
2626       int src_x, src_y;
2627       int width, height;
2628       int dst_x = PANEL_XPOS(pos);
2629       int dst_y = PANEL_YPOS(pos);
2630
2631       if (value != EL_UNDEFINED && value != EL_EMPTY)
2632       {
2633         element = value;
2634         graphic = el2panelimg(value);
2635
2636         // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
2637
2638         if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
2639           size = TILESIZE;
2640
2641         getSizedGraphicSource(graphic, frame, size, &src_bitmap,
2642                               &src_x, &src_y);
2643
2644         width  = graphic_info[graphic].width  * size / TILESIZE;
2645         height = graphic_info[graphic].height * size / TILESIZE;
2646
2647         if (draw_masked)
2648           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2649                            dst_x, dst_y);
2650         else
2651           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2652                      dst_x, dst_y);
2653       }
2654     }
2655     else if (type == TYPE_GRAPHIC)
2656     {
2657       int graphic        = gpc->graphic;
2658       int graphic_active = gpc->graphic_active;
2659       Bitmap *src_bitmap;
2660       int src_x, src_y;
2661       int width, height;
2662       int dst_x = PANEL_XPOS(pos);
2663       int dst_y = PANEL_YPOS(pos);
2664       boolean skip = (pos->class == get_hash_from_key("mm_engine_only") &&
2665                       level.game_engine_type != GAME_ENGINE_TYPE_MM);
2666
2667       if (graphic != IMG_UNDEFINED && !skip)
2668       {
2669         if (pos->style == STYLE_REVERSE)
2670           value = 100 - value;
2671
2672         getGraphicSource(graphic_active, frame, &src_bitmap, &src_x, &src_y);
2673
2674         if (pos->direction & MV_HORIZONTAL)
2675         {
2676           width  = graphic_info[graphic_active].width * value / 100;
2677           height = graphic_info[graphic_active].height;
2678
2679           if (pos->direction == MV_LEFT)
2680           {
2681             src_x += graphic_info[graphic_active].width - width;
2682             dst_x += graphic_info[graphic_active].width - width;
2683           }
2684         }
2685         else
2686         {
2687           width  = graphic_info[graphic_active].width;
2688           height = graphic_info[graphic_active].height * value / 100;
2689
2690           if (pos->direction == MV_UP)
2691           {
2692             src_y += graphic_info[graphic_active].height - height;
2693             dst_y += graphic_info[graphic_active].height - height;
2694           }
2695         }
2696
2697         if (draw_masked)
2698           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2699                            dst_x, dst_y);
2700         else
2701           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2702                      dst_x, dst_y);
2703
2704         getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2705
2706         if (pos->direction & MV_HORIZONTAL)
2707         {
2708           if (pos->direction == MV_RIGHT)
2709           {
2710             src_x += width;
2711             dst_x += width;
2712           }
2713           else
2714           {
2715             dst_x = PANEL_XPOS(pos);
2716           }
2717
2718           width = graphic_info[graphic].width - width;
2719         }
2720         else
2721         {
2722           if (pos->direction == MV_DOWN)
2723           {
2724             src_y += height;
2725             dst_y += height;
2726           }
2727           else
2728           {
2729             dst_y = PANEL_YPOS(pos);
2730           }
2731
2732           height = graphic_info[graphic].height - height;
2733         }
2734
2735         if (draw_masked)
2736           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2737                            dst_x, dst_y);
2738         else
2739           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2740                      dst_x, dst_y);
2741       }
2742     }
2743     else if (type == TYPE_STRING)
2744     {
2745       boolean active = (value != 0);
2746       char *state_normal = "off";
2747       char *state_active = "on";
2748       char *state = (active ? state_active : state_normal);
2749       char *s = (nr == GAME_PANEL_GRAVITY_STATE ? state :
2750                  nr == GAME_PANEL_PLAYER_NAME   ? setup.player_name :
2751                  nr == GAME_PANEL_LEVEL_NAME    ? level.name :
2752                  nr == GAME_PANEL_LEVEL_AUTHOR  ? level.author : NULL);
2753
2754       if (nr == GAME_PANEL_GRAVITY_STATE)
2755       {
2756         int font1 = pos->font;          // (used for normal state)
2757         int font2 = pos->font_alt;      // (used for active state)
2758
2759         font = (active ? font2 : font1);
2760       }
2761
2762       if (s != NULL)
2763       {
2764         char *s_cut;
2765
2766         if (size <= 0)
2767         {
2768           // don't truncate output if "chars" is zero or less
2769           size = strlen(s);
2770
2771           // dynamically correct text alignment
2772           pos->width = size * getFontWidth(font);
2773         }
2774
2775         s_cut = getStringCopyN(s, size);
2776
2777         DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2778                     s_cut, font, mask_mode);
2779
2780         free(s_cut);
2781       }
2782     }
2783
2784     redraw_mask |= REDRAW_DOOR_1;
2785   }
2786
2787   SetGameStatus(GAME_MODE_PLAYING);
2788 }
2789
2790 void UpdateAndDisplayGameControlValues(void)
2791 {
2792   if (tape.deactivate_display)
2793     return;
2794
2795   UpdateGameControlValues();
2796   DisplayGameControlValues();
2797 }
2798
2799 #if 0
2800 static void UpdateGameDoorValues(void)
2801 {
2802   UpdateGameControlValues();
2803 }
2804 #endif
2805
2806 void DrawGameDoorValues(void)
2807 {
2808   DisplayGameControlValues();
2809 }
2810
2811
2812 // ============================================================================
2813 // InitGameEngine()
2814 // ----------------------------------------------------------------------------
2815 // initialize game engine due to level / tape version number
2816 // ============================================================================
2817
2818 static void InitGameEngine(void)
2819 {
2820   int i, j, k, l, x, y;
2821
2822   // set game engine from tape file when re-playing, else from level file
2823   game.engine_version = (tape.playing ? tape.engine_version :
2824                          level.game_version);
2825
2826   // set single or multi-player game mode (needed for re-playing tapes)
2827   game.team_mode = setup.team_mode;
2828
2829   if (tape.playing)
2830   {
2831     int num_players = 0;
2832
2833     for (i = 0; i < MAX_PLAYERS; i++)
2834       if (tape.player_participates[i])
2835         num_players++;
2836
2837     // multi-player tapes contain input data for more than one player
2838     game.team_mode = (num_players > 1);
2839   }
2840
2841   // --------------------------------------------------------------------------
2842   // set flags for bugs and changes according to active game engine version
2843   // --------------------------------------------------------------------------
2844
2845   /*
2846     Summary of bugfix/change:
2847     Fixed handling for custom elements that change when pushed by the player.
2848
2849     Fixed/changed in version:
2850     3.1.0
2851
2852     Description:
2853     Before 3.1.0, custom elements that "change when pushing" changed directly
2854     after the player started pushing them (until then handled in "DigField()").
2855     Since 3.1.0, these custom elements are not changed until the "pushing"
2856     move of the element is finished (now handled in "ContinueMoving()").
2857
2858     Affected levels/tapes:
2859     The first condition is generally needed for all levels/tapes before version
2860     3.1.0, which might use the old behaviour before it was changed; known tapes
2861     that are affected are some tapes from the level set "Walpurgis Gardens" by
2862     Jamie Cullen.
2863     The second condition is an exception from the above case and is needed for
2864     the special case of tapes recorded with game (not engine!) version 3.1.0 or
2865     above (including some development versions of 3.1.0), but before it was
2866     known that this change would break tapes like the above and was fixed in
2867     3.1.1, so that the changed behaviour was active although the engine version
2868     while recording maybe was before 3.1.0. There is at least one tape that is
2869     affected by this exception, which is the tape for the one-level set "Bug
2870     Machine" by Juergen Bonhagen.
2871   */
2872
2873   game.use_change_when_pushing_bug =
2874     (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2875      !(tape.playing &&
2876        tape.game_version >= VERSION_IDENT(3,1,0,0) &&
2877        tape.game_version <  VERSION_IDENT(3,1,1,0)));
2878
2879   /*
2880     Summary of bugfix/change:
2881     Fixed handling for blocking the field the player leaves when moving.
2882
2883     Fixed/changed in version:
2884     3.1.1
2885
2886     Description:
2887     Before 3.1.1, when "block last field when moving" was enabled, the field
2888     the player is leaving when moving was blocked for the time of the move,
2889     and was directly unblocked afterwards. This resulted in the last field
2890     being blocked for exactly one less than the number of frames of one player
2891     move. Additionally, even when blocking was disabled, the last field was
2892     blocked for exactly one frame.
2893     Since 3.1.1, due to changes in player movement handling, the last field
2894     is not blocked at all when blocking is disabled. When blocking is enabled,
2895     the last field is blocked for exactly the number of frames of one player
2896     move. Additionally, if the player is Murphy, the hero of Supaplex, the
2897     last field is blocked for exactly one more than the number of frames of
2898     one player move.
2899
2900     Affected levels/tapes:
2901     (!!! yet to be determined -- probably many !!!)
2902   */
2903
2904   game.use_block_last_field_bug =
2905     (game.engine_version < VERSION_IDENT(3,1,1,0));
2906
2907   game_em.use_single_button =
2908     (game.engine_version > VERSION_IDENT(4,0,0,2));
2909
2910   game_em.use_snap_key_bug =
2911     (game.engine_version < VERSION_IDENT(4,0,1,0));
2912
2913   // --------------------------------------------------------------------------
2914
2915   // set maximal allowed number of custom element changes per game frame
2916   game.max_num_changes_per_frame = 1;
2917
2918   // default scan direction: scan playfield from top/left to bottom/right
2919   InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
2920
2921   // dynamically adjust element properties according to game engine version
2922   InitElementPropertiesEngine(game.engine_version);
2923
2924 #if 0
2925   printf("level %d: level version == %06d\n", level_nr, level.game_version);
2926   printf("          tape version == %06d [%s] [file: %06d]\n",
2927          tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
2928          tape.file_version);
2929   printf("       => game.engine_version == %06d\n", game.engine_version);
2930 #endif
2931
2932   // ---------- initialize player's initial move delay ------------------------
2933
2934   // dynamically adjust player properties according to level information
2935   for (i = 0; i < MAX_PLAYERS; i++)
2936     game.initial_move_delay_value[i] =
2937       get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
2938
2939   // dynamically adjust player properties according to game engine version
2940   for (i = 0; i < MAX_PLAYERS; i++)
2941     game.initial_move_delay[i] =
2942       (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
2943        game.initial_move_delay_value[i] : 0);
2944
2945   // ---------- initialize player's initial push delay ------------------------
2946
2947   // dynamically adjust player properties according to game engine version
2948   game.initial_push_delay_value =
2949     (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1);
2950
2951   // ---------- initialize changing elements ----------------------------------
2952
2953   // initialize changing elements information
2954   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2955   {
2956     struct ElementInfo *ei = &element_info[i];
2957
2958     // this pointer might have been changed in the level editor
2959     ei->change = &ei->change_page[0];
2960
2961     if (!IS_CUSTOM_ELEMENT(i))
2962     {
2963       ei->change->target_element = EL_EMPTY_SPACE;
2964       ei->change->delay_fixed = 0;
2965       ei->change->delay_random = 0;
2966       ei->change->delay_frames = 1;
2967     }
2968
2969     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2970     {
2971       ei->has_change_event[j] = FALSE;
2972
2973       ei->event_page_nr[j] = 0;
2974       ei->event_page[j] = &ei->change_page[0];
2975     }
2976   }
2977
2978   // add changing elements from pre-defined list
2979   for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++)
2980   {
2981     struct ChangingElementInfo *ch_delay = &change_delay_list[i];
2982     struct ElementInfo *ei = &element_info[ch_delay->element];
2983
2984     ei->change->target_element       = ch_delay->target_element;
2985     ei->change->delay_fixed          = ch_delay->change_delay;
2986
2987     ei->change->pre_change_function  = ch_delay->pre_change_function;
2988     ei->change->change_function      = ch_delay->change_function;
2989     ei->change->post_change_function = ch_delay->post_change_function;
2990
2991     ei->change->can_change = TRUE;
2992     ei->change->can_change_or_has_action = TRUE;
2993
2994     ei->has_change_event[CE_DELAY] = TRUE;
2995
2996     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
2997     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
2998   }
2999
3000   // ---------- initialize internal run-time variables ------------------------
3001
3002   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3003   {
3004     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
3005
3006     for (j = 0; j < ei->num_change_pages; j++)
3007     {
3008       ei->change_page[j].can_change_or_has_action =
3009         (ei->change_page[j].can_change |
3010          ei->change_page[j].has_action);
3011     }
3012   }
3013
3014   // add change events from custom element configuration
3015   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3016   {
3017     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
3018
3019     for (j = 0; j < ei->num_change_pages; j++)
3020     {
3021       if (!ei->change_page[j].can_change_or_has_action)
3022         continue;
3023
3024       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
3025       {
3026         // only add event page for the first page found with this event
3027         if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
3028         {
3029           ei->has_change_event[k] = TRUE;
3030
3031           ei->event_page_nr[k] = j;
3032           ei->event_page[k] = &ei->change_page[j];
3033         }
3034       }
3035     }
3036   }
3037
3038   // ---------- initialize reference elements in change conditions ------------
3039
3040   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3041   {
3042     int element = EL_CUSTOM_START + i;
3043     struct ElementInfo *ei = &element_info[element];
3044
3045     for (j = 0; j < ei->num_change_pages; j++)
3046     {
3047       int trigger_element = ei->change_page[j].initial_trigger_element;
3048
3049       if (trigger_element >= EL_PREV_CE_8 &&
3050           trigger_element <= EL_NEXT_CE_8)
3051         trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
3052
3053       ei->change_page[j].trigger_element = trigger_element;
3054     }
3055   }
3056
3057   // ---------- initialize run-time trigger player and element ----------------
3058
3059   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3060   {
3061     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
3062
3063     for (j = 0; j < ei->num_change_pages; j++)
3064     {
3065       ei->change_page[j].actual_trigger_element = EL_EMPTY;
3066       ei->change_page[j].actual_trigger_player = EL_EMPTY;
3067       ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
3068       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
3069       ei->change_page[j].actual_trigger_ce_value = 0;
3070       ei->change_page[j].actual_trigger_ce_score = 0;
3071     }
3072   }
3073
3074   // ---------- initialize trigger events -------------------------------------
3075
3076   // initialize trigger events information
3077   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3078     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
3079       trigger_events[i][j] = FALSE;
3080
3081   // add trigger events from element change event properties
3082   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3083   {
3084     struct ElementInfo *ei = &element_info[i];
3085
3086     for (j = 0; j < ei->num_change_pages; j++)
3087     {
3088       if (!ei->change_page[j].can_change_or_has_action)
3089         continue;
3090
3091       if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
3092       {
3093         int trigger_element = ei->change_page[j].trigger_element;
3094
3095         for (k = 0; k < NUM_CHANGE_EVENTS; k++)
3096         {
3097           if (ei->change_page[j].has_event[k])
3098           {
3099             if (IS_GROUP_ELEMENT(trigger_element))
3100             {
3101               struct ElementGroupInfo *group =
3102                 element_info[trigger_element].group;
3103
3104               for (l = 0; l < group->num_elements_resolved; l++)
3105                 trigger_events[group->element_resolved[l]][k] = TRUE;
3106             }
3107             else if (trigger_element == EL_ANY_ELEMENT)
3108               for (l = 0; l < MAX_NUM_ELEMENTS; l++)
3109                 trigger_events[l][k] = TRUE;
3110             else
3111               trigger_events[trigger_element][k] = TRUE;
3112           }
3113         }
3114       }
3115     }
3116   }
3117
3118   // ---------- initialize push delay -----------------------------------------
3119
3120   // initialize push delay values to default
3121   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3122   {
3123     if (!IS_CUSTOM_ELEMENT(i))
3124     {
3125       // set default push delay values (corrected since version 3.0.7-1)
3126       if (game.engine_version < VERSION_IDENT(3,0,7,1))
3127       {
3128         element_info[i].push_delay_fixed = 2;
3129         element_info[i].push_delay_random = 8;
3130       }
3131       else
3132       {
3133         element_info[i].push_delay_fixed = 8;
3134         element_info[i].push_delay_random = 8;
3135       }
3136     }
3137   }
3138
3139   // set push delay value for certain elements from pre-defined list
3140   for (i = 0; push_delay_list[i].element != EL_UNDEFINED; i++)
3141   {
3142     int e = push_delay_list[i].element;
3143
3144     element_info[e].push_delay_fixed  = push_delay_list[i].push_delay_fixed;
3145     element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
3146   }
3147
3148   // set push delay value for Supaplex elements for newer engine versions
3149   if (game.engine_version >= VERSION_IDENT(3,1,0,0))
3150   {
3151     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3152     {
3153       if (IS_SP_ELEMENT(i))
3154       {
3155         // set SP push delay to just enough to push under a falling zonk
3156         int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
3157
3158         element_info[i].push_delay_fixed  = delay;
3159         element_info[i].push_delay_random = 0;
3160       }
3161     }
3162   }
3163
3164   // ---------- initialize move stepsize --------------------------------------
3165
3166   // initialize move stepsize values to default
3167   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3168     if (!IS_CUSTOM_ELEMENT(i))
3169       element_info[i].move_stepsize = MOVE_STEPSIZE_NORMAL;
3170
3171   // set move stepsize value for certain elements from pre-defined list
3172   for (i = 0; move_stepsize_list[i].element != EL_UNDEFINED; i++)
3173   {
3174     int e = move_stepsize_list[i].element;
3175
3176     element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
3177   }
3178
3179   // ---------- initialize collect score --------------------------------------
3180
3181   // initialize collect score values for custom elements from initial value
3182   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3183     if (IS_CUSTOM_ELEMENT(i))
3184       element_info[i].collect_score = element_info[i].collect_score_initial;
3185
3186   // ---------- initialize collect count --------------------------------------
3187
3188   // initialize collect count values for non-custom elements
3189   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3190     if (!IS_CUSTOM_ELEMENT(i))
3191       element_info[i].collect_count_initial = 0;
3192
3193   // add collect count values for all elements from pre-defined list
3194   for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
3195     element_info[collect_count_list[i].element].collect_count_initial =
3196       collect_count_list[i].count;
3197
3198   // ---------- initialize access direction -----------------------------------
3199
3200   // initialize access direction values to default (access from every side)
3201   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3202     if (!IS_CUSTOM_ELEMENT(i))
3203       element_info[i].access_direction = MV_ALL_DIRECTIONS;
3204
3205   // set access direction value for certain elements from pre-defined list
3206   for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
3207     element_info[access_direction_list[i].element].access_direction =
3208       access_direction_list[i].direction;
3209
3210   // ---------- initialize explosion content ----------------------------------
3211   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3212   {
3213     if (IS_CUSTOM_ELEMENT(i))
3214       continue;
3215
3216     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
3217     {
3218       // (content for EL_YAMYAM set at run-time with game.yamyam_content_nr)
3219
3220       element_info[i].content.e[x][y] =
3221         (i == EL_PLAYER_1 ? EL_EMERALD_YELLOW :
3222          i == EL_PLAYER_2 ? EL_EMERALD_RED :
3223          i == EL_PLAYER_3 ? EL_EMERALD :
3224          i == EL_PLAYER_4 ? EL_EMERALD_PURPLE :
3225          i == EL_MOLE ? EL_EMERALD_RED :
3226          i == EL_PENGUIN ? EL_EMERALD_PURPLE :
3227          i == EL_BUG ? (x == 1 && y == 1 ? EL_DIAMOND : EL_EMERALD) :
3228          i == EL_BD_BUTTERFLY ? EL_BD_DIAMOND :
3229          i == EL_SP_ELECTRON ? EL_SP_INFOTRON :
3230          i == EL_AMOEBA_TO_DIAMOND ? level.amoeba_content :
3231          i == EL_WALL_EMERALD ? EL_EMERALD :
3232          i == EL_WALL_DIAMOND ? EL_DIAMOND :
3233          i == EL_WALL_BD_DIAMOND ? EL_BD_DIAMOND :
3234          i == EL_WALL_EMERALD_YELLOW ? EL_EMERALD_YELLOW :
3235          i == EL_WALL_EMERALD_RED ? EL_EMERALD_RED :
3236          i == EL_WALL_EMERALD_PURPLE ? EL_EMERALD_PURPLE :
3237          i == EL_WALL_PEARL ? EL_PEARL :
3238          i == EL_WALL_CRYSTAL ? EL_CRYSTAL :
3239          EL_EMPTY);
3240     }
3241   }
3242
3243   // ---------- initialize recursion detection --------------------------------
3244   recursion_loop_depth = 0;
3245   recursion_loop_detected = FALSE;
3246   recursion_loop_element = EL_UNDEFINED;
3247
3248   // ---------- initialize graphics engine ------------------------------------
3249   game.scroll_delay_value =
3250     (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
3251      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
3252   game.scroll_delay_value =
3253     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
3254
3255   // ---------- initialize game engine snapshots ------------------------------
3256   for (i = 0; i < MAX_PLAYERS; i++)
3257     game.snapshot.last_action[i] = 0;
3258   game.snapshot.changed_action = FALSE;
3259   game.snapshot.collected_item = FALSE;
3260   game.snapshot.mode =
3261     (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
3262      SNAPSHOT_MODE_EVERY_STEP :
3263      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
3264      SNAPSHOT_MODE_EVERY_MOVE :
3265      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
3266      SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
3267   game.snapshot.save_snapshot = FALSE;
3268
3269   // ---------- initialize level time for Supaplex engine ---------------------
3270   // Supaplex levels with time limit currently unsupported -- should be added
3271   if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3272     level.time = 0;
3273 }
3274
3275 static int get_num_special_action(int element, int action_first,
3276                                   int action_last)
3277 {
3278   int num_special_action = 0;
3279   int i, j;
3280
3281   for (i = action_first; i <= action_last; i++)
3282   {
3283     boolean found = FALSE;
3284
3285     for (j = 0; j < NUM_DIRECTIONS; j++)
3286       if (el_act_dir2img(element, i, j) !=
3287           el_act_dir2img(element, ACTION_DEFAULT, j))
3288         found = TRUE;
3289
3290     if (found)
3291       num_special_action++;
3292     else
3293       break;
3294   }
3295
3296   return num_special_action;
3297 }
3298
3299
3300 // ============================================================================
3301 // InitGame()
3302 // ----------------------------------------------------------------------------
3303 // initialize and start new game
3304 // ============================================================================
3305
3306 #if DEBUG_INIT_PLAYER
3307 static void DebugPrintPlayerStatus(char *message)
3308 {
3309   int i;
3310
3311   if (!options.debug)
3312     return;
3313
3314   printf("%s:\n", message);
3315
3316   for (i = 0; i < MAX_PLAYERS; i++)
3317   {
3318     struct PlayerInfo *player = &stored_player[i];
3319
3320     printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
3321            i + 1,
3322            player->present,
3323            player->connected,
3324            player->connected_locally,
3325            player->connected_network,
3326            player->active);
3327
3328     if (local_player == player)
3329       printf(" (local player)");
3330
3331     printf("\n");
3332   }
3333 }
3334 #endif
3335
3336 void InitGame(void)
3337 {
3338   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
3339   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
3340   int fade_mask = REDRAW_FIELD;
3341
3342   boolean emulate_bd = TRUE;    // unless non-BOULDERDASH elements found
3343   boolean emulate_sb = TRUE;    // unless non-SOKOBAN     elements found
3344   boolean emulate_sp = TRUE;    // unless non-SUPAPLEX    elements found
3345   int initial_move_dir = MV_DOWN;
3346   int i, j, x, y;
3347
3348   // required here to update video display before fading (FIX THIS)
3349   DrawMaskedBorder(REDRAW_DOOR_2);
3350
3351   if (!game.restart_level)
3352     CloseDoor(DOOR_CLOSE_1);
3353
3354   SetGameStatus(GAME_MODE_PLAYING);
3355
3356   if (level_editor_test_game)
3357     FadeSkipNextFadeIn();
3358   else
3359     FadeSetEnterScreen();
3360
3361   if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged())
3362     fade_mask = REDRAW_ALL;
3363
3364   FadeLevelSoundsAndMusic();
3365
3366   ExpireSoundLoops(TRUE);
3367
3368   FadeOut(fade_mask);
3369
3370   // needed if different viewport properties defined for playing
3371   ChangeViewportPropertiesIfNeeded();
3372
3373   ClearField();
3374
3375   DrawCompleteVideoDisplay();
3376
3377   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
3378
3379   InitGameEngine();
3380   InitGameControlValues();
3381
3382   // don't play tapes over network
3383   network_playing = (network.enabled && !tape.playing);
3384
3385   for (i = 0; i < MAX_PLAYERS; i++)
3386   {
3387     struct PlayerInfo *player = &stored_player[i];
3388
3389     player->index_nr = i;
3390     player->index_bit = (1 << i);
3391     player->element_nr = EL_PLAYER_1 + i;
3392
3393     player->present = FALSE;
3394     player->active = FALSE;
3395     player->mapped = FALSE;
3396
3397     player->killed = FALSE;
3398     player->reanimated = FALSE;
3399
3400     player->action = 0;
3401     player->effective_action = 0;
3402     player->programmed_action = 0;
3403
3404     player->mouse_action.lx = 0;
3405     player->mouse_action.ly = 0;
3406     player->mouse_action.button = 0;
3407     player->mouse_action.button_hint = 0;
3408
3409     player->effective_mouse_action.lx = 0;
3410     player->effective_mouse_action.ly = 0;
3411     player->effective_mouse_action.button = 0;
3412     player->effective_mouse_action.button_hint = 0;
3413
3414     player->score = 0;
3415     player->score_final = 0;
3416
3417     player->health = MAX_HEALTH;
3418     player->health_final = MAX_HEALTH;
3419
3420     player->gems_still_needed = level.gems_needed;
3421     player->sokoban_fields_still_needed = 0;
3422     player->sokoban_objects_still_needed = 0;
3423     player->lights_still_needed = 0;
3424     player->players_still_needed = 0;
3425     player->friends_still_needed = 0;
3426
3427     for (j = 0; j < MAX_NUM_KEYS; j++)
3428       player->key[j] = FALSE;
3429
3430     player->num_white_keys = 0;
3431
3432     player->dynabomb_count = 0;
3433     player->dynabomb_size = 1;
3434     player->dynabombs_left = 0;
3435     player->dynabomb_xl = FALSE;
3436
3437     player->MovDir = initial_move_dir;
3438     player->MovPos = 0;
3439     player->GfxPos = 0;
3440     player->GfxDir = initial_move_dir;
3441     player->GfxAction = ACTION_DEFAULT;
3442     player->Frame = 0;
3443     player->StepFrame = 0;
3444
3445     player->initial_element = player->element_nr;
3446     player->artwork_element =
3447       (level.use_artwork_element[i] ? level.artwork_element[i] :
3448        player->element_nr);
3449     player->use_murphy = FALSE;
3450
3451     player->block_last_field = FALSE;   // initialized in InitPlayerField()
3452     player->block_delay_adjustment = 0; // initialized in InitPlayerField()
3453
3454     player->gravity = level.initial_player_gravity[i];
3455
3456     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
3457
3458     player->actual_frame_counter = 0;
3459
3460     player->step_counter = 0;
3461
3462     player->last_move_dir = initial_move_dir;
3463
3464     player->is_active = FALSE;
3465
3466     player->is_waiting = FALSE;
3467     player->is_moving = FALSE;
3468     player->is_auto_moving = FALSE;
3469     player->is_digging = FALSE;
3470     player->is_snapping = FALSE;
3471     player->is_collecting = FALSE;
3472     player->is_pushing = FALSE;
3473     player->is_switching = FALSE;
3474     player->is_dropping = FALSE;
3475     player->is_dropping_pressed = FALSE;
3476
3477     player->is_bored = FALSE;
3478     player->is_sleeping = FALSE;
3479
3480     player->was_waiting = TRUE;
3481     player->was_moving = FALSE;
3482     player->was_snapping = FALSE;
3483     player->was_dropping = FALSE;
3484
3485     player->force_dropping = FALSE;
3486
3487     player->frame_counter_bored = -1;
3488     player->frame_counter_sleeping = -1;
3489
3490     player->anim_delay_counter = 0;
3491     player->post_delay_counter = 0;
3492
3493     player->dir_waiting = initial_move_dir;
3494     player->action_waiting = ACTION_DEFAULT;
3495     player->last_action_waiting = ACTION_DEFAULT;
3496     player->special_action_bored = ACTION_DEFAULT;
3497     player->special_action_sleeping = ACTION_DEFAULT;
3498
3499     player->switch_x = -1;
3500     player->switch_y = -1;
3501
3502     player->drop_x = -1;
3503     player->drop_y = -1;
3504
3505     player->show_envelope = 0;
3506
3507     SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
3508
3509     player->push_delay       = -1;      // initialized when pushing starts
3510     player->push_delay_value = game.initial_push_delay_value;
3511
3512     player->drop_delay = 0;
3513     player->drop_pressed_delay = 0;
3514
3515     player->last_jx = -1;
3516     player->last_jy = -1;
3517     player->jx = -1;
3518     player->jy = -1;
3519
3520     player->shield_normal_time_left = 0;
3521     player->shield_deadly_time_left = 0;
3522
3523     player->inventory_infinite_element = EL_UNDEFINED;
3524     player->inventory_size = 0;
3525
3526     if (level.use_initial_inventory[i])
3527     {
3528       for (j = 0; j < level.initial_inventory_size[i]; j++)
3529       {
3530         int element = level.initial_inventory_content[i][j];
3531         int collect_count = element_info[element].collect_count_initial;
3532         int k;
3533
3534         if (!IS_CUSTOM_ELEMENT(element))
3535           collect_count = 1;
3536
3537         if (collect_count == 0)
3538           player->inventory_infinite_element = element;
3539         else
3540           for (k = 0; k < collect_count; k++)
3541             if (player->inventory_size < MAX_INVENTORY_SIZE)
3542               player->inventory_element[player->inventory_size++] = element;
3543       }
3544     }
3545
3546     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
3547     SnapField(player, 0, 0);
3548
3549     player->GameOver = FALSE;
3550
3551     map_player_action[i] = i;
3552   }
3553
3554   network_player_action_received = FALSE;
3555
3556   // initial null action
3557   if (network_playing)
3558     SendToServer_MovePlayer(MV_NONE);
3559
3560   ZX = ZY = -1;
3561   ExitX = ExitY = -1;
3562
3563   FrameCounter = 0;
3564   TimeFrames = 0;
3565   TimePlayed = 0;
3566   TimeLeft = level.time;
3567   TapeTime = 0;
3568
3569   ScreenMovDir = MV_NONE;
3570   ScreenMovPos = 0;
3571   ScreenGfxPos = 0;
3572
3573   ScrollStepSize = 0;   // will be correctly initialized by ScrollScreen()
3574
3575   AllPlayersGone = FALSE;
3576
3577   game.LevelSolved = FALSE;
3578
3579   game.LevelSolved_GameWon = FALSE;
3580   game.LevelSolved_GameEnd = FALSE;
3581   game.LevelSolved_SaveTape = FALSE;
3582   game.LevelSolved_SaveScore = FALSE;
3583
3584   game.LevelSolved_CountingTime = 0;
3585   game.LevelSolved_CountingScore = 0;
3586   game.LevelSolved_CountingHealth = 0;
3587
3588   game.panel.active = TRUE;
3589
3590   game.no_time_limit = (level.time == 0);
3591
3592   game.yamyam_content_nr = 0;
3593   game.robot_wheel_active = FALSE;
3594   game.magic_wall_active = FALSE;
3595   game.magic_wall_time_left = 0;
3596   game.light_time_left = 0;
3597   game.timegate_time_left = 0;
3598   game.switchgate_pos = 0;
3599   game.wind_direction = level.wind_direction_initial;
3600
3601   game.lenses_time_left = 0;
3602   game.magnify_time_left = 0;
3603
3604   game.ball_state = level.ball_state_initial;
3605   game.ball_content_nr = 0;
3606
3607   game.explosions_delayed = TRUE;
3608
3609   game.envelope_active = FALSE;
3610
3611   for (i = 0; i < NUM_BELTS; i++)
3612   {
3613     game.belt_dir[i] = MV_NONE;
3614     game.belt_dir_nr[i] = 3;            // not moving, next moving left
3615   }
3616
3617   for (i = 0; i < MAX_NUM_AMOEBA; i++)
3618     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
3619
3620 #if DEBUG_INIT_PLAYER
3621   DebugPrintPlayerStatus("Player status at level initialization");
3622 #endif
3623
3624   SCAN_PLAYFIELD(x, y)
3625   {
3626     Feld[x][y] = Last[x][y] = level.field[x][y];
3627     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
3628     ChangeDelay[x][y] = 0;
3629     ChangePage[x][y] = -1;
3630     CustomValue[x][y] = 0;              // initialized in InitField()
3631     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
3632     AmoebaNr[x][y] = 0;
3633     WasJustMoving[x][y] = 0;
3634     WasJustFalling[x][y] = 0;
3635     CheckCollision[x][y] = 0;
3636     CheckImpact[x][y] = 0;
3637     Stop[x][y] = FALSE;
3638     Pushed[x][y] = FALSE;
3639
3640     ChangeCount[x][y] = 0;
3641     ChangeEvent[x][y] = -1;
3642
3643     ExplodePhase[x][y] = 0;
3644     ExplodeDelay[x][y] = 0;
3645     ExplodeField[x][y] = EX_TYPE_NONE;
3646
3647     RunnerVisit[x][y] = 0;
3648     PlayerVisit[x][y] = 0;
3649
3650     GfxFrame[x][y] = 0;
3651     GfxRandom[x][y] = INIT_GFX_RANDOM();
3652     GfxElement[x][y] = EL_UNDEFINED;
3653     GfxAction[x][y] = ACTION_DEFAULT;
3654     GfxDir[x][y] = MV_NONE;
3655     GfxRedraw[x][y] = GFX_REDRAW_NONE;
3656   }
3657
3658   SCAN_PLAYFIELD(x, y)
3659   {
3660     if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
3661       emulate_bd = FALSE;
3662     if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
3663       emulate_sb = FALSE;
3664     if (emulate_sp && !IS_SP_ELEMENT(Feld[x][y]))
3665       emulate_sp = FALSE;
3666
3667     InitField(x, y, TRUE);
3668
3669     ResetGfxAnimation(x, y);
3670   }
3671
3672   InitBeltMovement();
3673
3674   for (i = 0; i < MAX_PLAYERS; i++)
3675   {
3676     struct PlayerInfo *player = &stored_player[i];
3677
3678     // set number of special actions for bored and sleeping animation
3679     player->num_special_action_bored =
3680       get_num_special_action(player->artwork_element,
3681                              ACTION_BORING_1, ACTION_BORING_LAST);
3682     player->num_special_action_sleeping =
3683       get_num_special_action(player->artwork_element,
3684                              ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
3685   }
3686
3687   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
3688                     emulate_sb ? EMU_SOKOBAN :
3689                     emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
3690
3691   // initialize type of slippery elements
3692   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3693   {
3694     if (!IS_CUSTOM_ELEMENT(i))
3695     {
3696       // default: elements slip down either to the left or right randomly
3697       element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
3698
3699       // SP style elements prefer to slip down on the left side
3700       if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
3701         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3702
3703       // BD style elements prefer to slip down on the left side
3704       if (game.emulation == EMU_BOULDERDASH)
3705         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3706     }
3707   }
3708
3709   // initialize explosion and ignition delay
3710   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3711   {
3712     if (!IS_CUSTOM_ELEMENT(i))
3713     {
3714       int num_phase = 8;
3715       int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
3716                     game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
3717                    game.emulation == EMU_SUPAPLEX ? 3 : 2);
3718       int last_phase = (num_phase + 1) * delay;
3719       int half_phase = (num_phase / 2) * delay;
3720
3721       element_info[i].explosion_delay = last_phase - 1;
3722       element_info[i].ignition_delay = half_phase;
3723
3724       if (i == EL_BLACK_ORB)
3725         element_info[i].ignition_delay = 1;
3726     }
3727   }
3728
3729   // correct non-moving belts to start moving left
3730   for (i = 0; i < NUM_BELTS; i++)
3731     if (game.belt_dir[i] == MV_NONE)
3732       game.belt_dir_nr[i] = 3;          // not moving, next moving left
3733
3734 #if USE_NEW_PLAYER_ASSIGNMENTS
3735   for (i = 0; i < MAX_PLAYERS; i++)
3736   {
3737     stored_player[i].connected = FALSE;
3738
3739     // in network game mode, the local player might not be the first player
3740     if (stored_player[i].connected_locally)
3741       local_player = &stored_player[i];
3742   }
3743
3744   if (!network.enabled)
3745     local_player->connected = TRUE;
3746
3747   if (tape.playing)
3748   {
3749     for (i = 0; i < MAX_PLAYERS; i++)
3750       stored_player[i].connected = tape.player_participates[i];
3751   }
3752   else if (network.enabled)
3753   {
3754     // add team mode players connected over the network (needed for correct
3755     // assignment of player figures from level to locally playing players)
3756
3757     for (i = 0; i < MAX_PLAYERS; i++)
3758       if (stored_player[i].connected_network)
3759         stored_player[i].connected = TRUE;
3760   }
3761   else if (game.team_mode)
3762   {
3763     // try to guess locally connected team mode players (needed for correct
3764     // assignment of player figures from level to locally playing players)
3765
3766     for (i = 0; i < MAX_PLAYERS; i++)
3767       if (setup.input[i].use_joystick ||
3768           setup.input[i].key.left != KSYM_UNDEFINED)
3769         stored_player[i].connected = TRUE;
3770   }
3771
3772 #if DEBUG_INIT_PLAYER
3773   DebugPrintPlayerStatus("Player status after level initialization");
3774 #endif
3775
3776 #if DEBUG_INIT_PLAYER
3777   if (options.debug)
3778     printf("Reassigning players ...\n");
3779 #endif
3780
3781   // check if any connected player was not found in playfield
3782   for (i = 0; i < MAX_PLAYERS; i++)
3783   {
3784     struct PlayerInfo *player = &stored_player[i];
3785
3786     if (player->connected && !player->present)
3787     {
3788       struct PlayerInfo *field_player = NULL;
3789
3790 #if DEBUG_INIT_PLAYER
3791       if (options.debug)
3792         printf("- looking for field player for player %d ...\n", i + 1);
3793 #endif
3794
3795       // assign first free player found that is present in the playfield
3796
3797       // first try: look for unmapped playfield player that is not connected
3798       for (j = 0; j < MAX_PLAYERS; j++)
3799         if (field_player == NULL &&
3800             stored_player[j].present &&
3801             !stored_player[j].mapped &&
3802             !stored_player[j].connected)
3803           field_player = &stored_player[j];
3804
3805       // second try: look for *any* unmapped playfield player
3806       for (j = 0; j < MAX_PLAYERS; j++)
3807         if (field_player == NULL &&
3808             stored_player[j].present &&
3809             !stored_player[j].mapped)
3810           field_player = &stored_player[j];
3811
3812       if (field_player != NULL)
3813       {
3814         int jx = field_player->jx, jy = field_player->jy;
3815
3816 #if DEBUG_INIT_PLAYER
3817         if (options.debug)
3818           printf("- found player %d\n", field_player->index_nr + 1);
3819 #endif
3820
3821         player->present = FALSE;
3822         player->active = FALSE;
3823
3824         field_player->present = TRUE;
3825         field_player->active = TRUE;
3826
3827         /*
3828         player->initial_element = field_player->initial_element;
3829         player->artwork_element = field_player->artwork_element;
3830
3831         player->block_last_field       = field_player->block_last_field;
3832         player->block_delay_adjustment = field_player->block_delay_adjustment;
3833         */
3834
3835         StorePlayer[jx][jy] = field_player->element_nr;
3836
3837         field_player->jx = field_player->last_jx = jx;
3838         field_player->jy = field_player->last_jy = jy;
3839
3840         if (local_player == player)
3841           local_player = field_player;
3842
3843         map_player_action[field_player->index_nr] = i;
3844
3845         field_player->mapped = TRUE;
3846
3847 #if DEBUG_INIT_PLAYER
3848         if (options.debug)
3849           printf("- map_player_action[%d] == %d\n",
3850                  field_player->index_nr + 1, i + 1);
3851 #endif
3852       }
3853     }
3854
3855     if (player->connected && player->present)
3856       player->mapped = TRUE;
3857   }
3858
3859 #if DEBUG_INIT_PLAYER
3860   DebugPrintPlayerStatus("Player status after player assignment (first stage)");
3861 #endif
3862
3863 #else
3864
3865   // check if any connected player was not found in playfield
3866   for (i = 0; i < MAX_PLAYERS; i++)
3867   {
3868     struct PlayerInfo *player = &stored_player[i];
3869
3870     if (player->connected && !player->present)
3871     {
3872       for (j = 0; j < MAX_PLAYERS; j++)
3873       {
3874         struct PlayerInfo *field_player = &stored_player[j];
3875         int jx = field_player->jx, jy = field_player->jy;
3876
3877         // assign first free player found that is present in the playfield
3878         if (field_player->present && !field_player->connected)
3879         {
3880           player->present = TRUE;
3881           player->active = TRUE;
3882
3883           field_player->present = FALSE;
3884           field_player->active = FALSE;
3885
3886           player->initial_element = field_player->initial_element;
3887           player->artwork_element = field_player->artwork_element;
3888
3889           player->block_last_field       = field_player->block_last_field;
3890           player->block_delay_adjustment = field_player->block_delay_adjustment;
3891
3892           StorePlayer[jx][jy] = player->element_nr;
3893
3894           player->jx = player->last_jx = jx;
3895           player->jy = player->last_jy = jy;
3896
3897           break;
3898         }
3899       }
3900     }
3901   }
3902 #endif
3903
3904 #if 0
3905   printf("::: local_player->present == %d\n", local_player->present);
3906 #endif
3907
3908   // set focus to local player for network games, else to all players
3909   game.centered_player_nr = (network_playing ? local_player->index_nr : -1);
3910   game.centered_player_nr_next = game.centered_player_nr;
3911   game.set_centered_player = FALSE;
3912
3913   if (network_playing && tape.recording)
3914   {
3915     // store client dependent player focus when recording network games
3916     tape.centered_player_nr_next = game.centered_player_nr_next;
3917     tape.set_centered_player = TRUE;
3918   }
3919
3920   if (tape.playing)
3921   {
3922     // when playing a tape, eliminate all players who do not participate
3923
3924 #if USE_NEW_PLAYER_ASSIGNMENTS
3925
3926     if (!game.team_mode)
3927     {
3928       for (i = 0; i < MAX_PLAYERS; i++)
3929       {
3930         if (stored_player[i].active &&
3931             !tape.player_participates[map_player_action[i]])
3932         {
3933           struct PlayerInfo *player = &stored_player[i];
3934           int jx = player->jx, jy = player->jy;
3935
3936 #if DEBUG_INIT_PLAYER
3937           if (options.debug)
3938             printf("Removing player %d at (%d, %d)\n", i + 1, jx, jy);
3939 #endif
3940
3941           player->active = FALSE;
3942           StorePlayer[jx][jy] = 0;
3943           Feld[jx][jy] = EL_EMPTY;
3944         }
3945       }
3946     }
3947
3948 #else
3949
3950     for (i = 0; i < MAX_PLAYERS; i++)
3951     {
3952       if (stored_player[i].active &&
3953           !tape.player_participates[i])
3954       {
3955         struct PlayerInfo *player = &stored_player[i];
3956         int jx = player->jx, jy = player->jy;
3957
3958         player->active = FALSE;
3959         StorePlayer[jx][jy] = 0;
3960         Feld[jx][jy] = EL_EMPTY;
3961       }
3962     }
3963 #endif
3964   }
3965   else if (!network.enabled && !game.team_mode)         // && !tape.playing
3966   {
3967     // when in single player mode, eliminate all but the local player
3968
3969     for (i = 0; i < MAX_PLAYERS; i++)
3970     {
3971       struct PlayerInfo *player = &stored_player[i];
3972
3973       if (player->active && player != local_player)
3974       {
3975         int jx = player->jx, jy = player->jy;
3976
3977         player->active = FALSE;
3978         player->present = FALSE;
3979
3980         StorePlayer[jx][jy] = 0;
3981         Feld[jx][jy] = EL_EMPTY;
3982       }
3983     }
3984   }
3985
3986   for (i = 0; i < MAX_PLAYERS; i++)
3987     if (stored_player[i].active)
3988       local_player->players_still_needed++;
3989
3990   if (level.solved_by_one_player)
3991     local_player->players_still_needed = 1;
3992
3993   // when recording the game, store which players take part in the game
3994   if (tape.recording)
3995   {
3996 #if USE_NEW_PLAYER_ASSIGNMENTS
3997     for (i = 0; i < MAX_PLAYERS; i++)
3998       if (stored_player[i].connected)
3999         tape.player_participates[i] = TRUE;
4000 #else
4001     for (i = 0; i < MAX_PLAYERS; i++)
4002       if (stored_player[i].active)
4003         tape.player_participates[i] = TRUE;
4004 #endif
4005   }
4006
4007 #if DEBUG_INIT_PLAYER
4008   DebugPrintPlayerStatus("Player status after player assignment (final stage)");
4009 #endif
4010
4011   if (BorderElement == EL_EMPTY)
4012   {
4013     SBX_Left = 0;
4014     SBX_Right = lev_fieldx - SCR_FIELDX;
4015     SBY_Upper = 0;
4016     SBY_Lower = lev_fieldy - SCR_FIELDY;
4017   }
4018   else
4019   {
4020     SBX_Left = -1;
4021     SBX_Right = lev_fieldx - SCR_FIELDX + 1;
4022     SBY_Upper = -1;
4023     SBY_Lower = lev_fieldy - SCR_FIELDY + 1;
4024   }
4025
4026   if (full_lev_fieldx <= SCR_FIELDX)
4027     SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2;
4028   if (full_lev_fieldy <= SCR_FIELDY)
4029     SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2;
4030
4031   if (EVEN(SCR_FIELDX) && full_lev_fieldx > SCR_FIELDX)
4032     SBX_Left--;
4033   if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
4034     SBY_Upper--;
4035
4036   // if local player not found, look for custom element that might create
4037   // the player (make some assumptions about the right custom element)
4038   if (!local_player->present)
4039   {
4040     int start_x = 0, start_y = 0;
4041     int found_rating = 0;
4042     int found_element = EL_UNDEFINED;
4043     int player_nr = local_player->index_nr;
4044
4045     SCAN_PLAYFIELD(x, y)
4046     {
4047       int element = Feld[x][y];
4048       int content;
4049       int xx, yy;
4050       boolean is_player;
4051
4052       if (level.use_start_element[player_nr] &&
4053           level.start_element[player_nr] == element &&
4054           found_rating < 4)
4055       {
4056         start_x = x;
4057         start_y = y;
4058
4059         found_rating = 4;
4060         found_element = element;
4061       }
4062
4063       if (!IS_CUSTOM_ELEMENT(element))
4064         continue;
4065
4066       if (CAN_CHANGE(element))
4067       {
4068         for (i = 0; i < element_info[element].num_change_pages; i++)
4069         {
4070           // check for player created from custom element as single target
4071           content = element_info[element].change_page[i].target_element;
4072           is_player = ELEM_IS_PLAYER(content);
4073
4074           if (is_player && (found_rating < 3 ||
4075                             (found_rating == 3 && element < found_element)))
4076           {
4077             start_x = x;
4078             start_y = y;
4079
4080             found_rating = 3;
4081             found_element = element;
4082           }
4083         }
4084       }
4085
4086       for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
4087       {
4088         // check for player created from custom element as explosion content
4089         content = element_info[element].content.e[xx][yy];
4090         is_player = ELEM_IS_PLAYER(content);
4091
4092         if (is_player && (found_rating < 2 ||
4093                           (found_rating == 2 && element < found_element)))
4094         {
4095           start_x = x + xx - 1;
4096           start_y = y + yy - 1;
4097
4098           found_rating = 2;
4099           found_element = element;
4100         }
4101
4102         if (!CAN_CHANGE(element))
4103           continue;
4104
4105         for (i = 0; i < element_info[element].num_change_pages; i++)
4106         {
4107           // check for player created from custom element as extended target
4108           content =
4109             element_info[element].change_page[i].target_content.e[xx][yy];
4110
4111           is_player = ELEM_IS_PLAYER(content);
4112
4113           if (is_player && (found_rating < 1 ||
4114                             (found_rating == 1 && element < found_element)))
4115           {
4116             start_x = x + xx - 1;
4117             start_y = y + yy - 1;
4118
4119             found_rating = 1;
4120             found_element = element;
4121           }
4122         }
4123       }
4124     }
4125
4126     scroll_x = SCROLL_POSITION_X(start_x);
4127     scroll_y = SCROLL_POSITION_Y(start_y);
4128   }
4129   else
4130   {
4131     scroll_x = SCROLL_POSITION_X(local_player->jx);
4132     scroll_y = SCROLL_POSITION_Y(local_player->jy);
4133   }
4134
4135   // !!! FIX THIS (START) !!!
4136   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4137   {
4138     InitGameEngine_EM();
4139   }
4140   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4141   {
4142     InitGameEngine_SP();
4143   }
4144   else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
4145   {
4146     InitGameEngine_MM();
4147   }
4148   else
4149   {
4150     DrawLevel(REDRAW_FIELD);
4151     DrawAllPlayers();
4152
4153     // after drawing the level, correct some elements
4154     if (game.timegate_time_left == 0)
4155       CloseAllOpenTimegates();
4156   }
4157
4158   // blit playfield from scroll buffer to normal back buffer for fading in
4159   BlitScreenToBitmap(backbuffer);
4160   // !!! FIX THIS (END) !!!
4161
4162   DrawMaskedBorder(fade_mask);
4163
4164   FadeIn(fade_mask);
4165
4166 #if 1
4167   // full screen redraw is required at this point in the following cases:
4168   // - special editor door undrawn when game was started from level editor
4169   // - drawing area (playfield) was changed and has to be removed completely
4170   redraw_mask = REDRAW_ALL;
4171   BackToFront();
4172 #endif
4173
4174   if (!game.restart_level)
4175   {
4176     // copy default game door content to main double buffer
4177
4178     // !!! CHECK AGAIN !!!
4179     SetPanelBackground();
4180     // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
4181     DrawBackground(DX, DY, DXSIZE, DYSIZE);
4182   }
4183
4184   SetPanelBackground();
4185   SetDrawBackgroundMask(REDRAW_DOOR_1);
4186
4187   UpdateAndDisplayGameControlValues();
4188
4189   if (!game.restart_level)
4190   {
4191     UnmapGameButtons();
4192     UnmapTapeButtons();
4193
4194     FreeGameButtons();
4195     CreateGameButtons();
4196
4197     MapGameButtons();
4198     MapTapeButtons();
4199
4200     // copy actual game door content to door double buffer for OpenDoor()
4201     BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4202
4203     OpenDoor(DOOR_OPEN_ALL);
4204
4205     KeyboardAutoRepeatOffUnlessAutoplay();
4206
4207 #if DEBUG_INIT_PLAYER
4208     DebugPrintPlayerStatus("Player status (final)");
4209 #endif
4210   }
4211
4212   UnmapAllGadgets();
4213
4214   MapGameButtons();
4215   MapTapeButtons();
4216
4217   if (!game.restart_level && !tape.playing)
4218   {
4219     LevelStats_incPlayed(level_nr);
4220
4221     SaveLevelSetup_SeriesInfo();
4222   }
4223
4224   game.restart_level = FALSE;
4225   game.restart_game_message = NULL;
4226   game.request_active = FALSE;
4227
4228   if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
4229     InitGameActions_MM();
4230
4231   SaveEngineSnapshotToListInitial();
4232
4233   if (!game.restart_level)
4234   {
4235     PlaySound(SND_GAME_STARTING);
4236
4237     if (setup.sound_music)
4238       PlayLevelMusic();
4239   }
4240 }
4241
4242 void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y,
4243                         int actual_player_x, int actual_player_y)
4244 {
4245   // this is used for non-R'n'D game engines to update certain engine values
4246
4247   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4248   {
4249     actual_player_x = correctLevelPosX_EM(actual_player_x);
4250     actual_player_y = correctLevelPosY_EM(actual_player_y);
4251   }
4252
4253   // needed to determine if sounds are played within the visible screen area
4254   scroll_x = actual_scroll_x;
4255   scroll_y = actual_scroll_y;
4256
4257   // needed to get player position for "follow finger" playing input method
4258   local_player->jx = actual_player_x;
4259   local_player->jy = actual_player_y;
4260 }
4261
4262 void InitMovDir(int x, int y)
4263 {
4264   int i, element = Feld[x][y];
4265   static int xy[4][2] =
4266   {
4267     {  0, +1 },
4268     { +1,  0 },
4269     {  0, -1 },
4270     { -1,  0 }
4271   };
4272   static int direction[3][4] =
4273   {
4274     { MV_RIGHT, MV_UP,   MV_LEFT,  MV_DOWN },
4275     { MV_LEFT,  MV_DOWN, MV_RIGHT, MV_UP },
4276     { MV_LEFT,  MV_RIGHT, MV_UP, MV_DOWN }
4277   };
4278
4279   switch (element)
4280   {
4281     case EL_BUG_RIGHT:
4282     case EL_BUG_UP:
4283     case EL_BUG_LEFT:
4284     case EL_BUG_DOWN:
4285       Feld[x][y] = EL_BUG;
4286       MovDir[x][y] = direction[0][element - EL_BUG_RIGHT];
4287       break;
4288
4289     case EL_SPACESHIP_RIGHT:
4290     case EL_SPACESHIP_UP:
4291     case EL_SPACESHIP_LEFT:
4292     case EL_SPACESHIP_DOWN:
4293       Feld[x][y] = EL_SPACESHIP;
4294       MovDir[x][y] = direction[0][element - EL_SPACESHIP_RIGHT];
4295       break;
4296
4297     case EL_BD_BUTTERFLY_RIGHT:
4298     case EL_BD_BUTTERFLY_UP:
4299     case EL_BD_BUTTERFLY_LEFT:
4300     case EL_BD_BUTTERFLY_DOWN:
4301       Feld[x][y] = EL_BD_BUTTERFLY;
4302       MovDir[x][y] = direction[0][element - EL_BD_BUTTERFLY_RIGHT];
4303       break;
4304
4305     case EL_BD_FIREFLY_RIGHT:
4306     case EL_BD_FIREFLY_UP:
4307     case EL_BD_FIREFLY_LEFT:
4308     case EL_BD_FIREFLY_DOWN:
4309       Feld[x][y] = EL_BD_FIREFLY;
4310       MovDir[x][y] = direction[0][element - EL_BD_FIREFLY_RIGHT];
4311       break;
4312
4313     case EL_PACMAN_RIGHT:
4314     case EL_PACMAN_UP:
4315     case EL_PACMAN_LEFT:
4316     case EL_PACMAN_DOWN:
4317       Feld[x][y] = EL_PACMAN;
4318       MovDir[x][y] = direction[0][element - EL_PACMAN_RIGHT];
4319       break;
4320
4321     case EL_YAMYAM_LEFT:
4322     case EL_YAMYAM_RIGHT:
4323     case EL_YAMYAM_UP:
4324     case EL_YAMYAM_DOWN:
4325       Feld[x][y] = EL_YAMYAM;
4326       MovDir[x][y] = direction[2][element - EL_YAMYAM_LEFT];
4327       break;
4328
4329     case EL_SP_SNIKSNAK:
4330       MovDir[x][y] = MV_UP;
4331       break;
4332
4333     case EL_SP_ELECTRON:
4334       MovDir[x][y] = MV_LEFT;
4335       break;
4336
4337     case EL_MOLE_LEFT:
4338     case EL_MOLE_RIGHT:
4339     case EL_MOLE_UP:
4340     case EL_MOLE_DOWN:
4341       Feld[x][y] = EL_MOLE;
4342       MovDir[x][y] = direction[2][element - EL_MOLE_LEFT];
4343       break;
4344
4345     default:
4346       if (IS_CUSTOM_ELEMENT(element))
4347       {
4348         struct ElementInfo *ei = &element_info[element];
4349         int move_direction_initial = ei->move_direction_initial;
4350         int move_pattern = ei->move_pattern;
4351
4352         if (move_direction_initial == MV_START_PREVIOUS)
4353         {
4354           if (MovDir[x][y] != MV_NONE)
4355             return;
4356
4357           move_direction_initial = MV_START_AUTOMATIC;
4358         }
4359
4360         if (move_direction_initial == MV_START_RANDOM)
4361           MovDir[x][y] = 1 << RND(4);
4362         else if (move_direction_initial & MV_ANY_DIRECTION)
4363           MovDir[x][y] = move_direction_initial;
4364         else if (move_pattern == MV_ALL_DIRECTIONS ||
4365                  move_pattern == MV_TURNING_LEFT ||
4366                  move_pattern == MV_TURNING_RIGHT ||
4367                  move_pattern == MV_TURNING_LEFT_RIGHT ||
4368                  move_pattern == MV_TURNING_RIGHT_LEFT ||
4369                  move_pattern == MV_TURNING_RANDOM)
4370           MovDir[x][y] = 1 << RND(4);
4371         else if (move_pattern == MV_HORIZONTAL)
4372           MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
4373         else if (move_pattern == MV_VERTICAL)
4374           MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
4375         else if (move_pattern & MV_ANY_DIRECTION)
4376           MovDir[x][y] = element_info[element].move_pattern;
4377         else if (move_pattern == MV_ALONG_LEFT_SIDE ||
4378                  move_pattern == MV_ALONG_RIGHT_SIDE)
4379         {
4380           // use random direction as default start direction
4381           if (game.engine_version >= VERSION_IDENT(3,1,0,0))
4382             MovDir[x][y] = 1 << RND(4);
4383
4384           for (i = 0; i < NUM_DIRECTIONS; i++)
4385           {
4386             int x1 = x + xy[i][0];
4387             int y1 = y + xy[i][1];
4388
4389             if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
4390             {
4391               if (move_pattern == MV_ALONG_RIGHT_SIDE)
4392                 MovDir[x][y] = direction[0][i];
4393               else
4394                 MovDir[x][y] = direction[1][i];
4395
4396               break;
4397             }
4398           }
4399         }                
4400       }
4401       else
4402       {
4403         MovDir[x][y] = 1 << RND(4);
4404
4405         if (element != EL_BUG &&
4406             element != EL_SPACESHIP &&
4407             element != EL_BD_BUTTERFLY &&
4408             element != EL_BD_FIREFLY)
4409           break;
4410
4411         for (i = 0; i < NUM_DIRECTIONS; i++)
4412         {
4413           int x1 = x + xy[i][0];
4414           int y1 = y + xy[i][1];
4415
4416           if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
4417           {
4418             if (element == EL_BUG || element == EL_BD_BUTTERFLY)
4419             {
4420               MovDir[x][y] = direction[0][i];
4421               break;
4422             }
4423             else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY ||
4424                      element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
4425             {
4426               MovDir[x][y] = direction[1][i];
4427               break;
4428             }
4429           }
4430         }
4431       }
4432       break;
4433   }
4434
4435   GfxDir[x][y] = MovDir[x][y];
4436 }
4437
4438 void InitAmoebaNr(int x, int y)
4439 {
4440   int i;
4441   int group_nr = AmoebeNachbarNr(x, y);
4442
4443   if (group_nr == 0)
4444   {
4445     for (i = 1; i < MAX_NUM_AMOEBA; i++)
4446     {
4447       if (AmoebaCnt[i] == 0)
4448       {
4449         group_nr = i;
4450         break;
4451       }
4452     }
4453   }
4454
4455   AmoebaNr[x][y] = group_nr;
4456   AmoebaCnt[group_nr]++;
4457   AmoebaCnt2[group_nr]++;
4458 }
4459
4460 static void PlayerWins(void)
4461 {
4462   if (level.game_engine_type == GAME_ENGINE_TYPE_RND &&
4463       local_player->players_still_needed > 0)
4464     return;
4465
4466   game.LevelSolved = TRUE;
4467
4468   local_player->GameOver = TRUE;
4469
4470   local_player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
4471                                level.native_em_level->lev->score :
4472                                level.game_engine_type == GAME_ENGINE_TYPE_MM ?
4473                                game_mm.score :
4474                                local_player->score);
4475   local_player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
4476                                 MM_HEALTH(game_mm.laser_overload_value) :
4477                                 local_player->health);
4478
4479   game.LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft);
4480   game.LevelSolved_CountingScore = local_player->score_final;
4481   game.LevelSolved_CountingHealth = local_player->health_final;
4482 }
4483
4484 void GameWon(void)
4485 {
4486   static int time_count_steps;
4487   static int time, time_final;
4488   static int score, score_final;
4489   static int health, health_final;
4490   static int game_over_delay_1 = 0;
4491   static int game_over_delay_2 = 0;
4492   static int game_over_delay_3 = 0;
4493   int game_over_delay_value_1 = 50;
4494   int game_over_delay_value_2 = 25;
4495   int game_over_delay_value_3 = 50;
4496
4497   if (!game.LevelSolved_GameWon)
4498   {
4499     int i;
4500
4501     // do not start end game actions before the player stops moving (to exit)
4502     if (local_player->MovPos)
4503       return;
4504
4505     game.LevelSolved_GameWon = TRUE;
4506     game.LevelSolved_SaveTape = tape.recording;
4507     game.LevelSolved_SaveScore = !tape.playing;
4508
4509     if (!tape.playing)
4510     {
4511       LevelStats_incSolved(level_nr);
4512
4513       SaveLevelSetup_SeriesInfo();
4514     }
4515
4516     if (tape.auto_play)         // tape might already be stopped here
4517       tape.auto_play_level_solved = TRUE;
4518
4519     TapeStop();
4520
4521     game_over_delay_1 = 0;
4522     game_over_delay_2 = 0;
4523     game_over_delay_3 = game_over_delay_value_3;
4524
4525     time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
4526     score = score_final = local_player->score_final;
4527     health = health_final = local_player->health_final;
4528
4529     if (level.score[SC_TIME_BONUS] > 0)
4530     {
4531       if (TimeLeft > 0)
4532       {
4533         time_final = 0;
4534         score_final += TimeLeft * level.score[SC_TIME_BONUS];
4535       }
4536       else if (game.no_time_limit && TimePlayed < 999)
4537       {
4538         time_final = 999;
4539         score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS];
4540       }
4541
4542       time_count_steps = MAX(1, ABS(time_final - time) / 100);
4543
4544       game_over_delay_1 = game_over_delay_value_1;
4545
4546       if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
4547       {
4548         health_final = 0;
4549         score_final += health * level.score[SC_TIME_BONUS];
4550
4551         game_over_delay_2 = game_over_delay_value_2;
4552       }
4553
4554       local_player->score_final = score_final;
4555       local_player->health_final = health_final;
4556     }
4557
4558     if (level_editor_test_game)
4559     {
4560       time = time_final;
4561       score = score_final;
4562
4563       game.LevelSolved_CountingTime = time;
4564       game.LevelSolved_CountingScore = score;
4565
4566       game_panel_controls[GAME_PANEL_TIME].value = time;
4567       game_panel_controls[GAME_PANEL_SCORE].value = score;
4568
4569       DisplayGameControlValues();
4570     }
4571
4572     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
4573     {
4574       if (ExitX >= 0 && ExitY >= 0)     // local player has left the level
4575       {
4576         // close exit door after last player
4577         if ((AllPlayersGone &&
4578              (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
4579               Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
4580               Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN)) ||
4581             Feld[ExitX][ExitY] == EL_EM_EXIT_OPEN ||
4582             Feld[ExitX][ExitY] == EL_EM_STEEL_EXIT_OPEN)
4583         {
4584           int element = Feld[ExitX][ExitY];
4585
4586           Feld[ExitX][ExitY] =
4587             (element == EL_EXIT_OPEN            ? EL_EXIT_CLOSING :
4588              element == EL_EM_EXIT_OPEN         ? EL_EM_EXIT_CLOSING :
4589              element == EL_SP_EXIT_OPEN         ? EL_SP_EXIT_CLOSING:
4590              element == EL_STEEL_EXIT_OPEN      ? EL_STEEL_EXIT_CLOSING:
4591              EL_EM_STEEL_EXIT_CLOSING);
4592
4593           PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
4594         }
4595
4596         // player disappears
4597         DrawLevelField(ExitX, ExitY);
4598       }
4599
4600       for (i = 0; i < MAX_PLAYERS; i++)
4601       {
4602         struct PlayerInfo *player = &stored_player[i];
4603
4604         if (player->present)
4605         {
4606           RemovePlayer(player);
4607
4608           // player disappears
4609           DrawLevelField(player->jx, player->jy);
4610         }
4611       }
4612     }
4613
4614     PlaySound(SND_GAME_WINNING);
4615   }
4616
4617   if (game_over_delay_1 > 0)
4618   {
4619     game_over_delay_1--;
4620
4621     return;
4622   }
4623
4624   if (time != time_final)
4625   {
4626     int time_to_go = ABS(time_final - time);
4627     int time_count_dir = (time < time_final ? +1 : -1);
4628
4629     if (time_to_go < time_count_steps)
4630       time_count_steps = 1;
4631
4632     time  += time_count_steps * time_count_dir;
4633     score += time_count_steps * level.score[SC_TIME_BONUS];
4634
4635     game.LevelSolved_CountingTime = time;
4636     game.LevelSolved_CountingScore = score;
4637
4638     game_panel_controls[GAME_PANEL_TIME].value = time;
4639     game_panel_controls[GAME_PANEL_SCORE].value = score;
4640
4641     DisplayGameControlValues();
4642
4643     if (time == time_final)
4644       StopSound(SND_GAME_LEVELTIME_BONUS);
4645     else if (setup.sound_loops)
4646       PlaySoundLoop(SND_GAME_LEVELTIME_BONUS);
4647     else
4648       PlaySound(SND_GAME_LEVELTIME_BONUS);
4649
4650     return;
4651   }
4652
4653   if (game_over_delay_2 > 0)
4654   {
4655     game_over_delay_2--;
4656