paper - People Server at UNCW - University of North Carolina

2048 AI-Solver
Casey Savage, James Olson, & Hayley Stueber
University of North Carolina Wilmington
are no empty spaces left on the board and no more
moves can be made.
This game can take hours to play and does
not have a very high success rate if played manually.
Our algorithms are designed to solve the game as
quickly and as accurately as possible.
Abstract
2048 is a one-player game that inserts a
game tile when the player makes a move. As a result,
an artificial intelligence solver can treat 2048 as a
two-player game, which suits the structure needed to
evaluate it using a minimax algorithm or one of its
many variations. The minimax algorithm, alpha-beta
pruning, and the expectimax algorithm will all be
examined for accuracy and speed to determine which
is the most effective for solving this game.
2. Formal Problem Statement
The algorithms we implemented are
typically used in two player games. In our case, the
first player (maximizing player) is the person playing
the game. The second player (minimizing player) is
the computer who randomly places a 2 or 4 tile on the
board. The Minimax algorithm is an algorithm most
commonly used in constructing effective AI players
for computer games. It formulates a tree made up of
minimum nodes and maximum nodes, meaning, at
certain levels, the computer is to look for the lowest
value on a child node, while, on others, it is to look
for the highest value. A node is evaluated based on
the number of points produced by a certain move for
the starting board. The score used to evaluate each
node is based on the actual score, the number of
empty tiles on the board, and how scattered the
values are on the board. Formally this algorithm can
be expressed with pseudocode:
1. Introduction
The game 2048 was created in 2014 by
Gabriele Cirulli. The game board consists of a 4 X 4
grid and starts out with two randomly selected tiles
that each have a value of either 2 or 4. The objective
of the game is to slide these tiles left, right, up, or
down in order to combine them and ultimately reach
the 2048 tile. Any two numbers that are the same can
be combined. For example, two adjacent 2’s can be
combined to create a 4, two adjacent 4’s can make an
8, and so on. During a turn, tiles slide in the specified
direction until they are stopped by another tile or the
edge of the board. After every move, a new tile with
the value of 2 or 4 will appear in an empty spot on
the board. The score of the game is calculated by
adding the value of the new tile created by combining
two tiles to the current score. If two 2’s are combined,
four points would be added to the score. The player
wins once they reach the 2048 tile, but loses if there
MAX
function minimax(node, depth, maximizingPlayer):
if depth = 0 or node is a terminal node
return the heuristic value of node
if maximizingPlayer
bestValue := −∞
Minimax Algorithm Tree Example
for 2048:
MIN
MAX
The smallest values
from the max nodes
move up to the min
nodes. Then a max is
chosen from the new
min nodes to be the
best overall move.
1
The best move in this
case is to slide the board
right.
Alpha Beta Pruning Tree Example:
Alpha: -infinity
Beta: infinity
for each child of node
v := minimax(child, depth − 1, FALSE)
bestValue := max(bestValue, v)
return bestValue
else (* minimizing player *)
bestValue := +∞
for each child of node
v := minimax(child, depth − 1, TRUE)
bestValue := min(bestValue, v)
return bestValue
The Alpha-Beta Pruning algorithm is an
expansion of the Minimax algorithm. The goal
of this algorithm is the same as the Minimax
algorithm, but involves decreasing the number
of nodes to evaluate by comparing alpha and beta
values and “pruning” sub trees. By eliminating sub
trees, the time it takes to evaluate a tree is cut down
producing an outcome faster. In the algorithm, alpha
is the best value for max seen so far, beta is the best
value for min, and state is used to represent the
position in the game (in our case, the current board).
Informally, at any given max node, if the beta is less
than the alpha, then the rest of the subtrees can be
pruned. Conversely, at any given min node, if the
alpha is less than the beta, then the rest of the
subtrees can be pruned. The overall score of a node is
determined the same way as the Minimax algorithm.
Formally, this algorithm looks like this:
outcomes (the board moved up, down, right, or left)
will be branches and leaves on the tree. Branches
evaluated with the Alpha-Beta Pruning algorithm will
be eliminated if determined they will not produce the
best move possible. Ultimately, the algorithms will
select the move that will be most beneficial to the
overall outcome of the game.
Lastly the Expectimax Algorithm is also a variation
of the Minimax game algorithm. Like Minimax,
Expectimax still calculates all the possible moves, it
just also weighs the probability of each move
occurring. The probability is weighed by the chance
of a two or four tile being randomly generated on the
board. The heuristic scoring used in my expectimax
algorithm is to have the highest amount tile in the
bottom left corner. The move chosen had the best
score with highest tile in the left bottom corner and
had the best probability of future random tiles being
generate where the algorithm expected them to be
placed. The Big O time complexity for the
Expectimax algorithm is O( 𝑛𝑑 ), where n is the
number off possible moves, and d is the specified
depth to search into future moves. Below is the
pseudo code for the Expectimax algorithm:
Max (s [state], α, β, d [depth]):
If d = 0: return value(s)
Else, for depth:
α= Max(α, Min(s, α, β, d)
if α >= β: return α
Min (s [state], α, β, d [depth]):
If d = 0: return value(s)
Else, for depth:
β = Min(β, Max(s, α, β, d-1)
if β >= α: return β
To apply these to the game 2048, the current board
will be treated as the root node of the tree and all
function expectimax(node, depth, player)
if node is a terminal node or depth = 0
2
return the heuristic value of node
if the adversary is to play at node
// Return value of minimum-valued child node
let α := +∞
foreach child of node
α := min(α, expectimax(child, depth-1))
else if we are to play at node
// Return value of maximum-valued child node
let α := -∞
foreach child of node
α := max(α, expectimax(child, depth-1))
else if random event at node
// Return weighted average of all child nodes'
values
let α := 0
foreach child of node
α := α + (Probability[child] *
expectimax(child, depth-1))
return α
algorithm will incorporate the probability of
occurrence of a randomly generated tile. Similarly to
Expectimax the Minimax algorithm will run through
all the possible move outcomes but will not include
the probability of tile occurrence. Ultimately, the
algorithms will select the move that will be most
beneficial to the overall outcome of the game. Each
algorithm was run 20 times and highest tile and
elapsed time was recorded for each game.
The three algorithms had the following
results. Minimax showed the highest tiles achieved
throughout the 20 games were:
Highest Tile (Minimax)
Number of Tiles
256
1
512
8
1024
1
2048
10
The Minimax algorithm also had an average run time
of 185.6 seconds per game.
Next the alpha beta pruning algorithm
showed the following evidence for the 2:
Highest Tile (Alpha-Beta) Number of Tiles
512
1
1024
6
2048
13
The fastest of the three algorithms was Alpha-Beta
Pruning with an average run time of 72.4 seconds per
game.
Lastly, the Expectimax algorithm provided
the following evidence for highest tiles achieved in
its 20 trials:
Highest Tile (Expectimax) Number of Tiles
1024
4
2048
10
4096
6
Unfortunately, the Expectimax had the best
successful games but had the worst run time. The
average run time for the game was 597.2 seconds per
game trial.
Although each of our algorithms run and
finish the game in a reasonable amount of time, our
code would still show better efficiency results with
improved code optimization. Another possible hole in
our work is the sample size of game trials. We opted
to only run 20 games because the amount of time that
it takes to run 20 games continuously can be multiple
hour especially with the Expectimax algorithm.
3. Context
A 2048 game solver has been a common
algorithm since the games development in 2014.
The alpha beta pruning algorithm has been used to
create a game solver for 2048 previously by Vasilis
Vryniotis. He used Java to create his algorithm, but it
was very slow and ineffective. He tested several
different scoring methods which could be a key
factor in improving the accuracy (number of times
the algorithm solves the game) and ultimately found
that a scoring method that takes into account the
actual score, number of empty cells, and how
scattered the values were on the board was the best
out of the ones he tried. Gayas Chowdhury and
Vignesh Dhamodaran created code for a 2048
solver using the expectimax algorithm, which
reached a 2048 tile 90% of the time. They found
that they achieved the highest success rate when
they used a heuristic scoring to choose a move
that moves the tiles to the left.
4. Experimental Procedure
Applying each algorithm to the game, 2048,
the current board will be treated as the root node of
the tree and all outcomes will be branches and leaves
on the tree.
The depth of the algorithm determines how
many moves in advance the algorithm will search
before determining the best possible move. We
standardized our algorithms by each using a depth of
7 when running our solvers. Branches evaluated with
the Alpha-Beta Pruning algorithm will be eliminated
if determined they will not produce the best move
possible. Branches evaluated with the Expectimax
5. Interpretation & Conclusions
After running each of the three algorithms
20 times with a depth of 7, we found the Expectimax
algorithm to be the most successful with an 80%
success rate but the slowest in terms of time. Second,
the Alpha-Beta Pruning algorithm had a success rate
of 65% and had a very efficient run time. Finally, the
3
Minimax algorithm had the lowest success rate of
50% and had a run time a little slower than AlphaBeta. As the given depth increases the run time and
success rate both increase. At a low depth like 4 the
2048 solvers will have a short run time but not be
successful often. Below is a table of the total
percentage of tiles achieved over all three algorithms
Highest Tile
256
512
1024
2048
4096
winning score by calculating
probabilities.
3. What is the time complexity of the
expectimax algorithm?
O(n^d)
4. As tree depth increases, how does it affect
your algorithm?
It increases the likelihood of a
winning outcome, but it also
increases the time it takes to
complete.
Percentage
1.67%
18.33%
15%
55%
10%
6. Future Work
In the future, we should find ways to
improve the speed of the algorithm. Improving speed
will allow users to use larger depth and, as a result,
attain higher success rates. Additionally, we should
aim to tune heuristics, experimenting with the way
scores are calculated, the weights, and the board
characteristics that are taken into account. This will
also allow us to generate higher success rates and, in
the case of alpha-beta pruning, may decrease runtime.
7. Questions
1. What limits a minimax algorithm?
The depth of the search.
2. What are the differences between the
minimax, alpha-beta pruning, and
expectimax algorithms?
The Alpha Beta Pruning algorithm
expands on the Minimax algorithm
by eliminating branches to evaluate
to hopefully decrease runtime. The
Expectimax algorithm add chance
nodes to the Minimax algorithm to
increase the chances of getting a
4