summaryrefslogtreecommitdiff
path: root/src/sim/cell
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/cell')
-rw-r--r--src/sim/cell/cell.rs24
-rw-r--r--src/sim/cell/materials/fire.rs1
-rw-r--r--src/sim/cell/materials/gas.rs78
-rw-r--r--src/sim/cell/materials/liquid.rs (renamed from src/sim/cell/materials/water.rs)0
-rw-r--r--src/sim/cell/materials/mod.rs42
-rw-r--r--src/sim/cell/materials/powder.rs (renamed from src/sim/cell/materials/sand.rs)0
-rw-r--r--src/sim/cell/materials/smoke.rs20
7 files changed, 62 insertions, 103 deletions
diff --git a/src/sim/cell/cell.rs b/src/sim/cell/cell.rs
index d567893..edb2402 100644
--- a/src/sim/cell/cell.rs
+++ b/src/sim/cell/cell.rs
@@ -10,6 +10,7 @@ pub struct Cell {
impl Cell {
const FLAG_PARITY: u8 = 0b0000_0001;
const FLAG_RB: u8 = 0b0000_0010;
+ const MASK_SETTLED: u8 = 0b0001_1100;
#[inline]
pub fn parity(self) -> u8 {
@@ -33,6 +34,7 @@ impl Cell {
pub fn rb(self) -> bool {
(self.flags & Self::FLAG_RB) == Self::FLAG_RB
}
+ #[inline]
pub fn set_rb(&mut self, rb: bool) {
if rb {
self.flags |= Self::FLAG_RB
@@ -40,6 +42,28 @@ impl Cell {
self.flags = self.flags & !Self::FLAG_RB
}
}
+
+ #[inline]
+ pub fn settled(self) -> u8 {
+ (self.flags & Self::MASK_SETTLED) >> 2
+ }
+ #[inline]
+ fn set_settled(&mut self, settled: u8) {
+ debug_assert!(settled <= 7);
+ self.flags = (settled << 2) | (self.flags & !Self::MASK_SETTLED);
+ }
+ #[inline]
+ pub fn reset_settled(&mut self) {
+ self.flags &= !Self::MASK_SETTLED;
+ }
+
+ #[inline]
+ pub fn increment_settled(&mut self) {
+ let s = self.settled();
+ if s < 7 {
+ self.set_settled(s + 1);
+ }
+ }
}
impl Cell {
diff --git a/src/sim/cell/materials/fire.rs b/src/sim/cell/materials/fire.rs
index e0416b0..dd1ff8c 100644
--- a/src/sim/cell/materials/fire.rs
+++ b/src/sim/cell/materials/fire.rs
@@ -25,6 +25,7 @@ impl FireCellView for Cell {
}
// TODO optimize number of rng calls?
+// TODO wtf is fire
#[inline]
pub fn sim_update(ctx: &mut UpdateCtx) {
let ticks_lived = ctx.cell.get_ticks_lived();
diff --git a/src/sim/cell/materials/gas.rs b/src/sim/cell/materials/gas.rs
index c0cd9f9..2ee7c00 100644
--- a/src/sim/cell/materials/gas.rs
+++ b/src/sim/cell/materials/gas.rs
@@ -1,76 +1,20 @@
+use rand::RngExt;
+
use crate::sim::cell_sim::sim::UpdateCtx;
#[inline]
pub fn sim_update(ctx: &mut UpdateCtx) {
- // if the water can fall, do so
- if ctx.candidates_swap(&[
- (0, -1),
- (-1 + 2 * ctx.seqno_parity as i32, -1),
- (1 - 2 * ctx.seqno_parity as i32, -1),
- ]) {
+ // only allow upward movement some of the time to limit movement speed
+ if ctx.rng.random_range(0.0..1.0) > 0.8 && ctx.candidates_swap(&[(0, -1)]) {
return;
}
-
- // if the water can't fall, check if we can move left or right
- // these are inverted on parity so that we don't preference a direction
- let left_target = ctx.get_cell(-1, 0);
- let can_move_left =
- left_target.is_some_and(|c| c.material.def().density < ctx.material.density);
- let right_target = ctx.get_cell(1, 0);
- let can_move_right =
- right_target.is_some_and(|c| c.material.def().density < ctx.material.density);
-
- // we can't move down or to other side, so we're stuck
- if !can_move_left && !can_move_right {
+ // same for each horizontal direction
+ if ctx.rng.random_range(0.0..1.0) > 0.8
+ && ctx.candidates_swap(&[(1 - ctx.seqno_parity as i32 * 2, 0)])
+ {
return;
}
-
- // if we can't move left, just move right
- if !can_move_left {
- ctx.candidates_swap(&[(1, 0)]);
- return;
- }
- // and vice versa
- if !can_move_right {
- ctx.candidates_swap(&[(-1, 0)]);
- return;
- }
-
- // find the closest hole within 20 pixels (TODO optimize)
- // a hole is any space below us with a lesser density
- // prevents equidistance stuck state
- let starting_side = if ctx.seqno_parity == 0 { 1 } else { -1 };
- for i in 0..20 {
- let side = if i % 2 == 0 {
- starting_side
- } else {
- -starting_side
- };
-
- let offset = side * (1 + i / 2);
- let hole_target = ctx.get_cell(offset, -1);
- if let Some(target) = hole_target
- && target.material.def().density < ctx.material.density
- {
- // we identified a hole and we know that the space on this side is open
- // move toward the hole
- // new_target.flags = new_target.flags ^ 0b1;
- ctx.candidates_swap(&[(side, 0)]);
- return;
- }
- }
-
- // we didn't find a hole, so just move "randomly" on the same surface
- // TODO when to settle?
- let target_x = if !can_move_left {
- 1
- } else if !can_move_right {
- -1
- } else if ctx.seqno_parity % 2 == 1 {
- 1
- } else {
- -1
- };
-
- ctx.candidates_swap(&[(target_x, 0)]);
+ if ctx.rng.random_range(0.0..1.0) > 0.8
+ && ctx.candidates_swap(&[(-1 + ctx.seqno_parity as i32 * 2, 0)])
+ {}
}
diff --git a/src/sim/cell/materials/water.rs b/src/sim/cell/materials/liquid.rs
index 4b848fb..4b848fb 100644
--- a/src/sim/cell/materials/water.rs
+++ b/src/sim/cell/materials/liquid.rs
diff --git a/src/sim/cell/materials/mod.rs b/src/sim/cell/materials/mod.rs
index 0d19696..9bcf5e4 100644
--- a/src/sim/cell/materials/mod.rs
+++ b/src/sim/cell/materials/mod.rs
@@ -2,9 +2,8 @@ use crate::sim::cell_sim::sim::UpdateCtx;
mod fire;
mod gas;
-mod sand;
-mod smoke;
-mod water;
+mod liquid;
+mod powder;
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -13,71 +12,82 @@ pub enum MaterialId {
Sand,
Wood,
Water,
- Gas,
Fire,
Smoke,
}
+#[repr(u8)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum MaterialForm {
+ Void,
+ Gas,
+ Liquid,
+ Powder,
+ Solid,
+}
+
pub struct MaterialDef {
pub name: &'static str,
pub color: (u8, u8, u8, u8),
pub density: u8,
+ pub form: MaterialForm,
pub sim_update: Option<fn(ctx: &mut UpdateCtx) -> ()>,
}
-static MATERIALS: [MaterialDef; 7] = [
+static MATERIALS: [MaterialDef; 6] = [
MaterialDef {
name: "Void",
color: (0x00, 0x00, 0x00, 0x00),
density: 0,
+ // form usually but not always determines the update fn
+ form: MaterialForm::Void,
sim_update: None,
},
MaterialDef {
name: "Sand",
color: (0xDE, 0xCB, 0x85, 0xFF),
density: 50,
- sim_update: Some(sand::sim_update),
+ form: MaterialForm::Powder,
+ sim_update: Some(powder::sim_update),
},
MaterialDef {
name: "Wood",
color: (0x85, 0x56, 0x1D, 0xFF),
density: 50,
+ form: MaterialForm::Solid,
sim_update: None,
},
MaterialDef {
name: "Water",
color: (0x38, 0xA9, 0xFF, 0xFF),
density: 40,
- sim_update: Some(water::sim_update),
- },
- MaterialDef {
- name: "Gas",
- color: (0xBD, 0xFF, 0xE4, 0xAA),
- density: 10,
- sim_update: Some(gas::sim_update),
+ form: MaterialForm::Liquid,
+ sim_update: Some(liquid::sim_update),
},
+ // TODO this is not a material
MaterialDef {
name: "Fire",
color: (0xFC, 0x66, 0x00, 0xAA),
// for now this matches wood
density: 50,
+ form: MaterialForm::Gas,
sim_update: Some(fire::sim_update),
},
MaterialDef {
name: "Smoke",
color: (0x32, 0x35, 0x36, 0xAA),
density: 15,
- sim_update: Some(smoke::sim_update),
+ form: MaterialForm::Gas,
+ sim_update: Some(gas::sim_update),
},
];
impl MaterialId {
- pub const ALL: [MaterialId; 7] = [
+ pub const ALL: [MaterialId; 6] = [
MaterialId::Void,
MaterialId::Sand,
MaterialId::Wood,
MaterialId::Water,
- MaterialId::Gas,
MaterialId::Fire,
MaterialId::Smoke,
];
diff --git a/src/sim/cell/materials/sand.rs b/src/sim/cell/materials/powder.rs
index d2d1265..d2d1265 100644
--- a/src/sim/cell/materials/sand.rs
+++ b/src/sim/cell/materials/powder.rs
diff --git a/src/sim/cell/materials/smoke.rs b/src/sim/cell/materials/smoke.rs
deleted file mode 100644
index 2ee7c00..0000000
--- a/src/sim/cell/materials/smoke.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use rand::RngExt;
-
-use crate::sim::cell_sim::sim::UpdateCtx;
-
-#[inline]
-pub fn sim_update(ctx: &mut UpdateCtx) {
- // only allow upward movement some of the time to limit movement speed
- if ctx.rng.random_range(0.0..1.0) > 0.8 && ctx.candidates_swap(&[(0, -1)]) {
- return;
- }
- // same for each horizontal direction
- if ctx.rng.random_range(0.0..1.0) > 0.8
- && ctx.candidates_swap(&[(1 - ctx.seqno_parity as i32 * 2, 0)])
- {
- return;
- }
- if ctx.rng.random_range(0.0..1.0) > 0.8
- && ctx.candidates_swap(&[(-1 + ctx.seqno_parity as i32 * 2, 0)])
- {}
-}