the huge refactor
This commit is contained in:
+30
-28
@@ -5,13 +5,14 @@
|
||||
//! give boards some non-distracting visual flavor (textured ground) with little
|
||||
//! authoring effort, including randomly-generated "grass" / "dirt" / "stone".
|
||||
//!
|
||||
//! The actual placement / per-cell expansion happens in [`crate::layer`] during
|
||||
//! The actual placement / per-cell expansion happens in [`crate::board_spec`] during
|
||||
//! map load: a floor palette entry either names one of these generators (a fresh
|
||||
//! glyph is rolled per grid cell) or gives a fixed glyph. This module only owns
|
||||
//! the generators themselves.
|
||||
|
||||
use crate::glyph::Glyph;
|
||||
use color::Rgba8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tinyrand::{Probability, Rand, Seeded, StdRand};
|
||||
|
||||
/// A board's floor: the cosmetic backdrop drawn beneath everything, replacing the
|
||||
@@ -21,7 +22,7 @@ use tinyrand::{Probability, Rand, Seeded, StdRand};
|
||||
///
|
||||
/// Three forms: [`Blank`](Floor::Blank) (the canonical empty/black cell shows
|
||||
/// through), [`Fixed`](Floor::Fixed) (one glyph tiled across the whole board), or
|
||||
/// [`Biome`](Floor::Biome) (a procedural [`FloorGenerator`] texture). A biome keeps
|
||||
/// [`Biome`](Floor::Biome) (a procedural [`FloorBiome`] texture). A biome keeps
|
||||
/// its generator (so save re-emits the generator name) alongside a per-cell glyph
|
||||
/// buffer pre-rolled once at load from [`FLOOR_SEED`] — deterministic, and the
|
||||
/// direct replacement for the old per-cell floor-layer rolling.
|
||||
@@ -35,7 +36,7 @@ pub enum Floor {
|
||||
/// `glyphs` buffer holding one pre-rolled glyph per cell (row-major).
|
||||
Biome {
|
||||
/// The generator this biome was built from; re-emitted on save.
|
||||
generator: FloorGenerator,
|
||||
generator: FloorBiome,
|
||||
/// One pre-rolled glyph per cell (`width * height`, row-major).
|
||||
glyphs: Vec<Glyph>,
|
||||
},
|
||||
@@ -52,7 +53,7 @@ impl Floor {
|
||||
/// Builds a [`Floor::Biome`] for a `width × height` board, pre-rolling one glyph
|
||||
/// per cell from a [`FLOOR_SEED`]-seeded PRNG (so the result is deterministic and
|
||||
/// depends only on the board dimensions + generator).
|
||||
pub(crate) fn biome(generator: FloorGenerator, width: usize, height: usize) -> Floor {
|
||||
pub(crate) fn biome(generator: FloorBiome, width: usize, height: usize) -> Floor {
|
||||
let mut rng = StdRand::seed(FLOOR_SEED);
|
||||
let glyphs = (0..width * height).map(|_| generator.generate(&mut rng)).collect();
|
||||
Floor::Biome { generator, glyphs }
|
||||
@@ -80,8 +81,9 @@ pub(crate) const FLOOR_SEED: u64 = 0x_C0FF_EE15_F100_0001;
|
||||
/// and the probability/character set of its scattered "texture" glyphs; the
|
||||
/// colors are deliberately dark and low-saturation so foreground objects stay
|
||||
/// readable against them.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FloorGenerator {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum FloorBiome {
|
||||
/// Random green-to-greenish-yellow ground with a fairly high chance of grassy
|
||||
/// characters (comma, period, backquote, apostrophe).
|
||||
Grass,
|
||||
@@ -91,24 +93,24 @@ pub enum FloorGenerator {
|
||||
Stone,
|
||||
}
|
||||
|
||||
impl FloorGenerator {
|
||||
impl FloorBiome {
|
||||
/// Parses a generator from its map-file name, or `None` if unrecognized.
|
||||
pub fn from_name(name: &str) -> Option<FloorGenerator> {
|
||||
pub fn from_name(name: &str) -> Option<FloorBiome> {
|
||||
match name {
|
||||
"grass" => Some(FloorGenerator::Grass),
|
||||
"dirt" => Some(FloorGenerator::Dirt),
|
||||
"stone" => Some(FloorGenerator::Stone),
|
||||
"grass" => Some(FloorBiome::Grass),
|
||||
"dirt" => Some(FloorBiome::Dirt),
|
||||
"stone" => Some(FloorBiome::Stone),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The generator's map-file name (inverse of [`from_name`](FloorGenerator::from_name)),
|
||||
/// The generator's map-file name (inverse of [`from_name`](FloorBiome::from_name)),
|
||||
/// re-emitted on save so a biome floor round-trips.
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
FloorGenerator::Grass => "grass",
|
||||
FloorGenerator::Dirt => "dirt",
|
||||
FloorGenerator::Stone => "stone",
|
||||
FloorBiome::Grass => "grass",
|
||||
FloorBiome::Dirt => "dirt",
|
||||
FloorBiome::Stone => "stone",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ impl FloorGenerator {
|
||||
// (background color ranges, texture probability, texture chars).
|
||||
let (bg, chars, prob) = match self {
|
||||
// Green → greenish-yellow: g dominant, a touch of r for the yellow tilt.
|
||||
FloorGenerator::Grass => (
|
||||
FloorBiome::Grass => (
|
||||
Rgba8 {
|
||||
r: shade(rng, 20, 55),
|
||||
g: shade(rng, 45, 85),
|
||||
@@ -132,7 +134,7 @@ impl FloorGenerator {
|
||||
0.35,
|
||||
),
|
||||
// Brown: r highest, g mid, b low.
|
||||
FloorGenerator::Dirt => (
|
||||
FloorBiome::Dirt => (
|
||||
Rgba8 {
|
||||
r: shade(rng, 45, 75),
|
||||
g: shade(rng, 30, 50),
|
||||
@@ -143,7 +145,7 @@ impl FloorGenerator {
|
||||
0.20,
|
||||
),
|
||||
// Gray: all channels share one shade.
|
||||
FloorGenerator::Stone => {
|
||||
FloorBiome::Stone => {
|
||||
let v = shade(rng, 40, 70);
|
||||
(
|
||||
Rgba8 {
|
||||
@@ -199,7 +201,7 @@ mod tests {
|
||||
|
||||
/// Rolls `count` glyphs from `generator` against a freshly-seeded RNG, the
|
||||
/// same way the layer builder does.
|
||||
fn roll(generator: FloorGenerator, count: usize) -> Vec<Glyph> {
|
||||
fn roll(generator: FloorBiome, count: usize) -> Vec<Glyph> {
|
||||
let mut rng = StdRand::seed(FLOOR_SEED);
|
||||
(0..count).map(|_| generator.generate(&mut rng)).collect()
|
||||
}
|
||||
@@ -207,24 +209,24 @@ mod tests {
|
||||
#[test]
|
||||
fn from_name_parses_known_generators() {
|
||||
assert_eq!(
|
||||
FloorGenerator::from_name("grass"),
|
||||
Some(FloorGenerator::Grass)
|
||||
FloorBiome::from_name("grass"),
|
||||
Some(FloorBiome::Grass)
|
||||
);
|
||||
assert_eq!(
|
||||
FloorGenerator::from_name("dirt"),
|
||||
Some(FloorGenerator::Dirt)
|
||||
FloorBiome::from_name("dirt"),
|
||||
Some(FloorBiome::Dirt)
|
||||
);
|
||||
assert_eq!(
|
||||
FloorGenerator::from_name("stone"),
|
||||
Some(FloorGenerator::Stone)
|
||||
FloorBiome::from_name("stone"),
|
||||
Some(FloorBiome::Stone)
|
||||
);
|
||||
assert_eq!(FloorGenerator::from_name("lava"), None);
|
||||
assert_eq!(FloorBiome::from_name("lava"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grass_generator_stays_in_scheme_and_is_deterministic() {
|
||||
let a = roll(FloorGenerator::Grass, 64);
|
||||
let b = roll(FloorGenerator::Grass, 64);
|
||||
let a = roll(FloorBiome::Grass, 64);
|
||||
let b = roll(FloorBiome::Grass, 64);
|
||||
assert_eq!(a.len(), 64);
|
||||
// Same seed → identical rolls across builds.
|
||||
assert!(a.iter().zip(&b).all(|(x, y)| x == y));
|
||||
|
||||
Reference in New Issue
Block a user