document.addEventListener('DOMContentLoaded', () => { // Game constants const GRID_SIZE = 41; const CELL_COUNT = GRID_SIZE * GRID_SIZE; const ENEMY_COUNT = 5; const FOOD_COUNT = 5; const MAX_HEALTH = 5; const ENEMY_SCORE = 100; const FOOD_SCORE = 50; // Game state let playerPosition = (2 * GRID_SIZE) + 2; // 2 rows down, 2 columns in let health = MAX_HEALTH; let score = 0; let gameOver = false; let maze = []; let enemies = []; let foodPositions = []; let waterPosition = Math.floor((GRID_SIZE * GRID_SIZE) / 2); // Center let goalPosition = (GRID_SIZE * (GRID_SIZE - 2)) + (GRID_SIZE - 2); // 2 from bottom, 2 from right // DOM elements const mazeGrid = document.querySelector('.maze-grid'); const scoreValue = document.getElementById('scoreValue'); const healthBars = document.querySelectorAll('.health-bars div'); const newMazeBtn = document.getElementById('newMazeBtn'); const resetBtn = document.getElementById('resetBtn'); // Initialize game function initGame() { generateMaze(); placePlayer(); placeEnemies(); placeFood(); placeWater(); updateUI(); addEventListeners(); } // Generate maze with walls and paths ensuring a path exists function generateMaze() { mazeGrid.innerHTML = ''; maze = Array(CELL_COUNT).fill().map((_, i) => { const cell = document.createElement('div'); cell.className = 'cell'; cell.dataset.index = i; const row = Math.floor(i / GRID_SIZE); const col = i % GRID_SIZE; // Solid outer perimeter walls let isWall = (row === 0 || row === GRID_SIZE-1 || col === 0 || col === GRID_SIZE-1); // Create a guaranteed path from start to goal if (!isWall) { // Create a diagonal path from start to goal const isOnPath = (row === Math.floor(col * (GRID_SIZE-4)/(GRID_SIZE-4)) + 2) || (col === Math.floor(row * (GRID_SIZE-4)/(GRID_SIZE-4)) + 2); // Add some randomness to the path if (!isOnPath) { isWall = Math.random() < 0.3; } } // Ensure start, water and goal positions are accessible if (i === playerPosition || i === waterPosition || i === goalPosition) { isWall = false; } if (isWall) { cell.classList.add('wall'); } else { cell.classList.add('path'); } mazeGrid.appendChild(cell); return { element: cell, isWall: isWall }; }); } // Place player at start position function placePlayer() { playerPosition = (2 * GRID_SIZE) + 2; const cell = maze[playerPosition].element; cell.classList.add('player'); cell.innerHTML = '🌱'; } // Place enemies randomly function placeEnemies() { enemies = []; while (enemies.length < ENEMY_COUNT) { const pos = Math.floor(Math.random() * CELL_COUNT); if (!maze[pos].isWall && pos !== playerPosition && pos !== waterPosition && pos !== goalPosition && !enemies.includes(pos)) { enemies.push(pos); const cell = maze[pos].element; cell.classList.add('enemy'); cell.innerHTML = '🌸'; } } } // Place food randomly function placeFood() { foodPositions = []; while (foodPositions.length < FOOD_COUNT) { const pos = Math.floor(Math.random() * CELL_COUNT); if (!maze[pos].isWall && pos !== playerPosition && pos !== waterPosition && !enemies.includes(pos) && !foodPositions.includes(pos)) { foodPositions.push(pos); const cell = maze[pos].element; cell.classList.add('food'); cell.innerHTML = '🍕'; } } } // Place water at center with random outcome function placeWater() { const cell = maze[waterPosition].element; cell.classList.add('water'); cell.innerHTML = '💧'; updateWaterColor(); // Mark goal position const goalCell = maze[goalPosition].element; goalCell.classList.add('goal'); goalCell.innerHTML = '🏁'; } // Update water color based on random outcome function updateWaterColor() { const waterCell = maze[waterPosition].element; const willWin = Math.random() > 0.5; waterCell.style.backgroundColor = willWin ? '#bbf7d0' : '#fecaca'; waterCell.style.border = willWin ? '1px solid #4ade80' : '1px solid #ef4444'; } // Update UI elements function updateUI() { scoreValue.textContent = score; // Update health display healthBars.forEach((bar, i) => { if (i < health) { bar.classList.add('bg-green-500'); bar.classList.remove('bg-gray-300'); } else { bar.classList.add('bg-gray-300'); bar.classList.remove('bg-green-500'); } }); } // Handle player movement function movePlayer(direction) { if (gameOver) return; let newPosition = playerPosition; const row = Math.floor(playerPosition / GRID_SIZE); const col = playerPosition % GRID_SIZE; switch (direction) { case 'up': if (row > 0) newPosition = playerPosition - GRID_SIZE; break; case 'down': if (row < GRID_SIZE - 1) newPosition = playerPosition + GRID_SIZE; break; case 'left': if (col > 0) newPosition = playerPosition - 1; break; case 'right': if (col < GRID_SIZE - 1) newPosition = playerPosition + 1; break; } // Check if new position is valid (not a wall) if (newPosition !== playerPosition && !maze[newPosition].isWall) { // Clear current player position const currentCell = maze[playerPosition].element; currentCell.classList.remove('player'); currentCell.innerHTML = ''; // Check what's at new position const newCell = maze[newPosition].element; // Check for enemy collision if (enemies.includes(newPosition)) { health--; score += ENEMY_SCORE; enemies = enemies.filter(pos => pos !== newPosition); newCell.classList.remove('enemy'); if (health <= 0) { endGame(false); return; } } // Check for food collection if (foodPositions.includes(newPosition)) { health = Math.min(health + 1, MAX_HEALTH); score += FOOD_SCORE; foodPositions = foodPositions.filter(pos => pos !== newPosition); newCell.classList.remove('food'); } // Check for water pot if (newPosition === waterPosition) { const isWin = Math.random() > 0.5; endGame(isWin); return; } // Check for win condition (2 from bottom, 2 from right) if (newPosition === goalPosition) { endGame(true); return; } // Move player playerPosition = newPosition; newCell.classList.add('player'); newCell.innerHTML = '🌱'; // Move enemies moveEnemies(); // Update water color with each move updateWaterColor(); // Update UI updateUI(); } } // Move enemies towards player function moveEnemies() { enemies.forEach((enemyPos, index) => { const enemyCell = maze[enemyPos].element; enemyCell.classList.remove('enemy'); enemyCell.innerHTML = ''; const playerRow = Math.floor(playerPosition / GRID_SIZE); const playerCol = playerPosition % GRID_SIZE; const enemyRow = Math.floor(enemyPos / GRID_SIZE); const enemyCol = enemyPos % GRID_SIZE; // Simple AI: move towards player let newRow = enemyRow; let newCol = enemyCol; if (enemyRow < playerRow) newRow++; else if (enemyRow > playerRow) newRow--; if (enemyCol < playerCol) newCol++; else if (enemyCol > playerCol) newCol--; // Randomize direction sometimes if (Math.random() < 0.3) { if (Math.random() < 0.5) { newRow = enemyRow + (Math.random() < 0.5 ? 1 : -1); } else { newCol = enemyCol + (Math.random() < 0.5 ? 1 : -1); } } // Ensure new position is within bounds newRow = Math.max(0, Math.min(GRID_SIZE - 1, newRow)); newCol = Math.max(0, Math.min(GRID_SIZE - 1, newCol)); const newEnemyPos = newRow * GRID_SIZE + newCol; // Only move if not a wall and not another enemy if (!maze[newEnemyPos].isWall && !enemies.includes(newEnemyPos) && newEnemyPos !== playerPosition) { enemies[index] = newEnemyPos; } // Update enemy display const newEnemyCell = maze[enemies[index]].element; newEnemyCell.classList.add('enemy'); newEnemyCell.innerHTML = '🌸'; }); } // End game with win/lose function endGame(isWin) { gameOver = true; const gameOverDiv = document.createElement('div'); gameOverDiv.className = 'game-over'; gameOverDiv.innerHTML = `

${isWin ? 'You Won! 🎉' : 'Game Over! 💀'}

Final Score: ${score}

`; mazeGrid.appendChild(gameOverDiv); } // Add event listeners function addEventListeners() { // Keyboard controls document.addEventListener('keydown', (e) => { switch (e.key) { case 'ArrowUp': movePlayer('up'); break; case 'ArrowDown': movePlayer('down'); break; case 'ArrowLeft': movePlayer('left'); break; case 'ArrowRight': movePlayer('right'); break; } }); // New maze button newMazeBtn.addEventListener('click', () => { generateMaze(); placePlayer(); placeEnemies(); placeFood(); placeWater(); gameOver = false; score = 0; health = MAX_HEALTH; updateUI(); }); // Reset button resetBtn.addEventListener('click', () => { placePlayer(); placeEnemies(); placeFood(); gameOver = false; score = 0; health = MAX_HEALTH; updateUI(); }); } // Start the game initGame(); });