def analyse_ship(self, ship): """Must be executed after analyse_battleground""" self.reward = ship.agent.reward self.can_shoot = 0 if ship.can_shoot == 0 else 1 self.pointing = ship.pointing self.pos = Point(ship.body.x, ship.body.y) self.shipA = True # TODO add done to vector ? self.done = not ship.is_playable() self.toVector()
def crazy_runner(self, obs): """Ship is a fast boi. Ship can dance to.""" shoot = False thrust = random() < 0.9 if random() < 0.1: pointing = Point(randint(0, obs.dim.x), randint(0, obs.dim.y)) else: pointing = obs.pointing return Action(shoot=shoot, thrust=thrust, pointing=pointing)
def crazy_turret(self, obs): """Ship don't want to move. Ship only want to kill.""" shoot = random() < 0.8 thrust = False if random() < 0.3: pointing = Point(randint(0, obs.dim.x), randint(0, obs.dim.y)) else: pointing = obs.pointing return Action(shoot=shoot, thrust=thrust, pointing=pointing)
def read_keys(self): shoot = "shoot" in self.player.actions_set thrust = "thrust" in self.player.actions_set if "pointing" in self.player.actions_set: pointing = Point(self.player.cursor.x, self.player.cursor.y) else: pointing = self.pointing self.player.clear_keys() # print(shoot, thrust, pointing) return Action(shoot=shoot, thrust=thrust, pointing=pointing)
def __init__(self, x, y, battleground, behavior="idle"): # id of the fighter self.id = Ship.id_max Ship.id_max += 1 self.time = 0 # the ship know is own position # the ship is not invulnerable. the ship can be hit self.body = Circle(x, y, 8) # the ship resilience self.hull = 1 # the ship knows in which battleground he is self.battleground = battleground # the ship know is speed and direction self.speed = 0 self.max_speed = SHIPS_SPEED # the ship trajectory is an affine function that goes toward the cell the ship is pointing self.pointing = Point(x, y) # current state of the ship self.state = "flying" # there is no cooldown on the laser self.can_shoot = 1 # the human player controlling it. None if no player controls it self.player = None self.color = "Yellow" self.laser_color = "Red" # TODO improve. for the moment the score and steps are reset if the bot change in the middle if behavior == "network": self.agent = BrAIn() # self.initial_agent = BrAIn() elif behavior == "QlearnIA": self.agent = QlearnIA() # self.initial_agent = QlearnIA() # self.color = '#AA3300' self.color = "Green" self.laser_color = "Pink" else: self.agent = Agent(behavior) # self.initial_agent = Agent(behavior) # if the ia is in leroy mode time > 0 self.leroy_time = 0 # if the ship need to be actualised graphically self.actualise = False # the ship is colorful self.laser_speed = 10 self.obs_vector = np.array([]) self.act_vector = np.array([])
def fromVector(self, vector): # print("vector", vector) # if vector.size != Action.size: if vector.shape != Action.shape: raise Exception( "Invalid vector : expected shape {} but got shape {}.".format( Action.shape, vector.shape)) self.shoot = bool(vector[0][0]) self.thrust = bool(vector[1][0]) self.pointing = Point(vector[2][0], vector[3][0])
def random_play(self, obs): """Ship is confused. Ship don't know how to play.""" possibles = ["shoot", "thrust", "pointing"] action = choice(possibles) shoot = action == "shoot" thrust = action == "thrust" if action == "pointing": pointing = Point(randint(0, obs.dim.x), randint(0, obs.dim.y)) else: pointing = obs.pointing return Action(shoot=shoot, thrust=thrust, pointing=pointing)
def reset(self, x=None, y=None): # print("ship reset") # print(self.agent) self.agent.reset() self.time = 0 self.speed = 0 self.pointing = Point(self.body.x, self.body.y) self.body.x = x or self.body.x self.body.y = y or self.body.y self.state = "flying" self.can_shoot = 1 self.obs_vector = np.array([]) self.act_vector = np.array([])
def move(self, action): """The ship can think. The ship can act. The ship is a smart boi.""" self.time += 1 # If ship is destroyed ship can only contemplate sadness and despair if not action or not self.is_playable(): return None self.actualise = False if self.leroy_time == 1: self.back_to_normal() if self.leroy_time > 0: self.leroy_time -= 1 # there is a chance that the ia enter in leroy mode # the ia goes mad for some time, acting randomly # added to allow the ships to explore the possible actions and not stay passive if not self.player and self.leroy_time == 0 and self.agent.behavior == "network" and random( ) < LEROY_RATE: self.leroy_jenkins() # training reward depending on position # self.agent.reward = self.go_bottom_reward() if isinstance(action, ActionOneHot): if action.pointing: self.pointing = Point(randint(0, DEFAULT_WIDTH - 1), randint(0, DEFAULT_HEIGHT - 1)) elif isinstance(action, Action): if action.pointing: self.pointing = action.pointing # print("action.pointing", action.pointing) # print("turn ", self.direction) if action.thrust: self.thrust() if action.shoot: self.shoot()
def __init__(self, x, y, speed, pointing, battleground, owner=None, color="Red"): # print("piouu") self.id = Laser.id_max Laser.id_max += 1 self.body = Circle(x, y, radius=2) self.speed = speed * LIGHT_SPEED # the laser trajectory is an affine function that goes toward the cell the ship is pointing self.fired = Point(x, y) self.pointing = pointing self.battleground = battleground self.color = color self.time = 0 self.owner = owner self.state = "flying"
def shoot(self): edge = self.body.edge(self.pointing.x, self.pointing.y, 2) # there is no guarantee that such a edge exists if edge: laser = Laser(edge[0], edge[1], self.laser_speed, self.pointing, self.battleground, owner=self, color=self.laser_color) # if we point inside the ship hitbox the fired point of the laser become the center of the ship # but the real spawn point stay the same if self.body.collide(Circle(self.pointing.x, self.pointing.y, 2)): laser.fired = Point(self.body.x, self.body.y) self.battleground.lasers.append(laser) if self.any_enemy_aimed(self.pointing): self.agent.reward += REWARDS["aim"] if self.any_enemy_on_trajectory(self.pointing): self.agent.reward += REWARDS["trajectory"]
class Observation(): """ Observations can be stored in a vector of form 0 (binary) 1 if the ship can shot 0 otherwise 1 (int) reward from the last frame 2-3 (int>=0) cell on the map toward the ship is pointing 4-5 (int>=0) maxX, maxY. Dimensions of the map 6-7 (int>=0) position of the ship on the map w*h (binary 2d array) presence or absence of ship w*h (binary 2d array) presence or absence of laser """ observations = { "can_shoot": 1, "reward": 1, "pointing": 2, "dim": 2, "pos": 2, "ships_map": DEFAULT_WIDTH * DEFAULT_HEIGHT, "lasers_map": DEFAULT_WIDTH * DEFAULT_HEIGHT, } size = sum(observations.values()) print("size observations", size) def __init__(self, **kwargs): """ reward (int) value of the last frame reward can_shoot (bool) True if we can shoot pointing (Point) point on the map we are pointing dim (Couple) pair of integers storing the size of the map pos (Point) pair of integers storing the position of the ship ships_map (2d array/list like) presence or absence of ship lasers_map (2d array/list like) presence or absence of laser """ # vector storing the observation self.vector = None # are ship and battleground analysed self.btlgA = False self.shipA = False # battleground related infos self.battleground = None self.dim = None self.ship_map = None self.laser_map = None # ship related infos self.reward = None self.can_shoot = None self.pointing = None self.pos = None self.done = None battleground = kwargs.get('battleground') ship = kwargs.get('ship') if battleground: self.analyse_battleground(battleground) if ship: self.analyse_ship(ship) def analyse_battleground(self, battleground): self.battleground = battleground self.dim = battleground.dim # TODO check if coords need to be reverses as it is a numpy array and y comes first # could pose problems if the map is a rectangle # or we can try to create them already transposed self.ship_map = np.zeros((self.dim.x, self.dim.y)) for ship in battleground.ships: if ship.is_playable(): self.ship_map = ship.body.binary_draw(self.ship_map) self.laser_map = np.zeros((self.dim.x, self.dim.y)) for laser in battleground.lasers: self.laser_map = laser.body.binary_draw(self.laser_map) self.btlgA = True # .T to transpose to print it the right way # print("ship_map\n", self.ship_map.T) # print("laser_map\n", self.laser_map.T) def analyse_ship(self, ship): """Must be executed after analyse_battleground""" self.reward = ship.agent.reward self.can_shoot = 0 if ship.can_shoot == 0 else 1 self.pointing = ship.pointing self.pos = Point(ship.body.x, ship.body.y) self.shipA = True # TODO add done to vector ? self.done = not ship.is_playable() self.toVector() # TODO add information isPlayer def toVector(self): if not self.btlgA: raise Exception("You must execute analyse_battleground first.") if not self.shipA: raise Exception("You must execute analyse_ship first.") vector = np.array(self.reward) vector = np.append(vector, self.can_shoot) vector = np.append(vector, self.pointing.toArray()) vector = np.append(vector, self.dim.toArray()) vector = np.append(vector, self.pos.toArray()) vector = np.append(vector, self.ship_map) vector = np.append(vector, self.laser_map) # print(vector) # putting the vector vertically instead of horizontally vector = vector.reshape(vector.size, 1) # print("observations vector\n", vector) # print("vector size\n", vector.size) # print("expected size\n", Observation.size) self.vector = vector return vector def toNumpy(self): if not self.btlgA: raise Exception("You must execute analyse_battleground first.") if not self.shipA: raise Exception("You must execute analyse_ship first.") def fromVector(self, vector): raise Exception("Not implemented.") def toBattleground(self): raise Exception("Not implemented.")