"use strict"; (function (global) { function hashString(value = "") { const str = String(value || ""); let h = 2166136261; for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); } return (h >>> 0).toString(36); } function createWorldSeed() { const cryptoObj = global.crypto; if (cryptoObj?.getRandomValues) { const buf = new Uint32Array(2); cryptoObj.getRandomValues(buf); return `w${buf[0].toString(36)}${buf[1].toString(36)}`; } return `w${Date.now().toString(36)}${Math.floor(Math.random() * 0xffffffff).toString(36)}`; } function ensureWorldSeed(worldRef = null) { if (!worldRef) return createWorldSeed(); if (!worldRef.worldSeed) worldRef.worldSeed = createWorldSeed(); if (!Number.isFinite(worldRef.birthSerial)) worldRef.birthSerial = 0; return worldRef.worldSeed; } function childSeed(worldSeed = "", serial = 0, parentSeeds = []) { const safeSerial = Math.max(0, Math.floor(Number(serial) || 0)); const parents = (parentSeeds || []).filter(Boolean).join("+"); // \u533a\u5207\u308a\u3092\u5165\u308c\u3066\u304a\u304f\u3068\u3001\u5c06\u6765 birthSeed \u81ea\u4f53\u3092\u4fdd\u5b58\u3057\u306a\u3044\u5f62\u5f0f\u3078\u79fb\u308b\u6642\u306b // birthSerial \u3092\u5b89\u5168\u306b\u53d6\u308a\u51fa\u305b\u308b\u3002 return `b${safeSerial.toString(36)}_${hashString(`${worldSeed}|${safeSerial}|${parents}`)}`; } function serialFromBirthSeed(seed = "") { const match = /^b([0-9a-z]+)_/i.exec(String(seed || "")); if (!match) return 0; const n = parseInt(match[1], 36); return Number.isFinite(n) && n > 0 ? n : 0; } function prepareAddOptions(worldRef, opts = {}) { const next = { ...(opts || {}) }; ensureWorldSeed(worldRef); if (!next.birthSeed) { worldRef.birthSerial = Math.max(0, Number(worldRef.birthSerial) || 0) + 1; next.birthSerial = worldRef.birthSerial; const parentSeeds = Array.isArray(next.seedParents) ? next.seedParents.map(p => typeof p === "string" ? p : (p?.birthSeed || p?.familyKey || p?.id || "")) : []; next.birthSeed = childSeed(worldRef.worldSeed, next.birthSerial, parentSeeds); } else { if (!Number.isFinite(next.birthSerial)) { const parsedSerial = serialFromBirthSeed(next.birthSeed); if (parsedSerial > 0) next.birthSerial = parsedSerial; } if (Number.isFinite(next.birthSerial)) { worldRef.birthSerial = Math.max(Number(worldRef.birthSerial) || 0, Number(next.birthSerial) || 0); } } if (!next.familyKey) next.familyKey = next.birthSeed; return next; } function seedUnit(seed = "", key = "") { return stableUnit(seed, key); } function seedPick(seed = "", key = "", list = []) { if (!list?.length) return null; const i = Math.min(list.length - 1, Math.floor(seedUnit(seed, key) * list.length)); return list[i]; } function seededName(seed = "") { const len = 2 + Math.floor(seedUnit(seed, "name.len") * 6); // 2..7 const hasStop = len >= 2 && seedUnit(seed, "name.stop") < 0.30; const middleLen = Math.max(0, len - 1 - (hasStop ? 1 : 0)); let name = "\u306f"; for (let i = 0; i < middleLen; i++) name += seedUnit(seed, `name.u.${i}`) < 0.64 ? "\u3046" : "\u3045"; if (hasStop) name += "\u3063"; return name; } function seededType(seed = "") { const list = typeof spawnableSprites === "function" ? spawnableSprites().map(s => s.id).filter(Boolean) : ["smile"]; return seedPick(seed, "sprite.base", list) || "smile"; } function seededGoodMode(seed = "") { const list = typeof displayNormalSprites === "function" ? displayNormalSprites() : ["smile", "jito", "normal_smirk"]; return seedPick(seed, "sprite.good", list) || "smile"; } function seededPersonality(seed = "") { if (typeof randomBirthPersonality === "function") return randomBirthPersonality(seed); return { aggression: 0, openness: 0, sociability: 0, neuroticism: 0 }; } function seededGenetics(seed = "") { if (typeof normalizeGenetics === "function") return normalizeGenetics(null, seed); return { lifeSpanMul: 1, attackMul: 1, speedMul: 1, sizeMul: 1, temperatureOffset: 0 }; } function seededAdultScale(seed = "", genetics = null) { if (typeof adultScaleFromGenetics === "function") return adultScaleFromGenetics(seed, genetics); return 0.28; } function seededLifeSpan(seed = "", genetics = null) { const g = genetics || seededGenetics(seed); const base = 1400 + seedUnit(seed, "life.span") * 800; let span = base * (g.lifeSpanMul || 1); if (span < 900) span = (1200 + seedUnit(seed, "life.span.low") * 600) * (g.lifeSpanMul || 1); return span; } function birthProfile(seed = "", opts = {}) { const zunchiSlave = Boolean(opts.isZunchiSlave || opts.zunchiSlaveLocked); const genetics = opts.genetics && typeof normalizeGenetics === "function" ? normalizeGenetics(opts.genetics, seed) : seededGenetics(seed); const personality = zunchiSlave && typeof zunchiSlavePersonalityValue === "function" ? zunchiSlavePersonalityValue() : seededPersonality(seed); return { birthSeed: seed, name: zunchiSlave ? "\u305a\u3093\u3061\u3069\u308c\u3044" : seededName(seed), type: zunchiSlave ? "zunchi_slave" : seededType(seed), goodMode: zunchiSlave ? "zunchi_slave" : seededGoodMode(seed), birthPersonality: personality, genetics, adultScale: seededAdultScale(seed, genetics), lifeSpan: seededLifeSpan(seed, genetics), }; } function personalityArray(seed = "") { const p = birthProfile(seed).birthPersonality || {}; return ["aggression", "openness", "sociability", "neuroticism"].map(k => Math.round(((Number(p[k]) || 0) + 1) * 100)); } global.TarinaiSeedFactory = Object.freeze({ createWorldSeed, ensureWorldSeed, childSeed, serialFromBirthSeed, prepareAddOptions, birthProfile, personalityArray, }); })(typeof window !== "undefined" ? window : globalThis);