From 24f268b58d81d023459e07babbea84b528782b0e Mon Sep 17 00:00:00 2001 From: floriandelrieu Date: Mon, 20 Mar 2023 00:25:58 +0100 Subject: [PATCH] reload W40K folder from main --- .idea/HOI4_Calculator.iml | 0 .idea/csv-plugin.xml | 0 .idea/misc.xml | 0 CSVs/SaveCompanies.csv | 24 +- CSVs/SaveUnit.csv | 20 +- CSVs/SaveWeapons.csv | 14 +- CSVs/Saver.py | 12 +- Class/Battle.py | 142 ++++++---- Class/Company.py | 53 +++- Class/Leader.py | 7 + Class/Regiment.py | 51 +++- Class/Tactics.py | 4 +- Class/Terrain.py | 22 ++ Class/Unit.py | 54 ++-- Class/Weapons.py | 32 ++- Functions/Company_bonuses.py | 7 + Functions/Functions.py | 21 +- Functions/Leader_func.py | 21 ++ Functions/Stats_Functions.py | 185 +++++++------ Functions/Tactics_func.py | 90 ++++--- Functions/Terrain_func.py | 9 + Functions/Units_bonuses.py | 77 +++++- Functions/Upgrades_bonuses.py | 12 +- Functions/Weapons_bonuses.py | 245 +++++++++--------- Lists/Companies_list.py | 56 +++- Lists/Tactics_list.py | 15 +- Lists/Terrain_list.py | 12 + Lists/Unit_list.py | 42 +-- Run.py | 17 +- ...ther Division Calculator for HOI4 1.3.xlsx | Bin 30 files changed, 805 insertions(+), 439 deletions(-) mode change 100755 => 100644 .idea/HOI4_Calculator.iml mode change 100755 => 100644 .idea/csv-plugin.xml mode change 100755 => 100644 .idea/misc.xml create mode 100644 Class/Leader.py create mode 100644 Class/Terrain.py create mode 100644 Functions/Company_bonuses.py create mode 100644 Functions/Leader_func.py create mode 100644 Functions/Terrain_func.py create mode 100644 Lists/Terrain_list.py mode change 100755 => 100644 Yet Another Division Calculator for HOI4 1.3.xlsx diff --git a/.idea/HOI4_Calculator.iml b/.idea/HOI4_Calculator.iml old mode 100755 new mode 100644 diff --git a/.idea/csv-plugin.xml b/.idea/csv-plugin.xml old mode 100755 new mode 100644 diff --git a/.idea/misc.xml b/.idea/misc.xml old mode 100755 new mode 100644 diff --git a/CSVs/SaveCompanies.csv b/CSVs/SaveCompanies.csv index dac31f3..ab21dba 100644 --- a/CSVs/SaveCompanies.csv +++ b/CSVs/SaveCompanies.csv @@ -1,12 +1,12 @@ -Companies,Guardsmens_100A,Guardsmens_100B,Guardsmens_100C,Spaces_100A,Spaces_100B,Basilisk_40A -HP,25.0,25.0,25.0,38.0,38.0,30.0 -ORG,70,70,70,108.0,108.0,10 -SoftAttack,15.0,15.0,19.85,30.17,30.17,44.4 -HardAttack,0.0,1.0,2.4,7.28,7.28,12.8 -SoftMeleeAttack,1.0,1.0,9.0,1.0,13.87,1.2 -HardMeleeAttack,0.0,2.0,2.0,2.86,4.29,0.4 -Defense,20.0,20.0,20.1,20.05,20.05,0.0 -Breakthrought,2.0,2.0,2.0,2.0,2.0,0.0 -Armor,0,0,0,2,2,5.33 -Piercing,4.67,6.0,6.29,6.39,6.71,0.32 -Hardness,0,0,0,0.1,0.1,0.45 +Companies,Guardsmens_100A,Guardsmens_100B,Guardsmens_100C,Spaces_Tactical,Spaces_Devastator,Spaces_Assault,Basilisk_15A,Predator_9A,Earthshaker_Company +HP,25.0,25.0,25.0,38.0,38.0,38.0,11.25,6.75,6.0 +ORG,70,70,70,108.0,108.0,108.0,10,10,10 +SoftAttack,4.0,4.0,4.37,6.82,9.72,3.0,50.85,11.84,1.56 +HardAttack,0.0,0.0,0.43,2.9,5.0,0.29,1.65,4.25,1.2 +SoftMeleeAttack,1.0,1.0,9.0,13.87,7.44,15.59,0.0,0.0,0.0 +HardMeleeAttack,0.0,2.0,0.8,4.29,3.58,5.0,0.0,0.0,0.0 +Defense,23.0,23.0,23.92,20.7,22.0,22.0,0.0,0.0,0.0 +Breakthrought,2.3,2.3,2.19,2.32,2.19,3.25,0.0,0.0,0.0 +Armor,0,0,0,2,2,2,5.33,11.33,0 +Piercing,3.73,5.3,5.23,6.15,6.09,6.27,9.0,11.0,7.8 +Hardness,0,0,0,0.1,0.1,0.1,0.33,0.9,0 diff --git a/CSVs/SaveUnit.csv b/CSVs/SaveUnit.csv index c794f39..0a943ad 100644 --- a/CSVs/SaveUnit.csv +++ b/CSVs/SaveUnit.csv @@ -1,12 +1,12 @@ -Units,Gardes,SpaceMarines,LemanRuss_A,Predator_A,Basilisk,Field_Earthshaker +Units,Gardes,SpaceMarines,LemanRuss_A,Predator_A,Basilisk,Earthshaker_Platform HP,0.25,0.38,0.75,0.75,0.75,0.5 ORG,70,108.0,10,10,10,10 -SoftAttack,0.0,0.0,1.45,1.28,1.11,0.94 -HardAttack,0.0,0.0,0.24,0.27,0.32,0.3 -SoftMeleeAttack,0.01,0.01,0.05,0.03,0.03,0.03 -HardMeleeAttack,0.0,0.0,0.02,0.01,0.01,0.01 -Defense,0.2,0.2,0.02,0.02,0.0,0.0 -Breakthrought,0.02,0.02,0.0,0.0,0.0,0.0 -Armor,0,2,12.0,11.33,5.33,10.0 -Piercing,0,0,12,11,13,13 -Hardness,0,0.1,0.95,0.9,0.45,0.9 +SoftAttack,0.0,0.0,1.34,0.92,3.39,0.13 +HardAttack,0.0,0.0,0.84,0.33,0.11,0.1 +SoftMeleeAttack,0.01,0.01,0.0,0.0,0.0,0.0 +HardMeleeAttack,0.0,0.0,0.0,0.0,0.0,0.0 +Defense,0.23,0.2,0.6,0.33,0.33,0.33 +Breakthrought,0.02,0.02,4.0,2.0,0.2,2.0 +Armor,0,2,12.0,11.33,5.33,0 +Piercing,0.0,0.0,15.0,11,9.0,7.8 +Hardness,0,0.1,0.95,0.9,0.33,0 diff --git a/CSVs/SaveWeapons.csv b/CSVs/SaveWeapons.csv index 4719765..e3300f3 100644 --- a/CSVs/SaveWeapons.csv +++ b/CSVs/SaveWeapons.csv @@ -1,7 +1,7 @@ -Weapons,Lasgun,Bolter,MeltaGun,PlasmaGun,KrakGrenades,FragGrenades,BolterLD,CanonLaser,Earthshaker,Obusier,Autocanon,Astartes_CCW,Bayonet -SoftAttack,0.12,0.15,0.15,0.31,0.0,0.03,0.51,0.4,0.94,0.61,0.44,0.0,0.0 -HardAttack,0.0,0.01,0.25,0.14,0.01,0.0,0.07,0.72,0.3,0.12,0.15,0.0,0.0 -SoftMeleeAttack,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.09,0.08 -HardMeleeAttack,0.0,0.0,0.0,0.0,0.02,0.0,0.0,0.0,0.0,0.0,0.0,0.01,0.0 -Defense,0.0,0.0,0.0,0.0,0.0,0.0,0.01,0.0,0.0,0.0,0.0,0.0,0.0 -Breakthrought,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +Weapons,Lasgun,Bolter,BoltPistol,MeltaGun,PlasmaGun,PlasmaPistol,KrakGrenades,FragGrenades,BolterLD,CanonLaser,Earthshaker,Obusier,Autocanon,Astartes_CCW,Bayonet,MeltaBomb +SoftAttack,0.03,0.03,0.01,0.03,0.07,0.02,0.0,0.01,0.12,0.09,0.13,0.08,0.11,0.0,0.0,0.0 +HardAttack,0.0,0.01,0.0,0.08,0.05,0.02,0.0,0.0,0.03,0.27,0.1,0.04,0.06,0.0,0.0,0.0 +SoftMeleeAttack,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.09,0.08,0.12 +HardMeleeAttack,0.0,0.0,0.0,0.0,0.0,0.0,0.02,0.0,0.0,0.0,0.0,0.0,0.0,0.01,0.0,0.05 +Defense,1.0,1.0,1.0,1.0,1.0,1.0,0,0,1.5,1.5,1.0,1.0,1.5,0,0,1.0 +Breakthrought,1.0,1.0,1.0,1.5,1.0,1.0,0,0.15,0.9,0.9,1.0,1.0,0.9,0,0,1.0 diff --git a/CSVs/Saver.py b/CSVs/Saver.py index ac164a2..3dad856 100644 --- a/CSVs/Saver.py +++ b/CSVs/Saver.py @@ -43,8 +43,8 @@ DICO_3A["Units"] = fisrt_column_A for key, cur in DICO_2A.items(): assert type(cur) == Infantry or Tank or Walker - cur_list = [cur.HP, cur.org, cur.SoftAttack, cur.HardAttack, cur.SoftMeleeAttack, cur.HardMeleeAttack, cur.Defense, - cur.Breakthrought, cur.Armor, cur.Piercing, cur.Hardness] + cur_list = [cur.HP,cur.ORG,cur.SoftAttack,cur.HardAttack,cur.SoftMeleeAttack,cur.HardMeleeAttack,cur.Defense, + cur.Breakthrought,cur.Armor,cur.Piercing,cur.Hardness] round_Stats(cur) DICO_3A[key] = cur_list @@ -54,8 +54,8 @@ DICO_3B["Weapons"] = fisrt_column_B for key,cur in DICO_2B.items(): assert type(cur) == Weapon - cur_list = [cur.SoftAttack,cur.HardAttack,cur.SoftMeleeAttack,cur.HardMeleeAttack,cur.Defense, - cur.Breakthrought] + cur_list = [cur.SoftAttack,cur.HardAttack,cur.SoftMeleeAttack,cur.HardMeleeAttack,cur.Defense_bonus, + cur.Breakthrought_bonus] round_Stats(cur) DICO_3B[key] = cur_list @@ -65,8 +65,8 @@ DICO_3C["Companies"] = fisrt_column_C for key,cur in DICO_2C.items(): assert type(cur) == Company - cur_list = [cur.HP, cur.org, cur.SoftAttack, cur.HardAttack, cur.SoftMeleeAttack, cur.HardMeleeAttack, cur.Defense, - cur.Breakthrought, cur.Armor, cur.Piercing, cur.Hardness] + cur_list = [cur.HP,cur.ORG,cur.SoftAttack,cur.HardAttack,cur.SoftMeleeAttack,cur.HardMeleeAttack,cur.Defense, + cur.Breakthrought,cur.Armor,cur.Piercing,cur.Hardness] round_Stats(cur) DICO_3C[key] = cur_list diff --git a/Class/Battle.py b/Class/Battle.py index bde4516..78218ca 100644 --- a/Class/Battle.py +++ b/Class/Battle.py @@ -1,31 +1,49 @@ -from W40K.Functions.Functions import round_Stats from W40K.Class.Regiment import Regiment +from W40K.Class.Leader import Leader + from W40K.Functions.Tactics_func import * +from W40K.Functions.Functions import round_Stats +from W40K.Functions.Terrain_func import apply_Terrain +from W40K.Functions.Leader_func import set_LeaderSkills, apply_LeaderTactic + +from W40K.Lists.Terrain_list import Terrain_dico +from W40K.Lists.Tactics_list import ATK_all_tactics,DEF_all_tactics from MyPack.Utilities import AskUser class Battle: """ Objet contenant les divisions permettant de lancer les round et les logs """ - def __init__(self, ATK, DEF): + def __init__(self, + ATK, DEF, ATK_leader=Leader(1,1,1,[],[]), DEF_leader=Leader(1,1,1,[],[]), + Terrain="Plains", River = None + ): # Initials conditions assert type(ATK) == Regiment and type(DEF) == Regiment , "campA and campB must be regiment class" - assert ATK.is_defending == False , "ATK.isDefending must be FALSE" - assert DEF.is_defending == True , "DEF.isDefending must be TRUE" - # ATK team - self.ATK = ATK - self.ATK_Tactic = None - self.ATK_Leader = None - # DEF Team - self.DEF = DEF - self.DEF_Tactic = None - self.DEF_Leader = None + assert ATK.isDefending == False , "ATK.isDefending must be FALSE" + assert DEF.isDefending == True , "DEF.isDefending must be TRUE" + self.ATK = { + "Regiment": ATK, + "Leader": ATK_leader, + "Tactics": ATK_all_tactics.copy() + } + self.ATK_Tactic_chosen = None + self.DEF = { + "Regiment":DEF, + "Leader":DEF_leader, + "Tactics":DEF_all_tactics.copy() + } + self.DEF_Tactic_chosen = None # Battle parameters self.roundCounter = 0 self.CAC_level = 0 self.CAC_limit = 0 - self.Phase = "Default" # Phase de bataille en cours - self.Terrain = "Plain" + self.Current_Phase = "Default" # Phase de bataille en cours + self.Following_Phase = "Default" + self.Terrain = Terrain_dico[Terrain] + self.River = River + self.Initiative_winner = None + def isFinnish(self): """ Check si le combat est terminé @@ -33,16 +51,37 @@ def isFinnish(self): :return: True ou False """ return ( - (self.ATK.HP <= 0) - or (self.DEF.HP <= 0) - or (self.ATK.org <= 0) - or (self.DEF.org <= 0) + (self.ATK["Regiment"].HP <= 0) + or (self.DEF["Regiment"].HP <= 0) + or (self.ATK["Regiment"].ORG <= 0) + or (self.DEF["Regiment"].ORG <= 0) ) + + def _init_round(self): + self.Terrain.set_River(self.River) + set_LeaderSkills(self) + apply_LeaderTactic(self) + apply_Terrain(self) + update_CAC(self) + self.apply_river() + + def apply_river(self): + """ + TODO - Move function to Terrain_func + :return: + """ + if self.River is None: + for side in [self.ATK,self.DEF]: + for tactic in side["Tactics"]: + if "Bridge" in tactic.Name: + tactic.weight = 0 + def Round(self,Nb:int()=1,LogLevel=True): """ - Definit le nombre de lancement de round - run _Round :param Nb: Nombre de round souhaité (-1 si jusqu'a fin du combat) + :param LogLevel: """ if Nb != -1: i = 1 @@ -51,69 +90,76 @@ def Round(self,Nb:int()=1,LogLevel=True): i += 1 else: # Lancement des rounds jusqu'a fin du combat while not self.isFinnish(): - self._Round(Loglevel=LogLevel,PauseEachRound=True) + self._Round(Loglevel=LogLevel,PauseEachRound=False) + def _Round(self,Loglevel,PauseEachRound=False): + ATK_regiment = self.ATK["Regiment"] + DEF_regiment = self.DEF["Regiment"] """ Lancement d'une round ATTAQUE et RIPOSTE (1h de combat dans HOI IV) """ txt = """----------- round {} -----------------""".format(self.roundCounter) + self._init_round() if self.roundCounter%12 == 0: previous_CAC_limit = self.CAC_limit + self.Current_Phase = self.Following_Phase choose_Tactics(self) if Loglevel: - txt += "\nNew tactics / Battle phase: {}".format(self.Phase) - txt += "\n- {} choose {} tactic".format(self.ATK.name, self.ATK_Tactic) - txt += "\n- {} choose {} tactic".format(self.DEF.name, self.DEF_Tactic) + txt += "\nNew tactics / Battle phase: {}".format(self.Current_Phase) + txt += "\n- {} choose {} tactic".format(ATK_regiment.Name, self.ATK_Tactic_chosen) + txt += "\n- {} choose {} tactic".format(DEF_regiment.Name, self.DEF_Tactic_chosen) txt += "\n" txt += "\nOld CAC limit = {}".format(previous_CAC_limit) - update_CAC(self) if self.roundCounter%12 == 0 and Loglevel: - txt += "\n- Cac changes by ATK = {}".format(self.ATK_Tactic.CAC) - txt += "\n- Cac changes by DEF = {}".format(self.DEF_Tactic.CAC) + txt += "\n- Cac changes by ATK = {}".format(self.ATK_Tactic_chosen.CAC) + txt += "\n- Cac changes by DEF = {}".format(self.DEF_Tactic_chosen.CAC) txt += "\nNew CAC limit = {}".format(self.CAC_limit) txt += "\nNew cac_level = {}".format(self.CAC_level) txt += "\n" # Stats arrondis - round_Stats(self.ATK) - round_Stats(self.DEF) + round_Stats(ATK_regiment) + round_Stats(DEF_regiment) round_Stats(self) # ATK Round - self.ATK.do_attack(self.DEF, self.CAC_level) # ATK attaque + ATK_regiment.Attaque(DEF_regiment,self.CAC_level) # ATK attaque if Loglevel: - txt += "\n{} round".format(self.ATK.name) - txt += "\n - Shots: {} SA + {} HA = {}".format(self.ATK.SoftAttack,self.ATK.HardAttack, - self.ATK.SoftAttack+self.ATK.HardAttack) - txt += "\n - Melee: {} SMA + {} HMA = {}".format(round(self.ATK.SoftMeleeAttack*self.CAC_level,2), - round(self.ATK.HardMeleeAttack*self.CAC_level,2), - round(self.ATK.SoftMeleeAttack*self.CAC_level,2)+round(self.ATK.SoftMeleeAttack*self.CAC_level,2)) + txt += "\n{} round".format(ATK_regiment.Name) + txt += "\n - Shots: {} SA + {} HA = {}".format(ATK_regiment.SoftAttack,ATK_regiment.HardAttack, + ATK_regiment.SoftAttack+ATK_regiment.HardAttack) + txt += "\n - Melee: {} SMA + {} HMA = {}".format(round(ATK_regiment.SoftMeleeAttack*self.CAC_level,2), + round(ATK_regiment.HardMeleeAttack*self.CAC_level,2), + round(ATK_regiment.SoftMeleeAttack*self.CAC_level,2)+round(ATK_regiment.SoftMeleeAttack*self.CAC_level,2)) # DEF Round - self.DEF.do_attack(self.DEF, self.CAC_level) # DEF riposte + DEF_regiment.Attaque(DEF_regiment,self.CAC_level) # DEF riposte if Loglevel: - txt += "\n{} round".format(self.DEF.name) - txt += "\n - Shots: {} SA + {} HA = {}".format(self.DEF.SoftAttack, self.DEF.HardAttack, - self.DEF.SoftAttack + self.DEF.HardAttack) - txt += "\n - Melee: {} SMA + {} HMA = {}".format(round(self.DEF.SoftMeleeAttack*self.CAC_level, 2), - round(self.DEF.HardMeleeAttack*self.CAC_level, 2), - round(self.DEF.SoftMeleeAttack*self.CAC_level, 2) + round( - self.DEF.SoftMeleeAttack*self.CAC_level, 2)) - self.DEF.take_damage(self.ATK) # DEF prend les dommages - if Loglevel: txt+= "\n{} takes {} hits (-{} defenses)".format(self.DEF.name, self.ATK.nbr_attack, self.DEF.Defense) - self.ATK.take_damage(self.DEF) # ATK prend les dommages - if Loglevel: txt+= "\n{} takes {} hits (-{} breakthrought)".format(self.ATK.name, self.DEF.nbr_attack, self.ATK.Breakthrought) + txt += "\n{} round".format(DEF_regiment.Name) + txt += "\n - Shots: {} SA + {} HA = {}".format(DEF_regiment.SoftAttack, DEF_regiment.HardAttack, + DEF_regiment.SoftAttack + DEF_regiment.HardAttack) + txt += "\n - Melee: {} SMA + {} HMA = {}".format(round(DEF_regiment.SoftMeleeAttack*self.CAC_level, 2), + round(DEF_regiment.HardMeleeAttack*self.CAC_level, 2), + round(DEF_regiment.SoftMeleeAttack*self.CAC_level, 2) + round( + DEF_regiment.SoftMeleeAttack*self.CAC_level, 2)) + DEF_regiment.Damage(ATK_regiment) # DEF prend les dommages + if Loglevel: txt+= "\n{} takes {} hits (-{} defenses)".format(DEF_regiment.Name,ATK_regiment.NbATK,DEF_regiment.Defense) + ATK_regiment.Damage(DEF_regiment) # ATK prend les dommages + if Loglevel: txt+= "\n{} takes {} hits (-{} breakthrought)".format(ATK_regiment.Name,DEF_regiment.NbATK,ATK_regiment.Breakthrought) print(txt) # Log de fin de round self.roundCounter += 1 self.printLOG() if PauseEachRound: AskUser("pausing ...","Click Enter") + def printLOG(self): """ log pour chaque heure de combats """ + ATK_regiment = self.ATK["Regiment"] + DEF_regiment = self.DEF["Regiment"] txt= """{}: {}/{} {}/{} {}: {}/{} {}/{} -""".format(self.ATK.name, self.ATK.HP, self.ATK._Regiment__HP, self.ATK.org, self.ATK._Regiment__ORG, - self.DEF.name, self.DEF.HP, self.DEF._Regiment__HP, self.DEF.org, self.DEF._Regiment__ORG) +""".format(ATK_regiment.Name,ATK_regiment.HP,ATK_regiment._Regiment__HP,ATK_regiment.ORG,ATK_regiment._Regiment__ORG, + DEF_regiment.Name,DEF_regiment.HP,DEF_regiment._Regiment__HP,DEF_regiment.ORG,DEF_regiment._Regiment__ORG) if self.isFinnish(): txt += """ ----------- End of Battle ----------------- diff --git a/Class/Company.py b/Class/Company.py index e11a0d3..4b14ae4 100644 --- a/Class/Company.py +++ b/Class/Company.py @@ -1,19 +1,20 @@ from MyPack2.Utilities import * from W40K.Functions.Functions import * -#from W40K.Functions.Stats_Functions import bonus_CC,bonus_CT from W40K.Functions.Upgrades_bonuses import setUpgradeBonus +from W40K.Functions.Company_bonuses import apply_SpecialRules class Company: - def __init__(self,Unit=None,Equipement=None): + def __init__(self,Unit=None,Equipement=None,Upgrade=None): self.Unit = Unit self.Class = "Company" self.Type = "" self.Equipement = [] if Equipement is None else Equipement - self.Upgrade = [] + self.Upgrade = [] if Upgrade is None else Upgrade self.Manpower = float() self.Quantity_Equipement = float() self.BRK_bonus = 1 self.DEF_bonus = 1 + self.SpecialRules = self.Unit.SpecialRules # HOI Stats self.HP = float() self.ORG = float() @@ -29,15 +30,19 @@ def __init__(self,Unit=None,Equipement=None): self.Width = float() self.HOI4_Profil() def HOI4_Profil(self): + """ + FIXME + - Pourquoi self.Piercing est divisé par la quantité d'équipement ??? -- A VERIFIER + """ if self.Unit is not None: # TYPE - self.Type = self.Unit.Class + self.Type = self.Unit.Type # MANPOWER & EQUIPEMENT self.Manpower = self.Unit.Quantity self.Quantity_Equipement = np.sum([el.Quantity for el in self.Equipement]) # HEALTH self.HP = self.Unit.HP - self.ORG = self.Unit.org + self.ORG = self.Unit.ORG # ATTACK self.SoftAttack = (self.Unit.SoftAttack + np.sum([el.SoftAttack for el in self.Equipement]))\ *self.Unit.bonus_CT @@ -47,29 +52,61 @@ def HOI4_Profil(self): + self.Unit.SoftMeleeAttack self.HardMeleeAttack = np.sum([el.HardMeleeAttack for el in self.Equipement])*self.Unit.bonus_CC\ + self.Unit.HardMeleeAttack - self.Piercing = (self.Unit.Piercing + np.sum([el.Quantity*el.Piercing for el in self.Equipement]))\ + self.Piercing = (self.Manpower*self.Unit.Piercing + np.sum([el.Quantity*el.Piercing for el in self.Equipement]))\ /(self.Quantity_Equipement+self.Manpower) # DEFENSE - self.Defense = self.Unit.Defense + np.sum([el.Defense for el in self.Equipement]) - self.Breakthrought = self.Unit.Breakthrought + np.sum([el.Breakthrought for el in self.Equipement]) + self.set_Defense_bonuses() + self.set_Breakthrought_bonuses() + self.Defense = self.Unit.Defense + self.Breakthrought = self.Unit.Breakthrought self.Hardness = self.Unit.Hardness self.Armor = self.Unit.Armor + self.Bonus() # End round_Stats(self) + + def Bonus(self): + setUpgradeBonus(self) + apply_SpecialRules(self) + + def set_Defense_bonuses(self): + MANPOWER = self.Manpower + DEF_bonus = 1 if self.Type == "Vehicule" else 0 + for weapon in self.Equipement: + current_DEF_bonus = weapon.Defense_bonus + current_equip_ratio = weapon.Quantity / MANPOWER + current_DEF_bonus *= current_equip_ratio + DEF_bonus += current_DEF_bonus + self.Unit.Defense *= DEF_bonus + + def set_Breakthrought_bonuses(self): + MANPOWER = self.Manpower + BRK_bonus = 1 if self.Type == "Vehicule" else 0 + for weapon in self.Equipement: + current_BRK_bonus = weapon.Breakthrought_bonus + current_equip_ratio = weapon.Quantity / MANPOWER + current_BRK_bonus *= current_equip_ratio + BRK_bonus += current_BRK_bonus + self.Unit.Breakthrought *= BRK_bonus + def setUnit(self,Unit): self.Unit = Unit self.HOI4_Profil() + def setEquipement(self,List:list): self.Equipement = List self.HOI4_Profil() + def setUpgrade(self,List:list): self.Upgrade = List setUpgradeBonus(self) + def setWidth(self): if self.Type == "Infantry": self.Width = 2 elif self.Type == "Tank": self.Width = 2 elif self.Type == "Artillery": self.Width = 3 else: self.Width = 0 + def Show_HOI_Stats(self): self.HOI4_Profil() txt = """ diff --git a/Class/Leader.py b/Class/Leader.py new file mode 100644 index 0000000..15fbaf9 --- /dev/null +++ b/Class/Leader.py @@ -0,0 +1,7 @@ +class Leader: + def __init__(self,Level:int(1),Attack_skill:int(1),Defense_skill:int(1),Prefered_Tactics:list,Traits:list): + self.Level = Level + self.Attack_skill = Attack_skill + self.Defense_skill = Defense_skill + self.Traits_list = Traits + self.Prefered_Tactics = Prefered_Tactics \ No newline at end of file diff --git a/Class/Regiment.py b/Class/Regiment.py index 0d6a853..c7e009a 100644 --- a/Class/Regiment.py +++ b/Class/Regiment.py @@ -1,9 +1,10 @@ import numpy as np from MyPack2.Utilities import truncDecimal from W40K.Functions.Functions import round_Stats +from W40K.Functions.Leader_func import set_LeaderSkills class Regiment: - def __init__(self,CompagnieList=[],Name=""): + def __init__(self,CompagnieList=[],XP=0,Entrenchment_level=0,Name=""): self.Companies = CompagnieList self.Name = Name # Stats when stregth == 1 @@ -19,6 +20,8 @@ def __init__(self,CompagnieList=[],Name=""): self.Piercing = float() self.Hardness = float() # Current Stats + self.Experience = XP + self.Entrenchment = Entrenchment_level self.Strength = 1 self.SoftAttack = float() self.SoftMeleeAttack = float() @@ -34,25 +37,56 @@ def __init__(self,CompagnieList=[],Name=""): self.NbATK = float() self.isDefending = True self.set_STR() + round_Stats(self) + def __repr__(self): return self.Name + def setCompanies(self,CompaniesList=[]): self.Companies = CompaniesList self.HOI4_Profil() + def HOI4_Profil(self): # Default Stats self.__HP = np.sum([el.HP for el in self.Companies]) - self.__ORG = np.mean([el.org for el in self.Companies]) + self.__ORG = np.mean([el.ORG for el in self.Companies]) self.__SoftAttack = np.sum([el.SoftAttack for el in self.Companies]) self.__SoftMeleeAttack = np.sum([el.SoftMeleeAttack for el in self.Companies]) self.__HardAttack = np.sum([el.HardAttack for el in self.Companies]) self.__HardMeleeAttack = np.sum([el.HardMeleeAttack for el in self.Companies]) self.Hardness = np.mean([el.Hardness for el in self.Companies]) - self.Armor = np.mean([el.Armor for el in self.Companies]) - self.Piercing = np.mean([el.Piercing for el in self.Companies]) + self.Armor = 0.7*np.mean([el.Armor for el in self.Companies]) + 0.3*np.max([el.Armor for el in self.Companies]) + self.Piercing = 0.7*np.mean([el.Piercing for el in self.Companies]) + 0.3*np.max([el.Piercing for el in self.Companies]) self.__Breakthrought = np.sum([el.Breakthrought for el in self.Companies]) self.__Defense = np.sum([el.Defense for el in self.Companies]) self.Width = np.sum([el.Width for el in self.Companies]) + self.apply_bonuses() + + def apply_bonuses(self): + """Regroupe toutes les fonctions donnant des bonuses aux stats des Régiments""" + self.set_XP() + self.set_Entrenchment() + + def set_XP(self): # sourcery skip: flip-comparison + XP = self.Experience + if 0 <= XP < 10: Land_modificator = 0.75 + elif 10 <= XP < 30: Land_modificator = 1 + elif 30 <= XP < 75: Land_modificator = 1.25 + elif 75 <= XP < 90: Land_modificator = 0.50 + elif 90 <= XP : Land_modificator = 1.75 + else: Land_modificator = 1 + self.__SoftAttack *= Land_modificator + self.__HardAttack *= Land_modificator + self.__SoftMeleeAttack *= Land_modificator + self.__HardMeleeAttack *= Land_modificator + self.__Breakthrought *= Land_modificator + self.__Defense *= Land_modificator + + def set_Entrenchment(self): + self.__Defense *= 1.02**(self.Entrenchment) + self.__SoftAttack *= 1.02**(self.Entrenchment) + self.__HardAttack *= 1.02**(self.Entrenchment) + def set_STR(self): self.Strength = self.HP / self.__HP # Maj des stats @@ -62,6 +96,7 @@ def set_STR(self): self.HardMeleeAttack = self.__HardMeleeAttack * self.Strength self.Breakthrought = self.__Breakthrought * self.Strength self.Defense = self.__Defense * self.Strength + def Attaque(self,Target,CAC_level): assert type(Target) == Regiment self.set_STR() @@ -75,18 +110,19 @@ def Attaque(self,Target,CAC_level): self.NbATK = NbATK # si perce self.NbATK /= 10 # les attaques sont divisé par 10 (voir wiki) round_Stats(self) + def Damage(self,Striker): """ Calcul du nombre de touche et des dégats :param Striker: Division attaquante """ self.set_STR() # MAJ - NbDAMAGE = Striker.nbr_attack #Recupere le nombre d'attaque de l'attaquant + NbDAMAGE = Striker.NbATK #Recupere le nombre d'attaque de l'attaquant # Attaquant ou defenseur ? - DEF = self.Defense if self.isDefending else self.Breakthrought + DEF = self.Defense/10 if self.isDefending else self.Breakthrought/10 # Defense de la cible if DEF > NbDAMAGE: NbDAMAGE *= 0.1 - else: NbDAMAGE = self.Defense*0.1 + (NbDAMAGE-self.Defense)*0.4 + else: NbDAMAGE = DEF*0.1 + (NbDAMAGE-DEF)*0.4 # Arrondissement des dégats round_Stats(self) # Calcul des dégats entre les PV et l'ORG @@ -98,6 +134,7 @@ def Damage(self,Striker): self.ORG -= 3.5*NbDAMAGE if self.Piercing < Striker.Armor else 2.5*NbDAMAGE self.ORG = truncDecimal(self.ORG,1) self.ORG = max(self.ORG, 0) + def Show_HOI_Stats(self): self.HOI4_Profil() txt = """ diff --git a/Class/Tactics.py b/Class/Tactics.py index 9d63672..7eec4e1 100644 --- a/Class/Tactics.py +++ b/Class/Tactics.py @@ -1,4 +1,6 @@ + class Tactic: + def __init__(self,ATK_Damage=1,ATK_Defense=1,DEF_Damage=1,DEF_Defense=1,CAC=0,weight=4,CounteredBy=None,Name="", BeginPhase=None): self.Name = Name @@ -12,7 +14,7 @@ def __init__(self,ATK_Damage=1,ATK_Defense=1,DEF_Damage=1,DEF_Defense=1,CAC=0,we self.CAC = CAC self.weight = weight # Begin battle phase - self.Begin_battle_phase = None + self.Begin_battle_phase = BeginPhase def __repr__(self): return self.Name diff --git a/Class/Terrain.py b/Class/Terrain.py new file mode 100644 index 0000000..5a920e8 --- /dev/null +++ b/Class/Terrain.py @@ -0,0 +1,22 @@ +from MyPack2.Utilities import truncDecimal + +class Terrain(): + def __init__(self,Combat_Witdth=(90,45),Attrition=0,AttackMalus=0,AirSuperiorityMalus=0): + self.Type = "Plains" + self.RiverCrossing = False + self.Combat_width = Combat_Witdth + self.Attrition = Attrition + self.Attack_malus = AttackMalus + self.Defense_malus = 0 + self.AirSuperiorityMalus = AirSuperiorityMalus + self.Fort_level = 0 + self.River = None + + def set_River(self,river_width): + assert river_width in ["Small","Big",None] , "river-width must be 'Small', 'big' or 'None' " + self.River = river_width + self.RiverCrossing = self.River is not None + if self.River == "Small": self.Attack_malus *= (1-0.3) + elif self.River == "Big" : self.Attack_malus *= (1-0.6) + self.Attack_malus = truncDecimal(self.Attack_malus,2) + self.Defense_malus = self.Attack_malus diff --git a/Class/Unit.py b/Class/Unit.py index f9dbb89..1286d3d 100644 --- a/Class/Unit.py +++ b/Class/Unit.py @@ -1,6 +1,6 @@ from W40K.Functions.Stats_Functions import * from W40K.Functions.Functions import * -from W40K.Functions.Units_bonuses import apply_SpecialRules +from W40K.Functions.Units_bonuses import apply_SpecialRules, apply_Vehicule import numpy as np """ Ensemble des :class: pour Unité terrestre @@ -114,7 +114,7 @@ def __init__(self,CT=3,Blind_Av=14,Blind_Side=13,Blind_Arr=10,PC=3,Quantity=1,Ty Default is Leman Russ battle tank """ self.Quantity = Quantity - self.Class = "Tank" + self.Class = "Vehicule" self.Name = Name # W40K Stats self.CT = CT @@ -144,6 +144,7 @@ def __init__(self,CT=3,Blind_Av=14,Blind_Side=13,Blind_Arr=10,PC=3,Quantity=1,Ty self.bonus_CT = np.exp((CT - 3)/2.8) self.HOI4_Profil() round_Stats(self) + def HOI4_Profil(self): setHP(self) setORG(self) @@ -152,22 +153,30 @@ def HOI4_Profil(self): # Hardness & Armor setHardness(self) setArmor(self) - # Piercing - setPiercing(self) # Defense & Breakthrought setDefense(self) setBreakthrought(self) # Bonus + self.Bonus() round_Stats(self) + def __repr__(self): return str(self.Quantity) + " " + self.Name + + def Bonus(self): + apply_SpecialRules(self) + apply_Vehicule(self) + round_Stats(self) + def setWeapons(self,TurretList=[],SideList=[],HullList=[]): self.TurretWeapon = TurretList # first Turret weapon considered as Main gun self.SideWeapon = SideList self.HullWeapon = HullList self._setTankType() self._setWeapons() + self.HOI4_Profil() round_Stats(self) + def _setTankType(self): if len(self.TurretWeapon) == 0: # if any turret weapon if len(self.HullWeapon) != 0: # and have hull weapons @@ -176,29 +185,28 @@ def _setTankType(self): self.Type += " Defender" elif self.TurretWeapon[0].Type == "Ordnance" and self.Type != "Heavy": self.Type += " SP Artillery" # set tank type as SP artillery + def _setWeapons(self): - """ - FIXME - - Le basilisk perd tout ses valeurs Defense/Breakthrought a cause de cette fonction - - breakpoint: self.Name == "Basilisk" - """ + for weapon in self.TurretWeapon+self.HullWeapon+self.SideWeapon: + weapon.Defense_bonus = 1 + weapon.Breakthrought_bonus = 1 + if len(self.TurretWeapon) == 0 and len(self.HullWeapon) != 0: + self.Breakthrought *= 0.8 + self.Defense *= 1.2 if len(self.HullWeapon) != 0: for weapon in self.HullWeapon: weapon.SoftAttack *= 0.33 weapon.HardAttack *= 0.33 - weapon.Defense *= 0.33 - weapon.Breakthrought *= 0.33 if len(self.SideWeapon) != 0: for weapon in self.SideWeapon: weapon.SoftAttack *= 0.66 weapon.HardAttack *= 0.66 - weapon.Defense *= 0.66 - weapon.Breakthrought *= 0.66 self.SoftAttack = np.sum([el.SoftAttack for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) self.HardAttack = np.sum([el.HardAttack for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) - self.Defense = np.sum([el.Defense for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) - self.Breakthrought = np.sum([el.Breakthrought for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) + self.Defense *= np.prod([el.Defense_bonus for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) + self.Breakthrought *= np.prod([el.Breakthrought_bonus for el in self.HullWeapon+self.TurretWeapon+self.SideWeapon]) self.Piercing = np.max([weapon.Piercing for weapon in self.TurretWeapon+self.HullWeapon+self.SideWeapon]) + def Show_HOI_Stats(self): self.HOI4_Profil() txt = """ @@ -215,8 +223,10 @@ def Show_HOI_Stats(self): self.SoftMeleeAttack,self.HardMeleeAttack, self.Hardness,self.Armor) print(txt) + def set_Quantity(self,Quantity): setQuantity(self, Quantity) + def __copy__(self,Quantity=None): if Quantity is None: Quantity = self.Quantity newObject = Tank() @@ -229,13 +239,13 @@ def __copy__(self,Quantity=None): ######################################################################################################################## class Walker: - def __init__(self,CC=3,CT=3,F=5,Blind_Av=12,Blind_Side=10,Blind_Arr=10,A=1,PC=2,Quantity=1,Type="Marcheur" + def __init__(self,CC=3,CT=3,F=5,Blind_Av=12,Blind_Side=10,Blind_Arr=10,A=1,PC=2,Quantity=1,Type="Walker" ,SpecialRules=list,Name = ""): """ Default is Sentinel """ self.Quantity = Quantity - self.Class = "Walker" + self.Class = "Vehicule" self.Name = Name # W40K Stats self.CC = CC @@ -278,7 +288,13 @@ def HOI4_Profil(self): # Defense & Breakthrought setDefense(self) setBreakthrought(self) - # End + self.Bonus() + # End + + def Bonus(self): + apply_SpecialRules(self) + round_Stats(self) + def Show_HOI_Stats(self): self.HOI4_Profil() txt = """ @@ -295,8 +311,10 @@ def Show_HOI_Stats(self): self.SoftMeleeAttack,self.HardMeleeAttack, self.Hardness,self.Armor) print(txt) + def __repr__(self): return str(self.Quantity) + " " + self.Name + def set_Quantity(self,Quantity): setQuantity(self, Quantity) diff --git a/Class/Weapons.py b/Class/Weapons.py index f5b2152..5839c8c 100644 --- a/Class/Weapons.py +++ b/Class/Weapons.py @@ -1,6 +1,6 @@ from W40K.Functions.Stats_Functions import * from W40K.Functions.Functions import * -from W40K.Functions.Weapons_bonuses import setWeapons_SAHA_bonus,setWeapons_DEFBRK_bonus +from W40K.Functions.Weapons_bonuses import apply_SpecialsRules,apply_WeaponsType class Weapon: def __init__(self, F=3, PA=None, Range = 24, Type="Tir rapide", Cadence = 1,Quantity=1,SpecialsRules=[],Name=""): @@ -19,28 +19,24 @@ def __init__(self, F=3, PA=None, Range = 24, Type="Tir rapide", Cadence = 1,Quan self.HardAttack = float() self.SoftMeleeAttack = float() self.HardMeleeAttack = float() - self.Defense = float() - self.Breakthrought = float() self.Piercing = float() + self.Defense_bonus = float(1.0) + self.Breakthrought_bonus = float(1.0) self.HOI4_Profil() - def __repr__(self): - return str(self.Quantity) + " " + self.Name - def HOI4_Profil(self): # Cadence if self.Type == "Tir rapide":self.Cadence = 2 + elif self.Type == "Pistol": self.Cadence = 1 # Soft and Hard Attack setSA(self) setHA(self) setSMA(self) setHMA(self) - setWeapons_SAHA_bonus(self) setPiercing(self) # Defense and Break - setDefense(self) - setBreakthrought(self) - setWeapons_DEFBRK_bonus(self) + apply_WeaponsType(self) + apply_SpecialsRules(self) # End round_Stats(self) @@ -53,13 +49,19 @@ def Show_HOI_Stats(self): Breakthrought = {} Piercing = {} """.format(self.SoftAttack,self.HardAttack, - self.Defense,self.Breakthrought, + self.Defense_bonus,self.Breakthrought_bonus, self.Piercing) print(txt) def set_Quantity(self,Quantity): setQuantity(self, Quantity) + def isGrenade(self): + return any(("Grenade" or "grenade") in rule for rule in self.SpecialsRules) + + def __repr__(self): + return str(self.Quantity) + " " + self.Name + def __copy__(self, Quantity=None): if Quantity is None: Quantity = self.Quantity newObject = Weapon() @@ -70,11 +72,15 @@ def __copy__(self, Quantity=None): class Upgrade: - def __init__(self,SA=1,HA=1,SMA=1,HMA=1,DEF=1,BRK=1,Quantity=100): + def __init__(self,SA=1,HA=1,SMA=1,HMA=1,DEF=1,BRK=1,Quantity=100,Name=""): + self.Name = Name self.Quantity = Quantity self.SoftAttack_Bonus = SA self.HardAttack_Bonus = HA self.SoftMeleeAttack_Bonus = SMA self.HardMeleeAttack_Bonus = HMA self.Defense_Bonus = DEF - self.Breakthrought_Bonus = BRK \ No newline at end of file + self.Breakthrought_Bonus = BRK + + def __repr__(self): + return str(self.Quantity) + " " + self.Name \ No newline at end of file diff --git a/Functions/Company_bonuses.py b/Functions/Company_bonuses.py new file mode 100644 index 0000000..6aa4f14 --- /dev/null +++ b/Functions/Company_bonuses.py @@ -0,0 +1,7 @@ +def apply_SpecialRules(company): # sourcery skip: switch + unit = company.Unit + for rule in unit.SpecialRules: + if rule == "Heavy Weapons Team": + for weapon in company.Equipement: + if weapon.Type == "Lourde": + weapon.Breakthrought_bonus = 0 \ No newline at end of file diff --git a/Functions/Functions.py b/Functions/Functions.py index 75449ab..c45b9d5 100644 --- a/Functions/Functions.py +++ b/Functions/Functions.py @@ -19,25 +19,12 @@ def setQuantity(object, Quantity): object.HardAttack *= quantity_factor object.SoftMeleeAttack *= quantity_factor object.HardMeleeAttack *= quantity_factor - object.Defense *= quantity_factor - object.Breakthrought *= quantity_factor + try: object.Defense *= quantity_factor + except: pass + try: object.Breakthrought *= quantity_factor + except: pass def check_lists(self): from W40K.Class.Weapons import Weapon for el in self.Equipement: assert type(el) is Weapon , "Each element of Equipement list must be a :Weapon class:" -""" -def saveInCSV(Object): - Dico1 = Object.__dict__ - Dico2 = getFromDict(Dico1,["HP","ORG", - "SoftAttack","HardAttack","SoftMeleeAttack","HardMeleeAttack", - "Breaktrhought","Defense","Armor","Piercing","Hardness" - ]) - - if type(Object) == Infantry: Dict2CSV(Dico2,"Saved_Infantry.csv") - elif type(Object) == Tank: Dict2CSV(Dico2,"Saved_Tank.csv") - elif type(Object) == Walker: Dict2CSV(Dico2,"Saved_Walker.csv") - elif type(Object) == Weapon: Dict2CSV(Dico2,"Saved_Weapon.csv") - elif type(Object) == Company: Dict2CSV(Dico2,"Saved_Company.csv") - else: return TypeError , "Object must be Infantry, Walker, Tank, Weapon or Company. Save is not possible" -""" diff --git a/Functions/Leader_func.py b/Functions/Leader_func.py new file mode 100644 index 0000000..444309f --- /dev/null +++ b/Functions/Leader_func.py @@ -0,0 +1,21 @@ + +def set_LeaderSkills(Battle): + for side in [Battle.ATK, Battle.DEF]: + side["Regiment"]._Regiment__SoftAttack *= 1.05**(side["Leader"].Attack_skill-1) + side["Regiment"]._Regiment__HardAttack *= 1.05**(side["Leader"].Attack_skill-1) + side["Regiment"]._Regiment__SoftMeleeAttack *= 1.05**(side["Leader"].Attack_skill-1) + side["Regiment"]._Regiment__HardMeleeAttack *= 1.05**(side["Leader"].Attack_skill-1) + side["Regiment"]._Regiment__Defense *= 1.05**(side["Leader"].Defense_skill-1) + side["Regiment"]._Regiment__Breakthrought *= 1.05**(side["Leader"].Defense_skill-1) + +def apply_LeaderTactic(Battle): + """ + Modifie les tactiques en fonctions des Leaders + """ + for side in [Battle.ATK, Battle.DEF]: # Augmente le poids des tactiques préférés pour chaques camps + for each_tactic in side["Tactics"]: + if each_tactic.Name in side["Leader"].Prefered_Tactics: + each_tactic.weight *= 1.35 + +def apply_LeaderTraits(Leader): # sourcery skip: for-index-underscore + for trait in Leader.Traits_list: pass \ No newline at end of file diff --git a/Functions/Stats_Functions.py b/Functions/Stats_Functions.py index 9c7bd1c..be80e55 100644 --- a/Functions/Stats_Functions.py +++ b/Functions/Stats_Functions.py @@ -3,73 +3,69 @@ ######################################################################################################################## def setHP(object): - if object.Class == "Infantry": HP = object.pv*1.5**(object.E - 3) - elif object.Class == "Tank": HP = object.PC + if object.Class == "Infantry": HP = object.PV * 1.5**(object.E-3) + elif object.Class == "Vehicule": HP = object.PC else: return AttributeError ,"object.Class not found" object.HP = HP/4 ######################################################################################################################## def setORG(object): - if object.Class == "Infantry": - ORG = object.Cd*10 - elif object.Class == "Tank": - if object.Type == "SuperHeavy": ORG = 15 - elif object.Type == "Artillerie": ORG = 0 + """ + FIXME + - Revoir ci dessous + """ + if object.Class == "Infantry": ORG = object.Cd*10 + elif object.Class == "Vehicule": + if "SuperHeavy" in object.Type: ORG = 15 + elif "Artillerie" in object.Type: ORG = 0 + elif "Walker" in object.Type : ORG = 40 else: ORG = 10 - elif object.Class == "Walker": ORG = 40 else: return AttributeError ,"object.Type not found" - object.org = ORG + object.ORG = ORG ######################################################################################################################## def setSA(object): # sourcery skip: assign-if-exp, remove-unnecessary-else, swap-if-else-branches if object.Class == "Weapon": if object.Type == "Melee": SA = 0 - else: SA = (np.arctan(object.F/0.5)**6) /10 + else: SA = (np.arctan(object.F/0.5)**6) try: SA *= 1.2**(5-object.PA) except: pass SA *= object.Cadence else: return AttributeError ,"object.Type not found" - object.SoftAttack = truncDecimal(SA,2)/10 + object.SoftAttack = truncDecimal(SA,2) /500 ######################################################################################################################## def setHA(object): # sourcery skip: merge-duplicate-blocks, remove-redundant-if, remove-unnecessary-else, swap-if-else-branches if object.Class == "Weapon": if object.Type == "Melee": HA = 0 - elif object.F > 3: HA = np.exp(object.F/2) /100 + elif object.F > 3: HA = np.exp(object.F/2) else: HA = 0 try: HA *= ((1/object.PA**3)*216)**0.3 except: pass HA *= object.Cadence else: return AttributeError ,"object.Type not found" - object.HardAttack = HA/10 + object.HardAttack = truncDecimal(HA,2) /3000 ######################################################################################################################## def setSMA(object): # sourcery skip: assign-if-exp, switch - if object.Class == "Infantry": SMA = (object.A/10)*1.3**(object.CC-3) - elif object.Class == "Tank": - if object.Type == "Chariot": SMA = 0.1 - elif object.Type == "Tank": SMA = 0.3 - elif object.Type == "Heavy": SMA = 0.5 - elif object.Type == "SuperHeavy": SMA = 0.6 - elif object.Type == "Artillery": SMA = 0 - else: return AttributeError ,"object.Type not found" + if object.Class == "Infantry": SMA = (object.A/10)*1.3**(object.CC-3) /4 + elif object.Class == "Vehicule": + if "Walker" in object.Type: SMA = (object.A/10)*1.3**(object.CC-3) /4 + else: SMA = 0 elif object.Class == "Weapon": - if object.Type == "Melee": SMA = np.arctan(object.F/0.5)**6 /10 - else: SMA = 0 + if object.Type == "Melee": SMA = np.arctan(object.F/0.5)**6 /10 /4 + elif object.Type == "Pistol": SMA = 0.2 + else: SMA = 0 else: return AttributeError ,"object.Class not found" object.SoftMeleeAttack = SMA/10 ######################################################################################################################## def setHMA(object): # sourcery skip: merge-duplicate-blocks, remove-redundant-if, switch if object.Class == "Infantry" and object.F >= 4: - HMA = object.SoftMeleeAttack*1.6**(object.F-4) - elif object.Class == "Tank": - if object.Type == "Chariot": HMA = 0 - elif object.Type == "Tank": HMA = 0.1 - elif object.Type == "Heavy": HMA = 0.2 - elif object.Type == "SuperHeavy": HMA = 0.4 - elif object.Type == "Artillery": HMA = 0 - else: return AttributeError ,"object.Type not found" + HMA = object.SoftMeleeAttack*1.6**(object.F-4) /4 + elif object.Class == "Vehicule": + if "Walker" in object.Type: HMA = object.SoftMeleeAttack*1.6**(object.F-4) /4 + else: HMA = 0 elif object.Class == "Weapon" and object.F >= 4: - if object.Type == "Melee": HMA = np.exp(object.F/2) /100 + if object.Type == "Melee": HMA = np.exp(object.F/2) /100 /4 elif "Krak Grenade" in object.SpecialsRules: HMA = np.exp(object.F/2)/100 else: HMA = 0 @@ -82,7 +78,7 @@ def setArmor(object): # sourcery skip: remove-redundant-if elif object.Svg == 2: Armor = 4 else: Armor = 0 if object.SvgInvu in [6,5,4,3,2]: Armor *= 1.15**(7-object.SvgInvu) - elif object.Class == "Tank" or "Walker": + elif object.Class == "Vehicule": Armor = np.mean((object.Blind_Av, object.Blind_Side, object.Blind_Arr)) if "Oppen-Topped" in object.SpecialRules: Armor /= 2 else: return AttributeError ,"object.Class not found" @@ -90,22 +86,39 @@ def setArmor(object): # sourcery skip: remove-redundant-if ######################################################################################################################## def setHardness(object): # sourcery skip: remove-redundant-pass # check class + """ + FIXME + - Detailler plus précisément les types de :param object: pour determiner l'Hardness + - Revoir ci dessous + """ if object.Class == "Infantry": if object.Svg == 3: Hardness = 0.1 elif object.Svg == 2: Hardness = 0.2 else: Hardness = 0 - elif object.Class == "Tank": - if object.Type == "Chariot": Hardness = 0.80 - elif object.Type == "Tank": Hardness = 0.90 - elif object.Type == "Heavy": Hardness = 0.95 - elif object.Type == "SuperHeavy": Hardness = 0.99 - elif object.Type == "Artillery": Hardness = 0 - else: return AttributeError ,"object.Type not found" - elif object.Class == "Walker": Hardness = 0.7 + + elif object.Class == "Vehicule": + Type = object.Type + if Type == "Chariot": Hardness = 0.80 + elif Type == ("Tank" or ""): Hardness = 0.90 + elif Type == "Heavy": Hardness = 0.95 + elif Type == "SuperHeavy": Hardness = 0.99 + + elif Type == "Chariot SP Artillery": Hardness = 0.50 + elif Type == ("Tank SP Artillery" + or "SP Artillery"): Hardness = 0.65 + elif Type == "Heavy SP Artillery": Hardness = 0.80 + elif Type == "SuperHeavy SP Artillery": Hardness = 0.90 + + elif Type == "Chariot Destroyer": Hardness = 0.80 + elif Type == ("Tank Destroyer" + or "Destroyer"): Hardness = 0.90 + elif Type == "Heavy Destroyer": Hardness = 0.95 + elif Type == "SuperHeavy Destroyer": Hardness = 0.99 + + elif Type == "Walker": Hardness = 0.75 + else: return AttributeError, "Tank Type not Found" + else: return AttributeError ,"object.Class not found" -# check rules - if "Oppen-Topped" in object.SpecialRules: Hardness /= 2 - else: pass # check hardness out of bounds if Hardness <= 0: Hardness = 0 elif Hardness >= 1: Hardness = 1 @@ -118,65 +131,75 @@ def setPiercing(object): # sourcery skip: remove-redundant-pass, switch if object.PA == 2: PRC += 1 elif object.PA == 1: PRC += 2 else: pass - else: PRC = 0 - object.Piercing = PRC + object.Piercing = PRC + else: pass + ######################################################################################################################## def setDefense(object): # sourcery skip: merge-duplicate-blocks, remove-redundant-if, switch """ - BRK of an weapons regarding this F and E + Pour chaques catégories la valeur dest divisé par le nombre d'unité dans une compangie (plus simple) + afin de le rendre en accord avec les stats dans HOI IV """ Class,Type = object.Class , object.Type - if Class == "Weapon": DEF = 0.1 - elif Class == "Tank": - if Type == "Chariot": DEF = 4 - elif Type == ("Tank" or ""): DEF = 5 - elif Type == "Heavy": DEF = 6 - elif Type == "SuperHeavy": DEF = 10 + if Class == "Vehicule": + if Type == "Chariot": DEF = 4 / 15 + elif Type == ("Tank" or ""): DEF = 5 / 15 + elif Type == "Heavy": DEF = 6 / 10 + elif Type == "SuperHeavy": DEF = 10 / 4 - elif Type == "Chariot SP Artillery": DEF = 4 + elif Type == "Chariot SP Artillery": DEF = 4 / 15 elif Type == ("Tank SP Artillery" - or "SP Artillery"): DEF = 5 - elif Type == "Heavy SP Artillery": DEF = 6 - elif Type == "SuperHeavy SP Artillery": DEF = 7 + or "SP Artillery"): DEF = 5 / 15 + elif Type == "Heavy SP Artillery": DEF = 6 / 10 + elif Type == "SuperHeavy SP Artillery": DEF = 7 / 4 - elif Type == "Chariot Destroyer": DEF = 4 + elif Type == "Chariot Destroyer": DEF = 4 / 15 elif Type == ("Tank Destroyer" - or "Destroyer"): DEF = 5 - elif Type == "Heavy Destroyer": DEF = 6 - elif Type == "SuperHeavy Destroyer": DEF = 7 + or "Destroyer"): DEF = 5 / 15 + elif Type == "Heavy Destroyer": DEF = 6 / 10 + elif Type == "SuperHeavy Destroyer": DEF = 7 / 4 + + elif Type == "Walker": DEF = 10 / 15 else: return AttributeError, "Tank Type not Found" - elif object.Class == "Infantry": DEF = 20 + elif object.Class == "Infantry": DEF = 20 / 100 + else: return AttributeError ,"object.Class not found" - object.Defense = DEF / 100 + object.Defense = DEF ######################################################################################################################## def setBreakthrought(object): # sourcery skip: merge-duplicate-blocks, remove-pass-elif, remove-redundant-if, switch """ - BRK of an weapons regarding this F and E + Pour chaques catégories la valeur dest divisé par le nombre d'unité dans une compangie (plus simple) + afin de le rendre en accord avec les stats dans HOI IV + TODO + - add Super heavy walker (Titan) + - Heavy walker ?? """ Class, Type = object.Class, object.Type - if object.Class == "Weapon": BRK = 0.1 - elif object.Class == "Infantry": BRK = 2 - elif Class == "Tank": - if Type == "Chariot": BRK = 26 - elif Type == ("Tank" or ""): BRK = 30 - elif Type == "Heavy": BRK = 40 - elif Type == "SuperHeavy": BRK = 70 + if object.Class == "Infantry": BRK = 2 / 100 + elif Class == "Vehicule": + + if Type == "Chariot": BRK = 26 / 15 + elif Type == ("Tank" or ""): BRK = 30 / 15 + elif Type == "Heavy": BRK = 40 / 10 + elif Type == "SuperHeavy": BRK = 70 / 4 - elif Type == "Chariot SP Artillery": BRK = 2 + elif Type == "Chariot SP Artillery": BRK = 2 / 15 elif Type == ("Tank SP Artillery" - or "SP Artillery"): BRK = 3 - elif Type == "Heavy SP Artillery": BRK = 2 - elif Type == "SuperHeavy SP Artillery": BRK = 3 + or "SP Artillery"): BRK = 3 / 15 + elif Type == "Heavy SP Artillery": BRK = 2 / 10 + elif Type == "SuperHeavy SP Artillery": BRK = 3 /4 - elif Type == "Chariot Destroyer": BRK = 1 + elif Type == "Chariot Destroyer": BRK = 1 / 15 elif Type == ("Tank Destroyer" - or "Destroyer"): BRK = 1.3 - elif Type == "Heavy Destroyer": BRK = 1 - elif Type == "SuperHeavy Destroyer": BRK = 4 + or "Destroyer"): BRK = 1.3 / 15 + elif Type == "Heavy Destroyer": BRK = 1 / 10 + elif Type == "SuperHeavy Destroyer": BRK = 4 / 4 + + elif Type == "Walker": BRK = 12 / 15 else: return AttributeError, "Tank Type not Found" - elif Class == "Walker": pass + else: return AttributeError ,"object.Class not found" - object.Breakthrought = BRK / 100 \ No newline at end of file + object.Breakthrought = BRK \ No newline at end of file diff --git a/Functions/Tactics_func.py b/Functions/Tactics_func.py index 10ba073..a1c7691 100644 --- a/Functions/Tactics_func.py +++ b/Functions/Tactics_func.py @@ -5,7 +5,8 @@ from W40K.Lists.Tactics_list import ATK_tactics, ATK_HB_tactics, ATK_CQ_tactics, ATK_SB_tactics, ATK_TW_tactics from W40K.Lists.Tactics_list import DEF_tactics, DEF_HB_tactics, DEF_CQ_tactics, DEF_SB_tactics, DEF_TW_tactics - +all_Tactics_list = ATK_tactics + ATK_HB_tactics + ATK_CQ_tactics + ATK_SB_tactics + ATK_TW_tactics\ + + DEF_tactics + DEF_HB_tactics + DEF_CQ_tactics + DEF_SB_tactics + DEF_TW_tactics ######################################################################################################################## def choose_Tactics(Battle): @@ -19,33 +20,38 @@ def choose_Tactics(Battle): """ change_weight(Battle) # Which tactics lists is used according the battle phase - if Battle.Phase == "Default": + if Battle.Current_Phase == "Default": ATK_tactic_list = ATK_tactics DEF_tactic_list = DEF_tactics - elif Battle.Phase == "Close Quarter Combat": + Battle.Current_Phase == "Default" + elif Battle.Current_Phase == "Close Quarter Combat": ATK_tactic_list = ATK_CQ_tactics DEF_tactic_list = DEF_CQ_tactics - elif Battle.Phase == "Seize Bridge": + elif Battle.Current_Phase == "Seize Bridge": ATK_tactic_list = ATK_SB_tactics DEF_tactic_list = DEF_SB_tactics - elif Battle.Phase == "Hold Bridge": + elif Battle.Current_Phase == "Hold Bridge": ATK_tactic_list = ATK_HB_tactics DEF_tactic_list = DEF_HB_tactics - elif Battle.Phase == "Tactical Withdraw": + elif Battle.Current_Phase == "Tactical Withdraw": ATK_tactic_list = ATK_TW_tactics DEF_tactic_list = DEF_TW_tactics else: return NameError , "Wrong phase name" winner = Initiative_round(Battle) # wich side has initiative ATK_Tactic, DEF_Tactic = _choose_tactics(ATK_tactic_list,DEF_tactic_list,winner) # choose tactics - Battle.attacker_tactic = ATK_Tactic - Battle.defender_tactic = DEF_Tactic + Battle.ATK_Tactic_chosen = ATK_Tactic + Battle.DEF_Tactic_chosen = DEF_Tactic + Battle.Initiative_winner = winner isCountered(Battle) # test if any tactics has been coutered apply_Tactics(Battle) # apply bonuses + change_BattlePhase(Battle) def _choose_tactics(ATK_tactic_list,DEF_tactic_list,Initiative_winner): """ Le perdant du :initiative round: choisi la tactique en premier. Ensuite le gagnant tente de le contrer. :return: Tactiques choisis par les deux camps + FIXME + - Fusionner les boucles pour les cas ou le gagnant est soit le DEF / ATK dans une seule boucle """ ATK_Tactic = Tactic() DEF_Tactic = Tactic() @@ -55,7 +61,7 @@ def _choose_tactics(ATK_tactic_list,DEF_tactic_list,Initiative_winner): DEF_Tactic = rd.choices(DEF_tactic_list, DEF_tactic_weight)[0] # Change weight for try counter DEF tactic try: # Increase weight if counter tactic exist - Counter_tactic = [el for el in ATK_tactic_list if el.name == DEF_Tactic.countered_by][0] + Counter_tactic = [el for el in ATK_tactic_list if el.Name == DEF_Tactic.CounteredBy][0] Counter_tactic.weight *= 1.35 except: pass # if counter tactic doesn't exist # ATK choice finnaly @@ -66,7 +72,7 @@ def _choose_tactics(ATK_tactic_list,DEF_tactic_list,Initiative_winner): ATK_tactic_weight = [el.weight for el in ATK_tactic_list] ATK_Tactic = rd.choices(ATK_tactic_list, ATK_tactic_weight)[0] try: # Change weight for try counter ATK tactic - Counter_tactic = [el for el in DEF_tactic_list if el.name == ATK_Tactic.countered_by][0] + Counter_tactic = [el for el in DEF_tactic_list if el.Name == ATK_Tactic.CounteredBy][0] Counter_tactic.weight *= 1.35 except: pass # DEF choice @@ -78,11 +84,11 @@ def isCountered(Battle): """ Check if a tactic has been countered. Cancel countered ones """ - if Battle.defender_tactic.name == Battle.attacker_tactic.countered_by: - Cancel_Tactic(Battle.attacker_tactic) + if Battle.DEF_Tactic_chosen.Name == Battle.ATK_Tactic_chosen.CounteredBy: + Cancel_Tactic(Battle.ATK_Tactic_chosen) print("ATK tactic COUNTERED !!") - if Battle.attacker_tactic.name == Battle.defender_tactic.countered_by: - Cancel_Tactic(Battle.defender_tactic) + if Battle.ATK_Tactic_chosen.Name == Battle.DEF_Tactic_chosen.CounteredBy: + Cancel_Tactic(Battle.DEF_Tactic_chosen) print("DEF tactic COUNTERED !!") def Cancel_Tactic(Tactic_to_cancel): @@ -90,48 +96,45 @@ def Cancel_Tactic(Tactic_to_cancel): Retire tout les bonus d'une tactique """ assert type(Tactic_to_cancel) is Tactic - Tactic_to_cancel.attacker_damage = 1 - Tactic_to_cancel.attacker_defense = 1 - Tactic_to_cancel.defender_damage = 1 - Tactic_to_cancel.defender_defense = 1 + Tactic_to_cancel.ATK_Damage = 1 + Tactic_to_cancel.ATK_Defense = 1 + Tactic_to_cancel.DEF_Damage = 1 + Tactic_to_cancel.DEF_Defense = 1 Tactic_to_cancel.CAC = 0 - Tactic_to_cancel.begin_battle_phase = None + Tactic_to_cancel.Begin_battle_phase = None def Initiative_round(Battle): # sourcery skip: assign-if-exp, remove-redundant-pass """ - TODO -- NEED Leader Upgrade Choisis quel camp aura l'initiative - - Basic pour le moment car leaders ne sont pas ajoutés + - Pas en accord avec le wiki (a voir) + - Code perso """ - ATK_weight = int() - DEF_weight = int() - if Battle.AttackerLeader is None: ATK_weight = 1 - else: pass # Need Leader upgrade - if Battle.DefenderLeader is None: DEF_weight = 1 - else: pass # Need Leader upgrade - + DEF_leader = Battle.DEF["Leader"] + DEF_weight = DEF_leader.Defense_skill + DEF_leader.Level + ATK_leader = Battle.ATK["Leader"] + ATK_weight = ATK_leader.Attack_skill + ATK_leader.Level return rd.choices(["ATK","DEF"],[ATK_weight,DEF_weight])[0] def apply_Tactics(Battle): - DEF = Battle.defense - DEF_Tac = Battle.defender_tactic - ATK = Battle.attacker - ATK_Tac = Battle.attacker_tactic + DEF = Battle.DEF["Regiment"] + DEF_Tac = Battle.DEF_Tactic_chosen + ATK = Battle.ATK["Regiment"] + ATK_Tac = Battle.ATK_Tactic_chosen # Bonus for DEF - DEF.SoftAttack = DEF.SoftAttack*DEF_Tac.defender_damage*ATK_Tac.defender_damage - DEF.HardAttack = DEF.HardAttack*DEF_Tac.defender_damage*ATK_Tac.defender_damage - DEF.Defense = DEF.Defense*DEF_Tac.defender_defense*ATK_Tac.defender_defense + DEF.SoftAttack *= DEF_Tac.DEF_Damage * ATK_Tac.DEF_Damage + DEF.HardAttack *= DEF_Tac.DEF_Damage * ATK_Tac.DEF_Damage + DEF.Defense *= DEF_Tac.DEF_Defense * ATK_Tac.DEF_Defense # Bonus for ATK - ATK.SoftAttack = ATK.SoftAttack*ATK_Tac.attacker_damage*ATK_Tac.attacker_damage - ATK.HardAttack = ATK.HardAttack*ATK_Tac.attacker_damage*ATK_Tac.attacker_damage - ATK.Defense = ATK.Defense*ATK_Tac.attacker_defense*ATK_Tac.attacker_defense + ATK.SoftAttack *= DEF_Tac.ATK_Damage * ATK_Tac.ATK_Damage + ATK.HardAttack *= DEF_Tac.ATK_Damage * ATK_Tac.ATK_Damage + ATK.Defense *= DEF_Tac.ATK_Defense * ATK_Tac.ATK_Defense # Cac limit set_CAC_limit(Battle) def set_CAC_limit(Battle): - DEF_Tac = Battle.defender_tactic - ATK_Tac = Battle.attacker_tactic + DEF_Tac = Battle.DEF_Tactic_chosen + ATK_Tac = Battle.ATK_Tactic_chosen if Battle.CAC_limit < 0: Battle.CAC_limit = 0 # Mets le CAC limit entre 0 et 1 elif Battle.CAC_limit > 1: Battle.CAC_limit = 1 # Pour préparer le nouvel CAC limit Battle.CAC_limit = Battle.CAC_limit + np.sum(DEF_Tac.CAC + ATK_Tac.CAC) @@ -146,6 +149,13 @@ def update_CAC(Battle): if Battle.CAC_level < 0: Battle.CAC_level = 0 elif Battle.CAC_level > 1: Battle.CAC_level = 1 +def change_BattlePhase(Battle): + if Battle.Initiative_winner == "ATK": winner_tactic = Battle.ATK_Tactic_chosen + elif Battle.Initiative_winner == "DEF": winner_tactic = Battle.DEF_Tactic_chosen + else: return AttributeError , "Winner not exists" + if winner_tactic.Begin_battle_phase != None: + Battle.Following_Phase = winner_tactic.Begin_battle_phase + def change_weight(Battle): """Change tactics weight with regards to Generals skills and abilities and terrain""" pass \ No newline at end of file diff --git a/Functions/Terrain_func.py b/Functions/Terrain_func.py new file mode 100644 index 0000000..5f5314d --- /dev/null +++ b/Functions/Terrain_func.py @@ -0,0 +1,9 @@ + +def apply_Terrain(Battle): + ATK = Battle.ATK["Regiment"] + DEF = Battle.DEF["Regiment"] + Terrain = Battle.Terrain + + ATK.SoftAttack *= Terrain.Attack_malus + ATK.HardAttack *= Terrain.Attack_malus + ATK.Breakthrought *= Terrain.Defense_malus diff --git a/Functions/Units_bonuses.py b/Functions/Units_bonuses.py index b32e91a..1495efa 100644 --- a/Functions/Units_bonuses.py +++ b/Functions/Units_bonuses.py @@ -1,7 +1,74 @@ -def apply_SpecialRules(unit): +def apply_SpecialRules(unit): # sourcery skip: switch for rule in unit.SpecialRules: if rule == "Astartes": - unit.org *= 1.2 - elif rule == "Immobile": - unit.Breaktrought = 0 if unit.Type != "Artillery" else 0.8 - unit.Defense *= 1.2 \ No newline at end of file + unit.ORG *= 1.2 + if rule == "Oppen-Topped": + unit.Hardness /= 2 + if rule == "Combat Squads": + unit.Breaktrought *= 1.15 + if rule == "Combined Squads": + unit.Defense *= 1.15 + if "Chapter:" in rule: + apply_Faction(unit,rule.split(": ")[-1]) + + if "Platform" in unit.Name: + unit.Hardness = 0 + unit.Armor = 0 + unit.Type = "Platform" + +def apply_Vehicule(vehicule): # sourcery skip: remove-pass-elif + Class,Type = vehicule.Class, vehicule.Type + if Class == "Vehicule": + + if Type == "Chariot": + vehicule.SoftAttack *= 2 + vehicule.HardAttack *= 2 + elif Type == ("Tank" or ""): + vehicule.SoftAttack *= 3 + vehicule.HardAttack *= 3 + elif Type == "Heavy": + vehicule.SoftAttack *= 5 + vehicule.HardAttack *= 5 + elif Type == "SuperHeavy": + vehicule.SoftAttack *= 7 + vehicule.HardAttack *= 7 + + elif Type == "Chariot SP Artillery": + vehicule.SoftAttack *= 15 + vehicule.HardAttack *= 1 + elif Type == ("Tank SP Artillery" + or "SP Artillery"): + vehicule.SoftAttack *= 20 + vehicule.HardAttack *= 1 + elif Type == "Heavy SP Artillery": + vehicule.SoftAttack *= 25 + vehicule.HardAttack *= 1 + elif Type == "SuperHeavy SP Artillery": + vehicule.SoftAttack *= 30 + vehicule.HardAttack *= 3 + + elif Type == "Chariot Destroyer": + vehicule.SoftAttack *= 1 + vehicule.HardAttack *= 7 + elif Type == ("Tank Destroyer" + or "Destroyer"): + vehicule.SoftAttack *= 1 + vehicule.HardAttack *= 10 + elif Type == "Heavy Destroyer": + vehicule.SoftAttack *= 1 + vehicule.HardAttack *= 13 + elif Type == "SuperHeavy Destroyer": + vehicule.SoftAttack *= 1 + vehicule.HardAttack *= 16 + + elif Type == "Walker":pass + else: return AttributeError, "Tank Type not Found" + +def apply_Faction(unit,rule): + """ + FIXME + - Voir si je change les poids de certaines tactiques pour "ULTRAMARINES" + """ + if rule == "Ultramarines": + unit.SoftAttack *= 1.05 + unit.HardAttack *= 1.05 \ No newline at end of file diff --git a/Functions/Upgrades_bonuses.py b/Functions/Upgrades_bonuses.py index 3ea201f..994bfc5 100644 --- a/Functions/Upgrades_bonuses.py +++ b/Functions/Upgrades_bonuses.py @@ -18,9 +18,9 @@ def setUpgradeBonus(company): Defense_Bonus *= 1 + (el.Defense_Bonus-1)*equip_ratio Breakthrought_Bonus *= 1 + (el.Breakthrought_Bonus-1)*equip_ratio # Application des bonus - company.SoftAttack = company.SoftAttack*SoftAttack_Bonus - company.HardAttack = company.HardAttack*HardAttack_Bonus - company.SoftMeleeAttack = company.SoftMeleeAttack*SoftMeleeAttack_Bonus - company.HardMeleeAttack = company.HardMeleeAttack*HardMeleeAttack_Bonus - company.Defense = company.Defense*Defense_Bonus - company.Breakthrought = company.Breakthrought*Breakthrought_Bonus \ No newline at end of file + company.SoftAttack *= SoftAttack_Bonus + company.HardAttack *= HardAttack_Bonus + company.SoftMeleeAttack *= SoftMeleeAttack_Bonus + company.HardMeleeAttack *= HardMeleeAttack_Bonus + company.Defense *= Defense_Bonus + company.Breakthrought *= Breakthrought_Bonus \ No newline at end of file diff --git a/Functions/Weapons_bonuses.py b/Functions/Weapons_bonuses.py index 2882ed1..3d3cea0 100644 --- a/Functions/Weapons_bonuses.py +++ b/Functions/Weapons_bonuses.py @@ -1,127 +1,138 @@ -def setWeapons_SAHA_bonus(Object): +def apply_SpecialsRules(Weapon): """ Verifie les règles spéciales des :class Weapons: pour ajouté les bonus - :param Object: class weapons + :param Weapon: class weapons """ - #assert type(Object) == Weapon , "Object must be :class Weapon:" -# Weapons Specials rules - Rules = Object.SpecialsRules - if "Perforant" in Object.SpecialsRules: - Object.SoftAttack *= 1.1 - Object.HardAttack *= 1.1 - Object.Piercing += 1 - if "Fléau de la chair" in Object.SpecialsRules: - Object.SoftAttack *= 1.1 - if "Fléau des chars" in Object.SpecialsRules: - Object.HardAttack *= 1.1 - if "Ignore les couverts" in Object.SpecialsRules: - Object.SoftAttack *= 1.2 - if "Blast 3'" in Object.SpecialsRules: - Object.SoftAttack *= 1.1 - Object.HardAttack *= 0.4 - if "Blast 5'" in Object.SpecialsRules: - Object.SoftAttack *= 1.2 - Object.HardAttack *= 0.6 - if "Krak Grenade" in Object.SpecialsRules: - Object.SoftAttack *= 0 - if "Fusion" in Object.SpecialsRules: - Object.HardAttack *= 1.5 -# Weapons type - if Object.Type == "Lourde": pass - if Object.Type == "Assaut": pass - if Object.Type == "Tir rapide": pass - if Object.Type == "Salve": pass - if Object.Type == "Ordnance": - Object.SoftAttack *= 1.5 -# Weapon Range - if Object.Range == (0 or None): # melee weapons + # Weapons Specials rules + Rules = Weapon.SpecialsRules + if "Perforant" in Rules: + Weapon.SoftAttack *= 1.1 + Weapon.HardAttack *= 1.1 + Weapon.Piercing += 1 + if "Fléau de la chair" in Rules: + Weapon.SoftAttack *= 1.1 + if "Fléau des chars" in Rules: + Weapon.HardAttack *= 1.1 + if "Ignore les couverts" in Rules: + Weapon.SoftAttack *= 1.2 + if "Blast 3'" in Rules: + Weapon.SoftAttack *= 1.1 + Weapon.HardAttack *= 0.4 + Weapon.Piercing *= 0.6 + if "Blast 5'" in Rules: + Weapon.SoftAttack *= 1.2 + Weapon.HardAttack *= 0.6 + Weapon.Piercing *= 0.6 + if "Krak Grenade" in Rules: + Weapon.SoftAttack *= 0 + if ("Melta" or "Fusion") in Rules: + Weapon.HardAttack *= 1.5 + if "Defensive Grenade" in Rules: + Weapon.Defense_bonus += 0.15 + if "Assault Grenade" in Rules: + Weapon.Breakthrought_bonus += 0.15 + if "Gets Hot" in Rules: pass - elif Object.Range <= 8: - Object.SoftAttack *= 0.4 - Object.HardAttack *= 0.4 - elif 8 < Object.Range <= 18: - Object.SoftAttack *= 0.6 - Object.HardAttack *= 0.6 - elif 18 < Object.Range <= 24: - Object.SoftAttack *= 0.8 - Object.HardAttack *= 0.8 - elif 24 < Object.Range <= 30: - Object.SoftAttack *= 1.2 - Object.HardAttack *= 1.2 - elif 30 < Object.Range <= 36: - Object.SoftAttack *= 1.4 - Object.HardAttack *= 1.4 - elif 36 < Object.Range <= 48: - Object.SoftAttack *= 1.6 - Object.HardAttack *= 1.6 - elif 36 < Object.Range <= 48: - Object.SoftAttack *= 1.8 - Object.HardAttack *= 1.8 - elif 48 < Object.Range <= 72: - Object.SoftAttack *= 2.0 - Object.HardAttack *= 2.0 - elif 72 < Object.Range <= 96: - Object.SoftAttack *= 2.2 - Object.HardAttack *= 2.2 - elif 96 < Object.Range <= 120: - Object.SoftAttack *= 2.4 - Object.HardAttack *= 2.4 - elif 120 < Object.Range <= 240: - Object.SoftAttack *= 3.0 - Object.HardAttack *= 3.0 + ######################################################################################################################## -def setWeapons_DEFBRK_bonus(Object): # sourcery skip: switch +def apply_WeaponsType(Weapon): # sourcery skip: switch + # Weapons type - if Object.Type == "Lourde": - Object.Defense *= 1.8 - Object.Breakthrought *= 0.2 - elif Object.Type == "Assaut": - Object.Defense *= 0.6 - Object.Breakthrought *= 1.4 - elif Object.Type == "Tir rapide": + if Weapon.isGrenade(): # Pour que les grenades ne soient pas affectés par ces bonus + Weapon.Defense_bonus = 0 # Les grenades sont des armes particulières, les valeurs sont mises a 0 + Weapon.Breakthrought_bonus = 0 # pour ne pas gonfler les stats des compagnies + elif Weapon.Type == "Lourde": + Weapon.Defense_bonus += 0.50 + Weapon.Breakthrought_bonus += -0.1 + elif Weapon.Type == "Assaut": + Weapon.Defense_bonus += 0 + Weapon.Breakthrought_bonus += 0.50 + elif Weapon.Type == "Tir rapide": pass - elif Object.Type == "Salve": - Object.Breakthrought *= 1.2 - Object.Defense *= 0.8 - elif Object.Type == "Ordnance": - Object.Breakthrought *= 2 - Object.Defense *= 0.4 - # Weapon Range - if Object.Range == (0 or None): # melee weapons - Object.Defense *= 0.3 - Object.Breakthrought *= 0.6 - elif Object.Range <= 8: - Object.Defense *= 0.6 - Object.Breakthrought *= 0.8 - elif 8 < Object.Range <= 18: - Object.Defense *= 0.8 - Object.Breakthrought *= 0.9 - elif 18 < Object.Range <= 24: - Object.Defense *= 1 - Object.Breakthrought *= 1 - elif 24 < Object.Range <= 30: - Object.Defense *= 1.2 - Object.Breakthrought *= 1.1 - elif 30 < Object.Range <= 36: - Object.Defense *= 1.4 - Object.Breakthrought *= 1.2 - elif 36 < Object.Range <= 48: - Object.Defense *= 1.6 - Object.Breakthrought *= 1.3 - elif 48 < Object.Range <= 72: - Object.Defense *= 1.8 - Object.Breakthrought *= 1.4 - elif 72 < Object.Range <= 96: - Object.Defense *= 1.8 - Object.Breakthrought *= 1.4 - elif 96 < Object.Range <= 120: - Object.Defense *= 2.0 - Object.Breakthrought *= 1.5 - elif 120 < Object.Range <= 240: - Object.Defense *= 2.5 - Object.Breakthrought *= 1.8 + elif Weapon.Type == "Salve": + Weapon.Breakthrought_bonus += 0.2 + Weapon.Defense_bonus += 0.05 + elif Weapon.Type == "Ordnance": + Weapon.Breakthrought_bonus += 0 + Weapon.Defense_bonus += 0 + + # Weapon Range #Commented + if Weapon.Range == (0 or None): # melee weapons + Weapon.Defense_bonus = 0 + Weapon.Breakthrought_bonus = 0 + elif Weapon.Range <= 8: + Weapon.SoftAttack *= 0.4 + Weapon.HardAttack *= 0.4 + elif 8 < Weapon.Range <= 18: + Weapon.SoftAttack *= 0.6 + Weapon.HardAttack *= 0.6 + elif 18 < Weapon.Range <= 24: + Weapon.SoftAttack *= 0.8 + Weapon.HardAttack *= 0.8 + elif 24 < Weapon.Range <= 30: + Weapon.SoftAttack *= 1.2 + Weapon.HardAttack *= 1.2 + elif 30 < Weapon.Range <= 36: + Weapon.SoftAttack *= 1.4 + Weapon.HardAttack *= 1.4 + elif 36 < Weapon.Range <= 42: + Weapon.SoftAttack *= 1.6 + Weapon.HardAttack *= 1.6 + elif 42 < Weapon.Range <= 48: + Weapon.SoftAttack *= 1.8 + Weapon.HardAttack *= 1.8 + elif 48 < Weapon.Range <= 72: + Weapon.SoftAttack *= 2.0 + Weapon.HardAttack *= 2.0 + elif 72 < Weapon.Range <= 96: + Weapon.SoftAttack *= 2.2 + Weapon.HardAttack *= 2.2 + elif 96 < Weapon.Range <= 120: + Weapon.SoftAttack *= 2.4 + Weapon.HardAttack *= 2.4 + elif 120 < Weapon.Range <= 240: + Weapon.SoftAttack *= 3.0 + Weapon.HardAttack *= 3.0 + """ + if Weapon.Range == (0 or None): # melee weapons + Weapon.Defense *= 0.3 + Weapon.Breakthrought *= 0.6 + elif Weapon.Range <= 8: + Weapon.Defense *= 0.6 + Weapon.Breakthrought *= 0.8 + elif 8 < Weapon.Range <= 18: + Weapon.Defense *= 0.8 + Weapon.Breakthrought *= 0.9 + elif 18 < Weapon.Range <= 24: + Weapon.Defense *= 1 + Weapon.Breakthrought *= 1 + elif 24 < Weapon.Range <= 30: + Weapon.Defense *= 1.2 + Weapon.Breakthrought *= 1.1 + elif 30 < Weapon.Range <= 36: + Weapon.Defense *= 1.4 + Weapon.Breakthrought *= 1.2 + elif 36 < Weapon.Range <= 48: + Weapon.Defense *= 1.6 + Weapon.Breakthrought *= 1.3 + elif 48 < Weapon.Range <= 72: + Weapon.Defense *= 1.8 + Weapon.Breakthrought *= 1.4 + elif 72 < Weapon.Range <= 96: + Weapon.Defense *= 1.8 + Weapon.Breakthrought *= 1.4 + elif 96 < Weapon.Range <= 120: + Weapon.Defense *= 2.0 + Weapon.Breakthrought *= 1.5 + elif 120 < Weapon.Range <= 240: + Weapon.Defense *= 2.5 + Weapon.Breakthrought *= 1.8 + """ + # Weapons Fire rate - Object.Breakthrought *= 1.1*(Object.Cadence-1) - Object.Defense *= 1.1*(Object.Cadence-1) \ No newline at end of file + Weapon.Breakthrought_bonus += 0 #1.1**(Weapon.Cadence - 1) + Weapon.Defense_bonus += 0 #.1**(Weapon.Cadence - 1) + Weapon.SoftAttack *= 1.1**(Weapon.Cadence - 1) + Weapon.HardAttack *= 1.1**(Weapon.Cadence - 1) \ No newline at end of file diff --git a/Lists/Companies_list.py b/Lists/Companies_list.py index 4562286..1ec4e9a 100644 --- a/Lists/Companies_list.py +++ b/Lists/Companies_list.py @@ -1,3 +1,7 @@ +""" +TODO + - Ajouter les armes manquantes +""" from W40K.Lists.Unit_list import * from W40K.Class.Company import Company @@ -11,23 +15,23 @@ KrakGrenades.__copy__(100)]) Guardsmens_100C = Company(Unit= Gardes.__copy__(100), - Equipement=[ Lasgun.__copy__(85), + Equipement=[ Lasgun.__copy__(90), PlasmaGun.__copy__(5), - BolterLD.__copy__(10), - FragGrenades.__copy__(100), - KrakGrenades.__copy__(100), + BolterLD.__copy__(6), + FragGrenades.__copy__(60), + KrakGrenades.__copy__(40), Bayonet.__copy__(100)]) +DKK_LineInfantryCompany_IA5 = Company(Unit = Gardes_DKK.__copy__(600), + Equipement=[ + Lasgun.__copy__(7*6*10), + PlasmaGun.__copy__(2*10), + # Flamer._copy_(1*10) + MeltaGun.__copy__(1*10), + #GrenadeLauncher.__copy__(1*10), + ]) -Spaces_100A = Company(Unit= SpaceMarines.__copy__(100), - Equipement=[ Bolter.__copy__(85), - PlasmaGun.__copy__(5), - CanonLaser.__copy__(2), - MeltaGun.__copy__(3), - BolterLD.__copy__(5), - FragGrenades.__copy__(100), - KrakGrenades.__copy__(100)]) -Spaces_100B = Company(Unit= SpaceMarines.__copy__(100), +Spaces_Tactical = Company(Unit= SpaceMarines.__copy__(100), Equipement=[ Bolter.__copy__(85), PlasmaGun.__copy__(5), CanonLaser.__copy__(2), @@ -36,4 +40,28 @@ FragGrenades.__copy__(100), KrakGrenades.__copy__(100), Astartes_CCW.__copy__(100)]) -Basilisk_40A = Company(Unit= Basilisk.__copy__(40)) \ No newline at end of file + +Spaces_Devastator = Company(Unit= SpaceMarines.__copy__(100), + Equipement=[ Bolter.__copy__(50), + PlasmaGun.__copy__(10), + CanonLaser.__copy__(5), + MeltaGun.__copy__(5), + BolterLD.__copy__(25), + FragGrenades.__copy__(100), + KrakGrenades.__copy__(100), + Astartes_CCW.__copy__(50)]) + +Spaces_Assault = Company(Unit= SpaceMarines.__copy__(100), + Equipement=[ BoltPistol.__copy__(90), + PlasmaPistol.__copy__(10), + MeltaBomb.__copy__(10), + FragGrenades.__copy__(100), + KrakGrenades.__copy__(100), + Astartes_CCW.__copy__(100)], + Upgrade=[Upgrade(Name="Jump Pack",BRK=1.3,Quantity=100)]) + +Basilisk_15A = Company(Unit= Basilisk.__copy__(15)) + +Predator_9A = Company(Unit= Predator_A.__copy__(9)) + +Earthshaker_Company = Company(Unit=Earthshaker_Platform.__copy__(12)) \ No newline at end of file diff --git a/Lists/Tactics_list.py b/Lists/Tactics_list.py index 7bf8c1c..f3d3e2f 100644 --- a/Lists/Tactics_list.py +++ b/Lists/Tactics_list.py @@ -1,5 +1,6 @@ from W40K.Class.Tactics import Tactic +######################################################################################################################## ## ATTACKS ATK_tactics = [ Tactic(ATK_Damage=1.05,CAC=0,Name="Attaque", @@ -25,7 +26,6 @@ BeginPhase="Seize Bridge"), Tactic(DEF_Damage=1.1,ATK_Damage=1.1,CAC=.5,weight=0,Name="Mass Charge"), ] - ## DEFENSES DEF_tactics = [ Tactic(DEF_Damage=1.05,Name="Defense"), @@ -45,7 +45,6 @@ BeginPhase="Hold Bridge"), ] - ######################################################################################################################## ## Close Quarter Attack ATK_CQ_tactics = [ @@ -54,7 +53,6 @@ Tactic(ATK_Damage=1.05,DEF_Damage=1.05,weight=1,CAC=-0.3,Name="Close Quarter Withdraw", BeginPhase="Default"), ] - ## Close Quarter Defense DEF_CQ_tactics = [ Tactic(ATK_Damage=1.1,DEF_Damage=1.05,Name="Close Quarter Defense"), @@ -70,21 +68,18 @@ Tactic(ATK_Damage=0.95,DEF_Damage=0.90,CAC=0.4,Name="Intercept", BeginPhase="Default"), ] - ## Tactical withdraw Defend DEF_TW_tactics = [ Tactic(ATK_Damage=0.7,DEF_Damage=0.95,CAC=-0.3,Name="Withdrawal"), Tactic(ATK_Damage=0.6,DEF_Damage=0.9,CAC=-0.5,Name="Evade"), ] - ######################################################################################################################## ## Seize Bridge Attacks ATK_SB_tactics = [ Tactic(ATK_Damage=1.2,DEF_Damage=1,CAC=0,Name="Hold Bridge"), Tactic(ATK_Damage=1.2,DEF_Damage=0.9,CAC=0,Name="Defend Bridge"), ] - ## Seize Bridge Defend DEF_SB_tactics = [ Tactic(ATK_Damage=1,DEF_Damage=0.95,CAC=0.1,Name="Bridge Assaut"), @@ -94,7 +89,6 @@ BeginPhase="Hold Bridge"), ] - ######################################################################################################################## ## Hold Bridge Attacks ATK_HB_tactics = [ @@ -104,9 +98,14 @@ CounteredBy="Defend Bridge", BeginPhase="Seize Bridge"), ] - ## Hold Bridge Defend DEF_HB_tactics = [ Tactic(ATK_Damage=1.2,DEF_Damage=0.9,CAC=0,Name="Hold Bridge"), Tactic(ATK_Damage=1.1,DEF_Damage=1.05,CAC=0,Name="Defend Bridge"), ] + +######################################################################################################################## +######################################################################################################################## + +ATK_all_tactics = ATK_tactics + ATK_HB_tactics + ATK_SB_tactics + ATK_TW_tactics + ATK_CQ_tactics +DEF_all_tactics = DEF_tactics + DEF_HB_tactics + DEF_SB_tactics + DEF_TW_tactics + DEF_CQ_tactics diff --git a/Lists/Terrain_list.py b/Lists/Terrain_list.py new file mode 100644 index 0000000..8c0f893 --- /dev/null +++ b/Lists/Terrain_list.py @@ -0,0 +1,12 @@ +from W40K.Class.Terrain import Terrain + +Terrain_dico = { + "Plains": Terrain((90,45),Attrition=0,AttackMalus=1,AirSuperiorityMalus=1), + "Desert": Terrain((90,45),Attrition=.2,AttackMalus=1,AirSuperiorityMalus=1), + "Forest": Terrain((84,42),Attrition=0,AttackMalus=0.8,AirSuperiorityMalus=0.9), + "Hills": Terrain((80,40),Attrition=0,AttackMalus=0.7,AirSuperiorityMalus=-0.95), + "Jungle": Terrain((84,42),Attrition=0.3,AttackMalus=0.7,AirSuperiorityMalus=0.75), + "Marsh": Terrain((78,26),Attrition=0.5,AttackMalus=0.6,AirSuperiorityMalus=1), + "Moutain": Terrain((75,25),Attrition=0.4,AttackMalus=0.4,AirSuperiorityMalus=0.9), + "Urban": Terrain((96,32),Attrition=0,AttackMalus=0.7,AirSuperiorityMalus=0.5), +} \ No newline at end of file diff --git a/Lists/Unit_list.py b/Lists/Unit_list.py index 0d2d0d3..ab98562 100644 --- a/Lists/Unit_list.py +++ b/Lists/Unit_list.py @@ -1,21 +1,28 @@ -""" -FIXME - 1) Basilik.Type = "Tank" - - Cause une erreur dans les fonctions set_Defense/set_Breakthrough (DEF/BRK == 0 car non trouvé) -""" from W40K.Class.Unit import Infantry, Tank, Walker -from W40K.Class.Weapons import Weapon +from W40K.Class.Weapons import Weapon,Upgrade + # Units -Gardes = Infantry(3, 3, 3, 3, 1, 1, 7, 5, Name="Gardes") -SpaceMarines = Infantry(4, 4, 4, 4, 1, 1, 9, 3, Name="Space Marines", SpecialRules=["Astartes"]) +Gardes = Infantry(3, 3, 3, 3, 1, 1, 7, 5, Name="Gardes", + SpecialRules=["Combined Squads","Heavy Weapons Team"]) + +Gardes_DKK = Gardes +Gardes_DKK.SpecialRules = ["Iron Discipline","Death Korps"] + +Grenadier_DKK = Infantry(3, 3, 3, 3, 11, 1, 7, 4, Name="Grenadier", + SpecialRules=["Iron Discipline","Death Korps"]) + +SpaceMarines = Infantry(4, 4, 4, 4, 1, 1, 9, 3, Name="Space Marines", + SpecialRules=["Astartes","Combats Squads","Chapter: Ultramarines"]) # Weapons Lasgun = Weapon(3,None,Type="Tir rapide",Range=24,Name="Lasgun") Bolter = Weapon(4,5,Type="Tir rapide",Range=24,Name="Bolter") -MeltaGun = Weapon(8,1,Type="Assaut",SpecialsRules=["Fusion"],Range=12,Cadence=1) -PlasmaGun = Weapon(7,2,Type="Tir rapide",Range=24,Name="Plasma Gun") +BoltPistol = Weapon(4,5,Type="Pistol",Range=12,Name="Bolt Pistol") +MeltaGun = Weapon(8,1,Type="Assaut",SpecialsRules=["Melta"],Range=12,Cadence=1) +PlasmaGun = Weapon(7,2,Type="Tir rapide",Range=24,Name="Plasma Gun",SpecialsRules=["Gets Hot"]) +PlasmaPistol = Weapon(7,2,Type="Pistol",Range=12,Name="Plasma Pistol",SpecialsRules=["Gets Hot"]) KrakGrenades = Weapon(6,4,Range=8,Type="Assaut",Cadence=1,SpecialsRules=["Krak Grenade"],Name="Krak Grenade") -FragGrenades = Weapon(3,None,Range=8,Type="Assaut",Cadence=1,SpecialsRules=["Blast 3'"],Name="Frag Grenade") +FragGrenades = Weapon(3,None,Range=8,Type="Assaut",Cadence=1,SpecialsRules=["Blast 3'","Assault Grenade"],Name="Frag Grenade") BolterLD = Weapon(5,4,Type="Lourde",Range=36,Cadence=3,Name="Bolter LD") CanonLaser = Weapon(9,1,Type="Lourde",Range=48,Cadence=1,Name="Canon Laser") Earthshaker = Weapon(9,3,Type="Ordnance",Range=240,SpecialsRules=["Barrage","Blast 5'"],Name="Earthshaker") @@ -25,22 +32,27 @@ # CAC weapons Astartes_CCW = Weapon(4,None,None,"Melee",Name="Astartes Knife") Bayonet = Weapon(3,None,None,"Melee",Name="Lasgun bayonet") +MeltaBomb = Weapon(8,1,0,Type="Melee",SpecialsRules=["Melta"],Name="Melta Bomb") # Vehicules and Artillerie LemanRuss_A = Tank(3,14,12,10,3,Type="Heavy",Name="Leman Russ") LemanRuss_A.setWeapons( TurretList=[Obusier.__copy__(1)], - HullList=[BolterLD.__copy__(1)], + HullList=[CanonLaser.__copy__(1)], SideList=[BolterLD.__copy__(2)]) + Predator_A = Tank(4,13,11,10,3,Quantity=1,Type="Tank",Name="Predator") Predator_A.setWeapons( TurretList=[Autocanon.__copy__(1)], HullList=[BolterLD.__copy__(1)], SideList=[BolterLD.__copy__(2)]) -Basilisk = Tank(3,12,10,10,3,Type="Tank",SpecialRules=["Oppen-Topped"],Name="Basillisk") + +Basilisk = Tank(3,12,10,10,3,Type="Tank",SpecialRules=["Oppen-Topped"],Name="Basilisk") Basilisk.setWeapons( TurretList=[Earthshaker.__copy__(1)], HullList=[BolterLD.__copy__(1)]) -Field_Earthshaker = Tank(3,10,10,10,2,Type="Tank",SpecialRules=["Immobile"],Name="Earthshaker") -Field_Earthshaker.setWeapons( + +Earthshaker_Platform = Tank(3, 10, 10, 10, 2, Type="Tank", SpecialRules=["Immobile"], Name="Earthshaker Platform") +Earthshaker_Platform.setWeapons( TurretList=[Earthshaker.__copy__(1)]) + diff --git a/Run.py b/Run.py index 3d72bff..2db43a6 100644 --- a/Run.py +++ b/Run.py @@ -1,20 +1,25 @@ from W40K.Lists.Companies_list import * from W40K.Class.Regiment import Regiment from W40K.Class.Battle import Battle +from W40K.Class.Leader import Leader RegA = Regiment(Name = "101st Regiment", CompagnieList = [ - Guardsmens_100B,Guardsmens_100B,Guardsmens_100B,Guardsmens_100B, - Guardsmens_100B,Guardsmens_100B,Guardsmens_100C,Guardsmens_100C, - ]) + Guardsmens_100C,Guardsmens_100C,Guardsmens_100C, + Guardsmens_100C,Guardsmens_100C,Guardsmens_100C, + Basilisk_15A,Basilisk_15A, + ],Entrenchment_level=2) RegA.isDefending = True RegB = Regiment(Name = "Ultramarines", CompagnieList = [ - Spaces_100A,Spaces_100A,Spaces_100A,Spaces_100A - ]) + Spaces_Tactical,Spaces_Tactical,Spaces_Tactical, + Spaces_Tactical,Spaces_Tactical,Spaces_Tactical, + Spaces_Devastator,Spaces_Devastator, + Spaces_Assault,Spaces_Assault, + ],XP=100) RegB.isDefending = False -BattleA = Battle(RegB,RegA) +BattleA = Battle(RegB,RegA,ATK_leader=Leader(2,3,1,["Assaut"],[]),DEF_leader=Leader(3,1,3,[],[]),Terrain="Plains",River=None) BattleA.Round(-1) \ No newline at end of file diff --git a/Yet Another Division Calculator for HOI4 1.3.xlsx b/Yet Another Division Calculator for HOI4 1.3.xlsx old mode 100755 new mode 100644