Refactoring lab
This commit is contained in:
161
games/frogger/__init__.py
Normal file
161
games/frogger/__init__.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""Frogger: guide a frog across busy traffic lanes to reach the far side.
|
||||
|
||||
The frog starts at the bottom row. Cars move across the lanes between the
|
||||
start and goal. Each lane has cars moving at different speeds in alternating
|
||||
directions. The frog earns +10 for each row advanced, +50 for reaching the
|
||||
top row, and -10 for being hit by a car or falling off the edge. Episodes end
|
||||
when the frog reaches the top, gets hit, or energy runs out.
|
||||
"""
|
||||
|
||||
from random import randint
|
||||
from retro.game import Game
|
||||
|
||||
BOARD_WIDTH = 20
|
||||
BOARD_HEIGHT = 12
|
||||
NUM_LANES = BOARD_HEIGHT - 2
|
||||
START_ENERGY = 200
|
||||
|
||||
|
||||
class Frog:
|
||||
name = "Frog"
|
||||
character = 'O'
|
||||
color = "green_on_black"
|
||||
position = (0, 0)
|
||||
|
||||
UP = (0, -1)
|
||||
DOWN = (0, 1)
|
||||
LEFT = (-1, 0)
|
||||
RIGHT = (1, 0)
|
||||
|
||||
def __init__(self):
|
||||
self._direction = self.UP
|
||||
|
||||
def handle_keystroke(self, keystroke, game):
|
||||
if keystroke.name == "KEY_UP":
|
||||
self._direction = self.UP
|
||||
elif keystroke.name == "KEY_DOWN":
|
||||
self._direction = self.DOWN
|
||||
elif keystroke.name == "KEY_LEFT":
|
||||
self._direction = self.LEFT
|
||||
elif keystroke.name == "KEY_RIGHT":
|
||||
self._direction = self.RIGHT
|
||||
|
||||
def play_turn(self, game):
|
||||
bw, bh = game.board_size
|
||||
x, y = self.position
|
||||
dx, dy = self._direction
|
||||
nx, ny = x + dx, y + dy
|
||||
|
||||
if not (0 <= nx < bw):
|
||||
game.state['reward'] -= 10
|
||||
game.state['energy'] -= 50
|
||||
self._reset(game)
|
||||
return
|
||||
|
||||
if not (0 <= ny < bh):
|
||||
if ny < 0:
|
||||
game.state['score'] += 50
|
||||
game.state['reward'] += 50
|
||||
else:
|
||||
game.state['reward'] -= 5
|
||||
self._reset(game)
|
||||
return
|
||||
|
||||
prev_y = y
|
||||
self.position = (nx, ny)
|
||||
game.state['energy'] -= 1
|
||||
game.state['reward'] -= 0.01
|
||||
|
||||
if ny < prev_y:
|
||||
advancement = prev_y - ny
|
||||
game.state['score'] += advancement * 10
|
||||
game.state['reward'] += advancement * 5
|
||||
|
||||
for agent in game.agents:
|
||||
if hasattr(agent, '_is_car') and agent.position == self.position:
|
||||
game.state['reward'] -= 10
|
||||
game.state['energy'] -= 50
|
||||
self._reset(game)
|
||||
return
|
||||
|
||||
bw, bh = game.board_size
|
||||
fx, fy = self.position
|
||||
game.state['frog_x'] = fx / bw
|
||||
game.state['frog_y'] = fy / bh
|
||||
|
||||
if game.state['energy'] <= 0:
|
||||
game.end()
|
||||
|
||||
def _reset(self, game):
|
||||
bw, bh = game.board_size
|
||||
self.position = (bw // 2, bh - 1)
|
||||
self._direction = self.UP
|
||||
if game.state['energy'] <= 0:
|
||||
game.end()
|
||||
|
||||
|
||||
class Car:
|
||||
_is_car = True
|
||||
character = 'X'
|
||||
color = "red_on_black"
|
||||
|
||||
def __init__(self, lane, speed, direction, start_x, board_width):
|
||||
self.name = f"Car {lane}_{start_x}"
|
||||
self._lane = lane
|
||||
self._speed = speed
|
||||
self._direction = direction
|
||||
self._board_width = board_width
|
||||
self._step = 0
|
||||
self.position = (start_x, lane)
|
||||
|
||||
def play_turn(self, game):
|
||||
self._step += 1
|
||||
if self._step < self._speed:
|
||||
return
|
||||
self._step = 0
|
||||
x, y = self.position
|
||||
x = (x + self._direction) % self._board_width
|
||||
self.position = (x, y)
|
||||
|
||||
frog = game.get_agent_by_name("Frog")
|
||||
if frog.position == self.position:
|
||||
frog._reset(game)
|
||||
game.state['reward'] -= 10
|
||||
game.state['energy'] -= 50
|
||||
|
||||
|
||||
def create_game():
|
||||
bw, bh = BOARD_WIDTH, BOARD_HEIGHT
|
||||
frog = Frog()
|
||||
frog.position = (bw // 2, bh - 1)
|
||||
|
||||
agents = [frog]
|
||||
car_id = 0
|
||||
for lane_idx, row in enumerate(range(1, bh - 1)):
|
||||
direction = 1 if lane_idx % 2 == 0 else -1
|
||||
speed = 2 + (lane_idx % 3)
|
||||
num_cars = 2 + (lane_idx % 3)
|
||||
spacing = bw // num_cars
|
||||
for i in range(num_cars):
|
||||
start_x = (i * spacing + lane_idx * 3) % bw
|
||||
agents.append(Car(row, speed, direction, start_x, bw))
|
||||
car_id += 1
|
||||
|
||||
game = Game(
|
||||
agents,
|
||||
{
|
||||
'score': 0,
|
||||
'reward': 0.0,
|
||||
'energy': START_ENERGY,
|
||||
'frog_x': (bw // 2) / bw,
|
||||
'frog_y': (bh - 1) / bh,
|
||||
},
|
||||
board_size=(bw, bh),
|
||||
framerate=8,
|
||||
show_state=['score', 'energy'],
|
||||
)
|
||||
return game
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
create_game().play()
|
||||
Reference in New Issue
Block a user