• Weekly Update – December 1, 2023

    • History Event support for nested Map Components. This allows the map generator to place multi-room content in the context of a larger group of rooms. For example, a portion of the map could contain a bandit hideout, and within that hideout, there could be a sequence of guarded rooms leading to a treasure vault.
    • Chain Map Components fixed and improved. I spent most of the week on this. Map Chains are sequences of rooms and/or corridors with no branching. They stopped working (and didn’t work that well to begin with) after the Map Component model was introduced. In addition to adapting Chains to the Map Component model, some improvements to Chains were made. The rooms in a Chain are now ordered based on their distance from the starting room of the level. This allows content to be placed in the correct order, for example a boss room will appear before a treasure room. Also, when stocking a Chain, corridors can now be ignored. This addressed a frequent issue in which the stocking specification didn’t match the Chain structure. For example, a stocking specification that populates two rooms should work in a Chain containing two rooms as well as a Chain containing two rooms with corridors in between the rooms, before the first room, or after the last room.
    • New map content: Barracks and Cave-ins. These were built using Chain Map Components. The Barracks are placed in some of the dead-ends in Bandit Hideouts. The Cave-ins span a few rooms and/or corridors.
    Barracks and cave-ins

    Next week, I’ll continue creating content for the Bandit Hideout. Also, the map generator is regularly encountering dozens of errors. I’ll fix some, if not all, of these. Errors aside, map generation needs a dose of quality control to fix issues like the one below, in which different room types are applied to the same room.

    Multiple room types applied to the same room
  • Weekly Update – November 25, 2023

    • Map/History generation and graph support for Map Component Trees. (Background: when a level is generated, a graph of the connections between rooms is created. The graph is broken down into subgraphs, Map Components, based on node connection patterns. Last week’s main achievement enabled Map Components to be broken down as well.) To support nested Map Components, I changed the Map Component collection from a list to a tree. Unsurprisingly, that broke some things. I’ve fixed 80% of what’s broken; the History Event Type editor still needs to be updated. Graph visualization was updated to reflect nested Map Components.

    The filled in rectangles are groups; darker fill shades indicate nested groups. Chains are enclosed in rectangles with dotted lines. Required nodes have a black border; the thicker borders indicate the required nodes for the level, the thinner borders indicate nodes that are required relative to the groups they’re in.

    Next week, I’ll add History Event Type editor support for nested Map Components and share some Bandit Hideout examples.

  • Weekly Update – November 17, 2023

    I remained in the map generation rabbit hole this week, but I can see the sky above and I’m climbing out. 

    • Map Subgraph Decomposition. Decomposition of the entire map graph into key components (junction nodes, chains of nodes, node groups, etc.) was added a month ago. This capability enables the level to be populated in a more logical and precise manner. A limitation of this capability was that it only did one iteration of decomposition; if one of the components was a node group, the subgraph represented by that group wasn’t decomposed. I didn’t implement subgraph decomposition because I didn’t think I would need it. I believed it would be sufficient to iterate through each node in the group when placing group-level content. For example, to place a Bandit Hideout in a node group, the map generator would determine a room type for each node and room type placement conditions would ensure that each node was set to an appropriate room type. It was a serviceable solution until I needed to control the content placed in subgroups of a node group. To support this functionality, decomposition needed to iterate until there were no more node groups to decompose. This required refactoring. Many of the graph analysis methods had to be modified to act on a node group instead of the entire map. It was another opportunity to move code from an OOP paradigm to a Data-Oriented Programming paradigm. With this functionality added, the map generator now has access to nested map components and more options for placing content.
    • Bug fixes
      • Standard object placement checks (blocking paths, adjacent to doors, etc.) not being performed by the grid layout object placer.
      • Multi-room Map Elements such as the Bandit Hideout can be placed multiple times in the same room group.

    Next week, I’ll enable the history generator and dungeon stocker to use nested map components.

  • Weekly Update – November 10, 2023

    I solved the big history generation problem I mentioned last week (the first bullet below). An uninterrupted half-day last Sunday got me across the finish line. To increase weekly game dev time I added 30 minutes of dev time to the start of each weekday (5 AM). It’s a small amount of time, but I find that I naturally work faster because of the limitation.

    • History event entity attribute combination validation. That’s a mouthful. It’s best explained with an example. A history event that builds a new Barracks room will have two entities: the Map Block (the physical space where the Barracks will be built) and the Map Element (responsible for populating the Map Block with the Barracks content). The Map Element entity has two attributes: the Map Element Type (Barracks) and a reference to the  Map Block entity. The Barracks Map Element can only be placed in Map Blocks that are larger than 6×6. Previously, the history generator randomly selected from all of the Map Blocks when determining where to place a Map Element. This caused Map Element placements to fail when the selected Map Block didn’t meet the Map Element’s placement criteria. Now, by checking that an entity’s combination of attributes is compatible, the history generator will only place Map Elements in Map Blocks where they fit.
    • Multi-room purposing and stocking. Using the recently developed component model, the map and history generators can now designate a purpose, such as a bandit hideout, for a portion of the map and stock the rooms accordingly. This is a critical feature for achieving my level design vision. In addition to populating levels in a rational manner, it bridges the gap between history and map generation. For example, there is a history event type where faction A invades faction B’s settlement. This event type couldn’t be implemented by the map generator because the faction settlements weren’t defined. Now, the map generator can determine the exact area of faction B’s settlement and place invaders from faction A there.
    • Room repurposing. Rooms can now be repurposed by the history generator. For example, an ancient shrine could later on be used for goblin barracks. When the room is stocked, first the shrine Map Element (statue, decor) is placed, then the barracks Map Element (beds, chests) is placed. Map Elements have always had this capability, but the history and map generators didn’t support it until now. Yet to be done is modifying the previous Map Element in a room when a new Map Element is placed. Although this feature still needs a lot of refinement, it already shows great potential. In testing, I’ve seen a number of room type combinations I wouldn’t have thought of on my own that create interesting situations.
    • New history event type: New Bandit Hideout. This event type uses the new multi-room purposing capability to populate a subsection of the map. The rooms composing the subsection are set to room types found in a bandit hideout (barracks, guard posts, armory, etc.).
    • Cleaned up history generation code. I did this to make it easier to reacquaint myself with the code. I did some refactoring (combining and removing methods, simplifying branching, renaming), documented methods, and deleted commented-out code. 
    • Bug fixes.

    Next week, I’ll refine the new features added this week and update history event types to use the new features.

  • Weekly Update – November 3, 2023

    It was another week of close to zero free time. A major health issue in my family has necessitated changes to my daily routine. The small pockets of time I have been able to find have been unproductive because I’m stuck on a complex problem involving history and map generation. At a high level, the problem is that the procedurally generated history has become more concrete and more coupled to map generation within a framework designed to produce abstract, map implementation-independent histories. I’m going in circles trying to find a solution that avoids major rework. The fact that I haven’t found a solution yet indicates that I’m either too deep in the weeds or the problem’s source is more fundamental and major rework is unavoidable. I’ll keep at it next week.