For some time now I've been working on Cultura as a purely C++ project. My reasons were two-fold; I wanted to get a lot more comfortable building an incredibly complex C++ project and second, I love programming.
But, the issue is that building out Cultura using nothing but raw C++ has been taking a long time and at this point I have a greater desire to push out a game. That's why I've recently switched to building out a game in Unity. It felt like a good choice (my other was the Unreal engine). These days, Unity itself is free and unless I make over 200k revenue, then there's no fees to pay.
My first idea I'll be implementing in Unity will be a 4X Space Empire that I've tentatively called Black Star Ruler. It takes place in a post-apocalypse galaxy where the major species have just been reduced to a single colony ship each by the enigmatic Black Star Ruler. From this humble restart of civilization, you grow your people into a new empire. Along the way you may explore ruins, accidentally trigger defences of ancient starbases and colonize planets cleaned of sentient life in the previous war. It's in the vein of Master of Magic (but in SPAAAAAAAAACE) and Master of Orion. I liked those games and it's my take if you just rammed those together into a chimera beast.
As a side note, I've also made that game a public repo on Github, unlike Cultura which is a private repo on my own server.
The latest update now includes basic industry! The test industry was the manufacture of earthenware. Earthenware is a tier-2 good, meaning it requires at least one level of intermediate goods to construct.
Using my amazingly hand drawn graphic of a single blue pottery, you can see it stored inside the "cave" which is nothing more than a square border of rocks on a yellow savannah landscape.
Following this, work will begin on ensuring good consumption works fine. So people will pick up pottery and smash it into their faces to consume it for happiness and health.
There's currently two game cycles designed: food consumption and goods consumption. They're really the same thing except every person in your empire must eat at least one food per day, while they may go on without consuming any goods. The next game cycle to be designed is property items. There will eventually be a number of different kinds of property items but for now it'll just be goods.
In general everything in the Cultura economy is designed with these principles:
Each person wants to consume exactly a single unit of it per cycle. Any additional consumption has reduced or no benefits.
The optimal amount to produce/store of an item is your population size. For example if your population is 10 then you want to produce 10 items per cycle. This means family size or other factors mostly out of the control of the player do not affect the production amount.
All goods are designed such that trade is encouraged.
Make this as simple as possible for the player to calculate production requirements and bonuses.
So how does this work for the existing cycles?
Food Consumption
At the end of each day, a person tries to consume food that gets them the highest bonus. Each time a person consumes food the bonus stays with them for a cycle (this cycle is currently 7 days but that might change based on balancing). But, they MUST consume food every day. So even if the highest bonus for the food is zero they still will eat it.
Health and happiness bonuses are cumulative over a season. So at the start of each season every person starts at 0 health and 0 happiness. You have a goal to reach by the end of the season to avoid problems. This gives some leeway for having "bad" days and "good" days to catch up.
Good Consumption
Good consumption is similar to food consumption except that a person only consumes good if the bonus is more than zero.
Property
At the end of each day a family calculates the bonus it receives from the property it owns and adds up the cumulative health/happiness bonus for a season (which gets reset at the end of the season). The property also degrades over time and eventually requires repair.
During the bonus calculation, the family tries to maximize its score. The formula is intended to be simple. The property they own is added up. Each person's consumption of property is separate. So the first person consumes as many unique property as possible, then the next person and so on. In the end the formula would then be: You get full bonus for the first n of each property and half bonus beyond that. The number n is the size of the family.
So What is Property?
The current concept for Property goods increase health or happiness. Housing can only store a maximum amount of property; if a family wants to own more property then they must expand their housing. Housing can be expanded infinitely but requires land area.
There are some possible simplifications depending on game balancing and understanding difficulty:
The graphics engine is underway. There's three pieces to it. First is the graphics component that does the actual rendering, scene management and all the fancy stuff you heard about. Then there is the game-side of the engine where events are generated and processed before being sent off to the actual renderer. The third is the UI. This part sits separate from the game and rendering portions so that user input can be taken in at any time and then processed by the game (to take in commands) and to the rendering (to update the what the user sees).
Currently, the game engine is built to produce events from a unit moving to a tree being chopped down. That's sent off to the test-engine for now, until the rendering engine is built, and then you get to see some magical updates. People carrying rocks, balls of water, shiny rocks, heavy rocks, dark rocks and other stuff. It's the stone age, expect lots of rocks.
With the use of events, I can then move all the graphics code into one spot, the graphics component of the game engine and thus put it into a single class. This makes it easy when I want to switch to the real graphics engine and also centralizes the graphics code. Everyone else is just producing messages to be consumed by whatever component does the listening. It also allows multiplexing!
Here's a sample of the current generated world, all random whenever you start a new game, with graphic entities built via events!
So I'm on the long road to a first alpha right now. And by alpha I mean an actual alpha and not the "alpha" you see on Early Access these days (which means anything from an actual alpha to a finished game). That means getting the state machines bug free and reaching a point where I can start iterating on game design.
For now the features include: collecting resources, building structures, goods/food consumption, basic management of labour through work orders and labour assignment. These would constitute a game that is roughly equivalent to a Dwarf Fortress clone. After that I'll slowly introduce technological research, uprooting/planting of vegetation, AI factions and then diplomacy.
It's a short post since there's not much to talk about when you're bug squashing.
A lot of the joy from an economic game is watching your industries go ahead after you've set them up. One issue that usually stands out is storage of goods. A game like Cultura is really complex, it has fifteen types of raw items and perhaps upwards to thirty finished and intermediate goods (the exact number is still in flux). This gives us two immediate questions: How many types of storage buildings for the different goods? How many sizes of storage buildings of each type?
For Cultura, the question of types of storage buildings is going to be simplified to "food" and "not food". This is mostly because in the game, the idea of useful storage is more about accessibility, space and preventing spoilage. Only food spoils, so its storage is paramount. Everything else is not really much of a concern so they're mostly for space efficiency (piles of goods would generally be less efficient than a storage pit). Then perhaps there's just two sizes of each: big and small. That leaves us with just four types of storage buildings and then upgrades for them as you progress in technology.
Algorithmically interesting is how you decided which storage site to use to drop off your goods and how you coordinate the movement of goods between storage sites. This is where you get the "sit back and watch" comfortable feeling of an economic game. The current idea is to use a "big cup small cup". A worker chooses the closest drop off site to dump goods. Then when a storage location is full, if it has a larger storage location to transfer goods into then it'll queue up a goods transfer job. This means a small cup can be poured into a larger cup. Whether or not goods should transfer between same size cups is still questionable (right now the answer is no, that way any number of storage location sizes can be coded and people simply keep transferring only "upward").
The title is a pun because there is a movie with a similar name. Hurr. Anyway, Cultura, when it's good and ready to be released will involve farming. The end game will be the neolithic time period so the hope is that you'll be fascinating with min/maxing your empire, engaging in endless diplomatic schemes and building wonders. Also trading with distant lands and marching armies. But back to farming, the lithic time period of humans is probably split between pastoral societies and agrarian societies. There's some mixture but what's important here is getting down to the basics.
This is a simulation game of building up a society from the ground up and so the best place to gather numbers for game mechanics is the real world. Cultura is a game where it doesn't tell you what works, what doesn't and what policies get you what bonuses, instead you do what you want and then the simulation takes care of the effects in a natural manner. With farming, it means that the land production values are going to be design something along the lines of real life.
Okay, let's look at agrarian production rates:
223 kg/ha in Han Dynasty based on a statement from an official commenting on unfairly high tax rates
442 kg/ha in Qin Dynasty based on a statement from an official commenting on new farming methods
1431 kg/ha in Egypt Middle Kingdom based on a priests's statement on what a "good harvest" would be
714 kg/ha to 1429 kg/ha in Egypt New Kingdom based on some records from archaeologists
So that varies a lot and the Nile is especially productive. That's not a surprise; China's Yangtze is not going to be good competition against the floodplains of the Nile. We could probably average the Egyptians to be around 1000 kg/ha. The Chinese number is harder to judge but perhaps we could just take an average and say it is 300 kg/ha.
That brings us to pastoral societies. What kind of food production might one expect from herders? And for that matter, animal meat production.
1.16 kg/ha meat + ?? kg/ha milk for the Borana
That data... is a little sparse but there's little data gathering for pastoral societies. For the Borana, there's around 1162 kg/ha dry mass produced from the land they live on, on average per family, including the wet/dry areas they might move about in. They mostly rely on milk products to survive and their population density is exceptionally low. Each person lives on around 43 kg of meat per year plus a lot of dairy.
Lastly, we want to look at what animal production would be for grain-fed farm animals. This is important for mixed farming (where you do both herding and growing crops). These numbers come from a Stanford study:
Cattle: 8:1 feed to mass ratio, 20:1 feed to edible mass ratio
Pork: 7.3:1 feed to mass ratio, 4:1 feed to edible mass ratio
Chicken: 4.5:1 feed to mass ratio, 2.5:1 feed to edible mass ratio
Milk: 1.1:1 feed to mass ratio, 1:1 feed to edible mass ratio
Fish: 3:1 feed to mass ratio, 1.8:1 feed to edible mass ratio
These are fairly rough numbers and what they translate into game design here is relative values. So we want good arable land to produce around 200-400 units of food per square area, we want dryland to produce around 1100 units of dry mass for fodder per unit area, and we want a conversion ratio of grain feed or wild forage in the table above. Dryland would be unsuitable for growing crops, while floodplains would be super productive at 700-1400 units of food per unit area. We could translate this to being something simple like: dryland produces 1100 dry fodder per square per year or 50 units of cereal (so not worth it), grassland produces 450 units of cereal per year (or perhaps 1500 dry fodder?), floodplains or other super area produces 1000 units of cereal per year (and perhaps 2000 fodder?). Looking at data for dryland crops however appears to show that they can have quite good yields and especially during ancient times they may have rivalled the twentieth century yields (though I suspect that it was unsustainable and led to destruction of soil fertility since they would not have had access to many other technologies that could have kept up soil fertility).
I think perhaps I may simplify soil fertility or I may not, it depends on the sort of decisions it can give the player. If I bring in the concept of soil fertility, the idea is that certain technologies can maintain the fertility levels (such as the application of manure) but ultimately the land plus the technology determines the carrying capacity and going beyond this is a short term gain at a long term cost.
Soil fertility might be some value which decreases per unit harvested off of the land, increased by technological tools (such as manure) up to the max of what that technology can provide and there is some natural regrowth (and maximum). That model gives a very simple way of expressing responsible land use to the player, something well studied throughout history (accidental over farming leading to exhausted soil and then agricultural collapse) yet is still very very lenient because it doesn't consider fertilizer run-off causing algae blooms, deforestation leading to changes in the water cycle, drainage of wetlands leading to flooding and so on. I'm not quite building a weather simulator here but how far should I go to create the simulation to avoid sacrificing emergent properties that come out of environmental questions of how a society interacts with the land it lives on?
Deforestation can already be pretty devastating in the game. Wood is obviously a very useful resource but the growth rate depends on the number of trees. Chopping more trees gets you more wood but decreases the forest growth rate. It's similar to grasses and whatnot. Luckily, the player does not need to think about canopy cover and the like that prevents the soil from drying up from being overly exposed to sunlight. So your overgrazing won't lead to desertification but it does lead to loss of grasses and then your animals die of starvation, then you die of starvation.
Microactions, Parent Actions, Faction Actions, Family Actions
Microservices? Hah, just kidding. This isn't some web service SOA game. Because screw micropayment games. We're here to talk about the amazing and fascinating world of actions; the state machines that get your units doing the things you told them to do. In Cultura, it happens in a hierarchial manner: faction, family, unit. The short version is that when you queue up a big faction-wide action it then doles out unit actions to individual units. Some automated actions, like finding food for the family, are family actions which doles out actions to individual units within a family.
As it turns out, debugging this is super hard. A unit has a stack of actions to track what it should be doing, as each action finishes it pops and the next action in the stack is worked on. Every action has a simple shared interface so that the unit can processTick just by calling doAction on generic actions. Underneath, each action is a child class of UnitAction which has its own various states. But, big actions are complex. Something as simple as "harvest node" turns into a confusing mess of state transitions (what if my inventory is full? resource node is exhausted? I'm under attack? drop off location disappeared or is full?).
So, we go into refactoring code. The current round of refactoring involves devolving each action into "microactions". An action is now defined by three simple concepts: Exit Conditions, Stacking Conditions and the Action. A microaction is an action without Stacking Conditions.
Exit Conditions
In order to keep things simple, an action has clear exit conditions. By breaking things down to microactions, the exit conditions become very simple. Move action? If I'm there then exit. Build action? Apply enough labour and then exit. Drop off action? Drop off what I can and then exit. The larger actions usually wait until a microaction is finished for some its exit conditions and merely tracks the number of microactions successfully completed.
This requires a bit of paradigm shift within the code. Actions don't get wiped off the stack. There's a few edge cases where things get tricky (making sure that we keep track of resources used in the construction of an object don't get lost if a unit dies but they do get lost if the building they're in is destroyed/looted). Secondly, player initiated actions can get replaced or wiped but they need to only be of certain types of actions so that they don't hit those edge cases.
Stacking Conditions
For more complex actions, they are built using a variety of microactions. A single harvest action involves move actions, pick up actions, drop off actions and the actual harvesting itself. The core of a harvest action can be thought of as the "harvest" action. Everything else is a condition where we bump out of the action and do something else. In the case of microactions, we only ever exit; we never do any other action and therefore are atomic actions. In bigger actions, they may need to use a microaction to complete a task. By never wiping the stack, we can rely on the fact that no matter what happens between one action and the next, an action can be completed to the right conditions and we can safely pop.
A stack condition is something that is checked and if needed, a new action is stacked on the unit. For a harvest action, this may mean that a move action is triggered if the unit isn't close enough to a desired location. We can safely assume when this action completes we are at the right location. This is key. All actions can have any number of things happen before they actually complete. A move can be interrupted by another move, by a flee action or anything else but when the stack pops and goes back to the same move action, it does what we want it to do and when it is done we are assured we are in the right condition. And even if we are not, it'd hit the same stacking condition in the parent action.
As an example, say we are harvesting. We try to harvest but we hit "are we close enough" stacking condition. We aren't! So a move action is stacked. When that completes, we are at the node and can then do the harvest.
A more complex example: we are harvesting. We try to harvest but aren't close enough so we stack a move action. But then the player selects the unit to go chop a tree. Later when the tree has finished chopping, the unit is somewhere else entirely but it pops back to the original stacked move action. It then tries to move to the node before harvesting.
Action
Most of the actions involve some core action that it does. This is "harvest" or "drop off". However, some actions are merely just a collection of Exit Conditions and Stacking Conditions. Refactoring everything into simple if statements leaves the core of any action to be an incredibly simple and small amount of code. This is what makes the debugging super easy. State transitions are clearly defined.
The Future
At more well funded studios (ones with more than zero dollars) the state transitions and actions are usually data-driven. The engine defines a bunch of atomic actions and a whack of possible enter/exit conditions and/or triggers. Eventually, I would like to get Cultura to that point but the microaction refactoring is the first step. It makes a clear way for me to go ahead with the data-driven model. For instance, every "if statement" could instead be codified in a class with an interface that has a single bool function shouldContinue and the c++ code encompasses what it means but the data-driven part just uses labels like "check if inventory full/empty". Then actions are built dynamically on load time with arrays of exit and stacking conditions.
So, after the Alpha there's going to be some thought about how to build the opponents in the game: the AI. Most games are built using scripted AI and some limited heuristics in order for the player to compete against some rudimentary opponents. In games such as Civilization it's a make or break scenario; bad AI translates to a truly awful game experience. For most big budget games, ironically there's zero time/money for developing good AI, whereas for indie developed games, there's a lot more room for it. It's mostly because AI is about the most unreliable (timeline wise) aspect of a game to work on.
Cultura is going to use pre-trained AI. How much heuristics depends on how well the training goes but let's talk about the idealized world of having an AI trained from nothing!
The Metrics
The Cultura AI is going to be looked at from three different angles:
Data: What metrics is the AI going to rely upon and measure?
Score: This is a continuous game, so rather than a concept of winning/losing which the AI can train upon, it continuously checks itself against a score to see whether it is doing well
Actions: What is it that the AI actually has control over in order to attempt maximizing the Score?
The exact method used to maximize score could vary: using a perceptron or perhaps a multi-layer neural net or something more sophisticated would be the obvious choices. These can lead to different output values for types of actions and what to act upon. A highly scripted AI would be built similarly except that the metric -> action translation would be built by hand. In the case of a trained AI, it would rely on the Data and then produce an choice about which action to take.
Data
The data is one of the most important aspects of the AI. Choosing insufficient or irrelevant metrics will mean that the AI is not paying attention to the right things to make its actions. Some of the data is simple. It should know what land it owns, what resources are on that land at any given moment and the number of people. It might also try to track buildings, industrial buildings of different types, tools, weapons and military power. And finally, the more difficult to track is the relationship with each faction it knows about.
Non-renewable Resources: It should know about the current maximum draw rate and the current actual draw rate.
Renewable Resources: It should know about the current amount left, the rate of growth and the current draw rate.
People: It should know about the number of people, it might split them apart by labour skill
Buildings: It should know about number of buildings, industrial buildings
Goods: It should track number of tools and weapons available, by type and have more points for superior tools/weapons in a particular category
Military Power: It should track how powerful it's currently active military is
How might we track a relationship with someone? The issue is that an AI should be able to care that it has hostile neighbours. But how to do that?
Relationship Score
Military Power
Distance
We could track those two metrics for each known neighbour, have some interesting way of calculating distance (perhaps the closest distance between two land areas of the two factions) and then worry about the military power. Then, we could lump all this together for a total relationship score that is used for calculations... or we could leave it separate. Lumping it together makes it a bit easier for the "national AI" to make overall decisions. One hopes through training it figures out that highly hostile military powers near it means that it needs to defend itself against the enemy.
Score
Ultimately, any AI needs some kind of objective function or else it doesn't train against much. In the case of Cultura there is no winning or losing. It is a continuous game that you continue to play FOREVER. So, how might we picture this? I figure the simplest way is to see the game as a race with positions and you always want to be number one. So, how well an AI thinks it is doing depends on how well others are doing. This could make the AI pretty hard to train (though, another thought is to have opponents who are fake but always improving at a constant rate and try to train AI against this).
This means that we have a way of calculating score and then all the AI is trying to do is get one more point compared to the highest score.
The score is likely to be a function that is something like Total = Population * Happiness * Health + Wealth + Buildings + Land. Another option is to try to track population, health, happiness and wealth separately and have the AI try to be first place in each category.
Actions
And what is an AI without the ability to do anything? The main picture of the world to the AI is Labour Distribution. Oh ho ho, how communist! But more seriously, this is where the AI tries to decide economic activity to the best of its ability in order to cope with the world and become number one. Also, for those that might actually be concerned about a fully communist AI-run society, the future of Cultura involves a concept known as administrative cost which limits the amount the government can do (because any action it takes administration points thus it might be superior to leave some things to private hands).
Okay so one type of action is changing the amount of labour in a particular industry at the margin. Doing it at the margin is important because we don't want an AI that makes crazy decisions, we want one that edges a society toward the optimal solution in a finite amount of time. Another type of decision would be to expand or upgrade the industrial structures related to a particular industry. In a similar vein, it might decide to increase the number of tools being made for a particular industry to increase production.
But, the more difficult decisions comes from foreign interaction. Okay, so it's pretty easy to say "Gee my happiness is low, build some kind of luxury". Then it's more difficult to say what kind of good. But even if you were to decide that when would you figure out "Gee let's instead trade ivory figurines for wooden furniture because the comparative advantage makes this a superior choice than forming a domestic industry to do this?" One choice is to say that a generic action is "increase production of x" and then a subsequent sub-choice to that is "how to increase production of x" where "trade" is an action and then the sub-choice there is "what do I trade off and to who for this good?"
And then of course, there's raiding, war and peace. How to train an AI to be able to figure out when it should make these types of decisions? "Relationship metric is very low, attempt to fix this is triggered, peace is less costly than war" OR "Wealth Score needs to be improved, weak nation nearby, crush nation and take goods"
Conclusion
This is a pretty good start to the AI question. In the end, the most important thing is there to be an awesome AI that is interesting to play against and is highly intelligent. This is one of the few games where an AI who is really awesome at managing a society is totally okay. Striving for Nintendo Hard here.
There hasn't been an awful lot of work done on Cultura in the past few weeks due to other concerns (like my job :D ) but in any case, some progress was made. The calculation for placing down buildings was revamped and by revamped I mean it now works properly.
Industry
Other than that, some thought was put into how industry works. Right now it's pretty basic. You collect some resources and it becomes a good.
Grains -> Beer
Grains -> Flour -> Bread
But, what exact structure do I want out of Cultura? So I compiled my thoughts into a convenient list:
Each land region only has a set of resources. Each land region has a type that determines how much of each type it contains (Dry areas have more grass and animals, wet areas have more trees).
Each society will focus on making only a subset of the types of goods. This is determined by the Culture Tree they pursue. Someone rich in wood would choose more wood-based goods. Someone rich in earth would choose more earth-base goods.
For each society to develop uniquely and have access to a balanced number of goods, each resource type leads to exactly three types of goods, one type of intermediate good and is assisted by one type of tool and one type of factory.
The point of this design is that each society can have 6-7 goods they produce, easily understood by a player and encourage trade to benefit both societies. Or raiding, up to you. This lets you focus a society to produce specific goods, have clear-cut industries you work on and have trade routes that are obvious (I produce Red Clay Pottery and I trade with Oglandia for Blue Flower Potpourri). For the lithic ages, this mimics the kind of trading that would mostly occur: goods for different goods. In later editions of Cultura, the concept of comparative advantage would be more well developed (that's not to say it doesn't already occur in this game but concepts such as labour specialization, labour skill, industrial infrastructure heavily affect comparative advantage and encourage trade of similar goods).
So the concept is meant to be simple. While it seems wordy here, the player is simply presented with a set of goods that are available from their land. Based on that they would choose to invest Culture points into "buying" goods that they can definitely produce. Then they build up those industries like in any other game (Anno, Caesar, Children of the Nile)... as in they would expand resource collection, make more tools, build up workshops all to increase productivity. After that they can choose to overproduce in order to trade the excess to other societies.
Tools and Factories
Now onto productivity. Okay, so there's another list of ideas:
Tools
Workshop/factory
After a lot of thought and debate in my head, I've settled on something as simple as possible. Tools boost productivity. There'll be a tool per super type of good. What do I mean by super type? A super type would be something like "pottery", which might start off as "clayware" which becomes "pottery" which becomes "glazed pottery" and then becomes "lacquerware" and so on. All of these can be improved by the same type of tool. Your tech level determines the level of tool you produce. In my opinion, the "confusion" that arises from having lots of different kinds of tools comes from the UI. In my planned UI (which has yet to occur) is to have the industry management group goods and their respective tool together when doing labour assignment. This way you can quickly balance the number of tool makers to goods makers and have the correct flow of tools immediately.
I use the term factory loosely. I just mean a building that helps produce a particular good faster. It does it in one big way: it skips steps. For the cost of fuel you can skip a bunch of steps. So normally a production chain is like "Grain -> Flour -> Bread". Then a second tier good would be "Grain -> Flour -> Bread -> Fruitbread" (look, you try to come up with more advanced bread). So, Grain is harvested from grain fields. Flour is made from Grain using labour. Bread is made from Flour using labour. Fruitbread is made from Bread using labour and Fruit. But, what if you had the awesome technology of... Fire Pit? Well then, now you can skip steps! Fruitbread can alternatively be made from Flour and Fruit and Labour and Lithic Fuel. So you've skipped the step of making Bread and instead directly make Fruitbread. Imagine the labour savings!
As the game designer this means I need to balance the cost of Lithic Fuel against the time saving you earn from not making bread (if it takes a really long time to make Lithic Fuel then I need to make the Fire Pit more productive to make up for it).
For the first iteration of Cultura this doesn't seem like much. But imagine later down the line when it is something like "Metal -> Metal Bar -> Bronze Bar -> Steel Bar -> Fine Steel Bar -> Perfect Steel Bar", then something like the "Fan-blown Blast Furnace" which gives you "Metal + Coal-Fuel -> Perfect Steel Bar" would mean that a single unit of coal-fuel just skipped four steps which could mean enormous labour savings (5x less assuming each step costs the same). It's really about game balance.
Ecosystem
How about the ecosystem? Most games are designed after "keep building forever". Cultura is designed a bit differently. This is meant to be a game where you play a society from ground up. And when I say from ground up, I mean eeeeeeeverything. The ecosystem matters. Forests grow. Animals give birth. If I were simulating water sources in the first iteration, there'd even be rainfall. I try to keep it simple though. The number of plants and animals determines their growth rate. In real life, their interaction determines the growth rate. But all I'm trying to simulate is a carrying capacity.
How many resources you draw from the ecosystem is limited by your land and your technology. Better land or better technology lets you draw more from the land. You can choose to underdraw to keep the ecosystem healthy or you could choose to overdraw for some purpose of prestige or fighting hostile societies, as a temporary measure. Or you might sacrifice the ecosystem of some land regions because you're not going to farm there anyway due to urbanization. It's up to the player to decide how to best utilize the land but the land will matter in this game.
As is the case in game programming, my first performance roadblock that is really hurting the Alpha is the pathfinding. It uses A* and it is slow once you get to 40+ square length paths. By slow I mean you can see it takes on the order of 100s of ms for just a few units.
That's bad.
So I went ahead and added Jump Point Search, JPS, but interestingly it made my pathfinding EVEN SLOWER! The issue is that JPS is only superior to super vanilla blind implementation of A* without even, I guess, a heap to store the open list?
Jump Point Pain
Okay, JPS isn't just awesome by blindly implementing the algorithm as pointed out by Harabor (here's the white paper). But it does add value, if we can figure out what is slowing everything down then we can get what it promises: less nodes to check in the open list which is an O(logn) insert.
First, why is A* faster than A* + vanilla JPS? The issue comes down to how the open list is processed. A* with a simple heuristic ( c^2 = a^2 + b^2 ) gives us a very accurate way of determining the next path to analyze without over-estimation. Additionally, the modified A* in Cultura "prefers" to check paths of longer length between two equal cost (known + estimated cost) paths. This means it will traverse down something that is likely to hit the goal node first and end the search. In practice, this means racing down the correct path almost immediately and finding the goal node. So the costs are a bunch of O(logn) inserts and O(1) pops to get the head.
This is quick but the inserts eventually slow down the pathfinding to a very mediocre speed by even a 40-length path.
Thus begins our quest to optimize the shit out of pathfinding.
Cost Estimation Heuristic
The first and simplest optimization was to improve the cost estimation. Originally it was using the "squared" straight line distance to avoid performing a square root. This avoids the computationally expensive square root in the hopes that it doesn't damage performance.
Unfortunately, that just wasn't true. The more accurate straight line distance versus the square straight line distance was pretty much a different in runtime complexity on path lengths over a 10-step length. This was due to the poor "next node" selection in the A* open list. Doing the full calculation allowed A* to correctly choose the next node without trouble and thus be nearly linear in all typical use cases in Cultura.
These days you can use really awesome square root calculators that make it painless. Here are two things: the ole quick square root popularized by Carmack and the much newer asm_sqrt instruction. My box is a quad-core 3.6 Ghz i8 processor for reference.
Just so you know, here's fast inverse square root:
float CJumpPointSearch::Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
Method
Time
Quick Square Root
~25 000 000/s
asm_sqrt
~30 000 000/s
I can do thirty million sqrts a second. Or I can choose the wrong node eighty times and spend countless milliseconds hitting the A* open list. HMM!
JPS: Straight Line Jumps
A straight line is pretty simple. The JPS algorithm basically says keep going forward unless there are obstructions. Then you stop. Seems simple right? Well actually there's a lot of checks per square you need to do before you "jump" to the next square. Is the next square an obstruction or within the map? Is the next square the goal node? Are there any "forced neighbours"? Okay, NOW you jump. The number of checks is very significant.
That's not the worst part though. An unstated problem in JPS is that the jumping doesn't stop.
It doesn't look so bad here. We checked seven squares and then determined that this has no jump point successors. Therefore nothing gets added to the A* open list. Fantastic right? Except that in non-vanilla A* with a reasonable heuristic, I would have never checked all but one of those nodes. So what would have been the cost? Nearly nothing. But, with vanilla JPS, I've run through a "jump" check for all seven nodes. And it gets worse with map size. Cultura has very large maps but even something like a 90x90 test map, I'm nearly running 60-square checks for every straight line jump.
These checks can't be skiped. In order to preserve correctness we must do every square. However, you may not need to perform a full jump.
JPS: Diagonal Line Jumps
In JPS, a diagonal line jump is the most frequent kind of jump you want to do because very rarely do you have a straight path to your goal node. However, the JPS algorithm does an extra step to ensure correctness/optimality for diagonal jumps. Every square you jump forward you must also check the straight line jumps that come out of it.
These straight line jumps have all the performance issues as a normal straight line jump because they're the same thing. And notice they can't be skipped otherwise you might miss an optimal path. So for every square a diagonal jump can go we add two straight line jumps. The number of checks grows very rapidly. For a map such as 90x90, each straight line jump can be 50-60 iterations of the jump function each one consisting of 3-5 checks. Now imagine a reasonable map in Cultura, like a 500x500 map or a very large one like 2500x2500, a straight line jump can be 10000s of checks. So a diagonal line ends up being hundreds of thousands to millions of checks versus just a few in A* with a heap sorted open list. JPS becomes insanely slower.
Jump Point Optimizations
What do?
Order of Operation
Let's consider a few situations:
We could have a goal node accessible through a straight line path. We could have one accessible through a diagonal path. And we could have one accessible by neither.
The first step in JPS is to "prune neighbours" before deciding to figure out the jump point successors. That means we're trying to figure out, from the current node that we just pulled from the A* open list, which directions we should attempt to jump. We can immediately identify that if we're in a straight line path (the x or y value is the same as the current node) then we should see if a straight line jump works. Therefore we should prefer to check the straight line first. Otherwise, let's do the diagonal first because the straight line can't possibly hit the goal node; only a diagonal can. Obstructions can change this but the algorithm already accounts for this.
In practice this means using a deque to store the "pruned neighbours". We push front for the jumps we want to check first, push back to those we want to check second. We are preferring to look at jumps that have a chance of hitting the goal node first.
Of course this is only useful with an early exit. If we find a path that hits the goal node we are using the properties of A* and JPS to exit early from the jumping. We have found a path to the goal. Exit now and let the A* handle whether that is optimal or not. If not? It won't be analyzed again. If it is, we found a path and we can return it immediately. Due to the properties of A*, any other goal path can only at best be of equal length.
Delayed Diagonal Checks
A diagonal path needs to make a straight line check every step of the way. But, if the diagonal path can just simply take you to the goal node (because there were no obstructions), the question is: who gives a shit? The answer is nobody. You got an optimal path, you have an optimal path. Use it!
Rather than make a straight line check every step of the way, as stated in the original vanilla JPS algorithm, just delay those checks only when the diagonal path fails to yield a path.
Overrunning the Goal and A*
When you're using a heap for the A* open list, an insert is O(logn) and popping is O(1). Is that expensive? No! But it is more expensive if you didn't have to do it. JPS is meant to reduce the number of open list checks but that's not useful if the "jump" function takes so ****ing long that the heap inserts and pops were cheaper. What's the answer? Leverage both.
Whenever a jump overruns the goal node, just exit out and return that as a jump point successor. Let the A* algorithm figure out whether it should bother to keep going. The cost is cheap. Imagine a 2500x2500 map. You could do a million checks before realizing this jump is not useful. But A* would have known that far earlier, skipping so many checks that it was much much cheaper to have just simply inserted this into the open list. It's a heap, big deal. It'd have to grow to enormous sizes in order to be a problem.
Have a Path, Use the Path
Whenever we find that we have a path with a goal node, we immediately exit out of finding further jump point successors. The properties of A* will guarantee that we won't use this path if it is not optimal. But we can't tell if it is optimal without going to A*'s algorithm. This avoids the need in JPS to do pointless diagonal or straight line jumps, which again, have a significant cost to them. Inserting a potential goal node into A*'s open list and immediately checking its validity saves significant computation time (a single logn insert versus potentially 1000s of jump checks on various squares).
What's Next
Right now we're running at around 120 solutions for ~60 length paths in a 90x90 map per second. For the pathological case of thousands of units operating at the same time attempting to do pathfinding we would want something around 500-600 solutions per second. We can pursue a few other options: precomputation, caching calculating paths, using greedy whenever possible, reducing function calls and other super-optimization of code (right now the code is very pretty and laid out in OO manner).
I'll be taking a two week break from coding this so that is where I leave the pathfinding state in right now. This is a working real world example of using A* and JPS. I'll likely post up the code (as useful as that may be for people making games with completely different data structures, passability rules and so on), when I'm at the efficiency I'd like to be at for the pathfinder.
Much like the Colonial Marines, sometimes you just got to go on a bug hunt. Cultura is at an alpha stage. You can do things and these things probably have bugs or crashes. I'm here to get rid of those bugs using the power of my pulse rifle.
Right now, there's one glaring issue that will slowly get worked out with some placeholder graphics and dummy test values for growth/resource count; everything is a ****ing strawberry. Why? I don't have the graphics for 99% of the resources in the game and also they don't have their values properly set yet. So most of the resources look like strawberries and I'll have to slowly replace everything to get it to a reasonable test state (and then later replace those graphics).
Anyway, the easiest way to talk about what's going on is a changelog:
Added a cost to a cave so that it is a buildable structure
Placing buildings respects territory ownership
Create open area at start location for a starting cave
Added a cave
Harvest node or animal respects territory when deciding drop off point outside of a storage building
Removed silverleaf and replaced with darkwood
Added graphics and basic resource information for all eight types of wood, at least wood will stop looking like strawberries
Fixed resource node generation, was only making the last item type of each resource node type
Fixed resource node generation which put nodes on top of each other, passability map wasn't being updated properly
Added Jump Point Search to help with pathfinding performance
Fixed world generation of animals, unit ids weren't added to nature faction
Lingering issue: Pathfinding is toooooooo slow.
Another lingering issue: Everything looks like a strawberry. Hard to tell things weren't strawberries. People starved to death due to this.
Here's a screenshot of the current state. Some test graphics and also test graphics for the border.
Random world generation is in. The architecture is built. Test functions thrown out. Hostages rescued.
Right now the "random" world is a gigantic flat plain of grass. Faction starting points and animals have been thrown in but overall there isn't much to see. Everything needs balancing. Resource nodes have to be added. Starting caves have to be thrown in. Maybe I might add some starting resources, not sure about that yet.
Figure 1. Invisible everything.
The main point here is that since the world can be generated, it's a matter of filling it in. There's some algorithms I might explore. I'll explain in more detail once I put some real maff into the code. Maths are good.
A big part of Cultura is about the consumption of goods: property, consumables, food. Then there are tools and military items. With many planned items with variants, how to turn this into something that's understandable for a player? So let's start from the beginning. What do you consume in Cultura? You've got people and every day that passes they eat consumable goods and food. At the same time they enjoy bonuses from property they own in their homes.
Excellent. Materialism is complete. Or is it? Let's say you got an item like pottery. This takes an item called "earth" to make. So far so good. You mine some earth. Put it in a workshop. Workers and slaves poop out some pottery. You put the pottery in a home. Then you enjoy that pottery. But, earth has several variants. Maybe you're getting feldspar, or maybe you're getting red ochre. Those are two planned types of "earth". Although, I will admit, using red ochre to make pottery is going to be tough. In any case, what if you used red ochre instead of feldspar? Then you have a red ochre pot. If you use feldspar then you have a feldspar pot. Are these different?
In Cultura, yes they are! You get bonus from every unique type of item. Pottery made from different materials are considered different. What happens if you have same pottery? If a person has two red ochre pottery then she only gets full bonus from the first. Any subsequent one only gives half the bonus. That's simple and encourages variety.
Okay what about tools and military weapons? That's a bit different from luxury goods. Sure it might be cool to have oak furniture and then also have pine furniture in another room. It completes that missing part in my soul where I yearn to have every kind of wood in my house. That is a thing. But when it comes to military weapons what you care about are RPG stats. How much DPS, eh?
In this case, they take a different approach. Tools and weapons instead can use any number of materials but have no "base material" after it is constructed. Whether you use flint or chert to make your stone chopper, it doesn't create a different item. Instead, the more types of material you use then the higher the level of the item produced. So if you use only flint, then you have a level one stone chopper. If you use flint AND chert, then you have a level two stone chopper. Pretty simple and works well with tools, armour and weapons.
The level of complexity here is somewhat inbetween Dwarf Fortress (any item can be made out of any material or in fact a bunch of alloys and that affects its quality) and Anno (all items can only be made in one way thus there is no way to differentiate them). This "variation" allows for trade between societies making the same item but it's not so significant that close neighbours might not be producing exactly the same good. In that case, they're more likely to trade completely different items (I give you oak furniture for deer leather clothing).
As part of the game design process there's some decisions to be made about industrial structures and tools that help your people make more stuff so that they can consume more stuff in their evil capitalist materialist consumerist lifestyle of reckless abandon.
Tools
Tools cost a certain amount of resources to make, they last a certain amount of uses. This means it's more efficient to use them in conjunction with an industrial building. Then they break and must be replaced. This helps speed labour and of course the bonus must be balanced against the cost of the tool. By reducing labour time this frees up food (because labour time could be calculated in terms of the food that was eaten).
Their bonus is simple. Tool increases production speed and reduces labour time required.
Industrial Buildings
An industrial building takes up space and requires fuel. The kind of fuel changes with technology. This cost is balanced against the reduction in consumption of inputs and an increase in the amount of outputs. The building lasts forever but has high sunk costs.
First, it improves the ratio of input to output. Say you want to make pottery. If you have no building it costs 100 slip to make 1 pottery. If you have a firing pit it takes 180 slip and 10 lithic fuel to make 2 pottery. That's a better ratio. It takes the same amount of time but since you get twice the output, really your productivity has doubled.
Fuel
I've been wrestling with how to make fuel "simple". One issue is that you can effin burn anything. Let's power your evil firing pit with everything from orange peels to old people! Okay, maybe not orange peels. In any case, since so many things can be "fuel", how do I want to define it in game? My current design idea is something like this: there's a good you can make called "lithic fuel", this is the simplest fuel you can make. However, you can make the generic lithic fuel out of many different inputs. So you can select which items are allowed to be used in your lithic fuel industry and then your assigned workers automatically choose the "cheapest" (which would probably be interpreted as the "most abundant") input possible and then create lithic fuel from that. So lithic fuel could use "wood" or "filler" or "bones" or whatever.
However, perhaps the better industrial buildings then require something like "coal fuel". This has stricter input requirements. Now you can only use "wood" or "coal" (which sadly isn't in the game right now, but perhaps a future iteration!). As a side note, the early steampunk tech route is likely to just mirror China because their ancient technology is pretty much steampunk (they had blast furnaces for thousands of years before Europe). That or Greeks if they hadn't wasted all their technology as toys while using mass slave labour.
So the main issue here is that it makes the coding a bit tricky. While most of my goods have only one possible kind of input, fuel has several kinds of possible input. But, I've introduced a concept called "item super id", in addition to an "item id". So what I can do is have 3 or 4 different item ids that say "lithic fuel" and to the player they'll see they have several kinds of lithic fuel. They'll understand why they're in different bundles because it'll say something like Lithic Fuel (switchgrass) and another will say Lithic Fuel (oak). That's understandable. They can then have matching super ids, so that the "firing pit" will require the super id of "lithic fuel super category" which all of those different item ids fit in. Voila! Solved my code problem. With more ids.
Occupancy
Another aspect is how many people can live in the same structure? Originally I was going to do a flat "2 people per room". But then I thought "hmm maybe a bedroom can fit more than say a storage vault". So I'm introducing the concept of occupancy rate per room. It's pretty simple. Go beyond the rate then the family suffers some penalty.
One of the estates that a family owns is considered the primary residence. They get a base health/happiness bonus. If the family exceeds the occupancy rate of this estate then they suffer a penalty for every person beyond that to their health and happiness. Very simple.
Animal Growth
Trying to keep this one simple as well. Animals are born during their birthing season. The rate depends on the herd size. Outside of the birthing season, their numbers decrease to the maximum. The maximum herd size is determined by how many plants (if herbivores) there are in the land region or animals (if carnivores). Best to slaughter animals beyond the max herd size just as it leaves birthing season.
As Cultura head towards a playable Alpha it's time to lock down some of the game design decisions. What has been influencing the entire process has been a focus on:
Simplicity: Can the user understand what is happening at a glance?
Simulation: Is this a reasonable simplification of real life?
Longevity: What is the future path of this game element and is it fun to keep pursuing it?
That's a sort of rough list of what the factors are in saying whether a game element stays, is changed or is dropped.
UI: I'm leaning towards a "total" rather than location UI. It shows you what you have in total in the top right (just a few of the relevant resources or maybe I can splay the 15 resources across the top). Commands you give are carried out by government employed workers (eventually in a sequel there'll be private market). There may be a secondary advanced layer, which requires one additional click, for tweaking at the building or individual citizen level.
Buildings: There'll be probably just a simple set of five main buildings for residential purposes that allows the consumption of goods (consumable and property). They revolve around how to improve health and happiness. Then there are infrastructure buildings like work sites, roads, irrigation and walls. And then there are industrial buildings like mines and farms (maybe JUST mines and farms). These would pop up in a radial menu... probably by pressing "b" for basic buildings, "v" for industrial buildings, "x" for infrastructure buildings. Then perhaps a hideable bar for the same buttons at the bottom of the screen.
Additionally, buildings are built room by room. Doors are the connection points. You mush rooms together to form larger buildings. Each building can only be owned by one family. Ownership (for now) will be automatic. In the future, I'd like there to be an advanced assignment UI (especially if you are an evil dictator trying to form different classes of citizens, some should get better housing than others).
Goods consumption is facing a few changes at this point. There was the concept of consumable and property, where they were equal in health/happiness benefit. I'm going to change it such that property lasts longer, costs less resources over the long run but has high initial costs. That way consumables and property represent a trade off between short term gain and long term gain.
The environment will be separate from artificial structures (though not entirely realistic). This means there can be wild trees, plants and grasses and they grow, you can harvest them and they will regenerate. Same with animals (they'll run around and you can hunt them). Farms and pastures on the other hand require input (labour, maybe water, perhaps some other stuff) but are upgradeable to produce at a higher rate than nature (thus increasing per tile food productivity).
Consumption is automatic. You give orders to produce goods per industry, work orders for a specific amount of a particular good. This UI would be simplified so that you just give one general order for your whole society. I'd like it to be more advanced but that may make the UI too cluttered and I don't have a good solution to that yet.
The world will be designed such that each season represents a consumption of different resources so that there's always something interesting to do (especially during the stone age). As you shift into agrarian (in some future version of this game) it'll change into a more planting/do nothing/harvest rotation and you choose what you might want to do in the "do nothing" phase (like wage war as if you were the Romans).
Interesting diplomatic relations. This is a lot more about making believable AI and on top of that they would give you verbal cues to the rationale behind their actions. That way if they were to do something stupid on purpose, they inform you of this, so that you know. In this way it prevents the "do not dumb here, not dumb area" feeling. Hopefully. Needs some playtesting.
As the game gets inexorably closer to the stage wherein one collects raw resources, converts them into finished goods and then eats them in order to feed a hungry faceless mass of labourers whose only purpose is to reproduce in competition to other faceless masses of labourers, we get closer to thoughts on the world generation. For a game like Cultura one expects procedurally generated worlds (ie. random). That leads to a lot of questions about how to place resources, initially seeding the starting points of different peoples and how might biomes/climates work.
The general status of the game is that the consumption of food, consumable goods and property items is in! Seeing as how those are fairly complicated state machines, there's a lot of testing that needs to be done (and then bug fixing anything wrong that is found). There's also the delicate issue of balance but that comes later. It's an exciting time. The general idea is that food is pretty obvious (make food, eat food) but there will be a balance between consumable goods (consumed once, get a bonus) and property items (needs repair over time but get a better long term bonus for the cost). So your society's economy is a balance between short-term and long-term gain.
But, let's get back to world generation. In the world of Cultura it is powered by the "This Makes No Sense" resource engine. Essentially, the resource system boils down to fifteen different raw resources: wood, stone, earth, grain, meat... etc. For each type of resource there are eight different types of materials for it. As an example, wood could be pine or oak or ironwood. This allows you to create the same product between two different societies but use different materials and you can then trade these different goods. Bonuses are based on the consumption of a variety of materials (every material type consumed for a good it's a multiplier bonus). So an oak chair gives you +10 happiness. But an oak and pine chair would give you +20 happiness. I know that when I go home to my table made out of six different kinds of stone I get six times the happiness from it. Don't you?
The placement of each type of material is what matters most. So for the most simplistic version of a world generator, firstly it would build out where land exists. Everything in Cultura right now is flat (there are mountains but basically they're just rocky obstacle walls). Then the world is divided down into eight regions (or four regions). Each region is then claimed by a single material type (or two, if there are four regions). The selection is random. One part might be pine and then another might be oak. This process is repeated for the fifteen different types of resources each with differently shaped regions and so the overlap of resources varies. Some areas might have pine and unicorns, another might have silverwood and deer. It's random.
Now of course this isn't a super realistic resource placement but alas one developer can only do so much in order to actually finish a game within his/her lifetime.
You: Why is there pine near the equator? Shouldn't it be in the colder regions of the planet?
(ノಥ益ಥ)ノ ┻━┻
Me: Why is your table flipped?!
You: :(
There's a very large wish list of my own that I would like to eventually include in Cultura but all in due time! For now, I'll just discuss what I think is minimally necessary for the game to be fun and realistic enough. The main point is that different regions have access to different resources so that trading in the initial era (the lithic ages) is predicated on the exchange of different goods. As societies advance (and sequels to the game are made), they'll be based more on comparative advantage due to labour skill, non-residential capital investment (it'll be more fun doing in the game than what that sounds like) and education opportunities. For now, just an even spraying of resources across the world shall suffice. As a side bonus, it makes balancing a lot easier.
Work has been done, the latest aspect is property items. These kinds of items are stuff you stick into slots in a family's home and then they enjoy health/happiness bonus from it (spread evenly to every member in the family). That's on-going. Another on-going aspect is the graphics engine. Needless to say, a game needs a good graphics engine to be graphically nice. There's some technical thoughts on that but until it comes to fruition, it will be written about in later posts.
But, what of Cultura as a game? The total game design is coming along and let me take you along that journey. For a game as broad as Cultura, one problem is trying to bring it back together into a neat little box of designed fun. You want the game to be wide open, sandboxy and capable of creating unexpected situations. The emergent aspects. On the other hand you want it to be understandable at a glance, to have a low barrier to playing it so that you can say, I'm going to play for an hour and I can just dive right back into the game.
The whole of Cultura has been split into four neatly laid out focuses in the game that explore the whole of the setting that is displayed to you in all its glory.
Ecology and nature is the most apparent. You start off in an open world with different trees, plants and animals out there. Some you can eat, others you use for producing luxury goods. One of the big concerns in Cultura is the "carrying capacity" of the land. Trees grow, animals are born but at a rate determined by different factors. For Cultura, these factors are simplified. Until there's a "realistic mode", the simulation model is fairly simple so that a player can understand it quickly and adjust to meet social needs for short and long term goals. Forests grow based on the number of still standing trees. Most plants grow just the same, based on the number that exist. Animals grow based on the number of animals but the herd starts starving if it runs low on the number of plants in the wild. So maybe you think you're harvesting "glowing nettle" and it's fine, until you realise you're starving out the local deer of their food source and the herd dies out.
It'll be prominent and direct. The interface will show you each land region. Each land region lists the resources available in it. It shows you the rate at which they grow and what affects the growth rates. Then it's up to the player to decide how to handle that.
As the name would imply, Cultura revolves around culture and that's the biggest core focus as you play. Technology and cultural traits are thrown together like a bunch of miniature skill trees for you to pick and choose to develop the aesthetic feel of your society and also the play style. Most of the technology revolves around improving your industry (industrial buildings, tools, lifting resource extraction limitations), expanding your repertoire of goods you can manufacture (choosing between goods built from each kind of resource, or different high level goods, to build a particular aesthetic feel to the kind of luxuries your society makes), expanding your ability to consume (more or better structures to build), government policies (different ways of performing taxation and also ruling over a larger empire). Cultural traits revolve around social values to adhere to a particular play style. Choosing values that favour war and military, being able to hold Roman-style triumphs, would benefit an aggressive player who wants to gain happiness bonuses from going to war. Or you can choose a pacifist route where you can agree to unfavourable peace treaties yet still gain happiness in your society because your people abhor war so much.
Technology is very specific and the cultural traits you choose are very specific. They allow you to shape your society however you see fit. A militant raider society that produces wood carvings and yarn dolls. A trading society that produces stone axe heads and stone-tipped arrows. It's really what Cultura is all about.
Then there is industry. Handling your resource extraction and manufacturing. The focus is on how much resources you consume, how many goods you produce and whether your goods production matches your population's consumption. You can shore up missing goods through trade. You can over-produce specifically to sell the goods to others. The focus is on setting up new industries, expanding current ones and managing labour distribution. You can have seasonal industries (hunting after an animal herd's growth period). For the first iteration of Cultura, it's about making things for your people and trading the excess to others for things you don't have.
Finally there is diplomacy. This is the most emergent aspect of the game. Are you surrounded by aggressive barbarians? Is there perhaps a trading empire close by? Maybe there's a lot of weaker societies but each of them are more adept than yours at producing particular sets of goods. You interact with them for trade, treaties or war. Trading and raiding are the two most important interactions with other societies to gain goods you cannot produce or do not have enough of, and your choices depend on the total interaction within the world.
Diplomacy and trade are combined and they occur along trade routes. Convoys move back and forth between societies to deliver diplomatic messages, treaty proposals, trade agreements or just the goods you already agreed to trade. But, of course, you can always choose to forgo such polite diplomacy and opt for raiding and as your society becomes more advanced, waging war!
This is a lot more focused version of what Cultura will be about and it gives players a more clear-minded way to approach the game. It leaves the sandbox nature there (you can choose to interact with nature and people however you wish) but displayed in a clear way. Imagine, you have a land rich in iron but low in wood. A neighbour is rich in forests. Do you raid them for their wood using your superior metal-based weapons? But then others might see you as aggressive and refuse to trade with you and you haven't the military to attack them all. They provide valuable goods like wine and fruit juices to maintain your empire's health. You make your choices and live with the consequences.
Ever fathom the consumption type of a good? Cultura has! Bread? That's food. Ochre dye? That's a consumable good. Pottery? That's a property good. Polished gold rocks? That's super property. And it just so happens it finally made its way into the code base. The consumption type that is. No more eating ochre dye or smashing pottery into faces for good fun. That might look a little wrong to the player so it was decided by the Design Gods that it should be changed.
Food is eaten to prevent starvation and food must be eaten each day. The bonuses gained from food (usually health) last for seven days because that's the arbitrary length of time that was decided. Eating the same kind of food confers no additional bonus. Consumable goods when consumed confer a bonus and immediately disappear. The bonus lasts seven days. Property goods are placed into slots in a family's home. A home is comprised of different rooms, and so buildings are built room by room by the player. More slots means more property items that can be enjoyed at the same time. Once a slot is filled it spreads its bonus evenly across the people in the family. Property requires repair over time. Probably every seven days.
Collecting Goods
Once a day each person queues up actions to eat food, collect consumables and another to collect property goods. The one issue has been the hierarchy of the actions. If placed at the individual level, the actions of eat food and collect consumables works out fairly okay. Everybody needs to eat and everybody would like to consume as many goods as possible. But for property, you only need to fill the slots or repair damaged property. So if every person queued up such actions you'd end up with too much pottery. Too much pottery is a problem that exists in Cultura.
One solution is to have an action queued up at the family level (similar to faction level actions) so that the family needs it completed but it doesn't really care who in the family does so. That way it only doles out enough actions to individuals to meet the exact demands. It's possible to also shift collecting consumables up to this level. This is useful for maintaining a family budget when private markets are introduced into Cultura. At the very least, the code needs to be able to handle it if not do so currently.
So, hopefully in the next update you will hear how pottery has been enjoyed by the residents of Cultura. In fact you might consider that since they no longer consume pottery (presumably by smashing it into their faces and then laughing) and instead enjoy pottery in their homes what has been done is aesthetic pleasure has been hardcoded into the minds of Culturans.