From d25befabdd6e7670a239f6f98060eab07e092753 Mon Sep 17 00:00:00 2001 From: Magnus Wolffelt Date: Thu, 15 Jul 2021 22:34:09 +0200 Subject: [PATCH] Randomize mission temperature and pressure. --- game/weather.py | 66 +++++++++++++++++++++++++++++++++++++++++-- gen/environmentgen.py | 8 +++++- requirements.txt | 2 +- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/game/weather.py b/game/weather.py index 97c58f97..fae1d5a0 100644 --- a/game/weather.py +++ b/game/weather.py @@ -24,6 +24,14 @@ class TimeOfDay(Enum): Night = "night" +@dataclass(frozen=True) +class AtmosphericConditions: + #: Pressure at sea level in inches of mercury. + qnh_inches_mercury: float + #: Temperature at sea level in Celcius. + temperature_celsius: float + + @dataclass(frozen=True) class WindConditions: at_0m: Wind @@ -64,10 +72,16 @@ class Fog: class Weather: def __init__(self) -> None: + # Future improvement: Use theater, day and time of day + # to get a more realistic conditions + self.atmospheric = self.generate_atmospheric() self.clouds = self.generate_clouds() self.fog = self.generate_fog() self.wind = self.generate_wind() + def generate_atmospheric(self) -> AtmosphericConditions: + raise NotImplementedError + def generate_clouds(self) -> Optional[Clouds]: raise NotImplementedError @@ -105,8 +119,35 @@ class Weather: def random_cloud_thickness() -> int: return random.randint(100, 400) + @staticmethod + def random_pressure(average_pressure: float) -> float: + # "Safe" constants based roughly on ME and viper altimeter. + # Units are inches of mercury. + SAFE_MIN = 28.4 + SAFE_MAX = 30.9 + # Use normalvariate to get normal distribution, more realistic than uniform + pressure = random.normalvariate(average_pressure, 0.2) + return max(SAFE_MIN, min(SAFE_MAX, pressure)) + + @staticmethod + def random_temperature(average_temperature: float) -> float: + # "Safe" constants based roughly on ME. + # Temperatures are in Celcius. + SAFE_MIN = -12 + SAFE_MAX = 49 + # Use normalvariate to get normal distribution, more realistic than uniform + temperature = random.normalvariate(average_temperature, 4) + temperature = round(temperature) + return max(SAFE_MIN, min(SAFE_MAX, temperature)) + class ClearSkies(Weather): + def generate_atmospheric(self) -> AtmosphericConditions: + return AtmosphericConditions( + qnh_inches_mercury=self.random_pressure(29.96), + temperature_celsius=self.random_temperature(22), + ) + def generate_clouds(self) -> Optional[Clouds]: return None @@ -118,6 +159,12 @@ class ClearSkies(Weather): class Cloudy(Weather): + def generate_atmospheric(self) -> AtmosphericConditions: + return AtmosphericConditions( + qnh_inches_mercury=self.random_pressure(29.90), + temperature_celsius=self.random_temperature(20), + ) + def generate_clouds(self) -> Optional[Clouds]: return Clouds.random_preset(rain=False) @@ -130,6 +177,12 @@ class Cloudy(Weather): class Raining(Weather): + def generate_atmospheric(self) -> AtmosphericConditions: + return AtmosphericConditions( + qnh_inches_mercury=self.random_pressure(29.70), + temperature_celsius=self.random_temperature(16), + ) + def generate_clouds(self) -> Optional[Clouds]: return Clouds.random_preset(rain=True) @@ -142,6 +195,12 @@ class Raining(Weather): class Thunderstorm(Weather): + def generate_atmospheric(self) -> AtmosphericConditions: + return AtmosphericConditions( + qnh_inches_mercury=self.random_pressure(29.60), + temperature_celsius=self.random_temperature(15), + ) + def generate_clouds(self) -> Optional[Clouds]: return Clouds( base=self.random_cloud_base(), @@ -168,11 +227,12 @@ class Conditions: time_of_day: TimeOfDay, settings: Settings, ) -> Conditions: + _start_time = cls.generate_start_time( + theater, day, time_of_day, settings.night_disabled + ) return cls( time_of_day=time_of_day, - start_time=cls.generate_start_time( - theater, day, time_of_day, settings.night_disabled - ), + start_time=_start_time, weather=cls.generate_weather(), ) diff --git a/gen/environmentgen.py b/gen/environmentgen.py index cd4d09ff..a431abe9 100644 --- a/gen/environmentgen.py +++ b/gen/environmentgen.py @@ -2,7 +2,7 @@ from typing import Optional from dcs.mission import Mission -from game.weather import Clouds, Fog, Conditions, WindConditions +from game.weather import Clouds, Fog, Conditions, WindConditions, AtmosphericConditions class EnvironmentGenerator: @@ -10,6 +10,11 @@ class EnvironmentGenerator: self.mission = mission self.conditions = conditions + def set_atmospheric(self, atmospheric: AtmosphericConditions) -> None: + inch_to_mm = 25.400002776728 + self.mission.weather.qnh = atmospheric.qnh_inches_mercury * inch_to_mm + self.mission.weather.season_temperature = atmospheric.temperature_celsius + def set_clouds(self, clouds: Optional[Clouds]) -> None: if clouds is None: return @@ -32,6 +37,7 @@ class EnvironmentGenerator: def generate(self) -> None: self.mission.start_time = self.conditions.start_time + self.set_atmospheric(self.conditions.weather.atmospheric) self.set_clouds(self.conditions.weather.clouds) self.set_fog(self.conditions.weather.fog) self.set_wind(self.conditions.weather.wind) diff --git a/requirements.txt b/requirements.txt index fe4a96f7..54073289 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,7 @@ pathspec==0.8.1 pefile==2019.4.18 Pillow==8.2.0 pre-commit==2.10.1 --e git://github.com/pydcs/dcs@1fa15385d2f8300a125155c8ac307d5c37e70152#egg=pydcs +-e git://github.com/pydcs/dcs@2baba37e32bc55fed59ef977c43dad275c9821eb#egg=pydcs pyinstaller==4.3 pyinstaller-hooks-contrib==2021.1 pyparsing==2.4.7