# Generation of data for a campaign of Ticket to Ride Legacy: Legends of the West # Imports import os import random import jsonpickle class Circus: # There are: # 4 wagons of each colors (until 2 players' stop) # 2 wagons of each colors (until 3 players' stop) # 2 wagons of each colors (until 4 players' stop) # 2 wagons of each colors (until 5 players' stop) # NOTE: In the original distribution, the same color never appears twice in a row # We chose to remove this constraint, for the sake of simplicity def __init__(self, playersNb): wagonsPerColors = 2 * playersNb colors = "blue", "green", "black", "red", "yellow" remaining = {"blue": wagonsPerColors, "green": wagonsPerColors, "black": wagonsPerColors, "red": wagonsPerColors, "yellow": wagonsPerColors} self.wagons = [] for n in range(0, 5 * wagonsPerColors): color = colors[random.randint(0, 4)] while remaining[color] == 0: color = colors[random.randint(0, 4)] self.wagons.append(color) remaining[color] = remaining[color] - 1 self.state = 0 # 0 means Circus is not used in game yet, 1 means next wagon in list is #1, and so on def enable(self): if self.state == 0: print("Circus is not or no longer in game.") return False self.state = 1 def getNextColor(self): return self.wagons[self.state - 1] def takeWagon(self): if self.state == 0: print("Circus is not or no longer in game.") return False print("Player obtained a " + self.wagons[self.state - 1] + " circus sticker!") self.state = self.state + 1 if self.state > len(self.wagons): print("Circus stickers are now depleted.") self.state = 0 # effectively disable circus class TreasureCard: def __init__(self): self.treasures = [36, 33, 29, 27, 24] self.state = -1 # disabled def enable(self): self.state = 0 # 0 means 0 treasures have been found def getFoundNumber(self): if self.state == -1: print("Treasure hunt has not started yet or is completed.") return False return self.state def takeTreasure(self): if self.state == -1: print("Treasure hunt has not started yet or is completed.") return False self.state = self.state + 1 if self.state == 5: print("All treasures have been found.") self.state = -1 # effectively disable treasure card class ConcessionCard: # Each card contains: # 6 cities to connect to the player's concession. There is no need to implement those. # 7 gold nuggets, as rewards when the player succefully connects a city to their concession. The player can choose # which nugget to earn, and then discovers the associated reward (between 11 and 17 coins). # A ConcessionCard is then composed of 7 nuggets, with the rewards randomly distributed. def __init__(self): availableValues = [11, 12, 13, 14, 15, 16, 17] nuggetsNb = len(availableValues) - 1 self.nuggets = [] for n in range(0, 7): choice = random.randint(0, nuggetsNb - n) self.nuggets.append(availableValues[choice]) availableValues.pop(choice) self.taken = set() def getRemainingPepites(self): return {1, 2, 3, 4, 5, 6, 7} - self.taken def takeReward(self, choice): if choice in self.taken: print(str(choice) + " has already been obtained.") return False self.taken.add(choice) print("Congrats! You obtained $" + str(self.nuggets[choice])) class Player: def __init__(self, color): self.color = color self.concession = ConcessionCard() class Game: # initGame() is used to generate all data for a campaign and initialize status variables def initGame(self): self.years = 1865, 1868, 1871, 1874, 1877, 1880, 1883, 1886, 1889, 1892, 1895, 1898 playersNb = input("Enter the number of players (2-5): ") while not playersNb.isdigit() or int(playersNb) not in range(2, 6): playersNb = input("OUT OF RANGE! Enter the number of players (2-5): ") playersNb = int(playersNb) # Game status self.yearId = 0 self.concession = False # General data to generate self.circus = Circus(playersNb) # Mama O'Connell self.treasure = TreasureCard() # Players self.players = [] for n in range(0, playersNb): color = input("Enter player " + str(n + 1) + "'s color: ") self.players.append(Player(color)) def printStatus(self): print("") print("Ticket to Ride Legacy: Legends of the West") print("") print("Campaign - Year: " + str(self.years[self.yearId])) print("") print("Players:") for player in self.players: print(" " + player.color) if self.concession: print(" Concession card remaining nuggets: " + str(player.concession.getRemainingPepites())) print("") if self.circus.state > 0: print("Circus next sticker color: " + self.circus.getNextColor()) if self.treasure.state > -1: print(f"Treasures found: {self.treasure.getFoundNumber()}") def saveData(self): savefile = open('./savefile.json', 'w+') savefile.write(jsonpickle.encode(self)) savefile.close() def loadData(path): with open('./' + path, 'r') as savefile: content = savefile.read() data = jsonpickle.decode(content) return data print("") print("Ticket to Ride Legacy: Legends of the West") print("") choice = input("What do you want to do (new/load)? ") while choice not in ("new", "load"): choice = input("UNDEFINED! What do you want to do (new/load)? ") if choice == "new": myGame = Game() myGame.initGame() elif choice == "load": path = input("Path to save file (defaults to savefile.json)? ") if path == "": path = "savefile.json" myGame = loadData(path) myGame.printStatus() # TESTS # Test of data generation # myGame = Game() # myGame.initGame() # myGame.saveData() # Test of data loading # myGame = loadData('savefile.json') # myGame.printStatus() # Test of ConcessionCard # cc = ConcessionCard() # userChoice = 3 # print(cc.nuggets) # cc.takeReward(userChoice - 1) # print(cc.nuggets) # print(cc.taken) # print("Remaining: " + str(cc.getRemainingPepites())) # cc.takeReward(userChoice - 1) # print(cc.nuggets) # print(cc.taken) # print("Remaining: " + str(cc.getRemainingPepites())) # Test of Player # myGame = Game() # myGame.initGame() # myGame.printStatus() # myGame.treasure.enable() # myGame.printStatus() # myGame.treasure.takeTreasure() # myGame.treasure.takeTreasure() # myGame.treasure.takeTreasure() # myGame.treasure.takeTreasure() # myGame.printStatus() # myGame.treasure.takeTreasure() # myGame.printStatus()