1a204ba844a32892dfbe820aef484ab388aef870
[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   InitJoysticks();
1623 }
1624
1625 int GetElementFromGroupElement(int element)
1626 {
1627   if (IS_GROUP_ELEMENT(element))
1628   {
1629     struct ElementGroupInfo *group = element_info[element].group;
1630     int last_anim_random_frame = gfx.anim_random_frame;
1631     int element_pos;
1632
1633     if (group->choice_mode == ANIM_RANDOM)
1634       gfx.anim_random_frame = RND(group->num_elements_resolved);
1635
1636     element_pos = getAnimationFrame(group->num_elements_resolved, 1,
1637                                     group->choice_mode, 0,
1638                                     group->choice_pos);
1639
1640     if (group->choice_mode == ANIM_RANDOM)
1641       gfx.anim_random_frame = last_anim_random_frame;
1642
1643     group->choice_pos++;
1644
1645     element = group->element_resolved[element_pos];
1646   }
1647
1648   return element;
1649 }
1650
1651 static void InitPlayerField(int x, int y, int element, boolean init_game)
1652 {
1653   if (element == EL_SP_MURPHY)
1654   {
1655     if (init_game)
1656     {
1657       if (stored_player[0].present)
1658       {
1659         Feld[x][y] = EL_SP_MURPHY_CLONE;
1660
1661         return;
1662       }
1663       else
1664       {
1665         stored_player[0].initial_element = element;
1666         stored_player[0].use_murphy = TRUE;
1667
1668         if (!level.use_artwork_element[0])
1669           stored_player[0].artwork_element = EL_SP_MURPHY;
1670       }
1671
1672       Feld[x][y] = EL_PLAYER_1;
1673     }
1674   }
1675
1676   if (init_game)
1677   {
1678     struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1];
1679     int jx = player->jx, jy = player->jy;
1680
1681     player->present = TRUE;
1682
1683     player->block_last_field = (element == EL_SP_MURPHY ?
1684                                 level.sp_block_last_field :
1685                                 level.block_last_field);
1686
1687     /* ---------- initialize player's last field block delay --------------- */
1688
1689     /* always start with reliable default value (no adjustment needed) */
1690     player->block_delay_adjustment = 0;
1691
1692     /* special case 1: in Supaplex, Murphy blocks last field one more frame */
1693     if (player->block_last_field && element == EL_SP_MURPHY)
1694       player->block_delay_adjustment = 1;
1695
1696     /* special case 2: in game engines before 3.1.1, blocking was different */
1697     if (game.use_block_last_field_bug)
1698       player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
1699
1700     if (!options.network || player->connected)
1701     {
1702       player->active = TRUE;
1703
1704       /* remove potentially duplicate players */
1705       if (StorePlayer[jx][jy] == Feld[x][y])
1706         StorePlayer[jx][jy] = 0;
1707
1708       StorePlayer[x][y] = Feld[x][y];
1709
1710 #if DEBUG_INIT_PLAYER
1711       if (options.debug)
1712       {
1713         printf("- player element %d activated", player->element_nr);
1714         printf(" (local player is %d and currently %s)\n",
1715                local_player->element_nr,
1716                local_player->active ? "active" : "not active");
1717       }
1718     }
1719 #endif
1720
1721     Feld[x][y] = EL_EMPTY;
1722
1723     player->jx = player->last_jx = x;
1724     player->jy = player->last_jy = y;
1725   }
1726
1727   if (!init_game)
1728   {
1729     int player_nr = GET_PLAYER_NR(element);
1730     struct PlayerInfo *player = &stored_player[player_nr];
1731
1732     if (player->active && player->killed)
1733       player->reanimated = TRUE; /* if player was just killed, reanimate him */
1734   }
1735 }
1736
1737 static void InitField(int x, int y, boolean init_game)
1738 {
1739   int element = Feld[x][y];
1740
1741   switch (element)
1742   {
1743     case EL_SP_MURPHY:
1744     case EL_PLAYER_1:
1745     case EL_PLAYER_2:
1746     case EL_PLAYER_3:
1747     case EL_PLAYER_4:
1748       InitPlayerField(x, y, element, init_game);
1749       break;
1750
1751     case EL_SOKOBAN_FIELD_PLAYER:
1752       element = Feld[x][y] = EL_PLAYER_1;
1753       InitField(x, y, init_game);
1754
1755       element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
1756       InitField(x, y, init_game);
1757       break;
1758
1759     case EL_SOKOBAN_FIELD_EMPTY:
1760       local_player->sokobanfields_still_needed++;
1761       break;
1762
1763     case EL_STONEBLOCK:
1764       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
1765         Feld[x][y] = EL_ACID_POOL_TOPLEFT;
1766       else if (x > 0 && Feld[x-1][y] == EL_ACID)
1767         Feld[x][y] = EL_ACID_POOL_TOPRIGHT;
1768       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPLEFT)
1769         Feld[x][y] = EL_ACID_POOL_BOTTOMLEFT;
1770       else if (y > 0 && Feld[x][y-1] == EL_ACID)
1771         Feld[x][y] = EL_ACID_POOL_BOTTOM;
1772       else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPRIGHT)
1773         Feld[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
1774       break;
1775
1776     case EL_BUG:
1777     case EL_BUG_RIGHT:
1778     case EL_BUG_UP:
1779     case EL_BUG_LEFT:
1780     case EL_BUG_DOWN:
1781     case EL_SPACESHIP:
1782     case EL_SPACESHIP_RIGHT:
1783     case EL_SPACESHIP_UP:
1784     case EL_SPACESHIP_LEFT:
1785     case EL_SPACESHIP_DOWN:
1786     case EL_BD_BUTTERFLY:
1787     case EL_BD_BUTTERFLY_RIGHT:
1788     case EL_BD_BUTTERFLY_UP:
1789     case EL_BD_BUTTERFLY_LEFT:
1790     case EL_BD_BUTTERFLY_DOWN:
1791     case EL_BD_FIREFLY:
1792     case EL_BD_FIREFLY_RIGHT:
1793     case EL_BD_FIREFLY_UP:
1794     case EL_BD_FIREFLY_LEFT:
1795     case EL_BD_FIREFLY_DOWN:
1796     case EL_PACMAN_RIGHT:
1797     case EL_PACMAN_UP:
1798     case EL_PACMAN_LEFT:
1799     case EL_PACMAN_DOWN:
1800     case EL_YAMYAM:
1801     case EL_YAMYAM_LEFT:
1802     case EL_YAMYAM_RIGHT:
1803     case EL_YAMYAM_UP:
1804     case EL_YAMYAM_DOWN:
1805     case EL_DARK_YAMYAM:
1806     case EL_ROBOT:
1807     case EL_PACMAN:
1808     case EL_SP_SNIKSNAK:
1809     case EL_SP_ELECTRON:
1810     case EL_MOLE:
1811     case EL_MOLE_LEFT:
1812     case EL_MOLE_RIGHT:
1813     case EL_MOLE_UP:
1814     case EL_MOLE_DOWN:
1815       InitMovDir(x, y);
1816       break;
1817
1818     case EL_AMOEBA_FULL:
1819     case EL_BD_AMOEBA:
1820       InitAmoebaNr(x, y);
1821       break;
1822
1823     case EL_AMOEBA_DROP:
1824       if (y == lev_fieldy - 1)
1825       {
1826         Feld[x][y] = EL_AMOEBA_GROWING;
1827         Store[x][y] = EL_AMOEBA_WET;
1828       }
1829       break;
1830
1831     case EL_DYNAMITE_ACTIVE:
1832     case EL_SP_DISK_RED_ACTIVE:
1833     case EL_DYNABOMB_PLAYER_1_ACTIVE:
1834     case EL_DYNABOMB_PLAYER_2_ACTIVE:
1835     case EL_DYNABOMB_PLAYER_3_ACTIVE:
1836     case EL_DYNABOMB_PLAYER_4_ACTIVE:
1837       MovDelay[x][y] = 96;
1838       break;
1839
1840     case EL_EM_DYNAMITE_ACTIVE:
1841       MovDelay[x][y] = 32;
1842       break;
1843
1844     case EL_LAMP:
1845       local_player->lights_still_needed++;
1846       break;
1847
1848     case EL_PENGUIN:
1849       local_player->friends_still_needed++;
1850       break;
1851
1852     case EL_PIG:
1853     case EL_DRAGON:
1854       GfxDir[x][y] = MovDir[x][y] = 1 << RND(4);
1855       break;
1856
1857     case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
1858     case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
1859     case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
1860     case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
1861     case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
1862     case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
1863     case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
1864     case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
1865     case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
1866     case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
1867     case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
1868     case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
1869       if (init_game)
1870       {
1871         int belt_nr = getBeltNrFromBeltSwitchElement(Feld[x][y]);
1872         int belt_dir = getBeltDirFromBeltSwitchElement(Feld[x][y]);
1873         int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(Feld[x][y]);
1874
1875         if (game.belt_dir_nr[belt_nr] == 3)     /* initial value */
1876         {
1877           game.belt_dir[belt_nr] = belt_dir;
1878           game.belt_dir_nr[belt_nr] = belt_dir_nr;
1879         }
1880         else    /* more than one switch -- set it like the first switch */
1881         {
1882           Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
1883         }
1884       }
1885       break;
1886
1887     case EL_LIGHT_SWITCH_ACTIVE:
1888       if (init_game)
1889         game.light_time_left = level.time_light * FRAMES_PER_SECOND;
1890       break;
1891
1892     case EL_INVISIBLE_STEELWALL:
1893     case EL_INVISIBLE_WALL:
1894     case EL_INVISIBLE_SAND:
1895       if (game.light_time_left > 0 ||
1896           game.lenses_time_left > 0)
1897         Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
1898       break;
1899
1900     case EL_EMC_MAGIC_BALL:
1901       if (game.ball_state)
1902         Feld[x][y] = EL_EMC_MAGIC_BALL_ACTIVE;
1903       break;
1904
1905     case EL_EMC_MAGIC_BALL_SWITCH:
1906       if (game.ball_state)
1907         Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
1908       break;
1909
1910     case EL_TRIGGER_PLAYER:
1911     case EL_TRIGGER_ELEMENT:
1912     case EL_TRIGGER_CE_VALUE:
1913     case EL_TRIGGER_CE_SCORE:
1914     case EL_SELF:
1915     case EL_ANY_ELEMENT:
1916     case EL_CURRENT_CE_VALUE:
1917     case EL_CURRENT_CE_SCORE:
1918     case EL_PREV_CE_1:
1919     case EL_PREV_CE_2:
1920     case EL_PREV_CE_3:
1921     case EL_PREV_CE_4:
1922     case EL_PREV_CE_5:
1923     case EL_PREV_CE_6:
1924     case EL_PREV_CE_7:
1925     case EL_PREV_CE_8:
1926     case EL_NEXT_CE_1:
1927     case EL_NEXT_CE_2:
1928     case EL_NEXT_CE_3:
1929     case EL_NEXT_CE_4:
1930     case EL_NEXT_CE_5:
1931     case EL_NEXT_CE_6:
1932     case EL_NEXT_CE_7:
1933     case EL_NEXT_CE_8:
1934       /* reference elements should not be used on the playfield */
1935       Feld[x][y] = EL_EMPTY;
1936       break;
1937
1938     default:
1939       if (IS_CUSTOM_ELEMENT(element))
1940       {
1941         if (CAN_MOVE(element))
1942           InitMovDir(x, y);
1943
1944         if (!element_info[element].use_last_ce_value || init_game)
1945           CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
1946       }
1947       else if (IS_GROUP_ELEMENT(element))
1948       {
1949         Feld[x][y] = GetElementFromGroupElement(element);
1950
1951         InitField(x, y, init_game);
1952       }
1953
1954       break;
1955   }
1956
1957   if (!init_game)
1958     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
1959 }
1960
1961 inline static void InitField_WithBug1(int x, int y, boolean init_game)
1962 {
1963   InitField(x, y, init_game);
1964
1965   /* not needed to call InitMovDir() -- already done by InitField()! */
1966   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
1967       CAN_MOVE(Feld[x][y]))
1968     InitMovDir(x, y);
1969 }
1970
1971 inline static void InitField_WithBug2(int x, int y, boolean init_game)
1972 {
1973   int old_element = Feld[x][y];
1974
1975   InitField(x, y, init_game);
1976
1977   /* not needed to call InitMovDir() -- already done by InitField()! */
1978   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
1979       CAN_MOVE(old_element) &&
1980       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
1981     InitMovDir(x, y);
1982
1983   /* this case is in fact a combination of not less than three bugs:
1984      first, it calls InitMovDir() for elements that can move, although this is
1985      already done by InitField(); then, it checks the element that was at this
1986      field _before_ the call to InitField() (which can change it); lastly, it
1987      was not called for "mole with direction" elements, which were treated as
1988      "cannot move" due to (fixed) wrong element initialization in "src/init.c"
1989   */
1990 }
1991
1992 static int get_key_element_from_nr(int key_nr)
1993 {
1994   int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
1995                           level.game_engine_type == GAME_ENGINE_TYPE_EM ?
1996                           EL_EM_KEY_1 : EL_KEY_1);
1997
1998   return key_base_element + key_nr;
1999 }
2000
2001 static int get_next_dropped_element(struct PlayerInfo *player)
2002 {
2003   return (player->inventory_size > 0 ?
2004           player->inventory_element[player->inventory_size - 1] :
2005           player->inventory_infinite_element != EL_UNDEFINED ?
2006           player->inventory_infinite_element :
2007           player->dynabombs_left > 0 ?
2008           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
2009           EL_UNDEFINED);
2010 }
2011
2012 static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
2013 {
2014   /* pos >= 0: get element from bottom of the stack;
2015      pos <  0: get element from top of the stack */
2016
2017   if (pos < 0)
2018   {
2019     int min_inventory_size = -pos;
2020     int inventory_pos = player->inventory_size - min_inventory_size;
2021     int min_dynabombs_left = min_inventory_size - player->inventory_size;
2022
2023     return (player->inventory_size >= min_inventory_size ?
2024             player->inventory_element[inventory_pos] :
2025             player->inventory_infinite_element != EL_UNDEFINED ?
2026             player->inventory_infinite_element :
2027             player->dynabombs_left >= min_dynabombs_left ?
2028             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2029             EL_UNDEFINED);
2030   }
2031   else
2032   {
2033     int min_dynabombs_left = pos + 1;
2034     int min_inventory_size = pos + 1 - player->dynabombs_left;
2035     int inventory_pos = pos - player->dynabombs_left;
2036
2037     return (player->inventory_infinite_element != EL_UNDEFINED ?
2038             player->inventory_infinite_element :
2039             player->dynabombs_left >= min_dynabombs_left ?
2040             EL_DYNABOMB_PLAYER_1 + player->index_nr :
2041             player->inventory_size >= min_inventory_size ?
2042             player->inventory_element[inventory_pos] :
2043             EL_UNDEFINED);
2044   }
2045 }
2046
2047 static int compareGamePanelOrderInfo(const void *object1, const void *object2)
2048 {
2049   const struct GamePanelOrderInfo *gpo1 = (struct GamePanelOrderInfo *)object1;
2050   const struct GamePanelOrderInfo *gpo2 = (struct GamePanelOrderInfo *)object2;
2051   int compare_result;
2052
2053   if (gpo1->sort_priority != gpo2->sort_priority)
2054     compare_result = gpo1->sort_priority - gpo2->sort_priority;
2055   else
2056     compare_result = gpo1->nr - gpo2->nr;
2057
2058   return compare_result;
2059 }
2060
2061 int getPlayerInventorySize(int player_nr)
2062 {
2063   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2064     return level.native_em_level->ply[player_nr]->dynamite;
2065   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2066     return level.native_sp_level->game_sp->red_disk_count;
2067   else
2068     return stored_player[player_nr].inventory_size;
2069 }
2070
2071 void InitGameControlValues()
2072 {
2073   int i;
2074
2075   for (i = 0; game_panel_controls[i].nr != -1; i++)
2076   {
2077     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2078     struct GamePanelOrderInfo *gpo = &game_panel_order[i];
2079     struct TextPosInfo *pos = gpc->pos;
2080     int nr = gpc->nr;
2081     int type = gpc->type;
2082
2083     if (nr != i)
2084     {
2085       Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i);
2086       Error(ERR_EXIT, "this should not happen -- please debug");
2087     }
2088
2089     /* force update of game controls after initialization */
2090     gpc->value = gpc->last_value = -1;
2091     gpc->frame = gpc->last_frame = -1;
2092     gpc->gfx_frame = -1;
2093
2094     /* determine panel value width for later calculation of alignment */
2095     if (type == TYPE_INTEGER || type == TYPE_STRING)
2096     {
2097       pos->width = pos->size * getFontWidth(pos->font);
2098       pos->height = getFontHeight(pos->font);
2099     }
2100     else if (type == TYPE_ELEMENT)
2101     {
2102       pos->width = pos->size;
2103       pos->height = pos->size;
2104     }
2105
2106     /* fill structure for game panel draw order */
2107     gpo->nr = gpc->nr;
2108     gpo->sort_priority = pos->sort_priority;
2109   }
2110
2111   /* sort game panel controls according to sort_priority and control number */
2112   qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
2113         sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
2114 }
2115
2116 void UpdatePlayfieldElementCount()
2117 {
2118   boolean use_element_count = FALSE;
2119   int i, j, x, y;
2120
2121   /* first check if it is needed at all to calculate playfield element count */
2122   for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++)
2123     if (!PANEL_DEACTIVATED(game_panel_controls[i].pos))
2124       use_element_count = TRUE;
2125
2126   if (!use_element_count)
2127     return;
2128
2129   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2130     element_info[i].element_count = 0;
2131
2132   SCAN_PLAYFIELD(x, y)
2133   {
2134     element_info[Feld[x][y]].element_count++;
2135   }
2136
2137   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
2138     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2139       if (IS_IN_GROUP(j, i))
2140         element_info[EL_GROUP_START + i].element_count +=
2141           element_info[j].element_count;
2142 }
2143
2144 void UpdateGameControlValues()
2145 {
2146   int i, k;
2147   int time = (local_player->LevelSolved ?
2148               local_player->LevelSolved_CountingTime :
2149               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2150               level.native_em_level->lev->time :
2151               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2152               level.native_sp_level->game_sp->time_played :
2153               game.no_time_limit ? TimePlayed : TimeLeft);
2154   int score = (local_player->LevelSolved ?
2155                local_player->LevelSolved_CountingScore :
2156                level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2157                level.native_em_level->lev->score :
2158                level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2159                level.native_sp_level->game_sp->score :
2160                local_player->score);
2161   int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2162               level.native_em_level->lev->required :
2163               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2164               level.native_sp_level->game_sp->infotrons_still_needed :
2165               local_player->gems_still_needed);
2166   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
2167                      level.native_em_level->lev->required > 0 :
2168                      level.game_engine_type == GAME_ENGINE_TYPE_SP ?
2169                      level.native_sp_level->game_sp->infotrons_still_needed > 0 :
2170                      local_player->gems_still_needed > 0 ||
2171                      local_player->sokobanfields_still_needed > 0 ||
2172                      local_player->lights_still_needed > 0);
2173
2174   UpdatePlayfieldElementCount();
2175
2176   /* update game panel control values */
2177
2178   game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr;
2179   game_panel_controls[GAME_PANEL_GEMS].value = gems;
2180
2181   game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
2182   for (i = 0; i < MAX_NUM_KEYS; i++)
2183     game_panel_controls[GAME_PANEL_KEY_1 + i].value = EL_EMPTY;
2184   game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_EMPTY;
2185   game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value = 0;
2186
2187   if (game.centered_player_nr == -1)
2188   {
2189     for (i = 0; i < MAX_PLAYERS; i++)
2190     {
2191       /* only one player in Supaplex game engine */
2192       if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
2193         break;
2194
2195       for (k = 0; k < MAX_NUM_KEYS; k++)
2196       {
2197         if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2198         {
2199           if (level.native_em_level->ply[i]->keys & (1 << k))
2200             game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2201               get_key_element_from_nr(k);
2202         }
2203         else if (stored_player[i].key[k])
2204           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2205             get_key_element_from_nr(k);
2206       }
2207
2208       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2209         getPlayerInventorySize(i);
2210
2211       if (stored_player[i].num_white_keys > 0)
2212         game_panel_controls[GAME_PANEL_KEY_WHITE].value =
2213           EL_DC_KEY_WHITE;
2214
2215       game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2216         stored_player[i].num_white_keys;
2217     }
2218   }
2219   else
2220   {
2221     int player_nr = game.centered_player_nr;
2222
2223     for (k = 0; k < MAX_NUM_KEYS; k++)
2224     {
2225       if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2226       {
2227         if (level.native_em_level->ply[player_nr]->keys & (1 << k))
2228           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2229             get_key_element_from_nr(k);
2230       }
2231       else if (stored_player[player_nr].key[k])
2232         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
2233           get_key_element_from_nr(k);
2234     }
2235
2236     game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
2237       getPlayerInventorySize(player_nr);
2238
2239     if (stored_player[player_nr].num_white_keys > 0)
2240       game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
2241
2242     game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
2243       stored_player[player_nr].num_white_keys;
2244   }
2245
2246   for (i = 0; i < NUM_PANEL_INVENTORY; i++)
2247   {
2248     game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value =
2249       get_inventory_element_from_pos(local_player, i);
2250     game_panel_controls[GAME_PANEL_INVENTORY_LAST_1 + i].value =
2251       get_inventory_element_from_pos(local_player, -i - 1);
2252   }
2253
2254   game_panel_controls[GAME_PANEL_SCORE].value = score;
2255   game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
2256
2257   game_panel_controls[GAME_PANEL_TIME].value = time;
2258
2259   game_panel_controls[GAME_PANEL_TIME_HH].value = time / 3600;
2260   game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
2261   game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
2262
2263   game_panel_controls[GAME_PANEL_FRAME].value = FrameCounter;
2264
2265   game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
2266     (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
2267      EL_EMPTY);
2268   game_panel_controls[GAME_PANEL_SHIELD_NORMAL_TIME].value =
2269     local_player->shield_normal_time_left;
2270   game_panel_controls[GAME_PANEL_SHIELD_DEADLY].value =
2271     (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
2272      EL_EMPTY);
2273   game_panel_controls[GAME_PANEL_SHIELD_DEADLY_TIME].value =
2274     local_player->shield_deadly_time_left;
2275
2276   game_panel_controls[GAME_PANEL_EXIT].value =
2277     (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
2278
2279   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL].value =
2280     (game.ball_state ? EL_EMC_MAGIC_BALL_ACTIVE : EL_EMC_MAGIC_BALL);
2281   game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL_SWITCH].value =
2282     (game.ball_state ? EL_EMC_MAGIC_BALL_SWITCH_ACTIVE :
2283      EL_EMC_MAGIC_BALL_SWITCH);
2284
2285   game_panel_controls[GAME_PANEL_LIGHT_SWITCH].value =
2286     (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
2287   game_panel_controls[GAME_PANEL_LIGHT_SWITCH_TIME].value =
2288     game.light_time_left;
2289
2290   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH].value =
2291     (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
2292   game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH_TIME].value =
2293     game.timegate_time_left;
2294
2295   game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
2296     EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
2297
2298   game_panel_controls[GAME_PANEL_EMC_LENSES].value =
2299     (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
2300   game_panel_controls[GAME_PANEL_EMC_LENSES_TIME].value =
2301     game.lenses_time_left;
2302
2303   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER].value =
2304     (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
2305   game_panel_controls[GAME_PANEL_EMC_MAGNIFIER_TIME].value =
2306     game.magnify_time_left;
2307
2308   game_panel_controls[GAME_PANEL_BALLOON_SWITCH].value =
2309     (game.wind_direction == MV_LEFT  ? EL_BALLOON_SWITCH_LEFT  :
2310      game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
2311      game.wind_direction == MV_UP    ? EL_BALLOON_SWITCH_UP    :
2312      game.wind_direction == MV_DOWN  ? EL_BALLOON_SWITCH_DOWN  :
2313      EL_BALLOON_SWITCH_NONE);
2314
2315   game_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
2316     local_player->dynabomb_count;
2317   game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
2318     local_player->dynabomb_size;
2319   game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
2320     (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
2321
2322   game_panel_controls[GAME_PANEL_PENGUINS].value =
2323     local_player->friends_still_needed;
2324
2325   game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
2326     local_player->sokobanfields_still_needed;
2327   game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
2328     local_player->sokobanfields_still_needed;
2329
2330   game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
2331     (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
2332
2333   for (i = 0; i < NUM_BELTS; i++)
2334   {
2335     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1 + i].value =
2336       (game.belt_dir[i] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
2337        EL_CONVEYOR_BELT_1_MIDDLE) + i;
2338     game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH + i].value =
2339       getBeltSwitchElementFromBeltNrAndBeltDir(i, game.belt_dir[i]);
2340   }
2341
2342   game_panel_controls[GAME_PANEL_MAGIC_WALL].value =
2343     (game.magic_wall_active ? EL_MAGIC_WALL_ACTIVE : EL_MAGIC_WALL);
2344   game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
2345     game.magic_wall_time_left;
2346
2347   game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
2348     local_player->gravity;
2349
2350   for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
2351     game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
2352
2353   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2354     game_panel_controls[GAME_PANEL_ELEMENT_1 + i].value =
2355       (IS_DRAWABLE_ELEMENT(game.panel.element[i].id) ?
2356        game.panel.element[i].id : EL_UNDEFINED);
2357
2358   for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
2359     game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value =
2360       (IS_VALID_ELEMENT(game.panel.element_count[i].id) ?
2361        element_info[game.panel.element_count[i].id].element_count : 0);
2362
2363   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2364     game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value =
2365       (IS_CUSTOM_ELEMENT(game.panel.ce_score[i].id) ?
2366        element_info[game.panel.ce_score[i].id].collect_score : 0);
2367
2368   for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
2369     game_panel_controls[GAME_PANEL_CE_SCORE_1_ELEMENT + i].value =
2370       (IS_CUSTOM_ELEMENT(game.panel.ce_score_element[i].id) ?
2371        element_info[game.panel.ce_score_element[i].id].collect_score :
2372        EL_UNDEFINED);
2373
2374   game_panel_controls[GAME_PANEL_PLAYER_NAME].value = 0;
2375   game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
2376   game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
2377
2378   /* update game panel control frames */
2379
2380   for (i = 0; game_panel_controls[i].nr != -1; i++)
2381   {
2382     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2383
2384     if (gpc->type == TYPE_ELEMENT)
2385     {
2386       if (gpc->value != EL_UNDEFINED && gpc->value != EL_EMPTY)
2387       {
2388         int last_anim_random_frame = gfx.anim_random_frame;
2389         int element = gpc->value;
2390         int graphic = el2panelimg(element);
2391
2392         if (gpc->value != gpc->last_value)
2393         {
2394           gpc->gfx_frame = 0;
2395           gpc->gfx_random = INIT_GFX_RANDOM();
2396         }
2397         else
2398         {
2399           gpc->gfx_frame++;
2400
2401           if (ANIM_MODE(graphic) == ANIM_RANDOM &&
2402               IS_NEXT_FRAME(gpc->gfx_frame, graphic))
2403             gpc->gfx_random = INIT_GFX_RANDOM();
2404         }
2405
2406         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2407           gfx.anim_random_frame = gpc->gfx_random;
2408
2409         if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
2410           gpc->gfx_frame = element_info[element].collect_score;
2411
2412         gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
2413                                               gpc->gfx_frame);
2414
2415         if (ANIM_MODE(graphic) == ANIM_RANDOM)
2416           gfx.anim_random_frame = last_anim_random_frame;
2417       }
2418     }
2419   }
2420 }
2421
2422 void DisplayGameControlValues()
2423 {
2424   boolean redraw_panel = FALSE;
2425   int i;
2426
2427   for (i = 0; game_panel_controls[i].nr != -1; i++)
2428   {
2429     struct GamePanelControlInfo *gpc = &game_panel_controls[i];
2430
2431     if (PANEL_DEACTIVATED(gpc->pos))
2432       continue;
2433
2434     if (gpc->value == gpc->last_value &&
2435         gpc->frame == gpc->last_frame)
2436       continue;
2437
2438     redraw_panel = TRUE;
2439   }
2440
2441   if (!redraw_panel)
2442     return;
2443
2444   /* copy default game door content to main double buffer */
2445
2446   /* !!! CHECK AGAIN !!! */
2447   SetPanelBackground();
2448   // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
2449   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2450
2451   /* redraw game control buttons */
2452   RedrawGameButtons();
2453
2454   SetGameStatus(GAME_MODE_PSEUDO_PANEL);
2455
2456   for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
2457   {
2458     int nr = game_panel_order[i].nr;
2459     struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
2460     struct TextPosInfo *pos = gpc->pos;
2461     int type = gpc->type;
2462     int value = gpc->value;
2463     int frame = gpc->frame;
2464     int size = pos->size;
2465     int font = pos->font;
2466     boolean draw_masked = pos->draw_masked;
2467     int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_OPAQUE);
2468
2469     if (PANEL_DEACTIVATED(pos))
2470       continue;
2471
2472     gpc->last_value = value;
2473     gpc->last_frame = frame;
2474
2475     if (type == TYPE_INTEGER)
2476     {
2477       if (nr == GAME_PANEL_LEVEL_NUMBER ||
2478           nr == GAME_PANEL_TIME)
2479       {
2480         boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
2481
2482         if (use_dynamic_size)           /* use dynamic number of digits */
2483         {
2484           int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
2485           int size1 = (nr == GAME_PANEL_LEVEL_NUMBER ? 2 : 3);
2486           int size2 = size1 + 1;
2487           int font1 = pos->font;
2488           int font2 = pos->font_alt;
2489
2490           size = (value < value_change ? size1 : size2);
2491           font = (value < value_change ? font1 : font2);
2492         }
2493       }
2494
2495       /* correct text size if "digits" is zero or less */
2496       if (size <= 0)
2497         size = strlen(int2str(value, size));
2498
2499       /* dynamically correct text alignment */
2500       pos->width = size * getFontWidth(font);
2501
2502       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2503                   int2str(value, size), font, mask_mode);
2504     }
2505     else if (type == TYPE_ELEMENT)
2506     {
2507       int element, graphic;
2508       Bitmap *src_bitmap;
2509       int src_x, src_y;
2510       int width, height;
2511       int dst_x = PANEL_XPOS(pos);
2512       int dst_y = PANEL_YPOS(pos);
2513
2514       if (value != EL_UNDEFINED && value != EL_EMPTY)
2515       {
2516         element = value;
2517         graphic = el2panelimg(value);
2518
2519         // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
2520
2521         if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
2522           size = TILESIZE;
2523
2524         getSizedGraphicSource(graphic, frame, size, &src_bitmap,
2525                               &src_x, &src_y);
2526
2527         width  = graphic_info[graphic].width  * size / TILESIZE;
2528         height = graphic_info[graphic].height * size / TILESIZE;
2529
2530         if (draw_masked)
2531           BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
2532                            dst_x, dst_y);
2533         else
2534           BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
2535                      dst_x, dst_y);
2536       }
2537     }
2538     else if (type == TYPE_STRING)
2539     {
2540       boolean active = (value != 0);
2541       char *state_normal = "off";
2542       char *state_active = "on";
2543       char *state = (active ? state_active : state_normal);
2544       char *s = (nr == GAME_PANEL_GRAVITY_STATE ? state :
2545                  nr == GAME_PANEL_PLAYER_NAME   ? setup.player_name :
2546                  nr == GAME_PANEL_LEVEL_NAME    ? level.name :
2547                  nr == GAME_PANEL_LEVEL_AUTHOR  ? level.author : NULL);
2548
2549       if (nr == GAME_PANEL_GRAVITY_STATE)
2550       {
2551         int font1 = pos->font;          /* (used for normal state) */
2552         int font2 = pos->font_alt;      /* (used for active state) */
2553
2554         font = (active ? font2 : font1);
2555       }
2556
2557       if (s != NULL)
2558       {
2559         char *s_cut;
2560
2561         if (size <= 0)
2562         {
2563           /* don't truncate output if "chars" is zero or less */
2564           size = strlen(s);
2565
2566           /* dynamically correct text alignment */
2567           pos->width = size * getFontWidth(font);
2568         }
2569
2570         s_cut = getStringCopyN(s, size);
2571
2572         DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
2573                     s_cut, font, mask_mode);
2574
2575         free(s_cut);
2576       }
2577     }
2578
2579     redraw_mask |= REDRAW_DOOR_1;
2580   }
2581
2582   SetGameStatus(GAME_MODE_PLAYING);
2583 }
2584
2585 void UpdateAndDisplayGameControlValues()
2586 {
2587   if (tape.deactivate_display)
2588     return;
2589
2590   UpdateGameControlValues();
2591   DisplayGameControlValues();
2592 }
2593
2594 void UpdateGameDoorValues()
2595 {
2596   UpdateGameControlValues();
2597 }
2598
2599 void DrawGameDoorValues()
2600 {
2601   DisplayGameControlValues();
2602 }
2603
2604
2605 /*
2606   =============================================================================
2607   InitGameEngine()
2608   -----------------------------------------------------------------------------
2609   initialize game engine due to level / tape version number
2610   =============================================================================
2611 */
2612
2613 static void InitGameEngine()
2614 {
2615   int i, j, k, l, x, y;
2616
2617   /* set game engine from tape file when re-playing, else from level file */
2618   game.engine_version = (tape.playing ? tape.engine_version :
2619                          level.game_version);
2620
2621   /* set single or multi-player game mode (needed for re-playing tapes) */
2622   game.team_mode = setup.team_mode;
2623
2624   if (tape.playing)
2625   {
2626     int num_players = 0;
2627
2628     for (i = 0; i < MAX_PLAYERS; i++)
2629       if (tape.player_participates[i])
2630         num_players++;
2631
2632     /* multi-player tapes contain input data for more than one player */
2633     game.team_mode = (num_players > 1);
2634   }
2635
2636   /* ---------------------------------------------------------------------- */
2637   /* set flags for bugs and changes according to active game engine version */
2638   /* ---------------------------------------------------------------------- */
2639
2640   /*
2641     Summary of bugfix/change:
2642     Fixed handling for custom elements that change when pushed by the player.
2643
2644     Fixed/changed in version:
2645     3.1.0
2646
2647     Description:
2648     Before 3.1.0, custom elements that "change when pushing" changed directly
2649     after the player started pushing them (until then handled in "DigField()").
2650     Since 3.1.0, these custom elements are not changed until the "pushing"
2651     move of the element is finished (now handled in "ContinueMoving()").
2652
2653     Affected levels/tapes:
2654     The first condition is generally needed for all levels/tapes before version
2655     3.1.0, which might use the old behaviour before it was changed; known tapes
2656     that are affected are some tapes from the level set "Walpurgis Gardens" by
2657     Jamie Cullen.
2658     The second condition is an exception from the above case and is needed for
2659     the special case of tapes recorded with game (not engine!) version 3.1.0 or
2660     above (including some development versions of 3.1.0), but before it was
2661     known that this change would break tapes like the above and was fixed in
2662     3.1.1, so that the changed behaviour was active although the engine version
2663     while recording maybe was before 3.1.0. There is at least one tape that is
2664     affected by this exception, which is the tape for the one-level set "Bug
2665     Machine" by Juergen Bonhagen.
2666   */
2667
2668   game.use_change_when_pushing_bug =
2669     (game.engine_version < VERSION_IDENT(3,1,0,0) &&
2670      !(tape.playing &&
2671        tape.game_version >= VERSION_IDENT(3,1,0,0) &&
2672        tape.game_version <  VERSION_IDENT(3,1,1,0)));
2673
2674   /*
2675     Summary of bugfix/change:
2676     Fixed handling for blocking the field the player leaves when moving.
2677
2678     Fixed/changed in version:
2679     3.1.1
2680
2681     Description:
2682     Before 3.1.1, when "block last field when moving" was enabled, the field
2683     the player is leaving when moving was blocked for the time of the move,
2684     and was directly unblocked afterwards. This resulted in the last field
2685     being blocked for exactly one less than the number of frames of one player
2686     move. Additionally, even when blocking was disabled, the last field was
2687     blocked for exactly one frame.
2688     Since 3.1.1, due to changes in player movement handling, the last field
2689     is not blocked at all when blocking is disabled. When blocking is enabled,
2690     the last field is blocked for exactly the number of frames of one player
2691     move. Additionally, if the player is Murphy, the hero of Supaplex, the
2692     last field is blocked for exactly one more than the number of frames of
2693     one player move.
2694
2695     Affected levels/tapes:
2696     (!!! yet to be determined -- probably many !!!)
2697   */
2698
2699   game.use_block_last_field_bug =
2700     (game.engine_version < VERSION_IDENT(3,1,1,0));
2701
2702   /* ---------------------------------------------------------------------- */
2703
2704   /* set maximal allowed number of custom element changes per game frame */
2705   game.max_num_changes_per_frame = 1;
2706
2707   /* default scan direction: scan playfield from top/left to bottom/right */
2708   InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
2709
2710   /* dynamically adjust element properties according to game engine version */
2711   InitElementPropertiesEngine(game.engine_version);
2712
2713 #if 0
2714   printf("level %d: level version == %06d\n", level_nr, level.game_version);
2715   printf("          tape version == %06d [%s] [file: %06d]\n",
2716          tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
2717          tape.file_version);
2718   printf("       => game.engine_version == %06d\n", game.engine_version);
2719 #endif
2720
2721   /* ---------- initialize player's initial move delay --------------------- */
2722
2723   /* dynamically adjust player properties according to level information */
2724   for (i = 0; i < MAX_PLAYERS; i++)
2725     game.initial_move_delay_value[i] =
2726       get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
2727
2728   /* dynamically adjust player properties according to game engine version */
2729   for (i = 0; i < MAX_PLAYERS; i++)
2730     game.initial_move_delay[i] =
2731       (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
2732        game.initial_move_delay_value[i] : 0);
2733
2734   /* ---------- initialize player's initial push delay --------------------- */
2735
2736   /* dynamically adjust player properties according to game engine version */
2737   game.initial_push_delay_value =
2738     (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1);
2739
2740   /* ---------- initialize changing elements ------------------------------- */
2741
2742   /* initialize changing elements information */
2743   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2744   {
2745     struct ElementInfo *ei = &element_info[i];
2746
2747     /* this pointer might have been changed in the level editor */
2748     ei->change = &ei->change_page[0];
2749
2750     if (!IS_CUSTOM_ELEMENT(i))
2751     {
2752       ei->change->target_element = EL_EMPTY_SPACE;
2753       ei->change->delay_fixed = 0;
2754       ei->change->delay_random = 0;
2755       ei->change->delay_frames = 1;
2756     }
2757
2758     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2759     {
2760       ei->has_change_event[j] = FALSE;
2761
2762       ei->event_page_nr[j] = 0;
2763       ei->event_page[j] = &ei->change_page[0];
2764     }
2765   }
2766
2767   /* add changing elements from pre-defined list */
2768   for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++)
2769   {
2770     struct ChangingElementInfo *ch_delay = &change_delay_list[i];
2771     struct ElementInfo *ei = &element_info[ch_delay->element];
2772
2773     ei->change->target_element       = ch_delay->target_element;
2774     ei->change->delay_fixed          = ch_delay->change_delay;
2775
2776     ei->change->pre_change_function  = ch_delay->pre_change_function;
2777     ei->change->change_function      = ch_delay->change_function;
2778     ei->change->post_change_function = ch_delay->post_change_function;
2779
2780     ei->change->can_change = TRUE;
2781     ei->change->can_change_or_has_action = TRUE;
2782
2783     ei->has_change_event[CE_DELAY] = TRUE;
2784
2785     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
2786     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
2787   }
2788
2789   /* ---------- initialize internal run-time variables --------------------- */
2790
2791   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2792   {
2793     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2794
2795     for (j = 0; j < ei->num_change_pages; j++)
2796     {
2797       ei->change_page[j].can_change_or_has_action =
2798         (ei->change_page[j].can_change |
2799          ei->change_page[j].has_action);
2800     }
2801   }
2802
2803   /* add change events from custom element configuration */
2804   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2805   {
2806     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2807
2808     for (j = 0; j < ei->num_change_pages; j++)
2809     {
2810       if (!ei->change_page[j].can_change_or_has_action)
2811         continue;
2812
2813       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
2814       {
2815         /* only add event page for the first page found with this event */
2816         if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
2817         {
2818           ei->has_change_event[k] = TRUE;
2819
2820           ei->event_page_nr[k] = j;
2821           ei->event_page[k] = &ei->change_page[j];
2822         }
2823       }
2824     }
2825   }
2826
2827   /* ---------- initialize reference elements in change conditions --------- */
2828
2829   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2830   {
2831     int element = EL_CUSTOM_START + i;
2832     struct ElementInfo *ei = &element_info[element];
2833
2834     for (j = 0; j < ei->num_change_pages; j++)
2835     {
2836       int trigger_element = ei->change_page[j].initial_trigger_element;
2837
2838       if (trigger_element >= EL_PREV_CE_8 &&
2839           trigger_element <= EL_NEXT_CE_8)
2840         trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
2841
2842       ei->change_page[j].trigger_element = trigger_element;
2843     }
2844   }
2845
2846   /* ---------- initialize run-time trigger player and element ------------- */
2847
2848   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
2849   {
2850     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
2851
2852     for (j = 0; j < ei->num_change_pages; j++)
2853     {
2854       ei->change_page[j].actual_trigger_element = EL_EMPTY;
2855       ei->change_page[j].actual_trigger_player = EL_EMPTY;
2856       ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
2857       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
2858       ei->change_page[j].actual_trigger_ce_value = 0;
2859       ei->change_page[j].actual_trigger_ce_score = 0;
2860     }
2861   }
2862
2863   /* ---------- initialize trigger events ---------------------------------- */
2864
2865   /* initialize trigger events information */
2866   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2867     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
2868       trigger_events[i][j] = FALSE;
2869
2870   /* add trigger events from element change event properties */
2871   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2872   {
2873     struct ElementInfo *ei = &element_info[i];
2874
2875     for (j = 0; j < ei->num_change_pages; j++)
2876     {
2877       if (!ei->change_page[j].can_change_or_has_action)
2878         continue;
2879
2880       if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
2881       {
2882         int trigger_element = ei->change_page[j].trigger_element;
2883
2884         for (k = 0; k < NUM_CHANGE_EVENTS; k++)
2885         {
2886           if (ei->change_page[j].has_event[k])
2887           {
2888             if (IS_GROUP_ELEMENT(trigger_element))
2889             {
2890               struct ElementGroupInfo *group =
2891                 element_info[trigger_element].group;
2892
2893               for (l = 0; l < group->num_elements_resolved; l++)
2894                 trigger_events[group->element_resolved[l]][k] = TRUE;
2895             }
2896             else if (trigger_element == EL_ANY_ELEMENT)
2897               for (l = 0; l < MAX_NUM_ELEMENTS; l++)
2898                 trigger_events[l][k] = TRUE;
2899             else
2900               trigger_events[trigger_element][k] = TRUE;
2901           }
2902         }
2903       }
2904     }
2905   }
2906
2907   /* ---------- initialize push delay -------------------------------------- */
2908
2909   /* initialize push delay values to default */
2910   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2911   {
2912     if (!IS_CUSTOM_ELEMENT(i))
2913     {
2914       /* set default push delay values (corrected since version 3.0.7-1) */
2915       if (game.engine_version < VERSION_IDENT(3,0,7,1))
2916       {
2917         element_info[i].push_delay_fixed = 2;
2918         element_info[i].push_delay_random = 8;
2919       }
2920       else
2921       {
2922         element_info[i].push_delay_fixed = 8;
2923         element_info[i].push_delay_random = 8;
2924       }
2925     }
2926   }
2927
2928   /* set push delay value for certain elements from pre-defined list */
2929   for (i = 0; push_delay_list[i].element != EL_UNDEFINED; i++)
2930   {
2931     int e = push_delay_list[i].element;
2932
2933     element_info[e].push_delay_fixed  = push_delay_list[i].push_delay_fixed;
2934     element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
2935   }
2936
2937   /* set push delay value for Supaplex elements for newer engine versions */
2938   if (game.engine_version >= VERSION_IDENT(3,1,0,0))
2939   {
2940     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2941     {
2942       if (IS_SP_ELEMENT(i))
2943       {
2944         /* set SP push delay to just enough to push under a falling zonk */
2945         int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
2946
2947         element_info[i].push_delay_fixed  = delay;
2948         element_info[i].push_delay_random = 0;
2949       }
2950     }
2951   }
2952
2953   /* ---------- initialize move stepsize ----------------------------------- */
2954
2955   /* initialize move stepsize values to default */
2956   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2957     if (!IS_CUSTOM_ELEMENT(i))
2958       element_info[i].move_stepsize = MOVE_STEPSIZE_NORMAL;
2959
2960   /* set move stepsize value for certain elements from pre-defined list */
2961   for (i = 0; move_stepsize_list[i].element != EL_UNDEFINED; i++)
2962   {
2963     int e = move_stepsize_list[i].element;
2964
2965     element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
2966   }
2967
2968   /* ---------- initialize collect score ----------------------------------- */
2969
2970   /* initialize collect score values for custom elements from initial value */
2971   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2972     if (IS_CUSTOM_ELEMENT(i))
2973       element_info[i].collect_score = element_info[i].collect_score_initial;
2974
2975   /* ---------- initialize collect count ----------------------------------- */
2976
2977   /* initialize collect count values for non-custom elements */
2978   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2979     if (!IS_CUSTOM_ELEMENT(i))
2980       element_info[i].collect_count_initial = 0;
2981
2982   /* add collect count values for all elements from pre-defined list */
2983   for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
2984     element_info[collect_count_list[i].element].collect_count_initial =
2985       collect_count_list[i].count;
2986
2987   /* ---------- initialize access direction -------------------------------- */
2988
2989   /* initialize access direction values to default (access from every side) */
2990   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2991     if (!IS_CUSTOM_ELEMENT(i))
2992       element_info[i].access_direction = MV_ALL_DIRECTIONS;
2993
2994   /* set access direction value for certain elements from pre-defined list */
2995   for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
2996     element_info[access_direction_list[i].element].access_direction =
2997       access_direction_list[i].direction;
2998
2999   /* ---------- initialize explosion content ------------------------------- */
3000   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3001   {
3002     if (IS_CUSTOM_ELEMENT(i))
3003       continue;
3004
3005     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
3006     {
3007       /* (content for EL_YAMYAM set at run-time with game.yamyam_content_nr) */
3008
3009       element_info[i].content.e[x][y] =
3010         (i == EL_PLAYER_1 ? EL_EMERALD_YELLOW :
3011          i == EL_PLAYER_2 ? EL_EMERALD_RED :
3012          i == EL_PLAYER_3 ? EL_EMERALD :
3013          i == EL_PLAYER_4 ? EL_EMERALD_PURPLE :
3014          i == EL_MOLE ? EL_EMERALD_RED :
3015          i == EL_PENGUIN ? EL_EMERALD_PURPLE :
3016          i == EL_BUG ? (x == 1 && y == 1 ? EL_DIAMOND : EL_EMERALD) :
3017          i == EL_BD_BUTTERFLY ? EL_BD_DIAMOND :
3018          i == EL_SP_ELECTRON ? EL_SP_INFOTRON :
3019          i == EL_AMOEBA_TO_DIAMOND ? level.amoeba_content :
3020          i == EL_WALL_EMERALD ? EL_EMERALD :
3021          i == EL_WALL_DIAMOND ? EL_DIAMOND :
3022          i == EL_WALL_BD_DIAMOND ? EL_BD_DIAMOND :
3023          i == EL_WALL_EMERALD_YELLOW ? EL_EMERALD_YELLOW :
3024          i == EL_WALL_EMERALD_RED ? EL_EMERALD_RED :
3025          i == EL_WALL_EMERALD_PURPLE ? EL_EMERALD_PURPLE :
3026          i == EL_WALL_PEARL ? EL_PEARL :
3027          i == EL_WALL_CRYSTAL ? EL_CRYSTAL :
3028          EL_EMPTY);
3029     }
3030   }
3031
3032   /* ---------- initialize recursion detection ------------------------------ */
3033   recursion_loop_depth = 0;
3034   recursion_loop_detected = FALSE;
3035   recursion_loop_element = EL_UNDEFINED;
3036
3037   /* ---------- initialize graphics engine ---------------------------------- */
3038   game.scroll_delay_value =
3039     (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
3040      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
3041   game.scroll_delay_value =
3042     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
3043
3044   /* ---------- initialize game engine snapshots ---------------------------- */
3045   for (i = 0; i < MAX_PLAYERS; i++)
3046     game.snapshot.last_action[i] = 0;
3047   game.snapshot.changed_action = FALSE;
3048   game.snapshot.collected_item = FALSE;
3049   game.snapshot.mode =
3050     (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
3051      SNAPSHOT_MODE_EVERY_STEP :
3052      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
3053      SNAPSHOT_MODE_EVERY_MOVE :
3054      strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
3055      SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
3056   game.snapshot.save_snapshot = FALSE;
3057 }
3058
3059 int get_num_special_action(int element, int action_first, int action_last)
3060 {
3061   int num_special_action = 0;
3062   int i, j;
3063
3064   for (i = action_first; i <= action_last; i++)
3065   {
3066     boolean found = FALSE;
3067
3068     for (j = 0; j < NUM_DIRECTIONS; j++)
3069       if (el_act_dir2img(element, i, j) !=
3070           el_act_dir2img(element, ACTION_DEFAULT, j))
3071         found = TRUE;
3072
3073     if (found)
3074       num_special_action++;
3075     else
3076       break;
3077   }
3078
3079   return num_special_action;
3080 }
3081
3082
3083 /*
3084   =============================================================================
3085   InitGame()
3086   -----------------------------------------------------------------------------
3087   initialize and start new game
3088   =============================================================================
3089 */
3090
3091 void InitGame()
3092 {
3093   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
3094   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
3095   int fade_mask = REDRAW_FIELD;
3096
3097   boolean emulate_bd = TRUE;    /* unless non-BOULDERDASH elements found */
3098   boolean emulate_sb = TRUE;    /* unless non-SOKOBAN     elements found */
3099   boolean emulate_sp = TRUE;    /* unless non-SUPAPLEX    elements found */
3100   int initial_move_dir = MV_DOWN;
3101   int i, j, x, y;
3102
3103   // required here to update video display before fading (FIX THIS)
3104   DrawMaskedBorder(REDRAW_DOOR_2);
3105
3106   if (!game.restart_level)
3107     CloseDoor(DOOR_CLOSE_1);
3108
3109   SetGameStatus(GAME_MODE_PLAYING);
3110
3111   if (level_editor_test_game)
3112     FadeSkipNextFadeIn();
3113   else
3114     FadeSetEnterScreen();
3115
3116   if (CheckIfGlobalBorderHasChanged())
3117     fade_mask = REDRAW_ALL;
3118
3119   FadeSoundsAndMusic();
3120
3121   ExpireSoundLoops(TRUE);
3122
3123   FadeOut(fade_mask);
3124
3125   /* needed if different viewport properties defined for playing */
3126   ChangeViewportPropertiesIfNeeded();
3127
3128   ClearField();
3129
3130   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
3131
3132   DrawCompleteVideoDisplay();
3133
3134   InitGameEngine();
3135   InitGameControlValues();
3136
3137   /* don't play tapes over network */
3138   network_playing = (options.network && !tape.playing);
3139
3140   for (i = 0; i < MAX_PLAYERS; i++)
3141   {
3142     struct PlayerInfo *player = &stored_player[i];
3143
3144     player->index_nr = i;
3145     player->index_bit = (1 << i);
3146     player->element_nr = EL_PLAYER_1 + i;
3147
3148     player->present = FALSE;
3149     player->active = FALSE;
3150     player->mapped = FALSE;
3151
3152     player->killed = FALSE;
3153     player->reanimated = FALSE;
3154
3155     player->action = 0;
3156     player->effective_action = 0;
3157     player->programmed_action = 0;
3158
3159     player->score = 0;
3160     player->score_final = 0;
3161
3162     player->gems_still_needed = level.gems_needed;
3163     player->sokobanfields_still_needed = 0;
3164     player->lights_still_needed = 0;
3165     player->friends_still_needed = 0;
3166
3167     for (j = 0; j < MAX_NUM_KEYS; j++)
3168       player->key[j] = FALSE;
3169
3170     player->num_white_keys = 0;
3171
3172     player->dynabomb_count = 0;
3173     player->dynabomb_size = 1;
3174     player->dynabombs_left = 0;
3175     player->dynabomb_xl = FALSE;
3176
3177     player->MovDir = initial_move_dir;
3178     player->MovPos = 0;
3179     player->GfxPos = 0;
3180     player->GfxDir = initial_move_dir;
3181     player->GfxAction = ACTION_DEFAULT;
3182     player->Frame = 0;
3183     player->StepFrame = 0;
3184
3185     player->initial_element = player->element_nr;
3186     player->artwork_element =
3187       (level.use_artwork_element[i] ? level.artwork_element[i] :
3188        player->element_nr);
3189     player->use_murphy = FALSE;
3190
3191     player->block_last_field = FALSE;   /* initialized in InitPlayerField() */
3192     player->block_delay_adjustment = 0; /* initialized in InitPlayerField() */
3193
3194     player->gravity = level.initial_player_gravity[i];
3195
3196     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
3197
3198     player->actual_frame_counter = 0;
3199
3200     player->step_counter = 0;
3201
3202     player->last_move_dir = initial_move_dir;
3203
3204     player->is_active = FALSE;
3205
3206     player->is_waiting = FALSE;
3207     player->is_moving = FALSE;
3208     player->is_auto_moving = FALSE;
3209     player->is_digging = FALSE;
3210     player->is_snapping = FALSE;
3211     player->is_collecting = FALSE;
3212     player->is_pushing = FALSE;
3213     player->is_switching = FALSE;
3214     player->is_dropping = FALSE;
3215     player->is_dropping_pressed = FALSE;
3216
3217     player->is_bored = FALSE;
3218     player->is_sleeping = FALSE;
3219
3220     player->was_waiting = TRUE;
3221     player->was_moving = FALSE;
3222     player->was_snapping = FALSE;
3223     player->was_dropping = FALSE;
3224
3225     player->frame_counter_bored = -1;
3226     player->frame_counter_sleeping = -1;
3227
3228     player->anim_delay_counter = 0;
3229     player->post_delay_counter = 0;
3230
3231     player->dir_waiting = initial_move_dir;
3232     player->action_waiting = ACTION_DEFAULT;
3233     player->last_action_waiting = ACTION_DEFAULT;
3234     player->special_action_bored = ACTION_DEFAULT;
3235     player->special_action_sleeping = ACTION_DEFAULT;
3236
3237     player->switch_x = -1;
3238     player->switch_y = -1;
3239
3240     player->drop_x = -1;
3241     player->drop_y = -1;
3242
3243     player->show_envelope = 0;
3244
3245     SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
3246
3247     player->push_delay       = -1;      /* initialized when pushing starts */
3248     player->push_delay_value = game.initial_push_delay_value;
3249
3250     player->drop_delay = 0;
3251     player->drop_pressed_delay = 0;
3252
3253     player->last_jx = -1;
3254     player->last_jy = -1;
3255     player->jx = -1;
3256     player->jy = -1;
3257
3258     player->shield_normal_time_left = 0;
3259     player->shield_deadly_time_left = 0;
3260
3261     player->inventory_infinite_element = EL_UNDEFINED;
3262     player->inventory_size = 0;
3263
3264     if (level.use_initial_inventory[i])
3265     {
3266       for (j = 0; j < level.initial_inventory_size[i]; j++)
3267       {
3268         int element = level.initial_inventory_content[i][j];
3269         int collect_count = element_info[element].collect_count_initial;
3270         int k;
3271
3272         if (!IS_CUSTOM_ELEMENT(element))
3273           collect_count = 1;
3274
3275         if (collect_count == 0)
3276           player->inventory_infinite_element = element;
3277         else
3278           for (k = 0; k < collect_count; k++)
3279             if (player->inventory_size < MAX_INVENTORY_SIZE)
3280               player->inventory_element[player->inventory_size++] = element;
3281       }
3282     }
3283
3284     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
3285     SnapField(player, 0, 0);
3286
3287     player->LevelSolved = FALSE;
3288     player->GameOver = FALSE;
3289
3290     player->LevelSolved_GameWon = FALSE;
3291     player->LevelSolved_GameEnd = FALSE;
3292     player->LevelSolved_PanelOff = FALSE;
3293     player->LevelSolved_SaveTape = FALSE;
3294     player->LevelSolved_SaveScore = FALSE;
3295     player->LevelSolved_CountingTime = 0;
3296     player->LevelSolved_CountingScore = 0;
3297
3298     map_player_action[i] = i;
3299   }
3300
3301   network_player_action_received = FALSE;
3302
3303 #if defined(NETWORK_AVALIABLE)
3304   /* initial null action */
3305   if (network_playing)
3306     SendToServer_MovePlayer(MV_NONE);
3307 #endif
3308
3309   ZX = ZY = -1;
3310   ExitX = ExitY = -1;
3311
3312   FrameCounter = 0;
3313   TimeFrames = 0;
3314   TimePlayed = 0;
3315   TimeLeft = level.time;
3316   TapeTime = 0;
3317
3318   ScreenMovDir = MV_NONE;
3319   ScreenMovPos = 0;
3320   ScreenGfxPos = 0;
3321
3322   ScrollStepSize = 0;   /* will be correctly initialized by ScrollScreen() */
3323
3324   AllPlayersGone = FALSE;
3325
3326   game.no_time_limit = (level.time == 0);
3327
3328   game.yamyam_content_nr = 0;
3329   game.robot_wheel_active = FALSE;
3330   game.magic_wall_active = FALSE;
3331   game.magic_wall_time_left = 0;
3332   game.light_time_left = 0;
3333   game.timegate_time_left = 0;
3334   game.switchgate_pos = 0;
3335   game.wind_direction = level.wind_direction_initial;
3336
3337   game.lenses_time_left = 0;
3338   game.magnify_time_left = 0;
3339
3340   game.ball_state = level.ball_state_initial;
3341   game.ball_content_nr = 0;
3342
3343   game.envelope_active = FALSE;
3344
3345   /* set focus to local player for network games, else to all players */
3346   game.centered_player_nr = (network_playing ? local_player->index_nr : -1);
3347   game.centered_player_nr_next = game.centered_player_nr;
3348   game.set_centered_player = FALSE;
3349
3350   if (network_playing && tape.recording)
3351   {
3352     /* store client dependent player focus when recording network games */
3353     tape.centered_player_nr_next = game.centered_player_nr_next;
3354     tape.set_centered_player = TRUE;
3355   }
3356
3357   for (i = 0; i < NUM_BELTS; i++)
3358   {
3359     game.belt_dir[i] = MV_NONE;
3360     game.belt_dir_nr[i] = 3;            /* not moving, next moving left */
3361   }
3362
3363   for (i = 0; i < MAX_NUM_AMOEBA; i++)
3364     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
3365
3366 #if DEBUG_INIT_PLAYER
3367   if (options.debug)
3368   {
3369     printf("Player status at level initialization:\n");
3370   }
3371 #endif
3372
3373   SCAN_PLAYFIELD(x, y)
3374   {
3375     Feld[x][y] = level.field[x][y];
3376     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
3377     ChangeDelay[x][y] = 0;
3378     ChangePage[x][y] = -1;
3379     CustomValue[x][y] = 0;              /* initialized in InitField() */
3380     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
3381     AmoebaNr[x][y] = 0;
3382     WasJustMoving[x][y] = 0;
3383     WasJustFalling[x][y] = 0;
3384     CheckCollision[x][y] = 0;
3385     CheckImpact[x][y] = 0;
3386     Stop[x][y] = FALSE;
3387     Pushed[x][y] = FALSE;
3388
3389     ChangeCount[x][y] = 0;
3390     ChangeEvent[x][y] = -1;
3391
3392     ExplodePhase[x][y] = 0;
3393     ExplodeDelay[x][y] = 0;
3394     ExplodeField[x][y] = EX_TYPE_NONE;
3395
3396     RunnerVisit[x][y] = 0;
3397     PlayerVisit[x][y] = 0;
3398
3399     GfxFrame[x][y] = 0;
3400     GfxRandom[x][y] = INIT_GFX_RANDOM();
3401     GfxElement[x][y] = EL_UNDEFINED;
3402     GfxAction[x][y] = ACTION_DEFAULT;
3403     GfxDir[x][y] = MV_NONE;
3404     GfxRedraw[x][y] = GFX_REDRAW_NONE;
3405   }
3406
3407   SCAN_PLAYFIELD(x, y)
3408   {
3409     if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
3410       emulate_bd = FALSE;
3411     if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
3412       emulate_sb = FALSE;
3413     if (emulate_sp && !IS_SP_ELEMENT(Feld[x][y]))
3414       emulate_sp = FALSE;
3415
3416     InitField(x, y, TRUE);
3417
3418     ResetGfxAnimation(x, y);
3419   }
3420
3421   InitBeltMovement();
3422
3423   for (i = 0; i < MAX_PLAYERS; i++)
3424   {
3425     struct PlayerInfo *player = &stored_player[i];
3426
3427     /* set number of special actions for bored and sleeping animation */
3428     player->num_special_action_bored =
3429       get_num_special_action(player->artwork_element,
3430                              ACTION_BORING_1, ACTION_BORING_LAST);
3431     player->num_special_action_sleeping =
3432       get_num_special_action(player->artwork_element,
3433                              ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
3434   }
3435
3436   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
3437                     emulate_sb ? EMU_SOKOBAN :
3438                     emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
3439
3440   /* initialize type of slippery elements */
3441   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3442   {
3443     if (!IS_CUSTOM_ELEMENT(i))
3444     {
3445       /* default: elements slip down either to the left or right randomly */
3446       element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
3447
3448       /* SP style elements prefer to slip down on the left side */
3449       if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
3450         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3451
3452       /* BD style elements prefer to slip down on the left side */
3453       if (game.emulation == EMU_BOULDERDASH)
3454         element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
3455     }
3456   }
3457
3458   /* initialize explosion and ignition delay */
3459   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3460   {
3461     if (!IS_CUSTOM_ELEMENT(i))
3462     {
3463       int num_phase = 8;
3464       int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
3465                     game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
3466                    game.emulation == EMU_SUPAPLEX ? 3 : 2);
3467       int last_phase = (num_phase + 1) * delay;
3468       int half_phase = (num_phase / 2) * delay;
3469
3470       element_info[i].explosion_delay = last_phase - 1;
3471       element_info[i].ignition_delay = half_phase;
3472
3473       if (i == EL_BLACK_ORB)
3474         element_info[i].ignition_delay = 1;
3475     }
3476   }
3477
3478   /* correct non-moving belts to start moving left */
3479   for (i = 0; i < NUM_BELTS; i++)
3480     if (game.belt_dir[i] == MV_NONE)
3481       game.belt_dir_nr[i] = 3;          /* not moving, next moving left */
3482
3483 #if USE_NEW_PLAYER_ASSIGNMENTS
3484   /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */
3485   /* choose default local player */
3486   local_player = &stored_player[0];
3487
3488   for (i = 0; i < MAX_PLAYERS; i++)
3489     stored_player[i].connected = FALSE;
3490
3491   local_player->connected = TRUE;
3492   /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */
3493
3494   if (tape.playing)
3495   {
3496     for (i = 0; i < MAX_PLAYERS; i++)
3497       stored_player[i].connected = tape.player_participates[i];
3498   }
3499   else if (game.team_mode && !options.network)
3500   {
3501     /* try to guess locally connected team mode players (needed for correct
3502        assignment of player figures from level to locally playing players) */
3503
3504     for (i = 0; i < MAX_PLAYERS; i++)
3505       if (setup.input[i].use_joystick ||
3506           setup.input[i].key.left != KSYM_UNDEFINED)
3507         stored_player[i].connected = TRUE;
3508   }
3509
3510 #if DEBUG_INIT_PLAYER
3511   if (options.debug)
3512   {
3513     printf("Player status after level initialization:\n");
3514
3515     for (i = 0; i < MAX_PLAYERS; i++)
3516     {
3517       struct PlayerInfo *player = &stored_player[i];
3518
3519       printf("- player %d: present == %d, connected == %d, active == %d",
3520              i + 1,
3521              player->present,
3522              player->connected,
3523              player->active);
3524
3525       if (local_player == player)
3526         printf(" (local player)");
3527
3528       printf("\n");
3529     }
3530   }
3531 #endif
3532
3533 #if DEBUG_INIT_PLAYER
3534   if (options.debug)
3535     printf("Reassigning players ...\n");
3536 #endif
3537
3538   /* check if any connected player was not found in playfield */
3539   for (i = 0; i < MAX_PLAYERS; i++)
3540   {
3541     struct PlayerInfo *player = &stored_player[i];
3542
3543     if (player->connected && !player->present)
3544     {
3545       struct PlayerInfo *field_player = NULL;
3546
3547 #if DEBUG_INIT_PLAYER
3548       if (options.debug)
3549         printf("- looking for field player for player %d ...\n", i + 1);
3550 #endif
3551
3552       /* assign first free player found that is present in the playfield */
3553
3554       /* first try: look for unmapped playfield player that is not connected */
3555       for (j = 0; j < MAX_PLAYERS; j++)
3556         if (field_player == NULL &&
3557             stored_player[j].present &&
3558             !stored_player[j].mapped &&
3559             !stored_player[j].connected)
3560           field_player = &stored_player[j];
3561
3562       /* second try: look for *any* unmapped playfield player */
3563       for (j = 0; j < MAX_PLAYERS; j++)
3564         if (field_player == NULL &&
3565             stored_player[j].present &&
3566             !stored_player[j].mapped)
3567           field_player = &stored_player[j];
3568
3569       if (field_player != NULL)
3570       {
3571         int jx = field_player->jx, jy = field_player->jy;
3572
3573 #if DEBUG_INIT_PLAYER
3574         if (options.debug)
3575           printf("- found player %d\n", field_player->index_nr + 1);
3576 #endif
3577
3578         player->present = FALSE;
3579         player->active = FALSE;
3580
3581         field_player->present = TRUE;
3582         field_player->active = TRUE;
3583
3584         /*
3585         player->initial_element = field_player->initial_element;
3586         player->artwork_element = field_player->artwork_element;
3587
3588         player->block_last_field       = field_player->block_last_field;
3589         player->block_delay_adjustment = field_player->block_delay_adjustment;
3590         */
3591
3592         StorePlayer[jx][jy] = field_player->element_nr;
3593
3594         field_player->jx = field_player->last_jx = jx;
3595         field_player->jy = field_player->last_jy = jy;
3596
3597         if (local_player == player)
3598           local_player = field_player;
3599
3600         map_player_action[field_player->index_nr] = i;
3601
3602         field_player->mapped = TRUE;
3603
3604 #if DEBUG_INIT_PLAYER
3605         if (options.debug)
3606           printf("- map_player_action[%d] == %d\n",
3607                  field_player->index_nr + 1, i + 1);
3608 #endif
3609       }
3610     }
3611
3612     if (player->connected && player->present)
3613       player->mapped = TRUE;
3614   }
3615
3616 #if DEBUG_INIT_PLAYER
3617   if (options.debug)
3618   {
3619     printf("Player status after player assignment (first stage):\n");
3620
3621     for (i = 0; i < MAX_PLAYERS; i++)
3622     {
3623       struct PlayerInfo *player = &stored_player[i];
3624
3625       printf("- player %d: present == %d, connected == %d, active == %d",
3626              i + 1,
3627              player->present,
3628              player->connected,
3629              player->active);
3630
3631       if (local_player == player)
3632         printf(" (local player)");
3633
3634       printf("\n");
3635     }
3636   }
3637 #endif
3638
3639 #else
3640
3641   /* check if any connected player was not found in playfield */
3642   for (i = 0; i < MAX_PLAYERS; i++)
3643   {
3644     struct PlayerInfo *player = &stored_player[i];
3645
3646     if (player->connected && !player->present)
3647     {
3648       for (j = 0; j < MAX_PLAYERS; j++)
3649       {
3650         struct PlayerInfo *field_player = &stored_player[j];
3651         int jx = field_player->jx, jy = field_player->jy;
3652
3653         /* assign first free player found that is present in the playfield */
3654         if (field_player->present && !field_player->connected)
3655         {
3656           player->present = TRUE;
3657           player->active = TRUE;
3658
3659           field_player->present = FALSE;
3660           field_player->active = FALSE;
3661
3662           player->initial_element = field_player->initial_element;
3663           player->artwork_element = field_player->artwork_element;
3664
3665           player->block_last_field       = field_player->block_last_field;
3666           player->block_delay_adjustment = field_player->block_delay_adjustment;
3667
3668           StorePlayer[jx][jy] = player->element_nr;
3669
3670           player->jx = player->last_jx = jx;
3671           player->jy = player->last_jy = jy;
3672
3673           break;
3674         }
3675       }
3676     }
3677   }
3678 #endif
3679
3680 #if 0
3681   printf("::: local_player->present == %d\n", local_player->present);
3682 #endif
3683
3684   if (tape.playing)
3685   {
3686     /* when playing a tape, eliminate all players who do not participate */
3687
3688 #if USE_NEW_PLAYER_ASSIGNMENTS
3689
3690     if (!game.team_mode)
3691     {
3692       for (i = 0; i < MAX_PLAYERS; i++)
3693       {
3694         if (stored_player[i].active &&
3695             !tape.player_participates[map_player_action[i]])
3696         {
3697           struct PlayerInfo *player = &stored_player[i];
3698           int jx = player->jx, jy = player->jy;
3699
3700 #if DEBUG_INIT_PLAYER
3701           if (options.debug)
3702             printf("Removing player %d at (%d, %d)\n", i + 1, jx, jy);
3703 #endif
3704
3705           player->active = FALSE;
3706           StorePlayer[jx][jy] = 0;
3707           Feld[jx][jy] = EL_EMPTY;
3708         }
3709       }
3710     }
3711
3712 #else
3713
3714     for (i = 0; i < MAX_PLAYERS; i++)
3715     {
3716       if (stored_player[i].active &&
3717           !tape.player_participates[i])
3718       {
3719         struct PlayerInfo *player = &stored_player[i];
3720         int jx = player->jx, jy = player->jy;
3721
3722         player->active = FALSE;
3723         StorePlayer[jx][jy] = 0;
3724         Feld[jx][jy] = EL_EMPTY;
3725       }
3726     }
3727 #endif
3728   }
3729   else if (!options.network && !game.team_mode)         /* && !tape.playing */
3730   {
3731     /* when in single player mode, eliminate all but the first active player */
3732
3733     for (i = 0; i < MAX_PLAYERS; i++)
3734     {
3735       if (stored_player[i].active)
3736       {
3737         for (j = i + 1; j < MAX_PLAYERS; j++)
3738         {
3739           if (stored_player[j].active)
3740           {
3741             struct PlayerInfo *player = &stored_player[j];
3742             int jx = player->jx, jy = player->jy;
3743
3744             player->active = FALSE;
3745             player->present = FALSE;
3746
3747             StorePlayer[jx][jy] = 0;
3748             Feld[jx][jy] = EL_EMPTY;
3749           }
3750         }
3751       }
3752     }
3753   }
3754
3755   /* when recording the game, store which players take part in the game */
3756   if (tape.recording)
3757   {
3758 #if USE_NEW_PLAYER_ASSIGNMENTS
3759     for (i = 0; i < MAX_PLAYERS; i++)
3760       if (stored_player[i].connected)
3761         tape.player_participates[i] = TRUE;
3762 #else
3763     for (i = 0; i < MAX_PLAYERS; i++)
3764       if (stored_player[i].active)
3765         tape.player_participates[i] = TRUE;
3766 #endif
3767   }
3768
3769 #if DEBUG_INIT_PLAYER
3770   if (options.debug)
3771   {
3772     printf("Player status after player assignment (final stage):\n");
3773
3774     for (i = 0; i < MAX_PLAYERS; i++)
3775     {
3776       struct PlayerInfo *player = &stored_player[i];
3777
3778       printf("- player %d: present == %d, connected == %d, active == %d",
3779              i + 1,
3780              player->present,
3781              player->connected,
3782              player->active);
3783
3784       if (local_player == player)
3785         printf(" (local player)");
3786
3787       printf("\n");
3788     }
3789   }
3790 #endif
3791
3792   if (BorderElement == EL_EMPTY)
3793   {
3794     SBX_Left = 0;
3795     SBX_Right = lev_fieldx - SCR_FIELDX;
3796     SBY_Upper = 0;
3797     SBY_Lower = lev_fieldy - SCR_FIELDY;
3798   }
3799   else
3800   {
3801     SBX_Left = -1;
3802     SBX_Right = lev_fieldx - SCR_FIELDX + 1;
3803     SBY_Upper = -1;
3804     SBY_Lower = lev_fieldy - SCR_FIELDY + 1;
3805   }
3806
3807   if (full_lev_fieldx <= SCR_FIELDX)
3808     SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2;
3809   if (full_lev_fieldy <= SCR_FIELDY)
3810     SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2;
3811
3812   if (EVEN(SCR_FIELDX) && full_lev_fieldx > SCR_FIELDX)
3813     SBX_Left--;
3814   if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
3815     SBY_Upper--;
3816
3817   /* if local player not found, look for custom element that might create
3818      the player (make some assumptions about the right custom element) */
3819   if (!local_player->present)
3820   {
3821     int start_x = 0, start_y = 0;
3822     int found_rating = 0;
3823     int found_element = EL_UNDEFINED;
3824     int player_nr = local_player->index_nr;
3825
3826     SCAN_PLAYFIELD(x, y)
3827     {
3828       int element = Feld[x][y];
3829       int content;
3830       int xx, yy;
3831       boolean is_player;
3832
3833       if (level.use_start_element[player_nr] &&
3834           level.start_element[player_nr] == element &&
3835           found_rating < 4)
3836       {
3837         start_x = x;
3838         start_y = y;
3839
3840         found_rating = 4;
3841         found_element = element;
3842       }
3843
3844       if (!IS_CUSTOM_ELEMENT(element))
3845         continue;
3846
3847       if (CAN_CHANGE(element))
3848       {
3849         for (i = 0; i < element_info[element].num_change_pages; i++)
3850         {
3851           /* check for player created from custom element as single target */
3852           content = element_info[element].change_page[i].target_element;
3853           is_player = ELEM_IS_PLAYER(content);
3854
3855           if (is_player && (found_rating < 3 ||
3856                             (found_rating == 3 && element < found_element)))
3857           {
3858             start_x = x;
3859             start_y = y;
3860
3861             found_rating = 3;
3862             found_element = element;
3863           }
3864         }
3865       }
3866
3867       for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
3868       {
3869         /* check for player created from custom element as explosion content */
3870         content = element_info[element].content.e[xx][yy];
3871         is_player = ELEM_IS_PLAYER(content);
3872
3873         if (is_player && (found_rating < 2 ||
3874                           (found_rating == 2 && element < found_element)))
3875         {
3876           start_x = x + xx - 1;
3877           start_y = y + yy - 1;
3878
3879           found_rating = 2;
3880           found_element = element;
3881         }
3882
3883         if (!CAN_CHANGE(element))
3884           continue;
3885
3886         for (i = 0; i < element_info[element].num_change_pages; i++)
3887         {
3888           /* check for player created from custom element as extended target */
3889           content =
3890             element_info[element].change_page[i].target_content.e[xx][yy];
3891
3892           is_player = ELEM_IS_PLAYER(content);
3893
3894           if (is_player && (found_rating < 1 ||
3895                             (found_rating == 1 && element < found_element)))
3896           {
3897             start_x = x + xx - 1;
3898             start_y = y + yy - 1;
3899
3900             found_rating = 1;
3901             found_element = element;
3902           }
3903         }
3904       }
3905     }
3906
3907     scroll_x = SCROLL_POSITION_X(start_x);
3908     scroll_y = SCROLL_POSITION_Y(start_y);
3909   }
3910   else
3911   {
3912     scroll_x = SCROLL_POSITION_X(local_player->jx);
3913     scroll_y = SCROLL_POSITION_Y(local_player->jy);
3914   }
3915
3916   /* !!! FIX THIS (START) !!! */
3917   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3918   {
3919     InitGameEngine_EM();
3920   }
3921   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3922   {
3923     InitGameEngine_SP();
3924   }
3925   else
3926   {
3927     DrawLevel(REDRAW_FIELD);
3928     DrawAllPlayers();
3929
3930     /* after drawing the level, correct some elements */
3931     if (game.timegate_time_left == 0)
3932       CloseAllOpenTimegates();
3933   }
3934
3935   /* blit playfield from scroll buffer to normal back buffer for fading in */
3936   BlitScreenToBitmap(backbuffer);
3937   /* !!! FIX THIS (END) !!! */
3938
3939   DrawMaskedBorder(fade_mask);
3940
3941   FadeIn(fade_mask);
3942
3943 #if 1
3944   // full screen redraw is required at this point in the following cases:
3945   // - special editor door undrawn when game was started from level editor
3946   // - drawing area (playfield) was changed and has to be removed completely
3947   redraw_mask = REDRAW_ALL;
3948   BackToFront();
3949 #endif
3950
3951   if (!game.restart_level)
3952   {
3953     /* copy default game door content to main double buffer */
3954
3955     /* !!! CHECK AGAIN !!! */
3956     SetPanelBackground();
3957     // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
3958     DrawBackground(DX, DY, DXSIZE, DYSIZE);
3959   }
3960
3961   SetPanelBackground();
3962   SetDrawBackgroundMask(REDRAW_DOOR_1);
3963
3964   UpdateAndDisplayGameControlValues();
3965
3966   if (!game.restart_level)
3967   {
3968     UnmapGameButtons();
3969     UnmapTapeButtons();
3970
3971     FreeGameButtons();
3972     CreateGameButtons();
3973
3974     game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music;
3975     game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops;
3976     game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple;
3977
3978     MapGameButtons();
3979     MapTapeButtons();
3980
3981     /* copy actual game door content to door double buffer for OpenDoor() */
3982     BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
3983
3984     OpenDoor(DOOR_OPEN_ALL);
3985
3986     PlaySound(SND_GAME_STARTING);
3987
3988     if (setup.sound_music)
3989       PlayLevelMusic();
3990
3991     KeyboardAutoRepeatOffUnlessAutoplay();
3992
3993 #if DEBUG_INIT_PLAYER
3994     if (options.debug)
3995     {
3996       printf("Player status (final):\n");
3997
3998       for (i = 0; i < MAX_PLAYERS; i++)
3999       {
4000         struct PlayerInfo *player = &stored_player[i];
4001
4002         printf("- player %d: present == %d, connected == %d, active == %d",
4003                i + 1,
4004                player->present,
4005                player->connected,
4006                player->active);
4007
4008         if (local_player == player)
4009           printf(" (local player)");
4010
4011         printf("\n");
4012       }
4013     }
4014 #endif
4015   }
4016
4017   UnmapAllGadgets();
4018
4019   MapGameButtons();
4020   MapTapeButtons();
4021
4022   if (!game.restart_level && !tape.playing)
4023   {
4024     LevelStats_incPlayed(level_nr);
4025
4026     SaveLevelSetup_SeriesInfo();
4027   }
4028
4029   game.restart_level = FALSE;
4030
4031   SaveEngineSnapshotToListInitial();
4032 }
4033
4034 void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y,
4035                         int actual_player_x, int actual_player_y)
4036 {
4037   /* this is used for non-R'n'D game engines to update certain engine values */
4038
4039   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4040   {
4041     actual_player_x = correctLevelPosX_EM(actual_player_x);
4042     actual_player_y = correctLevelPosY_EM(actual_player_y);
4043   }
4044
4045   /* needed to determine if sounds are played within the visible screen area */
4046   scroll_x = actual_scroll_x;
4047   scroll_y = actual_scroll_y;
4048
4049   /* needed to get player position for "follow finger" playing input method */
4050   local_player->jx = actual_player_x;
4051   local_player->jy = actual_player_y;
4052 }
4053
4054 void InitMovDir(int x, int y)
4055 {
4056   int i, element = Feld[x][y];
4057   static int xy[4][2] =
4058   {
4059     {  0, +1 },
4060     { +1,  0 },
4061     {  0, -1 },
4062     { -1,  0 }
4063   };
4064   static int direction[3][4] =
4065   {
4066     { MV_RIGHT, MV_UP,   MV_LEFT,  MV_DOWN },
4067     { MV_LEFT,  MV_DOWN, MV_RIGHT, MV_UP },
4068     { MV_LEFT,  MV_RIGHT, MV_UP, MV_DOWN }
4069   };
4070
4071   switch (element)
4072   {
4073     case EL_BUG_RIGHT:
4074     case EL_BUG_UP:
4075     case EL_BUG_LEFT:
4076     case EL_BUG_DOWN:
4077       Feld[x][y] = EL_BUG;
4078       MovDir[x][y] = direction[0][element - EL_BUG_RIGHT];
4079       break;
4080
4081     case EL_SPACESHIP_RIGHT:
4082     case EL_SPACESHIP_UP:
4083     case EL_SPACESHIP_LEFT:
4084     case EL_SPACESHIP_DOWN:
4085       Feld[x][y] = EL_SPACESHIP;
4086       MovDir[x][y] = direction[0][element - EL_SPACESHIP_RIGHT];
4087       break;
4088
4089     case EL_BD_BUTTERFLY_RIGHT:
4090     case EL_BD_BUTTERFLY_UP:
4091     case EL_BD_BUTTERFLY_LEFT:
4092     case EL_BD_BUTTERFLY_DOWN:
4093       Feld[x][y] = EL_BD_BUTTERFLY;
4094       MovDir[x][y] = direction[0][element - EL_BD_BUTTERFLY_RIGHT];
4095       break;
4096
4097     case EL_BD_FIREFLY_RIGHT:
4098     case EL_BD_FIREFLY_UP:
4099     case EL_BD_FIREFLY_LEFT:
4100     case EL_BD_FIREFLY_DOWN:
4101       Feld[x][y] = EL_BD_FIREFLY;
4102       MovDir[x][y] = direction[0][element - EL_BD_FIREFLY_RIGHT];
4103       break;
4104
4105     case EL_PACMAN_RIGHT:
4106     case EL_PACMAN_UP:
4107     case EL_PACMAN_LEFT:
4108     case EL_PACMAN_DOWN:
4109       Feld[x][y] = EL_PACMAN;
4110       MovDir[x][y] = direction[0][element - EL_PACMAN_RIGHT];
4111       break;
4112
4113     case EL_YAMYAM_LEFT:
4114     case EL_YAMYAM_RIGHT:
4115     case EL_YAMYAM_UP:
4116     case EL_YAMYAM_DOWN:
4117       Feld[x][y] = EL_YAMYAM;
4118       MovDir[x][y] = direction[2][element - EL_YAMYAM_LEFT];
4119       break;
4120
4121     case EL_SP_SNIKSNAK:
4122       MovDir[x][y] = MV_UP;
4123       break;
4124
4125     case EL_SP_ELECTRON:
4126       MovDir[x][y] = MV_LEFT;
4127       break;
4128
4129     case EL_MOLE_LEFT:
4130     case EL_MOLE_RIGHT:
4131     case EL_MOLE_UP:
4132     case EL_MOLE_DOWN:
4133       Feld[x][y] = EL_MOLE;
4134       MovDir[x][y] = direction[2][element - EL_MOLE_LEFT];
4135       break;
4136
4137     default:
4138       if (IS_CUSTOM_ELEMENT(element))
4139       {
4140         struct ElementInfo *ei = &element_info[element];
4141         int move_direction_initial = ei->move_direction_initial;
4142         int move_pattern = ei->move_pattern;
4143
4144         if (move_direction_initial == MV_START_PREVIOUS)
4145         {
4146           if (MovDir[x][y] != MV_NONE)
4147             return;
4148
4149           move_direction_initial = MV_START_AUTOMATIC;
4150         }
4151
4152         if (move_direction_initial == MV_START_RANDOM)
4153           MovDir[x][y] = 1 << RND(4);
4154         else if (move_direction_initial & MV_ANY_DIRECTION)
4155           MovDir[x][y] = move_direction_initial;
4156         else if (move_pattern == MV_ALL_DIRECTIONS ||
4157                  move_pattern == MV_TURNING_LEFT ||
4158                  move_pattern == MV_TURNING_RIGHT ||
4159                  move_pattern == MV_TURNING_LEFT_RIGHT ||
4160                  move_pattern == MV_TURNING_RIGHT_LEFT ||
4161                  move_pattern == MV_TURNING_RANDOM)
4162           MovDir[x][y] = 1 << RND(4);
4163         else if (move_pattern == MV_HORIZONTAL)
4164           MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
4165         else if (move_pattern == MV_VERTICAL)
4166           MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
4167         else if (move_pattern & MV_ANY_DIRECTION)
4168           MovDir[x][y] = element_info[element].move_pattern;
4169         else if (move_pattern == MV_ALONG_LEFT_SIDE ||
4170                  move_pattern == MV_ALONG_RIGHT_SIDE)
4171         {
4172           /* use random direction as default start direction */
4173           if (game.engine_version >= VERSION_IDENT(3,1,0,0))
4174             MovDir[x][y] = 1 << RND(4);
4175
4176           for (i = 0; i < NUM_DIRECTIONS; i++)
4177           {
4178             int x1 = x + xy[i][0];
4179             int y1 = y + xy[i][1];
4180
4181             if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
4182             {
4183               if (move_pattern == MV_ALONG_RIGHT_SIDE)
4184                 MovDir[x][y] = direction[0][i];
4185               else
4186                 MovDir[x][y] = direction[1][i];
4187
4188               break;
4189             }
4190           }
4191         }                
4192       }
4193       else
4194       {
4195         MovDir[x][y] = 1 << RND(4);
4196
4197         if (element != EL_BUG &&
4198             element != EL_SPACESHIP &&
4199             element != EL_BD_BUTTERFLY &&
4200             element != EL_BD_FIREFLY)
4201           break;
4202
4203         for (i = 0; i < NUM_DIRECTIONS; i++)
4204         {
4205           int x1 = x + xy[i][0];
4206           int y1 = y + xy[i][1];
4207
4208           if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
4209           {
4210             if (element == EL_BUG || element == EL_BD_BUTTERFLY)
4211             {
4212               MovDir[x][y] = direction[0][i];
4213               break;
4214             }
4215             else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY ||
4216                      element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
4217             {
4218               MovDir[x][y] = direction[1][i];
4219               break;
4220             }
4221           }
4222         }
4223       }
4224       break;
4225   }
4226
4227   GfxDir[x][y] = MovDir[x][y];
4228 }
4229
4230 void InitAmoebaNr(int x, int y)
4231 {
4232   int i;
4233   int group_nr = AmoebeNachbarNr(x, y);
4234
4235   if (group_nr == 0)
4236   {
4237     for (i = 1; i < MAX_NUM_AMOEBA; i++)
4238     {
4239       if (AmoebaCnt[i] == 0)
4240       {
4241         group_nr = i;
4242         break;
4243       }
4244     }
4245   }
4246
4247   AmoebaNr[x][y] = group_nr;
4248   AmoebaCnt[group_nr]++;
4249   AmoebaCnt2[group_nr]++;
4250 }
4251
4252 static void PlayerWins(struct PlayerInfo *player)
4253 {
4254   player->LevelSolved = TRUE;
4255   player->GameOver = TRUE;
4256
4257   player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
4258                          level.native_em_level->lev->score : player->score);
4259
4260   player->LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed :
4261                                       TimeLeft);
4262   player->LevelSolved_CountingScore = player->score_final;
4263 }
4264
4265 void GameWon()
4266 {
4267   static int time, time_final;
4268   static int score, score_final;
4269   static int game_over_delay_1 = 0;
4270   static int game_over_delay_2 = 0;
4271   int game_over_delay_value_1 = 50;
4272   int game_over_delay_value_2 = 50;
4273
4274   if (!local_player->LevelSolved_GameWon)
4275   {
4276     int i;
4277
4278     /* do not start end game actions before the player stops moving (to exit) */
4279     if (local_player->MovPos)
4280       return;
4281
4282     local_player->LevelSolved_GameWon = TRUE;
4283     local_player->LevelSolved_SaveTape = tape.recording;
4284     local_player->LevelSolved_SaveScore = !tape.playing;
4285
4286     if (!tape.playing)
4287     {
4288       LevelStats_incSolved(level_nr);
4289
4290       SaveLevelSetup_SeriesInfo();
4291     }
4292
4293     if (tape.auto_play)         /* tape might already be stopped here */
4294       tape.auto_play_level_solved = TRUE;
4295
4296     TapeStop();
4297
4298     game_over_delay_1 = game_over_delay_value_1;
4299     game_over_delay_2 = game_over_delay_value_2;
4300
4301     time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
4302     score = score_final = local_player->score_final;
4303
4304     if (TimeLeft > 0)
4305     {
4306       time_final = 0;
4307       score_final += TimeLeft * level.score[SC_TIME_BONUS];
4308     }
4309     else if (game.no_time_limit && TimePlayed < 999)
4310     {
4311       time_final = 999;
4312       score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS];
4313     }
4314
4315     local_player->score_final = score_final;
4316
4317     if (level_editor_test_game)
4318     {
4319       time = time_final;
4320       score = score_final;
4321
4322       local_player->LevelSolved_CountingTime = time;
4323       local_player->LevelSolved_CountingScore = score;
4324
4325       game_panel_controls[GAME_PANEL_TIME].value = time;
4326       game_panel_controls[GAME_PANEL_SCORE].value = score;
4327
4328       DisplayGameControlValues();
4329     }
4330
4331     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
4332     {
4333       if (ExitX >= 0 && ExitY >= 0)     /* local player has left the level */
4334       {
4335         /* close exit door after last player */
4336         if ((AllPlayersGone &&
4337              (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
4338               Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
4339               Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN)) ||
4340             Feld[ExitX][ExitY] == EL_EM_EXIT_OPEN ||
4341             Feld[ExitX][ExitY] == EL_EM_STEEL_EXIT_OPEN)
4342         {
4343           int element = Feld[ExitX][ExitY];
4344
4345           Feld[ExitX][ExitY] =
4346             (element == EL_EXIT_OPEN            ? EL_EXIT_CLOSING :
4347              element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING :
4348              element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
4349              element == EL_STEEL_EXIT_OPEN      ? EL_STEEL_EXIT_CLOSING:
4350              EL_EM_STEEL_EXIT_CLOSING);
4351
4352           PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
4353         }
4354
4355         /* player disappears */
4356         DrawLevelField(ExitX, ExitY);
4357       }
4358
4359       for (i = 0; i < MAX_PLAYERS; i++)
4360       {
4361         struct PlayerInfo *player = &stored_player[i];
4362
4363         if (player->present)
4364         {
4365           RemovePlayer(player);
4366
4367           /* player disappears */
4368           DrawLevelField(player->jx, player->jy);
4369         }
4370       }
4371     }
4372
4373     PlaySound(SND_GAME_WINNING);
4374   }
4375
4376   if (game_over_delay_1 > 0)
4377   {
4378     game_over_delay_1--;
4379
4380     return;
4381   }
4382
4383   if (time != time_final)
4384   {
4385     int time_to_go = ABS(time_final - time);
4386     int time_count_dir = (time < time_final ? +1 : -1);
4387     int time_count_steps = (time_to_go > 100 && time_to_go % 10 == 0 ? 10 : 1);
4388
4389     time  += time_count_steps * time_count_dir;
4390     score += time_count_steps * level.score[SC_TIME_BONUS];
4391
4392     local_player->LevelSolved_CountingTime = time;
4393     local_player->LevelSolved_CountingScore = score;
4394
4395     game_panel_controls[GAME_PANEL_TIME].value = time;
4396     game_panel_controls[GAME_PANEL_SCORE].value = score;
4397
4398     DisplayGameControlValues();
4399
4400     if (time == time_final)
4401       StopSound(SND_GAME_LEVELTIME_BONUS);
4402     else if (setup.sound_loops)
4403       PlaySoundLoop(SND_GAME_LEVELTIME_BONUS);
4404     else
4405       PlaySound(SND_GAME_LEVELTIME_BONUS);
4406
4407     return;
4408   }
4409
4410   local_player->LevelSolved_PanelOff = TRUE;
4411
4412   if (game_over_delay_2 > 0)
4413   {
4414     game_over_delay_2--;
4415
4416     return;
4417   }
4418
4419   GameEnd();
4420 }
4421
4422 void GameEnd()
4423 {
4424   int hi_pos;
4425   boolean raise_level = FALSE;
4426
4427   local_player->LevelSolved_GameEnd = TRUE;
4428
4429   if (!global.use_envelope_request)
4430     CloseDoor(DOOR_CLOSE_1);
4431
4432   if (local_player->LevelSolved_SaveTape)
4433   {
4434     SaveTapeChecked(tape.level_nr);     /* ask to save tape */
4435   }
4436
4437   CloseDoor(DOOR_CLOSE_ALL);
4438
4439   if (level_editor_test_game)
4440   {
4441     SetGameStatus(GAME_MODE_MAIN);
4442
4443     DrawMainMenu();
4444
4445     return;
4446   }
4447
4448   if (!local_player->LevelSolved_SaveScore)
4449   {
4450     SetGameStatus(GAME_MODE_MAIN);
4451
4452     DrawMainMenu();
4453
4454     return;
4455   }
4456
4457   if (level_nr == leveldir_current->handicap_level)
4458   {
4459     leveldir_current->handicap_level++;
4460
4461     SaveLevelSetup_SeriesInfo();
4462   }
4463
4464   if (level_nr < leveldir_current->last_level)
4465     raise_level = TRUE;                 /* advance to next level */
4466
4467   if ((hi_pos = NewHiScore()) >= 0) 
4468   {
4469     SetGameStatus(GAME_MODE_SCORES);
4470
4471     DrawHallOfFame(hi_pos);
4472
4473     if (raise_level)
4474     {
4475       level_nr++;
4476       TapeErase();
4477     }
4478   }
4479   else
4480   {
4481     SetGameStatus(GAME_MODE_MAIN);
4482
4483     if (raise_level)
4484     {
4485       level_nr++;
4486       TapeErase();
4487     }
4488
4489     DrawMainMenu();
4490   }
4491 }
4492
4493 int NewHiScore()
4494 {
4495   int k, l;
4496   int position = -1;
4497
4498   LoadScore(level_nr);
4499
4500   if (strEqual(setup.player_name, EMPTY_PLAYER_NAME) ||
4501       local_player->score_final < highscore[MAX_SCORE_ENTRIES - 1].Score) 
4502     return -1;
4503
4504   for (k = 0; k < MAX_SCORE_ENTRIES; k++) 
4505   {
4506     if (local_player->score_final > highscore[k].Score)
4507     {
4508       /* player has made it to the hall of fame */
4509
4510       if (k < MAX_SCORE_ENTRIES - 1)
4511       {
4512         int m = MAX_SCORE_ENTRIES - 1;
4513
4514 #ifdef ONE_PER_NAME
4515         for (l = k; l < MAX_SCORE_ENTRIES; l++)
4516           if (strEqual(setup.player_name, highscore[l].Name))
4517             m = l;
4518         if (m == k)     /* player's new highscore overwrites his old one */
4519           goto put_into_list;
4520 #endif
4521
4522         for (l = m; l > k; l--)
4523         {
4524           strcpy(highscore[l].Name, highscore[l - 1].Name);
4525           highscore[l].Score = highscore[l - 1].Score;
4526         }
4527       }
4528
4529 #ifdef ONE_PER_NAME
4530       put_into_list:
4531 #endif
4532       strncpy(highscore[k].Name, setup.player_name, MAX_PLAYER_NAME_LEN);
4533       highscore[k].Name[MAX_PLAYER_NAME_LEN] = '\0';
4534       highscore[k].Score = local_player->score_final; 
4535       position = k;
4536       break;
4537     }
4538
4539 #ifdef ONE_PER_NAME
4540     else if (!strncmp(setup.player_name, highscore[k].Name,
4541                       MAX_PLAYER_NAME_LEN))
4542       break;    /* player already there with a higher score */
4543 #endif
4544
4545   }
4546
4547   if (position >= 0) 
4548     SaveScore(level_nr);
4549
4550   return position;
4551 }
4552
4553 inline static int getElementMoveStepsizeExt(int x, int y, int direction)
4554 {
4555   int element = Feld[x][y];
4556   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
4557   int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
4558   int horiz_move = (dx != 0);
4559   int sign = (horiz_move ? dx : dy);
4560   int step = sign * element_info[element].move_stepsize;
4561
4562   /* special values for move stepsize for spring and things on conveyor belt */
4563   if (horiz_move)
4564   {
4565     if (CAN_FALL(element) &&
4566         y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
4567       step = sign * MOVE_STEPSIZE_NORMAL / 2;
4568     else if (element == EL_SPRING)
4569       step = sign * MOVE_STEPSIZE_NORMAL * 2;
4570   }
4571
4572   return step;
4573 }
4574
4575 inline static int getElementMoveStepsize(int x, int y)
4576 {
4577   return getElementMoveStepsizeExt(x, y, MovDir[x][y]);
4578 }
4579
4580 void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
4581 {
4582   if (player->GfxAction != action || player->GfxDir != dir)
4583   {
4584     player->GfxAction = action;
4585     player->GfxDir = dir;
4586     player->Frame = 0;
4587     player->StepFrame = 0;
4588   }
4589 }
4590
4591 static void ResetGfxFrame(int x, int y)
4592 {
4593   int element = Feld[x][y];
4594   int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
4595
4596   if (graphic_info[graphic].anim_global_sync)
4597     GfxFrame[x][y] = FrameCounter;
4598   else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
4599     GfxFrame[x][y] = CustomValue[x][y];
4600   else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
4601     GfxFrame[x][y] = element_info[element].collect_score;
4602   else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
4603     GfxFrame[x][y] = ChangeDelay[x][y];
4604 }
4605
4606 static void ResetGfxAnimation(int x, int y)
4607 {
4608   GfxAction[x][y] = ACTION_DEFAULT;
4609   GfxDir[x][y] = MovDir[x][y];
4610   GfxFrame[x][y] = 0;
4611
4612   ResetGfxFrame(x, y);
4613 }
4614
4615 static void ResetRandomAnimationValue(int x, int y)
4616 {
4617   GfxRandom[x][y] = INIT_GFX_RANDOM();
4618 }
4619
4620 void InitMovingField(int x, int y, int direction)
4621 {
4622   int element = Feld[x][y];
4623   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
4624   int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
4625   int newx = x + dx;
4626   int newy = y + dy;
4627   boolean is_moving_before, is_moving_after;
4628
4629   /* check if element was/is moving or being moved before/after mode change */
4630   is_moving_before = (WasJustMoving[x][y] != 0);
4631   is_moving_after  = (getElementMoveStepsizeExt(x, y, direction)    != 0);
4632
4633   /* reset animation only for moving elements which change direction of moving
4634      or which just started or stopped moving
4635      (else CEs with property "can move" / "not moving" are reset each frame) */
4636   if (is_moving_before != is_moving_after ||
4637       direction != MovDir[x][y])
4638     ResetGfxAnimation(x, y);
4639
4640   MovDir[x][y] = direction;
4641   GfxDir[x][y] = direction;
4642
4643   GfxAction[x][y] = (!is_moving_after ? ACTION_WAITING :
4644                      direction == MV_DOWN && CAN_FALL(element) ?
4645                      ACTION_FALLING : ACTION_MOVING);
4646
4647   /* this is needed for CEs with property "can move" / "not moving" */
4648
4649   if (is_moving_after)
4650   {
4651     if (Feld[newx][newy] == EL_EMPTY)
4652       Feld[newx][newy] = EL_BLOCKED;
4653
4654     MovDir[newx][newy] = MovDir[x][y];
4655
4656     CustomValue[newx][newy] = CustomValue[x][y];
4657
4658     GfxFrame[newx][newy] = GfxFrame[x][y];
4659     GfxRandom[newx][newy] = GfxRandom[x][y];
4660     GfxAction[newx][newy] = GfxAction[x][y];
4661     GfxDir[newx][newy] = GfxDir[x][y];
4662   }
4663 }
4664
4665 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
4666 {
4667   int direction = MovDir[x][y];
4668   int newx = x + (direction & MV_LEFT ? -1 : direction & MV_RIGHT ? +1 : 0);
4669   int newy = y + (direction & MV_UP   ? -1 : direction & MV_DOWN  ? +1 : 0);
4670
4671   *goes_to_x = newx;
4672   *goes_to_y = newy;
4673 }
4674