config structs

This commit is contained in:
2025-04-14 15:32:48 +03:00
parent afb60c956f
commit e70a38b919
+169
View File
@@ -0,0 +1,169 @@
use std::collections::HashMap;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SymmetryType {
Rotational180,
Rotational90,
Diagonal,
Mirror,
None,
}
impl Default for SymmetryType {
fn default() -> Self {
Self::Rotational180
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DifficultyPreset {
Glyph,
Rune,
Scroll,
Codex,
Grimoire,
}
impl DifficultyPreset {
pub fn grid_size(&self) -> usize {
match self {
Self::Glyph => 5,
Self::Rune => 5,
Self::Scroll => 9,
Self::Codex => 15,
Self::Grimoire => 21,
}
}
pub fn black_cell_density(&self) -> f64 {
match self {
Self::Glyph => 0.40,
Self::Rune => 0.35,
Self::Scroll => 0.28,
Self::Codex => 0.20,
Self::Grimoire => 0.18,
}
}
pub fn frequency_threshold(&self) -> f64 {
match self {
Self::Glyph => 0.5,
Self::Rune => 0.1,
Self::Scroll => 0.0,
Self::Codex => 0.0,
Self::Grimoire => 0.0,
}
}
pub fn difficulty_level(&self) -> u8 {
match self {
Self::Glyph => 0,
Self::Rune => 1,
Self::Scroll => 2,
Self::Codex => 3,
Self::Grimoire => 3,
}
}
pub fn obscurity_budget(&self) -> f64 {
match self {
Self::Glyph => 0.0,
Self::Rune => 0.0,
Self::Scroll => 0.05,
Self::Codex => 0.20,
Self::Grimoire => 0.20,
}
}
pub fn rand_top_base(&self) -> usize {
match self {
Self::Glyph => 20,
Self::Rune => 20,
Self::Scroll => 15,
Self::Codex => 10,
Self::Grimoire => 8,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenerationConfig {
pub width: usize,
pub height: usize,
pub symmetry: SymmetryType,
pub black_cell_density: f64,
pub min_word_length: usize,
pub frequency_threshold: f64,
pub obscurity_budget: f64,
pub max_backtrack: usize,
pub max_restarts: usize,
pub timeout_seconds: u64,
pub seed: Option<u64>,
pub cryptic_grid: bool,
pub rand_top_base: usize,
#[serde(skip)]
pub cancelled: Option<Arc<AtomicBool>>,
/// Per-word staleness penalties (0.0 = max penalty, 1.0 = no penalty).
/// Applied during solver scoring to deprioritize recently used words.
#[serde(skip)]
pub staleness: Option<Arc<HashMap<String, f64>>>,
}
impl Default for GenerationConfig {
fn default() -> Self {
Self {
width: 15,
height: 15,
symmetry: SymmetryType::default(),
black_cell_density: 0.22,
min_word_length: 3,
frequency_threshold: 0.0,
obscurity_budget: 0.20,
max_backtrack: 5000,
max_restarts: 10,
timeout_seconds: 90,
seed: None,
cryptic_grid: false,
rand_top_base: 10,
cancelled: None,
staleness: None,
}
}
}
impl GenerationConfig {
pub fn rand_top_for_size(size: usize) -> usize {
match size {
0..=5 => 20,
6..=9 => 15,
10..=14 => 10,
_ => 8,
}
}
pub fn from_preset(preset: DifficultyPreset) -> Self {
let size = preset.grid_size();
let (bt, restarts) = match preset {
DifficultyPreset::Codex => (200000, 40),
DifficultyPreset::Grimoire => (500000, 60),
_ => (5000, 10),
};
Self {
width: size,
height: size,
black_cell_density: preset.black_cell_density(),
frequency_threshold: preset.frequency_threshold(),
obscurity_budget: preset.obscurity_budget(),
max_backtrack: bt,
max_restarts: restarts,
rand_top_base: preset.rand_top_base(),
..Default::default()
}
}
}