fixed sound for charging level time (energy) for MM engine
[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 /* game button identifiers */
1006 #define GAME_CTRL_ID_STOP               0
1007 #define GAME_CTRL_ID_PAUSE              1
1008 #define GAME_CTRL_ID_PLAY               2
1009 #define GAME_CTRL_ID_UNDO               3
1010 #define GAME_CTRL_ID_REDO               4
1011 #define GAME_CTRL_ID_SAVE               5
1012 #define GAME_CTRL_ID_PAUSE2             6
1013 #define GAME_CTRL_ID_LOAD               7
1014 #define SOUND_CTRL_ID_MUSIC             8
1015 #define SOUND_CTRL_ID_LOOPS             9
1016 #define SOUND_CTRL_ID_SIMPLE            10
1017
1018 #define NUM_GAME_BUTTONS                11
1019
1020
1021 /* forward declaration for internal use */
1022
1023 static void CreateField(int, int, int);
1024
1025 static void ResetGfxAnimation(int, int);
1026
1027 static void SetPlayerWaiting(struct PlayerInfo *, boolean);
1028 static void AdvanceFrameAndPlayerCounters(int);
1029
1030 static boolean MovePlayerOneStep(struct PlayerInfo *, int, int, int, int);
1031 static boolean MovePlayer(struct PlayerInfo *, int, int);
1032 static void ScrollPlayer(struct PlayerInfo *, int);
1033 static void ScrollScreen(struct PlayerInfo *, int);
1034
1035 static int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
1036 static boolean DigFieldByCE(int, int, int);
1037 static boolean SnapField(struct PlayerInfo *, int, int);
1038 static boolean DropElement(struct PlayerInfo *);
1039
1040 static void InitBeltMovement(void);
1041 static void CloseAllOpenTimegates(void);
1042 static void CheckGravityMovement(struct PlayerInfo *);
1043 static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *);
1044 static void KillPlayerUnlessEnemyProtected(int, int);
1045 static void KillPlayerUnlessExplosionProtected(int, int);
1046
1047 static void TestIfPlayerTouchesCustomElement(int, int);
1048 static void TestIfElementTouchesCustomElement(int, int);
1049 static void TestIfElementHitsCustomElement(int, int, int);
1050
1051 static void HandleElementChange(int, int, int);
1052 static void ExecuteCustomElementAction(int, int, int, int);
1053 static boolean ChangeElement(int, int, int, int);
1054
1055 static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
1056 #define CheckTriggeredElementChange(x, y, e, ev)                        \
1057         CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY,CH_SIDE_ANY, -1)
1058 #define CheckTriggeredElementChangeByPlayer(x, y, e, ev, p, s)          \
1059         CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
1060 #define CheckTriggeredElementChangeBySide(x, y, e, ev, s)               \
1061         CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, s, -1)
1062 #define CheckTriggeredElementChangeByPage(x, y, e, ev, p)               \
1063         CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
1064
1065 static boolean CheckElementChangeExt(int, int, int, int, int, int, int);
1066 #define CheckElementChange(x, y, e, te, ev)                             \
1067         CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, CH_SIDE_ANY)
1068 #define CheckElementChangeByPlayer(x, y, e, ev, p, s)                   \
1069         CheckElementChangeExt(x, y, e, EL_EMPTY, ev, p, s)
1070 #define CheckElementChangeBySide(x, y, e, te, ev, s)                    \
1071         CheckElementChangeExt(x, y, e, te, ev, CH_PLAYER_ANY, s)
1072
1073 static void PlayLevelSound(int, int, int);
1074 static void PlayLevelSoundNearest(int, int, int);
1075 static void PlayLevelSoundAction(int, int, int);
1076 static void PlayLevelSoundElementAction(int, int, int, int);
1077 static void PlayLevelSoundElementActionIfLoop(int, int, int, int);
1078 static void PlayLevelSoundActionIfLoop(int, int, int);
1079 static void StopLevelSoundActionIfLoop(int, int, int);
1080 static void PlayLevelMusic();
1081 static void FadeLevelSoundsAndMusic();
1082
1083 static void HandleGameButtons(struct GadgetInfo *);
1084
1085 int AmoebeNachbarNr(int, int);
1086 void AmoebeUmwandeln(int, int);
1087 void ContinueMoving(int, int);
1088 void Bang(int, int);
1089 void InitMovDir(int, int);
1090 void InitAmoebaNr(int, int);
1091 int NewHiScore(void);
1092
1093 void TestIfGoodThingHitsBadThing(int, int, int);
1094 void TestIfBadThingHitsGoodThing(int, int, int);
1095 void TestIfPlayerTouchesBadThing(int, int);
1096 void TestIfPlayerRunsIntoBadThing(int, int, int);
1097 void TestIfBadThingTouchesPlayer(int, int);
1098 void TestIfBadThingRunsIntoPlayer(int, int, int);
1099 void TestIfFriendTouchesBadThing(int, int);
1100 void TestIfBadThingTouchesFriend(int, int);
1101 void TestIfBadThingTouchesOtherBadThing(int, int);
1102 void TestIfGoodThingGetsHitByBadThing(int, int, int);
1103
1104 void KillPlayer(struct PlayerInfo *);
1105 void BuryPlayer(struct PlayerInfo *);
1106 void RemovePlayer(struct PlayerInfo *);
1107
1108 static int getInvisibleActiveFromInvisibleElement(int);
1109 static int getInvisibleFromInvisibleActiveElement(int);
1110
1111 static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
1112
1113 /* for detection of endless loops, caused by custom element programming */
1114 /* (using maximal playfield width x 10 is just a rough approximation) */
1115 #define MAX_ELEMENT_CHANGE_RECURSION_DEPTH      (MAX_PLAYFIELD_WIDTH * 10)
1116
1117 #define RECURSION_LOOP_DETECTION_START(e, rc)                           \
1118 {                                                                       \
1119   if (recursion_loop_detected)                                          \
1120     return (rc);                                                        \
1121                                                                         \
1122   if (recursion_loop_depth > MAX_ELEMENT_CHANGE_RECURSION_DEPTH)        \
1123   {                                                                     \
1124     recursion_loop_detected = TRUE;                                     \
1125     recursion_loop_element = (e);                                       \
1126   }                                                                     \
1127                                                                         \
1128   recursion_loop_depth++;                                               \
1129 }
1130
1131 #define RECURSION_LOOP_DETECTION_END()                                  \
1132 {                                                                       \
1133   recursion_loop_depth--;                                               \
1134 }
1135
1136 static int recursion_loop_depth;
1137 static boolean recursion_loop_detected;
1138 static boolean recursion_loop_element;
1139
1140 static int map_player_action[MAX_PLAYERS];
1141
1142
1143 /* ------------------------------------------------------------------------- */
1144 /* definition of elements that automatically change to other elements after  */
1145 /* a specified time, eventually calling a function when changing             */
1146 /* ------------------------------------------------------------------------- */
1147
1148 /* forward declaration for changer functions */
1149 static void InitBuggyBase(int, int);
1150 static void WarnBuggyBase(int, int);
1151
1152 static void InitTrap(int, int);
1153 static void ActivateTrap(int, int);
1154 static void ChangeActiveTrap(int, int);
1155
1156 static void InitRobotWheel(int, int);
1157 static void RunRobotWheel(int, int);
1158 static void StopRobotWheel(int, int);
1159
1160 static void InitTimegateWheel(int, int);
1161 static void RunTimegateWheel(int, int);
1162
1163 static void InitMagicBallDelay(int, int);
1164 static void ActivateMagicBall(int, int);
1165
1166 struct ChangingElementInfo
1167 {
1168   int element;
1169   int target_element;
1170   int change_delay;
1171   void (*pre_change_function)(int x, int y);
1172   void (*change_function)(int x, int y);
1173   void (*post_change_function)(int x, int y);
1174 };
1175
1176 static struct ChangingElementInfo change_delay_list[] =
1177 {
1178   {
1179     EL_NUT_BREAKING,
1180     EL_EMERALD,
1181     6,
1182     NULL,
1183     NULL,
1184     NULL
1185   },
1186   {
1187     EL_PEARL_BREAKING,
1188     EL_EMPTY,
1189     8,
1190     NULL,
1191     NULL,
1192     NULL
1193   },
1194   {
1195     EL_EXIT_OPENING,
1196     EL_EXIT_OPEN,
1197     29,
1198     NULL,
1199     NULL,
1200     NULL
1201   },
1202   {
1203     EL_EXIT_CLOSING,
1204     EL_EXIT_CLOSED,
1205     29,
1206     NULL,
1207     NULL,
1208     NULL
1209   },
1210   {
1211     EL_STEEL_EXIT_OPENING,
1212     EL_STEEL_EXIT_OPEN,
1213     29,
1214     NULL,
1215     NULL,
1216     NULL
1217   },
1218   {
1219     EL_STEEL_EXIT_CLOSING,
1220     EL_STEEL_EXIT_CLOSED,
1221     29,
1222     NULL,
1223     NULL,
1224     NULL
1225   },
1226   {
1227     EL_EM_EXIT_OPENING,
1228     EL_EM_EXIT_OPEN,
1229     29,
1230     NULL,
1231     NULL,
1232     NULL
1233   },
1234   {
1235     EL_EM_EXIT_CLOSING,
1236     EL_EMPTY,
1237     29,
1238     NULL,
1239     NULL,
1240     NULL
1241   },
1242   {
1243     EL_EM_STEEL_EXIT_OPENING,
1244     EL_EM_STEEL_EXIT_OPEN,
1245     29,
1246     NULL,
1247     NULL,
1248     NULL
1249   },
1250   {
1251     EL_EM_STEEL_EXIT_CLOSING,
1252     EL_STEELWALL,
1253     29,
1254     NULL,
1255     NULL,
1256     NULL
1257   },
1258   {
1259     EL_SP_EXIT_OPENING,
1260     EL_SP_EXIT_OPEN,
1261     29,
1262     NULL,
1263     NULL,
1264     NULL
1265   },
1266   {
1267     EL_SP_EXIT_CLOSING,
1268     EL_SP_EXIT_CLOSED,
1269     29,
1270     NULL,
1271     NULL,
1272     NULL
1273   },
1274   {
1275     EL_SWITCHGATE_OPENING,
1276     EL_SWITCHGATE_OPEN,
1277     29,
1278     NULL,
1279     NULL,
1280     NULL
1281   },
1282   {
1283     EL_SWITCHGATE_CLOSING,
1284     EL_SWITCHGATE_CLOSED,
1285     29,
1286     NULL,
1287     NULL,
1288     NULL
1289   },
1290   {
1291     EL_TIMEGATE_OPENING,
1292     EL_TIMEGATE_OPEN,
1293     29,
1294     NULL,
1295     NULL,
1296     NULL
1297   },
1298   {
1299     EL_TIMEGATE_CLOSING,
1300     EL_TIMEGATE_CLOSED,
1301     29,
1302     NULL,
1303     NULL,
1304     NULL
1305   },
1306
1307   {
1308     EL_ACID_SPLASH_LEFT,
1309     EL_EMPTY,
1310     8,
1311     NULL,
1312     NULL,
1313     NULL
1314   },
1315   {
1316     EL_ACID_SPLASH_RIGHT,
1317     EL_EMPTY,
1318     8,
1319     NULL,
1320     NULL,
1321     NULL
1322   },
1323   {
1324     EL_SP_BUGGY_BASE,
1325     EL_SP_BUGGY_BASE_ACTIVATING,
1326     0,
1327     InitBuggyBase,
1328     NULL,
1329     NULL
1330   },
1331   {
1332     EL_SP_BUGGY_BASE_ACTIVATING,
1333     EL_SP_BUGGY_BASE_ACTIVE,
1334     0,
1335     InitBuggyBase,
1336     NULL,
1337     NULL
1338   },
1339   {
1340     EL_SP_BUGGY_BASE_ACTIVE,
1341     EL_SP_BUGGY_BASE,
1342     0,
1343     InitBuggyBase,
1344     WarnBuggyBase,
1345     NULL
1346   },
1347   {
1348     EL_TRAP,
1349     EL_TRAP_ACTIVE,
1350     0,
1351     InitTrap,
1352     NULL,
1353     ActivateTrap
1354   },
1355   {
1356     EL_TRAP_ACTIVE,
1357     EL_TRAP,
1358     31,
1359     NULL,
1360     ChangeActiveTrap,
1361     NULL
1362   },
1363   {
1364     EL_ROBOT_WHEEL_ACTIVE,
1365     EL_ROBOT_WHEEL,
1366     0,
1367     InitRobotWheel,
1368     RunRobotWheel,
1369     StopRobotWheel
1370   },
1371   {
1372     EL_TIMEGATE_SWITCH_ACTIVE,
1373     EL_TIMEGATE_SWITCH,
1374     0,
1375     InitTimegateWheel,
1376     RunTimegateWheel,
1377     NULL
1378   },
1379   {
1380     EL_DC_TIMEGATE_SWITCH_ACTIVE,
1381     EL_DC_TIMEGATE_SWITCH,
1382     0,
1383     InitTimegateWheel,
1384     RunTimegateWheel,
1385     NULL
1386   },
1387   {
1388     EL_EMC_MAGIC_BALL_ACTIVE,
1389     EL_EMC_MAGIC_BALL_ACTIVE,
1390     0,
1391     InitMagicBallDelay,
1392     NULL,
1393     ActivateMagicBall
1394   },
1395   {
1396     EL_EMC_SPRING_BUMPER_ACTIVE,
1397     EL_EMC_SPRING_BUMPER,
1398     8,
1399     NULL,
1400     NULL,
1401     NULL
1402   },
1403   {
1404     EL_DIAGONAL_SHRINKING,
1405     EL_UNDEFINED,
1406     0,
1407     NULL,
1408     NULL,
1409     NULL
1410   },
1411   {
1412     EL_DIAGONAL_GROWING,
1413     EL_UNDEFINED,
1414     0,
1415     NULL,
1416     NULL,
1417     NULL,
1418   },
1419
1420   {
1421     EL_UNDEFINED,
1422     EL_UNDEFINED,
1423     -1,
1424     NULL,
1425     NULL,
1426     NULL
1427   }
1428 };
1429
1430 struct
1431 {
1432   int element;
1433   int push_delay_fixed, push_delay_random;
1434 }
1435 push_delay_list[] =
1436 {
1437   { EL_SPRING,                  0, 0 },
1438   { EL_BALLOON,                 0, 0 },
1439
1440   { EL_SOKOBAN_OBJECT,          2, 0 },
1441   { EL_SOKOBAN_FIELD_FULL,      2, 0 },
1442   { EL_SATELLITE,               2, 0 },
1443   { EL_SP_DISK_YELLOW,          2, 0 },
1444
1445   { EL_UNDEFINED,               0, 0 },
1446 };
1447
1448 struct
1449 {
1450   int element;
1451   int move_stepsize;
1452 }
1453 move_stepsize_list[] =
1454 {
1455   { EL_AMOEBA_DROP,             2 },
1456   { EL_AMOEBA_DROPPING,         2 },
1457   { EL_QUICKSAND_FILLING,       1 },
1458   { EL_QUICKSAND_EMPTYING,      1 },
1459   { EL_QUICKSAND_FAST_FILLING,  2 },
1460   { EL_QUICKSAND_FAST_EMPTYING, 2 },
1461   { EL_MAGIC_WALL_FILLING,      2 },
1462   { EL_MAGIC_WALL_EMPTYING,     2 },
1463   { EL_BD_MAGIC_WALL_FILLING,   2 },
1464   { EL_BD_MAGIC_WALL_EMPTYING,  2 },
1465   { EL_DC_MAGIC_WALL_FILLING,   2 },
1466   { EL_DC_MAGIC_WALL_EMPTYING,  2 },
1467
1468   { EL_UNDEFINED,               0 },
1469 };
1470
1471 struct
1472 {
1473   int element;
1474   int count;
1475 }
1476 collect_count_list[] =
1477 {
1478   { EL_EMERALD,                 1 },
1479   { EL_BD_DIAMOND,              1 },
1480   { EL_EMERALD_YELLOW,          1 },
1481   { EL_EMERALD_RED,             1 },
1482   { EL_EMERALD_PURPLE,          1 },
1483   { EL_DIAMOND,                 3 },
1484   { EL_SP_INFOTRON,             1 },
1485   { EL_PEARL,                   5 },
1486   { EL_CRYSTAL,                 8 },
1487
1488   { EL_UNDEFINED,               0 },
1489 };
1490
1491 struct
1492 {
1493   int element;
1494   int direction;
1495 }
1496 access_direction_list[] =
1497 {
1498   { EL_TUBE_ANY,                        MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
1499   { EL_TUBE_VERTICAL,                                        MV_UP | MV_DOWN },
1500   { EL_TUBE_HORIZONTAL,                 MV_LEFT | MV_RIGHT                   },
1501   { EL_TUBE_VERTICAL_LEFT,              MV_LEFT |            MV_UP | MV_DOWN },
1502   { EL_TUBE_VERTICAL_RIGHT,                       MV_RIGHT | MV_UP | MV_DOWN },
1503   { EL_TUBE_HORIZONTAL_UP,              MV_LEFT | MV_RIGHT | MV_UP           },
1504   { EL_TUBE_HORIZONTAL_DOWN,            MV_LEFT | MV_RIGHT |         MV_DOWN },
1505   { EL_TUBE_LEFT_UP,                    MV_LEFT |            MV_UP           },
1506   { EL_TUBE_LEFT_DOWN,                  MV_LEFT |                    MV_DOWN },
1507   { EL_TUBE_RIGHT_UP,                             MV_RIGHT | MV_UP           },
1508   { EL_TUBE_RIGHT_DOWN,                           MV_RIGHT |         MV_DOWN },
1509
1510   { EL_SP_PORT_LEFT,                              MV_RIGHT                   },
1511   { EL_SP_PORT_RIGHT,                   MV_LEFT                              },
1512   { EL_SP_PORT_UP,                                                   MV_DOWN },
1513   { EL_SP_PORT_DOWN,                                         MV_UP           },
1514   { EL_SP_PORT_HORIZONTAL,              MV_LEFT | MV_RIGHT                   },
1515   { EL_SP_PORT_VERTICAL,                                     MV_UP | MV_DOWN },
1516   { EL_SP_PORT_ANY,                     MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
1517   { EL_SP_GRAVITY_PORT_LEFT,                      MV_RIGHT                   },
1518   { EL_SP_GRAVITY_PORT_RIGHT,           MV_LEFT                              },
1519   { EL_SP_GRAVITY_PORT_UP,                                           MV_DOWN },
1520   { EL_SP_GRAVITY_PORT_DOWN,                                 MV_UP           },
1521   { EL_SP_GRAVITY_ON_PORT_LEFT,                   MV_RIGHT                   },
1522   { EL_SP_GRAVITY_ON_PORT_RIGHT,        MV_LEFT                              },
1523   { EL_SP_GRAVITY_ON_PORT_UP,                                        MV_DOWN },
1524   { EL_SP_GRAVITY_ON_PORT_DOWN,                              MV_UP           },
1525   { EL_SP_GRAVITY_OFF_PORT_LEFT,                  MV_RIGHT                   },
1526   { EL_SP_GRAVITY_OFF_PORT_RIGHT,       MV_LEFT                              },
1527   { EL_SP_GRAVITY_OFF_PORT_UP,                                       MV_DOWN },
1528   { EL_SP_GRAVITY_OFF_PORT_DOWN,                             MV_UP           },
1529
1530   { EL_UNDEFINED,                       MV_NONE                              }
1531 };
1532
1533 static boolean trigger_events[MAX_NUM_ELEMENTS][NUM_CHANGE_EVENTS];
1534
1535 #define IS_AUTO_CHANGING(e)     (element_info[e].has_change_event[CE_DELAY])
1536 #define IS_JUST_CHANGING(x, y)  (ChangeDelay[x][y] != 0)
1537 #define IS_CHANGING(x, y)       (IS_AUTO_CHANGING(Feld[x][y]) || \
1538                                  IS_JUST_CHANGING(x, y))
1539
1540 #define CE_PAGE(e, ce)          (element_info[e].event_page[ce])
1541
1542 /* static variables for playfield scan mode (scanning forward or backward) */
1543 static int playfield_scan_start_x = 0;
1544 static int playfield_scan_start_y = 0;
1545 static int playfield_scan_delta_x = 1;
1546 static int playfield_scan_delta_y = 1;
1547
1548 #define SCAN_PLAYFIELD(x, y)    for ((y) = playfield_scan_start_y;      \
1549                                      (y) >= 0 && (y) <= lev_fieldy - 1; \
1550                                      (y) += playfield_scan_delta_y)     \
1551                                 for ((x) = playfield_scan_start_x;      \
1552                                      (x) >= 0 && (x) <= lev_fieldx - 1; \
1553                                      (x) += playfield_scan_delta_x)
1554
1555 #ifdef DEBUG
1556 void DEBUG_SetMaximumDynamite()
1557 {
1558   int i;
1559
1560   for (i = 0; i < MAX_INVENTORY_SIZE; i++)
1561     if (local_player->inventory_size < MAX_INVENTORY_SIZE)
1562       local_player->inventory_element[local_player->inventory_size++] =
1563         EL_DYNAMITE;
1564 }
1565 #endif
1566
1567 static void InitPlayfieldScanModeVars()
1568 {
1569   if (game.use_reverse_scan_direction)
1570   {
1571     playfield_scan_start_x = lev_fieldx - 1;
1572     playfield_scan_start_y = lev_fieldy - 1;
1573
1574     playfield_scan_delta_x = -1;
1575     playfield_scan_delta_y = -1;
1576   }
1577   else
1578   {
1579     playfield_scan_start_x = 0;
1580     playfield_scan_start_y = 0;
1581
1582     playfield_scan_delta_x = 1;
1583     playfield_scan_delta_y = 1;
1584   }
1585 }
1586
1587 static void InitPlayfieldScanMode(int mode)
1588 {
1589   game.use_reverse_scan_direction =
1590     (mode == CA_ARG_SCAN_MODE_REVERSE ? TRUE : FALSE);
1591
1592   InitPlayfieldScanModeVars();
1593 }
1594
1595 static int get_move_delay_from_stepsize(int move_stepsize)
1596 {
1597   move_stepsize =
1598     MIN(MAX(MOVE_STEPSIZE_MIN, move_stepsize), MOVE_STEPSIZE_MAX);
1599
1600   /* make sure that stepsize value is always a power of 2 */
1601   move_stepsize = (1 << log_2(move_stepsize));
1602
1603   return TILEX / move_stepsize;
1604 }
1605
1606 static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
1607                                boolean init_game)
1608 {
1609   int player_nr = player->index_nr;
1610   int move_delay = get_move_delay_from_stepsize(move_stepsize);
1611   boolean cannot_move = (move_stepsize == STEPSIZE_NOT_MOVING ? TRUE : FALSE);
1612
1613   /* do no immediately change move delay -- the player might just be moving */
1614   player->move_delay_value_next = move_delay;
1615
1616   /* information if player can move must be set separately */
1617   player->cannot_move = cannot_move;
1618
1619   if (init_game)
1620   {
1621     player->move_delay       = game.initial_move_delay[player_nr];
1622     player->move_delay_value = game.initial_move_delay_value[player_nr];
1623
1624     player->move_delay_value_next = -1;
1625
1626     player->move_delay_reset_counter = 0;
1627   }
1628 }
1629
1630 void GetPlayerConfig()
1631 {
1632   GameFrameDelay = setup.game_frame_delay;
1633
1634   if (!audio.sound_available)
1635     setup.sound_simple = FALSE;
1636
1637   if (!audio.loops_available)
1638     setup.sound_loops = FALSE;
1639
1640   if (!audio.music_available)
1641     setup.sound_music = FALSE;
1642
1643   if (!video.fullscreen_available)
1644     setup.fullscreen = FALSE;
1645
1646   setup.sound = (setup.sound_simple || setup.sound_loops || setup.sound_music);
1647
1648   SetAudioMode(setup.sound);
1649 }
1650
1651 int GetElementFromGroupElement(int element)
1652 {
1653   if (IS_GROUP_ELEMENT(element))
1654   {
1655     struct ElementGroupInfo *group = element_info[element].group;
1656     int last_anim_random_frame = gfx.anim_random_frame;
1657     int element_pos;
1658
1659     if (group->choice_mode == ANIM_RANDOM)
1660       gfx.anim_random_frame = RND(group->num_elements_resolved);
1661
1662     element_pos = getAnimationFrame(group->num_elements_resolved, 1,
1663                                     group->choice_mode, 0,
1664                                     group->choice_pos);
1665
1666     if (group->choice_mode == ANIM_RANDOM)
1667       gfx.anim_random_frame = last_anim_random_frame;
1668
1669     group->choice_pos++;
1670
1671     element = group->element_resolved[element_pos];
1672   }
1673
1674   return element;
1675 }
1676
1677 static void InitPlayerField(int x, int y, int element, boolean init_game)
1678 {
1679   if (element == EL_SP_MURPHY)
1680   {
1681     if (init_game)
1682     {
1683       if (stored_player[0].present)
1684       {
1685         Feld[x][y] = EL_SP_MURPHY_CLONE;
1686
1687         return;
1688       }
1689       else
1690       {
1691         stored_player[0].initial_element = element;
1692         stored_player[0].use_murphy = TRUE;
1693
1694         if (!level.use_artwork_element[0])
1695           stored_player[0].artwork_element = EL_SP_MURPHY;
1696       }
1697
1698       Feld[x][y] = EL_PLAYER_1;
1699     }
1700   }
1701
1702   if (init_game)
1703   {
1704     struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1];
1705     int jx = player->jx, jy = player->jy;
1706
1707     player->present = TRUE;
1708
1709     player->block_last_field = (element == EL_SP_MURPHY ?
1710                                 level.sp_block_last_field :
1711                                 level.block_last_field);
1712
1713     /* ---------- initialize player's last field block delay --------------- */
1714
1715     /* always start with reliable default value (no adjustment needed) */
1716     player->block_delay_adjustment = 0;
1717
1718     /* special case 1: in Supaplex, Murphy blocks last field one more frame */
1719     if (player->block_last_field && element == EL_SP_MURPHY)
1720       player->block_delay_adjustment = 1;
1721
1722     /* special case 2: in game engines before 3.1.1, blocking was different */
1723     if (game.use_block_last_field_bug)
1724       player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
1725
1726     if (!options.network || player->connected)
1727     {
1728       player->active = TRUE;
1729
1730       /* remove potentially duplicate players */
1731       if (StorePlayer[jx][jy] == Feld[x][y])
1732         StorePlayer[jx][jy] = 0;
1733
1734       StorePlayer[x][y] = Feld[x][y];
1735
1736 #if DEBUG_INIT_PLAYER
1737       if (options.debug)
1738       {
1739         printf("- player element %d activated", player->element_nr);
1740         printf(" (local player is %d and currently %s)\n",
1741                local_player->element_nr,
1742                local_player->active ? "active" : "not active");
1743       }
1744     }
1745 #endif
1746
1747     Feld[x][y] = EL_EMPTY;
1748
1749     player->jx = player->last_jx = x;
1750     player->jy = player->last_jy = y;
1751   }
1752
1753   if (!init_game)
1754   {
1755     int player_nr = GET_PLAYER_NR(element);
1756     struct PlayerInfo *player = &stored_player[player_nr];
1757
1758     if (player->active && player->killed)
1759       player->reanimated = TRUE; /* if player was just killed, reanimate him */
1760   }
1761 }
1762
1763 static void InitField(int x, int y, boolean init_game)
1764 {
1765   int element = Feld[x][y];
1766
1767   switch (element)
1768   {
1769     case EL_SP_MURPHY:
1770     case EL_PLAYER_1:
1771     case EL_PLAYER_2:
1772     case EL_PLAYER_3:
1773     case EL_PLAYER_4:
1774       InitPlayerField(x, y, element, init_game);
1775       break;
1776
1777     case EL_SOKOBAN_FIELD_PLAYER:
1778       element = Feld[x][y] = EL_PLAYER_1;
1779       InitField(x, y, init_game);
1780
1781       element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
1782       InitField(x, y, init_game);
1783       break;
1784
1785     case EL_SOKOBAN_FIELD_EMPTY:
1786       local_player->sokobanfields_still_needed++;
1787       break;
1788
1789     case EL_STONEBLOCK:
1790       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
1791         Feld[x][y] = EL_ACID_POOL_TOPLEFT;
1792       else if (x > 0 && Feld[x-1][y] == EL_ACID)
1793         Feld[x][y] = EL_ACID_POOL_TOPRIGHT;
1794       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPLEFT)
1795         Feld[x][y] = EL_ACID_POOL_BOTTOMLEFT;
1796       else if (y > 0 && Feld[x][y-1] == EL_ACID)
1797         Feld[x][y] = EL_ACID_POOL_BOTTOM;
1798       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPRIGHT)
1799         Feld[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
1800       break;
1801
1802     case EL_BUG:
1803     case EL_BUG_RIGHT:
1804     case EL_BUG_UP:
1805     case EL_BUG_LEFT:
1806     case EL_BUG_DOWN:
1807     case EL_SPACESHIP:
1808     case EL_SPACESHIP_RIGHT:
1809     case EL_SPACESHIP_UP:
1810     case EL_SPACESHIP_LEFT:
1811     case EL_SPACESHIP_DOWN:
1812     case EL_BD_BUTTERFLY:
1813     case EL_BD_BUTTERFLY_RIGHT:
1814     case EL_BD_BUTTERFLY_UP:
1815     case EL_BD_BUTTERFLY_LEFT:
1816     case EL_BD_BUTTERFLY_DOWN:
1817     case EL_BD_FIREFLY:
1818     case EL_BD_FIREFLY_RIGHT:
1819     case EL_BD_FIREFLY_UP:
1820     case EL_BD_FIREFLY_LEFT:
1821     case EL_BD_FIREFLY_DOWN:
1822     case EL_PACMAN_RIGHT:
1823     case EL_PACMAN_UP:
1824     case EL_PACMAN_LEFT:
1825     case EL_PACMAN_DOWN:
1826     case EL_YAMYAM:
1827     case EL_YAMYAM_LEFT:
1828     case EL_YAMYAM_RIGHT:
1829     case EL_YAMYAM_UP:
1830     case EL_YAMYAM_DOWN:
1831     case EL_DARK_YAMYAM:
1832     case EL_ROBOT:
1833     case EL_PACMAN:
1834     case EL_SP_SNIKSNAK:
1835     case EL_SP_ELECTRON:
1836     case EL_MOLE:
1837     case EL_MOLE_LEFT:
1838     case EL_MOLE_RIGHT:
1839     case EL_MOLE_UP:
1840     case EL_MOLE_DOWN:
1841       InitMovDir(x, y);
1842       break;
1843
1844     case EL_AMOEBA_FULL:
1845     case EL_BD_AMOEBA:
1846       InitAmoebaNr(x, y);
1847       break;
1848
1849     case EL_AMOEBA_DROP:
1850       if (y == lev_fieldy - 1)
1851       {
1852         Feld[x][y] = EL_AMOEBA_GROWING;
1853         Store[x][y] = EL_AMOEBA_WET;
1854       }
1855       break;
1856
1857     case EL_DYNAMITE_ACTIVE:
1858     case EL_SP_DISK_RED_ACTIVE:
1859     case EL_DYNABOMB_PLAYER_1_ACTIVE:
1860     case EL_DYNABOMB_PLAYER_2_ACTIVE:
1861     case EL_DYNABOMB_PLAYER_3_ACTIVE:
1862     case EL_DYNABOMB_PLAYER_4_ACTIVE:
1863       MovDelay[x][y] = 96;
1864       break;
1865
1866     case EL_EM_DYNAMITE_ACTIVE:
1867       MovDelay[x][y] = 32;
1868       break;
1869
1870     case EL_LAMP:
1871       local_player->lights_still_needed++;
1872       break;
1873
1874     case EL_PENGUIN:
1875       local_player->friends_still_needed++;
1876       break;
1877
1878     case EL_PIG:
1879     case EL_DRAGON:
1880       GfxDir[x][y] = MovDir[x][y] = 1 << RND(4);
1881       break;
1882
1883     case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
1884     case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
1885     case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
1886     case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
1887     case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
1888     case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
1889     case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
1890     case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
1891     case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
1892     case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
1893     case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
1894     case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
1895       if (init_game)
1896       {
1897         int belt_nr = getBeltNrFromBeltSwitchElement(Feld[x][y]);
1898         int belt_dir = getBeltDirFromBeltSwitchElement(Feld[x][y]);
1899         int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(Feld[x][y]);
1900
1901         if (game.belt_dir_nr[belt_nr] == 3)     /* initial value */
1902         {
1903           game.belt_dir[belt_nr] = belt_dir;
1904           game.belt_dir_nr[belt_nr] = belt_dir_nr;
1905         }
1906         else    /* more than one switch -- set it like the first switch */
1907         {
1908           Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
1909         }
1910       }
1911       break;
1912
1913     case EL_LIGHT_SWITCH_ACTIVE:
1914       if (init_game)
1915         game.light_time_left = level.time_light * FRAMES_PER_SECOND;
1916       break;
1917
1918     case EL_INVISIBLE_STEELWALL:
1919     case EL_INVISIBLE_WALL:
1920     case EL_INVISIBLE_SAND:
1921       if (game.light_time_left > 0 ||
1922           game.lenses_time_left > 0)
1923         Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
1924       break;
1925
1926     case EL_EMC_MAGIC_BALL:
1927       if (game.ball_state)
1928         Feld[x][y] = EL_EMC_MAGIC_BALL_ACTIVE;
1929       break;
1930
1931     case EL_EMC_MAGIC_BALL_SWITCH:
1932       if (game.ball_state)
1933         Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
1934       break;
1935
1936     case EL_TRIGGER_PLAYER:
1937     case EL_TRIGGER_ELEMENT:
1938     case EL_TRIGGER_CE_VALUE:
1939     case EL_TRIGGER_CE_SCORE:
1940     case EL_SELF:
1941     case EL_ANY_ELEMENT:
1942     case EL_CURRENT_CE_VALUE:
1943     case EL_CURRENT_CE_SCORE:
1944     case EL_PREV_CE_1:
1945     case EL_PREV_CE_2:
1946     case EL_PREV_CE_3:
1947     case EL_PREV_CE_4:
1948     case EL_PREV_CE_5:
1949     case EL_PREV_CE_6:
1950     case EL_PREV_CE_7:
1951     case EL_PREV_CE_8:
1952     case EL_NEXT_CE_1:
1953     case EL_NEXT_CE_2:
1954     case EL_NEXT_CE_3:
1955     case EL_NEXT_CE_4:
1956     case EL_NEXT_CE_5:
1957     case EL_NEXT_CE_6:
1958     case EL_NEXT_CE_7:
1959     case EL_NEXT_CE_8:
1960       /* reference elements should not be used on the playfield */
1961       Feld[x][y] = EL_EMPTY;
1962       break;
1963
1964     default:
1965       if (IS_CUSTOM_ELEMENT(element))
1966       {
1967         if (CAN_MOVE(element))
1968           InitMovDir(x, y);
1969
1970         if (!element_info[element].use_last_ce_value || init_game)
1971           CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
1972       }
1973       else if (IS_GROUP_ELEMENT(element))
1974       {
1975         Feld[x][y] = GetElementFromGroupElement(element);
1976
1977         InitField(x, y, init_game);
1978       }
1979
1980       break;
1981   }
1982
1983   if (!init_game)
1984     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
1985 }
1986
1987 inline static void InitField_WithBug1(int x, int y, boolean init_game)
1988 {
1989   InitField(x, y, init_game);
1990
1991   /* not needed to call InitMovDir() -- already done by InitField()! */
1992   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
1993       CAN_MOVE(Feld[x][y]))
1994     InitMovDir(x, y);
1995 }
1996
1997 inline static void InitField_WithBug2(int x, int y, boolean init_game)
1998 {
1999   int old_element = Feld[x][y];
2000
2001   InitField(x, y, init_game);
2002
2003   /* not needed to call InitMovDir() -- already done by InitField()! */
2004   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2005       CAN_MOVE(old_element) &&
2006       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
2007     InitMovDir(x, y);
2008
2009   /* this case is in fact a combination of not less than three bugs:
2010      first, it calls InitMovDir() for elements that can move, although this is
2011      already done by InitField(); then, it checks the element that was at this
2012      field _before_ the call to InitField() (which can change it); lastly, it
2013      was not called for "mole with direction" elements, which were treated as
2014      "cannot move" due to (fixed) wrong element initialization in "src/init.c"
2015   */
2016 }
2017
2018 static int get_key_element_from_nr(int key_nr)
2019 {
2020   int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
2021                           level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2022                           EL_EM_KEY_1 : EL_KEY_1);
2023
2024   return key_base_element + key_nr;
2025 }
2026
2027 static int get_next_dropped_element(struct PlayerInfo *player)
2028 {
2029   return (player->inventory_size > 0 ?
2030           player->inventory_element[player->inventory_size - 1] :
2031           player->inventory_infinite_element != EL_UNDEFINED ?
2032           player->inventory_infinite_element :
2033           player->dynabombs_left > 0 ?
2034           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
2035           EL_UNDEFINED);
2036 }
2037
2038 static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
2039 {
2040   /* pos >= 0: get element from bottom of the stack;
2041      pos <  0: get element from top of the stack */
2042
2043   if (pos < 0)
2044   {
2045     int min_inventory_size = -pos;
2046     int inventory_pos = player->inventory_size - min_inventory_size;
2047     int min_dynabombs_left = min_inventory_size - player->inventory_size;
2048
2049     return (player->inventory_size >= min_inventory_size ?
2050             player->inventory_element[inventory_pos] :
2051             player->inventory_infinite_element != EL_UNDEFINED ?
2052             player->inventory_infinite_element :
2053             player->dynabombs_left >= min_dynabombs_left ?
2054             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2055             EL_UNDEFINED);
2056   }
2057   else
2058   {
2059     int min_dynabombs_left = pos + 1;
2060     int min_inventory_size = pos + 1 - player->dynabombs_left;
2061     int inventory_pos = pos - player->dynabombs_left;
2062
2063     return (player->inventory_infinite_element != EL_UNDEFINED ?
2064             player->inventory_infinite_element :
2065             player->dynabombs_left >= min_dynabombs_left ?
2066             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2067             player->inventory_size >= min_inventory_size ?
2068             player->inventory_element[inventory_pos] :
2069             EL_UNDEFINED);
2070   }
2071 }
2072
2073 static int compareGamePanelOrderInfo(const void *object1, const void *object2)
2074 {
2075   const struct GamePanelOrderInfo *gpo1 = (struct GamePanelOrderInfo *)object1;
2076   const struct GamePanelOrderInfo *gpo2 = (struct GamePanelOrderInfo *)object2;
2077   int compare_result;
2078
2079   if (gpo1->sort_priority != gpo2->sort_priority)
2080     compare_result = gpo1->sort_priority - gpo2->sort_priority;
2081   else
2082     compare_result = gpo1->nr - gpo2->nr;
2083
2084   return compare_result;
2085 }
2086
2087 int getPlayerInventorySize(int player_nr)
2088 {
2089   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2090     return level.native_em_level->ply[player_nr]->dynamite;
2091   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2092     return level.native_sp_level->game_sp->red_disk_count;
2093   else
2094     return stored_player[player_nr].inventory_size;
2095 }
2096
2097 void InitGameControlValues()
2098 {
2099   int i;
2100
2101   for (i = 0; game_panel_controls[i].nr != -1; i++)
2102   {
2103     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2104     struct GamePanelOrderInfo *gpo = &game_panel_order[i];
2105     struct TextPosInfo *pos = gpc->pos;
2106     int nr = gpc->nr;
2107     int type = gpc->type;
2108
2109     if (nr != i)
2110     {
2111       Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i);
2112       Error(ERR_EXIT, "this should not happen -- please debug");
2113     }
2114
2115     /* force update of game controls after initialization */
2116     gpc->value = gpc->last_value = -1;
2117     gpc->frame = gpc->last_frame = -1;
2118     gpc->gfx_frame = -1;
2119
2120     /* determine panel value width for later calculation of alignment */
2121     if (type == TYPE_INTEGER || type == TYPE_STRING)
2122     {
2123       pos->width = pos->size * getFontWidth(pos->font);
2124       pos->height = getFontHeight(pos->font);
2125     }
2126     else if (type == TYPE_ELEMENT)
2127     {
2128       pos->width = pos->size;
2129       pos->height = pos->size;
2130     }
2131
2132     /* fill structure for game panel draw order */
2133     gpo->nr = gpc->nr;
2134     gpo->sort_priority = pos->sort_priority;
2135   }
2136
2137   /* sort game panel controls according to sort_priority and control number */
2138   qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
2139         sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
2140 }
2141
2142 void UpdatePlayfieldElementCount()
2143 {
2144   boolean use_element_count = FALSE;
2145   int i, j, x, y;
2146
2147   /* first check if it is needed at all to calculate playfield element count */
2148   for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++)
2149     if (!PANEL_DEACTIVATED(game_panel_controls[i].pos))
2150       use_element_count = TRUE;
2151
2152   if (!use_element_count)
2153     return;
2154
2155   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2156     element_info[i].element_count = 0;
2157
2158   SCAN_PLAYFIELD(x, y)
2159   {
2160     element_info[Feld[x][y]].element_count++;
2161   }
2162
2163   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
2164     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2165       if (IS_IN_GROUP(j, i))
2166         element_info[EL_GROUP_START + i].element_count +=
2167           element_info[j].element_count;
2168 }
2169
2170 void UpdateGameControlValues()
2171 {
2172   int i, k;
2173   int time = (local_player->LevelSolved ?
2174               local_player->LevelSolved_CountingTime :
2175               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2176               level.native_em_level->lev->time :
2177               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2178               level.native_sp_level->game_sp->time_played :
2179               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2180               game_mm.energy_left :
2181               game.no_time_limit ? TimePlayed : TimeLeft);
2182   int score = (local_player->LevelSolved ?
2183                local_player->LevelSolved_CountingScore :
2184                level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2185                level.native_em_level->lev->score :
2186                level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2187                level.native_sp_level->game_sp->score :
2188                level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2189                game_mm.score :
2190                local_player->score);
2191   int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2192               level.native_em_level->lev->required :
2193               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2194               level.native_sp_level->game_sp->infotrons_still_needed :
2195               level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2196               game_mm.kettles_still_needed :
2197               local_player->gems_still_needed);
2198   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2199                      level.native_em_level->lev->required > 0 :
2200                      level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2201                      level.native_sp_level->game_sp->infotrons_still_needed > 0 :
2202                      level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2203                      game_mm.kettles_still_needed > 0 ||
2204                      game_mm.lights_still_needed > 0 :
2205                      local_player->gems_still_needed > 0 ||
2206                      local_player->sokobanfields_still_needed > 0 ||
2207                      local_player->lights_still_needed > 0);
2208   int health = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
2209                 MIN(MAX(0, 100 - game_mm.laser_overload_value), 100) : 100);
2210
2211   UpdatePlayfieldElementCount();
2212
2213   /* update game panel control values */
2214
2215   game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr;
2216   game_panel_controls[GAME_PANEL_GEMS].value = gems;
2217
2218   game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
2219   for (i = 0; i < MAX_NUM_KEYS; i++)
2220     game_panel_controls[GAME_PANEL_KEY_1 + i].value = EL_EMPTY;
2221   game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_EMPTY;
2222   game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value = 0;
2223
2224   if (game.centered_player_nr == -1)
2225   {
2226     for (i = 0; i < MAX_PLAYERS; i++)
2227     {
2228       /* only one player in Supaplex game engine */
2229       if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
2230         break;
2231
2232       for (k = 0; k < MAX_NUM_KEYS; k++)
2233       {
2234         if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2235         {
2236           if (level.native_em_level->ply[i]->keys & (1 << k))
2237             game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2238               get_key_element_from_nr(k);
2239         }
2240         else if (stored_player[i].key[k])
2241           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2242             get_key_element_from_nr(k);
2243       }
2244
2245       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2246         getPlayerInventorySize(i);
2247
2248       if (stored_player[i].num_white_keys > 0)
2249         game_panel_controls[GAME_PANEL_KEY_WHITE].value =
2250           EL_DC_KEY_WHITE;
2251
2252       game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2253         stored_player[i].num_white_keys;
2254     }
2255   }
2256   else
2257   {
2258     int player_nr = game.centered_player_nr;
2259
2260     for (k = 0; k < MAX_NUM_KEYS; k++)
2261     {
2262       if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2263       {
2264         if (level.native_em_level->ply[player_nr]->keys & (1 << k))
2265           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2266             get_key_element_from_nr(k);
2267       }
2268       else if (stored_player[player_nr].key[k])
2269         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2270           get_key_element_from_nr(k);
2271     }
2272
2273     game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2274       getPlayerInventorySize(player_nr);
2275
2276     if (stored_player[player_nr].num_white_keys > 0)
2277       game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
2278
2279     game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2280       stored_player[player_nr].num_white_keys;
2281   }
2282
2283   for (i = 0; i < NUM_PANEL_INVENTORY; i++)
2284   {
2285     game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value =
2286       get_inventory_element_from_pos(local_player, i);
2287     game_panel_controls[GAME_PANEL_INVENTORY_LAST_1 + i].value =
2288       get_inventory_element_from_pos(local_player, -i - 1);
2289   }
2290
2291   game_panel_controls[GAME_PANEL_SCORE].value = score;
2292   game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
2293
2294   game_panel_controls[GAME_PANEL_TIME].value = time;
2295
2296   game_panel_controls[GAME_PANEL_TIME_HH].value = time / 3600;
2297   game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
2298   game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
2299
2300   if (game.no_time_limit)
2301     game_panel_controls[GAME_PANEL_TIME_ANIM].value = 100;
2302   else
2303     game_panel_controls[GAME_PANEL_TIME_ANIM].value = time * 100 / level.time;
2304
2305   game_panel_controls[GAME_PANEL_HEALTH].value = health;
2306   game_panel_controls[GAME_PANEL_HEALTH_ANIM].value = health;
2307
2308   game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter;
2309
2310   game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
2311     (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
2312      EL_EMPTY);
2313   game_panel_controls[GAME_PANEL_SHIELD_NORMAL_TIME].value =
2314     local_player->shield_normal_time_left;
2315   game_panel_controls[GAME_PANEL_SHIELD_DEADLY].value =
2316     (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
2317      EL_EMPTY);
2318   game_panel_controls[GAME_PANEL_SHIELD_DEADLY_TIME].value =
2319     local_player->shield_deadly_time_left;
2320
2321   game_panel_controls[GAME_PANEL_EXIT].value =
2322     (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
2323
2324   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL].value =
2325     (game.ball_state ? EL_EMC_MAGIC_BALL_ACTIVE : EL_EMC_MAGIC_BALL);
2326   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL_SWITCH].value =
2327     (game.ball_state ? EL_EMC_MAGIC_BALL_SWITCH_ACTIVE :
2328      EL_EMC_MAGIC_BALL_SWITCH);
2329
2330   game_panel_controls[GAME_PANEL_LIGHT_SWITCH].value =
2331     (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
2332   game_panel_controls[GAME_PANEL_LIGHT_SWITCH_TIME].value =
2333     game.light_time_left;
2334
2335   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH].value =
2336     (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
2337   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH_TIME].value =
2338     game.timegate_time_left;
2339
2340   game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
2341     EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
2342
2343   game_panel_controls[GAME_PANEL_EMC_LENSES].value =
2344     (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
2345   game_panel_controls[GAME_PANEL_EMC_LENSES_TIME].value =
2346     game.lenses_time_left;
2347
2348   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER].value =
2349     (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
2350   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER_TIME].value =
2351     game.magnify_time_left;
2352
2353   game_panel_controls[GAME_PANEL_BALLOON_SWITCH].value =
2354     (game.wind_direction == MV_LEFT  ? EL_BALLOON_SWITCH_LEFT  :
2355      game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
2356      game.wind_direction == MV_UP    ? EL_BALLOON_SWITCH_UP    :
2357      game.wind_direction == MV_DOWN  ? EL_BALLOON_SWITCH_DOWN  :
2358      EL_BALLOON_SWITCH_NONE);
2359
2360   game_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
2361     local_player->dynabomb_count;
2362   game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
2363     local_player->dynabomb_size;
2364   game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
2365     (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
2366
2367   game_panel_controls[GAME_PANEL_PENGUINS].value =
2368     local_player->friends_still_needed;
2369
2370   game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
2371     local_player->sokobanfields_still_needed;
2372   game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
2373     local_player->sokobanfields_still_needed;
2374
2375   game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
2376     (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
2377
2378   for (i = 0; i < NUM_BELTS; i++)
2379   {
2380     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1 + i].value =
2381       (game.belt_dir[i] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
2382        EL_CONVEYOR_BELT_1_MIDDLE) + i;
2383     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH + i].value =
2384       getBeltSwitchElementFromBeltNrAndBeltDir(i, game.belt_dir[i]);
2385   }
2386
2387   game_panel_controls[GAME_PANEL_MAGIC_WALL].value =
2388     (game.magic_wall_active ? EL_MAGIC_WALL_ACTIVE : EL_MAGIC_WALL);
2389   game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
2390     game.magic_wall_time_left;
2391
2392   game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
2393     local_player->gravity;
2394
2395   for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
2396     game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
2397
2398   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2399     game_panel_controls[GAME_PANEL_ELEMENT_1 + i].value =
2400       (IS_DRAWABLE_ELEMENT(game.panel.element[i].id) ?
2401        game.panel.element[i].id : EL_UNDEFINED);
2402
2403   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2404     game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value =
2405       (IS_VALID_ELEMENT(game.panel.element_count[i].id) ?
2406        element_info[game.panel.element_count[i].id].element_count : 0);
2407
2408   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2409     game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value =
2410       (IS_CUSTOM_ELEMENT(game.panel.ce_score[i].id) ?
2411        element_info[game.panel.ce_score[i].id].collect_score : 0);
2412
2413   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2414     game_panel_controls[GAME_PANEL_CE_SCORE_1_ELEMENT + i].value =
2415       (IS_CUSTOM_ELEMENT(game.panel.ce_score_element[i].id) ?
2416        element_info[game.panel.ce_score_element[i].id].collect_score :
2417        EL_UNDEFINED);
2418
2419   game_panel_controls[GAME_PANEL_PLAYER_NAME].value = 0;
2420   game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
2421   game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
2422
2423   /* update game panel control frames */
2424
2425   for (i = 0; game_panel_controls[i].nr != -1; i++)
2426   {
2427     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2428
2429     if (gpc->type == TYPE_ELEMENT)
2430     {
2431       if (gpc->value != EL_UNDEFINED && gpc->value != EL_EMPTY)
2432       {
2433         int last_anim_random_frame = gfx.anim_random_frame;
2434         int element = gpc->value;
2435         int graphic = el2panelimg(element);
2436
2437         if (gpc->value != gpc->last_value)
2438         {
2439           gpc->gfx_frame = 0;
2440           gpc->gfx_random = INIT_GFX_RANDOM();
2441         }
2442         else
2443         {
2444           gpc->gfx_frame++;
2445
2446           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2447               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2448             gpc->gfx_random = INIT_GFX_RANDOM();
2449         }
2450
2451         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2452           gfx.anim_random_frame = gpc->gfx_random;
2453
2454         if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
2455           gpc->gfx_frame = element_info[element].collect_score;
2456
2457         gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
2458                                               gpc->gfx_frame);
2459
2460         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2461           gfx.anim_random_frame = last_anim_random_frame;
2462       }
2463     }
2464     else if (gpc->type == TYPE_GRAPHIC)
2465     {
2466       if (gpc->graphic != IMG_UNDEFINED)
2467       {
2468         int last_anim_random_frame = gfx.anim_random_frame;
2469         int graphic = gpc->graphic;
2470
2471         if (gpc->value != gpc->last_value)
2472         {
2473           gpc->gfx_frame = 0;
2474           gpc->gfx_random = INIT_GFX_RANDOM();
2475         }
2476         else
2477         {
2478           gpc->gfx_frame++;
2479
2480           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2481               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2482             gpc->gfx_random = INIT_GFX_RANDOM();
2483         }
2484
2485         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2486           gfx.anim_random_frame = gpc->gfx_random;
2487
2488         gpc->frame = getGraphicAnimationFrame(graphic, gpc->gfx_frame);
2489
2490         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2491           gfx.anim_random_frame = last_anim_random_frame;
2492       }
2493     }
2494   }
2495 }
2496
2497 void DisplayGameControlValues()
2498 {
2499   boolean redraw_panel = FALSE;
2500   int i;
2501
2502   for (i = 0; game_panel_controls[i].nr != -1; i++)
2503   {
2504     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2505
2506     if (PANEL_DEACTIVATED(gpc->pos))
2507       continue;
2508
2509     if (gpc->value == gpc->last_value &&
2510         gpc->frame == gpc->last_frame)
2511       continue;
2512
2513     redraw_panel = TRUE;
2514   }
2515
2516   if (!redraw_panel)
2517     return;
2518
2519   /* copy default game door content to main double buffer */
2520
2521   /* !!! CHECK AGAIN !!! */
2522   SetPanelBackground();
2523   // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
2524   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2525
2526   /* redraw game control buttons */
2527   RedrawGameButtons();
2528
2529   SetGameStatus(GAME_MODE_PSEUDO_PANEL);
2530
2531   for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
2532   {
2533     int nr = game_panel_order[i].nr;
2534     struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
2535     struct TextPosInfo *pos = gpc->pos;
2536     int type = gpc->type;
2537     int value = gpc->value;
2538     int frame = gpc->frame;
2539     int size = pos->size;
2540     int font = pos->font;
2541     boolean draw_masked = pos->draw_masked;
2542     int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_OPAQUE);
2543
2544     if (PANEL_DEACTIVATED(pos))
2545       continue;
2546
2547     gpc->last_value = value;
2548     gpc->last_frame = frame;
2549
2550     if (type == TYPE_INTEGER)
2551     {
2552       if (nr == GAME_PANEL_LEVEL_NUMBER ||
2553           nr == GAME_PANEL_TIME)
2554       {
2555         boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
2556
2557         if (use_dynamic_size)           /* use dynamic number of digits */
2558         {
2559           int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
2560           int size1 = (nr == GAME_PANEL_LEVEL_NUMBER ? 2 : 3);
2561           int size2 = size1 + 1;
2562           int font1 = pos->font;
2563           int font2 = pos->font_alt;
2564
2565           size = (value < value_change ? size1 : size2);
2566           font = (value < value_change ? font1 : font2);
2567         }
2568       }
2569
2570       /* correct text size if "digits" is zero or less */
2571       if (size <= 0)
2572         size = strlen(int2str(value, size));
2573
2574       /* dynamically correct text alignment */
2575       pos->width = size * getFontWidth(font);
2576
2577       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2578                   int2str(value, size), font, mask_mode);
2579     }
2580     else if (type == TYPE_ELEMENT)
2581     {
2582       int element, graphic;
2583       Bitmap *src_bitmap;
2584       int src_x, src_y;
2585       int width, height;
2586       int dst_x = PANEL_XPOS(pos);
2587       int dst_y = PANEL_YPOS(pos);
2588
2589       if (value != EL_UNDEFINED && value != EL_EMPTY)
2590       {
2591         element = value;
2592         graphic = el2panelimg(value);
2593
2594         // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
2595
2596         if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
2597           size = TILESIZE;
2598
2599         getSizedGraphicSource(graphic, frame, size, &src_bitmap,
2600                               &src_x, &src_y);
2601
2602         width  = graphic_info[graphic].width  * size / TILESIZE;
2603         height = graphic_info[graphic].height * size / TILESIZE;
2604
2605         if (draw_masked)
2606           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2607                            dst_x, dst_y);
2608         else
2609           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2610                      dst_x, dst_y);
2611       }
2612     }
2613     else if (type == TYPE_GRAPHIC)
2614     {
2615       int graphic        = gpc->graphic;
2616       int graphic_active = gpc->graphic_active;
2617       Bitmap *src_bitmap;
2618       int src_x, src_y;
2619       int width, height;
2620       int dst_x = PANEL_XPOS(pos);
2621       int dst_y = PANEL_YPOS(pos);
2622       boolean skip = (pos->class == get_hash_from_key("mm_engine_only") &&
2623                       level.game_engine_type != GAME_ENGINE_TYPE_MM);
2624
2625       if (graphic != IMG_UNDEFINED && !skip)
2626       {
2627         if (pos->style == STYLE_REVERSE)
2628           value = 100 - value;
2629
2630         getGraphicSource(graphic_active, frame, &src_bitmap, &src_x, &src_y);
2631
2632         if (pos->direction & MV_HORIZONTAL)
2633         {
2634           width  = graphic_info[graphic_active].width * value / 100;
2635           height = graphic_info[graphic_active].height;
2636
2637           if (pos->direction == MV_LEFT)
2638           {
2639             src_x += graphic_info[graphic_active].width - width;
2640             dst_x += graphic_info[graphic_active].width - width;
2641           }
2642         }
2643         else
2644         {
2645           width  = graphic_info[graphic_active].width;
2646           height = graphic_info[graphic_active].height * value / 100;
2647
2648           if (pos->direction == MV_UP)
2649           {
2650             src_y += graphic_info[graphic_active].height - height;
2651             dst_y += graphic_info[graphic_active].height - height;
2652           }
2653         }
2654
2655         if (draw_masked)
2656           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2657                            dst_x, dst_y);
2658         else
2659           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2660                      dst_x, dst_y);
2661
2662         getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2663
2664         if (pos->direction & MV_HORIZONTAL)
2665         {
2666           if (pos->direction == MV_RIGHT)
2667           {
2668             src_x += width;
2669             dst_x += width;
2670           }
2671           else
2672           {
2673             dst_x = PANEL_XPOS(pos);
2674           }
2675
2676           width = graphic_info[graphic].width - width;
2677         }
2678         else
2679         {
2680           if (pos->direction == MV_DOWN)
2681           {
2682             src_y += height;
2683             dst_y += height;
2684           }
2685           else
2686           {
2687             dst_y = PANEL_YPOS(pos);
2688           }
2689
2690           height = graphic_info[graphic].height - height;
2691         }
2692
2693         if (draw_masked)
2694           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2695                            dst_x, dst_y);
2696         else
2697           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2698                      dst_x, dst_y);
2699       }
2700     }
2701     else if (type == TYPE_STRING)
2702     {
2703       boolean active = (value != 0);
2704       char *state_normal = "off";
2705       char *state_active = "on";
2706       char *state = (active ? state_active : state_normal);
2707       char *s = (nr == GAME_PANEL_GRAVITY_STATE ? state :
2708                  nr == GAME_PANEL_PLAYER_NAME   ? setup.player_name :
2709                  nr == GAME_PANEL_LEVEL_NAME    ? level.name :
2710                  nr == GAME_PANEL_LEVEL_AUTHOR  ? level.author : NULL);
2711
2712       if (nr == GAME_PANEL_GRAVITY_STATE)
2713       {
2714         int font1 = pos->font;          /* (used for normal state) */
2715         int font2 = pos->font_alt;      /* (used for active state) */
2716
2717         font = (active ? font2 : font1);
2718       }
2719
2720       if (s != NULL)
2721       {
2722         char *s_cut;
2723
2724         if (size <= 0)
2725         {
2726           /* don't truncate output if "chars" is zero or less */
2727           size = strlen(s);
2728
2729           /* dynamically correct text alignment */
2730           pos->width = size * getFontWidth(font);
2731         }
2732
2733         s_cut = getStringCopyN(s, size);
2734
2735         DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2736                     s_cut, font, mask_mode);
2737
2738         free(s_cut);
2739       }
2740     }
2741
2742     redraw_mask |= REDRAW_DOOR_1;
2743   }
2744
2745   SetGameStatus(GAME_MODE_PLAYING);
2746 }
2747
2748 void UpdateAndDisplayGameControlValues()
2749 {
2750   if (tape.deactivate_display)
2751     return;
2752
2753   UpdateGameControlValues();
2754   DisplayGameControlValues();
2755 }
2756
2757 void UpdateGameDoorValues()
2758 {
2759   UpdateGameControlValues();
2760 }
2761
2762 void DrawGameDoorValues()
2763 {
2764   DisplayGameControlValues();
2765 }
2766
2767
2768 /*
2769   =============================================================================
2770   InitGameEngine()
2771   -----------------------------------------------------------------------------
2772   initialize game engine due to level / tape version number
2773   =============================================================================
2774 */
2775
2776 static void InitGameEngine()
2777 {
2778   int i, j, k, l, x, y;
2779
2780   /* set game engine from tape file when re-playing, else from level file */
2781   game.engine_version = (tape.playing ? tape.engine_version :
2782                          level.game_version);
2783
2784   /* set single or multi-player game mode (needed for re-playing tapes) */
2785   game.team_mode = setup.team_mode;
2786
2787   if (tape.playing)
2788   {
2789     int num_players = 0;
2790
2791     for (i = 0; i < MAX_PLAYERS; i++)
2792       if (tape.player_participates[i])
2793         num_players++;
2794
2795     /* multi-player tapes contain input data for more than one player */
2796     game.team_mode = (num_players > 1);
2797   }
2798
2799   /* ---------------------------------------------------------------------- */
2800   /* set flags for bugs and changes according to active game engine version */
2801   /* ---------------------------------------------------------------------- */
2802
2803   /*
2804     Summary of bugfix/change:
2805     Fixed handling for custom elements that change when pushed by the player.
2806
2807     Fixed/changed in version:
2808     3.1.0
2809
2810     Description:
2811     Before 3.1.0, custom elements that "change when pushing" changed directly
2812     after the player started pushing them (until then handled in "DigField()").
2813     Since 3.1.0, these custom elements are not changed until the "pushing"
2814     move of the element is finished (now handled in "ContinueMoving()").
2815
2816     Affected levels/tapes:
2817     The first condition is generally needed for all levels/tapes before version
2818     3.1.0, which might use the old behaviour before it was changed; known tapes
2819     that are affected are some tapes from the level set "Walpurgis Gardens" by
2820     Jamie Cullen.
2821     The second condition is an exception from the above case and is needed for
2822     the special case of tapes recorded with game (not engine!) version 3.1.0 or
2823     above (including some development versions of 3.1.0), but before it was
2824     known that this change would break tapes like the above and was fixed in
2825     3.1.1, so that the changed behaviour was active although the engine version
2826     while recording maybe was before 3.1.0. There is at least one tape that is
2827     affected by this exception, which is the tape for the one-level set "Bug
2828     Machine" by Juergen Bonhagen.
2829   */
2830
2831   game.use_change_when_pushing_bug =
2832     (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2833      !(tape.playing &&
2834        tape.game_version >= VERSION_IDENT(3,1,0,0) &&
2835        tape.game_version <  VERSION_IDENT(3,1,1,0)));
2836
2837   /*
2838     Summary of bugfix/change:
2839     Fixed handling for blocking the field the player leaves when moving.
2840
2841     Fixed/changed in version:
2842     3.1.1
2843
2844     Description:
2845     Before 3.1.1, when "block last field when moving" was enabled, the field
2846     the player is leaving when moving was blocked for the time of the move,
2847     and was directly unblocked afterwards. This resulted in the last field
2848     being blocked for exactly one less than the number of frames of one player
2849     move. Additionally, even when blocking was disabled, the last field was
2850     blocked for exactly one frame.
2851     Since 3.1.1, due to changes in player movement handling, the last field
2852     is not blocked at all when blocking is disabled. When blocking is enabled,
2853     the last field is blocked for exactly the number of frames of one player
2854     move. Additionally, if the player is Murphy, the hero of Supaplex, the
2855     last field is blocked for exactly one more than the number of frames of
2856     one player move.
2857
2858     Affected levels/tapes:
2859     (!!! yet to be determined -- probably many !!!)
2860   */
2861
2862   game.use_block_last_field_bug =
2863     (game.engine_version < VERSION_IDENT(3,1,1,0));
2864
2865   game_em.use_single_button =
2866     (game.engine_version > VERSION_IDENT(4,0,0,2));
2867
2868   game_em.use_snap_key_bug =
2869     (game.engine_version < VERSION_IDENT(4,0,1,0));
2870
2871   /* ---------------------------------------------------------------------- */
2872
2873   /* set maximal allowed number of custom element changes per game frame */
2874   game.max_num_changes_per_frame = 1;
2875
2876   /* default scan direction: scan playfield from top/left to bottom/right */
2877   InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
2878
2879   /* dynamically adjust element properties according to game engine version */
2880   InitElementPropertiesEngine(game.engine_version);
2881
2882 #if 0
2883   printf("level %d: level version == %06d\n", level_nr, level.game_version);
2884   printf("          tape version == %06d [%s] [file: %06d]\n",
2885          tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
2886          tape.file_version);
2887   printf("       => game.engine_version == %06d\n", game.engine_version);
2888 #endif
2889
2890   /* ---------- initialize player's initial move delay --------------------- */
2891
2892   /* dynamically adjust player properties according to level information */
2893   for (i = 0; i < MAX_PLAYERS; i++)
2894     game.initial_move_delay_value[i] =
2895       get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
2896
2897   /* dynamically adjust player properties according to game engine version */
2898   for (i = 0; i < MAX_PLAYERS; i++)
2899     game.initial_move_delay[i] =
2900       (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
2901        game.initial_move_delay_value[i] : 0);
2902
2903   /* ---------- initialize player's initial push delay --------------------- */
2904
2905   /* dynamically adjust player properties according to game engine version */
2906   game.initial_push_delay_value =
2907     (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1);
2908
2909   /* ---------- initialize changing elements ------------------------------- */
2910
2911   /* initialize changing elements information */
2912   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2913   {
2914     struct ElementInfo *ei = &element_info[i];
2915
2916     /* this pointer might have been changed in the level editor */
2917     ei->change = &ei->change_page[0];
2918
2919     if (!IS_CUSTOM_ELEMENT(i))
2920     {
2921       ei->change->target_element = EL_EMPTY_SPACE;
2922       ei->change->delay_fixed = 0;
2923       ei->change->delay_random = 0;
2924       ei->change->delay_frames = 1;
2925     }
2926
2927     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2928     {
2929       ei->has_change_event[j] = FALSE;
2930
2931       ei->event_page_nr[j] = 0;
2932       ei->event_page[j] = &ei->change_page[0];
2933     }
2934   }
2935
2936   /* add changing elements from pre-defined list */
2937   for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++)
2938   {
2939     struct ChangingElementInfo *ch_delay = &change_delay_list[i];
2940     struct ElementInfo *ei = &element_info[ch_delay->element];
2941
2942     ei->change->target_element       = ch_delay->target_element;
2943     ei->change->delay_fixed          = ch_delay->change_delay;
2944
2945     ei->change->pre_change_function  = ch_delay->pre_change_function;
2946     ei->change->change_function      = ch_delay->change_function;
2947     ei->change->post_change_function = ch_delay->post_change_function;
2948
2949     ei->change->can_change = TRUE;
2950     ei->change->can_change_or_has_action = TRUE;
2951
2952     ei->has_change_event[CE_DELAY] = TRUE;
2953
2954     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
2955     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
2956   }
2957
2958   /* ---------- initialize internal run-time variables --------------------- */
2959
2960   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2961   {
2962     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2963
2964     for (j = 0; j < ei->num_change_pages; j++)
2965     {
2966       ei->change_page[j].can_change_or_has_action =
2967         (ei->change_page[j].can_change |
2968          ei->change_page[j].has_action);
2969     }
2970   }
2971
2972   /* add change events from custom element configuration */
2973   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2974   {
2975     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2976
2977     for (j = 0; j < ei->num_change_pages; j++)
2978     {
2979       if (!ei->change_page[j].can_change_or_has_action)
2980         continue;
2981
2982       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
2983       {
2984         /* only add event page for the first page found with this event */
2985         if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
2986         {
2987           ei->has_change_event[k] = TRUE;
2988
2989           ei->event_page_nr[k] = j;
2990           ei->event_page[k] = &ei->change_page[j];
2991         }
2992       }
2993     }
2994   }
2995
2996   /* ---------- initialize reference elements in change conditions --------- */
2997
2998   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2999   {
3000     int element = EL_CUSTOM_START + i;
3001     struct ElementInfo *ei = &element_info[element];
3002
3003     for (j = 0; j < ei->num_change_pages; j++)
3004     {
3005       int trigger_element = ei->change_page[j].initial_trigger_element;
3006
3007       if (trigger_element >= EL_PREV_CE_8 &&
3008           trigger_element <= EL_NEXT_CE_8)
3009         trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
3010
3011       ei->change_page[j].trigger_element = trigger_element;
3012     }
3013   }
3014
3015   /* ---------- initialize run-time trigger player and element ------------- */
3016
3017   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3018   {
3019     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
3020
3021     for (j = 0; j < ei->num_change_pages; j++)
3022     {
3023       ei->change_page[j].actual_trigger_element = EL_EMPTY;
3024       ei->change_page[j].actual_trigger_player = EL_EMPTY;
3025       ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
3026       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
3027       ei->change_page[j].actual_trigger_ce_value = 0;
3028       ei->change_page[j].actual_trigger_ce_score = 0;
3029     }
3030   }
3031
3032   /* ---------- initialize trigger events ---------------------------------- */
3033
3034   /* initialize trigger events information */
3035   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3036     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
3037       trigger_events[i][j] = FALSE;
3038
3039   /* add trigger events from element change event properties */
3040   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3041   {
3042     struct ElementInfo *ei = &element_info[i];
3043
3044     for (j = 0; j < ei->num_change_pages; j++)
3045     {
3046       if (!ei->change_page[j].can_change_or_has_action)
3047         continue;
3048
3049       if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
3050       {
3051         int trigger_element = ei->change_page[j].trigger_element;
3052
3053         for (k = 0; k < NUM_CHANGE_EVENTS; k++)
3054         {
3055           if (ei->change_page[j].has_event[k])
3056           {
3057             if (IS_GROUP_ELEMENT(trigger_element))
3058             {
3059               struct ElementGroupInfo *group =
3060                 element_info[trigger_element].group;
3061
3062               for (l = 0; l < group->num_elements_resolved; l++)
3063                 trigger_events[group->element_resolved[l]][k] = TRUE;
3064             }
3065             else if (trigger_element == EL_ANY_ELEMENT)
3066               for (l = 0; l < MAX_NUM_ELEMENTS; l++)
3067                 trigger_events[l][k] = TRUE;
3068             else
3069               trigger_events[trigger_element][k] = TRUE;
3070           }
3071         }
3072       }
3073     }
3074   }
3075
3076   /* ---------- initialize push delay -------------------------------------- */
3077
3078   /* initialize push delay values to default */
3079   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3080   {
3081     if (!IS_CUSTOM_ELEMENT(i))
3082     {
3083       /* set default push delay values (corrected since version 3.0.7-1) */
3084       if (game.engine_version < VERSION_IDENT(3,0,7,1))
3085       {
3086         element_info[i].push_delay_fixed = 2;
3087         element_info[i].push_delay_random = 8;
3088       }
3089       else
3090       {
3091         element_info[i].push_delay_fixed = 8;
3092         element_info[i].push_delay_random = 8;
3093       }
3094     }
3095   }
3096
3097   /* set push delay value for certain elements from pre-defined list */
3098   for (i = 0; push_delay_list[i].element != EL_UNDEFINED; i++)
3099   {
3100     int e = push_delay_list[i].element;
3101
3102     element_info[e].push_delay_fixed  = push_delay_list[i].push_delay_fixed;
3103     element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
3104   }
3105
3106   /* set push delay value for Supaplex elements for newer engine versions */
3107   if (game.engine_version >= VERSION_IDENT(3,1,0,0))
3108   {
3109     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3110     {
3111       if (IS_SP_ELEMENT(i))
3112       {
3113         /* set SP push delay to just enough to push under a falling zonk */
3114         int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
3115
3116         element_info[i].push_delay_fixed  = delay;
3117         element_info[i].push_delay_random = 0;
3118       }
3119     }
3120   }
3121
3122   /* ---------- initialize move stepsize ----------------------------------- */
3123
3124   /* initialize move stepsize values to default */
3125   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3126     if (!IS_CUSTOM_ELEMENT(i))
3127       element_info[i].move_stepsize = MOVE_STEPSIZE_NORMAL;
3128
3129   /* set move stepsize value for certain elements from pre-defined list */
3130   for (i = 0; move_stepsize_list[i].element != EL_UNDEFINED; i++)
3131   {
3132     int e = move_stepsize_list[i].element;
3133
3134     element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
3135   }
3136
3137   /* ---------- initialize collect score ----------------------------------- */
3138
3139   /* initialize collect score values for custom elements from initial value */
3140   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3141     if (IS_CUSTOM_ELEMENT(i))
3142       element_info[i].collect_score = element_info[i].collect_score_initial;
3143
3144   /* ---------- initialize collect count ----------------------------------- */
3145
3146   /* initialize collect count values for non-custom elements */
3147   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3148     if (!IS_CUSTOM_ELEMENT(i))
3149       element_info[i].collect_count_initial = 0;
3150
3151   /* add collect count values for all elements from pre-defined list */
3152   for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
3153     element_info[collect_count_list[i].element].collect_count_initial =
3154       collect_count_list[i].count;
3155
3156   /* ---------- initialize access direction -------------------------------- */
3157
3158   /* initialize access direction values to default (access from every side) */
3159   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3160     if (!IS_CUSTOM_ELEMENT(i))
3161       element_info[i].access_direction = MV_ALL_DIRECTIONS;
3162
3163   /* set access direction value for certain elements from pre-defined list */
3164   for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
3165     element_info[access_direction_list[i].element].access_direction =
3166       access_direction_list[i].direction;
3167
3168   /* ---------- initialize explosion content ------------------------------- */
3169   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3170   {
3171     if (IS_CUSTOM_ELEMENT(i))
3172       continue;
3173
3174     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
3175     {
3176       /* (content for EL_YAMYAM set at run-time with game.yamyam_content_nr) */
3177
3178       element_info[i].content.e[x][y] =
3179         (i == EL_PLAYER_1 ? EL_EMERALD_YELLOW :
3180          i == EL_PLAYER_2 ? EL_EMERALD_RED :
3181          i == EL_PLAYER_3 ? EL_EMERALD :
3182          i == EL_PLAYER_4 ? EL_EMERALD_PURPLE :
3183          i == EL_MOLE ? EL_EMERALD_RED :
3184          i == EL_PENGUIN ? EL_EMERALD_PURPLE :
3185          i == EL_BUG ? (x == 1 && y == 1 ? EL_DIAMOND : EL_EMERALD) :
3186          i == EL_BD_BUTTERFLY ? EL_BD_DIAMOND :
3187          i == EL_SP_ELECTRON ? EL_SP_INFOTRON :
3188          i == EL_AMOEBA_TO_DIAMOND ? level.amoeba_content :
3189          i == EL_WALL_EMERALD ? EL_EMERALD :
3190          i == EL_WALL_DIAMOND ? EL_DIAMOND :
3191          i == EL_WALL_BD_DIAMOND ? EL_BD_DIAMOND :
3192          i == EL_WALL_EMERALD_YELLOW ? EL_EMERALD_YELLOW :
3193          i == EL_WALL_EMERALD_RED ? EL_EMERALD_RED :
3194          i == EL_WALL_EMERALD_PURPLE ? EL_EMERALD_PURPLE :
3195          i == EL_WALL_PEARL ? EL_PEARL :
3196          i == EL_WALL_CRYSTAL ? EL_CRYSTAL :
3197          EL_EMPTY);
3198     }
3199   }
3200
3201   /* ---------- initialize recursion detection ------------------------------ */
3202   recursion_loop_depth = 0;
3203   recursion_loop_detected = FALSE;
3204   recursion_loop_element = EL_UNDEFINED;
3205
3206   /* ---------- initialize graphics engine ---------------------------------- */
3207   game.scroll_delay_value =
3208     (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
3209      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
3210   game.scroll_delay_value =
3211     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
3212
3213   /* ---------- initialize game engine snapshots ---------------------------- */
3214   for (i = 0; i < MAX_PLAYERS; i++)
3215     game.snapshot.last_action[i] = 0;
3216   game.snapshot.changed_action = FALSE;
3217   game.snapshot.collected_item = FALSE;
3218   game.snapshot.mode =
3219     (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
3220      SNAPSHOT_MODE_EVERY_STEP :
3221      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
3222      SNAPSHOT_MODE_EVERY_MOVE :
3223      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
3224      SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
3225   game.snapshot.save_snapshot = FALSE;
3226
3227   /* ---------- initialize level time for Supaplex engine ------------------- */
3228   /* Supaplex levels with time limit currently unsupported -- should be added */
3229   if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3230     level.time = 0;
3231 }
3232
3233 int get_num_special_action(int element, int action_first, int action_last)
3234 {
3235   int num_special_action = 0;
3236   int i, j;
3237
3238   for (i = action_first; i <= action_last; i++)
3239   {
3240     boolean found = FALSE;
3241
3242     for (j = 0; j < NUM_DIRECTIONS; j++)
3243       if (el_act_dir2img(element, i, j) !=
3244           el_act_dir2img(element, ACTION_DEFAULT, j))
3245         found = TRUE;
3246
3247     if (found)
3248       num_special_action++;
3249     else
3250       break;
3251   }
3252
3253   return num_special_action;
3254 }
3255
3256
3257 /*
3258   =============================================================================
3259   InitGame()
3260   -----------------------------------------------------------------------------
3261   initialize and start new game
3262   =============================================================================
3263 */
3264
3265 void InitGame()
3266 {
3267   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
3268   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
3269   int fade_mask = REDRAW_FIELD;
3270
3271   boolean emulate_bd = TRUE;    /* unless non-BOULDERDASH elements found */
3272   boolean emulate_sb = TRUE;    /* unless non-SOKOBAN     elements found */
3273   boolean emulate_sp = TRUE;    /* unless non-SUPAPLEX    elements found */
3274   int initial_move_dir = MV_DOWN;
3275   int i, j, x, y;
3276
3277   // required here to update video display before fading (FIX THIS)
3278   DrawMaskedBorder(REDRAW_DOOR_2);
3279
3280   if (!game.restart_level)
3281     CloseDoor(DOOR_CLOSE_1);
3282
3283   SetGameStatus(GAME_MODE_PLAYING);
3284
3285   if (level_editor_test_game)
3286     FadeSkipNextFadeIn();
3287   else
3288     FadeSetEnterScreen();
3289
3290   if (CheckIfGlobalBorderHasChanged())
3291     fade_mask = REDRAW_ALL;
3292
3293   FadeLevelSoundsAndMusic();
3294
3295   ExpireSoundLoops(TRUE);
3296
3297   FadeOut(fade_mask);
3298
3299   /* needed if different viewport properties defined for playing */
3300   ChangeViewportPropertiesIfNeeded();
3301
3302   ClearField();
3303
3304   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
3305
3306   DrawCompleteVideoDisplay();
3307
3308   InitGameEngine();
3309   InitGameControlValues();
3310
3311   /* don't play tapes over network */
3312   network_playing = (options.network && !tape.playing);
3313
3314   for (i = 0; i < MAX_PLAYERS; i++)
3315   {
3316     struct PlayerInfo *player = &stored_player[i];
3317
3318     player->index_nr = i;
3319     player->index_bit = (1 << i);
3320     player->element_nr = EL_PLAYER_1 + i;
3321
3322     player->present = FALSE;
3323     player->active = FALSE;
3324     player->mapped = FALSE;
3325
3326     player->killed = FALSE;
3327     player->reanimated = FALSE;
3328
3329     player->action = 0;
3330     player->effective_action = 0;
3331     player->programmed_action = 0;
3332
3333     player->mouse_action.lx = 0;
3334     player->mouse_action.ly = 0;
3335     player->mouse_action.button = 0;
3336
3337     player->score = 0;
3338     player->score_final = 0;
3339
3340     player->gems_still_needed = level.gems_needed;
3341     player->sokobanfields_still_needed = 0;
3342     player->lights_still_needed = 0;
3343     player->friends_still_needed = 0;
3344
3345     for (j = 0; j < MAX_NUM_KEYS; j++)
3346       player->key[j] = FALSE;
3347
3348     player->num_white_keys = 0;
3349
3350     player->dynabomb_count = 0;
3351     player->dynabomb_size = 1;
3352     player->dynabombs_left = 0;
3353     player->dynabomb_xl = FALSE;
3354
3355     player->MovDir = initial_move_dir;
3356     player->MovPos = 0;
3357     player->GfxPos = 0;
3358     player->GfxDir = initial_move_dir;
3359     player->GfxAction = ACTION_DEFAULT;
3360     player->Frame = 0;
3361     player->StepFrame = 0;
3362
3363     player->initial_element = player->element_nr;
3364     player->artwork_element =
3365       (level.use_artwork_element[i] ? level.artwork_element[i] :
3366        player->element_nr);
3367     player->use_murphy = FALSE;
3368
3369     player->block_last_field = FALSE;   /* initialized in InitPlayerField() */
3370     player->block_delay_adjustment = 0; /* initialized in InitPlayerField() */
3371
3372     player->gravity = level.initial_player_gravity[i];
3373
3374     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
3375
3376     player->actual_frame_counter = 0;
3377
3378     player->step_counter = 0;
3379
3380     player->last_move_dir = initial_move_dir;
3381
3382     player->is_active = FALSE;
3383
3384     player->is_waiting = FALSE;
3385     player->is_moving = FALSE;
3386     player->is_auto_moving = FALSE;
3387     player->is_digging = FALSE;
3388     player->is_snapping = FALSE;
3389     player->is_collecting = FALSE;
3390     player->is_pushing = FALSE;
3391     player->is_switching = FALSE;
3392     player->is_dropping = FALSE;
3393     player->is_dropping_pressed = FALSE;
3394
3395     player->is_bored = FALSE;
3396     player->is_sleeping = FALSE;
3397
3398     player->was_waiting = TRUE;
3399     player->was_moving = FALSE;
3400     player->was_snapping = FALSE;
3401     player->was_dropping = FALSE;
3402
3403     player->force_dropping = FALSE;
3404
3405     player->frame_counter_bored = -1;
3406     player->frame_counter_sleeping = -1;
3407
3408     player->anim_delay_counter = 0;
3409     player->post_delay_counter = 0;
3410
3411     player->dir_waiting = initial_move_dir;
3412     player->action_waiting = ACTION_DEFAULT;
3413     player->last_action_waiting = ACTION_DEFAULT;
3414     player->special_action_bored = ACTION_DEFAULT;
3415     player->special_action_sleeping = ACTION_DEFAULT;
3416
3417     player->switch_x = -1;
3418     player->switch_y = -1;
3419
3420     player->drop_x = -1;
3421     player->drop_y = -1;
3422
3423     player->show_envelope = 0;
3424
3425     SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
3426
3427     player->push_delay       = -1;      /* initialized when pushing starts */
3428     player->push_delay_value = game.initial_push_delay_value;
3429
3430     player->drop_delay = 0;
3431     player->drop_pressed_delay = 0;
3432
3433     player->last_jx = -1;
3434     player->last_jy = -1;
3435     player->jx = -1;
3436     player->jy = -1;
3437
3438     player->shield_normal_time_left = 0;
3439     player->shield_deadly_time_left = 0;
3440
3441     player->inventory_infinite_element = EL_UNDEFINED;
3442     player->inventory_size = 0;
3443
3444     if (level.use_initial_inventory[i])
3445     {
3446       for (j = 0; j < level.initial_inventory_size[i]; j++)
3447       {
3448         int element = level.initial_inventory_content[i][j];
3449         int collect_count = element_info[element].collect_count_initial;
3450         int k;
3451
3452         if (!IS_CUSTOM_ELEMENT(element))
3453           collect_count = 1;
3454
3455         if (collect_count == 0)
3456           player->inventory_infinite_element = element;
3457         else
3458           for (k = 0; k < collect_count; k++)
3459             if (player->inventory_size < MAX_INVENTORY_SIZE)
3460               player->inventory_element[player->inventory_size++] = element;
3461       }
3462     }
3463
3464     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
3465     SnapField(player, 0, 0);
3466
3467     player->LevelSolved = FALSE;
3468     player->GameOver = FALSE;
3469
3470     player->LevelSolved_GameWon = FALSE;
3471     player->LevelSolved_GameEnd = FALSE;
3472     player->LevelSolved_PanelOff = FALSE;
3473     player->LevelSolved_SaveTape = FALSE;
3474     player->LevelSolved_SaveScore = FALSE;
3475     player->LevelSolved_CountingTime = 0;
3476     player->LevelSolved_CountingScore = 0;
3477
3478     map_player_action[i] = i;
3479   }
3480
3481   network_player_action_received = FALSE;
3482
3483 #if defined(NETWORK_AVALIABLE)
3484   /* initial null action */
3485   if (network_playing)
3486     SendToServer_MovePlayer(MV_NONE);
3487 #endif
3488
3489   ZX = ZY = -1;
3490   ExitX = ExitY = -1;
3491
3492   FrameCounter = 0;
3493   TimeFrames = 0;
3494   TimePlayed = 0;
3495   TimeLeft = level.time;
3496   TapeTime = 0;
3497
3498   ScreenMovDir = MV_NONE;
3499   ScreenMovPos = 0;
3500   ScreenGfxPos = 0;
3501
3502   ScrollStepSize = 0;   /* will be correctly initialized by ScrollScreen() */
3503
3504   AllPlayersGone = FALSE;
3505
3506   game.no_time_limit = (level.time == 0);
3507
3508   game.yamyam_content_nr = 0;
3509   game.robot_wheel_active = FALSE;
3510   game.magic_wall_active = FALSE;
3511   game.magic_wall_time_left = 0;
3512   game.light_time_left = 0;
3513   game.timegate_time_left = 0;
3514   game.switchgate_pos = 0;
3515   game.wind_direction = level.wind_direction_initial;
3516
3517   game.lenses_time_left = 0;
3518   game.magnify_time_left = 0;
3519
3520   game.ball_state = level.ball_state_initial;
3521   game.ball_content_nr = 0;
3522
3523   game.envelope_active = FALSE;
3524
3525   /* set focus to local player for network games, else to all players */
3526   game.centered_player_nr = (network_playing ? local_player->index_nr : -1);
3527   game.centered_player_nr_next = game.centered_player_nr;
3528   game.set_centered_player = FALSE;
3529
3530   if (network_playing && tape.recording)
3531   {
3532     /* store client dependent player focus when recording network games */
3533     tape.centered_player_nr_next = game.centered_player_nr_next;
3534     tape.set_centered_player = TRUE;
3535   }
3536
3537   for (i = 0; i < NUM_BELTS; i++)
3538   {
3539     game.belt_dir[i] = MV_NONE;
3540     game.belt_dir_nr[i] = 3;            /* not moving, next moving left */
3541   }
3542
3543   for (i = 0; i < MAX_NUM_AMOEBA; i++)
3544     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
3545
3546 #if DEBUG_INIT_PLAYER
3547   if (options.debug)
3548   {
3549     printf("Player status at level initialization:\n");
3550   }
3551 #endif
3552
3553   SCAN_PLAYFIELD(x, y)
3554   {
3555     Feld[x][y] = level.field[x][y];
3556     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
3557     ChangeDelay[x][y] = 0;
3558     ChangePage[x][y] = -1;
3559     CustomValue[x][y] = 0;              /* initialized in InitField() */
3560     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
3561     AmoebaNr[x][y] = 0;
3562     WasJustMoving[x][y] = 0;
3563     WasJustFalling[x][y] = 0;
3564     CheckCollision[x][y] = 0;
3565     CheckImpact[x][y] = 0;
3566     Stop[x][y] = FALSE;
3567     Pushed[x][y] = FALSE;
3568
3569     ChangeCount[x][y] = 0;
3570     ChangeEvent[x][y] = -1;
3571
3572     ExplodePhase[x][y] = 0;
3573     ExplodeDelay[x][y] = 0;
3574     ExplodeField[x][y] = EX_TYPE_NONE;
3575
3576     RunnerVisit[x][y] = 0;
3577     PlayerVisit[x][y] = 0;
3578
3579     GfxFrame[x][y] = 0;
3580     GfxRandom[x][y] = INIT_GFX_RANDOM();
3581     GfxElement[x][y] = EL_UNDEFINED;
3582     GfxAction[x][y] = ACTION_DEFAULT;
3583     GfxDir[x][y] = MV_NONE;
3584     GfxRedraw[x][y] = GFX_REDRAW_NONE;
3585   }
3586
3587   SCAN_PLAYFIELD(x, y)
3588   {
3589     if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
3590       emulate_bd = FALSE;
3591     if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
3592       emulate_sb = FALSE;
3593     if (emulate_sp && !IS_SP_ELEMENT(Feld[x][y]))
3594       emulate_sp = FALSE;
3595
3596     InitField(x, y, TRUE);
3597
3598     ResetGfxAnimation(x, y);
3599   }
3600
3601   InitBeltMovement();
3602
3603   for (i = 0; i < MAX_PLAYERS; i++)
3604   {
3605     struct PlayerInfo *player = &stored_player[i];
3606
3607     /* set number of special actions for bored and sleeping animation */
3608     player->num_special_action_bored =
3609       get_num_special_action(player->artwork_element,
3610                              ACTION_BORING_1, ACTION_BORING_LAST);
3611     player->num_special_action_sleeping =
3612       get_num_special_action(player->artwork_element,
3613                              ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
3614   }
3615
3616   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
3617                     emulate_sb ? EMU_SOKOBAN :
3618                     emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
3619
3620   /* initialize type of slippery elements */
3621   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3622   {
3623     if (!IS_CUSTOM_ELEMENT(i))
3624     {
3625       /* default: elements slip down either to the left or right randomly */
3626       element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
3627
3628       /* SP style elements prefer to slip down on the left side */
3629       if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
3630         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3631
3632       /* BD style elements prefer to slip down on the left side */
3633       if (game.emulation == EMU_BOULDERDASH)
3634         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3635     }
3636   }
3637
3638   /* initialize explosion and ignition delay */
3639   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3640   {
3641     if (!IS_CUSTOM_ELEMENT(i))
3642     {
3643       int num_phase = 8;
3644       int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
3645                     game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
3646                    game.emulation == EMU_SUPAPLEX ? 3 : 2);
3647       int last_phase = (num_phase + 1) * delay;
3648       int half_phase = (num_phase / 2) * delay;
3649
3650       element_info[i].explosion_delay = last_phase - 1;
3651       element_info[i].ignition_delay = half_phase;
3652
3653       if (i == EL_BLACK_ORB)
3654         element_info[i].ignition_delay = 1;
3655     }
3656   }
3657
3658   /* correct non-moving belts to start moving left */
3659   for (i = 0; i < NUM_BELTS; i++)
3660     if (game.belt_dir[i] == MV_NONE)
3661       game.belt_dir_nr[i] = 3;          /* not moving, next moving left */
3662
3663 #if USE_NEW_PLAYER_ASSIGNMENTS
3664   /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */
3665   /* choose default local player */
3666   local_player = &stored_player[0];
3667
3668   for (i = 0; i < MAX_PLAYERS; i++)
3669     stored_player[i].connected = FALSE;
3670
3671   local_player->connected = TRUE;
3672   /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */
3673
3674   if (tape.playing)
3675   {
3676     for (i = 0; i < MAX_PLAYERS; i++)
3677       stored_player[i].connected = tape.player_participates[i];
3678   }
3679   else if (game.team_mode && !options.network)
3680   {
3681     /* try to guess locally connected team mode players (needed for correct
3682        assignment of player figures from level to locally playing players) */
3683
3684     for (i = 0; i < MAX_PLAYERS; i++)
3685       if (setup.input[i].use_joystick ||
3686           setup.input[i].key.left != KSYM_UNDEFINED)
3687         stored_player[i].connected = TRUE;
3688   }
3689
3690 #if DEBUG_INIT_PLAYER
3691   if (options.debug)
3692   {
3693     printf("Player status after level initialization:\n");
3694
3695     for (i = 0; i < MAX_PLAYERS; i++)
3696     {
3697       struct PlayerInfo *player = &stored_player[i];
3698
3699       printf("- player %d: present == %d, connected == %d, active == %d",
3700              i + 1,
3701              player->present,
3702              player->connected,
3703              player->active);
3704
3705       if (local_player == player)
3706         printf(" (local player)");
3707
3708       printf("\n");
3709     }
3710   }
3711 #endif
3712
3713 #if DEBUG_INIT_PLAYER
3714   if (options.debug)
3715     printf("Reassigning players ...\n");
3716 #endif
3717
3718   /* check if any connected player was not found in playfield */
3719   for (i = 0; i < MAX_PLAYERS; i++)
3720   {
3721     struct PlayerInfo *player = &stored_player[i];
3722
3723     if (player->connected && !player->present)
3724     {
3725       struct PlayerInfo *field_player = NULL;
3726
3727 #if DEBUG_INIT_PLAYER
3728       if (options.debug)
3729         printf("- looking for field player for player %d ...\n", i + 1);
3730 #endif
3731
3732       /* assign first free player found that is present in the playfield */
3733
3734       /* first try: look for unmapped playfield player that is not connected */
3735       for (j = 0; j < MAX_PLAYERS; j++)
3736         if (field_player == NULL &&
3737             stored_player[j].present &&
3738             !stored_player[j].mapped &&
3739             !stored_player[j].connected)
3740           field_player = &stored_player[j];
3741
3742       /* second try: look for *any* unmapped playfield player */
3743       for (j = 0; j < MAX_PLAYERS; j++)
3744         if (field_player == NULL &&
3745             stored_player[j].present &&
3746             !stored_player[j].mapped)
3747           field_player = &stored_player[j];
3748
3749       if (field_player != NULL)
3750       {
3751         int jx = field_player->jx, jy = field_player->jy;
3752
3753 #if DEBUG_INIT_PLAYER
3754         if (options.debug)
3755           printf("- found player %d\n", field_player->index_nr + 1);
3756 #endif
3757
3758         player->present = FALSE;
3759         player->active = FALSE;
3760
3761         field_player->present = TRUE;
3762         field_player->active = TRUE;
3763
3764         /*
3765         player->initial_element = field_player->initial_element;
3766         player->artwork_element = field_player->artwork_element;
3767
3768         player->block_last_field       = field_player->block_last_field;
3769         player->block_delay_adjustment = field_player->block_delay_adjustment;
3770         */
3771
3772         StorePlayer[jx][jy] = field_player->element_nr;
3773
3774         field_player->jx = field_player->last_jx = jx;
3775         field_player->jy = field_player->last_jy = jy;
3776
3777         if (local_player == player)
3778           local_player = field_player;
3779
3780         map_player_action[field_player->index_nr] = i;
3781
3782         field_player->mapped = TRUE;
3783
3784 #if DEBUG_INIT_PLAYER
3785         if (options.debug)
3786           printf("- map_player_action[%d] == %d\n",
3787                  field_player->index_nr + 1, i + 1);
3788 #endif
3789       }
3790     }
3791
3792     if (player->connected && player->present)
3793       player->mapped = TRUE;
3794   }
3795
3796 #if DEBUG_INIT_PLAYER
3797   if (options.debug)
3798   {
3799     printf("Player status after player assignment (first stage):\n");
3800
3801     for (i = 0; i < MAX_PLAYERS; i++)
3802     {
3803       struct PlayerInfo *player = &stored_player[i];
3804
3805       printf("- player %d: present == %d, connected == %d, active == %d",
3806              i + 1,
3807              player->present,
3808              player->connected,
3809              player->active);
3810
3811       if (local_player == player)
3812         printf(" (local player)");
3813
3814       printf("\n");
3815     }
3816   }
3817 #endif
3818
3819 #else
3820
3821   /* check if any connected player was not found in playfield */
3822   for (i = 0; i < MAX_PLAYERS; i++)
3823   {
3824     struct PlayerInfo *player = &stored_player[i];
3825
3826     if (player->connected && !player->present)
3827     {
3828       for (j = 0; j < MAX_PLAYERS; j++)
3829       {
3830         struct PlayerInfo *field_player = &stored_player[j];
3831         int jx = field_player->jx, jy = field_player->jy;
3832
3833         /* assign first free player found that is present in the playfield */
3834         if (field_player->present && !field_player->connected)
3835         {
3836           player->present = TRUE;
3837           player->active = TRUE;
3838
3839           field_player->present = FALSE;
3840           field_player->active = FALSE;
3841
3842           player->initial_element = field_player->initial_element;
3843           player->artwork_element = field_player->artwork_element;
3844
3845           player->block_last_field       = field_player->block_last_field;
3846           player->block_delay_adjustment = field_player->block_delay_adjustment;
3847
3848           StorePlayer[jx][jy] = player->element_nr;
3849
3850           player->jx = player->last_jx = jx;
3851           player->jy = player->last_jy = jy;
3852
3853           break;
3854         }
3855       }
3856     }
3857   }
3858 #endif
3859
3860 #if 0
3861   printf("::: local_player->present == %d\n", local_player->present);
3862 #endif
3863
3864   if (tape.playing)
3865   {
3866     /* when playing a tape, eliminate all players who do not participate */
3867
3868 #if USE_NEW_PLAYER_ASSIGNMENTS
3869
3870     if (!game.team_mode)
3871     {
3872       for (i = 0; i < MAX_PLAYERS; i++)
3873       {