+ Feld[x][y] = GetElementFromGroupElement(element);
+
+ InitField(x, y, init_game);
+ }
+
+ break;
+ }
+
+ if (!init_game)
+ CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
+}
+
+static inline void InitField_WithBug1(int x, int y, boolean init_game)
+{
+ InitField(x, y, init_game);
+
+ /* not needed to call InitMovDir() -- already done by InitField()! */
+ if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+ CAN_MOVE(Feld[x][y]))
+ InitMovDir(x, y);
+}
+
+static inline void InitField_WithBug2(int x, int y, boolean init_game)
+{
+ int old_element = Feld[x][y];
+
+ InitField(x, y, init_game);
+
+ /* not needed to call InitMovDir() -- already done by InitField()! */
+ if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+ CAN_MOVE(old_element) &&
+ (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
+ InitMovDir(x, y);
+
+ /* this case is in fact a combination of not less than three bugs:
+ first, it calls InitMovDir() for elements that can move, although this is
+ already done by InitField(); then, it checks the element that was at this
+ field _before_ the call to InitField() (which can change it); lastly, it
+ was not called for "mole with direction" elements, which were treated as
+ "cannot move" due to (fixed) wrong element initialization in "src/init.c"
+ */
+}
+
+#if 1
+
+static int get_key_element_from_nr(int key_nr)
+{
+ int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
+ level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+ EL_EM_KEY_1 : EL_KEY_1);
+
+ return key_base_element + key_nr;
+}
+
+void InitGameControlValues()
+{
+ int i;
+
+ for (i = 0; game_controls[i].nr != -1; i++)
+ {
+ int nr = game_controls[i].nr;
+ int type = game_controls[i].type;
+ struct TextPosInfo *pos = game_controls[i].pos;
+
+ /* force update of game controls after initialization */
+ game_control_value[nr] = last_game_control_value[nr] = -1;
+
+ /* determine panel value width for later calculation of alignment */
+ if (type == TYPE_INTEGER || type == TYPE_STRING)
+ pos->width = pos->chars * getFontWidth(pos->font);
+ else if (type == TYPE_ELEMENT)
+ pos->width = MINI_TILESIZE;
+ }
+}
+
+void UpdateGameControlValues()
+{
+ int i, k;
+
+ game_control_value[GAME_CONTROL_LEVEL_NUMBER] = level_nr;
+ game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+
+ game_control_value[GAME_CONTROL_INVENTORY] = 0;
+ for (i = 0; i < MAX_NUM_KEYS; i++)
+ game_control_value[GAME_CONTROL_KEY_1 + i] = EL_EMPTY;
+ game_control_value[GAME_CONTROL_KEY_WHITE] = EL_EMPTY;
+ game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] = 0;
+
+ if (game.centered_player_nr == -1)
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ for (k = 0; k < MAX_NUM_KEYS; k++)
+ if (stored_player[i].key[k])
+ game_control_value[GAME_CONTROL_KEY_1 + k] =
+ get_key_element_from_nr(k);
+
+ game_control_value[GAME_CONTROL_INVENTORY] +=
+ stored_player[i].inventory_size;
+
+ if (stored_player[i].num_white_keys > 0)
+ game_control_value[GAME_CONTROL_KEY_WHITE] = EL_DC_KEY_WHITE;
+
+ game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+ stored_player[i].num_white_keys;
+ }
+ }
+ else
+ {
+ int player_nr = game.centered_player_nr;
+
+ for (k = 0; k < MAX_NUM_KEYS; k++)
+ if (stored_player[player_nr].key[k])
+ game_control_value[GAME_CONTROL_KEY_1 + k] =
+ get_key_element_from_nr(k);
+
+ game_control_value[GAME_CONTROL_INVENTORY] +=
+ stored_player[player_nr].inventory_size;
+
+ if (stored_player[player_nr].num_white_keys > 0)
+ game_control_value[GAME_CONTROL_KEY_WHITE] = EL_DC_KEY_WHITE;
+
+ game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+ stored_player[player_nr].num_white_keys;
+ }
+
+ game_control_value[GAME_CONTROL_SCORE] = (local_player->LevelSolved ?
+ local_player->score_final :
+ local_player->score);
+
+ game_control_value[GAME_CONTROL_TIME] = (level.time == 0 ?
+ TimePlayed :
+ TimeLeft);
+
+ game_control_value[GAME_CONTROL_TIME_HH] = TapeTime / 3600;
+ game_control_value[GAME_CONTROL_TIME_MM] = (TapeTime / 60) % 60;
+ game_control_value[GAME_CONTROL_TIME_SS] = TapeTime % 60;
+
+ /* !!! TODO !!! */
+ for (i = 0; i < 8; i++)
+ game_control_value[GAME_CONTROL_DROP_NEXT_1 + i] = EL_UNDEFINED;
+
+ game_control_value[GAME_CONTROL_SHIELD_NORMAL] =
+ (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
+ EL_EMPTY);
+ game_control_value[GAME_CONTROL_SHIELD_NORMAL_TIME] =
+ local_player->shield_normal_time_left;
+ game_control_value[GAME_CONTROL_SHIELD_DEADLY] =
+ (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
+ EL_EMPTY);
+ game_control_value[GAME_CONTROL_SHIELD_DEADLY_TIME] =
+ local_player->shield_deadly_time_left;
+
+ if (local_player->gems_still_needed > 0 ||
+ local_player->sokobanfields_still_needed > 0 ||
+ local_player->lights_still_needed > 0)
+ {
+ game_control_value[GAME_CONTROL_EXIT] = EL_EXIT_CLOSED;
+ game_control_value[GAME_CONTROL_EM_EXIT] = EL_EM_EXIT_CLOSED;
+ game_control_value[GAME_CONTROL_SP_EXIT] = EL_SP_EXIT_CLOSED;
+ game_control_value[GAME_CONTROL_STEEL_EXIT] = EL_STEEL_EXIT_CLOSED;
+ game_control_value[GAME_CONTROL_EM_STEEL_EXIT] = EL_EM_STEEL_EXIT_CLOSED;
+ }
+ else
+ {
+ game_control_value[GAME_CONTROL_EXIT] = EL_EXIT_OPEN;
+ game_control_value[GAME_CONTROL_EM_EXIT] = EL_EM_EXIT_OPEN;
+ game_control_value[GAME_CONTROL_SP_EXIT] = EL_SP_EXIT_OPEN;
+ game_control_value[GAME_CONTROL_STEEL_EXIT] = EL_STEEL_EXIT_OPEN;
+ game_control_value[GAME_CONTROL_EM_STEEL_EXIT] = EL_EM_STEEL_EXIT_OPEN;
+ }
+
+ /* !!! TODO !!! */
+ game_control_value[GAME_CONTROL_EMC_MAGIC_BALL] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_EMC_MAGIC_BALL_SWITCH] = EL_UNDEFINED;
+
+ game_control_value[GAME_CONTROL_LIGHT_SWITCH] =
+ (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
+ game_control_value[GAME_CONTROL_LIGHT_SWITCH_TIME] = game.light_time_left;
+
+ game_control_value[GAME_CONTROL_TIMEGATE_SWITCH] =
+ (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
+ game_control_value[GAME_CONTROL_TIMEGATE_SWITCH_TIME] =
+ game.timegate_time_left;
+
+ /* !!! TODO !!! */
+ game_control_value[GAME_CONTROL_SWITCHGATE_SWITCH] = EL_UNDEFINED;
+
+ game_control_value[GAME_CONTROL_EMC_LENSES] =
+ (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
+ game_control_value[GAME_CONTROL_EMC_LENSES_TIME] = game.lenses_time_left;
+
+ game_control_value[GAME_CONTROL_EMC_MAGNIFIER] =
+ (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
+ game_control_value[GAME_CONTROL_EMC_MAGNIFIER_TIME] = game.magnify_time_left;
+
+ game_control_value[GAME_CONTROL_BALLOON_SWITCH] =
+ (game.wind_direction == MV_LEFT ? EL_BALLOON_SWITCH_LEFT :
+ game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
+ game.wind_direction == MV_UP ? EL_BALLOON_SWITCH_UP :
+ game.wind_direction == MV_DOWN ? EL_BALLOON_SWITCH_DOWN :
+ EL_BALLOON_SWITCH_NONE);
+
+ game_control_value[GAME_CONTROL_DYNABOMB_NUMBER] =
+ local_player->dynabomb_count;
+ game_control_value[GAME_CONTROL_DYNABOMB_SIZE] =
+ local_player->dynabomb_size;
+ game_control_value[GAME_CONTROL_DYNABOMB_POWER] =
+ (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
+
+ game_control_value[GAME_CONTROL_PENGUINS] =
+ local_player->friends_still_needed;
+
+ game_control_value[GAME_CONTROL_SOKOBAN_OBJECTS] =
+ local_player->sokobanfields_still_needed;
+ game_control_value[GAME_CONTROL_SOKOBAN_FIELDS] =
+ local_player->sokobanfields_still_needed;
+
+ /* !!! TODO !!! */
+ game_control_value[GAME_CONTROL_ROBOT_WHEEL] = EL_UNDEFINED;
+
+ /* !!! TODO !!! */
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_1] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_1_SWITCH] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_2] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_2_SWITCH] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_3] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_3_SWITCH] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_4] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_CONVEYOR_BELT_4_SWITCH] = EL_UNDEFINED;
+
+ /* !!! TODO !!! */
+ game_control_value[GAME_CONTROL_MAGIC_WALL] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_MAGIC_WALL_TIME] =
+ game.magic_wall_time_left;
+ game_control_value[GAME_CONTROL_BD_MAGIC_WALL] = EL_UNDEFINED;
+ game_control_value[GAME_CONTROL_DC_MAGIC_WALL] = EL_UNDEFINED;
+
+ game_control_value[GAME_CONTROL_PLAYER_NAME] = 0;
+ game_control_value[GAME_CONTROL_LEVEL_NAME] = 0;
+ game_control_value[GAME_CONTROL_LEVEL_AUTHOR] = 0;
+}
+
+void DisplayGameControlValues()
+{
+ int i;
+
+ for (i = 0; game_controls[i].nr != -1; i++)
+ {
+ int nr = game_controls[i].nr;
+ int type = game_controls[i].type;
+ struct TextPosInfo *pos = game_controls[i].pos;
+ int value = game_control_value[nr];
+ int last_value = last_game_control_value[nr];
+ int chars = pos->chars;
+ int font = pos->font;
+
+ if (value == last_value)
+ continue;
+
+ last_game_control_value[nr] = value;
+
+#if 0
+ printf("::: value %d changed from %d to %d\n", nr, last_value, value);
+#endif
+
+ if (PANEL_DEACTIVATED(pos))
+ continue;
+
+ if (type == TYPE_INTEGER)
+ {
+ if (nr == GAME_CONTROL_LEVEL_NUMBER || nr == GAME_CONTROL_TIME)
+ {
+ boolean use_dynamic_chars = (pos->chars == -1 ? TRUE : FALSE);
+
+ if (use_dynamic_chars) /* use dynamic number of chars */
+ {
+ int value_change = (nr == GAME_CONTROL_LEVEL_NUMBER ? 100 : 1000);
+ int chars1 = (nr == GAME_CONTROL_LEVEL_NUMBER ? 2 : 3);
+ int chars2 = chars1 + 1;
+ int font1 = pos->font;
+ int font2 = pos->font_alt;
+
+ chars = (value < value_change ? chars1 : chars2);
+ font = (value < value_change ? font1 : font2);
+
+ /* clear background if value just changed its size (dynamic chars) */
+ if ((last_value < value_change) != (value < value_change))
+ {
+ int width1 = chars1 * getFontWidth(font1);
+ int width2 = chars2 * getFontWidth(font2);
+ int max_width = MAX(width1, width2);
+ int max_height = MAX(getFontHeight(font1), getFontHeight(font2));
+
+ pos->width = max_width;
+
+ ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+ max_width, max_height);
+ }
+ }
+
+ pos->width = chars * getFontWidth(font);
+ }
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font);
+ }
+ else if (type == TYPE_ELEMENT)
+ {
+ int dst_x = PANEL_XPOS(pos);
+ int dst_y = PANEL_YPOS(pos);
+
+ if (value == EL_UNDEFINED || value == EL_EMPTY)
+ {
+ int src_x = DOOR_GFX_PAGEX5 + ALIGNED_TEXT_XPOS(pos);
+ int src_y = DOOR_GFX_PAGEY1 + ALIGNED_TEXT_YPOS(pos);
+
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
+ MINI_TILEX, MINI_TILEY, dst_x, dst_y);
+ }
+ else
+ {
+ int graphic = el2edimg(value);
+
+ DrawMiniGraphicExt(drawto, dst_x, dst_y, graphic);
+ }
+ }
+ else if (type == TYPE_STRING)
+ {
+ char *s = (nr == GAME_CONTROL_PLAYER_NAME ? setup.player_name :
+ nr == GAME_CONTROL_LEVEL_NAME ? level.name :
+ nr == GAME_CONTROL_LEVEL_AUTHOR ? level.author : NULL);
+
+ if (s != NULL)
+ {
+ char *s_cut = getStringCopyN(s, pos->chars);
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), s_cut, pos->font);
+
+ free(s_cut);
+ }
+ }
+
+ redraw_mask |= REDRAW_DOOR_1;
+ }
+}
+
+void DrawGameValue_Emeralds(int value)
+{
+ struct TextPosInfo *pos = &game.panel.gems;
+#if 1
+ int font_nr = pos->font;
+#else
+ int font_nr = FONT_TEXT_2;
+#endif
+ int font_width = getFontWidth(font_nr);
+ int chars = pos->chars;
+
+#if 1
+ return; /* !!! USE NEW STUFF !!! */
+#endif