Picking from Random Tables

Once again, I started a weekend project on a minor problem that ended up being more involved than expected. This time, the topic is random tables. Random tables are used often in role playing games, to create random items or ideas on the fly, based on a dice roll.

The process of rolling physical dice is fun, but can be slow, so I started coding some of these random tables to help me keep the flow going during games. As an example, this page creates “random citizens” you might encounter in the fictional city of Doskvol. Every roll will produce a new citizen, like this one for instance:

Random Doskvol Citizen

In general, these are not too complicated. However, some generators can become quite tricky. As an example, “The Perilous Wilds” has complex tables like this one:

Ability (roll 1d12)
---
1  bless/curse
2  entangle/trap/ensnare
// omitted entries
8  MAGIC TYPE
9  drain life/magic
10 immunity: ELEMENT
11 read/control minds
12 roll twice on this table

I have had a lot of fun so far trying to model these tables in F#, so I figured perhaps sharing my exploration would make an interesting topic!

More...

Playing Audio with an F# Discord bot

This post is a follow up to that one. As mentioned earlier, my overarching goal is to build a Discord bot to help play “atmosphere” soundtracks during D&D games. Last time, we went over creating a simple Discord bot in F# to support basic text commands. This time, we’ll add sound.

How it works overall

Our application builds on what we did last time. We will use DSharpPlus to create a console application that exposes commands we can trigger from a Discord server. The part we need to add is a way to stream sound to Discord. To do that, we will use Lavalink, a java program that supports searching and streaming audio sources. The NuGet package DSharpPlus.Lavalink handles integration with Lavalink already, so most of the work is done for us already, all we have to do is bolt the parts together. Rather than repeating the DSharpPlus docs, I will highlight the parts where I had some issues.

To run the complete solution locally, you will need to:

  • Run Lavalink on your machine,
  • Run BardicInspiration on your machine: it will connect to Lavalink, and respond to Discord commands, searching audio tracks via Lavalink and streaming them to your Discord server.
More...

Create a basic Discord bot in F#

I have been using Discord a lot lately, mainly because I needed a space to meet for role-playing games remotely during the Black Plague. One nice perk of Discord is its support for bots. In particular, I used a bot called Groovy, which allowed streaming music from various sources like YouTube during games, and was great to set the tone for epic moments in a campaign. Unfortunately, Groovy wasn’t complying with the YouTube terms of service, and fell to the ban hammer. No more epic music for my epic D&D encounters :(

As the proverb goes, “necessity is the mother of invention”. If there is no bot I can readily use, how difficult could it be to create my own replacement, in F#?

In this post, I will go over the basics of creating a Discord bot in F#, using the DSharpPlus library. Later on, I will follow up with a post focusing on streaming music.

The bot we will write here will be pretty basic: we will add a fancier version of hello world, with a command inspire that we can trigger from Discord:

/inspire @bruenor

.. which will cast Bardic Inspiration on @bruenor, a user on our server, responding with a message

Bardic Inspiration! @bruenor, add 3 (1d6) to your next ability check, attack, or saving throw.

More...

Graph Layout with Spring Embedders in F#

I have been obsessing over the problem of graphs layouts lately. To provide a bit of context, the starting point for that obsession was role-playing games. When running an adventure, you often need to quickly find various pieces of information, and how they are connected, for instance “Who is the leader of the Lampblacks”, or “What are notable locations in the Six Towers district”. This type of information clearly forms a graph. It would be nice to be able to navigate that information quickly, to figure out how various entities are connected.

This is how I got interested in building up a knowledge base for a game I am running (the wonderful Blades in the Dark), and displaying the information as a graph.

Before diving into the code, as a teaser, here is how the result looks like at the moment:

Graph layout of Dosvol factions

Or you can try it live here.

I can search for entries, select them, and as I do, the relationships between them is added to the graph, automatically highlighting existing connections.

Graph Layout with Spring Embedders

The part I found interesting was the automatic graph layout. The goal here is to take a graph, a set of nodes (or vertices) which may or may not have edges connecting them, and display them in a manner that is hopefully informative and pleasing to the eye.

As it turns out, this is not an entirely trivial problem.

More...

Santa's Mailbox

This post is part of the F# Advent Calendar 2019. Check out other posts in this series, under the #fsadvent hashtag, and… happy holidays everybody :)

It is that time of the year again for Santa, Inc. - a time of celebration for most, but for Mister Claus, a time of intense and stressful activity. Every year, keeping up with all these letters coming from kids everywhere, and assigning them to the Elves crew, is a problem. Mister Claus is a diligent CEO, and keeps up with current trends in technology. Perhaps this F# thing he keeps hearing about might help him handle all these letters?

Setting up the Problem

Instead of cute handwritten kids letters, we will take a much less cute, but conceptually similar problem. Imagine that, at regular intervals, we receive a batch of work items (the letters), which we need to process. We will represent each item as a Job, storing its batch number and number within the batch, and a Value, representing the job that needs doing:

type Job = { 
    Batch: int
    Number: int
    Value: int 
    }
More...