neurodoom 0.6.7

Deterministic no_std Doom engine with semantic and depth perception buffers for AI
Documentation
//! Game rules trait — the deterministic transition function.
//!
//! All peers agree on a `GameRules` implementation. Each tick, they collect
//! player actions, run the same transition function, and arrive at the same
//! world state. No trust needed — just determinism.

use crate::types::Buttons;
use crate::world::{Entity, EntityId, PeerId, World};

/// What a player submits each tick. Minimal, serializable, validatable.
#[derive(Clone, Copy, Debug, Default)]
pub struct PlayerAction {
    pub forward_move: i8,
    pub side_move: i8,
    pub angle_turn: i16,
    pub buttons: Buttons,
    /// Requested weapon slot (1-7), or 0 for no change.
    pub weapon_select: u8,
}

/// Actions from an external authority that modify the world.
#[derive(Clone, Debug)]
pub enum WorldAction {
    /// Spawn an entity with the given properties.
    SpawnEntity(Entity),
    /// Remove an entity by ID.
    RemoveEntity(EntityId),
    /// Modify a sector's properties.
    ModifySector {
        sector: u16,
        floor_height: Option<i32>,
        ceiling_height: Option<i32>,
        light_level: Option<i16>,
    },
}

/// Result of two entities touching. Used by rule implementations
/// (see `ClassicDoomRules`); not called by the engine directly.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TouchResult {
    /// Nothing happened.
    Nothing,
    /// Entity was picked up (remove it).
    PickedUp,
    /// Solid collision (block movement).
    Blocked,
    /// Deal damage to the toucher.
    Damaged(i32),
}

/// The agreed-upon game rules. All peers must use the same implementation.
/// Must be deterministic: same `(world, actions)` → same `world'`.
///
/// This trait is intentionally minimal — just the transition function the
/// engine invokes every tick, plus two default-true validators for pre-
/// consensus filtering. Internal structure (behavior categories, state
/// machines, touch / damage callbacks) is entirely up to each
/// implementation; see `ClassicDoomRules` for the classic-Doom flavour.
pub trait GameRules {
    /// Full tick: apply player inputs, run behaviors, physics, specials.
    /// Must be deterministic for given `(world, player_actions, world_actions)`.
    fn tick(
        &self,
        world: &mut World,
        map: &crate::map::MapData,
        player_actions: &[(PeerId, PlayerAction)],
        world_actions: &[WorldAction],
    );

    /// Validate a player action before including it in consensus. Called
    /// by networking layers — default is "accept everything". Override to
    /// reject out-of-range inputs, cheats, etc.
    #[inline]
    fn validate_player_action(
        &self,
        _world: &World,
        _player: PeerId,
        _action: &PlayerAction,
    ) -> bool {
        true
    }

    /// Validate a world action before applying. Default: accept.
    #[inline]
    fn validate_world_action(&self, _world: &World, _action: &WorldAction) -> bool {
        true
    }
}