← Arcade ๐Ÿ† Players My player card

Game Snake

โ˜… Game Snake โ˜…
Game Snake gameplay screenshot
๐Ÿ“ฆ Game code, download & prompt info
๐Ÿ–ฅ๏ธ Desktop app (python) โ€” play it live above, right in your browser, or download it below
  • Model: openrouter:stealth/union-alpha
  • Test: Game: Snake (playable, pygame UI)
  • Category: gamedev
  • Kind: code ยท scored as score (higher is better)
  • Run: โ€”
  • Benchmark score: 98.0
  • Benchmark date: 2026-09-16
  • Published: 2026-09-25
Original prompt
Write a complete, runnable Python program using `pygame` that implements a playable Snake game. Open a window, draw a grid, a snake that grows by one segment when it eats food, and control direction with the arrow keys. The game ends when the snake hits the wall or itself. Display the current length/score. Include a game loop that handles the QUIT event. Use only primitive shapes - no external assets. Design note (interpret freely): Snake became a global obsession as the bundled Nokia phone game - a minimalist grow-vs-avoid loop where the snake glides across a grid at a fixed speed, grows with every food item, and dies on the wall or its own body. Faithfully capture that tight, escalating survival tension. SCORING & PERSISTENT HIGH-SCORE BOARD (REQUIRED): The game MUST award points for gameplay actions and maintain a persistent high-score table. When a run finishes, prompt the player to enter their name/initials and record it with the score. Save the top 5 scores (name + score) to a local JSON file in the working directory (e.g. high_scores.json), and also write the latest finished run as {"initials": name, "score": number} to /tmp/alpaca_score.json (overwrite it every run) so the arcade scoreboard can pick it up automatically, load and display them on startup and on the game-over screen, and write a new entry whenever a run finishes. Scores must survive restarting the program. Every new game MUST start with the score reset to 0 - never carry over the previous game's score into the next session. The program must run top-to-bottom and open a visible window. OUTPUT REQUIREMENT: Respond with ONLY the raw, runnable source code in a single fenced code block, with the first line starting at column 0 (no leading indentation). Do not include any thinking, explanation, summary, or prose before or after the code, and keep comments inside the code minimal.
โฌ‡ Download game.py
import json
import os
import random
from pathlib import Path

import pygame


CELL = 24
COLS, ROWS = 26, 22
HEADER = 76
WIDTH, HEIGHT = COLS * CELL, HEADER + ROWS * CELL
STEP_TIME = 0.105
SCORE_FILE = Path.cwd() / "high_scores.json"
LATEST_FILE = Path("/tmp/alpaca_score.json")

BG = (168, 190, 118)
GRID = (151, 175, 104)
INK = (34, 53, 30)
BODY = (55, 79, 38)
PANEL = (190, 208, 150)
MUTED = (82, 106, 57)

DIRECTIONS = {
    pygame.K_UP: (0, -1),
    pygame.K_DOWN: (0, 1),
    pygame.K_LEFT: (-1, 0),
    pygame.K_RIGHT: (1, 0),
}


def load_scores():
    try:
        with SCORE_FILE.open("r", encoding="utf-8") as handle:
            data = json.load(handle)
        if not isinstance(data, list):
            return []
        entries = []
        for entry in data:
            if not isinstance(entry, dict):
                continue
            name = entry.get("initials")
            score = entry.get("score")
            if isinstance(name, str) and type(score) is int and score >= 0:
                entries.append({
                    "initials": name.strip()[:12] or "ANON",
                    "score": score,
                })
        return sorted(entries, key=lambda item: item["score"], reverse=True)[:5]
    except (OSError, ValueError):
        return []


def write_json(path, data):
    temporary = path.with_name(path.name + ".tmp")
    with temporary.open("w", encoding="utf-8") as handle:
        json.dump(data, handle, indent=2)
        handle.write("\n")
    os.replace(temporary, path)


