test(opstack): measure the box verdict on BOTH densities -- the fixture cannot prove a tile

The widened sampler worked: 39 of 40 tiles now land clear of the (0,0) spine.
The verdict did not move -- rooms still hit 40 of 40. By my own pre-registered
rule that means the room-lattice model was wrong, and it was, for a reason the
report had been printing at me for three runs: "= 7.6 x RoomSpacing 42".

RoomSpacing is 42 here, not the 80 I did the arithmetic with. I read the
UPROPERTY default out of the header instead of the fixture that overrides it.
Fifth premise this refactor that reversed on being checked, and the plainest:
the number was on screen.

EnableTunnelFeatures densifies on purpose -- RoomSpacing 80 -> 42, RoomDensity
0.35 -> 0.85 -- because at the defaults only 1.1% of samples were in open cave
and the equivalence compared solid rock to solid rock. That densification is what
makes check 1 mean anything, and it is exactly antagonistic to provability:

  room cull radius = max(R*1.5, R*HeightRatio) + 3*SDFBlendRadius
                   = 1.5R + 12  for R in [10,30]  =>  27..57, mean ~42
  lattice spacing  = 42 at 85% occupancy

The mean cull radius equals the lattice spacing, so cull spheres cover that world
~3.6x over and NO box can be outside all of them. "6.3 of 8.3 rooms reach" is not
a loose test, it is a saturated world. No sampler change and no tunnel tightening
can move it -- which is why widening the sampler correctly changed nothing.

So 0 proved on this fixture is the RIGHT answer, and informative: the prize
shrinks to nothing as caves saturate. It is simply not an answer about
production.

Check 4 is now a lambda run twice -- parameterised rather than copy-pasted,
because two copies of the criterion would drift and the second would lie:
[dense fixture] as before, expected to stay ~0 and now documented as correct;
[production defaults] the same 40 tiles against RoomSpacing 80 / RoomDensity
0.35, the real UVoxelStrateDefinition defaults. Both brute-forced voxel by voxel.
Not "widen it until it passes": the dense run stays in the report, must stay ~0,
and a false verdict in either still fails. The two stacks deliberately share
FRoomGraphSource's thread_local caches, so this run and check 3 now watch each
other through the params fingerprint in the key.

Unbuilt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 18:37:45 +02:00
parent f2fefade4c
commit 87a0b996ec
2 changed files with 313 additions and 171 deletions
+85
View File
@@ -2850,3 +2850,88 @@ tunnels.
`SpanCells` / `SpanVoxelsReported` / `NumTilesAwayFromSpine` are new locals hoisted **outside** the `SpanCells` / `SpanVoxelsReported` / `NumTilesAwayFromSpine` are new locals hoisted **outside** the
tile loop (the report line needs them); `P.OriginRoomRadius` and `P.RoomSpacing` are read in check 4. tile loop (the report line needs them); `P.OriginRoomRadius` and `P.RoomSpacing` are read in check 4.
## 2026-07-28 — the sampler fix worked, the prediction failed, and the fixture is the reason
The widened sampler did exactly what it was meant to: **39 of 40 tiles now land clear of the (0,0)
spine.** And the verdict did not move.
```
[before] rooms 40, tunnels 40 | 4.9 of 7.2 rooms, 69.2 of 80.4 tunnels (XY ±32)
[after ] rooms 40, tunnels 40 | 6.3 of 8.3 rooms, 78.0 of 87.7 tunnels (XY ±320, 39/40 off-spine)
```
My stated prediction was *"rooms should stop hitting every tile."* **They did not.** By my own
pre-registered rule that means the room-lattice model was wrong — and it was, for a reason printed in
the report I had been reading past for three runs:
> `= 7.6 x RoomSpacing 42`
**`RoomSpacing` is 42 here, not the 80 I computed with.** I read the `UPROPERTY` default out of the
header instead of the fixture, which overrides it. Fifth premise this refactor that reversed on being
checked, and the plainest one: *the number was on screen.*
### Why the fixture cannot ever prove a tile — arithmetic, not opinion
`EnableTunnelFeatures` densifies **on purpose**, and says so: `RoomSpacing` 80 → 42,
`RoomDensity` 0.35 → 0.85, because at the defaults the first run had **1.1 %** of samples in open
cave and the equivalence was comparing solid rock to solid rock. That densification is what makes
check 1 mean anything.
It is also exactly antagonistic to provability:
```
room cull radius = max(R·1.5, R·HeightRatio) + 3·SDFBlendRadius
= 1.5R + 12 for R ∈ [10,30] ⇒ 27 … 57, mean ≈ 42
lattice spacing = 42, occupancy 0.85
```
**The mean cull radius equals the lattice spacing.** Sphere volume over cell volume gives ~3.6×
redundant coverage — *no box in that world can be outside all room cull spheres.* `6.3 of 8.3 rooms
reach` is not a symptom of a loose test; it is the world being saturated. No sampler change and no
tightening of tunnels can move it, which is why widening the sampler correctly changed nothing.
**So `0 proved` on this fixture is the right answer**, and it is informative: the tile-skipping prize
shrinks to nothing as caves saturate. What it is *not* is an answer about production.
### Both worlds, one criterion
Check 4 is now a lambda run twice — **parameterised, not copy-pasted**, because two copies of the
criterion would drift and the second one would lie:
- **`[dense fixture]`** — as before. Expected to keep reporting ~0, and that is now written down as
the correct result rather than read as a failure.
- **`[production defaults]`** — the same 40 tiles against `RoomSpacing 80 / RoomDensity 0.35`, the
actual `UVoxelStrateDefinition` defaults, which is the world the question "how many tiles can we
skip" is really about. At that spacing, cull spheres of mean radius 42 on an 80-lattice at 35 %
occupancy cover roughly a fifth of space.
Both are brute-forced voxel by voxel. This is **not** "widen it until it passes": the dense run stays
in the report and must stay ~0, and a false verdict in either run still fails the assertion. The two
stacks deliberately share `FRoomGraphSource`'s `thread_local` caches — the params fingerprint in the
key is what keeps them apart, so this run and check 3 now watch each other.
### The lesson, and it is not the one I expected to write
Three runs in a row I reasoned from `RoomSpacing = 80` while the test printed 42 at me. The
instrument was right, the arithmetic done on it was right, and the *input to the arithmetic* was
taken from the wrong file. **"Verify the premise" has to include the premises you are confident
enough about not to look up** — especially a default, when a fixture exists whose entire job is to
override defaults.
### Ready to build. Compile-error spots
1. Check 4 is now `auto RunTileScan = [&](const FVoxelOpStack& S, const FStrateGenerationParams& TP,
const FVoxelOpContext& TCtx, const TCHAR* Label)`, called twice. Verified mechanically: zero bare
`Stack` / `P.` / `Ctx` references survive inside the lambda body, braces and parens balance.
2. Five `FString::Printf` sites gained a leading `%s` **and** the matching `Label` argument — the
mismatch was caught and fixed before commit; worth re-checking if the log looks scrambled.
3. `SparseStack` is a second `FVoxelOpStack` built by `BuildTunnelNetworkStack` and `PrepareChunk`ed.
### What to read
**`[production defaults] Box verdicts`** — the only new number that matters. Non-zero is the first
real T1.d saving in the plugin. If it is *also* zero, then the per-class line under it says whether
rooms still saturate at 80 spacing (my model is wrong again, look there) or whether tunnels are
finally alone (the segment-vs-box disjunction from the previous entry is then the whole remaining
job, and its three unverified premises are listed there).
@@ -1102,6 +1102,12 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
// would now forbid the very gain this change makes. What replaces it is the assertion that // would now forbid the very gain this change makes. What replaces it is the assertion that
// actually matters — every proved tile is brute-forced voxel by voxel, because a false verdict // actually matters — every proved tile is brute-forced voxel by voxel, because a false verdict
// means no geometry and NO COLLISION until a player falls through it. // means no geometry and NO COLLISION until a player falls through it.
// ⚠️ UNE SEULE DÉFINITION DU BALAYAGE, DEUX MONDES. Voir le commentaire d'appel plus bas :
// la densité de la fixture rend ce verdict STRUCTURELLEMENT impossible, donc mesurer sur elle
// seule ne dit rien de la production. Copier-coller le balayage aurait donné deux critères qui
// divergent ; c'est un paramètre, pas un doublon.
auto RunTileScan = [&](const FVoxelOpStack& S, const FStrateGenerationParams& TP,
const FVoxelOpContext& TCtx, const TCHAR* Label)
{ {
int32 NumProved = 0, NumMixed = 0, NumSolid = 0, NumAir = 0; int32 NumProved = 0, NumMixed = 0, NumSolid = 0, NumAir = 0;
int32 NumBruteSamples = 0, NumViolations = 0; int32 NumBruteSamples = 0, NumViolations = 0;
@@ -1149,7 +1155,7 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
// Combien de tuiles échappent vraiment au hub de la spine : sans ce compte, un futur // Combien de tuiles échappent vraiment au hub de la spine : sans ce compte, un futur
// resserrement de l'étendue redeviendrait invisible. // resserrement de l'étendue redeviendrait invisible.
if (FMath::Square((float)Origin.X) + FMath::Square((float)Origin.Y) if (FMath::Square((float)Origin.X) + FMath::Square((float)Origin.Y)
> FMath::Square(3.0f * P.OriginRoomRadius)) > FMath::Square(3.0f * TP.OriginRoomRadius))
{ {
++NumTilesAwayFromSpine; ++NumTilesAwayFromSpine;
} }
@@ -1163,11 +1169,11 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
// savait nommer aucun coupable : les deux causes que la mise en garde proposait étaient // savait nommer aucun coupable : les deux causes que la mise en garde proposait étaient
// toutes les deux fausses, la vraie étant un troisième opérateur. On ne redevine pas. // toutes les deux fausses, la vraie étant un troisième opérateur. On ne redevine pas.
int32 SolidKiller = INDEX_NONE, AirKiller = INDEX_NONE; int32 SolidKiller = INDEX_NONE, AirKiller = INDEX_NONE;
const EVoxelTileClass Verdict = Stack.ClassifyBoxAttributed(Box, Ctx, SolidKiller, AirKiller); const EVoxelTileClass Verdict = S.ClassifyBoxAttributed(Box, TCtx, SolidKiller, AirKiller);
if (SolidKiller != INDEX_NONE) if (SolidKiller != INDEX_NONE)
{ {
const FString KillerName = Stack.GetOpDebugName(SolidKiller); const FString KillerName = S.GetOpDebugName(SolidKiller);
SolidKillerCounts.FindOrAdd(KillerName)++; SolidKillerCounts.FindOrAdd(KillerName)++;
// VENTILATION PAR CLASSE DE PRIMITIVE. Quand c'est la source de salles qui tue, // VENTILATION PAR CLASSE DE PRIMITIVE. Quand c'est la source de salles qui tue,
@@ -1203,7 +1209,7 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
for (float Y = (float)Box.Min.Y; Y <= (float)Box.Max.Y; Y += 1.0f) for (float Y = (float)Box.Min.Y; Y <= (float)Box.Max.Y; Y += 1.0f)
for (float X = (float)Box.Min.X; X <= (float)Box.Max.X; X += 1.0f) for (float X = (float)Box.Min.X; X <= (float)Box.Max.X; X += 1.0f)
{ {
const float D = Stack.EvalMC(X, Y, Z); const float D = S.EvalMC(X, Y, Z);
++NumBruteSamples; ++NumBruteSamples;
const bool bViolates = bClaimSolid ? (D > 0.0f) : (D < 0.0f); const bool bViolates = bClaimSolid ? (D > 0.0f) : (D < 0.0f);
if (bViolates) if (bViolates)
@@ -1215,17 +1221,17 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
} }
AddInfo(FString::Printf( AddInfo(FString::Printf(
TEXT("Tile sampler: 40 tiles of 10 voxels, XY drawn from +/-%d voxels (= %.1f x ") TEXT("[%s] Tile sampler: 40 tiles of 10 voxels, XY drawn from +/-%d voxels (= %.1f x ")
TEXT("RoomSpacing %.0f), Z across the strate; %d of 40 landed further than 3 x ") TEXT("RoomSpacing %.0f), Z across the strate; %d of 40 landed further than 3 x ")
TEXT("OriginRoomRadius from the (0,0) spine. THIS LINE EXISTS BECAUSE THE SAMPLER WAS ") TEXT("OriginRoomRadius from the (0,0) spine. THIS LINE EXISTS BECAUSE THE SAMPLER WAS ")
TEXT("THE BUG ONCE: it drew XY from +/-32 voxels, i.e. entirely inside the origin room's ") TEXT("THE BUG ONCE: it drew XY from +/-32 voxels, i.e. entirely inside the origin room's ")
TEXT("cull sphere, so every number below described the spine hub rather than the world. ") TEXT("cull sphere, so every number below described the spine hub rather than the world. ")
TEXT("If the last count is low, nothing below says anything about deep rock."), TEXT("If the last count is low, nothing below says anything about deep rock."),
SpanVoxelsReported, (float)SpanVoxelsReported / FMath::Max(P.RoomSpacing, 1.0f), Label, SpanVoxelsReported, (float)SpanVoxelsReported / FMath::Max(TP.RoomSpacing, 1.0f),
P.RoomSpacing, NumTilesAwayFromSpine)); TP.RoomSpacing, NumTilesAwayFromSpine));
AddInfo(FString::Printf( AddInfo(FString::Printf(
TEXT("Box verdicts over 40 TunnelNetwork tiles: %d proved (%d AllSolid, %d AllAir), ") TEXT("[%s] Box verdicts over 40 TunnelNetwork tiles: %d proved (%d AllSolid, %d AllAir), ")
TEXT("%d Mixed -- brute-forced over %d voxels, %d violations. This number was 0 proved / ") TEXT("%d Mixed -- brute-forced over %d voxels, %d violations. This number was 0 proved / ")
TEXT("40 Mixed until FRoomGraphSource::EffectOverBox learned to answer spatially, and it ") TEXT("40 Mixed until FRoomGraphSource::EffectOverBox learned to answer spatially, and it ")
TEXT("is the single largest perf item of the whole plan (OPSTACK-DECOMPOSITION 0.2): a ") TEXT("is the single largest perf item of the whole plan (OPSTACK-DECOMPOSITION 0.2): a ")
@@ -1233,7 +1239,7 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
TEXT("30000+ density evaluations. Read the PROVED count as a measurement, never as a ") TEXT("30000+ density evaluations. Read the PROVED count as a measurement, never as a ")
TEXT("contract -- what is asserted below is that none of them is WRONG, because a false ") TEXT("contract -- what is asserted below is that none of them is WRONG, because a false ")
TEXT("verdict leaves no geometry and no collision behind it."), TEXT("verdict leaves no geometry and no collision behind it."),
NumProved, NumSolid, NumAir, NumMixed, NumBruteSamples, NumViolations)); Label, NumProved, NumSolid, NumAir, NumMixed, NumBruteSamples, NumViolations));
// QUI TUE `AllSolid`, ET COMBIEN DE FOIS. Toujours imprimé, pas seulement en cas d'échec : // QUI TUE `AllSolid`, ET COMBIEN DE FOIS. Toujours imprimé, pas seulement en cas d'échec :
// c'est aussi la ligne qui dit, quand des tuiles SONT prouvées, ce qui bloque les autres. // c'est aussi la ligne qui dit, quand des tuiles SONT prouvées, ce qui bloque les autres.
@@ -1248,19 +1254,19 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
if (Breakdown.IsEmpty()) { Breakdown = TEXT("nothing -- AllSolid survived every tile"); } if (Breakdown.IsEmpty()) { Breakdown = TEXT("nothing -- AllSolid survived every tile"); }
AddInfo(FString::Printf( AddInfo(FString::Printf(
TEXT("AllSolid killed by: %s. This is the line that replaced a guess. The first ") TEXT("[%s] AllSolid killed by: %s. This is the line that replaced a guess. The first ")
TEXT("build of the spatial EffectOverBox reported 0 proved of 40, and the warning ") TEXT("build of the spatial EffectOverBox reported 0 proved of 40, and the warning ")
TEXT("offered two candidate causes -- BOTH WRONG. The real one was a third operator ") TEXT("offered two candidate causes -- BOTH WRONG. The real one was a third operator ")
TEXT("nobody was looking at: FWormFieldSource answered CarveOnly everywhere, and ") TEXT("nobody was looking at: FWormFieldSource answered CarveOnly everywhere, and ")
TEXT("since BaseDensity=8 < WormStrength=10 BY DEFAULT, its provable amplitude bound ") TEXT("since BaseDensity=8 < WormStrength=10 BY DEFAULT, its provable amplitude bound ")
TEXT("alone drove SolidMargin negative on every tile in the world. Attribution is ") TEXT("alone drove SolidMargin negative on every tile in the world. Attribution is ")
TEXT("cheap; a second wrong guess is not."), TEXT("cheap; a second wrong guess is not."),
*Breakdown)); Label, *Breakdown));
if (NumRoomKilled > 0) if (NumRoomKilled > 0)
{ {
AddInfo(FString::Printf( AddInfo(FString::Printf(
TEXT("...and when RoomGraphSource is the killer (%d tiles), WHICH primitive class ") TEXT("[%s] ...and when RoomGraphSource is the killer (%d tiles), WHICH primitive class ")
TEXT("reaches the box: rooms %d, tunnels %d, pits %d, chimneys %d (tiles, not ") TEXT("reaches the box: rooms %d, tunnels %d, pits %d, chimneys %d (tiles, not ")
TEXT("primitives -- a tile can be hit by several). Averages per killed tile: ") TEXT("primitives -- a tile can be hit by several). Averages per killed tile: ")
TEXT("%.1f of %.1f rooms reach, %.1f of %.1f tunnels reach. THIS is the line that ") TEXT("%.1f of %.1f rooms reach, %.1f of %.1f tunnels reach. THIS is the line that ")
@@ -1269,7 +1275,7 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
TEXT("sphere is a fair fit. So tunnels >> rooms here would mean the box test is ") TEXT("sphere is a fair fit. So tunnels >> rooms here would mean the box test is ")
TEXT("losing to capsule bounding spheres, not to real cave -- and the fix would ") TEXT("losing to capsule bounding spheres, not to real cave -- and the fix would ")
TEXT("be a segment-vs-box distance, not anything about the sampler."), TEXT("be a segment-vs-box distance, not anything about the sampler."),
NumRoomKilled, TilesHitByRooms, TilesHitByTunnels, TilesHitByPits, TilesHitByChimneys, Label, NumRoomKilled, TilesHitByRooms, TilesHitByTunnels, TilesHitByPits, TilesHitByChimneys,
(float)SumHitRooms / (float)NumRoomKilled, (float)SumNumRooms / (float)NumRoomKilled, (float)SumHitRooms / (float)NumRoomKilled, (float)SumNumRooms / (float)NumRoomKilled,
(float)SumHitTunnels / (float)NumRoomKilled, (float)SumNumTunnels / (float)NumRoomKilled)); (float)SumHitTunnels / (float)NumRoomKilled, (float)SumNumTunnels / (float)NumRoomKilled));
} }
@@ -1277,18 +1283,69 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
if (NumProved == 0) if (NumProved == 0)
{ {
AddWarning(TEXT("No TunnelNetwork tile was proved, so the brute force below verified ") AddWarning(FString::Printf(
TEXT("nothing -- it has no verdict to contradict. Do NOT re-derive the cause: ") TEXT("[%s] No tile was proved, so the brute force verified nothing -- it has no ")
TEXT("read the 'AllSolid killed by' line above, which names the operator and ") TEXT("verdict to contradict. Do NOT re-derive the cause: read the two lines above, ")
TEXT("counts how often. If it names RoomGraphSource, the tiles genuinely ") TEXT("which name the operator and then the primitive class. ⚠️ On the DENSE ")
TEXT("straddle cave (check the bake-coverage line of 5b); anything else is an ") TEXT("FIXTURE this is the EXPECTED and correct result, not a defect: room cull ")
TEXT("operator whose box answer is more pessimistic than its Eval.")); TEXT("radius (1.5R + 3*SDFBlendRadius, mean ~42) equals RoomSpacing 42 at 85%% ")
TEXT("occupancy, so cull spheres cover that world ~3.6x over and no box can be ")
TEXT("outside all of them. It is the 'production defaults' run that answers ")
TEXT("whether real worlds have skippable rock."),
Label));
} }
TestEqual(FString::Printf( TestEqual(FString::Printf(
TEXT("every proved TunnelNetwork tile survives brute force (worst |density| ") TEXT("[%s] every proved TunnelNetwork tile survives brute force (worst ")
TEXT("on the wrong side: %.9g)"), WorstViolation), TEXT("|density| on the wrong side: %.9g)"), Label, WorstViolation),
NumViolations, 0); NumViolations, 0);
};
//-------------------------------------------------------------------------
// LES DEUX MONDES, ET POURQUOI IL EN FAUT DEUX
//-------------------------------------------------------------------------
// ⚠️ LA FIXTURE REND CE VERDICT STRUCTURELLEMENT IMPOSSIBLE, ET CE N'EST PAS UN DÉFAUT DE LA
// FIXTURE. `EnableTunnelFeatures` densifie délibérément (`RoomSpacing` 80 → 42,
// `RoomDensity` 0.35 → 0.85) parce qu'aux défauts le premier run n'avait que 1,1 % des
// échantillons en grotte — l'équivalence comparait du roc plein à du roc plein. Cette
// densification est ce qui rend le contrôle 1 SIGNIFIANT.
//
// Mais elle est exactement ANTAGONISTE de la prouvabilité, et l'arithmétique le dit sans
// ambiguïté : le rayon de cull d'une salle vaut `max(R·1.5, R·HeightRatio) + 3·SDFBlendRadius`,
// soit `1.5R + 12` ⇒ entre 27 et 57 pour `R ∈ [10, 30]`, moyenne ≈ 42 — c'est-à-dire
// **exactement le pas du réseau**, à 85 % d'occupation. Des sphères de cull de rayon égal au pas
// du réseau recouvrent l'espace ~3,6 fois. **Aucune boîte de ce monde ne peut être hors de
// toutes les sphères de cull.** Le « 6.3 salles sur 8.3 atteignent la boîte » mesuré est
// exactement ça, et élargir l'échantillonneur n'y a rien changé (39 tuiles sur 40 étaient déjà
// loin de la spine, et le compte est resté 40 sur 40).
//
// Donc on mesure les DEUX : la fixture dense, où `0 prouvé` est le résultat CORRECT et
// informatif (le gain disparaît quand les grottes saturent), et un jeu de params aux DÉFAUTS
// DE PRODUCTION, qui est le monde dont la question « combien de tuiles peut-on sauter » parle
// réellement. Ce n'est pas « élargir jusqu'à ce que ça passe » : les deux sont rapportés, les
// deux sont brute-forcés, et le dense DOIT continuer à rendre ~0.
//
// Two worlds on purpose: the fixture is deliberately densified so the equivalence check means
// something, and that same densification makes tile-proving structurally impossible (room cull
// radius ~= the lattice spacing, at 85% occupancy). Both are measured and both are brute-forced;
// the dense one reporting ~0 is the correct answer, not a failure.
RunTileScan(Stack, P, Ctx, TEXT("dense fixture"));
{
FStrateGenerationParams SparseP = P;
SparseP.RoomSpacing = 80.0f; // le défaut d'`UVoxelStrateDefinition`
SparseP.RoomDensity = 0.35f; // idem — voir `EnableTunnelFeatures`
FVoxelOpStack SparseStack;
VoxelDensityOps::BuildTunnelNetworkStack(SparseStack, SparseP, World.Settings->Seed,
Gen->OriginSpineRadius, World.StrateManager.Get());
SparseStack.PrepareChunk(Ctx);
// ⚠️ Les deux piles partagent les caches `thread_local` de `FRoomGraphSource`. C'est VOULU,
// et c'est exactement ce que le contrôle 3 vérifie : l'empreinte de params est dans la clé,
// donc l'une ne peut pas se servir les salles de l'autre. Le jour où ce contrôle tombe,
// cette ligne-ci devient fausse en même temps — elles se surveillent mutuellement.
RunTileScan(SparseStack, SparseP, Ctx, TEXT("production defaults"));
} }
//========================================================================= //=========================================================================