Morgemil Part 9 – BSP Dungeon Generation Part 2

I’ve started a list of tiles to be found

module Morgemil.Map.Tiles
 
let DungeonFloor = TileDefinition(1, "Floor", "Dungeon floors are often trapped", false, false, TileType.Land)
let DungeonWall = TileDefinition(2, "Wall", "Dungeon walls are built from the prisoner's bones", true, true, TileType.Land)

I’ve also changed the coloring slightly which is reflected in the header image.

      let tileColor =
        match tile with
        | _ when TileDefinition.IsDefault tile -> Color.Black
        | _ when Tiles.DungeonFloor.ID = tile.ID -> Color.White
        | _ when Tiles.DungeonWall.ID = tile.ID -> Color.Red
        | _ -> Color.Gray

Continue reading Morgemil Part 9 – BSP Dungeon Generation Part 2

Morgemil Part 7 – A whole new world

My first order of business is to create a world. So before I go off typing up a code-storm, I want to give the one defining rule:

Interesting results is more important to Morgemil than consistent or realistic results. I will leave making an amazingly complex believable world up to the genius making Ultima Ratio Regum.

Now that the rule is out of the way, I’m going to start: The portion of the world I’m building today is a simple dungeon. The generation of this dungeon will be absurdly simple. The bigger concern is storage of this dungeon.

Continue reading Morgemil Part 7 – A whole new world

Morgemil Part 6 – RNG

Morgemil can be loosely defined as a roguelike. Indeed, I’ve drawn much inspiration from some roguelikes of which the first I ever played was Angband eight years ago. The largest influence is ToME 2 “Troubles of Middle Earth” which is now mostly defunct and replaced by ToME 4 “Tales of Maj’Eyal”.

Now something most roguelikes have is procedural generation placing the player at the mercy of the Random Number Generator (RNG). This, simply put, determines whether the player lives or dies by creating unique dungeon levels, the level’s population of monsters, and the loot dropped by monsters.

My search’s first action was to check RogueBasin’s article on RNGs which quoted the Mersenne Twister as a good candidate “which produces fast and high-quality random numbers“. This is a sufficient recommendation for me so I then started searching for an implementation. I am fortunate in that there is an existing Mersenne Twister implementation in F# from a reputable source, the Math.NET Numerics library. So armed with the NuGet package I set to work.

module Morgemil.Math.RNG
 
open MathNet.Numerics.Random
 
/// <summary>
/// Type alias for a System.Random implementation
/// </summary>
type DefaultRNG = MersenneTwister
 
let SeedRNG(seed : int) = DefaultRNG seed
 
/// <summary>
/// Given an RNG and likelihood, returns the success
/// </summary>
/// <param name="chance">[0.0, 1.0]</param>
let Probability (rng : DefaultRNG) chance =
  match chance with
  | 0m -> false
  | 1m -> true
  | _ -> (rng.NextDecimal() >= chance)

This is not perfect, but it is at least a placeholder while I figure out what is needed. Testing this is a problem. All I know to test is the edge cases of 0.0 and 1.0.

module Morgemil.Test.RNGTest
 
open Morgemil.Math
open NUnit.Framework
 
[<Test>]
let ``RNG Probability test``() =
  let seed = 150
  let rng = RNG.SeedRNG seed
  Assert.IsFalse(RNG.Probability rng 0m)
  Assert.True(RNG.Probability rng 1m)

With pseudo-random numbers I shall create a world generation equation that will dwarf any amount of creative content I could create myself.

Morgemil Part 5 – A step backwards and forwards

My brother and I once took a ballroom dancing class where we were taught the basics of the waltz, salsa, tango, and foxtrot. I wasn’t much interested in the salsa and I no longer remember the foxtrot or the tango. What I do remember is a few steps of the waltz, especially the box where the movement of your feet make the corners of the box.

The dance instructor kept me making the box for a while and it was a little boring, we didn’t actually go anywhere. And that is what I feel like I’ve been doing on this project: taking a step backwards for every step I take forward. After I learned how to make the box and practiced it for a while, the instructor then showed me more steps that can be taken with the waltz to allow free-reign of the ballroom. In the same way, I’ve been brushing up on F# and functional paradigms so that I may have all the power they offer.

Continue reading Morgemil Part 5 – A step backwards and forwards

Morgemil Part 4 – Confidence

Being able to say that I have confidence in something I programmed is a great feeling. To build this confidence, I’m using unit testing. Unit testing is a method of verifying that individual pieces of code work as expected. I will not get into all the benefits of unit testing, I’ll just say why I am doing it: to check my work since no one else is doing so.

I began work on unit testing this afternoon. I installed NUnit and the Visual Studio extension to run unit tests directly:Nunit_extensionThen I added a new project to the solution called “Test”Nunit_projectI started with the easy file to test. Vector2i is all integer math, the expected results should be easy to reason about. To test Vector2i I made a new file with the same name and added a suffix “Test” in the new project. I read up on a quickstart with NUnit and F# and I wrote some code:

Continue reading Morgemil Part 4 – Confidence

Morgemil Part 3 – The Core

I’m going to be taking a bottom-up design approach to this project. Yes, I have an overarching general design, but I fully expect it to change. Change is acceptable and a constant. I’m going to be doing bottom-up design since I am unfamiliar with it, so another chance to learn. I’m not obsessed with keeping my original game design pure as some great mechanics could arise from unforeseen interactions.

Unforeseen interactions is sure to occur since as much of the game as possible will be procedurally generated (another hint, are you keeping track?). Therefore there will be a lot of math involved, not hard math, just a lot of it. So I’m going to start off with some clear functionality that I know will be required. Also, this is a chance to start becoming accustomed to the F# environment. Continue reading Morgemil Part 3 – The Core

Morgemil Part 2 – A Technicality

About five years ago I almost made a video game. I say “almost” because I got bogged down in constant rewriting while searching for perfection so that project lost momentum and was never finished. Not to mention that I hardly knew anything, as this was the summer before I started college. A bit of digging in the history banks turned up the old Google site created for it. https://sites.google.com/site/intimidationgameproject/

I remember learning a lot during that project: Python, Panda3D, a ton of search algorithms, and a little linear algebra. All of that knowledge served me well as a springboard to further concepts. Just as importantly, it helped reinforce some concepts of software development I was taught later: the language doesn’t matter, results matter, and to focus on working software as the perfect code will never be reached, no matter the iteration count. Continue reading Morgemil Part 2 – A Technicality