awacke1 commited on
Commit
d3c35bd
·
verified ·
1 Parent(s): e654f48

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +206 -0
app.py ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import time
4
+ from dataclasses import dataclass
5
+ from typing import Dict, List, Optional
6
+
7
+ @dataclass
8
+ class Building:
9
+ name: str
10
+ cost: Dict[str, int]
11
+ produces: Dict[str, float] # Changed to dict for multiple outputs
12
+ color: str
13
+ icon: str
14
+ description: str
15
+
16
+ class FactoryGame:
17
+ def __init__(self):
18
+ self.GRID_SIZE = 8
19
+ self.buildings = {
20
+ "solar_panel": Building(
21
+ name="Solar Panel",
22
+ cost={"minerals": 10},
23
+ produces={"electricity": 1},
24
+ color="#FEF08A",
25
+ icon="☀️",
26
+ description="Produces 1 electricity unit"
27
+ ),
28
+ "mineral_extractor": Building(
29
+ name="Mineral Extractor",
30
+ cost={"electricity": 2},
31
+ produces={"minerals": 1},
32
+ color="#D1D5DB",
33
+ icon="⛏️",
34
+ description="Extracts minerals from the ground"
35
+ ),
36
+ "circuit_factory": Building(
37
+ name="Circuit Factory",
38
+ cost={"electricity": 5, "minerals": 15},
39
+ produces={"circuits": 1},
40
+ color="#BBF7D0",
41
+ icon="🔧",
42
+ description="Produces electronic circuits"
43
+ ),
44
+ "nuclear_plant": Building(
45
+ name="Nuclear Plant",
46
+ cost={"minerals": 50, "circuits": 20},
47
+ produces={"electricity": 10},
48
+ color="#A7F3D0",
49
+ icon="⚛️",
50
+ description="Produces 10 electricity units"
51
+ ),
52
+ "gpu_factory": Building(
53
+ name="GPU Factory",
54
+ cost={"circuits": 30, "minerals": 40},
55
+ produces={"tflops": 100, "electricity": -5}, # Negative for consumption
56
+ color="#C7D2FE",
57
+ icon="🎮",
58
+ description="Produces 100 TFLOPS, consumes 5 electricity"
59
+ )
60
+ }
61
+
62
+ # Initialize session state if needed
63
+ if "resources" not in st.session_state:
64
+ st.session_state.resources = {
65
+ "electricity": 50,
66
+ "minerals": 50,
67
+ "circuits": 0,
68
+ "tflops": 0
69
+ }
70
+ if "grid" not in st.session_state:
71
+ st.session_state.grid = [[None for _ in range(self.GRID_SIZE)]
72
+ for _ in range(self.GRID_SIZE)]
73
+ if "last_update" not in st.session_state:
74
+ st.session_state.last_update = time.time()
75
+ if "selected_building" not in st.session_state:
76
+ st.session_state.selected_building = None
77
+
78
+ def update_resources(self):
79
+ current_time = time.time()
80
+ elapsed = current_time - st.session_state.last_update
81
+
82
+ if elapsed >= 1.0: # Update every second
83
+ new_resources = st.session_state.resources.copy()
84
+
85
+ # First calculate total electricity production/consumption
86
+ electricity_delta = 0
87
+ for row in range(self.GRID_SIZE):
88
+ for col in range(self.GRID_SIZE):
89
+ building_id = st.session_state.grid[row][col]
90
+ if building_id:
91
+ building = self.buildings[building_id]
92
+ if "electricity" in building.produces:
93
+ electricity_delta += building.produces["electricity"]
94
+
95
+ # Only run other production if we have enough electricity
96
+ if new_resources["electricity"] + electricity_delta >= 0:
97
+ new_resources["electricity"] += electricity_delta
98
+
99
+ for row in range(self.GRID_SIZE):
100
+ for col in range(self.GRID_SIZE):
101
+ building_id = st.session_state.grid[row][col]
102
+ if building_id:
103
+ building = self.buildings[building_id]
104
+ for resource, amount in building.produces.items():
105
+ if resource != "electricity": # Already handled above
106
+ new_resources[resource] += amount
107
+
108
+ st.session_state.resources = new_resources
109
+ st.session_state.last_update = current_time
110
+
111
+ def can_afford(self, building_id: str) -> bool:
112
+ building = self.buildings[building_id]
113
+ for resource, cost in building.cost.items():
114
+ if st.session_state.resources.get(resource, 0) < cost:
115
+ return False
116
+ return True
117
+
118
+ def place_building(self, row: int, col: int, building_id: str) -> bool:
119
+ if not self.can_afford(building_id):
120
+ return False
121
+
122
+ if st.session_state.grid[row][col] is not None:
123
+ return False
124
+
125
+ # Deduct costs
126
+ building = self.buildings[building_id]
127
+ for resource, cost in building.cost.items():
128
+ st.session_state.resources[resource] -= cost
129
+
130
+ # Place building
131
+ st.session_state.grid[row][col] = building_id
132
+ return True
133
+
134
+ def select_building(building_id: str):
135
+ st.session_state.selected_building = building_id
136
+
137
+ def handle_cell_click(row: int, col: int, game: FactoryGame):
138
+ if st.session_state.selected_building:
139
+ game.place_building(row, col, st.session_state.selected_building)
140
+
141
+ def main():
142
+ st.set_page_config(page_title="Factory Game", layout="wide")
143
+
144
+ game = FactoryGame()
145
+
146
+ # Title
147
+ st.title("🏭 Factory Game", anchor=False)
148
+
149
+ # Layout columns
150
+ col1, col2 = st.columns([3, 1])
151
+
152
+ with col2:
153
+ # Resources display
154
+ st.subheader("Resources")
155
+ col_a, col_b = st.columns(2)
156
+ with col_a:
157
+ st.metric("⚡ Power", f"{int(st.session_state.resources['electricity'])}")
158
+ st.metric("🪨 Minerals", f"{int(st.session_state.resources['minerals'])}")
159
+ with col_b:
160
+ st.metric("🔌 Circuits", f"{int(st.session_state.resources['circuits'])}")
161
+ st.metric("💻 TFLOPS", f"{int(st.session_state.resources['tflops'])}")
162
+
163
+ # Building selection
164
+ st.subheader("Buildings")
165
+ for building_id, building in game.buildings.items():
166
+ if st.button(
167
+ f"{building.icon} {building.name}\n"
168
+ f"Cost: {', '.join(f'{cost} {res}' for res, cost in building.cost.items())}",
169
+ help=building.description,
170
+ key=f"building_{building_id}",
171
+ type="secondary" if st.session_state.selected_building != building_id else "primary"
172
+ ):
173
+ select_building(building_id)
174
+
175
+ st.caption(f"Selected: {game.buildings[st.session_state.selected_building].icon if st.session_state.selected_building else 'None'}")
176
+
177
+ with col1:
178
+ # Game grid with minimal spacing
179
+ grid_container = st.container()
180
+ with grid_container:
181
+ for row in range(game.GRID_SIZE):
182
+ cols = st.columns(game.GRID_SIZE)
183
+ for col, column in enumerate(cols):
184
+ building_id = st.session_state.grid[row][col]
185
+ building = game.buildings.get(building_id) if building_id else None
186
+
187
+ # Just show the emoji, no labels
188
+ label = building.icon if building else "⬜"
189
+ with column:
190
+ if st.button(
191
+ label,
192
+ key=f"cell_{row}_{col}",
193
+ help=building.name if building else "Empty space",
194
+ use_container_width=True
195
+ ):
196
+ handle_cell_click(row, col, game)
197
+
198
+ # Update resources periodically
199
+ game.update_resources()
200
+
201
+ # Force a rerun every second to update resources
202
+ time.sleep(0.1)
203
+ st.rerun()
204
+
205
+ if __name__ == "__main__":
206
+ main()