Something went wrong. Try again.
HEXWORK - A Lantern in the Deep: 3D ASCII terminal roguelike RPG in Rust.
Entirely designed and built by Muse Spark 1.3 to evaluate if I like the model.
Something went wrong. Try again.
3.9 kB · 119 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120//! Exhaustive v5 action timing policy. Admission and completion are separate://! this table prices time, and never applies effects or advances a State.use crate::action::CommittedAction;use crate::services::{sleep_ticks, Service};use std::num::NonZeroU64;
pub const WORLD_TICK_MS: u64 = 100;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]pub enum ActionTiming { Observation, World(NonZeroU64), Unattended(NonZeroU64),}
impl ActionTiming { pub fn ticks(self) -> u64 { match self { Self::Observation => 0, Self::World(ticks) | Self::Unattended(ticks) => ticks.get(), } }}
/// No wildcard/default arm: new committed operations must choose their timing./// InspectBoard will move out of the committed vocabulary during v5 integration.pub fn action_timing(action: &CommittedAction) -> ActionTiming { let world = |ticks| ActionTiming::World(NonZeroU64::new(ticks).expect("positive action duration")); match action { CommittedAction::Move(_) | CommittedAction::Wait => world(1), CommittedAction::InspectBoard { .. } => ActionTiming::Observation, CommittedAction::AcceptContract { .. } | CommittedAction::UseTransition { .. } | CommittedAction::ResolveAttack { .. } | CommittedAction::Pickup { .. } | CommittedAction::Drop { .. } | CommittedAction::Wield { .. } | CommittedAction::TurnIn { .. } => world(10), CommittedAction::TinkerIdentify { .. } => world(20), CommittedAction::UseService { service } => match service { Service::Inn => ActionTiming::Unattended( NonZeroU64::new(sleep_ticks()).expect("positive authored inn duration"), ), Service::Tinker | Service::Lampwright | Service::Warden | Service::Mender | Service::Fence | Service::Auction => world(10), }, }}
#[cfg(test)]mod tests { use super::*; use crate::action::Direction;
#[test] fn all_actions_duration_table() { let cases = [ (CommittedAction::Move(Direction::North), 1), (CommittedAction::Wait, 1), ( CommittedAction::InspectBoard { town: "town".into(), }, 0, ), ( CommittedAction::AcceptContract { id: "contract".into(), }, 10, ), (CommittedAction::UseTransition { transition_id: 7 }, 10), (CommittedAction::ResolveAttack { target_actor: 9 }, 10), (CommittedAction::Pickup { item_id: 11 }, 10), (CommittedAction::Drop { item_id: 11 }, 10), (CommittedAction::Wield { item_id: 11 }, 10), (CommittedAction::TinkerIdentify { item_id: 11 }, 20), ( CommittedAction::TurnIn { contract_id: "contract".into(), }, 10, ), ( CommittedAction::UseService { service: Service::Inn, }, 8640, ), ]; for (action, expected) in cases { assert_eq!(action_timing(&action).ticks(), expected, "{action:?}"); } for service in [ Service::Tinker, Service::Lampwright, Service::Warden, Service::Mender, Service::Fence, Service::Auction, ] { assert_eq!( action_timing(&CommittedAction::UseService { service }).ticks(), 10 ); } assert!(matches!( action_timing(&CommittedAction::UseService { service: Service::Inn }), ActionTiming::Unattended(_) )); }}