Deterministic 3D Combat Resolution System for Massive-Scale Battle Simulations
A React + Three.js component implementing the ZeroBytes "position-is-seed" methodology for fully deterministic, reproducible combat simulations. Supports 2000 vs 2000 battles (4000 units) at 60 FPS with a single draw call.
Version 3.0 introduces GPU-optimized rendering and spatial partitioning to handle 2000 vs 2000 battles while maintaining full ZeroBytes determinism.
| Feature | V1 | V2 | V3 |
|---|---|---|---|
| Max Units | ~120 | ~200 | 4000 |
| Default Army | 30 vs 30 | 60 vs 60 | 600 vs 600 |
| Max Battle | 60 vs 60 | 100 vs 100 | 2000 vs 2000 |
| Rendering | Individual meshes | Individual meshes | InstancedMesh |
| Draw Calls | 1 per unit | 1 per unit | 1 total |
| Target Finding | O(n) linear scan | O(n) linear scan | O(1) SpatialGrid |
| Damage Indicators | Create/destroy | Create/destroy | Object Pool (200) |
| Position System | Single pos |
simPos + renderPos |
simPos + renderPos |
| Damage Application | Sequential | Batched | Batched |
| Determinism | โ Frame-dependent | โ Verified | โ Verified |
| Army Size Control | Fixed | Fixed | Slider 100-4000 |
| Performance Monitor | None | None | FPS + Draw Calls |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ V3: 2000 vs 2000 BATTLE ARCHITECTURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ InstancedMesh Renderer โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โข 4000 unit capacity in single mesh โ โ
โ โ โข 1 draw call regardless of unit count โ โ
โ โ โข GPU-side transform via instanceMatrix โ โ
โ โ โข Per-instance colors via Float32Array โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ SpatialGrid โ โ FloatingTextPool โ โ
โ โ โโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโ โ โ
โ โ 5x5 unit cells โ โ 200 reusable โ โ
โ โ O(1) neighbor โ โ Canvas sprites โ โ
โ โ lookup vs O(n) โ โ Zero allocation โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Result: 2000 vs 2000 @ 30-50 FPS (single draw call) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Battle Size | Total Units | Expected FPS | Draw Calls | GPU Load |
|---|---|---|---|---|
| 50 vs 50 | 100 | 60+ | 1 | Low |
| 250 vs 250 | 500 | 60+ | 1 | Low |
| 600 vs 600 | 1,200 | 60+ | 1 | Medium |
| 1000 vs 1000 | 2,000 | 55-60 | 1 | Medium |
| 2000 vs 2000 | 4,000 | 30-50 | 1 | High |
V1 had subtle bugs that violated ZeroBytes Law #5 (Determinism):
// V1 BUG: Frame-rate dependent interpolation
unit.pos.x += (unit.targetPos.x - unit.pos.x) * lerpSpeed * delta;
// delta varies (16ms @ 60fps vs 7ms @ 144fps)
// โ positions drift differently
// โ combat hashes differ
// โ outcomes vary per machineV1 Issues:
- Interpolated
posused for combat calculations - Sequential damage application (order-dependent)
- No separation between simulation and rendering
- Results varied between 60fps and 144fps displays
V2 introduced architectural separation that guarantees reproducibility:
// V2 FIX: Separate simulation from rendering
unit.simPos // DETERMINISTIC - used for all game logic
unit.renderPos // VISUAL ONLY - interpolated, never used for combat
// Combat uses ONLY simPos
const hash = attackSeed(attacker.simPos, target.simPos, worldSeed);
// Damage is BATCHED - order doesn't matter
const damageMap = new Map();
allAttacks.forEach(({ target, damage }) => {
damageMap.set(target.id, (damageMap.get(target.id) || 0) + damage);
});
// Apply ALL damage after ALL attacks resolvedV2 Achievements:
simPos/renderPosseparation- Batched damage application
- Built-in
verifyDeterminism()function - Guaranteed identical outcomes
V3 preserves all V2 guarantees while enabling 20x more units:
// V3: Same determinism, massive scale
class SpatialGrid {
// Deterministic cell keys from quantized positions
_key(x, z) {
return `${Math.floor(x / this.cellSize)},${Math.floor(z / this.cellSize)}`;
}
// O(1) neighbor lookup instead of O(n) iteration
// But still uses simPos โ still deterministic!
findClosest(unit, enemyGrid, maxRange) {
const nearby = enemyGrid.getNearby(unit.simPos.x, unit.simPos.z, maxRange);
// ... find closest from nearby cells
}
}
// InstancedMesh renders 4000 units in 1 draw call
// But combat resolution is unchanged from V2
// Same simPos โ same hash โ same outcomeV3 Achievements:
- All V2 determinism guarantees preserved
InstancedMeshfor single draw call renderingSpatialGridfor O(1) target findingFloatingTextPoolfor zero-allocation damage text- Slider control for 100-4000 units
- Live performance monitoring (FPS, draw calls)
- 100% Deterministic โ Same seed = identical outcomes on any machine
- Massive Scale โ 2000 vs 2000 battles with instanced rendering
- O(1) Targeting โ Spatial grid enables constant-time neighbor lookup
- Single Draw Call โ GPU instancing keeps frame rates high
- 3D Spatial Combat โ Elevation, range, terrain, morale modifiers
- Zero State Storage โ Position IS the seed
- Replay-Ready โ Store only the seed to recreate any battle
- Built-in Verification โ
verifyDeterminism()proves identical outcomes - Live Performance โ FPS and draw call monitoring
# Clone the repository
git clone https://github.com/MushroomFleet/ZB-3DCombatLayer.git
cd ZB-3DCombatLayer
# V3 (Recommended) - Massive Scale, 2000 vs 2000 capable
open demov3.html
# V2 - Deterministic, smaller scale
open demov2.html
# V1 - Educational (shows determinism issues)
open demo.html| Demo | Default | Max Scale | Best For |
|---|---|---|---|
demov3.html |
600 vs 600 | 2000 vs 2000 | Production, massive battles |
demov2.html |
60 vs 60 | ~100 vs 100 | Learning determinism fixes |
demo.html |
30 vs 30 | ~60 vs 60 | Understanding V1 problems |
npm install three react// Use V3 for massive scale battles
import {
generateArmy,
SpatialGrid,
InstancedArmyRenderer,
resolveBattleRound,
verifyDeterminism
} from './ZB-3DCombatLayerV3';
// Generate 2000 vs 2000 battle
const blueArmy = generateArmy(-30, 0, 2000, 1.5, worldSeed, 0, 0);
const redArmy = generateArmy(30, 0, 2000, 1.5, worldSeed, 1, 2000);
// Verify determinism
const result = verifyDeterminism(worldSeed, 400, 10);
console.log(result.verified); // trueTraditional combat systems use sequential RNG requiring state tracking:
Traditional: state โ random() โ outcome โ state โ random() โ ...
(must track state, can't parallelize, can't replay)
ZeroBytes inverts this โ the coordinate IS the seed:
ZeroBytes: position โ hash โ outcome
(stateless, parallelizable, perfectly reproducible)
| Law | Description | V3 Implementation |
|---|---|---|
| O(1) Access | Compute any position without iteration | positionHash() + SpatialGrid |
| Parallelism | Units independent during generation | InstancedMesh batch updates |
| Coherence | Adjacent coordinates relate via noise | coherentValue3D() terrain |
| Hierarchy | Child seeds derive from parent + position | Battle โ Army โ Unit โ Attack |
| Determinism | Same inputs โ same outputs always | simPos + batched damage |
worldSeed = 42
โ
โโโบ armySeed = hash(worldSeed, faction)
โ โ
โ โโโบ unitSeed = hash(armySeed, position)
โ โ โ
โ โ โโโบ attackSeed = hash(attackerSimPos, targetSimPos, worldSeed)
โ โ โ
โ โ โโโบ hitRoll, critRoll, damageRoll (all deterministic)
โ โ
โ โโโบ (next unit...)
โ
โโโบ (other army...)
O(1) spatial partitioning for massive-scale neighbor queries:
import { SpatialGrid } from './ZB-3DCombatLayerV3';
const blueGrid = new SpatialGrid(5); // 5-unit cell size
const redGrid = new SpatialGrid(5);
// Rebuild each round from alive units
blueGrid.insertAll(blueArmy.filter(u => u.alive));
redGrid.insertAll(redArmy.filter(u => u.alive));
// O(1) lookup - critical for 4000 units
const closest = blueGrid.findClosest(attacker, redGrid, 30);Single draw call for 4000 units:
import { InstancedArmyRenderer } from './ZB-3DCombatLayerV3';
// Pre-allocate for max capacity
const renderer = new InstancedArmyRenderer(scene, 4000);
// Update all transforms and colors in one call
renderer.updateAll(blueArmy, redArmy);
// Internally:
// - Composes Matrix4 per unit (position, rotation, scale)
// - Sets per-instance color based on HP and faction
// - Hides unused instances by scaling to zeroZero-allocation damage indicators:
import { FloatingTextPool } from './ZB-3DCombatLayerV3';
const textPool = new FloatingTextPool(scene, 200);
// Spawn from pool (no memory allocation)
textPool.spawn('-25', position, '#ff6666', false); // normal hit
textPool.spawn('๐ฅ42', position, '#ffaa00', true); // critical
// Update in animation loop
textPool.update(deltaTime);Dynamic army sizing with adaptive spacing:
import { generateArmy } from './ZB-3DCombatLayerV3';
// Generate 2000 units with automatic grid formation
const army = generateArmy(
-30, // centerX
0, // centerZ
2000, // unitCount
1.5, // spacing (tighter for larger armies)
42, // worldSeed (deterministic!)
0, // faction
0 // startIndex for instanced mesh
);Prove identical outcomes:
import { verifyDeterminism } from './ZB-3DCombatLayerV3';
// Run same battle twice, compare results
const result = verifyDeterminism(
42, // worldSeed
400, // totalUnits to test
10 // rounds to simulate
);
console.log(result.verified); // true
console.log(result.r1.blueAlive); // e.g., 156
console.log(result.r2.blueAlive); // identical: 156| Control | Range | Description |
|---|---|---|
| Army Size Slider | 100 - 4000 | Total units (both armies) |
| Seed Input | 1 - 999999 | World seed for reproduction |
| Button | Function |
|---|---|
| โถ Start / โธ Pause | Begin or pause auto-battle |
| โญ Step Round | Advance one round manually |
| ๐ Reset | Regenerate armies from seed |
| Speed Slider | 0.25x to 4x battle speed |
| Button | Target | Effect |
|---|---|---|
| ๐ฅ Fireball | Red Army | 20 base damage, 12 unit radius |
| โก Lightning | Blue Army | 15 base damage, 12 unit radius |
| ๐ Heal | Both | 10-25 HP restored |
| ๐ฌ Verify | N/A | Run determinism check |
| Input | Action |
|---|---|
| Drag | Rotate view |
| Scroll | Zoom in/out |
| Shift+Drag | Pan camera |
All modifiers calculated from simPos (deterministic):
| Modifier | Condition | Effect |
|---|---|---|
| High Ground | attacker.y > target.y + 3 | +15% hit chance |
| Low Ground | attacker.y < target.y - 3 | -12% hit chance |
| Optimal Range | 3-8 units distance | +10% hit chance |
| Too Close | < 1.5 units | -20% hit chance |
| Too Far | > 15 units | -30% hit chance |
| Rough Terrain | noise > 0.5 | -10% hit chance |
| Clear Terrain | noise < -0.5 | +5% hit chance |
| Morale Zone | regional noise | ยฑ10% hit chance |
| Type | ATK | DEF | Precision | Evasion | Crit | Scale |
|---|---|---|---|---|---|---|
| Infantry | 10 | 8 | 55% | 15% | 8% | 1.0x |
| Cavalry | 14 | 6 | 45% | 25% | 12% | 1.3x |
| Archer | 8 | 4 | 70% | 10% | 15% | 0.9x |
| Mage | 16 | 3 | 60% | 8% | 20% | 1.0x |
| Heavy | 12 | 15 | 40% | 5% | 5% | 1.4x |
| File | Version | Description |
|---|---|---|
demov3.html |
V3 | โ Recommended - 2000 vs 2000 capable |
demov2.html |
V2 | Deterministic demo |
demo.html |
V1 | Educational (shows bugs) |
ZB-3DCombatLayerV3.jsx |
V3 | โ Production - Massive scale |
ZB-3DCombatLayerV2.jsx |
V2 | Deterministic component |
ZB-3DCombatLayer.jsx |
V1 | Original (has issues) |
ZB-3DCombatLayer-integration.md |
All | Integration guide |
README.md |
All | This documentation |
| Use Case | Recommended Version |
|---|---|
| Strategy game combat | V3 |
| Multiplayer sync | V2 or V3 |
| Battle replay system | V2 or V3 |
| AI training environment | V3 |
| Tournament/esports | V2 or V3 |
| Stress testing | V3 |
| Learning ZeroBytes | V1 โ V2 โ V3 |
| Scenario | V1 Result | V2/V3 Result |
|---|---|---|
| Same seed on 60fps vs 144fps | โ Different winner | โ Identical |
| Same seed with browser lag | โ Different casualties | โ Identical |
| Same seed on Windows vs Mac | โ May differ | โ Identical |
| Replay battle from seed | โ Approximate | โ Exact frame |
| Multiplayer combat sync | โ Need full state | โ Seed only |
| Tournament verification | โ Can't verify | โ Provable |
| Unit tests | โ Flaky | โ 100% reliable |
// 1. Tighter spacing for denser formations
const spacing = Math.max(1.0, 2.5 - (totalUnits / 3000));
// 2. Limit floating text to prevent sprite overload
const maxTexts = Math.min(50, hitCount);
// 3. Throttle UI updates
if (performance.now() - lastUpdate > 500) {
updatePerformanceUI();
}
// 4. Consider reducing shadow quality for 4000 units
sun.shadow.mapSize.width = 1024; // instead of 2048# Clone
git clone https://github.com/MushroomFleet/ZB-3DCombatLayer.git
cd ZB-3DCombatLayer
# Run V3 demo
open demov3.html
# Copy to your project
cp ZB-3DCombatLayerV3.jsx /your/project/src/components/MIT License - see LICENSE for details.
Built on the ZeroBytes procedural generation methodology:
"The universe springs complete from coordinates. Zero bytes store infinity."
V3 proves this scales to 4000 simultaneous combatants with verified determinism.
@software{zb_3d_combat_layer,
title = {ZB-3DCombatLayer: Deterministic 3D Combat Resolution System},
author = {Drift Johnson},
year = {2025},
url = {https://github.com/MushroomFleet/ZB-3DCombatLayer},
version = {3.0.0},
note = {Supports 2000 vs 2000 battles with instanced rendering}
}