From 923655df9c970e4edbf5885a9a71254d2a703055 Mon Sep 17 00:00:00 2001 From: Alexandre CATTEAU Date: Tue, 21 May 2024 20:11:54 +0200 Subject: [PATCH] Finish implementing MOC --- src/moc-tracking.py | 170 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 27 deletions(-) diff --git a/src/moc-tracking.py b/src/moc-tracking.py index 42ce89d..424fc76 100644 --- a/src/moc-tracking.py +++ b/src/moc-tracking.py @@ -41,11 +41,9 @@ class Board: self.cities.append(City("Charlotte", neighbors)) neighbors = "Lewisburg", "Charlotte", "Atlanta", "Nashville", "Cincinnati" self.cities.append(City("Knoxville", neighbors)) - #neighbors = "Detroit", "Pittsburgh", "Lewisburg", "Knoxville", "Nashville", "St Louis" - neighbors = "Detroit", "Pittsburgh", "Lewisburg", "Knoxville", "Nashville" + neighbors = "Detroit", "Pittsburgh", "Lewisburg", "Knoxville", "Nashville", "St Louis" self.cities.append(City("Cincinnati", neighbors)) - #neighbors = "Detroit", "Cincinnati", "St Louis", "Davenport", "St Paul", "Duluth" - neighbors = "Detroit", "Cincinnati" + neighbors = "Detroit", "Cincinnati", "St Louis", "Davenport", "St Paul", "Duluth" self.cities.append(City("Chicago", neighbors)) neighbors = "Pittsburgh", "Baltimore", "Norfolk", "Charlotte", "Knoxville", "Cincinnati" self.cities.append(City("Lewisburg", neighbors)) @@ -59,15 +57,13 @@ class Board: self.cities.append(City("Savannah", neighbors)) # The South (4 cities) - #neighbors = "Cincinnati", "Knoxville", "Atlanta", "New Orleans", "Little Rock", "St Louis" - neighbors = "Cincinnati", "Knoxville", "Atlanta", "New Orleans" + neighbors = "Cincinnati", "Knoxville", "Atlanta", "New Orleans", "Little Rock", "St Louis" self.cities.append(City("Nashville", neighbors)) neighbors = "Charlotte", "Charleston", "Savannah", "Mobile", "Nashville", "Knoxville" self.cities.append(City("Atlanta", neighbors)) neighbors = "Atlanta", "Savannah", "Jacksonville", "Tampa", "New Orleans" self.cities.append(City("Mobile", neighbors)) - #neighbors = "Nashville", "Mobile", "Houston", "Little Rock" - neighbors = "Nashville", "Mobile" + neighbors = "Nashville", "Mobile", "Houston", "Little Rock" self.cities.append(City("New Orleans", neighbors)) # Florida (3 cities) @@ -78,6 +74,94 @@ class Board: neighbors = "Jacksonville", "Miami", "Mobile" self.cities.append(City("Tampa", neighbors)) + # Great Plains (6 cities) + neighbors = "Chicago", "St Paul", "Fargo", "Winnipeg" + self.cities.append(City("Duluth", neighbors)) + neighbors = "Duluth", "Chicago", "Davenport", "Omaha", "Fargo" + self.cities.append(City("St Paul", neighbors)) + neighbors = "Chicago", "St Louis", "Kansas City", "Omaha", "St Paul" + self.cities.append(City("Davenport", neighbors)) + neighbors = "St Paul", "Davenport", "Kansas City", "Denver", "Cheyenne" + self.cities.append(City("Omaha", neighbors)) + neighbors = "Chicago", "Cincinnati", "Nashville", "Little Rock", "Kansas City", "Davenport" + self.cities.append(City("St Louis", neighbors)) + neighbors = "Davenport", "St Louis", "Little Rock", "Oklahoma City", "Dodge City", "Omaha" + self.cities.append(City("Kansas City", neighbors)) + + # Open Range (6 cities) + neighbors = "Kansas City", "Oklahoma City", "Santa Fe", "Denver" + self.cities.append(City("Dodge City", neighbors)) + neighbors = "Kansas City", "Little Rock", "Dallas", "Santa Fe", "Dodge City" + self.cities.append(City("Oklahoma City", neighbors)) + neighbors = "Nashville", "New Orleans", "Houston", "Dallas", "Oklahoma City", "Kansas City", "St Louis" + self.cities.append(City("Little Rock", neighbors)) + neighbors = "Little Rock", "Houston", "San Antonio", "El Paso", "Oklahoma City" + self.cities.append(City("Dallas", neighbors)) + neighbors = "Little Rock", "New Orleans", "San Antonio", "Dallas" + self.cities.append(City("Houston", neighbors)) + neighbors = "Dallas", "Houston", "Monterrey", "El Paso" + self.cities.append(City("San Antonio", neighbors)) + + # Badlands (4 cities) + neighbors = "Winnipeg", "Miles City", "Calgary" + self.cities.append(City("Regina", neighbors)) + neighbors = "Duluth", "Fargo", "Miles City", "Regina" + self.cities.append(City("Winnipeg", neighbors)) + neighbors = "Regina", "Winnipeg", "Fargo", "Cheyenne", "Helena", "Calgary" + self.cities.append(City("Miles City", neighbors)) + neighbors = "Duluth", "St Paul", "Cheyenne", "Miles City", "Winnipeg" + self.cities.append(City("Fargo", neighbors)) + + # Haunted Wastes (5 cities) + neighbors = "Fargo", "Omaha", "Denver", "Salt Lake City", "Helena", "Miles City" + self.cities.append(City("Cheyenne", neighbors)) + neighbors = "Helena", "Cheyenne", "Denver", "Phoenix", "Cemetery City", "Portland", "Spokane" + self.cities.append(City("Salt Lake City", neighbors)) + neighbors = "Cheyenne", "Omaha", "Dodge City", "Santa Fe", "Phoenix", "Salt Lake City" + self.cities.append(City("Denver", neighbors)) + neighbors = "Denver", "Dodge City", "Oklahoma City", "El Paso", "Phoenix" + self.cities.append(City("Santa Fe", neighbors)) + neighbors = "Salt Lake City", "Denver", "Santa Fe", "El Paso", "Hermosillo", "Baja", "Nuevos Angeles" + self.cities.append(City("Phoenix", neighbors)) + + # Sierra Madre (4 cities) + neighbors = "Dallas", "San Antonio", "Monterrey", "Chihuhua", "Hermosillo", "Phoenix", "Santa Fe" + self.cities.append(City("El Paso", neighbors)) + neighbors = "El Paso", "Chihuhua", "Baja", "Phoenix" + self.cities.append(City("Hermosillo", neighbors)) + neighbors = "El Paso", "Monterrey", "Hermosillo" + self.cities.append(City("Chihuhua", neighbors)) + neighbors = "San Antonio", "Chihuhua", "El Paso" + self.cities.append(City("Monterrey", neighbors)) + + # Cascadia (6 cities) + neighbors = "Calgary", "Spokane", "Seattle" + self.cities.append(City("Vancouver", neighbors)) + neighbors = "Regina", "Miles City", "Helena", "Spokane", "Vancouver" + self.cities.append(City("Calgary", neighbors)) + neighbors = "Vancouver", "Spokane", "Portland" + self.cities.append(City("Seattle", neighbors)) + neighbors = "Seattle", "Spokane", "Salt Lake City", "San Francisco" + self.cities.append(City("Portland", neighbors)) + neighbors = "Calgary", "Helena", "Salt Lake City", "Portland", "Seattle", "Vancouver" + self.cities.append(City("Spokane", neighbors)) + neighbors = "Miles City", "Cheyenne", "Salt Lake City", "Spokane" + self.cities.append(City("Helena", neighbors)) + + # California (6 cities) + neighbors = "Cemetery City", "Nuevos Angeles", "San Francisco" + self.cities.append(City("Sacramento", neighbors)) + neighbors = "Salt Lake City", "Sacramento" + self.cities.append(City("Cemetery City", neighbors)) + neighbors = "Portland", "Sacramento", "Nuevos Angeles", "Pacific Haven" + self.cities.append(City("San Francisco", neighbors)) + neighbors = "San Francisco", "Nuevos Angeles" + self.cities.append(City("Pacific Haven", neighbors)) + neighbors = "Sacramento", "Phoenix", "Baja", "Pacific Haven", "San Francisco" + self.cities.append(City("Nuevos Angeles", neighbors)) + neighbors = "Phoenix", "Hermosillo", "Nuevos Angeles" + self.cities.append(City("Baja", neighbors)) + def getCityByName(self, name): for city in self.cities: if city.name == name: @@ -94,11 +178,8 @@ class Board: cities = [start] passedCities = [] - #print("start = " + start.name + " ; target = " + target.name) while True: - #print("dist = " + str(dist)) for city in cities: - #print("city = " + city.name) if target.name in city.neighbors: return dist passedCities.extend(cities) @@ -110,55 +191,90 @@ class Board: cities = newCities dist = dist + 1 + def getNeighbors(self, city, n): # n the degree + if n < 1: + print("ERROR: getNeighbors() needs n > 0") + return False + cities = [city] + i = 1 + while n > 0: + result = [] + for c in cities: + for neighbor in c.neighbors: + neighbor = self.getCityByName(neighbor) + if self.distance(city, neighbor) == i and neighbor not in result: + result.append(neighbor) + cities = result + n = n - 1 + i = i + 1 + return result + class MamaOConnel: def __init__(self): - self.board = Board() # TODO Board should be a "static" or "constant" class, see what we can do - self.location = self.board.cities[random.randint(0, len(self.board.cities) - 1)] + board = Board() # TODO Board should be a "static" or "constant" class, see what we can do + self.location = board.cities[random.randint(0, len(board.cities) - 1)] # We need at least 3 accesses to the city, to provide hints through different axes (but even cities with 3 accesses # can generate a triangle (like Bangor or Tampa), hence the need for 4 accesses) # It could be more proper to have a dedicated method to check if a city can be the location (using distance?) # Moreover, due to their location and their corner neighbors, Montreal and Jacksonville can never have enough hints - # TODO Buffalo sometimes runs in an infinte loop as well; check if still the case after we finished adding cities + # TODO Albany & Boston sometimes run in an infinte loop as well while len(self.location.neighbors) < 4 or self.location.name in ("Montreal", "Jacksonville"): - self.location = self.board.cities[random.randint(0, len(self.board.cities) - 1)] + self.location = board.cities[random.randint(0, len(board.cities) - 1)] hints = [], [], [] - hintsDistance = 3, 3, 2 # TODO randomize + hintsDistance = random.randint(2, 3), random.randint(2, 3), random.randint(2, 3) + while hintsDistance == (2, 2, 2): + hintsDistance = random.randint(2, 3), random.randint(2, 3), random.randint(2, 3) + for h in range(0, 3): - - - # Next hop(s) of hint - #for i in range(0, hintsDistance[h] - 1): i = -1 while i < hintsDistance[h] - 1: if i == -1: # First hop of hint - city = self.board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) + city = board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) if h == 1: while city in hints[0]: - city = self.board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) + city = board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) if h == 2: while city in hints[0] or city in hints[1]: - city = self.board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) + city = board.getCityByName(self.location.neighbors[random.randint(0, len(self.location.neighbors) - 1)]) hints[h].insert(0, city) i = 0 else: do = True - city = self.board.getCityByName(hints[h][i].neighbors[random.randint(0, len(hints[h][i].neighbors) - 1)]) + city = board.getCityByName(hints[h][i].neighbors[random.randint(0, len(hints[h][i].neighbors) - 1)]) counter = 0 - while self.board.distance(city, self.location) < i + 2 or h >= 1 and city in hints[0] or h == 2 and city in hints[1]: + while board.distance(city, self.location) < i + 2 or h >= 1 and city in hints[0] or h == 2 and city in hints[1]: if counter > len(hints[h][i].neighbors) + 5: # arbitrary failsafe i = i - 1 do = False hints[h].pop() break - city = self.board.getCityByName(hints[h][i].neighbors[random.randint(0, len(hints[h][i].neighbors) - 1)]) + city = board.getCityByName(hints[h][i].neighbors[random.randint(0, len(hints[h][i].neighbors) - 1)]) counter = counter + 1 if do: hints[h].insert(i + 1, city) i = i + 1 - # at the end of generation, board and cities should be dropped (no use to keep them in saved data) + self.hint1 = hints[0][-1], hintsDistance[0] + self.hint2 = hints[1][-1], hintsDistance[1] + self.hint3 = hints[2][-1], hintsDistance[2] + + # solver() returns False if criteria are not met (see comments in method), True if they are + def solver(self): + board = Board() + hint1nodes = board.getNeighbors(self.hint1[0], self.hint1[1]) + hint2nodes = board.getNeighbors(self.hint2[0], self.hint2[1]) + cross = [city for city in hint1nodes if city in hint2nodes] + if len(cross) == 1: # only one city remaining after 2 hints + return False + hint3nodes = board.getNeighbors(self.hint3[0], self.hint3[1]) + cross = [city for city in cross if city in hint3nodes] + if len(cross) > 1: # multiple cities remaining after 3 hints + return False + return True myMama = MamaOConnel() +while not myMama.solver(): + myMama = MamaOConnel()