Spaces:
Running
Running
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Factory Game</title> | |
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" /> | |
<style> | |
html, body { | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<gradio-lite> | |
<gradio-file name="app.py" entrypoint> | |
import gradio as gr | |
import json | |
GRID_SIZE = 8 | |
class GameState: | |
def __init__(self): | |
self.resources = { | |
"energy": 50, | |
"minerals": 50, | |
"circuits": 0 | |
} | |
self.grid = [[None for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)] | |
self.message = "" | |
def to_json(self): | |
return json.dumps({ | |
"resources": self.resources, | |
"grid": self.grid, | |
"message": self.message | |
}) | |
def process_click(row, col, building_type, state_json): | |
if not state_json: | |
return GameState().to_json() | |
state = json.loads(state_json) | |
game = GameState() | |
game.resources = state["resources"] | |
game.grid = state["grid"] | |
# Building costs | |
costs = { | |
"solarPanel": {"minerals": 10}, | |
"mineralExtractor": {"energy": 10}, | |
"circuitFactory": {"energy": 15, "minerals": 15} | |
} | |
# Check if we can afford the building | |
if building_type in costs: | |
can_afford = True | |
for resource, cost in costs[building_type].items(): | |
if game.resources[resource] < cost: | |
can_afford = False | |
game.message = f"Not enough {resource}!" | |
break | |
if can_afford: | |
# Deduct resources | |
for resource, cost in costs[building_type].items(): | |
game.resources[resource] -= cost | |
# Place building | |
if game.grid[row][col] is None: | |
game.grid[row][col] = building_type | |
game.message = f"Placed {building_type}" | |
else: | |
game.message = "Space already occupied!" | |
# Produce resources from buildings | |
for r in range(GRID_SIZE): | |
for c in range(GRID_SIZE): | |
building = game.grid[r][c] | |
if building == "solarPanel": | |
game.resources["energy"] += 1 | |
elif building == "mineralExtractor": | |
game.resources["minerals"] += 1 | |
elif building == "circuitFactory": | |
game.resources["circuits"] += 1 | |
return game.to_json() | |
def create_ui(): | |
building_colors = { | |
"solarPanel": "#FEF08A", | |
"mineralExtractor": "#D1D5DB", | |
"circuitFactory": "#BBF7D0" | |
} | |
html = f""" | |
<div style="max-width: 800px; margin: 0 auto; padding: 1rem;"> | |
<div id="resources" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem;"> | |
<div style="padding: 0.75rem; border-radius: 0.5rem; background: #FEF9C3;">Energy: <span id="energy">50</span></div> | |
<div style="padding: 0.75rem; border-radius: 0.5rem; background: #F3F4F6;">Minerals: <span id="minerals">50</span></div> | |
<div style="padding: 0.75rem; border-radius: 0.5rem; background: #DCFCE7;">Circuits: <span id="circuits">0</span></div> | |
</div> | |
<div style="display: flex; gap: 1rem; margin-bottom: 1rem;"> | |
<button onclick="window.selectedBuilding='solarPanel'" style="padding: 1rem; border-radius: 0.5rem; background: #FEF08A;"> | |
Solar Panel<br>Cost: 10 minerals | |
</button> | |
<button onclick="window.selectedBuilding='mineralExtractor'" style="padding: 1rem; border-radius: 0.5rem; background: #D1D5DB;"> | |
Mineral Extractor<br>Cost: 10 energy | |
</button> | |
<button onclick="window.selectedBuilding='circuitFactory'" style="padding: 1rem; border-radius: 0.5rem; background: #BBF7D0;"> | |
Circuit Factory<br>Cost: 15 energy, 15 minerals | |
</button> | |
</div> | |
<div id="message" style="text-align: center; color: #2563EB; font-weight: 500; margin: 0.5rem 0;"></div> | |
<div id="grid" style="display: grid; grid-template-columns: repeat({GRID_SIZE}, 1fr); gap: 0.25rem; background: #F3F4F6; padding: 0.5rem; border-radius: 0.5rem;"> | |
{''''.join(f''' | |
<button | |
onclick="placeBuilding({r}, {c})" | |
id="cell-{r}-{c}" | |
style="aspect-ratio: 1; border-radius: 0.5rem; border: none; cursor: pointer; background: white;"> | |
</button> | |
''' for r in range(GRID_SIZE) for c in range(GRID_SIZE))} | |
</div> | |
</div> | |
<script> | |
</script> | |
""" | |
return gr.HTML(html) | |
with gr.Blocks() as demo: | |
state = gr.State() | |
click_handler = gr.Interface( | |
fn=process_click, | |
inputs=[ | |
gr.Number(label="Row"), | |
gr.Number(label="Col"), | |
gr.Text(label="Building"), | |
gr.Text(label="State") | |
], | |
outputs=gr.Text(label="New State"), | |
live=True | |
) | |
ui = create_ui() | |
def update_ui(value): | |
return value | |
click_handler.load(lambda: GameState().to_json()) | |
demo.load(lambda: None, None, _js="() => { window.send_click = (row, col, building, state) => { "+click_handler.jsfn+"(row, col, building, state).then((v) => updateUI(JSON.parse(v))) } }") | |
demo.launch() | |
</gradio-file> | |
<gradio-requirements> | |
</gradio-requirements> | |
</gradio-lite> | |
</body> | |
</html> |