awacke1 commited on
Commit
6881280
·
verified ·
1 Parent(s): 2804ca9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -74
app.py CHANGED
@@ -12,11 +12,11 @@ import numpy as np
12
 
13
  GRID_WIDTH = 16
14
  GRID_HEIGHT = 9
15
- REFRESH_RATE = 10
16
  INTERACTION_RADIUS = 2
17
  POINTS_PER_INTERACTION = 1
18
 
19
- @st.cache_resource
20
  def get_game_images():
21
  return {
22
  'tile': Image.new('RGB', (50, 50), color='green'),
@@ -33,7 +33,7 @@ def get_name_components():
33
  'is', 'ax', 'on', 'ir', 'ex', 'az', 'er', 'eth', 'ys', 'ix']
34
  }
35
 
36
- @st.cache_data(ttl=2)
37
  def load_all_players(timestamp):
38
  players = {}
39
  if os.path.exists('players'):
@@ -48,87 +48,170 @@ def load_all_players(timestamp):
48
  continue
49
  return {'players': players, 'last_update': time.time()}
50
 
51
- def create_sync_mechanism():
52
- sync_js = """
53
- <script>
54
- function updateGameState() {
55
- const timestamp = Date.now();
56
- window.parent.document.querySelector('.stApp').classList.add('refreshing');
57
- setTimeout(() => window.location.reload(), 100);
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- function displayCharacterSheet(playerData) {
61
- const sidebar = window.parent.document.querySelector('[data-testid="stSidebar"]');
62
- if (sidebar && playerData) {
63
- const statsDiv = document.createElement('div');
64
- statsDiv.innerHTML = `
65
- <div style="padding: 10px; margin: 5px; border: 1px solid #ccc; border-radius: 5px;">
66
- <h3>${playerData.name}</h3>
67
- <p>Score: ${playerData.stats.score}</p>
68
- <p>HP: ${playerData.stats.HP}/${playerData.stats.MAX_HP}</p>
69
- <p>STR: ${playerData.stats.STR}</p>
70
- <p>DEX: ${playerData.stats.DEX}</p>
71
- <p>CON: ${playerData.stats.CON}</p>
72
- <p>INT: ${playerData.stats.INT}</p>
73
- <p>WIS: ${playerData.stats.WIS}</p>
74
- <p>CHA: ${playerData.stats.CHA}</p>
75
- </div>
76
- `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
  }
79
 
80
- function startSync() {
81
- // Update game state every 10 seconds
82
- setInterval(updateGameState, 10000);
83
-
84
- // Handle visibility changes
85
  document.addEventListener('visibilitychange', function() {
86
  if (!document.hidden) {
87
- updateGameState();
88
  }
89
  });
90
-
91
- // Handle focus changes
92
- window.addEventListener('focus', updateGameState);
93
  }
94
 
95
  if (document.readyState === 'complete') {
96
- startSync();
97
  } else {
98
- window.addEventListener('load', startSync);
99
  }
100
  </script>
101
  """
102
- st.components.v1.html(sync_js, height=0)
103
-
104
- def show_character_sheet(player_data):
105
- st.sidebar.markdown("### Character Sheet")
106
- st.sidebar.markdown(f"""
107
- **Name:** {player_data['name']}
108
-
109
- **Stats:**
110
- - HP: {player_data['stats']['HP']}/{player_data['stats']['MAX_HP']}
111
- - STR: {player_data['stats']['STR']}
112
- - DEX: {player_data['stats']['DEX']}
113
- - CON: {player_data['stats']['CON']}
114
- - INT: {player_data['stats']['INT']}
115
- - WIS: {player_data['stats']['WIS']}
116
- - CHA: {player_data['stats']['CHA']}
117
-
118
- **Score:** {player_data['stats']['score']}
119
- """)
120
-
121
- [Previous functions remain the same: generate_fantasy_name, load_game_state, save_game_state, calculate_distance, update_position, etc.]
122
 
123
  def main():
124
- create_sync_mechanism()
125
  update_nearby_players()
126
 
127
  st.sidebar.title("Player Info")
128
 
129
- current_time = time.time()
130
- all_players = load_all_players(current_time)['players']
131
-
132
  if st.session_state.player_name is None:
133
  default_name = generate_fantasy_name()
134
  player_name = st.sidebar.text_input("Enter your name or use generated name:", value=default_name)
@@ -150,12 +233,9 @@ def main():
150
  save_player_state()
151
  st.rerun()
152
  else:
153
- show_character_sheet({'name': st.session_state.player_name, 'stats': st.session_state.character_stats})
154
-
155
- st.sidebar.markdown("### Other Players")
156
- for player_name, player_data in all_players.items():
157
- if player_name != st.session_state.player_name:
158
- show_character_sheet(player_data)
159
 
