// === スコア基本値 & レア度倍率 === const BASE_BIG = 1000; const BASE_REG = 300; const rarityMultiplier = { common: 1.2, uncommon: 1.4, rare: 1.6, ultra: 1.8, final: 2.0 }; function rarityLabel(r) { switch (r) { case "common": return "コモン"; case "uncommon": return "アンコモン"; case "rare": return "レア"; case "ultra": return "ウルトラレア"; case "final": return "ファイナルレア"; default: return r; } } // === 設定ごとの確率(アイム準拠の簡易モデル) === const settingTable = { 1: { grape: 1/6.49, cherry: 1/35, big: 1/287, reg: 1/455 }, 2: { grape: 1/6.44, cherry: 1/35, big: 1/282, reg: 1/431 }, 3: { grape: 1/6.40, cherry: 1/35, big: 1/273, reg: 1/372 }, 4: { grape: 1/6.37, cherry: 1/35, big: 1/264, reg: 1/336 }, 5: { grape: 1/6.33, cherry: 1/35, big: 1/252, reg: 1/302 }, 6: { grape: 1/6.00, cherry: 1/35, big: 1/240, reg: 1/287 } }; // 設定の重み(設定1が多い) const settingWeights = [ { setting: 1, w: 60 }, { setting: 2, w: 16 }, { setting: 3, w: 10 }, { setting: 4, w: 7 }, { setting: 5, w: 5 }, { setting: 6, w: 2 } ]; function chooseRandomSetting() { const total = settingWeights.reduce((s, x) => s + x.w, 0); let r = Math.random() * total; for (const item of settingWeights) { if (r < item.w) return item.setting; r -= item.w; } return 1; } // === コレクション取得 === function getCollectedCharacters() { const collectedIds = JSON.parse(localStorage.getItem("collection") || "[]"); if (collectedIds.length === 0) return characters.slice(); return characters.filter(c => collectedIds.includes(c.id)); } const allCollected = getCollectedCharacters(); function pickRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } // === BIG/REG キャラ & 小役キャラ === let bigChar = null; let regChar = null; let grapeChar = null; let cherryChar = null; function chooseBonusCharacters() { bigChar = pickRandom(allCollected); do { regChar = pickRandom(allCollected); } while (regChar.id === bigChar.id); // 小役キャラも選ぶ do { grapeChar = pickRandom(allCollected); } while (grapeChar.id === bigChar.id || grapeChar.id === regChar.id); do { cherryChar = pickRandom(allCollected); } while (cherryChar.id === bigChar.id || cherryChar.id === regChar.id || cherryChar.id === grapeChar.id); document.getElementById("bigInfo").textContent = `BIG図柄:${bigChar.name}(${rarityLabel(bigChar.rarity)})`; document.getElementById("regInfo").textContent = `REG図柄:${regChar.name}(${rarityLabel(regChar.rarity)})`; } // === リール・状態 === const reelImgs = [ document.getElementById("reel0"), document.getElementById("reel1"), document.getElementById("reel2") ]; const cardBack = "assets/card_back.png"; let spinning = false; let stopped = [false, false, false]; let currentSetting = null; let currentResult = "NONE"; // "BIG" "REG" "GRAPE" "CHERRY" "NONE" let decidedSymbols = [null, null, null]; // スコア let totalScore = parseInt(localStorage.getItem("slotTotalScore") || "0"); let bestScore = parseInt(localStorage.getItem("slotBestScore") || "0"); function updateScoreBoard() { document.getElementById("totalScore").textContent = totalScore; document.getElementById("bestScore").textContent = bestScore; } updateScoreBoard(); chooseBonusCharacters(); const lamp = document.getElementById("gogoLamp"); const gakoSound = document.getElementById("gakoSound"); const leverBtn = document.getElementById("leverBtn"); const stopBtns = [ document.getElementById("stop0"), document.getElementById("stop1"), document.getElementById("stop2") ]; const lastResultEl = document.getElementById("lastResult"); function resetReels() { for (let i = 0; i < 3; i++) { reelImgs[i].src = cardBack; stopped[i] = false; } } function enableStops(enable) { stopBtns.forEach(btn => btn.disabled = !enable); } // === 小役抽選 → ボーナス抽選 → ハズレ === function lottery() { const st = currentSetting; const tbl = settingTable[st]; // ① ブドウ if (Math.random() < tbl.grape) return "GRAPE"; // ② チェリー if (Math.random() < tbl.cherry) return "CHERRY"; // ③ ボーナス if (Math.random() < tbl.big) return "BIG"; if (Math.random() < tbl.reg) return "REG"; // ④ ハズレ return "NONE"; } // === レバーON === leverBtn.addEventListener("click", () => { if (spinning) return; if (!currentSetting) currentSetting = chooseRandomSetting(); spinning = true; lamp.classList.remove("on"); resetReels(); enableStops(true); lastResultEl.textContent = ""; currentResult = lottery(); // 小役・ボーナス決定に応じて停止図柄を決める decidedSymbols = [null, null, null]; if (currentResult === "BIG") { decidedSymbols = [bigChar, bigChar, bigChar]; } else if (currentResult === "REG") { decidedSymbols = [regChar, regChar, regChar]; } else if (currentResult === "GRAPE") { decidedSymbols = [grapeChar, grapeChar, grapeChar]; } else if (currentResult === "CHERRY") { decidedSymbols = [ cherryChar, pickRandom(allCollected), pickRandom(allCollected) ]; } else { for (let i = 0; i < 3; i++) { decidedSymbols[i] = pickRandom(allCollected); } } // ボーナスの場合はペカ&ガコッ if (currentResult === "BIG" || currentResult === "REG") { const delay = 200 + Math.random() * 800; setTimeout(() => { lamp.classList.add("on"); try { gakoSound.currentTime = 0; gakoSound.play(); } catch(e){} }, delay); } }); // === ストップ処理 === stopBtns.forEach((btn, i) => { btn.addEventListener("click", () => { if (!spinning || stopped[i]) return; stopped[i] = true; reelImgs[i].src = decidedSymbols[i].image; if (stopped.every(v => v)) { spinning = false; enableStops(false); evaluate(); } }); }); // === 判定 === function evaluate() { if (currentResult === "BIG" || currentResult === "REG") { const char = (currentResult === "BIG") ? bigChar : regChar; const base = (currentResult === "BIG") ? BASE_BIG : BASE_REG; const mul = rarityMultiplier[char.rarity]; const add = Math.round(base * mul); totalScore += add; if (totalScore > bestScore) bestScore = totalScore; localStorage.setItem("slotTotalScore", totalScore); localStorage.setItem("slotBestScore", bestScore); updateScoreBoard(); lastResultEl.textContent = `${currentResult} 当選! +${add}点`; } else if (currentResult === "GRAPE") { totalScore += 3; lastResultEl.textContent = `ブドウ +3点`; } else if (currentResult === "CHERRY") { totalScore += 10; lastResultEl.textContent = `チェリー +10点`; } else { lastResultEl.textContent = "ハズレ…"; } localStorage.setItem("slotTotalScore", totalScore); // たまに設定変更 if (Math.random() < 0.05) { currentSetting = null; } }