Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>๐ฒ D20 Dungeon Crawler ๐ฐ</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
min-height: 100vh; | |
margin: 0; | |
background-color: #2c3e50; | |
color: #ecf0f1; | |
} | |
#game-container { | |
background-color: #34495e; | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: 0 0 20px rgba(0,0,0,0.3); | |
max-width: 800px; | |
width: 100%; | |
} | |
button { | |
margin: 5px; | |
padding: 10px 15px; | |
background-color: #3498db; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: background-color 0.3s; | |
} | |
button:hover { | |
background-color: #2980b9; | |
} | |
select { | |
margin: 5px; | |
padding: 5px 10px; | |
} | |
#dungeon-image { | |
width: 100%; | |
height: 200px; | |
background-color: #2c3e50; | |
margin-bottom: 20px; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
font-size: 24px; | |
text-align: center; | |
} | |
#choices { | |
display: grid; | |
grid-template-columns: 1fr 1fr; | |
gap: 10px; | |
} | |
#combat-log { | |
max-height: 200px; | |
overflow-y: auto; | |
background-color: #2c3e50; | |
padding: 10px; | |
border-radius: 5px; | |
margin-top: 20px; | |
} | |
#monster-trophies { | |
display: flex; | |
flex-wrap: wrap; | |
margin-top: 10px; | |
} | |
.monster-trophy { | |
font-size: 24px; | |
margin-right: 5px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="game-container"> | |
<h1>๐ฒ D20 Dungeon Crawler ๐ฐ</h1> | |
<div id="character-creation"> | |
<h2>๐ค Character Creation</h2> | |
<select id="race"> | |
<option value="human">๐จ Human</option> | |
<option value="elf">๐งโโ๏ธ Elf</option> | |
<option value="dwarf">๐ง Dwarf</option> | |
<option value="halfling">๐ง Halfling</option> | |
</select> | |
<select id="class"> | |
<option value="warrior">โ๏ธ Warrior</option> | |
<option value="mage">๐งโโ๏ธ Mage</option> | |
<option value="rogue">๐ก๏ธ Rogue</option> | |
<option value="cleric">โจ Cleric</option> | |
</select> | |
<button onclick="createCharacter()">๐ญ Create Character</button> | |
</div> | |
<div id="game-area" style="display: none;"> | |
<div id="dungeon-image"></div> | |
<div id="encounter-description"></div> | |
<div id="choices"></div> | |
<div id="player-stats"></div> | |
<div id="combat-log"></div> | |
<div id="monster-trophies"></div> | |
</div> | |
</div> | |
<svg id="d20" width="100" height="100" viewBox="0 0 100 100" style="display: none;"> | |
<polygon points="50,5 95,75 5,75" fill="#f3f3f3" stroke="#000" stroke-width="2"/> | |
<text x="50" y="55" font-size="24" text-anchor="middle" id="roll-result"></text> | |
</svg> | |
<script> | |
let player, currentEncounter, score = 0, monsterTrophies = []; | |
const settingsData = ` | |
๐๏ธ๐ฎ,Ancient Temple,A crumbling temple with flickering torches and moss-covered statues | |
๐ณ๐,Enchanted Forest,A mystical forest filled with glowing mushrooms and whispering trees | |
๐๏ธโ๏ธ,Frozen Peaks,Treacherous icy mountains with howling winds and hidden crevasses | |
๐๏ธ๐ซ,Desert Ruins,Sun-baked ruins half-buried in shifting sands | |
๐๐ฅ,Volcanic Cavern,A scorching cave system with rivers of lava and sulfurous air | |
๐๐,Sunken City,The remains of an ancient city submerged beneath crystal-clear waters | |
๐ฏ๏ธ๐,Arcane Library,Towering bookshelves filled with magical tomes and floating candles | |
โฐ๏ธ๐,Haunted Crypt,A chilling burial chamber echoing with unseen whispers | |
๐ฟ๐ฆ,Fairy Glade,A serene clearing shimmering with magical butterflies and flower petals | |
๐ฐ๏ธโ๏ธ,Clockwork Maze,An intricate labyrinth of gears, pistons, and ticking mechanisms | |
๐๐บ,Shadowy Woods,Dark and foreboding forest where eyes seem to watch from every shadow | |
๐ฎ๐ญ,Illusory Palace,A grand castle where nothing is as it seems, constantly shifting | |
๐ณ๏ธ๐ฆ,Abyssal Chasm,A deep, dark pit with strange echoes and unseen terrors | |
๐๐ฆ,Crystal Cavern,A dazzling cave system filled with luminous, multi-colored crystals | |
๐ช๐ญ,Carnival of Souls,An eerie, abandoned fairground with a sinister undercurrent | |
๐ฟ๐ด,Primal Jungle,A dense, primordial jungle teeming with ancient creatures and ruins | |
๐๐,Astral Plane,A surreal realm of floating islands and swirling cosmic energies | |
๐ดโโ ๏ธ๐ฆ,Ghost Ship,A decrepit vessel sailing through mists, crewed by spectral pirates | |
๐๐ถ,Harmonic Sanctuary,A tranquil temple where magical music fills the air | |
๐ญ๐พ,Alien Hive,A bizarre, organic structure pulsing with otherworldly life | |
`; | |
const monstersData = ` | |
๐น๐ก๏ธ,Goblin,A small, green-skinned creature with a wicked grin and rusty dagger | |
๐๐น,Skeleton Archer,A reanimated skeleton wielding a creaky bow with surprising accuracy | |
๐บ๐,Dire Wolf,A massive wolf with glowing eyes and razor-sharp fangs | |
๐ท๏ธ๐ธ๏ธ,Giant Spider,A hairy arachnid the size of a horse, with venom dripping from its fangs | |
๐งโโ๏ธ๐,Zombie,A shambling corpse with rotting flesh, driven by an insatiable hunger | |
๐งโโ๏ธ๐ฎ,Evil Witch,A cackling hag with gnarled fingers and a bubbling cauldron of curses | |
๐๐ฅ,Young Dragon,A scaled wyrm with smoke curling from its nostrils, hungry for treasure | |
๐ฆ๐งโโ๏ธ,Vampire,A pale, aristocratic figure with razor-sharp fangs and hypnotic eyes | |
๐ฟ๐,Treant,An ancient tree come to life, with bark-covered limbs and mossy beard | |
๐ฆ๐ฑ,Lizardfolk Warrior,A scaly humanoid with sharp claws and primitive weapons | |
๐ป๐,Poltergeist,An invisible spirit that delights in chaos and flying objects | |
๐๐,Kraken Spawn,A mass of writhing tentacles emerging from dark waters | |
๐ฆ ๐ฆ,Griffin,A majestic creature with the head and wings of an eagle and body of a lion | |
๐ฟ๐จ,Stone Golem,A hulking figure carved from living rock, nearly impervious to harm | |
๐ฆ๐,Corrupted Unicorn,Once pure, now twisted by dark magic with a deadly horn | |
๐งโโ๏ธ๐ถ,Siren,A hauntingly beautiful creature with an alluring, deadly song | |
๐ฒโ๏ธ,Cloud Giant,A towering humanoid wreathed in mists, with storm-powered magic | |
๐ฆ๐ฅ,Infernal Scorpion,A massive scorpion with a carapace of smoldering coals | |
๐ง ๐๏ธ,Mind Flayer,A tentacle-faced horror with powerful psionic abilities | |
๐๐บ,Shadow Wolf,A beast made of living darkness with glowing red eyes | |
`; | |
const settings = parseCSV(settingsData); | |
const monsters = parseCSV(monstersData); | |
function parseCSV(data) { | |
return data.trim().split('\n').map(line => { | |
const [emoji, name, description] = line.split(','); | |
return { emoji, name, description }; | |
}); | |
} | |
function createCharacter() { | |
const race = document.getElementById('race').value; | |
const characterClass = document.getElementById('class').value; | |
player = { | |
race, | |
class: characterClass, | |
maxHp: 50, | |
hp: 50, | |
attack: 10, | |
defense: 5, | |
magic: 8 | |
}; | |
document.getElementById('character-creation').style.display = 'none'; | |
document.getElementById('game-area').style.display = 'block'; | |
updateStats(); | |
nextEncounter(); | |
} | |
function updateStats() { | |
document.getElementById('player-stats').innerHTML = ` | |
๐ค Player: โค๏ธ HP ${player.hp}/${player.maxHp}, โ๏ธ ATK ${player.attack}, ๐ก๏ธ DEF ${player.defense}, ๐ฎ MAG ${player.magic} | |
<br>๐ Score: ${score} | |
`; | |
} | |
function nextEncounter() { | |
const setting = settings[Math.floor(Math.random() * settings.length)]; | |
const monster = monsters[Math.floor(Math.random() * monsters.length)]; | |
currentEncounter = { | |
setting, | |
monster, | |
monsterHp: 30, | |
description: `${setting.emoji} You find yourself in ${setting.name}. ${setting.description} | |
<br><br>${monster.emoji} Suddenly, a ${monster.name} appears! ${monster.description}`, | |
choices: generateChoices() | |
}; | |
document.getElementById('dungeon-image').innerHTML = setting.emoji; | |
document.getElementById('encounter-description').innerHTML = currentEncounter.description; | |
displayChoices(); | |
} | |
function generateChoices() { | |
return [ | |
{ text: "โ๏ธ Attack with your weapon", successRate: 0.7, statUsed: "attack" }, | |
{ text: "๐ฎ Cast a spell", successRate: 0.6, statUsed: "magic" }, | |
{ text: "๐ต๏ธ Try to sneak past", successRate: 0.5, statUsed: "defense" }, | |
{ text: "๐ฃ๏ธ Attempt to communicate", successRate: 0.3, statUsed: "magic" } | |
]; | |
} | |
function displayChoices() { | |
const choicesDiv = document.getElementById('choices'); | |
choicesDiv.innerHTML = ""; | |
currentEncounter.choices.forEach((choice, index) => { | |
const button = document.createElement('button'); | |
button.textContent = `${String.fromCharCode(65 + index)}. ${choice.text}`; | |
button.onclick = () => makeChoice(index); | |
choicesDiv.appendChild(button); | |
}); | |
} | |
async function makeChoice(index) { | |
const choice = currentEncounter.choices[index]; | |
const roll = await rollD20(); | |
const success = roll / 20 <= choice.successRate; | |
const statBonus = player[choice.statUsed] / 10; | |
const totalSuccessRate = Math.min(choice.successRate + statBonus, 1); | |
if (success) { | |
const damage = Math.floor(roll * totalSuccessRate); | |
currentEncounter.monsterHp -= damage; | |
score += damage; | |
log(`โ Success! ${choice.text} (๐ฒ Roll: ${roll}, ๐ Success Rate: ${(totalSuccessRate * 100).toFixed(1)}%, ๐ฅ Damage: ${damage}, ๐ Score: +${damage})`); | |
} else { | |
player.hp -= 5; | |
log(`โ Failure... ${choice.text} (๐ฒ Roll: ${roll}, ๐ Success Rate: ${(totalSuccessRate * 100).toFixed(1)}%, โค๏ธ HP: -5)`); | |
} | |
updateStats(); | |
if (player.hp <= 0) { | |
log("๐ Game over! You have been defeated."); | |
return; | |
} | |
if (currentEncounter.monsterHp <= 0) { | |
log(`๐ Victory! You defeated the ${currentEncounter.monster.name}!`); | |
monsterTrophies.push(currentEncounter.monster.emoji); | |
updateMonsterTrophies(); | |
player.hp = player.maxHp; // Heal to full after battle | |
updateStats(); | |
nextEncounter(); | |
} else { | |
log(`The ${currentEncounter.monster.name} has ${currentEncounter.monsterHp} HP remaining.`); | |
} | |
} | |
function updateMonsterTrophies() { | |
const trophiesDiv = document.getElementById('monster-trophies'); | |
trophiesDiv.innerHTML = monsterTrophies.map(emoji => `<span class="monster-trophy">${emoji}</span>`).join(''); | |
} | |
function rollD20() { | |
return new Promise(resolve => { | |
const d20 = document.getElementById('d20'); | |
d20.style.display = 'block'; | |
const result = Math.floor(Math.random() * 20) + 1; | |
document.getElementById('roll-result').textContent = result; | |
d20.animate([ | |
{ transform: 'rotate(0deg)' }, | |
{ transform: 'rotate(360deg)' } | |
], { | |
duration: 1000, | |
iterations: 1 | |
}).onfinish = () => { | |
d20.style.display = 'none'; | |
resolve(result); | |
}; | |
}); | |
} | |
function log(message) { | |
const combatLog = document.getElementById('combat-log'); | |
combatLog.innerHTML += `<p>${message}</p>`; | |
combatLog.scrollTop = combatLog.scrollHeight; | |
} | |
</script> | |
</body> | |
</html> |