The generation is largely done at this point, still a few minor points of polish to do on it. Implementing it was painfully slow for reasons I can’t really articulate. Just one of those kinds of weeks. Hopefully I’ll be able to run a test of the new map system by the end of this month, but it might end up being more of an early March kind of test.
The remaining stuff is largely just tweaks. The gold/experience gain rate was never balanced for the new system which hands out gold/exp far more frequently, so that needs to be tweaked. PVP classes were never made for the new single class system, so I need to add some rough versions of them (the new map system benefits PVP more than co-op so I really want to test it this time). Quests need to be revised to deal with the new map structure. I need to do some personal testing to get map feel right, figure out what the ideal length is. Lots of minor stuff. I’d like to get it done this week, but I’m not going to bet on it either.
As it turns out the solution to the new generation was to simply expand the existing system further. Much like how node tags have rules describing how they should be generated to create more interesting patterns, I added two new pieces of data to represent interesting patterns in the world shape as a whole. The first one is that of Area. Area basically describes the entirety of one difficulty rank (for reference there are currently 3 ranks in a single game). Doing it on a per rank basis makes it easy to set it up so that further ranks can have longer or more difficult patterns. It’s also important because certain world shapes are more interesting than what would tend to happen naturally (for instance I like the pattern where the map starts with several branches, then has a section with no branches, then returns to several branches- the middle section having no choice serves as an interesting melting pot of gathering the players together at the mid point)
Then comes segments. Segments represent the entirety of a single map branch. In a lot of ways segments are secretly just probability charts for the players to consider. Having partial control over the patterns allows for stuff like “make all of this section’s positive tiles gold gain”, and “front load all of the negative tiles at the beginning” etc. Segments rely on node tag categorization to make broad generalizations such as “positive tile” or “major negative tile”, rather than specifying exact nodes themselves. Naturally the final phase is the same as it was in the previous generation system (essentially just picking a random node within a tag set whose constraints are valid), just applied to a smaller space.
It’s all really simple now that I put it out here, but much of the week was spent dealing with thorny issues. One such issue was how to apply gradual difficulty transitions across the map. Doing a transition mid-segment would result in imbalances of how a segment was designed (ie the negative tiles might end up as lower difficulty than positive tiles, making that segment too good). Eventually I settled on making the length of segments directly correspond to the length of difficulties. Consequently any extra long segments have to be built with the knowledge of when their difficulty will transition, so they won’t be designed in ways that promote imbalance.
There’s a lot more complicated additions the new generation system will need for stuff like lock/key nodes, but right now I’m just trying to get a basic version up and running so we can tell if this style of map is even worth generating in the first place. I kind of have a bad feeling about writing a generator before being certain of what map structures play well, but in theory the system should be able to adapt to any changes (of course that’s also what I said about the single worst waste of time of this project that was one of the previous generators).
At this point the conversion of game systems to the new format is finished. Lots of new systems (fancier gates, a warp system), lots of updated old ones (ranged attacks/parties/etc). What remains is implementing a map generator for the new map format. A skeleton of it is already in place for creating basic maps, but there are no brains behind it. The main stumbling block for me right now is deciding how much of the old system is applicable to the new map style.
I don’t remember if I actually documented the newest version of the generation system here. It’s pretty simple. Every type of node (that is, a location in the game with behaviors attached to it. ie, a trap node that hurts players who pass by it or a gold node that gives players gold when landing on it) has two special properties attached to it: Tags and constraints. Tags are for organizational purposes such as “healing nodes” or “negative nodes”. Constraints are requirements and limits: ie only spawn this on medium difficulty tiles or only spawn 3 of these. Tags also have constraints and are the organizational structure that the core generator uses to decide what things to spawn (it picks a random tag and then spawns it somewhere and then moves on until out of tags or slots to fill). It becomes very easy to create behaviors like “only spawn 1 healing node per rank” or “only spawn this near other trap nodes”, especially since multiple tags per node allows varying degrees of classification. It worked great when the world only consisted of about 9 nodes per rank, and the positions of other nodes was rarely of importance.
The new system has more considerations to take. Nodes have a lot more importance to each other based on the branch they’re within. It’s trivial to generate a branch with the concept of “there should be 4 positive nodes and 2 negative nodes”, but what each of those nodes is matters a lot. If we went purely random on these players will likely end up making a decision on “what has the least negatives / the least costly negatives” or “what has the easiest gates” because the composition of each branch would be a mish mash where anything could be possible. Now imagine if we made that same branch “4 gold nodes, 2 damage nodes”. At this point players now have a good idea that if they go down this branch they will probably get some gold. If gold is a desirable resource for them at the moment, then they will weigh it against the damage nodes and have to make an interesting choice of whether the risk is worth it. While it’s easy to take that example and say “well, then have whatever node you randomly pick be used for all nodes on a given branch”, it doesn’t take into account the bigger picture. ie, having most branches randomly happen to be gold diminishes the value of gold over time. The old system by itself just won’t be enough, and complicating the problem is the fact that I don’t fully understand all the important factors of the new map style yet. That is going to be the focus of this week: figuring out what matters on maps, deciding how much of the old system can be used to generate it, and then applying it all as needed.
Starting to make progress on actually putting the new map system together. Still very early. A fair amount of the time consumed was due to building a feature more thoroughly than initially expected. Technically this feature was problematic in the last iteration, instead of properly integrating item drop offs in the new system I was just using the same system as several iterations ago. This meant item drop offs worked in a way that was very confusing for testers, but was close enough that it was an easy thing to delay doing properly. With the advent of the new system being so dependent on pass-by actions, it became necessary to integrate them correctly. Had to pull out the old code, make it capable of working in multiple places, etc. End result is we can finally have node actions that demand gold or items to use them, and quest drop offs can be done as a pass by.
The other big thing of the week is a bit more technical. Around 7 months ago after a driver update, lines between tiles in the game started appearing for me. There was no logical reason in the code for these lines to be appearing, and I figured maybe it was just a problem with the new drivers. Months past, and the issue persisted in every new driver update. Looking for answers online didn’t lead to much since I had assumed it was an issue tied specifically to the newer drivers. This week I finally set my foot down and decided I was going to get this thing fixed. After a whole lot of fiddling it became clear that the issue behaved differently depending on two factors: when you change the resolution of the window from its starting resolution, and when you use decimals in sprite positions. After I boiled it down to symptoms it finally became possible to look up solutions online. Apparently when dealing with floating point positions video cards can blur the edges of things to create a smoother movement effect. This is useful for moving objects, but terrible when triggered on static things like my map tiles. Even removing decimal positions for these static objects isn’t enough to fix it since it can also be triggered by things like having the screen size coordinates not match the texture coordinates (which occurs by resizing the display window). Different cards deal with the rounding in different ways, too, presumably the driver update made my AMD card start to deal with it in a slightly different way. The solution in the end is to add exactly .375 to these static object’s positions to force the rounding to occur in a specific way between all cards. Programming, huh.