# Note: this file as a whole isn't supposed to be included in the program. # However, parts of it will go into various classes that use microchunks. # Various chunks of documentation: # # Pointers are a crucial part of MicroChunks, but we don't have any "pointers" # to accessors in Ruby, so I invented something called valueId. A valueId # works almost like a pointer, but it doesn't reference any specific object, # it just tells the program what attribute should be referenced in an object # supplied by some other means. This has the advantage that I don't have to # use li, xx_ei, yy_ei etc. # ValueId is stored as an array: first member (optional) is the type of # attribute the valueId is referencing (possible values are TYPE_INTEGER, # TYPE_BOOLEAN, TYPE_BITFIELD, TYPE_ELEMENT, TYPE_ELEMENT_LIST, TYPE_STRING # and TYPE_CONTENT_LIST) (if it isn't present or is nil, TYPE_INTEGER is # assumed). Second member is name of the referenced attribute (in form of a # symbol), and third (optional) member is an index in it (valueIds can point # even inside arrays and hashes). For example, pointer # '&li.score[SC_TIME_BONUS]' could be written as valueId '[TYPE_INTEGER, # :score, SC_TIME_BONUS]'. # When you use a non-array value (e.g. nil) where valueId is expected, reading # from the valueId results in the value and writing to the valueId does # nothing. That means that '&xx_string_length_unused' can be written as 'nil', # and '&xx_num_contents' can be written as '1'. # Note: the type of valueId is only used when writing to it. For example, # there's no guarantee that '[TYPE_INTEGER, ...]' really returns an integer. # # # Because of big differencies between C and Ruby, the LevelFileConfigInfo # structure was rapidly changed: # 1. I call LevelFileConfigInfo instances 'rules' and arrays of rules # 'rulesets'. I consider it more fitting (and shorter to type:). The # "structure" (actually, standardized array layout, see below) itself is # still referred to as LevelFileConfigInfo. # 2. LevelFileConfigInfo members are now in camelCase instead of lower_case. # confType was renamed to confId. value was renamed to propertyId. (Note: # Names of fields probably don't matter much in ruleset definitions, because # they're used only in functions that work with rules.) # 3. Instead of pointers, I use valueIds. (Ruby does't know pointers to # accesors - methods - in Ruby.) ValueIds can be used in propertyId and # defaultValue fields. Nil is a valid valueId, so we don't need # xx_string_length_unused and such stuff anymore. # (TODO: point to valueId documentation when it will be on its right place) # 4. valueIds can store type of attributes they point to. dataType became # a part of propertyId. TYPE_INTEGER is the default, but you should write # it anyway. If defaultValue is a valueId, you don't have to specify the # type, because defaultValue is never written to. (Type of valueId is only # used when writing to it to cast the value.) # 5. Arrays in Ruby have variable length, and numEntities stops having sense. # numEntities was removed and length of the array/string itself is used. # 5. LevelFileConfigInfo isn't a structure anymore, rules are just simple # arrays. You can create a new rule by using normal [...] literals. (That's # because LevelFileConfigInfo doesn't have methods, so I don't think it it # would be a good class, and I consider LevelFileConfigInfo.new() - or # AnyIdentifier.new(), for that matter - too long to type before each rule # definition, so a Struct also was't a good idea.) # 6. Nil is used instead of -1. # 7. Because I use valueIds (which don't point to an object, only to an # accessor in it), valueCopy isn't needed anymore and was removed. # 8. defaultString and defaultValue do the same (with one exception, see # below), they just have different types. In C such thing was needed, but # Ruby is a weakly-typed language, so defaultString was removed and # defaultValue is used instead of it. (The exception is that defaultString # could point to a string that wasn't constant, namely xx_default_description. # To support xx_default_description, you can use a valueId in defaultValue # instead of a fixed value. Both '[:defaultDescription]', '2' and '""' are # valid values.) # 9. Because Ruby doesn't have the concept of "macros", CONF_VALUE_(x)_BIT is # now a synonym to CONF_MASK_(x/8)_BYTE[S], so CONF_VALUE_8_BIT(1) becomes # CONF_VALUE_8_BIT|1. # 10. I decided to change order of fields in LevelFileConfigInfo, because the # old one isn't very good IMHO: for example, 'element' is the first field, # but only ruleset ELEM uses it, so every rule outside it starts with 'nil'. # The new order is: propertyId, defaultValue, confId, element, saveType, # maxNumEntities, defaultNumEntities. Only propertyId and confId have to be # non-nil. # # TODO merge this with the valueId documentation above. # A note about value IDs: the second parameter (index) is just a shortcut for array/hash elements. # obj.mcGetValue([:someProperty,1]) = obj.mcGetValue([:someProperty])[1] # # LevelFileConfigInfo definitions should be formatted like this: # [ # a comment about the property (optional) # propertyId, defaultValue, # confId, element, saveType, # maxNumEntities, defaultNumEntities ], # For example: # [ # initial direction of the wind # [TYPE_BITFIELD,:wind_direction_initial], MV_NONE, # CONF_VALUE_8_BIT|4 ], # Another example: # [ [TYPE_INTEGER,:score,SC_SPACESHIP], 10, # CONF_VALUE_16_BIT|1, EL_SPACESHIP ], # An example with multibyte data: # [ [TYPE_ELEMENT_LIST,:android_clone_element], EL_EMPTY, # CONF_VALUE_BYTES|1, EL_EMC_ANDROID, nil, # MAX_ANDROID_ELEMENTS, 1 ], # # # We store variables of TYPE_STRING as regular Ruby string, not as arrays of # characters. Variables of TYPE_STRING should use confId=CONF_MASK_BYTES|x. # If loaded string is longer than maxNumEntities, it gets shortened. # (It may not work if maxNumEntities is nil, but that shouldn't cause trouble, # because it is non-nil everywhere in original code anyway.) # # TODO: in the original, SAVE_CONF_WHEN_CHANGED was -1. We changed all -1s to # nils. Either define SAVE_CONF_WHEN_CHANGED to nil, or allow both values. (But # defining it to nil is probably preferred.) # TODO: IDs in classes probably were changed to camelCase in the meantime. If # they did, correct symbols in rulesets. # TODO: accept nil as a valid value for defaultNumEntities (keep in mind that # it was -1 in original code) # Note: maybe this isn't needed, as it's nil only when dataType=TYPE_STRING. # Note: defaultNumEntities is only used when numEntities is set to # defaultNumEntities in MicroChunkLoader#setToDefaults, so this will # probably be connected to refactoring of numEntities. # Note: because of the above, the only danger is when defaultNumEntities is # nil and numEntities is non-nil (in that case numEntities, which normally # is Numeric, is set to nil), but that currently doesn't happen in any rule. # TODO: probably nil is used on some places where -1 would be better # defaultValue - maybe -1? not very likely, but check it (TODO) # element - EL_UNDEFINED # saveType - SAVE_CONF_WHEN_CHANGED, see above (but I like nil more) # defaultNumEntities - see the TODO directly above this one # TODO maxNumEntities probably don't work. #-## xx_default_description = [:defaultDescription] #-## xx_num_contents = 1 #-## xx_current_change_page = [:currentChangePage] # TODO currently this is incorrect, fix it #-## xx_default_string_empty = "" #-## xx_string_length_unused = nil #-## xx_event_bits[n] = [TYPE_BITFIELD,:eventBits,n] # TODO make this file use tabs instead of spaces (when it will be safe) $ruleset_INFO = [ # ---------- values not related to single elements ----------------------- [ [TYPE_INTEGER,:game_engine_type], GAME_ENGINE_TYPE_RND, CONF_VALUE_8_BIT|1, nil, SAVE_CONF_ALWAYS ], [ [TYPE_INTEGER,:fieldx], STD_LEV_FIELDX, CONF_VALUE_16_BIT|1, nil, SAVE_CONF_ALWAYS ], [ [TYPE_INTEGER,:fieldy], STD_LEV_FIELDY, CONF_VALUE_16_BIT|2, nil, SAVE_CONF_ALWAYS ], [ # available time (seconds) [TYPE_INTEGER,:time], 100, CONF_VALUE_16_BIT|3, nil, SAVE_CONF_ALWAYS ], [ [TYPE_INTEGER,:gems_needed], 0, CONF_VALUE_16_BIT|4, nil, SAVE_CONF_ALWAYS ], [ # count steps instead of seconds for level [TYPE_BOOLEAN,:use_step_counter], false, CONF_VALUE_8_BIT|2 ], [ [TYPE_BITFIELD,:wind_direction_initial], MV_NONE, CONF_VALUE_8_BIT|4 ], [ # EM style "gems slip from wall" behaviour [TYPE_BOOLEAN,:em_slippery_gems], false, CONF_VALUE_8_BIT|5 ], [ # use custom properties from template file [TYPE_BOOLEAN,:use_custom_template], false, CONF_VALUE_8_BIT|6 ], [ # bitfield to store property for elements [TYPE_BITFIELD,:can_move_into_acid_bits], (1 << 32)-1 # default: everything can, CONF_VALUE_32_BIT|1 ], [ # bitfield to store property for elements [TYPE_BITFIELD,:dont_collide_with_bits], (1 << 32)-1 # default: always deadly, CONF_VALUE_8_BIT|7 ], [ [TYPE_INTEGER,:score,SC_TIME_BONUS], 1, CONF_VALUE_16_BIT|5 ], ] $ruleset_ELEM = [ # (these values are the same for each player) [ # player blocks previous field while moving [TYPE_BOOLEAN,:block_last_field], false # default case for EM levels, CONF_VALUE_8_BIT|1, EL_PLAYER_1 ], [ # player blocks previous field while moving [TYPE_BOOLEAN,:sp_block_last_field], true # default case for SP levels, CONF_VALUE_8_BIT|2, EL_PLAYER_1 ], [ # no visual delay when relocating player [TYPE_BOOLEAN,:instant_relocation], false, CONF_VALUE_8_BIT|3, EL_PLAYER_1 ], [ # player can pass to empty or walkable tile [TYPE_BOOLEAN,:can_pass_to_walkable], false, CONF_VALUE_8_BIT|4, EL_PLAYER_1 ], [ # snapping blocks field to show animation [TYPE_BOOLEAN,:block_snap_field], true, CONF_VALUE_8_BIT|5, EL_PLAYER_1 ], [ # repeated snapping without releasing key [TYPE_BOOLEAN,:continuous_snapping], true, CONF_VALUE_8_BIT|6, EL_PLAYER_1 ], # (these values are different for each player) [ # initial player speed [TYPE_INTEGER,:initial_player_stepsize,0], STEPSIZE_NORMAL, CONF_VALUE_8_BIT|7, EL_PLAYER_1 ], [ [TYPE_BOOLEAN,:initial_player_gravity,0], false, CONF_VALUE_8_BIT|8, EL_PLAYER_1 ], [ [TYPE_BOOLEAN,:use_start_element,0], false, CONF_VALUE_8_BIT|9, EL_PLAYER_1 ], [ [TYPE_ELEMENT,:start_element,0], EL_PLAYER_1, CONF_VALUE_16_BIT|1, EL_PLAYER_1 ], [ [TYPE_BOOLEAN,:use_artwork_element,0], false, CONF_VALUE_8_BIT|10, EL_PLAYER_1 ], [ [TYPE_ELEMENT,:artwork_element,0], EL_PLAYER_1, CONF_VALUE_16_BIT|2, EL_PLAYER_1 ], [ [TYPE_BOOLEAN,:use_explosion_element,0], false, CONF_VALUE_8_BIT|11, EL_PLAYER_1 ], [ [TYPE_ELEMENT,:explosion_element,0], EL_PLAYER_1, CONF_VALUE_16_BIT|3, EL_PLAYER_1 ], [ [TYPE_INTEGER,:initial_player_stepsize,1], STEPSIZE_NORMAL, CONF_VALUE_8_BIT|7, EL_PLAYER_2 ], [ [TYPE_BOOLEAN,:initial_player_gravity,1], false, CONF_VALUE_8_BIT|8, EL_PLAYER_2 ], [ [TYPE_BOOLEAN,:use_start_element,1], false, CONF_VALUE_8_BIT|9, EL_PLAYER_2 ], [ [TYPE_ELEMENT,:start_element,1], EL_PLAYER_2, CONF_VALUE_16_BIT|1, EL_PLAYER_2 ], [ [TYPE_BOOLEAN,:use_artwork_element,1], false, CONF_VALUE_8_BIT|10, EL_PLAYER_2 ], [ [TYPE_ELEMENT,:artwork_element,1], EL_PLAYER_2, CONF_VALUE_16_BIT|2, EL_PLAYER_2 ], [ [TYPE_BOOLEAN,:use_explosion_element,1], false, CONF_VALUE_8_BIT|11, EL_PLAYER_2 ], [ [TYPE_ELEMENT,:explosion_element,1], EL_PLAYER_2, CONF_VALUE_16_BIT|3, EL_PLAYER_2 ], [ [TYPE_INTEGER,:initial_player_stepsize,2], STEPSIZE_NORMAL, CONF_VALUE_8_BIT|7, EL_PLAYER_3 ], [ [TYPE_BOOLEAN,:initial_player_gravity,2], false, CONF_VALUE_8_BIT|8, EL_PLAYER_3 ], [ [TYPE_BOOLEAN,:use_start_element,2], false, CONF_VALUE_8_BIT|9, EL_PLAYER_3 ], [ [TYPE_ELEMENT,:start_element,2], EL_PLAYER_3, CONF_VALUE_16_BIT|1, EL_PLAYER_3 ], [ [TYPE_BOOLEAN,:use_artwork_element,2], false, CONF_VALUE_8_BIT|10, EL_PLAYER_3 ], [ [TYPE_ELEMENT,:artwork_element,2], EL_PLAYER_3, CONF_VALUE_16_BIT|2, EL_PLAYER_3 ], [ [TYPE_BOOLEAN,:use_explosion_element,2], false, CONF_VALUE_8_BIT|11, EL_PLAYER_3 ], [ [TYPE_ELEMENT,:explosion_element,2], EL_PLAYER_3, CONF_VALUE_16_BIT|3, EL_PLAYER_3 ], [ [TYPE_INTEGER,:initial_player_stepsize,3], STEPSIZE_NORMAL, CONF_VALUE_8_BIT|7, EL_PLAYER_4 ], [ [TYPE_BOOLEAN,:initial_player_gravity,3], false, CONF_VALUE_8_BIT|8, EL_PLAYER_4 ], [ [TYPE_BOOLEAN,:use_start_element,3], false, CONF_VALUE_8_BIT|9, EL_PLAYER_4 ], [ [TYPE_ELEMENT,:start_element,3], EL_PLAYER_4, CONF_VALUE_16_BIT|1, EL_PLAYER_4 ], [ [TYPE_BOOLEAN,:use_artwork_element,3], false, CONF_VALUE_8_BIT|10, EL_PLAYER_4 ], [ [TYPE_ELEMENT,:artwork_element,3], EL_PLAYER_4, CONF_VALUE_16_BIT|2, EL_PLAYER_4 ], [ [TYPE_BOOLEAN,:use_explosion_element,3], false, CONF_VALUE_8_BIT|11, EL_PLAYER_4 ], [ [TYPE_ELEMENT,:explosion_element,3], EL_PLAYER_4, CONF_VALUE_16_BIT|3, EL_PLAYER_4 ], [ [TYPE_INTEGER,:score,SC_EMERALD], 10, CONF_VALUE_16_BIT|1, EL_EMERALD ], [ [TYPE_INTEGER,:score,SC_DIAMOND], 10, CONF_VALUE_16_BIT|1, EL_DIAMOND ], [ [TYPE_INTEGER,:score,SC_BUG], 10, CONF_VALUE_16_BIT|1, EL_BUG ], [ [TYPE_INTEGER,:score,SC_SPACESHIP], 10, CONF_VALUE_16_BIT|1, EL_SPACESHIP ], [ [TYPE_INTEGER,:score,SC_PACMAN], 10, CONF_VALUE_16_BIT|1, EL_PACMAN ], [ [TYPE_INTEGER,:score,SC_NUT], 10, CONF_VALUE_16_BIT|1, EL_NUT ], [ [TYPE_INTEGER,:score,SC_DYNAMITE], 10, CONF_VALUE_16_BIT|1, EL_DYNAMITE ], [ [TYPE_INTEGER,:score,SC_KEY], 10, CONF_VALUE_16_BIT|1, EL_KEY_1 ], [ [TYPE_INTEGER,:score,SC_PEARL], 10, CONF_VALUE_16_BIT|1, EL_PEARL ], [ [TYPE_INTEGER,:score,SC_CRYSTAL], 10, CONF_VALUE_16_BIT|1, EL_CRYSTAL ], [ [TYPE_ELEMENT,:amoeba_content], EL_DIAMOND, CONF_VALUE_16_BIT|1, EL_BD_AMOEBA ], [ [TYPE_INTEGER,:amoeba_speed], 10, CONF_VALUE_16_BIT|2, EL_BD_AMOEBA ], [ # amoeba can grow into anything diggable [TYPE_BOOLEAN,:grow_into_diggable], true, CONF_VALUE_8_BIT|1, EL_BD_AMOEBA ], [ [TYPE_CONTENT_LIST,:yamyam_content], EL_ROCK, CONF_VALUE_BYTES|1, EL_YAMYAM, nil, MAX_ELEMENT_CONTENTS, 4 ], [ [TYPE_INTEGER,:score,SC_YAMYAM], 10, CONF_VALUE_16_BIT|1, EL_YAMYAM ], [ [TYPE_INTEGER,:score,SC_ROBOT], 10, CONF_VALUE_16_BIT|1, EL_ROBOT ], [ [TYPE_INTEGER,:slurp_score], 10, CONF_VALUE_16_BIT|2, EL_ROBOT ], [ [TYPE_INTEGER,:time_wheel], 10, CONF_VALUE_16_BIT|1, EL_ROBOT_WHEEL ], [ [TYPE_INTEGER,:time_magic_wall], 10, CONF_VALUE_16_BIT|1, EL_MAGIC_WALL ], [ [TYPE_INTEGER,:game_of_life,0], 2, CONF_VALUE_8_BIT|1, EL_GAME_OF_LIFE ], [ [TYPE_INTEGER,:game_of_life,1], 3, CONF_VALUE_8_BIT|2, EL_GAME_OF_LIFE ], [ [TYPE_INTEGER,:game_of_life,2], 3, CONF_VALUE_8_BIT|3, EL_GAME_OF_LIFE ], [ [TYPE_INTEGER,:game_of_life,3], 3, CONF_VALUE_8_BIT|4, EL_GAME_OF_LIFE ], [ [TYPE_INTEGER,:biomaze,0], 2, CONF_VALUE_8_BIT|1, EL_BIOMAZE ], [ [TYPE_INTEGER,:biomaze,1], 3, CONF_VALUE_8_BIT|2, EL_BIOMAZE ], [ [TYPE_INTEGER,:biomaze,2], 3, CONF_VALUE_8_BIT|3, EL_BIOMAZE ], [ [TYPE_INTEGER,:biomaze,3], 3, CONF_VALUE_8_BIT|4, EL_BIOMAZE ], [ [TYPE_INTEGER,:time_timegate], 10, CONF_VALUE_16_BIT|1, EL_TIMEGATE_SWITCH ], [ [TYPE_INTEGER,:time_light], 10, CONF_VALUE_16_BIT|1, EL_LIGHT_SWITCH_ACTIVE ], [ [TYPE_INTEGER,:shield_normal_time], 10, CONF_VALUE_16_BIT|1, EL_SHIELD_NORMAL ], [ [TYPE_INTEGER,:score,SC_SHIELD], 10, CONF_VALUE_16_BIT|2, EL_SHIELD_NORMAL ], [ [TYPE_INTEGER,:shield_deadly_time], 10, CONF_VALUE_16_BIT|1, EL_SHIELD_DEADLY ], [ [TYPE_INTEGER,:score,SC_SHIELD], 10, CONF_VALUE_16_BIT|2, EL_SHIELD_DEADLY ], [ [TYPE_INTEGER,:extra_time], 10, CONF_VALUE_16_BIT|1, EL_EXTRA_TIME ], [ [TYPE_INTEGER,:extra_time_score], 10, CONF_VALUE_16_BIT|2, EL_EXTRA_TIME ], [ [TYPE_INTEGER,:time_orb_time], 10, CONF_VALUE_16_BIT|1, EL_TIME_ORB_FULL ], [ # for compatibility with old levels [TYPE_BOOLEAN,:use_time_orb_bug], false, CONF_VALUE_8_BIT|1, EL_TIME_ORB_FULL ], [ # for compatibility with old levels [TYPE_BOOLEAN,:use_spring_bug], false, CONF_VALUE_8_BIT|1, EL_SPRING ], [ [TYPE_INTEGER,:android_move_time], 10, CONF_VALUE_16_BIT|1, EL_EMC_ANDROID ], [ [TYPE_INTEGER,:android_clone_time], 10, CONF_VALUE_16_BIT|2, EL_EMC_ANDROID ], [ [TYPE_ELEMENT_LIST,:android_clone_element], EL_EMPTY, CONF_VALUE_BYTES|1, EL_EMC_ANDROID, nil, MAX_ANDROID_ELEMENTS, 1 ], [ [TYPE_INTEGER,:lenses_score], 10, CONF_VALUE_16_BIT|1, EL_EMC_LENSES ], [ [TYPE_INTEGER,:lenses_time], 10, CONF_VALUE_16_BIT|2, EL_EMC_LENSES ], [ [TYPE_INTEGER,:magnify_score], 10, CONF_VALUE_16_BIT|1, EL_EMC_MAGNIFIER ], [ [TYPE_INTEGER,:magnify_time], 10, CONF_VALUE_16_BIT|2, EL_EMC_MAGNIFIER ], [ [TYPE_INTEGER,:ball_time], 10, CONF_VALUE_16_BIT|1, EL_EMC_MAGIC_BALL ], [ [TYPE_BOOLEAN,:ball_random], false, CONF_VALUE_8_BIT|1, EL_EMC_MAGIC_BALL ], [ [TYPE_BOOLEAN,:ball_state_initial], false, CONF_VALUE_8_BIT|2, EL_EMC_MAGIC_BALL ], [ [TYPE_CONTENT_LIST,:ball_content], EL_EMPTY, CONF_VALUE_BYTES|1, EL_EMC_MAGIC_BALL, nil, MAX_ELEMENT_CONTENTS, 4 ], # ---------- unused values ----------------------------------------------- [ [TYPE_INTEGER,:score,SC_UNKNOWN_14], 10, CONF_VALUE_16_BIT|1, EL_UNKNOWN, SAVE_CONF_NEVER ], [ [TYPE_INTEGER,:score,SC_UNKNOWN_15], 10, CONF_VALUE_16_BIT|2, EL_UNKNOWN, SAVE_CONF_NEVER ], ] $ruleset_NOTE = [ [ [TYPE_INTEGER,:xsize], MAX_ENVELOPE_XSIZE, CONF_VALUE_8_BIT|1 ], [ [TYPE_INTEGER,:ysize], MAX_ENVELOPE_YSIZE, CONF_VALUE_8_BIT|2 ], [ [TYPE_STRING,:text], "", CONF_VALUE_BYTES|1, nil, nil, MAX_ENVELOPE_TEXT_LEN ], ] $ruleset_CUSX_base = [ [ # for custom/group elements [TYPE_STRING,:description], [:defaultDescription], CONF_VALUE_BYTES|1, nil, nil, MAX_ELEMENT_NAME_LEN ], [ # element base properties [TYPE_BITFIELD,:properties,EP_BITFIELD_BASE_NR], EP_BITMASK_BASE_DEFAULT, CONF_VALUE_32_BIT|1 ], [ # use custom graphic element [TYPE_BOOLEAN,:use_gfx_element], false, CONF_VALUE_8_BIT|1 ], [ # optional custom graphic element [TYPE_ELEMENT,:gfx_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|1 ], [ # accessible from which direction [TYPE_BITFIELD,:access_direction], MV_ALL_DIRECTIONS, CONF_VALUE_8_BIT|2 ], [ # initial score value for collecting [TYPE_INTEGER,:collect_score_initial], 10, CONF_VALUE_16_BIT|2 ], [ # initial count value for collecting [TYPE_INTEGER,:collect_count_initial], 1, CONF_VALUE_16_BIT|3 ], [ # initial value for custom variable (fix) [TYPE_INTEGER,:ce_value_fixed_initial], 0, CONF_VALUE_16_BIT|4 ], [ # initial value for custom variable (rnd) [TYPE_INTEGER,:ce_value_random_initial], 0, CONF_VALUE_16_BIT|5 ], [ # use value from element before change [TYPE_BOOLEAN,:use_last_ce_value], false, CONF_VALUE_8_BIT|3 ], [ # constant delay before pushing [TYPE_INTEGER,:push_delay_fixed], 8, CONF_VALUE_16_BIT|6 ], [ # additional random delay before pushing [TYPE_INTEGER,:push_delay_random], 8, CONF_VALUE_16_BIT|7 ], [ # constant delay after dropping [TYPE_INTEGER,:drop_delay_fixed], 0, CONF_VALUE_16_BIT|8 ], [ # additional random delay after dropping [TYPE_INTEGER,:drop_delay_random], 0, CONF_VALUE_16_BIT|9 ], [ # constant delay after moving [TYPE_INTEGER,:move_delay_fixed], 0, CONF_VALUE_16_BIT|10 ], [ # additional random delay after moving [TYPE_INTEGER,:move_delay_random], 0, CONF_VALUE_16_BIT|11 ], [ # direction movable element moves to [TYPE_BITFIELD,:move_pattern], MV_ALL_DIRECTIONS, CONF_VALUE_32_BIT|3 ], [ # initial direction element moves to [TYPE_BITFIELD,:move_direction_initial], MV_START_AUTOMATIC, CONF_VALUE_8_BIT|4 ], [ # step size element moves with [TYPE_INTEGER,:move_stepsize], TILEX / 8, CONF_VALUE_8_BIT|5 ], [ # element that can be entered (and removed) [TYPE_ELEMENT,:move_enter_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|12 ], [ # element that can be left behind [TYPE_ELEMENT,:move_leave_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|13 ], [ # change (limited) or leave (unlimited) [TYPE_INTEGER,:move_leave_type], LEAVE_TYPE_UNLIMITED, CONF_VALUE_8_BIT|6 ], [ # how/where other elements slip away [TYPE_INTEGER,:slippery_type], SLIPPERY_ANY_RANDOM, CONF_VALUE_8_BIT|7 ], [ # type of explosion, like 3x3, 3+3 or 1x1 [TYPE_INTEGER,:explosion_type], EXPLODES_3X3, CONF_VALUE_8_BIT|8 ], [ # duration of explosion of this element [TYPE_INTEGER,:explosion_delay], 16, CONF_VALUE_16_BIT|14 ], [ # delay for explosion by other explosion [TYPE_INTEGER,:ignition_delay], 8, CONF_VALUE_16_BIT|15 ], [ # new elements after explosion [TYPE_CONTENT_LIST,:content], EL_EMPTY_SPACE, CONF_VALUE_BYTES|2, nil, nil, 1, 1 ], # ---------- "num_change_pages" must be the last entry ------------------- # TODO: why exactly? investigate. [ # actual number of change pages [TYPE_INTEGER,:num_change_pages], 1, CONF_VALUE_8_BIT|9, nil, SAVE_CONF_ALWAYS ], ] $ruleset_CUSX_change = [ # ---------- "current_change_page" must be the first entry --------------- [ [:currentChangePage], nil, CONF_VALUE_8_BIT|1, nil, SAVE_CONF_ALWAYS ], # ---------- (the remaining entries can be in any order) ----------------- [ # use or ignore this change info [TYPE_BOOLEAN,:can_change], false, CONF_VALUE_8_BIT|2 ], [ # change events [TYPE_BITFIELD,:eventBits,0], 0, CONF_VALUE_32_BIT|1 ], [ [TYPE_BITFIELD,:eventBits,1], 0, CONF_VALUE_32_BIT|2 ], [ # player triggering change [TYPE_BITFIELD,:trigger_player], CH_PLAYER_ANY, CONF_VALUE_8_BIT|3 ], [ # side triggering change [TYPE_BITFIELD,:trigger_side], CH_SIDE_ANY, CONF_VALUE_8_BIT|4 ], [ # page triggering change [TYPE_BITFIELD,:trigger_page], CH_PAGE_ANY, CONF_VALUE_32_BIT|3 ], [ # target element after change [TYPE_ELEMENT,:target_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|1 ], [ # added frame delay before changed (fixed) [TYPE_INTEGER,:delay_fixed], 0, CONF_VALUE_16_BIT|2 ], [ # added frame delay before changed (random) [TYPE_INTEGER,:delay_random], 0, CONF_VALUE_16_BIT|3 ], [ # either 1 (frames) or 50 (seconds; 50 fps) [TYPE_INTEGER,:delay_frames], FRAMES_PER_SECOND, CONF_VALUE_16_BIT|4 ], [ # element triggering change [TYPE_ELEMENT,:trigger_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|5 ], [ # explode instead of change [TYPE_BOOLEAN,:explode], false, CONF_VALUE_8_BIT|6 ], [ # use extended change target [TYPE_BOOLEAN,:use_target_content], false, CONF_VALUE_8_BIT|7 ], [ # only use complete target content [TYPE_BOOLEAN,:only_if_complete], false, CONF_VALUE_8_BIT|8 ], [ # use random value for replacing elements [TYPE_BOOLEAN,:use_random_replace], false, CONF_VALUE_8_BIT|9 ], [ # random value for replacing elements [TYPE_INTEGER,:random_percentage], 100, CONF_VALUE_8_BIT|10 ], [ # type of elements that can be replaced [TYPE_INTEGER,:replace_when], CP_WHEN_EMPTY, CONF_VALUE_8_BIT|11 ], [ # execute action on specified condition [TYPE_BOOLEAN,:has_action], false, CONF_VALUE_8_BIT|12 ], [ # type of action [TYPE_INTEGER,:action_type], CA_NO_ACTION, CONF_VALUE_8_BIT|13 ], [ # mode of action [TYPE_INTEGER,:action_mode], CA_MODE_UNDEFINED, CONF_VALUE_8_BIT|14 ], [ # parameter of action [TYPE_INTEGER,:action_arg], CA_ARG_UNDEFINED, CONF_VALUE_16_BIT|6 ], [ # elements for extended change target [TYPE_CONTENT_LIST,:target_content], EL_EMPTY_SPACE, CONF_VALUE_BYTES|1, nil, nil, 1, 1 ], ] $ruleset_GRPX = [ [ # for custom/group elements [TYPE_STRING,:description], [:defaultDescription], CONF_VALUE_BYTES|1, nil, nil, MAX_ELEMENT_NAME_LEN ], [ # use custom graphic element [TYPE_BOOLEAN,:use_gfx_element], false, CONF_VALUE_8_BIT|1 ], [ # optional custom graphic element [TYPE_ELEMENT,:gfx_element], EL_EMPTY_SPACE, CONF_VALUE_16_BIT|1 ], [ # how to choose element from group [TYPE_INTEGER,:choice_mode], ANIM_RANDOM, CONF_VALUE_8_BIT|2 ], [ # list of elements in this group [TYPE_ELEMENT_LIST,:element], EL_EMPTY_SPACE, CONF_VALUE_BYTES|2, nil, nil, MAX_ELEMENTS_IN_GROUP, 1 ], ] #-## level file chunk 'CONF' isn't supported