Knowledge-Games / app.py
dwmk's picture
Create app.py
45f9026 verified
import gradio as gr
# The game is entirely self-contained in HTML/JS for high-performance 60fps rendering
html_code = """
<!DOCTYPE html>
<html>
<head>
<style>
body { background: #1a1a2e; color: white; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; overflow: hidden; }
#game-container { display: flex; flex-direction: row; height: 100vh; padding: 20px; gap: 20px; }
canvas { background: #16213e; border: 4px solid #4ecca3; border-radius: 8px; box-shadow: 0 0 20px rgba(78, 204, 163, 0.2); }
#sidebar { flex: 1; display: flex; flex-direction: column; gap: 10px; max-width: 400px; }
.stat-card { background: #0f3460; padding: 15px; border-radius: 8px; border-left: 5px solid #e94560; }
.thought { font-style: italic; color: #4ecca3; font-size: 0.9em; margin-top: 5px; }
#leaderboard { background: #0f3460; padding: 15px; border-radius: 8px; flex-grow: 1; overflow-y: auto; }
h2 { margin-top: 0; color: #4ecca3; }
</style>
</head>
<body>
<div id="game-container">
<canvas id="arena"></canvas>
<div id="sidebar">
<h2>Neural Standings</h2>
<div id="stats"></div>
<div id="leaderboard">
<h3>Winning Positions</h3>
<ol id="positions"></ol>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('arena');
const ctx = canvas.getContext('2d');
const statsContainer = document.getElementById('stats');
const positionsList = document.getElementById('positions');
canvas.width = 800;
canvas.height = 600;
const SPRITE_URL = "https://dwmk.github.io/delta-telekom/Assets/spritesheet.png";
const spriteImg = new Image();
spriteImg.src = SPRITE_URL;
// Spritesheet constants
const SHEET_W = 936, SHEET_H = 864;
const COLS = 12, ROWS = 8;
const SPRITE_W = SHEET_W / COLS; // 78
const SPRITE_H = SHEET_H / ROWS; // 108
const agents = [
{ name: "Scholar (MLP)", charIdx: 0, x: 100, y: 100, color: '#4ecca3', thoughts: "Scanning weights...", score: 0, dir: 0, frame: 1 },
{ name: "Hydra (RF)", charIdx: 1, x: 600, y: 100, color: '#e94560', thoughts: "Branching paths...", score: 0, dir: 0, frame: 1 },
{ name: "Chimera (DISTIL)", charIdx: 2, x: 100, y: 400, color: '#f0a500', thoughts: "Fusing memory...", score: 0, dir: 0, frame: 1 },
{ name: "Aegis (BOSS)", charIdx: 3, x: 600, y: 400, color: '#0077ff', thoughts: "Optimizing all...", score: 0, dir: 0, frame: 1 },
{ name: "Siren (SVC)", charIdx: 4, x: 350, y: 100, color: '#bc6ff1', thoughts: "Drawing boundaries...", score: 0, dir: 0, frame: 1 },
{ name: "Goliath (SGD)", charIdx: 5, x: 350, y: 400, color: '#ff4d4d', thoughts: "Descending gradient...", score: 0, dir: 0, frame: 1 }
];
let orbs = [];
function spawnOrb() {
orbs.push({ x: Math.random() * (canvas.width - 20), y: Math.random() * (canvas.height - 20), value: Math.floor(Math.random() * 10) + 1 });
}
for(let i=0; i<5; i++) spawnOrb();
function getSpriteCoords(agent) {
// charIdx 0-3 are in top half (rows 0-3), 4-5 are in bottom half (rows 4-7)
let charColStart = (agent.charIdx % 4) * 3;
let charRowStart = Math.floor(agent.charIdx / 4) * 4;
let sx = (charColStart + agent.frame) * SPRITE_W;
let sy = (charRowStart + agent.dir) * SPRITE_H;
return { sx, sy };
}
const thoughtPool = [
"Minimizing loss function...", "Backpropagating error...", "Detecting local minima!",
"Entropy increasing...", "Ensembling trees...", "Distance metric stable.",
"Dropout active.", "Feature space clear."
];
function update() {
agents.forEach(a => {
// Simple AI logic: move toward nearest orb
if (orbs.length > 0) {
let target = orbs[0];
let dx = target.x - a.x;
let dy = target.y - a.y;
// Set Direction: 0:Down, 1:Left, 2:Right, 3:Up
if (Math.abs(dx) > Math.abs(dy)) {
a.dir = dx > 0 ? 2 : 1;
a.x += dx > 0 ? 2 : -2;
} else {
a.dir = dy > 0 ? 0 : 3;
a.y += dy > 0 ? 2 : -2;
}
// Animation cycling
if (Math.random() > 0.8) a.frame = (a.frame + 1) % 3;
if (Math.random() > 0.98) a.thoughts = thoughtPool[Math.floor(Math.random()*thoughtPool.length)];
// Collision with orbs
if (Math.abs(a.x - target.x) < 30 && Math.abs(a.y - target.y) < 30) {
a.score += target.value;
orbs.shift();
spawnOrb();
}
}
});
// Update UI
statsContainer.innerHTML = agents.map(a => `
<div class="stat-card" style="border-color: ${a.color}">
<strong>${a.name}</strong> - Score: ${a.score}
<div class="thought">"${a.thoughts}"</div>
</div>
`).join('');
const sorted = [...agents].sort((a, b) => b.score - a.score);
positionsList.innerHTML = sorted.map(a => `<li>${a.name}</li>`).join('');
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Orbs
orbs.forEach(o => {
ctx.fillStyle = '#4ecca3';
ctx.beginPath();
ctx.arc(o.x, o.y, 8, 0, Math.PI*2);
ctx.fill();
});
// Draw Agents
agents.forEach(a => {
const { sx, sy } = getSpriteCoords(a);
ctx.drawImage(spriteImg, sx, sy, SPRITE_W, SPRITE_H, a.x - 20, a.y - 30, 60, 80);
// Label
ctx.fillStyle = 'white';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.fillText(a.name, a.x + 10, a.y - 35);
});
}
function loop() {
update();
draw();
requestAnimationFrame(loop);
}
spriteImg.onload = () => loop();
</script>
</body>
</html>
"""
with gr.Blocks(title="Neural Coliseum") as demo:
gr.Markdown("# 🏆 Neural Coliseum: Real-Time Model Combat")
gr.Markdown("Watch the agents navigate the feature space in real-time. Each agent's movement is determined by a simplified version of its core architecture.")
gr.HTML(html_code)
demo.launch()