Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Yu-Gi-Oh! Dungeon Dice Monsters</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@400;700&display=swap'); | |
body { | |
font-family: 'Roboto Condensed', sans-serif; | |
background-color: #1a1a2e; | |
color: #fff; | |
overflow-x: hidden; | |
} | |
.dice { | |
perspective: 1000px; | |
transition: transform 0.5s; | |
} | |
.dice:hover { | |
transform: scale(1.05); | |
} | |
.dice-face { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
backface-visibility: hidden; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
border-radius: 10px; | |
box-shadow: 0 0 10px rgba(0,0,0,0.3); | |
} | |
.dice-3d { | |
width: 60px; | |
height: 60px; | |
position: relative; | |
transform-style: preserve-3d; | |
transition: transform 1s; | |
} | |
.game-board { | |
background-image: url('https://i.imgur.com/XJQZ9Q9.jpg'); | |
background-size: cover; | |
position: relative; | |
background-position: center; | |
} | |
.monster-card { | |
transition: all 0.3s; | |
transform-style: preserve-3d; | |
} | |
.monster-card:hover { | |
transform: translateY(-5px) rotateY(5deg); | |
box-shadow: 0 10px 20px rgba(0,0,0,0.3); | |
} | |
.monster-stats { | |
background: rgba(0,0,0,0.7); | |
border-radius: 5px; | |
padding: 2px 5px; | |
} | |
@keyframes diceRoll { | |
0% { transform: rotateX(0) rotateY(0); } | |
100% { transform: rotateX(360deg) rotateY(360deg); } | |
} | |
.rolling { | |
animation: diceRoll 1s ease-out; | |
} | |
.cell { | |
position: relative; | |
border: 1px dashed rgba(255,255,255,0.2); | |
} | |
.cell::after { | |
content: ''; | |
display: block; | |
padding-bottom: 100%; | |
} | |
.cell-highlight { | |
box-shadow: inset 0 0 10px 5px rgba(255, 215, 0, 0.5); | |
} | |
.cell-occupied { | |
background-color: rgba(255,0,0,0.2); | |
} | |
</style> | |
</head> | |
<body class="min-h-screen flex flex-col"> | |
<!-- Header --> | |
<header class="bg-gradient-to-r from-blue-900 to-purple-900 py-4 px-6 shadow-lg"> | |
<div class="container mx-auto flex justify-between items-center"> | |
<div class="flex items-center space-x-2"> | |
<i class="fas fa-dice-d20 text-3xl text-yellow-400"></i> | |
<h1 class="text-2xl md:text-3xl font-bold text-white">Dungeon Dice Monsters</h1> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<div class="bg-black bg-opacity-50 px-4 py-2 rounded-lg"> | |
<span class="text-yellow-400 font-bold">Turn: </span> | |
<span id="turn-counter" class="text-white">1</span> | |
</div> | |
<button id="end-turn-btn" class="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg font-bold transition"> | |
End Turn | |
</button> | |
</div> | |
</div> | |
</header> | |
<!-- Main Game Area --> | |
<main class="flex-1 container mx-auto px-4 py-6 flex flex-col lg:flex-row gap-6"> | |
<!-- Player Area --> | |
<div class="w-full lg:w-1/4 bg-gray-800 bg-opacity-70 rounded-xl p-4 shadow-lg"> | |
<h2 class="text-xl font-bold text-yellow-400 mb-4 flex items-center"> | |
<i class="fas fa-user mr-2"></i> Player 1 | |
</h2> | |
<!-- Life Points --> | |
<div class="bg-black bg-opacity-50 rounded-lg p-3 mb-4"> | |
<div class="flex justify-between items-center"> | |
<span class="font-bold">Life Points:</span> | |
<span id="player-life" class="text-2xl font-bold text-green-400">4000</span> | |
</div> | |
<div class="w-full bg-gray-700 h-4 rounded-full mt-2"> | |
<div id="life-bar" class="bg-green-500 h-4 rounded-full" style="width: 100%"></div> | |
</div> | |
</div> | |
<!-- Dice Counter --> | |
<div class="bg-black bg-opacity-50 rounded-lg p-3 mb-4"> | |
<div class="flex justify-between items-center"> | |
<span class="font-bold">Dice Remaining:</span> | |
<span id="dice-count" class="text-2xl font-bold text-blue-400">5</span> | |
</div> | |
</div> | |
<!-- Monster Cards --> | |
<h3 class="font-bold text-lg mb-2 flex items-center"> | |
<i class="fas fa-dragon mr-2"></i> Your Monsters | |
</h3> | |
<div id="player-monsters" class="grid grid-cols-2 gap-3 mb-4"> | |
<!-- Monster cards will be added here dynamically --> | |
</div> | |
<!-- Dice Roll Area --> | |
<div class="mt-auto"> | |
<h3 class="font-bold text-lg mb-3 flex items-center"> | |
<i class="fas fa-dice mr-2"></i> Roll Dice | |
</h3> | |
<div class="flex justify-center mb-3"> | |
<div id="dice-result" class="dice-3d relative w-16 h-16 mx-auto"></div> | |
</div> | |
<button id="roll-dice-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-lg font-bold text-lg transition flex items-center justify-center"> | |
<i class="fas fa-dice mr-2"></i> Roll Dice | |
</button> | |
</div> | |
</div> | |
<!-- Game Board --> | |
<div class="flex-1 bg-gray-900 bg-opacity-80 rounded-xl p-4 shadow-lg"> | |
<div class="game-board rounded-lg overflow-hidden border-2 border-yellow-600"> | |
<div id="game-grid" class="grid grid-cols-7 gap-0"> | |
<!-- 7x7 grid will be generated here --> | |
</div> | |
</div> | |
<!-- Game Log --> | |
<div class="mt-4 bg-black bg-opacity-50 rounded-lg p-3 h-32 overflow-y-auto"> | |
<h3 class="font-bold text-lg mb-2 flex items-center"> | |
<i class="fas fa-scroll mr-2"></i> Battle Log | |
</h3> | |
<div id="game-log" class="text-sm"> | |
<p class="text-blue-300">Game started! Player 1's turn.</p> | |
</div> | |
</div> | |
</div> | |
<!-- Opponent Area --> | |
<div class="w-full lg:w-1/4 bg-gray-800 bg-opacity-70 rounded-xl p-4 shadow-lg"> | |
<h2 class="text-xl font-bold text-red-400 mb-4 flex items-center"> | |
<i class="fas fa-robot mr-2"></i> Kaiba Corp AI | |
</h2> | |
<!-- Life Points --> | |
<div class="bg-black bg-opacity-50 rounded-lg p-3 mb-4"> | |
<div class="flex justify-between items-center"> | |
<span class="font-bold">Life Points:</span> | |
<span id="opponent-life" class="text-2xl font-bold text-green-400">4000</span> | |
</div> | |
<div class="w-full bg-gray-700 h-4 rounded-full mt-2"> | |
<div id="opponent-life-bar" class="bg-green-500 h-4 rounded-full" style="width: 100%"></div> | |
</div> | |
</div> | |
<!-- Dice Counter --> | |
<div class="bg-black bg-opacity-50 rounded-lg p-3 mb-4"> | |
<div class="flex justify-between items-center"> | |
<span class="font-bold">Dice Remaining:</span> | |
<span id="opponent-dice-count" class="text-2xl font-bold text-blue-400">5</span> | |
</div> | |
</div> | |
<!-- Monster Cards --> | |
<h3 class="font-bold text-lg mb-2 flex items-center"> | |
<i class="fas fa-dragon mr-2"></i> Opponent Monsters | |
</h3> | |
<div id="opponent-monsters" class="grid grid-cols-2 gap-3"> | |
<!-- Opponent monster cards will be added here dynamically --> | |
</div> | |
</div> | |
</main> | |
<!-- Modal for summoning --> | |
<div id="summon-modal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden"> | |
<div class="bg-gray-800 rounded-xl p-6 w-full max-w-md"> | |
<h2 class="text-2xl font-bold text-yellow-400 mb-4">Summon Monster</h2> | |
<p id="summon-message" class="mb-4">You rolled a <span class="font-bold">3</span>. Choose a monster to summon:</p> | |
<div id="summon-options" class="grid grid-cols-2 gap-3 mb-4"> | |
<!-- Summon options will be added here dynamically --> | |
</div> | |
<div class="flex justify-end space-x-3"> | |
<button id="cancel-summon" class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg"> | |
Cancel | |
</button> | |
<button id="confirm-summon" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg"> | |
Summon | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Modal for game over --> | |
<div id="game-over-modal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden"> | |
<div class="bg-gray-800 rounded-xl p-8 w-full max-w-md text-center"> | |
<h2 id="game-over-title" class="text-3xl font-bold mb-4">Victory!</h2> | |
<p id="game-over-message" class="text-xl mb-6">You defeated Kaiba Corp AI!</p> | |
<div class="flex justify-center"> | |
<button id="play-again-btn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg text-lg font-bold"> | |
Play Again | |
</button> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Game state | |
const gameState = { | |
currentPlayer: 1, | |
turn: 1, | |
playerLife: 4000, | |
opponentLife: 4000, | |
playerDice: 5, | |
opponentDice: 5, | |
selectedMonster: null, | |
selectedCell: null, | |
diceResult: 0, | |
gameBoard: Array(7).fill().map(() => Array(7).fill(null)), | |
highlightedCells: [] | |
}; | |
// Monster data with actual images | |
const monsters = [ | |
{ id: 1, name: "Dark Magician", attack: 2500, defense: 2100, level: 7, diceReq: 5, image: "https://i.imgur.com/9vQHwjK.png" }, | |
{ id: 2, name: "Blue-Eyes White Dragon", attack: 3000, defense: 2500, level: 8, diceReq: 6, image: "https://i.imgur.com/RkZqVYF.png" }, | |
{ id: 3, name: "Summoned Skull", attack: 2500, defense: 1200, level: 6, diceReq: 4, image: "https://i.imgur.com/5zQmLyP.png" }, | |
{ id: 4, name: "Celtic Guardian", attack: 1400, defense: 1200, level: 4, diceReq: 3, image: "https://i.imgur.com/JYw0T3j.png" }, | |
{ id: 5, name: "Kuriboh", attack: 300, defense: 200, level: 1, diceReq: 1, image: "https://i.imgur.com/3JQZ9Q9.png" }, | |
{ id: 6, name: "Mystical Elf", attack: 800, defense: 2000, level: 4, diceReq: 3, image: "https://i.imgur.com/8QZQZQZ.png" }, | |
{ id: 7, name: "Red-Eyes B. Dragon", attack: 2400, defense: 2000, level: 7, diceReq: 5, image: "https://i.imgur.com/7vQHwjK.png" }, | |
{ id: 8, name: "Gaia The Fierce Knight", attack: 2300, defense: 2100, level: 7, diceReq: 5, image: "https://i.imgur.com/6zQmLyP.png" }, | |
{ id: 9, name: "Time Wizard", attack: 500, defense: 400, level: 2, diceReq: 2, image: "https://i.imgur.com/4JQZ9Q9.png" }, | |
{ id: 10, name: "Black Luster Soldier", attack: 3000, defense: 2500, level: 8, diceReq: 6, image: "https://i.imgur.com/5vQHwjK.png" } | |
]; | |
// Initialize game | |
document.addEventListener('DOMContentLoaded', () => { | |
initializeGame(); | |
setupEventListeners(); | |
}); | |
// Initialize game elements | |
function initializeGame() { | |
createGameGrid(); | |
renderPlayerMonsters(); | |
renderOpponentMonsters(); | |
updateUI(); | |
} | |
// Create 7x7 game grid | |
function createGameGrid() { | |
const gameGrid = document.getElementById('game-grid'); | |
gameGrid.innerHTML = ''; | |
for (let row = 0; row < 7; row++) { | |
for (let col = 0; col < 7; col++) { | |
const cell = document.createElement('div'); | |
cell.className = 'cell relative'; | |
cell.dataset.row = row; | |
cell.dataset.col = col; | |
// Add cell content if there's a monster | |
if (gameState.gameBoard[row][col]) { | |
const monster = gameState.gameBoard[row][col]; | |
cell.innerHTML = ` | |
<div class="monster-card absolute inset-0 flex flex-col items-center justify-center p-1"> | |
<img src="${monster.image}" alt="${monster.name}" class="w-full h-full object-contain"> | |
<div class="monster-stats absolute bottom-0 left-0 right-0 flex justify-between px-1 text-xs"> | |
<span class="text-red-400">${monster.attack}</span> | |
<span class="text-blue-400">${monster.defense}</span> | |
</div> | |
<div class="absolute top-0 left-0 bg-black bg-opacity-70 px-1 text-xs"> | |
${monster.owner === 1 ? 'P1' : 'P2'} | |
</div> | |
</div> | |
`; | |
} | |
cell.addEventListener('click', () => handleCellClick(row, col)); | |
gameGrid.appendChild(cell); | |
} | |
} | |
} | |
// Render player's monster cards (random 5) | |
function renderPlayerMonsters() { | |
const container = document.getElementById('player-monsters'); | |
container.innerHTML = ''; | |
// Get 5 random unique monsters | |
const shuffled = [...monsters].sort(() => 0.5 - Math.random()); | |
const playerMonsters = shuffled.slice(0, 5); | |
playerMonsters.forEach(monster => { | |
const card = document.createElement('div'); | |
card.className = 'monster-card bg-gray-700 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg'; | |
card.dataset.monsterId = monster.id; | |
card.innerHTML = ` | |
<div class="p-2"> | |
<img src="${monster.image}" alt="${monster.name}" class="w-full h-24 object-contain"> | |
</div> | |
<div class="px-2 pb-2"> | |
<h4 class="font-bold text-sm truncate">${monster.name}</h4> | |
<div class="flex justify-between text-xs mt-1"> | |
<span class="text-red-400">ATK: ${monster.attack}</span> | |
<span class="text-blue-400">DEF: ${monster.defense}</span> | |
</div> | |
<div class="mt-1 text-xs text-yellow-400"> | |
<i class="fas fa-dice"></i> ${monster.diceReq} | |
</div> | |
</div> | |
`; | |
card.addEventListener('click', () => selectMonster(monster.id)); | |
container.appendChild(card); | |
}); | |
} | |
// Render opponent's monster cards (random 5 different from player) | |
function renderOpponentMonsters() { | |
const container = document.getElementById('opponent-monsters'); | |
container.innerHTML = ''; | |
// Get player's monster IDs | |
const playerMonsterIds = Array.from(document.querySelectorAll('#player-monsters .monster-card')) | |
.map(card => parseInt(card.dataset.monsterId)); | |
// Get 5 random monsters not in player's deck | |
const availableMonsters = monsters.filter(m => !playerMonsterIds.includes(m.id)); | |
const shuffled = [...availableMonsters].sort(() => 0.5 - Math.random()); | |
const opponentMonsters = shuffled.slice(0, 5); | |
opponentMonsters.forEach(monster => { | |
const card = document.createElement('div'); | |
card.className = 'monster-card bg-gray-700 rounded-lg overflow-hidden opacity-70'; | |
card.innerHTML = ` | |
<div class="p-2"> | |
<img src="${monster.image}" alt="${monster.name}" class="w-full h-24 object-contain"> | |
</div> | |
<div class="px-2 pb-2"> | |
<h4 class="font-bold text-sm truncate">${monster.name}</h4> | |
<div class="flex justify-between text-xs mt-1"> | |
<span class="text-red-400">ATK: ${monster.attack}</span> | |
<span class="text-blue-400">DEF: ${monster.defense}</span> | |
</div> | |
<div class="mt-1 text-xs text-yellow-400"> | |
<i class="fas fa-dice"></i> ${monster.diceReq} | |
</div> | |
</div> | |
`; | |
container.appendChild(card); | |
}); | |
} | |
// Update UI elements | |
function updateUI() { | |
document.getElementById('turn-counter').textContent = gameState.turn; | |
document.getElementById('player-life').textContent = gameState.playerLife; | |
document.getElementById('opponent-life').textContent = gameState.opponentLife; | |
document.getElementById('dice-count').textContent = gameState.playerDice; | |
document.getElementById('opponent-dice-count').textContent = gameState.opponentDice; | |
// Update life bars | |
const playerLifePercent = (gameState.playerLife / 4000) * 100; | |
const opponentLifePercent = (gameState.opponentLife / 4000) * 100; | |
document.getElementById('life-bar').style.width = `${playerLifePercent}%`; | |
document.getElementById('opponent-life-bar').style.width = `${opponentLifePercent}%`; | |
// Change life bar color based on percentage | |
if (playerLifePercent < 30) { | |
document.getElementById('life-bar').classList.remove('bg-green-500'); | |
document.getElementById('life-bar').classList.add('bg-red-500'); | |
} else { | |
document.getElementById('life-bar').classList.remove('bg-red-500'); | |
document.getElementById('life-bar').classList.add('bg-green-500'); | |
} | |
if (opponentLifePercent < 30) { | |
document.getElementById('opponent-life-bar').classList.remove('bg-green-500'); | |
document.getElementById('opponent-life-bar').classList.add('bg-red-500'); | |
} else { | |
document.getElementById('opponent-life-bar').classList.remove('bg-red-500'); | |
document.getElementById('opponent-life-bar').classList.add('bg-green-500'); | |
} | |
} | |
// Setup event listeners | |
function setupEventListeners() { | |
// Roll dice button | |
document.getElementById('roll-dice-btn').addEventListener('click', rollDice); | |
// End turn button | |
document.getElementById('end-turn-btn').addEventListener('click', endTurn); | |
// Summon modal buttons | |
document.getElementById('cancel-summon').addEventListener('click', () => { | |
document.getElementById('summon-modal').classList.add('hidden'); | |
}); | |
document.getElementById('confirm-summon').addEventListener('click', confirmSummon); | |
// Play again button | |
document.getElementById('play-again-btn').addEventListener('click', resetGame); | |
} | |
// Handle cell click | |
function handleCellClick(row, col) { | |
if (gameState.currentPlayer !== 1) return; | |
// If we have a selected monster and valid dice roll | |
if (gameState.selectedMonster && gameState.diceResult > 0) { | |
const monster = monsters.find(m => m.id === gameState.selectedMonster); | |
// Check if cell is empty | |
if (!gameState.gameBoard[row][col]) { | |
gameState.selectedCell = { row, col }; | |
showSummonModal(monster); | |
} else { | |
addToGameLog(`Cell is already occupied!`); | |
} | |
} | |
} | |
// Select monster | |
function selectMonster(monsterId) { | |
if (gameState.currentPlayer !== 1) return; | |
gameState.selectedMonster = monsterId; | |
// Highlight the selected monster card | |
document.querySelectorAll('#player-monsters .monster-card').forEach(card => { | |
if (parseInt(card.dataset.monsterId) === monsterId) { | |
card.classList.add('ring-2', 'ring-yellow-400'); | |
} else { | |
card.classList.remove('ring-2', 'ring-yellow-400'); | |
} | |
}); | |
addToGameLog(`Selected ${monsters.find(m => m.id === monsterId).name}`); | |
} | |
// Roll dice | |
function rollDice() { | |
if (gameState.currentPlayer !== 1) return; | |
if (gameState.diceResult > 0) { | |
addToGameLog(`You already rolled a ${gameState.diceResult} this turn!`); | |
return; | |
} | |
const diceElement = document.getElementById('dice-result'); | |
diceElement.classList.add('rolling'); | |
// Disable button during roll | |
document.getElementById('roll-dice-btn').disabled = true; | |
// Random number between 1-6 | |
setTimeout(() => { | |
const result = Math.floor(Math.random() * 6) + 1; | |
gameState.diceResult = result; | |
// Update dice visual | |
renderDiceFace(result); | |
diceElement.classList.remove('rolling'); | |
// Re-enable button | |
document.getElementById('roll-dice-btn').disabled = false; | |
addToGameLog(`You rolled a ${result}!`); | |
// Highlight summonable monsters | |
highlightSummonableMonsters(); | |
}, 1000); | |
} | |
// Render dice face | |
function renderDiceFace(value) { | |
const diceElement = document.getElementById('dice-result'); | |
diceElement.innerHTML = ''; | |
// Create dice faces (simplified for this example) | |
for (let i = 1; i <= 6; i++) { | |
const face = document.createElement('div'); | |
face.className = `dice-face absolute bg-white flex items-center justify-center text-2xl font-bold`; | |
// Position each face correctly in 3D space | |
switch(i) { | |
case 1: // Front | |
face.style.transform = 'translateZ(30px)'; | |
break; | |
case 2: // Back | |
face.style.transform = 'rotateY(180deg) translateZ(30px)'; | |
break; | |
case 3: // Top | |
face.style.transform = 'rotateX(90deg) translateZ(30px)'; | |
break; | |
case 4: // Bottom | |
face.style.transform = 'rotateX(-90deg) translateZ(30px)'; | |
break; | |
case 5: // Left | |
face.style.transform = 'rotateY(-90deg) translateZ(30px)'; | |
break; | |
case 6: // Right | |
face.style.transform = 'rotateY(90deg) translateZ(30px)'; | |
break; | |
} | |
// Add dots based on face value | |
if (i === value) { | |
face.innerHTML = '<div class="w-4 h-4 rounded-full bg-black"></div>'; | |
} else { | |
face.innerHTML = '<div class="w-4 h-4 rounded-full bg-transparent"></div>'; | |
} | |
diceElement.appendChild(face); | |
} | |
// Rotate to show the correct face | |
diceElement.style.transform = `rotateX(${Math.random() * 360}deg) rotateY(${Math.random() * 360}deg)`; | |
} | |
// Highlight summonable monsters based on dice roll | |
function highlightSummonableMonsters() { | |
document.querySelectorAll('#player-monsters .monster-card').forEach(card => { | |
const monsterId = parseInt(card.dataset.monsterId); | |
const monster = monsters.find(m => m.id === monsterId); | |
if (monster.diceReq <= gameState.diceResult) { | |
card.classList.add('ring-2', 'ring-green-400'); | |
} else { | |
card.classList.remove('ring-2', 'ring-green-400'); | |
} | |
}); | |
} | |
// Show summon modal | |
function showSummonModal(monster) { | |
if (monster.diceReq > gameState.diceResult) { | |
addToGameLog(`You need at least ${monster.diceReq} to summon ${monster.name}!`); | |
return; | |
} | |
document.getElementById('summon-message').innerHTML = | |
`You rolled a <span class="font-bold">${gameState.diceResult}</span>. Summon ${monster.name}?`; | |
document.getElementById('summon-modal').classList.remove('hidden'); | |
} | |
// Confirm summon | |
function confirmSummon() { | |
const modal = document.getElementById('summon-modal'); | |
modal.classList.add('hidden'); | |
if (!gameState.selectedMonster || !gameState.selectedCell) return; | |
const monster = monsters.find(m => m.id === gameState.selectedMonster); | |
const { row, col } = gameState.selectedCell; | |
// Place monster on board | |
gameState.gameBoard[row][col] = { | |
...monster, | |
owner: gameState.currentPlayer, | |
position: { row, col } | |
}; | |
// Deduct dice cost | |
if (gameState.currentPlayer === 1) { | |
gameState.playerDice -= monster.diceReq; | |
} else { | |
gameState.opponentDice -= monster.diceReq; | |
} | |
// Reset selection | |
gameState.selectedMonster = null; | |
gameState.selectedCell = null; | |
gameState.diceResult = 0; | |
// Clear highlights | |
clearHighlights(); | |
// Update UI | |
createGameGrid(); | |
updateUI(); | |
addToGameLog(`Summoned ${monster.name} at (${row+1}, ${col+1})!`); | |
// Check for attacks | |
checkForAttacks(row, col); | |
} | |
// Check for attacks after summon | |
function checkForAttacks(row, col) { | |
const directions = [ | |
{ dr: -1, dc: 0 }, // up | |
{ dr: 1, dc: 0 }, // down | |
{ dr: 0, dc: -1 }, // left | |
{ dr: 0, dc: 1 } // right | |
]; | |
const attacker = gameState.gameBoard[row][col]; | |
let attacked = false; | |
directions.forEach(dir => { | |
const newRow = row + dir.dr; | |
const newCol = col + dir.dc; | |
// Check bounds | |
if (newRow >= 0 && newRow < 7 && newCol >= 0 && newCol < 7) { | |
const defender = gameState.gameBoard[newRow][newCol]; | |
// If there's an opponent monster | |
if (defender && defender.owner !== attacker.owner) { | |
attacked = true; | |
resolveBattle(attacker, defender, newRow, newCol); | |
} | |
} | |
}); | |
if (!attacked && gameState.currentPlayer === 2) { | |
// AI turn continues if no attacks happened | |
setTimeout(aiTurn, 1000); | |
} | |
} | |
// Resolve battle between two monsters | |
function resolveBattle(attacker, defender, defRow, defCol) { | |
let logMessage = `${attacker.name} (ATK ${attacker.attack}) attacks ${defender.name} (DEF ${defender.defense}) - `; | |
if (attacker.attack > defender.defense) { | |
// Defender is destroyed | |
gameState.gameBoard[defRow][defCol] = null; | |
// Damage opponent | |
if (defender.owner === 1) { | |
gameState.playerLife -= attacker.attack - defender.defense; | |
} else { | |
gameState.opponentLife -= attacker.attack - defender.defense; | |
} | |
logMessage += `${defender.name} is destroyed!`; | |
} else if (attacker.attack < defender.defense) { | |
// Attacker is destroyed | |
const attRow = attacker.position.row; | |
const attCol = attacker.position.col; | |
gameState.gameBoard[attRow][attCol] = null; | |
// Damage player | |
if (attacker.owner === 1) { | |
gameState.playerLife -= defender.defense - attacker.attack; | |
} else { | |
gameState.opponentLife -= defender.defense - attacker.attack; | |
} | |
logMessage += `${attacker.name} is destroyed!`; | |
} else { | |
// Both are destroyed | |
const attRow = attacker.position.row; | |
const attCol = attacker.position.col; | |
gameState.gameBoard[attRow][attCol] = null; | |
gameState.gameBoard[defRow][defCol] = null; | |
logMessage += `Both monsters are destroyed!`; | |
} | |
addToGameLog(logMessage); | |
// Update game board | |
createGameGrid(); | |
updateUI(); | |
// Check for game over | |
checkGameOver(); | |
// If it's AI's turn and game isn't over, continue | |
if (gameState.currentPlayer === 2 && !isGameOver()) { | |
setTimeout(aiTurn, 1000); | |
} | |
} | |
// Clear highlighted cells | |
function clearHighlights() { | |
gameState.highlightedCells.forEach(({ row, col }) => { | |
const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`); | |
if (cell) { | |
cell.classList.remove('cell-highlight'); | |
} | |
}); | |
gameState.highlightedCells = []; | |
} | |
// End current player's turn | |
function endTurn() { | |
if (gameState.currentPlayer === 1) { | |
gameState.currentPlayer = 2; | |
addToGameLog(`Player 1 ends turn. Kaiba Corp AI's turn!`); | |
// AI turn | |
setTimeout(aiTurn, 1000); | |
} else { | |
gameState.currentPlayer = 1; | |
gameState.turn++; | |
addToGameLog(`Kaiba Corp AI ends turn. Player 1's turn!`); | |
} | |
// Reset dice result for new turn | |
gameState.diceResult = 0; | |
document.getElementById('dice-result').innerHTML = ''; | |
// Update UI | |
updateUI(); | |
} | |
// AI turn logic | |
function aiTurn() { | |
if (gameState.currentPlayer !== 2) return; | |
// AI rolls dice | |
const aiRoll = Math.floor(Math.random() * 6) + 1; | |
addToGameLog(`Kaiba Corp AI rolled a ${aiRoll}!`); | |
// Find summonable monsters | |
const summonableMonsters = monsters.filter(m => m.diceReq <= aiRoll); | |
if (summonableMonsters.length > 0 && gameState.opponentDice > 0) { | |
// Choose random monster to summon | |
const monsterToSummon = summonableMonsters[Math.floor(Math.random() * summonableMonsters.length)]; | |
// Find empty cell | |
const emptyCells = []; | |
for (let row = 0; row < 7; row++) { | |
for (let col = 0; col < 7; col++) { | |
if (!gameState.gameBoard[row][col]) { | |
emptyCells.push({ row, col }); | |
} | |
} | |
} | |
if (emptyCells.length > 0) { | |
// Choose random empty cell | |
const { row, col } = emptyCells[Math.floor(Math.random() * emptyCells.length)]; | |
// Summon monster | |
gameState.gameBoard[row][col] = { | |
...monsterToSummon, | |
owner: 2, | |
position: { row, col } | |
}; | |
// Deduct dice cost | |
gameState.opponentDice -= monsterToSummon.diceReq; | |
addToGameLog(`Kaiba Corp AI summoned ${monsterToSummon.name} at (${row+1}, ${col+1})!`); | |
// Update game board | |
createGameGrid(); | |
updateUI(); | |
// Check for attacks | |
checkForAttacks(row, col); | |
} else { | |
addToGameLog(`Kaiba Corp AI has no empty cells to summon!`); | |
endTurn(); | |
} | |
} else { | |
addToGameLog(`Kaiba Corp AI has no summonable monsters or no dice left!`); | |
endTurn(); | |
} | |
} | |
// Check if game is over | |
function isGameOver() { | |
return gameState.playerLife <= 0 || gameState.opponentLife <= 0; | |
} | |
// Check for game over condition | |
function checkGameOver() { | |
if (!isGameOver()) return; | |
const modal = document.getElementById('game-over-modal'); | |
const title = document.getElementById('game-over-title'); | |
const message = document.getElementById('game-over-message'); | |
if (gameState.playerLife <= 0) { | |
title.textContent = "Defeat!"; | |
message.textContent = "Kaiba Corp AI defeated you!"; | |
title.classList.remove('text-green-500'); | |
title.classList.add('text-red-500'); | |
} else { | |
title.textContent = "Victory!"; | |
message.textContent = "You defeated Kaiba Corp AI!"; | |
title.classList.remove('text-red-500'); | |
title.classList.add('text-green-500'); | |
} | |
modal.classList.remove('hidden'); | |
} | |
// Reset game | |
function resetGame() { | |
// Reset game state | |
gameState.currentPlayer = 1; | |
gameState.turn = 1; | |
gameState.playerLife = 4000; | |
gameState.opponentLife = 4000; | |
gameState.playerDice = 5; | |
gameState.opponentDice = 5; | |
gameState.selectedMonster = null; | |
gameState.selectedCell = null; | |
gameState.diceResult = 0; | |
gameState.gameBoard = Array(7).fill().map(() => Array(7).fill(null)); | |
gameState.highlightedCells = []; | |
// Clear dice display | |
document.getElementById('dice-result').innerHTML = ''; | |
// Clear game log | |
document.getElementById('game-log').innerHTML = | |
'<p class="text-blue-300">Game started! Player 1\'s turn.</p>'; | |
// Hide modals | |
document.getElementById('summon-modal').classList.add('hidden'); | |
document.getElementById('game-over-modal').classList.add('hidden'); | |
// Reinitialize game | |
initializeGame(); | |
} | |
// Add message to game log | |
function addToGameLog(message) { | |
const log = document.getElementById('game-log'); | |
const entry = document.createElement('p'); | |
entry.className = gameState.currentPlayer === 1 ? 'text-blue-300' : 'text-red-300'; | |
entry.textContent = message; | |
log.appendChild(entry); | |
log.scrollTop = log.scrollHeight; | |
} | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://deepsite.hf.co/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://deepsite.hf.co" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://deepsite.hf.co?remix=Juno360219/bhj" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |