G5: bump engine (regex tooling), showcase grouping/patch/validators

Engine pointer -> d044caf (formula gene grouping, content patches, def
field validation). Game-side demonstration of all three:

- genes.json: GeneHardiness whose effect is gsum('Gene.*Tolerance') — a
  derived trait summing all tolerance genes via regex grouping.
- patches.json: a content patch giving every Bush* plant a wood harvest
  product, applied to Core's own defs at load.
- GameContent registers load-time validators: Gene/Product defNames must
  carry their type prefix.
- Program: a --check-content headless mode that loads all mod defs (running
  patches + validators) and computes a sample genome's traits (compiling
  every gene formula, grouping included) — a CI-friendly content lint.

Verified: --check-content reports 6 def types, 18 genes, 8 plants, 18
traits with hardiness computed from the gene group. Full suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-06-13 04:00:26 +03:00
co-authored by Claude Opus 4.8
parent 7fc4bcd301
commit 37d8c976a3
5 changed files with 50 additions and 1 deletions
+8
View File
@@ -62,6 +62,14 @@ public sealed class GameContent
defs.RegisterType<PlantDef>("Plant");
defs.RegisterType<PawnDef>("Pawn");
defs.RegisterType<WorldPresetDef>("WorldPreset");
// Валидация имён при загрузке (фаза G5): гены и продукты обязаны иметь префикс типа.
defs.RegisterValidator("Gene", "defName", "^Gene", "gene defName must start with 'Gene'");
defs.RegisterValidator(
"Product",
"defName",
"^Product",
"product defName must start with 'Product'"
);
defs.Load(mods);
var languages = new LanguageManager(defaultLanguage: "ru");
+27
View File
@@ -1,8 +1,35 @@
using LittleSim.Content;
using LittleSim.Scenes;
using Microsoft.Xna.Framework;
using MrGameEng.Core;
using MrGameEng.Genetics;
using MrGameEng.Host;
// Контент-линт без окна/GPU: грузит моды/дефы (патчи и валидаторы тоже), компилирует формулы генов
// (включая группировку gsum) и выходит. Удобно для CI.
if (args.Contains("--check-content"))
{
try
{
var content = GameContent.Load();
var genes = content.Defs.All<GeneDef>();
var registry = genes.ToDictionary(g => g.DefName, g => g, StringComparer.Ordinal);
var traits = Phenotype.Compute(Genome.Generate(genes, new Random(1)), registry);
Console.WriteLine(
$"content ok: {content.Defs.TypeKeys.Count} def types, {genes.Count} genes, "
+ $"{content.Defs.NamesOf("Plant").Count} plants, {traits.Count} traits "
+ $"(hardiness={traits.GetValueOrDefault("hardiness"):0.##})"
);
return;
}
catch (Exception error)
{
Console.Error.WriteLine($"content FAILED: {error.Message}");
Environment.Exit(1);
return;
}
}
// Контент Core-мода грузится уже в окне — на загрузочном экране (BootScene), в фоне.
using var host = new GameHost(
new GameHostOptions