rnd-20051122-1-src
authorHolger Schemel <info@artsoft.org>
Tue, 22 Nov 2005 01:32:59 +0000 (02:32 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:49:21 +0000 (10:49 +0200)
Makefile
src/conftime.h
src/editor.c
src/files.c
src/game.c
src/main.h
src/tape.c

index bf09646daa34bb1b8136ea31f0cf5ecced63cba3..832269b0b1ba5341c20cce999bd1df8c69ef2c98 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -123,6 +123,9 @@ enginetestfast: all
 enginetestnew: all
        ./Scripts/make_enginetest.sh new
 
+leveltest: all
+       ./Scripts/make_enginetest.sh leveltest
+
 backup:
        ./Scripts/make_backup.sh src
 
index 8b2851d2fac094fcc1f2718520adc64919352f52..3352ec2e6f30df70ba54da384a7a9ae3f55855a2 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2005-11-20 02:42]"
+#define COMPILE_DATE_STRING "[2005-11-22 02:31]"
index 04409147596f6e9a62a0b4ae66b5498686f06b13..4385eb8b96e4ca5305caef2eafc8f565e0184d6b 100644 (file)
 #define GADGET_ID_CHANGE_PLAYER                (GADGET_ID_SELECTBOX_FIRST + 19)
 #define GADGET_ID_CHANGE_PAGE          (GADGET_ID_SELECTBOX_FIRST + 20)
 #define GADGET_ID_CHANGE_REPLACE_WHEN  (GADGET_ID_SELECTBOX_FIRST + 21)
-#define GADGET_ID_CHANGE_ACTION                (GADGET_ID_SELECTBOX_FIRST + 22)
-#define GADGET_ID_CHANGE_ACTION_MODE   (GADGET_ID_SELECTBOX_FIRST + 23)
-#define GADGET_ID_CHANGE_ACTION_ARG    (GADGET_ID_SELECTBOX_FIRST + 24)
+#define GADGET_ID_ACTION_TYPE          (GADGET_ID_SELECTBOX_FIRST + 22)
+#define GADGET_ID_ACTION_MODE          (GADGET_ID_SELECTBOX_FIRST + 23)
+#define GADGET_ID_ACTION_ARG           (GADGET_ID_SELECTBOX_FIRST + 24)
 #define GADGET_ID_SELECT_CHANGE_PAGE   (GADGET_ID_SELECTBOX_FIRST + 25)
 #define GADGET_ID_GROUP_CHOICE_MODE    (GADGET_ID_SELECTBOX_FIRST + 26)
 
 #define ED_SELECTBOX_ID_CHANGE_PLAYER          19
 #define ED_SELECTBOX_ID_CHANGE_PAGE            20
 #define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN    21
-#define ED_SELECTBOX_ID_CHANGE_ACTION          22
-#define ED_SELECTBOX_ID_CHANGE_ACTION_MODE     23
-#define ED_SELECTBOX_ID_CHANGE_ACTION_ARG      24
+#define ED_SELECTBOX_ID_ACTION_TYPE            22
+#define ED_SELECTBOX_ID_ACTION_MODE            23
+#define ED_SELECTBOX_ID_ACTION_ARG             24
 #define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE     25
 #define ED_SELECTBOX_ID_GROUP_CHOICE_MODE      26
 
 
 /* values for elements with count for collecting */
 #define MIN_COLLECT_COUNT              0
-#define MAX_COLLECT_COUNT              100
+#define MAX_COLLECT_COUNT              255
 
 /* values for random placement */
 #define RANDOM_USE_PERCENTAGE          0
@@ -1433,6 +1433,7 @@ static struct ValueTextInfo options_change_direct_action[] =
 
   { CE_IMPACT,                 "impact (on something)"         },
   { CE_SMASHED,                        "smashed (from above)"          },
+  { CE_COUNT_AT_ZERO,          "CE count at zero"              },
 
   { -1,                                NULL                            }
 };
@@ -1455,6 +1456,7 @@ static struct ValueTextInfo options_change_other_action[] =
   { CE_SWITCH_OF_X,            "switch of"                     },
   { CE_CHANGE_OF_X,            "change by page of"             },
   { CE_EXPLOSION_OF_X,         "explosion of"                  },
+  { CE_COUNT_AT_ZERO_OF_X,     "CE count at zero of"           },
 
   { -1,                                NULL                            }
 };
@@ -1534,7 +1536,7 @@ static struct ValueTextInfo options_change_replace_when[] =
   { -1,                                NULL                            }
 };
 
