diff options
author | elioat <elioat@tilde.institute> | 2024-12-02 21:09:16 -0500 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2024-12-02 21:09:16 -0500 |
commit | 5db4d92b3a6e2db45df6e471d676fd78b07be1f3 (patch) | |
tree | c985fd80464870cd93dbb1347f8b1e57c948910f /html/broughlike | |
parent | 2ffdc2c8b757571c934a64d5289ffcf9766c860a (diff) | |
download | tour-5db4d92b3a6e2db45df6e471d676fd78b07be1f3.tar.gz |
*
Diffstat (limited to 'html/broughlike')
-rw-r--r-- | html/broughlike/broughlike.js | 184 |
1 files changed, 148 insertions, 36 deletions
diff --git a/html/broughlike/broughlike.js b/html/broughlike/broughlike.js index 87718f3..5e82ebb 100644 --- a/html/broughlike/broughlike.js +++ b/html/broughlike/broughlike.js @@ -1,7 +1,5 @@ import { CONFIG, COLORS, CANVAS } from './config.js'; -const DEBUG = false; - let highScore = localStorage.getItem('highScore') || 0; const player = { x: 0, @@ -673,7 +671,7 @@ function resetGame() { generateEnemies(); generateItems(); render(); - if (DEBUG) + if (AUTO_PLAY) autoPlay(); } @@ -697,7 +695,7 @@ function checkPlayerAtExit() { generateEnemies(); generateItems(); render(); - if (DEBUG) + if (AUTO_PLAY) autoPlay(); } } @@ -793,40 +791,146 @@ render(); -function autoPlay() { + + +function autoPlay() { + let lastPosition = { x: player.x, y: player.y }; + let stuckCounter = 0; + const playerAtExit = () => player.x === exit.x && player.y === exit.y; const playerCanMove = (dx, dy) => isValidMove(player.x + dx, player.y + dy); - const playerCanAttack = (enemy) => Math.abs(enemy.x - player.x) + Math.abs(enemy.y - player.y) === 10; + + const checkIfStuck = () => { + if (lastPosition.x === player.x && lastPosition.y === player.y) { + stuckCounter++; + } else { + stuckCounter = 0; + lastPosition = { x: player.x, y: player.y }; + } + return stuckCounter > 3; // Consider yourself stuck after 3 turns in the same position + }; - const movePlayerTowardsExit = () => { - const path = findPath(player, exit); - if (path.length > 1) { - const nextStep = path[1]; - const dx = nextStep.x - player.x; - const dy = nextStep.y - player.y; + const desperateEscape = () => { + const allDirections = [ + {dx: 1, dy: 0}, {dx: -1, dy: 0}, + {dx: 0, dy: 1}, {dx: 0, dy: -1}, + {dx: 1, dy: 1}, {dx: -1, dy: 1}, + {dx: 1, dy: -1}, {dx: -1, dy: -1} + ]; + + allDirections.sort(() => Math.random() - 0.5); + + for (const {dx, dy} of allDirections) { if (playerCanMove(dx, dy)) { movePlayer(dx, dy); + return true; } } + return false; }; - const attackEnemies = () => { - const enemiesInRange = enemies.filter(enemy => playerCanAttack(enemy)); - if (enemiesInRange.length > 0) { - const randomIndex = Math.floor(Math.random() * enemiesInRange.length); - const targetEnemy = enemiesInRange[randomIndex]; - const dx = targetEnemy.x - player.x; - const dy = targetEnemy.y - player.y; - movePlayer(dx, dy); + const hasAdjacentEnemy = (x, y) => { + return enemies.some(enemy => + Math.abs(enemy.x - x) + Math.abs(enemy.y - y) === 1 + ); + }; + + const findNearestItem = () => { + if (items.length === 0) return null; + return items.reduce((nearest, item) => { + const distToCurrent = Math.abs(player.x - item.x) + Math.abs(player.y - item.y); + const distToNearest = nearest ? Math.abs(player.x - nearest.x) + Math.abs(player.y - nearest.y) : Infinity; + return distToCurrent < distToNearest ? item : nearest; + }, null); + }; + + const decideNextTarget = () => { + + const healingItem = items.find(item => + item.type === 'pentagon' && + player.health < CONFIG.PLAYER_HEALTH * 0.5 + ); + if (healingItem) return healingItem; + + const nearestItem = findNearestItem(); + if (nearestItem && Math.abs(player.x - nearestItem.x) + Math.abs(player.y - nearestItem.y) < 5) { + return nearestItem; } + + return exit; }; - const collectItem = () => { - const item = items.find(item => item.x === player.x && item.y === player.y); - if (item) { - handleItemCollection(); + const moveTowardsTarget = (target) => { + const path = findPath(player, target); + if (path.length > 1) { + const nextStep = path[1]; + + if (Math.random() < 0.2) { + const alternateDirections = [ + {dx: 1, dy: 0}, {dx: -1, dy: 0}, + {dx: 0, dy: 1}, {dx: 0, dy: -1} + ].filter(({dx, dy}) => + playerCanMove(dx, dy) && + !hasAdjacentEnemy(player.x + dx, player.y + dy) + ); + + if (alternateDirections.length > 0) { + const randomDir = alternateDirections[Math.floor(Math.random() * alternateDirections.length)]; + movePlayer(randomDir.dx, randomDir.dy); + return true; + } + } + + if (!hasAdjacentEnemy(nextStep.x, nextStep.y)) { + const dx = nextStep.x - player.x; + const dy = nextStep.y - player.y; + if (playerCanMove(dx, dy)) { + movePlayer(dx, dy); + return true; + } + } } + return false; + }; + + const handleCombat = () => { + const adjacentEnemy = enemies.find(enemy => + Math.abs(enemy.x - player.x) + Math.abs(enemy.y - player.y) === 1 + ); + + if (adjacentEnemy) { + // Increase the chance of retreating when stuck + const retreatChance = checkIfStuck() ? 0.8 : 0.3; + + if (Math.random() < retreatChance) { + const retreatDirections = [ + {dx: 1, dy: 0}, {dx: -1, dy: 0}, + {dx: 0, dy: 1}, {dx: 0, dy: -1} + ]; + + retreatDirections.sort(() => Math.random() - 0.5); + + for (const {dx, dy} of retreatDirections) { + if (playerCanMove(dx, dy) && !hasAdjacentEnemy(player.x + dx, player.y + dy)) { + movePlayer(dx, dy); + return true; + } + } + } + + // If stuck, try desperate escape + if (checkIfStuck()) { + return desperateEscape(); + } + + // Attack if can't retreat + const dx = adjacentEnemy.x - player.x; + const dy = adjacentEnemy.y - player.y; + movePlayer(dx, dy); + return true; + } + return false; }; const play = () => { @@ -834,22 +938,30 @@ function autoPlay() { return; } - movePlayerTowardsExit(); - - enemies.forEach(enemy => { - if (playerCanAttack(enemy)) { - attackEnemies(enemy); - } - }); - - collectItem(); + // If stuck, try desperate escape + if (checkIfStuck() && desperateEscape()) { + // Successfully escaped + } else if (!handleCombat()) { + // If no combat, move towards the next target + const target = decideNextTarget(); + moveTowardsTarget(target); + } - setTimeout(play, 1000); + setTimeout(play, 400); // 400ms is about 1.5 moves per second because 1000ms was terribly slow. }; play(); } +let AUTO_PLAY = false; -if (DEBUG) - autoPlay(); \ No newline at end of file +document.addEventListener('keydown', (e) => { + if (e.key === 'v') { + // alert to confirm that the user wants to toggle auto play + if (confirm("Are you sure you want to toggle auto play? Once auto play is turned on, the only way to turn it off is to reload the page.")) { + AUTO_PLAY = !AUTO_PLAY; + if (AUTO_PLAY) + autoPlay(); + } + } +}); \ No newline at end of file |