Feature: Implement game initialization on startup and add "New Game" button to UI
Browse files- api.py +17 -0
- frontend/static/index.html +32 -0
api.py
CHANGED
|
@@ -17,6 +17,23 @@ app.add_middleware(
|
|
| 17 |
engine: Engine | None = None
|
| 18 |
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
class StartGameRequest(BaseModel):
|
| 21 |
grid_size: int = 20
|
| 22 |
max_turns: int = 50
|
|
|
|
| 17 |
engine: Engine | None = None
|
| 18 |
|
| 19 |
|
| 20 |
+
@app.on_event("startup")
|
| 21 |
+
async def _seed_default_game():
|
| 22 |
+
"""Pre-create a game so visitors see a live arena instead of a lobby."""
|
| 23 |
+
global engine
|
| 24 |
+
try:
|
| 25 |
+
cfg = GameConfig(grid_size=20, max_turns=100, max_agents=4, num_chests=15)
|
| 26 |
+
eng = Engine(config=cfg)
|
| 27 |
+
eng.generate_grid()
|
| 28 |
+
eng.scatter_chests()
|
| 29 |
+
for i, name in enumerate(_default_names(4)):
|
| 30 |
+
eng.spawn_agent(agent_id=f"agent_{i}", name=name)
|
| 31 |
+
engine = eng
|
| 32 |
+
except Exception as exc:
|
| 33 |
+
import logging
|
| 34 |
+
logging.getLogger("uvicorn.error").warning(f"Default game seed failed: {exc}")
|
| 35 |
+
|
| 36 |
+
|
| 37 |
class StartGameRequest(BaseModel):
|
| 38 |
grid_size: int = 20
|
| 39 |
max_turns: int = 50
|
frontend/static/index.html
CHANGED
|
@@ -1187,6 +1187,7 @@ body {
|
|
| 1187 |
</div>
|
| 1188 |
|
| 1189 |
<div class="top-right">
|
|
|
|
| 1190 |
<button class="camera-mode-badge" id="cameraModeBadge" onclick="togglePov()" title="Toggle chase cam (V) — select an agent first" disabled>📹 OVERVIEW</button>
|
| 1191 |
<span class="winner-announce" id="winnerAnnounce"></span>
|
| 1192 |
</div>
|
|
@@ -3072,6 +3073,37 @@ document.addEventListener('keydown', e => {
|
|
| 3072 |
});
|
| 3073 |
|
| 3074 |
window.addEventListener('resize', ()=>{ if (app) app.resize(); });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3075 |
</script>
|
| 3076 |
</body>
|
| 3077 |
</html>
|
|
|
|
| 1187 |
</div>
|
| 1188 |
|
| 1189 |
<div class="top-right">
|
| 1190 |
+
<button class="camera-mode-badge" id="newGameBtn" onclick="returnToLobby()" title="Open lobby to start a new game">⚙ NEW GAME</button>
|
| 1191 |
<button class="camera-mode-badge" id="cameraModeBadge" onclick="togglePov()" title="Toggle chase cam (V) — select an agent first" disabled>📹 OVERVIEW</button>
|
| 1192 |
<span class="winner-announce" id="winnerAnnounce"></span>
|
| 1193 |
</div>
|
|
|
|
| 3073 |
});
|
| 3074 |
|
| 3075 |
window.addEventListener('resize', ()=>{ if (app) app.resize(); });
|
| 3076 |
+
|
| 3077 |
+
function returnToLobby() {
|
| 3078 |
+
if (autoRunning) auto();
|
| 3079 |
+
gameStarted = false; selectedId = null; state = null;
|
| 3080 |
+
document.getElementById('lobby').classList.remove('hidden');
|
| 3081 |
+
const g = document.getElementById('game'); g.classList.remove('visible'); g.style.display = 'none';
|
| 3082 |
+
}
|
| 3083 |
+
|
| 3084 |
+
async function bootProbe() {
|
| 3085 |
+
try {
|
| 3086 |
+
const r = await fetch('/api/game/state');
|
| 3087 |
+
if (!r.ok) return;
|
| 3088 |
+
const s = await r.json();
|
| 3089 |
+
if (!s || !s.agents || !s.agents.length) return;
|
| 3090 |
+
state = s;
|
| 3091 |
+
gameStarted = true;
|
| 3092 |
+
nameMaterialCache = {};
|
| 3093 |
+
traceHistory = {};
|
| 3094 |
+
document.getElementById('lobby').classList.add('hidden');
|
| 3095 |
+
const game = document.getElementById('game');
|
| 3096 |
+
game.classList.add('visible'); game.style.display = 'flex';
|
| 3097 |
+
showLoading('Joining live arena...');
|
| 3098 |
+
try {
|
| 3099 |
+
await loadThree();
|
| 3100 |
+
if (!app) initScene();
|
| 3101 |
+
requestAnimationFrame(() => { if (app) app.resize(); renderScene(); });
|
| 3102 |
+
updateUI();
|
| 3103 |
+
} finally { hideLoading(); }
|
| 3104 |
+
} catch (_) { /* keep lobby */ }
|
| 3105 |
+
}
|
| 3106 |
+
bootProbe();
|
| 3107 |
</script>
|
| 3108 |
</body>
|
| 3109 |
</html>
|