Gostars - Creating Star Names
Tags: go
Published: 2020-02-20 21:35:22

---
title: Gostars - Creating Star Names
published: true
date: 2018-03-05 23:43:40 UTC
tags: go
canonical_url: https://www.skillscheck.co.uk/post/gostars-creating-star-names/
---

When we want to create a new Gostars game, we want to enter the minimum of parameters. Specifically, we want to create a game by setting the size of the universe and density of stars but _not_ the names of individual stars.

So how do we generate readable names from scratch?

# Generating the names

## Random strings

Let’s try creating totally random strings. Start with 26 letters and pick them at random until you get bored. [Here’s](https://github.com/dnnrly/gostars/blob/feature/star-names/tools/randtxt/randtxt.go) some code that will do just that, select letters at random for random sized words. Give it a go [here](https://goplay.space/#saj4F_db44k).

Here’s some words that I generated:

```
Pthc
Dnlbn
Ugfb
Vndmm
Ikvji
Leafd
Krxpzaelp
Ldwnps
Pmcnaxr
Rcucryh

```

These do certainly look alien, maybe a little too much! `Leafd` and `Krxpzaelp` look decent enough but I don’t know that I can pronounce any of the rest. This doesn’t seem friendly for our players.

## Random phonemes

What if we could generate English sounding words by picking random ‘sounds’. By this I mean [graphemes](https://www.phonicbooks.co.uk/2011/09/03/what-is-a-grapheme/). Great idea, let’s try that - but it is a _pain_ finding a complete list of graphemes! After a lot of looking I eventually found that the best resource is [this](http://www.dyslexia-reading-well.com/44-phonemes-in-english.html).

The next tool to use does something similar to selecting random letters. Given a set of graphemes, select random ones a random number of times. The code to do this is [here](https://github.com/dnnrly/gostars/blob/feature/star-names/tools/graphemetxt/graphemetxt.go). You’ll need to supply a data file containing a grapheme on each line. Run it like this:

```
go run graphemetxt.go -source data.txt

```

Let’s take a look at what kind of names are generated:

```
guskngcklff
nbquwhcggrch
lkghged
seghssghcc
btgufflkghst
rgschdpn
jzgzwhsssfgh
lfzzrpsggguked
sejscftbbgezfpn
gueuthss

```

I’m not sure that’s any better.

## Markov generator

Here we’ll break out the big guns. [Markov chains](https://en.wikipedia.org/wiki/Markov_chain) look at an existing body of data and randomly select the next ‘state’ based on its probability of following the current one. In our case, each letter will be a state.

A quick search of the internet revealed a handy little [library](https://github.com/unixpickle/markovchain) that will help us out here. [Here](https://github.com/dnnrly/gostars/blob/feature/star-names/tools/textgen/textgen.go) is a program that will read in a data file with a new name per line to build a model of how names are constructed. To use it, type the following in to the command line:

```
go run tools/textgen/textgen.go -source <your data file>

```

We need some source data to seed the Markov Chain. For this I did a search for place names in the UK, I chose a list of English nouns and place names (counties and towns). As long as the place names are 1 per line, this will server as our data.

You can set the number of words with the `words` parameter. There is another parameter too, the ‘prefix’. This is used to set how far ‘back’ back in the chain the algorithm looks when deciding what letter (state) to pick next. I’m still learning how this affects the output but using `2` gave some interesting output:

```
Implain-landear
Adamod
Mouningendroold
Anchal
Olelughtemplail
Ariabervaging
Hdrack
Entivult
Rimbe
Usholynx

```

That’s _much_ better! Quite alien but somehow readable.

Some interesting features of this tool are:

- When we meet a newline, it’s the end of the word so pick a new location in the chain
- We filter out the original words by adding them to a set of known words
- Duplicate words are removed by only storing them in our set too

Using `map` keys will work very well for a set.

# Deploying the names

Now we have a large list of names, how do we get them in to our game? So this is where we take advantage of the fact that we’re using[Buffalo](https://gobuffalo.io). It icludes a tool, `packr`, that allows you to embed static resources in to the binary that you produce with `buffalo build`. So first of all, we need to produce a list of names (you can find them [here](https://github.com/dnnrly/gostars/blob/feature/star-names/data/starnames.txt)). So how do we make them available to the program?

Let’s start with how we will use the names when we need them. The first version of cut of Gostars created new stars when you created the game. When a client does a `POST` against `/games`, the handler looks at the size and star density of the universe defined in the request fields and generates a random number of stars at random positions.When we generate the star, we need to look ip a name from our list, preferably randomly. Otherwise every game would have the same star names. How do we solve this? Well, it turns out that Go has a solution to this. When you `range` over map keys, Go will present them in a random order. To simplify our code as much as possible, I’m thinking we need to provide a type that will let us get an arbitrary number of these names from the map keys. Take a look at [`names.go`](https://github.com/dnnrly/gostars/blob/feature/star-names/actions/names.go) for a type that will do this.

The next question is, how do we populate our `nameList`?When you are writing a Buffalo application, you don’t jump in to `main`, you entry point as a developer is `actions.App()`. This is where all the initialisation of resources happens. We need to create a package variable of type `nameList` and instantiated it in `App()`, passing in a string with all of the data in the file we created earlier. To do this, we create use a `packr.Box` that refers to the `data` directory in our repo. When we run `buffalo build`, the `packr` tool will scan the source code and detect where we call `packr.NewBox(...)` and store the contents of this directory as data in the binary.To access files in this directory, we need to look them up in the box that they are stored in. For our star names, we just look up `starnames.txt` from the box and pass this string to our `nameList`.

When we create the stars, we have access to the static data generated by our Markov Chain tool and can draw on them quickly when we need them.

I hope this is useful.