PROCEDURAL GENERATION OF METROIDVANIA STYLE LEVELS by Trevor Stalnaker 2020 ©c2020 Trevor Stalnaker All Rights Reserved TABLE OF CONTENTS LIST OF TABLES ................................ vi LIST OF FIGURES ............................... vii ABSTRACT ................................... ix Chapter 1 INTRODUCTION .............................. 1 1.1 Motivation ................................. 2 2 BACKGROUND ............................... 3 2.1 Metroidvanias ............................... 3 2.2 Gating Taxonomy ............................. 3 2.3 Graphs ................................... 4 2.4 Pygame .................................. 5 2.5 Physics Engines .............................. 5 2.6 In-House Graphics Package ........................ 5 2.7 Other Used Files ............................. 6 2.8 Related Works ............................... 6 3 APPROACH ................................. 10 3.1 Overview .................................. 10 3.2 Model ................................... 11 3.2.1 Modeling the Map ........................ 11 3.2.2 Modeling the Key Orderings ................... 12 3.3 Implementation .............................. 12 3.3.1 Representing Keys and Gates .................. 12 3.3.2 Preprocessing ........................... 3.3.2.1 Generating an Ordering for the Keys ......... 13 3.3.2.2 Creating Directional Mappings for Gate Types ... 14 3.3.3 Generating the Underlying Map ................. 16 3.3.3.1 Creating the Lattice .................. 16 3.3.3.2 Verifying that the Map Con.guration is Winnable .. 20 3.3.3.3 Placing the Keys .................... 21 3.3.4 Rendering the Map into a Playable Form ............ 23 3.3.4.1 Keys ........................... 25 3.3.4.2 Gates .......................... 26 3.3.4.3 Barriers, Walls, and Platforms ............. 27 3.3.4.4 The Player ....................... 29 3.3.4.5 Creating the Physical Representation of the Map .. 33 3.3.5 Mini Map ............................. 39 3.3.6 Drawing, Updating, and Event Handling ............ 40 3.3.7 Other Visualizations ....................... 41 3.3.8 Summary of Implementation ................... 42 3.4 Saving and Loading Maps and Templates ................ 43 3.4.1 Pickling and Loading ....................... 43 3.4.2 The User Interface ........................ 44 3.4.3 Supporting Past Versions ..................... 45 3.5 Playing the Generated Level ....................... 45 3.5.1 Controls .............................. 45 3.5.2 Collecting Keys and Passing Through Gates .......... 46 3.6 Plotting the Underlying Graphing of Maps ............... 47 4 ANALYSIS .................................. 48 4.1 The Ability to Win Generated Levels .................. 48 4.2 Enforcing Gate Ordering ......................... 48 4.3 Playability of Generated Maps ...................... 49 4.4 Level Generation Times ......................... 49 4.5 Example Map Generations ........................ 5 CONCLUSION ................................ 58 6 FUTURE WORK .............................. 59 6.1 Improved Generation of Maps ...................... 59 6.1.1 More Intelligent Generation ................... 59 6.1.2 Improved Dropout Rates ..................... 60 6.2 Adding Other Gating Types ....................... 60 6.3 Increase Non-Linearity of Key Collection ................ 61 6.4 Improve the Mini Map .......................... 61 6.5 Improve the Graphics of the Game ................... 62 6.6 Increase Variability ............................ 62 6.7 Human Level Designer Access ...................... 63 6.8 User Interface for Designers ....................... 63 6.9 User Studies ................................ 63 BIBLIOGRAPHY ................................ 65 LIST OF TABLES 3.1 Formulae Determining Location of Nodes in the Lattice ....... 19 4.1 Generation Data by Level Size and Key Count ............ 51 LIST OF FIGURES 2.1 Representation of the Gating Taxonomy ............... 4 3.1 Flowchart of Algorithm ........................ 11 3.2 Example Key Orderings ........................ 14 3.3 Example User Input to Gate Ordering ................ 15 3.4 Abstraction of a Map Lattice ..................... 17 3.5 Possible Positions for Node i in the Grid ............... 18 3.6 Finding the Current Explorable Region ................ 22 3.7 Zone for Proper Key Placement .................... 24 3.8 An Example of an Unwinnable Pit in the Map ............ 24 3.9 Anatomy of Gate Types ........................ 30 3.10 Example of Corner Generated without Overlap ........... 31 3.11 Anatomy of a Platform ......................... 31 3.12 Player’s Finite State Machine ..................... 32 3.13 Horizontal Movement Physics ..................... 34 3.14 Vertical Movement Physics ....................... 35 3.15 Plotting Interior Walls on the Map .................. 37 3.16 Plotting Interior Walls on the Map .................. 38 3.17 The Save Interface ........................... 45 4.1 Undirected 4x4 Level Demo View and Underlying Graph ...... 52 4.2 Undirected 4x4 Level Demo View and Underlying Graph ...... 53 4.3 Undirected 6x6 Level Demo View and Underlying Graph ...... 53 4.4 Early Rendering of a 4x6 Game Map and Associated Level Demo View ................................... 54 4.5 Directed 6x6 Level Demo ....................... 55 4.6 Rendered Game View and Underlying Graph ............ 56 4.7 Generated Game View, Level View, and Underlying Graph (5x5) . 56 4.8 Generated Game View, Level View, and Underlying Graph (8x8) . 57 4.9 Generated Game View, Level View, and Underlying Graph (8x12) . 57 ABSTRACT Video game maps can become dull with repeated play-throughs and hand­crafting a variety of maps can be a tedious and time consuming process. This is especially true for games of the Metroidvania genre, games which focus on exploration. If there was a way to adequately automate the creation of levels, then in theory, the games would have enhanced replay value. Previous researchers have used arti.cial in­telligence and genetic programming techniques to engineer new mappings. But, is it possible to procedurally generate levels using graph theory and without using training examples or simply placing pre-built assets? In this paper we propose a system to model Metroidvania maps as directional graph structures. The system uses an algo­rithm that crafts graphs meeting all of the constraints necessary for level generation. These generated graphs are veri.ed as winnable with the keys assigned to appropriate nodes. Once the graph has been created and validated it is rendered into a 2-D level using pygame. During the rendering process, the game demo constructs the walls and platforms essential to the game. We were able to procedurally generate Metroidvania levels of varying sizes and gating techniques using this sequence of steps. Chapter 1 INTRODUCTION Metroidvanias, named after the classic franchises Metroid and Castlevania, have been a staple of gaming since the late eighties and early nineties [6]. A game in the Metroidvania genre typically provides the player with a non-linear gaming experience. Access to parts of the world are “gated,” meaning that access to these areas is not immediately available. Various di.erent gating technologies are collected by the player throughout the course of their play, each allowing them to access and explore more and more new regions of the map. The order in which these gating technologies can be collected by the player is called the gating order or the gate ordering. As a game designer, creating worlds such as these can be a tedious and time consuming process. If the process could be automated, then the number of levels these games contain could be near in.nite. A game could provide players with new levels on each play through, preventing the game from becoming stale. Gutierrez-Rodriguez et al. make use of ar­ti.cial intelligence and genetic algorithms to create novel levels [1, 9], however their work has not been veri.ed through user studies. In this paper, we discuss how we used principles of procedural generation to create new maps. Procedural generation is not a new innovation in the .eld of gaming. Hendrikx et al. describe the various facets that procedurally designed content can fall into, including textures, sounds, vegeta­tion, maps, environments, puzzles, stories, and leaderboards [3]. None of the previous research has applied these techniques to the creation of gated-style maps required of Metroidvania games. So, while the ideas and principles of procedural generation are nothing new, applying them to create Metroidvania levels is a novel approach. Contributions made in this thesis: 1. created a gating type taxonomy for Metroidvanias based upon Castlevania: Sym­phony of the Night, 2. devised a system to represent Metroidvania gating orders as directed acyclic graphs, 3. designed and implemented an algorithm for procedurally generating Metroidvania levels as directed planar graphs, 4. created two systems to render the underlying level graph into a playable game representation, 5. evaluated the e.ectiveness of and the time it takes to procedurally generate Metroidvania-style levels, 6. provided a github repository with the code base necessary for designers to gen­erate their own Metroidvania-style levels. 1.1 Motivation The creation of levels and maps for video games can be a time consuming and arduous process. This is especially true for games in the Metroidvania genre. These games are known for their large maps and exploration based game play. As map sizes increase, it can also be increasingly di.cult to verify that there are no ways for the player to cheat the gating order. Therefore, if a machine were able to procedurally generate maps, it could dramatically decrease the time and e.ort needed to create and design such a game. Even if the generated maps were edited and improved by a human designer, it is easier to improve on something functional, than to start completely from scratch. For this reason, we developed a program that is capable of Metroidvania-style level generation. As discussed in Section 3.3, the designer has access to many parameters which they can use to tailor the map design to their speci.c needs. Additionally, a map checker was also created as part of the generation process, which could easily be repurposed to verify that purely human designed maps meet the exploration criteria set by the designer. Chapter 2 BACKGROUND 2.1 Metroidvanias Metroidvanias are a genre of video game with a focus on exploration. The genre is named after the two .agships of the genre: Metroid and Castlevania [6]. Typically these games incorporate a platforming element and various di.erent gating techniques. Gating, as a term in Metroidvania, includes but is not limited to literal gates and keys. Sometimes a “gate” can be a ledge too high to reach and the key a grappling hook. In order to progress through the map, the player must collect a series of keys or movement technologies, each of which will allow for further exploration. The player continues to explore and navigate through the maze-like world until they reach the .nal goal (usually a boss enemy). Gutierrez Rodriguez et al. aptly summarize Metroidvanias as games that: “Feature a large interconnected map through which the player can move, having to obtain objects, weapons or abilities to unlock the di.erent locked areas. The map is composed of di.erent areas, each of which is in turn composed of di.erent rooms (including secret rooms). Rooms are where the di.erent enemies, objects, new abilities, are placed [9].” 2.2 Gating Taxonomy The popular Metroidvania Castlevania: Symphony of the Night was chosen for analysis based on its standing as one of the two video games that founded the genre [4]. From this analysis we devised a gating taxonomy. This hierarchy groups gates into cat­egories, thus making conceptualizing them for procedural generation easier. Categories include movement tech, doors, enemies, transport, transformations, and puzzles. While other categories undoubtedly exist, these seem to make up the vast majority. Addition­ally, some gating techniques could reasonably fall under multiple categories, making some sort of a hybrid gate. Double jump with a keyed gate or a puzzle using enemies would be good examples of this. For simplicity, these combinations are not included in the taxonomy. See Figure 2.1 for the full taxonomy diagram. In this project, we focus on the movement, doors, and transformation categories, however the other categories could also be implemented given adequate time and planning. 2.3 Graphs Graphs are data structures made up of nodes and edges. Each node can repre­sent a data point and each edge a connection between points. Nodes can be numbered or named and edges can have weights. Graphs also come in a variety of forms. In undirected graphs, the edges have no direction. This means that if there is a connec­tion between node A and node B, then there is also a connection between B and A. In a directed graph, this isn’t necessarily the case. Each edge in a directed graph has a direction as well as a weight. Thus A could lead to B, but B might not lead back to A. Planar graphs are also key to the implementation of this project. A planar graph is a graph that can be visualized in a 2-dimensional plane without any of its edges crossing. Finally, directed acyclic graphs (DAGS), are directed graphs that contain no cycles. In a DAG, sources are nodes that have no incoming edges and sinks nodes that have no outgoing edges. This means they are analogous to the root node and leaf nodes of a tree respectively. To model the graphs in this project, we make use of the networkx Python package [2]. 2.4 Pygame Pygame is a Python package used primarily for video game development. The interactive game demos of this project are built using pygame. In a nutshell, pygame allows a programmer to draw a game to the screen, handle game events, and update the game accordingly [8]. 2.5 Physics Engines Physics engines establish the rules for how objects in a virtual world behave. Forces such as gravity, friction, and velocity are all simulated by the physics engine. The physics for this project are de.ned within the avatar class. Normally a physics engine would be more generalized, allowing for all objects to be a.ected by the forces de.ned. However, since the player is the only object in the demo that needs to be a.ected by gravity and the like, the physics engine is built into that class. More information on how this is accomplished can be found in Section 3.3.4.4. 2.6 In-House Graphics Package The user interfaces for saving and loading maps were built using a previously created graphics package. Justin Pusztay, my partner at the time, and I created this graphics package while working on our game Squirrel Simulator [10]. This package builds upon pygame’s functionality, allowing game designers to more easily create UI elements. Buttons, scroll boxes, text .elds, and more are de.ned in the package. Minor modi.cations were required to some of the .les for this project, further improving their functionality. 2.7 Other Used Files In addition to the graphics package, a number of other .les used in this project originated from Squirrel Simulator [10]. The .rst of these is Drawable. This class provides a framework that streamlines the process of interacting with pygame objects. It provides methods for drawing sprites, handling events, updating sprites, and much much more. Another example is the FSM class, which is used to model .nite statement machines. 2.8 Related Works Other scholars have also worked towards automating the generation of levels in the Metroidvania genre. Typically, these other projects aim to automate the creation of more than just the underlying map structure of a level. That is to say that components such as weapons, tools, or even the story could be generated as well. It is generally accepted that video games with few or static level designs can become monotonous on future play-throughs [1]. Additionally, creating more levels to solve this issue proves challenging for a development team. Creating more content can be time consuming, tedious, and expensive [1]. Using procedural generation to produce this new content typically lessens the issue of monotony and is appreciated by players [9]. Overall, the design phase makes or breaks a game [9]. Gutierrez-Rodriguez et al. worked to automate the video game design process using deep evolutionary training [1]. This project was a continuation of their past work and sought to create an AI-assisted design tool for developers capable of designing full games. This tool was speci.cally designed to aid in the creation of Metroidvania levels [1]. They used evolutionary algorithms to generate the in-game content and neural networks to simulate a designer’s thought processes. In the end, they were able to generate ’acceptable’ results [1]. However, there is no mention of user studies comparing the generated levels with those of human design. In another project, Gutierrez-Rodriguez et al, once again furthered their work in the .eld of video game design automation. In this study, they sought to create a tool capable of producing a complete game, with the exception of art and sound [9]. This would involve an autonomous designer creating mechanics, game rules, game elements, Non Player Character behaviors, and levels [9]. A very ambitious project. The authors discuss some of the di.culties involved in procedural generation. For example, there could be in.nitely many designs for the player sprite, but which of those designs best encompasses the character of the main protagonist [9]? Human artists are readily able to craft characters based o. of their traits and abilities. Evil characters could be shrouded in black, while heroic characters wear pristine white for example. They then explain how this issue can be expanded to the fuller game design. What sort of experience should the game bring to the player? How do the mechanics, rules, etc e.ect or bring about that experience [9]? To tackle these issues, they used a combination of neural networks and evolutionary algorithms [9]. The evolutionary algorithms simulated the di.erent ideas that a development team might create during brainstorming [9]. They determined that their resulting proof of concept was capable of creating quality levels, but was also able to provide promising hints to designers [9]. Sentient Sketchbook is a project geared towards map design. The created tool is capable of determining a map’s play-ability and balance and of providing suggestions for alternative mappings [5]. This tool was used to generate levels for strategy games, like Starcraft, rather than Metroidvanias [5]. Most strategy games consist of a board-like grid of tiles, which the player and NPCs can navigate. Sentient Sketchbook can be used to design low-resolution abstractions of these tiled game maps [5]. Designers are also able to interact with Sentient Sketchbook through a graphical user interface [5]. The tool was tested on industry experts, and proved to provide useful suggestions and feedback to the designers [5]. Players expect more and more out of the games that they play. As Hendrikx et al. put it, “the most popular commercial games get larger, prettier, more atmospheric, and more detailed with each generation” [3]. Procedurally generating content can be used more broadly to help meet these demands. There are six types of game content that can be procedurally generated [3]. These include game bits, game space, game systems, game scenarios, game design, and derived content [3]. Game bits make up the fundamental units of a game. Textures, sound, vegetation, buildings, and behavior are examples of game bits. The game space is comprised of indoor and outdoor maps. The game systems include the environment, roads, and entity behaviors. Puzzles, stories, and levels make up game design. And .nally, derived content consists of news and leaderboards [3]. Needless to say, there are di.erent methods and techniques for generating content from the various categories. These include arti.cial intelligence, genetic programming, and algorithmic approaches. There are four distinct approaches to game space generation. These include designer-created, random, player-created, and procedural spaces [7]. Very few games however make use of procedural space generation [7]. The main obstacle in procedurally generating spaces for game play isn’t making the content itself but making the content interactive. Games like MojoWorld generate fractal based planets with great detail, but the worlds are devoid of active NPCs and interactive objects [7]. Nitsche et al. decided to bridge the gap with their Charbitat prototype. Charbitat is capable of gen­erating worlds based on the playing styles of its users. That is that the player shapes and changes the game world as they play [7]. The crux of procedurally generating worlds is that the game space might not make sense. The only limits on the proce­durally generated worlds are provided in their rule sets. For example, in Minecraft’s newest April Fool’s update, they allowed the player to travel to a near in.nite number of procedurally generated dimensions. Some of these were well-formed and interest­ing, while in others the ground was made entirely of .owerpots. The problem with in.nity is that you get everything. This is the main reason some would contend that human-designed worlds are superior. But it has been shown time and time again that procedural generation can be used, often times in conjunction with human designers, to enhance or augment game play. Chapter 3 APPROACH 3.1 Overview Generating fully playable, winnable Metroidvania-style levels is the ultimate goal of this project. Generally a level can be considered as one of many areas or maps that comprise a larger, complete game. Metroidvanias are often games that are made up of one or just a handful of levels. Accordingly, the games generated by this process, consist of a single level. Figure 3.1 provides a visualization of the level creation algorithm. At the start of the process, the designer provides a gating order, a horizontal mapping, a vertical mapping, the number of columns n, the number of rows m, the player’s start position, the end goal position, and a weighted neutral. All of these inputs are described in more detail in Section 3.3. A DAG is created from the designer’s provided ordering input, and a topological ordering of the DAG is generated (Section 3.3.2.1). This manufactures a linear gating order from the designers speci.cations, which the generated level will have to obey. The mapping inputs are standardized, a process that simply adds convenience for the designer. See Section 3.3.2.2. All of the inputs are then used to produce a graph representing a potential level, as described in Section 3.3.3.1. This graph is veri.ed for winnability, according to the criteria of Metroidvanias and the gating order (Section 3.3.3.2). If the graph does not represent a winnable con.guration, then another potential graph is produced using the same inputs. Otherwise, the keys from the linear gate ordering are assigned positions in the graph, with respect to that ordering. This process is described more fully in 3.3.3.3. The .nal graph representation, the speci.ed room dimensions, and a player object are all used to render the underlying graph into a .nalized playable level. This process is explained in Section 3.3.4. The end result is a playable, winnable game that meets all of the criteria speci.ed by the designer at the start of the algorithm. 3.2 Model Before unique level mappings can be procedurally generated, we need to have representations that model the map and key orderings. 3.2.1 Modeling the Map A level map can be represented as a directed graph of nodes and edges. Each node represents a room within the map and each edge represents a gated connection. The weights or labels across these edges signify the particular gating technique required to cross that connection. More speci.cally, wherever an edge between two nodes exists, there is also one in the opposite direction. These two edges, connecting the same two nodes, most often have the same label or weight, but are not required to have such a pattern. The edge in one direction can be completely di.erent from the one in the opposite direction. The graph model is also planar; there exists a 2-Dimensional representation of the graph structure in which no edges overlap. To create a physically possible map, planarization of the graph is required. Each node in the graph can be connected to no more than 4 nodes and to no less than 1 node, ensuring that every node is reachable. The 4 node maximum constraint mirrors the structure of a room in a typical Metrodivania using 2D graphics. There is an up, down, left, and right. The resulting graph model resembles a lattice of nodes and edges. Figure 3.4 shows an example of a Map Lattice that could be used. The process through which this structure is constructed is described in Section 3.3.3.1 below. 3.2.2 Modeling the Key Orderings The ordering in which keys can be found is also represented as a graph, more aptly a directed acyclic graph (DAG). The single source of this DAG, the node with no incoming edges, is the .rst gating technique that the player will have access to. In most cases, this .rst gating technique is the neutral connection, but the designer can change this as they please. The children of a node represent gating techniques that are reachable once the parent node has been attained. For example, if single jump were a parent node, then double jump could be one of its children nodes. This creates a rigid system that enforces the progression of the gating techniques. This prevents situations where you collect single jump after you already had access to double jump. The sinks of the DAG, the nodes with no out going edges, represent all of the potential ending gating techniques. The process through which this model is created and how a gate ordering is generated from it are described more fully in Section 3.3.2.1. 3.3 Implementation This section will cover in detail the implementation and design responsible for the generation of our Metroidvania style levels. 3.3.1 Representing Keys and Gates When providing information to the level map generator, keys and gates are synonymous. There is no need to make a distinction between the two at this point, since it follows logically that the red key opens the red gate and the double jump key allows the player to double jump. These gating techniques, as they will be referred to from this point forward, are represented by strings. For more information on how this gating technique information is input into the generator, see Section 3.3.2.1. 3.3.2 Preprocessing A short pre-processing step allows designers to provide inputs before levels are successfully generated. That is that the designer provides information on the desired gate ordering. 3.3.2.1 Generating an Ordering for the Keys As was described in Section 3.2.2, the designer can provide a DAG structure to convey all of the viable orderings for their map. Such a DAG could be skinny with only one valid ordering, or it could be bushy, with many many valid orderings. See Figure 3.2 for examples of potential orderings. The typical user or designer cannot be expected to create a DAG such as these to input into the generator, so instead they provide the generator with a dictionary, where keys represent a gating technique and values represent all the new keys that are viable after said key has been found. See Figure 3.3 for an example of just such an input and an example of its output generation. If a particular gating technique can only lead to one other technique, then the designer can simply provide that technique as a string for the value associated with that key. If there is more than one viable next gating technique reachable, the designer can assign a list of such strings to the value. To .nd the actual linear order of the keys for the particular level, the get-GateOrder function in the grapher module is called. This function in turn calls the helper function createGraph, to create a networkx representation of the gating DAG. createGraph is provided with the dictionary created by the designer, called ordering. createGraph iterates through the keys of ordering and adds each gating technique as a node in the graph. Speci.cally, it adds an edge between the key (parent gating technique) and the value (child gating technique). If the value at a key is a list, then each of the elements in that list is added as described previously. Once this graph is (b) Simple Branched Ordering (c) More Complex Branched Ordering constructed, it is returned and control returns back to getGateOrder. With the gating techniques graph now available, getGateOrder .nds the one source of the DAG, i.e. the .rst key that a player should come across (typically the one they start out with by default). Next, while the length of the constructed ordering is less than the number of nodes in the returned gating techniques graph, each node currently in the constructed ordering is looped through and all of its children are saved as potential next keys. One of these potential next keys is selected at random and appended to the end of the constructed ordering. This process continues until all keys have been added. This system provides for variation in the orderings for maps, while obeying the constraints outlined by the designer. 3.3.2.2 Creating Directional Mappings for Gate Types Along with being able to control the gate ordering, the user can also specify which gates can appear on platforms and which can occur on walls. They can do this by specifying rules for bi-directional gates. The designer can provide a horizontal mapping and a vertical mapping. Both of these are lists, which contain strings, which once again represent the various gating techniques. All gates that can be present in walls should be within the horizontal mapping, all of those that can be present in platforms on the vertical mapping. Some gates are yet more complicated. Take for example double jump. The player should be required to have double jump in order to pass up through a double jump gate. But what if they fall o. from the top of the platform? The player shouldn’t be required to have double jump in order to fall. Such a constraint would seem contrived and inhibit game play. By providing a tuple of two strings, instead of just a single string, we can convey to the generator a setup that allows for di.erent gatings in di.erent directions. ‘(“double jump”,“neutral”)’ for example would mean that you need to have the double jump movement tech in order to proceed upwards through the gate, but only need the neutral tech to pass downwards. Although designed for this speci.c case, the functionality is generalized such that any combination of bi-directional gatings is possible (in some cases additional steps may need to be taken in order for the gates to be properly rendered and playable, see Section 3.3.4.3). As you can probably imagine, having some elements of the list as strings and others as tuples could present issues down the line. Luckily the getDirectionalMapping function in the grapher module cleans up the list such that all items are tuples. That is that each string in the list is converted to a tuple where both elements contained within it are that string. This serves mostly as a convenience function allowing designers to specify ‘[“red”]’ instead of ‘[(“red”,“red”)].’ Also, gating techniques can occur in more than one tuple. Take this for example, ‘[(“red”,“red”),(“red”,“blue”)].’ With this setup, in one con.guration a player could pass through the red gate with the red key in both directions. In the other con.guration, the player could pass through the gate with the red key, but would need the blue key to return to where they came from. This allows for further variation in the design of maps. 3.3.3 Generating the Underlying Map Once the pre-processing has been completed and the designer has speci.ed the gating criteria, the underlying structure of the map can be generated. 3.3.3.1 Creating the Lattice Once the gating order and the directional mappings have been set, the actual graph representing the map level can be created. Parts of this graph are created through random generation, but the underlying structure is created in the form of a lattice. This intelligently designed lattice ensures that the graph is planarizable, no node has more than four connections, and that those connections are its ‘proper’ neighbors. What is considered a proper neighbor can be seen in Figure 3.4. To construct the lattice, we use a list to simulate a stack, appropriately called nodeStack. nodeStack contains the nodes which are yet to be processed. Contrary to popular computer science convention, the .rst node of the graph is labeled with the number 1, thus 1 is the .rst thing pushed on the stack. As long as the nodeStack is not empty the following continues to happen. The nodeStack is popped and the popped node is saved to a variable i. Using the logic found in Table 3.1 to .nd the relative location of i within the overall structure of the lattice, the various connections of i are determined. Examples of the di.erent con.gurations can be found in Figure 3.5. If a potential connection is between i and a node that hasn’t been processed yet and it isn’t randomly dropped out, it is assigned a gating technique and is added to the growing graph. The newly connected node is also pushed onto the nodeStack, so that it too can be processed. The detConnection function is responsible for the logic behind which connections are added and of what gate variety. The connection being considered is between the node i and another node. If this other node has already been processed, meaning that all of its connections have already been determined, then there is no need to re-evaluate the connection. Therefore no additional connection is added. If the other node has not yet been processed, then the available gates are pulled from the mapping. Next, the connection is randomly assigned one of these available gating techniques. This assignment is not truly random, since the designer can also provide a weighted neutral as a parameter. This weighted neutral a.ects how many of the nodes are connected via neutral edges. This allows for the map world to be more open and less restrictive. There is no need for all rooms, or nearly all rooms, to be connected by locked doors (b) Top Edge (a) Top Left Corner (c) Top Right Corner (d) Left Edge (e) Middle (f) Right Edge (h) Bottom Edge (g) Bottom Left Corner (i) Bottom Right Corner Figure 3.5: Possible Positions for Node i in the Grid Position in the Grid Criteria for Being in that Position Top Left Corner i == 1 Top Edge 2 <= i <= (n-1) Top Right Corner i == n Left Edge i % n == 1 and i != 1 and i != (m-1)n + 1 Middle i % n != 0 and i % n != 1 and n