Highly complex, in-depth, system simulation is like a siren song for game developers and players alike.
There's this perception that an amazing simulation will be the basis for an amazing game.
In practice, high-quality simulations seem to be interesting but not all that fun. See: F.E.A.R.'s Goal-Oriented Action Planning (https://alumni.media.mit.edu/~jorkin/goap.html) which had to be modified to broadcast its intent to the player, because play-testers felt the game was unfair and that the A.I. was cheating.
And it also seems like players can't really tell the difference between a sophisticated simulation and a handful of heuristics with some calls to random() thrown in. From the perspective of a player who does not know how the simulation works, the latter can _seem_ like the output of a complex system. See: _Designing Games_ by Tynan Sylvester, developer of RimWorld (https://tynansylvester.com/book/).
Dwarf Fortress, I think, is the exception which proves this rule.
Anyway, I think simulations like this are really cool to build, but hard to turn into a fun game.
And I would argue that Dwarf Fortress is no exception at all. In all of my time with the game I've enjoyed the idea of the game more than I actually enjoyed playing it. This is the player side of the simulation siren song. The more time you spend with it, the more you understand how it works, the more you realize how incredibly unbalanced it is.
The game's legendary difficulty is entirely due to the impenetrability of its user interface and systems. When you actually finish getting through all the tutorials needed to learn how to play the game it falls flat on its face. It is quite trivial then to get a fortress up and running and produce far more food, drinks, and goods than you ever need and grow your wealth rapidly. And then when the enemy comes knocking it's quite trivial to pull up your drawbridges and line the entry halls with traps and generally grind them into a smooth red paste.
Dwarf Fortress may be a fine simulation and an interesting study in systems and a great conversation piece but it is not a very good game. It is like the Great Salt Lake of games: a hundred miles wide and a few feet deep.
> It is quite trivial then to get a fortress up and running and produce far more food, drinks, and goods than you ever need and grow your wealth rapidly. And then when the enemy comes knocking it's quite trivial to pull up your drawbridges and line the entry halls with traps and generally grind them into a smooth red paste.
I'd say that the point of this kind of open-ended simulation game without a clear goal is not to "win" since there is nothing to win, but to create your own challenges.
I've played a lot of these games and from Civilization II to Dwarf Fortress, just winning by using the game weaknesses has always been very uninteresting, but building a world-class city-state on an island or an above-ground wooden fortress without digging, for example, are challenges that you can create for yourself and that make these games interesting to play.
Since they are single-player, I find just "mastering the game" to maximise end-game score to be quite pointless, but that's just how I feel of course.
Sounds like the problem is that you basically cheated your way into boredom by reading all the tutorials and player guides first. The most fun I ever had with DF was just going in blind and thrashing about trying to discover how everything works which generally resulted in spectacular failure. The fun of a complex system is in learning how all that complexity works. Once you know everything about it it loses its appeal.
You can not like a game without saying that the game in general isn't good. It's been around for more than 10 years, and seems to be getting more and more popular, not less. The community grows, and development continues. Countless of people do find it fun, which is the most important part of a game, otherwise you won't play it.
By most metrics, Dwarf Fortress is a good game, despite its impenetrable UI and UX.
We'll also see how well received the game will be by mainstream gamers once they're done with the new UI, as it'll attract a bunch of new players then.
You should really try Rimworld. He took the concept of Dwarf Fortress and perfected it. The systems are incredibly well balanced, and there is less of an emphasis on "industrialization", and more of an emphasis on scheduling of tasks for your workers. So that even once you have a fully functional colony running that is able to overproduce food and fend off any attackers, you then have to deal with the interpersonal and personal emotional issues between your workers to keep things stable.
I really think those two games are in different genres. DF isn’t about perfecting some kind of dwarf version of a factory. It’s computer assisted world building. The point is to create interesting history, locations and items which you then recount as stories or you explore in adventure mode. I’d like to see DF grow further with more interaction with the world. It would be amazing to eventually have something capable of building an entire fantasy world with that you could then explore.
For what it’s worth, I feel the same about Eve Online. You hear these amazing, rich stories of political intrigue and massive battles but I’ve found it incredibly tedious any time I’ve tried to get into it. I do think there’s something powerful in these engines of story creation, and maybe this is some of Twitch’s appeal, but a lot of these games aren’t for me. I guess the Odyssey would have been a bunch of walking about if you were there.
The concept of Second Degree Fun applies here, although I think it should be called second order fun. Semantics aside, first order fun is something that you enjoy while you’re doing it. Second order fun is something that may be unpleasant or boring while you’re doing it but turns out to be enjoyable to recall or tell others about after the fact. A lot of life falls into the latter category.
>The game's legendary difficulty is entirely due to the impenetrability of its user interface and systems.
It's also a cultural legacy left over from early versions that were more challenging but less open ended simulations.
In particular, farming required setting up an irrigation system, which required exposing your fortress to a river that occasionally spawned hostile creatures which would disrupt farming. Coupled with winters where farms went fallow, it was much easier to lose a fortress for want of basics.
Additionally, there was a progression involved where access to better metals meant digging deeper and exposing yourself to additional hazards generated from fratures deeper inside the mountain.
Most of these dangers went away in the newer system, and what other dangers were added can often be avoided more easily.
With that said, the older versions also had a lot less replayability. Once you knew what you were doing, each fortress mostly played out the same, but it did make for better progression for someone new looking for a challenge.
> It is quite trivial then to get a fortress up and running and produce far more food, drinks, and goods than you ever need and grow your wealth rapidly.
At that point it turns into a big-system management game with a variety of mechanisms to trip you up, starting with the raids and megabeasts attracted by wealth, vampire infiltration, cranky nobility, and other ways that your system turns self-destructive.
That doesn't make it a great game — it can be incredibly tedious — but, it sounds like you played until you reached prosperity, and just declared the first 1/3-of-the-game-tops as too easy.
Every game is going have some aspect that is out of balance, and if you leverage it enough then sure it’s going to be easy. I remember might and magic 3 you could work your initial party to an old age, then fire them all and keep their earnings, then pimp out your new party with platemail and magic swords. It made the game super easy and boring, but that was my fault for playing that way.
If you’ve found a way to play the game that isn’t fun for you, just don’t play that way. Add a restriction for yourself to make it more interesting.
The best simulation games are those that have done a good job at giving your systems a purpose that requires using what you have built. One such game is Factorio. It's a logistics and manufacturing simluation at it's core, but they gave a half decent attempt at making a story and antagonist that makes your factory have a purpose outside of just building the factory.
Another great example is Stormworks: Search and Rescue. There's no shortage of lego-like vehicle building games, but Stormworks gives you the purpose of completing various search and rescue missions with your vehicles. From that, you suddenly have practical reasons to build things certain ways. I can build a boat in a few different games, but only in Stormworks would I need to build a boat that can extract a piece of mining equipment from the sea floor and have provisions for delivering it onto a wharf.
>because play-testers felt the game was unfair and that the A.I. was cheating
the F.E.A.R ai is still amazing to me after all these years. I'm surprised by the play tester reaction because even without the broadcasting of intent I think the AI felt very organic. Honestly still one of the most convincing ones to this day in shooters.
It wasn't just about the play tester reaction. Other benefits of broadcasting:
- Sometimes AI characters can't act on their knowledge in a way that is obvious to the player, so they might seem more dumb than they are. The fact that they can vocalise their knowledge even if they can't act on it makes it clear that they are more intelligent than they appear.
- By vocalising their knowledge about the situation, fortuitous incidents will more easily appear like consequences of AI direction, even though they were not actually related. (Narrative bias in the human.)
- Since the AI actually works with a shared mind, it can seem unnatural that each AI character knows what all the others are doing without any voice communication.
> Since the AI actually works with a shared mind, it can seem unnatural that each AI character knows what all the others are doing without any voice communication.
Isn't that an argument for simulation of the type citybound is doing, rather against it? Even the dumbest most "gamified" AIs can have that fault. E.g. think about the enemy AI in Far Cry.
In essence, yes, "the AI" as one whole just shouts out what it is doing. What's sort of neat is that since all AI characters share one mind, they can have one character give orders to another, which then appears to comply – even though it was effectively the character that was going to do the thing that decided to do the thing in the first place. In other words, the "order" is just "the AI" telling itself what it's doing – but it looks to the player as though one AI character instructs another on what to do, and the other obeys.
Haha, yeah, I wonder if they at least designated a ‘squad leader’ that was the designated ‘order giver’, or whether it was always a random nearby soldier.
I guess it doesn’t matter from a game perspective since I never noticed, but from a technical perspective it seems more elegant to me.
Not every game has to be fun in the common sense of the word. Flight simulations are another example where you spend dozens of hours to understand how to fly a plane correctly which is much more like work.
There are just different kind of people who like different kind of experiences.
On that same note, they tend to underestimate the time it takes to develop a good complex simulation, like DF, when it has taken like 10 to 15 years to get to the level of detail DF has. One developer isn’t usually going to be able to develop that much complexity in a few years or something, it’s gonna take a while.
> heuristics with some calls to random() thrown in
I've come to see one aspect of game design as "shaping randomness into more interesting and artistic forms". Just a plain rand() call is sort of interesting, you never know exactly what you're going to get, but with some art and careful shaping it can be made much more interesting.
Also consider that random will give you random. A lot of things can be better if they follow different distributions (e.g. gaussian or a bounded random walk)
The Football (nee Championship) Manager series is one of my all time favourites, and is effectively just a bunch of spreadsheets about football players and teams. It has the advantage that the numbers underlying the simulation are also interesting enough to form the majority of the UI. In some ways it proves your rule though - for a long time there was no actual visual match engine so you couldn’t watch your team play, and it was every bit as addictive back then.
I agree about the siren song aspect, and how full system simulation is very non correlated to fun, but I think it’s one of those things where we haven’t seen the full potential yet - we’re still maybe a few computational leaps away from it.
Kind of like ray tracing, or voxel worlds; for the latter, Minecraft was a great example of a first game meeting that “computation required” vs “fun” slope intercept; Teardown is a more recent game that uses its voxel engine to enable novel gameplay that would be totally infeasible without it.
> In practice, high-quality simulations seem to be interesting but not all that fun.
I think a great deal about good games is the communication of their black box of rules and mechanics. In a simulation this is especially hard, as much to communicate, and they are usually created by more techno-orientated people, which simply suck at these things. So the player is confronted with a highly complex world where things happen, but for the player it's not always obvious why something happened, which impact their actions have, and sometimes they don't even get that something happened. Thus, giving players a way to explore the rules of the simulation, and understand the state of the world they are playing, is far more important in a simulation because of it's complexity.
Forcibly coding heuristics is how you get suburbia simulators like cities skylines. The heuristics reward car centric designs because you need to build dedicated pedestrian pathways for the AI heuristics to pick up the intended change. Your city will get to look very ugly.
The project is currently on a hiatus because I’m focusing on building a startup, but Citybound is an will always be my 100% passion and “anything goes” research project.
I’m not on a computer today, but I will try to get back to everyone who posted in this thread.
If you have any other questions about the project or the tech please just reply to this!
(Side note: the main way I built a wonderful community for Citybound was to directly reply to each and every comment whenever it got interest somewhere - a tactic I can highly recommend)
I had one person join as a significant contributor for a while early on. Unfortunately life circumstances brought us apart, I only reconnected with them now after many years.
There were a couple other direct contributors to the code, which always made me really happy, but the idiosyncracy of the codebase made it hard for others to contribute more than housekeeping/refactoring.
The rest of the community contributed through lots of in-depth discussions, ideas, what-ifs etc. I'm really grateful for all the interest and thoughtfulness my community always displayed.
Im working on a game in the same vein: Archapolis, a city builder with real time traffic simulation and interior views of your citizens homes (which you can customize/build yourself if you want), so you can watch them live their lives. I'd like the player to have a more hands on approach to managing the city as well.
I created a path finding algorithm that can simultaneously path hundreds of thousands of units to random destinations at a comfortable frame rate (or around 100-200K like in the video using one CPU core). Units can choose from any of the shortest paths between two points (there are many in a grid), and from those paths, can also choose the path that matches any preferences they have.
I’m confused. The game says 55 fps, but it looks like 4? Is it just computing positions at a lower rate while rendering at 55?
Anyway, from my experience with Songs of Syx, which also has large scale pathfinding, I’d like to encourage you to find a way to spread it (and other calculations) around. When you reach larger city sizes, the game becomes noticably slower on some ticks. Still smooth, but when your guys are moving at 4x speed, and everyone suddenly slows down to 2x speed (presumably because calculations take so long that running at 4x isn’t possible any more), it’s very jarring.
Right now the units are moving in tile-sized increments. I'll be implementing floating point movement soon. I move the map around while the units are moving and you'll see its not at 4 FPS.
I think with any quasi-infinite growth game, you are going to run into a problem of it slowing down, eventually. That's what inspired me to create this algorithm. I wanted a game that could scale, and traditionally path finding is a CPU intensive task.
The video I linked is out of date, I'll be making a new one soon.
Now: building the path finding graph is now stored in a vector (i.e. array) instead of an unordered_map (and still has constant time access/find). This cut CPU cycles by 66% since a vector doesnt use linked list/pointers/store a hash, and reduced RAM requirements by 75%. Then I parallelized that part of the code base.
So for my 6 core machine, I can find all the all-pairs, all-possible shortest paths in a 50 x 50 grid of roads in 10 seconds. This is about 13 square miles of city if each block is the size of a Manhattan block. I'll be working around this time by implementing a planning mode so it only updates as needed.
Currently I can close edges (i.e. an individual road between two intersections), but right now I would have to rebuild the path finding graph each time the graph changes. I was thinking of this problem too, cause it would be really cool to temporarily close a road down for repairs/construction. I think there is a way to make it work without needing to rebuild! Just havent had time to look into it.
The way I did it in Citybound is to assume that the graph constantly changes anyways (also because the player can add/remove roads quite rapidly) and route the cars more like packets on the internet than with static A*-ish algorithms.
That way, road nodes can propagate changes locally.
Interesting, I assumed the roads were not going to change frequently (but rather, in bursts). So I used that premises to develop my algo. To enforce this behavior (on a code level), I will be adding a "planning" mode, where roads can be placed freely/frequently. Once the user sends the plan off to be constructed, then the graph will update. I may go one step further and have construction (i.e. graph updating) only happen at night, and give the user something else to do while its updating.
That being said, if they have a modern machine, then there will be no need for this at all (just need to figure out the avg user CPU GHz & core count). It takes 10 seconds for my algo to find the all pairs/all possible shortest paths between two nodes on my machine for 10,000 nodes, which by that point is a HUGE city.
The reason I did not go with A* is because it doesn't scale to 100K+ units and it always chooses the same path.
That's a shame, seems like a cool idea. I wish the open source community was a bit better at open project management and more resilient to projects going dormant like this.
And Cities Skylines was a better game that used an actor based model released shortly after. Some of it was an evolution of their entirely transport focused Cities In Motion series, and some of it a reaction to Simcity 2013.
Shameless plugs for the two games I created, incoming! Both games use an "actor/agent" -based AI.
The AI is driven via needs-based utility scoring & heuristics, and action/object selection uses attenuated-delta scoring; this creates agent behavior that is "opportunistic". The AI itself is largely based on prior work, substantial portions of which I believe can be (at least largely) attributed to Don Hopkins, who I see posting here pretty regularly. :)
Do you have any good reference/links for wanting to learn more about implementing or doing something with utility scoring and heuristics? Or any of the tech behind those games?
I'd played SimAirport but would love to learn more about the tech because I am a hobbyist gamedev
One thing makes me wonder: supposedly the fancy simulation models are supposed to make the game feel more realistic - but then the player still seems to have an extent of control that no mayor or other single individual would have (in democratic societies at least)?
There's a lot of fiction in these games in order to make them fun.
If you had to deal with committees, contractors, NIMBYs, and real human cost of bulldozing houses for highways, it would have been a completely different game, likely a sad and frustrating one.
City builders also start from an empty free land, even though true greenfield development is very rare. SimCity has famously ignored the problem of parking, because it made cities look depressingly ugly. Even in Cities Skylines people pull cars out of their pockets.
I built a minimal city sim in HTML+vanilla JS a couple years ago and similarly used a "microscopic transport simulation" (you can see roads get "redder" as traffic increases during peak times) and a similar model of having households seek out their requirements. Everything on a much smaller & simpler scale obviously, but clearly I've though about how neat it would be to see something larger along these lines. This project looks like exactly that. Absolutely love it, will be following closely and hoping it matures into something wonderful.
How does one do simulation without synchrony and some kind of global clock? Actors and message passing aren't sufficient; at the very least one needs causal ordering, and even that won't be enough, I suspect.
This is the problem dealt with by the field of parallel and distributed simulation [1]. The two basic approaches are to either block the receiver until you can guarantee that a received message will not be displaced by one with earlier timestamp (conservative algorithms) or to speculatively handle messages and roll back if an earlier message ends up arriving (optimistic algorithms). If the simulation is stepwise, life is little bit easier compared to arbitrarily timestamped messages, but even then the questions of a "correct" ordering and the handling of conflicts must be dealt with. It's a pretty rich field, partially due to the often-unpredictable runtime behavior of simulation models and the challenge of balancing the generality of the algorithms with their efficiency for particular problem domains (such as the agent-based simulations discussed here).
It won't, true, but that's not the point. The question is what order does a receiver process messages received from multiple senders. Please see the response to the other poster in this mini-thread.
A sends a message to "x = 2" to B and C.
B receives this message and sends "x = 3" to C.
Now, C receives two messages one from A and one from B. It could receive them in any order. However, there is no way for it to tell whether there is a causal order or not.
With a clock embedded in the messages, one can state that "x=2" happened before "x=3". (or more strictly, "x=3" def did not happen before "x=2").
Extending this, if C and D receive copies of the above messages from A and B, we want C and D to both process them in the same (deterministic) order.
Besides that it's a very synthetic example that I don't think makes sense in the context of a city simulation, I think that it's also a bad design. You shouldn't have multiple authorities on the value of x, C shouldn't rely on both A and B to get a value for x.
In the context of a city simulator, every road segment could be an actor, as well as every simulated vehicle. Two vehicles might try to enter a road segment at the same time, so they both send a message :enter(entity_1) to :road_segment_1. Then the :road_segment_1 actor decides what to do with those messages.
Structuring it this way allows you to massively distribute these kinds of simulations, which is exactly why citybound attempted an actor-based approach. There's a load of overhead, and there's still issues with buffers and backpressure, but in theory you could infinitely scale a simulation this way.
It isn't a synthetic example at all. We want two receivers of the same set of messages from the same set of senders to process them in the same order. Determinism is of utmost importance.
In your example, the vehicles' messages have no causal relationship; they are concurrent. Order does not matter. However, for the sake of determinism in a simulation, the above constraint is necessary even for concurrent messages.
For me, determinism is a fundamental property to be aimed for, to build testable and repeatable systems, whether they are simulation engines or real-world systems.
For example, one of the projects I have worked on is one of the largest trading engines in the world, with high concurrency. To make it testable and fault-tolerant, all incoming messages are timestamped and handled in time-serial order. The same timestamp helps with idempotence.
When testing the engine core and downstream systems, a previous day's test data can be input in timestamp order (instead of concurrently), so that we know the behaviour of the system in the face of a fix.
Dataflow systems (which is most software) should be idempotent and deterministic. If random() is called, then fixing the seed should make it deterministic.
The only reason your system needs to be deterministic is because your company is afraid. If it wasn't afraid and instead just interested in making an accurate model of reality, it wouldn't be interested in determinism.
Basing the behavior of your simulator on yesterdays data is a neat trick, but it has no relationship to the actual world. Not in a million years would the exact same market behavior of yesterday happen again.
Instead of building it deterministic, you could simply run your system a hundred times, and maybe purposefully mess with the timings to make execution more non-deterministic. And instead of a precise number "yesterday we would have made X amount of money with our trading engine", you would come up with a distribution that is much more predictive of the future "with market circumstances similar to yesterday we would have made between X and Y amount of money with our trading engine".
Anyway, I don't work on trading systems so I probably shouldn't tell you how to do your job. This is just how I see simulation systems.
> The only reason your system needs to be deterministic is because your company is afraid
With good reason. It is called caution. We're talking about a nation's economy.
You misunderstand me about the reason for running yesterday's or any other day's full load. The idea is that after you have made a bug fix or a performance fix, you want to see that the output reflects the fix; the best way to do that is do a diff with yesterday's output given the same input, and one should be able to ensure both correctness (all changes accounted for) and completeness (all the input tuples that ought to reflect a difference do reflect the correct difference).
Given that there are a hundreds of thousands of events a second and terabytes of data, it is impractical to run a test 100 different ways. Besides, how do you know you got it correct? Events are not commutative because there are limits. Deposit is not commutative with Withdraw, because Withdraw can throw an OutOfMoneyException. Order matters.
Please refer to [1] Parallel and Distributed Simulation, fig. 9.4, pg 265 for an example of an anomaly introduced by the lack of a total order. The text also covers why it is necessary to have a model of time; it is not enough to have agents sending messages to each other and let them duke it out.
Ah you're right, I misunderstood. In your simulation you actually already know what the result of the simulation has to be ahead of time and you're just verifying the system arrives at that end result. That's very different from the type of simulation of citybound where they're actually modeling the behaviour of all the actors, and as long as none of them violate any invariants it doesn't matter what the end result is, any result would be correct.
When you said financial simulation I thought you were modeling the behaviours of actors in a market, and how your system would trade against those actors, but what you're doing is more like banking or an exchange?
If the only non determinism is in the message passing, then recording and replaying the receive buffer should look exactly the same between your system and city bound, without forcing an ordering — replaying is itself eliminating the source of non-determinism. So testing should look exactly the same.
Rand() and friends obviously needs to be handled appropriately but as long as you have only one owner of data (and thus one writer), by passing messages of the form “try to add 1 to x” rather than “x=5” or “add 1 to x” message-queues have a strict ordering by nature.
It's always interesting to see this approach. It's becoming more common now with more capable hardware but never seems to quite fit as it requires so many inputs and the emergent properties can be unpredictable and cause issues with the main game loop.
I've thought about building a more generic system to simulate characters that can be plugged into many of these open-world and other games that need activity to fill cities and locations.
For realism, whenever road work is being done they should block off the area for 6 months without a single worker ever being present before any construction begins
They should have different modes for different states. In California, the plots should generate more tax revenue when being built, and there should be a 75% chance the owner is bankrupted before it breaks ground.
After completion, basic things that should have been checked by inspectors should go horribly wrong. (Electrical fires, sewage backups, landslides, etc.)
There should be an optional environmental tax that doubles revenues and construction times, but causes massive environmental damage about 25% of the time, and attracts the mob, regardless.
In other places, like rural Texas, there wouldn't be any building codes or zoning in unincorporated areas, and you'd need to maintain a fleet of aircraft to enforce property taxes. 75% of buildings would just fall over every few decades.
In Texas, the entire power grid would collapse periodically. In California, there would he weekly brownouts in rural areas, and natural gas exlosions would sometimes destroy entire city blocks. When this happened, PG&E would get to arbitrarily raid the government coffers, and funnel the money into organized crime.
(Not particularly, but the dev did not even make a working prototype in JS before getting in on the Rust hype-train. He wanted to work on cool actor models, complex systems, et al and over-engineered the project. I have nothing against him. It's his project and he gets to decide what it becomes.)
(He did go though a hard time - working fulltime (I think) on this for quite a while, not having a great work-life balance, etc)
> A much simpler, but faster version of some of Erlang yes. It was a huge inspiration. If I hadn't done some stuff in Erlang before, I would never have invented this architecture, and probably would never get the idea to do multiplayer.
There's this perception that an amazing simulation will be the basis for an amazing game.
In practice, high-quality simulations seem to be interesting but not all that fun. See: F.E.A.R.'s Goal-Oriented Action Planning (https://alumni.media.mit.edu/~jorkin/goap.html) which had to be modified to broadcast its intent to the player, because play-testers felt the game was unfair and that the A.I. was cheating.
And it also seems like players can't really tell the difference between a sophisticated simulation and a handful of heuristics with some calls to random() thrown in. From the perspective of a player who does not know how the simulation works, the latter can _seem_ like the output of a complex system. See: _Designing Games_ by Tynan Sylvester, developer of RimWorld (https://tynansylvester.com/book/).
Dwarf Fortress, I think, is the exception which proves this rule.
Anyway, I think simulations like this are really cool to build, but hard to turn into a fun game.