about summary refs log tree commit diff stats
path: root/html/broughlike/broughlike.js
diff options
context:
space:
mode:
authorelioat <{ID}+{username}@users.noreply.github.com>2024-11-01 15:49:20 -0400
committerelioat <{ID}+{username}@users.noreply.github.com>2024-11-01 15:49:20 -0400
commit3b607e7e3c2364613f6d1f1b41ad4ca16d0c98fb (patch)
tree5311d0a4c8060c41267495859948ceb850785879 /html/broughlike/broughlike.js
parent32f23188b63c8995f1a5aa6efbc62e5e616250fa (diff)
downloadtour-3b607e7e3c2364613f6d1f1b41ad4ca16d0c98fb.tar.gz
*
Diffstat (limited to 'html/broughlike/broughlike.js')
-rw-r--r--html/broughlike/broughlike.js79
1 files changed, 51 insertions, 28 deletions
diff --git a/html/broughlike/broughlike.js b/html/broughlike/broughlike.js
index 2960c95..8933e31 100644
--- a/html/broughlike/broughlike.js
+++ b/html/broughlike/broughlike.js
@@ -50,7 +50,7 @@ function generateEnemies() {
     const numEnemies = player.score > 4 
     ? Math.floor(Math.random() * (CONFIG.MAX_ENEMIES_ON_LEVEL - CONFIG.MIN_ENEMIES_ON_LEVEL + 1)) + CONFIG.MIN_ENEMIES_ON_LEVEL 
     : Math.floor(Math.random() * (CONFIG.MAX_ENEMIES_ON_LEVEL + 1));
-    for (let i = 0; i < numEnemies; i++) {
+    for (let i = 0; i < numEnemies;) {
         let enemyX, enemyY;
         do {
             enemyX = Math.floor(Math.random() * CONFIG.GRID_SIZE);
@@ -61,12 +61,15 @@ function generateEnemies() {
             walls.some(wall => wall.x === enemyX && wall.y === enemyY) ||
             (Math.abs(enemyX - player.x) + Math.abs(enemyY - player.y) < 2) // Ensure enemy is at least 2 spaces away from player
         );
-        enemies.push({
-            color: COLORS.enemy,
-            x: enemyX,
-            y: enemyY,
-            health: Math.floor(Math.random() * (CONFIG.MAX_ENEMY_HEALTH - CONFIG.MIN_ENEMY_HEALTH + 1)) + CONFIG.MIN_ENEMY_HEALTH
-        });
+        if (isReachable(player.x, player.y, enemyX, enemyY)) {
+            enemies.push({
+                color: COLORS.enemy,
+                x: enemyX,
+                y: enemyY,
+                health: Math.floor(Math.random() * (CONFIG.MAX_ENEMY_HEALTH - CONFIG.MIN_ENEMY_HEALTH + 1)) + CONFIG.MIN_ENEMY_HEALTH
+            });
+            i++; // Only increment i if the enemy is reachable and actually placed on the board, this avoids levels with fewer enemies than MIN_ENEMIES_ON_LEVEL
+        }
     }
 
     // Generate a boss enemy every ENEMY_BOSS_OCCURRENCE levels
@@ -78,13 +81,15 @@ function generateEnemies() {
         } while (
             (Math.abs(bossX - player.x) + Math.abs(bossY - player.y) < 2) // Ensure boss is at least 2 spaces away from player
         );
-        enemies.push({
-            isBoss: true,
-            color: COLORS.boss,
-            x: bossX,
-            y: bossY,
-            health: CONFIG.MAX_ENEMY_HEALTH + 2
-        });
+        if (isReachable(player.x, player.y, bossX, bossY)) {
+            enemies.push({
+                isBoss: true,
+                color: COLORS.boss,
+                x: bossX,
+                y: bossY,
+                health: CONFIG.MAX_ENEMY_HEALTH + 2
+            });
+        }
     }
 }
 
@@ -299,27 +304,43 @@ function generateItems() {
             items.some(item => item.x === itemX && item.y === itemY)
         );
         const itemType = Math.random() < 0.5 ? 'diamond' : 'pentagon'; // 50% chance for each type
-        items.push({ x: itemX, y: itemY, type: itemType });
+        if (isReachable(player.x, player.y, itemX, itemY))
+            items.push({ x: itemX, y: itemY, type: itemType });
     }
 }
 