160
  st.sidebar.markdown("### Movement Controls")
161
  move_cols = st.sidebar.columns(3)
@@ -180,11 +260,6 @@ def main():
180
 
181
  st.title("Multiplayer Tile Game")
182
  create_game_board()
183
-
184
- if (time.time() - st.session_state.last_move) > REFRESH_RATE:
185
- st.session_state.last_move = time.time()
186
- save_player_state()
187
- st.rerun()
188
 
189
  if __name__ == "__main__":
190
  main()
 
12
 
13
  GRID_WIDTH = 16
14
  GRID_HEIGHT = 9
15
+ REFRESH_RATE = 5
16
  INTERACTION_RADIUS = 2
17
  POINTS_PER_INTERACTION = 1
18
 
19
+ @st.cache_resource(show_spinner="Loading game resources...")
20
  def get_game_images():
21
  return {
22
  'tile': Image.new('RGB', (50, 50), color='green'),
 
33
  'is', 'ax', 'on', 'ir', 'ex', 'az', 'er', 'eth', 'ys', 'ix']
34
  }
35
 
36
+ @st.cache_data(ttl=5)
37
  def load_all_players(timestamp):
38
  players = {}
39
  if os.path.exists('players'):
 
48
  continue
49
  return {'players': players, 'last_update': time.time()}
50
 
51
+ def clear_caches():
52
+ st.cache_resource.clear()
53
+ st.cache_data.clear()
54
+
55
+ def generate_fantasy_name():
56
+ name_parts = get_name_components()
57
+ return random.choice(name_parts['prefixes']) + random.choice(name_parts['suffixes'])
58
+
59
+ def load_game_state():
60
+ if 'player_name' in st.query_params:
61
+ st.session_state.player_name = st.query_params.player_name
62
+ st.session_state.position = {
63
+ 'x': int(st.query_params.get('x', random.randint(0, GRID_WIDTH - 1))),
64
+ 'y': int(st.query_params.get('y', random.randint(0, GRID_HEIGHT - 1)))
65
+ }
66
+ st.session_state.character_stats = {
67
+ 'STR': int(st.query_params.get('STR', 10)),
68
+ 'DEX': int(st.query_params.get('DEX', 10)),
69
+ 'CON': int(st.query_params.get('CON', 10)),
70
+ 'INT': int(st.query_params.get('INT', 10)),
71
+ 'WIS': int(st.query_params.get('WIS', 10)),
72
+ 'CHA': int(st.query_params.get('CHA', 10)),
73
+ 'HP': int(st.query_params.get('HP', 20)),
74
+ 'MAX_HP': int(st.query_params.get('MAX_HP', 40)),
75
+ 'score': int(st.query_params.get('score', 0)),
76
+ 'created_at': float(st.query_params.get('created_at', time.time()))
77
+ }
78
+
79
+ def save_game_state():
80
+ if st.session_state.player_name and st.session_state.character_stats:
81
+ params = {
82
+ 'player_name': st.session_state.player_name,
83
+ 'x': str(st.session_state.position['x']),
84
+ 'y': str(st.session_state.position['y']),
85
+ **{k: str(v) for k, v in st.session_state.character_stats.items()}
86
+ }
87
+ st.query_params.from_dict(params)
88
+
89
+ if 'initialized' not in st.session_state:
90
+ st.session_state.initialized = False
91
+ st.session_state.game_state = {
92
+ 'players': {},
93
+ 'chat_messages': [],
94
+ 'last_sync': time.time()
95
+ }
96
+ st.session_state.player_name = None
97
+ st.session_state.character_stats = None
98
+ st.session_state.position = {
99
+ 'x': random.randint(0, GRID_WIDTH - 1),
100
+ 'y': random.randint(0, GRID_HEIGHT - 1)
101
+ }
102
+ st.session_state.last_move = time.time()
103
+ st.session_state.nearby_players = []
104
+ load_game_state()
105
+
106
+ def save_player_state():
107
+ if st.session_state.player_name:
108
+ player_data = {
109
+ 'name': st.session_state.player_name,
110
+ 'position': st.session_state.position,
111
+ 'stats': st.session_state.character_stats,
112
+ 'last_update': time.time()
113
+ }
114
+ os.makedirs('players', exist_ok=True)
115
+ with open(f"players/{st.session_state.player_name}.json", 'w') as f:
116
+ json.dump(player_data, f)
117
+ save_game_state()
118
+
119
+ def calculate_distance(pos1, pos2):
120
+ dx = min(abs(pos1['x'] - pos2['x']), GRID_WIDTH - abs(pos1['x'] - pos2['x']))
121
+ dy = min(abs(pos1['y'] - pos2['y']), GRID_HEIGHT - abs(pos1['y'] - pos2['y']))
122
+ return dx + dy
123
+
124
+ def update_position(direction):
125
+ if direction == "up":
126
+ st.session_state.position['y'] = (st.session_state.position['y'] - 1) % GRID_HEIGHT
127
+ elif direction == "down":
128
+ st.session_state.position['y'] = (st.session_state.position['y'] + 1) % GRID_HEIGHT
129
+ elif direction == "left":
130
+ st.session_state.position['x'] = (st.session_state.position['x'] - 1) % GRID_WIDTH
131
+ elif direction == "right":
132
+ st.session_state.position['x'] = (st.session_state.position['x'] + 1) % GRID_WIDTH
133
+ st.session_state.last_move = time.time()
134
+ save_player_state()
135
+
136
+ def update_nearby_players():
137
+ current_time = time.time()
138
+ all_players = load_all_players(current_time)['players']
139
+ nearby = []
140
+ score_gain = 0
141
+ for player_name, player_data in all_players.items():
142
+ if player_name != st.session_state.player_name:
143
+ distance = calculate_distance(st.session_state.position, player_data['position'])
144
+ if distance <= INTERACTION_RADIUS:
145
+ nearby.append({
146
+ 'name': player_name,
147
+ 'distance': distance,
148
+ 'score': player_data['stats']['score']
149
+ })
150
+ score_gain += POINTS_PER_INTERACTION
151
+ if score_gain > 0:
152
+ st.session_state.character_stats['score'] += score_gain
153
+ save_player_state()
154
+ st.session_state.nearby_players = nearby
155
 
