def get_entities_in_front(self, entity): """ Get the entities that are in front of the given entity. :param entity: The entity for which we should get the entities that are in front of it """ pos = Position(entity.get_position()) pos.add(entity.get_move_delta()) return self.get_entities_at(pos)
def can_step(self, agent): position = Position(agent.get_position()) position.add(agent.get_move_delta(1)) return not self.entity_rect_collision( ( position.get_x(), position.get_y(), agent.get_width(), agent.get_height() ) )
def assert_input(): b = Board() b.put(Position(4, 3), Soldier(player_1)) b.put(Position(4, 2), Soldier(player_1)) b.put(Position(4, 4), Soldier(player_2)) b.put(Position(4, 5), Soldier(player_2)) g = Game(b) g.replenish(100) player_action = g.validate_player_move(PlayerMove.from_literal(player_2, "4443 4546")) assert(str(player_action) == '55->54(ATK),56->57(MOV)') player_action = g.validate_player_move(PlayerMove.from_literal(player_1, "4342 4252")) assert(str(player_action) == '54->53(DEF),53->63(UPG)')
def assert_invalid_input(): b = Board() b.put(Position(4, 3), Soldier(player_1)) b.put(Position(4, 4), Soldier(player_2)) g = Game(b) g.replenish(100) try: g.validate_player_move(PlayerMove.from_literal(player_2, "5554 5565")) except rule.InvalidMoveException: pass else: assert (None)
def assert_attack_defend(): b = Board() p2u1 = Position.from_literal('55') p2u2 = Position.from_literal('66') p2u3 = Position.from_literal('61') #p2u4 = Position.from_literal('65') p1u1 = Position.from_literal('54') p1u2 = Position.from_literal('53') p1u3 = Position.from_literal('62') p1u4 = Position.from_literal('67') p1u5 = Position.from_literal('56') b.put(p2u1, Soldier(player_2)) b.put(p2u2, Rider(player_2, flip_skillset=True)) b.put(p2u3, Soldier(player_2)) #b.put(p2u4, Barbarian(player_2, flip_skillset=True))) b.put(p1u1, Rider(player_1)) b.put(p1u2, Soldier(player_1)) b.put(p1u3, Rider(player_1)) b.put(p1u4, Soldier(player_1)) b.put(p1u5, Soldier(player_1)) g = Game(b) g.replenish(100) # renderer.show_canvas( # paint.get_painted_canvas( # g, {player_1:'a', player_2:'b'}, player_1)) g = g.make_move([ PlayerMove.from_literal(player_2, "5554 6654 6162"), PlayerMove.from_literal(player_1, "5354 6254 6766 5655 5446") ]) # for clash_brief in g.round_brief.clash_briefs: # print(clash_brief.brief()) # for battle_brief in g.round_brief.battle_briefs: # print(battle_brief.brief()) assert (g.board.at(p2u1).owner == player_1) assert (g.board.at(p2u2).owner == player_1) assert (g.board.at(p2u3) is None) assert (g.board.at(p1u1) is None) assert (g.board.at(p1u2).owner == player_1) assert (g.board.at(p1u3).owner == player_2) assert (g.board.at(p1u4) is None) assert (g.board.at(p1u5) is None) assert (g.board.at(Position.from_literal('46')).owner == player_1)
def assert_clash(): b = Board() p1p = Position(4, 3) p2p = Position(4, 4) b.put(p1p, Soldier(player_1)) b.put(p2p, Soldier(player_2)) g = Game(b) g.replenish(100) g = g.make_move([ PlayerMove.from_literal(player_2, "5554"), PlayerMove.from_literal(player_1, "5455") ]) assert (g.board.at(p1p) is None) assert (g.board.at(p2p) is None)
def set_out(board): for row, setting, player in [ (0, board_setting_1st_row, player_2), (1, board_setting_2nd_row, player_2), (board_size_y - 1, board_setting_1st_row, player_1), (board_size_y - 2, board_setting_2nd_row, player_1) ]: for i in range(board_size_x): board.put(Position(i, row), setting[i](player))
def deserialize(cls, payload): b = Board() s = json.loads(payload) for i in range(board_size_x): for j in range(board_size_y): u = s.pop(0) if u != 0: b.put(Position(i, j), Unit.deserialize(u)) return b
def serialize(self): s = [] for i in range(board_size_x): for j in range(board_size_y): unit = self.at(Position(i, j)) if unit: s.append(unit.serialize()) else: s.append(0) return json.dumps(s)
def assert_move_conflict(): b = Board() p1p1 = Position(4, 2) p2p1 = Position(4, 4) p1p2 = Position(5, 2) p1p3 = Position(6, 1) p2p2 = Position(5, 4) b.put(p1p1, Soldier(player_1)) b.put(p2p1, Soldier(player_2)) b.put(p1p2, Soldier(player_1)) b.put(p1p3, Rider(player_1)) b.put(p2p2, Soldier(player_2)) g = Game(b) g.replenish(100) g = g.make_move([ PlayerMove.from_literal(player_2, "5554 6564"), PlayerMove.from_literal(player_1, "5354 6364 7264") ]) assert (g.board.at(p1p1) is None) assert (g.board.at(p2p1) is None) assert (g.board.at(p1p2) is None) assert (g.board.at(p1p3) is not None) assert (g.board.at(p2p2) is None) assert (g.board.at(Position(5, 3)).owner == player_1)
def center(pos, cent, w, h): """ Given a position in-game, returns the corresponding position when padded to 128 by 128, around cent, the center. """ if (pos.x - cent.x) % w < (cent.x - pos.x) % w: x_adj = 64 + (pos.x - cent.x) % w else: x_adj = 64 - (cent.x - pos.x) % w if (pos.y - cent.y) % h < (cent.y - pos.y) % h: y_adj = 64 + (pos.y - cent.y) % h else: y_adj = 64 - (cent.y - pos.y) % h return Position(x_adj, y_adj)
def assert_clash(): b = Board() p1p = Position(4, 3) p1p2 = Position(5, 6) p2p = Position(4, 4) s = Spearman(player_1, SkillSet()) s.endow(Skill(PositionDelta(0, 1))) b.put(p1p, s) r = Rider(player_1) r.endow(Skill(PositionDelta(-1, -2))) b.put(p1p2, r) b.put(p2p, Soldier(player_2)) g = Game(b) g.replenish(100) g = g.make_move([ PlayerMove.from_literal(player_2, "4443"), PlayerMove.from_literal(player_1, "5644 4344")]) assert(type(g.martyr_list[0].board_unit.unit) == Soldier) assert(type(g.board.at(p1p)) == Spearman) assert(type(g.board.at(p2p)) == Rider)
def assert_buffs(): b = Board() b.put(Position.from_literal('55'), make_perfect(Lancer(player_1, SkillSet()))) b.put(Position.from_literal('66'), make_perfect(Knight(player_1, SkillSet()))) b.put(Position.from_literal('46'), make_perfect(Knight(player_1, SkillSet()))) b.put(Position.from_literal('68'), make_perfect(Warrior(player_2, SkillSet()))) b.put(Position.from_literal('78'), make_perfect(Spearman(player_1, SkillSet()))) b.put(Position.from_literal('88'), make_perfect(Spearman(player_1, SkillSet()))) b.put(Position.from_literal('53'), make_perfect(Soldier(player_1))) b.put(Position.from_literal('52'), make_perfect(Soldier(player_2))) b.put(Position.from_literal('59'), Swordsman(player_1, SkillSet())) g = Game(b) g = g.make_move([ PlayerMove.from_literal(player_1, "4241 4442 5563 4857 6757 7757"), PlayerMove.from_literal(player_2, "")]) assert(g.supply[player_1] == 29) # 40 - 16 + 5
def get_free_positions(self): """ Get all positions without any entities :return: A list of positions without entities. """ free = [] for x in range(self.width): for y in range(self.height): p = Position((x, y)) if len(self.get_entities_at(p)) == 0: free.append(p) return free
def assert_attack_defend(): b = Board() p2u1 = Position.from_literal('55') p2u2 = Position.from_literal('66') p2u3 = Position.from_literal('61') p1u1 = Position.from_literal('54') p1u2 = Position.from_literal('53') p1u3 = Position.from_literal('62') p1u4 = Position.from_literal('67') p1u5 = Position.from_literal('56') b.put(p2u1, Soldier(player_2)) b.put(p2u2, make_perfect(Rider(player_2))) b.put(p2u3, Soldier(player_2)) b.put(p1u1, make_perfect(Rider(player_1))) b.put(p1u2, Soldier(player_1)) b.put(p1u3, make_perfect(Rider(player_1))) b.put(p1u4, Soldier(player_1)) b.put(p1u5, Soldier(player_1)) g = Game(b) g.replenish(100) g = g.make_move([ PlayerMove.from_literal(player_2, "4443 5543 5051"), PlayerMove.from_literal(player_1, "4243 5143 5655 4544 4335")]) assert(g.board.at(p2u1).owner == player_1) assert(g.board.at(p2u2).owner == player_1) assert(g.board.at(p2u3) is None) assert(g.board.at(p1u1) is None) assert(g.board.at(p1u2).owner == player_1) assert(g.board.at(p1u3).owner == player_2) assert(g.board.at(p1u4) is None) assert(g.board.at(p1u5) is None) assert(g.board.at(Position.from_literal('46')).owner == player_1)
def get_random_player_move(self, player): move_list = [] while random.randint(0, 12) != 0: if random.randint(0, 8) == 0: recruit_position = Position( random.randint(0, board_size_x - 1), rule.spawn_row[player]) move = Move(recruit_position, recruit_position) else: move = random.choice( rule.all_valid_moves(self.board, player, True)) try: self.validate_player_move( PlayerMove(player, move_list + [move])) move_list.append(move) except rule.InvalidMoveException: break print(move_list) return PlayerMove(player, move_list)
def assert_recall(): b = Board() b.put(Position.from_literal('55'), King(player_1)) b.put(Position.from_literal('57'), make_perfect(Soldier(player_2, SkillSet()))) b.put(Position.from_literal('88'), make_perfect(Soldier(player_2, SkillSet()))) b.put(Position.from_literal('89'), make_perfect(Lancer(player_1, SkillSet()))) b.put(Position.from_literal('11'), make_perfect(Lancer(player_1, SkillSet()))) g = Game(b) try: g = g.make_move([ PlayerMove.from_literal(player_1, "5478"), PlayerMove.from_literal(player_2, "")]) except: pass else: raise Exception() try: g = g.make_move([ PlayerMove.from_literal(player_1, "4500"), PlayerMove.from_literal(player_2, "")]) except: pass else: raise Exception() g = g.make_move([ PlayerMove.from_literal(player_1, "5400"), PlayerMove.from_literal(player_2, "")]) assert(g.board.at(Position.from_literal('11')) is None) assert(g.board.at(Position.from_literal('65')).owner == player_1)
def step(self, game): def dist(a, b): return min(abs(a.x - b.x), game.size - abs(a.x - b.x)) + min(abs(a.y - b.y), game.size - abs(a.y - b.y)) commands = {} next_pos = {} # ship id: next position next_ships = [] # next_ships[y][x] = list of ships that will end want to move to y x rem = game.max_turns - game.turn for y in range(game.size): next_ships.append([]) for x in range(game.size): next_ships[y].append([]) self.halite = game.banks[self.id] for ship in game.ships.values(): if ship.owner_id == self.id: if ship.halite > 800 or game.turn + dist(ship, self.shipyard) + 20 > game.max_turns: self.returning[ship.id] = True elif ship.x == self.shipyard.x and ship.y == self.shipyard.y: self.returning[ship.id] = False if ship.halite < game.cells[ship.y][ship.x][0] // 10: next_pos[ship.id] = Position(ship.x, ship.y) else: if random.random() < self.eps: t = Position(random.randint(0, game.size), random.randint(0, game.size)) elif self.returning[ship.id]: t = Position(self.shipyard.x, self.shipyard.y) else: t = Position(ship.x, ship.y) for dx in range(-2, 3): for dy in range(-2, 3): p = Position((ship.x + dx) % game.size, (ship.y + dy) % game.size) if (game.cells[p.y][p.x][0]) / (dist(ship, p) + 1) > game.cells[t.y][t.x][0] / (dist(t, ship) + 1): t = p xdl = (ship.x - t.x) % game.size xdr = (t.x - ship.x) % game.size ydd = (ship.y - t.y) % game.size ydu = (t.y - ship.y) % game.size if xdl == xdr == 0: x_dir = 0 elif xdl <= xdr: x_dir = -1 else: x_dir = 1 if ydd == ydu == 0: y_dir = 0 elif ydd <= ydu: y_dir = -1 else: y_dir = 1 if x_dir != 0 and y_dir != 0: x_pen = game.cells[ship.y][(ship.x + x_dir) % game.size][0] y_pen = game.cells[(ship.y + y_dir) % game.size][ship.x][0] if len(next_ships[ship.y][(ship.x + x_dir) % game.size]) > 0: x_pen += 3000 elif game.cells[ship.y][(ship.x + x_dir) % game.size][2] != -1: x_pen += 300 if len(next_ships[(ship.y + y_dir) % game.size][ship.x]) > 0: y_pen += 3000 elif game.cells[(ship.y + y_dir) % game.size][ship.x][2] != -1: y_pen += 300 if x_pen < y_pen: next_pos[ship.id] = Position((ship.x + x_dir) % game.size, ship.y) if x_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') else: next_pos[ship.id] = Position(ship.x, (ship.y + y_dir) % game.size) if y_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') elif x_dir != 0: next_pos[ship.id] = Position((ship.x + x_dir) % game.size, ship.y) if x_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') elif y_dir != 0: next_pos[ship.id] = Position(ship.x, (ship.y + y_dir) % game.size) if y_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') else: next_pos[ship.id] = Position(ship.x, ship.y) next_ships[next_pos[ship.id].y][next_pos[ship.id].x].append(ship) q = [ship for ship in game.ships.values() if ship.owner_id == self.id and ship.id in next_pos and (next_pos[ship.id].x != ship.x or next_pos[ship.id].y != ship.y)] while q: ship = q.pop() nx = next_pos[ship.id].x ny = next_pos[ship.id].y if len(next_ships[ny][nx]) > 1 and not (rem <= 50 and nx == self.shipyard.x and ny == self.shipyard.y): cur = Position(ship.x, ship.y) done = False visited = set() while not done: cur = next_pos[game.cells[cur.y][cur.x][2]] # if hits empty or enemy, then not a cycle if game.cells[cur.y][cur.x][2] == -1 or game.ships[game.cells[cur.y][cur.x][2]].owner_id != self.id: break # if ship stops, then not a cycle if cur == next_pos[game.cells[cur.y][cur.x][2]]: break if cur == Position(ship.x, ship.y): done = True continue elif game.cells[cur.y][cur.x][2] in visited: break visited.add(game.cells[cur.y][cur.x][2]) else: continue next_ships[next_pos[ship.id].y][next_pos[ship.id].x].remove(ship) next_pos[ship.id].x = ship.x next_pos[ship.id].y = ship.y commands[ship.id] = MoveCommand(self.id, ship.id, 'O') q.extend(next_ships[ship.y][ship.x]) next_ships[ship.y][ship.x].append(ship) ret = list(commands.values()) if (len(next_ships[self.shipyard.y][self.shipyard.x]) == 0 and self.halite >= 1000 and rem > 100 and np.sum(game.cells[:, :, 0]) * 3 > self.map_starting_halite): ret.append(SpawnShipCommand(self.id, None)) return ret
def iterate_units(self, func): for i in range(board_size_x): for j in range(board_size_y): u = self.board[i][j] if u is not None: func(u, Position(i, j))
def iterate(self, func): for i in range(board_size_x): for j in range(board_size_y): p = Position(i, j) func(self.board.at(p), p)
def iterate_battles(self, func): for i in range(board_size_x): for j in range(board_size_y): p = Position(i, j) if self.arrive_board.at(p).count() > 0: func(p)
def step(self, game): def dist(a, b): return min(abs(a.x - b.x), game.width - abs(a.x - b.x)) + min( abs(a.y - b.y), game.height - abs(a.y - b.y)) commands = {} next_pos = {} # ship id: next position next_ships = [ ] # next_ships[y][x] = list of ships that will end want to move to y x for y in range(game.height): next_ships.append([]) for x in range(game.width): next_ships[y].append([]) for dropoff in self.new_dropoffs: self.dropoffs.append( game.constructs[game.cells[dropoff.y][dropoff.x][1]]) # attraction = np.zeros((game.height, game.width)) dominance = np.zeros((game.height, game.width), dtype=int) mined = np.zeros((game.height, game.width), dtype=bool) for x in range(game.width): for y in range(game.height): for dx in range(-5, 6): for dy in range(-5 + abs(dx), 6 - abs(dx)): wx = (x + dx) % game.width wy = (y + dy) % game.height if game.cells[wy][wx][2] != -1: if game.ships[game.cells[wy][wx] [2]].owner_id == self.id: dominance[y][x] += 1 else: dominance[y][x] -= 1 # attraction[y][x] += game.cells[wy][wx][0] / (2 ** (abs(dx) + abs(dy))) self.halite = game.bank[self.id] if game.max_turns - game.turn > 200: for x in range(game.width): for y in range(game.height): for dropoff in self.dropoffs: if abs(x - dropoff.x) + abs(y - dropoff.y) < 25: break else: if game.cells[y][x][1] != -1 or dominance[y][ x] < 5 or game.max_turns - game.turn <= 100: continue surrounding_halite = 0 for dx in range(-10, 11): for dy in range(-10 + abs(dx), 11 - abs(dx)): surrounding_halite += game.cells[ (y + dy) % game.height][(x + dx) % game.width][0] if surrounding_halite > 2000: self.pd = Position(x, y) dropoff_ship_id = None if self.pd is not None: mine = [s for s in game.ships.values() if s.owner_id == self.id] rich = [ s for s in game.ships.values() if s.owner_id == self.id and s.halite + self.halite + game.cells[self.pd.y][self.pd.x][0] >= 4000 ] if len(mine) > 0: cm = min(mine, key=lambda s: dist(s, self.pd)) dropoff_ship_id = cm.id if len(rich) > 0: cr = min(rich, key=lambda s: dist(s, self.pd)) if dist(cr, self.pd) - 3 < dist(cm, self.pd): dropoff_ship_id = cr.id for ship in sorted(game.ships.values(), key=lambda s: s.id): if ship.owner_id != self.id: continue if dropoff_ship_id is not None and ship.id == dropoff_ship_id: if ship.x != self.pd.x or ship.y != self.pd.y: t = self.pd # print(f'Ship {dropoff_ship_id} targeting {t} for dropoff construction') elif self.halite + game.cells[self.pd.y][self.pd.x][ 0] + game.ships[dropoff_ship_id].halite >= 4000: commands[ship.id] = ConstructDropoffCommand( self.id, ship.id) self.pd = None self.halite -= 4000 self.new_dropoffs.append(Position(ship.x, ship.y)) continue else: # print(f'Ship {dropoff_ship_id} waiting for dropoff construction halite') next_pos[ship.id] = Position(ship.x, ship.y) continue else: nd = min(self.dropoffs, key=lambda d: dist(ship, d)) # nearest dropoff if ship.halite > 950 or game.turn + dist( ship, nd) + 20 > game.max_turns: self.returning[ship.id] = True elif ship.halite == 0: self.returning[ship.id] = False if ship.halite < game.cells[ship.y][ship.x][0] // 10: next_pos[ship.id] = Position(ship.x, ship.y) next_ships[next_pos[ship.id].y][next_pos[ ship.id].x].append(ship) continue if self.returning[ship.id]: t = Position(nd.x, nd.y) # print(f'Ship {ship.id} targeting {t} for a return') else: # local mining t = Position(ship.x, ship.y) for dx in range(-3, 4): for dy in range(-3 + abs(dx), 4 - abs(dx)): wx = (ship.x + dx) % game.width wy = (ship.y + dy) % game.height if not mined[wy][wx] and game.cells[wy][wx][ 0] - 50 * (abs(dx) + abs(dy) + dist( Position(wx, wy), nd)) > game.cells[ t.y][t.x][0] - 50 * ( dist(t, ship) + dist(t, nd)): t.x = wx t.y = wy # long distance mining if game.cells[t.y][t.x][0] - 50 * (dist(t, ship) + dist( t, nd) - dist(ship, nd)) <= 100: v = game.cells[t.y][t.x][0] / (dist(t, ship) + dist(t, nd) + 1) for dx in range(-10, 11): for dy in range(-10 + abs(dx), 11 - abs(dx)): pos = Position((ship.x + dx) % game.width, (ship.y + dy) % game.height) pnd = min(self.dropoffs, key=lambda d: dist(pos, d)) if not mined[pos.y][pos.x] and game.cells[ pos.y][pos.x][0] / (dist(pos, ship) + dist(pos, pnd) + 1) > v: t = pos v = game.cells[pos.y][pos.x][0] / ( abs(dx) + abs(dy) + dist(pos, pnd) + 1) # print(f'Ship {ship.id} targeting {t} for long distance mining') else: pass # print(f'Ship {ship.id} targeting {t} for local mining') mined[t.y][t.x] = True xdl = (ship.x - t.x) % game.width xdr = (t.x - ship.x) % game.width ydd = (ship.y - t.y) % game.height ydu = (t.y - ship.y) % game.height if xdl == xdr == 0: x_dir = 0 elif xdl <= xdr: x_dir = -1 else: x_dir = 1 if ydd == ydu == 0: y_dir = 0 elif ydd <= ydu: y_dir = -1 else: y_dir = 1 if x_dir != 0 and y_dir != 0: x_pen = game.cells[ship.y][(ship.x + x_dir) % game.width][0] y_pen = game.cells[(ship.y + y_dir) % game.height][ship.x][0] if len(next_ships[ship.y][(ship.x + x_dir) % game.width]) > 0: x_pen += 3000 elif game.cells[ship.y][(ship.x + x_dir) % game.width][2] != -1: x_pen += 300 if len(next_ships[ship.y + y_dir][ship.x]) > 0: y_pen += 3000 elif game.cells[(ship.y + y_dir) % game.height][ship.x][2] != -1: y_pen += 300 if x_pen < y_pen: next_pos[ship.id] = Position((ship.x + x_dir) % game.width, ship.y) if x_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') else: next_pos[ship.id] = Position(ship.x, (ship.y + y_dir) % game.height) if y_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') elif x_dir != 0: next_pos[ship.id] = Position((ship.x + x_dir) % game.width, ship.y) if x_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') elif y_dir != 0: next_pos[ship.id] = Position(ship.x, (ship.y + y_dir) % game.height) if y_dir == -1: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') else: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') else: next_pos[ship.id] = Position(ship.x, ship.y) next_ships[next_pos[ship.id].y][next_pos[ship.id].x].append(ship) # print(next_pos) # print(game.ships) # print(next_ships) q = [ ship for ship in game.ships.values() if ship.owner_id == self.id and ship.id in next_pos and ( next_pos[ship.id].x != ship.x or next_pos[ship.id].y != ship.y) ] while q: ship = q.pop() nx = next_pos[ship.id].x ny = next_pos[ship.id].y if len(next_ships[ny][nx]) > 1 and not ( game.max_turns - game.turn <= 50 and any(d.x == nx and d.y == ny for d in self.dropoffs)): # is ship part of cycle, let the cycle do its thing no matter what current = next_pos[ship.id] while current != Position(ship.x, ship.y): if game.cells[next_pos[ship.id].y][next_pos[ ship.id].x][2] == -1 or game.ships[game.cells[ next_pos[ship.id].y][next_pos[ ship.id].x][2]].owner_id != self.id: break if current == next_pos[game.cells[next_pos[ship.id].y][ next_pos[ship.id].x][2]]: break current = next_pos[game.cells[next_pos[ship.id].y][ next_pos[ship.id].x][2]] else: continue # print(f'Stopped ship id {ship.id} to prevent collision') next_ships[next_pos[ship.id].y][next_pos[ship.id].x].remove( ship) next_pos[ship.id].x = ship.x next_pos[ship.id].y = ship.y commands[ship.id] = MoveCommand(self.id, ship.id, 'O') q.extend(next_ships[ship.y][ship.x]) next_ships[ship.y][ship.x].append(ship) ret = list(commands.values()) if (len(next_ships[self.shipyard.y][self.shipyard.x]) == 0 and self.halite >= (1000 if self.pd is None else 5000) and game.max_turns - game.turn > 100): ret.append(SpawnShipCommand(self.id, None)) return ret
def build_position(self, ticker): global positions, highest, lowest try: last = float(ticker['last']) amount = int(position_unit * 2 * last) # 建仓 if len(positions) == 0 and last >= highest: ret = futureAPI.take_order('', self.instrument_id, 1, last, amount, 1, 20) if ret and ret['result']: new_order_id = ret['order_id'] print('建多仓:挂单开多,order_id: %s' % new_order_id) time.sleep(WAIT_DEAL) info = futureAPI.get_order_info(new_order_id, self.instrument_id) print('建仓订单信息: %s' % info) status = info['status'] if status == '2': deal_price = float(info['price_avg']) filled_qty = int(info['filled_qty']) coin_amount = float(filled_qty * 10 / deal_price) stop_loss = deal_price - 0.5 * N position = Position(price=deal_price, amount=coin_amount, stop_loss=stop_loss, time=timestamp2string(time.time()), side='more') positions.append(position) else: futureAPI.revoke_order(self.instrument_id, new_order_id) if len(positions) == 0 and last <= lowest: ret = futureAPI.take_order('', self.instrument_id, 2, last, amount, 1, 20) if ret and ret['result']: new_order_id = ret['order_id'] print('建空仓:挂单开空,order_id: %s' % new_order_id) time.sleep(WAIT_DEAL) info = futureAPI.get_order_info(new_order_id, self.instrument_id) print('订单信息: %s' % info) status = info['status'] if status == '2': deal_price = float(info['price_avg']) filled_qty = int(info['filled_qty']) coin_amount = float(filled_qty * 10 / deal_price) stop_loss = deal_price + 0.5 * N position = Position(price=deal_price, amount=coin_amount, stop_loss=stop_loss, time=timestamp2string(time.time()), side='less') positions.append(position) else: futureAPI.revoke_order(self.instrument_id, new_order_id) highest = max(highest, last) lowest = min(lowest, last) except Exception as e: print('建仓出错, %s' % repr(e)) traceback.print_exc()
def add_position(self, ticker): global positions, N try: # 加仓&止损 if len(positions) > 0: last = float(ticker['last']) print('当前仓位: %d, 仓位信息:' % len(positions)) for i in range(len(positions)): cur = positions[i] if cur.side == 'more': profit = (last - cur.price) / cur.price * 100 else: profit = (cur.price - last) / cur.price * 100 print( '第%d个仓位: 委托价: %.3f, 数量: %.2f, 方向: %s, 止损价: %.3f, 买入时间: %s, 当前盈利: %.2f%%' % (i + 1, cur.price, cur.amount, cur.side, cur.stop_loss, cur.time, profit)) prev_position = positions[-1] last_buy_price = prev_position.price side = prev_position.side amount = int(position_unit * 2 * last) last_stop_loss_price = prev_position.stop_loss if side == 'more': if last - last_buy_price >= 0.5 * N: ret = futureAPI.take_order('', self.instrument_id, 1, last, amount, 1, 20) if ret and ret['result']: new_order_id = ret['order_id'] print('多仓加仓,order_id: %s' % new_order_id) time.sleep(WAIT_DEAL) info = futureAPI.get_order_info( new_order_id, self.instrument_id) print('订单信息: %s' % info) status = info['status'] if status == '2': deal_price = float(info['price_avg']) filled_qty = int(info['filled_qty']) coin_amount = float(filled_qty * 10 / deal_price) stop_loss = deal_price - 0.5 * N position = Position(price=deal_price, amount=coin_amount, stop_loss=stop_loss, time=timestamp2string( time.time()), side='more') positions.append(position) else: futureAPI.revoke_order(self.instrument_id, new_order_id) elif last <= last_stop_loss_price or last <= lowest: sell_more_batch(futureAPI, self.instrument_id, last) thread.start_new_thread(ensure_sell_more, ( futureAPI, self.coin_name, self.instrument_id, last, last_buy_price, )) positions = [] if side == 'less': if last < last_buy_price - 0.5 * N: ret = futureAPI.take_order('', self.instrument_id, 2, last, amount, 1, 20) if ret and ret['result']: new_order_id = ret['order_id'] print('空仓加仓,order_id: %s' % new_order_id) time.sleep(WAIT_DEAL) info = futureAPI.get_order_info( new_order_id, self.instrument_id) print('订单信息: %s' % info) status = info['status'] if status == '2': deal_price = float(info['price_avg']) filled_qty = int(info['filled_qty']) coin_amount = float(filled_qty * 10 / deal_price) stop_loss = deal_price + 0.5 * N position = Position(price=deal_price, amount=coin_amount, stop_loss=stop_loss, time=timestamp2string( time.time()), side='less') positions.append(position) else: futureAPI.revoke_order(self.instrument_id, new_order_id) elif last >= last_stop_loss_price or last >= highest: sell_less_batch(futureAPI, self.instrument_id, last) thread.start_new_thread(ensure_sell_less, ( futureAPI, self.coin_name, self.instrument_id, last, last_buy_price, )) positions = [] except Exception as e: print('加仓出错:%s' % repr(e)) traceback.print_exc()
def generate_start(self): """ Sets self to a standard initial game state, generating a map using perlin noise. """ for i, player in enumerate(self.players): player.id = i self.max_turns = round(self.size * 3.125) + 300 self.banks = {player.id: 5000 for player in self.players} if len(self.players) == 2: perlin = np.square( _generate_perlin_noise_2d((self.size, self.size // 2), (4, 2))) noise = np.clip( np.random.normal(1, 0.5, size=(self.size, self.size // 2)), 0.5, 10) max_halite = np.amax(perlin * noise) actual_max = random.randint(800, 1000) left_half = np.clip(perlin * noise * (actual_max / max_halite), 0, 1000).astype(int) else: perlin = np.square( _generate_perlin_noise_2d((self.size // 2, self.size // 2), (2, 2))) noise = np.clip( np.random.normal(1, 0.5, size=(self.size // 2, self.size // 2)), 0.5, 10) max_halite = np.amax(perlin * noise) actual_max = random.randint(800, 1000) upper_left = np.clip(perlin * noise * (actual_max / max_halite), 0, 1000).astype(int) left_half = np.concatenate((upper_left, np.flip(upper_left, 0)), 0) hlt = np.concatenate((left_half, np.flip(left_half, 1)), 1) if len(self.players) == 2: self.constructs[0] = Shipyard(self.players[0].id, 0, self.size / 4, self.size / 2) self.shipyard_pos[self.players[0].id] = Position( self.size / 4, self.size / 2) self.constructs[1] = Shipyard(self.players[1].id, 1, self.size * 3 / 4 - 1, self.size / 2) self.shipyard_pos[self.players[1].id] = Position( self.size * 3 / 4 - 1, self.size / 2) else: self.constructs[0] = Shipyard(self.players[0].id, 0, self.size / 4, self.size / 4) self.shipyard_pos[self.players[0].id] = Position( self.size / 4, self.size / 4) self.constructs[1] = Shipyard(self.players[1].id, 1, self.size * 3 / 4 - 1, self.size / 4) self.shipyard_pos[self.players[1].id] = Position( self.size * 3 / 4 - 1, self.size / 4) self.constructs[2] = Shipyard(self.players[2].id, 2, self.size / 4, self.size * 3 / 4 - 1) self.shipyard_pos[self.players[2].id] = Position( self.size / 4, self.size * 3 / 4 - 1) self.constructs[3] = Shipyard(self.players[3].id, 3, self.size * 3 / 4 - 1, self.size * 3 / 4 - 1) self.shipyard_pos[self.players[3].id] = Position( self.size * 3 / 4 - 1, self.size * 3 / 4 - 1) self.cells = np.zeros(shape=(self.size, self.size, 4), dtype=int) self.cells[:, :, 0] = hlt self.cells[:, :, 1:3] = -1 for shipyard in self.constructs.values(): self.cells[shipyard.y][shipyard.x][0] = 0 self.cells[shipyard.y][shipyard.x][1] = shipyard.id
def can_step(self, agent): position = Position(agent.get_position()) position.add(agent.get_move_delta(1)) return not self.entity_rect_collision( (position.get_x(), position.get_y(), agent.get_width(), agent.get_height()))
def step(self, game): frame = game.cells.copy() no_ship = frame[:, :, 2] == -1 for ship in game.ships.values(): frame[:, :, 2][frame[:, :, 2] == ship.id] = (1 if ship.owner_id == self.id else -1) frame[:, :, 2][no_ship] = 0 frame = pad_frame(frame, game.shipyard_pos[self.id]) frame = np.divide(frame, (1000, 1, 1, 1000)) meta = (game.width, game.max_turns - game.turn, game.bank[self.id], max(game.bank[p.id] for p in game.players if p.id != self.id)) meta = np.divide(meta, (64, 500, 10000, 10000)) if self.memory is not None: if self.prev_frame is not None: ship_hlt_delta = sum( s.halite for s in game.ships.values() if s.owner_id == self.id) - self.prev_ship_halite bank_hlt_delta = game.bank[self.id] - self.halite ship_delta = (len( [s for s in game.ships.values() if s.owner_id == self.id]) - self.prev_ships) reward = R_HLT_SHIP * ship_hlt_delta + R_HLT_BANK * bank_hlt_delta + R_SHIP * ship_delta self.memory.add_sample(self.prev_frame, self.prev_meta, self.prev_action, reward, False, frame, meta) if game.turn + 1 == game.max_turns: reward = R_WIN if meta[2] > meta[3] else R_LOSE self.memory.add_sample(frame, meta, self.prev_action, reward, True, None, None) if self.memory.num_samples >= min(320, self.memory.size / 10): self.total_loss += train(self.network, self.memory) self.prev_action = np.zeros((128, 128), dtype=int) self.prev_ship_halite = sum(s.halite for s in game.ships.values() if s.owner_id == self.id) self.prev_ships = len( [s for s in game.ships.values() if s.owner_id == self.id]) self.prev_frame = frame.copy() self.prev_meta = meta.copy() moves = self.network.predict([ np.array(frame).reshape((1, 128, 128, 4)), np.array(meta).reshape(1, -1) ])[0] self.halite = game.bank[self.id] commands = {} next_pos = {} next_ships = [ ] # next_ships[y][x] = list of ships that will end want to move to y x rem = game.max_turns - game.turn for y in range(game.height): next_ships.append([]) for x in range(game.width): next_ships[y].append([]) for x in range(game.width): for y in range(game.height): p = center(Position(x, y), self.shipyard, game.width, game.height) if game.cells[y][x][2] == -1 or game.ships[ game.cells[y][x][2]].owner_id != self.id: continue move = np.argmax(moves[p.y][p.x]) if random.random() < ( 1 - self.eps) else random.randint(0, 5) self.prev_action[x][y] = move ship = game.ships[game.cells[y][x][2]] if move == 0: if self.override_collisions: next_pos[ship.id] = Position(x, y) elif game.cells[y][x][3] < game.cells[y][x][0] // 10: if self.verbose == 1: print( f'{game.ships[game.cells[y][x][2]]} attempted to move without sufficient halite' ) if self.override_collisions: next_pos[ship.id] = Position(x, y) elif move == 1: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') if self.override_collisions: next_pos[ship.id] = Position(x, (y + 1) % game.height) elif move == 2: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') if self.override_collisions: next_pos[ship.id] = Position((x + 1) % game.width, y) elif move == 3: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') if self.override_collisions: next_pos[ship.id] = Position(x, (y - 1) % game.height) elif move == 4: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') if self.override_collisions: next_pos[ship.id] = Position((x - 1) % game.width, y) elif move == 5: if self.halite + game.cells[y][x][0] + game.cells[y][x][ 3] >= 4000 and game.cells[y][x][1] == -1: commands[ship.id] = ConstructDropoffCommand( self.id, ship.id) elif self.override_collisions: next_pos[ship.id] = Position(x, y) if self.override_collisions: next_ships[next_pos[ship.id].y][next_pos[ ship.id].x].append(ship) if self.override_collisions: q = [ ship for ship in game.ships.values() if ship.owner_id == self.id and (next_pos[ ship.id].x != ship.x or next_pos[ship.id].y != ship.y) ] while q: ship = q.pop() nx = next_pos[ship.id].x ny = next_pos[ship.id].y if len(next_ships[ny][nx]) > 1 and not ( rem <= 50 and nx == self.shipyard.x and ny == self.shipyard.y): p = Position(ship.x, ship.y) done = False visited = set() while not done: p = next_pos[game.cells[p.y][p.x][2]] # if hits empty or enemy, then not a cycle if game.cells[p.y][p.x][2] == -1 or game.ships[ game.cells[p.y][p.x][2]].owner_id != self.id: break # if ship stops, then not a cycle if p == next_pos[game.cells[p.y][p.x][2]]: break if p == Position(ship.x, ship.y): done = True continue elif game.cells[p.y][p.x][2] in visited: break visited.add(game.cells[p.y][p.x][2]) else: continue if self.verbose == 1: print(f'Overrode collision for {ship}') next_ships[next_pos[ship.id].y][next_pos[ ship.id].x].remove(ship) next_pos[ship.id].x = ship.x next_pos[ship.id].y = ship.y commands[ship.id] = MoveCommand(self.id, ship.id, 'O') q.extend(next_ships[ship.y][ship.x]) next_ships[ship.y][ship.x].append(ship) ret = list(commands.values()) if (len(next_ships[self.shipyard.y][self.shipyard.x]) == 0 and self.halite >= 1000 and rem > 100 and np.sum(game.cells[:, :, 0]) * 3 > self.map_starting_halite): ret.append(SpawnShipCommand(self.id, None)) return ret
def step(self, game): frame = game.cells.copy() no_ship = frame[:, :, 2] == -1 for ship in game.ships.values(): frame[:, :, 2][frame[:, :, 2] == ship.id] = (1 if ship.owner_id == self.id else -1) frame[:, :, 2][no_ship] = 0 frame = pad_frame(frame, game.shipyard_pos[self.id]) frame = np.divide(frame, (1000, 1, 1, 1000)) meta = (game.width, game.max_turns - game.turn, game.bank[self.id], max(game.bank[p.id] for p in game.players if p.id != self.id)) meta = np.divide(meta, (64, 500, 10000, 10000)) moves = self.model.predict([ np.array(frame).reshape((1, 128, 128, 4)), np.array(meta).reshape(1, -1) ])[0] self.halite = game.bank[self.id] commands = {} next_pos = {} next_ships = [ ] # next_ships[y][x] = list of ships that will end want to move to y x rem = game.max_turns - game.turn for y in range(game.height): next_ships.append([]) for x in range(game.width): next_ships[y].append([]) for x in range(game.width): for y in range(game.height): p = center(Position(x, y), self.shipyard, game.width, game.height) if game.cells[y][x][2] == -1 or game.ships[ game.cells[y][x][2]].owner_id != self.id: continue move = np.argmax(moves[p.y][p.x]) ship = game.ships[game.cells[y][x][2]] if move == 0: if self.override_collisions: next_pos[ship.id] = Position(x, y) elif game.cells[y][x][3] < game.cells[y][x][0] // 10: if self.verbose == 1: print( f'{game.ships[game.cells[y][x][2]]} attempted to move without sufficient halite' ) if self.override_collisions: next_pos[ship.id] = Position(x, y) elif move == 1: commands[ship.id] = MoveCommand(self.id, ship.id, 'N') if self.override_collisions: next_pos[ship.id] = Position(x, (y + 1) % game.height) elif move == 2: commands[ship.id] = MoveCommand(self.id, ship.id, 'E') if self.override_collisions: next_pos[ship.id] = Position((x + 1) % game.width, y) elif move == 3: commands[ship.id] = MoveCommand(self.id, ship.id, 'S') if self.override_collisions: next_pos[ship.id] = Position(x, (y - 1) % game.height) elif move == 4: commands[ship.id] = MoveCommand(self.id, ship.id, 'W') if self.override_collisions: next_pos[ship.id] = Position((x - 1) % game.width, y) elif move == 5: if self.halite + game.cells[y][x][0] + game.cells[y][x][ 3] >= 4000: commands[ship.id] = ConstructDropoffCommand( self.id, ship.id) elif self.override_collisions: next_pos[ship.id] = Position(x, y) if self.override_collisions: next_ships[next_pos[ship.id].y][next_pos[ ship.id].x].append(ship) if self.override_collisions: q = [ ship for ship in game.ships.values() if ship.owner_id == self.id and (next_pos[ ship.id].x != ship.x or next_pos[ship.id].y != ship.y) ] while q: ship = q.pop() nx = next_pos[ship.id].x ny = next_pos[ship.id].y if len(next_ships[ny][nx]) > 1 and not ( rem <= 50 and nx == self.shipyard.x and ny == self.shipyard.y): cur = Position(ship.x, ship.y) done = False visited = set() while not done: cur = next_pos[game.cells[cur.y][cur.x][2]] # if hits empty or enemy, then not a cycle if game.cells[cur.y][ cur.x][2] == -1 or game.ships[game.cells[ cur.y][cur.x][2]].owner_id != self.id: break # if ship stops, then not a cycle if cur == next_pos[game.cells[cur.y][cur.x][2]]: break if cur == Position(ship.x, ship.y): done = True continue elif game.cells[cur.y][cur.x][2] in visited: break visited.add(game.cells[cur.y][cur.x][2]) else: continue if self.verbose == 1: print(f'Overrode collision for {ship}') next_ships[next_pos[ship.id].y][next_pos[ ship.id].x].remove(ship) next_pos[ship.id].x = ship.x next_pos[ship.id].y = ship.y commands[ship.id] = MoveCommand(self.id, ship.id, 'O') q.extend(next_ships[ship.y][ship.x]) next_ships[ship.y][ship.x].append(ship) ret = list(commands.values()) if (len(next_ships[self.shipyard.y][self.shipyard.x]) == 0 and self.halite >= 1000 and rem > 100 and np.sum(game.cells[:, :, 0]) * 3 > self.map_starting_halite): ret.append(SpawnShipCommand(self.id, None)) return ret