def nearest_land_pos(self, point: Point, extend_dist: int = 50) -> Point: """Returns the nearest point inside a land exclusion zone from point `extend_dist` determines how far inside the zone the point should be placed""" if self.is_on_land(point): return point point = geometry.Point(point.x, point.y) nearest_points = [] if not self.landmap: raise RuntimeError("Landmap not initialized") for inclusion_zone in self.landmap[0]: nearest_pair = ops.nearest_points(point, inclusion_zone) nearest_points.append(nearest_pair[1]) min_distance = point.distance( nearest_points[0]) # type: geometry.Point nearest_point = nearest_points[0] # type: geometry.Point for pt in nearest_points[1:]: distance = point.distance(pt) if distance < min_distance: min_distance = distance nearest_point = pt assert isinstance(nearest_point, geometry.Point) point = Point(point.x, point.y) nearest_point = Point(nearest_point.x, nearest_point.y) new_point = point.point_from_heading( point.heading_between_point(nearest_point), point.distance_to_point(nearest_point) + extend_dist) return new_point
def generate_defensive_groups(self) -> None: # AAA for defending against close targets. aa_group = self.add_auxiliary_group("AA") num_launchers = random.randint(6, 8) positions = self.get_circular_position( num_launchers, launcher_distance=210, coverage=360 ) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group( aa_group, AirDefence.SAM_SA_19_Tunguska_Grison, f"AA#{i}", Point(x, y), heading, ) # SA-15 for both shorter range targets and point defense. pd_group = self.add_auxiliary_group("PD") num_launchers = random.randint(2, 4) positions = self.get_circular_position( num_launchers, launcher_distance=140, coverage=360 ) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group( pd_group, AirDefence.SAM_SA_15_Tor_Gauntlet, f"PD#{i}", Point(x, y), heading, )
def test_point(self): p1 = Point(2, 2) p2 = p1 + Point(1, 1) self.assertEqual(p2.x, 3) self.assertEqual(p2.y, 3) p2 = 1 + p1 self.assertEqual(p2.x, 3) self.assertEqual(p2.y, 3) self.assertEqual(3 * p2, Point(9, 9)) self.assertEqual(p2.x, 3) self.assertEqual(p2.y, 3) self.assertEqual(p2 * 0.5, Point(1.5, 1.5)) p2 = p1 - 1 self.assertEqual(p2.x, 1) self.assertEqual(p2.y, 1) p2 = p1 - p2 self.assertEqual(p2.x, 1) self.assertEqual(p2.y, 1)
def add_json_cp(self, theater, p: dict) -> ControlPoint: if p["type"] == "airbase": airbase = theater.terrain.airports[p["id"]].__class__ if "radials" in p.keys(): radials = p["radials"] else: radials = LAND if "size" in p.keys(): size = p["size"] else: size = SIZE_REGULAR if "importance" in p.keys(): importance = p["importance"] else: importance = IMPORTANCE_MEDIUM cp = ControlPoint.from_airport(airbase, radials, size, importance) elif p["type"] == "carrier": cp = ControlPoint.carrier("carrier", Point(p["x"], p["y"]), p["id"]) else: cp = ControlPoint.lha("lha", Point(p["x"], p["y"]), p["id"]) if "captured_invert" in p.keys(): cp.captured_invert = p["captured_invert"] else: cp.captured_invert = False return cp
def add_json_cp(self, theater, p: dict) -> ControlPoint: cp: ControlPoint if p["type"] == "airbase": airbase = theater.terrain.airports[p["id"]] if "size" in p.keys(): size = p["size"] else: size = SIZE_REGULAR if "importance" in p.keys(): importance = p["importance"] else: importance = IMPORTANCE_MEDIUM cp = Airfield(airbase, size, importance) elif p["type"] == "carrier": cp = Carrier("carrier", Point(p["x"], p["y"]), p["id"]) else: cp = Lha("lha", Point(p["x"], p["y"]), p["id"]) if "captured_invert" in p.keys(): cp.captured_invert = p["captured_invert"] else: cp.captured_invert = False return cp
def generate_defensive_groups(self) -> None: # AAA for defending against close targets. aa_group = self.add_auxiliary_group(SkynetRole.NoSkynetBehavior) num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=210, coverage=360 ) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group( aa_group, AirDefence._2S6_Tunguska, f"AA#{i}", Point(x, y), heading, ) # SA-15 for both shorter range targets and point defense. pd_group = self.add_auxiliary_group(SkynetRole.PointDefense) num_launchers = 2 positions = self.get_circular_position( num_launchers, launcher_distance=140, coverage=360 ) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group( pd_group, AirDefence.Tor_9A331, f"PD#{i}", Point(x, y), heading, )
def compute_conflicts_position(self): """ Compute the current conflict center position(s), mainly used for culling calculation :return: List of points of interests """ points = [] # By default, use the existing frontline conflict position for front_line in self.theater.conflicts(): position = Conflict.frontline_position(front_line.control_point_a, front_line.control_point_b, self.theater) points.append(position[0]) points.append(front_line.control_point_a.position) points.append(front_line.control_point_b.position) # If do_not_cull_carrier is enabled, add carriers as culling point if self.settings.perf_do_not_cull_carrier: for cp in self.theater.controlpoints: if cp.is_carrier or cp.is_lha: points.append(cp.position) # If there is no conflict take the center point between the two nearest opposing bases if len(points) == 0: cpoint = None min_distance = sys.maxsize for cp in self.theater.player_points(): for cp2 in self.theater.enemy_points(): d = cp.position.distance_to_point(cp2.position) if d < min_distance: min_distance = d cpoint = Point((cp.position.x + cp2.position.x) / 2, (cp.position.y + cp2.position.y) / 2) points.append(cp.position) points.append(cp2.position) break if cpoint is not None: break if cpoint is not None: points.append(cpoint) packages = itertools.chain(self.blue_ato.packages, self.red_ato.packages) for package in packages: if package.primary_task is FlightType.BARCAP: # BARCAPs will be planned at most locations on smaller theaters, # rendering culling fairly useless. BARCAP packages don't really # need the ground detail since they're defensive. SAMs nearby # are only interesting if there are enemies in the area, and if # there are they won't be culled because of the enemy's mission. continue points.append(package.target.position) # Else 0,0, since we need a default value # (in this case this means the whole map is owned by the same player, so it is not an issue) if len(points) == 0: points.append(Point(0, 0)) self.__culling_points = points
class PersianGulfTheater(ConflictTheater): terrain = persiangulf.PersianGulf() overview_image = "persiangulf.gif" reference_points = ( ReferencePoint(persiangulf.Jiroft_Airport.position, Point(1692, 1343)), ReferencePoint(persiangulf.Liwa_Airbase.position, Point(358, 3238)), ) landmap = load_landmap("resources\\gulflandmap.p") daytime_map = { "dawn": (6, 8), "day": (8, 16), "dusk": (16, 18), "night": (0, 5), }
class NevadaTheater(ConflictTheater): terrain = nevada.Nevada() overview_image = "nevada.gif" reference_points = ( ReferencePoint(nevada.Mina_Airport_3Q0.position, Point(252, 295)), ReferencePoint(nevada.Laughlin_Airport.position, Point(844, 909)), ) landmap = load_landmap("resources\\nevlandmap.p") daytime_map = { "dawn": (4, 6), "day": (6, 17), "dusk": (17, 18), "night": (0, 5), }
class NormandyTheater(ConflictTheater): terrain = normandy.Normandy() overview_image = "normandy.gif" reference_points = ( ReferencePoint(normandy.Needs_Oar_Point.position, Point(515, 329)), ReferencePoint(normandy.Evreux.position, Point(2029, 1709)), ) landmap = load_landmap("resources\\normandylandmap.p") daytime_map = { "dawn": (6, 8), "day": (10, 17), "dusk": (17, 18), "night": (0, 5), }
class TheChannelTheater(ConflictTheater): terrain = thechannel.TheChannel() overview_image = "thechannel.gif" reference_points = (ReferencePoint(thechannel.Abbeville_Drucat.position, Point(2005, 2390)), ReferencePoint(thechannel.Detling.position, Point(706, 382))) landmap = load_landmap("resources\\channellandmap.p") daytime_map = { "dawn": (6, 8), "day": (10, 17), "dusk": (17, 18), "night": (0, 5), }
class SyriaTheater(ConflictTheater): terrain = syria.Syria() overview_image = "syria.gif" reference_points = ( ReferencePoint(syria.Eyn_Shemer.position, Point(564, 1289)), ReferencePoint(syria.Tabqa.position, Point(1329, 491)), ) landmap = load_landmap("resources\\syrialandmap.p") daytime_map = { "dawn": (6, 8), "day": (8, 16), "dusk": (16, 18), "night": (0, 5), }
def test_poly_triangulation(self): points = [Point(1, 2), Point(3, 1), Point(7, 2), Point(9, 4), Point(6, 6), Point(6, 9), Point(4, 8), Point(2, 9), Point(1, 7), Point(0, 5)] poly = Polygon(points) areas = [x.area() for x in poly.triangulate()] self.assertEqual(areas, [2.5, 9.5, 10.0, 7.5, 9.0, 1.0, 5.0, 0.0])
def load_templates(): temp_mis = Mission() temp_mis.load_file("resources/tools/groundobject_templates.miz") groups = { } # type: typing.Dict[str, typing.Dict[int, typing.List[Static]]] for static_group in temp_mis.country( "USA").static_group + temp_mis.country( "USAF Aggressors").static_group: for static in static_group.units: static_name = str(static.name).split()[0] tpl_name, tpl_idx = static_name[:-1], int(static_name[-1]) groups[tpl_name] = groups.get(tpl_name, {}) groups[tpl_name][tpl_idx] = groups[tpl_name].get(tpl_idx, []) groups[tpl_name][tpl_idx].append(static) tpls = { name: {idx: [] for idx in groups[name].keys()} for name in groups.keys() } for category_name, category_groups in groups.items(): for idx, static_groups in category_groups.items(): dist = -1 a, b = None, None for aa in static_groups: for bb in static_groups: if aa.position.distance_to_point(bb.position) > dist: dist = aa.position.distance_to_point(bb.position) a = aa b = bb center = a.position.point_from_heading( a.position.heading_between_point(b.position), dist / 2) for static in static_groups: tpls[category_name][idx].append({ "type": static.type, "offset": Point(center.x - static.position.x, center.y - static.position.y), "heading": static.heading, }) tpls["aa"] = {0: [{"type": "AA", "offset": Point(0, 0), "heading": 0}]} return tpls
class CaucasusTheater(ConflictTheater): terrain = caucasus.Caucasus() overview_image = "caumap.gif" reference_points = ( ReferencePoint(caucasus.Gelendzhik.position, Point(176, 298)), ReferencePoint(caucasus.Batumi.position, Point(1307, 1205)), ) landmap = load_landmap("resources\\caulandmap.p") daytime_map = { "dawn": (6, 9), "day": (9, 18), "dusk": (18, 20), "night": (0, 5), }
def test_add_oblong(self) -> None: m: Mission = dcs.mission.Mission() layer = m.drawings.get_layer(StandardLayer.Common) self.assertEqual(0, len(layer.objects)) oblong = layer.add_oblong( Point(1000, 1000, m.terrain), Point(4000, 1000, m.terrain), 1000, resolution=20, ) self.assertEqual(1, len(layer.objects)) # Resolution 20 should give 43 points # (21 in each end and one extra to close polygon) self.assertEqual(43, len(oblong.points))
def test_add_drawings_to_loaded_mission(self) -> None: m: Mission = dcs.mission.Mission() self.assertEqual(0, len(m.load_file('tests/missions/Draw_tool_test.miz'))) circle = Circle( True, Point(10, 10, m.terrain), "TEST CIRCLE", Rgba(20, 30, 40, 200), ":S", Rgba(50, 60, 70, 150), 10, LineStyle.Solid, 100 ) m.drawings.layers[0].add_drawing(circle) self.assertEqual("TEST CIRCLE", m.drawings.layers[0].objects[1].name) mission_path = 'missions/Draw_tool_test_added_drawings.miz' m.save(mission_path) m2 = dcs.mission.Mission() self.assertEqual(0, len(m2.load_file(mission_path))) self.assert_expected_stuff(m2) self.assertEqual("TEST CIRCLE", m2.drawings.layers[0].objects[1].name)
def generate_strike_target_at(self, category: str, position: Point) -> None: obj_name = namegen.random_objective_name() template = random.choice(list(self.templates[category].values())) object_id = 0 group_id = self.game.next_group_id() # TODO: Create only one TGO per objective, each with multiple units. for unit in template: object_id += 1 template_point = Point(unit["offset"].x, unit["offset"].y) g = BuildingGroundObject( obj_name, category, group_id, object_id, position + template_point, unit["heading"], self.control_point, unit["type"], ) self.control_point.connected_objectives.append(g)
def load_points_from_data(self, points_data) -> List[Point]: points: List[Point] = [] for point_index in sorted(points_data.keys()): x = points_data[point_index]["x"] y = points_data[point_index]["y"] points.append(Point(x, y, self._terrain)) return points
def generate_fob(self) -> None: category = "fob" obj_name = self.control_point.name template = random.choice(list(self.templates[category].values())) point = self.control_point.position # Pick from preset locations object_id = 0 group_id = self.game.next_group_id() # TODO: Create only one TGO per objective, each with multiple units. for unit in template: object_id += 1 template_point = Point(unit["offset"].x, unit["offset"].y) g = BuildingGroundObject( obj_name, category, group_id, object_id, point + template_point, unit["heading"], self.control_point, unit["type"], is_fob_structure=True, ) self.control_point.connected_objectives.append(g)
def _generate_destroyed_units(cls) -> None: """Add destroyed units to the Mission""" for d in cls.game.get_destroyed_units(): try: type_name = d["type"] if not isinstance(type_name, str): raise TypeError( "Expected the type of the destroyed static to be a string" ) utype = db.unit_type_from_name(type_name) except KeyError: continue pos = Point(cast(float, d["x"]), cast(float, d["z"])) if (utype is not None and not cls.game.position_culled(pos) and cls.game.settings.perf_destroyed_units): cls.current_mission.static_group( country=cls.current_mission.country( cls.game.player_country), name="", _type=utype, hidden=True, position=pos, heading=d["orientation"], dead=True, )
def generate_ground_point(self) -> None: try: category = random.choice(self.faction.building_set) except IndexError: logging.exception("Faction has no buildings defined") return obj_name = namegen.random_objective_name() template = random.choice(list(self.templates[category].values())) if category == "oil": location_type = LocationType.OffshoreStrikeTarget else: location_type = LocationType.StrikeTarget # Pick from preset locations point = self.location_finder.location_for(location_type) if point is None: return object_id = 0 group_id = self.game.next_group_id() # TODO: Create only one TGO per objective, each with multiple units. for unit in template: object_id += 1 template_point = Point(unit["offset"].x, unit["offset"].y) g = BuildingGroundObject(obj_name, category, group_id, object_id, point + template_point, unit["heading"], self.control_point, unit["type"]) self.control_point.connected_objectives.append(g)
def generate_fob(self) -> None: try: category = self.faction.building_set[ self.faction.building_set.index('fob')] except IndexError: logging.exception("Faction has no fob buildings defined") return obj_name = self.control_point.name template = random.choice(list(self.templates[category].values())) point = self.control_point.position # Pick from preset locations object_id = 0 group_id = self.game.next_group_id() # TODO: Create only one TGO per objective, each with multiple units. for unit in template: object_id += 1 template_point = Point(unit["offset"].x, unit["offset"].y) g = BuildingGroundObject(obj_name, category, group_id, object_id, point + template_point, unit["heading"], self.control_point, unit["type"], airbase_group=True) self.control_point.connected_objectives.append(g)
def generate(self): # Command Post self.add_unit(AirDefence.SAM_Patriot_STR_AN_MPQ_53, "STR", self.position.x + 30, self.position.y + 30, self.heading) self.add_unit(AirDefence.SAM_Patriot_AMG_AN_MRC_137, "MRC", self.position.x, self.position.y, self.heading) self.add_unit(AirDefence.SAM_Patriot_ECS_AN_MSQ_104, "MSQ", self.position.x + 30, self.position.y, self.heading) self.add_unit(AirDefence.SAM_Patriot_ICC, "ICC", self.position.x + 60, self.position.y, self.heading) self.add_unit(AirDefence.SAM_Patriot_EPP_III, "EPP", self.position.x, self.position.y + 30, self.heading) num_launchers = random.randint(3, 4) positions = self.get_circular_position(num_launchers, launcher_distance=120, coverage=360) for i, position in enumerate(positions): self.add_unit(AirDefence.SAM_Patriot_LN_M901, "LN#" + str(i), position[0], position[1], position[2]) # Short range protection for high value site aa_group = self.add_auxiliary_group("AA") num_launchers = random.randint(3, 4) positions = self.get_circular_position(num_launchers, launcher_distance=200, coverage=360) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group(aa_group, AirDefence.AAA_Vulcan_M163, f"SPAAA#{i}", Point(x, y), heading)
def __init__(self, position: Point=Point(0, 0), zone_radius=200): super(DisembarkFromTransport, self).__init__(self.Id) self.params = { "x": position.x, "y": position.y, "zoneRadius": zone_radius }
def test_poly_random(self): points = [ Point(1, 2), Point(3, 1), Point(7, 2), Point(9, 4), Point(6, 6), Point(6, 9), Point(4, 8), Point(2, 9), Point(1, 7), Point(0, 5)] poly = Polygon(points) for i in range(0, 100): rp = poly.random_point() self.assertTrue(poly.point_in_poly(rp))
def generate(self): self.add_unit( AirDefence.HQ_7_Self_Propelled_STR, "STR", self.position.x, self.position.y, self.heading, ) self.add_unit( AirDefence.HQ_7_Self_Propelled_LN, "LN", self.position.x + 20, self.position.y, self.heading, ) # Triple A for close range defense aa_group = self.add_auxiliary_group("AA") self.add_unit_to_group( aa_group, AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375, "AAA1", self.position + Point(20, 30), self.heading, ) self.add_unit_to_group( aa_group, AirDefence.SPAAA_ZU_23_2_Mounted_Ural_375, "AAA2", self.position - Point(20, 30), self.heading, ) num_launchers = random.randint(0, 3) if num_launchers > 0: positions = self.get_circular_position(num_launchers, launcher_distance=120, coverage=360) for i, position in enumerate(positions): self.add_unit( AirDefence.HQ_7_Self_Propelled_LN, "LN#" + str(i), position[0], position[1], position[2], )
def __init__(self, position: Point=Point(0, 0), duration: int=None): super(Land, self).__init__(self.Id) self.params = { "x": position.x, "y": position.y, "duration": duration if duration else 300, "durationFlag": duration is not None }
def get_default_arrow_points(terrain: Terrain) -> List[Point]: return [ Point(976.01054900139, 0, terrain), Point(976.01054900139, 5205.3895946741, terrain), Point(2602.694797337, 5205.3895946741, terrain), Point(0, 7808.0843920111, terrain), Point(-2602.694797337, 5205.3895946741, terrain), Point(-976.01054900139, 5205.3895946741, terrain), Point(-976.01054900139, 0, terrain), Point(976.01054900139, 0, terrain), ]
def generate_defensive_groups(self) -> None: # AAA for defending against close targets. aa_group = self.add_auxiliary_group("AA") num_launchers = random.randint(6, 8) positions = self.get_circular_position(num_launchers, launcher_distance=210, coverage=360) for i, (x, y, heading) in enumerate(positions): self.add_unit_to_group(aa_group, AirDefence.SPAAA_ZSU_23_4_Shilka, f"AA#{i}", Point(x, y), heading)