open-weights-breakout / app /LogoAlliance.tsx
burtenshaw's picture
burtenshaw HF Staff
Remove logo seams and game sidebar
95be329 verified
Raw
History Blame Contribute Delete
23.7 kB
"use client";
import { useCallback, useEffect, useRef, useState } from "react";
const COLS = 10;
const ROWS = 18;
const CELL = 42;
const BOARD_WIDTH = COLS * CELL;
const BOARD_HEIGHT = ROWS * CELL;
const TARGET_ROW = 11;
const TARGET_LAYERS = ROWS - TARGET_ROW;
const LOGOS = [
["Anthropic", "anthropic-wordmark", "/anthropic-wordmark.png"],
["AI21", "ai21", "/logos/ai21.png"],
["AMD", "amd", "/logos/amd.png"],
["American Innovators Network", "american-innovators-network", "/logos/american-innovators-network.png"],
["AMP", "amp", "/logos/amp.png"],
["Andreessen Horowitz", "andreessen-horowitz", "/logos/andreessen-horowitz.png"],
["Arcee AI", "arcee-ai", "/logos/arcee-ai.png"],
["Arena", "arena", "/logos/arena.png"],
["Baseten", "baseten", "/logos/baseten.png"],
["Black Forest Labs", "black-forest-labs", "/logos/black-forest-labs.png"],
["Block", "block", "/logos/block.png"],
["Box", "box", "/logos/box.png"],
["Cisco", "cisco", "/logos/cisco.png"],
["Cloudflare", "cloudflare", "/logos/cloudflare.png"],
["Cohere", "cohere", "/logos/cohere.png"],
["CrowdStrike", "crowdstrike", "/logos/crowdstrike.png"],
["Dell Technologies", "dell-technologies", "/logos/dell-technologies.png"],
["DoorDash", "doordash", "/logos/doordash.png"],
["Emergence Capital", "emergence-capital", "/logos/emergence-capital.png"],
["Fireworks AI", "fireworks-ai", "/logos/fireworks-ai.png"],
["Genspark", "genspark", "/logos/genspark.png"],
["GitHub", "github", "/logos/github.png"],
["Google", "google", "/logos/google.png"],
["Hugging Face", "hugging-face", "/logos/hugging-face.png"],
["IBM", "ibm", "/logos/ibm.png"],
["Inferact", "inferact", "/logos/inferact.png"],
["Interconnects AI", "interconnects-ai", "/logos/interconnects-ai.png"],
["The Linux Foundation", "linux-foundation", "/logos/linux-foundation.png"],
["Mariana Minerals", "mariana-minerals", "/logos/mariana-minerals.png"],
["Meta", "meta", "/logos/meta.png"],
["Microsoft", "microsoft", "/logos/microsoft.png"],
["Mistral", "mistral", "/logos/mistral.png"],
["Morph", "morph", "/logos/morph.png"],
["Mozilla", "mozilla", "/logos/mozilla.png"],
["Nebius", "nebius", "/logos/nebius.png"],
["Nous Research", "nous-research", "/logos/nous-research.png"],
["NVIDIA", "nvidia", "/logos/nvidia.png"],
["Ollama", "ollama", "/logos/ollama.png"],
["OpenAI", "openai", "/logos/openai.png"],
["OpenClaw", "openclaw", "/logos/openclaw.png"],
["Palantir", "palantir", "/logos/palantir.png"],
["Palo Alto Networks", "palo-alto-networks", "/logos/palo-alto-networks.png"],
["Periodic Labs", "periodic-labs", "/logos/periodic-labs.png"],
["Perplexity", "perplexity", "/logos/perplexity.png"],
["Prime Intellect", "prime-intellect", "/logos/prime-intellect.png"],
["Reflection", "reflection", "/logos/reflection.png"],
["Replit", "replit", "/logos/replit.png"],
["ServiceNow", "servicenow", "/logos/servicenow.png"],
["Telnyx", "telnyx", "/logos/telnyx.png"],
["Trajectory", "trajectory", "/logos/trajectory.png"],
["Y Combinator", "y-combinator", "/logos/y-combinator.png"],
] as const;
const SHAPES = {
I: [
{ x: 0, y: 0 },
{ x: 1, y: 0 },
{ x: 2, y: 0 },
{ x: 3, y: 0 },
],
O: [
{ x: 0, y: 0 },
{ x: 1, y: 0 },
{ x: 0, y: 1 },
{ x: 1, y: 1 },
],
T: [
{ x: 1, y: 0 },
{ x: 0, y: 1 },
{ x: 1, y: 1 },
{ x: 2, y: 1 },
],
L: [
{ x: 0, y: 0 },
{ x: 0, y: 1 },
{ x: 1, y: 1 },
{ x: 2, y: 1 },
],
J: [
{ x: 2, y: 0 },
{ x: 0, y: 1 },
{ x: 1, y: 1 },
{ x: 2, y: 1 },
],
S: [
{ x: 1, y: 0 },
{ x: 2, y: 0 },
{ x: 0, y: 1 },
{ x: 1, y: 1 },
],
Z: [
{ x: 0, y: 0 },
{ x: 1, y: 0 },
{ x: 1, y: 1 },
{ x: 2, y: 1 },
],
} as const;
type ShapeId = keyof typeof SHAPES;
type Status = "loading" | "ready" | "running" | "paused" | "won" | "lost";
type Point = { x: number; y: number };
type QueueEntry = { shapeId: ShapeId; logoIndex: number };
type BoardCell = { groupId: number; logoIndex: number };
type Piece = QueueEntry & {
cells: Point[];
x: number;
y: number;
groupId: number;
};
type Game = {
status: Status;
board: (BoardCell | null)[][];
current: Piece | null;
queue: QueueEntry[];
shapeBag: ShapeId[];
logoBag: number[];
held: QueueEntry | null;
holdUsed: boolean;
pieces: number;
completedLayers: number;
nextGroupId: number;
lastDrop: number;
images: HTMLImageElement[];
};
type Action =
| "start"
| "restart"
| "pause"
| "left"
| "right"
| "down"
| "rotate"
| "drop"
| "hold";
const shuffle = <T,>(values: T[]): T[] => {
const result = [...values];
for (let index = result.length - 1; index > 0; index -= 1) {
const swapIndex = Math.floor(Math.random() * (index + 1));
[result[index], result[swapIndex]] = [result[swapIndex], result[index]];
}
return result;
};
const loadImage = (src: string) =>
new Promise<HTMLImageElement>((resolve, reject) => {
const image = new Image();
image.onload = () => resolve(image);
image.onerror = () => reject(new Error(`Could not load ${src}`));
image.src = src;
});
const normalizeCells = (cells: Point[]): Point[] => {
const minX = Math.min(...cells.map((cell) => cell.x));
const minY = Math.min(...cells.map((cell) => cell.y));
return cells.map((cell) => ({ x: cell.x - minX, y: cell.y - minY }));
};
const rotateCells = (shapeId: ShapeId, cells: Point[]): Point[] => {
if (shapeId === "O") return cells;
return normalizeCells(cells.map((cell) => ({ x: -cell.y, y: cell.x })));
};
const refillQueue = (game: Game) => {
while (game.queue.length < 4) {
if (!game.shapeBag.length) {
game.shapeBag = shuffle(Object.keys(SHAPES) as ShapeId[]);
}
if (!game.logoBag.length) {
game.logoBag = shuffle(LOGOS.map((_, index) => index));
}
game.queue.push({
shapeId: game.shapeBag.shift() as ShapeId,
logoIndex: game.logoBag.shift() as number,
});
}
};
const canPlace = (
game: Game,
cells: Point[],
offsetX: number,
offsetY: number,
) =>
cells.every((cell) => {
const x = offsetX + cell.x;
const y = offsetY + cell.y;
return (
x >= 0 &&
x < COLS &&
y >= 0 &&
y < ROWS &&
game.board[y][x] === null
);
});
const makePiece = (game: Game, entry: QueueEntry): Piece => {
const cells = SHAPES[entry.shapeId].map((cell) => ({ ...cell }));
const width = Math.max(...cells.map((cell) => cell.x)) + 1;
return {
...entry,
cells,
x: Math.floor((COLS - width) / 2),
y: 0,
groupId: game.nextGroupId++,
};
};
const spawnNext = (game: Game) => {
refillQueue(game);
const entry = game.queue.shift() as QueueEntry;
refillQueue(game);
game.current = makePiece(game, entry);
game.lastDrop = performance.now();
if (!canPlace(game, game.current.cells, game.current.x, game.current.y)) {
game.status = "lost";
game.current = null;
}
};
const countCompletedLayers = (game: Game) => {
let layers = 0;
for (let row = ROWS - 1; row >= TARGET_ROW; row -= 1) {
if (game.board[row].every(Boolean)) layers += 1;
}
return layers;
};
const lockPiece = (game: Game) => {
if (!game.current) return;
for (const cell of game.current.cells) {
const x = game.current.x + cell.x;
const y = game.current.y + cell.y;
game.board[y][x] = {
groupId: game.current.groupId,
logoIndex: game.current.logoIndex,
};
}
game.pieces += 1;
game.completedLayers = countCompletedLayers(game);
game.current = null;
game.holdUsed = false;
if (game.completedLayers === TARGET_LAYERS) {
game.status = "won";
return;
}
spawnNext(game);
};
const createGame = (images: HTMLImageElement[]): Game => {
const game: Game = {
status: "ready",
board: Array.from({ length: ROWS }, () =>
Array.from({ length: COLS }, () => null),
),
current: null,
queue: [],
shapeBag: [],
logoBag: [],
held: null,
holdUsed: false,
pieces: 0,
completedLayers: 0,
nextGroupId: 1,
lastDrop: performance.now(),
images,
};
refillQueue(game);
spawnNext(game);
return game;
};
const absoluteCells = (piece: Piece, yOverride = piece.y) =>
piece.cells.map((cell) => ({
x: piece.x + cell.x,
y: yOverride + cell.y,
}));
const movePiece = (game: Game, x: number, y: number) => {
if (!game.current) return false;
if (
!canPlace(
game,
game.current.cells,
game.current.x + x,
game.current.y + y,
)
) {
return false;
}
game.current.x += x;
game.current.y += y;
return true;
};
const tryRotate = (game: Game) => {
if (!game.current) return false;
const rotated = rotateCells(game.current.shapeId, game.current.cells);
for (const kick of [0, -1, 1, -2, 2]) {
if (canPlace(game, rotated, game.current.x + kick, game.current.y)) {
game.current.cells = rotated;
game.current.x += kick;
return true;
}
}
return false;
};
const ghostY = (game: Game) => {
if (!game.current) return 0;
let y = game.current.y;
while (canPlace(game, game.current.cells, game.current.x, y + 1)) y += 1;
return y;
};
const drawLogoGroup = (
context: CanvasRenderingContext2D,
cells: Point[],
image: HTMLImageElement,
alpha = 1,
) => {
if (!cells.length) return;
const minX = Math.min(...cells.map((cell) => cell.x));
const maxX = Math.max(...cells.map((cell) => cell.x));
const minY = Math.min(...cells.map((cell) => cell.y));
const maxY = Math.max(...cells.map((cell) => cell.y));
const x = minX * CELL;
const y = minY * CELL;
const width = (maxX - minX + 1) * CELL;
const height = (maxY - minY + 1) * CELL;
context.save();
context.globalAlpha = alpha;
context.fillStyle = "#efefec";
for (const cell of cells) {
context.fillRect(cell.x * CELL, cell.y * CELL, CELL, CELL);
}
context.beginPath();
for (const cell of cells) {
context.rect(cell.x * CELL, cell.y * CELL, CELL, CELL);
}
context.clip();
context.globalCompositeOperation = "multiply";
const maxWidth = Math.max(1, width - 12);
const maxHeight = Math.max(1, height - 12);
const scale = Math.min(
maxWidth / image.naturalWidth,
maxHeight / image.naturalHeight,
);
const drawWidth = image.naturalWidth * scale;
const drawHeight = image.naturalHeight * scale;
context.drawImage(
image,
x + (width - drawWidth) / 2,
y + (height - drawHeight) / 2,
drawWidth,
drawHeight,
);
context.restore();
};
export function LogoAlliance() {
const canvasRef = useRef<HTMLCanvasElement>(null);
const gameRef = useRef<Game | null>(null);
const soundRef = useRef<{ muted: boolean; context: AudioContext | null }>({
muted: false,
context: null,
});
const [status, setStatus] = useState<Status>("loading");
const [pieces, setPieces] = useState(0);
const [layers, setLayers] = useState(0);
const [muted, setMuted] = useState(false);
const tone = useCallback((frequency: number, duration = 0.055) => {
if (soundRef.current.muted) return;
const AudioContextClass =
window.AudioContext ||
(
window as typeof window & {
webkitAudioContext?: typeof AudioContext;
}
).webkitAudioContext;
if (!AudioContextClass) return;
const audioContext =
soundRef.current.context ?? new AudioContextClass();
soundRef.current.context = audioContext;
const oscillator = audioContext.createOscillator();
const gain = audioContext.createGain();
const now = audioContext.currentTime;
oscillator.type = "sine";
oscillator.frequency.setValueAtTime(frequency, now);
gain.gain.setValueAtTime(0.018, now);
gain.gain.exponentialRampToValueAtTime(0.0001, now + duration);
oscillator.connect(gain);
gain.connect(audioContext.destination);
oscillator.start(now);
oscillator.stop(now + duration);
}, []);
const syncUi = useCallback((game: Game) => {
setStatus(game.status);
setPieces(game.pieces);
setLayers(game.completedLayers);
}, []);
const dispatch = useCallback(
(action: Action) => {
let game = gameRef.current;
if (!game) return;
if (action === "restart") {
game = createGame(game.images);
gameRef.current = game;
syncUi(game);
return;
}
if (action === "start") {
if (game.status === "won" || game.status === "lost") {
game = createGame(game.images);
game.status = "running";
gameRef.current = game;
syncUi(game);
tone(520, 0.08);
return;
}
if (game.status === "ready") {
game.status = "running";
game.lastDrop = performance.now();
syncUi(game);
tone(520, 0.08);
}
return;
}
if (action === "pause") {
if (game.status === "running") game.status = "paused";
else if (game.status === "paused") {
game.status = "running";
game.lastDrop = performance.now();
}
syncUi(game);
return;
}
if (game.status !== "running" || !game.current) return;
if (action === "left" || action === "right") {
if (movePiece(game, action === "left" ? -1 : 1, 0)) tone(250, 0.025);
return;
}
if (action === "rotate") {
if (tryRotate(game)) tone(340, 0.04);
return;
}
if (action === "down") {
if (!movePiece(game, 0, 1)) {
const before = game.completedLayers;
lockPiece(game);
tone(game.status === "won" ? 880 : game.completedLayers > before ? 720 : 420, 0.09);
syncUi(game);
}
game.lastDrop = performance.now();
return;
}
if (action === "drop") {
const landingY = ghostY(game);
game.current.y = landingY;
const before = game.completedLayers;
lockPiece(game);
tone(game.status === "won" ? 880 : game.completedLayers > before ? 720 : 420, 0.1);
syncUi(game);
return;
}
if (action === "hold" && !game.holdUsed) {
const currentEntry = {
shapeId: game.current.shapeId,
logoIndex: game.current.logoIndex,
};
if (game.held) {
const heldEntry = game.held;
game.held = currentEntry;
game.current = makePiece(game, heldEntry);
if (!canPlace(game, game.current.cells, game.current.x, game.current.y)) {
game.status = "lost";
game.current = null;
}
} else {
game.held = currentEntry;
game.current = null;
spawnNext(game);
}
game.holdUsed = true;
tone(300, 0.06);
syncUi(game);
}
},
[syncUi, tone],
);
useEffect(() => {
let cancelled = false;
Promise.all(LOGOS.map(([, , src]) => loadImage(src)))
.then((images) => {
if (cancelled) return;
const game = createGame(images);
gameRef.current = game;
syncUi(game);
})
.catch(() => {
if (!cancelled) setStatus("lost");
});
return () => {
cancelled = true;
};
}, [syncUi]);
useEffect(() => {
const keyDown = (event: KeyboardEvent) => {
const actionByKey: Record<string, Action | undefined> = {
ArrowLeft: "left",
ArrowRight: "right",
ArrowDown: "down",
ArrowUp: "rotate",
" ": status === "ready" ? "start" : "drop",
c: "hold",
C: "hold",
p: "pause",
P: "pause",
};
const action = actionByKey[event.key];
if (!action) return;
event.preventDefault();
dispatch(action);
};
window.addEventListener("keydown", keyDown);
return () => window.removeEventListener("keydown", keyDown);
}, [dispatch, status]);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext("2d");
if (!context) return;
let frame = 0;
const draw = (game: Game) => {
context.clearRect(0, 0, BOARD_WIDTH, BOARD_HEIGHT);
context.fillStyle = "#ffffff";
context.fillRect(0, 0, BOARD_WIDTH, BOARD_HEIGHT);
context.fillStyle = "rgba(0, 158, 209, 0.028)";
context.fillRect(
0,
TARGET_ROW * CELL,
BOARD_WIDTH,
TARGET_LAYERS * CELL,
);
const groups = new Map<
number,
{ cells: Point[]; logoIndex: number }
>();
game.board.forEach((row, y) => {
row.forEach((cell, x) => {
if (!cell) return;
const group = groups.get(cell.groupId) ?? {
cells: [],
logoIndex: cell.logoIndex,
};
group.cells.push({ x, y });
groups.set(cell.groupId, group);
});
});
groups.forEach((group) => {
drawLogoGroup(
context,
group.cells,
game.images[group.logoIndex],
);
});
for (let row = TARGET_ROW; row < ROWS; row += 1) {
if (!game.board[row].every(Boolean)) continue;
context.fillStyle = "rgba(0, 158, 209, 0.11)";
context.fillRect(0, row * CELL + 2, BOARD_WIDTH, CELL - 4);
}
if (game.current) {
const landingY = ghostY(game);
if (landingY !== game.current.y) {
const ghostCells = absoluteCells(game.current, landingY);
context.save();
context.fillStyle = "rgba(17, 17, 17, 0.055)";
for (const cell of ghostCells) {
context.fillRect(
cell.x * CELL + 4,
cell.y * CELL + 4,
CELL - 8,
CELL - 8,
);
}
context.restore();
}
drawLogoGroup(
context,
absoluteCells(game.current),
game.images[game.current.logoIndex],
);
}
const lineY = TARGET_ROW * CELL;
context.save();
context.strokeStyle = "#009ed1";
context.lineWidth = 4;
context.beginPath();
context.moveTo(0, lineY);
context.lineTo(BOARD_WIDTH, lineY);
context.stroke();
context.fillStyle = "#009ed1";
context.font = "700 11px ui-monospace, monospace";
context.letterSpacing = "1.5px";
context.fillText("ALLIANCE", 10, lineY - 10);
context.restore();
};
const loop = (time: number) => {
const game = gameRef.current;
if (game) {
if (game.status === "running" && game.current) {
const interval = Math.max(250, 720 - game.pieces * 8);
if (time - game.lastDrop >= interval) {
if (!movePiece(game, 0, 1)) {
const before = game.completedLayers;
lockPiece(game);
tone(
game.status === "won"
? 880
: game.completedLayers > before
? 720
: 420,
0.09,
);
syncUi(game);
}
game.lastDrop = time;
}
}
draw(game);
} else {
context.fillStyle = "#ffffff";
context.fillRect(0, 0, BOARD_WIDTH, BOARD_HEIGHT);
}
frame = requestAnimationFrame(loop);
};
frame = requestAnimationFrame(loop);
return () => cancelAnimationFrame(frame);
}, [syncUi, tone]);
const overlay =
status === "paused"
? {
kicker: "Alliance suspended",
title: "Paused",
copy: "The structure is holding.",
action: "Resume",
}
: status === "won"
? {
kicker: "Foundation complete",
title: "Alliance!",
copy: `${pieces} logo pieces formed seven permanent layers.`,
action: "Build again",
}
: status === "lost"
? {
kicker: "Structure blocked",
title: "Try again",
copy: `${layers} of ${TARGET_LAYERS} alliance layers completed.`,
action: "Restart",
}
: status === "loading"
? {
kicker: "Preparing the alliance",
title: "Loading logos",
copy: "Assembling all 51 participants.",
action: "Please wait",
}
: null;
return (
<section className="alliance-game" aria-label="Alliance logo Tetris game">
<header className="alliance-header">
<div className="alliance-title">
<span aria-hidden="true" />
Alliance
</div>
<div className="alliance-hud" aria-live="polite">
<div>
<span>Layers</span>
<strong>
{layers}/{TARGET_LAYERS}
</strong>
</div>
<div>
<span>Pieces</span>
<strong>{String(pieces).padStart(2, "0")}</strong>
</div>
</div>
<div className="alliance-actions">
<button
type="button"
onClick={() => dispatch("pause")}
disabled={status !== "running" && status !== "paused"}
>
{status === "paused" ? "Resume" : "Pause"}
</button>
<button type="button" onClick={() => dispatch("restart")}>
Restart
</button>
</div>
</header>
<div className="alliance-layout">
<div className="board-shell">
<canvas
ref={canvasRef}
width={BOARD_WIDTH}
height={BOARD_HEIGHT}
aria-label="Ten-column Tetris board with an Alliance target line"
/>
{status === "ready" && (
<div className="alliance-overlay">
<button
className="primary-action start-action"
type="button"
onClick={() => dispatch("start")}
>
Start
</button>
</div>
)}
{overlay && (
<div className="alliance-overlay">
<div className="status-card">
<p>{overlay.kicker}</p>
<h2>{overlay.title}</h2>
<span>{overlay.copy}</span>
<button
className="primary-action"
type="button"
disabled={status === "loading"}
onClick={() =>
dispatch(status === "paused" ? "pause" : "start")
}
>
{overlay.action}
</button>
</div>
</div>
)}
</div>
</div>
<div className="touch-controls" aria-label="Touch controls">
<button type="button" onClick={() => dispatch("hold")}>
Hold
</button>
<button type="button" onClick={() => dispatch("left")}>
</button>
<button type="button" onClick={() => dispatch("rotate")}>
</button>
<button type="button" onClick={() => dispatch("right")}>
</button>
<button type="button" onClick={() => dispatch("down")}>
</button>
<button type="button" onClick={() => dispatch("drop")}>
Drop
</button>
</div>
<button
className="sound-toggle"
type="button"
onClick={() => {
const nextMuted = !muted;
setMuted(nextMuted);
soundRef.current.muted = nextMuted;
}}
aria-label={muted ? "Turn sound on" : "Turn sound off"}
>
{muted ? "Sound off" : "Sound on"}
</button>
</section>
);
}