def checkTurn(self, iGameTurn): for i in range(iNumTotalPlayers + 1): if (gc.getPlayer(i).isAlive()): iCountdown = sd.getPlagueCountdown(i) if (iCountdown > 0): iCountdown -= 1 sd.setPlagueCountdown(i, iCountdown) if (iCountdown == 2): self.preStopPlague(i) if (iCountdown == 0): self.stopPlague(i) elif (iCountdown < 0): sd.setPlagueCountdown(i, iCountdown + 1) for i in range(iNumPlagues): if (iGameTurn == sd.getGenericPlagueDates(i)): self.startPlague(i) #retry if the epidemic is dead too quickly if iGameTurn == sd.getGenericPlagueDates(i) + 4 and i > 0: iInfectedCounter = 0 for j in range(iNumTotalPlayers + 1): if (gc.getPlayer(j).isAlive() and sd.getPlagueCountdown(j) > 0): iInfectedCounter += 1 if (iInfectedCounter <= 1): self.startPlague(i)
def onCityRazed(self, argsList): city, iNewOwner = argsList if (city.getNumRealBuilding(iPlague) > 0): if (sd.getPlagueCountdown(iNewOwner) > 0): apCityList = PyPlayer(iNewOwner).getCityList() iNumCitiesInfected = 0 for pCity in apCityList: otherCity = pCity.GetCy() if (otherCity.getX() != city.getX() or otherCity.getY() != city.getY() ): #because the city razed still has the plague if (otherCity.getNumRealBuilding(iPlague) > 0): iNumCitiesInfected += 1 if (iNumCitiesInfected == 0): sd.setPlagueCountdown( iNewOwner, 0) #undo spreadPlague called in onCityAcquired()
def onCityAcquired(self, iOldOwner, iNewOwner, city): if (city.getNumRealBuilding(iPlague) > 0): if ( sd.getPlagueCountdown(iNewOwner) <= 0 and gc.getGame().getGameTurn() > getTurnForYear( con.tBirth[iNewOwner]) + utils.getTurns(iImmunity) ): #skip immunity in this case (to prevent expoiting of being immune to conquer weak civs), but not for the new born civs self.spreadPlague(iNewOwner) apCityList = PyPlayer(iNewOwner).getCityList() for pCity in apCityList: cityNear = pCity.GetCy() if (utils.calculateDistance(city.getX(), city.getY(), cityNear.getX(), cityNear.getY()) <= 3): self.infectCity(cityNear) return city.setNumRealBuilding(iPlague, 0)
def isVulnerable(self, iPlayer): iCountdown = sd.getPlagueCountdown(iPlayer) # less pickling if (iPlayer >= iNumPlayers): if (iCountdown <= 0 and iCountdown > -10): #more vulnerable return True else: pPlayer = gc.getPlayer(iPlayer) if (iCountdown == 0): #vulnerable #if (not gc.getTeam(pPlayer.getTeam()).isHasTech(con.iSanitation)): iHealth = -30 if (pPlayer.calculateTotalCityHealthiness() > 0): iHealth = int((1.0 * pPlayer.calculateTotalCityHealthiness()) / (pPlayer.calculateTotalCityHealthiness() + \ pPlayer.calculateTotalCityUnhealthiness()) * 100) - 60 if (iHealth < 15): #no spread for iHealth >= 75 years return True return False
def checkGrid(self, iCiv): pCiv = gc.getPlayer(iCiv) tCiv = gc.getTeam(pCiv.getTeam()) lTargetCivs = [] #clean it, sometimes it takes old values in memory for k in range(iNumTotalPlayers): lTargetCivs.append(0) #set alive civs to 1 to differentiate them from dead civs for k in range(iNumTotalPlayers): if gc.getPlayer(k).isAlive() and tCiv.isHasMet(k): lTargetCivs[k] = 1 #set master or vassal to 0 for k in range(iNumPlayers): if gc.getTeam(gc.getPlayer(k).getTeam()).isVassal( iCiv) or tCiv.isVassal(k): lTargetCivs[k] = 0 #if already at war for k in range(iNumTotalPlayers): if tCiv.isAtWar(k): lTargetCivs[k] = 0 lTargetCivs[iCiv] = 0 #edead: changed Rhye's code to Regions (provinces) map = CyMap() for i in range(map.numPlots()): plot = map.plotByIndex(i) if plot.isCity(): iOwner = plot.getOwner() if iOwner >= 0 and iOwner < iNumTotalPlayers and iOwner != iCiv: if lTargetCivs[iOwner] > 0: regionID = plot.getRegionID() if regionID in utils.getCoreRegions(iCiv): lTargetCivs[iOwner] += 10 elif regionID in utils.getNormalRegions(iCiv): lTargetCivs[iOwner] += 5 elif regionID in utils.getBroaderRegions(iCiv): lTargetCivs[iOwner] += 2 #srpt: important war if utils.getYear() >= -250 and utils.getYear() < -150: if iCiv == con.iRome: lTargetCivs[con.iCarthage] += 30 elif iCiv == con.iCarthage: lTargetCivs[con.iRome] += 30 #srpt: important war if utils.getYear() >= -400 and utils.getYear() < -300: if iCiv == con.iMacedon: lTargetCivs[con.iAthens] += 30 elif iCiv == con.iAthens: lTargetCivs[con.iMacedon] += 30 #srpt: important war if utils.getYear() >= -350 and utils.getYear() < -300: if iCiv == con.iQin: lTargetCivs[con.iJinState] += 30 elif iCiv == con.iJinState: lTargetCivs[con.iQin] += 30 #there are other routines for this lTargetCivs[iIndependent1] /= 3 lTargetCivs[iIndependent2] /= 3 lTargetCivs[iIndependent3] /= 3 lTargetCivs[iIndependent4] /= 3 #no random silly wars - edead for k in range(iNumTotalPlayers): if lTargetCivs[k] == 1: lTargetCivs[k] = 0 print("AIWars grid for ", iCiv) print(lTargetCivs) #normalization iMaxTempValue = -1 for k in range(iNumTotalPlayers): if (lTargetCivs[k] > iMaxTempValue): iMaxTempValue = lTargetCivs[k] if (iMaxTempValue > 0): for k in range(iNumTotalPlayers): if (lTargetCivs[k] > 0): lTargetCivs[k] = lTargetCivs[k] * 500 / iMaxTempValue print(lTargetCivs) for iLoopCiv in range(iNumTotalPlayers): if (lTargetCivs[iLoopCiv] <= 0): continue #add a random value if (lTargetCivs[iLoopCiv] <= iThreshold): lTargetCivs[iLoopCiv] += gc.getGame().getSorenRandNum( 100, 'random modifier') if (lTargetCivs[iLoopCiv] > iThreshold): lTargetCivs[iLoopCiv] += gc.getGame().getSorenRandNum( 300, 'random modifier') #balanced with attitude attitude = 2 * (pCiv.AI_getAttitude(iLoopCiv) - 2) if (attitude > 0): lTargetCivs[iLoopCiv] /= attitude #exploit plague if iLoopCiv < iNumPlayers: if (sd.getPlagueCountdown(iLoopCiv) > 0 or sd.getPlagueCountdown(iLoopCiv) < -10 and not (gc.getGame().getGameTurn() <= getTurnForYear( con.tBirth[iLoopCiv]) + utils.getTurns(20))): lTargetCivs[iLoopCiv] *= 3 lTargetCivs[iLoopCiv] /= 2 #balanced with master's attitude for j in range(iNumTotalPlayers): if (tCiv.isVassal(j)): attitude = 2 * (gc.getPlayer(j).AI_getAttitude(iLoopCiv) - 2) if (attitude > 0): lTargetCivs[iLoopCiv] /= attitude #if already at war if (not tCiv.isAtWar(iLoopCiv)): #consider peace counter iCounter = min(7, max(1, tCiv.AI_getAtPeaceCounter(iLoopCiv))) if (iCounter <= 7): lTargetCivs[iLoopCiv] *= 20 + 10 * iCounter lTargetCivs[iLoopCiv] /= 100 #if under pact if (tCiv.isDefensivePact(iLoopCiv)): lTargetCivs[iLoopCiv] /= 4 #if friend of a friend ## for jLoopCiv in range( iNumTotalPlayers ): ## if (tCiv.isDefensivePact(jLoopCiv) and gc.getTeam(gc.getPlayer(iLoopCiv).getTeam()).isDefensivePact(jLoopCiv)): ## lTargetCivs[iLoopCiv] /= 2 print(lTargetCivs) #find max iMaxValue = 0 iTargetCiv = -1 for iLoopCiv in range(iNumTotalPlayers): if (lTargetCivs[iLoopCiv] > iMaxValue): iMaxValue = lTargetCivs[iLoopCiv] iTargetCiv = iLoopCiv print("maxvalue", iMaxValue) print("target civ", iTargetCiv) if (iMaxValue >= iMinValue): return iTargetCiv return -1
def chooseAttackingPlayer(self): #finding max teams ever alive (countCivTeamsEverAlive() doesn't work as late human starting civ gets killed every turn) iMaxCivs = iNumPlayers for i in range(iNumPlayers): j = iNumPlayers - 1 - i if (gc.getPlayer(j).isAlive()): iMaxCivs = j break #print ("iMaxCivs", iMaxCivs) if (gc.getGame().countCivPlayersAlive() <= 3): return -1 else: iRndnum = gc.getGame().getSorenRandNum(iMaxCivs, 'attacking civ index') # Important war: Carthage vs. Rome if utils.getYear() >= -250 and utils.getYear() < -150: if gc.getPlayer(con.iRome).isAlive() and gc.getPlayer( con.iCarthage).isAlive(): if not gc.getTeam(gc.getPlayer( con.iRome).getTeam()).isAtWar(con.iCarthage): if gc.getPlayer(con.iRome) != utils.getHumanID(): iRndnum = con.iRome elif gc.getPlayer(con.iCarthage) != utils.getHumanID(): iRndnum = con.iCarthage # Important war: Macedon vs. Athens if utils.getYear() >= -400 and utils.getYear() < -300: if gc.getPlayer(con.iMacedon).isAlive() and gc.getPlayer( con.iAthens).isAlive(): if not gc.getTeam(gc.getPlayer( con.iMacedon).getTeam()).isAtWar(con.iAthens): if gc.getPlayer(con.iMacedon) != utils.getHumanID(): iRndnum = con.iMacedon elif gc.getPlayer(con.iAthens) != utils.getHumanID(): iRndnum = con.iAthens iRndnum = con.iCarthage # Important war: Qin vs. Jin if utils.getYear() >= -350 and utils.getYear() < -300: if gc.getPlayer(con.iQin).isAlive() and gc.getPlayer( con.iJinState).isAlive(): if not gc.getTeam(gc.getPlayer( con.iQin).getTeam()).isAtWar(con.iJinState): if gc.getPlayer(con.iQin) != utils.getHumanID(): iRndnum = con.iQin elif gc.getPlayer(con.iJinState) != utils.getHumanID(): iRndnum = con.iJinState #print ("iRndnum", iRndnum) iAlreadyAttacked = -100 iMin = 100 iCiv = -1 for i in range(iRndnum, iRndnum + iMaxCivs): iLoopCiv = i % iMaxCivs pLoopPlayer = gc.getPlayer(iLoopCiv) if (pLoopPlayer.isAlive() and not pLoopPlayer.isHuman()): if (sd.getPlagueCountdown(iLoopCiv) >= -10 and sd.getPlagueCountdown(iLoopCiv) <= 0 ): #civ is not under plague or quit recently from it iAlreadyAttacked = sd.getAttackingCivsArray(iLoopCiv) if (utils.isAVassal(iLoopCiv)): iAlreadyAttacked += 1 #less likely to attack #check if a world war is already in place iNumAlreadyWar = 0 tLoopCiv = gc.getTeam(pLoopPlayer.getTeam()) for kLoopCiv in range(iNumPlayers): if (tLoopCiv.isAtWar(kLoopCiv)): if gc.getPlayer(kLoopCiv).isAlive(): iNumAlreadyWar += 1 if (iNumAlreadyWar >= 4): iAlreadyAttacked += 2 #much less likely to attack elif (iNumAlreadyWar >= 2): iAlreadyAttacked += 1 #less likely to attack if (iAlreadyAttacked < iMin): iMin = iAlreadyAttacked iCiv = iLoopCiv #print ("attacking civ", iCiv) if (iAlreadyAttacked != -100): sd.setAttackingCivsArray(iCiv, iAlreadyAttacked + 1) return iCiv else: return -1 return -1
def checkPlayerTurn(self, iGameTurn, iPlayer): if (iPlayer < iNumTotalPlayers + 1): if (sd.getPlagueCountdown(iPlayer) > 0): self.processPlague(iPlayer)
def processPlague(self, iPlayer): pPlayer = gc.getPlayer(iPlayer) #first spread to close locations cityList = [] #see below apCityList = PyPlayer(iPlayer).getCityList() for pCity in apCityList: city = pCity.GetCy() cityList.append(city) #see below if (city.getNumRealBuilding(iPlague) > 0): #print ("plague in city", city.getName()) if (city.getPopulation() > 1): #print("healthRate in city", 35 + 5*city.healthRate(False, 0)) if utils.getYear() < 1250: iMin = 80 elif city.plot().getRegionID() in con.lBlackDeathRegions: if city.getOwner() in con.lBlackDeathSurvivors: iMin = 80 else: iMin = 50 else: iMin = 90 if (gc.getGame().getSorenRandNum(100, 'roll') > iMin + 5 * city.healthRate(False, 0)): city.changePopulation(-1) if (city.isCapital()): #delete in vanilla for iLoopCiv in range(iNumPlayers): if (gc.getTeam(pPlayer.getTeam()).isVassal(iLoopCiv) or \ gc.getTeam(gc.getPlayer(iLoopCiv).getTeam()).isVassal(iPlayer)): if ( gc.getPlayer(iLoopCiv).getNumCities() > 0 ): #this check is needed, otherwise game crashes capital = gc.getPlayer( iLoopCiv).getCapitalCity() if (self.isVulnerable(iLoopCiv) == True): if (sd.getPlagueCountdown(iPlayer) > 2): #don't spread the last turns self.spreadPlague(iLoopCiv) self.infectCity(capital) #print ("infect master/vassal", city.getName(), "to", capital.getName()) for x in range(city.getX() - 2, city.getX() + 3): for y in range(city.getY() - 2, city.getY() + 3): ##print ("plagueXY", x, y) pCurrent = gc.getMap().plot(x, y) if (pCurrent.getOwner() != iPlayer and pCurrent.getOwner() >= 0): if (sd.getPlagueCountdown(iPlayer) > 2): #don't spread the last turns if (self.isVulnerable( pCurrent.getOwner()) == True): self.spreadPlague(pCurrent.getOwner()) self.infectCitiesNear( pCurrent.getOwner(), x, y) #print ("infect foreign near", city.getName()) else: if (pCurrent.isCity() and not (x == city.getX() and y == city.getY())): #print ("is city", x, y) cityNear = pCurrent.getPlotCity() if (not cityNear.getNumRealBuilding(iPlague) > 0): if (sd.getPlagueCountdown(iPlayer) > 2): #don't spread the last turns self.infectCity(cityNear) #print ("infect near", city.getName(), "to", cityNear.getName()) else: if (x == city.getX() and y == city.getY()): self.killUnitsByPlague( city, pCurrent, 0, 42, 2) else: if (pCurrent.isRoute()): self.killUnitsByPlague( city, pCurrent, 10, 35, 0) elif (pCurrent.isWater()): self.killUnitsByPlague( city, pCurrent, 30, 35, 0) else: self.killUnitsByPlague( city, pCurrent, 30, 35, 0) for x in range(city.getX() - 3, city.getX() + 4): pCurrent = gc.getMap().plot(x, city.getY() - 3) if (pCurrent.getOwner() == iPlayer or not pCurrent.isOwned()): if (not pCurrent.isCity()): if (pCurrent.isRoute() or pCurrent.isWater()): self.killUnitsByPlague(city, pCurrent, 30, 35, 0) pCurrent = gc.getMap().plot(x, city.getY() + 4) if (pCurrent.getOwner() == iPlayer or not pCurrent.isOwned()): if (not pCurrent.isCity()): if (pCurrent.isRoute() or pCurrent.isWater()): self.killUnitsByPlague(city, pCurrent, 30, 35, 0) for y in range(city.getY() - 2, city.getY() + 3): pCurrent = gc.getMap().plot(city.getX() - 3, y) if (pCurrent.getOwner() == iPlayer or not pCurrent.isOwned()): if (not pCurrent.isCity()): if (pCurrent.isRoute() or pCurrent.isWater()): self.killUnitsByPlague(city, pCurrent, 30, 35, 0) pCurrent = gc.getMap().plot(city.getX() + 4, y) if (pCurrent.getOwner() == iPlayer or not pCurrent.isOwned()): if (not pCurrent.isCity()): if (pCurrent.isRoute() or pCurrent.isWater()): self.killUnitsByPlague(city, pCurrent, 30, 35, 0) #spread to trade route cities if (sd.getPlagueCountdown(iPlayer) > 2): #don't spread the last turns for i in range(city.getTradeRoutes()): #for i in range(gc.getDefineINT("MAX_TRADE_ROUTES")): loopCity = city.getTradeCity(i) if (not loopCity.isNone()): if (not loopCity.getNumRealBuilding(iPlague) > 0): #utils.echo("Plagued caravan arrives at %s" %(loopCity.getName())) iOwner = loopCity.getOwner() if (iPlayer == iOwner or gc.getTeam(pPlayer.getTeam()).isOpenBorders(iOwner) or \ gc.getTeam(pPlayer.getTeam()).isVassal(iOwner) or \ gc.getTeam(gc.getPlayer(iOwner).getTeam()).isVassal(iPlayer)): #own city, or open borders, or vassal if (iPlayer != iOwner): if (self.isVulnerable(iOwner) == True): self.spreadPlague(iOwner) self.infectCity(loopCity) #utils.echo("infect by trade route: %s to %s" %(city.getName(), loopCity.getName())) iHuman = utils.getHumanID() if (gc.getPlayer( iHuman).canContact(iOwner) and iHuman != iOwner): CyInterface().addMessage( iHuman, True, con.iDuration / 2, CyTranslator().getText( "TXT_KEY_PLAGUE_SPREAD_CITY", ()) + " " + loopCity.getName() + " (" + gc.getPlayer(iOwner). getCivilizationAdjective(0) + ")", "AS2D_PLAGUE", 0, "", ColorTypes(con.iLime), -1, -1, True, True) else: self.infectCity(loopCity) #utils.echo("infect by trade route: %s to %s" %(city.getName(), loopCity.getName())) #spread to other cities of the empire if (len(cityList)): if (sd.getPlagueCountdown(iPlayer) > 2): #don't spread the last turns for city1 in cityList: ##print ("citylist", city1.getName()) if (not city1.getNumRealBuilding(iPlague) > 0): for city2 in cityList: if (city1 != city2): if (city2.getNumRealBuilding(iPlague) > 0): if (city1.isConnectedTo(city2)): ##print ("infect distant", city1.getName(), "to", city2.getName(), utils.calculateDistance(city1.getX(), city1.getY(), city2.getX(), city2.getY())) if (utils.calculateDistance( city1.getX(), city1.getY(), city2.getX(), city2.getY()) <= 6): #print ("infect distant", city2.getName(), "to", city1.getName()) self.infectCity(city1) return