March 2018 Update - AI rewrite and heading back to Kickstarter


There's big updates and small updates since last month, so let's go over the small news first. Firstly many thanks to Alex Esin who has been a huge help with logging bugs at the Github issue tracker. Simulation games are an incredibly complicated programming problem, and bugs/issues are inevitable once there's a certain number of moving parts in the system (a number which was passed a long time ago!) so getting the community to highlight any issues they are finding is a huge help - particular when like this one they appear to be a combination of Intel no longer supporting older integrated graphics cards on Windows 10 with Java - something I would never have encountered on any of my development machines.

If you're finding any problems at all with the game, particularly any crashes to desktop, please sign up for a free Github account, get them logged on there (if someone hasn't already raised it) and I'll get back to you ASAP and make it a priority to fix. To this end, the game now logs out any information and error messages to a file named "log.txt" in the game's main directory which will be a huge help with investigating any crashes - please include the contents of this immediately after a crash to desktop.

With that out of the way, the big feature this month was finally giving the dwarves a well-deserved rest - literally making them being able to sleep! (Please excuse the placeholder bed artwork)

First of all the dwarves needed to decide when and where to go to sleep - until now the settler AI has basically boiled down to "If there's a job you can work on, go and do it, otherwise idle around for a bit".  That's glossing over a large amount of complexity in keeping track of which jobs need doing, who can do them, if they are accessible, and the steps needed to carry those out (including pathfinding to them) but the dwarven settlers didn't have any conflicting needs or desires - just "work on a job if you can".

The next few planned features are around introducing the basic needs of a dwarf or human or other creature - needing to sleep, needing to eat, and needing to drink. This meant the way characters choose which actions to perform or goals to pick from needed turning into something a bit more clever. Recently, the guys working on impressive-looking fellow Dwarf-Fortress-alike Starmancer ran their Kickstarter campaign to great success (congrats guys!). This included releasing a few dev blogs on the workings of the game and the first was on colonist AI and how it works. King under the Mountain has always been written to use "Goal-Oriented Action Planning" but I wasn't very happy with the approach taken so far (everything was a goal, and a goal could be made up of other goals, and so on) as there wasn't much work put into deciding which goal to pick, and it wasn't at all open to modding (which is always one of the central concerns when designing a new system).

Goals

