Title of State:
Adding Seed
Goal of Change:
full seed + PRNG change on the exact code you pasted, and we’ll wire the Seed control into the MENU (so it’s real, not theoretical). No resources generated yet — this just gives us deterministic randomness ready to use.
PATCH 1 — MENU: add a Seed input above START GAME
Code to Remove
199 -
<div class="menuActions">
<button id="btnStartGame" class="btnPrimary" type="button" disabled>START GAME</button>
</div>
Code to Add
199 -
<div class="menuActions">
<div class="seedRow">
<div class="seedLabel">Seed</div>
<input id="seedInput" class="seedInput" type="number" step="1" value="12345" />
</div>
<button id="btnStartGame" class="btnPrimary" type="button" disabled>START GAME</button>
</div>
PATCH 2 — CSS: style the seed row + input
Code to Remove
124 -
.menuActions{
width:100%;
display:flex;
justify-content:center;
padding-top:4px;
}
Code to Add
124 -
.menuActions{
width:100%;
display:flex;
flex-direction:column;
align-items:center;
gap:10px;
padding-top:4px;
}
.seedRow{
display:flex;
align-items:center;
gap:10px;
padding:10px 12px;
border-radius:12px;
border:1px solid rgba(255,255,255,.14);
background:rgba(255,255,255,.06);
}
.seedLabel{
font-size:13px;
opacity:.9;
}
.seedInput{
width:180px;
padding:10px 12px;
border-radius:10px;
border:1px solid rgba(255,255,255,.16);
background:rgba(0,0,0,.25);
color:#e9f0ff;
font-size:14px;
outline:none;
}
PATCH 3 — JS: grab the seed input element
Code to Remove
256 -
const btnBegin = document.getElementById("btnBegin");
const btnStartGame = document.getElementById("btnStartGame");
Code to Add
256 -
const btnBegin = document.getElementById("btnBegin");
const btnStartGame = document.getElementById("btnStartGame");
const seedInput = document.getElementById("seedInput");
PATCH 4 — JS: add seed to State
Code to Remove
266 -
const S = {
paused:false,
view:"TITLE", // "TITLE" | "MENU" | "GAME"
mapKey:null, // "GRASS" | "SAND" | "SNOW"
mouseX:0, mouseY:0,
camX:0, camY:0, // viewport top-left in map pixels
keys:{}, // pressed keys map
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
Code to Add
266 -
const S = {
paused:false,
view:"TITLE", // "TITLE" | "MENU" | "GAME"
mapKey:null, // "GRASS" | "SAND" | "SNOW"
mouseX:0, mouseY:0,
camX:0, camY:0, // viewport top-left in map pixels
keys:{}, // pressed keys map
seed: 12345, // deterministic seed for procedural generation
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
PATCH 5 — JS: add seeded RNG utilities (right after clamp)
Code to Remove
291 -
function clamp(v, a, b){ return Math.max(a, Math.min(b, v)); }
Code to Add
291 -
function clamp(v, a, b){ return Math.max(a, Math.min(b, v)); }
/* =========================
SEEDED PRNG (DETERMINISTIC)
========================= */
// Mulberry32: compact + reliable for procedural placement
function makeRng(seed){
let t = (seed >>> 0);
return function RNG(){
t += 0x6D2B79F5;
let r = Math.imul(t ^ (t >>> 15), 1 | t);
r ^= r + Math.imul(r ^ (r >>> 7), 61 | r);
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
};
}
let RNG = makeRng(S.seed);
function reseed(newSeed){
const s = (Number(newSeed) | 0) >>> 0;
S.seed = s;
RNG = makeRng(S.seed);
if(seedInput) seedInput.value = String(S.seed);
}
PATCH 6 — JS: wire the seed input to reseed immediately
Code to Remove
336 -
window.addEventListener("keyup", (e)=>{
S.keys[e.code] = false;
});
Code to Add
336 -
window.addEventListener("keyup", (e)=>{
S.keys[e.code] = false;
});
/* Seed input */
seedInput.addEventListener("change", ()=>{
reseed(seedInput.value);
});
seedInput.addEventListener("keydown", (e)=>{
if(e.key === "Enter"){
reseed(seedInput.value);
}
});
PATCH 7 — JS: reseed when starting the game
Code to Remove
447 -
btnStartGame.addEventListener("click", ()=>{
if(!S.mapKey) return;
setView("GAME");
});
Code to Add
447 -
btnStartGame.addEventListener("click", ()=>{
if(!S.mapKey) return;
reseed(seedInput.value);
setView("GAME");
});
PATCH 8 — Boot: sync seed input + initialize RNG
Code to Remove
551 -
setHUD("READY");
setView("TITLE");
preloadMaps();
requestAnimationFrame(loop);
Code to Add
551 -
setHUD("READY");
setView("TITLE");
reseed(S.seed);
preloadMaps();
requestAnimationFrame(loop);