From 817397ed44a9410ca6b7565bedeec4099ef383e5 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Fri, 18 Apr 2025 23:04:16 +0000 Subject: [PATCH] Final --- __pycache__/ai.cpython-312.pyc | Bin 1497 -> 8902 bytes __pycache__/cell.cpython-312.pyc | Bin 1431 -> 1618 bytes __pycache__/cell_terrain.cpython-312.pyc | Bin 404 -> 405 bytes __pycache__/faction.cpython-312.pyc | Bin 1309 -> 1688 bytes __pycache__/params.cpython-312.pyc | Bin 1556 -> 1557 bytes __pycache__/unit.cpython-312.pyc | Bin 2300 -> 1961 bytes ai.py | 181 +++++++++++++++++++++++ cell.py | 22 +-- cell_terrain.py | 2 +- faction.py | 8 +- main.py | 81 +++++++--- params.py | 2 +- unit.py | 16 +- 13 files changed, 266 insertions(+), 46 deletions(-) diff --git a/__pycache__/ai.cpython-312.pyc b/__pycache__/ai.cpython-312.pyc index a24255d06469a0d5477774020540b1cc1a1708ec..3166d7bb30d37deaecf8ad80f996715f74796a0d 100644 GIT binary patch literal 8902 zcmeHNZ){W76@Slu{ukS^V}}@$5If)`*d?T){3#)jrU?+BBxFE0(si!!bHGkw!+Q>G zvS+m)`oT!4Fzci^6B?-+sg9r`Op^#wB|w|hcAL~XFKxU>J|L~q#J3cXChgPCdG@nk zG6zCSsXFa`IQP#x_y0NPp5MLiuSR1L0pa$H;#5TgLHq+VQlPSl2b&==O3(yN_7fi~ zNK7gE$sSUS6+H?Cv5%mY?-De1S&^yJqa0GWRQE9BA_daj>C2R7D4ESXa6@90@Dtcn zkAf!OC3=*!0w{&e^{8kHsG3#*)eNa!8bQ&z-zU|UT2w;f0giQ)7=qq9C$US4_4oI( z$m;mFz2VI;)5o6n`uuEzFU)S)@nZd1Z~dt^w={SIn@$f2T8}3X3Pe1fVSVfVO;V-` zDzhpe?+|IN;Q=HFpBia4;KGT0e*@i&5+{kMnp1M*8YqrxBDqmUkVgy=Y)lNC=5qG? z(m1M(Xe6$nR!Ze#PAk4N_S?mbG1+FO^apZYWt! zNIhK6jyzh#se>gFS3c&7BuYgJ4)#o2#1=FGMS--5FtC&GS5Q=)ezDOV(@&sr>n@zLOU?39kvw~_6dSV6Y z%p(4hmYFfrkz-EXsysQDAg9 z0yQ%j@^}NoI?$3#5~Pn{zXb9Qv7jZ)mKe2AOsuL%G^I*wW4d`;#l<}n>&F8hZsIE& zdE4fgVP0E&zW7{moSW4;?^vp0FV9=njW?z38
  • =$ySFWp9|b*IbH@MUy?#is_Q% zuXua&1C_$MJJzT!3{dzGG~r#g7cu2@^zV9vLwAuQz!2Etq# z(=(`1i_{&}5*6YBom2O`_;N~GRD4MYX+__5f?zh~l^;Yg%R?(f^+b!cB+$y7SZYA! za)uz!mNy)r{*t7aQDl|G z19Q{`3(N})g=9)rFs~6w-Kb7M(-R&z0piWzxgwA~E?}?&KT-4vhS!JA4)kIr>awqEpv|T zDaZD-V?By|%_5PX1(8=jb!jhJM%qzQL}~vGEZdKExYa+&;YO1=DZ>NH1T$C?79Cg( z6d^m1!Rx2?&!~N zSKhKla_&G7Reeba;sPuQQcu!ONijGEsQqGCp=0nk8G5hqibRXK;vgECB_W9BW=Vh+ zR>(OF7JZp^9ZMR8>@w{Z;KX)&6;V@Uz0?Y4qLp%OSoB3B|I*hEd-c_7$ ztD$}5a%687iWxcu@`#{n8)W>n z=p5d|OA3K(`{(b*Fx+Ti(1j7mJp%c2f$Y3TLC#g0@ek3gXZ%Rfam4dyiAO0IeS-|+ z4@Hi8nUnrV#;;1{#2&H{|ns0P+dNzCn32F7ry9&}tmc zIwWY2MW0mAN5TeCx!_#*Xyrs>E<=wL7+dzQR7Cn(!rEABK3xR=#3e?3H^oBS9R)kjIMlYaiJny1hUB)Xy2+MQSyN08bG6vw!(WxG zi?t%CEjj=8xwprkn=#ct1pm8ybk~Jl@3)K}nXzujBGoHL|LDB#zUIE(aIJyg+{V|p z^Y%UQj`?y|(mmz9PG6&^JNWWF@wRm7>d}K24vs5lOP%Rbbmz+}F4@QIaWy2J?vI*2 zX!@x6gXXE~>owPEuGd|wORe8Az3pbxji#H;H<~}I{-WmdnlI`;uS@Oh{&L;V;wBuA zE&lfSnUu}NTisWVOxbUhq#AJqGuHOBtycV!Y@M;y&sWtagVWVFoj07flzdhDnDU$d zD!Kb)6%xw3=F(C91%0Az*6hfP<;>{dg~2(S3kH;|MF7s*w({0()77)qo%6Qx#7^E; zmu#G|ZJc*Mf3<$Hep=7F+Y{tP)7{mTm-J)$iLR*wx5!Va+tiQMT-)cYFhZG1ja{riT8MYw{$=B?|;&%lO$ zviIhp8;3r7j&FW7S^aTC+EpL-&X(2AS5#lxHMZ+Y=@t5Fa58u`JQ?OUweYT&_=?uJ zcD}4;JP3Q{yyl$N@@1`YWm;O7ug#7HxUaOVU+5(t2ekeIaQ}Z5XcYn&05(J?vjEt5 z9d8boajlJ=^`yN)GnkSz!-RC4$rbDT}ITK**mEJS`%fQ1~0Ag~Ze@dW+J zfyq+`7NV?^Y@=+QRt_)K7dxN5;?blD+kfwa#6nF?Os&;(v|u@!~CF0{FFMi7!nENS7iL$Y;Qb zAq!3beEI2NQy!Rz1z$i_cI`6*CGZlI#XQNfDP771Z(2>$uiiSC+I2WpdN`(AgcH<6 znQhc_!4uni*R(3JX2!Jc>4SxzI6}Bt^}2?uwQB!Ye}BuE4HRLZBDda?D~6U^|uSMtC#d6T+9ebRe#;Ksn;+Go3u&2_()>V9pm`;Aoh8+`W({uLj; zo8~M1v*zBcr~ahXVC%E6&^cqOO;+PGGwbfUW3P+vOWUf(0sd@EJ6*}T ziOxj3Z0IVY=7j|n;n=WHlpX)~f*5@w#0beCMyE@Qe>H@>1AdQ3DDrp)!t`K2rVSp? znL%%V<_iP%nP9-26U;^=tw=hM02m>}H&9VA8T@lWB&fcu1IW9?{W4NzynleKQkCBC zAT2=Mhe=iGgI>ixh%%M2o{JJRzRVMN=AmvM6lPjn+>4-X&J1%ma|l@Qsh!2U@dYJG bk`Jp0vg{6FyhG^!MYU06>3ssJ*v)?c3l=vA delta 101 zcmX@+dXt;)G%qg~0}vcO!I-g(ee9-NVwl3!k|Ia!-YhgAZoqC=wb|r>tm1&lu}pF{vZ^bDXT?t_x*%Y@K@mvY5tO|ysCrRQ^|~O~ zp)x8fm}mJ9 zR|Iu#h%0?yW)RXX;+ky6xJmLQ6HspvnBW7kgn>jcBaoOpomrbz7RdNKIhIL5O5%>7 z>~%rai-M}x1tG>rAR7ZQK@4O9nlX&5x|}K?aS4#2?W{(sA|RePh>!vjD;bJF?l0m1 z5iBr5VDddy33JKMe5|aJ5P6W4CQ}hVOhu6#hy~Yri^C>2KczG$)vic>vM!rAADbkj LlMNYz1O+-$`ZGH- OzcMf}3Ka1Gl>-1DKoLX$ delta 59 zcmbQrJcXI}G%qg~0}x2Ke@VYPk@pNcn_GTSYH`WLhrTSle2s3CjTnOj`8!hjGdnZC NGB7dn7x4g90{{wU5aj>> diff --git a/__pycache__/faction.cpython-312.pyc b/__pycache__/faction.cpython-312.pyc index 9ff820ccd5486326b64647f76b195db65b7472cd..0f6e0da17a63f7e020ae4605b45ce93ebd35eded 100644 GIT binary patch delta 573 zcmbQsHG`M$G%qg~0}!+nGi4;PY~;Jm#Hcy>6;nNv0psL{j8YaAj46!S8Vn3YT8s=e z3|UMdwWuJA6_pR-)i6wEWD=RYo>>TF022WN*zp-)lEMtuu8G5TPJEhUDj76c{BE&F z<>w}4rWW7g3@$Ay%Ph+;D!#?)Tw0WxqRCps1~j0E14!KBD=N*4Pt1(3f~ppP@{8e` zc%UN5Aia}sF`L%kVuJ`(@wp`?mt^MW=|T9?Km&_wfJ6hs4L+g%^v?9Vf>JlcrKguq zEWa+Udr@3>Maug0mFXKQ4v3u)y$}#`Sv>TDK8L*77xB45d49eK}d44AB#Dg zD9D3~le<|=W!YIn7>oEod=?;~$#jdQG%vFR%qdcxe3wN+Lmep22*kx=K;i>4BO~Ky UJ_bgf?`#r`A&j3GKqS}z07?{&eE^G%qg~0}%X){*rFZypiuV6XVLsubAo?Lnc39lxE6eo}9=c%E$sFg(n-Z z2uc=-02OO87jXcoTWm$8dGU#vMQlLMyIGb5|p sWIHxVDFu)aABf-q61O;Pa`RJ4b5iY!lqMIlN$?9Xx-ouY0Fhut06^L}vj6}9 diff --git a/__pycache__/params.cpython-312.pyc b/__pycache__/params.cpython-312.pyc index fd51a0b7c279fc464deef271e8d988f5a15da62a..d195f368fd16bbf289178c48782a8078f32ebf88 100644 GIT binary patch delta 47 zcmbQjGnI$;G%qg~0}$LPW6Chw$ord_gFQGSF(tpecr!l>HzS+EMHYnxijx&szW@L$ Ca}6#4 delta 46 zcmbQrGlhruG%qg~0}x2Ke@Qpp$ord_oy{%3D7Cm`vj7V>Bb)q17WoB&lNDLN000@& B46^_L diff --git a/__pycache__/unit.cpython-312.pyc b/__pycache__/unit.cpython-312.pyc index d0cbe04dc2310d23f47c5cd5c773563ecced020b..3f81f24a21952c67cdcfa5a5d288878d34504088 100644 GIT binary patch delta 713 zcmY+B&ubG=5Xax!>?UjDHfoZ#skUq)#%#e@MMOaYCH_c6A~f4V1xZ7)X&2Jn^0Gl1 z3iVK^h?npVy%szb{{;^s2!fa5kITb0g`^KT;!6OgATY;b!*@UE1b6q$ur0z8;21F>Rd2Hte=p6Ih1TjbW;veOWNVfOcXH3_cGxr&vJ~Ph;v8ZI zF$?ISxE>ly^L!*r%e)e~seM*6-=btT_e}nxPV?Q!^YekA6pq75hQxF@1a*73yskt4 z6?uv-^84~-n&Sg`doAcugtk4oi=StuW(1OI=p|4 zVc_E*G9(dYO{eW{h!~!>;~jsO>TWjr-qxn|pT5l8Zg+4ZP)BzahV+tvr{rrgvtJsP z4zdS}pOS^6lLeN8e9ho*WBHvdxara95}xCUHj`TW9pnNVqJl z4?!V4B=ev_&`J*}{R=@a5>EL41g4|@8L}2MtRc%&P^TAO=w>!MW zurn)kVwp-6icCgyL!(2fjC!>{nMn-~rCDxnki8qc(tj;8=%u&!oS>oIQzyp8ZQV5X zpQsxX+PJ-YqPIxXRIC-o{F)eOgF|M>8inZ<>|B2PA_2@ z6>t{cZKI#3rGTcYK6}P2$97{j#4wuzg&NE9S>fgGDQVF3qFM^Y-;0X>CF(`}DN(PC znna5=iK6|P{Z5_#+ zQRnRW8ExNv3dGFi@&VRAFuhHstOCUX+6smrTZ@-g>}UBW`L*T_D0hr phCnBiD22?l$yr#-0QS#Gz0+oPE~oX8^G>&aGIRYegHiL=K%l! diff --git a/ai.py b/ai.py index ac00d85..3893d8b 100644 --- a/ai.py +++ b/ai.py @@ -95,3 +95,184 @@ class AI: # return all the command objects. return cmds + + + # Needs Seperate AI's for each faction + + # AI for Zombies + def run_ai_zombies(self, faction_id, factions, cities, units, gmap): + cmds = [] + + # Generate Zombies (Typically Done Only At Start) + # Verify there are remaining zombie cities + if (len(cities['Zombies']) != 0): + cmd = BuildUnitCommand(faction_id, + cities['Zombies'][0].ID, + "Z") + cmds.append(cmd) + + # Random moves (zombies) + my_units = units[faction_id] + for u in my_units: + rand_dir = random.choice(list(vec2.MOVES.keys())) + cmd = MoveUnitCommand(faction_id, u.ID, rand_dir) + cmds.append(cmd) + + return cmds + + # AI for Survivors + def run_ai_survivors(self, faction_id, factions, cities, units, gmap): + cmds = [] + + # Attempts to create new survivors via reproduction + my_cities = cities[faction_id] + city_indexes = list(range(len(my_cities))) + random.shuffle(city_indexes) + for ci in city_indexes: + cmd = BuildUnitCommand(faction_id, + my_cities[ci].ID, + "S") + cmds.append(cmd) + + # Rare case + # If cured city is lost, and there are adequate survivors to make a new cured city + # one survivor city at random can produce a cured unit + if (len(cities['Cured']) == 0) and (len(units[faction_id]) >= 50): + my_cities = cities[faction_id] + city_indexes = list(range(len(my_cities))) + random.shuffle(city_indexes) + cmd = BuildUnitCommand("Cured", + my_cities[city_indexes].ID, + "C") + cmds.append(cmd) + + # Survivors will also attempt to defend cured cities + totalCities = cities[faction_id] + cities['Cured'] + + # Loop through all of the survivors + for u in units[faction_id]: + # First checks to see if the survivor was given another tasking previously (i.e defend x city) + # If so, verify city had not fallen and move towards it + # If within 3 tiles of city, pick another target + if u.currentTarget in totalCities: + + # 10% chance of random movement + if random.random() < 0.1: + rand_dir = random.choice(list(vec2.MOVES.keys())) + cmd = MoveUnitCommand(faction_id, u.ID, rand_dir) + cmds.append(cmd) + continue + + # Target is a city, so move towards it + target = u.currentTarget + + #Given current position as (x,y) and target as (x,y), calculate next move to get closer to city + vectorDirection = (target.pos.x - u.pos.x, target.pos.y - u.pos.y) + + # X is larger, move that way first + if abs(vectorDirection[0]) > abs(vectorDirection[1]): + if vectorDirection[0] > 0: + cmd = MoveUnitCommand(faction_id, u.ID, 'E') + else: + cmd = MoveUnitCommand(faction_id, u.ID, 'W') + else: + if vectorDirection[1] > 0: + cmd = MoveUnitCommand(faction_id, u.ID, 'S') + else: + cmd = MoveUnitCommand(faction_id, u.ID, 'N') + + cmds.append(cmd) + + # Too close to city, so pick another target + if abs(u.pos.distance_man(target.pos)) <= 4: + if len(totalCities) != 0: + u.currentTarget = random.choice(totalCities) + # 2 Actions to prevent clumping + cmds.append(MoveUnitCommand(faction_id, u.ID, random.choice(list(vec2.MOVES.keys())))) + cmds.append(MoveUnitCommand(faction_id, u.ID, random.choice(list(vec2.MOVES.keys())))) + else: u.currentTarget = None + + else: + # City has fallen, so clear target + # Establish new target (if available) and move randomly + if len(totalCities) != 0: u.currentTarget = random.choice(totalCities) + else: u.cuurrentTarget = None + rand_dir = random.choice(list(vec2.MOVES.keys())) + cmd = MoveUnitCommand(faction_id, u.ID, rand_dir) + cmds.append(cmd) + + return cmds + + # AI for Cured + def run_ai_cured(self, faction_id, factions, cities, units, gmap): + cmds = [] + + # Attempts to create new cured + my_cities = cities[faction_id] + city_indexes = list(range(len(my_cities))) + random.shuffle(city_indexes) + for ci in city_indexes: + cmd = BuildUnitCommand(faction_id, + my_cities[ci].ID, + "C") + cmds.append(cmd) + + allCities = cities[faction_id] + cities['Zombies'] + cities['Survivors'] + + # Loop through all of the cured + for u in units[faction_id]: + # Once there are cured in the world, they will attempt to "infect" any cities on the map, one at a time + # Check if we are currently targeting a city + target = u.currentTarget + + if target in allCities: + + # 10% chance of random movement + if random.random() < 0.1: + rand_dir = random.choice(list(vec2.MOVES.keys())) + cmd = MoveUnitCommand(faction_id, u.ID, rand_dir) + cmds.append(cmd) + continue + + #Given current position as (x,y) and target as (x,y), calculate next move to get closer to city + vectorDirection = (target.pos.x - u.pos.x, target.pos.y - u.pos.y) + + # X is larger, move that way first + if abs(vectorDirection[0]) > abs(vectorDirection[1]): + if vectorDirection[0] > 0: + cmd = MoveUnitCommand(faction_id, u.ID, 'E') + else: + cmd = MoveUnitCommand(faction_id, u.ID, 'W') + else: + if vectorDirection[1] > 0: + cmd = MoveUnitCommand(faction_id, u.ID, 'S') + else: + cmd = MoveUnitCommand(faction_id, u.ID, 'N') + + cmds.append(cmd) + + if (target not in allCities) or (abs(u.pos.distance_man(target.pos)) <= 4): + # Pick first city that is not already Cured and target it + if len(allCities) != 0: + for city in allCities: + if city.faction_id != "Cured": + u.currentTarget = city + break + else: u.currentTarget = None + + cmds.append(MoveUnitCommand(faction_id, u.ID, random.choice(list(vec2.MOVES.keys())))) + cmds.append(MoveUnitCommand(faction_id, u.ID, random.choice(list(vec2.MOVES.keys())))) + + # No cities left to infect, so target remaining uncured units + if u.currentTarget == None or u.currentTarget.faction_id == "Cured": + for faction in factions: + if faction != faction_id: + for unit in units[faction]: + u.currentTarget = unit + break + else: u.currentTarget = None + rand_dir = random.choice(list(vec2.MOVES.keys())) + cmd = MoveUnitCommand(faction_id, u.ID, rand_dir) + cmds.append(cmd) + + return cmds \ No newline at end of file diff --git a/cell.py b/cell.py index 23d1491..6e595a6 100644 --- a/cell.py +++ b/cell.py @@ -12,7 +12,9 @@ import cell_terrain - +# Modified +# Open: -2 for Zombies +# Shadows: +4 for Zombies class Cell: def __init__(self, terrain): self.terrain = terrain @@ -23,19 +25,19 @@ class Cell: match self.terrain: case cell_terrain.Terrain.Open: return "cornsilk2" - case cell_terrain.Terrain.Forest: + case cell_terrain.Terrain.Shadows: return "cornsilk3" - def get_attack_mod(self): + def get_attack_mod(self, unitType): match self.terrain: case cell_terrain.Terrain.Open: - return 2 - case cell_terrain.Terrain.Forest: - return 0 + return -2 if unitType == "Z" else 0 + case cell_terrain.Terrain.Shadows: + return 4 if unitType == "Z" else 0 - def get_defense_mod(self): + def get_defense_mod(self, unitType): match self.terrain: case cell_terrain.Terrain.Open: - return 0 - case cell_terrain.Terrain.Forest: - return 2 + return -2 if unitType == "Z" else 0 + case cell_terrain.Terrain.Shadows: + return +4 if unitType == "Z" else 0 diff --git a/cell_terrain.py b/cell_terrain.py index 006a525..4f8c39d 100644 --- a/cell_terrain.py +++ b/cell_terrain.py @@ -8,4 +8,4 @@ import enum class Terrain(enum.Enum): Open = 0 - Forest = 1 + Shadows = 1 diff --git a/faction.py b/faction.py index fea3eb4..0c3b05c 100644 --- a/faction.py +++ b/faction.py @@ -25,4 +25,10 @@ class Faction: # ################################################################ def run_ai(self, factions, cities, units, gmap): - return self.ai.run_ai(self.ID, factions, cities, units, gmap) + match self.ID: + case "Zombies": + return self.ai.run_ai_zombies(self.ID, factions, cities, units, gmap) + case "Survivors": + return self.ai.run_ai_survivors(self.ID, factions, cities, units, gmap) + case "Cured": + return self.ai.run_ai_cured(self.ID, factions, cities, units, gmap) diff --git a/main.py b/main.py index 7bb52fe..984d4c9 100644 --- a/main.py +++ b/main.py @@ -99,6 +99,7 @@ class Display: def init_display(sw, sh): pygame.init() + pygame.display.set_caption('Infection') screen = pygame.display.set_mode((sw, sh)) clock = pygame.time.Clock() display = Display(screen, clock) @@ -124,7 +125,7 @@ def gen_factions(gmap): # Allows one time generation of X zombies # x = random.randint(4, 8) * 100 factions['Zombies'] = faction.Faction( - 'Zombies', random.randint(8, 16) * 100, + 'Zombies', random.randint(3, 16) * 100, ai.AI(), 'darkgreen') # Starts with normal amount of money @@ -380,8 +381,8 @@ def RunCombat(attacker, defender, cmd, factions, unit_dict, cities, gmap): def_roll = defender.roll(attacker.utype) # Add terrain modifiers. - att_roll += att_cell.get_attack_mod() - def_roll += def_cell.get_defense_mod() + att_roll += att_cell.get_attack_mod(attacker.faction_id) + def_roll += def_cell.get_defense_mod(defender.faction_id) # Damage health. defender.health -= att_roll @@ -491,11 +492,20 @@ class UnitDict: -def CheckForGameOver(cities): +def CheckForGameOver(cities, unit_dict): faction_ids_with_cities = [] for c in cities: if c.faction_id not in faction_ids_with_cities: faction_ids_with_cities.append(c.faction_id) + + # Verify all units are of same type + for unit in unit_dict.allUnits: + if unit.faction_id not in faction_ids_with_cities: + faction_ids_with_cities.append(unit.faction_id) + + if len(faction_ids_with_cities) == 2 and "Survivors" in faction_ids_with_cities and "Cured" in faction_ids_with_cities: + return True, "Cured" + return len(faction_ids_with_cities) == 1, faction_ids_with_cities[0] @@ -517,6 +527,8 @@ def GameLoop(display): # - The map_cell_size given in the Display class above. gmap = gen_game_map(40, 30) + maxY = None + factions = gen_factions(gmap) # City gen is basically locked cities = gen_cities(gmap) @@ -547,8 +559,10 @@ def GameLoop(display): speed = speed * 2 - display.screen.fill("white") + display.screen.fill("cornsilk3") + game_over = [False, None] + if ticks >= speed: ticks = 0 cities_by_faction = {} @@ -562,11 +576,7 @@ def GameLoop(display): RunAllCommands(commands, factions, unit_dict, cities, gmap) turn += 1 - game_over = CheckForGameOver(cities) - if game_over[0]: - print(f"Winning faction: {game_over[1]}") - display.run = False - + game_over = CheckForGameOver(cities, unit_dict) display.draw_map(gmap) display.draw_cities(cities, factions) @@ -575,26 +585,51 @@ def GameLoop(display): # ###########################################3 # RIGHT_SIDE UI display.draw_text(f"TURN {turn}", 805, 5, "black") - display.draw_text(f"{'Fctn':<5} {'C':>2} {'U':>3} {'M':>4}", - 805, 25, "black") - y = 45 - for fid, f in factions.items(): - num_cities = 0 - for c in cities: - if c.faction_id == fid: - num_cities += 1 - - display.draw_text(f"{fid:<5} {num_cities:>2} {len(unit_dict.unitsByFaction()[fid]):>3} {f.money:>4}", - 805, y, "black") - y += 20 + + numZombies = len(unit_dict.unitsByFaction()["Zombies"]) + numSurvivors = len(unit_dict.unitsByFaction()["Survivors"]) + numCured = len(unit_dict.unitsByFaction()["Cured"]) + totalUnits = len(unit_dict.allUnits) + + infectionRate = numZombies / totalUnits * 100 if totalUnits > 0 else 0 + cureRate = numCured / totalUnits * 100 if totalUnits > 0 else 0 + + display.draw_text("Infection Rate", 805, 45, "black") + display.draw_text(f"{infectionRate:.2f}%", 805, 65, "black") + + display.draw_text("Cure Progress", 805, 85, "black") + display.draw_text(f"{cureRate:.2f}%", 805, 105, "black") + + y = 145 + display.draw_text(f"Cities", 805, y, "black") + y += 20 + for city in cities: + display.draw_text(f"{city.ID}", 805, y, factions[city.faction_id].color) + y += 20 + + maxY = y + + if game_over[0]: + display.draw_text(f"{game_over[1]} won", 805, maxY + 20, "black") + display.draw_text("Press any key to quit", 805, maxY + 40, "black") + pygame.display.flip() + key = None + while key == None: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + display.run = False + elif event.type == pygame.KEYDOWN: + key = event.key + print(f"Winning faction: {game_over[1]}") + display.run = False pygame.display.flip() def main(): random.seed(None) - display = init_display(1000, 600) + display = init_display(1100, 600) GameLoop(display) diff --git a/params.py b/params.py index 561be31..a507f63 100644 --- a/params.py +++ b/params.py @@ -14,7 +14,7 @@ import random # algorithms here. If you want something fancier, you'd need # to add them below and call them in game_map.py. CELL_TERRAIN_PROBABILITY = { - cell_terrain.Terrain.Forest: 1, + cell_terrain.Terrain.Shadows: 1, cell_terrain.Terrain.Open: 4 } diff --git a/unit.py b/unit.py index 1aa43dd..a646065 100644 --- a/unit.py +++ b/unit.py @@ -15,8 +15,8 @@ import math # C = CURED (EXTREMELY SLOW) UNIT_COSTS = { "Z": 100, - "S": 500, - "C": 2500 + "S": 250, + "C": 2000 } # UNIT_HEALATH is a constant dictionary that holds the starting health @@ -28,7 +28,7 @@ UNIT_COSTS = { # C = CURED (HIGH HEALTH) UNIT_HEALTH = { - "Z": 5, + "Z": 6, "S": 7, "C": 7 } @@ -75,6 +75,9 @@ class Unit: # sight_radius: int - how far it sees # NOT USED. self.sight_radius = sight_radius + + # Allows for persistent target (if applicable) + self.currentTarget = None def __eq__(self, o): return self.ID == o.ID and self.faction_id == o.faction_id @@ -91,11 +94,4 @@ class Unit: # rock-paper-scissors have max damage of 20. All other # combinations are 10. Feel free to modify if you want. def roll(self, op_utype): - if op_utype == 'R' and self.utype == 'P': - return random.randint(0, 20) - elif op_utype == 'P' and self.utype == 'S': - return random.randint(0, 20) - elif op_utype == 'S' and self.utype == 'R': - return random.randint(0, 20) - else: return random.randint(0, 10)