updates to CAP op

This commit is contained in:
Vasyl Horbachenko 2018-07-18 00:45:55 +03:00
parent 3b454470f9
commit 683114f916
7 changed files with 58 additions and 25 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
__pycache__ __pycache__
build/* build/*
resources/payloads/*.lua resources/payloads/*.lua
venv
logs.txt logs.txt
.DS_Store .DS_Store
# User-specific stuff # User-specific stuff

View File

@ -16,7 +16,7 @@ class FrontlineAttackEvent(Event):
ATTACKER_AMOUNT_FACTOR = 0.4 ATTACKER_AMOUNT_FACTOR = 0.4
ATTACKER_DEFENDER_FACTOR = 0.7 ATTACKER_DEFENDER_FACTOR = 0.7
STRENGTH_INFLUENCE = 0.2 STRENGTH_INFLUENCE = 0.2
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.25 SUCCESS_FACTOR = 1.5
defenders = None # type: db.ArmorDict defenders = None # type: db.ArmorDict
@ -28,16 +28,13 @@ class FrontlineAttackEvent(Event):
return "Frontline attack from {} at {}".format(self.from_cp, self.to_cp) return "Frontline attack from {} at {}".format(self.from_cp, self.to_cp)
def is_successfull(self, debriefing: Debriefing): def is_successfull(self, debriefing: Debriefing):
total_targets = sum(self.defenders.values()) alive_attackers = sum([v for k, v in debriefing.alive_units[self.attacker_name].items() if db.unit_task(k) == PinpointStrike])
destroyed_targets = 0 alive_defenders = sum([v for k, v in debriefing.alive_units[self.defender_name].items() if db.unit_task(k) == PinpointStrike])
for unit, count in debriefing.destroyed_units[self.defender_name].items(): attackers_success = (float(alive_attackers) / alive_defenders) > self.SUCCESS_FACTOR
if unit in self.defenders:
destroyed_targets += count
if self.from_cp.captured: if self.from_cp.captured:
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE return attackers_success
else: else:
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE return not attackers_success
def commit(self, debriefing: Debriefing): def commit(self, debriefing: Debriefing):
super(FrontlineAttackEvent, self).commit(debriefing) super(FrontlineAttackEvent, self).commit(debriefing)

View File

@ -13,7 +13,7 @@ from userdata.debriefing import Debriefing
class FrontlinePatrolEvent(Event): class FrontlinePatrolEvent(Event):
ESCORT_FACTOR = 0.5 ESCORT_FACTOR = 0.5
STRENGTH_INFLUENCE = 0.2 STRENGTH_INFLUENCE = 0.2
SUCCESS_TARGETS_HIT_PERCENTAGE = 0.33 SUCCESS_FACTOR = 0.8
cas = None # type: db.PlaneDict cas = None # type: db.PlaneDict
escort = None # type: db.PlaneDict escort = None # type: db.PlaneDict
@ -25,6 +25,7 @@ class FrontlinePatrolEvent(Event):
def __str__(self): def __str__(self):
return "Frontline CAP from {} at {}".format(self.from_cp, self.to_cp) return "Frontline CAP from {} at {}".format(self.from_cp, self.to_cp)
"""
def is_successfull(self, debriefing: Debriefing): def is_successfull(self, debriefing: Debriefing):
total_targets = sum(self.cas.values()) total_targets = sum(self.cas.values())
destroyed_targets = 0 destroyed_targets = 0
@ -36,6 +37,16 @@ class FrontlinePatrolEvent(Event):
return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE return float(destroyed_targets) / total_targets >= self.SUCCESS_TARGETS_HIT_PERCENTAGE
else: else:
return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE return float(destroyed_targets) / total_targets < self.SUCCESS_TARGETS_HIT_PERCENTAGE
"""
def is_successfull(self, debriefing: Debriefing):
alive_attackers = sum([v for k, v in debriefing.alive_units[self.attacker_name].items() if db.unit_task(k) == PinpointStrike])
alive_defenders = sum([v for k, v in debriefing.alive_units[self.defender_name].items() if db.unit_task(k) == PinpointStrike])
attackers_success = (float(alive_attackers) / alive_defenders) >= self.SUCCESS_FACTOR
if self.from_cp.captured:
return attackers_success
else:
return not attackers_success
def commit(self, debriefing: Debriefing): def commit(self, debriefing: Debriefing):
super(FrontlinePatrolEvent, self).commit(debriefing) super(FrontlinePatrolEvent, self).commit(debriefing)
@ -54,7 +65,7 @@ class FrontlinePatrolEvent(Event):
def skip(self): def skip(self):
pass pass
def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict): def player_attacking(self, interceptors: db.PlaneDict, clients: db.PlaneDict, armor: db.ArmorDict):
self.cas = self.to_cp.base.scramble_cas(self.game.settings.multiplier) self.cas = self.to_cp.base.scramble_cas(self.game.settings.multiplier)
self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR) self.escort = self.to_cp.base.scramble_sweep(self.game.settings.multiplier * self.ESCORT_FACTOR)
@ -65,10 +76,12 @@ class FrontlinePatrolEvent(Event):
defender_clients={}, defender_clients={},
from_cp=self.from_cp, from_cp=self.from_cp,
to_cp=self.to_cp) to_cp=self.to_cp)
defenders = self.to_cp.base.assemble_attack()
op.setup(cas=self.cas, op.setup(cas=self.cas,
escort=self.escort, escort=self.escort,
interceptors=interceptors, interceptors=interceptors,
armor_attackers=self.from_cp.base.assemble_attack(), armor_attackers=db.unitdict_restrict_count(armor, sum(defenders.values())),
armor_defenders=self.to_cp.base.assemble_attack()) armor_defenders=defenders)
self.operation = op self.operation = op

View File

@ -262,11 +262,12 @@ class AircraftConflictGenerator:
client_count=client_count, client_count=client_count,
at=at and at or self._group_point(self.conflict.air_defenders_location)) at=at and at or self._group_point(self.conflict.air_defenders_location))
pos = self.conflict.air_defenders_location.point_from_heading(self.conflict.heading-90, CAP_CAS_DISTANCE) location = self._group_point(self.conflict.air_defenders_location)
waypoint = group.add_waypoint(pos, CAS_ALTITUDE, WARM_START_AIRSPEED) insertion_point = self.conflict.find_insertion_point(location)
waypoint = group.add_waypoint(insertion_point, CAS_ALTITUDE, WARM_START_AIRSPEED)
if self.conflict.is_vector: if self.conflict.is_vector:
destination_tail = self.conflict.tail.distance_to_point(pos) > self.conflict.position.distance_to_point(pos) destination_tail = self.conflict.tail.distance_to_point(insertion_point) > self.conflict.position.distance_to_point(insertion_point)
group.add_waypoint(destination_tail and self.conflict.tail or self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED) group.add_waypoint(destination_tail and self.conflict.tail or self.conflict.position, CAS_ALTITUDE, WARM_START_AIRSPEED)
group.task = CAS.name group.task = CAS.name

View File

@ -20,7 +20,7 @@ AIR_DISTANCE = 40000
CAPTURE_AIR_ATTACKERS_DISTANCE = 25000 CAPTURE_AIR_ATTACKERS_DISTANCE = 25000
CAPTURE_AIR_DEFENDERS_DISTANCE = 60000 CAPTURE_AIR_DEFENDERS_DISTANCE = 60000
CAP_CAS_DISTANCE = 10000 CAP_CAS_DISTANCE = 10000, 120000
GROUND_INTERCEPT_SPREAD = 5000 GROUND_INTERCEPT_SPREAD = 5000
GROUND_DISTANCE_FACTOR = 1 GROUND_DISTANCE_FACTOR = 1
@ -123,6 +123,21 @@ class Conflict:
def to_size(self): def to_size(self):
return self.to_cp.size * GROUND_DISTANCE_FACTOR return self.to_cp.size * GROUND_DISTANCE_FACTOR
def find_insertion_point(self, other_point: Point) -> Point:
dx = self.position.x - self.tail.x
dy = self.position.y - self.tail.y
dr2 = float(dx ** 2 + dy ** 2)
lerp = ((other_point.x - self.tail.x) * dx + (other_point.y - self.tail.y) * dy) / dr2
if lerp < 0:
lerp = 0
elif lerp > 1:
lerp = 1
x = lerp * dx + self.tail.x
y = lerp * dy + self.tail.y
return Point(x, y)
@classmethod @classmethod
def has_frontline_between(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> bool: def has_frontline_between(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> bool:
return from_cp.has_frontline and to_cp.has_frontline return from_cp.has_frontline and to_cp.has_frontline
@ -138,6 +153,7 @@ class Conflict:
center_position, heading = cls.frontline_position(from_cp, to_cp) center_position, heading = cls.frontline_position(from_cp, to_cp)
left_position = center_position left_position = center_position
for offset in range(0, int(FRONTLINE_LENGTH / 2), 1000): for offset in range(0, int(FRONTLINE_LENGTH / 2), 1000):
pos = center_position.point_from_heading(_heading_sum(heading, -90), offset) pos = center_position.point_from_heading(_heading_sum(heading, -90), offset)
if not theater.is_on_land(pos): if not theater.is_on_land(pos):
@ -266,7 +282,7 @@ class Conflict:
position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater) position, heading, distance = cls.frontline_vector(from_cp, to_cp, theater)
attack_position = position.point_from_heading(heading, randint(0, int(distance))) attack_position = position.point_from_heading(heading, randint(0, int(distance)))
attackers_position = attack_position.point_from_heading(heading - 90, AIR_DISTANCE) attackers_position = attack_position.point_from_heading(heading - 90, AIR_DISTANCE)
defenders_position = attack_position.point_from_heading(heading + 90, CAP_CAS_DISTANCE) defenders_position = attack_position.point_from_heading(heading + 90, random.randint(*CAP_CAS_DISTANCE))
return cls( return cls(
position=position, position=position,

View File

@ -18,7 +18,7 @@ from gen import *
WEATHER_CLOUD_BASE = 2000, 3000 WEATHER_CLOUD_BASE = 2000, 3000
WEATHER_CLOUD_DENSITY = 1, 8 WEATHER_CLOUD_DENSITY = 1, 8
WEATHER_CLOUD_THICKNESS = 100, 400 WEATHER_CLOUD_THICKNESS = 100, 400
WEATHER_CLOUD_BASE_MIN = 2400 WEATHER_CLOUD_BASE_MIN = 1600
RANDOM_TIME = { RANDOM_TIME = {
"night": 5, "night": 5,
@ -28,10 +28,10 @@ RANDOM_TIME = {
} }
RANDOM_WEATHER = { RANDOM_WEATHER = {
1: 5, # heavy rain 1: 10, # heavy rain
2: 15, # rain 2: 20, # rain
3: 25, # dynamic 3: 30, # dynamic
4: 35, # clear 4: 40, # clear
5: 100, # random 5: 100, # random
} }
@ -90,8 +90,13 @@ class EnviromentGenerator:
self.mission.weather.wind_at_8000 = Wind(wind_direction, wind_speed * 3) self.mission.weather.wind_at_8000 = Wind(wind_direction, wind_speed * 3)
if self.mission.weather.clouds_density > 0: if self.mission.weather.clouds_density > 0:
# sometimes clouds are randomized way too low and need to be fixed
self.mission.weather.clouds_base = max(self.mission.weather.clouds_base, WEATHER_CLOUD_BASE_MIN) self.mission.weather.clouds_base = max(self.mission.weather.clouds_base, WEATHER_CLOUD_BASE_MIN)
if self.mission.weather.wind_at_ground == 0:
# frontline smokes look silly w/o any wind
self.mission.weather.wind_at_ground = random.randint(1, 2)
def generate(self) -> EnvironmentSettings: def generate(self) -> EnvironmentSettings:
self._gen_random_time() self._gen_random_time()
self._gen_random_weather() self._gen_random_weather()

View File

@ -8,7 +8,7 @@ from game.event import *
UNITTYPES_FOR_EVENTS = { UNITTYPES_FOR_EVENTS = {
FrontlineAttackEvent: [CAS, PinpointStrike], FrontlineAttackEvent: [CAS, PinpointStrike],
FrontlinePatrolEvent: [CAP], FrontlinePatrolEvent: [CAP, PinpointStrike],
InterceptEvent: [CAP], InterceptEvent: [CAP],
InsurgentAttackEvent: [CAS], InsurgentAttackEvent: [CAS],
NavalInterceptEvent: [CAS], NavalInterceptEvent: [CAS],
@ -218,7 +218,7 @@ class EventMenu(Menu):
e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients) e.player_attacking(armor=scrambled_armor, strikegroup=scrambled_aircraft, clients=scrambled_clients)
elif type(self.event) is FrontlinePatrolEvent: elif type(self.event) is FrontlinePatrolEvent:
e = self.event # type: FrontlinePatrolEvent e = self.event # type: FrontlinePatrolEvent
e.player_attacking(interceptors=scrambled_aircraft, clients=scrambled_clients) e.player_attacking(interceptors=scrambled_aircraft, clients=scrambled_clients, armor=scrambled_armor)
elif type(self.event) is NavalInterceptEvent: elif type(self.event) is NavalInterceptEvent:
e = self.event # type: NavalInterceptEvent e = self.event # type: NavalInterceptEvent