After liberally borrowing the approach taken by Starmancer (so credit where it's due!) instead the AI now has a series of potential "goals" and separately "actions" to carry them out. A goal is something like "Work on a job", "Go to sleep" or "Eat some food".

For a settler to decide that they want to attain one of these goals, they usually have several criteria against them: If they're feeling fairly well rested they'll look for a job to work on; If they're hungry they'll look for food to eat; If they're tired they'll want to sleep and so on.

A settler will usually want to fulfil several of these goals at any one time, so they are queued up with a priority. The priorities are (currently) taken straight from the list the Starmancer guys came up with, going from highest to lowest priority:

Highest > Need > Job > Want > Lowest

However, this means a dwarf will work on jobs, ignoring anything they "want" until it becomes a more urgent "need". To tackle this, goals are also organised around a schedule. Prison Architect did a very similar thing using a "Regime" which was open to modification by the player:


Screenshot of Prison Architect's "Regime" UI[/caption]

Now, King under the Mountain follows the same concept with a schedule that has several categories across each hour. These categories are currently (again taken from Starmancer):

Nourishment, Work, Sleep, Free time, Any

With all these concepts together - which goals to work on according to differing criteria, how to prioritise them and when to work on them according to the schedule - goals can be specified with a set of criteria which define what priority and schedule category they are queued up as. A goal will replace itself if it is already queued up with a lower priority, i.e. a settler may "want" to sleep if they're fairly tired, then change to "need" to sleep when they're very tired.

Actions

That's a lot of info on which goals are selected and when, but how does a dwarf actually achieve one of these goals? Using actions! Actions are the individual steps which make up a goal such as "Move to the relevant location", "Equip a tool to work with" or "Find a bed to sleep in".

Actions associated with the "Sleep" goal

Actions related to a goal are set up as a simple finite state machine, or a series of steps with transitions between them. Every action has (up to) two possible outcomes: it was completed successfully, or something went wrong and the action failed. A goal defines these relationships - for every action associated with the goal, there are a further set of actions to be performed if that action succeeds, or a different set of actions if it fails. For the sleeping example above, it looks like this:

Relationships between actions - green arrows are on success, red arrows on failure

This simple model of relationships between actions is very powerful, and can be used to "retry" actions in certain cases by looping around to a previous action. For example, the "Sleep in bed" action moves to "Go to (bed) location" if the action fails - so if a dwarf is somehow knocked out of the bed while sleeping (or perhaps the bed is removed), they will fail the sleep in bed action, get the "go to (bed) location" action, perform that, and continue their hopefully uninterrupted sleep.

Opening it up to the player - Modding

One of the biggest benefits to this decoupled approach to goals and actions is it means modding the AI is much more approachable. Most of the data used by King under the Mountain is contained in JSON files, and the goal definitions are no exception. The sleep goal above is (currently) defined as follows:

{
  "name": "Sleep in bed goal",
  "selectors": [
    {
      "conditions": [
        {
          "need": "SLEEP",
          "operator": "LESS_THAN_OR_EQUAL_TO",
          "value": 5
        }
      ],
      "priority": "NEED_URGENT",
      "scheduleCategory": "ANY"
    },
    {
      "conditions": [
        {
          "need": "SLEEP",
          "operator": "LESS_THAN_OR_EQUAL_TO",
          "value": 50
        }
      ],
      "priority": "WANT_NORMAL",
      "scheduleCategory": "SLEEP"
    }
  ],
  "initialActions": ["LocateBed"],
  "actionRelationships": {
    "LocateBed": {
      "pass": ["GoToLocation"],
      "fail": ["SleepOnFloor"]
    },
    "GoToLocation": {
      "pass": ["SleepInBed"],
      "fail": ["UnassignFurniture", "SleepOnFloor"]
    },
    "SleepInBed": {
      "pass": ["UnassignFurniture"],
      "fail": ["GoToLocation"]
    },
    "SleepOnFloor": {},
    "UnassignFurniture": {}
  }
}


Let's break this down a bit:

  • "name" defines how this goal is known to the game engine, it doesn't really have much effect other than to let a specific goal be replaced by a mod.
  • "selectors" is a list of different sets of criteria, in this case "sleep is less than 5" or "sleep is less than 50". Sleep is one of the "needs" of a creature and the only one implemented so far, with needs for food and drink soon to follow, as well as others like a social interaction need to come later. A need is a numerical score from 0 (dangerously unsatisfied) to 100 (completely satisfied). If the sleep need is less than 5, this "Sleep in bed goal" is queued up with a priority of NEED_URGENT in the ANY schedule category, meaning it will almost certainly be the next highest priority goal for the settler regardless of what the current schedule category is. If need is less than 50, the goal is queued up with a priority of WANT_NORMAL in the SLEEP category, meaning the settler will wait until it's a normal time for sleeping to select the goal.
  • "initialActions" is the list of actions to queue up when the goal is first started.
  • "actionRelationships" is a JSON object which defines each action used by the goal ("LocateBed", "GoToLocation", "SleepInBed", "SleepOnFloor" and "UnassignFurniture") as well as the actions to queue up when this action is passed (successful) or failed. These pass or fail actions are not required and can be skipped out.

A modder will be able to create their own goals using the syntax above, defining different selectors for how the goals are chosen, and defining the relationships between the associated actions. Currently the actions available are not moddable, although there should be a wide range to pick from for modders upon release. The plan is for new actions to be supported by mods too, though this will require some kind of scripting support which isn't in the engine yet - but it's in the pipeline!

What's next

In the short term there's still work to be done with goals and actions for multi-language support (another central concern with any new system) - expect to see some extra data in the goal JSON above to support internationalisation when the next build is released to Patreon. I'm happy to announce that the funds brought in by Patreon are responsible for new artwork that is currently in progress, and I hope to give a much bigger update on this next month.

Perhaps the biggest news is that I'm now committed to relaunching on Kickstarter this July - most likely towards the end of July but it'll depend where the third party work (getting a trailer produced, ensuring multi-language support is present and correct, etc.) is up to. July feels like quite a distance away (4 months!) but I'm determined to show a reasonable level of progress since the last campaign despite having to suspend development for most of 2017. To this end, the plan is to have the following features in the new pre-alpha demo:

  • Farming of assorted crops
  • Farming of underground mushrooms (done by innoculating logs with mushroom spawn)
  • A detailed production chain for brewing beer reflecting a semi-realistic take on medieval brewing
  • Production of food including baking bread from milled wheat (flour)
  • Places to eat and drink, including a beer tapper for serving beer from kegs into tankards
  • Dwarves will need to eat and drink to avoid starvation or dehydration, so there'll also be death as a minimal feature

To get all of that ready, it roughly needs to be done by the end of May to have time for the trailer to be produced using all the new features, as well as getting translations created for other languages. It's a lot to get done so I'll say now it's certainly possible this date might slip backwards, but I managed to hit my previous Kickstarter timeline and I think the same can be achieved here.

On that final note, I learned a lot from running the previous (and my first) Kickstarter campaign and I'm a lot more confident in achieving success with a second one (a common occurrence for creators new to Kickstarter). I'll be able to incorporate all of the feedback received last time as well as drive a much better marketing push. In retrospect, launching the previous Kickstarter followed by 5 days in London exhibiting at EGX Rezzed was a lot of time away from the internet in the crucial first days of the campaign and I won't be making the same mistake again. If you have any feedback or suggestions for the upcoming Kickstarter campaign, I'd love to hear them! Please get involved in the community at r/KingUnderTheMountain

Get King under the Mountain Prototype

Leave a comment

Log in with itch.io to leave a comment.