def update_state_opponent(self, world, count): enemy = [] for hockeyist in world.hockeyists: if (hockeyist.teammate or hockeyist.type == HockeyistType.GOALIE or hockeyist.state == HockeyistState.RESTING): continue if hockeyist.angle == world.puck.angle: enemy.append(hockeyist) if len(enemy) != count: self.both_enemy_catch = False return None if count == 2: if Unit.get_distance_to_unit(enemy[0], enemy[1]) < world.width / 8: self.both_enemy_catch = True
def test_get_distance_to_unit(): unit1 = Unit(x=0, y=0) unit2 = Unit(x=3, y=4) assert unit1.get_distance_to_unit(unit2) == 5
class Strategy: def __init__(self, me, world, game): #print "================ " + str(world.tick) self.me = me self.world = world self.game = game self.move_turn = None self.move_speed_up = None self.move_action = None self.move_pass_angle = None self.move_pass_power = None self.angle = self.me.angle speed = sqrt(self.me.speed_x * self.me.speed_x + self.me.speed_y * self.me.speed_y) if self.me.speed_y > 0.0 and self.angle > 0.0: self.speed = speed elif self.me.speed_y > 0.0 and self.angle < 0.0: self.speed = -speed elif self.me.speed_y < 0.0 and self.angle > 0.0: self.speed = -speed elif self.me.speed_y < 0.0 and self.angle < 0.0: self.speed = speed elif self.me.speed_x > 0.0 and -pi / 2.0 < self.angle < pi / 2.0: self.speed = speed else: self.speed = -speed self.player = self.world.get_my_player() self.opponentPlayer = self.world.get_opponent_player() self.myUnits = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.id != self.me.id and hockeyist.type != HockeyistType.GOALIE and hockeyist.state != HockeyistState.RESTING ] self.myUnits.sort(key=lambda x: self.me.get_distance_to_unit(x)) self.team_count = len(self.myUnits) + 1 goalies = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.GOALIE ] if goalies: self.goalie = goalies[0] else: self.goalie = None forwards = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.FORWARD ] if forwards: self.forward = forwards[0] else: self.forward = None versatiles = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.VERSATILE ] if versatiles: self.versatile = versatiles[0] else: self.versatile = None defenders = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.DEFENCEMAN ] if defenders: self.defender = defenders[0] else: self.defender = None self.opponentUnits = [ hockeyist for hockeyist in self.world.hockeyists if not hockeyist.teammate and hockeyist.type != HockeyistType.GOALIE and hockeyist.state != HockeyistState.RESTING ] self.opponentUnits.sort(key=lambda x: self.me.get_distance_to_unit(x)) self.rink_center_x = 0.5 * (self.game.rink_left + self.game.rink_right) self.rink_center_y = 0.5 * (self.game.rink_top + self.game.rink_bottom) if self.player.net_front < self.rink_center_x: self.position = "left" forward_x = self.opponentPlayer.net_front - 0.4 * self.game.world_width defence_x = self.player.net_front + 3.1 * self.me.radius # defence2_x = self.player.net_front + 4.1*self.me.radius else: self.position = "right" forward_x = self.opponentPlayer.net_front + 0.4 * self.game.world_width defence_x = self.player.net_front - 3.1 * self.me.radius # defence2_x = self.player.net_front - 4.1*self.me.radius if self.me.y < self.rink_center_y: forward_y = self.game.rink_top + 0.2 * self.game.world_height else: forward_y = self.game.rink_bottom - 0.2 * self.game.world_height self.forwardPlace = Unit(9906, 0.0, 0.0, forward_x, forward_y, 0.0, 0.0, 0.0, 0.0) self.defendCircle = Unit(9907, 0.0, 1.0 * self.game.stick_length, defence_x, self.rink_center_y, 0.0, 0.0, 0.0, 0.0) #self.defendCircle2 = Unit(9901, 0.0, 1.0*self.game.stick_length, # defence2_x, self.rink_center_y+self.me.radius, # 0.0, 0.0, 0.0, 0.0) self.attackAngle = pi / 2.0 - pi / 6.0 if self.goalie: self.attackCircle = Unit(9908, 1.0, 0.4 * self.game.world_height, self.opponentPlayer.net_front, self.rink_center_y, 0.0, 0.0, 0.0, 0.0) self.attackPassDistance = 3.0 * self.me.radius else: self.attackCircle = Unit(9909, 1.0, self.game.world_width, self.opponentPlayer.net_front, self.rink_center_y, 0.0, 0.0, 0.0, 0.0) self.attackPassDistance = self.game.world_width def getStrategy2(self): if self.world.puck.owner_hockeyist_id == self.me.id: # if self.tryPass('Forward'): # return True # else: self.setStrategyAttackGate() return True elif self.me.state == HockeyistState.SWINGING: self.move_action = ActionType.CANCEL_STRIKE return True elif self.world.puck.owner_player_id == self.me.player_id: self.setStrategyDefendGate() return True elif abs(self.me.x - self.player.net_front) < abs(self.myUnits[0].x - self.player.net_front): self.setStrategyDefendGate() return True else: self.setStrategyTakePuck() return True def getStrategy3(self): if self.world.puck.owner_hockeyist_id == self.me.id: if self.me.state == HockeyistState.SWINGING or self.me.type == HockeyistType.FORWARD: self.setStrategyAttackGate() return True elif self.me.type != HockeyistType.FORWARD and self.tryPass( 'Forward', self.forward): print "Pass to forward" return True elif self.me.type == HockeyistType.DEFENCEMAN and self.tryPass( 'Forward', self.versatile): print "Pass to versatile" return True else: self.setStrategyAttackGate() return True elif self.me.state == HockeyistState.SWINGING: self.move_action = ActionType.CANCEL_STRIKE return True if self.me.type == HockeyistType.DEFENCEMAN: #print "DEFENCEMAN: Defend gate" self.setStrategyDefendGate() return True if self.me.type == HockeyistType.FORWARD: if ( #self.me.get_distance_to_unit(self.attackCircle) < self.attackCircle.radius #or abs(self.me.x - self.attackCircle.x) > abs(self.world.puck.x - self.attackCircle.x) abs(self.world.puck.x - self.attackCircle.x) < 0.55 * self.game.world_width or self.me.get_distance_to_unit( self.world.puck) < self.game.stick_length #or self.world.puck.owner_player_id == self.opponentPlayer.id ): #print "FORWARD: Take puck" self.setStrategyTakePuck() return True elif self.me.get_distance_to_unit( self.forwardPlace) < 1.0 * self.me.radius: #print "FORWARD: Stay near opponent gate" self.move_turn = self.me.get_angle_to_unit(self.world.puck) return True else: #print "FORWARD: Skate to (" + str(self.forwardPlace.x) + ", " + str(self.forwardPlace.y) + ")" self.trySkate(self.forwardPlace.x, self.forwardPlace.y, True) return True if self.me.type == HockeyistType.VERSATILE: if (self.world.puck.owner_hockeyist_id == self.defender.id or self.defender.get_distance_to_unit(self.defendCircle) > 2.0 * self.game.stick_length or self.defender == None): self.setStrategyDefendGate() return True elif self.world.puck.owner_player_id == self.me.player_id: #print "VERSATILE: Strike opponent" self.setStrategyStrikeOpponent() return True elif self.tryStrikeOpponent(): return True #elif self.world.puck.owner_player_id == self.opponentPlayer.id: # self.setStrategyDefendGate() # return True else: #print "VERSATILE: Take puck" self.setStrategyTakePuck() return True def calcAcceleration(self, skateX, skateY): Tmin = 10000 a_min = 1.0 if self.me.get_distance_to(skateX, skateY) > self.game.world_width / 5.0: self.move_turn = self.me.get_angle_to(skateX, skateY) self.move_speed_up = 1.0 return True if abs(self.me.get_angle_to(skateX, skateY)) <= pi / 2.0: direction = 'forward' else: direction = 'back' for i in range(10): (x, y) = (self.me.x, self.me.y) v = self.speed alpha = self.angle a0 = 1.0 - i / 10.0 T = Tmin if direction == 'forward' and a0 < 0.0: break # if direction == 'back' and self.me.get_distance_to(skateX, skateY) > 100.0 and a < 0.0: # break for j in range(100): aj = a0 - j * 0.001 unit = Unit(999 + i * 100 + j, 0.0, 0.0, x, y, 0.0, 0.0, alpha, 0.0) if (x < self.game.rink_left or x > self.game.rink_right or y < self.game.rink_top or y > self.game.rink_bottom): break if unit.get_distance_to(skateX, skateY) < 1.0: T = j break if aj > 0.0: v += aj * self.game.hockeyist_speed_up_factor else: v += aj * self.game.hockeyist_speed_down_factor v = 0.95 * v # friction dalpha = unit.get_angle_to(skateX, skateY) if v < 0.0 and dalpha < 0.0: dalpha = dalpha + pi elif v < 0.0 and dalpha > 0.0: dalpha = dalpha - pi dalpha = copysign( min(abs(dalpha), self.game.hockeyist_turn_angle_factor), dalpha) alpha = normAngle(alpha + dalpha) (x, y) = (x + v * cos(alpha), y + v * sin(alpha)) if T < Tmin: Tmin = T a_min = a0 alpha = self.me.get_angle_to(skateX, skateY) if T == 10000: #print self.me.x, self.me.y, skateX, skateY, self.angle, direction, self.speed self.move_turn = alpha self.move_speed_up = 1.0 elif direction == 'back' and a_min < 0.0 and alpha < 0.0: self.move_turn = alpha + pi self.move_speed_up = a_min elif direction == 'back' and a_min < 0.0 and alpha > 0.0: self.move_turn = alpha - pi self.move_speed_up = a_min else: self.move_turn = alpha self.move_speed_up = a_min return True def tryPass(self, method='Forward', unit=None): if not unit: unit = self.myUnits[-1] puck_can_pass = True for opponentUnit in self.opponentUnits: if dist2segment(self.me, unit, opponentUnit) < self.game.stick_length: puck_can_pass = False if ((method == 'Forward' and abs(self.me.x - self.opponentPlayer.net_front) - abs(unit.x - self.opponentPlayer.net_front) > self.game.world_width / 5.0 and puck_can_pass and abs(unit.get_angle_to_unit(self.me)) < pi / 3.0) #or (method == 'Backward' and puck_can_pass) or (method == 'Strike')): angle = self.me.get_angle_to_unit(unit) if abs(angle) < pi / 3.0: self.move_pass_angle = angle if method == 'Forward': self.move_pass_power = 0.8 #elif method == 'Backward': # self.move_pass_power = 0.6 elif method == 'Strike': self.move_pass_power = 1.0 self.move_action = ActionType.PASS #print "pass " + method return True else: #self.move_turn = angle return False else: return False def probTakePuck(self): puck = self.world.puck puck_speed = sqrt(puck.speed_x * puck.speed_x + puck.speed_y * puck.speed_y) return 60.0 + max(self.me.dexterity, self.me.agility) - puck_speed * 5.0 def setStrategyDefendGate(self): #print "====== defence ======" if self.probTakePuck() < 100 and self.tryStrikePuck(): #print "defence: tryStrikePuck" return True distMe = self.me.get_distance_to_unit(self.world.puck) distOpponent = min([ unit.get_distance_to_unit(self.world.puck) for unit in self.opponentUnits ]) # if puck is close - let's catch it! if (self.me.type == HockeyistType.VERSATILE and distMe < 0.5 * distOpponent and self.world.puck.owner_player_id != self.me.player_id and self.setStrategyTakePuck()): #print "defence: setStrategyTakePuck" return True if ( #self.me.type == HockeyistType.DEFENCEMAN and self.defendCircle.get_distance_to_unit( self.world.puck) < self.defendCircle.radius and self.world.puck.owner_player_id != self.me.player_id and self.setStrategyTakePuck()): #print "defence: setStrategyTakePuck" return True # To stand or to move if self.me.get_distance_to_unit( self.defendCircle) < 1.0 * self.me.radius: self.move_turn = self.me.get_angle_to_unit(self.world.puck) #print "defence: turn to puck" else: #print "defence: skate" self.trySkate(self.defendCircle.x, self.defendCircle.y, True) return True def tryStrikePuck(self): unit = self.world.puck if (self.me.get_distance_to_unit(unit) < self.game.stick_length and abs(self.me.get_angle_to_unit(unit)) < 0.5 * self.game.stick_sector): self.move_action = ActionType.STRIKE #print "strike puck" return True else: return False def tryStrikeOpponent(self): for unit in self.opponentUnits: if (self.me.get_distance_to_unit(unit) < self.game.stick_length and abs(self.me.get_angle_to_unit(unit)) < 0.5 * self.game.stick_sector and unit.state != HockeyistState.KNOCKED_DOWN): self.move_action = ActionType.STRIKE #print "strike opponent" return True return False def setStrategyStrikeOpponent(self): if self.tryStrikeOpponent(): return True else: units = self.opponentUnits units.sort( key=lambda x: self.me.get_distance_to_unit(self.forward)) self.trySkate(units[0].x, units[0].y) return True def setStrategyTakePuck(self): if self.world.puck.owner_player_id == self.me.player_id: return False elif self.me.get_distance_to_unit( self.world.puck) < self.game.stick_length: self.move_turn = self.me.get_angle_to_unit(self.world.puck) self.move_speed_up = 1.0 self.move_action = ActionType.TAKE_PUCK elif abs(self.player.net_front - self.me.x ) > self.game.world_width / 2.0 and self.tryStrikeOpponent(): return True else: puck = self.world.puck (max_speed_x, max_speed_y) = (puck.speed_x - self.me.speed_x, puck.speed_y - self.me.speed_y) max_speed = sqrt(max_speed_x * max_speed_x + max_speed_y * max_speed_y) if max_speed == 0.0: n_tick = 1.0 elif self.me.get_distance_to_unit( self.world.puck) < self.game.stick_length: n_tick = 1.0 else: n_tick = self.me.get_distance_to_unit( self.world.puck) / max_speed if n_tick > 40.0: n_tick = 40.0 if n_tick < 7.0: n_tick = 1.0 gotoX = self.world.puck.x + self.world.puck.speed_x * n_tick if gotoX < self.game.rink_left or gotoX > self.game.rink_right: gotoX = self.me.x gotoY = self.world.puck.y + self.world.puck.speed_y * n_tick if gotoY < self.game.rink_top or gotoY > self.game.rink_bottom: gotoY = self.me.y self.calcAcceleration(gotoX, gotoY) self.move_action = ActionType.TAKE_PUCK return True def setStrategyAttackGate(self): # if the position is good or i am swinging >> let's strike! if ((self.me.get_distance_to_unit( self.attackCircle) < self.attackCircle.radius and abs(self.me.get_angle_to_unit(self.attackCircle)) < self.attackAngle) or self.me.state == HockeyistState.SWINGING): strikeX = self.opponentPlayer.net_front if self.me.y < self.rink_center_y: strikeY1 = self.opponentPlayer.net_bottom - self.world.puck.radius strikeY2 = self.opponentPlayer.net_bottom - 2.0 * self.world.puck.radius else: strikeY1 = self.opponentPlayer.net_top + self.world.puck.radius strikeY2 = self.opponentPlayer.net_top + 2.0 * self.world.puck.radius unit1 = Unit(9910, 0.0, 0.0, strikeX, strikeY1, 0.0, 0.0, 0.0, 0.0) unit2 = Unit(9911, 0.0, 0.0, strikeX, strikeY2, 0.0, 0.0, 0.0, 0.0) dist1 = min([ dist2segment(self.me, unit1, opponent) for opponent in self.opponentUnits ]) dist2 = min([ dist2segment(self.me, unit2, opponent) for opponent in self.opponentUnits ]) if dist1 < dist2: #print "trystrike2 " + str(dist1) + " " + str(dist2) self.tryStrike(strikeX, strikeY2) else: #print "trystrike1 " + str(dist1) + " " + str(dist2) self.tryStrike(strikeX, strikeY1) return True if abs(self.me.x - self.opponentPlayer.net_front) > self.game.world_width / 2.0: if self.me.y < self.rink_center_y: self.trySkate(self.attackCircle.x, 0.2 * self.game.world_height) else: self.trySkate(self.attackCircle.x, 0.8 * self.game.world_height) else: if self.me.y < self.rink_center_y: self.trySkate( self.attackCircle.x, self.opponentPlayer.net_bottom - self.world.puck.radius) else: self.trySkate( self.attackCircle.x, self.opponentPlayer.net_top + self.world.puck.radius) return True def tryStrike(self, strikeX, strikeY): PASS_ACCURACY = pi / 3.0 STRIKE_ACCURACY = 1.0 * pi / 180.0 angle = self.me.get_angle_to(strikeX, strikeY) self.move_turn = angle self.move_speed_up = 1.0 danger = False for opponentUnit in self.opponentUnits: if (opponentUnit.get_distance_to_unit( self.me) < 1.1 * self.game.stick_length and abs(opponentUnit.get_angle_to_unit( self.me)) < 0.6 * self.game.stick_sector and opponentUnit.state != HockeyistState.KNOCKED_DOWN): danger = True if (opponentUnit.get_distance_to_unit( self.world.puck) < 1.1 * self.game.stick_length and abs(opponentUnit.get_angle_to_unit( self.world.puck)) < 0.7 * self.game.stick_sector and opponentUnit.state != HockeyistState.KNOCKED_DOWN): danger = True if abs(angle) < STRIKE_ACCURACY and self.me.get_distance_to_unit( self.attackCircle) > self.attackPassDistance: if self.me.swing_ticks < self.game.max_effective_swing_ticks and not danger: #print "swing: " + str(self.me.swing_ticks) self.move_action = ActionType.SWING return True if (self.me.state == HockeyistState.SWINGING or abs(angle) < STRIKE_ACCURACY): #print "strike puck: " + str(self.me.swing_ticks) self.move_action = ActionType.STRIKE return True if (abs(angle) < PASS_ACCURACY #and danger and self.me.state != HockeyistState.SWINGING and self.me.get_distance_to_unit( self.attackCircle) < self.attackPassDistance): print "strike pass" unit = Unit(9912, 0.0, 0.0, strikeX, strikeY, 0.0, 0.0, 0.0, 0.0) self.tryPass('Strike', unit) return True return False def trySkate(self, skateX, skateY, zeroSpeed=False): if self.world.puck.owner_hockeyist_id == self.me.id: #print "trySkate: calcAcceleration1" self.calcAcceleration(skateX, skateY) #if self.speed < 0.1: test = Unit( 9913, 0.0, 0.0, self.me.x + 6.0 * self.me.radius * cos(self.me.angle + self.move_turn), self.me.y + 6.0 * self.me.radius * sin(self.me.angle + self.move_turn), 0.0, 0.0, 0.0, 0.0) dangerUnits = [ unit for unit in self.opponentUnits if unit.get_angle_to_unit(self.me) < pi / 3.0 ] if dangerUnits: dangerUnits.sort(key=lambda x: dist2segment(self.me, test, x)) dist = dist2segment(self.me, test, dangerUnits[0]) if dist < 10.0 and self.me.get_angle_to_unit( dangerUnits[0]) < 0.0: self.move_turn = self.game.hockeyist_turn_angle_factor #print "me+puck: angle +" elif dist < 10.0: self.move_turn = -self.game.hockeyist_turn_angle_factor #print "me+puck: angle -" return True elif self.tryStrikeOpponent(): #print "trySkate: tryStrikeOpponent" return True elif zeroSpeed: # i don't have a puck # i don't have a puck angle = self.me.get_angle_to(skateX, skateY) dist = self.me.get_distance_to(skateX, skateY) #if dist < 10.0*self.me.radius and abs(angle) > pi/2: if abs(angle) > pi / 2.0 and dist < self.game.world_width / 2.0: # going back if angle > 0.0: self.move_turn = angle - pi else: self.move_turn = angle + pi if self.speed >= 0.0: self.move_speed_up = -1.0 elif dist / self.speed > self.speed / self.game.hockeyist_speed_up_factor: self.move_speed_up = self.speed / self.game.hockeyist_speed_up_factor else: self.move_speed_up = -1.0 else: # going front self.move_turn = angle if self.speed <= 0.0: self.move_speed_up = 1.0 elif dist / self.speed < self.speed / self.game.hockeyist_speed_down_factor: self.move_speed_up = -self.speed / self.game.hockeyist_speed_down_factor else: self.move_speed_up = 1.0 #print "zeroSpeed: " + str(self.move_turn) + " " + str(self.move_speed_up) return True else: #print "trySkate: calcAcceleration2" self.calcAcceleration(skateX, skateY) if self.speed < 0.1: test = Unit( 9914, 0.0, 0.0, self.me.x + 2.0 * self.me.radius * cos(self.me.angle + self.move_turn), self.me.y + 2.0 * self.me.radius * sin(self.me.angle + self.move_turn), 0.0, 0.0, 0.0, 0.0) dist = min([ unit.get_distance_to_unit(test) for unit in self.opponentUnits ]) if test.x < self.game.rink_left or test.x > self.game.rink_right or test.y < self.game.rink_top or test.y > self.game.rink_bottom: dist = 0.0 if dist < 2.0 and self.me.get_angle_to_unit( self.attackCircle) > 0.0: self.move_turn += self.game.hockeyist_turn_angle_factor #print "me-puck: angle +" elif dist < 2.0: self.move_turn -= self.game.hockeyist_turn_angle_factor #print "me-puck: angle -" return True
class Strategy: def __init__(self, me, world, game): # print "================ " + str(world.tick) self.me = me self.world = world self.game = game self.move_turn = None self.move_speed_up = None self.move_action = None self.move_pass_angle = None self.move_pass_power = None self.angle = self.me.angle speed = sqrt(self.me.speed_x * self.me.speed_x + self.me.speed_y * self.me.speed_y) if self.me.speed_y > 0.0 and self.angle > 0.0: self.speed = speed elif self.me.speed_y > 0.0 and self.angle < 0.0: self.speed = -speed elif self.me.speed_y < 0.0 and self.angle > 0.0: self.speed = -speed elif self.me.speed_y < 0.0 and self.angle < 0.0: self.speed = speed elif self.me.speed_x > 0.0 and -pi / 2.0 < self.angle < pi / 2.0: self.speed = speed else: self.speed = -speed self.player = self.world.get_my_player() self.opponentPlayer = self.world.get_opponent_player() self.myUnits = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.id != self.me.id and hockeyist.type != HockeyistType.GOALIE and hockeyist.state != HockeyistState.RESTING ] self.myUnits.sort(key=lambda x: self.me.get_distance_to_unit(x)) self.team_count = len(self.myUnits) + 1 goalies = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.GOALIE ] if goalies: self.goalie = goalies[0] else: self.goalie = None forwards = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.FORWARD ] if forwards: self.forward = forwards[0] else: self.forward = None versatiles = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.VERSATILE ] if versatiles: self.versatile = versatiles[0] else: self.versatile = None defenders = [ hockeyist for hockeyist in self.world.hockeyists if hockeyist.teammate and hockeyist.type == HockeyistType.DEFENCEMAN ] if defenders: self.defender = defenders[0] else: self.defender = None self.opponentUnits = [ hockeyist for hockeyist in self.world.hockeyists if not hockeyist.teammate and hockeyist.type != HockeyistType.GOALIE and hockeyist.state != HockeyistState.RESTING ] self.opponentUnits.sort(key=lambda x: self.me.get_distance_to_unit(x)) self.rink_center_x = 0.5 * (self.game.rink_left + self.game.rink_right) self.rink_center_y = 0.5 * (self.game.rink_top + self.game.rink_bottom) if self.player.net_front < self.rink_center_x: self.position = "left" forward_x = self.opponentPlayer.net_front - 0.4 * self.game.world_width defence_x = self.player.net_front + 3.1 * self.me.radius # defence2_x = self.player.net_front + 4.1*self.me.radius else: self.position = "right" forward_x = self.opponentPlayer.net_front + 0.4 * self.game.world_width defence_x = self.player.net_front - 3.1 * self.me.radius # defence2_x = self.player.net_front - 4.1*self.me.radius if self.me.y < self.rink_center_y: forward_y = self.game.rink_top + 0.2 * self.game.world_height else: forward_y = self.game.rink_bottom - 0.2 * self.game.world_height self.forwardPlace = Unit(9906, 0.0, 0.0, forward_x, forward_y, 0.0, 0.0, 0.0, 0.0) self.defendCircle = Unit( 9907, 0.0, 1.0 * self.game.stick_length, defence_x, self.rink_center_y, 0.0, 0.0, 0.0, 0.0 ) # self.defendCircle2 = Unit(9901, 0.0, 1.0*self.game.stick_length, # defence2_x, self.rink_center_y+self.me.radius, # 0.0, 0.0, 0.0, 0.0) self.attackAngle = pi / 2.0 - pi / 6.0 if self.goalie: self.attackCircle = Unit( 9908, 1.0, 0.4 * self.game.world_height, self.opponentPlayer.net_front, self.rink_center_y, 0.0, 0.0, 0.0, 0.0, ) self.attackPassDistance = 3.0 * self.me.radius else: self.attackCircle = Unit( 9909, 1.0, self.game.world_width, self.opponentPlayer.net_front, self.rink_center_y, 0.0, 0.0, 0.0, 0.0 ) self.attackPassDistance = self.game.world_width def getStrategy2(self): if self.world.puck.owner_hockeyist_id == self.me.id: # if self.tryPass('Forward'): # return True # else: self.setStrategyAttackGate() return True elif self.me.state == HockeyistState.SWINGING: self.move_action = ActionType.CANCEL_STRIKE return True elif self.world.puck.owner_player_id == self.me.player_id: self.setStrategyDefendGate() return True elif abs(self.me.x - self.player.net_front) < abs(self.myUnits[0].x - self.player.net_front): self.setStrategyDefendGate() return True else: self.setStrategyTakePuck() return True def getStrategy3(self): if self.world.puck.owner_hockeyist_id == self.me.id: if self.me.state == HockeyistState.SWINGING or self.me.type == HockeyistType.FORWARD: self.setStrategyAttackGate() return True elif self.me.type != HockeyistType.FORWARD and self.tryPass("Forward", self.forward): print "Pass to forward" return True elif self.me.type == HockeyistType.DEFENCEMAN and self.tryPass("Forward", self.versatile): print "Pass to versatile" return True else: self.setStrategyAttackGate() return True elif self.me.state == HockeyistState.SWINGING: self.move_action = ActionType.CANCEL_STRIKE return True if self.me.type == HockeyistType.DEFENCEMAN: # print "DEFENCEMAN: Defend gate" self.setStrategyDefendGate() return True if self.me.type == HockeyistType.FORWARD: if ( # self.me.get_distance_to_unit(self.attackCircle) < self.attackCircle.radius # or abs(self.me.x - self.attackCircle.x) > abs(self.world.puck.x - self.attackCircle.x) abs(self.world.puck.x - self.attackCircle.x) < 0.55 * self.game.world_width or self.me.get_distance_to_unit(self.world.puck) < self.game.stick_length # or self.world.puck.owner_player_id == self.opponentPlayer.id ): # print "FORWARD: Take puck" self.setStrategyTakePuck() return True elif self.me.get_distance_to_unit(self.forwardPlace) < 1.0 * self.me.radius: # print "FORWARD: Stay near opponent gate" self.move_turn = self.me.get_angle_to_unit(self.world.puck) return True else: # print "FORWARD: Skate to (" + str(self.forwardPlace.x) + ", " + str(self.forwardPlace.y) + ")" self.trySkate(self.forwardPlace.x, self.forwardPlace.y, True) return True if self.me.type == HockeyistType.VERSATILE: if ( self.world.puck.owner_hockeyist_id == self.defender.id or self.defender.get_distance_to_unit(self.defendCircle) > 2.0 * self.game.stick_length or self.defender == None ): self.setStrategyDefendGate() return True elif self.world.puck.owner_player_id == self.me.player_id: # print "VERSATILE: Strike opponent" self.setStrategyStrikeOpponent() return True elif self.tryStrikeOpponent(): return True # elif self.world.puck.owner_player_id == self.opponentPlayer.id: # self.setStrategyDefendGate() # return True else: # print "VERSATILE: Take puck" self.setStrategyTakePuck() return True def calcAcceleration(self, skateX, skateY): Tmin = 10000 a_min = 1.0 if self.me.get_distance_to(skateX, skateY) > self.game.world_width / 5.0: self.move_turn = self.me.get_angle_to(skateX, skateY) self.move_speed_up = 1.0 return True if abs(self.me.get_angle_to(skateX, skateY)) <= pi / 2.0: direction = "forward" else: direction = "back" for i in range(10): (x, y) = (self.me.x, self.me.y) v = self.speed alpha = self.angle a0 = 1.0 - i / 10.0 T = Tmin if direction == "forward" and a0 < 0.0: break # if direction == 'back' and self.me.get_distance_to(skateX, skateY) > 100.0 and a < 0.0: # break for j in range(100): aj = a0 - j * 0.001 unit = Unit(999 + i * 100 + j, 0.0, 0.0, x, y, 0.0, 0.0, alpha, 0.0) if ( x < self.game.rink_left or x > self.game.rink_right or y < self.game.rink_top or y > self.game.rink_bottom ): break if unit.get_distance_to(skateX, skateY) < 1.0: T = j break if aj > 0.0: v += aj * self.game.hockeyist_speed_up_factor else: v += aj * self.game.hockeyist_speed_down_factor v = 0.95 * v # friction dalpha = unit.get_angle_to(skateX, skateY) if v < 0.0 and dalpha < 0.0: dalpha = dalpha + pi elif v < 0.0 and dalpha > 0.0: dalpha = dalpha - pi dalpha = copysign(min(abs(dalpha), self.game.hockeyist_turn_angle_factor), dalpha) alpha = normAngle(alpha + dalpha) (x, y) = (x + v * cos(alpha), y + v * sin(alpha)) if T < Tmin: Tmin = T a_min = a0 alpha = self.me.get_angle_to(skateX, skateY) if T == 10000: # print self.me.x, self.me.y, skateX, skateY, self.angle, direction, self.speed self.move_turn = alpha self.move_speed_up = 1.0 elif direction == "back" and a_min < 0.0 and alpha < 0.0: self.move_turn = alpha + pi self.move_speed_up = a_min elif direction == "back" and a_min < 0.0 and alpha > 0.0: self.move_turn = alpha - pi self.move_speed_up = a_min else: self.move_turn = alpha self.move_speed_up = a_min return True def tryPass(self, method="Forward", unit=None): if not unit: unit = self.myUnits[-1] puck_can_pass = True for opponentUnit in self.opponentUnits: if dist2segment(self.me, unit, opponentUnit) < self.game.stick_length: puck_can_pass = False if ( ( method == "Forward" and abs(self.me.x - self.opponentPlayer.net_front) - abs(unit.x - self.opponentPlayer.net_front) > self.game.world_width / 5.0 and puck_can_pass and abs(unit.get_angle_to_unit(self.me)) < pi / 3.0 ) # or (method == 'Backward' and puck_can_pass) or (method == "Strike") ): angle = self.me.get_angle_to_unit(unit) if abs(angle) < pi / 3.0: self.move_pass_angle = angle if method == "Forward": self.move_pass_power = 0.8 # elif method == 'Backward': # self.move_pass_power = 0.6 elif method == "Strike": self.move_pass_power = 1.0 self.move_action = ActionType.PASS # print "pass " + method return True else: # self.move_turn = angle return False else: return False def probTakePuck(self): puck = self.world.puck puck_speed = sqrt(puck.speed_x * puck.speed_x + puck.speed_y * puck.speed_y) return 60.0 + max(self.me.dexterity, self.me.agility) - puck_speed * 5.0 def setStrategyDefendGate(self): # print "====== defence ======" if self.probTakePuck() < 100 and self.tryStrikePuck(): # print "defence: tryStrikePuck" return True distMe = self.me.get_distance_to_unit(self.world.puck) distOpponent = min([unit.get_distance_to_unit(self.world.puck) for unit in self.opponentUnits]) # if puck is close - let's catch it! if ( self.me.type == HockeyistType.VERSATILE and distMe < 0.5 * distOpponent and self.world.puck.owner_player_id != self.me.player_id and self.setStrategyTakePuck() ): # print "defence: setStrategyTakePuck" return True if ( # self.me.type == HockeyistType.DEFENCEMAN and self.defendCircle.get_distance_to_unit(self.world.puck) < self.defendCircle.radius and self.world.puck.owner_player_id != self.me.player_id and self.setStrategyTakePuck() ): # print "defence: setStrategyTakePuck" return True # To stand or to move if self.me.get_distance_to_unit(self.defendCircle) < 1.0 * self.me.radius: self.move_turn = self.me.get_angle_to_unit(self.world.puck) # print "defence: turn to puck" else: # print "defence: skate" self.trySkate(self.defendCircle.x, self.defendCircle.y, True) return True def tryStrikePuck(self): unit = self.world.puck if ( self.me.get_distance_to_unit(unit) < self.game.stick_length and abs(self.me.get_angle_to_unit(unit)) < 0.5 * self.game.stick_sector ): self.move_action = ActionType.STRIKE # print "strike puck" return True else: return False def tryStrikeOpponent(self): for unit in self.opponentUnits: if ( self.me.get_distance_to_unit(unit) < self.game.stick_length and abs(self.me.get_angle_to_unit(unit)) < 0.5 * self.game.stick_sector and unit.state != HockeyistState.KNOCKED_DOWN ): self.move_action = ActionType.STRIKE # print "strike opponent" return True return False def setStrategyStrikeOpponent(self): if self.tryStrikeOpponent(): return True else: units = self.opponentUnits units.sort(key=lambda x: self.me.get_distance_to_unit(self.forward)) self.trySkate(units[0].x, units[0].y) return True def setStrategyTakePuck(self): if self.world.puck.owner_player_id == self.me.player_id: return False elif self.me.get_distance_to_unit(self.world.puck) < self.game.stick_length: self.move_turn = self.me.get_angle_to_unit(self.world.puck) self.move_speed_up = 1.0 self.move_action = ActionType.TAKE_PUCK elif abs(self.player.net_front - self.me.x) > self.game.world_width / 2.0 and self.tryStrikeOpponent(): return True else: puck = self.world.puck (max_speed_x, max_speed_y) = (puck.speed_x - self.me.speed_x, puck.speed_y - self.me.speed_y) max_speed = sqrt(max_speed_x * max_speed_x + max_speed_y * max_speed_y) if max_speed == 0.0: n_tick = 1.0 elif self.me.get_distance_to_unit(self.world.puck) < self.game.stick_length: n_tick = 1.0 else: n_tick = self.me.get_distance_to_unit(self.world.puck) / max_speed if n_tick > 40.0: n_tick = 40.0 if n_tick < 7.0: n_tick = 1.0 gotoX = self.world.puck.x + self.world.puck.speed_x * n_tick if gotoX < self.game.rink_left or gotoX > self.game.rink_right: gotoX = self.me.x gotoY = self.world.puck.y + self.world.puck.speed_y * n_tick if gotoY < self.game.rink_top or gotoY > self.game.rink_bottom: gotoY = self.me.y self.calcAcceleration(gotoX, gotoY) self.move_action = ActionType.TAKE_PUCK return True def setStrategyAttackGate(self): # if the position is good or i am swinging >> let's strike! if ( self.me.get_distance_to_unit(self.attackCircle) < self.attackCircle.radius and abs(self.me.get_angle_to_unit(self.attackCircle)) < self.attackAngle ) or self.me.state == HockeyistState.SWINGING: strikeX = self.opponentPlayer.net_front if self.me.y < self.rink_center_y: strikeY1 = self.opponentPlayer.net_bottom - self.world.puck.radius strikeY2 = self.opponentPlayer.net_bottom - 2.0 * self.world.puck.radius else: strikeY1 = self.opponentPlayer.net_top + self.world.puck.radius strikeY2 = self.opponentPlayer.net_top + 2.0 * self.world.puck.radius unit1 = Unit(9910, 0.0, 0.0, strikeX, strikeY1, 0.0, 0.0, 0.0, 0.0) unit2 = Unit(9911, 0.0, 0.0, strikeX, strikeY2, 0.0, 0.0, 0.0, 0.0) dist1 = min([dist2segment(self.me, unit1, opponent) for opponent in self.opponentUnits]) dist2 = min([dist2segment(self.me, unit2, opponent) for opponent in self.opponentUnits]) if dist1 < dist2: # print "trystrike2 " + str(dist1) + " " + str(dist2) self.tryStrike(strikeX, strikeY2) else: # print "trystrike1 " + str(dist1) + " " + str(dist2) self.tryStrike(strikeX, strikeY1) return True if abs(self.me.x - self.opponentPlayer.net_front) > self.game.world_width / 2.0: if self.me.y < self.rink_center_y: self.trySkate(self.attackCircle.x, 0.2 * self.game.world_height) else: self.trySkate(self.attackCircle.x, 0.8 * self.game.world_height) else: if self.me.y < self.rink_center_y: self.trySkate(self.attackCircle.x, self.opponentPlayer.net_bottom - self.world.puck.radius) else: self.trySkate(self.attackCircle.x, self.opponentPlayer.net_top + self.world.puck.radius) return True def tryStrike(self, strikeX, strikeY): PASS_ACCURACY = pi / 3.0 STRIKE_ACCURACY = 1.0 * pi / 180.0 angle = self.me.get_angle_to(strikeX, strikeY) self.move_turn = angle self.move_speed_up = 1.0 danger = False for opponentUnit in self.opponentUnits: if ( opponentUnit.get_distance_to_unit(self.me) < 1.1 * self.game.stick_length and abs(opponentUnit.get_angle_to_unit(self.me)) < 0.6 * self.game.stick_sector and opponentUnit.state != HockeyistState.KNOCKED_DOWN ): danger = True if ( opponentUnit.get_distance_to_unit(self.world.puck) < 1.1 * self.game.stick_length and abs(opponentUnit.get_angle_to_unit(self.world.puck)) < 0.7 * self.game.stick_sector and opponentUnit.state != HockeyistState.KNOCKED_DOWN ): danger = True if abs(angle) < STRIKE_ACCURACY and self.me.get_distance_to_unit(self.attackCircle) > self.attackPassDistance: if self.me.swing_ticks < self.game.max_effective_swing_ticks and not danger: # print "swing: " + str(self.me.swing_ticks) self.move_action = ActionType.SWING return True if self.me.state == HockeyistState.SWINGING or abs(angle) < STRIKE_ACCURACY: # print "strike puck: " + str(self.me.swing_ticks) self.move_action = ActionType.STRIKE return True if ( abs(angle) < PASS_ACCURACY # and danger and self.me.state != HockeyistState.SWINGING and self.me.get_distance_to_unit(self.attackCircle) < self.attackPassDistance ): print "strike pass" unit = Unit(9912, 0.0, 0.0, strikeX, strikeY, 0.0, 0.0, 0.0, 0.0) self.tryPass("Strike", unit) return True return False def trySkate(self, skateX, skateY, zeroSpeed=False): if self.world.puck.owner_hockeyist_id == self.me.id: # print "trySkate: calcAcceleration1" self.calcAcceleration(skateX, skateY) # if self.speed < 0.1: test = Unit( 9913, 0.0, 0.0, self.me.x + 6.0 * self.me.radius * cos(self.me.angle + self.move_turn), self.me.y + 6.0 * self.me.radius * sin(self.me.angle + self.move_turn), 0.0, 0.0, 0.0, 0.0, ) dangerUnits = [unit for unit in self.opponentUnits if unit.get_angle_to_unit(self.me) < pi / 3.0] if dangerUnits: dangerUnits.sort(key=lambda x: dist2segment(self.me, test, x)) dist = dist2segment(self.me, test, dangerUnits[0]) if dist < 10.0 and self.me.get_angle_to_unit(dangerUnits[0]) < 0.0: self.move_turn = self.game.hockeyist_turn_angle_factor # print "me+puck: angle +" elif dist < 10.0: self.move_turn = -self.game.hockeyist_turn_angle_factor # print "me+puck: angle -" return True elif self.tryStrikeOpponent(): # print "trySkate: tryStrikeOpponent" return True elif zeroSpeed: # i don't have a puck # i don't have a puck angle = self.me.get_angle_to(skateX, skateY) dist = self.me.get_distance_to(skateX, skateY) # if dist < 10.0*self.me.radius and abs(angle) > pi/2: if abs(angle) > pi / 2.0 and dist < self.game.world_width / 2.0: # going back if angle > 0.0: self.move_turn = angle - pi else: self.move_turn = angle + pi if self.speed >= 0.0: self.move_speed_up = -1.0 elif dist / self.speed > self.speed / self.game.hockeyist_speed_up_factor: self.move_speed_up = self.speed / self.game.hockeyist_speed_up_factor else: self.move_speed_up = -1.0 else: # going front self.move_turn = angle if self.speed <= 0.0: self.move_speed_up = 1.0 elif dist / self.speed < self.speed / self.game.hockeyist_speed_down_factor: self.move_speed_up = -self.speed / self.game.hockeyist_speed_down_factor else: self.move_speed_up = 1.0 # print "zeroSpeed: " + str(self.move_turn) + " " + str(self.move_speed_up) return True else: # print "trySkate: calcAcceleration2" self.calcAcceleration(skateX, skateY) if self.speed < 0.1: test = Unit( 9914, 0.0, 0.0, self.me.x + 2.0 * self.me.radius * cos(self.me.angle + self.move_turn), self.me.y + 2.0 * self.me.radius * sin(self.me.angle + self.move_turn), 0.0, 0.0, 0.0, 0.0, ) dist = min([unit.get_distance_to_unit(test) for unit in self.opponentUnits]) if ( test.x < self.game.rink_left or test.x > self.game.rink_right or test.y < self.game.rink_top or test.y > self.game.rink_bottom ): dist = 0.0 if dist < 2.0 and self.me.get_angle_to_unit(self.attackCircle) > 0.0: self.move_turn += self.game.hockeyist_turn_angle_factor # print "me-puck: angle +" elif dist < 2.0: self.move_turn -= self.game.hockeyist_turn_angle_factor # print "me-puck: angle -" return True