SHARE
TWEET

Untitled

a guest Nov 15th, 2016 122 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import math
  2. import random
  3. import sys
  4.  
  5. from model.ActionType import ActionType
  6. from model.Faction import Faction
  7. from model.Game import Game
  8. from model.Move import Move
  9. from model.Wizard import Wizard
  10. from model.World import World
  11.  
  12. WAYPOINT_RADIUS = 100.00
  13. LOW_HP_FACTOR = 0.25
  14.  
  15. class Point2D:
  16.     """
  17.    Вспомогательный класс для хранения позиций на карте.
  18.    """
  19.  
  20.     def __init__(self, x, y):
  21.         self.x = x
  22.         self.y = y
  23.  
  24.     def get_distance_to(self, x, y):
  25.         return math.hypot(self.x - x, self.y - y)
  26.  
  27.     def get_distance_to_point(self, point):
  28.         return self.get_distance_to(point.x, point.y)
  29.  
  30.     def get_distance_to_unit(self, unit):
  31.         return self.get_distance_to(unit.x, unit.y)
  32.  
  33.  
  34. def get_nearest_target(me: Wizard, world: World):
  35.     """
  36.    Находим ближайшую цель для атаки, независимо от её типа и других характеристик.
  37.    """
  38.     targets = []
  39.     targets.extend(world.buildings)
  40.     targets.extend(world.wizards)
  41.     targets.extend(world.minions)
  42.  
  43.     nearest_target = None
  44.     nearest_target_distance = sys.float_info.max
  45.  
  46.     for target in targets:
  47.         # Нейтралов атакуем тоже если их хп меньше максимального - они стригеренны
  48.         if (target.faction == me.faction or
  49.                         target.faction == Faction.NEUTRAL and target.life < target.max_life):
  50.             continue
  51.  
  52.         distance = me.get_distance_to_unit(target)
  53.         if distance < nearest_target_distance:
  54.             nearest_target = target
  55.             nearest_target_distance = distance
  56.     return nearest_target
  57.  
  58.  
  59. def apply_go_to_move(point: Point2D, me: Wizard, game: Game, move: Move):
  60.     """
  61.    Простейший способ перемещения волшебника.
  62.    """
  63.     angle = me.get_angle_to(point.x, point.y)
  64.     move.turn = angle
  65.  
  66.     if math.fabs(angle) < game.staff_sector / 4.0:
  67.         move.speed = game.wizard_forward_speed
  68.  
  69.  
  70. def get_next_waypoint(waypoints, me: Wizard):
  71.     """
  72.    Данный метод предполагает, что все ключевые точки на линии упорядочены по уменьшению дистанции до последней
  73.    ключевой точки. Перебирая их по порядку, находим первую попавшуюся точку, которая находится ближе к последней
  74.    точке на линии, чем волшебник. Это и будет следующей ключевой точкой.
  75.  
  76.    Дополнительно проверяем, не находится ли волшебник достаточно близко к какой-либо из ключевых точек. Если это
  77.    так, то мы сразу возвращаем следующую ключевую точку.
  78.    """
  79.     last_waypoint = waypoints[-1]
  80.     for i, waypoint in enumerate(waypoints[:-1]):
  81.         if waypoint.get_distance_to_unit(me) <= WAYPOINT_RADIUS:
  82.             return waypoints[i + 1]
  83.  
  84.         if last_waypoint.get_distance_to_point(waypoint) < last_waypoint.get_distance_to_unit(me):
  85.             return waypoint
  86.  
  87.     return last_waypoint
  88.  
  89.  
  90. def get_waypoints_by_id(id, game: Game):
  91.     map_size = game.map_size
  92.     if id in [1, 2, 6, 7]:
  93.         # точки верхней линии
  94.         return [
  95.             Point2D(100.0, map_size - 100.0),
  96.             Point2D(100.0, map_size - 400.0),
  97.             Point2D(200.0, map_size - 800.0),
  98.             Point2D(200.0, map_size * 0.75),
  99.             Point2D(200.0, map_size * 0.5),
  100.             Point2D(200.0, map_size * 0.25),
  101.             Point2D(200.0, 200.0),
  102.             Point2D(map_size * 0.25, 200.0),
  103.             Point2D(map_size * 0.5, 200.0),
  104.             Point2D(map_size * 0.75, 200.0),
  105.             Point2D(map_size - 200.0, 200.0)
  106.         ]
  107.     elif id in [3, 8]:
  108.         # точки средней линии
  109.         return [
  110.             Point2D(100.0, map_size - 100.0),
  111.             random.choice([Point2D(600.0, map_size - 200.0), Point2D(200.0, map_size - 600.0)]),
  112.             Point2D(800.0, map_size - 800.0),
  113.             Point2D(map_size - 600.0, 600.0)
  114.         ]
  115.     else:
  116.         # точки нижней линии
  117.         return [
  118.             Point2D(100.0, map_size - 100.0),
  119.             Point2D(400.0, map_size - 100.0),
  120.             Point2D(800.0, map_size - 200.0),
  121.             Point2D(map_size * 0.25, map_size - 200.0),
  122.             Point2D(map_size * 0.5, map_size - 200.0),
  123.             Point2D(map_size * 0.75, map_size - 200.0),
  124.             Point2D(map_size - 200.0, map_size - 200.0),
  125.             Point2D(map_size - 200.0, map_size * 0.75),
  126.             Point2D(map_size - 200.0, map_size * 0.5),
  127.             Point2D(map_size - 200.0, map_size * 0.25),
  128.             Point2D(map_size - 200.0, 200.0)
  129.         ]
  130.  
  131.  
  132. class MyStrategy:
  133.     def __init__(self):
  134.         super().__init__()
  135.         self.initialized = False
  136.         self.waypoints = None
  137.  
  138.     def initialize(self, me: Wizard, game: Game):
  139.         random.seed(game.random_seed)
  140.         self.waypoints = get_waypoints_by_id(me.id, game)
  141.         self.initialized = True
  142.  
  143.     def move(self, me: Wizard, world: World, game: Game, move: Move):
  144.         if not self.initialized:
  145.             self.initialize(me, game)
  146.  
  147.         move.strafe_speed = random.choice([game.wizard_strafe_speed, -game.wizard_strafe_speed])
  148.  
  149.         if me.life < me.max_life * LOW_HP_FACTOR:
  150.             apply_go_to_move(get_next_waypoint(self.waypoints[::-1], me))
  151.             return
  152.  
  153.         nearest_target = get_nearest_target(me, world)
  154.         if nearest_target is not None:
  155.             distance = me.get_distance_to_unit(nearest_target)
  156.  
  157.             if distance <= me.cast_range:
  158.                 angle = me.get_angle_to_unit(nearest_target)
  159.                 move.turn = angle
  160.  
  161.                 if math.fabs(angle) < game.staff_sector / 2.0:
  162.                     move.action = ActionType.MAGIC_MISSILE
  163.                     move.cast_angle = angle
  164.                     move.min_cast_distance = distance - nearest_target.radius + game.magic_missile_radius
  165.                     return
  166.  
  167.         apply_go_to_move(get_next_waypoint(self.waypoints, me), me, game, move)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top