-static struct ValueTextInfo options_change_action[] =
+static struct ValueTextInfo options_action_type[] =
 {
   { CA_NO_ACTION,              "no action"                     },
   { CA_EXIT_PLAYER,            "exit player"                   },
@@ -1545,9 +1547,10 @@ static struct ValueTextInfo options_change_action[] =
   { CA_DEL_KEY,                        "remove key"                    },
   { CA_SET_PLAYER_SPEED,       "set player speed"              },
   { CA_SET_GEMS,               "set gems"                      },
-  { CA_SET_SCORE,              "set score"                     },
   { CA_SET_TIME,               "set time"                      },
-  { CA_SET_COUNTER,            "set counter"                   },
+  { CA_SET_SCORE,              "set score"                     },
+  { CA_SET_CE_SCORE,           "set CE score"                  },
+  { CA_SET_CE_COUNT,           "set CE count"                  },
   { CA_SET_DYNABOMB_NUMBER,    "set bomb number"               },
   { CA_SET_DYNABOMB_SIZE,      "set bomb size"                 },
   { CA_SET_DYNABOMB_POWER,     "set bomb power"                },
@@ -1558,7 +1561,7 @@ static struct ValueTextInfo options_change_action[] =
   { -1,                                NULL                            }
 };
 
-static struct ValueTextInfo options_change_action_mode[] =
+static struct ValueTextInfo options_action_mode[] =
 {
   { CA_MODE_UNDEFINED,         " "                             },
   { CA_MODE_ADD,               "+"                             },
@@ -1570,9 +1573,9 @@ static struct ValueTextInfo options_change_action_mode[] =
   { -1,                                NULL                            }
 };
 
-static struct ValueTextInfo options_change_action_arg[] =
+static struct ValueTextInfo options_action_arg[] =
 {
-  { CA_ARG_PLAYER_HEADLINE,    "[players]"                     },
+  { CA_ARG_PLAYER_HEADLINE,    "[player]"                      },
   { CA_ARG_PLAYER_1,           "1"                             },
   { CA_ARG_PLAYER_2,           "2"                             },
   { CA_ARG_PLAYER_3,           "3"                             },
@@ -1580,21 +1583,14 @@ static struct ValueTextInfo options_change_action_arg[] =
   { CA_ARG_PLAYER_ANY,         "any"                           },
   { CA_ARG_PLAYER_TRIGGER,     "trigger"                       },
   { CA_ARG_UNDEFINED,          " "                             },
-  { CA_ARG_NUMBER_HEADLINE,    "[numbers]"                     },
+  { CA_ARG_NUMBER_HEADLINE,    "[number]"                      },
   { CA_ARG_0,                  "0"                             },
   { CA_ARG_1,                  "1"                             },
   { CA_ARG_2,                  "2"                             },
   { CA_ARG_3,                  "3"                             },
   { CA_ARG_4,                  "4"                             },
   { CA_ARG_5,                  "5"                             },
-  { CA_ARG_6,                  "6"                             },
-  { CA_ARG_7,                  "7"                             },
-  { CA_ARG_8,                  "8"                             },
-  { CA_ARG_9,                  "9"                             },
   { CA_ARG_10,                 "10"                            },
-  { CA_ARG_20,                 "20"                            },
-  { CA_ARG_25,                 "25"                            },
-  { CA_ARG_50,                 "50"                            },
   { CA_ARG_100,                        "100"                           },
   { CA_ARG_1000,               "1000"                          },
   { CA_ARG_UNDEFINED,          " "                             },
@@ -1602,7 +1598,13 @@ static struct ValueTextInfo options_change_action_arg[] =
   { CA_ARG_NUMBER_MAX,         "max"                           },
   { CA_ARG_NUMBER_NORMAL,      "normal"                        },
   { CA_ARG_NUMBER_RESET,       "reset"                         },
-  { CA_ARG_NUMBER_COUNT,       "counter"                       },
+  { CA_ARG_NUMBER_CE_SCORE,    "CE score"                      },
+  { CA_ARG_NUMBER_CE_COUNT,    "CE count"                      },
+  { CA_ARG_NUMBER_CE_DELAY,    "CE delay"                      },
+  { CA_ARG_UNDEFINED,          " "                             },
+  { CA_ARG_ELEMENT_HEADLINE,   "[element]"                     },
+  { CA_ARG_ELEMENT_TARGET,     "target"                        },
+  { CA_ARG_ELEMENT_TRIGGER,    "trigger"                       },
 
   { -1,                                NULL                            }
 };
