diff --git a/robotarena/roborally/robots/cautious.py b/robotarena/roborally/robots/cautious.py new file mode 100644 index 0000000..4edfc75 --- /dev/null +++ b/robotarena/roborally/robots/cautious.py @@ -0,0 +1,71 @@ +import random +from roborally.api import * + +name = 'Cautious' + +def move(): + my_moves = list(MOVES) + # Score the moves based on damage received + scored_moves = {} + for move in my_moves: + scored_moves[move] = score(move) + my_moves = get_best(scored_moves) + if len(my_moves) == 1: + return my_moves[0] + # Score the moves based on moving away from danger + scored_moves = {} + for move in my_moves: + scored_moves[move] = away_from_danger_toward_flag(move) + my_moves = get_best(scored_moves) + return random.choice(my_moves) +def get_best(scored_moves): + best_score = max(scored_moves.values()) + return [key for key in scored_moves if scored_moves[key] == best_score] +def score(move): + if falls_into_pit(move): + return -10 + move_score = 0 + if move in PRIORITY_MOVES and charges() < 1: + move_score -= 2 + for shooter in shot_by(move): + if shooter[TYPE] == MOUNTED_LASER: + move_score -= 2 + else: + move_score -= 1 + target = shooting(move) + if target: + if target[NAME] == myself()[NAME]: + move_score -= 1 + if move == LASER: + move_score -= 2 + elif target[TYPE] == ROBOT: + if move == LASER: + move_score += 1 + if move in PROGRESS_MOVES: + direction = direction_of_move(move) + pos = get_pos_in_direction(myself()[POSITION], direction) + cell = get_cell_in_sight(pos) + pos_past = get_pos_in_direction(position_after_move(move), direction) + cell_past = get_cell_in_sight(pos_past) + if cell_past.floor == PIT and cell.content and cell.content[TYPE] == ROBOT: + if cell.content[NAME] == myself()[NAME]: + move_score -= 10 + else: + move_score += 4 + return move_score +def away_from_danger_toward_flag(move): + pos = position_after_move(move) + score = 0 + for row in sight(): + for cell in row: + if cell and cell.content: + if cell.content[TYPE] == ROBOT and cell.content[NAME] != myself()[NAME]: + score += distance_between(pos, cell.content[POSITION]) - 20 + elif cell.content[TYPE] in [MOUNTED_LASER, CORPSE]: + score += distance_between(pos, cell.content[POSITION]) - 7 + if move not in PRIORITY_MOVES: + score += 1 + moves_toward_flag = moves_in_directions(sense_flag()) + if move in moves_toward_flag and not bumps_into_wall(move): + score += 4 + return score diff --git a/robotarena/roborally/robots/feelitout.py b/robotarena/roborally/robots/feelitout.py new file mode 100644 index 0000000..6ac7c1e --- /dev/null +++ b/robotarena/roborally/robots/feelitout.py @@ -0,0 +1,284 @@ +import random +from roborally.api import * + +name = 'FeelItOut' + +AVOIDING_PIT = 1 + +PIT_WEIGHT_ONE = 1000 +PIT_WEIGHT_TWO = 20 +PIT_WEIGHT_THREE = 2 +PIT_WEIGHT_FOUR = 1 +PIT_WEIGHT_FIVE = 1 + +FLAG_WEIGHT = 505 + + +AVOID_PIT_OFFSET_WEIGHT = 100 + +def move(): + my_memory = memory() + my_memory['left'] = 0 + my_memory['right'] = 0 + my_memory['ahead'] = 1 + my_memory['behind'] = 0 + my_memory['state'] = 0 + if 'my_life' not in my_memory: + my_memory['my_life'] = myself()['life'] + if 'prev_life' not in my_memory: + my_memory['prev_life'] = myself()['life'] + if 'two_prev_life' not in my_memory: + my_memory['two_prev_life'] = myself()['life'] + + #set up my current and previous life + my_memory['two_prev_life'] = my_memory['prev_life'] + my_memory['prev_life'] = my_memory['my_life'] + my_memory['my_life'] = myself()['life'] + + my_sight = sight() + + #Let's see what's around me + center = len(my_sight) // 2 + start_pos = (center,center) + + + my_sight = sight() + for row in range(len(my_sight)): + for col in range(len(my_sight[row])): + end_pos = (row, col) + thinkaboutit(start_pos, end_pos) + + # special handling for corpses piled up, this goes around them unless the flag is in line with the piled up corpses + stack_of_corpses() + + feelforflag() + + #if you're on a wall, deprioritize turning, so that you won't do a bunch of back and forth garbage + if my_memory['state'] == AVOIDING_PIT: + my_memory['ahead'] += 1 + my_memory['behind'] -= (2 * AVOID_PIT_OFFSET_WEIGHT) + my_memory['left'] -= AVOID_PIT_OFFSET_WEIGHT + my_memory['right'] -= AVOID_PIT_OFFSET_WEIGHT + + return bestfeeling() + +def feelforflag(): + + my_memory = memory() + #find which direction the flag is, and weight it + if AHEAD in sense_flag(): + my_memory['ahead'] += FLAG_WEIGHT + elif LEFT in sense_flag(): + my_memory['left'] += FLAG_WEIGHT + elif RIGHT in sense_flag(): + my_memory['right'] += FLAG_WEIGHT + elif BEHIND in sense_flag(): + my_memory['behind'] += FLAG_WEIGHT + + return + + +def stack_of_corpses(): + + my_own_self = myself() + my_memory = memory() + + one = get_cell_in_sight((get_pos_in_direction(my_own_self[POSITION], AHEAD, 1)[0], get_pos_in_direction(my_own_self[POSITION], AHEAD, 1)[1])) + two = get_cell_in_sight((get_pos_in_direction(my_own_self[POSITION], AHEAD, 2)[0], get_pos_in_direction(my_own_self[POSITION], AHEAD, 2)[1])) + three = get_cell_in_sight((get_pos_in_direction(my_own_self[POSITION], AHEAD, 3)[0], get_pos_in_direction(my_own_self[POSITION], AHEAD, 3)[1])) + four = get_cell_in_sight((get_pos_in_direction(my_own_self[POSITION], AHEAD, 4)[0], get_pos_in_direction(my_own_self[POSITION], AHEAD, 4)[1])) + + # if there's a destroyed robot in front of you and a wall just past that, reconsider + if one.content and two.content and one.content[TYPE] == CORPSE and two.content[TYPE] in [WALL, MOUNTED_LASER]: + my_memory['state'] = AVOIDING_PIT + my_memory['ahead'] -= PIT_WEIGHT_ONE + + + # if there's 2 destroyed robots in front of you and a wall just past that, reconsider + #I don't know the correct python syntax for doing this more elegantly than just a bunch of if statements + if one.content and two.content and three.content and one.content[TYPE] == CORPSE and two.content[TYPE] == CORPSE and three.content[TYPE] in [WALL, MOUNTED_LASER]: + my_memory['state'] = AVOIDING_PIT + my_memory['ahead'] -= PIT_WEIGHT_ONE + + + + if one.content and two.content and three.content and four.content and one.content[TYPE] == CORPSE and two.content[TYPE] == CORPSE and three.content[TYPE] == CORPSE and four.content[TYPE] in [WALL, MOUNTED_LASER]: + my_memory['state'] = AVOIDING_PIT + my_memory['ahead'] -= PIT_WEIGHT_ONE + + return + + + +def thinkaboutit(start_pos, end_pos): + + my_memory = memory() + my_cell = get_cell_in_sight(start_pos) + target_cell = get_cell_in_sight(end_pos) + direction = direction_toward(start_pos,end_pos) + distance = distance_between(end_pos) + + + weight = 0 + # weight all ares based on pits and walls + #the weight for 4 and 5 is 0, because it was feeling too much, causing it to make wrong decisions like turning the wrong way. I'd need to limit where it can feel (like only feel in front of you), to take advantage of this for navigation. + if target_cell.content and target_cell.content[TYPE] in [WALL,MOUNTED_LASER]: + if distance <= 1: + my_memory['state'] = AVOIDING_PIT + weight -= PIT_WEIGHT_ONE + elif distance < 2: + my_memory['state'] = AVOIDING_PIT + weight -= PIT_WEIGHT_TWO + elif distance < 3: + #my_memory['state'] = AVOIDING_PIT + weight -= PIT_WEIGHT_THREE + elif distance < 4 and AHEAD in direction: + weight -= PIT_WEIGHT_FOUR + elif AHEAD in direction: + weight -= PIT_WEIGHT_FIVE + + if target_cell.floor == PIT: + if distance <= 1: + weight -= PIT_WEIGHT_ONE + my_memory['state'] = AVOIDING_PIT + elif distance <= 2: + weight -= PIT_WEIGHT_TWO + my_memory['state'] = AVOIDING_PIT + elif distance <= 3: + weight -= PIT_WEIGHT_THREE + #my_memory['state'] = AVOIDING_PIT + elif distance <= 4 and AHEAD in direction: + weight -= PIT_WEIGHT_FOUR + elif AHEAD in direction: + weight -= PIT_WEIGHT_FIVE + + + + + + if AHEAD in direction: + my_memory['ahead'] += weight + if LEFT in direction: + my_memory['left'] += weight + if RIGHT in direction: + my_memory['right'] += weight + if BEHIND in direction: + my_memory['behind'] += weight + + + + + + return + + +def bestfeeling(): + + my_memory = memory() + + #find the direction with the best value + highest_direction = 'ahead' + highest_value = my_memory['ahead'] + + if my_memory['left'] > highest_value: + highest_value = my_memory['left'] + highest_direction = 'left' + + + if my_memory['right'] > highest_value: + highest_value = my_memory['right'] + highest_direction = 'right' + + + if my_memory['behind'] > highest_value: + highest_value = my_memory['behind'] + highest_direction = 'behind' + + + if highest_direction == 'ahead': + return considermovingforward() + + #if you want to turn, but you're on a spinner, just slide off + elif highest_direction == 'left': + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == LEFT_SPINNER and charges() > 0: + return SIDESTEP_LEFT + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == RIGHT_SPINNER and charges() > 0: + return SIDESTEP_LEFT + return TURN_LEFT + elif highest_direction == 'right': + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == RIGHT_SPINNER and charges() > 0: + return SIDESTEP_RIGHT + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == LEFT_SPINNER and charges() > 0: + return SIDESTEP_RIGHT + return TURN_RIGHT + elif highest_direction == 'behind': + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == RIGHT_SPINNER: + return REVERSE + if get_cell_in_sight((len(sight()) // 2,len(sight()) // 2)).floor == LEFT_SPINNER: + return REVERSE + return U_TURN + + return FORWARD + + +def considermovingforward(): + + my_own_self = myself() + shooting_target = shooting() + + +# if there's a spinner in front of me and it won't kill me to move past it, just move two spaces to avoid that crap + if get_cell_in_sight(get_pos_in_direction((len(sight()) // 2,len(sight()) // 2) , AHEAD)).floor == LEFT_SPINNER: + if not falls_into_pit(FORWARD_TWO) and not bumps_into_wall(FORWARD_TWO) and charges() > 0: + return FORWARD_TWO + if get_cell_in_sight(get_pos_in_direction((len(sight()) // 2,len(sight()) // 2) , AHEAD)).floor == RIGHT_SPINNER: + if not falls_into_pit(FORWARD_TWO) and not bumps_into_wall(FORWARD_TWO) and charges() > 0: + return FORWARD_TWO + + #if i'm shooting another of my robots and we're either going the same direction or going head to head, let's sidestep that, as long at it won't kill me + if shooting_target and shooting_target[TYPE] == ROBOT and shooting_target[NAME] == my_own_self[NAME] and my_own_self[FACING] == shooting_target[FACING]: + my_choice = random.choice([SIDESTEP_LEFT, SIDESTEP_RIGHT]) + if not falls_into_pit(my_choice) and not bumps_into_wall(my_choice) and charges() > 0: + return my_choice + if not falls_into_pit(SIDESTEP_LEFT) and not bumps_into_wall(SIDESTEP_LEFT) and charges() > 0: + return SIDESTEP_LEFT + if not falls_into_pit(SIDESTEP_RIGHT) and not bumps_into_wall(SIDESTEP_RIGHT) and charges() > 0: + return SIDESTEP_RIGHT + + if shooting_target and shooting_target[TYPE] == ROBOT and shooting_target[NAME] == my_own_self[NAME] and my_own_self[FACING] == opposite_direction(shooting_target[FACING]): + if not falls_into_pit(SIDESTEP_LEFT) and not bumps_into_wall(SIDESTEP_LEFT) and charges() > 0: + return SIDESTEP_LEFT + #doing it both ways makes it so that two guys facing each other along a wall will keep facing each other, and does not really impact other scenarios, so only try one way + + + # if there's a wall mounted laser in front of or behind me, consider sidestepping + shot_me = shot_by() + for hitter in shot_me: + if hitter[TYPE] == MOUNTED_LASER and hitter[FACING] == my_own_self[FACING] and charges() > 0 and not falls_into_pit(SIDESTEP_LEFT) and not bumps_into_wall(SIDESTEP_LEFT): + return SIDESTEP_LEFT + if hitter[TYPE] == MOUNTED_LASER and hitter[FACING] == my_own_self[FACING] and charges() > 0 and not falls_into_pit(SIDESTEP_RIGHT) and not bumps_into_wall(SIDESTEP_RIGHT): + return SIDESTEP_RIGHT + if hitter[TYPE] == MOUNTED_LASER and hitter[FACING] == opposite_direction(my_own_self[FACING]) and charges() > 0 and not falls_into_pit(SIDESTEP_LEFT) and not bumps_into_wall(SIDESTEP_LEFT): + return SIDESTEP_LEFT + if hitter[TYPE] == MOUNTED_LASER and hitter[FACING] == opposite_direction(my_own_self[FACING]) and charges() > 0 and not falls_into_pit(SIDESTEP_RIGHT) and not bumps_into_wall(SIDESTEP_RIGHT): + return SIDESTEP_RIGHT + + # if there's a bad guy who is not one of me behind me shooting me, let's shake him (if he's one of me, he will move himself) + if hitter[TYPE] == ROBOT and hitter[FACING] == my_own_self[FACING] and charges() > 0 and not falls_into_pit(SIDESTEP_RIGHT) and not bumps_into_wall(SIDESTEP_RIGHT) and not hitter[NAME] == my_own_self[NAME]: + return SIDESTEP_RIGHT + if hitter[TYPE] == ROBOT and hitter[FACING] == my_own_self[FACING] and charges() > 0 and not falls_into_pit(SIDESTEP_LEFT) and not bumps_into_wall(SIDESTEP_LEFT) and not hitter[NAME] == my_own_self[NAME]: + return SIDESTEP_LEFT + + # if there is a bad guy in front of me (not named me) and he's looking at me, let's rock his face off. + if shooting_target and shooting_target[TYPE] == ROBOT and not shooting_target[NAME] == my_own_self[NAME] and my_own_self[FACING] == opposite_direction(shooting_target[FACING]): + return LASER + + #if i've been shot twice in a row, there's a chance i'll dodge. i give it one for free, since my own type will move out of the way after one shot + my_memory = memory() + if my_memory['two_prev_life'] > (my_memory['my_life'] + 1) and charges() > 0: + my_dodge_choice = random.choice([FORWARD, SIDESTEP_LEFT, SIDESTEP_RIGHT, FORWARD, FORWARD, FORWARD, FORWARD]) + if not falls_into_pit(my_dodge_choice) and not bumps_into_wall(my_dodge_choice): + return my_dodge_choice + + return FORWARD + diff --git a/robotarena/roborally/robots/leeroybot.py b/robotarena/roborally/robots/leeroybot.py new file mode 100644 index 0000000..a8e7529 --- /dev/null +++ b/robotarena/roborally/robots/leeroybot.py @@ -0,0 +1,21 @@ +import random +from roborally.api import * + +name = 'Leeroy' + +def move(): + vision = sight() + + in_front = [vision[4][5], vision[3][5], vision[2][5], vision[1][5], vision[0][5]] + if any(space.content and space.content[TYPE] == ROBOT for space in in_front): + return FORWARD + + to_the_right = [vision[5][6], vision[5][7], vision[5][8], vision[5][9], vision[5][10]] + if any(space.content and space.content[TYPE] == ROBOT for space in to_the_right): + return TURN_RIGHT + + to_the_left = [vision[5][0], vision[5][1], vision[5][2], vision[5][3], vision[5][4]] + if any(space.content and space.content[TYPE] == ROBOT for space in to_the_left): + return TURN_LEFT + + return FORWARD diff --git a/robotarena/roborally/robots/murder_if_convenient.py b/robotarena/roborally/robots/murder_if_convenient.py new file mode 100644 index 0000000..5fd015d --- /dev/null +++ b/robotarena/roborally/robots/murder_if_convenient.py @@ -0,0 +1,209 @@ +""" +murder_if_convenient's first priority is to murder other robots, but only +if they happen to be right in the way. Otherwise he'll head for the flag +as best as possible, attempting to follow an obsticle if one is in the way. +""" +from roborally.api import * + +name = 'ConvenientMurderer' + +friendly_bots = ('ConvenientMurderer', 'ConvenientMurderer2') +surroundings = {} + +def is_friendly(content): + return content and content[TYPE] == ROBOT and content[NAME] in friendly_bots + +def is_enemy(content): + return content and content[TYPE] == ROBOT and content[NAME] not in friendly_bots + +def contains_enemy(cell): + return is_enemy(cell.content) + +def is_corpse(content): + return content and content[TYPE] == CORPSE + +def is_pit(cell): + return not cell.floor + +def is_obstacle(cell): + return is_pit(cell) or cell.content and cell.content[TYPE] in (WALL, MOUNTED_LASER) + +def is_spinner(cell): + return cell.floor in (LEFT_SPINNER, RIGHT_SPINNER) + +def am_on_flag(): + cell = get_cell_in_sight(me) + return cell.floor == FLAG + +def turn(direction): + mem = memory()['flag_directions'] + new_mem = set() + + for remembered_dir in mem: + new_mem.add(convert_direction(direction, remembered_dir)) + memory()['flag_directions'] = new_mem + + if direction == LEFT: + return TURN_LEFT + if direction == RIGHT: + return TURN_RIGHT + return U_TURN + +def sidestep(direction): + if 'follow_obstacle' in memory(): + if memory()['follow_obstacle'] == direction: + memory()['distance_from_obstacle'] += 1 + else: + memory()['distance_from_obstacle'] -= 1 + + if direction == LEFT: + return SIDESTEP_LEFT + return SIDESTEP_RIGHT + +def follow_obstacle(direction): + opposite = opposite_direction(direction) + cell = get_cell_in_sight(get_pos_in_direction(me, opposite, distance=memory()['distance_from_obstacle'])) + if not cell or not is_obstacle(cell): + # we reached the end, turn that way and stop following + memory()['follow_obstacle'] = False + return turn(opposite) + if is_obstacle(surroundings['forward1']): + return turn(direction) + return FORWARD + + +def go_towards_flag(good_options): + direction = good_options[0] + if AHEAD in good_options: + if not is_obstacle(surroundings['forward1']): + return FORWARD + + if len(good_options) == 1: + good_options = memory()['flag_directions'] + + direction_decided = False + if len(good_options) > 1: + other = list(set(good_options) - set([AHEAD]))[0] + if not is_obstacle(get_cell_in_sight(get_pos_in_direction(me, other))): + memory()['follow_obstacle'] = other + direction_decided = True + + if not direction_decided: + if is_obstacle(surroundings['right1']): + memory()['follow_obstacle'] = LEFT + else: + memory()['follow_obstacle'] = RIGHT + + memory()['distance_from_obstacle'] = 1 + return turn(memory()['follow_obstacle']) + + return turn(direction) + + +def move(): + """ + if we can shove an enemy in a pit, do it! + if enemy robot is straight ahead, blast him! + if going around obstacle, follow it + else go towards flag + - don't fall into holes + - go towards flag + """ + # setup variables + global surroundings, me + me = (5,5) + surroundings['forward1'] = get_cell_in_sight(get_pos_in_direction(me, AHEAD)) + surroundings['forward2'] = get_cell_in_sight(get_pos_in_direction(me, AHEAD, distance=2)) + surroundings['forward3'] = get_cell_in_sight(get_pos_in_direction(me, AHEAD, distance=3)) + surroundings['back1'] = get_cell_in_sight(get_pos_in_direction(me, BEHIND)) + surroundings['back2'] = get_cell_in_sight(get_pos_in_direction(me, BEHIND, distance=2)) + surroundings['left1'] = get_cell_in_sight(get_pos_in_direction(me, LEFT)) + surroundings['left2'] = get_cell_in_sight(get_pos_in_direction(me, LEFT, distance=2)) + surroundings['right1'] = get_cell_in_sight(get_pos_in_direction(me, RIGHT)) + surroundings['right2'] = get_cell_in_sight(get_pos_in_direction(me, RIGHT, distance=2)) + + # remember the last two directions that we sensed the flag in + flag_direction = sense_flag() + if not 'flag_directions' in memory() or len(flag_direction) == 2: + memory()['flag_directions'] = set(flag_direction) + + # remember what turn it is + if not 'turn' in memory(): + memory()['turn'] = 1 + else: + memory()['turn'] += 1 + + # remember how many turns in a row we get shot + health = life() + if 'life_last_turn' not in memory(): + memory()['life_last_turn'] = 10 + else: + memory()['life_last_turn'] = memory()['life_this_turn'] + memory()['life_this_turn'] = health + if memory()['life_last_turn'] > health: + if not 'turns_getting_shot' in memory(): + memory()['turns_getting_shot'] = 1 + else: + memory()['turns_getting_shot'] += 1 + else: + if 'turns_getting_shot' in memory(): + del memory()['turns_getting_shot'] + + # if we can shove an enemy in a pit, do it! + if contains_enemy(surroundings['forward1']) and is_pit(surroundings['forward2']): + return FORWARD + + if (contains_enemy(surroundings['forward1']) or contains_enemy(surroundings['forward2'])) and is_pit(surroundings['forward3']): + return FORWARD_TWO + + if contains_enemy(surroundings['back1']) and is_pit(surroundings['back2']): + return REVERSE + + if contains_enemy(surroundings['left1']) and is_pit(surroundings['left2']): + return sidestep(LEFT) + + if contains_enemy(surroundings['right1']) and is_pit(surroundings['right2']): + return sidestep(RIGHT) + + # if enemy is straight ahead, blast him! + target = shooting() + if is_enemy(target) or is_corpse(target): + return LASER + + # if i'm shooting friendly, try to sidestep. + if is_friendly(shooting()) and not is_obstacle(surroundings['right1']): + friendly = shooting() + if not friendly[FACING] == RIGHT and not is_obstacle(surroundings['right1']): + return sidestep(RIGHT) + #if not friendly[FACING] == LEFT and not is_obstacle(surroundings['left1']): + # return SIDESTEP_LEFT + + # if it's after the initial fray and i've been shot three turns in a row, + # someone's probably following me. try to dodge. + if memory()['turn'] > 20 and 'turns_getting_shot' in memory() and memory()['turns_getting_shot'] > 2: + if not is_obstacle(surroundings['left1']): + del memory()['turns_getting_shot'] + return sidestep(LEFT) + if not is_obstacle(surroundings['right1']): + del memory()['turns_getting_shot'] + return sidestep(RIGHT) + + # if going around obstacle, follow it + if 'follow_obstacle' in memory(): + if not memory()['follow_obstacle']: + # we are in the process of not following the obstacle any more. + # go forward the appropriate number of times. + if memory()['distance_from_obstacle'] <= 1: + del memory()['follow_obstacle'] + del memory()['distance_from_obstacle'] + else: + memory()['distance_from_obstacle'] -= 1 + return FORWARD + return follow_obstacle(memory()['follow_obstacle']) + + # if i'm on a spinner, get off the dang thing + if is_spinner(get_cell_in_sight(me)): + return FORWARD + + # else go towards flag + return go_towards_flag(flag_direction)