export let grid = createGrid(10, 10); // Example grid size export let player = { position: { x: 0, y: 0 }, inventory: [], health: 10, power: 10, level: 0, steps: 0, par: 0, didScan: false, flashing: false }; let targetPosition = { x: 0, y: 0 }; export let levelPar; function createGrid(rows, cols) { let grid = []; for (let i = 0; i < rows; i++) { let row = []; for (let j = 0; j < cols; j++) { row.push(null); } grid.push(row); } return grid; } function generatePar(level) { let par; if (level < 6) { par = 7; } else { par = Math.floor(Math.random() * 7) + 1; } document.getElementById('par').textContent = `Par: ${par}`; return par; } function generateCollectables(grid, numCollectables) { const collectableTypes = ['potion', 'shield', 'battery']; const collectableColors = { 'potion': 'peachpuff', 'shield': 'cornflowerBlue', 'battery': 'gold' }; for (let i = 0; i < numCollectables; i++) { let x, y; do { x = Math.floor(Math.random() * grid.length); y = Math.floor(Math.random() * grid[0].length); } while (x === 0 && y === 0); // don't put items at (0,0) const type = collectableTypes[Math.floor(Math.random() * collectableTypes.length)]; grid[x][y] = { type, color: collectableColors[type] }; } } function generateDamagingSpaces(grid, numSpaces) { for (let i = 0; i < numSpaces; i++) { let x, y; do { x = Math.floor(Math.random() * grid.length); y = Math.floor(Math.random() * grid[0].length); } while (x === 0 && y === 0); // don't put damaging stuff at (0,0) grid[x][y] = { type: 'damage', color: 'tomato' }; } } function generateTraps(grid, numTraps) { for (let i = 0; i < numTraps; i++) { let x, y; do { x = Math.floor(Math.random() * grid.length); y = Math.floor(Math.random() * grid[0].length); } while (x === 0 && y === 0); // don't be an asshole grid[x][y] = { type: 'trap', color: 'rgba(0,0,0,0)' }; } } function generateTargetBlock(grid) { let x, y; do { x = Math.floor(Math.random() * grid.length); y = Math.floor(Math.random() * grid[0].length); } while (x === 0 && y === 0); // don't make it too easy grid[x][y] = { type: 'target', color: 'lightgreen' }; // x marks the spot! targetPosition = { x, y }; } export function drawGrid(grid) { const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const cellSize = Math.min(canvas.width / grid.length, canvas.height / grid[0].length); ctx.clearRect(0, 0, canvas.width, canvas.height); grid.forEach((row, x) => { row.forEach((cell, y) => { ctx.strokeStyle = '#2d2d2d'; ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize); if (cell && cell.color) { ctx.fillStyle = cell.color; ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); ctx.fillStyle = '#2d2d2d'; ctx.font = `${cellSize / 2}px Arial`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; let char = ''; if (cell.type === 'potion') char = 'p'; if (cell.type === 'shield') char = 's'; if (cell.type === 'battery') char = 'b'; if (cell.type === 'damage') char = '!'; if (cell.type === 'target') char = '#'; if (cell.type === 'trap' && player.didScan) char = 't'; ctx.fillText(char, x * cellSize + cellSize / 2, y * cellSize + cellSize / 2); } }); }); // Draw player ctx.fillStyle = player.flashing ? 'white' : 'thistle'; ctx.fillRect(player.position.x * cellSize, player.position.y * cellSize, cellSize, cellSize); ctx.fillStyle = '#2d2d2d'; ctx.font = `${cellSize / 2}px Arial`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('@', player.position.x * cellSize + cellSize / 2, player.position.y * cellSize + cellSize / 2); } export function initializeGame() { grid = createGrid(10, 10); // reset grid levelPar = generatePar(player.level); generateCollectables(grid, 10); // how many collectables? generateDamagingSpaces(grid, Math.floor(Math.random() * 7) + 1); // random number of damaging spaces, no more than 7 generateTargetBlock(grid); generateTraps(grid, Math.floor(Math.random() * 3) + 1); // random number of traps, no more than 3 if (player.level === 0) { player.inventory = []; player.health = 10; player.power = 10; } player.position = { x: 0, y: 0 }; // player always starts at 0,0 player.steps = 0; // steps are counted per-level player.didScan = false; // scans are counted per-level resizeCanvas(); drawGrid(grid); updatePlayerStatus(); } export function resizeCanvas() { const canvas = document.getElementById('gameCanvas'); const width = Math.min(window.innerWidth, window.innerHeight) * 0.5; canvas.width = width; canvas.height = width; drawGrid(grid); } export function updatePlayerPosition(newX, newY) { player.position.x = newX; player.position.y = newY; checkForDamageOrTarget(); drawGrid(grid); updatePlayerStatus(); } export function updatePlayerStatus() { document.getElementById('playerPosition').textContent = `Position: (${player.position.x}, ${player.position.y})`; document.getElementById('playerHealth').textContent = `Health: ${player.health}`; document.getElementById('playerPower').textContent = `Power: ${player.power}`; document.getElementById('playerInventory').textContent = `Inventory: [${player.inventory.join(', ')}]`; document.getElementById('playerLevel').textContent = `Level: ${player.level}`; } function checkForDamageOrTarget() { const { x, y } = player.position; const cell = grid[x][y]; if (cell && cell.type === 'damage') { const shieldIndex = player.inventory.indexOf('shield'); if (shieldIndex > -1) { player.inventory.splice(shieldIndex, 1); // Use one shield console.log('Used shield to avoid damage'); } else { player.health -= 2; console.log(`Stepped on damaging space, health is now ${player.health}`); if (player.health <= 0) { alertGameOver(); return; } flashPlayer(); } } else if (cell && cell.type === 'trap') { const item = player.inventory.pop(); if (item) { console.log(`Stepped on trap, removed ${item} from inventory`); } else { player.power -= Math.floor(Math.random() * 3) + 1; console.log('Stepped on trap, drained some power'); } } else if (x === targetPosition.x && y === targetPosition.y) { player.level += 1; console.log(`Reached target block, level is now ${player.level}`); initializeGame(); // Generate new level and reset player position } } export function alertGameOver() { const gameStatsString = `Level: ${player.level}, Health: ${player.health}, Power: ${player.power}`; alert('You have lost the game!' + '\n' + gameStatsString); initializeGame(); }