use crate::status::Status::*;
use crate::tracer::{first_child_id, next_sibling_id, NodeMeta, Tracer};
use crate::Float;
use crate::{event::UpdateEvent, state::State, ActionArgs, Behavior, Status, RUNNING};
pub struct SequenceArgs<'a, A, E, F, B, T> {
pub select: bool,
pub upd: Option<Float>,
pub seq: &'a [Behavior<A>],
pub i: &'a mut usize,
pub cursor: &'a mut Box<State<A>>,
pub e: &'a E,
pub blackboard: &'a mut B,
pub f: &'a mut F,
pub parent_id: usize,
pub metas: &'a [NodeMeta],
pub tracer: &'a mut T,
}
pub fn sequence<A, E, F, B, T>(args: SequenceArgs<A, E, F, B, T>) -> (Status, Float)
where
A: Clone,
E: UpdateEvent,
F: FnMut(ActionArgs<E, A>, &mut B) -> (Status, Float),
T: Tracer,
{
let SequenceArgs {
select,
upd,
seq,
i,
cursor,
e,
blackboard,
f,
parent_id,
metas,
tracer,
} = args;
let (status, inv_status) = if select {
(Status::Failure, Status::Success)
} else {
(Status::Success, Status::Failure)
};
let mut child_id = first_child_id::<T>(parent_id);
if T::IS_RECORDING {
for _ in 0..*i {
child_id = next_sibling_id::<T>(metas, child_id);
}
}
let mut remaining_dt = upd.unwrap_or(0.0);
let mut remaining_e;
while *i < seq.len() {
match cursor.tick(
child_id,
metas,
match upd {
Some(_) => {
remaining_e = UpdateEvent::from_dt(remaining_dt, e).unwrap();
&remaining_e
}
_ => e,
},
blackboard,
f,
tracer,
) {
(Running, _) => {
break;
}
(s, new_dt) if s == inv_status => {
return (inv_status, new_dt);
}
(s, new_dt) if s == status => {
remaining_dt = match upd {
Some(_) => new_dt,
_ => {
if *i == seq.len() - 1 {
return (status, new_dt);
} else {
*i += 1;
**cursor = State::new(seq[*i].clone());
return RUNNING;
}
}
}
}
_ => unreachable!(),
};
*i += 1;
if T::IS_RECORDING {
child_id = next_sibling_id::<T>(metas, child_id);
}
if *i >= seq.len() {
return (status, remaining_dt);
}
**cursor = State::new(seq[*i].clone());
}
RUNNING
}
pub struct MemorylessSequenceArgs<'a, A, E, F, B, T> {
pub select: bool,
pub upd: Option<Float>,
pub seq: &'a [Behavior<A>],
pub cursor: &'a mut Box<State<A>>,
pub e: &'a E,
pub blackboard: &'a mut B,
pub f: &'a mut F,
pub parent_id: usize,
pub metas: &'a [NodeMeta],
pub tracer: &'a mut T,
}
#[inline]
pub fn memoryless_sequence<A, E, F, B, T>(args: MemorylessSequenceArgs<A, E, F, B, T>) -> (Status, Float)
where
A: Clone,
E: UpdateEvent,
F: FnMut(ActionArgs<E, A>, &mut B) -> (Status, Float),
T: Tracer,
{
let MemorylessSequenceArgs {
select,
upd,
seq,
cursor,
e,
blackboard,
f,
parent_id,
metas,
tracer,
} = args;
let initial_dt = upd.unwrap_or(0.0);
if seq.is_empty() {
return if select {
(Status::Failure, initial_dt)
} else {
(Status::Success, initial_dt)
};
}
let (terminal_status, short_circuit_status) = if select {
(Status::Failure, Status::Success)
} else {
(Status::Success, Status::Failure)
};
let mut child_id = first_child_id::<T>(parent_id);
let mut remaining_dt = initial_dt;
let mut remaining_e;
for child in seq {
**cursor = State::new(child.clone());
let ev = match upd {
Some(_) => {
remaining_e = UpdateEvent::from_dt(remaining_dt, e).unwrap();
&remaining_e
}
None => e,
};
match cursor.tick(child_id, metas, ev, blackboard, f, tracer) {
(Running, _) => return RUNNING,
(s, dt) if s == short_circuit_status => return (s, dt),
(s, dt) if s == terminal_status => {
if upd.is_some() {
remaining_dt = dt;
}
}
_ => unreachable!(),
}
if T::IS_RECORDING {
child_id = next_sibling_id::<T>(metas, child_id);
}
}
(terminal_status, remaining_dt)
}