Lorentz Attactor visualization with Fable Elmish

Yesterday, I needed a bit of a break after a long day, and decided to try and visualize the Lorentz attractor in Fable. As it turns out, it wasn’t complicated, and I was pretty proud of the result, so I shared a gif on Twitter:

People of The Internet expressed interest in knowing more about this, so here we go: let’s talk about the Lorentz Attractor, F# and Fable.


Give me Monsters! (Part 7)

Welcome back to our ever-expanding series attempting to model D&D 5e rules in F#! In our previous episode, we began to dive in the representation of turn-based combat. We left off with a sketch of a design, where we keep track of the state of affairs in a World entity, updating the position of each creatures by applying a Move command to it.

We also left a few open issues that need to be addressed. The most glaring issue at that point is that, in our current model, every creature can move in any direction, at any moment. This isn’t right: according to the rules,

On your turn, you can move a distance up to your speed. You can use as much or as little of your speed as you like on your turn. […] You can break up your movement on your turn, using some of your speed before and after your action.

To make that happen, we need to incorporate turns (which creature can currently make decisions), and movement (how many feet a creature is allowed to move).


Give me Monsters! (Part 6)

It’s been a while since I posted any update in this series, but we are back! Besides life and work getting in the way, I also needed to give some thought on where I wanted to take this next. We have a reasonable draft model to represent Monsters at that point, but I feel it’s time to take a slightly different direction.

The driving question behind this whole project was, how can we check if an encounter between Adventurers and Monsters is balanced? To do this, I think the easiest approach is to simulate encounters. Put together some Monsters and Adventurers, let them fight it out, repeatedly, and see what happens.

This requires two distinct pieces:

  • an engine responsible for enforcing the rules, to determine what actions a creatures can take, and resolve what the results are,
  • some form of AI, to make reasonable decisions for the creatures, so we can simulate how an encounter might unfold.

The engine modeling the game itself is a prerequisite to build the AI system, so that is what we will start with. Once we have that piece in place, we should be able to deal with the AI part, and hopefully refactor the code we wrote so far to plug it in.


Give me Monsters! (Part 5)

Let’s face it, one of the main purposes of Monsters in D&D is to serve as battle fodder for Adventurers. It’s time to explore the bottom section of the Monster stats, and talk Weapons and Combat.

Warning: I have tried my best to make the contents of this series understandable without too much knowledge of the D&D 5e rules. This post goes into more arcane details than the previous ones, because the rules of combat are pretty intricate, and the details matter. I guess that is unavoidable: anything non trivial domain modeling effort will require diving into nitty-gritty details at some point.

Goblin Stat Block

From a domain modeling standpoint, this part is a bit messy. We have a sub-section labeled “Actions”, but the items listed there are not actions - a Scimitar or a Shortbow are weapons. To make things even more confusing, right above, we have a section that isn’t even labeled, but contains actions - Nimble Escape allows the Goblin to take special Bonus Actions, Disengage or Hide.

So… what should we make of this?


Give me Monsters! (Part 4)

In our previous episode, we took at stab at modeling Hit Points, which lead us to exploring the representation of dice rolls as expressions. Today, we’ll relax a bit, and finish up the missing parts of the top section of the Monster description:

Goblin Stat Block

What are we missing at that point? The creature type (“small humanoid”), Alignment (“neutral evil”), the Armor Class, and Speed. Let’s add that in, and improve our Markdown renderer in the process.