Hello and welcome back. In this post I will be finishing off the base scripts for the GOAP system. After that it will be numerous amounts of testing and making improvements, and finally, expanding the functionality of the system. As in the previous post, if you haven't been keeping up to date with my previous posts about the A.I system, I would highly recommend heading back and reading them as I talk about the systems creation up until this point. If you have been keeping up to date, let us continue.
The Base System
I finished off last post with creating the idle action script which was the last script I needed to create before I could start creating the Action Planner script. Even though the script itself has been declared, the body, or functionality, of the methods were not implemented as I needed scripts for the actions and agent before the planner could function.
Action Planner
To finish off the foundation of the GOAP system, I proceeded to build the planning methods.
As I needed to start with the smaller methods that would be used within the larger scope methods, I decided to begin with the RemainingActions() method. What this method would do is create a list of actions that the agent could perform without the actions that are already part of the action plan. After that, I moved onto the isViable() method, which allows the planner to determine whether the prerequisites would be fulfilled by the previous task, and finally the simulateAction() method which, as the name suggests, simulates the action being performed within the planner. I won't be showing these methods as some are quite short and not as complicated as others, however the plan builder and executer methods will be shown in more detail below.
Currently, for the plan and build method, I have opted out of including world data as a parameter for the plan as the only data that the world data holds is faction relations. This is not important for testing purposes at the moment, however when I start adding more variety of agents to show the versatility of the A.I system, I plan on testing its capabilities in a variety of game genre test scenarios. It is within these genres that some of the A.I agents would require the faction relation data to function as intended. When I reach this stage, I will then incorporate this parameter into the agent's action plan building stage.
Game genres that I could test which would require the faction relation data include:
RPG style games (wolves, bandits, Merchants etc)
Team based war games (soldiers, archers)
Base building/Simulation games (rival city civilians etc)
The Plan Method
One of the two major methods the action planner holds is the plan method, the other being the build method. The Plan method is in control of resetting the agents actions as well as telling the planner that the agent wants to create a new plan due to not having one. This means there are three main parts to this method:
Action resetting.
Plan build request.
Plan processing.
Action Resetting
The easiest part of this method is the action resetting section. All that happens in this section is that the planner loops through the list of available agent actions and calls their respective reset method. Once this is done, the planner than creates a list of usable actions from these.
As shown above, it is just a couple of method calls to reset the actions and determine if they are classed as usable.
Plan Build Request
After resetting and creating a new list of usable actions, the planner proceeds to request a plan to be built using the agents data and the new list of usable actions. The plan being built will need to be stored in a temporary list, but instead of IAction they will use the private class created within the action planner called Node.
As the build request will result in a Boolean pass or fail, I created a cut-off point in the method based on a failed build request. There would be no reason to try and process a failed plan so the method is told to return a null reference for the plan. This will then be used by the agent to check if there is a plan to perform or not.
Plan Processing
Finally, the last section of the plan method is plan processing. Here the plan is converted from the simulated list of nodes to a readable list of actions for the agent. To begin the conversion, the planner needs to find the start of the plan, denoted by the node with the lowest weight value. To find this, I just loop through the list of nodes and check the currently selected node to a temporary node variable I created which the lowest weighing node is assigned to.
Once the starting node has been found, the planner simply loops through all the nodes of the plan via parentage to determine the order of the actions for the agents plan.
Now that the plan method has been created, the build method is the last one needed before the GOAP is functional on a basic level. Once that is implemented, action plan creation and action performance testing can commence.
The Build Method
Even though the build method isn't exactly long due to its recurring nature, it could be seen as complicated in terms of function. It will simulate the use of actions to reach the desired goal, without enacting any changes onto the agent.
For this to work, the planner needs to keep a version of the agents data on which it can perform the necessary alterations to ensure the plan is correctly built. This will be referred to as the 'parent(s) state' throughout this section.
Breaking down the method, there are 4 main parts to it.
For loop around the usable actions.
The viability check of the action to the current parent state.
The viability check of the action to the agents goal.
The recurring method call to continue building a plan if one is not created.
Usable Action Loop
This is the most straight forward part of the method, all this does is simply cycles through the list of available actions so the embedded viability check can determine if the currently cycled action's prerequisites are fulfilled by the parent's state (the combination of child action effects).
Prerequisite Viability Check
The next part of the method, as state above, checks the viability of the action based on its prerequisite needs. If the parent's state matches or fulfils the actions prerequisites then the planner proceeds to further the building of the plan, however if the prerequisites are not met, then the planner simply ends that actions checks and cycles to the next usable action.
If the prerequisite check was a success, then the builder will create a new node based on the current action. The new node will need to have four pieces of data in order to be created:
Parent node: This is a parameter of the build method so assigning will be straight forward.
Running cost (weight): The cumulative value of the parent node and current action's weights.
Parent state: The state of the data used to check viability of prerequisites, simulated with the new actions effects.
Related Action: The new action.
Goal Viability Check
Once the new node is created, the builder will check of the goal of the agent is fulfilled by the current action. If the current action is a viable solution to the agents goal, then the node holding the plan data is added to the list of nodes which will become the usable action plan. If the goal is not satisfied with the current actions effects, then the builder will continue planning until the goal is satisfied or all usable actions are checked.
To continue the planning, the builder will create a subset of usable actions without the current action. The build plan method is recursively called if the goal viability check results in a fail, using an updated list and a newly created node each time it does so.
System Testing
I have finally implemented all of the necessary features needed to make the basic GOAP system function, albeit I have not been able to test its functionality. To ensure that everything is implemented correctly, it is time to start test phases.
This is it for this post. I won't be posting my test phases as testing can go on for ages, but once the system is fully operational with this basic setup I shall return with new a blog post detailing the updates I have made to the system and my future plans.
As always, if you would like to stay up to date, be sure to check back regularly to see if there is any news or updates regarding this project!
Comments