Random Walkers
In this tutorial I will be showing you how to use a random walker function to create dungeon maps. A random walker is a computational model used to simulate a random path. It was first introduced by Karl Pearson in 1905 as a mathematical model for Brownian motion, a phenomenon in which particles suspended in a fluid move randomly due to collisions with the fluid molecules.
The walker starts from a given position and takes random steps in any direction. These steps are determined by a set of rules, such as a probability distribution. The path generated by the walker is random and unpredictable, but it can be used to model many different phenomena, such as diffusion, animal movements, or stock prices.
In this tutorial, we will use C# to implement a random walker function that generates a dungeon map. The dungeon will consist of a rectangular grid of tiles, where each tile can be either a wall or a floor. The walker will start from a random position on the grid and move randomly, creating a path of floor tiles. The path will stop when a certain percentage of the tiles on the grid have been visited. The resulting map will be a random dungeon layout that can be used in a role-playing game or other applications.
Define the Tile class that represents a single tile on the dungeon map. Each tile has a character representation, a foreground color, and a background color.
public class Tile { public char character; public ConsoleColor foregroundColor; public ConsoleColor backgroundColor; public Tile(char p_character, ConsoleColor p_foregroundColor, ConsoleColor p_backgroundColor) { character = p_character; foregroundColor = p_foregroundColor; backgroundColor = p_backgroundColor; } public void Print() { Console.ForegroundColor = foregroundColor; Console.BackgroundColor = backgroundColor; Console.Write(character); } }
Define the Dungeon class that represents the entire dungeon map. The dungeon consists of a 2D array of tiles, a 2D array of booleans to keep track of the fog of war (i.e., which tiles have been visited by the player), a random number generator, an entrance tuple that stores the position of the entrance to the dungeon, and some other properties such as the name of the dungeon, the total number of tiles, and the width and height of the map.
public class Dungeon { public string name; Tile[,] map; public Random rand; Tuple<int, int> entrance; int tilesTotal; int width; int height; //tiles Tile floorTile = new Tile('.', ConsoleColor.Gray, ConsoleColor.Black); Tile wallTile; public Dungeon(string p_name, int p_width, int p_height, Tile p_wallTile, Tile p_groundTile, float percentage) { name = p_name; rand = new Random(name.GetHashCode()); wallTile = p_wallTile; groundTile = p_groundTile; tilesTotal = p_width * p_height; width = p_width; height = p_height; RandomWalk(width, height, percentage); } }
We will need to define a walker class . The purpose of this class is to represent a walker that will move around a grid of tiles. Each walker has an X and Y position, which can be accessed using the "X" and "Y" properties. Additionally, each walker has a "walkerTile" object, which represents the tile that the walker places as it creates a path
class Walker { public int X { get; set; } public int Y { get; set; } public Tile walkerTile; public Walker(int x, int y, int width, int height, Random random, Tile p_walkerTile) { while (x == 0 && y == 0) { if (random.Next(0, 2) == 0) { x++; } else { y++; } } while (x == width - 1 && y == height - 1) { if (random.Next(0, 2) == 0) { x--; } else { y--; } } X = x; Y = y; walkerTile = p_walkerTile; } public void Move(int width, int height, Random random) { int direction = random.Next(0, 4); if (direction == 0) { X--; } else if (direction == 1) { X++; } else if (direction == 2) { Y--; } else if (direction == 3) { Y++; } X = X < 1 ? 1 : X; X = X > width - 2 ? width - 2 : X; Y = Y < 1 ? 1 : Y; Y = Y > height - 2 ? height - 2 : Y; } }
In this code, we have a class called Walker
, which has three public properties: X
, Y
, and walkerTile
. The X
and Y
properties represent the position of the walker in a 2D grid, and the walkerTile
property is an instance of a Tile
class.
The Walker
class has two methods: a constructor and a Move
method. The constructor takes six arguments: x
and y
(the initial position of the walker), width
and height
(the size of the 2D grid), random
(an instance of the Random
class), and p_walkerTile
(an instance of the Tile
class that represents the walker).
The constructor makes sure that the walker starts on the out side edge of the map, excluding the corners. This how I want my map to generate, but you could make the walker start anywhere in the map you want.
The Move
method takes three arguments: width
, height
, and random
. It first generates a random integer between 0 and 3 (inclusive), which represents a direction for the walker to move in (up, down, left, or right). Depending on the direction, it updates the X
or Y
property of the Walker
instance.
Finally, the Move
method checks if the walker is at the edge of the 2D grid (i.e., if its X
or Y
property is either 0 or width
- 1 for X
, or either 0 or height
- 1 for Y
). If it is, it moves the walker back one
Now that we have a Walker
class, we can create a function that will use it to randomly generate a dungeon. We will call this function RandomWalk
. The RandomWalk
function will take in the width
, height
, and percentage
of the dungeon to generate, as well as the groundTile
and wallTile
objects to use for the floor and walls of the dungeon.
We will start by initializing an empty 2D array of Tile
objects that will represent the dungeon map. We will then set all the tiles to the wallTile
object to start with.
Next, we will create a Walker
object that will start at a random position on the edge of the map. We will use this Walker
object to randomly generate the dungeon by making it walk around the map and setting the tiles it steps on to the groundTile
object. We will also save the position of the first tile the Walker
steps on as the entrance to the dungeon.
Finally, we will stop generating tiles when the desired percentage of tiles have been converted to groundTile
objects.
Here's what the RandomWalk
function should look like:
void RandomWalk(int width, int height, float percentage) { // Initialize the map array map = new Tile[width, height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { map[x, y] = wallTile; } } // Create the first Walker object int randX = rand.Next(0, 2) == 1 ? rand.Next(0, 2) * (width - 1) : rand.Next(1, width - 2); int randY = rand.Next(0, 2) == 1 ? rand.Next(0, 2) * (height - 1) : rand.Next(1, height - 2); Walker walker = new Walker(randX, randY, width, height, rand, groundTile); // Set the entrance tile map[walker.X, walker.Y] = walker.walkerTile; entrence = new Tuple<int, int>(walker.X, walker.Y); // Generate the rest of the dungeon int tilesPlaced = 0; while (tilesPlaced < tilesTotal * percentage) { while (map[walker.X, walker.Y] != wallTile) { walker.Move(width, height, rand); } map[walker.X, walker.Y] = walker.walkerTile; tilesPlaced++; } }
Finally, we can print out the generated dungeon by adding the following code to the Dungeon
class:
public void Print() { Console.WriteLine(name + " " + name.GetHashCode()); for (int y = 0; y < map.GetLength(1); y++) { for (int x = 0; x < map.GetLength(0); x++) { map[x, y].Print(); } Console.WriteLine(); } }
This method will iterate over the tiles in the map
array and call the Print
method on each tile to print it to the console.
Now we can create a new instance of the Dungeon
class and print out the generated dungeon. Add the following code to the Main
method:
var dungeon = new Dungeon( "My Dungeon", 30, 10, new Tile('#', ConsoleColor.DarkGray), new Tile('.', ConsoleColor.DarkGray), 0.3f ); dungeon.Print();
This code will create a new dungeon with a name of "My Dungeon", a size of 30 by 10 tiles, a wall tile with the '#' character and a dark gray color, a ground tile with the '.' character and a dark gray color, a percentage of 0.3 for the amount of tiles to generate, and a maximum amount of money of 100. Then it will print out the generated dungeon to the console.
Congratulations, you have successfully created a random walker algorithm to generate a dungeon! You can now play around with the code to see what happens if you change the size of the dungeon, the percentage of tiles to generate, or the types of tiles used. You could also add new features to the dungeon, such as enemies, traps, or treasure. The possibilities are endless!
Endless Prose
The long awaited 3rd addition to the Epic Prose series!
Status | In development |
Author | logicandchaos |
Genre | Role Playing |
Tags | Text based |
More posts
- Finishing the LibraryApr 05, 2024
- Text Adventure Library - Builder PatternMar 27, 2024
- Text Adventure Library - Slaying the Spaghetti Monster!Nov 22, 2023
- From Prototype to ProductionSep 25, 2023
- Redesign!Jul 22, 2023
- Improving the Name Generator using ChatGPTApr 20, 2023
- Creatures & Encounters!Mar 30, 2023
- Travelling Across The MapMar 23, 2023
- Exploring DungeonsMar 13, 2023
Leave a comment
Log in with itch.io to leave a comment.