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> |