@@ -1824,26 +1826,26 @@ static struct
   },
   {
     ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(13),
-    GADGET_ID_CHANGE_ACTION,           GADGET_ID_NONE,
+    GADGET_ID_ACTION_TYPE,             GADGET_ID_NONE,
     -1,
-    options_change_action,
-    &custom_element_change.change_action,
+    options_action_type,
+    &custom_element_change.action_type,
     NULL, NULL,                                "action on specified condition"
   },
   {
     -1,                                        ED_ELEMENT_SETTINGS_YPOS(13),
-    GADGET_ID_CHANGE_ACTION_MODE,      GADGET_ID_CHANGE_ACTION,
+    GADGET_ID_ACTION_MODE,             GADGET_ID_ACTION_TYPE,
     -1,
-    options_change_action_mode,
-    &custom_element_change.change_action_mode,
+    options_action_mode,
+    &custom_element_change.action_mode,
     NULL, NULL,                                "action operator"
   },
   {
     -1,                                        ED_ELEMENT_SETTINGS_YPOS(13),
-    GADGET_ID_CHANGE_ACTION_ARG,       GADGET_ID_CHANGE_ACTION_MODE,
+    GADGET_ID_ACTION_ARG,              GADGET_ID_ACTION_MODE,
     -1,
-    options_change_action_arg,
-    &custom_element_change.change_action_arg,
+    options_action_arg,
+    &custom_element_change.action_arg,
     NULL, NULL,                                "action parameter"
   },
   {
@@ -2365,7 +2367,7 @@ static struct
   {
     ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(13),
     GADGET_ID_CHANGE_USE_ACTION,       GADGET_ID_NONE,
-    &custom_element_change.use_change_action,
+    &custom_element_change.use_action,
     NULL, NULL,                                "execute action on specified condition"
   },
 };
@@ -6311,6 +6313,7 @@ static void CopyCustomElementPropertiesToEditor(int element)
      HAS_CHANGE_EVENT(element, CE_BLOCKED) ? CE_BLOCKED :
      HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT :
      HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED :
+     HAS_CHANGE_EVENT(element, CE_COUNT_AT_ZERO) ? CE_COUNT_AT_ZERO :
      custom_element_change.direct_action);
 
   /* set "change by other element action" selectbox help value */
@@ -6329,6 +6332,7 @@ static void CopyCustomElementPropertiesToEditor(int element)
      HAS_CHANGE_EVENT(element, CE_SWITCH_OF_X) ? CE_SWITCH_OF_X :
      HAS_CHANGE_EVENT(element, CE_CHANGE_OF_X) ? CE_CHANGE_OF_X :
      HAS_CHANGE_EVENT(element, CE_EXPLOSION_OF_X) ? CE_EXPLOSION_OF_X :
+     HAS_CHANGE_EVENT(element, CE_COUNT_AT_ZERO_OF_X) ? CE_COUNT_AT_ZERO_OF_X :
      custom_element_change.other_action);
 }
 
@@ -6500,6 +6504,7 @@ static void CopyCustomElementPropertiesToGame(int element)
   custom_element_change_events[CE_BLOCKED] = FALSE;
   custom_element_change_events[CE_IMPACT] = FALSE;
   custom_element_change_events[CE_SMASHED] = FALSE;
+  custom_element_change_events[CE_COUNT_AT_ZERO] = FALSE;
   custom_element_change_events[custom_element_change.direct_action] =
     custom_element_change_events[CE_BY_DIRECT_ACTION];
 
@@ -6518,6 +6523,7 @@ static void CopyCustomElementPropertiesToGame(int element)
   custom_element_change_events[CE_SWITCH_OF_X] = FALSE;
   custom_element_change_events[CE_CHANGE_OF_X] = FALSE;
   custom_element_change_events[CE_EXPLOSION_OF_X] = FALSE;
+  custom_element_change_events[CE_COUNT_AT_ZERO_OF_X] = FALSE;
   custom_element_change_events[custom_element_change.other_action] =
     custom_element_change_events[CE_BY_OTHER_ACTION];
 
index d522761ce9127dc3e3291d299c2d23e66fd638b3..8d3cbc9986c90b83e4536bf78bc15e59f8a1ffb8 100644 (file)
@@ -114,10 +114,10 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
   change->random_percentage = 100;
   change->replace_when = CP_WHEN_EMPTY;
 
-  change->use_change_action = FALSE;
-  change->change_action = CA_NO_ACTION;
-  change->change_action_mode = CA_MODE_UNDEFINED;
-  change->change_action_arg = CA_ARG_UNDEFINED;
+  change->use_action = FALSE;
+  change->action_type = CA_NO_ACTION;
+  change->action_mode = CA_MODE_UNDEFINED;
+  change->action_arg = CA_ARG_UNDEFINED;
 
   for (x = 0; x < 3; x++)
     for (y = 0; y < 3; y++)
@@ -1306,8 +1306,18 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
     change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
                            CH_PAGE_ANY : (1 << change->trigger_page));
 
+#if 1
+    change->use_action = getFile8Bit(file);
+    change->action_type = getFile8Bit(file);
+    change->action_mode = getFile8Bit(file);
+    change->action_arg = getFile16BitBE(file);
+
+    /* some free bytes for future change property values and padding */
+    ReadUnusedBytesFromFile(file, 1);
+#else
     /* some free bytes for future change property values and padding */
     ReadUnusedBytesFromFile(file, 6);
+#endif
 
 #else
 
