File size: 7,990 Bytes
d3c35bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import streamlit as st
import numpy as np
import time
from dataclasses import dataclass
from typing import Dict, List, Optional

@dataclass
class Building:
    name: str
    cost: Dict[str, int]
    produces: Dict[str, float]  # Changed to dict for multiple outputs
    color: str
    icon: str
    description: str

class FactoryGame:
    def __init__(self):
        self.GRID_SIZE = 8
        self.buildings = {
            "solar_panel": Building(
                name="Solar Panel",
                cost={"minerals": 10},
                produces={"electricity": 1},
                color="#FEF08A",
                icon="โ˜€๏ธ",
                description="Produces 1 electricity unit"
            ),
            "mineral_extractor": Building(
                name="Mineral Extractor",
                cost={"electricity": 2},
                produces={"minerals": 1},
                color="#D1D5DB",
                icon="โ›๏ธ",
                description="Extracts minerals from the ground"
            ),
            "circuit_factory": Building(
                name="Circuit Factory",
                cost={"electricity": 5, "minerals": 15},
                produces={"circuits": 1},
                color="#BBF7D0",
                icon="๐Ÿ”ง",
                description="Produces electronic circuits"
            ),
            "nuclear_plant": Building(
                name="Nuclear Plant",
                cost={"minerals": 50, "circuits": 20},
                produces={"electricity": 10},
                color="#A7F3D0",
                icon="โš›๏ธ",
                description="Produces 10 electricity units"
            ),
            "gpu_factory": Building(
                name="GPU Factory",
                cost={"circuits": 30, "minerals": 40},
                produces={"tflops": 100, "electricity": -5},  # Negative for consumption
                color="#C7D2FE",
                icon="๐ŸŽฎ",
                description="Produces 100 TFLOPS, consumes 5 electricity"
            )
        }

        # Initialize session state if needed
        if "resources" not in st.session_state:
            st.session_state.resources = {
                "electricity": 50,
                "minerals": 50,
                "circuits": 0,
                "tflops": 0
            }
        if "grid" not in st.session_state:
            st.session_state.grid = [[None for _ in range(self.GRID_SIZE)] 
                                   for _ in range(self.GRID_SIZE)]
        if "last_update" not in st.session_state:
            st.session_state.last_update = time.time()
        if "selected_building" not in st.session_state:
            st.session_state.selected_building = None

    def update_resources(self):
        current_time = time.time()
        elapsed = current_time - st.session_state.last_update
        
        if elapsed >= 1.0:  # Update every second
            new_resources = st.session_state.resources.copy()
            
            # First calculate total electricity production/consumption
            electricity_delta = 0
            for row in range(self.GRID_SIZE):
                for col in range(self.GRID_SIZE):
                    building_id = st.session_state.grid[row][col]
                    if building_id:
                        building = self.buildings[building_id]
                        if "electricity" in building.produces:
                            electricity_delta += building.produces["electricity"]

            # Only run other production if we have enough electricity
            if new_resources["electricity"] + electricity_delta >= 0:
                new_resources["electricity"] += electricity_delta
                
                for row in range(self.GRID_SIZE):
                    for col in range(self.GRID_SIZE):
                        building_id = st.session_state.grid[row][col]
                        if building_id:
                            building = self.buildings[building_id]
                            for resource, amount in building.produces.items():
                                if resource != "electricity":  # Already handled above
                                    new_resources[resource] += amount
            
            st.session_state.resources = new_resources
            st.session_state.last_update = current_time

    def can_afford(self, building_id: str) -> bool:
        building = self.buildings[building_id]
        for resource, cost in building.cost.items():
            if st.session_state.resources.get(resource, 0) < cost:
                return False
        return True

    def place_building(self, row: int, col: int, building_id: str) -> bool:
        if not self.can_afford(building_id):
            return False

        if st.session_state.grid[row][col] is not None:
            return False

        # Deduct costs
        building = self.buildings[building_id]
        for resource, cost in building.cost.items():
            st.session_state.resources[resource] -= cost

        # Place building
        st.session_state.grid[row][col] = building_id
        return True

def select_building(building_id: str):
    st.session_state.selected_building = building_id

def handle_cell_click(row: int, col: int, game: FactoryGame):
    if st.session_state.selected_building:
        game.place_building(row, col, st.session_state.selected_building)

def main():
    st.set_page_config(page_title="Factory Game", layout="wide")
    
    game = FactoryGame()
    
    # Title
    st.title("๐Ÿญ Factory Game", anchor=False)
    
    # Layout columns
    col1, col2 = st.columns([3, 1])
    
    with col2:
        # Resources display
        st.subheader("Resources")
        col_a, col_b = st.columns(2)
        with col_a:
            st.metric("โšก Power", f"{int(st.session_state.resources['electricity'])}")
            st.metric("๐Ÿชจ Minerals", f"{int(st.session_state.resources['minerals'])}")
        with col_b:
            st.metric("๐Ÿ”Œ Circuits", f"{int(st.session_state.resources['circuits'])}")
            st.metric("๐Ÿ’ป TFLOPS", f"{int(st.session_state.resources['tflops'])}")
        
        # Building selection
        st.subheader("Buildings")
        for building_id, building in game.buildings.items():
            if st.button(
                f"{building.icon} {building.name}\n"
                f"Cost: {', '.join(f'{cost} {res}' for res, cost in building.cost.items())}",
                help=building.description,
                key=f"building_{building_id}",
                type="secondary" if st.session_state.selected_building != building_id else "primary"
            ):
                select_building(building_id)

        st.caption(f"Selected: {game.buildings[st.session_state.selected_building].icon if st.session_state.selected_building else 'None'}")

    with col1:
        # Game grid with minimal spacing
        grid_container = st.container()
        with grid_container:
            for row in range(game.GRID_SIZE):
                cols = st.columns(game.GRID_SIZE)
                for col, column in enumerate(cols):
                    building_id = st.session_state.grid[row][col]
                    building = game.buildings.get(building_id) if building_id else None
                    
                    # Just show the emoji, no labels
                    label = building.icon if building else "โฌœ"
                    with column:
                        if st.button(
                            label,
                            key=f"cell_{row}_{col}",
                            help=building.name if building else "Empty space",
                            use_container_width=True
                        ):
                            handle_cell_click(row, col, game)
    
    # Update resources periodically
    game.update_resources()
    
    # Force a rerun every second to update resources
    time.sleep(0.1)
    st.rerun()

if __name__ == "__main__":
    main()