Merz leck Eier: MTG troll site

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pascal Linxweiler
2026-09-23 15:49:55 +02:00
commit c1cff189cb
15 changed files with 1690 additions and 0 deletions

125
app/Game.tsx Normal file
View File

@@ -0,0 +1,125 @@
"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>
</>
);
}