use std::collections::HashSet;
use std::fmt;
use crate::planning::belief::BeliefId;
pub trait Strategy: fmt::Debug + Send + Sync {
fn can_perform(&self) -> bool {
true
}
fn is_complete(&self) -> bool;
fn start(&mut self) {}
fn update(&mut self, _dt: f32) {}
fn stop(&mut self) {}
}
pub struct ActionDef {
pub name: String,
pub cost: f32,
pub preconditions: HashSet<BeliefId>,
pub effects: HashSet<BeliefId>,
strategy: Box<dyn Strategy>,
}
impl ActionDef {
pub fn strategy(&self) -> &dyn Strategy {
&*self.strategy
}
pub fn strategy_mut(&mut self) -> &mut dyn Strategy {
&mut *self.strategy
}
pub fn is_complete(&self) -> bool {
self.strategy.is_complete()
}
pub fn can_perform(&self) -> bool {
self.strategy.can_perform()
}
pub fn start(&mut self) {
self.strategy.start();
}
pub fn update(&mut self, dt: f32) {
self.strategy.update(dt);
}
pub fn stop(&mut self) {
self.strategy.stop();
}
}
impl fmt::Debug for ActionDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Action")
.field("name", &self.name)
.field("cost", &self.cost)
.field("preconditions", &self.preconditions)
.field("effects", &self.effects)
.finish()
}
}
pub struct ActionBuilder {
name: String,
cost: f32,
preconditions: HashSet<BeliefId>,
effects: HashSet<BeliefId>,
strategy: Option<Box<dyn Strategy>>,
}
impl ActionBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
cost: 1.0,
preconditions: HashSet::new(),
effects: HashSet::new(),
strategy: None,
}
}
pub fn cost(mut self, cost: f32) -> Self {
self.cost = cost;
self
}
pub fn precondition(mut self, belief: impl Into<BeliefId>) -> Self {
self.preconditions.insert(belief.into());
self
}
pub fn effect(mut self, belief: impl Into<BeliefId>) -> Self {
self.effects.insert(belief.into());
self
}
pub fn strategy(mut self, strategy: impl Strategy + 'static) -> Self {
self.strategy = Some(Box::new(strategy));
self
}
pub fn build(self) -> ActionDef {
ActionDef {
name: self.name,
cost: self.cost,
preconditions: self.preconditions,
effects: self.effects,
strategy: self.strategy.expect("Action must have a strategy"),
}
}
}