Wednesday, June 12, 2013

SimBlob. This is the project that got me interested in tile games, hex maps, pathfinding, road drawing, economic simulation, AI, and procedural map generation. Those of you who have been following me for a long time know that these are topics I'm especially fond of. This project was a huge influence on me and my game programming site. It ended 15 summers ago.

SimBlob was the simulation game engine / project that I was going to use for a building game called BlobCity, but I also wanted to use it for other games. As typical for people who work on a game engine first, I didn't finish. But that's ok. I was writing the game in order to learn and experiment, not learning and experimenting in order to write a game.

Screenshot from Aug 1998
More screenshots from 1995-1998

Playing the game

The reason I'm going through this code is that I'm porting it to run on modern systems; the next blog post will describe that process. (I'm not planning to work on it beyond the port.) Once I got it running, I spent some time playing the game. The UI feels clunky today but it followed the standard "paint program" paradigm that I saw in games like Pinball Construction Set and SimCity.

I only had 8-bit graphics back then, so I used lots of dithering. The dithering on ground textures looks terrible to me today, but it probably looked ok on fuzzy CRTs. Some of the placeholder art is terrible, but I'm quite happy with roads and walls. There are some neat patterns you can make. Putting them together in a triangle or hexagon forms some nicely curved shapes, not because these shapes were specifically implemented, but because the way I made the individual tiles, these shapes came out automatically:

Road shapes Wall shapes

I spent way too much time on simulation, both water and economic. A lot of this stuff just isn't visible to the player. A simpler version would've worked just as well. I also tuned the difficulty for myself. Since I knew how the simulation algorithms worked, I knew what to look for and could play the game reasonably, but I think the simulation might be too difficult to understand for anyone who hasn't understood the code.

Looking through the code

I've not looked at this code for a very long time. I've learned a lot since then. Some aspects of my coding and design style are different now. But other aspects are still the same, which tells me I have so much more yet to learn.

There's plenty of extra complexity that never paid off:

  • There are two separate class hierarchies for windowing:
    • Window works with OS/2 windows. The main map, minimap, toolbar, statusbar, and menus are all using this level.
    • Glyph is another window hierarchy, independent of OS/2 windows. The design was inspired by the InterViews GUI toolkit, which had quite an impact on my impressionable yound mind. The buttons, statusbar items, tabbed information area, and a few other things fit into this hierarchy.
  • There are multiple event processing systems. There's the OS/2 native one, WndProc, then one for my Window hierarchy, and another one for my Glyph hierarchy.
  • The widget libraries include things I never used, like state cycling buttons and radio buttons.
  • The layout manager was complete overkill, but something I wanted to experiment with. I had vertical layouts, horizontal layouts, overlapping layouts, and toggleable panels. It supported centering, stretching, and spacers. The original idea was that SimBlob was a simulation game engine that would support multiple games, and therefore would need an easy way to build UIs. In practice, I only ever partially wrote one game, and I could have manually placed the elements.

My main goal with the project was to learn things by trying things out. It's a good thing my main goal wasn't to finish a game. I learned a lot from all of these experiments, but I didn't finish the game.

I'm reasonably happy with the way the code looks. The main thing I don't like is that the modules don't cleanly map onto files. This was fine back when I was working on it, since I had the mapping in my head, but when I try to navigate the code now, it takes more effort. It's a good thing there are code navigation tools available.

Algorithms - environmental

I spent a huge amount of time playing with procedural map generation: fractal terrain, mountains and valleys, ridges and canyons, soil erosion, continental uplift, water erosion, volcanos, floods, forests, river channels. I followed the standard model of: try something out, run it, see if I like it. This was a huge time sink. At the very least I should have automated some of the testing. When I work on map projects today, I try to avoid this time sink by instead working backwards, building maps based on the game's requirements instead of trying to make a realistic simulation.

Programming the map generator and environment simulator led me to learn a lot about geology, hydrology, and other fun subjects.

The environment simulation was largely about water. Water flows downhill from springs. There are seasonal floods and droughts. Water moistens the soil (which affects farms and trees). It evaporates. It is absorbed by plants. It destroys towns. Flowing water picks up sediment and deposits it in other places, creating erosion patterns. Add simulation of energy and momentum, and I got some really interesting patterns. For example, water picks up sediment on the straight parts of a river then deposits it on the inner bank of a curve, creating meandering rivers and oxbow lakes.

For gameplay, I wanted a continually changing surface. In SimBlob, continental uplift followed by soil erosion happens not only during map generation but also while the game is being played. Soil erosion rates vary by area; it's higher on mountains and near towns and lower in deserts and on river banks.

Vegetation was modeled in two ways: plants and trees. Plants are entirely based on elevation. Low elevation gets plants; high elevation does not. Trees are much more interesting. Trees would grow over time, and older trees would spread seeds to nearby tiles. Seeds sprouted if the soil was moist. Fires spread across the landscape, damaging forests.

Volcanos would spread lava, which flowed downhill and then hardened into new land. Lava also set fire to any nearby trees. Volcanos are part of the map generator but can also be triggered in the game by the player.

Algorithms - economic

Writing the economic system led me to learn about economic geography, including location theory, central place theory, and economic rent. The model is: Farms generate food; Houses generate labor; and Markets bring them together. Farms need to be near water and roads. Houses want to be near other houses, but also like water. Markets need to be near roads but away from other markets. Markets and houses are more valuable near the city center. The first economic system automatically built roads where transportation was needed; it generated neat fractal-like patterns. My later economic system required the player to build roads, as I was moving away from pure simulation and towards having a playable game.

The simulation was based on a resource flow model. Resources flow from sources to sinks along roads. Food flows from the market to houses. If there's excess food, blobs move into houses; if there's a lack of food, blobs move out of houses. Labor flows from houses to farms, and houses to markets to farms. The more laborthere is, the more food is produced.

The intended effect was for land near the town center to be more valuable to markets than to farms. At a medium radius from the center, houses are more valuable than farms, and there are just a few markets. On the outskirts of town are the farms. As the town grows, tiles near the center would switch from farms to houses to markets. It's a nice simple model that leads to pleasant towns.

The job system for builders was rather bad. Each builder blob would accept up to 6 nearby jobs, but this greedy algorithm wouldn't consider cases where another builder was better suited for the job. The code is messy. It worked fine for a single builder but worked poorly when there were multiple builders. If I were approaching it today, I'd look at algorithms for the Assignment Problem.

The original implementation of firefighter blobs used an influence map to "follow the heat". I was a big fan of influence maps. However, it didn't work that well, because after a fire was put out, it took too long to propagate. Also, all firefighters would end up going to the same place (I hear this is a problem in some other games too). I changed it to an algorithm that divides the map into regions, and chooses regions based on the number of fires and firefighters already there. That worked much better.

I have a lot more notes written up here.

If you want to try out the game, I've made it run in a web browser.

Conclusions

Working on SimBlob was great for me. I learned a lot about science, economics, simulation, and programming. I learned that finishing a game wasn't as interesting to me as understanding a topic and writing about it. So that's my site's "origin story": SimBlob is the project that led to the original game programming topics covered on my site.

Labels:

3 comments:

Chris wrote at June 13, 2013 2:14 AM

I've been following your site for many years, and I must say it's been inspiring. Thanks for sharing your experience and knowledge. I hope one day you do finish a game based on these ideas. Maybe Minecraft on crack?

xaminmo wrote at June 13, 2013 12:32 PM

I've always liked your attention to detail in the economics of empire building. Obviously, fancy graphics are not entirely necessary when the gameplay is detailed and good.

Amit wrote at June 15, 2013 6:41 AM

Thanks Chris! Water flow is a fascinating and fun game element. Minecraft and Dwarf Fortress and Terraria have their much simpler versions, without erosion, momentum, energy, sediment. A lot of times, the simpler thing is better. It's easier for the player to understand and it's easier to implement. :)

When I look at the games I'd like to work on, they almost all involve building things to harness and alter flow, not only of water. For example this warehouse game idea is about building sorters and other devices to alter the flow of goods flowing along conveyor belts.

Part of what's keeping me from writing a game is that it's both more useful and more straightforward for me to write a tutorial. But this project reminded me that the topics for the tutorials come from games, and that means I need to work on new games so that I have materials for future tutorials. :)

Thanks xaminmo! I agree that fancy graphics are not entirely necessary but they can help in making games more appealing / accessible. For the most part I think I will stick to 2d graphics for my projects. With my 3d projects, I found that I spent the time on graphics instead of gameplay…