@@ -2711,7 +2721,8 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
   int i, j, x, y;
 
   /* map custom element change events that have changed in newer versions
-     (these following values were accidentally changed in version 3.0.1) */
+     (these following values were accidentally changed in version 3.0.1)
+     (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */
   if (level->game_version <= VERSION_IDENT(3,0,0,0))
   {
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -2719,7 +2730,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
       int element = EL_CUSTOM_START + i;
 
       /* order of checking and copying events to be mapped is important */
-      for (j = CE_BY_OTHER_ACTION; j >= CE_BY_PLAYER_OBSOLETE; j--)
+      for (j = CE_BY_OTHER_ACTION; j >= CE_COUNT_AT_ZERO; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 2))
        {
@@ -2740,20 +2751,30 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
     }
   }
 
+#if 0
+  /* !!! TESTS SHOWED THAT THIS CODE SEGMENT IS NOT NEEDED FOR ANY LEVEL !!! */
+
   /* some custom element change events get mapped since version 3.0.3 */
-  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+#if 1
+  if (level->game_version >= VERSION_IDENT(3,0,3,0) &&
+      level->game_version <= VERSION_IDENT(3,2,0,3))
+#endif
   {
-    int element = EL_CUSTOM_START + i;
-
-    if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
-       HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
     {
-      SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
-      SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
+      int element = EL_CUSTOM_START + i;
+
+      if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
+         HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+      {
+       SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
+       SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
 
-      SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+       SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+      }
     }
   }
+#endif
 
   /* initialize "can_change" field for old levels with only one change page */
   if (level->game_version <= VERSION_IDENT(3,0,2,0))
@@ -3388,8 +3409,19 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
     putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE :
                       log_2(change->trigger_page)));
 
+#if 1
+
+    putFile8Bit(file, change->use_action);
+    putFile8Bit(file, change->action_type);
+    putFile8Bit(file, change->action_mode);
+    putFile16BitBE(file, change->action_arg);
+
+    /* some free bytes for future change property values and padding */
+    WriteUnusedBytesToFile(file, 1);
+#else
     /* some free bytes for future change property values and padding */
     WriteUnusedBytesToFile(file, 6);
+#endif
 
 #else
 
index e3007408dd8b4f65da4ffddb77f446689f338357..78a112f29bba5bcf059b50a0c211c58ca5c40230 100644 (file)
                                 RND(element_info[e].move_delay_random))
 #define GET_MAX_MOVE_DELAY(e)  (   (element_info[e].move_delay_fixed) + \
                                    (element_info[e].move_delay_random))
+#define GET_CHANGE_DELAY(c)    (   ((c)->delay_fixed  * (c)->delay_frames) + \
+                                RND((c)->delay_random * (c)->delay_frames))
 
 #define GET_TARGET_ELEMENT(e, ch)                                      \
        ((e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element :     \
@@ -1130,9 +1132,15 @@ inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
 
   /* currently only 4 of 8 possible keys are displayed */
   for (i = 0; i < STD_NUM_KEYS; i++)
+  {
     if (key[i])
       DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
                         el2edimg(EL_KEY_1 + i));
+    else
+      BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+                DOOR_GFX_PAGEX5 + XX_KEYS + i * MINI_TILEX, YY_KEYS,
+                MINI_TILEX, MINI_TILEY, DX_KEYS + i * MINI_TILEX, DY_KEYS);
+  }
 }
 
 inline void DrawGameValue_Score(int value)
@@ -7859,21 +7867,301 @@ static void ChangeActiveTrap(int x, int y)
     DrawLevelFieldCrumbledSand(x, y);
 }
 
