use std::sync::{Arc, Mutex};
use bevy::prelude::*;
use crossbeam_channel::*;
use crate::AIGymSettings;
#[derive(Resource)]
pub struct AIGymStateInner<
A: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
B: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
> {
pub render_image_handles: Vec<Handle<Image>>,
pub(crate) step_request_tx: Sender<Vec<Option<String>>>,
pub(crate) step_request_rx: Receiver<Vec<Option<String>>>,
pub(crate) reset_request_tx: Sender<bool>,
pub(crate) reset_request_rx: Receiver<bool>,
pub(crate) step_result_tx: Sender<Vec<bool>>,
pub(crate) step_result_rx: Receiver<Vec<bool>>,
pub(crate) reset_result_tx: Sender<bool>,
pub(crate) reset_result_rx: Receiver<bool>,
pub(crate) environment_state: Option<B>,
pub settings: AIGymSettings,
pub visual_observations: Vec<image::RgbaImage>,
pub rewards: Vec<f32>,
pub actions: Vec<Option<A>>,
pub terminations: Vec<bool>,
}
impl<
A: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
B: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
> AIGymStateInner<A, B>
{
pub fn new(settings: AIGymSettings) -> Self {
let (step_tx, step_rx) = bounded(1);
let (reset_tx, reset_rx) = bounded(1);
let (result_tx, result_rx) = bounded(1);
let (result_reset_tx, result_reset_rx) = bounded(1);
Self {
step_request_tx: step_tx,
step_request_rx: step_rx,
step_result_tx: result_tx,
step_result_rx: result_rx,
reset_request_tx: reset_tx,
reset_request_rx: reset_rx,
reset_result_tx: result_reset_tx,
reset_result_rx: result_reset_rx,
environment_state: None,
render_image_handles: Vec::new(),
visual_observations: Vec::new(),
rewards: vec![0.0; settings.num_agents as usize],
actions: vec![None; settings.num_agents as usize],
terminations: vec![false; settings.num_agents as usize],
settings,
}
}
pub fn send_step_result(&self, results: Vec<bool>) {
if self.step_result_tx.is_empty() {
self.step_result_tx.send(results).unwrap();
}
}
pub fn send_reset_result(&self, result: bool) {
if self.reset_result_tx.is_empty() {
self.reset_result_tx.send(result).unwrap();
}
}
pub fn receive_action_strings(&self) -> Vec<Option<String>> {
self.step_request_rx.recv().unwrap()
}
pub fn receive_reset_request(&self) {
self.reset_request_rx.recv().unwrap();
}
pub fn is_next_action(&self) -> bool {
!self.step_request_rx.is_empty()
}
pub fn is_reset_request(&self) -> bool {
!self.reset_request_rx.is_empty()
}
pub fn set_reward(&mut self, agent_index: usize, score: f32) {
self.rewards[agent_index] = score;
}
pub fn set_terminated(&mut self, agent_index: usize, result: bool) {
self.terminations[agent_index] = result;
}
pub fn reset(&mut self) {
for i in 0..self.terminations.len() {
self.set_terminated(i, false);
self.set_reward(i, 0.0);
}
self.send_reset_result(true);
}
pub fn set_env_state(&mut self, state: B) {
self.environment_state = Some(state);
}
}
#[derive(Resource, Deref, DerefMut, Clone)]
pub struct AIGymState<
A: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
B: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
>(pub Arc<Mutex<AIGymStateInner<A, B>>>);
impl<
A: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
B: 'static + Send + Sync + Clone + std::panic::RefUnwindSafe,
> AIGymState<A, B>
{
pub fn new(settings: AIGymSettings) -> Self {
Self(Arc::new(Mutex::new(AIGymStateInner::new(settings))))
}
}