The egocentric/egocentric_player/egocentric_radius flags were removed from retro_gamer in favor of an explicit observation_function. snake_observation.py reproduces the old egocentric+board+extras behavior by calling egocentric_board/encode_board/encode_state directly, and runs/snake/config.toml now points at it. That config change made the prior 12,000-episode checkpoint history incompatible (retro_gamer's checkpoint compatibility checker can't verify a new observation_function is behaviorally equivalent to the old flags, so it conservatively refuses to resume), so the old checkpoints were deleted and a fresh 20,000-episode run was recorded. Track only the four checkpoints the lab actually references (ep_1300, ep_2300, ep_4000, ep_20000) instead of all 200, and update .gitignore so future student runs of runs/snake aren't committed by default. snake_training.md's Q5 training-curve table and Q6 checkpoint episodes are updated to match the real numbers from this run.
32 lines
1.2 KiB
Python
32 lines
1.2 KiB
Python
"""A custom observation_function for retro.examples.snake.
|
|
|
|
Crops the board to a window centered on the snake's head before encoding,
|
|
using egocentric_board()/encode_board() from retro_gamer.observation as
|
|
building blocks. This replaces retro_gamer's old built-in egocentric flags —
|
|
cropping is now just something an observation_function does for itself.
|
|
|
|
Point a run's config.toml at this with:
|
|
|
|
[metadata]
|
|
observation_function = "snake_observation:egocentric_observation"
|
|
board_size = [17, 17] # must match RADIUS below: 2*8+1 = 17
|
|
"""
|
|
import numpy as np
|
|
from retro.views.headless import HeadlessView
|
|
from retro_gamer.observation import egocentric_board, encode_board, encode_state
|
|
|
|
CHARACTER_SET = ["@", "*", ">", "<", "^", "v"]
|
|
RADIUS = 8
|
|
|
|
|
|
def egocentric_observation(game):
|
|
"""Board cropped to a (2*RADIUS+1)^2 window around the snake's head, plus apple_dx/apple_dy."""
|
|
view = HeadlessView()
|
|
view.on_game_start(game)
|
|
view.render(game)
|
|
head = game.get_agent_by_name("Snake head")
|
|
cropped = egocentric_board(view.board_characters, head.position, RADIUS)
|
|
board_vec = encode_board(cropped, CHARACTER_SET).flatten()
|
|
extras = encode_state(game.state, ["apple_dx", "apple_dy"])
|
|
return np.concatenate([board_vec, extras])
|