base capture operation implementation

This commit is contained in:
Vasiliy Horbachenko 2018-05-29 03:11:42 +03:00
parent f4a3aef2d5
commit 3809ce67fe
20 changed files with 902 additions and 64 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
*.pyc
__pycache__
output.miz
build/*
.DS_Store

11
.idea/dcs_pmcliberation.iml generated Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>

View File

@ -0,0 +1,10 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

4
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" filepath="$PROJECT_DIR$/.idea/dcs_pmcliberation.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

534
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,534 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="0a178182-a894-4b80-88c5-080f98f4887d" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/shop/db.py" beforeDir="false" afterPath="$PROJECT_DIR$/shop/db.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/theater/base.py" beforeDir="false" afterPath="$PROJECT_DIR$/theater/base.py" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="585">
<caret line="39" lean-forward="true" selection-start-line="39" selection-end-line="39" />
<folding>
<element signature="e#24#34#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="mission.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/game/mission.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="141">
<caret line="41" selection-start-line="41" selection-end-line="41" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="game.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/game/game.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="3" selection-start-line="3" selection-end-line="3" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="globals.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/globals.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret column="9" selection-start-column="9" selection-end-column="9" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="conflictgen.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/gen/conflictgen.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="120">
<caret line="8" column="1" selection-start-line="8" selection-start-column="1" selection-end-line="8" selection-end-column="1" />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="controlpoint.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/theater/controlpoint.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="438">
<caret line="41" column="40" selection-start-line="41" selection-start-column="40" selection-end-line="41" selection-end-column="40" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="aircraft.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/gen/aircraft.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="168">
<caret line="49" column="40" selection-start-line="49" selection-start-column="40" selection-end-line="49" selection-end-column="40" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="base.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/theater/base.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="86" column="72" selection-start-line="86" selection-start-column="72" selection-end-line="86" selection-end-column="72" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="db.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/shop/db.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="274">
<caret line="40" column="46" selection-start-line="40" selection-start-column="46" selection-end-line="40" selection-end-column="46" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="caucasus.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/theater/caucasus.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" selection-start-line="15" selection-end-line="15" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindInProjectRecents">
<replaceStrings>
<replace />
</replaceStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/theater/conflicttheater.py" />
<option value="$PROJECT_DIR$/gen/conflictgen.py" />
<option value="$PROJECT_DIR$/game/game.py" />
<option value="$PROJECT_DIR$/theater/controlpoint.py" />
<option value="$PROJECT_DIR$/theater/caucasus.py" />
<option value="$PROJECT_DIR$/globals.py" />
<option value="$PROJECT_DIR$/game/mission.py" />
<option value="$PROJECT_DIR$/shop/db.py" />
<option value="$PROJECT_DIR$/gen/aircraft.py" />
<option value="$PROJECT_DIR$/theater/base.py" />
<option value="$PROJECT_DIR$/__init__.py" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6" fullScreen="true">
<option name="x" value="10" />
<option name="y" value="20" />
<option name="width" value="1260" />
<option name="height" value="760" />
</component>
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="dcs_pmcliberation" type="b2602c69:ProjectViewProjectNode" />
<item name="dcs_pmcliberation" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="dcs_pmcliberation" type="b2602c69:ProjectViewProjectNode" />
<item name="dcs_pmcliberation" type="462c0819:PsiDirectoryNode" />
<item name="game" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="dcs_pmcliberation" type="b2602c69:ProjectViewProjectNode" />
<item name="dcs_pmcliberation" type="462c0819:PsiDirectoryNode" />
<item name="gen" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="dcs_pmcliberation" type="b2602c69:ProjectViewProjectNode" />
<item name="dcs_pmcliberation" type="462c0819:PsiDirectoryNode" />
<item name="shop" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="dcs_pmcliberation" type="b2602c69:ProjectViewProjectNode" />
<item name="dcs_pmcliberation" type="462c0819:PsiDirectoryNode" />
<item name="theater" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="SearchEverywhereHistoryKey" value="contro&#9;FILE&#9;file:///Users/sp/projects/dcs_pmcliberation/theater/controlpoint.py&#10;base&#9;null&#9;null&#10;air&#9;null&#9;null&#10;game&#9;null&#9;null&#10;oppo&#9;null&#9;null&#10;controlpo&#9;null&#9;null&#10;cau&#9;null&#9;null&#10;theater&#9;null&#9;null" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager">
<configuration name="__init__" type="PythonConfigurationType" factoryName="Python" temporary="true">
<module name="dcs_pmcliberation" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/__init__.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.__init__" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="0a178182-a894-4b80-88c5-080f98f4887d" name="Default" comment="" />
<created>1527543981624</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1527543981624</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="0" width="1280" height="800" extended-state="6" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" weight="0.27421874" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Event Log" order="7" side_tool="true" weight="0.328877" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Version Control" order="7" />
<window_info anchor="bottom" id="Python Console" order="7" weight="0.328877" />
<window_info anchor="bottom" id="Run" order="2" weight="0.328877" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Terminal" order="7" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.39973262" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
</layout>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/game/mission.py</url>
<line>41</line>
<option name="timeStamp" value="1" />
</line-breakpoint>
</breakpoints>
<option name="time" value="3" />
</breakpoint-manager>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="22" lean-forward="true" selection-start-line="22" selection-end-line="22" />
<folding>
<element signature="e#24#34#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/globals.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/gen/aircraft.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/conflicttheater.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285">
<caret line="22" column="101" selection-start-line="22" selection-start-column="101" selection-end-line="22" selection-end-column="101" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/controlpoint.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="450">
<caret line="38" selection-start-line="38" selection-end-line="38" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/base.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="120">
<caret line="14" column="11" selection-start-line="14" selection-start-column="11" selection-end-line="14" selection-end-column="11" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/shop/db.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/caucasus.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="6" column="53" selection-start-line="6" selection-start-column="53" selection-end-line="6" selection-end-column="53" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/gen/conflictgen.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="27" lean-forward="true" selection-start-line="27" selection-end-line="27" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="120">
<caret line="12" selection-start-line="12" selection-end-line="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/globals.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/theater/conflicttheater.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="9" lean-forward="true" selection-start-line="9" selection-end-line="9" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/caucasus.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="6" column="4" selection-start-line="6" selection-start-column="4" selection-end-line="6" selection-end-column="4" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file:///usr/local/lib/python3.6/site-packages/dcs/mapping.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="159">
<caret line="65" selection-start-line="65" selection-end-line="65" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/shop/__init__.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/theater/conflicttheater.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330">
<caret line="22" column="101" selection-start-line="22" selection-start-column="101" selection-end-line="22" selection-end-column="101" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/game/side.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file:///usr/local/lib/python3.6/site-packages/dcs/unitgroup.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="241">
<caret line="454" column="6" selection-start-line="454" selection-start-column="6" selection-end-line="454" selection-end-column="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/caucasus.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" selection-start-line="15" selection-end-line="15" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/gen/conflictgen.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="120">
<caret line="8" column="1" selection-start-line="8" selection-start-column="1" selection-end-line="8" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/controlpoint.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="438">
<caret line="41" column="40" selection-start-line="41" selection-start-column="40" selection-end-line="41" selection-end-column="40" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/shop/db.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="274">
<caret line="40" column="46" selection-start-line="40" selection-start-column="46" selection-end-line="40" selection-end-column="46" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/game/mission.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="141">
<caret line="41" selection-start-line="41" selection-end-line="41" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/game/game.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
<caret line="3" selection-start-line="3" selection-end-line="3" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/globals.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<caret column="9" selection-start-column="9" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/gen/aircraft.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="168">
<caret line="49" column="40" selection-start-line="49" selection-start-column="40" selection-end-line="49" selection-end-column="40" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/theater/base.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="86" column="72" selection-start-line="86" selection-start-column="72" selection-end-line="86" selection-end-column="72" />
<folding>
<element signature="e#0#13#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="585">
<caret line="39" lean-forward="true" selection-start-line="39" selection-end-line="39" />
<folding>
<element signature="e#24#34#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@ -5,33 +5,37 @@ import os
import gen
import theater.caucasus
import game.mission
from dcs.planes import *
from dcs.vehicles import *
m = dcs.Mission()
theater = theater.caucasus.CaucasusTheater()
conflict = theater.controlpoints[0].conflict_attack(theater.controlpoints[1], m.country("USA"), m.country("Russia"))
theater.kutaisi.base.aircraft = {
A_10C: 4,
F_15C: 4,
}
"""
conflict = gen.Conflict(
heading=100,
attacker=m.country("USA"),
defender=m.country("Russia"),
point=m.terrain.krymsk().position,
size=10000)
"""
theater.kutaisi.base.armor = {
Armor.MBT_M1A2_Abrams: 4,
}
armor_conflict = gen.ArmorConflictGenerator(m, conflict)
armor_conflict.generate(
attackers={dcs.vehicles.Armor.MBT_M1A2_Abrams: 8},
defenders={dcs.vehicles.Armor.MBT_T_80U: 10})
theater.senaki.base.aircraft = {
MiG_21Bis: 8,
}
aircraft_conflict = gen.AircraftConflictGenerator(m, conflict)
aircraft_conflict.generate_cas({dcs.planes.A_10C: 4})
aircraft_conflict.generate_escort({dcs.planes.F_15C: 4})
aircraft_conflict.generate_interceptors({dcs.planes.Su_27: 6})
theater.senaki.base.armor = {
Armor.MBT_T_55: 6,
}
aa_conflict = gen.AAConflictGenerator(m, conflict)
aa_conflict.generate({dcs.vehicles.AirDefence.AAA_ZU_23_on_Ural_375: 3})
theater.senaki.base.aa = {
AirDefence.AAA_ZU_23_on_Ural_375: 2,
}
m.save("output.miz")
op = game.mission.CaptureOperation.playerless(m, theater.kutaisi, theater.senaki)
op.generate()
m.save("build/output.miz")

View File

@ -1,11 +1,10 @@
import typing
from theater.conflicttheater import *
from theater.controlpoint import *
class Game:
def __init__(self, theater: ConflictTheater):
self.theater = theater
def pass_time(self, time: int):
pass

99
game/mission.py Normal file
View File

@ -0,0 +1,99 @@
import typing
from globals import *
from dcs.mission import *
from dcs.unitgroup import *
from dcs.vehicles import *
from theater.controlpoint import *
from theater.base import *
from gen.armor import *
from gen.aircraft import *
from gen.aaa import *
from gen.conflictgen import *
class Operation:
def __init__(self, mission: Mission, conflict: Conflict):
self.mission = mission
self.conflict = conflict
self.armorgen = ArmorConflictGenerator(self.mission, self.conflict)
self.airgen = AircraftConflictGenerator(self.mission, self.conflict)
self.aagen = AAConflictGenerator(self.mission, self.conflict)
class CaptureOperation(Operation):
def __init__(self,
mission: Mission,
from_cp: ControlPoint,
to_cp: ControlPoint,
cas: typing.Dict[PlaneType, int],
escort: typing.Dict[PlaneType, int],
attack: typing.Dict[Armor, int],
intercept: typing.Dict[PlaneType, int],
defense: typing.Dict[Armor, int],
aa: typing.Dict[AirDefence, int]):
conflict = None
if from_cp.captured:
assert not to_cp.captured
conflict = to_cp.conflict_attack(from_cp, US, THEM)
else:
assert not from_cp.captured
conflict = to_cp.conflict_attack(from_cp, THEM, US)
super(CaptureOperation, self).__init__(mission, conflict)
self.from_cp = from_cp
self.to_cp = to_cp
self.cas = cas
self.escort = escort
self.intercept = intercept
self.attack = attack
self.defense = defense
self.aa = aa
@classmethod
def player_defending(self, from_cp: ControlPoint, to_cp: ControlPoint, interceptors: typing.Dict[PlaneType, int]):
cas = from_cp.base.scramble_cas(to_cp)
escort = from_cp.base.scramble_sweep(to_cp)
attackers = from_cp.base.assemble_cap(to_cp)
return CaptureOperation(from_cp=from_cp,
to_cp=to_cp,
cas=cas,
escort=escort,
attack=attackers,
intercept=interceptors,
defense=to_cp.base.armor,
aa=to_cp.base.aa)
@classmethod
def player_attacking(self, from_cp: ControlPoint, to_cp: ControlPoint, cas: typing.Dict[PlaneType, int], escort: typing.Dict[PlaneType, int], armor: typing.Dict[Armor, int]):
interceptors = to_cp.base.scramble_sweep()
return CaptureOperation(from_cp=from_cp,
to_cp=to_cp,
cas=cas,
escort=escort,
attack=armor,
intercept=interceptors,
defense=to_cp.base.armor,
aa=to_cp.base.aa)
@classmethod
def playerless(self, mission: Mission, from_cp: ControlPoint, to_cp: ControlPoint):
return CaptureOperation(mission=mission,
from_cp=from_cp,
to_cp=to_cp,
cas=from_cp.base.scramble_cas(to_cp),
escort=from_cp.base.scramble_sweep(to_cp),
attack=from_cp.base.assemble_cap(to_cp),
intercept=to_cp.base.scramble_interceptors(0.5),
defense=to_cp.base.assemble_defense(0.5),
aa=to_cp.base.aa)
def generate(self):
self.armorgen.generate(self.attack, self.defense)
self.airgen.generate_cas(self.cas)
self.airgen.generate_escort(self.escort)
self.airgen.generate_interceptors(self.intercept)
self.aagen.generate(self.aa)

View File

@ -1,3 +0,0 @@
import typing
import dcs

View File

@ -72,7 +72,7 @@ class AircraftConflictGenerator:
airport=airport)
self.escort_targets.append(group)
group.add_waypoint(self.conflict.point, CAS_ALTITUDE)
group.add_waypoint(self.conflict.position, CAS_ALTITUDE)
group.task = CAS.name
def generate_escort(self, attackers: typing.Dict[PlaneType, int], airport: Airport = None):
@ -88,7 +88,7 @@ class AircraftConflictGenerator:
group.task = Escort.name
group.load_task_default_loadout(dcs.task.Escort.name)
heading = group.position.heading_between_point(self.conflict.point)
heading = group.position.heading_between_point(self.conflict.position)
position = group.position # type: Point
wayp = group.add_waypoint(position.point_from_heading(heading, 3000), CAS_ALTITUDE)
@ -107,6 +107,6 @@ class AircraftConflictGenerator:
group.task = FighterSweep.name
group.load_task_default_loadout(dcs.task.FighterSweep())
wayp = group.add_waypoint(self.conflict.point, CAS_ALTITUDE)
wayp = group.add_waypoint(self.conflict.position, CAS_ALTITUDE)
wayp.tasks.append(dcs.task.EngageTargets(max_distance=self.conflict.size * INTERCEPT_MAX_DISTANCE_FACTOR))
wayp.tasks.append(dcs.task.OrbitAction())

View File

@ -43,7 +43,7 @@ class ArmorConflictGenerator:
position=self._group_point(at),
group_size=1,
move_formation=PointAction.OffRoad)
wayp = group.add_waypoint(self.conflict.point)
wayp = group.add_waypoint(self.conflict.position)
wayp.tasks = []
def generate(self, attackers: typing.Dict[UnitType, int], defenders: typing.Dict[UnitType, int]):

View File

@ -20,18 +20,15 @@ GROUND_DISTANCE_FACTOR = 2
AIR_DISTANCE_FACTOR = 5
class Conflict:
trigger_zone = None # type: TriggerZone
activation_trigger = None # type: Trigger
def __init__(self, attacker: Country, attack_heading: int, defender: Country, defense_heading: int, point: Point, size: int):
def __init__(self, attacker: Country, attack_heading: int, defender: Country, defense_heading: int, position: Point, size: int):
self.attackers_side = attacker
self.defenders_side = defender
self.point = point
self.position = position
self.size = size
self.ground_attackers_location = self.point.point_from_heading(attack_heading, self.size * GROUND_DISTANCE_FACTOR)
self.ground_defenders_location = self.point.point_from_heading(defense_heading, self.size * GROUND_DISTANCE_FACTOR)
self.ground_attackers_location = self.position.point_from_heading(attack_heading, self.size * GROUND_DISTANCE_FACTOR)
self.ground_defenders_location = self.position.point_from_heading(defense_heading, self.size * GROUND_DISTANCE_FACTOR)
self.air_attackers_location = self.point.point_from_heading(attack_heading, self.size * AIR_DISTANCE_FACTOR)
self.air_defenders_location = self.point.point_from_heading(defense_heading, self.size * AIR_DISTANCE_FACTOR)
self.air_attackers_location = self.position.point_from_heading(attack_heading, self.size * AIR_DISTANCE_FACTOR)
self.air_defenders_location = self.position.point_from_heading(defense_heading, self.size * AIR_DISTANCE_FACTOR)

View File

@ -1,4 +1,5 @@
import dcs
mission = dcs.mission.Mission()
country = mission.country("USA")
MISSION = dcs.mission.Mission()
US = MISSION.country("USA")
THEM = MISSION.country("Russia")

44
shop/db.py Normal file
View File

@ -0,0 +1,44 @@
import typing
import dcs
import globals
from dcs.vehicles import *
from dcs.unitgroup import *
from dcs.planes import *
from dcs.task import *
from dcs.unittype import *
PRICES = {
# planes
Su_25T: 10,
A_10A: 15,
A_10C: 20,
Su_27: 20,
Su_33: 23,
F_15C: 25,
M_2000C: 17,
MiG_15bis: 10,
MiG_21Bis: 13,
# armor
Armor.MBT_T_55: 18,
Armor.MBT_T_80U: 20,
Armor.MBT_T_90: 22,
Armor.MBT_M60A3_Patton: 15,
Armor.MBT_M1A2_Abrams: 20,
Armor.ATGM_M1134_Stryker: 12,
Armor.APC_BTR_80: 10,
}
UNIT_BY_TASK = {
FighterSweep: [Su_27, Su_33, Su_25, F_15C, MiG_15bis, MiG_21Bis, MiG_29A, ],
CAS: [Su_25T, A_10A, A_10C, ],
CAP: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ]
}

View File

@ -1,11 +1,88 @@
import typing
import dcs
import math
from .controlpoint import *
from shop import db
from theater.controlpoint import ControlPoint
from dcs.planes import *
from dcs.vehicles import *
from dcs.task import *
PLANES_IN_GROUP = 2
PLANES_IMPORTANCE_FACTOR = 2
ARMOR_IMPORTANCE_FACTOR = 4
class Base:
aircraft = [] # type: typing.Dict[PlaneType, int]
armor = [] # type: typing.Dict[Armor, int]
aircraft = {} # type: typing.Dict[PlaneType, int]
armor = {} # type: typing.Dict[Armor, int]
aa = {} # type: typing.Dict[AirDefence, int]
def __init__(self):
pass
@property
def total_planes(self) -> int:
return sum(self.aircraft.values())
@property
def total_armor(self) -> int:
return sum(self.armor.values())
def _find_best_unit(self, dict, for_type: Task, count: int) -> typing.Dict:
sorted_planes = [key for key in dict.keys() if key in db.UNIT_BY_TASK[for_type]]
sorted_planes.sort(key=lambda x: db.PRICES[x], reverse=True)
result = {}
for plane in sorted_planes:
existing_count = dict[plane] # type: int
if not existing_count:
continue
result_unit_count = min(count, existing_count)
count -= result_unit_count
result[plane] = result.get(plane, 0) + result_unit_count
return result
def _find_best_planes(self, for_type: Task, count: int) -> typing.Dict[PlaneType, int]:
return self._find_best_unit(self.aircraft, for_type, count)
def _find_best_armor(self, for_type: Task, count: int) -> typing.Dict[PlaneType, int]:
return self._find_best_unit(self.armor, for_type, count)
def _group_sizes(self, total_planes: int) -> typing.List[int]:
total_scrambled = 0
for _ in range(math.ceil(total_planes / PLANES_IN_GROUP)):
total_scrambled += PLANES_IN_GROUP
yield total_scrambled < total_planes and PLANES_IN_GROUP or total_planes - total_scrambled
def _group_sizes_for(self, target: ControlPoint) -> typing.List[int]:
total_planes = target.importance * PLANES_IMPORTANCE_FACTOR
total_scrambled = 0
for _ in range(math.ceil(total_planes / PLANES_IN_GROUP)):
total_scrambled += PLANES_IN_GROUP
yield PLANES_IN_GROUP and total_scrambled < total_planes or total_planes - total_scrambled
def commit_scramble(self, scrambled_aircraft: typing.Dict[PlaneType, int]):
for k, c in scrambled_aircraft:
self.aircraft[k] -= c
assert self.aircraft[k] >= 0
if self.aircraft[k] == 0:
del self.aircraft[k]
def scramble_cas(self, for_target: ControlPoint) -> typing.Dict[PlaneType, int]:
return self._find_best_planes(CAS, int(for_target.importance * PLANES_IMPORTANCE_FACTOR))
def scramble_sweep(self, for_target: ControlPoint) -> typing.Dict[PlaneType, int]:
return self._find_best_planes(FighterSweep, int(for_target.importance * PLANES_IMPORTANCE_FACTOR))
def scramble_interceptors(self, factor: float) -> typing.Dict[PlaneType, int]:
return self._find_best_planes(FighterSweep, int(self.total_planes * factor))
def assemble_cap(self, for_target: ControlPoint) -> typing.Dict[Armor, int]:
return self._find_best_armor(CAP, int(for_target.importance * ARMOR_IMPORTANCE_FACTOR))
def assemble_defense(self, factor: float) -> typing.Dict[Armor, int]:
return self._find_best_armor(CAP, int(self.total_armor * factor))

View File

@ -4,11 +4,20 @@ from .conflicttheater import *
from .base import *
class CaucasusTheater(ConflictTheater):
sukhumi = ControlPoint(caucasus.Sukhumi().position, 1000, 5, True, Base())
krymsk = ControlPoint(caucasus.Krymsk().position, 1500, 10, False, None)
kransnodar = ControlPoint(caucasus.KrasnodarCenter().position, 3000, 30, False, Base())
kutaisi = ControlPoint(caucasus.Kutaisi.position, ALL_RADIALS, SIZE_SMALL, IMPORTANCE_LOW)
senaki = ControlPoint(caucasus.Senaki.position, ALL_RADIALS, SIZE_REGULAR, IMPORTANCE_LOW)
kobuleti = ControlPoint(caucasus.Kobuleti.position, COAST_VERTICAL, SIZE_SMALL, IMPORTANCE_LOW)
batumi = ControlPoint(caucasus.Batumi.position, COAST_VERTICAL, SIZE_REGULAR, IMPORTANCE_MEDIUM)
sukhumi = ControlPoint(caucasus.Sukhumi.position, COAST_VERTICAL, SIZE_REGULAR, IMPORTANCE_MEDIUM)
gudauta = ControlPoint(caucasus.Gudauta.position, COAST_VERTICAL, SIZE_REGULAR, IMPORTANCE_MEDIUM)
sochi = ControlPoint(caucasus.Sochi.position, COAST_VERTICAL, SIZE_BIG, IMPORTANCE_HIGH)
def __init__(self):
self.add_controlpoint(self.sukhumi, [self.krymsk])
self.add_controlpoint(self.krymsk, [self.sukhumi, self.kransnodar])
self.add_controlpoint(self.kransnodar, [self.krymsk])
self.add_controlpoint(self.kutaisi, connected_to=[self.senaki])
self.add_controlpoint(self.senaki, connected_to=[self.kobuleti, self.sukhumi])
self.add_controlpoint(self.kobuleti, connected_to=[self.batumi])
self.add_controlpoint(self.batumi)
self.add_controlpoint(self.sukhumi, connected_to=[self.gudauta])
self.add_controlpoint(self.gudauta, connected_to=[self.sochi])
self.add_controlpoint(self.sochi)

View File

@ -3,10 +3,24 @@ import dcs
from .controlpoint import *
class ConflictTheater:
controlpoints = [] # type: typing.Collection[ControlPoint]
SIZE_SMALL = 600
SIZE_REGULAR = 1000
SIZE_BIG = 2000
SIZE_LARGE = 3000
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint]):
IMPORTANCE_LOW = 1
IMPORTANCE_MEDIUM = 2
IMPORTANCE_HIGH = 3
ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ]
COAST_VERTICAL = [45, 90, 135, ]
COAST_HORIZONTAL = [315, 0, 45, ]
class ConflictTheater:
controlpoints = [] # type: typing.List[ControlPoint]
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
for connected_point in connected_to:
point.connect(to=connected_point)

View File

@ -1,30 +1,54 @@
import typing
import dcs
import math
from dcs.mapping import *
from dcs.country import *
from gen.conflictgen import Conflict
from .base import *
class ControlPoint:
connected_points = [] # type: typing.Collection[ControlPoint]
point = None # type: Point
connected_points = [] # type: typing.List[ControlPoint]
position = None # type: Point
captured = False
base = None # type: Base
strength = 100
base: None # type: theater.base.Base
def __init__(self, point: Point, size: int, importance: int, captured: bool, base: Base):
self.point = point
def __init__(self, point: Point, radials: typing.Collection[int], size: int, importance: int):
import theater.base
self.position = point
self.size = size
self.importance = importance
self.captured = captured
self.base = base
self.captured = False
self.radials = radials
self.base = theater.base.Base()
def connect(self, to):
self.connected_points.append(to)
def conflict_attack(self, x, attacker: Country, defender: Country) -> Conflict:
#heading = heading_between_points(self.point.x, self.point.y, x.point.x, x.point.y)
return Conflict(attacker, 0, defender, 90, self.point, self.size)
def find_radial(self, heading: int):
closest_radial = 0
closest_radial_delta = 360
for radial in self.radials:
delta = math.fabs(radial - heading)
if closest_radial_delta < delta:
closest_radial = radial
closest_radial_delta = delta
return closest_radial
def conflict_attack(self, from_cp, attacker: Country, defender: Country) -> Conflict:
cp = from_cp # type: ControlPoint
attack_radial = self.find_radial(cp.position.heading_between_point(self.position))
defense_radial = self.find_radial(self.position.heading_between_point(cp.position))
return Conflict(attacker=attacker,
attack_heading=attack_radial,
defender=defender,
defense_heading=defense_radial,
position=self.position,
size=self.size)