Robot Rumble ALPHA
try it!
boards
docs
login
/
signup
# # I decided to rename this chaos-squad # # Chaos-legion will be released once chaos-squad is given a challenge # # Come at me # # finds sqr distance between two points def sqr_dist(pos1, pos2): return (pos1.x - pos2.x) ** 2 + (pos1.y - pos2.y) ** 2 # Returns whether or not the pos is in bounds def in_bounds(pos): if pos.x < 0 or pos.x >= 19: return False if pos.y < 0 or pos.y >= 19: return False obj = gstate.obj_by_coords(pos) if obj and obj.obj_type == ObjType.Terrain: return False return True # Returns whether or not its possible to move to this location (in bounds and not already in planned moves) def movable(pos): if not in_bounds(pos): return False return pos not in claimed_locs # Returns a list of all in-bound Coords that are exactly n manhattan distance away from the given Coord def positions_n_away(pos, n): adj = [] dx_dir = 1 dy_dir = 1 dx = n dy = 0 for a in range(4*n): new_pos = Coords(pos.x + dx, pos.y + dy) if in_bounds(new_pos): adj.append(new_pos) if dy == 0: dx_dir *= -1 if dx == 0: dy_dir *= -1 dx += dx_dir dy += dy_dir return adj # Returns a list of all adjacent in-bound Coords def get_adj_coords(pos): return positions_n_away(pos, 1) # Returns True if there is a friendly unit at this location def friend_here(loc): obj_at_loc = gstate.obj_by_coords(loc) if not obj_at_loc: return False if not obj_at_loc.team: return False return obj_at_loc.team == gstate.our_team # Returns True if there is an enemy unit at this location def enemy_here(loc): obj_at_loc = gstate.obj_by_coords(loc) if not obj_at_loc: return False if not obj_at_loc.team: return False return obj_at_loc.team == gstate.other_team # Takes a Coords object and returns an estimate of how dangerous those coords are to move to def danger_of(pos): danger = 0 if enemy_here(pos) or pos in claimed_locs: return 5 for loc in get_adj_coords(pos): if enemy_here(loc): danger += 1 for loc in positions_n_away(pos, 2): if enemy_here(loc): danger += 0.4 if friend_here(loc): danger -= 0.01 return danger def shared_adj(pos1, pos2): if (pos1.x - pos2.x) in [-2, 0, 2]: c1 = Coords(pos2.x + (pos1.x - pos2.x) // 2, pos2.y + (pos1.y - pos2.y) // 2) if in_bounds(c1): return [Coords(pos2.x + (pos1.x - pos2.x) // 2, pos2.y + (pos1.y - pos2.y) // 2)] else: return [] c1 = Coords(pos2.x, pos2.y + (pos1.y - pos2.y)) c2 = Coords(pos2.x + (pos1.x - pos2.x), pos2.y) shared = [] if in_bounds(c1): shared.append(c1) if in_bounds(c2): shared.append(c2) return shared # Helps find the best navigation square def navigate_to(unit, loc): d = sqr_dist(loc, unit.coords) ** 0.5 best_score = -2 best_loc = None for pos in get_adj_coords(unit.coords): score = 5 + d - sqr_dist(loc, pos) ** 0.5 for pos_adj in get_adj_coords(pos): if pos_adj == pos: continue if enemy_here(pos_adj): score -= 1 if friend_here(pos_adj): score -= 0.5 if friend_here(pos) or enemy_here(pos): score -= 5 if score > best_score: best_loc = pos best_score = score return best_loc # Handles everything to do with moving into a position def move_to(unit, loc): claimed_locs.append(loc) move_dir = unit.coords.direction_to(loc) return Action.move(move_dir) # Handling everything to do with moving into a position def attack(unit, pos): attack_plans.append(pos) claimed_locs.append(unit.coords) attack_dir = unit.coords.direction_to(pos) return Action.attack(attack_dir) # Returns the closest enemy unit def closest_enemy(pos): closest_enemy = None closest_dist = 500 for enemy in gstate.objs_by_team(gstate.other_team): dist = sqr_dist(pos, enemy.coords) if dist < closest_dist: closest_enemy = enemy closest_dist = dist return closest_enemy # Returns the best square to run to if in danger (and the danger level of that square) def run_awayyy(unit): best_move = None best_score = 5 for pos in get_adj_coords(unit.coords): danger = danger_of(pos) if danger <= best_score: best_move = pos best_score = danger return [best_move, best_score] def init_turn(state): # Handle coordination so we dont run into each other global gstate, attack_plans, claimed_locs, weak_enemies gstate = state attack_plans = [] claimed_locs = [] weak_enemies = [] for enemy in gstate.objs_by_team(gstate.other_team): balance = -1 for loc in positions_n_away(enemy.coords, 2): balance -= enemy_here(loc) if friend_here(loc): friend = state.obj_by_coords(loc) if friend.health > 2: balance += 1 if balance > 0: weak_enemies.append(enemy) # Just a useful constant to have global CENTER CENTER = Coords(9, 9) # TODO: handle some calculations of which enemies are worth advancing on def robot(state, unit): # Pre-processing im_in_danger = danger_of(unit.coords) adj_locs = get_adj_coords(unit.coords) dist_to_center = sqr_dist(unit.coords, CENTER) adj_enemy_locs = [] num_adj_enemies = 0 for loc in adj_locs: if enemy_here(loc): num_adj_enemies += 1 adj_enemy_locs.append(loc) # Retreat logic if im_in_danger > 1.8 or (unit.health <= 1 and num_adj_enemies >= 1): retreat_loc, retreat_danger = run_awayyy(unit) if unit.health <= 1 and num_adj_enemies >= 1: if num_adj_enemies == 1 and state.obj_by_coords(adj_enemy_locs[0]).health <= 1: if retreat_danger >= 1: attack(unit, adj_enemy_locs[0]) if retreat_danger < im_in_danger: return move_to(unit, retreat_loc) # Close combat logic for pos in adj_locs: if enemy_here(pos): enemy = state.obj_by_coords(pos) if enemy.health > 1: return attack(unit, pos) # Chase or trapped? logic escape_squares = 0 for enemy_adj in get_adj_coords(pos): # For the moment, I'm assuming that most agents aren't smart enough to move out of the way for their friends. This will change if not friend_here(enemy_adj) and not enemy_here(enemy_adj): escape_squares += 1 if escape_squares == 0: return attack(unit, pos) else: return move_to(unit, pos) # Standoff/join fight logic standoff_scores = {} max_standoff_score = 0 max_standoff_loc = None push_scores = {} max_push_score = 0 max_push_loc = None for pos in adj_locs: apcp = attack_plans.count(pos) picl = pos in claimed_locs fhp = friend_here(pos) standoff_scores[pos] = - (0.5 * apcp + 5 * picl + fhp) push_scores[pos] = - (5 * apcp + 5 * picl + 5 * fhp) for pos in positions_n_away(unit.coords, 2): if enemy_here(pos): enemy = state.obj_by_coords(pos) for between in shared_adj(pos, unit.coords): if in_bounds(between): standoff_scores[between] += 1 if standoff_scores[between] > max_standoff_score: max_standoff_score = standoff_scores[between] max_standoff_loc = between push_scores[between] += (unit.health - enemy.health) / 2.0 for enemy_adj in get_adj_coords(pos): if friend_here(enemy_adj): friend = state.obj_by_coords(enemy_adj) push_scores[between] += (friend.health > 2) / 2.0 if pos in weak_enemies: push_scores[between] += 1 if friend_here(pos): friend = state.obj_by_coords(pos) for between in shared_adj(pos, unit.coords): if in_bounds(between): push_scores[between] -= (friend.health > 2) / 4.0 for pos in adj_locs: if push_scores[pos] > max_push_score: max_push_score = push_scores[pos] max_push_loc = pos if max_push_score > 0: return move_to(unit, max_push_loc) if max_standoff_score > 0: return attack(unit, max_standoff_loc) # Centralize a bit based on strength, then hunt enemies if dist_to_center > 35 + unit.health * 3: best_move = navigate_to(unit, CENTER) if best_move: return move_to(unit, best_move) else: enemy = closest_enemy(pos) target = navigate_to(unit, enemy.coords) if target: return move_to(unit, target) pass
Made with <3 by Anton and Noa
github org