class SnakeGame:
    def __init__(self):
        pygame.init()
        pygame.display.set_caption("Snake โ€ข Pocket Arcade")
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 28)
        self.small = pygame.font.Font(None, 22)
        self.large = pygame.font.Font(None, 54)
        self.high_scores = load_scores()
        self.state = "menu"
        self.running = True
        self.snake = [(12, 11), (11, 11), (10, 11)]
        self.food = (18, 11)
        self.score = 0
        self.initials = ""
        self.saved = False
        self.save_message = ""
        self.result = ""

    def text(self, message, position, font=None, color=INK, center=False):
        image = (font or self.font).render(message, True, color)
        rect = image.get_rect()
        if center:
            rect.center = position
        else:
            rect.topleft = position
        self.screen.blit(image, rect)

    def new_game(self):
        self.snake = [(COLS // 2, ROWS // 2),
                      (COLS // 2 - 1, ROWS // 2),
                      (COLS // 2 - 2, ROWS // 2)]
        self.direction = (1, 0)
        self.turns = []
        self.elapsed = 0.0
        self.score = 0
        self.initials = ""
        self.saved = False
        self.save_message = ""
        self.result = ""
        self.state = "playing"
        self.place_food()

    def place_food(self):
        occupied = set(self.snake)
        empty = [(x, y) for y in range(ROWS) for x in range(COLS)
                 if (x, y) not in occupied]
        self.food = random.choice(empty) if empty else None

    def finish(self, result):
        self.result = result
        self.state = "entry"
        self.elapsed = 0.0
        self.turns.clear()
        self.initials = ""

    def record_run(self):
        if self.saved:
            return
        entry = {
            "initials": self.initials.strip()[:12] or "ANON",
            "score": self.score,
        }
        self.high_scores.append(entry)
        self.high_scores.sort(key=lambda item: item["score"], reverse=True)
        self.high_scores = self.high_scores[:5]

        errors = []
        for path, data in (
            (SCORE_FILE, self.high_scores),
            (LATEST_FILE, entry),
        ):
            try:
                write_json(path, data)
            except OSError as error:
                errors.append(path.name)
                print(f"Could not save {path}: {error}")
        self.save_message = (
            "Save failed: " + ", ".join(errors)
            if errors else "Score saved."
        )
        self.saved = True
        self.state = "gameover"

    def queue_turn(self, direction):
        previous = self.turns[-1] if self.turns else self.direction
        if (len(self.turns) < 2 and direction != previous
                and direction != (-previous[0], -previous[1])):
            self.turns.append(direction)

    def step(self):
        if self.turns:
            self.direction = self.turns.pop(0)
        dx, dy = self.direction
        head = (self.snake[0][0] + dx, self.snake[0][1] + dy)
        eating = head == self.food
        occupied = self.snake if eating else self.snake[:-1]

        if not (0 <= head[0] < COLS and 0 <= head[1] < ROWS):
            self.finish("You hit the wall!")
            return
        if head in occupied:
            self.finish("You hit your own tail!")
            return

        self.snake.insert(0, head)
        if eating:
            self.score += 10
            self.place_food()
            if self.food is None:
                self.finish("Perfect run! Grid cleared.")
        else:
            self.snake.pop()

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                if self.state == "entry":
                    self.record_run()
                self.running = False
                return

            if event.type != pygame.KEYDOWN:
                continue

            if self.state == "playing":
                if event.key in DIRECTIONS:
                    self.queue_turn(DIRECTIONS[event.key])
            elif self.state == "entry":
                if event.key == pygame.K_RETURN:
                    self.record_run()
                elif event.key == pygame.K_BACKSPACE:
                    self.initials = self.initials[:-1]
                elif len(self.initials) < 12:
                    character = event.unicode
                    if character and character.isascii() and (
                        character.isalnum() or character in " -_"
                    ):
                        self.initials += character.upper()
            elif self.state in ("menu", "gameover"):
                if event.key in (pygame.K_RETURN, pygame.K_SPACE):
                    self.new_game()
                elif event.key == pygame.K_ESCAPE:
                    self.running = False
                    return

    def draw_board(self):
        self.screen.fill(BG)
        pygame.draw.rect(self.screen, INK, (0, 0, WIDTH, HEADER))
        self.text("SNAKE", (18, 13), color=PANEL)
        self.text(f"SCORE {self.score:04d}", (180, 13), color=PANEL)
        self.text(f"LENGTH {len(self.snake)}", (390, 13), color=PANEL)
        best = self.high_scores[0]["score"] if self.high_scores else 0
        self.text(f"BEST {best}    |    ARROWS TO STEER    |    +10 / FOOD",
                  (18, 46), font=self.small, color=BG)

        for x in range(COLS + 1):
            pygame.draw.line(self.screen, GRID,
                             (x * CELL, HEADER), (x * CELL, HEIGHT))
        for y in range(ROWS + 1):
            pygame.draw.line(self.screen, GRID,
                             (0, HEADER + y * CELL),
                             (WIDTH, HEADER + y * CELL))

        if self.food is not None:
            x, y = self.food
            center = (x * CELL + CELL // 2,
                      HEADER + y * CELL + CELL // 2)
            pygame.draw.circle(self.screen, INK, center, 8)
            pygame.draw.rect(self.screen, BG,
                             (center[0] - 2, center[1] - 2, 4, 4))

        for index, (x, y) in enumerate(self.snake):
            rect = pygame.Rect(x * CELL + 2, HEADER + y * CELL + 2,
                               CELL - 4, CELL - 4)
            pygame.draw.rect(self.screen, INK if index == 0 else BODY, rect)
            if index == 0:
                dx, dy = getattr(self, "direction", (1, 0))
                cx, cy = rect.center
                for side in (-1, 1):
                    eye = (cx + dx * 5 - dy * side * 4,
                           cy + dy * 5 + dx * side * 4)
                    pygame.draw.circle(self.screen, PANEL, eye, 2)

    def draw_scores(self, top):
        self.text("TOP 5 โ€ข HIGH SCORES", (WIDTH // 2, top),
                  center=True)
        for index in range(5):
            y = top + 32 + index * 28
            if index < len(self.high_scores):
                entry = self.high_scores[index]
                name, score = entry["initials"], str(entry["score"])
            else:
                name, score = "---", "---"
            self.text(f"{index + 1}.  {name}", (118, y), font=self.small)
            image = self.small.render(score, True, INK)
            self.screen.blit(image, (WIDTH - 118 - image.get_width(), y))

    def draw_overlay(self):
        rect = pygame.Rect(64, HEADER + 24, WIDTH - 128, ROWS * CELL - 48)
        pygame.draw.rect(self.screen, PANEL, rect)
        pygame.draw.rect(self.screen, INK, rect, 3)
        cx = WIDTH // 2
        top = rect.top

        if self.state == "menu":
            self.text("SNAKE", (cx, top + 43), self.large, center=True)
            self.text("Eat. Grow. Stay alive.", (cx, top + 88), center=True)
            self.text("Arrow keys steer. Walls and body are fatal.",
                      (cx, top + 122), self.small, center=True)
            self.draw_scores(top + 168)
            self.text("ENTER / SPACE to start", (cx, top + 389), center=True)
            self.text("ESC to quit", (cx, top + 425), self.small, center=True)
        else:
            title = "GRID CLEARED!" if self.food is None else "GAME OVER"
            self.text(title, (cx, top + 38), self.large, center=True)
            self.text(self.result, (cx, top + 77), self.small, center=True)
            self.text(f"Score: {self.score}     Length: {len(self.snake)}",
                      (cx, top + 111), center=True)

            if self.state == "entry":
                self.text("Enter name / initials, then press ENTER:",
                          (cx, top + 147), self.small, center=True)
                field = pygame.Rect(150, top + 165, WIDTH - 300, 37)
                pygame.draw.rect(self.screen, BG, field)
                pygame.draw.rect(self.screen, INK, field, 2)
                cursor = "_" if pygame.time.get_ticks() % 1000 < 500 else ""
                self.text(self.initials + cursor, field.center, center=True)
            else:
                self.text(self.save_message, (cx, top + 164),
                          self.small, center=True)

            self.draw_scores(top + 233)
            if self.state == "entry":
                footer = "Blank name saves as ANON."
            else:
                footer = "ENTER: play again    |    ESC: quit"
            self.text(footer, (cx, top + 440), self.small, center=True)

    def run(self):
        while self.running:
            dt = min(self.clock.tick(60) / 1000.0, 0.25)
            self.handle_events()
            if not self.running:
                break
            if self.state == "playing":
                self.elapsed += dt
                while self.elapsed >= STEP_TIME and self.state == "playing":
                    self.elapsed -= STEP_TIME
                    self.step()
            self.draw_board()
            if self.state != "playing":
                self.draw_overlay()
            pygame.display.flip()
        pygame.quit()


if __name__ == "__main__":
    SnakeGame().run()

๐ŸŽฎ Press โ–ถ Play above to run it live in your browser, or download it below and run locally (pip install pygame), then enter your score by hand