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