I like designing new code. Especially when I’m starting with a blank slate. I’ve got the initial framework for AI built now and am slowly testing ideas and fleshing it out. I went through several iterations of design, and I’ve ended up with something I think will work, and that can grow as the game does.
(The bad thing about new code is it generally doesn’t come with screenshots or videos of cool things right away…)
Before designing anything, or writing any code, I went through a bit of time just writing down what I’d like the AI to do in the game. I’m going to list some of it here, plus some of my vision for what the game will be, but remember, game design is fluid and not all my ideas will necessarily end up in what I finish.
What I’m trying to explore this time is a colony simulation that is higher in detail than Banished, with a smaller set of villagers. This includes things like beds to sleep in, each villager owning equipment that’s stored somewhere, and having skills unique to each citizen that are needed to make the village work. I’d like to slow down the simulation to days, including time to sleep, rest, work, and join in town festivities, like weddings or annual celebrations.
So here are some things I’d like to see.
Let’s say a villager wants to paint her stone house white. But she doesn’t have a painting skill. So she’ll let the village know what she wants. If there’s a painter in the village, he’ll do the job, but there might not be paint. So he’ll let the village know there’s a need for paint. The worker that makes paint gets to work gathering limestone, or white clay, or white flowers, or whatever it ends up being ingredients. He’ll make the paint. The painter will later grab it, and paint the house. And if I want the complication, a tool maker needs to make a paint brush first using animal hair and wood. And the animal hair comes from… etc, etc. And then the first villager gets what she wants.
The main idea there is that if you’ve got the production line and workers setup, the player won’t have to manage turning things on and off, or setting limits. The village will just do it as needed. But the player will have the option of specifying that they want to drive production of a certain resource on purpose.
I’d also like to see group activities. There might be large bison-like animals that take more than one hunter take down. So the villagers need to get organized somehow, and then all follow the same plan to get close to one and attack at the same time.
Lastly I want smarter villagers. If you’ve directed villagers to build a building and you need a log to complete it, it’s probably more efficient to cut down the tree that’s nearby rather than walk all the way across the village and back to get one. Similarly, if a wood splitter has a store of logs nearby but isn’t working to cut firewood, it’s okay to grab the log from that location rather than a far away generic storage yard.
My final goal is that all this needs to be data driven and extensible without the need for a full scripting language. After working with it for a few months, I should be able to add new things villagers do and locations they use without modifying any game code. There are certainly a lot of similarities to what Banished had, but that code is too rigid, messy, and not configurable. It’s nice to start again knowing what sort of issues to deal with.
So how am I going to accomplish all this? We’ll first I need to start with the smallest case and grow. But also keep in mind my future needs. I’ve also been doing some research to see what others are doing. Over the last year or so, I’ve read a lot of game postmortems and AI papers on getting AI characters to do things like I describe. There’s a few algorithms that stand out. Namely Utility AI, Behavior Trees, and Goal Oriented Action Planning.
None of them are perfect for what I want, but they all have good ideas. So I’m blending and modifying, to get what I want.
The basics of my idea is to have each villager have goals they want, and keep track of how strongly or weakly they want to do them. As the player places buildings and objects, those objects will be able to fill those needs. Each object gives a score to the villager as to how useful it is to perform it’s actions, which will be combined with the desires of the villager. Considering all the possible actions available to them, the villager will pick one of the top ones. Objects can also have their own desires. For example, if a location turns reeds into baskets, the location will desire the source materials if the number of stored materials is low. This in turn will cause villagers to consider collecting reeds when needed.
Objects and locations will also be compartmentalized. A boat building area will handle telling villagers how to use it, rather than the villager handling each and every object it can interact with. The object would hold the animations, particle systems, audio, and other resources needed for use, the actions it can give out to villagers, and the desires that it can satisfy. This way, as the game grows, I (hopefully) don’t have to modify existing resources to add a new object.
But where to start!? Designing and writing a giant system with a zillion requirements is hard. Without being able to test its parts as you work is very difficult and usually doesn’t work. If you try this, as the code expands it shows you where your design falls flat and needs fixing. It’s hard to debug, and it’s time consuming to change things when you hit the walls of your design. There are too many unknowable design issues to be able to decide on them up front and roll with it. So I like to start small and simple then grow.
I decided to find the simplest thing the villagers will actually do that makes simple cases for everything I want to be able to handle. This took me a while to come up with, because it’s not really a focus in the game, but it’s still in there. Of course once I thought of it, it was obvious.
I originally thought I’d implement a campfire to satisfy the desire of villagers to be warm. Seems simple, and is a scenario that will play out in many similar ways throughout the game. But it requires a lot of structure all at once and doesn’t quite cover the wide berth of ai systems that I want. When the villager is cold, it desires warming up. The campfire can handle that, but it needs to be burning fuel of some sort for that. I could fake that with the campfire turning on and off automatically for testing. But I feel like to continue down that path, fuel needs to be harvested and/or stored and brought to the fire, which requires inventory, and more locations and actions, cutting trees, splitting firewood, or collecting something else that can burn. That’s all too complex, and doesn’t have an obvious outlet for group actions.
Trying smaller actions villagers will be able to perform was a non-starter as well. Just collecting rocks and putting them somewhere else seemed a bit to big for a start, as it still requires other systems like inventory, carrying things, and an object that can store things. I wanted to be up a running with the ai without writing other systems at the same time.
So what did I come up with? It’s idling. That’s right, doing sort of nothing. Find places to hang out, pick one based on distance criteria, walk around. Talking to each other, or have a party. I can get things up and running without harvesting resources, needing storage and inventory, or production chains. There’s no game there, but it meets the needs of most of what I want to do. And all I had to write is the core AI systems to make it work. Extending it with more things that objects in the word can do should then be easy(ish).
So that’s where I am. After my paper design phase and coming up with a plan, I’ve implemented the basic structure of villagers with desires, objects that can satisfy those desires, and being able to pick the best action from it’s weights. It’s all data driven. Each object has animations it can hand out to villagers to make interacting with it look unique and correct. Villagers look at what they can idle near, weight it based on distance and pick from the top choices. They can satisfy their own need to idle and wander randomly as another possible action. Currently it seems to be in a flexible space where it will be easy to extend and add features.
Coming up I’ll be working on group idling – getting two or more villagers to decide to stand close to each other and play synced animations as if they are having a conversation. (I hope in the future this sort of thing will build friendships and relationships, but that’s really getting ahead of myself…) I also want to setup up triggers for group events, where villagers immediate desire becomes attending that event over anything else. I’ll probably also add some rudimentary time of day schedule which changes what sort of idling occurs at different times.
That should set me up with a fairly solid foundation for the more complex systems that will be built on top of the desire/satisfaction system. Then it will make more sense to get into the fun game parts where resources are harvested, production lines are setup, and players try to balance everything so that everyone survives.