Room bug fixes/enhancements
This update fixes a number of bugs and adds significant functionality to room generation (including vaults/Static maps), makes level generation more reliable (some tunnelling bug fixes, fewer recreations required), fixes several bugs with entity generation, and provides improved support for content creation (levels and maps).
RoomsLoader changes:
Added support for new fields in room and Static map definitions (both .lua and .tmx) files:
unique: a tag (true is converted to the room name) marking the room as unique, two rooms with the same unique tag will not be generated on the same map
border: the size (in grids, default 0) of a border zone around the room in which no other rooms are allowed to be placed
no_tunnels: set true to prevent automatically connecting tunnels to the room (depending on the map generator, Roomer, Forest)
roomcheck: if defined, a function(room, zone, level, map) checked to determine if the room should be added to the map (return true to add)
onplace: a function(room, zone, level, map, placement_data) called after the room has been added to the map (see RoomsLoader:roomPlace)
map_data: a table to merge into the room definition
If a room cannot be placed at the coordinates returned by a prefer_location function, subsequent attempts to find a spot will be clustered around the preferred coordinates.
Added lists of rooms added (room_map.rooms) and failed to add (room_map.rooms_failed) to the room_map during generation to make this information more readily available to map generators. This is handled in RoomsLoader:roomPlace (and supported in engine.Generator and engine.Map) rather than the various map generators.
Added a new function RoomsLoader:roomCheck(room, zone, level, map) that determines if a room should be generated. Checks room.unique and room.roomcheck fields by default, but map generators can overload it to filter the rooms generated.
Updated roomPlace/roomFrom to mark edge walls ('#') of standard rooms so that they will be tunnelled around. (This was a significant source of map connectivity failures.)
Added a failsafe to convert undefined grids into default grids (resolves '.' or 'floor' then a basic grid as needed). (Rather than leaving the corresponding map grid undefined, with a warning in the log file.)
Setting Zone._retain_level_room_map will cause the room_map to not be deleted until engine.Zone:runPostGeneration, keeping it available to various generators longer. Some map generators (Forest, Roomer, Town) will make extra attempts to generate random rooms (randomly selecting new ones each time), more reliably generating the specified number of rooms.
Tunneling Improvements:
Special grids will be tunnelled over (terrain left unchanged) if can_open is set. (This allows several ToME vaults with central connection points to be properly connected.) Special grids next to the end point will be accepted as the end point of the tunnel. Room grids with can_open == false are explicitly rejected.
The Forest map generator will tunnel between rooms to ensure connectivity.
Static map changes:
For Static maps, assigning a table to map_data or calling mapData({params}) can be used to define additional fields in map root.
Updated Static:resolve to check self.data for defined grids to use to more closely match the way engine.Generator:resolve works. (i.e. defineTile('X', data.wall or "WALL") will try to use generator.tiles['wall'] and then generator.grids_list.WALL if they are defined.)
Improved support for specialLists for actors, traps, and objects, allowing them to be merged with the zone entity lists as needed. If a static map has specified alternate entity lists (through the specialList loader function), related room_map[x][y].add_entities tables will get a copy of the alternate entity lists. Zone:newLevel will then use the alternate lists when adding the entities to the level. In ToME, this allows escorts and specific equipment to be generated properly when placing vaults (without altering the entity lists for the zone in which they are placed.), fixing an existing bug causing additional entities to fail to generate if they are not in the zone entity list(s), even if they are on the Static map special list(s).
Updated the Static map generator to gracefully handle failure of a subgenerator.
Fixed errors in coordinate translation in Static:loadMap that were calculating connection points for rooms incorrectly.
Fixed a bug that was causing vaults (loaded as static maps) to incorrectly mark uniques as generated even if they couldn't be placed during map generation. Added a check for a room:removed(x, y) in RoomsLoader:roomAlloc.
engine.Zone:newLevel will keep track of the number of attempts (Zone._level_generation_count) it has used to generate a new level (storing the count in level._level_generation_count) and will terminate generation when the count reaches Zone._max_level_generation_count (default 50, can be overloaded).
Spcific room/vault updates (ToME):
Corrected the starting coordinates for many vaults so that tunnels will connect to them properly. This was causing a number of vaults to fail to generate or to trigger level recreation due to lack of connectivity. (Setting no_tunnels will exclude a room from the connectivity list in Roomer, etc. allowing for unconnected rooms that must be discovered by the player.)
Added support for automatic lesser vaults (like automatic greater vaults).
The room generators lesser_vault and greater_vault will try up to 5 times to create a vault when called, and each will also search both the vaults and opposite vaults/auto directories to find vault definitions. All vaults get a border of 1 by default, which prevents them from occasionally being placed with a blocked entrance. Zones can define the fields lesser_vaults_list_add and greater_vaults_list_add tables in generator.map to add extra vaults to the corresponding lists rather than replacing the lists completely.
Moved a number of vaults to the auto/lesser directory: bandit-fortress, circle, loot-vault, mage-hideout, rat-nest, skeleton-mage-cabal, snow-giant-camp, thief-hideout, xorn-trap. Moved some vaults to the auto/greater directory: horror-chamber, orc-armoury, orc-necromancer.
Added minimum level limits to vaults that generate specific (level-restricted) npcs. This limits generation of high level vaults in low level zones (using the rule: resolvers.current_level >= 5 less than highest minimum level of the npcs guaranteed to be generated).
Updated the definitions of several vaults as needed to load appropriate entity lists so that escorts will be generated properly and added restrictions (roomcheck) based on the zone entity lists loaded so that vaults with specific summoning npcs (ghouls, for example) will not be generated if the summons are not available. (Changes to Static, above, do not correct this since they intentionally do not affect the zone entity lists.)
Updated the VaultLevel map generator to handle room generation errors (multiple tries, always places an up exit), use the defined vault connection point, to provide for more natural room placement (map center with a tunnel to the room). The sub-vault event limits stair scumming (the portal stairs collapse after a few uses), is flagged with the applied game difficulty, and inherits the parent zone's no_worldport value.
Made the items-vault room for the I.D. unique so that only one will be spawned on the map.
Added a new greater vault ("portal-vault") that uses most of the new functionality.
Pits are marked special to prevent player/stairs from spawning inside them.
mod.class.Game:changeLevelReal will halt new level generation after zone._level_generation_count attempts and give the player options to continue trying, go back to last good level, report the error (stub, just outputs zone/level info to the log file currently), or debug it (if in developer mode).
Fixed a bug that was causing levers (grids) functions to receive the wrong entity argument.
Added documentation to most functions affected by these code changes.