|
<!DOCTYPE html> |
|
<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; |
|
} |
|
|
|
#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; |
|
border: 1px solid #aaa; |
|
background-color: #f9f9f9; |
|
padding: 15px 10px; |
|
margin: 5px; |
|
min-width: 80px; |
|
min-height: 50px; |
|
border-radius: 4px; |
|
box-shadow: 1px 1px 3px rgba(0,0,0,0.1); |
|
text-align: center; |
|
vertical-align: top; |
|
font-size: 0.9em; |
|
cursor: default; |
|
} |
|
|
|
.inboxCard { |
|
background-color: #e0f7fa; |
|
border-color: #00acc1; |
|
font-weight: bold; |
|
} |
|
|
|
.replyCard { |
|
background-color: #fff9c4; |
|
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; |
|
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> |
|
|
|
console.log("π Booting up the Card Game Engine... Hold onto your hats! Or don't. Free will is a thing. π€"); |
|
|
|
const numberOfPlayers = 3; |
|
const cardsPerHand = 7; |
|
|
|
let inboxDeck = []; |
|
let replyDeck = []; |
|
let players = []; |
|
let discardInbox = []; |
|
let discardReply = []; |
|
let currentJudgeIndex = 0; |
|
let currentInboxCard = null; |
|
|
|
|
|
|
|
|
|
function createDecks() { |
|
console.log("π Generating sacred texts... I mean, card decks."); |
|
|
|
|
|
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? π€·ββοΈ", |
|
]; |
|
|
|
|
|
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(); |
|
} |
|
|
|
|
|
|
|
|
|
function shuffleDeck(deck) { |
|
console.log(`π² Shuffling the deck... Don't peek! π`); |
|
let currentIndex = deck.length, randomIndex; |
|
|
|
while (currentIndex !== 0) { |
|
|
|
randomIndex = Math.floor(Math.random() * currentIndex); |
|
currentIndex--; |
|
|
|
[deck[currentIndex], deck[randomIndex]] = [deck[randomIndex], deck[currentIndex]]; |
|
} |
|
console.log("πͺοΈ Deck successfully randomized!"); |
|
return deck; |
|
} |
|
|
|
|
|
function createCardElement(cardText, cardType) { |
|
const cardDiv = document.createElement('div'); |
|
cardDiv.classList.add('card'); |
|
cardDiv.classList.add(cardType === 'inbox' ? 'inboxCard' : 'replyCard'); |
|
cardDiv.innerText = cardText; |
|
|
|
return cardDiv; |
|
} |
|
|
|
function updateStatus(message) { |
|
const statusEl = document.getElementById('status'); |
|
statusEl.innerText = `π’ ${message} ${Date().toLocaleTimeString()}`; |
|
console.log(`Status Update: ${message}`); |
|
} |
|
|
|
function updateDeckCounts() { |
|
document.getElementById('inboxCount').innerText = inboxDeck.length; |
|
document.getElementById('replyCount').innerText = replyDeck.length; |
|
} |
|
|
|
|
|
|
|
|
|
function dealInitialHands() { |
|
console.log(`π€ Dealing cards... Everyone gets ${cardsPerHand}. No cheating!`); |
|
players = []; |
|
for (let i = 0; i < numberOfPlayers; i++) { |
|
const playerHand = replyDeck.splice(0, cardsPerHand); |
|
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?`); |
|
|
|
updateStatus(`Error: Not enough REPLY cards to deal! Game paused. π¬`); |
|
return false; |
|
} |
|
players.push({ |
|
id: i, |
|
name: `Player ${i + 1}`, |
|
hand: playerHand |
|
}); |
|
console.log(`Player ${i + 1} received their hand.`); |
|
} |
|
updateDeckCounts(); |
|
return true; |
|
} |
|
|
|
function selectStartingJudge() { |
|
|
|
|
|
|
|
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?"); |
|
|
|
updateStatus("INBOX deck empty! Need to reshuffle or end game. π€"); |
|
currentInboxCard = "The INBOX is empty... what does it all mean?!"; |
|
return false; |
|
} |
|
|
|
currentInboxCard = inboxDeck.shift(); |
|
discardInbox.push(currentInboxCard); |
|
console.log(`βοΈ Judge drew: "${currentInboxCard}"`); |
|
updateDeckCounts(); |
|
updateStatus(`Judge drew the INBOX card. Players, prepare your replies!`); |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
function renderGame() { |
|
console.log("π¨ Painting the game state onto the screen... like digital Bob Ross. Happy little cards! π³"); |
|
|
|
|
|
const judgeArea = document.getElementById('currentInboxCard'); |
|
judgeArea.innerHTML = ''; |
|
if (currentInboxCard) { |
|
judgeArea.appendChild(createCardElement(currentInboxCard, 'inbox')); |
|
} else { |
|
judgeArea.innerText = "Waiting for Judge to draw..."; |
|
} |
|
|
|
|
|
const handsDisplay = document.getElementById('handsDisplay'); |
|
handsDisplay.innerHTML = ''; |
|
players.forEach(player => { |
|
const playerDiv = document.createElement('div'); |
|
playerDiv.classList.add('player-hand'); |
|
|
|
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); |
|
}); |
|
|
|
|
|
updateDeckCounts(); |
|
|
|
console.log("πΌοΈ Render complete. The stage is set!"); |
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
selectStartingJudge(); |
|
|
|
updateStatus("First round: Judge draws an INBOX card..."); |
|
if (!judgeDrawsInbox()) return; |
|
|
|
|
|
renderGame(); |
|
|
|
updateStatus(`Round 1 started. Judge ${players[currentJudgeIndex].name} reads: "${currentInboxCard}". Players select a REPLY card! (Interaction needed next!)`); |
|
} |
|
|
|
|
|
window.onload = startGame; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script> |
|
|
|
</body> |
|
</html> |