NPC strategy is now a Brain field on the entity (Idle, Wander, Hunt(Prey)) that Sim::think matches on, so behavior is data independent of species. Hunt follows the first step of an A* route to the nearest prey in sight, replanned every window; the pathfinder moves from game/ to sim/ for that. A greedy step-toward-target was tried first and oscillated at walls. Bumps between the same species no longer fight, and six foxes join the hens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
55 lines
1.4 KiB
Rust
Executable File
55 lines
1.4 KiB
Rust
Executable File
/// Who decides an entity's actions. The sim only schedules intents for `Npc`s; a
|
|
/// `Player`'s intents come from outside (input) through `Sim::set_action`.
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
pub enum EntityKind {
|
|
Player,
|
|
Npc,
|
|
}
|
|
|
|
/// What a hunter goes after.
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
pub enum Prey {
|
|
Player,
|
|
Kind(u16),
|
|
}
|
|
|
|
/// The decision strategy `Sim::think` runs for an NPC. Data, not code: it can be
|
|
/// swapped at runtime (a hit hen may start fleeing) and serializes with the entity.
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
pub enum Brain {
|
|
/// Never schedules anything — the player, furniture.
|
|
Idle,
|
|
/// Occasionally a random king move.
|
|
Wander,
|
|
/// Step toward the nearest prey in sight, bumping into it on contact. Wanders
|
|
/// when nothing is in sight.
|
|
Hunt(Prey),
|
|
}
|
|
|
|
pub struct Entity {
|
|
pub id: u32,
|
|
pub kind: EntityKind,
|
|
pub type_id: u16, // sprite index into the entity tileset; also the species
|
|
pub brain: Brain,
|
|
pub pos: (i16, i16),
|
|
pub hp: u16,
|
|
pub hp_max: u16,
|
|
/// Damage dealt per bump.
|
|
pub attack: u16,
|
|
}
|
|
|
|
impl Entity {
|
|
pub fn new(id: u32, kind: EntityKind, type_id: u16, brain: Brain, pos: (i16, i16), hp: u16, attack: u16) -> Self {
|
|
Self {
|
|
id,
|
|
kind,
|
|
type_id,
|
|
brain,
|
|
pos,
|
|
hp,
|
|
hp_max: hp,
|
|
attack,
|
|
}
|
|
}
|
|
}
|