This week I’ve pretty much finished off crowd mechanics for cities. I’ve also been working on the lower tiers of clothing, and the middle-class clothing looks great, but the lower-class clothing needs some work to be aesthetically comparable to the upper/middle equivalents, so I’ll show that off in a future entry. Right now, though: crowd mechanics are done (or cities), and that’s what we’re going to talk about here.
Permissions (and Guards)
Each tile of the human-scale in the game now has a variable called only_allow – this lists the permissions required to enter that tile (if the list is empty, than anyone can enter it). For example, we might have (“Religion”, 25) which means that believers of the religion with the “25” id can enter it, (“Family”, 6), and so forth. Sometimes I’m sure these will overlap, though currently they do not. At the moment these restrictions exist on upper-class mansions (where only that family and its allies can enter), warehouses in shop districts (so that random citizens don’t path towards them for no reason), religious buildings in religious districts (where only believers will enter them, though I suppose very occasionally someone from another hostile religion will…?), embassies in city centres (which are heavily guarded), and military districts per se. I’m sure some others will appear in the near future, but those are the only permissions in the city so far. As well as the existing crowd mechanics, I’ve also begun to write the code for guards who are tethered to a given permission, and are alerted if/when that permission is violated, and will act accordingly – but this isn’t a crowd mechanic, and isn’t finished, so we’ll talk about it more later. Here’s a simple example of a permissions diagram for an upper class district along with the outside of that district, where the areas inside walls for each of the major families is blocked for any outside that family (I will be adding in “lesser families” this release and giving them appropriately less-impressive crests). It’s simple, but effective (the other houses around the edge are wealthy, but not wealthy enough to merit guards, “territory” in the district, etc).
Irrelevant and Branching Roads
The NPCs on roads now avoid (for the most part) roads which go nowhere, and if they do go down a road which goes nowhere, they know that and will generally branch off and move towards their own target outside the road system. Equally, NPCs will no longer run in circles sometimes (a major improvement, as I’m sure you’ll all agree) and won’t branch onto tiny pieces of road. They can also cross each other intelligently without losing their sense of direction – in an earlier version two NPCs walking around each other would sometimes get “diverted” by the act of stepping around each other and wind up changing direction. Many of these irrelevant roads are also connected to permission-based areas as in the above section, and this is obviously a system I’ll be developing in more depth in the future as NPC/player relationships and factions become more complex. So this is the district from the above diagrams, where the light green roads can be walked by anyone, and the dark green roads either cannot be walked, or will only be walked by those with appropriate permissions or pathfinding objectives:
Moving Off-Road and On-Road
As above, NPCs can now sometimes decide to move off the road to find their own targets. They’ll do this if they see themselves approaching a dead-end road, and they’ll sometimes do this anyway regardless of what kind of road they’re on. In these circumstances they either select a region of the map where there is nothing in particular and path to there, and then continue pathing from there to elsewhere if the player is still viewing them (or despawn if they’re out of sight), or they will choose to path towards a specific door (which they have permission to enter) and then go through that door. As the below gif hopefully shows, this makes the movement of NPCs appear far more organic and stops NPCs looking like creatures just being channeled down the road with no ability for doing their own thing. We’ll obviously see how this works once we introduce important NPCs who have their own non-crowd objectives, etc, but you can see it pretty well in the gif in the section below…
The game can now generate appropriate “crowds” who might move around. For example, a civilization with the “Theocracy” and “Vassalage” ideologies might decide to have priests moving around their city, escorted by priests. A civilization with the “Monastic” (new to this release) and “Conscription” ideologies might enlist conscripts to escort high-ranking monks safely. Equally, there are some more general groups – groups of clerks and diplomats in the city centre, groups of general humans in any area, etc – who can also spawn in any nation regardless of their ideological preferences. Here’s an example of a priest and a few general citizen followers moving around a district – one will also note that certain skin tones are surprisingly hard to see against the road’s background colour. On the one hand, all roguelikes which expand their colour schemes a little bit (e.g. DF, CoQ, etc) will sometimes have certain colours which can’t be combined well, and whilst it’s annoying I’m not sure if there’s a solution; but on the other hand, maybe there is some solution? Change the road colour to make it more grey so it always stands out against all skin tones? I’ll ponder it. Either way, this gif starts with a priest (‘p’) being escorted by a bunch of soldiers (‘5') moving around the corner around this religious building. I then just let it play on a little longer to see the slaves (since this is a slaving nation) wandering about. Note also that the game ensures the priest is “leading” the little convoy, since I had some problems with the leader’s escorts dancing around in front of the leader due to a quirk in the pathfinding system.
I’ve also implemented a system where “parties” (in the “group” sense of that word) can spawn more organically around certain areas – these include parks and gardens, around taverns, around markets, and in graveyards. In this case a number of NPCs from all over the map will path towards the area and then basically “hang around” for a while, before then making their way off. I’ve found around some places it gives an interesting feeling to these areas when you just sit and watch, and although I’m still working on exactly balancing the algorithm so that the ebb and flow of NPCs is exactly how I want it, this gif from a city centre garden is *fairly* illustrative, though it still needs some tweaking. And bear in mind, of course, one isn’t generally going to be waiting around to see the grounds form and un-form, but I’ve just stood here for this example so we could see groups forming, growing, and then disbanding.
I’ve also implemented a system for spawning appropriate demographics of NPCs (and their clothes, items, etc) for each NPC who spawns in each district. This comes down to three things: NPC type, NPC wealth, and NPC “distance”. To explain this slightly better, let’s have a look at this diagram, newly added to the in-game Guidebook (‘?’ to access). This is (currently) the full set of possible NPC types which will be able to spawn in the game:
So, NPC type is the “class” of NPC – we might want general humans to be spawning in lower-class housing districts, classes of soldier to spawn in the military districts (who I intend to give patrol routes to, but that hasn’t been coded yet), clerks and diplomats might be spawning in the city centre, and so forth. Capital letter NPCs will be specially tracked by the game, whereas lower-case NPCs make up the crowd. Also, nations which keep slaves will spawn slaves in the appropriate districts, just as nations which have eunuchs will spawn a very small number of those unfortunate individuals around the place. NPC wealth, meanwhile, means currently the quality of their clothing (and, in the future, the quality of any armour, weapons, bodyguards, jewelry, etc) – this is obviously closely tied to the district that the crowd NPC is spawning in, but with some variation. Middle-class districts spawn mostly middle and a few lower wealth NPCs, lower-class districts do the reverse, markets spawn an even mix, and so on. NPC distance, lastly, relates to whether the NPC spawning is from that nation and from its capital; from that nation and from a distant town or colony; or from a different nation altogether. Currently everyone who walks around in a city is from that nation (though I will of course later add groups from other nations) but might be from different regions, so you’ll see people who are culturally similar – clothing, hair style, etc – but physically different (skin tone, hair colour, eye colour, etc) as they come from different areas of the same nation. The game picks all of these according to a range of factors, and then spawns a mix of NPCs appropriate for the crowd in a given nation.
Bugs and Issues
In this process I ran into a bunch of bugs and issues. Firstly, for some reason, saving and loading the game would cause the AI for each NPC in the crowd, and the NPC itself, to become disconnected so they no longer referred to each other, meaning that when I tried to delete “self” from the list of NPCs when a given NPC no longer needed to be around, it couldn’t find self, and crashed. Weird. I tried to find a proper solution to this issue, but in the end I just changed it so that the scheduler only referenced the .npcid of each NPC, rather than the NPC itself, and that meant that even if some byte somewhere in the AI changed itself in saving/loading for reasons I could not divine, the npcid was always remaining the same (being a variable, not an instance of the AI class attached to an instance of the NPC class), and so the game could always identify the correct NPC and AI to delete upon reloading. Similarly, moving on the human-scale from district to district made some weird errors like massive groups of NPC suddenly spawning and NPCs from the next map tile teleporting into another map tile, but those were all quickly fixed. Some maps were also coming up with extremely rare tiles which didn’t have a .roadmarker variable, which denotes what NPCs are/aren’t allowed on it and whether it is a road curve which should be treated specially, but that was due to another bug I hadn’t even noticed involving the types of terrain spawning under trees (we had some trees spawning on road tiles!). This has all been sorted, and it all runs extremely smoothly. Additionally I noticed some unnecessary variables were still stored on every tile in the human-scale maps, so those have been removed, and save files have been reduced by around 15% as a result, with an attendant (very minor) improvement in load times!
Well, the next things to do are to extend this outside cities. I need to get NPCs behaving sensibly in slums, graveyards, villages, fortresses and tribal settlements, each of which is going to need some unique changes to the algorithms I’ve worked on for cities. After that, we’ll be moving onto handling NPCs within buildings (and entering/leaving buildings), which is obviously extremely imporant. Then we’ll be moving onto unique NPCs who are specially tracked by the game because they matter (merchants in shops, rulers, nobles, etc) and who therefore need to be able to move around the world. These three steps are my three primary goals for the rest of July (it’s a lot, but I think I can crunch it), then in August I’ll be moving onto finishing off clothing styles (we’ve got feudal clothing almost finished, but I need to add military clothing, religious clothing, nomadic clothing, and tribal clothing, so there’s still a ton to do on that front!) and adding in a conversation system to the game. This system is going to be essential, so I really need to think hard about how the conversation system should work, what the balance is between the hand-made and procedural, etc. Then I need to redo how families and allegiances/associations work, fix a bunch of minor bugs from the last few versions which continue to stack up, and then 0.8 will (amazingly) be pretty much done. Aiming for a September release currently, which is around the time I’ll be starting a new job I can’t yet formally announce, and probably starting work on the other secret project I also can’t yet announce (both game-related, though!). Exciting times! Let me know what you think of this week’s development, and I’ll see you all in seven days…