Skip to content

MushroomFleet/zerobytes-3dcombatlayer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

5 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ZB-3DCombatLayer

License: MIT Three.js React Determinism Scale

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.

ZB-3DCombatLayer V3 Demo


๐Ÿš€ V3: Massive Scale Edition

Version 3.0 introduces GPU-optimized rendering and spatial partitioning to handle 2000 vs 2000 battles while maintaining full ZeroBytes determinism.

Version Comparison Table

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 Optimization Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚            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)       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Performance Benchmarks

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

๐ŸŽฏ Determinism Evolution: V1 โ†’ V2 โ†’ V3

V1: The Frame-Rate Problem

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 machine

V1 Issues:

  • Interpolated pos used for combat calculations
  • Sequential damage application (order-dependent)
  • No separation between simulation and rendering
  • Results varied between 60fps and 144fps displays

V2: The Determinism Fix

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 resolved

V2 Achievements:

  • simPos/renderPos separation
  • Batched damage application
  • Built-in verifyDeterminism() function
  • Guaranteed identical outcomes

V3: Determinism at Massive Scale

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 outcome

V3 Achievements:

  • All V2 determinism guarantees preserved
  • InstancedMesh for single draw call rendering
  • SpatialGrid for O(1) target finding
  • FloatingTextPool for zero-allocation damage text
  • Slider control for 100-4000 units
  • Live performance monitoring (FPS, draw calls)

โœจ Features

  • 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

๐Ÿš€ Quick Start

View the Demos

# 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

Install in Your Project

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); // true

๐Ÿ“– The ZeroBytes Methodology

Position-as-Seed Principle

Traditional 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)

The Five Laws

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

Hierarchical Seed Chain

worldSeed = 42
    โ”‚
    โ”œโ”€โ–บ armySeed = hash(worldSeed, faction)
    โ”‚       โ”‚
    โ”‚       โ”œโ”€โ–บ unitSeed = hash(armySeed, position)
    โ”‚       โ”‚       โ”‚
    โ”‚       โ”‚       โ””โ”€โ–บ attackSeed = hash(attackerSimPos, targetSimPos, worldSeed)
    โ”‚       โ”‚               โ”‚
    โ”‚       โ”‚               โ””โ”€โ–บ hitRoll, critRoll, damageRoll (all deterministic)
    โ”‚       โ”‚
    โ”‚       โ””โ”€โ–บ (next unit...)
    โ”‚
    โ””โ”€โ–บ (other army...)

๐Ÿ”ง V3 API Reference

SpatialGrid

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);

InstancedArmyRenderer

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 zero

FloatingTextPool

Zero-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);

generateArmy (V3)

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
);

verifyDeterminism

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

๐ŸŽฎ V3 Demo Controls

Army Configuration

Control Range Description
Army Size Slider 100 - 4000 Total units (both armies)
Seed Input 1 - 999999 World seed for reproduction

Battle Controls

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

AOE Abilities

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

Camera

Input Action
Drag Rotate view
Scroll Zoom in/out
Shift+Drag Pan camera

๐Ÿ“Š Combat Modifiers

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

๐ŸŽ–๏ธ Unit Types

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 Reference

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 Cases

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

๐Ÿ”ฌ Why Determinism Matters

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

โšก Performance Tips

For 2000 vs 2000 Battles

// 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

๐Ÿ› ๏ธ Development

# 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/

๐Ÿ“„ License

MIT License - see LICENSE for details.


๐Ÿ™ Acknowledgments

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.


๐Ÿ“š Citation

@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}
}

Donate

Ko-Fi

About

3D Combat Layer with Endless Procedural Determinism for Massive Scale Combat, Zerobytes JSX Component | https://www.scuffedepoch.com | https://www.oragenai.com | ORAGEN TEAM

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors