use serde::{Deserialize, Serialize};
pub const ZONE_COUNT: usize = 41;
pub const ZONE_ATOM_OFFSET: usize = 23;
pub const SHELL_SIZES: [usize; 4] = [1, 6, 12, 22];
pub const SHELL_BASE_RESONANCE: [f32; 4] = [1.0, 0.8, 0.5, 0.2];
pub const SHELL_STABILITY_SCALE: [f32; 4] = [1.0, 0.9, 0.6, 0.3];
pub const SHELL_RADII: [f32; 4] = [0.0, 8.0, 18.0, 30.0];
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct WorldAtom {
pub zone_id: u8,
pub shell: u8,
pub topology: u8,
pub active_ops: u64,
pub resonance: f32,
pub stability: f32,
pub owner_hash: u32,
pub angle: f32,
}
impl Default for WorldAtom {
fn default() -> Self {
Self {
zone_id: 0,
shell: 0,
topology: 0,
active_ops: 0,
resonance: 0.0,
stability: 0.0,
owner_hash: 0,
angle: 0.0,
}
}
}
pub struct WorldGrid {
pub zones: [WorldAtom; ZONE_COUNT],
}
impl WorldGrid {
pub fn new() -> Self {
let mut zones = [WorldAtom::default(); ZONE_COUNT];
let mut zone_id: u8 = 0;
for (shell, &count) in SHELL_SIZES.iter().enumerate() {
let shell_u8 = shell as u8;
for i in 0..count {
let angle = if count > 1 {
2.0 * std::f32::consts::PI * (i as f32) / (count as f32)
} else {
0.0
};
zones[zone_id as usize] = WorldAtom {
zone_id,
shell: shell_u8,
topology: (i % 6) as u8,
active_ops: 0,
resonance: SHELL_BASE_RESONANCE[shell],
stability: SHELL_STABILITY_SCALE[shell],
owner_hash: 0,
angle,
};
zone_id += 1;
}
}
Self { zones }
}
pub fn apply_op(&mut self, zone_id: u32, op_id: u32) -> bool {
if zone_id as usize >= ZONE_COUNT || op_id >= 55 {
return false;
}
let zone = &mut self.zones[zone_id as usize];
let mask = 1u64 << op_id;
let was_new = zone.active_ops & mask == 0;
zone.active_ops |= mask;
was_new
}
pub fn has_op(&self, zone_id: u32, op_id: u32) -> bool {
if zone_id as usize >= ZONE_COUNT || op_id >= 55 {
return false;
}
self.zones[zone_id as usize].active_ops & (1u64 << op_id) != 0
}
pub fn op_count(&self, zone_id: u32) -> u32 {
if zone_id as usize >= ZONE_COUNT {
return 0;
}
self.zones[zone_id as usize].active_ops.count_ones()
}
pub fn active_ops(&self, zone_id: u32) -> Vec<u32> {
if zone_id as usize >= ZONE_COUNT {
return vec![];
}
let bits = self.zones[zone_id as usize].active_ops;
(0..55).filter(|&i| bits & (1u64 << i) != 0).collect()
}
pub fn update_stability(&mut self, substrate_r: f32) {
for zone in &mut self.zones {
let shell = zone.shell as usize;
if shell < 4 {
zone.stability = substrate_r * SHELL_STABILITY_SCALE[shell];
zone.resonance = SHELL_BASE_RESONANCE[shell] * (0.5 + substrate_r * 0.5);
}
}
}
pub fn apply_shockwave(&mut self, bass_peak: f32) {
if bass_peak < 0.3 {
return;
}
for zone in &mut self.zones {
let shell = zone.shell as usize;
if shell < 4 {
let intensity = bass_peak * (1.0 - shell as f32 * 0.2);
zone.resonance = (zone.resonance + intensity * 0.3).min(1.0);
}
}
}
pub fn tick(&mut self, dt: f32) {
let decay = (-dt * 2.0).exp(); for zone in &mut self.zones {
let shell = zone.shell as usize;
if shell < 4 {
let base = SHELL_BASE_RESONANCE[shell];
zone.resonance = base + (zone.resonance - base) * decay;
}
}
}
pub fn witness_flat(&self) -> Vec<f32> {
let mut out = Vec::with_capacity(ZONE_COUNT * 4);
for zone in &self.zones {
out.push(zone.resonance);
out.push(zone.stability);
out.push(zone.active_ops.count_ones() as f32 / 55.0); out.push(zone.topology as f32);
}
out
}
pub fn zone_shell(zone_id: u32) -> u8 {
if zone_id == 0 { return 0; }
if zone_id <= 6 { return 1; }
if zone_id <= 18 { return 2; }
if zone_id <= 40 { return 3; }
3 }
}
impl Default for WorldGrid {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_world_creation() {
let world = WorldGrid::new();
assert_eq!(world.zones.len(), ZONE_COUNT);
assert_eq!(world.zones[0].shell, 0); assert_eq!(world.zones[1].shell, 1); assert_eq!(world.zones[7].shell, 2); assert_eq!(world.zones[19].shell, 3); }
#[test]
fn test_apply_op() {
let mut world = WorldGrid::new();
assert!(world.apply_op(0, 5)); assert!(!world.apply_op(0, 5)); assert!(world.has_op(0, 5));
assert!(!world.has_op(0, 6));
assert_eq!(world.op_count(0), 1);
}
#[test]
fn test_apply_op_bounds() {
let mut world = WorldGrid::new();
assert!(!world.apply_op(50, 0)); assert!(!world.apply_op(0, 55)); assert!(!world.apply_op(0, 60)); }
#[test]
fn test_active_ops() {
let mut world = WorldGrid::new();
world.apply_op(5, 0);
world.apply_op(5, 10);
world.apply_op(5, 54);
let ops = world.active_ops(5);
assert_eq!(ops, vec![0, 10, 54]);
}
#[test]
fn test_update_stability() {
let mut world = WorldGrid::new();
world.update_stability(0.5);
assert!((world.zones[0].stability - 0.5).abs() < 1e-6); assert!((world.zones[1].stability - 0.45).abs() < 1e-6); }
#[test]
fn test_shockwave() {
let mut world = WorldGrid::new();
let zone_idx = 19; let pre_res = world.zones[zone_idx].resonance;
world.apply_shockwave(0.8);
assert!(world.zones[zone_idx].resonance > pre_res,
"resonance {} should exceed pre {}", world.zones[zone_idx].resonance, pre_res);
}
#[test]
fn test_shockwave_below_threshold() {
let mut world = WorldGrid::new();
let pre_res = world.zones[0].resonance;
world.apply_shockwave(0.2); assert_eq!(world.zones[0].resonance, pre_res);
}
#[test]
fn test_tick_decay() {
let mut world = WorldGrid::new();
world.zones[1].resonance = 1.0; world.tick(1.0); assert!(world.zones[1].resonance < 1.0); assert!(world.zones[1].resonance > 0.8); }
#[test]
fn test_witness_flat() {
let world = WorldGrid::new();
let flat = world.witness_flat();
assert_eq!(flat.len(), ZONE_COUNT * 4);
}
#[test]
fn test_zone_shell() {
assert_eq!(WorldGrid::zone_shell(0), 0);
assert_eq!(WorldGrid::zone_shell(1), 1);
assert_eq!(WorldGrid::zone_shell(6), 1);
assert_eq!(WorldGrid::zone_shell(7), 2);
assert_eq!(WorldGrid::zone_shell(18), 2);
assert_eq!(WorldGrid::zone_shell(19), 3);
assert_eq!(WorldGrid::zone_shell(40), 3);
}
}