-static void HandleChangeAction(int change_action)
+static int getSpecialActionElement(int element, int number, int base_element)
 {
-  if (change_action == CA_EXIT_PLAYER)
-  {
-    printf("::: CA_EXIT_GAME\n");
+  return (element != EL_EMPTY ? element :
+         number != -1 ? base_element + number - 1 :
+         EL_EMPTY);
+}
 
-    /* !!! local_player <-> 4 players !!! (EXTEND THIS) !!! */
-    local_player->LevelSolved = local_player->GameOver = TRUE;
-  }
-  else if (change_action == CA_KILL_PLAYER)
-  {
-    printf("::: CA_KILL_PLAYER\n");
+static int getModifiedActionNumber(int value_old, int value_min, int value_max,
+                                  int operator, int operand)
+{
+  int value_new = (operator == CA_MODE_ADD      ? value_old + operand :
+                  operator == CA_MODE_SUBTRACT ? value_old - operand :
+                  operator == CA_MODE_MULTIPLY ? value_old * operand :
+                  operator == CA_MODE_DIVIDE   ? value_old / MAX(1, operand) :
+                  operator == CA_MODE_SET      ? operand :
+                  value_old);
+
+  return (value_new < value_min ? value_min :
+         value_new > value_max ? value_max :
+         value_new);
+}
+
+static void ExecuteCustomElementAction(int x, int y, int element, int page)
+{
+  struct ElementInfo *ei = &element_info[element];
+  struct ElementChangeInfo *change = &ei->change_page[page];
+  int action_type = change->action_type;
+  int action_mode = change->action_mode;
+  int action_arg = change->action_arg;
+  int i;
+
+  /* ---------- determine action paramater values ---------- */
+
+  int action_arg_element =
+    (action_arg == CA_ARG_PLAYER_TRIGGER  ? change->actual_trigger_player :
+     action_arg == CA_ARG_ELEMENT_TRIGGER ? change->actual_trigger_element :
+     action_arg == CA_ARG_ELEMENT_TARGET  ? change->target_element :
+     EL_EMPTY);
+
+  int action_arg_number =
+    (action_arg <= CA_ARG_MAX ? action_arg :
+     action_arg == CA_ARG_NUMBER_MIN ? CA_ARG_MIN :
+     action_arg == CA_ARG_NUMBER_MAX ? CA_ARG_MAX :
+     action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
+     action_arg == CA_ARG_NUMBER_CE_COUNT ? ei->collect_count :
+     action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) :
+     -1);
+
+  /* (for explicit player choice, set invalid value to "no player") */
+  int action_arg_player_bits =
+    (action_arg == CA_ARG_PLAYER_ANY ? action_arg - CA_ARG_PLAYER :
+     action_arg >= CA_ARG_PLAYER_1 &&
+     action_arg <= CA_ARG_PLAYER_4 ? action_arg - CA_ARG_PLAYER :
+     action_arg >= CA_ARG_1 &&
+     action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - 1)) :
+     action_arg_element >= EL_PLAYER_1 &&
+     action_arg_element <= EL_PLAYER_4 ?
+     (1 << (action_arg_element - EL_PLAYER_1)) :
+     0);
+
+  /* (for implicit player choice, set invalid value to "all players") */
+  int trigger_player_bits =
+    (change->actual_trigger_player >= EL_PLAYER_1 &&
+     change->actual_trigger_player <= EL_PLAYER_4 ?
+     (1 << (change->actual_trigger_player - EL_PLAYER_1)) :
+     PLAYER_BITS_ANY);
+
+  /* ---------- execute action  ---------- */
+
+  switch(action_type)
+  {
+    case CA_NO_ACTION:
+    {
+      return;
+    }
+
+    case CA_EXIT_PLAYER:
+    {
+      for (i = 0; i < MAX_PLAYERS; i++)
+       if (action_arg_player_bits & (1 << i))
+         stored_player[i].LevelSolved = stored_player[i].GameOver = TRUE;
+
+      break;
+    }
+
+    case CA_KILL_PLAYER:
+    {
+      for (i = 0; i < MAX_PLAYERS; i++)
+       if (action_arg_player_bits & (1 << i))
+         KillHero(&stored_player[i]);
+
+      break;
+    }
+
+    case CA_RESTART_LEVEL:
+    {
+      printf("::: CA_RESTART_LEVEL -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_SHOW_ENVELOPE:
+    {
+      int element = getSpecialActionElement(action_arg_element,
+                                           action_arg_number, EL_ENVELOPE_1);
+
+      if (IS_ENVELOPE(element))
+       local_player->show_envelope = element;
+
+      break;
+    }
+
+    case CA_ADD_KEY:
+    {
+      int element = getSpecialActionElement(action_arg_element,
+                                           action_arg_number, EL_KEY_1);
+
+      if (IS_KEY(element))
+      {
+       for (i = 0; i < MAX_PLAYERS; i++)
+       {
+         if (trigger_player_bits & (1 << i))
+         {
+           stored_player[i].key[KEY_NR(element)] = TRUE;
+
+           DrawGameValue_Keys(stored_player[i].key);
+
+           redraw_mask |= REDRAW_DOOR_1;
+         }
+       }
+      }
+
+      break;
+    }
+
+    case CA_DEL_KEY:
+    {
+      int element = getSpecialActionElement(action_arg_element,
+                                           action_arg_number, EL_KEY_1);
+
+      if (IS_KEY(element))
+      {
+       for (i = 0; i < MAX_PLAYERS; i++)
+       {
+         if (trigger_player_bits & (1 << i))
+         {
+           stored_player[i].key[KEY_NR(element)] = FALSE;
+
+           DrawGameValue_Keys(stored_player[i].key);
+
+           redraw_mask |= REDRAW_DOOR_1;
+         }
+       }
+      }
+
+      break;
+    }
+
+    case CA_SET_PLAYER_SPEED:
+    {
+      for (i = 0; i < MAX_PLAYERS; i++)
+      {
+       if (trigger_player_bits & (1 << i))
+       {
+         if (action_arg == CA_ARG_NUMBER_RESET)
+           stored_player[i].move_delay_value = game.initial_move_delay_value;
+         else if (action_arg == CA_ARG_NUMBER_NORMAL)
+           stored_player[i].move_delay_value = MOVE_DELAY_NORMAL_SPEED;
+         else if (action_arg == CA_ARG_NUMBER_MIN)
+           stored_player[i].move_delay_value = 16;
+         else if (action_arg == CA_ARG_NUMBER_MAX)
+           stored_player[i].move_delay_value = MOVE_DELAY_HIGH_SPEED;
+         else
+         {
+#if 0
+           if (action_mode == CA_MODE_ADD)
+           {
+             action_mode = CA_MODE_DIVIDE;
+             action_arg_number = (1 << action_arg_number);
+           }
+           else if (action_mode == CA_MODE_SUBTRACT)
+           {
+             action_mode = CA_MODE_MULTIPLY;
+             action_arg_number = (1 << action_arg_number);
+           }
 
-    /* !!! local_player <-> 4 players !!! (EXTEND THIS) !!! */
-    KillHero(local_player);
+           int mode = (action_mode == CA_MODE_MULTIPLY ? CA_MODE_DIVIDE :
+                       action_mode == CA_MODE_DIVIDE   ? CA_MODE_MULTIPLY :
+                       action_mode);
+
+           stored_player[i].move_delay_value =
+             getModifiedActionNumber(stored_player[i].move_delay_value,
+                                     1, 16,
+                                     action_mode, action_arg_number);
+#endif
+         }
+       }
+      }
+
+      break;
+    }
+
+    case CA_SET_GEMS:
+    {
+      local_player->gems_still_needed =
+       getModifiedActionNumber(local_player->gems_still_needed, 0, 999,
+                               action_mode, action_arg_number);
+
+      DrawGameValue_Emeralds(local_player->gems_still_needed);
+
+      break;
+    }
+
+    case CA_SET_TIME:
+    {
+      if (level.time > 0)      /* only modify limited time value */
+      {
+       TimeLeft = getModifiedActionNumber(TimeLeft, 0, 9999,
+                                          action_mode, action_arg_number);
+
+       DrawGameValue_Time(TimeLeft);
+      }
+
+      break;
+    }
+
+    case CA_SET_SCORE:
+    {
+      local_player->score =
+       getModifiedActionNumber(local_player->score, 0, 99999,
+                               action_mode, action_arg_number);
+
+      DrawGameValue_Score(local_player->score);
+
+      break;
+    }
+
+    case CA_SET_CE_SCORE:
+    {
+      printf("::: CA_SET_CE_SCORE -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_SET_CE_COUNT:
+    {
+      printf("::: CA_SET_CE_COUNT -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_SET_DYNABOMB_NUMBER:
+    {
+      printf("::: CA_SET_DYNABOMB_NUMBER -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_SET_DYNABOMB_SIZE:
+    {
+      printf("::: CA_SET_DYNABOMB_SIZE -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_SET_DYNABOMB_POWER:
+    {
+      printf("::: CA_SET_DYNABOMB_POWER -- not yet implemented\n");
+
+      break;
+    }
+
+    case CA_TOGGLE_PLAYER_GRAVITY:
+    {
+      game.gravity = !game.gravity;
+
+      break;
+    }
+
+    case CA_ENABLE_PLAYER_GRAVITY:
+    {
+      game.gravity = TRUE;
+
+      break;
+    }
+
+    case CA_DISABLE_PLAYER_GRAVITY:
+    {
+      game.gravity = FALSE;
+
+      break;
+    }
+
+    default:
+      break;
   }
 }
 
@@ -7966,8 +8254,10 @@ static void ChangeElementNowExt(struct ElementChangeInfo *change,
   TestIfElementTouchesCustomElement(x, y);
 #endif
 
-  if (change->use_change_action)
-    HandleChangeAction(change->change_action);
+#if 0
+  if (change->use_action)
+    ExecuteCustomElementAction(...);
+#endif
 }
 
 static boolean ChangeElementNow(int x, int y, int element, int page)
@@ -7982,7 +8272,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page)
 
   if (ChangeEvent[x][y] == CE_DELAY)
   {
-    /* reset actual trigger element and player */
+    /* reset actual trigger element, trigger player and action element */
     change->actual_trigger_element = EL_EMPTY;
     change->actual_trigger_player = EL_PLAYER_1;
   }
@@ -8210,8 +8500,12 @@ static void ChangeElement(int x, int y, int page)
 
   if (ChangeDelay[x][y] == 0)          /* initialize element change */
   {
+#if 1
+    ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1;
+#else
     ChangeDelay[x][y] = (    change->delay_fixed  * change->delay_frames +
                         RND(change->delay_random * change->delay_frames)) + 1;
+#endif
 
     ResetGfxAnimation(x, y);
     ResetRandomAnimationValue(x, y);
@@ -8254,6 +8548,11 @@ static void ChangeElement(int x, int y, int page)
       return;
     }
 
+#if 1
+    if (change->use_action)
+      ExecuteCustomElementAction(x, y, element, page);
+#endif
+
     if (ChangeElementNow(x, y, element, page))
     {
       if (change->post_change_function)
@@ -11817,7 +12116,9 @@ int DigField(struct PlayerInfo *player,
        }
 
        if (element == EL_SPEED_PILL)
+       {
          player->move_delay_value = MOVE_DELAY_HIGH_SPEED;
+       }
        else if (element == EL_EXTRA_TIME && level.time > 0)
        {
          TimeLeft += 10;
index 10fed0f80d84f600a77ad97b031b90bc22bd6d71..a5b300d725a6422d8cdb207d48bca35bed516d37 100644 (file)
 #define CE_PLAYER_PUSHES_X     13
 #define CE_PLAYER_COLLECTS_X   14
 #define CE_PLAYER_DROPS_X      15
+
+#if 1
+#define CE_COUNT_AT_ZERO       16
+#define CE_COUNT_AT_ZERO_OF_X  17
+#else
 #define CE_BY_PLAYER_OBSOLETE  16      /* obsolete; now CE_BY_DIRECT_ACTION */
 #define CE_BY_COLLISION_OBSOLETE 17    /* obsolete; now CE_BY_DIRECT_ACTION */
+#endif
+
 #define CE_BY_OTHER_ACTION     18      /* activates other element events */
 #define CE_BY_DIRECT_ACTION    19      /* activates direct element events */
 #define CE_PLAYER_DIGS_X       20
                                (CH_ANY_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
 #endif
 
+/* values for player bitmasks */
+#define PLAYER_BITS_NONE       0
+#define PLAYER_BITS_1          (1 << 0)
+#define PLAYER_BITS_2          (1 << 1)
+#define PLAYER_BITS_3          (1 << 2)
+#define PLAYER_BITS_4          (1 << 3)
+#define PLAYER_BITS_ANY                (PLAYER_BITS_1 | \
+                                PLAYER_BITS_2 | \
+                                PLAYER_BITS_3 | \
+                                PLAYER_BITS_4)
+#define PLAYER_BITS_TRIGGER    (1 << 4)
+
 /* values for change side for custom elements */
 #define CH_SIDE_NONE           MV_NO_MOVING
 #define CH_SIDE_LEFT           MV_LEFT
 #define CH_SIDE_ANY            MV_ANY_DIRECTION
 
 /* values for change player for custom elements */
-#define CH_PLAYER_NONE         0
-#define CH_PLAYER_1            (1 << 0)
-#define CH_PLAYER_2            (1 << 1)
-#define CH_PLAYER_3            (1 << 2)
-#define CH_PLAYER_4            (1 << 3)
-#define CH_PLAYER_ANY          (CH_PLAYER_1 | \
-                                CH_PLAYER_2 | \
-                                CH_PLAYER_3 | \
-                                CH_PLAYER_4)
-#define CH_PLAYER_TRIGGER      (1 << 4)
+#define CH_PLAYER_NONE         PLAYER_BITS_NONE
+#define CH_PLAYER_1            PLAYER_BITS_1
+#define CH_PLAYER_2            PLAYER_BITS_2
+#define CH_PLAYER_3            PLAYER_BITS_3
+#define CH_PLAYER_4            PLAYER_BITS_4
+#define CH_PLAYER_ANY          PLAYER_BITS_ANY
 
 /* values for change page for custom elements */
 #define CH_PAGE_ANY_FILE       (0xff)
 #define CA_DEL_KEY             6
 #define CA_SET_PLAYER_SPEED    7
 #define CA_SET_GEMS            8
-#define CA_SET_SCORE           9
-#define CA_SET_TIME            10
-#define CA_SET_COUNTER         11
-#define CA_SET_DYNABOMB_NUMBER 12
-#define CA_SET_DYNABOMB_SIZE   13
-#define CA_SET_DYNABOMB_POWER  14
-#define CA_TOGGLE_PLAYER_GRAVITY  15
-#define CA_ENABLE_PLAYER_GRAVITY  16
-#define CA_DISABLE_PLAYER_GRAVITY 17
+#define CA_SET_TIME            9
+#define CA_SET_SCORE           10
+#define CA_SET_CE_SCORE                11
+#define CA_SET_CE_COUNT                12
+#define CA_SET_DYNABOMB_NUMBER 13
+#define CA_SET_DYNABOMB_SIZE   14
+#define CA_SET_DYNABOMB_POWER  15
+#define CA_TOGGLE_PLAYER_GRAVITY  16
+#define CA_ENABLE_PLAYER_GRAVITY  17
+#define CA_DISABLE_PLAYER_GRAVITY 18
 
 /* values for change action mode for custom elements */
 #define CA_MODE_UNDEFINED      0
 #define CA_MODE_SET            5
 
 /* values for change action parameters for custom elements */
+#define CA_ARG_MIN             0
 #define CA_ARG_0               0
 #define CA_ARG_1               1
 #define CA_ARG_2               2
 #define CA_ARG_3               3
 #define CA_ARG_4               4
 #define CA_ARG_5               5
-#define CA_ARG_6               6
-#define CA_ARG_7               7
-#define CA_ARG_8               8
-#define CA_ARG_9               9
 #define CA_ARG_10              10
-#define CA_ARG_20              20
-#define CA_ARG_25              25
-#define CA_ARG_50              50
 #define CA_ARG_100             100
 #define CA_ARG_1000            1000
-#define CA_ARG_PLAYER          20000
+#define CA_ARG_MAX             9999
+#define CA_ARG_PLAYER          10000
 #define CA_ARG_PLAYER_HEADLINE (CA_ARG_PLAYER + 0)
-#define CA_ARG_PLAYER_1                (CA_ARG_PLAYER + CH_PLAYER_1)
-#define CA_ARG_PLAYER_2                (CA_ARG_PLAYER + CH_PLAYER_2)
-#define CA_ARG_PLAYER_3                (CA_ARG_PLAYER + CH_PLAYER_3)
-#define CA_ARG_PLAYER_4                (CA_ARG_PLAYER + CH_PLAYER_4)
-#define CA_ARG_PLAYER_ANY      (CA_ARG_PLAYER + CH_PLAYER_ANY)
-#define CA_ARG_PLAYER_TRIGGER  (CA_ARG_PLAYER + CH_PLAYER_TRIGGER)
-#define CA_ARG_NUMBER          30000
+#define CA_ARG_PLAYER_1                (CA_ARG_PLAYER + PLAYER_BITS_1)
+#define CA_ARG_PLAYER_2                (CA_ARG_PLAYER + PLAYER_BITS_2)
+#define CA_ARG_PLAYER_3                (CA_ARG_PLAYER + PLAYER_BITS_3)
+#define CA_ARG_PLAYER_4                (CA_ARG_PLAYER + PLAYER_BITS_4)
+#define CA_ARG_PLAYER_ANY      (CA_ARG_PLAYER + PLAYER_BITS_ANY)
+#define CA_ARG_PLAYER_TRIGGER  (CA_ARG_PLAYER + PLAYER_BITS_TRIGGER)
+#define CA_ARG_NUMBER          20000
 #define CA_ARG_NUMBER_HEADLINE (CA_ARG_NUMBER + 0)
 #define CA_ARG_NUMBER_MIN      (CA_ARG_NUMBER + 1)
 #define CA_ARG_NUMBER_MAX      (CA_ARG_NUMBER + 2)
 #define CA_ARG_NUMBER_NORMAL   (CA_ARG_NUMBER + 3)
 #define CA_ARG_NUMBER_RESET    (CA_ARG_NUMBER + 4)
-#define CA_ARG_NUMBER_COUNT    (CA_ARG_NUMBER + 5)
+#define CA_ARG_NUMBER_CE_SCORE (CA_ARG_NUMBER + 5)
+#define CA_ARG_NUMBER_CE_COUNT (CA_ARG_NUMBER + 6)
+#define CA_ARG_NUMBER_CE_DELAY (CA_ARG_NUMBER + 7)
+#define CA_ARG_ELEMENT         30000
+#define CA_ARG_ELEMENT_HEADLINE        (CA_ARG_ELEMENT + 0)
+#define CA_ARG_ELEMENT_TARGET  (CA_ARG_ELEMENT + 1)
+#define CA_ARG_ELEMENT_TRIGGER (CA_ARG_ELEMENT + 2)
 #define CA_ARG_UNDEFINED       30999
 
 /* values for custom move patterns (bits 0 - 3: basic move directions) */
@@ -1894,10 +1911,10 @@ struct ElementChangeInfo
 
   boolean explode;             /* explode instead of change */
 
-  boolean use_change_action;   /* execute change action after change */
-  int change_action;           /* type of change action after change */
-  int change_action_mode;      /* mode of change action after change */
-  int change_action_arg;       /* parameter of change action after change */
+  boolean use_action;          /* execute action on specified condition */
+  int action_type;             /* type of action */
+  int action_mode;             /* mode of action */
+  int action_arg;              /* parameter of action */
 
   /* ---------- internal values used at runtime when playing ---------- */
 
index 172af415b67bdf451da87957f3dd39926853aa0d..05c6f7c2d2c8640a4db2c62f74f52cdfa5ce3ad2 100644 (file)
@@ -1297,6 +1297,12 @@ void AutoPlayTape()
       continue;
     }
 
+#if 0
+    /* ACTIVATE THIS FOR LOADING/TESTING OF LEVELS ONLY */
+    printf("(only testing level)\n");
+    continue;
+#endif
+
     LoadSolutionTape(level_nr);
 #if 1
     if (tape.no_valid_file)