How Jev is called
The whole decision, in Python. jev_move(board) takes the 4x4 board as a list of lists (0 = empty) and returns the chosen direction plus the probabilities. The page does exactly this on every move.
import os, requests
def slide(row):
tiles = [v for v in row if v]
out, points, i = [], 0, 0
while i < len(tiles):
if i + 1 < len(tiles) and tiles[i] == tiles[i + 1]:
out.append(tiles[i] * 2); points += tiles[i] * 2; i += 2
else:
out.append(tiles[i]); i += 1
return out + [0] * (4 - len(out)), points
def move(board, d):
if d in ("up", "down"):
cols = [list(c) for c in zip(*board)]
new, pts = move(cols, "left" if d == "up" else "right")
return [list(r) for r in zip(*new)], pts
rows, pts = [], 0
for r in board:
s, p = slide(r if d == "left" else r[::-1])
rows.append(s if d == "left" else s[::-1]); pts += p
return rows, pts
def facts(board, points, empty_now):
flat = [v for r in board for v in r]
top = max(flat)
in_corner = top in (board[0][0], board[0][3], board[3][0], board[3][3])
pairs = sum(1 for r in range(4) for c in range(4) if board[r][c] and (
(c < 3 and board[r][c] == board[r][c + 1]) or (r < 3 and board[r][c] == board[r + 1][c])))
breaks = 0
for line in board + [list(c) for c in zip(*board)]:
nz = [v for v in line if v]
steps = list(zip(nz, nz[1:]))
breaks += len(steps) - max(sum(a <= b for a, b in steps), sum(a >= b for a, b in steps))
return (f"points +{points}; empty cells after move {flat.count(0)} (now {empty_now}); "
f"biggest tile {top} {'stays in a corner' if in_corner else 'NOT in a corner'}; "
f"adjacent equal pairs ready to merge next {pairs}; "
f"order breaks in rows/cols {breaks} (lower is better)")
def jev_move(board):
empty_now = sum(v == 0 for r in board for v in r)
outcomes = {}
for d in ("up", "down", "left", "right"):
new, pts = move(board, d)
if new != board: # only legal moves become options
outcomes[d] = facts(new, pts, empty_now)
grid = "\n".join(" ".join(str(v or ".") for v in r) for r in board)
state = ("2048 board (4x4, . = empty):\n" + grid +
"\nComputed outcome of each legal move:\n" +
"\n".join(f"{d}: {f}" for d, f in outcomes.items()))
r = requests.post(
"https://api.typesafe.ai/v1/systemone",
headers={"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}"},
json={
"model": "jev-latest",
"state": state,
"questions": {"move": {
"type": "choice",
"instructions": ("Pick the 2048 move that best keeps the game alive and grows the biggest tile. "
"Strongly prefer: the biggest tile staying in its corner, more empty cells, "
"fewer order breaks, more pairs ready to merge. "
"Points gained matter less than keeping the board healthy."),
"criteria": {d: f"slide {d}: {f}" for d, f in outcomes.items()},
}},
},
)
answer = r.json()["answers"]["move"]
return answer["choice"], answer["probabilities"]
Last request and response
Body sent to POST https://api.typesafe.ai/v1/systemone for the last move, and what Jev returned.
Press Play to see it.