4a3d1eef4d4e63bbe088da3b3209f31ce03088ad
[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 InitPlayerField(int x, int y, int element, boolean init_game)
1687 {
1688   if (element == EL_SP_MURPHY)
1689   {
1690     if (init_game)
1691     {
1692       if (stored_player[0].present)
1693       {
1694         Feld[x][y] = EL_SP_MURPHY_CLONE;
1695
1696         return;
1697       }
1698       else
1699       {
1700         stored_player[0].initial_element = element;
1701         stored_player[0].use_murphy = TRUE;
1702
1703         if (!level.use_artwork_element[0])
1704           stored_player[0].artwork_element = EL_SP_MURPHY;
1705       }
1706
1707       Feld[x][y] = EL_PLAYER_1;
1708     }
1709   }
1710
1711   if (init_game)
1712   {
1713     struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1];
1714     int jx = player->jx, jy = player->jy;
1715
1716     player->present = TRUE;
1717
1718     player->block_last_field = (element == EL_SP_MURPHY ?
1719                                 level.sp_block_last_field :
1720                                 level.block_last_field);
1721
1722     // ---------- initialize player's last field block delay ------------------
1723
1724     // always start with reliable default value (no adjustment needed)
1725     player->block_delay_adjustment = 0;
1726
1727     // special case 1: in Supaplex, Murphy blocks last field one more frame
1728     if (player->block_last_field && element == EL_SP_MURPHY)
1729       player->block_delay_adjustment = 1;
1730
1731     // special case 2: in game engines before 3.1.1, blocking was different
1732     if (game.use_block_last_field_bug)
1733       player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
1734
1735     if (!network.enabled || player->connected_network)
1736     {
1737       player->active = TRUE;
1738
1739       // remove potentially duplicate players
1740       if (StorePlayer[jx][jy] == Feld[x][y])
1741         StorePlayer[jx][jy] = 0;
1742
1743       StorePlayer[x][y] = Feld[x][y];
1744
1745 #if DEBUG_INIT_PLAYER
1746       if (options.debug)
1747       {
1748         printf("- player element %d activated", player->element_nr);
1749         printf(" (local player is %d and currently %s)\n",
1750                local_player->element_nr,
1751                local_player->active ? "active" : "not active");
1752       }
1753     }
1754 #endif
1755
1756     Feld[x][y] = EL_EMPTY;
1757
1758     player->jx = player->last_jx = x;
1759     player->jy = player->last_jy = y;
1760   }
1761
1762   if (!init_game)
1763   {
1764     int player_nr = GET_PLAYER_NR(element);
1765     struct PlayerInfo *player = &stored_player[player_nr];
1766
1767     if (player->active && player->killed)
1768       player->reanimated = TRUE; // if player was just killed, reanimate him
1769   }
1770 }
1771
1772 static void InitField(int x, int y, boolean init_game)
1773 {
1774   int element = Feld[x][y];
1775
1776   switch (element)
1777   {
1778     case EL_SP_MURPHY:
1779     case EL_PLAYER_1:
1780     case EL_PLAYER_2:
1781     case EL_PLAYER_3:
1782     case EL_PLAYER_4:
1783       InitPlayerField(x, y, element, init_game);
1784       break;
1785
1786     case EL_SOKOBAN_FIELD_PLAYER:
1787       element = Feld[x][y] = EL_PLAYER_1;
1788       InitField(x, y, init_game);
1789
1790       element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
1791       InitField(x, y, init_game);
1792       break;
1793
1794     case EL_SOKOBAN_FIELD_EMPTY:
1795       local_player->sokoban_fields_still_needed++;
1796       break;
1797
1798     case EL_SOKOBAN_OBJECT:
1799       local_player->sokoban_objects_still_needed++;
1800       break;
1801
1802     case EL_STONEBLOCK:
1803       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
1804         Feld[x][y] = EL_ACID_POOL_TOPLEFT;
1805       else if (x > 0 && Feld[x-1][y] == EL_ACID)
1806         Feld[x][y] = EL_ACID_POOL_TOPRIGHT;
1807       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPLEFT)
1808         Feld[x][y] = EL_ACID_POOL_BOTTOMLEFT;
1809       else if (y > 0 && Feld[x][y-1] == EL_ACID)
1810         Feld[x][y] = EL_ACID_POOL_BOTTOM;
1811       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPRIGHT)
1812         Feld[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
1813       break;
1814
1815     case EL_BUG:
1816     case EL_BUG_RIGHT:
1817     case EL_BUG_UP:
1818     case EL_BUG_LEFT:
1819     case EL_BUG_DOWN:
1820     case EL_SPACESHIP:
1821     case EL_SPACESHIP_RIGHT:
1822     case EL_SPACESHIP_UP:
1823     case EL_SPACESHIP_LEFT:
1824     case EL_SPACESHIP_DOWN:
1825     case EL_BD_BUTTERFLY:
1826     case EL_BD_BUTTERFLY_RIGHT:
1827     case EL_BD_BUTTERFLY_UP:
1828     case EL_BD_BUTTERFLY_LEFT:
1829     case EL_BD_BUTTERFLY_DOWN:
1830     case EL_BD_FIREFLY:
1831     case EL_BD_FIREFLY_RIGHT:
1832     case EL_BD_FIREFLY_UP:
1833     case EL_BD_FIREFLY_LEFT:
1834     case EL_BD_FIREFLY_DOWN:
1835     case EL_PACMAN_RIGHT:
1836     case EL_PACMAN_UP:
1837     case EL_PACMAN_LEFT:
1838     case EL_PACMAN_DOWN:
1839     case EL_YAMYAM:
1840     case EL_YAMYAM_LEFT:
1841     case EL_YAMYAM_RIGHT:
1842     case EL_YAMYAM_UP:
1843     case EL_YAMYAM_DOWN:
1844     case EL_DARK_YAMYAM:
1845     case EL_ROBOT:
1846     case EL_PACMAN:
1847     case EL_SP_SNIKSNAK:
1848     case EL_SP_ELECTRON:
1849     case EL_MOLE:
1850     case EL_MOLE_LEFT:
1851     case EL_MOLE_RIGHT:
1852     case EL_MOLE_UP:
1853     case EL_MOLE_DOWN:
1854       InitMovDir(x, y);
1855       break;
1856
1857     case EL_AMOEBA_FULL:
1858     case EL_BD_AMOEBA:
1859       InitAmoebaNr(x, y);
1860       break;
1861
1862     case EL_AMOEBA_DROP:
1863       if (y == lev_fieldy - 1)
1864       {
1865         Feld[x][y] = EL_AMOEBA_GROWING;
1866         Store[x][y] = EL_AMOEBA_WET;
1867       }
1868       break;
1869
1870     case EL_DYNAMITE_ACTIVE:
1871     case EL_SP_DISK_RED_ACTIVE:
1872     case EL_DYNABOMB_PLAYER_1_ACTIVE:
1873     case EL_DYNABOMB_PLAYER_2_ACTIVE:
1874     case EL_DYNABOMB_PLAYER_3_ACTIVE:
1875     case EL_DYNABOMB_PLAYER_4_ACTIVE:
1876       MovDelay[x][y] = 96;
1877       break;
1878
1879     case EL_EM_DYNAMITE_ACTIVE:
1880       MovDelay[x][y] = 32;
1881       break;
1882
1883     case EL_LAMP:
1884       local_player->lights_still_needed++;
1885       break;
1886
1887     case EL_PENGUIN:
1888       local_player->friends_still_needed++;
1889       break;
1890
1891     case EL_PIG:
1892     case EL_DRAGON:
1893       GfxDir[x][y] = MovDir[x][y] = 1 << RND(4);
1894       break;
1895
1896     case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
1897     case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
1898     case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
1899     case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
1900     case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
1901     case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
1902     case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
1903     case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
1904     case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
1905     case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
1906     case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
1907     case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
1908       if (init_game)
1909       {
1910         int belt_nr = getBeltNrFromBeltSwitchElement(Feld[x][y]);
1911         int belt_dir = getBeltDirFromBeltSwitchElement(Feld[x][y]);
1912         int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(Feld[x][y]);
1913
1914         if (game.belt_dir_nr[belt_nr] == 3)     // initial value
1915         {
1916           game.belt_dir[belt_nr] = belt_dir;
1917           game.belt_dir_nr[belt_nr] = belt_dir_nr;
1918         }
1919         else    // more than one switch -- set it like the first switch
1920         {
1921           Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
1922         }
1923       }
1924       break;
1925
1926     case EL_LIGHT_SWITCH_ACTIVE:
1927       if (init_game)
1928         game.light_time_left = level.time_light * FRAMES_PER_SECOND;
1929       break;
1930
1931     case EL_INVISIBLE_STEELWALL:
1932     case EL_INVISIBLE_WALL:
1933     case EL_INVISIBLE_SAND:
1934       if (game.light_time_left > 0 ||
1935           game.lenses_time_left > 0)
1936         Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
1937       break;
1938
1939     case EL_EMC_MAGIC_BALL:
1940       if (game.ball_state)
1941         Feld[x][y] = EL_EMC_MAGIC_BALL_ACTIVE;
1942       break;
1943
1944     case EL_EMC_MAGIC_BALL_SWITCH:
1945       if (game.ball_state)
1946         Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
1947       break;
1948
1949     case EL_TRIGGER_PLAYER:
1950     case EL_TRIGGER_ELEMENT:
1951     case EL_TRIGGER_CE_VALUE:
1952     case EL_TRIGGER_CE_SCORE:
1953     case EL_SELF:
1954     case EL_ANY_ELEMENT:
1955     case EL_CURRENT_CE_VALUE:
1956     case EL_CURRENT_CE_SCORE:
1957     case EL_PREV_CE_1:
1958     case EL_PREV_CE_2:
1959     case EL_PREV_CE_3:
1960     case EL_PREV_CE_4:
1961     case EL_PREV_CE_5:
1962     case EL_PREV_CE_6:
1963     case EL_PREV_CE_7:
1964     case EL_PREV_CE_8:
1965     case EL_NEXT_CE_1:
1966     case EL_NEXT_CE_2:
1967     case EL_NEXT_CE_3:
1968     case EL_NEXT_CE_4:
1969     case EL_NEXT_CE_5:
1970     case EL_NEXT_CE_6:
1971     case EL_NEXT_CE_7:
1972     case EL_NEXT_CE_8:
1973       // reference elements should not be used on the playfield
1974       Feld[x][y] = EL_EMPTY;
1975       break;
1976
1977     default:
1978       if (IS_CUSTOM_ELEMENT(element))
1979       {
1980         if (CAN_MOVE(element))
1981           InitMovDir(x, y);
1982
1983         if (!element_info[element].use_last_ce_value || init_game)
1984           CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
1985       }
1986       else if (IS_GROUP_ELEMENT(element))
1987       {
1988         Feld[x][y] = GetElementFromGroupElement(element);
1989
1990         InitField(x, y, init_game);
1991       }
1992
1993       break;
1994   }
1995
1996   if (!init_game)
1997     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
1998 }
1999
2000 static void InitField_WithBug1(int x, int y, boolean init_game)
2001 {
2002   InitField(x, y, init_game);
2003
2004   // not needed to call InitMovDir() -- already done by InitField()!
2005   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2006       CAN_MOVE(Feld[x][y]))
2007     InitMovDir(x, y);
2008 }
2009
2010 static void InitField_WithBug2(int x, int y, boolean init_game)
2011 {
2012   int old_element = Feld[x][y];
2013
2014   InitField(x, y, init_game);
2015
2016   // not needed to call InitMovDir() -- already done by InitField()!
2017   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2018       CAN_MOVE(old_element) &&
2019       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
2020     InitMovDir(x, y);
2021
2022   /* this case is in fact a combination of not less than three bugs:
2023      first, it calls InitMovDir() for elements that can move, although this is
2024      already done by InitField(); then, it checks the element that was at this
2025      field _before_ the call to InitField() (which can change it); lastly, it
2026      was not called for "mole with direction" elements, which were treated as
2027      "cannot move" due to (fixed) wrong element initialization in "src/init.c"
2028   */
2029 }
2030
2031 static int get_key_element_from_nr(int key_nr)
2032 {
2033   int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
2034                           level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2035                           EL_EM_KEY_1 : EL_KEY_1);
2036
2037   return key_base_element + key_nr;
2038 }
2039
2040 static int get_next_dropped_element(struct PlayerInfo *player)
2041 {
2042   return (player->inventory_size > 0 ?
2043           player->inventory_element[player->inventory_size - 1] :
2044           player->inventory_infinite_element != EL_UNDEFINED ?
2045           player->inventory_infinite_element :
2046           player->dynabombs_left > 0 ?
2047           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
2048           EL_UNDEFINED);
2049 }
2050
2051 static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
2052 {
2053   // pos >= 0: get element from bottom of the stack;
2054   // pos <  0: get element from top of the stack
2055
2056   if (pos < 0)
2057   {
2058     int min_inventory_size = -pos;
2059     int inventory_pos = player->inventory_size - min_inventory_size;
2060     int min_dynabombs_left = min_inventory_size - player->inventory_size;
2061
2062     return (player->inventory_size >= min_inventory_size ?
2063             player->inventory_element[inventory_pos] :
2064             player->inventory_infinite_element != EL_UNDEFINED ?
2065             player->inventory_infinite_element :
2066             player->dynabombs_left >= min_dynabombs_left ?
2067             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2068             EL_UNDEFINED);
2069   }
2070   else
2071   {
2072     int min_dynabombs_left = pos + 1;
2073     int min_inventory_size = pos + 1 - player->dynabombs_left;
2074     int inventory_pos = pos - player->dynabombs_left;
2075
2076     return (player->inventory_infinite_element != EL_UNDEFINED ?
2077             player->inventory_infinite_element :
2078             player->dynabombs_left >= min_dynabombs_left ?
2079             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2080             player->inventory_size >= min_inventory_size ?
2081             player->inventory_element[inventory_pos] :
2082             EL_UNDEFINED);
2083   }
2084 }
2085
2086 static int compareGamePanelOrderInfo(const void *object1, const void *object2)
2087 {
2088   const struct GamePanelOrderInfo *gpo1 = (struct GamePanelOrderInfo *)object1;
2089   const struct GamePanelOrderInfo *gpo2 = (struct GamePanelOrderInfo *)object2;
2090   int compare_result;
2091
2092   if (gpo1->sort_priority != gpo2->sort_priority)
2093     compare_result = gpo1->sort_priority - gpo2->sort_priority;
2094   else
2095     compare_result = gpo1->nr - gpo2->nr;
2096
2097   return compare_result;
2098 }
2099
2100 int getPlayerInventorySize(int player_nr)
2101 {
2102   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2103     return level.native_em_level->ply[player_nr]->dynamite;
2104   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2105     return level.native_sp_level->game_sp->red_disk_count;
2106   else
2107     return stored_player[player_nr].inventory_size;
2108 }
2109
2110 static void InitGameControlValues(void)
2111 {
2112   int i;
2113
2114   for (i = 0; game_panel_controls[i].nr != -1; i++)
2115   {
2116     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2117     struct GamePanelOrderInfo *gpo = &game_panel_order[i];
2118     struct TextPosInfo *pos = gpc->pos;
2119     int nr = gpc->nr;
2120     int type = gpc->type;
2121
2122     if (nr != i)
2123     {
2124       Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i);
2125       Error(ERR_EXIT, "this should not happen -- please debug");
2126     }
2127
2128     // force update of game controls after initialization
2129     gpc->value = gpc->last_value = -1;
2130     gpc->frame = gpc->last_frame = -1;
2131     gpc->gfx_frame = -1;
2132
2133     // determine panel value width for later calculation of alignment
2134     if (type == TYPE_INTEGER || type == TYPE_STRING)
2135     {
2136       pos->width = pos->size * getFontWidth(pos->font);
2137       pos->height = getFontHeight(pos->font);
2138     }
2139     else if (type == TYPE_ELEMENT)
2140     {
2141       pos->width = pos->size;
2142       pos->height = pos->size;
2143     }
2144
2145     // fill structure for game panel draw order
2146     gpo->nr = gpc->nr;
2147     gpo->sort_priority = pos->sort_priority;
2148   }
2149
2150   // sort game panel controls according to sort_priority and control number
2151   qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
2152         sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
2153 }
2154
2155 static void UpdatePlayfieldElementCount(void)
2156 {
2157   boolean use_element_count = FALSE;
2158   int i, j, x, y;
2159
2160   // first check if it is needed at all to calculate playfield element count
2161   for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++)
2162     if (!PANEL_DEACTIVATED(game_panel_controls[i].pos))
2163       use_element_count = TRUE;
2164
2165   if (!use_element_count)
2166     return;
2167
2168   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2169     element_info[i].element_count = 0;
2170
2171   SCAN_PLAYFIELD(x, y)
2172   {
2173     element_info[Feld[x][y]].element_count++;
2174   }
2175
2176   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
2177     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2178       if (IS_IN_GROUP(j, i))
2179         element_info[EL_GROUP_START + i].element_count +=
2180           element_info[j].element_count;
2181 }
2182
2183 static void UpdateGameControlValues(void)
2184 {
2185   int i, k;
2186   int time = (local_player->LevelSolved ?
2187               local_player->LevelSolved_CountingTime :
2188               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2189               level.native_em_level->lev->time :
2190               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2191               level.native_sp_level->game_sp->time_played :
2192               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2193               game_mm.energy_left :
2194               game.no_time_limit ? TimePlayed : TimeLeft);
2195   int score = (local_player->LevelSolved ?
2196                local_player->LevelSolved_CountingScore :
2197                level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2198                level.native_em_level->lev->score :
2199                level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2200                level.native_sp_level->game_sp->score :
2201                level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2202                game_mm.score :
2203                local_player->score);
2204   int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2205               level.native_em_level->lev->required :
2206               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2207               level.native_sp_level->game_sp->infotrons_still_needed :
2208               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2209               game_mm.kettles_still_needed :
2210               local_player->gems_still_needed);
2211   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2212                      level.native_em_level->lev->required > 0 :
2213                      level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2214                      level.native_sp_level->game_sp->infotrons_still_needed > 0 :
2215                      level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2216                      game_mm.kettles_still_needed > 0 ||
2217                      game_mm.lights_still_needed > 0 :
2218                      local_player->gems_still_needed > 0 ||
2219                      local_player->sokoban_fields_still_needed > 0 ||
2220                      local_player->sokoban_objects_still_needed > 0 ||
2221                      local_player->lights_still_needed > 0);
2222   int health = (local_player->LevelSolved ?
2223                 local_player->LevelSolved_CountingHealth :
2224                 level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2225                 MM_HEALTH(game_mm.laser_overload_value) :
2226                 local_player->health);
2227
2228   UpdatePlayfieldElementCount();
2229
2230   // update game panel control values
2231
2232   // used instead of "level_nr" (for network games)
2233   game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = levelset.level_nr;
2234   game_panel_controls[GAME_PANEL_GEMS].value = gems;
2235
2236   game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
2237   for (i = 0; i < MAX_NUM_KEYS; i++)
2238     game_panel_controls[GAME_PANEL_KEY_1 + i].value = EL_EMPTY;
2239   game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_EMPTY;
2240   game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value = 0;
2241
2242   if (game.centered_player_nr == -1)
2243   {
2244     for (i = 0; i < MAX_PLAYERS; i++)
2245     {
2246       // only one player in Supaplex game engine
2247       if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
2248         break;
2249
2250       for (k = 0; k < MAX_NUM_KEYS; k++)
2251       {
2252         if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2253         {
2254           if (level.native_em_level->ply[i]->keys & (1 << k))
2255             game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2256               get_key_element_from_nr(k);
2257         }
2258         else if (stored_player[i].key[k])
2259           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2260             get_key_element_from_nr(k);
2261       }
2262
2263       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2264         getPlayerInventorySize(i);
2265
2266       if (stored_player[i].num_white_keys > 0)
2267         game_panel_controls[GAME_PANEL_KEY_WHITE].value =
2268           EL_DC_KEY_WHITE;
2269
2270       game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2271         stored_player[i].num_white_keys;
2272     }
2273   }
2274   else
2275   {
2276     int player_nr = game.centered_player_nr;
2277
2278     for (k = 0; k < MAX_NUM_KEYS; k++)
2279     {
2280       if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2281       {
2282         if (level.native_em_level->ply[player_nr]->keys & (1 << k))
2283           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2284             get_key_element_from_nr(k);
2285       }
2286       else if (stored_player[player_nr].key[k])
2287         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2288           get_key_element_from_nr(k);
2289     }
2290
2291     game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2292       getPlayerInventorySize(player_nr);
2293
2294     if (stored_player[player_nr].num_white_keys > 0)
2295       game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
2296
2297     game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2298       stored_player[player_nr].num_white_keys;
2299   }
2300
2301   for (i = 0; i < NUM_PANEL_INVENTORY; i++)
2302   {
2303     game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value =
2304       get_inventory_element_from_pos(local_player, i);
2305     game_panel_controls[GAME_PANEL_INVENTORY_LAST_1 + i].value =
2306       get_inventory_element_from_pos(local_player, -i - 1);
2307   }
2308
2309   game_panel_controls[GAME_PANEL_SCORE].value = score;
2310   game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
2311
2312   game_panel_controls[GAME_PANEL_TIME].value = time;
2313
2314   game_panel_controls[GAME_PANEL_TIME_HH].value = time / 3600;
2315   game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
2316   game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
2317
2318   if (level.time == 0)
2319     game_panel_controls[GAME_PANEL_TIME_ANIM].value = 100;
2320   else
2321     game_panel_controls[GAME_PANEL_TIME_ANIM].value = time * 100 / level.time;
2322
2323   game_panel_controls[GAME_PANEL_HEALTH].value = health;
2324   game_panel_controls[GAME_PANEL_HEALTH_ANIM].value = health;
2325
2326   game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter;
2327
2328   game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
2329     (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
2330      EL_EMPTY);
2331   game_panel_controls[GAME_PANEL_SHIELD_NORMAL_TIME].value =
2332     local_player->shield_normal_time_left;
2333   game_panel_controls[GAME_PANEL_SHIELD_DEADLY].value =
2334     (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
2335      EL_EMPTY);
2336   game_panel_controls[GAME_PANEL_SHIELD_DEADLY_TIME].value =
2337     local_player->shield_deadly_time_left;
2338
2339   game_panel_controls[GAME_PANEL_EXIT].value =
2340     (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
2341
2342   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL].value =
2343     (game.ball_state ? EL_EMC_MAGIC_BALL_ACTIVE : EL_EMC_MAGIC_BALL);
2344   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL_SWITCH].value =
2345     (game.ball_state ? EL_EMC_MAGIC_BALL_SWITCH_ACTIVE :
2346      EL_EMC_MAGIC_BALL_SWITCH);
2347
2348   game_panel_controls[GAME_PANEL_LIGHT_SWITCH].value =
2349     (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
2350   game_panel_controls[GAME_PANEL_LIGHT_SWITCH_TIME].value =
2351     game.light_time_left;
2352
2353   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH].value =
2354     (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
2355   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH_TIME].value =
2356     game.timegate_time_left;
2357
2358   game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
2359     EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
2360
2361   game_panel_controls[GAME_PANEL_EMC_LENSES].value =
2362     (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
2363   game_panel_controls[GAME_PANEL_EMC_LENSES_TIME].value =
2364     game.lenses_time_left;
2365
2366   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER].value =
2367     (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
2368   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER_TIME].value =
2369     game.magnify_time_left;
2370
2371   game_panel_controls[GAME_PANEL_BALLOON_SWITCH].value =
2372     (game.wind_direction == MV_LEFT  ? EL_BALLOON_SWITCH_LEFT  :
2373      game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
2374      game.wind_direction == MV_UP    ? EL_BALLOON_SWITCH_UP    :
2375      game.wind_direction == MV_DOWN  ? EL_BALLOON_SWITCH_DOWN  :
2376      EL_BALLOON_SWITCH_NONE);
2377
2378   game_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
2379     local_player->dynabomb_count;
2380   game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
2381     local_player->dynabomb_size;
2382   game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
2383     (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
2384
2385   game_panel_controls[GAME_PANEL_PENGUINS].value =
2386     local_player->friends_still_needed;
2387
2388   game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
2389     local_player->sokoban_objects_still_needed;
2390   game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
2391     local_player->sokoban_fields_still_needed;
2392
2393   game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
2394     (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
2395
2396   for (i = 0; i < NUM_BELTS; i++)
2397   {
2398     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1 + i].value =
2399       (game.belt_dir[i] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
2400        EL_CONVEYOR_BELT_1_MIDDLE) + i;
2401     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH + i].value =
2402       getBeltSwitchElementFromBeltNrAndBeltDir(i, game.belt_dir[i]);
2403   }
2404
2405   game_panel_controls[GAME_PANEL_MAGIC_WALL].value =
2406     (game.magic_wall_active ? EL_MAGIC_WALL_ACTIVE : EL_MAGIC_WALL);
2407   game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
2408     game.magic_wall_time_left;
2409
2410   game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
2411     local_player->gravity;
2412
2413   for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
2414     game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
2415
2416   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2417     game_panel_controls[GAME_PANEL_ELEMENT_1 + i].value =
2418       (IS_DRAWABLE_ELEMENT(game.panel.element[i].id) ?
2419        game.panel.element[i].id : EL_UNDEFINED);
2420
2421   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2422     game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value =
2423       (IS_VALID_ELEMENT(game.panel.element_count[i].id) ?
2424        element_info[game.panel.element_count[i].id].element_count : 0);
2425
2426   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2427     game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value =
2428       (IS_CUSTOM_ELEMENT(game.panel.ce_score[i].id) ?
2429        element_info[game.panel.ce_score[i].id].collect_score : 0);
2430
2431   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2432     game_panel_controls[GAME_PANEL_CE_SCORE_1_ELEMENT + i].value =
2433       (IS_CUSTOM_ELEMENT(game.panel.ce_score_element[i].id) ?
2434        element_info[game.panel.ce_score_element[i].id].collect_score :
2435        EL_UNDEFINED);
2436
2437   game_panel_controls[GAME_PANEL_PLAYER_NAME].value = 0;
2438   game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
2439   game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
2440
2441   // update game panel control frames
2442
2443   for (i = 0; game_panel_controls[i].nr != -1; i++)
2444   {
2445     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2446
2447     if (gpc->type == TYPE_ELEMENT)
2448     {
2449       if (gpc->value != EL_UNDEFINED && gpc->value != EL_EMPTY)
2450       {
2451         int last_anim_random_frame = gfx.anim_random_frame;
2452         int element = gpc->value;
2453         int graphic = el2panelimg(element);
2454
2455         if (gpc->value != gpc->last_value)
2456         {
2457           gpc->gfx_frame = 0;
2458           gpc->gfx_random = INIT_GFX_RANDOM();
2459         }
2460         else
2461         {
2462           gpc->gfx_frame++;
2463
2464           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2465               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2466             gpc->gfx_random = INIT_GFX_RANDOM();
2467         }
2468
2469         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2470           gfx.anim_random_frame = gpc->gfx_random;
2471
2472         if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
2473           gpc->gfx_frame = element_info[element].collect_score;
2474
2475         gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
2476                                               gpc->gfx_frame);
2477
2478         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2479           gfx.anim_random_frame = last_anim_random_frame;
2480       }
2481     }
2482     else if (gpc->type == TYPE_GRAPHIC)
2483     {
2484       if (gpc->graphic != IMG_UNDEFINED)
2485       {
2486         int last_anim_random_frame = gfx.anim_random_frame;
2487         int graphic = gpc->graphic;
2488
2489         if (gpc->value != gpc->last_value)
2490         {
2491           gpc->gfx_frame = 0;
2492           gpc->gfx_random = INIT_GFX_RANDOM();
2493         }
2494         else
2495         {
2496           gpc->gfx_frame++;
2497
2498           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2499               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2500             gpc->gfx_random = INIT_GFX_RANDOM();
2501         }
2502
2503         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2504           gfx.anim_random_frame = gpc->gfx_random;
2505
2506         gpc->frame = getGraphicAnimationFrame(graphic, gpc->gfx_frame);
2507
2508         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2509           gfx.anim_random_frame = last_anim_random_frame;
2510       }
2511     }
2512   }
2513 }
2514
2515 static void DisplayGameControlValues(void)
2516 {
2517   boolean redraw_panel = FALSE;
2518   int i;
2519
2520   for (i = 0; game_panel_controls[i].nr != -1; i++)
2521   {
2522     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2523
2524     if (PANEL_DEACTIVATED(gpc->pos))
2525       continue;
2526
2527     if (gpc->value == gpc->last_value &&
2528         gpc->frame == gpc->last_frame)
2529       continue;
2530
2531     redraw_panel = TRUE;
2532   }
2533
2534   if (!redraw_panel)
2535     return;
2536
2537   // copy default game door content to main double buffer
2538
2539   // !!! CHECK AGAIN !!!
2540   SetPanelBackground();
2541   // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
2542   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2543
2544   // redraw game control buttons
2545   RedrawGameButtons();
2546
2547   SetGameStatus(GAME_MODE_PSEUDO_PANEL);
2548
2549   for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
2550   {
2551     int nr = game_panel_order[i].nr;
2552     struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
2553     struct TextPosInfo *pos = gpc->pos;
2554     int type = gpc->type;
2555     int value = gpc->value;
2556     int frame = gpc->frame;
2557     int size = pos->size;
2558     int font = pos->font;
2559     boolean draw_masked = pos->draw_masked;
2560     int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_OPAQUE);
2561
2562     if (PANEL_DEACTIVATED(pos))
2563       continue;
2564
2565     gpc->last_value = value;
2566     gpc->last_frame = frame;
2567
2568     if (type == TYPE_INTEGER)
2569     {
2570       if (nr == GAME_PANEL_LEVEL_NUMBER ||
2571           nr == GAME_PANEL_TIME)
2572       {
2573         boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
2574
2575         if (use_dynamic_size)           // use dynamic number of digits
2576         {
2577           int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
2578           int size1 = (nr == GAME_PANEL_LEVEL_NUMBER ? 2 : 3);
2579           int size2 = size1 + 1;
2580           int font1 = pos->font;
2581           int font2 = pos->font_alt;
2582
2583           size = (value < value_change ? size1 : size2);
2584           font = (value < value_change ? font1 : font2);
2585         }
2586       }
2587
2588       // correct text size if "digits" is zero or less
2589       if (size <= 0)
2590         size = strlen(int2str(value, size));
2591
2592       // dynamically correct text alignment
2593       pos->width = size * getFontWidth(font);
2594
2595       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2596                   int2str(value, size), font, mask_mode);
2597     }
2598     else if (type == TYPE_ELEMENT)
2599     {
2600       int element, graphic;
2601       Bitmap *src_bitmap;
2602       int src_x, src_y;
2603       int width, height;
2604       int dst_x = PANEL_XPOS(pos);
2605       int dst_y = PANEL_YPOS(pos);
2606
2607       if (value != EL_UNDEFINED && value != EL_EMPTY)
2608       {
2609         element = value;
2610         graphic = el2panelimg(value);
2611
2612         // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
2613
2614         if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
2615           size = TILESIZE;
2616
2617         getSizedGraphicSource(graphic, frame, size, &src_bitmap,
2618                               &src_x, &src_y);
2619
2620         width  = graphic_info[graphic].width  * size / TILESIZE;
2621         height = graphic_info[graphic].height * size / TILESIZE;
2622
2623         if (draw_masked)
2624           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2625                            dst_x, dst_y);
2626         else
2627           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2628                      dst_x, dst_y);
2629       }
2630     }
2631     else if (type == TYPE_GRAPHIC)
2632     {
2633       int graphic        = gpc->graphic;
2634       int graphic_active = gpc->graphic_active;
2635       Bitmap *src_bitmap;
2636       int src_x, src_y;
2637       int width, height;
2638       int dst_x = PANEL_XPOS(pos);
2639       int dst_y = PANEL_YPOS(pos);
2640       boolean skip = (pos->class == get_hash_from_key("mm_engine_only") &&
2641                       level.game_engine_type != GAME_ENGINE_TYPE_MM);
2642
2643       if (graphic != IMG_UNDEFINED && !skip)
2644       {
2645         if (pos->style == STYLE_REVERSE)
2646           value = 100 - value;
2647
2648         getGraphicSource(graphic_active, frame, &src_bitmap, &src_x, &src_y);
2649
2650         if (pos->direction & MV_HORIZONTAL)
2651         {
2652           width  = graphic_info[graphic_active].width * value / 100;
2653           height = graphic_info[graphic_active].height;
2654
2655           if (pos->direction == MV_LEFT)
2656           {
2657             src_x += graphic_info[graphic_active].width - width;
2658             dst_x += graphic_info[graphic_active].width - width;
2659           }
2660         }
2661         else
2662         {
2663           width  = graphic_info[graphic_active].width;
2664           height = graphic_info[graphic_active].height * value / 100;
2665
2666           if (pos->direction == MV_UP)
2667           {
2668             src_y += graphic_info[graphic_active].height - height;
2669             dst_y += graphic_info[graphic_active].height - height;
2670           }
2671         }
2672
2673         if (draw_masked)
2674           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2675                            dst_x, dst_y);
2676         else
2677           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2678                      dst_x, dst_y);
2679
2680         getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2681
2682         if (pos->direction & MV_HORIZONTAL)
2683         {
2684           if (pos->direction == MV_RIGHT)
2685           {
2686             src_x += width;
2687             dst_x += width;
2688           }
2689           else
2690           {
2691             dst_x = PANEL_XPOS(pos);
2692           }
2693
2694           width = graphic_info[graphic].width - width;
2695         }
2696         else
2697         {
2698           if (pos->direction == MV_DOWN)
2699           {
2700             src_y += height;
2701             dst_y += height;
2702           }
2703           else
2704           {
2705             dst_y = PANEL_YPOS(pos);
2706           }
2707
2708           height = graphic_info[graphic].height - height;
2709         }
2710
2711         if (draw_masked)
2712           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2713                            dst_x, dst_y);
2714         else
2715           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2716                      dst_x, dst_y);
2717       }
2718     }
2719     else if (type == TYPE_STRING)
2720     {
2721       boolean active = (value != 0);
2722       char *state_normal = "off";
2723       char *state_active = "on";
2724       char *state = (active ? state_active : state_normal);
2725       char *s = (nr == GAME_PANEL_GRAVITY_STATE ? state :
2726                  nr == GAME_PANEL_PLAYER_NAME   ? setup.player_name :
2727                  nr == GAME_PANEL_LEVEL_NAME    ? level.name :
2728                  nr == GAME_PANEL_LEVEL_AUTHOR  ? level.author : NULL);
2729
2730       if (nr == GAME_PANEL_GRAVITY_STATE)
2731       {
2732         int font1 = pos->font;          // (used for normal state)
2733         int font2 = pos->font_alt;      // (used for active state)
2734
2735         font = (active ? font2 : font1);
2736       }
2737
2738       if (s != NULL)
2739       {
2740         char *s_cut;
2741
2742         if (size <= 0)
2743         {
2744           // don't truncate output if "chars" is zero or less
2745           size = strlen(s);
2746
2747           // dynamically correct text alignment
2748           pos->width = size * getFontWidth(font);
2749         }
2750
2751         s_cut = getStringCopyN(s, size);
2752
2753         DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2754                     s_cut, font, mask_mode);
2755
2756         free(s_cut);
2757       }
2758     }
2759
2760     redraw_mask |= REDRAW_DOOR_1;
2761   }
2762
2763   SetGameStatus(GAME_MODE_PLAYING);
2764 }
2765
2766 void UpdateAndDisplayGameControlValues(void)
2767 {
2768   if (tape.deactivate_display)
2769     return;
2770
2771   UpdateGameControlValues();
2772   DisplayGameControlValues();
2773 }
2774
2775 #if 0
2776 static void UpdateGameDoorValues(void)
2777 {
2778   UpdateGameControlValues();
2779 }
2780 #endif
2781
2782 void DrawGameDoorValues(void)
2783 {
2784   DisplayGameControlValues();
2785 }
2786
2787
2788 // ============================================================================
2789 // InitGameEngine()
2790 // ----------------------------------------------------------------------------
2791 // initialize game engine due to level / tape version number
2792 // ============================================================================
2793
2794 static void InitGameEngine(void)
2795 {
2796   int i, j, k, l, x, y;
2797
2798   // set game engine from tape file when re-playing, else from level file
2799   game.engine_version = (tape.playing ? tape.engine_version :
2800                          level.game_version);
2801
2802   // set single or multi-player game mode (needed for re-playing tapes)
2803   game.team_mode = setup.team_mode;
2804
2805   if (tape.playing)
2806   {
2807     int num_players = 0;
2808
2809     for (i = 0; i < MAX_PLAYERS; i++)
2810       if (tape.player_participates[i])
2811         num_players++;
2812
2813     // multi-player tapes contain input data for more than one player
2814     game.team_mode = (num_players > 1);
2815   }
2816
2817   // --------------------------------------------------------------------------
2818   // set flags for bugs and changes according to active game engine version
2819   // --------------------------------------------------------------------------
2820
2821   /*
2822     Summary of bugfix/change:
2823     Fixed handling for custom elements that change when pushed by the player.
2824
2825     Fixed/changed in version:
2826     3.1.0
2827
2828     Description:
2829     Before 3.1.0, custom elements that "change when pushing" changed directly
2830     after the player started pushing them (until then handled in "DigField()").
2831     Since 3.1.0, these custom elements are not changed until the "pushing"
2832     move of the element is finished (now handled in "ContinueMoving()").
2833
2834     Affected levels/tapes:
2835     The first condition is generally needed for all levels/tapes before version
2836     3.1.0, which might use the old behaviour before it was changed; known tapes
2837     that are affected are some tapes from the level set "Walpurgis Gardens" by
2838     Jamie Cullen.
2839     The second condition is an exception from the above case and is needed for
2840     the special case of tapes recorded with game (not engine!) version 3.1.0 or
2841     above (including some development versions of 3.1.0), but before it was
2842     known that this change would break tapes like the above and was fixed in
2843     3.1.1, so that the changed behaviour was active although the engine version
2844     while recording maybe was before 3.1.0. There is at least one tape that is
2845     affected by this exception, which is the tape for the one-level set "Bug
2846     Machine" by Juergen Bonhagen.
2847   */
2848
2849   game.use_change_when_pushing_bug =
2850     (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2851      !(tape.playing &&
2852        tape.game_version >= VERSION_IDENT(3,1,0,0) &&
2853        tape.game_version <  VERSION_IDENT(3,1,1,0)));
2854
2855   /*
2856     Summary of bugfix/change:
2857     Fixed handling for blocking the field the player leaves when moving.
2858
2859     Fixed/changed in version:
2860     3.1.1
2861
2862     Description:
2863     Before 3.1.1, when "block last field when moving" was enabled, the field
2864     the player is leaving when moving was blocked for the time of the move,
2865     and was directly unblocked afterwards. This resulted in the last field
2866     being blocked for exactly one less than the number of frames of one player
2867     move. Additionally, even when blocking was disabled, the last field was
2868     blocked for exactly one frame.
2869     Since 3.1.1, due to changes in player movement handling, the last field
2870     is not blocked at all when blocking is disabled. When blocking is enabled,
2871     the last field is blocked for exactly the number of frames of one player
2872     move. Additionally, if the player is Murphy, the hero of Supaplex, the
2873     last field is blocked for exactly one more than the number of frames of
2874     one player move.
2875
2876     Affected levels/tapes:
2877     (!!! yet to be determined -- probably many !!!)
2878   */
2879
2880   game.use_block_last_field_bug =
2881     (game.engine_version < VERSION_IDENT(3,1,1,0));
2882
2883   game_em.use_single_button =
2884     (game.engine_version > VERSION_IDENT(4,0,0,2));
2885
2886   game_em.use_snap_key_bug =
2887     (game.engine_version < VERSION_IDENT(4,0,1,0));
2888
2889   // --------------------------------------------------------------------------
2890
2891   // set maximal allowed number of custom element changes per game frame
2892   game.max_num_changes_per_frame = 1;
2893
2894   // default scan direction: scan playfield from top/left to bottom/right
2895   InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
2896
2897   // dynamically adjust element properties according to game engine version
2898   InitElementPropertiesEngine(game.engine_version);
2899
2900 #if 0
2901   printf("level %d: level version == %06d\n", level_nr, level.game_version);
2902   printf("          tape version == %06d [%s] [file: %06d]\n",
2903          tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
2904          tape.file_version);
2905   printf("       => game.engine_version == %06d\n", game.engine_version);
2906 #endif
2907
2908   // ---------- initialize player's initial move delay ------------------------
2909
2910   // dynamically adjust player properties according to level information
2911   for (i = 0; i < MAX_PLAYERS; i++)
2912     game.initial_move_delay_value[i] =
2913       get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
2914
2915   // dynamically adjust player properties according to game engine version
2916   for (i = 0; i < MAX_PLAYERS; i++)
2917     game.initial_move_delay[i] =
2918       (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
2919        game.initial_move_delay_value[i] : 0);
2920
2921   // ---------- initialize player's initial push delay ------------------------
2922
2923   // dynamically adjust player properties according to game engine version
2924   game.initial_push_delay_value =
2925     (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1);
2926
2927   // ---------- initialize changing elements ----------------------------------
2928
2929   // initialize changing elements information
2930   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2931   {
2932     struct ElementInfo *ei = &element_info[i];
2933
2934     // this pointer might have been changed in the level editor
2935     ei->change = &ei->change_page[0];
2936
2937     if (!IS_CUSTOM_ELEMENT(i))
2938     {
2939       ei->change->target_element = EL_EMPTY_SPACE;
2940       ei->change->delay_fixed = 0;
2941       ei->change->delay_random = 0;
2942       ei->change->delay_frames = 1;
2943     }
2944
2945     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2946     {
2947       ei->has_change_event[j] = FALSE;
2948
2949       ei->event_page_nr[j] = 0;
2950       ei->event_page[j] = &ei->change_page[0];
2951     }
2952   }
2953
2954   // add changing elements from pre-defined list
2955   for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++)
2956   {
2957     struct ChangingElementInfo *ch_delay = &change_delay_list[i];
2958     struct ElementInfo *ei = &element_info[ch_delay->element];
2959
2960     ei->change->target_element       = ch_delay->target_element;
2961     ei->change->delay_fixed          = ch_delay->change_delay;
2962
2963     ei->change->pre_change_function  = ch_delay->pre_change_function;
2964     ei->change->change_function      = ch_delay->change_function;
2965     ei->change->post_change_function = ch_delay->post_change_function;
2966
2967     ei->change->can_change = TRUE;
2968     ei->change->can_change_or_has_action = TRUE;
2969
2970     ei->has_change_event[CE_DELAY] = TRUE;
2971
2972     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
2973     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
2974   }
2975
2976   // ---------- initialize internal run-time variables ------------------------
2977
2978   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2979   {
2980     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2981
2982     for (j = 0; j < ei->num_change_pages; j++)
2983     {
2984       ei->change_page[j].can_change_or_has_action =
2985         (ei->change_page[j].can_change |
2986          ei->change_page[j].has_action);
2987     }
2988   }
2989
2990   // add change events from custom element configuration
2991   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2992   {
2993     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2994
2995     for (j = 0; j < ei->num_change_pages; j++)
2996     {
2997       if (!ei->change_page[j].can_change_or_has_action)
2998         continue;
2999
3000       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
3001       {
3002         // only add event page for the first page found with this event
3003         if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
3004         {
3005           ei->has_change_event[k] = TRUE;
3006
3007           ei->event_page_nr[k] = j;
3008           ei->event_page[k] = &ei->change_page[j];
3009         }
3010       }
3011     }
3012   }
3013
3014   // ---------- initialize reference elements in change conditions ------------
3015
3016   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3017   {
3018     int element = EL_CUSTOM_START + i;
3019     struct ElementInfo *ei = &element_info[element];
3020
3021     for (j = 0; j < ei->num_change_pages; j++)
3022     {
3023       int trigger_element = ei->change_page[j].initial_trigger_element;
3024
3025       if (trigger_element >= EL_PREV_CE_8 &&
3026           trigger_element <= EL_NEXT_CE_8)
3027         trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
3028
3029       ei->change_page[j].trigger_element = trigger_element;
3030     }
3031   }
3032
3033   // ---------- initialize run-time trigger player and element ----------------
3034
3035   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3036   {
3037     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
3038
3039     for (j = 0; j < ei->num_change_pages; j++)
3040     {
3041       ei->change_page[j].actual_trigger_element = EL_EMPTY;
3042       ei->change_page[j].actual_trigger_player = EL_EMPTY;
3043       ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
3044       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
3045       ei->change_page[j].actual_trigger_ce_value = 0;
3046       ei->change_page[j].actual_trigger_ce_score = 0;
3047     }
3048   }
3049
3050   // ---------- initialize trigger events -------------------------------------
3051
3052   // initialize trigger events information
3053   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3054     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
3055       trigger_events[i][j] = FALSE;
3056
3057   // add trigger events from element change event properties
3058   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3059   {
3060     struct ElementInfo *ei = &element_info[i];
3061
3062     for (j = 0; j < ei->num_change_pages; j++)
3063     {
3064       if (!ei->change_page[j].can_change_or_has_action)
3065         continue;
3066
3067       if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
3068       {
3069         int trigger_element = ei->change_page[j].trigger_element;
3070
3071         for (k = 0; k < NUM_CHANGE_EVENTS; k++)
3072         {
3073           if (ei->change_page[j].has_event[k])
3074           {
3075             if (IS_GROUP_ELEMENT(trigger_element))
3076             {
3077               struct ElementGroupInfo *group =
3078                 element_info[trigger_element].group;
3079
3080               for (l = 0; l < group->num_elements_resolved; l++)
3081                 trigger_events[group->element_resolved[l]][k] = TRUE;
3082             }
3083             else if (trigger_element == EL_ANY_ELEMENT)
3084               for (l = 0; l < MAX_NUM_ELEMENTS; l++)
3085                 trigger_events[l][k] = TRUE;
3086             else
3087               trigger_events[trigger_element][k] = TRUE;
3088           }
3089         }
3090       }
3091     }
3092   }
3093
3094   // ---------- initialize push delay -----------------------------------------
3095
3096   // initialize push delay values to default
3097   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3098   {
3099     if (!IS_CUSTOM_ELEMENT(i))
3100     {
3101       // set default push delay values (corrected since version 3.0.7-1)
3102       if (game.engine_version < VERSION_IDENT(3,0,7,1))
3103       {
3104         element_info[i].push_delay_fixed = 2;
3105         element_info[i].push_delay_random = 8;
3106       }
3107       else
3108       {
3109         element_info[i].push_delay_fixed = 8;
3110         element_info[i].push_delay_random = 8;
3111       }
3112     }
3113   }
3114
3115   // set push delay value for certain elements from pre-defined list
3116   for (i = 0; push_delay_list[i].element != EL_UNDEFINED; i++)
3117   {
3118     int e = push_delay_list[i].element;
3119
3120     element_info[e].push_delay_fixed  = push_delay_list[i].push_delay_fixed;
3121     element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
3122   }
3123
3124   // set push delay value for Supaplex elements for newer engine versions
3125   if (game.engine_version >= VERSION_IDENT(3,1,0,0))
3126   {
3127     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3128     {
3129       if (IS_SP_ELEMENT(i))
3130       {
3131         // set SP push delay to just enough to push under a falling zonk
3132         int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
3133
3134         element_info[i].push_delay_fixed  = delay;
3135         element_info[i].push_delay_random = 0;
3136       }
3137     }
3138   }
3139
3140   // ---------- initialize move stepsize --------------------------------------
3141
3142   // initialize move stepsize values to default
3143   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3144     if (!IS_CUSTOM_ELEMENT(i))
3145       element_info[i].move_stepsize = MOVE_STEPSIZE_NORMAL;
3146
3147   // set move stepsize value for certain elements from pre-defined list
3148   for (i = 0; move_stepsize_list[i].element != EL_UNDEFINED; i++)
3149   {
3150     int e = move_stepsize_list[i].element;
3151
3152     element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
3153   }
3154
3155   // ---------- initialize collect score --------------------------------------
3156
3157   // initialize collect score values for custom elements from initial value
3158   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3159     if (IS_CUSTOM_ELEMENT(i))
3160       element_info[i].collect_score = element_info[i].collect_score_initial;
3161
3162   // ---------- initialize collect count --------------------------------------
3163
3164   // initialize collect count values for non-custom elements
3165   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3166     if (!IS_CUSTOM_ELEMENT(i))
3167       element_info[i].collect_count_initial = 0;
3168
3169   // add collect count values for all elements from pre-defined list
3170   for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
3171     element_info[collect_count_list[i].element].collect_count_initial =
3172       collect_count_list[i].count;
3173
3174   // ---------- initialize access direction -----------------------------------
3175
3176   // initialize access direction values to default (access from every side)
3177   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3178     if (!IS_CUSTOM_ELEMENT(i))
3179       element_info[i].access_direction = MV_ALL_DIRECTIONS;
3180
3181   // set access direction value for certain elements from pre-defined list
3182   for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
3183     element_info[access_direction_list[i].element].access_direction =
3184       access_direction_list[i].direction;
3185
3186   // ---------- initialize explosion content ----------------------------------
3187   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3188   {
3189     if (IS_CUSTOM_ELEMENT(i))
3190       continue;
3191
3192     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
3193     {
3194       // (content for EL_YAMYAM set at run-time with game.yamyam_content_nr)
3195
3196       element_info[i].content.e[x][y] =
3197         (i == EL_PLAYER_1 ? EL_EMERALD_YELLOW :
3198          i == EL_PLAYER_2 ? EL_EMERALD_RED :
3199          i == EL_PLAYER_3 ? EL_EMERALD :
3200          i == EL_PLAYER_4 ? EL_EMERALD_PURPLE :
3201          i == EL_MOLE ? EL_EMERALD_RED :
3202          i == EL_PENGUIN ? EL_EMERALD_PURPLE :
3203          i == EL_BUG ? (x == 1 && y == 1 ? EL_DIAMOND : EL_EMERALD) :
3204          i == EL_BD_BUTTERFLY ? EL_BD_DIAMOND :
3205          i == EL_SP_ELECTRON ? EL_SP_INFOTRON :
3206          i == EL_AMOEBA_TO_DIAMOND ? level.amoeba_content :
3207          i == EL_WALL_EMERALD ? EL_EMERALD :
3208          i == EL_WALL_DIAMOND ? EL_DIAMOND :
3209          i == EL_WALL_BD_DIAMOND ? EL_BD_DIAMOND :
3210          i == EL_WALL_EMERALD_YELLOW ? EL_EMERALD_YELLOW :
3211          i == EL_WALL_EMERALD_RED ? EL_EMERALD_RED :
3212          i == EL_WALL_EMERALD_PURPLE ? EL_EMERALD_PURPLE :
3213          i == EL_WALL_PEARL ? EL_PEARL :
3214          i == EL_WALL_CRYSTAL ? EL_CRYSTAL :
3215          EL_EMPTY);
3216     }
3217   }
3218
3219   // ---------- initialize recursion detection --------------------------------
3220   recursion_loop_depth = 0;
3221   recursion_loop_detected = FALSE;
3222   recursion_loop_element = EL_UNDEFINED;
3223
3224   // ---------- initialize graphics engine ------------------------------------
3225   game.scroll_delay_value =
3226     (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
3227      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
3228   game.scroll_delay_value =
3229     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
3230
3231   // ---------- initialize game engine snapshots ------------------------------
3232   for (i = 0; i < MAX_PLAYERS; i++)
3233     game.snapshot.last_action[i] = 0;
3234   game.snapshot.changed_action = FALSE;
3235   game.snapshot.collected_item = FALSE;
3236   game.snapshot.mode =
3237     (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
3238      SNAPSHOT_MODE_EVERY_STEP :
3239      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
3240      SNAPSHOT_MODE_EVERY_MOVE :
3241      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
3242      SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
3243   game.snapshot.save_snapshot = FALSE;
3244
3245   // ---------- initialize level time for Supaplex engine ---------------------
3246   // Supaplex levels with time limit currently unsupported -- should be added
3247   if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3248     level.time = 0;
3249 }
3250
3251 static int get_num_special_action(int element, int action_first,
3252                                   int action_last)
3253 {
3254   int num_special_action = 0;
3255   int i, j;
3256
3257   for (i = action_first; i <= action_last; i++)
3258   {
3259     boolean found = FALSE;
3260
3261     for (j = 0; j < NUM_DIRECTIONS; j++)
3262       if (el_act_dir2img(element, i, j) !=
3263           el_act_dir2img(element, ACTION_DEFAULT, j))
3264         found = TRUE;
3265
3266     if (found)
3267       num_special_action++;
3268     else
3269       break;
3270   }
3271
3272   return num_special_action;
3273 }
3274
3275
3276 // ============================================================================
3277 // InitGame()
3278 // ----------------------------------------------------------------------------
3279 // initialize and start new game
3280 // ============================================================================
3281
3282 #if DEBUG_INIT_PLAYER
3283 static void DebugPrintPlayerStatus(char *message)
3284 {
3285   int i;
3286
3287   if (!options.debug)
3288     return;
3289
3290   printf("%s:\n", message);
3291
3292   for (i = 0; i < MAX_PLAYERS; i++)
3293   {
3294     struct PlayerInfo *player = &stored_player[i];
3295
3296     printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
3297            i + 1,
3298            player->present,
3299            player->connected,
3300            player->connected_locally,
3301            player->connected_network,
3302            player->active);
3303
3304     if (local_player == player)
3305       printf(" (local player)");
3306
3307     printf("\n");
3308   }
3309 }
3310 #endif
3311
3312 void InitGame(void)
3313 {
3314   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
3315   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
3316   int fade_mask = REDRAW_FIELD;
3317
3318   boolean emulate_bd = TRUE;    // unless non-BOULDERDASH elements found
3319   boolean emulate_sb = TRUE;    // unless non-SOKOBAN     elements found
3320   boolean emulate_sp = TRUE;    // unless non-SUPAPLEX    elements found
3321   int initial_move_dir = MV_DOWN;
3322   int i, j, x, y;
3323
3324   // required here to update video display before fading (FIX THIS)
3325   DrawMaskedBorder(REDRAW_DOOR_2);
3326
3327   if (!game.restart_level)
3328     CloseDoor(DOOR_CLOSE_1);
3329
3330   SetGameStatus(GAME_MODE_PLAYING);
3331
3332   if (level_editor_test_game)
3333     FadeSkipNextFadeIn();
3334   else
3335     FadeSetEnterScreen();
3336
3337   if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged())
3338     fade_mask = REDRAW_ALL;
3339
3340   FadeLevelSoundsAndMusic();
3341
3342   ExpireSoundLoops(TRUE);
3343
3344   FadeOut(fade_mask);
3345
3346   // needed if different viewport properties defined for playing
3347   ChangeViewportPropertiesIfNeeded();
3348
3349   ClearField();
3350
3351   DrawCompleteVideoDisplay();
3352
3353   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
3354
3355   InitGameEngine();
3356   InitGameControlValues();
3357
3358   // don't play tapes over network
3359   network_playing = (network.enabled && !tape.playing);
3360
3361   for (i = 0; i < MAX_PLAYERS; i++)
3362   {
3363     struct PlayerInfo *player = &stored_player[i];
3364
3365     player->index_nr = i;
3366     player->index_bit = (1 << i);
3367     player->element_nr = EL_PLAYER_1 + i;
3368
3369     player->present = FALSE;
3370     player->active = FALSE;
3371     player->mapped = FALSE;
3372
3373     player->killed = FALSE;
3374     player->reanimated = FALSE;
3375
3376     player->action = 0;
3377     player->effective_action = 0;
3378     player->programmed_action = 0;
3379
3380     player->mouse_action.lx = 0;
3381     player->mouse_action.ly = 0;
3382     player->mouse_action.button = 0;
3383     player->mouse_action.button_hint = 0;
3384
3385     player->effective_mouse_action.lx = 0;
3386     player->effective_mouse_action.ly = 0;
3387     player->effective_mouse_action.button = 0;
3388     player->effective_mouse_action.button_hint = 0;
3389
3390     player->score = 0;
3391     player->score_final = 0;
3392
3393     player->health = MAX_HEALTH;
3394     player->health_final = MAX_HEALTH;
3395
3396     player->gems_still_needed = level.gems_needed;
3397     player->sokoban_fields_still_needed = 0;
3398     player->sokoban_objects_still_needed = 0;
3399     player->lights_still_needed = 0;
3400     player->players_still_needed = 0;
3401     player->friends_still_needed = 0;
3402
3403     for (j = 0; j < MAX_NUM_KEYS; j++)
3404       player->key[j] = FALSE;
3405
3406     player->num_white_keys = 0;
3407
3408     player->dynabomb_count = 0;
3409     player->dynabomb_size = 1;
3410     player->dynabombs_left = 0;
3411     player->dynabomb_xl = FALSE;
3412
3413     player->MovDir = initial_move_dir;
3414     player->MovPos = 0;
3415     player->GfxPos = 0;
3416     player->GfxDir = initial_move_dir;
3417     player->GfxAction = ACTION_DEFAULT;
3418     player->Frame = 0;
3419     player->StepFrame = 0;
3420
3421     player->initial_element = player->element_nr;
3422     player->artwork_element =
3423       (level.use_artwork_element[i] ? level.artwork_element[i] :
3424        player->element_nr);
3425     player->use_murphy = FALSE;
3426
3427     player->block_last_field = FALSE;   // initialized in InitPlayerField()
3428     player->block_delay_adjustment = 0; // initialized in InitPlayerField()
3429
3430     player->gravity = level.initial_player_gravity[i];
3431
3432     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
3433
3434     player->actual_frame_counter = 0;
3435
3436     player->step_counter = 0;
3437
3438     player->last_move_dir = initial_move_dir;
3439
3440     player->is_active = FALSE;
3441
3442     player->is_waiting = FALSE;
3443     player->is_moving = FALSE;
3444     player->is_auto_moving = FALSE;
3445     player->is_digging = FALSE;
3446     player->is_snapping = FALSE;
3447     player->is_collecting = FALSE;
3448     player->is_pushing = FALSE;
3449     player->is_switching = FALSE;
3450     player->is_dropping = FALSE;
3451     player->is_dropping_pressed = FALSE;
3452
3453     player->is_bored = FALSE;
3454     player->is_sleeping = FALSE;
3455
3456     player->was_waiting = TRUE;
3457     player->was_moving = FALSE;
3458     player->was_snapping = FALSE;
3459     player->was_dropping = FALSE;
3460
3461     player->force_dropping = FALSE;
3462
3463     player->frame_counter_bored = -1;
3464     player->frame_counter_sleeping = -1;
3465
3466     player->anim_delay_counter = 0;
3467     player->post_delay_counter = 0;
3468
3469     player->dir_waiting = initial_move_dir;
3470     player->action_waiting = ACTION_DEFAULT;
3471     player->last_action_waiting = ACTION_DEFAULT;
3472     player->special_action_bored = ACTION_DEFAULT;
3473     player->special_action_sleeping = ACTION_DEFAULT;
3474
3475     player->switch_x = -1;
3476     player->switch_y = -1;
3477
3478     player->drop_x = -1;
3479     player->drop_y = -1;
3480
3481     player->show_envelope = 0;
3482
3483     SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
3484
3485     player->push_delay       = -1;      // initialized when pushing starts
3486     player->push_delay_value = game.initial_push_delay_value;
3487
3488     player->drop_delay = 0;
3489     player->drop_pressed_delay = 0;
3490
3491     player->last_jx = -1;
3492     player->last_jy = -1;
3493     player->jx = -1;
3494     player->jy = -1;
3495
3496     player->shield_normal_time_left = 0;
3497     player->shield_deadly_time_left = 0;
3498
3499     player->inventory_infinite_element = EL_UNDEFINED;
3500     player->inventory_size = 0;
3501
3502     if (level.use_initial_inventory[i])
3503     {
3504       for (j = 0; j < level.initial_inventory_size[i]; j++)
3505       {
3506         int element = level.initial_inventory_content[i][j];
3507         int collect_count = element_info[element].collect_count_initial;
3508         int k;
3509
3510         if (!IS_CUSTOM_ELEMENT(element))
3511           collect_count = 1;
3512
3513         if (collect_count == 0)
3514           player->inventory_infinite_element = element;
3515         else
3516           for (k = 0; k < collect_count; k++)
3517             if (player->inventory_size < MAX_INVENTORY_SIZE)
3518               player->inventory_element[player->inventory_size++] = element;
3519       }
3520     }
3521
3522     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
3523     SnapField(player, 0, 0);
3524
3525     player->LevelSolved = FALSE;
3526     player->GameOver = FALSE;
3527
3528     player->LevelSolved_GameWon = FALSE;
3529     player->LevelSolved_GameEnd = FALSE;
3530     player->LevelSolved_SaveTape = FALSE;
3531     player->LevelSolved_SaveScore = FALSE;
3532
3533     player->LevelSolved_CountingTime = 0;
3534     player->LevelSolved_CountingScore = 0;
3535     player->LevelSolved_CountingHealth = 0;
3536
3537     map_player_action[i] = i;
3538   }
3539
3540   network_player_action_received = FALSE;
3541
3542   // initial null action
3543   if (network_playing)
3544     SendToServer_MovePlayer(MV_NONE);
3545
3546   ZX = ZY = -1;
3547   ExitX = ExitY = -1;
3548
3549   FrameCounter = 0;
3550   TimeFrames = 0;
3551   TimePlayed = 0;
3552   TimeLeft = level.time;
3553   TapeTime = 0;
3554
3555   ScreenMovDir = MV_NONE;
3556   ScreenMovPos = 0;
3557   ScreenGfxPos = 0;
3558
3559   ScrollStepSize = 0;   // will be correctly initialized by ScrollScreen()
3560
3561   AllPlayersGone = FALSE;
3562
3563   game.panel.active = TRUE;
3564
3565   game.no_time_limit = (level.time == 0);
3566
3567   game.yamyam_content_nr = 0;
3568   game.robot_wheel_active = FALSE;
3569   game.magic_wall_active = FALSE;
3570   game.magic_wall_time_left = 0;
3571   game.light_time_left = 0;
3572   game.timegate_time_left = 0;
3573   game.switchgate_pos = 0;
3574   game.wind_direction = level.wind_direction_initial;
3575
3576   game.lenses_time_left = 0;
3577   game.magnify_time_left = 0;
3578
3579   game.ball_state = level.ball_state_initial;
3580   game.ball_content_nr = 0;
3581
3582   game.explosions_delayed = TRUE;
3583
3584   game.envelope_active = FALSE;
3585
3586   for (i = 0; i < NUM_BELTS; i++)
3587   {
3588     game.belt_dir[i] = MV_NONE;
3589     game.belt_dir_nr[i] = 3;            // not moving, next moving left
3590   }
3591
3592   for (i = 0; i < MAX_NUM_AMOEBA; i++)
3593     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
3594
3595 #if DEBUG_INIT_PLAYER
3596   DebugPrintPlayerStatus("Player status at level initialization");
3597 #endif
3598
3599   SCAN_PLAYFIELD(x, y)
3600   {
3601     Feld[x][y] = Last[x][y] = level.field[x][y];
3602     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
3603     ChangeDelay[x][y] = 0;
3604     ChangePage[x][y] = -1;
3605     CustomValue[x][y] = 0;              // initialized in InitField()
3606     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
3607     AmoebaNr[x][y] = 0;
3608     WasJustMoving[x][y] = 0;
3609     WasJustFalling[x][y] = 0;
3610     CheckCollision[x][y] = 0;
3611     CheckImpact[x][y] = 0;
3612     Stop[x][y] = FALSE;
3613     Pushed[x][y] = FALSE;
3614
3615     ChangeCount[x][y] = 0;
3616     ChangeEvent[x][y] = -1;
3617
3618     ExplodePhase[x][y] = 0;
3619     ExplodeDelay[x][y] = 0;
3620     ExplodeField[x][y] = EX_TYPE_NONE;
3621
3622     RunnerVisit[x][y] = 0;
3623     PlayerVisit[x][y] = 0;
3624
3625     GfxFrame[x][y] = 0;
3626     GfxRandom[x][y] = INIT_GFX_RANDOM();
3627     GfxElement[x][y] = EL_UNDEFINED;
3628     GfxAction[x][y] = ACTION_DEFAULT;
3629     GfxDir[x][y] = MV_NONE;
3630     GfxRedraw[x][y] = GFX_REDRAW_NONE;
3631   }
3632
3633   SCAN_PLAYFIELD(x, y)
3634   {
3635     if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
3636       emulate_bd = FALSE;
3637     if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
3638       emulate_sb = FALSE;
3639     if (emulate_sp && !IS_SP_ELEMENT(Feld[x][y]))
3640       emulate_sp = FALSE;
3641
3642     InitField(x, y, TRUE);
3643
3644     ResetGfxAnimation(x, y);
3645   }
3646
3647   InitBeltMovement();
3648
3649   for (i = 0; i < MAX_PLAYERS; i++)
3650   {
3651     struct PlayerInfo *player = &stored_player[i];
3652
3653     // set number of special actions for bored and sleeping animation
3654     player->num_special_action_bored =
3655       get_num_special_action(player->artwork_element,
3656                              ACTION_BORING_1, ACTION_BORING_LAST);
3657     player->num_special_action_sleeping =
3658       get_num_special_action(player->artwork_element,
3659                              ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
3660   }
3661
3662   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
3663                     emulate_sb ? EMU_SOKOBAN :
3664                     emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
3665
3666   // initialize type of slippery elements
3667   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3668   {
3669     if (!IS_CUSTOM_ELEMENT(i))
3670     {
3671       // default: elements slip down either to the left or right randomly
3672       element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
3673
3674       // SP style elements prefer to slip down on the left side
3675       if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
3676         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3677
3678       // BD style elements prefer to slip down on the left side
3679       if (game.emulation == EMU_BOULDERDASH)
3680         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3681     }
3682   }
3683
3684   // initialize explosion and ignition delay
3685   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3686   {
3687     if (!IS_CUSTOM_ELEMENT(i))
3688     {
3689       int num_phase = 8;
3690       int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
3691                     game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
3692                    game.emulation == EMU_SUPAPLEX ? 3 : 2);
3693       int last_phase = (num_phase + 1) * delay;
3694       int half_phase = (num_phase / 2) * delay;
3695
3696       element_info[i].explosion_delay = last_phase - 1;
3697       element_info[i].ignition_delay = half_phase;
3698
3699       if (i == EL_BLACK_ORB)
3700         element_info[i].ignition_delay = 1;
3701     }
3702   }
3703
3704   // correct non-moving belts to start moving left
3705   for (i = 0; i < NUM_BELTS; i++)
3706     if (game.belt_dir[i] == MV_NONE)
3707       game.belt_dir_nr[i] = 3;          // not moving, next moving left
3708
3709 #if USE_NEW_PLAYER_ASSIGNMENTS
3710   for (i = 0; i < MAX_PLAYERS; i++)
3711   {
3712     stored_player[i].connected = FALSE;
3713
3714     // in network game mode, the local player might not be the first player
3715     if (stored_player[i].connected_locally)
3716       local_player = &stored_player[i];
3717   }
3718
3719   if (!network.enabled)
3720     local_player->connected = TRUE;
3721
3722   if (tape.playing)
3723   {
3724     for (i = 0; i < MAX_PLAYERS; i++)
3725       stored_player[i].connected = tape.player_participates[i];
3726   }
3727   else if (network.enabled)
3728   {
3729     // add team mode players connected over the network (needed for correct
3730     // assignment of player figures from level to locally playing players)
3731
3732     for (i = 0; i < MAX_PLAYERS; i++)
3733       if (stored_player[i].connected_network)
3734         stored_player[i].connected = TRUE;
3735   }
3736   else if (game.team_mode)
3737   {
3738     // try to guess locally connected team mode players (needed for correct
3739     // assignment of player figures from level to locally playing players)
3740
3741     for (i = 0; i < MAX_PLAYERS; i++)
3742       if (setup.input[i].use_joystick ||
3743           setup.input[i].key.left != KSYM_UNDEFINED)
3744         stored_player[i].connected = TRUE;
3745   }
3746
3747 #if DEBUG_INIT_PLAYER
3748   DebugPrintPlayerStatus("Player status after level initialization");
3749 #endif
3750
3751 #if DEBUG_INIT_PLAYER
3752   if (options.debug)
3753     printf("Reassigning players ...\n");
3754 #endif
3755
3756   // check if any connected player was not found in playfield
3757   for (i = 0; i < MAX_PLAYERS; i++)
3758   {
3759     struct PlayerInfo *player = &stored_player[i];
3760
3761     if (player->connected && !player->present)
3762     {
3763       struct PlayerInfo *field_player = NULL;
3764
3765 #if DEBUG_INIT_PLAYER
3766       if (options.debug)
3767         printf("- looking for field player for player %d ...\n", i + 1);
3768 #endif
3769
3770       // assign first free player found that is present in the playfield
3771
3772       // first try: look for unmapped playfield player that is not connected
3773       for (j = 0; j < MAX_PLAYERS; j++)
3774         if (field_player == NULL &&
3775             stored_player[j].present &&
3776             !stored_player[j].mapped &&
3777             !stored_player[j].connected)
3778           field_player = &stored_player[j];
3779
3780       // second try: look for *any* unmapped playfield player
3781       for (j = 0; j < MAX_PLAYERS; j++)
3782         if (field_player == NULL &&
3783             stored_player[j].present &&
3784             !stored_player[j].mapped)
3785           field_player = &stored_player[j];
3786
3787       if (field_player != NULL)
3788       {
3789         int jx = field_player->jx, jy = field_player->jy;
3790
3791 #if DEBUG_INIT_PLAYER
3792         if (options.debug)
3793           printf("- found player %d\n", field_player->index_nr + 1);
3794 #endif
3795
3796         player->present = FALSE;
3797         player->active = FALSE;
3798
3799         field_player->present = TRUE;
3800         field_player->active = TRUE;
3801
3802         /*
3803         player->initial_element = field_player->initial_element;
3804         player->artwork_element = field_player->artwork_element;
3805
3806         player->block_last_field       = field_player->block_last_field;
3807         player->block_delay_adjustment = field_player->block_delay_adjustment;
3808         */
3809
3810         StorePlayer[jx][jy] = field_player->element_nr;
3811
3812         field_player->jx = field_player->last_jx = jx;
3813         field_player->jy = field_player->last_jy = jy;
3814
3815         if (local_player == player)
3816           local_player = field_player;
3817
3818         map_player_action[field_player->index_nr] = i;
3819
3820         field_player->mapped = TRUE;
3821
3822 #if DEBUG_INIT_PLAYER
3823         if (options.debug)
3824           printf("- map_player_action[%d] == %d\n",
3825                  field_player->index_nr + 1, i + 1);
3826 #endif
3827       }
3828     }
3829
3830     if (player->connected && player->present)
3831       player->mapped = TRUE;
3832   }
3833
3834 #if DEBUG_INIT_PLAYER
3835   DebugPrintPlayerStatus("Player status after player assignment (first stage)");
3836 #endif
3837
3838 #else
3839
3840   // check if any connected player was not found in playfield
3841   for (i = 0; i < MAX_PLAYERS; i++)
3842   {
3843     struct PlayerInfo *player = &stored_player[i];
3844
3845     if (player->connected && !player->present)
3846     {
3847       for (j = 0; j < MAX_PLAYERS; j++)
3848       {
3849         struct PlayerInfo *field_player = &stored_player[j];
3850         int jx = field_player->jx, jy = field_player->jy;
3851
3852         // assign first free player found that is present in the playfield
3853         if (field_player->present && !field_player->connected)
3854         {
3855           player->present = TRUE;
3856           player->active = TRUE;
3857
3858           field_player->present = FALSE;
3859           field_player->active = FALSE;
3860
3861           player->initial_element = field_player->initial_element;
3862           player->artwork_element = field_player->artwork_element;
3863
3864           player->block_last_field       = field_player->block_last_field;
3865           player->block_delay_adjustment = field_player->block_delay_adjustment;
3866
3867           StorePlayer[jx][jy] = player->element_nr;
3868
3869           player->jx = player->last_jx = jx;
3870           player->jy = player->last_jy = jy;
3871
3872           break;
3873         }
3874       }
3875     }
3876   }
3877 #endif
3878