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