156
+ def create_game_board():
157
+ current_time = time.time()
158
+ all_players = load_all_players(current_time)['players']
159
+ images = get_game_images()
160
+ for y in range(GRID_HEIGHT):
161
+ cols = st.columns(GRID_WIDTH)
162
+ for x in range(GRID_WIDTH):
163
+ player_here = None
164
+ for player_name, player_data in all_players.items():
165
+ if (player_data['position']['x'] == x and
166
+ player_data['position']['y'] == y):
167
+ player_here = player_name
168
+ if x == st.session_state.position['x'] and y == st.session_state.position['y']:
169
+ cols[x].image(images['player'], use_column_width=True)
170
+ cols[x].markdown(f"**You** ({st.session_state.character_stats['score']} pts)")
171
+ elif player_here:
172
+ cols[x].image(images['other_player'], use_column_width=True)
173
+ cols[x].markdown(f"**{player_here}** ({all_players[player_here]['stats']['score']} pts)")
174
+ else:
175
+ cols[x].image(images['tile'], use_column_width=True)
176
+
177
+ def create_autorefresh():
178
+ refresh_html = """
179
+ <script>
180
+ let lastUpdate = Date.now();
181
+
182
+ function checkForUpdates() {
183
+ const now = Date.now();
184
+ if (now - lastUpdate >= 5000) {
185
+ lastUpdate = now;
186
+ window.parent.document.querySelector('.stApp').classList.add('refreshing');
187
+ setTimeout(() => window.location.reload(), 100);
188
  }
189
  }
190
 
191
+ function startAutoRefresh() {
192
+ setInterval(checkForUpdates, 1000);
 
 
 
193
  document.addEventListener('visibilitychange', function() {
194
  if (!document.hidden) {
195
+ lastUpdate = Date.now() - 4900;
196
  }
197
  });
 
 
 
198
  }
199
 
200
  if (document.readyState === 'complete') {
201
+ startAutoRefresh();
202
  } else {
203
+ window.addEventListener('load', startAutoRefresh);
204
  }
205
  </script>
206
  """
207
+ st.components.v1.html(refresh_html, height=0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
  def main():
210
+ create_autorefresh()
211
  update_nearby_players()
212
 
213
  st.sidebar.title("Player Info")
214
 
 
 
 
215
  if st.session_state.player_name is None:
216
  default_name = generate_fantasy_name()
217
  player_name = st.sidebar.text_input("Enter your name or use generated name:", value=default_name)
 
233
  save_player_state()
234
  st.rerun()
235
  else:
236
+ st.sidebar.markdown("### Nearby Players")
237
+ for player in st.session_state.nearby_players:
238
+ st.sidebar.markdown(f"**{player['name']}** - {player['distance']} tiles away - {player['score']} pts")
 
 
 
239
 
240
  st.sidebar.markdown("### Movement Controls")
241
  move_cols = st.sidebar.columns(3)
 
260
 
261
  st.title("Multiplayer Tile Game")
262
  create_game_board()
 
 
 
 
 
263
 
264
  if __name__ == "__main__":
265
  main()