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