Skip to content

Commit

Permalink
Moved around more stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
victorb committed Aug 11, 2024
1 parent 5ce8b90 commit 083e42b
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 122 deletions.
28 changes: 2 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/dogoap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ homepage = "https://github.com/victorb/dogoap"
bevy_reflect = "0.14.0"
log = "0.4.22"
pathfinding = "4.10.0"
serde_json = "1.0.120"
10 changes: 1 addition & 9 deletions crates/dogoap/benches/long_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ mod tests {

let goal = Goal::new().with_req("gold", Compare::Equals(Datum::I64(7)));

// TOOD should keep the `10 as 64` syntax with .from somehow
let sleep_action = simple_increment_action("sleep", "energy", Datum::I64(10));

let eat_action = simple_decrement_action("eat", "hunger", Datum::I64(10))
Expand All @@ -46,20 +45,13 @@ mod tests {

let plan = make_plan_with_strategy(strategy, &start, &actions[..], &goal);
let effects = get_effects_from_plan(plan.clone().unwrap().0);
assert_eq!(11, effects.len());

print_plan(plan.unwrap());

assert_eq!(11, effects.len());
assert_eq!(expected_state, effects.last().unwrap().state);
}

#[bench]
fn bench_start_to_goal_strategy(b: &mut Bencher) {
b.iter(|| long_plan(PlanningStrategy::StartToGoal));
}

// #[bench]
// fn bench_goal_to_start_strategy(b: &mut Bencher) {
// b.iter(|| long_plan(PlanningStrategy::GoalToStart));
// }
}
3 changes: 2 additions & 1 deletion crates/dogoap/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ use crate::mutator::Mutator;
pub struct Action {
/// String like `eat_action`
pub key: String,
// TODO arguments coupled with Effects
// TODO arguments coupled with Effects, maybe
// pub argument: Option<Datum>,
/// What preconditions need to be true before we can execute this action
pub preconditions: Vec<(String, Compare)>,
/// What is the outcome from doing this action
// TODO temporarily plural effects, as maybe we want to implement arguments with many effects...
pub effects: Vec<Effect>,
}

Expand Down
5 changes: 1 addition & 4 deletions crates/dogoap/src/compare.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use crate::{action::Action, datum::Datum, state::LocalState};
use crate::{action::Action, datum::Datum, localstate::LocalState};
use bevy_reflect::Reflect;
use std::hash::{Hash, Hasher};

// TODO rename these to more rust familiar names?
// https://doc.rust-lang.org/reference/expressions/operator-expr.html#comparison-operators
#[derive(Reflect, Clone, Debug, PartialEq)]
pub enum Compare {
Equals(Datum),
Expand Down Expand Up @@ -55,7 +53,6 @@ pub fn compare_values(comparison: &Compare, value: &Datum) -> bool {
}
}

