Enhance enemy AI and area connectivity

- Introduced area grid management in WolfEngine to track player-connected areas.
- Updated enemy behavior to consider area connectivity when alerting and moving.
- Added debugging logs for enemy states and movements to assist in tracking AI behavior.
- Implemented fallback area generation for levels lacking area data.
- Enhanced patrol behavior for dogs and guards to prevent rapid direction changes after hitting walls.
- Updated tests to validate new area connectivity logic and enemy behavior under various conditions.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-19 18:03:01 +01:00
parent 7b1ec777d3
commit 4700e669ce
21 changed files with 565 additions and 135 deletions

View File

@@ -66,6 +66,8 @@ void main() {
playerAngle: 0,
isPlayerRunning: false,
isWalkable: (_, _) => false,
areaAt: (_, _) => 0,
isAreaConnectedToPlayer: (_) => true,
onDamagePlayer: (_) {},
tryOpenDoor: (_, _) {},
onPlaySound: (_) {},
@@ -78,6 +80,8 @@ void main() {
playerAngle: 0,
isPlayerRunning: false,
isWalkable: (_, _) => false,
areaAt: (_, _) => 0,
isAreaConnectedToPlayer: (_) => true,
onDamagePlayer: (_) {},
tryOpenDoor: (_, _) {},
onPlaySound: (_) {},
@@ -100,6 +104,8 @@ void main() {
playerAngle: 0,
isPlayerRunning: false,
isWalkable: (_, _) => true,
areaAt: (_, _) => 0,
isAreaConnectedToPlayer: (_) => true,
onDamagePlayer: (_) {},
tryOpenDoor: (_, _) {},
onPlaySound: (_) {},
@@ -112,16 +118,53 @@ void main() {
playerAngle: 0,
isPlayerRunning: false,
isWalkable: (_, _) => true,
areaAt: (_, _) => 0,
isAreaConnectedToPlayer: (_) => true,
onDamagePlayer: (_) {},
tryOpenDoor: (_, _) {},
onPlaySound: (_) {},
);
expect(guardIntent.movement.x.abs() + guardIntent.movement.y.abs(),
greaterThan(0));
expect(
dogIntent.movement.x.abs() + dogIntent.movement.y.abs(), greaterThan(0));
guardIntent.movement.x.abs() + guardIntent.movement.y.abs(),
greaterThan(0),
);
expect(
dogIntent.movement.x.abs() + dogIntent.movement.y.abs(),
greaterThan(0),
);
});
test(
'alerted dog can choose alternate path when direct chase is blocked',
() {
final dog = Dog(x: 8.99, y: 8.99, angle: 0, mapId: MapObject.dogStart);
dog.isAlerted = true;
final intent = dog.update(
elapsedMs: 1000,
elapsedDeltaMs: 16,
playerPosition: const Coordinate2D(11.99, 8.99),
playerAngle: 0,
isPlayerRunning: false,
isWalkable: (x, y) {
// Block the direct east chase tile only.
if (x == 9 && y == 8) return false;
return true;
},
areaAt: (_, _) => 0,
isAreaConnectedToPlayer: (_) => true,
onDamagePlayer: (_) {},
tryOpenDoor: (_, _) {},
onPlaySound: (_) {},
);
expect(
intent.movement.x.abs() + intent.movement.y.abs(),
greaterThan(0),
);
},
);
});
}