dcs_liberation/gen/conflictgen.py
walterroach 967574820f Remove unused conflictgen globals
Remove unused  `Conflict` properties

mypy fixes

Cleanup
2020-11-23 18:14:25 -06:00

200 lines
7.4 KiB
Python

import logging
import random
from typing import Tuple
from dcs.country import Country
from dcs.mapping import Point
from game.theater.conflicttheater import ConflictTheater, FrontLine
from game.theater.controlpoint import ControlPoint
FRONTLINE_LENGTH = 80000
def _opposite_heading(h):
return h+180
def _heading_sum(h, a) -> int:
h += a
if h > 360:
return h - 360
elif h < 0:
return 360 + h
else:
return h
class Conflict:
def __init__(self,
theater: ConflictTheater,
from_cp: ControlPoint,
to_cp: ControlPoint,
attackers_side: str,
defenders_side: str,
attackers_country: Country,
defenders_country: Country,
position: Point,
heading=None,
distance=None,
):
self.attackers_side = attackers_side
self.defenders_side = defenders_side
self.attackers_country = attackers_country
self.defenders_country = defenders_country
self.from_cp = from_cp
self.to_cp = to_cp
self.theater = theater
self.position = position
self.heading = heading
self.distance = distance
self.size = to_cp.size
@property
def center(self) -> Point:
return self.position.point_from_heading(self.heading, self.distance / 2)
@property
def tail(self) -> Point:
return self.position.point_from_heading(self.heading, self.distance)
@property
def is_vector(self) -> bool:
return self.heading is not None
@property
def opposite_heading(self) -> int:
return _heading_sum(self.heading, 180)
def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> Point:
return Conflict._find_ground_position(at, max_distance, heading, self.theater)
@classmethod
def has_frontline_between(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> bool:
return from_cp.has_frontline and to_cp.has_frontline
@staticmethod
def frontline_position(from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int]:
frontline = FrontLine(from_cp, to_cp, theater)
attack_heading = frontline.attack_heading
position = frontline.position
return position, _opposite_heading(attack_heading)
@classmethod
def flight_frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int, int]:
"""Returns the frontline vector without regard for exclusion zones, used in CAS flight plan"""
frontline = cls.frontline_position(from_cp, to_cp, theater)
center_position, heading = frontline
left_position = center_position.point_from_heading(_heading_sum(heading, -90), int(FRONTLINE_LENGTH/2))
right_position = center_position.point_from_heading(_heading_sum(heading, 90), int(FRONTLINE_LENGTH/2))
return left_position, _heading_sum(heading, 90), int(right_position.distance_to_point(left_position))
@classmethod
def frontline_vector(cls, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater) -> Tuple[Point, int, int]:
"""
probe_end_point = initial.point_from_heading(heading, FRONTLINE_LENGTH)
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
intersection = probe.intersection(theater.land_poly)
if isinstance(intersection, geometry.LineString):
intersection = intersection
elif isinstance(intersection, geometry.MultiLineString):
intersection = intersection.geoms[0]
else:
print(intersection)
return None
return Point(*intersection.xy[0]), _heading_sum(heading, 90), intersection.length
"""
frontline = cls.frontline_position(from_cp, to_cp, theater)
center_position, heading = frontline
left_position, right_position = None, None
if not theater.is_on_land(center_position):
pos = cls._find_ground_position(center_position, FRONTLINE_LENGTH, _heading_sum(heading, -90), theater)
if pos:
right_position = pos
center_position = pos
else:
pos = cls._find_ground_position(center_position, FRONTLINE_LENGTH, _heading_sum(heading, +90), theater)
if pos:
left_position = pos
center_position = pos
if left_position is None:
left_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, -90), theater)
if right_position is None:
right_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, 90), theater)
return left_position, _heading_sum(heading, 90), int(right_position.distance_to_point(left_position))
@classmethod
def frontline_cas_conflict(cls, attacker_name: str, defender_name: str, attacker: Country, defender: Country, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
assert cls.has_frontline_between(from_cp, to_cp)
position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater)
return cls(
position=position,
heading=heading,
distance=distance,
theater=theater,
from_cp=from_cp,
to_cp=to_cp,
attackers_side=attacker_name,
defenders_side=defender_name,
attackers_country=attacker,
defenders_country=defender,
)
@classmethod
def _extend_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
pos = initial
for offset in range(0, int(max_distance), 500):
new_pos = initial.point_from_heading(heading, offset)
if theater.is_on_land(new_pos):
pos = new_pos
else:
return pos
return pos
"""
probe_end_point = initial.point_from_heading(heading, max_distance)
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y)])
intersection = probe.intersection(theater.land_poly)
if intersection is geometry.LineString:
return Point(*intersection.xy[1])
elif intersection is geometry.MultiLineString:
return Point(*intersection.geoms[0].xy[1])
return None
"""
@classmethod
def _find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point:
pos = initial
for _ in range(0, int(max_distance), 100):
if theater.is_on_land(pos):
return pos
pos = pos.point_from_heading(heading, 500)
"""
probe_end_point = initial.point_from_heading(heading, max_distance)
probe = geometry.LineString([(initial.x, initial.y), (probe_end_point.x, probe_end_point.y) ])
intersection = probe.intersection(theater.land_poly)
if isinstance(intersection, geometry.LineString):
return Point(*intersection.xy[1])
elif isinstance(intersection, geometry.MultiLineString):
return Point(*intersection.geoms[0].xy[1])
"""
logging.error("Didn't find ground position ({})!".format(initial))
return initial