2048
Slide the tiles of a 4 x 4 board - or 3 x 3 to 6 x 6 - up, down, left or right: two equal tiles that meet join into one with their sum, each tile once a move, and every move that changes the board brings a new 2 or 4. Reach the goal tile and keep going until no move is left; the same seed brings the same tiles.
Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.
About
Slide every tile on the board up, down, left or right. Two equal tiles that meet join into one tile holding their sum, and the sum is added to your score. Every move that changes the board brings a new tile. Try to reach the goal tile - 2048, unless a new game sets another - and keep going until no move is left.
main.eml- the menu, the moves and their messages, and a new game with its size, goal and seedboard.eml- the board: sliding a row, turning the board for the other directions, the new tiles, and whether a move is leftrng.eml- random numbers written in EML, the generator of P008
How each part works:
- A row slides left in two steps. First the tiles close up. Then two equal tiles side by side join, taken from the left, and a tile joins at most once a move:
2 2 2 2becomes4 4, not8. - The other directions reuse the left slide on a turned board, and turn the result back. Right reverses each row; up transposes the board, as in the corpus case
matrix-transpose-manual; down transposes it and reverses each row. So the tiles join from the side they move towards. - A move that changes nothing is not a move: no new tile comes, and the move count stays the same. Otherwise a new tile appears on an empty cell, every empty cell equally likely: a 2 nine times in ten, a 4 otherwise. The random numbers come from EML code, so a seed brings the same tiles on every machine.
- A move is left while a cell is empty or two equal tiles touch, side by side or one above the other. When none is left the game is over, and its score is shown.
What is checked: moves as w, a, s and d, or as up, left, down and right; n for a new game, q to quit. A new game takes a size from 3 to 6, a goal that is a power of two from 8 to 65536, and a seed from 0 to 999999999. An empty answer cancels.
Sessions: sessions/basic.in makes eight moves on the default board (seed 2026). The second move lines up 2 2 2 2 along the top, and the third turns it into 4 4 for 8 points. A down move joins 2 2 near the top of a column whose bottom tiles do not join. Then a new 3 x 3 game with goal 32 (seed 318) runs to the end. A left move joins three rows at once, 4 + 8 + 32 points, and makes the goal on move 21. The board is full after 26 moves, with no two equal tiles touching, and the score is 152.
sessions/bad-input.in gives: - the moves x and an empty one; - moves written as up and left; - up when nothing can move up; - a new game that first gets sizes 2, 7 and x, goals 4, 12 (not a power of two) and 100000, and seed abc. It then runs a 3 x 3 game with goal 8 (seed 261) to the end: the goal is made on move 5, and the game is over after 18 moves with a score of 72; - a move after that; - a new game cancelled at each of its three questions.
Built on the verified corpus case matrix-transpose-manual (a list of lists transposed by hand, column by column).
Recorded sessions
What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.
bad-input
interpreter: byte-equal== 2048 ==
Slide the tiles: two equal tiles that meet join into one. Every move brings a new tile.
A board of 4 x 4, goal 2048, seed 2026.
. . . .
. . . 2
2 . . .
. . . .
Score 0, moves 0, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> x
Type w, a, s or d to move, n for a new game or q to quit.
w) up a) left s) down d) right n) new game q) quit
move>
Type w, a, s or d to move, n for a new game or q to quit.
w) up a) left s) down d) right n) new game q) quit
move> up
2 . . 2
. . 2 .
. . . .
. . . .
Score 0, moves 1, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> w
2 2 2 2
. . . .
. . . .
. . . .
Score 0, moves 2, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> left
4 4 . .
. 2 . .
. . . .
. . . .
Score 8, moves 3, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> w
Nothing moves up.
w) up a) left s) down d) right n) new game q) quit
move> n
size (3 to 6)> 2
Type a number from 3 to 6.
size (3 to 6)> 7
Type a number from 3 to 6.
size (3 to 6)> x
Type a number from 3 to 6.
size (3 to 6)> 3
goal (8 to 65536)> 4
Type a number from 8 to 65536.
goal (8 to 65536)> 12
The goal is a tile, so a power of two: 8, 16, 32 and so on.
goal (8 to 65536)> 100000
Type a number from 8 to 65536.
goal (8 to 65536)> 8
seed (0 to 999999999)> abc
Type a number from 0 to 999999999.
seed (0 to 999999999)> 261
A board of 3 x 3, goal 8, seed 261.
. . .
. . 2
. 2 .
Score 0, moves 0, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> s
. . 2
. . .
. 2 2
Score 0, moves 1, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> s
. . .
4 . .
. 2 4
Score 4, moves 2, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . 2
. . .
4 2 4
Score 4, moves 3, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
4 . .
. . 2
4 2 4
Score 4, moves 4, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . .
. 4 2
8 2 4
Score 12, moves 5, largest tile 8.
You made 8 in 5 moves - keep going if you like.
w) up a) left s) down d) right n) new game q) quit
move> a
2 . .
4 2 .
8 2 4
Score 12, moves 6, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . .
4 4 .
8 4 4
Score 16, moves 7, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 2 .
4 . .
8 8 4
Score 24, moves 8, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 2 .
4 2 .
8 8 4
Score 24, moves 9, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 2
4 4 .
8 8 4
Score 28, moves 10, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 4
4 4 2
8 8 4
Score 28, moves 11, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> a
2 4 .
8 2 2
16 4 .
Score 52, moves 12, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 .
8 2 2
16 4 2
Score 52, moves 13, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 2
8 2 .
16 4 4
Score 56, moves 14, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 2
8 2 2
16 4 4
Score 56, moves 15, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 2
8 2 4
16 4 4
Score 60, moves 16, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 2
8 2 2
16 4 8
Score 68, moves 17, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 4 2
8 2 4
16 4 8
Score 72, moves 18, largest tile 16.
No move is left. Game over: score 72, largest tile 16, 18 moves.
w) up a) left s) down d) right n) new game q) quit
move> a
No move is left - start a new game.
w) up a) left s) down d) right n) new game q) quit
move> n
size (3 to 6)>
Cancelled.
w) up a) left s) down d) right n) new game q) quit
move> n
size (3 to 6)> 3
goal (8 to 65536)>
Cancelled.
w) up a) left s) down d) right n) new game q) quit
move> n
size (3 to 6)> 3
goal (8 to 65536)> 16
seed (0 to 999999999)>
Cancelled.
w) up a) left s) down d) right n) new game q) quit
move> q
Bye.
What was typed (46 lines)
x
up
w
left
w
n
2
7
x
3
4
12
100000
8
abc
261
s
s
s
s
s
a
s
s
s
s
s
a
s
s
s
s
s
s
a
n
n
3
n
3
16
q
basic
interpreter: byte-equal== 2048 ==
Slide the tiles: two equal tiles that meet join into one. Every move brings a new tile.
A board of 4 x 4, goal 2048, seed 2026.
. . . .
. . . 2
2 . . .
. . . .
Score 0, moves 0, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> w
2 . . 2
. . 2 .
. . . .
. . . .
Score 0, moves 1, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> w
2 2 2 2
. . . .
. . . .
. . . .
Score 0, moves 2, largest tile 2.
w) up a) left s) down d) right n) new game q) quit
move> a
4 4 . .
. 2 . .
. . . .
. . . .
Score 8, moves 3, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . . .
. 2 . .
. 4 . .
4 2 . .
Score 8, moves 4, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> d
2 . . .
. . . 2
. . . 4
. . 4 2
Score 8, moves 5, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . . 2
. . . 2
. . . 4
2 . 4 2
Score 8, moves 6, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> a
2 2 . .
2 . . .
4 . . .
2 4 2 .
Score 8, moves 7, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . 2 .
4 . . .
4 2 . .
2 4 2 .
Score 12, moves 8, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> n
size (3 to 6)> 3
goal (8 to 65536)> 32
seed (0 to 999999999)> 318
A board of 3 x 3, goal 32, seed 318.
. . .
. 4 2
. . .
Score 0, moves 0, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. . .
. . .
2 4 2
Score 0, moves 1, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> w
2 4 2
. . .
. 2 .
Score 0, moves 2, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
. 2 .
. 4 .
2 2 2
Score 0, moves 3, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> a
2 . .
4 . .
4 2 2
Score 4, moves 4, largest tile 4.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . .
2 . .
8 2 2
Score 12, moves 5, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . .
4 . .
8 2 2
Score 16, moves 6, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> a
2 2 .
4 . .
8 4 .
Score 20, moves 7, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 2 .
4 2 .
8 4 .
Score 20, moves 8, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 2
4 4 .
8 4 .
Score 24, moves 9, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 2
4 . .
8 8 2
Score 32, moves 10, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . .
4 . 2
8 8 4
Score 36, moves 11, largest tile 8.
w) up a) left s) down d) right n) new game q) quit
move> a
2 2 .
4 2 .
16 4 .
Score 52, moves 12, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . .
4 4 .
16 4 2
Score 56, moves 13, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 4
4 . .
16 8 2
Score 64, moves 14, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 2 .
4 . 4
16 8 2
Score 64, moves 15, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 2 .
4 2 4
16 8 2
Score 64, moves 16, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
2 . 2
4 4 4
16 8 2
Score 68, moves 17, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> a
4 2 .
8 4 .
16 8 2
Score 80, moves 18, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> d
2 4 2
. 8 4
16 8 2
Score 80, moves 19, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> s
. 2 2
2 4 4
16 16 2
Score 96, moves 20, largest tile 16.
w) up a) left s) down d) right n) new game q) quit
move> a
4 . .
2 8 2
32 2 .
Score 140, moves 21, largest tile 32.
You made 32 in 21 moves - keep going if you like.
w) up a) left s) down d) right n) new game q) quit
move> s
4 4 .
2 8 .
32 2 2
Score 140, moves 22, largest tile 32.
w) up a) left s) down d) right n) new game q) quit
move> a
8 2 .
2 8 .
32 4 .
Score 152, moves 23, largest tile 32.
w) up a) left s) down d) right n) new game q) quit
move> d
2 8 2
. 2 8
. 32 4
Score 152, moves 24, largest tile 32.
w) up a) left s) down d) right n) new game q) quit
move> s
4 8 2
. 2 8
2 32 4
Score 152, moves 25, largest tile 32.
w) up a) left s) down d) right n) new game q) quit
move> s
2 8 2
4 2 8
2 32 4
Score 152, moves 26, largest tile 32.
No move is left. Game over: score 152, largest tile 32, 26 moves.
w) up a) left s) down d) right n) new game q) quit
move> q
Bye.
What was typed (39 lines)
w
w
a
s
d
s
a
s
n
3
32
318
s
w
s
a
s
s
a
s
s
s
s
a
s
s
s
s
s
a
d
s
a
s
a
d
s
s
q
Modules
The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.
main.eml(entry)
eml# P048 2048: slide the tiles; two equal tiles that meet join into one with
# their sum, and every move brings a new tile. Reach the goal tile - 2048
# unless a new game sets another - and keep going until no move is left.
import board
import rng
def trim(s):
0 => i
len(s) => j
while i < j and s[i] == " ":
i + 1 => i
while j > i and s[j - 1] == " ":
j - 1 => j
return s[i:j]
def number(s):
if s == "" or len(s) > 9:
return -1
0 => n
for c in s:
if not (c in "0123456789"):
return -1
n * 10 + int(c) => n
return n
def show(game):
for line in board.drawn(game[0]):
line ^0
("Score " + str(game[2]) + ", moves " + str(game[3]) + ", largest tile " + str(board.largest(game[0])) + ".") ^0
def start(size, goal, seed):
("A board of " + str(size) + " x " + str(size) + ", goal " + str(goal) + ", seed " + str(seed) + ".") ^0
# [board, the generator, score, moves, goal, goal reached, over]
[board.empty_board(size), rng.Rng(seed), 0, 0, goal, False, False] => game
board.add_tile(game[0], game[1])
board.add_tile(game[0], game[1])
show(game)
return game
def play(game, direction):
if game[6]:
"No move is left - start a new game." ^0
return game
board.moved(game[0], direction) => res
if res[0] == game[0]:
("Nothing moves " + direction + ".") ^0
return game
res[0] => game[0]
game[2] + res[1] => game[2]
game[3] + 1 => game[3]
board.add_tile(game[0], game[1])
show(game)
if not game[5] and board.largest(game[0]) >= game[4]:
True => game[5]
("You made " + str(game[4]) + " in " + str(game[3]) + " moves - keep going if you like.") ^0
if not board.can_move(game[0]):
True => game[6]
("No move is left. Game over: score " + str(game[2]) + ", largest tile " + str(board.largest(game[0])) + ", " + str(game[3]) + " moves.") ^0
return game
def ask_number(prompt, low, high):
while True:
trim(input(prompt + " (" + str(low) + " to " + str(high) + ")> ")) => answer
if answer == "":
return -1
number(answer) => n
if n >= low and n <= high:
return n
("Type a number from " + str(low) + " to " + str(high) + ".") ^0
def power_of_two(n):
while n > 1 and n % 2 == 0:
int(n / 2) => n
return n == 1
def new_game(game):
ask_number("size", 3, 6) => size
if size == -1:
"Cancelled." ^0
return game
-1 => goal
while goal == -1:
ask_number("goal", 8, 65536) => goal
if goal == -1:
"Cancelled." ^0
return game
if not power_of_two(goal):
"The goal is a tile, so a power of two: 8, 16, 32 and so on." ^0
-1 => goal
ask_number("seed", 0, 999999999) => seed
if seed == -1:
"Cancelled." ^0
return game
return start(size, goal, seed)
"== 2048 ==" ^0
"Slide the tiles: two equal tiles that meet join into one. Every move brings a new tile." ^0
start(4, 2048, 2026) => game
True => running
while running:
"" ^0
"w) up a) left s) down d) right n) new game q) quit" ^0
trim(input("move> ")) => choice
if choice == "w" or choice == "up":
play(game, "up") => game
elif choice == "a" or choice == "left":
play(game, "left") => game
elif choice == "s" or choice == "down":
play(game, "down") => game
elif choice == "d" or choice == "right":
play(game, "right") => game
elif choice == "n":
new_game(game) => game
elif choice == "q":
False => running
else:
"Type w, a, s or d to move, n for a new game or q to quit." ^0
"Bye." ^0
Python projection (main.py)
import board
import rng
def trim(s):
i = 0
j = len(s)
while i < j and s[i] == " ":
i = i + 1
while j > i and s[j - 1] == " ":
j = j - 1
return s[i:j]
def number(s):
if s == "" or len(s) > 9:
return -1
n = 0
for c in s:
if not c in "0123456789":
return -1
n = n * 10 + int(c)
return n
def show(game):
for line in board.drawn(game[0]):
print(line)
print("Score " + str(game[2]) + ", moves " + str(game[3]) + ", largest tile " + str(board.largest(game[0])) + ".")
def start(size, goal, seed):
print("A board of " + str(size) + " x " + str(size) + ", goal " + str(goal) + ", seed " + str(seed) + ".")
game = [board.empty_board(size), rng.Rng(seed), 0, 0, goal, False, False]
board.add_tile(game[0], game[1])
board.add_tile(game[0], game[1])
show(game)
return game
def play(game, direction):
if game[6]:
print("No move is left - start a new game.")
return game
res = board.moved(game[0], direction)
if res[0] == game[0]:
print("Nothing moves " + direction + ".")
return game
game[0] = res[0]
game[2] = game[2] + res[1]
game[3] = game[3] + 1
board.add_tile(game[0], game[1])
show(game)
if not game[5] and board.largest(game[0]) >= game[4]:
game[5] = True
print("You made " + str(game[4]) + " in " + str(game[3]) + " moves - keep going if you like.")
if not board.can_move(game[0]):
game[6] = True
print("No move is left. Game over: score " + str(game[2]) + ", largest tile " + str(board.largest(game[0])) + ", " + str(game[3]) + " moves.")
return game
def ask_number(prompt, low, high):
while True:
answer = trim(input(prompt + " (" + str(low) + " to " + str(high) + ")> "))
if answer == "":
return -1
n = number(answer)
if n >= low and n <= high:
return n
print("Type a number from " + str(low) + " to " + str(high) + ".")
def power_of_two(n):
while n > 1 and n % 2 == 0:
n = int(n / 2)
return n == 1
def new_game(game):
size = ask_number("size", 3, 6)
if size == -1:
print("Cancelled.")
return game
goal = -1
while goal == -1:
goal = ask_number("goal", 8, 65536)
if goal == -1:
print("Cancelled.")
return game
if not power_of_two(goal):
print("The goal is a tile, so a power of two: 8, 16, 32 and so on.")
goal = -1
seed = ask_number("seed", 0, 999999999)
if seed == -1:
print("Cancelled.")
return game
return start(size, goal, seed)
print("== 2048 ==")
print("Slide the tiles: two equal tiles that meet join into one. Every move brings a new tile.")
game = start(4, 2048, 2026)
running = True
while running:
print("")
print("w) up a) left s) down d) right n) new game q) quit")
choice = trim(input("move> "))
if choice == "w" or choice == "up":
game = play(game, "up")
elif choice == "a" or choice == "left":
game = play(game, "left")
elif choice == "s" or choice == "down":
game = play(game, "down")
elif choice == "d" or choice == "right":
game = play(game, "right")
elif choice == "n":
game = new_game(game)
elif choice == "q":
running = False
else:
print("Type w, a, s or d to move, n for a new game or q to quit.")
print("Bye.")
board.eml
eml# P048 2048 - the board: a list of rows of numbers, 0 for an empty cell.
def empty_board(size):
[] => b
for r in [1:size]:
b + [[0] * size] => b
return b
def slid_left(row):
# One row pushed to the left. The tiles close up, then two equal tiles
# side by side join into one, taken from the left, and a tile joins at
# most once a move: 2 2 2 2 gives 4 4, not 8. Returns [the row, the
# points gained - the value of every joined tile].
[] => tiles
for x in row:
if x != 0:
tiles + [x] => tiles
[] => out
0 => gained
0 => i
while i < len(tiles):
if i + 1 < len(tiles) and tiles[i] == tiles[i + 1]:
out + [tiles[i] * 2] => out
gained + tiles[i] * 2 => gained
i + 2 => i
else:
out + [tiles[i]] => out
i + 1 => i
while len(out) < len(row):
out + [0] => out
return [out, gained]
def reversed_rows(b):
[] => out
for row in b:
[] => r
for x in row:
[x] + r => r
out + [r] => out
return out
def transposed(b):
# The corpus case matrix-transpose-manual: row j of the result is column
# j of the board.
[] => out
for j in [0:len(b[0]) - 1]:
[] => new_row
for i in [0:len(b) - 1]:
new_row + [b[i][j]] => new_row
out + [new_row] => out
return out
def moved(b, direction):
# Every move is a slide to the left on a turned board, turned back: right
# reverses each row, up transposes the board, down transposes it and
# reverses each row. Returns [the new board, the points gained].
b => t
if direction == "right":
reversed_rows(b) => t
elif direction == "up":
transposed(b) => t
elif direction == "down":
reversed_rows(transposed(b)) => t
[] => slid
0 => gained
for row in t:
slid_left(row) => res
slid + [res[0]] => slid
gained + res[1] => gained
slid => out
if direction == "right":
reversed_rows(slid) => out
elif direction == "up":
transposed(slid) => out
elif direction == "down":
transposed(reversed_rows(slid)) => out
return [out, gained]
def empty_cells(b):
[] => out
for r in [0:len(b) - 1]:
for c in [0:len(b) - 1]:
if b[r][c] == 0:
out + [[r, c]] => out
return out
def add_tile(b, rng):
# A new tile on an empty cell, every empty cell equally likely: a 2 nine
# times in ten, otherwise a 4. Returns [row, column, value], or [] when
# no cell is empty.
empty_cells(b) => cells
if len(cells) == 0:
return []
cells[rng.below(len(cells))] => cell
2 => value
if rng.below(10) == 0:
4 => value
value => b[cell[0]][cell[1]]
return [cell[0], cell[1], value]
def can_move(b):
# Some move changes the board while a cell is empty or two equal tiles
# touch, side by side or one above the other. (A board in play always
# holds a tile; on an empty one nothing would move.)
len(b) => n
for r in [0:n - 1]:
for c in [0:n - 1]:
if b[r][c] == 0:
return True
if c + 1 < n and b[r][c] == b[r][c + 1]:
return True
if r + 1 < n and b[r][c] == b[r + 1][c]:
return True
return False
def largest(b):
0 => top
for row in b:
for x in row:
if x > top:
x => top
return top
def drawn(b):
# Each cell five characters wide, a dot for an empty one.
[] => lines
for row in b:
"" => line
for x in row:
"." => s
if x != 0:
str(x) => s
while len(s) < 5:
" " + s => s
line + " " + s => line
lines + [line] => lines
return lines
Python projection (board.py)
def empty_board(size):
b = []
for r in range(1, size+1):
b = b + [[0] * size]
return b
def slid_left(row):
tiles = []
for x in row:
if x != 0:
tiles = tiles + [x]
out = []
gained = 0
i = 0
while i < len(tiles):
if i + 1 < len(tiles) and tiles[i] == tiles[i + 1]:
out = out + [tiles[i] * 2]
gained = gained + tiles[i] * 2
i = i + 2
else:
out = out + [tiles[i]]
i = i + 1
while len(out) < len(row):
out = out + [0]
return [out, gained]
def reversed_rows(b):
out = []
for row in b:
r = []
for x in row:
r = [x] + r
out = out + [r]
return out
def transposed(b):
out = []
for j in range(0, len(b[0])):
new_row = []
for i in range(0, len(b)):
new_row = new_row + [b[i][j]]
out = out + [new_row]
return out
def moved(b, direction):
t = b
if direction == "right":
t = reversed_rows(b)
elif direction == "up":
t = transposed(b)
elif direction == "down":
t = reversed_rows(transposed(b))
slid = []
gained = 0
for row in t:
res = slid_left(row)
slid = slid + [res[0]]
gained = gained + res[1]
out = slid
if direction == "right":
out = reversed_rows(slid)
elif direction == "up":
out = transposed(slid)
elif direction == "down":
out = transposed(reversed_rows(slid))
return [out, gained]
def empty_cells(b):
out = []
for r in range(0, len(b)):
for c in range(0, len(b)):
if b[r][c] == 0:
out = out + [[r, c]]
return out
def add_tile(b, rng):
cells = empty_cells(b)
if len(cells) == 0:
return []
cell = cells[rng.below(len(cells))]
value = 2
if rng.below(10) == 0:
value = 4
b[cell[0]][cell[1]] = value
return [cell[0], cell[1], value]
def can_move(b):
n = len(b)
for r in range(0, n):
for c in range(0, n):
if b[r][c] == 0:
return True
if c + 1 < n and b[r][c] == b[r][c + 1]:
return True
if r + 1 < n and b[r][c] == b[r + 1][c]:
return True
return False
def largest(b):
top = 0
for row in b:
for x in row:
if x > top:
top = x
return top
def drawn(b):
lines = []
for row in b:
line = ""
for x in row:
s = "."
if x != 0:
s = str(x)
while len(s) < 5:
s = " " + s
line = line + " " + s
lines = lines + [line]
return lines
rng.eml
eml# P048 2048 - random numbers written in EML: the linear congruential
# generator of P008 (number guessing), with the constants of the C
# standard's example rand(). Python's random module is not used, so a seed
# gives the same tiles on every machine, and the interpreter can check a
# whole session byte for byte.
class Rng:
def __init__(self, seed):
seed % 2147483648 => self.state
def step(self):
(1103515245 * self.state + 12345) % 2147483648 => self.state
return self.state
def below(self, n):
# A number from 0 to n - 1, taken from the high bits of the state: the
# low bits of this generator repeat with short periods. Dividing by
# 65536 is exact in a float for a state below 2^31.
return int(self.step() / 65536) % n
Python projection (rng.py)
class Rng:
def __init__(self, seed):
self.state = seed % 2147483648
def step(self):
self.state = (1103515245 * self.state + 12345) % 2147483648
return self.state
def below(self, n):
return int(self.step() / 65536) % n