(dx: number, dy: number)
| 217 | } |
| 218 | |
| 219 | function tryMove(dx: number, dy: number): void { |
| 220 | const nx = player.x + dx; |
| 221 | const ny = player.y + dy; |
| 222 | |
| 223 | if (tileAt(nx, ny) === TILE_WALL) return; |
| 224 | |
| 225 | const ei = enemyAt(nx, ny); |
| 226 | if (ei >= 0) { |
| 227 | // Attack enemy |
| 228 | const dmg = randomInt(player.attack - 1, player.attack + 1); |
| 229 | enemies[ei].hp = enemies[ei].hp - dmg; |
| 230 | if (enemies[ei].hp <= 0) { |
| 231 | enemies[ei].active = false; |
| 232 | showMessage("Defeated " + enemies[ei].name + "!"); |
| 233 | } else { |
| 234 | showMessage("Hit " + enemies[ei].name + " for " + dmg.toString() + " damage"); |
| 235 | } |
| 236 | } else { |
| 237 | player.x = nx; |
| 238 | player.y = ny; |
| 239 | } |
| 240 | |
| 241 | // Check stairs |
| 242 | if (tileAt(player.x, player.y) === TILE_STAIRS) { |
| 243 | floor = floor + 1; |
| 244 | generateDungeon(); |
| 245 | showMessage("Descended to floor " + floor.toString()); |
| 246 | computeVisibility(); |
| 247 | return; |
| 248 | } |
| 249 | |
| 250 | // Enemy turns |
| 251 | for (let i = 0; i < enemies.length; i++) { |
| 252 | if (!enemies[i].active) continue; |
| 253 | const edx = player.x - enemies[i].x; |
| 254 | const edy = player.y - enemies[i].y; |
| 255 | const dist = Math.abs(edx) + Math.abs(edy); |
| 256 | |
| 257 | if (dist <= 1) { |
| 258 | // Attack player |
| 259 | const dmg = randomInt(enemies[i].attack - 1, enemies[i].attack + 1); |
| 260 | player.hp = player.hp - dmg; |
| 261 | showMessage(enemies[i].name + " hits you for " + dmg.toString() + "!"); |
| 262 | } else if (dist <= FOV_RADIUS && isVisible(enemies[i].x, enemies[i].y)) { |
| 263 | // Move toward player |
| 264 | let mx = 0; |
| 265 | let my = 0; |
| 266 | if (Math.abs(edx) > Math.abs(edy)) { |
| 267 | mx = edx > 0 ? 1 : -1; |
| 268 | } else { |
| 269 | my = edy > 0 ? 1 : -1; |
| 270 | } |
| 271 | const enx = enemies[i].x + mx; |
| 272 | const eny = enemies[i].y + my; |
| 273 | if (tileAt(enx, eny) !== TILE_WALL && enemyAt(enx, eny) < 0 && |
| 274 | !(enx === player.x && eny === player.y)) { |
| 275 | enemies[i].x = enx; |
| 276 | enemies[i].y = eny; |
no test coverage detected