-function isPassable() {
-    const visited = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(false));
-
+function isReachable(startX, startY, targetX, targetY) {
+    const visited = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(false)); // Initialize a 2D array of false values
     function dfs(x, y) {
         if (x < 0 || x >= CONFIG.GRID_SIZE || y < 0 || y >= CONFIG.GRID_SIZE) return false; // Are the coordinates in bounds?
-        if (visited[x][y]) return false;
-        if (walls.some(wall => wall.x === x && wall.y === y)) return false;
-        visited[x][y] = true;
-        if (x === exit.x && y === exit.y) return true;
-        return dfs(x + 1, y) || dfs(x - 1, y) || dfs(x, y + 1) || dfs(x, y - 1);
+        if (visited[x][y]) return false;                                                    // Have we already visited this cell?
+        if (walls.some(wall => wall.x === x && wall.y === y)) return false;                 // Is there a wall here?
+        visited[x][y] = true;                                                               // Mark this cell as visited
+        if (x === targetX && y === targetY) return true;                                    // Have we reached the target?
+        return dfs(x + 1, y) || dfs(x - 1, y) || dfs(x, y + 1) || dfs(x, y - 1);            // Recursively check neighbors
     }
+    return dfs(startX, startY);
+}
 
+// This function is used to check if the player can reach the exit after generating the level
+// It is almost the same as isReachable, but it checks for the exit instead of an arbitrary target
+// I could defo use isReachable for this, but I...am not doing that right now.
+function isPassable() {
+    const visited = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(false)); // Initialize a 2D array of false values
+    function dfs(x, y) {
+        if (x < 0 || x >= CONFIG.GRID_SIZE || y < 0 || y >= CONFIG.GRID_SIZE) return false; // Are the coordinates in bounds?
+        if (visited[x][y]) return false;                                                    // Have we already visited this cell?
+        if (walls.some(wall => wall.x === x && wall.y === y)) return false;                 // Is there a wall here?
+        visited[x][y] = true;                                                               // Mark this cell as visited
+        if (x === exit.x && y === exit.y) return true;                                      // Have we reached the exit?
+        return dfs(x + 1, y) || dfs(x - 1, y) || dfs(x, y + 1) || dfs(x, y - 1);            // Recursively check neighbors
+    }
     return dfs(player.x, player.y);
 }
 
 function drawGrid() {
     ctx.clearRect(0, 0, canvas.width, canvas.height);
+    ctx.lineWidth = 2;
     ctx.strokeStyle = COLORS.grid;
     for (let row = 0; row < CONFIG.GRID_SIZE; row++) {
         for (let col = 0; col < CONFIG.GRID_SIZE; col++) {
@@ -628,11 +649,13 @@ function handleDamage(player, enemy) {
 
     if (enemy.health <= 0) {
         player.killCount++;
-        enemies = enemies.filter(e => e !== enemy);                
+        enemies = enemies.filter(e => e !== enemy);
         if (enemy.isBoss) {
             // Defeating a boss restores 3 player health
             player.health = Math.min(player.health + 3, CONFIG.PLAYER_MAX_HEALTH);
-            console.log("Defeated a boss! Healed " + 3 + " health.");
+            console.log("Defeated a boss! Healed " + 3 + " health. Player health " + player.health);
+        } else if (Math.random() < 0.25) {
+            player.health = Math.min(player.health + 1, CONFIG.PLAYER_MAX_HEALTH);
         }
     }
 
@@ -664,9 +687,9 @@ function resetGame() {
     player.y = 0;
     combatDots = {};
     generateExit();
+    generateWalls();
     generateEnemies();
     generateItems();
-    generateWalls();
     render();
 }
 
@@ -686,9 +709,9 @@ function checkPlayerAtExit() {
         console.groupEnd();
         combatDots = {};
         generateExit();
+        generateWalls();
         generateEnemies();
         generateItems();
-        generateWalls();
         render();
     }
 }
@@ -775,7 +798,7 @@ resizeCanvas();
 
 // Initial level setup
 generateExit();
+generateWalls();
 generateEnemies();
 generateItems();
-generateWalls();
 render();
\ No newline at end of file