Files
leckeier/app/Game.tsx
Pascal Linxweiler c1cff189cb Merz leck Eier: MTG troll site
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 15:49:55 +02:00

126 lines
3.9 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useState } from "react";
import { CardView } from "./CardView";
import { COMMANDER, DECK, type Card } from "./cards";
const shuffle = <T,>(a: T[]) => [...a].sort(() => Math.random() - 0.5);
const LOG_LINES = [
"Die Umfragewerte sinken. Merz macht eine Pressekonferenz über Bierdeckel.",
"Merz tappt Sauerland. Niemand ist überrascht.",
"Das Volk wirkt „Leck Eier“. Es ist sehr effektiv.",
"Merz versucht zu mulliganen, aber die Koalition sagt nein.",
"BlackRock ruft an. Merz geht natürlich ran.",
"Merz zieht eine Karte. Es ist wieder ein Wahlversprechen. Er wirft es ab.",
];
export function Game() {
const [library, setLibrary] = useState<Card[]>([]);
const [hand, setHand] = useState<Card[]>([]);
const [grave, setGrave] = useState<Card[]>([]);
const [polls, setPolls] = useState(25);
const [eggs, setEggs] = useState(0);
const [log, setLog] = useState<string[]>(["Merz, Leck Eier betritt das Schlachtfeld. Aus einem Privatjet."]);
useEffect(() => {
setLibrary(shuffle(DECK));
try {
setEggs(Number(localStorage.getItem("eggs") ?? 0));
} catch {}
}, []);
const say = (line: string) => setLog((l) => [line, ...l].slice(0, 6));
function draw() {
if (library.length === 0) {
say("Deine Bibliothek ist leer. Wie das Rentenkonzept.");
return;
}
const [top, ...rest] = library;
setLibrary(rest);
setHand((h) => [...h, top]);
say(`Du ziehst „${top.name}“.`);
}
function cast(i: number) {
const card = hand[i];
setHand((h) => h.filter((_, j) => j !== i));
setGrave((g) => [card, ...g]);
const dmg = card.name === "Leck Eier" ? 10 : Math.ceil(Math.random() * 4);
setPolls((p) => Math.max(0, p - dmg));
say(`Du wirkst „${card.name}“. Merz verliert ${dmg}% Zustimmung.`);
}
function mulligan() {
setLibrary(shuffle(DECK));
setHand([]);
setGrave([]);
setPolls(25);
say("Mulligan! Neue Hand, gleicher Kanzler.");
}
function lick() {
const n = eggs + 1;
setEggs(n);
try {
localStorage.setItem("eggs", String(n));
} catch {}
say(LOG_LINES[Math.floor(Math.random() * LOG_LINES.length)]);
}
return (
<>
<section className="board">
<div className="commander">
<div className="label">Commander</div>
<CardView card={COMMANDER} big />
<div className="life">
<span>Umfragewerte</span>
<strong className={polls === 0 ? "dead" : ""}>{polls}%</strong>
<div className="meter">
<div style={{ width: `${(polls / 25) * 100}%` }} />
</div>
{polls === 0 && <p className="win">🏆 Du hast gewonnen. Neuwahlen!</p>}
</div>
</div>
<div className="side">
<div className="buttons">
<button onClick={draw}>🃏 Karte ziehen ({library.length})</button>
<button onClick={mulligan} className="ghost">
🔄 Mulligan
</button>
<button onClick={lick} className="egg">
🥚 Leck Eier ({eggs})
</button>
</div>
<ol className="log">
{log.map((l, i) => (
<li key={i + l}>{l}</li>
))}
</ol>
<div className="grave">
⚰️ Friedhof: {grave.length ? grave.map((c) => c.name).join(", ") : "leer (wie die Staatskasse)"}
</div>
</div>
</section>
<section>
<h2>Deine Hand {hand.length > 0 && <small>— klick eine Karte zum Wirken</small>}</h2>
{hand.length === 0 ? (
<p className="empty">Noch keine Karten. Zieh eine, bevor Merz es privatisiert.</p>
) : (
<div className="hand">
{hand.map((c, i) => (
<button key={i + c.name} className="card-btn" onClick={() => cast(i)}>
<CardView card={c} />
</button>
))}
</div>
)}
</section>
</>
);
}