Skip to content

Commit

Permalink
simulation docs
Browse files Browse the repository at this point in the history
  • Loading branch information
twof committed Dec 9, 2024
1 parent 90e0ad2 commit 869bf46
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 11 deletions.
3 changes: 2 additions & 1 deletion frontend/app/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,8 @@ impl Game {
.collect();
let rand_seed = rand::thread_rng().gen();

// If replaying, reuse last seed instead of using a newly generated seed
// If replaying, reuse previous seed if it exists
// instead of using a newly generated seed
let seed = match execution_mode {
ExecutionMode::Initial | ExecutionMode::Run => {
self.configured_seed(context).unwrap_or(rand_seed)
Expand Down
1 change: 1 addition & 0 deletions frontend/simulation_worker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl yew_agent::Worker for SimAgent {
nonce,
} => {
self.sim = Some(Simulation::new(&scenario_name, seed, &codes));
// Snapshot of the starting state of the simulation
let snapshot = self.sim().snapshot(nonce);
self.errored = !snapshot.errors.is_empty();
self.link.respond(who, Response::Snapshot { snapshot });
Expand Down
19 changes: 10 additions & 9 deletions shared/simulator/src/bullet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,24 @@ pub fn destroy(sim: &mut Simulation, handle: BulletHandle) {
);
}

/// Process movement and collisions for each bullet in the simulation
pub fn tick(sim: &mut Simulation) {
let dt = PHYSICS_TICK_LENGTH;
let (indices_by_team, coarse_grids_by_team) = build_indices(sim, dt);
let mut stack = Vec::new();
let shape = rapier2d_f64::geometry::Ball { radius: 1.0 };
let bullets: Vec<BulletHandle> = sim.bullets.iter().cloned().collect();
for handle in bullets {
let team = {
let data = data_mut(sim, handle);
data.ttl -= dt as f32;
if data.ttl <= 0.0 {
destroy(sim, handle);
continue;
}
data.team
};
let data = data_mut(sim, handle);

// If a bullet's lifetime has been exceeded, destroy it and move on to the next bullet
data.ttl -= dt as f32;
if data.ttl <= 0.0 {
destroy(sim, handle);
continue;
}

let team = data.team;
let has_collider;
let coarse_grid_hit;
let mut needs_collider = false;
Expand Down
1 change: 1 addition & 0 deletions shared/simulator/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Line {
pub color: Vector4<f32>,
}

/// Display gun orientation, acceleration vector, and radar radius for each ship
pub fn emit_ship(sim: &mut Simulation, handle: ShipHandle) {
let mut lines = Vec::with_capacity(2 + sim.ship(handle).data().guns.len());
let body = sim.ship(handle).body();
Expand Down
8 changes: 8 additions & 0 deletions shared/simulator/src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ impl Simulation {
let mut scenario = scenario::load(scenario_name);

log::debug!("seed {seed}");

// Create channel to communicate collision events
let (contact_send, contact_recv) = crossbeam::channel::unbounded();
let mut sim = Box::new(Simulation {
scenario: None,
Expand Down Expand Up @@ -112,6 +114,7 @@ impl Simulation {

collision::add_walls(&mut sim);

// Configure the simulation according to the scenario
scenario.init(&mut sim, seed);
sim.scenario = Some(scenario);

Expand Down Expand Up @@ -216,6 +219,7 @@ impl Simulation {
.collect();
teams.sort_by_key(|(k, _)| *k);

// Run ship tick functions for each ship in each team
for (_, team_controller) in teams.iter() {
team_controller.borrow_mut().tick(self);
}
Expand Down Expand Up @@ -321,6 +325,9 @@ impl Simulation {
s.finish()
}

/// Generate a snapshot based on the current state of the simulation
///
/// Collects the statuses of bullets and ships
pub fn snapshot(&self, nonce: u32) -> Snapshot {
let mut snapshot = Snapshot {
nonce,
Expand Down Expand Up @@ -382,6 +389,7 @@ impl Simulation {
self.team_controllers.get_mut(&team).map(|x| x.clone())
}

/// Provide's every ship in the team with environment information
pub fn update_environment(&mut self, team: i32, mut environment: BTreeMap<String, String>) {
environment.insert(
"SCENARIO_NAME".to_string(),
Expand Down
1 change: 1 addition & 0 deletions shared/simulator/src/vm/limiter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Based on https://github.com/scrtlabs/SecretNetwork/blob/621d3899babc4741ef1ba596152c097677d246db/cosmwasm/enclaves/shared/contract-engine/src/wasm3/gas.rs
use walrus::{ir::*, FunctionBuilder, GlobalId, InitExpr, LocalFunction, ValType};

/// Alters wasm to insert gas functions
pub fn rewrite(wasm: &[u8]) -> Result<Vec<u8>, super::Error> {
let mut module = match walrus::Module::from_buffer(wasm) {
Ok(m) => m,
Expand Down
25 changes: 24 additions & 1 deletion shared/simulator/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ impl TeamController {
}

fn tick_ship(&mut self, sim: &mut Simulation, handle: ShipHandle) -> Result<(), Error> {
// If ship code crashed
if let Some(msg) = sim.ship(handle).data().crash_message.as_ref() {
sim.emit_debug_text(handle, format!("Crashed: {}", msg.clone()));
let mut rng = new_rng(sim.tick());
Expand All @@ -195,6 +196,8 @@ impl TeamController {
let v =
sim.ship(handle).body().linvel() + rot.transform_vector(&vector![speed, 0.0]);
let offset = v * rng.gen_range(0.0..PHYSICS_TICK_LENGTH);

// Display ship exploding animation
sim.events.particles.push(Particle {
position: p + offset,
velocity: v,
Expand Down Expand Up @@ -229,7 +232,7 @@ impl TeamController {
slice.write_slice(&state.state).expect("system state write");
}

// Run user's ship tick
// Run user's ship tick function
let result = vm.tick_ship.call(vm.store_mut().deref_mut(), &[]);
if let Err(e) = result {
// If gas has run out, throw an error
Expand All @@ -252,6 +255,8 @@ impl TeamController {
) {
let null_pos = vec.iter().position(|&x| x == 0).unwrap_or(vec.len());
let msg = String::from_utf8_lossy(&vec[0..null_pos]).to_string();

// Assume gas error if error message is missing
if msg.is_empty() {
return Err(Error {
msg: "Ship exceeded maximum number of instructions".to_string(),
Expand All @@ -273,13 +278,15 @@ impl TeamController {
);
}

// Read shared memory after ship tick, and apply and actions to the simulation
{
let store = vm.store();
let memory_view = vm.memory.view(store.deref());
let ptr = ship_controller.system_state_ptr;
let slice = ptr
.slice(&memory_view, SystemState::Size as u32)
.expect("system state read");

slice
.read_slice(&mut state.state)
.expect("system state read");
Expand Down Expand Up @@ -337,6 +344,7 @@ impl TeamController {
Ok(())
}

/// Writes `environment` to each ship's memory
pub fn update_environment(&mut self, environment: &Environment) -> Result<(), Error> {
self.environment = environment.clone();
for (_, ship_controller) in self.ship_controllers.iter_mut() {
Expand Down Expand Up @@ -371,6 +379,8 @@ impl WasmVm {
let module = match code {
Code::Wasm(wasm) => {
let wasm = wasm_submemory::rewrite(wasm, SUBMEMORY_SIZE)?;

// Add gas tracking and functions
let wasm = limiter::rewrite(&wasm)?;
translate_error(Module::new(&store, wasm))?
}
Expand Down Expand Up @@ -461,6 +471,9 @@ impl WasmVm {
Some(src_slice.to_vec())
}

/// Write environment as a string to the VM's memory
///
/// Throws error if environment size exceeds `MAX_ENVIRONMENT_SIZE`
fn update_environment(&self, ptr: WasmPtr<u8>, environment: &Environment) -> Result<(), Error> {
let environment_string = environment
.iter()
Expand Down Expand Up @@ -550,6 +563,7 @@ impl LocalSystemState {
}
}

/// Set ship memory based on the state of the ship in the simulator
fn generate_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut LocalSystemState) {
state.set(
SystemState::Class,
Expand Down Expand Up @@ -657,17 +671,22 @@ fn generate_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut L
}
}

/// Draws ship state from memory, applies it to the simulator,
/// and then resets memory to default values
fn apply_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut LocalSystemState) {
// Set ship acceleration
sim.ship_mut(handle).accelerate(Vec2::new(
state.get(SystemState::AccelerateX),
state.get(SystemState::AccelerateY),
));
state.set(SystemState::AccelerateX, 0.0);
state.set(SystemState::AccelerateY, 0.0);

// Set torque
sim.ship_mut(handle).torque(state.get(SystemState::Torque));
state.set(SystemState::Torque, 0.0);

// Fire guns
for (i, (aim, fire)) in [
(SystemState::Aim0, SystemState::Fire0),
(SystemState::Aim1, SystemState::Fire1),
Expand All @@ -684,6 +703,7 @@ fn apply_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut Loca
}
}

// Set radar positions
for (idx, radar) in sim
.ship_mut(handle)
.data_mut()
Expand All @@ -699,6 +719,7 @@ fn apply_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut Loca
radar.set_ecm_mode(translate_ecm_mode(state.get(idxs.ecm_mode)));
}

// Activate abilities
let active_abilities = ActiveAbilities(state.get_u64(SystemState::ActivateAbility));
for &ability in oort_api::ABILITIES {
let current = sim.ship(handle).is_ability_active(ability);
Expand All @@ -712,11 +733,13 @@ fn apply_system_state(sim: &mut Simulation, handle: ShipHandle, state: &mut Loca
}
}

// Explode
if state.get(SystemState::Explode) > 0.0 {
sim.ship_mut(handle).explode();
state.set(SystemState::Explode, 0.0);
}

// Set radio channels and send messages
for (i, radio) in sim
.ship_mut(handle)
.data_mut()
Expand Down

0 comments on commit 869bf46

Please sign in to comment.