Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Witty Card Game Prototype π€π</title> | |
<style> | |
body { | |
font-family: sans-serif; | |
background-color: #f0f0f0; | |
color: #333; | |
padding: 20px; | |
} | |
h1, h2 { | |
text-align: center; | |
color: #5a3a7e; /* A deep purple, because why not? */ | |
} | |
#gameArea { | |
max-width: 900px; | |
margin: 20px auto; | |
background-color: #fff; | |
padding: 20px; | |
border-radius: 8px; | |
box-shadow: 0 4px 8px rgba(0,0,0,0.1); | |
} | |
.deck-area, #judgeArea, #playerHands { | |
margin-bottom: 20px; | |
padding: 15px; | |
border: 1px dashed #ccc; | |
border-radius: 5px; | |
} | |
#judgeArea h3, #playerHands h3 { | |
margin-top: 0; | |
color: #333; | |
} | |
.card { | |
display: inline-block; /* Lay them out like real cards, kinda */ | |
border: 1px solid #aaa; | |
background-color: #f9f9f9; | |
padding: 15px 10px; /* A bit more padding for readability */ | |
margin: 5px; | |
min-width: 80px; | |
min-height: 50px; /* Let content define height mostly */ | |
border-radius: 4px; | |
box-shadow: 1px 1px 3px rgba(0,0,0,0.1); | |
text-align: center; | |
vertical-align: top; /* Align cards nicely if they wrap */ | |
font-size: 0.9em; | |
cursor: default; /* Looks like a thing you can't click... yet! */ | |
} | |
.inboxCard { | |
background-color: #e0f7fa; /* Light cyan - like a fresh email! π§ */ | |
border-color: #00acc1; | |
font-weight: bold; | |
} | |
.replyCard { | |
background-color: #fff9c4; /* Light yellow - like a sticky note reply! π */ | |
border-color: #ffeb3b; | |
} | |
.player-hand { | |
margin-bottom: 15px; | |
padding-bottom: 10px; | |
border-bottom: 1px solid #eee; | |
} | |
.player-hand:last-child { | |
border-bottom: none; | |
} | |
#status { | |
margin-top: 20px; | |
padding: 10px; | |
background-color: #e8f5e9; /* Calming green for status updates */ | |
border: 1px solid #a5d6a7; | |
border-radius: 4px; | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Card Game Extravaganza! (Prototype Stage) π</h1> | |
<div id="gameArea"> | |
<h2>Game Board</h2> | |
<div class="deck-area"> | |
<h3>Decks (Conceptual)</h3> | |
<p>Imagine two piles here: one for INBOX π₯, one for REPLY π€. We draw from these in JS!</p> | |
<p>INBOX cards remaining: <span id="inboxCount">?</span></p> | |
<p>REPLY cards remaining: <span id="replyCount">?</span></p> | |
</div> | |
<div id="judgeArea"> | |
<h3>Judge's INBOX Card π€</h3> | |
<div id="currentInboxCard">Waiting for the round to start...</div> | |
</div> | |
<div id="playerHands"> | |
<h3>Player Hands π</h3> | |
<div id="handsDisplay">Players are gathering... cards are being shuffled... suspense!</div> | |
</div> | |
<div id="status"> | |
Game initializing... Prepare for witty banter! π | |
</div> | |
</div> | |
<script> | |
// === CONFIGURATION & INITIAL STATE === | |
console.log("π Booting up the Card Game Engine... Hold onto your hats! Or don't. Free will is a thing. π€"); | |
const numberOfPlayers = 3; // Let's start with 3 players. More players, more chaos! π | |
const cardsPerHand = 7; // As requested, 7 REPLY cards each. A sacred number? Probably not. β¨ | |
let inboxDeck = []; | |
let replyDeck = []; | |
let players = []; // Array to hold player objects { id: number, name: string, hand: array } | |
let discardInbox = []; // Where used INBOX cards go to ponder their existence. | |
let discardReply = []; // Where used REPLY cards go to await reincarnation (reshuffling?). | |
let currentJudgeIndex = 0; // We'll figure out the 'oldest' part later, for now player 0 starts. π΄π | |
let currentInboxCard = null; // The card currently demanding attention. | |
// === DECK CREATION === | |
// Let's fill our decks with profound nonsense and digital ephemera. π§ | |
function createDecks() { | |
console.log("π Generating sacred texts... I mean, card decks."); | |
// --- INBOX Deck: The prompts, the questions, the existential crises! --- | |
inboxDeck = [ | |
"What's the sound of one hand clapping... in a Zoom meeting? ππ»", | |
"My therapist told me to embrace my mistakes. So I hugged my code. π€", | |
"The real treasure was the _______ we made along the way. π΄ββ οΈ", | |
"Why did the AI cross the road? π€π£οΈ", | |
"What's secretly controlling the world? ππ½", | |
"Describe your last debugging session using only interpretive dance. ππΊπ", | |
"Complete the prophecy: 'And lo, the user shall _______'. π", | |
"What's the wifi password in the afterlife? πΆπ»", | |
"If cats could text, their first message would be _______. πΌπ±", | |
"The meaning of life is apparently _______. Who knew? π€·ββοΈ", | |
]; | |
// --- REPLY Deck: The answers, the non-sequiturs, the genius strokes! --- | |
replyDeck = [ | |
"A rogue semicolon. ;", | |
"Blaming the intern. π ", | |
"Aggressively Googling it. π", | |
"Turning it off and on again. π", | |
"Insufficient caffeine. β", | |
"A quantum fluctuation. β¨", | |
"Feature, not a bug. β’οΈ", | |
"Squirrels. Definitely squirrels. πΏοΈ", | |
"The 'any' key. Where is it?! π€", | |
"Asking for a friend... π", | |
"My other notification. π", | |
"A deeply profound nap. π΄", | |
"Imposter syndrome. π", | |
"Running 'sudo make me a sandwich'. π₯ͺ", | |
"Emptying the browser cache... and my soul. π¨", | |
"Just vibing. β¨πβ¨", | |
"Three ducks in a trench coat. π¦π¦π¦π§₯", | |
"The algorithm demands it. π€", | |
"Error 404: Witty response not found. π«", | |
"A moment of existential dread. π¨", | |
"Lasers! Pew pew! β¨", | |
"The overwhelming urge to automate everything. βοΈ", | |
"Another meeting that could have been an email. π§", | |
"Forgetting to save.πΎπ±", | |
"The sheer audacity. π", | |
]; | |
console.log(`π₯ INBOX deck created with ${inboxDeck.length} cards. Ready to perplex!`); | |
console.log(`π€ REPLY deck created with ${replyDeck.length} cards. Ready to amuse/confuse!`); | |
updateDeckCounts(); // Show initial counts | |
} | |
// === UTILITY FUNCTIONS === | |
// Fisher-Yates (Knuth) Shuffle Algorithm - The gold standard for shuffling digital things! π° | |
function shuffleDeck(deck) { | |
console.log(`π² Shuffling the deck... Don't peek! π`); | |
let currentIndex = deck.length, randomIndex; | |
// While there remain elements to shuffle... | |
while (currentIndex !== 0) { | |
// Pick a remaining element... | |
randomIndex = Math.floor(Math.random() * currentIndex); | |
currentIndex--; | |
// And swap it with the current element. | |
[deck[currentIndex], deck[randomIndex]] = [deck[randomIndex], deck[currentIndex]]; // Fancy swap! | |
} | |
console.log("πͺοΈ Deck successfully randomized!"); | |
return deck; | |
} | |
// Creates the visual representation of a card | |
function createCardElement(cardText, cardType) { | |
const cardDiv = document.createElement('div'); | |
cardDiv.classList.add('card'); | |
cardDiv.classList.add(cardType === 'inbox' ? 'inboxCard' : 'replyCard'); | |
cardDiv.innerText = cardText; // Simple text for now | |
// Maybe add icons or other generative stuff later? Sky's the limit! π | |
return cardDiv; | |
} | |
function updateStatus(message) { | |
const statusEl = document.getElementById('status'); | |
statusEl.innerText = `π’ ${message} ${Date().toLocaleTimeString()}`; // Add a timestamp for extra officiousness | |
console.log(`Status Update: ${message}`); | |
} | |
function updateDeckCounts() { | |
document.getElementById('inboxCount').innerText = inboxDeck.length; | |
document.getElementById('replyCount').innerText = replyDeck.length; | |
} | |
// === GAME SETUP FUNCTIONS === | |
function dealInitialHands() { | |
console.log(`π€ Dealing cards... Everyone gets ${cardsPerHand}. No cheating!`); | |
players = []; // Reset players if dealing again | |
for (let i = 0; i < numberOfPlayers; i++) { | |
const playerHand = replyDeck.splice(0, cardsPerHand); // Take cards from the *top* of the shuffled deck | |
if (playerHand.length < cardsPerHand) { | |
console.error(`π± Oh no! Not enough REPLY cards left to deal full hands! Need ${cardsPerHand}, got ${playerHand.length}. Maybe reshuffle discard? Or just panic?`); | |
// Handle deck running out - reshuffle discard pile? End game? Add more cards? | |
updateStatus(`Error: Not enough REPLY cards to deal! Game paused. π¬`); | |
return false; // Stop dealing | |
} | |
players.push({ | |
id: i, | |
name: `Player ${i + 1}`, // TODO: Get actual player names later? π€ Maybe ask them politely? | |
hand: playerHand | |
}); | |
console.log(`Player ${i + 1} received their hand.`); | |
} | |
updateDeckCounts(); | |
return true; // Dealing successful | |
} | |
function selectStartingJudge() { | |
// Rule: Oldest player starts. | |
// Reality: We don't know ages yet. Let's just pick Player 1 (index 0) for now. π€·ββοΈ | |
// TODO: Implement actual age check or a random selection later. | |
currentJudgeIndex = 0; | |
console.log(`π Player ${currentJudgeIndex + 1} is declared the first Judge! By decree of... well, me, the code.`); | |
updateStatus(`Player ${currentJudgeIndex + 1} starts as the Judge.`); | |
} | |
function judgeDrawsInbox() { | |
console.log("π§ββοΈ Judge is drawing an INBOX card..."); | |
if (inboxDeck.length === 0) { | |
console.warn("π¬ INBOX deck is empty! Time to reshuffle the discard pile or ponder the void?"); | |
// TODO: Implement reshuffling logic for inboxDeck from discardInbox | |
updateStatus("INBOX deck empty! Need to reshuffle or end game. π€"); | |
currentInboxCard = "The INBOX is empty... what does it all mean?!"; // Placeholder | |
return false; // Can't draw | |
} | |
currentInboxCard = inboxDeck.shift(); // Take the top card (array.shift()) | |
discardInbox.push(currentInboxCard); // Add it to the discard pile | |
console.log(`βοΈ Judge drew: "${currentInboxCard}"`); | |
updateDeckCounts(); | |
updateStatus(`Judge drew the INBOX card. Players, prepare your replies!`); | |
return true; // Draw successful | |
} | |
// === RENDERING FUNCTION === | |
// This function updates the HTML to show the current game state | |
function renderGame() { | |
console.log("π¨ Painting the game state onto the screen... like digital Bob Ross. Happy little cards! π³"); | |
// Render Judge's Card | |
const judgeArea = document.getElementById('currentInboxCard'); | |
judgeArea.innerHTML = ''; // Clear previous card | |
if (currentInboxCard) { | |
judgeArea.appendChild(createCardElement(currentInboxCard, 'inbox')); | |
} else { | |
judgeArea.innerText = "Waiting for Judge to draw..."; | |
} | |
// Render Player Hands | |
const handsDisplay = document.getElementById('handsDisplay'); | |
handsDisplay.innerHTML = ''; // Clear previous hands | |
players.forEach(player => { | |
const playerDiv = document.createElement('div'); | |
playerDiv.classList.add('player-hand'); | |
// Add player name, maybe bold the judge? | |
const namePrefix = player.id === currentJudgeIndex ? 'π Judge ' : ''; | |
playerDiv.innerHTML = `<h4>${namePrefix}${player.name}'s Hand:</h4>`; | |
player.hand.forEach(cardText => { | |
playerDiv.appendChild(createCardElement(cardText, 'reply')); | |
}); | |
handsDisplay.appendChild(playerDiv); | |
}); | |
// Update deck counts display too | |
updateDeckCounts(); | |
console.log("πΌοΈ Render complete. The stage is set!"); | |
} | |
// === INITIAL GAME START === | |
function startGame() { | |
console.log("π LET THE GAMES BEGIN! π May the wittiest human (or bot?) win!"); | |
updateStatus("Game starting! Shuffling decks..."); | |
createDecks(); | |
shuffleDeck(inboxDeck); | |
shuffleDeck(replyDeck); | |
updateStatus("Dealing initial hands..."); | |
if (!dealInitialHands()) return; // Stop if dealing failed | |
selectStartingJudge(); | |
updateStatus("First round: Judge draws an INBOX card..."); | |
if (!judgeDrawsInbox()) return; // Stop if drawing failed | |
// Initial render of the game state | |
renderGame(); | |
updateStatus(`Round 1 started. Judge ${players[currentJudgeIndex].name} reads: "${currentInboxCard}". Players select a REPLY card! (Interaction needed next!)`); | |
} | |
// --- Kick off the game when the page loads --- | |
window.onload = startGame; | |
// === FUTURE LOGIC PLACEHOLDERS === | |
// console.log("β³ Next steps: Implement player REPLY submission, judging, scoring, card drawing, next round logic... It's a marathon, not a sprint! Unless you're coding really fast. ππ¨"); | |
// function playerSubmitsReply(playerId, cardIndex) { ... } | |
// function judgeSelectsWinner(submittedCard) { ... } | |
// function nextRound() { ... } | |
// function refillPlayerHand(playerId) { ... } | |
</script> | |
</body> | |
</html> |