The C# code for Match-3 exists inside of the Unity package (com.unity.ml-agents
).
The good first step would be to take a look at how we have implemented the C# code in the example Match-3 scene (located
under /Project/Assets/ML-Agents/Examples/match3). Once you have some familiarity, then the next step would be to
implement the C# code for Match-3 from the extensions package.
Additionally, see below for additional technical specifications on the C# code for Match-3. Please note the Match-3 game isn't human playable as implemented and can be only played via training.
The AbstractBoard
is the bridge between ML-Agents and your game. It allows ML-Agents to
- ask your game what the current and maximum sizes (rows, columns, and potential piece types) of the board are
- ask your game what the "color" of a cell is
- ask whether the cell is a "special" piece type or not
- ask your game whether a move is allowed
- request that your game make a move
These are handled by implementing the abstract methods of AbstractBoard
.
Returns the largest BoardSize
that the game can use. This is used to determine the sizes of observations and sensors,
so don't make it larger than necessary.
Returns the current size of the board. Each field on this BoardSize must be less than or equal to the corresponding
field returned by GetMaxBoardSize()
. This method is optional; if your always use the same size board, you don't
need to override it.
If the current board size is smaller than the maximum board size, GetCellType()
and GetSpecialType()
will not be
called for cells outside the current board size, and IsValidMove
won't be called for moves that would go outside of
the current board size.
Returns the "color" of piece at the given row and column. This should be between 0 and BoardSize.NumCellTypes-1 (inclusive). The actual order of the values doesn't matter.
Returns the special type of the piece at the given row and column. This should be between 0 and BoardSize.NumSpecialTypes (inclusive). The actual order of the values doesn't matter.
Check whether the particular Move
is valid for the game.
The actual results will depend on the rules of the game, but we provide the SimpleIsMoveValid()
method
that handles basic match3 rules with no special or immovable pieces.
Instruct the game to make the given move. Returns true if the move was made. Note that during training, a move that was marked as invalid may occasionally still be requested. If this happens, it is safe to do nothing and request another move.
The Move struct encapsulates a swap of two adjacent cells. You can get the number of potential moves
for a board of a given size with. Move.NumPotentialMoves(maxBoardSize)
. There are two helper
functions to create a new Move
:
public static Move FromMoveIndex(int moveIndex, BoardSize maxBoardSize)
can be used to iterate over all potential moves for the board by looping from 0 toMove.NumPotentialMoves()
public static Move FromPositionAndDirection(int row, int col, Direction dir, BoardSize maxBoardSize)
creates aMove
from a row, column, and direction (and board size).
Describes the "size" of the board, including the number of potential piece types that the board can have. This is returned by the AbstractBoard.GetMaxBoardSize() and GetCurrentBoardSize() methods.
The Match3Sensor
generates observations about the state using the AbstractBoard
interface. You can
choose whether to use vector or "visual" observations; in theory, visual observations should perform
better because they are 2-dimensional like the board, but we need to experiment more on this.
A Match3SensorComponent
generates Match3Sensor
s (the exact number of sensors depends on your configuration)
at runtime, and should be added to the same GameObject as your Agent
implementation. You do not need to write any
additional code to use them.
The Match3Actuator
converts actions from training or inference into a Move
that is sent to AbstractBoard.MakeMove()
It also checks AbstractBoard.IsMoveValid
for each potential move and uses this to set the action mask for Agent.
A Match3ActuatorComponent
generates a Match3Actuator
at runtime, and should be added to the same GameObject
as your Agent
implementation. You do not need to write any additional code to use them.
- Implement the
AbstractBoard
methods to integrate with your game. - Give the
Agent
rewards when it does what you want it to (match multiple pieces in a row, clears pieces of a certain type, etc). - Add the
Agent
,AbstractBoard
implementation,Match3SensorComponent
, andMatch3ActuatorComponent
to the sameGameObject
. - Call
Agent.RequestDecision()
when you're ready for theAgent
to make a move on the nextAcademy
step. During the nextAcademy
step, theMakeMove()
method on the board will be called.
The indexing for actions is the same as described in Human Like Playtesting with Deep Learning (for example, Figure 2b). The horizontal moves are enumerated first, then the vertical ones.