Source code for ple.games.waterworld

import pygame
import sys
import math

import base

from utils.vec2d import vec2d
from utils import percent_round_int
from pygame.constants import K_w, K_a, K_s, K_d
from primitives import Player, Creep

[docs]class WaterWorld(base.Game): """ Based Karpthy's WaterWorld in `REINFORCEjs`_. .. _REINFORCEjs: https://github.com/karpathy/reinforcejs Parameters ---------- width : int Screen width. height : int Screen height, recommended to be same dimension as width. num_creeps : int (default: 3) The number of creeps on the screen at once. """ def __init__(self, width=48, height=48, num_creeps=3): actions = { "up": K_w, "left": K_a, "right": K_d, "down": K_s } base.Game.__init__(self, width, height, actions=actions) self.BG_COLOR = (255, 255, 255) self.N_CREEPS = num_creeps self.CREEP_TYPES = [ "GOOD", "BAD" ] self.CREEP_COLORS = [ (40, 140, 40), (150, 95, 95) ] radius = percent_round_int(width, 0.047) self.CREEP_RADII = [ radius, radius ] self.CREEP_REWARD = [ self.rewards["positive"], self.rewards["negative"] ] self.CREEP_SPEED = 0.25*width self.AGENT_COLOR = (60, 60, 140) self.AGENT_SPEED = 0.25*width self.AGENT_RADIUS = radius self.AGENT_INIT_POS = (self.width/2, self.height/2) self.creep_counts = { "GOOD": 0, "BAD": 0 } self.dx = 0 self.dy = 0 self.player = None self.creeps = None def _handle_player_events(self): self.dx = 0 self.dy = 0 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: key = event.key if key == self.actions["left"]: self.dx -= self.AGENT_SPEED if key == self.actions["right"]: self.dx += self.AGENT_SPEED if key == self.actions["up"]: self.dy -= self.AGENT_SPEED if key == self.actions["down"]: self.dy += self.AGENT_SPEED def _add_creep(self): creep_type = self.rng.choice([0, 1]) creep = None pos = ( 0,0 ) dist = 0.0 while dist < 1.5: radius = self.CREEP_RADII[creep_type]*1.5 pos = self.rng.uniform(radius, self.height-radius, size=2) dist = math.sqrt( (self.player.pos.x - pos[0])**2 + (self.player.pos.y - pos[1])**2 ) creep = Creep( self.CREEP_COLORS[creep_type], self.CREEP_RADII[creep_type], pos, self.rng.choice([-1,1], 2), self.rng.rand()*self.CREEP_SPEED, self.CREEP_REWARD[creep_type], self.CREEP_TYPES[creep_type], self.width, self.height, self.rng.rand() ) self.creeps.add(creep) self.creep_counts[ self.CREEP_TYPES[creep_type] ] += 1
[docs] def getGameState(self): """ Returns ------- dict * player x position. * player y position. * player x velocity. * player y velocity. * player distance to each creep """ state = { "player_x": self.player.pos.x, "player_y": self.player.pos.y, "player_velocity_x": self.player.vel.x, "player_velocity_y": self.player.vel.y, "creep_dist": { "GOOD": [], "BAD": [] } } for c in self.creeps: dist = math.sqrt( (self.player.pos.x - c.pos.x)**2 + (self.player.pos.y - c.pos.y)**2 ) state["creep_dist"][c.TYPE].append(dist) return state
def getScore(self): return self.score def game_over(self): """ Return bool if the game has 'finished' """ return ( self.creep_counts['GOOD'] == 0 ) def init(self): """ Starts/Resets the game to its inital state """ self.creep_counts = { "GOOD":0, "BAD":0 } if self.player is None: self.player = Player( self.AGENT_RADIUS, self.AGENT_COLOR, self.AGENT_SPEED, self.AGENT_INIT_POS, self.width, self.height ) else: self.player.pos = vec2d(self.AGENT_INIT_POS) self.player.vel = vec2d((0.0,0.0)) if self.creeps is None: self.creeps = pygame.sprite.Group() else: self.creeps.empty() for i in range(self.N_CREEPS): self._add_creep() self.score = 0 self.ticks = 0 self.lives = -1 def step(self, dt): """ Perform one step of game emulation. """ dt /= 1000.0 self.screen.fill(self.BG_COLOR) self.score += self.rewards["tick"] self._handle_player_events() self.player.update(self.dx, self.dy, dt) hits = pygame.sprite.spritecollide(self.player, self.creeps, True) for creep in hits: self.creep_counts[creep.TYPE] -= 1 self.score += creep.reward self._add_creep() if self.creep_counts["GOOD"] == 0: self.score += self.rewards["win"] self.creeps.update(dt) self.player.draw(self.screen) self.creeps.draw(self.screen)
if __name__ == "__main__": import numpy as np pygame.init() game = WaterWorld(width=256, height=256, num_creeps=10) game.screen = pygame.display.set_mode( game.getScreenDims(), 0, 32) game.clock = pygame.time.Clock() game.rng = np.random.RandomState(24) game.init() while True: dt = game.clock.tick_busy_loop(30) game.step(dt) pygame.display.update()