You are on page 1of 6

1

Pattern Recognition and Completion in the Context of a 2D Puzzle


Fighter
Nolan Yoo, Corey Bowen

1 Introduction

2D puzzle fighters are a sub-genre of game in which the players solve geometric puzzles. In
other words, the players are responsible for recognizing the pattern to complete it.
However, any multiplayer game should be playable solo – that is to say, against an
appropriate AI player. Such an AI player would need to understand the rules of the game,
victory condition, and the game’s controls (there hereafter: “the game’s systems”).
Furthermore, the AI must prove to be a reasonable challenge.
Therefore, for game development purposes, it is in the best interests of a designer to
initially develop two test cases: a randomly-moving AI, and the best AI possible. This is to
gauge what competency of AI is most appropriate for an average player. The intent of this
paper is to discuss these two test cases in the context of a sample game, their
implementations, and what was learned during the process.

2 Targeted Game and Background Information

2.1 Game Overview and Rules


We chose ShockLock as the 2D puzzle fighter that we would add AI to, an in-progress GAM
project specifically designed to be a competitive puzzler. Ignoring the game’s attack
mechanic (which alters the puzzle on the opponent’s side), gameplay is as follows:
- The player selects a “polyomino” to place on the board, and rotates it if necessary.
o A polyomino is a game piece made up of between 2 and 5 squares, all
attached orthogonally to each other. See Figure 1.
o “Gravity” is not in play – pieces do not fall during placement, and so can be
played anywhere in the player’s 2D space as long as no part of the polyomino
goes off of the board or overlaps with a square already placed on the board.
- The player’s (or AI’s) performance measurement is based on the number of lines he
is clearing per time unit. The more lines, the better.
o A cleared line is a row or column that is filled. The squares in the line are
removed from the board, and credit is given to the player for the line. See
Figure 2.
- The game is won when the opponent’s board can no longer accommodate the game’s
smallest polyomino.
o In other words, the 2x1 polyomino. If the spaces in the opponent’s board only
has 1x1 holes, then the 2x1 polyomino can’t be placed and the opponent has
lost.
2

Figure 1 Four examples of polyominos.

Figure 2 Players score by filling in a row or column. Yellow is about to score 2 lines.

2.2 Game Complexity


The AI’s complexity will be proportional to the game’s complexity, so it’s important to
understand what decisions the players are making at any given time. Complexity can be
roughly measured by the number of decisions there are at any given time, even if none of
them are being considered by the player.
At any given time, there can be at most 1024 different options, and there are
normally less. This is calculated by accounting for:
- At most, 4 selectable polyominos
- At most, 4 valid rotations
- At most, 64 valid positions
- 4 * 4 * 64 = 1024 options
3

2.3 Game Engine and Deployment


ShockLock is written in Unity, and deployed for two plaforms:
- WebGL, by unbinding the C# code to its C++ using its IL2CPP tool, and then from
C++ to JavaScript using emscripten.
- Standalone executable, using the Mono runtime to handle just-in-time compilation of
the C# .NET libraries generated by Unity itself.
The WebGL deployment presents a problem: specifically, each operation or comparison is
computationally more expensive than in the Mono deployment. This is discussed further in
Section 3.1: AI Architecture.

3 Research and Implementation

3.1 AI Architecture
The original plan to facilitate the game’s AI was to design a “Behavior Forest” architecture.
The intent was for there to be templates from which Behavior Trees would be built and
stored in the “forest”. As the game state progresses, the AI would pick a more offensive,
defensive, accurate, or agile Behavior Tree template based on its analysis of the game state.
However, upon presenting this plan at a GAM presentation, Chi-Hao Kuo pointed
out that, due to the low number of options available to a player at a given time, a utility-
based architecture would be simpler to implement and still suit our needs. This advice was
not initially heeded, leading to about 10 hours of “wasted” development as it became clearer
that such an architecture would require a massive time investment. Instead, a utility-based
architecture with a finite state machine (for control flow) was selected:
- The utility-based architecture would assign each of the available options an
attractiveness value. Since the goal is to develop the upper bar for ShockLock’s AI,
we can simply choose the most attractive option.
- The finite state machine allows us to make a cycle in which each state is its own
frame. Simplified, these are:
o ReceivedNewMoveRequest
o CopyData
o StallCalculation
o AnalyzeBottomRows
 Analyze moves that fill rows, but only in the bottom half of the board
