she put her bidge to the bidge.
commit
8a93dc36f0
|
|
@ -0,0 +1,50 @@
|
|||
from enum import Enum
|
||||
|
||||
from engine import Recipe
|
||||
|
||||
class Item(Enum):
|
||||
IronBar = "Iron Bar"
|
||||
CopperBar = "Copper Bar"
|
||||
SteelBar = "Steel Bar"
|
||||
IronPlate = "Iron Plate"
|
||||
CopperPlate = "Copper Plate"
|
||||
IronBeam = "Iron Beam"
|
||||
CopperBeam = "Copper Beam"
|
||||
SteelBeam = "Steel Beam"
|
||||
IronMechanicalParts = "Iron Mechanical Parts"
|
||||
CopperMechanicalParts = "Copper Mechanical Parts"
|
||||
SteelMechanicalParts = "Steel Mechanical Parts"
|
||||
CrushedIron = "Crushed Iron"
|
||||
CrushedCoalCoke = "Crushed Coal Coke"
|
||||
SteelBlend = "Steel Blend"
|
||||
CoalCoke = "Coal Coke"
|
||||
SteamEngine = "Steam Engine"
|
||||
SteamAssembler = "Steam Assembler"
|
||||
SteamCrusher = "Steam Crusher"
|
||||
Pipe = "Pipe"
|
||||
|
||||
class Recipes(Enum):
|
||||
IronPlate = Recipe([Item.IronBar], [Item.IronPlate], "Iron Plate")
|
||||
CopperPlate = Recipe([Item.CopperBar], [Item.CopperPlate], "Copper Plate")
|
||||
IronBeam = Recipe([Item.IronBar], [Item.IronBeam], "Iron Beam")
|
||||
CopperBeam = Recipe([Item.CopperBar], [Item.CopperBeam], "Copper Beam")
|
||||
SteelBeam = Recipe([Item.SteelBar], [Item.SteelBeam], "Steel Beam")
|
||||
IronMechanicalParts = Recipe([Item.IronBar], [Item.IronMechanicalParts], "Iron Mechanical Parts")
|
||||
CopperMechanicalParts = Recipe([Item.CopperBar], [Item.CopperMechanicalParts], "Copper Mechanical Parts")
|
||||
SteelMechanicalParts = Recipe([Item.SteelBar], [Item.SteelMechanicalParts], "Steel Mechanical Parts")
|
||||
Pipe = Recipe([Item.IronPlate, Item.IronMechanicalParts], [Item.Pipe], "Pipe")
|
||||
SteamEngine = Recipe([Item.Pipe, Item.CopperMechanicalParts], [Item.SteamEngine], "Steam Engine")
|
||||
SteamAssembler = Recipe([
|
||||
Item.Pipe,
|
||||
Item.CopperMechanicalParts,
|
||||
Item.SteamEngine,
|
||||
Item.CopperBeam
|
||||
], [Item.SteamAssembler], "Steam Assembler")
|
||||
SteamCrusher = Recipe([
|
||||
Item.Pipe,
|
||||
Item.IronMechanicalParts,
|
||||
Item.SteamEngine,
|
||||
Item.CopperBeam
|
||||
], [Item.SteamCrusher], "Steam Crusher")
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
from typing import List, Set, Tuple
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.patches import Rectangle
|
||||
from typing import List, Any
|
||||
|
||||
class Item:
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
class Recipe:
|
||||
def __init__(self, inputs: List[Item], outputs: List[Item], name: str) -> None:
|
||||
self.inputs = inputs
|
||||
self.outputs = outputs
|
||||
self.name = name
|
||||
|
||||
class World:
|
||||
def __init__(
|
||||
self,
|
||||
recipes: Set[Recipe],
|
||||
items: Set[Item],
|
||||
bus: Set[Item],
|
||||
size: int
|
||||
) -> None:
|
||||
self.recipes = recipes
|
||||
self.items = items
|
||||
self.bus = bus
|
||||
self.size = size
|
||||
|
||||
|
||||
def find_valid_recipes(output: Item, world: World) -> List[Recipe]:
|
||||
valid_recipes = []
|
||||
for recipe in world.recipes:
|
||||
if output in recipe.value.outputs:
|
||||
valid_recipes.append(recipe.value)
|
||||
return valid_recipes
|
||||
|
||||
|
||||
class Assembler:
|
||||
def __init__(self, recipe: Recipe, world: World) -> None:
|
||||
self.recipe = recipe
|
||||
self.input_links = [] # List[Assembler]
|
||||
self.world = world
|
||||
|
||||
def link_input(self, assembler: "Assembler") -> None:
|
||||
self.input_links.append(assembler)
|
||||
|
||||
def get_unlinked_inputs(self) -> List[Item]:
|
||||
return [
|
||||
item
|
||||
for item in self.recipe.inputs
|
||||
if item not in [
|
||||
assembler.recipe.outputs
|
||||
for assembler in self.input_links
|
||||
].flatten()
|
||||
and item not in self.world.bus
|
||||
]
|
||||
|
||||
def is_solved(self) -> bool:
|
||||
return len(self.get_unlinked_inputs()) == 0
|
||||
|
||||
class Graph:
|
||||
def __init__(self, world: World) -> None:
|
||||
self.grid: List[List["Assembler"]] = [
|
||||
[
|
||||
None for _ in range(world.size)
|
||||
] for _ in range(world.size)
|
||||
]
|
||||
self.world = world
|
||||
|
||||
def create_graph(world: World, recipe: Recipe) -> "Graph":
|
||||
graph = Graph(world)
|
||||
graph.grid[1][world.size // 2] = recipe
|
||||
return graph
|
||||
|
||||
def get_coordinates_of_assembler(self, assembler: Assembler) -> (int, int):
|
||||
for i in range(len(self.grid)):
|
||||
for j in range(len(self.grid)):
|
||||
if self.grid[i][j] == assembler:
|
||||
return (i, j)
|
||||
return None
|
||||
|
||||
def clone(self) -> "Graph":
|
||||
new_graph = Graph(len(self.grid))
|
||||
for i in range(len(self.grid)):
|
||||
for j in range(len(self.grid)):
|
||||
if self.grid[i][j] is not None:
|
||||
assembler = self.grid[i][j]
|
||||
new_assembler = Assembler(assembler.recipe)
|
||||
|
||||
# re-link assemblers in cloned graph
|
||||
for i in range(len(self.grid)):
|
||||
for j in range(len(self.grid)):
|
||||
if self.grid[i][j] is not None:
|
||||
assembler = self.grid[i][j]
|
||||
new_assembler = Assembler(assembler.recipe)
|
||||
for link in assembler.input_links:
|
||||
coords = self.get_coordinates_of_assembler(link)
|
||||
new_assembler.link_input(new_graph.grid[coords[0]][coords[1]])
|
||||
|
||||
return new_graph
|
||||
|
||||
def add_assembler(self, recipe: Assembler, x: int, y: int) -> "Graph":
|
||||
graph = self.clone()
|
||||
graph.grid[x][y] = recipe
|
||||
return graph
|
||||
|
||||
def is_solved_at(self, x: int, y: int) -> bool:
|
||||
if self.grid[x][y] is None:
|
||||
return False
|
||||
return self.grid[x][y].is_solved()
|
||||
|
||||
def is_solved(self) -> bool:
|
||||
for i in range(len(self.grid)):
|
||||
for j in range(len(self.grid)):
|
||||
if not self.is_solved_at(i, j):
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_adjacent_coordinates(self, x: int, y: int) -> List[Tuple[int, int]]:
|
||||
return [
|
||||
(x + 1, y) if x < len(self.grid) - 1 else None,
|
||||
(x - 1, y) if x > 0 else None,
|
||||
(x, y + 1) if y < len(self.grid) - 1 else None,
|
||||
(x, y - 1) if y > 0 else None,
|
||||
(x + 1, y + 1) if x < len(self.grid) - 1 and y < len(self.grid) - 1 and y % 2 == 0 else None,
|
||||
(x + 1, y - 1) if x < len(self.grid) - 1 and y > 0 and y % 2 == 0 else None,
|
||||
(x - 1, y + 1) if x > 0 and y < len(self.grid) - 1 and y % 2 == 1 else None,
|
||||
(x - 1, y - 1) if x > 0 and y > 0 and y % 2 == 1 else None,
|
||||
].filter(lambda x: x is not None)
|
||||
|
||||
def are_coordinates_adjacent(self, a: (int, int), b: (int, int)) -> bool:
|
||||
adjacent_coordinates = self.get_adjacent_coordinates(a[0], a[1])
|
||||
return b in adjacent_coordinates
|
||||
|
||||
def draw(self) -> None:
|
||||
plt.figure()
|
||||
|
||||
def convert_coords(p: (int, int)) -> (int, int):
|
||||
(x, y) = p
|
||||
return (x + 0.5 if y % 2 == 1 else x, y * 0.86602540378)
|
||||
|
||||
|
||||
for row in self.grid:
|
||||
for assembler in row:
|
||||
if assembler is not None:
|
||||
(x, y) = convert_coords(self.get_coordinates_of_assembler(assembler))
|
||||
plt.gca().add_patch(Rectangle((x - 0.5, y - 0.5), 1, 1, fill=True))
|
||||
plt.annotate("thing", (x, y), textcoords="offset points", xytext=(0,5), ha='center')
|
||||
|
||||
# # Adding edges (arrows) between nodes
|
||||
# plt.arrow(0, 0, 0.9, 0.9, head_width=0.05, head_length=0.1, fc='k', ec='k')
|
||||
# plt.arrow(1, 1, 0.9, -0.9, head_width=0.05, head_length=0.1, fc='k', ec='k')
|
||||
|
||||
# Setting the plot limits
|
||||
plt.xlim(-1, 11)
|
||||
plt.ylim(-1, 11)
|
||||
|
||||
# Show the plot
|
||||
plt.show()
|
||||
|
||||
def get_solutions(self) -> List["Graph"]:
|
||||
if self.is_solved():
|
||||
return []
|
||||
|
||||
graphs: List["Graph"] = []
|
||||
|
||||
for x in range(len(self.grid)):
|
||||
for y in range(len(self.grid)):
|
||||
assembler = self.grid[x][y]
|
||||
if assembler == None:
|
||||
continue
|
||||
print(assembler)
|
||||
# for item in assembler.get_unlinked_inputs():
|
||||
# for recipes in find_valid_recipes(item):
|
||||
# graph = self.add_assembler(assembler, x, y)
|
||||
# graphs.append(graph)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from typing import List
|
||||
from data import Item, Recipes
|
||||
from engine import Graph
|
||||
|
||||
bus_resources = [
|
||||
Item.IronBar,
|
||||
Item.CopperBar,
|
||||
Item.SteelBar,
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
solutions = Graph.create_graph(10, Recipes.IronPlate).get_solutions()
|
||||
for solution in solutions:
|
||||
solution.draw()
|
||||
Loading…
Reference in New Issue