Add entity blocking and a wandering NPC
Occupied tiles now block movement through World::blocked, the one predicate the sim and the pathfinder share. Entities carry an EntityKind so the sim knows which ones to think for; Sim::think gives each NPC a random king move one window in four. Intents execute in id order so contested tiles resolve deterministically. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+19
-3
@@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::chunk::{Chunk, TileFlags};
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::{Entity, EntityKind};
|
||||
|
||||
pub fn tile_to_chunk(tx: i16, ty: i16) -> (i16, i16) {
|
||||
(tx >> 5, ty >> 5)
|
||||
@@ -52,14 +52,30 @@ impl World {
|
||||
chunk.set_tile(lx, ly, id);
|
||||
}
|
||||
|
||||
pub fn spawn_entity(&mut self, type_id: u16, pos: (i16, i16), hp: u16) -> u32 {
|
||||
pub fn spawn_entity(&mut self, kind: EntityKind, type_id: u16, pos: (i16, i16), hp: u16) -> u32 {
|
||||
let id = self.next_entity_id;
|
||||
self.next_entity_id += 1;
|
||||
let entity = Entity::new(id, type_id, pos, hp);
|
||||
let entity = Entity::new(id, kind, type_id, pos, hp);
|
||||
self.add_entity(entity);
|
||||
id
|
||||
}
|
||||
|
||||
/// True if any entity stands on `(wx, wy)`. Goes through the chunk index, so it is
|
||||
/// cheap enough to call per pathfinder expansion.
|
||||
pub fn occupied(&self, wx: i16, wy: i16) -> bool {
|
||||
let (cx, cy) = tile_to_chunk(wx, wy);
|
||||
self.entities_in_chunk(cx, cy).iter()
|
||||
.any(|id| self.entities[id].pos == (wx, wy))
|
||||
}
|
||||
|
||||
/// The movement blocker predicate: a tile blocks if it is solid, outside the loaded
|
||||
/// world, or occupied by an entity. Both the sim and the pathfinder plan with this.
|
||||
pub fn blocked(&self, wx: i32, wy: i32) -> bool {
|
||||
let Ok(wx) = i16::try_from(wx) else { return true };
|
||||
let Ok(wy) = i16::try_from(wy) else { return true };
|
||||
self.tile_flags(wx, wy).map_or(true, |f| f.collidable()) || self.occupied(wx, wy)
|
||||
}
|
||||
|
||||
pub fn add_entity(&mut self, entity: Entity) {
|
||||
let chunk_key = tile_to_chunk(entity.pos.0, entity.pos.1);
|
||||
let id = entity.id;
|
||||
|
||||
Reference in New Issue
Block a user