It’s been a while since I gave an update on my Settlers of Catan Starcraft map, so here it is. I’ve made a lot of major improvements to how the game board is generated, how player data is stored, and how the map keeps track of the game state. The image above shows what the game looks like at this point. Continue reading to get an idea of what I’m doing with the project from here, and what new systems I made.
Before I discuss the map I want to discuss why I’ve been so quiet about it. I lvoe working on this map, but I know that no matter how good it is, I cannot release it without the permission of Mayfair Games, the creators of Catan. While they might let me release the map, I don’t think I’ll ever be able to since you can already play Catan online for free on a site they own. While this won’t stop me from working on the map for fun, I know that any work I do on the map is really just for myself. With this in mind I am going to keep working on the map as a side project, and hope to eventually finish it, but I don’t have any idea what will happen from there and I will simply have to cross that bridge when I come to it. So basically, don’t expect this to be released any time soon.
Building a Better Grid System
When I returned to the map after some time with other projects, I found my biggest issue was understanding the systems I had created to make the Catan gameplay work. When I originally made the map, my knowledge of Starcraft 2′s editor was not very strong, and many of the systems were poorly made because of this. I eventually determined the best course of action would be to re-design the back-end of the map now that I had more experience with the editor, and to use the original version as a prototype and a way to see where big issues may come up.
The first thing I set out to improve was the game board. When I made the original map, the only way I found to make a hex-grid, was to impose a square-grid over a hex-grid, and create the illusion of a hex-grid by hard-coding the coordinates I found, into the game. While this was an okay, if sloppy, solution to my problem, it quickly became hard to manage when I started to see how much data each hex actually gave the system. The grid I created did a good job of imitating a hex-grid, but failed to give me any information on how the different hexes were interacting, or how the road points and settlement points were actually related to a given hex. Because of this, each new feature of the game required me to personally study the grid I had made, and create another convoluted system which could give me information which was not there to begin with. Here is an image depicting what I made originally, and how I imposed a square-grid over the hex-grid Catan uses.
In the image above, a number of problems become apparent. First, the grid lines were not even. This meant that to create true hexes, I had to create a system which would have different rows of the grid use different spacing depending on whether they were odd rows or even rows. On top of this, I actually had another grid which was entirely separate from this one to keep track of where the roads would be placed, and a third to find the positioning of hexes, since the intersections in this grid only accounted for the positions of settlements. Finally, this gird doesn’t allow me to easily add more hexes, so adding gameplay from any of Catan’s expansions would be almost impossible without re-working every major system.
All of these problems came down to the fact that when I made the original map I believed that you couldn’t create custom object types within SC2. This forced me to use a number of multi-dimensional arrays to store all of the information about the game. This was very hard to manage because each feature required me to modify the way an already existing array worked, or create a new array to store the new information. In the end I had 10+ arrays which all had related information, but were not directly linked.
After working with SC2 more I discovered Records, an object type within SC2 which can store variables. This allowed me to keep all the information about each Hex, Road, or Settlement in one object, and meant that new features could simply be added to existing Records, and wouldn’t require a new arrays to be made. By re-designing the way Roads, Hexes, and Settlements are stored within the game I was able to build a custom grid system which could dynamically generate multiple different gird sizes and change the size of the hexes on the fly. Below you can see the Records I created to store the Hexes and the Roads.
How the Grid is Built
Once I had Records for all of the important objects on the game board, I set about creating a system which would generate the game board itself. At this point I knew I wanted to be able to integrate the gameplay of any expansions down the line. Since all of the expansions require larger hex grids, I set out to build a system which could dynamically generate the game board using the Hex, Road, and Settlement Records I had built.
The system uses what I refer to as a “growth” algorithm, which is built on a recursive function. The first function call creates a Hex at the center of the game board. On top of that, each Hex stores a list of all the Hexes which are neighboring it, and how many neighbors it has. Once the first Hex has been made, all subsequent calls of the function go through every Hex that exists and check to see how many neighbors the Hex has. If the Hex has six neighbors it does nothing, since that is the maximum number of neighbors a Hex can have. If a Hex doesn’t have six neighbors, it checks each neighboring position to see if a Hex exists at that location. If it finds there is no Hex at that location, it creates a Hex and sets it so that both Hexes have each other listed as neighbors. If a Hex does exist at the location, it ensures sure both Hexes already list each other as neighbors, and moves on.
In the gif below, you can see how the Hexes and the connections between them are formed.
This continues until the board has the appropriate number of Hexes for the desired board size. At that point, it goes through all of the Hexes in the final layer of the Hex grid, and performs the check for neighboring Hexes once again, to make sure that all of these hexes are correctly linked to each other.
After building the Hexes themselves, the system finds the locations for the Settlements. Along with a list of neighboring Hexes, each Hex has a list of every Settlement that is linked to that Hex. To populate these lists, the System goes through each Hex and checks each of the possible locations a settlement could be in. When it finds one of these locations is empty, it creates a new settlement, and then adds that settlement to the list of ones the Hex is connected to. On the other hand, when it finds a settlement the Hex should be connected to already exists, it simply adds that settlement to its list, and moves on to the next position.
In the gif below you can see how the Settlements for a Hex get built, and how the neighboring Hexes connect to pre-built settlements.
Finally, the system builds the Roads. Just like how Hexes have a list of Settlements they are connected to, all settlements keep track of the Roads they are connected to, and all Roads keep track of the Settlements and Roads they connect to. The actual process of building the Roads is very similar to that of building the Settlements. The primary difference between the two is that when Roads are built, they also populate their own lists of connecting Roads and Settlements by looking at positions where connecting roads and settlements should be, and adding ones that they find.
The new system worked out excellently because it simplified the connections between each game element. By creating the “network” of Roads and Settlements, I was able to calculate things like Longest Road more easily than I could with the previous system. In the original version, Longest Road was challenging to calculate since none of the Roads were truly connected. On top of that, because of the way the Roads had been stored and laid out onto the square grid without a more complex system linking them, there was no easy way to consistently find both horizontal and vertical neighbors. This meant that the system was inherently flawed, and in some very rare scenarios it would calculate the Longest Road incorrectly. With the network correctly in place, calculating things like Longest Road became easy since I could start from any Road or Settlement I wanted and travel along a path through the game board.
The new system also allowed me to add other features which would have been much harder in the previous version. Specifically, it allowed me to improve the interface so that when a player is build a new Road or Settlement, only valid positions will be shown to them. If you look to the images below, you can see what I mean.
In this image, the current player is placing one of their starting settlements. As you can see, the three locations around the settlement that has already been placed are not available to the player. With the old version of the game all settlement positions were shown as viable options and it only told you a position was invalid after you tried using it.
In these images you can see that the player is trying to build a new settlement in the top one, and a new road in the bottom. In both cases, only spots that are actually viable are able to be used, and the player does not even see spaces which would be illegal.
The other thing this system allowed me to do, was make the entirety of the game board more “flexible”. Since all of the positions for the Hexes, Settlements, and Roads are calculated based on formulas and variables I define, the size of the game board can be manipulated by adjusting two variables. This meant that if I wanted to expand the number of hexes on the board, I only had to edit a few lines of code and everything would just work. It also meant I could change the size of the hexes themselves as I saw fit and didn’t have to recalculate the positioning of every in-game item. In the pictures below you can see images of the game board when I add more Hexes, or modify the size of the Hexes.
Finally, it made many gameplay elements easier to execute. Since this system linked Settlements directly to the Hexes, resource distribution was much simpler. All I had to do was write a function which found the Hexes with the value of the most recent die roll, and told those Hexes to give a resource to all surrounding settlements. The original system I created required cross-referencing and looking through at least 3 different arrays to distribute resources after each die roll.
On top of all that, the new tools I was using within Starcraft 2 also had a huge impact on the back-end and made many of the later systems easier to integrate as well.
At this point I’ve covered most of what I wanted to discuss, and this post is longer than I originally intended, so I’m going to call it a day. I hope you liked my explanation of the system I created to generate the game board, and I also hope it all made sense. Check back soon, and hopefully I’ll have more updates on this project or some of the other systems I created to get it where it is now.