// ==UserScript== // @name Torn Chest Solver (No-Zero Edition) // @namespace Gemini.Torn // @version 5.9 // @description 4x3 grid, "Suggested Number" title, logic restricted to digits 1-9. // @author Gemini // @match *.torn.com/christmas_town.php* // @grant none // @downloadURL https://update.greasyfork.icu/scripts/559905/Torn%20Chest%20Solver%20%28No-Zero%20Edition%29.user.js // @updateURL https://update.greasyfork.icu/scripts/559905/Torn%20Chest%20Solver%20%28No-Zero%20Edition%29.meta.js // ==/UserScript== (function() { 'use strict'; let storage = JSON.parse(localStorage.getItem('tornSolverData')) || { history: [], currentInput: [], x: 20, y: 80, minimized: false }; if (storage.x < 0 || storage.x > window.innerWidth) storage.x = 20; if (storage.y < 0 || storage.y > window.innerHeight) storage.y = 80; function saveData() { localStorage.setItem('tornSolverData', JSON.stringify(storage)); } let showHelp = false; const style = document.createElement('style'); style.innerHTML = ` @keyframes blinker { 50% { opacity: 0.2; color: #fff; } } .blinking-link { animation: blinker 1.2s linear infinite; } .help-text b { color: #0f0; font-size: 12px; } .help-text p { margin: 8px 0; color: #ccc; } .num-btn { padding: 12px 0; background: #333; color: #fff; border: none; border-radius: 4px; font-weight: bold; font-size: 16px; cursor: pointer; } .num-btn:active { background: #555; } `; document.head.appendChild(style); function createUI() { if (document.getElementById("torn-solver-window")) return; const container = document.createElement('div'); container.id = "torn-solver-window"; container.style = `position: fixed; top: ${storage.y}px; left: ${storage.x}px; z-index: 999999; background: #222; color: #fff; border-radius: 10px; border: 2px solid #444; font-family: sans-serif; width: 250px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); touch-action: none; user-select: none;`; const header = document.createElement('div'); header.style = "background: #444; padding: 10px; cursor: move; border-radius: 8px 8px 0 0; display: flex; justify-content: space-between; align-items: center; touch-action: none;"; header.innerHTML = ` COMBO SOLVER `; container.appendChild(header); const contentArea = document.createElement('div'); contentArea.style = "padding: 10px; display: " + (storage.minimized ? "none" : "block"); container.appendChild(contentArea); document.body.appendChild(container); const render = () => { if (storage.minimized) { contentArea.style.display = "none"; document.getElementById('min-btn').innerText = "□"; container.style.width = "140px"; } else if (showHelp) { contentArea.style.display = "block"; container.style.width = "250px"; contentArea.innerHTML = `
🌟 STEP 1: LOOK AT THE BOX

At the top, this tool shows a "Suggested Number." Type those numbers into the game and into this tool's keypad.

🌟 STEP 2: COPY THE COLORS

After you guess in the game, the game boxes will turn colors. Tap the boxes in THIS tool to match them!

🌟 STEP 3: WHAT COLORS MEAN?

Gray: We haven't guessed yet.
🟥 Red: That number is NOT in the code.
🟨 Yellow: The number is correct, but in the WRONG spot.
🟩 Green: Perfect! This number is correct and in the right spot.

🌟 STEP 4: HIT THE "OK" BUTTON

Once the colors in this tool match the game colors, hit OK. The tool will calculate the next best guess!


Questions, comments, and concerns can be directed to:

Weeb_Phydoe [3262527]
`; document.getElementById('close-help').onclick = () => { showHelp = false; render(); }; } else { contentArea.style.display = "block"; container.style.width = "250px"; const {suggestion, prob} = solveLogic(); contentArea.innerHTML = `
✨ SUGGESTED NUMBER ✨
${suggestion}
Win Chance: ${prob}%
${[0,1,2].map(i => { const item = storage.currentInput[i] || {num: '-', color: '#444'}; return `
${item.num}
`; }).join('')}
${[1,2,3,4,5,6,7,8,9,'C','OK'].map(k => { let style = ""; if (k === 'OK') style = "background:#080; grid-column: span 2;"; if (k === 'C') style = "background:#800;"; return ``; }).join('')}
`; contentArea.querySelectorAll('.input-slot').forEach(slot => { slot.onclick = () => { const i = slot.getAttribute('data-index'); if (!storage.currentInput[i]) return; const colors = ['#666', '#ff4444', '#ffcc00', '#00aa00']; storage.currentInput[i].color = colors[(colors.indexOf(storage.currentInput[i].color) + 1) % colors.length]; saveData(); render(); }; }); contentArea.querySelectorAll('.num-btn').forEach(btn => btn.onclick = () => { const v = btn.getAttribute('data-val'); if (v === 'C') storage.currentInput = []; else if (v === 'OK' && storage.currentInput.length === 3) { storage.history.push([...storage.currentInput]); storage.currentInput = []; } else if (storage.currentInput.length < 3 && !isNaN(v)) { storage.currentInput.push({num: v, color: '#666'}); } saveData(); render(); }); document.getElementById('reset-game-btn').onclick = () => { storage.history = []; storage.currentInput = []; saveData(); render(); }; } }; let isDragging = false, startX, startY; const dStart = (e) => { const t = e.touches ? e.touches[0] : e; isDragging = true; startX = t.clientX - container.offsetLeft; startY = t.clientY - container.offsetTop; }; const dMove = (e) => { if (!isDragging) return; const t = e.touches ? e.touches[0] : e; storage.x = t.clientX - startX; storage.y = t.clientY - startY; container.style.left = storage.x + "px"; container.style.top = storage.y + "px"; if (e.cancelable) e.preventDefault(); }; const dEnd = () => { isDragging = false; saveData(); }; header.addEventListener('mousedown', dStart); header.addEventListener('touchstart', dStart, {passive: false}); window.addEventListener('mousemove', dMove); window.addEventListener('touchmove', dMove, {passive: false}); window.addEventListener('mouseup', dEnd); window.addEventListener('touchend', dEnd); document.getElementById('help-toggle').onclick = () => { showHelp = !showHelp; render(); }; document.getElementById('min-btn').onclick = () => { storage.minimized = !storage.minimized; saveData(); render(); }; render(); } function solveLogic() { let possibilities = []; for (let i = 111; i <= 999; i++) { let p = i.toString().split(''); if (!p.includes('0') && new Set(p).size === 3) possibilities.push(p); } storage.history.forEach(attempt => { possibilities = possibilities.filter(p => { for (let i = 0; i < 3; i++) { const color = attempt[i].color; const num = attempt[i].num; if (color === '#00aa00' && p[i] !== num) return false; if (color === '#ff4444' && p.includes(num)) return false; if (color === '#ffcc00') { if (!p.includes(num) || p[i] === num) return false; } } return true; }); }); const count = possibilities.length; const confidence = count === 0 ? 0 : Math.floor(100 / count); // Turn 1, 2, 3 Sweep (using only 1-9) if (storage.history.length < 3 && count > 1) { let tested = new Set(); storage.history.forEach(att => att.forEach(item => tested.add(item.num))); let untried = "123456789".split("").filter(d => !tested.has(d)); if (untried.length >= 3) return { suggestion: untried.slice(0,3).join(" "), prob: confidence }; } return { suggestion: possibilities[0] ? possibilities[0].join(" ") : "???", prob: confidence }; } setInterval(createUI, 2000); createUI(); })();