Jochem Bruijninckx

hello@jochembruijninckx.nl

Train Board Generator

See it in action!

A few years ago, two of my roommates and I decided that our student house needed a boardgame. We went to a store and picked one called 'Ticket to Ride: Europe', which seemed fun. We sat down at a cafe next door to give it a try, and thus my board game addiction was born.

In the game, you are assigned a couple of tickets, each requiring you to connect two cities in Europe by building a set of train tracks between them. As everybody has a set of tickets to complete, you'll quickly find yourself competing with other players to claim train tracks before you get locked out!

Over the years, we played that game so much that the cards started to wear. And while it has always remained tremendous fun to play, it suffers from a drawback that is difficult to avoid for many boardgames: at some point, we started to become familiar with the cards in the deck, and we all knew the best ways to navigate the board. In this article I'll explain how I solved this problem by creating a tool that can generate an infinite amount of new maps for the game!

Ticket to Ride around the world

Luckily, the designer of Ticket To Ride (Alan R. Moon) has published many expansions for the game, each introducing a new game board to play on to keep things fresh. Each version also adds a few new rules that often force you to completely change your approach to the game.

In addition, there is a vibrant community of fans of Ticket to Ride that have taken to creating their own custom boards of new geographical regions to play on. The game's publisher Days of Wonder even has a dedicated page where they showcase some of these fan-made expansions! If you check out the game's expansions page on the internet's largest boardgame forum, you'll find that new fan-made expansions are still regularly being added.

Ticket to Ride is quite unique in this regard. For most boardgames, putting together your own expansion would be nigh unthinkable. But for Ticket to Ride, provided you own the base game, all you need to do to play any of these fan-made expansions is print the new board and the new set of tickets. Add in the fact that you can base your self-made expansion on your own city, state or country and it's very understandable why so many people have taken a shot at creating one!


Lockdown hobbies

My roommates had often joked about what an expansion of the game based on our hometown of Tilburg would look like, and which locations would be included. When the lockdown started in March 2020, I figured this would be the perfect time for me to see if I actually could create it. The approach I took consisted of the following four steps:

  1. Decide which locations in your map should be included
    This part is probably the most fun. Open up a map of your city, and start placing markers wherever you feel would be interesting! Of course, the places need to be spread out a bit. Somewhere between 30 and 40 locations is a good amount for a Ticket to Ride board.
  2. Decide which locations should be connected by tracks
    I printed my map filled with markers, and started drawing connections between locations wherever I felt was fitting. Don't make the map too well-connected, and try to draw tracks of varied lengths so that there are both short and long ones.
  3. Determine which colours the tracks should be
    This part is the most difficult. Start colouring the tracks, and try to do it in such a way that all colours have equal presence on the board. If possible, never connect two tracks of the same colour to the same location!
  4. Create the set of tickets to play with
    Finally, create a set of tickets to play with. No two tickets should be too similar, or they will be too easy to complete at the same time. In addition, try to make it so that there are a few easy (short) tickets, a few hard (long) ones, and many intermediate ones. To make for a varied ticket deck, my advice would be to create twice as many tickets as your map has locations.

Of course, as a trained Data Scientist, I couldn't allow myself to simply visually judge whether my designed map was balanced or not - I had to have some statistics to prove it properly! I listed all tracks, destinations and tickets in a large spreadsheet. I then constructed a few formulas that judged the balancedness of various aspects of the game, such as the variance of track/ticket length, or the proportionality of how well-connected a destination is on the board compared to how many times it appears on tickets.

As it turned out, I still had quite some tweaking to do. Especially balancing out the colours proved rather tricky, but the spreadsheet helped a lot in keeping a clear overview of which areas needed improvement. If you're interested in the spreadsheet I used, you can check it out here! After a lot of small adjustments, I ended up at a final version I was content with. You can view the final Tilburg Ticket to Ride board here. Then, all that was left to do was to play it - a lot!


If you can do it, you can automate it

With the improvements in place, the Tilburg version felt like a balanced game to play. Still, it's unlikely that I ended up making it as balanced as it could have been given the set of locations I had chosen. Reflecting on the process, you could say that I started by manually creating a reasonable initial solution. Then I improved it through a greedy nearest neighbour search, until I couldn't find anymore improvements with respect to my different indicators of balancedness.

That got me thinking - steps 2, 3 and 4 of the procedure I used in building the Tilburg board can each be seen as a seperate optimization problem, with their own balancedness indicator as objective function. Solving them consecutively should therefore produce new, balanced game boards! The only question that then remains to be answered is how we should obtain a set of locations for the first step.

Finding your destination(s)

What's so special about all of the existing Ticket to Ride expansions, is the way in which you explore the world by playing them. Completing tickets to cities in India or Japan that you had never heard of before is a fun way to explore the topography of those countries. And, of course, nothing beats being able to play a game on a board of your home country. Therefore, once my algorithm worked, I wanted a way to be able to generate maps for any country on earth! As a starting point, I downloaded a data set containing information on all cities on earth with a population larger than 1000 from here.

I figured that if I handled the selection of destinations in such a way that they would be different each time, then the resulting board would also be unique on each run. This would allow for the creation of not just one board per country, but inifinitely many boards! The pseudocode below gives a rough idea of how the destinations are selected. The actual implementation features some extra details which ensure that the largest empty spaces are filled first.

// Select an initial set of 30 destinations
destinations = sample_by_population(all_destinations, 30)

// Remove destinations that are too close
destinations = remove_too_close(destinations)

// Fill empty spaces
for destination in all_destinations {
   // Check if the destination fits on the board
   if (can_be_added(destination)) {
      destinations.add(destination)
      // The actual maximum destination amount differs with board size
      if (len(destinations >= 30)) break
   }
}

What's nice about this approach is that theoretically, every city in the data set has a chance to be selected. It makes sure that the chosen destinations are not too close to each other, and that the board is nicely filled. But what I like most about it, is that the most populous (and often the most famous) cities of a country will nearly always be on every map generated for that country. For example, check out this map that the algorithm generated for Spain, which is a country that has never had an official expansion dedicated to it so far:

The above map features cities that we would expect to see on a board of Spain like Madrid, Barcelona, Valencia and Sevilla. But at the same time it includes cities like Almendralejo, Roses and Narón - all of which have less than 40.000 inhabitants!


The end of our (train) journey

Selecting destinations was of course only the first step of the algorithm. To travel from that point to an algorithm that generates boards I'm truly happy with took a lot of extra steps - too many to explain in this blog post! Of course, if there's any part of the algorithm you're curious about, feel free to reach out via hello@jochembruijninckx.nl. Some examples of challenges solved by the algorithm include:

  1. Figuring out which tracks are most important in the network and should therefore be turned into a double track.
  2. Figuring out which tracks cross a sea or ocean (based on geolocation) and should therefore cost a locomotive card.
  3. Dynamically determining a good ruleset that works well for the produced board.

Once the algorithm started to feel finished, it was incredibly fun to build a front-end for this project and see the generated boards come to life . Especially because this allowed me to include tons of options that you can tweak for your board! For example, it's now possible to enter cities that you would prefer to be included, allowing you to create a board for your home country that is sure to include your hometown.

Putting pen to paper

For the very final step, I dove into the world of paper sizes, print margins, browser zoom and display scaling. The result: it is now possible to directly print the boards you generate - and if you know your way around a pair of scissors, you'll be playing in no time!

If this article piqued your interest, make sure to click the button below and try it out yourself. And if you have any tips or ideas for improvements, I would love to hear about them! I'll definitely keep adding any received suggestions to make the tool even better - but for now, this concludes our journey!

See it in action!