feat: m2 etagengenerierung — prefabs, floors, korridore, abstieg und sieg
Der handgebaute Testraum ist weg; Etagen entstehen aus Daten. - game/rng.rs: xorshift64*, Seed im Game (Ticket 14) - game/generate.rs: freie Platzierung, Pflichtraeume zuerst, Kette i->i-1 fuer strukturelle Erreichbarkeit, acht Orientierungen - data/: [[prefabs]] und [[floors]] als neunte und zehnte Registry, Ladepruefungen fuer rechteckige Layouts und Pflichtraum-Flaeche - Descend plus Siegbedingung: keine [[floors]] mit der naechsten Nummer heisst gewonnen — die Zahl 5 steht nirgends im Code - GameOver-Screen, mitlaufender Bildausschnitt im Grid Befund: Korridore stanzten 2340 Loecher in gezeichnete Waende, weil sie AUF der Tuer starteten. Erst Schritt nach aussen, dann L-Form, sonst Wegsuche ueber den freien Raum — die kann eine Raumwand nicht beruehren. Der Test zaehlt jetzt null. 21 Tests.
This commit is contained in:
@@ -14,7 +14,7 @@ use serde::Deserialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use toml::Spanned;
|
||||
|
||||
use super::registries::{Category, CharacterOption, Item, Registries, Slot};
|
||||
use super::registries::{Category, CharacterOption, FloorDef, Item, Prefab, Registries, Slot};
|
||||
|
||||
/// Genau drei harte Fehler (Ticket 04). Alles Uebrige ist Warnung plus
|
||||
/// Verwerfen des **einzelnen Eintrags**.
|
||||
@@ -244,6 +244,10 @@ struct ModFile {
|
||||
categories: Vec<Spanned<toml::Value>>,
|
||||
#[serde(default)]
|
||||
options: Vec<Spanned<toml::Value>>,
|
||||
#[serde(default)]
|
||||
prefabs: Vec<Spanned<toml::Value>>,
|
||||
#[serde(default)]
|
||||
floors: Vec<Spanned<toml::Value>>,
|
||||
}
|
||||
|
||||
/// Damit die vier Registry-Typen durch dieselbe Einlese-Schleife passen.
|
||||
@@ -272,6 +276,8 @@ impl_entry!(Item);
|
||||
impl_entry!(Slot);
|
||||
impl_entry!(Category);
|
||||
impl_entry!(CharacterOption);
|
||||
impl_entry!(Prefab);
|
||||
impl_entry!(FloorDef);
|
||||
|
||||
struct FileCtx<'a> {
|
||||
module: &'a str,
|
||||
@@ -366,6 +372,66 @@ fn resolve(reg: &mut Registries, warnings: &mut Vec<String>) {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// Ticket 10: `layout`-Zeilen muessen gleich lang sein, sonst ist der Block
|
||||
// kein Rechteck und die Platzierung rechnet mit Muell. Ein Zweizeiler, der
|
||||
// eine ganze Klasse von Modder-Frust abfaengt.
|
||||
reg.prefabs.retain(|id, prefab| {
|
||||
let rows = prefab.rows();
|
||||
if rows.is_empty() {
|
||||
warnings.push(format!("{id}: layout ist leer — verworfen"));
|
||||
return false;
|
||||
}
|
||||
let width = rows[0].chars().count();
|
||||
match rows.iter().position(|r| r.chars().count() != width) {
|
||||
Some(i) => {
|
||||
warnings.push(format!(
|
||||
"{id}: layout-Zeile {} ist {} Zeichen breit, erwartet {width} — verworfen",
|
||||
i + 1,
|
||||
rows[i].chars().count()
|
||||
));
|
||||
false
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
});
|
||||
|
||||
// Ticket 10: Passen die Pflicht-Tags grundsaetzlich nicht in `size`, ist das
|
||||
// ein **Datenfehler und beim Laden erkennbar**. Zur Laufzeit gibt es dafuer
|
||||
// dann keinen Wiederholungszaehler und keinen Rueckfallpfad — die Pruefung
|
||||
// sitzt dort, wo der Fehler gemacht wurde.
|
||||
let prefabs = ®.prefabs;
|
||||
reg.floors.retain(|id, floor| {
|
||||
let mut needed = 0u32;
|
||||
|
||||
for tag in &floor.required {
|
||||
let smallest = prefabs
|
||||
.values()
|
||||
.filter(|p| p.tags.iter().any(|t| t == tag))
|
||||
.map(|p| {
|
||||
let (w, h) = p.size();
|
||||
(w as u32 + 1) * (h as u32 + 1)
|
||||
})
|
||||
.min();
|
||||
|
||||
match smallest {
|
||||
None => {
|
||||
warnings.push(format!("{id}: kein Prefab mit dem Pflicht-Tag '{tag}'"));
|
||||
return false;
|
||||
}
|
||||
Some(area) => needed += area,
|
||||
}
|
||||
}
|
||||
|
||||
let available = floor.size.0 as u32 * floor.size.1 as u32;
|
||||
if needed > available {
|
||||
warnings.push(format!(
|
||||
"{id}: Pflichträume brauchen mindestens {needed} Felder, size bietet {available}"
|
||||
));
|
||||
return false;
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -414,6 +480,8 @@ pub fn load_mods() -> Result<(Registries, Vec<String>), LoadError> {
|
||||
parse_entries(parsed.slots, &ctx, &mut reg.slots, &mut warnings);
|
||||
parse_entries(parsed.categories, &ctx, &mut reg.categories, &mut warnings);
|
||||
parse_entries(parsed.options, &ctx, &mut reg.options, &mut warnings);
|
||||
parse_entries(parsed.prefabs, &ctx, &mut reg.prefabs, &mut warnings);
|
||||
parse_entries(parsed.floors, &ctx, &mut reg.floors, &mut warnings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user