// TODO should be in Action or LocalState instead perhaps?
/// Checks all the preconditions from the `Action` against passed in `LocalState`
/// Returns `true` if all the preconditions pass (or if there is none), otherwise `false`
pub fn check_preconditions(state: &LocalState, action: &Action) -> bool {
Expand Down
3 changes: 2 additions & 1 deletion crates/dogoap/src/datum.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use bevy_reflect::*;
use std::fmt::Display;
use std::hash::Hash;
use std::ops::{Add, AddAssign, Sub, SubAssign};

use bevy_reflect::Reflect;

#[derive(Reflect, Clone, Debug, PartialOrd, Copy)]
pub enum Datum {
Bool(bool),
Expand Down
2 changes: 1 addition & 1 deletion crates/dogoap/src/effect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{mutator::Mutator, state::LocalState};
use crate::{localstate::LocalState, mutator::Mutator};
use bevy_reflect::Reflect;
use std::hash::{Hash, Hasher};

Expand Down
1 change: 0 additions & 1 deletion crates/dogoap/src/goal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::hash::{Hash, Hasher};

use bevy_reflect::*;

// use crate::requirement::DynRequirement;
use crate::compare::Compare;

#[derive(Reflect, Clone, Debug, PartialEq)]
Expand Down
3 changes: 2 additions & 1 deletion crates/dogoap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#![feature(trivial_bounds)]
#![doc = include_str!("../README.md")]
mod action;
mod compare;
mod datum;
mod effect;
mod goal;
mod localstate;
mod mutator;
mod state;

pub mod planner;
pub mod prelude;
Expand Down
17 changes: 10 additions & 7 deletions crates/dogoap/src/state.rs → crates/dogoap/src/localstate.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
use std::hash::{Hash, Hasher};

use std::collections::BTreeMap;
// List of other hashmap-likes we've tried, but none faster than BTreeMap
// use scc::HashMap as BTreeMap;
// use rustc_hash::FxHashMap as BTreeMap;
// use ahash::HashMapExt;
// use indexset::BTreeMap;
// use cow_hashmap::CowHashMap as BTreeMap;
use std::hash::{Hash, Hasher};

// use ahash::{AHasher, RandomState};
// use std::collections::HashMap as BTreeMap;

// use ahash::AHashMap as BTreeMap;
// use indexmap::IndexMap; // 37,873.88 ns/iter
// use micromap::Map; // 30,480.55 ns/iter

use bevy_reflect::Reflect;

use crate::datum::Datum;
use crate::goal::Goal;

use bevy_reflect::*;
// use indexmap::IndexMap;
pub type InternalData = BTreeMap<String, Datum>;

#[derive(Reflect, Debug, Clone, Eq, PartialEq, Default)]
pub struct LocalState {
pub data: BTreeMap<String, Datum>,
pub data: InternalData,
}

impl LocalState {
pub fn new() -> Self {
Self {
data: BTreeMap::new(),
data: InternalData::new(),
}
}

Expand Down
22 changes: 21 additions & 1 deletion crates/dogoap/src/mutator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::datum::Datum;
use std::collections::BTreeMap;

use crate::{datum::Datum, localstate::InternalData};

use bevy_reflect::*;

Expand All @@ -9,6 +11,24 @@ pub enum Mutator {
Decrement(String, Datum), // :key, :decrement-by
}

pub fn apply_mutator(data: &mut InternalData, mutator: &Mutator) {
match mutator {
Mutator::Set(key, value) => {
data.insert(key.to_string(), *value);
}
Mutator::Increment(key, value) => {
if let Some(current_value) = data.get_mut(key) {
*current_value += *value;
}
}
Mutator::Decrement(key, value) => {
if let Some(current_value) = data.get_mut(key) {
*current_value -= *value;
}
}
}
}

pub fn print_mutators(mutators: Vec<Mutator>) {
for mutator in mutators {
match mutator {
Expand Down
70 changes: 30 additions & 40 deletions crates/dogoap/src/planner.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::collections::BTreeMap;

use crate::{
action::Action,
compare::{check_preconditions, compare_values},
datum::Datum,
effect::Effect,
goal::Goal,
mutator::{print_mutators, Mutator},
state::LocalState,
localstate::LocalState,
mutator::{apply_mutator, print_mutators, Mutator},
};

use bevy_reflect::Reflect;
Expand Down Expand Up @@ -44,35 +47,22 @@ fn successors<'a>(
) -> impl Iterator<Item = (Node, usize)> + 'a {
let state = node.state();
actions.iter().filter_map(move |action| {
if check_preconditions(state, action) {
let mut new_state = state.clone();
if action.effects.len() == 0 {
return None;
}
for mutator in &action.effects[0].mutators {
match mutator {
Mutator::Set(key, value) => {
new_state.data.insert(key.to_string(), *value);
}
Mutator::Increment(key, value) => {
if let Some(current_value) = new_state.data.get_mut(key) {
*current_value += *value;
}
}
Mutator::Decrement(key, value) => {
if let Some(current_value) = new_state.data.get_mut(key) {
*current_value -= *value;
}
}
}
if check_preconditions(state, action) && !action.effects.is_empty() {
let new_state = state.clone();
let first_effect = &action.effects[0];

let mut new_data = new_state.data.clone();
for mutator in &first_effect.mutators {
apply_mutator(&mut new_data, mutator);
}

let new_effect = Effect {
action: action.effects[0].action.clone(),
mutators: action.effects[0].mutators.clone(),
cost: action.effects[0].cost,
state: new_state,
action: first_effect.action.clone(),
mutators: first_effect.mutators.clone(),
cost: first_effect.cost,
state: LocalState { data: new_data },
};
Some((Node::Effect(new_effect), action.effects[0].cost))
Some((Node::Effect(new_effect), first_effect.cost))
} else {
None
}
Expand All @@ -89,18 +79,6 @@ fn is_goal(node: &Node, goal: &Goal) -> bool {
})
}

/// We implement two different strategies for finding a solution
#[derive(Default)]
pub enum PlanningStrategy {
#[default]
/// StartToGoal begins with our current state, and finds the most optimal path to the goal, based on the costs
/// Might take longer time than GoalToStart, but finds the path with the lowest cost
StartToGoal,
/// GoalToStart begins with the goal state, and works backwards from there, in order to find a path as quick as possible
/// Might lead to less-than-optimial paths, but should find a valid path quicker
GoalToStart,
}

pub fn make_plan_with_strategy(
strategy: PlanningStrategy,
start: &LocalState,
Expand All @@ -123,6 +101,18 @@ pub fn make_plan_with_strategy(
}
}

/// We implement two different strategies for finding a solution
#[derive(Default)]
pub enum PlanningStrategy {
#[default]
/// StartToGoal begins with our current state, and finds the most optimal path to the goal, based on the costs
/// Might take longer time than GoalToStart, but finds the path with the lowest cost
StartToGoal,
/// GoalToStart begins with the goal state, and works backwards from there, in order to find a path as quick as possible
/// Might lead to less-than-optimial paths, but should find a valid path quicker
GoalToStart,
}

pub fn make_plan(
start: &LocalState,
actions: &[Action],
Expand Down
2 changes: 1 addition & 1 deletion crates/dogoap/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pub use crate::compare::Compare;
pub use crate::datum::Datum;
pub use crate::effect::Effect;
pub use crate::goal::Goal;
pub use crate::localstate::LocalState;
pub use crate::mutator::Mutator;
pub use crate::planner::{
get_effects_from_plan, make_plan, make_plan_with_strategy, print_plan, Node, PlanningStrategy,
};
pub use crate::state::LocalState;
Loading

0 comments on commit 083e42b

Please sign in to comment.