o AnalyzeTopRows
 Analyze moves that fill rows, but only in the top half of the board
o AnalyzeLeftColumns
 Analyze moves that fill columns, but only in the left half…
o AnalyzeRightColumns
 Analyze moves that fill columns, but only in the right half…
o ChooseMove
o SendChosenMove
This allows us to spread the work of choosing a move over the course of 9 frames.
Attempting to place all 1024 move evaluations in a single frame results in both the WebGL
and Mono builds “stuttering”, with the WebGL version also crashing due to running out of
memory – the garbage collector was unable to keep up.
4

3.2 Playtesting
Deciding on the formula for attractiveness required gaining an understanding of how actual
players of the game operated.
According to the lead designer, playtesting data showed that players who “filled
holes” (see Figure 3) before preparing to fill lines. Furthermore, it appeared to be self-
evident that placing larger pieces would allow for more lines to be filled per time unit.
Therefore, the equation for attractiveness (assuming that the option is valid) needs to
account for:
- Number of lines filled
- Number of holes filled
- Size of the piece

Figure 3 A row with 3 “holes” in it.

3.3 Trial and Error


The initial and final formula was:

attractiveness = 𝑎(lines filled) + 𝑏(holes filled − holes created) +


𝑐(size of polyomino)

The tested values are as follows:

Table 1 Attempted optimizations for attractiveness of options.


a b c Observed Problem(s) over 5 minutes
5 2 3 AI too willing to create holes
4 1 2 AI willing to make many holes at cost of filling lines
4 2 1 AI willing to use very small pieces to fill lines
5 2 1 None, shipped values

4 Comparisons

4.1 Opposing Player: AI


In order to verify that the greedy-lines-first AI (previously described utility-based AI) has
been successfully implemented, it must be true that the AI can compete against:
- Random-but-valid
- A human
5

The functionality of random-but-valid is as follows:


- Every frame, the AI looks at all 1024 moves, and randomly selects moves until either
5 guesses have been made, or a valid move has been found, whichever comes first.
- If a move wasn’t found, the AI does nothing for that iteration. Otherwise, it does the
selected move.
Through testing, it was found that greedy-lines-first is more than capable of competing
against random-but-valid… because random-but-valid, in every test, will play until it can’t
play a polyomino, thereby eventually losing the game. Greedy-lines-first, in 10 5-minute
trials, was not capable of putting itself in such a position. See Figure 4.

Figure 4 A game in which random-but-valid loses to greedy-lines first (11-20).

4.2 Opposing Player: Nolan


As part of the original game development team and a playtest observer, I (Nolan) am
familiar with some of the game’s meta-strategies. Furthermore, of the development team, I
am consistently able to clear more lines-per-minute than any other teammate. I attempted to
race the AI to 50 lines, with the following results:

Table 2 Nolan vs AI Trials


Nolan AI Victor Advantage % Running Time (Minutes : Seconds)
[(Victor/Loser) – 1]*100
42 50 AI 19.05% 3:02
46 50 AI 8.69% 3:05
43 50 AI 16.27% 3:04

This shows that the AI is roughly 15% better than me at filling lines, and is therefore able to
compete against me.
6

5 Conclusion

We have thusly demonstrated that it is possibly to implement a highly-competitive AI in the


context of a 2D puzzle fighter, specifically one in which pattern recognition and completion
are the primary mechanics of the game. Further, a need to spread the AI’s computations over
several frames was found, and a method for meeting that need was implemented in response.
The AI is competitive enough that – with some tweaking that must eventually happen – it is
possible to ship it as an opponent to provide a “single player” experience to an otherwise
2-player game.

You might also like