Working with Artificial Intelligence
Players and developers interested in working with artificial intelligence can run demonstrations of different artificial intelligence agents in the game that attempt to solve the puzzles for each provided level. This document will guide you through the theory behind the AI agent work in the game, how to run examples with existing agents, and how to implement your own into the game.
ImportantArtificial intelligence features require a Mac running macOS 10.15 Catalina or greater, and The Costumemaster v1.1.0 or greater.
How The Costumemaster Handles AI Gameplay
The Costumemasters works with GameplayKit, a framework provided by Apple Inc. that adds extra tools and utilities for game developers to use, to provide the basis for AI agent testing.
Levels that agents can test work with a subclass of the game scene class,
AIGameScene. This subclass provides the necessary
methods and properties to let an AI agent play the level in a safe manner, keeping track of updates such as costume changes,
time to complete the level, and others.
When the game scene finishes setting up the level, a strategist (
AIGameStrategist) is created based on user parameters with a
given strategy (
GKStrategist). The strategy includes a method,
bestMoveForActivePlayer, that gets called in the AI scene
that will determine the best move for the current player based on the current state of the game world, abstracted away to the struct
The strategist is given the initial state of the world with
AIGameScene.getState and will begin creating a set of moves using
AIGameScene.strategize(with:). The logic for creating a set of moves is as follows:
- Assess the current state of the world.
- If the state is a winning state, don’t make any more moves.
- Otherwise, generate a move using
AIGameStrategist.nextAction(), which internally calls
- Add the move to the set of moves, apply the update, and set the state of the agent to that of updated state.
Depending on what conditions the user supplies, the agent can make a different amount of moves at a given time. Once the agent creates a set of moves, the moves are passed to the scene to apply the update to the real game world and will wait until a new batch is generated, unless the level is complete.
Supplied Game Strategists
GameplayKit does not provide strategists that work with solving puzzles due to the turn-based, competitive nature of the agents.
However, The Costumemaster ships with a few agents designed for solving puzzles. These strategists conform to the
GKStrategist protocol to ensure compatibility with GameplayKit.
AIRandomMoveStrategist is a strategist designed to pick a move randomly. The strategist does not assess the state to
determine a random move.
AIRandomWeightedStrategist functionally performs similarly to the
AIRandomMoveStrategist in that it picks a random
move to perform without assessing any states. However, this strategist will generate a list of all possible actions and assign a
random value to them. The strategist will pick the action with the highest value.
AIPredeterminedTreeStrategist is a strategist that determines an actions based on an assesement of the current game
state. The strategist answers a set of questions that get fed into a decision tree (implemented with
GKDecisionTree) to determine
an optimal move:
"canEscape?"- Whether the agent has completed the puzzle and can leave the level.
"nearExit"?- Whether the agent is near the exit door.
"nearInput?"- Whether the agent is near an input.
"inputRelevant?"- Whether the input closest to the agent links to the exit door.
"inputActive?"- Whether the input closes to the agent is active.
For this strategist, the tree is pre-determined and that questions listed above are already sorted in the tree in such a way
that some questions take priority over others (see:
In some cases, the action returned in the tree will pertain to moving closer to a device or an exit. The strategist will perform extra checks to determine the directional move that will move the agent closer to a specified target using taxicab/Manhattan distance:
\lvert x_1 - x_2 \rvert + \lvert y_1 - y_2 \rvert
The logic is as follows:
Set the current action to stop. Set the current minimum distance to infinity. For all possible movement actions: Create a new state and apply the movement action. Set the new distance to the taxicab distance between the exit and the player in the new state. If the new distance is less than the current minimum distance: Set the current minimum distance to the new distance. Set the current action to the movement action that caused the distance change. Finally, return the current action.
AITealConverseStrategist is a strategy that uses a decision tree generated from CoreML and/or Create ML to make
decisions. The agent asks the same questions as the
AIPredeterminedTreeStrategist, but uses the capabilities of CoreML to
answer those questions with an ML model.
Details on how the model is generated can be found on the Teal Converse repository.
Testing the Included Agents
Via the Simulator Tool
ImportantThe simulator tool is included in v1.2.0 of The Costumemaster or greater.
To test the agents in a sample level for AI, open The Costumemaster and go to Game › Run AI Simulation… or press ⌘R on your keyboard to open the AI Simulator tool. The AI simulator tool allows you to select an agent type, move generation rate, and level for the simulator.
Apply the settings you wish to use and then click “Start Simulation” to run the simulation.
Via the Terminal
To test the agents in a sample level for AI, you will need to run The Costumemaster through the Terminal. In a terminal application, point to the Costumemaster app and run the following:
./Contents/MacOS/The\ Costumemaster --agent-testing-mode true
There are extra commands you can supply to the game to control the overall output of the game:
||String||The name of the level to run the AI simulation in*.|
||String||The type of agent to use (
||Integer||The maximum number of moves the agent can make at a given time in a batch.|
Note*Due to limited testing, there is only one level available for testing, Entry. Additional AI levels may be added in the future.
--agent-move-rate are not provided, the game will automatically chose the random move strategist and
a move rate of one (1) move per batch.
The Costumemaster comes with an AI simulator console that will log any messages throughout the duration of the AI simulation.
Messages sent to the console are also reflected in the command line if launched from the Terminal, with the exception of debug messages. If the console is closed, the console can be re-opened by going to Game › AI Simulator Console in the menu bar or press ⌥⌘C on your keyboard.
Now Mode allows you to view the console messages as a stack, with the most recent message at the top. Click the Now Mode button in the console toolbar to toggle Now Mode on/off.
Creating a Custom Agent
To add a custom agent to the game, you will need to make sure you have cloned the game’s source code from GitHub and ensured that you have the required software to build the project.
- Create a class that subclasses from
AIGameStrategy. Be sure to override and implement the
bestMoveForActivePlayermethod and return an action of type
- Add an entry in the
CommandLineArguments.AgentTestingTypeenumeration that will represent your custom agent.
- Modify the method
AIGameScene.getStrategy(with:)and include a case that instantiates your strategy.
- Add a symbol from SF Symbols that best represents your agent, then update
AISimulatorAgentImageto include backgrounds and the symbol image for your agent accordingly.
- Add a dictionary entry in AgentTypes.plist with a title and description for your agent.
- Build and run The Costumemaster.
- Agent efficiency matters. Try to reduce the number of times you make state updates or you make a calculation to ensure that the simulation will properly run and allow the game window to appear correctly.
- When reading the game state, ensure that you are checking the game state by casting it to the
AIAbstractGameStatestruct. Without this cast, you may be unable to determine key components such as positions and whether certain inputs are active.
- If your agent requires training, ensure that you have some means of communicating to the user that your agent is in training. This
can be easily achieved by printing a message like
"[INFO] Training the agent..."or by using the
AIGameScene.console.debugmethod to use the AI Simulator Console.
- Try to restrict what extra information you need from the user to do any decision-making. The
AIGameScene.getStrategy(with:)method opaquely returns a type of
AIGameStrategistand will not provide details on what kind of strategy was used.