def findStartingPlot(argsList): # This function is only called for Snaky Continents (or if an entire region should fail to produce a valid start plot via the regional method). [playerID] = argsList # Check to see if a region failed. If so, try the default implementation. (The rest of this process could get stuck in an infinite loop, so don't risk it!) global bSuccessFlag if bSuccessFlag == False: CyPythonMgr().allowDefaultImpl() return # Identify the best land area available to this player. global areas global area_values global iBestArea gc = CyGlobalContext() map = CyMap() iBestValue = 0 iBestArea = -1 areas = CvMapGeneratorUtil.getAreas() for area in areas: if area.isWater(): continue # Don't want to start "in the drink"! iNumPlayersOnArea = area.getNumStartingPlots( ) + 1 # Number of players starting on the area, plus this player. iTileValue = area.calculateTotalBestNatureYield( ) + area.getNumRiverEdges( ) + 2 * area.countCoastalLand() + 3 * area.countNumUniqueBonusTypes() iValue = iTileValue / iNumPlayersOnArea if (iNumPlayersOnArea == 1): iValue *= 4 iValue /= 3 if (iValue > iBestValue): iBestValue = iValue iBestArea = area.getID() # Ensure that starting plot is in chosen Area and is along the coast. def isValid(playerID, x, y): global iBestArea pPlot = CyMap().plot(x, y) if pPlot.getArea() != iBestArea: return false pWaterArea = pPlot.waterArea() if (pWaterArea.isNone()): return false return not pWaterArea.isLake() return CvMapGeneratorUtil.findStartingPlot(playerID, isValid)
def findStartingPlot(argsList): # This function is only called for Snaky Continents (or if an entire region should fail to produce a valid start plot via the regional method). [playerID] = argsList # Check to see if a region failed. If so, try the default implementation. (The rest of this process could get stuck in an infinite loop, so don't risk it!) global bSuccessFlag if bSuccessFlag == False: CyPythonMgr().allowDefaultImpl() return # Identify the best land area available to this player. global areas global area_values global iBestArea gc = CyGlobalContext() map = CyMap() iBestValue = 0 iBestArea = -1 areas = CvMapGeneratorUtil.getAreas() for area in areas: if area.isWater(): continue # Don't want to start "in the drink"! iNumPlayersOnArea = area.getNumStartingPlots() + 1 # Number of players starting on the area, plus this player. iTileValue = area.calculateTotalBestNatureYield() + area.getNumRiverEdges() + 2 * area.countCoastalLand() + 3 * area.countNumUniqueBonusTypes() iValue = iTileValue / iNumPlayersOnArea if (iNumPlayersOnArea == 1): iValue *= 4; iValue /= 3 if (iValue > iBestValue): iBestValue = iValue iBestArea = area.getID() # Ensure that starting plot is in chosen Area and is along the coast. def isValid(playerID, x, y): global iBestArea pPlot = CyMap().plot(x, y) if pPlot.getArea() != iBestArea: return false pWaterArea = pPlot.waterArea() if (pWaterArea.isNone()): return false return not pWaterArea.isLake() return CvMapGeneratorUtil.findStartingPlot(playerID, isValid)
def findStartingPlot(argsList): gc = CyGlobalContext() map = CyMap() dice = gc.getGame().getMapRand() iPlayers = gc.getGame().countCivPlayersEverAlive() areas = CvMapGeneratorUtil.getAreas() areaValue = [0] * map.getIndexAfterLastArea() isolatedStarts = false userInputLandmass = CyMap().getCustomMapOption(0) if (userInputLandmass == 4): # "Islands" isolatedStarts = true if iPlayers < 2 or iPlayers > 18: bSuccessFlag = False CyPythonMgr().allowDefaultImpl() return for area in areas: if area.isWater(): continue areaValue[area.getID( )] = area.calculateTotalBestNatureYield() + area.getNumRiverEdges( ) + 2 * area.countCoastalLand() + 3 * area.countNumUniqueBonusTypes() # Shuffle players so the same player doesn't always get the first pick. player_list = [] for plrCheckLoop in range(18): if CyGlobalContext().getPlayer(plrCheckLoop).isEverAlive(): player_list.append(plrCheckLoop) shuffledPlayers = [] for playerLoop in range(iPlayers): iChoosePlayer = dice.get(len(player_list), "Shuffling Players - Highlands PYTHON") shuffledPlayers.append(player_list[iChoosePlayer]) del player_list[iChoosePlayer] # Loop through players, assigning starts for each. for assign_loop in range(iPlayers): playerID = shuffledPlayers[assign_loop] player = gc.getPlayer(playerID) bestAreaValue = 0 global bestArea bestArea = None for area in areas: if area.isWater(): continue players = 2 * area.getNumStartingPlots() #Avoid single players on landmasses: if (false == isolatedStarts and players == 0): if (assign_loop == iPlayers - 1): players = 4 else: players = 2 value = areaValue[area.getID()] / (1 + 2 * area.getNumStartingPlots()) if (value > bestAreaValue): bestAreaValue = value bestArea = area def isValid(playerID, x, y): global bestArea plot = CyMap().plot(x, y) if (plot.getArea() != bestArea): return false if (self.getLatitudeAtPlot(x, y) >= 75): return false return true findstart = CvMapGeneratorUtil.findStartingPlot(playerID, isValid) sPlot = map.plotByIndex(findstart) player.setStartingPlot(sPlot, true) # return None return CvMapGeneratorUtil.findStartingPlot(playerID, isValid)
def assignStartingPlots(): gc = CyGlobalContext() dice = gc.getGame().getMapRand() global shuffle global shuffledTeams global assignedPlayers assignedPlayers = [0] * gc.getGame().countCivTeamsEverAlive() print assignedPlayers shuffle = gc.getGame().getMapRand().get(2, "Start Location Shuffle - PYTHON") if gc.getGame().countCivTeamsEverAlive() < 5: team_list = [0, 1, 2, 3] shuffledTeams = [] for teamLoop in range(gc.getGame().countCivTeamsEverAlive()): iChooseTeam = dice.get(len(team_list), "Shuffling Regions - TBG PYTHON") shuffledTeams.append(team_list[iChooseTeam]) del team_list[iChooseTeam] # For Lakes and Continents settings, ensure that starts are all placed on the biggest landmass on each side. global biggest_areas biggest_areas = [] areas = CvMapGeneratorUtil.getAreas() area_sizes = [(area.getNumTiles(), area.getID()) for area in areas if not area.isWater()] area_sizes.sort() # sort by size -- biggest areas last. # pop the biggest two areas off the list. area_size, area_ID = area_sizes.pop() biggest_areas.append(area_ID) if area_sizes != []: area_size, area_ID = area_sizes.pop() biggest_areas.append(area_ID) # First check to see if teams chose to "Start Separated" or "Start Anywhere". map = CyMap() userInputProximity = map.getCustomMapOption(1) if userInputProximity == 1: # Teams set to Start Separated. Use default impl. CyPythonMgr().allowDefaultImpl() return # Shuffle the players. global playersOnTeamOne global playersOnTeamTwo iPlayers = gc.getGame().countCivPlayersEverAlive() playersOnTeamOne = [] playersOnTeamTwo = [] player_list = [] for plrCheckLoop in range(18): if CyGlobalContext().getPlayer(plrCheckLoop).isEverAlive(): player_list.append(plrCheckLoop) shuffledPlayers = [] for playerLoopTwo in range(iPlayers): iChoosePlayer = dice.get(len(player_list), "Shuffling Player Order - Mirror PYTHON") shuffledPlayers.append(player_list[iChoosePlayer]) del player_list[iChoosePlayer] if userInputProximity == 2: # Teams set to Start Anywhere! def isValidToStartAnywhere(playerID, x, y): global biggest_areas global terrainRoll userInputTerrain = CyMap().getCustomMapOption(2) if userInputTerrain < 3 or (userInputTerrain == 5 and terrainRoll < 6): pPlot = CyMap().plot(x, y) areaID = pPlot.getArea() if areaID not in biggest_areas: return false return true # Since the default alternates by team, must use the shuffled players list to assign starting locs. # This will provide a truly random order, which may or may not be "fair". But hey, starting anywhere means ANYwhere. OK? for playerID in shuffledPlayers: player = gc.getPlayer(playerID) startPlot = CvMapGeneratorUtil.findStartingPlot( playerID, isValidToStartAnywhere) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) # All done. return None # OK, so the teams have chosen to Start Together. # # Check for the special case of two teams with even players. # If found, force perfect mirrorization of start plots! # # (This is necessary because the default start plot process # resolves "ties" differently on each side due to minor # differences in the order of operations. Odd but true!) # iTeams = gc.getGame().countCivTeamsEverAlive() if iTeams != 2: CyPythonMgr().allowDefaultImpl() return team_one = gc.getTeam(0) team_two = gc.getTeam(1) if team_one.getNumMembers() != team_two.getNumMembers(): CyPythonMgr().allowDefaultImpl() return # We are dealing with two teams who are evenly matched. # Assign all start plots for the first team, then mirrorize the locations for the second team! # Start by determining which players are on which teams. for iLoop in range(iPlayers): thisPlayerID = shuffledPlayers[iLoop] this_player = gc.getPlayer(thisPlayerID) teamID = gc.getPlayer(thisPlayerID).getTeam() print("Player: ", thisPlayerID, " Team: ", teamID) if teamID == 1: playersOnTeamTwo.append(shuffledPlayers[iLoop]) else: playersOnTeamOne.append(shuffledPlayers[iLoop]) # Now we pick a team to assign to the left side and assign them there. userInputPlots = map.getCustomMapOption(0) iW = map.getGridWidth() iH = map.getGridHeight() if userInputPlots == 0: # Reflection reflect_x = lambda x: iW - iX - 1 reflect_y = lambda y: iY elif userInputPlots == 1: # Inversion reflect_x = lambda x: iW - iX - 1 reflect_y = lambda y: iH - iY - 1 elif userInputPlots == 2: # Copy reflect_x = lambda x: iX + (iW / 2) reflect_y = lambda y: iY else: # userInputPlots == 3: Opposite reflect_x = lambda x: iX + (iW / 2) reflect_y = lambda y: iH - iY - 1 def isValidForMirror(playerID, x, y): global biggest_areas global terrainRoll userInputTerrain = CyMap().getCustomMapOption(2) if userInputTerrain < 3 or (userInputTerrain == 5 and terrainRoll < 6): pPlot = CyMap().plot(x, y) areaID = pPlot.getArea() if areaID not in biggest_areas: return false userInputPlots = CyMap().getCustomMapOption(0) iPlayers = CyGlobalContext().getGame().countCivPlayersEverAlive() teamID = CyGlobalContext().getPlayer(playerID).getTeam() iW = CyMap().getGridWidth() # Two Evenly-Matched Teams, Start Together if iPlayers > 2 and userInputPlots <= 1 and x <= iW * 0.4: return true if iPlayers > 2 and userInputPlots >= 2 and x >= iW * 0.1 and x <= iW * 0.4: return true # 1 vs 1 game, so make sure the players start farther apart! if iPlayers == 2 and userInputPlots <= 1 and x <= iW * 0.2: return true if iPlayers == 2 and userInputPlots >= 2 and x >= iW * 0.2 and x <= iW * 0.3: return true # if not true, then false! (Duh? Well, the program still has to be told.) return false if shuffle: # We will put team two on the left. teamOneIndex = 0 for thisPlayer in playersOnTeamTwo: player = gc.getPlayer(thisPlayer) startPlot = CvMapGeneratorUtil.findStartingPlot( thisPlayer, isValidForMirror) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) iX = sPlot.getX() iY = sPlot.getY() mirror_x = reflect_x(iX) mirror_y = reflect_y(iY) opposite_player = gc.getPlayer(playersOnTeamOne[teamOneIndex]) oppositePlot = map.plot(mirror_x, mirror_y) opposite_player.setStartingPlot(oppositePlot, true) teamOneIndex += 1 else: # will put team one on the left. teamTwoIndex = 0 for thisPlayer in playersOnTeamOne: player = gc.getPlayer(thisPlayer) startPlot = CvMapGeneratorUtil.findStartingPlot( thisPlayer, isValidForMirror) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) iX = sPlot.getX() iY = sPlot.getY() mirror_x = reflect_x(iX) mirror_y = reflect_y(iY) opposite_player = gc.getPlayer(playersOnTeamTwo[teamTwoIndex]) oppositePlot = map.plot(mirror_x, mirror_y) opposite_player.setStartingPlot(oppositePlot, true) teamTwoIndex += 1 # All done. return None
def findStartingPlot(argsList): gc = CyGlobalContext() map = CyMap() dice = gc.getGame().getMapRand() iPlayers = gc.getGame().countCivPlayersEverAlive() areas = CvMapGeneratorUtil.getAreas() areaValue = [0] * map.getIndexAfterLastArea() isolatedStarts = false userInputLandmass = CyMap().getCustomMapOption(0) if (userInputLandmass == 4): # "Islands" isolatedStarts = true if iPlayers < 2 or iPlayers > 18: bSuccessFlag = False CyPythonMgr().allowDefaultImpl() return for area in areas: if area.isWater(): continue areaValue[area.getID()] = area.calculateTotalBestNatureYield() + area.getNumRiverEdges() + 2 * area.countCoastalLand() + 3 * area.countNumUniqueBonusTypes() # Shuffle players so the same player doesn't always get the first pick. player_list = [] for plrCheckLoop in range(18): if CyGlobalContext().getPlayer(plrCheckLoop).isEverAlive(): player_list.append(plrCheckLoop) shuffledPlayers = [] for playerLoop in range(iPlayers): iChoosePlayer = dice.get(len(player_list), "Shuffling Players - Highlands PYTHON") shuffledPlayers.append(player_list[iChoosePlayer]) del player_list[iChoosePlayer] # Loop through players, assigning starts for each. for assign_loop in range(iPlayers): playerID = shuffledPlayers[assign_loop] player = gc.getPlayer(playerID) bestAreaValue = 0 global bestArea bestArea = None for area in areas: if area.isWater(): continue players = 2*area.getNumStartingPlots() #Avoid single players on landmasses: if (false == isolatedStarts and players == 0): if (assign_loop == iPlayers - 1): players = 4 else: players = 2 value = areaValue[area.getID()] / (1 + 2*area.getNumStartingPlots() ) if (value > bestAreaValue): bestAreaValue = value; bestArea = area def isValid(playerID, x, y): global bestArea plot = CyMap().plot(x,y) if (plot.getArea() != bestArea): return false if (self.getLatitudeAtPlot(x,y) >= 75): return false return true findstart = CvMapGeneratorUtil.findStartingPlot(playerID,isValid) sPlot = map.plotByIndex(findstart) player.setStartingPlot(sPlot,true) # return None return CvMapGeneratorUtil.findStartingPlot(playerID, isValid)
def assignStartingPlots(): gc = CyGlobalContext() dice = gc.getGame().getMapRand() global shuffle global shuffledTeams global assignedPlayers assignedPlayers = [0] * gc.getGame().countCivTeamsEverAlive() print assignedPlayers shuffle = gc.getGame().getMapRand().get(2, "Start Location Shuffle - PYTHON") if gc.getGame().countCivTeamsEverAlive() < 5: team_list = [0, 1, 2, 3] shuffledTeams = [] for teamLoop in range(gc.getGame().countCivTeamsEverAlive()): iChooseTeam = dice.get(len(team_list), "Shuffling Regions - TBG PYTHON") shuffledTeams.append(team_list[iChooseTeam]) del team_list[iChooseTeam] # For Lakes and Continents settings, ensure that starts are all placed on the biggest landmass on each side. global biggest_areas biggest_areas = [] areas = CvMapGeneratorUtil.getAreas() area_sizes = [(area.getNumTiles(), area.getID()) for area in areas if not area.isWater()] area_sizes.sort() # sort by size -- biggest areas last. # pop the biggest two areas off the list. area_size, area_ID = area_sizes.pop() biggest_areas.append(area_ID) if area_sizes != []: area_size, area_ID = area_sizes.pop() biggest_areas.append(area_ID) # First check to see if teams chose to "Start Separated" or "Start Anywhere". map = CyMap() userInputProximity = map.getCustomMapOption(1) if userInputProximity == 1: # Teams set to Start Separated. Use default impl. CyPythonMgr().allowDefaultImpl() return # Shuffle the players. global playersOnTeamOne global playersOnTeamTwo iPlayers = gc.getGame().countCivPlayersEverAlive() playersOnTeamOne = [] playersOnTeamTwo = [] player_list = [] for plrCheckLoop in range(18): if CyGlobalContext().getPlayer(plrCheckLoop).isEverAlive(): player_list.append(plrCheckLoop) shuffledPlayers = [] for playerLoopTwo in range(iPlayers): iChoosePlayer = dice.get(len(player_list), "Shuffling Player Order - Mirror PYTHON") shuffledPlayers.append(player_list[iChoosePlayer]) del player_list[iChoosePlayer] if userInputProximity == 2: # Teams set to Start Anywhere! def isValidToStartAnywhere(playerID, x, y): global biggest_areas global terrainRoll userInputTerrain = CyMap().getCustomMapOption(2) if userInputTerrain < 3 or (userInputTerrain == 5 and terrainRoll < 6): pPlot = CyMap().plot(x, y) areaID = pPlot.getArea() if areaID not in biggest_areas: return false return true # Since the default alternates by team, must use the shuffled players list to assign starting locs. # This will provide a truly random order, which may or may not be "fair". But hey, starting anywhere means ANYwhere. OK? for playerID in shuffledPlayers: player = gc.getPlayer(playerID) startPlot = CvMapGeneratorUtil.findStartingPlot(playerID, isValidToStartAnywhere) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) # All done. return None # OK, so the teams have chosen to Start Together. # # Check for the special case of two teams with even players. # If found, force perfect mirrorization of start plots! # # (This is necessary because the default start plot process # resolves "ties" differently on each side due to minor # differences in the order of operations. Odd but true!) # iTeams = gc.getGame().countCivTeamsEverAlive() if iTeams != 2: CyPythonMgr().allowDefaultImpl() return team_one = gc.getTeam(0) team_two = gc.getTeam(1) if team_one.getNumMembers() != team_two.getNumMembers(): CyPythonMgr().allowDefaultImpl() return # We are dealing with two teams who are evenly matched. # Assign all start plots for the first team, then mirrorize the locations for the second team! # Start by determining which players are on which teams. for iLoop in range(iPlayers): thisPlayerID = shuffledPlayers[iLoop] this_player = gc.getPlayer(thisPlayerID) teamID = gc.getPlayer(thisPlayerID).getTeam() print("Player: ", thisPlayerID, " Team: ", teamID) if teamID == 1: playersOnTeamTwo.append(shuffledPlayers[iLoop]) else: playersOnTeamOne.append(shuffledPlayers[iLoop]) # Now we pick a team to assign to the left side and assign them there. userInputPlots = map.getCustomMapOption(0) iW = map.getGridWidth() iH = map.getGridHeight() if userInputPlots == 0: # Reflection reflect_x = lambda x: iW - iX - 1 reflect_y = lambda y: iY elif userInputPlots == 1: # Inversion reflect_x = lambda x: iW - iX - 1 reflect_y = lambda y: iH - iY - 1 elif userInputPlots == 2: # Copy reflect_x = lambda x: iX + (iW / 2) reflect_y = lambda y: iY else: # userInputPlots == 3: Opposite reflect_x = lambda x: iX + (iW / 2) reflect_y = lambda y: iH - iY - 1 def isValidForMirror(playerID, x, y): global biggest_areas global terrainRoll userInputTerrain = CyMap().getCustomMapOption(2) if userInputTerrain < 3 or (userInputTerrain == 5 and terrainRoll < 6): pPlot = CyMap().plot(x, y) areaID = pPlot.getArea() if areaID not in biggest_areas: return false userInputPlots = CyMap().getCustomMapOption(0) iPlayers = CyGlobalContext().getGame().countCivPlayersEverAlive() teamID = CyGlobalContext().getPlayer(playerID).getTeam() iW = CyMap().getGridWidth() # Two Evenly-Matched Teams, Start Together if iPlayers > 2 and userInputPlots <= 1 and x <= iW * 0.4: return true if iPlayers > 2 and userInputPlots >= 2 and x >= iW * 0.1 and x <= iW * 0.4: return true # 1 vs 1 game, so make sure the players start farther apart! if iPlayers == 2 and userInputPlots <= 1 and x <= iW * 0.2: return true if iPlayers == 2 and userInputPlots >= 2 and x >= iW * 0.2 and x <= iW * 0.3: return true # if not true, then false! (Duh? Well, the program still has to be told.) return false if shuffle: # We will put team two on the left. teamOneIndex = 0 for thisPlayer in playersOnTeamTwo: player = gc.getPlayer(thisPlayer) startPlot = CvMapGeneratorUtil.findStartingPlot(thisPlayer, isValidForMirror) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) iX = sPlot.getX() iY = sPlot.getY() mirror_x = reflect_x(iX) mirror_y = reflect_y(iY) opposite_player = gc.getPlayer(playersOnTeamOne[teamOneIndex]) oppositePlot = map.plot(mirror_x, mirror_y) opposite_player.setStartingPlot(oppositePlot, true) teamOneIndex += 1 else: # will put team one on the left. teamTwoIndex = 0 for thisPlayer in playersOnTeamOne: player = gc.getPlayer(thisPlayer) startPlot = CvMapGeneratorUtil.findStartingPlot(thisPlayer, isValidForMirror) sPlot = map.plotByIndex(startPlot) player.setStartingPlot(sPlot, true) iX = sPlot.getX() iY = sPlot.getY() mirror_x = reflect_x(iX) mirror_y = reflect_y(iY) opposite_player = gc.getPlayer(playersOnTeamTwo[teamTwoIndex]) oppositePlot = map.plot(mirror_x, mirror_y) opposite_player.setStartingPlot(oppositePlot, true) teamTwoIndex += 1 # All done. return None
def generateBonusDistributionList(self): "Displays Bonus Advisor Popup" d_TableData = {} map = CyMap() areas = CvMapGeneratorUtil.getAreas() area_sizes = [(area.getNumTiles(), area) for area in areas] area_sizes.sort() # sort by size -- biggest area last area_sizes.reverse() # biggest area first areas = [area for (area_size, area) in area_sizes] bonus_infos = [ gc.getBonusInfo(i) for i in range(gc.getNumBonusInfos()) ] title_list = [u"BonusDistro"] + [u"Area"] + [u"Size"] + [ u"Starting Plots" ] + [u"Unique Bonus Types"] + [u"Total Bonuses"] bonusList = "" for bonus in bonus_infos: bonusList += bonus.getDescription()[0] title_list += bonusList d_TableData[0] = title_list total = 0 loopRowData = [] for i in range(len(areas)): area = areas[i] area_string = "%d" % area.getID() if area.isWater(): area_string = "w" + area_string loopRowData.append(area_string) loopRowData.append("%d" % area.getNumTiles()) start_plots = area.getNumStartingPlots() if start_plots > 0: loopRowData.append("%d" % start_plots) else: loopRowData.append("") num_unique = area.countNumUniqueBonusTypes() if num_unique > 0: loopRowData.append("%d" % num_unique) else: loopRowData.append("") total_in_area = area.getNumTotalBonuses() total += total_in_area loopRowData.append("%d" % total_in_area) for j in range(len(bonus_infos)): quantity = area.getNumBonuses(j) if quantity > 0: loopRowData.append("%d" % quantity) else: loopRowData.append("") d_TableData[i + 1] = loopRowData loopRowData = [] # Add last row of totals: last_row = len(areas) + 1 loopRowData.append("Total") loopRowData.append(map.numPlots()) loopRowData.append("") loopRowData.append("") loopRowData.append("%d" % total) for j in range(len(bonus_infos)): quantity = map.getNumBonuses(j) if quantity > 0: loopRowData.append("%d" % quantity) else: loopRowData.append("-") iLastRow = len(d_TableData) d_TableData[iLastRow] = loopRowData #print d_TableData self.setTableData(d_TableData)