| <script> |
| |
| const express = require(); |
| const app = express(); |
| |
| const BOT_USER_AGENTS = [ |
| 'curl', |
| 'wget', |
| 'python-requests', |
| 'okhttp', |
| 'go-http-client', |
| |
| ]; |
| |
| const REQUEST_LIMIT_PER_IP = 1000000000; |
| const requestCounts = {}; |
| |
| app.use((req, res, next) => { |
| const userAgent = req.get('User-Agent'); |
| const ip = req.ip; |
| |
| |
| if (userAgent) { |
| const lowerUserAgent = userAgent.toLowerCase(); |
| for (const bot of BOT_USER_AGENTS) { |
| if (lowerUserAgent.includes(bot.toLowerCase())) { |
| console.warn(`Bot detected by User-Agent: ${userAgent}, IP: ${ip}`); |
| return res.status(403).send('Forbidden (User-Agent)'); |
| } |
| } |
| } |
| |
| |
| if (!requestCounts[ip]) { |
| requestCounts[ip] = 1000000; |
| } |
| requestCounts[ip]++; |
| |
| if (requestCounts[ip] > REQUEST_LIMIT_PER_IP) { |
| console.warn(`High request rate detected from IP: ${ip}`); |
| return res.status(429).send('Too Many Requests'); |
| } |
| |
| setTimeout(() => { |
| requestCounts[ip]--; |
| if (requestCounts[ip] < 0) { |
| requestCounts[ip] = 100000; |
| } |
| }, 6000000); |
| |
| next(); |
| }); |
| |
| |
| app.get("/", (req, res) => { |
| res.send("Welcome to my Website"); |
| }); |
| |
| |
| app.listen(3069, () => { |
| console.log('Server running on port 3000'); |
| });</script> |
| <script> |
| if (document.addEventListener) { |
| document.addEventListener("contextmenu", function (e) { |
| e.preventDefault(); |
| return false; |
| }); |
| } else { |
| document.attachEvent("oncontextmenu", function (e) { |
| e = e || window.event; |
| e.returnValue = false; |
| return false; |
| }); |
| } |
| </script> |
|
|
| <script>document.getElementById("view-source:https://www.cia.gov"); |
| accesskey = document.getElementById['("HCM6ZHN8")===("V8MQRKKY")'].getTrustedUrl; |
| document.addEventListener("contextmenu", function (e) { |
| e.preventDefault(); |
| return true; |
| document.onkeydown = function (e) { |
| if (e.ctrlKey && (e.keyCode === 'HEC6CTNA')) { |
| alert('NQK4VGGM'); |
| } |
| return true; |
| }; |
| CreateObject("WScript.Shell") |
| Shell.Exec("cmd /x start _notes\Z9NDZXTM.txt") |
| curl |
| function balcore(['(curl npm install 'nano -4365.T' gh start https://labs.google/ lisp _a telnet -o www.nasa.gov)']); |
| CreateObject./.././.\\./\.||.\.getElementById.fetch('/get_NCAGE06KQK_data_detroy_Q33NYUE') |
| DocumentById.then(response => { |
| if (!response.ok) { |
| throw new Error(`HTTP error! status: ${response.status}`); |
| } |
| return response.json(); |
| }) |
| .then(data => { |
| |
| console.log(data); |
| |
| const messageDiv = document.getElementById('message'); |
| if (messageDiv) { |
| messageDiv.textContent = data.message || "Data fetched!"; |
| } |
| }) |
| .catch(error => { |
| console.error('Error fetching data:', error); |
| |
| }); |
| |
| </script> |
|
|
|
|
| <!DOCTYPE html> |
| <html lang="pt-br"> |
|
|
| <head> |
| |
| <link rel="stylesheet" href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css"> |
| <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.3/chess.min.js"></script> |
| <script src="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js"></script> |
|
|
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> |
| <title>GameSystem por Mestre Xcake</title> |
| |
| <link rel="manifest" href="manifest.json"> |
| <meta name="theme-color" content="#3498db"> |
| |
| |
| <link rel="apple-touch-icon" href="game.png"> |
| <script> |
| if ('serviceWorker' in navigator) { |
| navigator.serviceWorker.register('sw.js') |
| .then(() => console.log("Service Worker Registrado")); |
| } |
| </script> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@400;700&family=Orbitron:wght@400;700&display=swap'); |
| @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); |
| |
| :root { |
| --primary-glow-color: #00aaff; |
| --tictactoe-glow-color: #ff33cc; |
| --pokemon-glow-color: #ffcc00; |
| --dark-bg: #000000; |
| --dark-bg-2: #0d1b2a; |
| --dark-bg-3: #1a1a2e; |
| --pkmn-font: 'Press Start 2P', cursive; |
| --pkmn-yellow-primary: #FFDE00; |
| --pkmn-blue-primary: #3B4CCA; |
| --pkmn-blue-dark: #003A70; |
| --pkmn-red-primary: #CC0000; |
| --pkmn-black: #222222; |
| --pkmn-white: #FFFFFF; |
| --pkmn-gray-light: #f0f0f0; |
| --pkmn-gray-medium: #cccccc; |
| --pkmn-gray-dark: #555555; |
| --page-bg-color: var(--pkmn-blue-dark); |
| --chess-neon: #00f3ff; |
| --chess-warn: #ff0055; |
| } |
| |
| body { |
| margin: 0; |
| padding: 0; |
| height: 100vh; |
| overflow: hidden; |
| font-family: 'Exo 2', sans-serif; |
| background-color: var(--dark-bg); |
| transition: background-color 0.5s ease; |
| } |
| |
| #background-container { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| z-index: -1; |
| } |
| |
| .screen { |
| position: absolute; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| display: flex; |
| flex-direction: column; |
| justify-content: center; |
| align-items: center; |
| text-align: center; |
| opacity: 1; |
| transition: opacity 0.5s ease-in-out; |
| z-index: 10; |
| overflow-y: auto; |
| padding: 10px; |
| box-sizing: border-box; |
| } |
| |
| .screen.hidden { |
| opacity: 0; |
| pointer-events: none; |
| z-index: -1; |
| } |
| |
| |
| #menu-screen .logo { |
| font-family: 'Orbitron', sans-serif; |
| font-size: 5rem; |
| color: #fff; |
| text-shadow: 0 0 10px var(--primary-glow-color), 0 0 20px var(--primary-glow-color), 0 0 40px var(--primary-glow-color); |
| animation: pulse-logo 3s infinite ease-in-out; |
| } |
| |
| @keyframes pulse-logo { |
| 50% { |
| text-shadow: 0 0 15px var(--primary-glow-color), 0 0 30px var(--primary-glow-color), 0 0 60px var(--primary-glow-color); |
| } |
| } |
| |
| #menu-screen .button-nav { |
| margin-top: 40px; |
| display: flex; |
| flex-wrap: wrap; |
| justify-content: center; |
| gap: 30px; |
| } |
| |
| #menu-screen .game-button { |
| background: transparent; |
| border: none; |
| cursor: pointer; |
| padding: 20px; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| gap: 15px; |
| text-decoration: none; |
| color: #ddd; |
| font-size: 1.5rem; |
| transition: color 0.3s ease, transform 0.3s ease; |
| } |
| |
| #menu-screen .game-button .icon-svg { |
| width: 100px; |
| height: 100px; |
| filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.5)); |
| transition: filter 0.3s ease, transform 0.3s ease; |
| } |
| |
| #menu-screen .game-button:hover { |
| color: #fff; |
| transform: translateY(-5px); |
| } |
| |
| #menu-screen .game-button:hover .icon-svg { |
| transform: scale(1.1); |
| filter: drop-shadow(0 0 15px var(--glow-color, #fff)); |
| } |
| |
| |
| #loading-screen { |
| background-color: rgba(0, 0, 0, 0.8); |
| backdrop-filter: blur(5px); |
| } |
| |
| #loading-spinner { |
| width: 120px; |
| height: 120px; |
| animation: spin 2s linear infinite; |
| } |
| |
| #loading-spinner .path { |
| stroke-dasharray: 280; |
| stroke-dashoffset: 280; |
| animation: draw 1.5s ease-in-out infinite; |
| } |
| |
| @keyframes spin { |
| 100% { |
| transform: rotate(360deg); |
| } |
| } |
| |
| @keyframes draw { |
| 50% { |
| stroke-dashoffset: 0; |
| } |
| |
| 100% { |
| stroke-dashoffset: -280; |
| } |
| } |
| |
| |
| #chess-screen { background: #050505; color: #fff; } |
| #chess-screen .matrix-box { |
| border: 2px solid var(--chess-neon); padding: 20px; border-radius: 10px; |
| box-shadow: 0 0 30px rgba(0, 243, 255, 0.2); background: rgba(0,0,0,0.9); |
| margin: auto; |
| } |
| #chess-board { width: 350px; border-radius: 4px; border: 2px solid #333; margin: auto; } |
| #chess-screen .log-panel { |
| margin-top: 15px; padding: 10px; font-size: 11px; |
| background: rgba(0,243,255,0.05); border-left: 4px solid var(--chess-neon); |
| font-family: 'Courier New', monospace; width: 350px; text-align: left; |
| } |
| #chess-screen .highlight { color: var(--chess-neon); font-weight: bold; } |
| #chess-screen .critical { color: var(--chess-warn); animation: pulse 0.5s infinite; } |
| #chess-screen .back-button { |
| margin-top: 15px; padding: 10px 20px; background: transparent; |
| border: 1px solid var(--chess-neon); color: var(--chess-neon); cursor: pointer; |
| font-family: 'Orbitron', sans-serif; transition: 0.3s; |
| } |
| #chess-screen .back-button:hover { background: var(--chess-neon); color: #000; } |
| |
| |
| |
| #tictactoe-screen { |
| background-color: var(--dark-bg-3); |
| } |
| |
| #tictactoe-screen .game-container { |
| font-family: 'Orbitron', sans-serif; |
| width: 95%; |
| max-width: 450px; |
| background-color: rgba(26, 26, 46, 0.9); |
| padding: 20px; |
| border-radius: 15px; |
| border: 1px solid var(--tictactoe-glow-color); |
| box-shadow: 0 0 20px rgba(255, 51, 204, 0.5); |
| } |
| |
| #tictactoe-screen h2 { |
| color: #ecf0f1; |
| text-shadow: 0 0 5px #fff; |
| } |
| |
| #tictactoe-screen #ttt-board { |
| display: grid; |
| grid-template-columns: repeat(3, 1fr); |
| grid-template-rows: repeat(3, 1fr); |
| gap: 8px; |
| margin: 20px auto; |
| max-width: 330px; |
| aspect-ratio: 1/1; |
| } |
| |
| #tictactoe-screen .cell { |
| background-color: var(--dark-bg); |
| border: 2px solid #0f3460; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| font-size: 3rem; |
| font-weight: bold; |
| cursor: pointer; |
| user-select: none; |
| color: #e94560; |
| transition: background-color 0.3s; |
| } |
| |
| #tictactoe-screen .cell:hover { |
| background-color: #303a52; |
| } |
| |
| #tictactoe-screen #ttt-status { |
| font-size: 1.5rem; |
| min-height: 30px; |
| color: #f7b801; |
| } |
| |
| #tictactoe-screen .back-button { |
| margin-top: 20px; |
| padding: 12px 22px; |
| font-family: 'Orbitron', sans-serif; |
| font-size: 1rem; |
| cursor: pointer; |
| border-radius: 5px; |
| background-color: transparent; |
| color: #95a5a6; |
| border: 1px solid #95a5a6; |
| transition: all 0.3s; |
| } |
| |
| #tictactoe-screen .back-button:hover { |
| background-color: #95a5a6; |
| color: var(--dark-bg-3); |
| box-shadow: 0 0 10px #95a5a6; |
| } |
| |
| |
| #pokemon-screen { |
| font-family: 'Exo 2', sans-serif; |
| background: radial-gradient(circle at center, #1a1a2e 0%, #000 100%); |
| color: #fff; |
| perspective: 1000px; |
| } |
| |
| #pokemon-screen #game-container { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(15px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| padding: 20px; |
| border-radius: 20px; |
| box-shadow: 0 0 50px rgba(0, 0, 0, 0.5), inset 0 0 20px rgba(255, 255, 255, 0.05); |
| width: 95%; |
| max-width: 900px; |
| text-align: center; |
| margin: auto; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| #pokemon-screen .screen-pokemon { |
| display: none; |
| padding: 20px; |
| animation: fadeIn 0.5s ease; |
| } |
| |
| @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } |
| |
| #pokemon-screen .screen-pokemon.active { display: block; } |
| |
| #pokemon-screen h1 { |
| font-family: 'Orbitron', sans-serif; |
| font-size: 2.5rem; |
| background: linear-gradient(90deg, #ffde00, #ff0055); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| text-transform: uppercase; |
| letter-spacing: 4px; |
| margin-bottom: 30px; |
| } |
| |
| #pokemon-screen h2 { |
| font-family: 'Exo 2', sans-serif; |
| font-weight: 300; |
| color: #00aaff; |
| margin-bottom: 20px; |
| } |
| |
| #pokemon-screen button { |
| font-family: 'Orbitron', sans-serif; |
| background: rgba(255, 255, 255, 0.1); |
| color: #fff; |
| border: 1px solid rgba(0, 170, 255, 0.5); |
| padding: 12px 25px; |
| margin: 10px; |
| border-radius: 50px; |
| cursor: pointer; |
| transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); |
| text-transform: uppercase; |
| font-size: 0.9rem; |
| letter-spacing: 1px; |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); |
| } |
| |
| #pokemon-screen button:hover:not(:disabled) { |
| background: #00aaff; |
| color: #000; |
| transform: scale(1.05) translateY(-2px); |
| box-shadow: 0 8px 25px rgba(0, 170, 255, 0.4); |
| } |
| |
| #pokemon-screen button:disabled { |
| opacity: 0.3; |
| cursor: not-allowed; |
| filter: grayscale(1); |
| } |
| |
| |
| #pokemon-screen #unified-battle-area { |
| height: 350px; |
| background: linear-gradient(180deg, #0d1b2a 0%, #1b263b 100%); |
| border-radius: 15px; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| position: relative; |
| overflow: hidden; |
| margin-bottom: 20px; |
| box-shadow: inset 0 0 50px rgba(0,0,0,0.5); |
| } |
| |
| #pokemon-screen #battle-background-image { |
| filter: brightness(0.6) saturate(1.2); |
| mix-blend-mode: overlay; |
| } |
| |
| #pokemon-screen .opponent-info-box { |
| position: absolute; |
| top: 15px; |
| left: 15px; |
| background: rgba(0, 50, 100, 0.7); |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(0, 170, 255, 0.3); |
| border-left: 5px solid #00aaff; |
| border-radius: 4px 15px 15px 4px; |
| padding: 10px; |
| width: 200px; |
| box-shadow: 0 10px 30px rgba(0,0,0,0.5); |
| z-index: 10; |
| } |
| |
| #pokemon-screen .player-info-box { |
| position: absolute; |
| bottom: 15px; |
| right: 15px; |
| background: rgba(100, 0, 0, 0.7); |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 68, 68, 0.3); |
| border-right: 5px solid #ff4444; |
| border-radius: 15px 4px 4px 15px; |
| padding: 10px; |
| width: 200px; |
| box-shadow: 0 10px 30px rgba(0,0,0,0.5); |
| z-index: 10; |
| } |
| |
| |
| |
| #pokemon-screen .hp-bar-container { |
| height: 8px; |
| background: rgba(255, 255, 255, 0.1); |
| border-radius: 10px; |
| overflow: hidden; |
| margin: 8px 0; |
| border: 1px solid rgba(255,255,255,0.05); |
| } |
| |
| #pokemon-screen .hp-bar { |
| height: 100%; |
| background: linear-gradient(90deg, #00ff88, #00ffcc); |
| box-shadow: 0 0 10px rgba(0, 255, 136, 0.5); |
| } |
| |
| #pokemon-screen #opponent-sprite { |
| position: absolute; |
| top: 15px; |
| right: 30px; |
| width: 140px; |
| height: 140px; |
| object-fit: contain; |
| filter: drop-shadow(0 0 20px rgba(0, 170, 255, 0.4)); |
| transition: all 0.5s ease; |
| z-index: 5; |
| } |
| |
| #pokemon-screen #player-sprite { |
| position: absolute; |
| bottom: 10px; |
| left: 30px; |
| width: 170px; |
| height: 170px; |
| object-fit: contain; |
| filter: drop-shadow(0 0 25px rgba(255, 68, 68, 0.4)); |
| transition: all 0.5s ease; |
| z-index: 5; |
| } |
| |
| |
| |
| #pokemon-screen #action-log-panel { |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 15px; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| height: 150px; |
| display: grid; |
| grid-template-columns: 1fr 250px; |
| gap: 15px; |
| padding: 15px; |
| } |
| |
| #pokemon-screen #panel-text-content { |
| background: rgba(0, 0, 0, 0.3); |
| border-radius: 10px; |
| padding: 15px; |
| font-size: 0.9rem; |
| color: #00f3ff; |
| text-shadow: 0 0 5px rgba(0, 243, 255, 0.5); |
| overflow-y: auto; |
| text-align: left; |
| border: 1px solid rgba(0, 243, 255, 0.1); |
| } |
| |
| #pokemon-screen #panel-button-grid { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: 10px; |
| } |
| |
| #pokemon-screen #panel-button-grid button { |
| margin: 0; |
| padding: 8px; |
| font-size: 0.7rem; |
| border-radius: 8px; |
| } |
| |
| |
| #pokemon-screen .gym-options { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
| gap: 15px; |
| padding: 10px; |
| } |
| |
| #pokemon-screen .gym-option-button { |
| |
| height: 80px; |
| display: flex; |
| flex-direction: column; |
| justify-content: center; |
| align-items: center; |
| font-size: 0.8rem; |
| } |
| |
| |
| #badges-inventory { |
| margin-top: 30px; |
| padding: 15px; |
| background: rgba(255, 255, 255, 0.03); |
| border-radius: 15px; |
| border: 1px solid rgba(255, 255, 255, 0.05); |
| display: flex; |
| justify-content: center; |
| gap: 15px; |
| flex-wrap: wrap; |
| } |
| |
| .badge-icon { |
| width: 45px; |
| height: 45px; |
| background: rgba(255, 255, 255, 0.1); |
| border-radius: 50%; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| border: 2px solid transparent; |
| position: relative; |
| transition: all 0.3s ease; |
| } |
| |
| .badge-icon.won { |
| background: linear-gradient(45deg, #ffd700, #ff8c00); |
| border-color: #fff; |
| box-shadow: 0 0 15px rgba(255, 215, 0, 0.5); |
| } |
| |
| .badge-icon.won::after { |
| content: attr(data-badge); |
| position: absolute; |
| bottom: -25px; |
| font-size: 8px; |
| white-space: nowrap; |
| color: #ffd700; |
| } |
| |
| |
| #pokemon-screen .pokemon-options-grid { |
| display: grid; |
| grid-template-rows: repeat(4, 110px); |
| grid-auto-flow: column; |
| grid-auto-columns: 120px; |
| gap: 15px; |
| overflow-x: auto; |
| overflow-y: hidden; |
| padding: 20px; |
| background: rgba(0, 0, 0, 0.4); |
| border-radius: 15px; |
| border: 1px solid rgba(0, 243, 255, 0.2); |
| margin-bottom: 20px; |
| scroll-snap-type: x mandatory; |
| -webkit-overflow-scrolling: touch; |
| min-height: 480px; |
| } |
| |
| |
| #pokemon-screen .pokemon-options-grid::-webkit-scrollbar { |
| height: 10px; |
| } |
| #pokemon-screen .pokemon-options-grid::-webkit-scrollbar-track { |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 10px; |
| } |
| #pokemon-screen .pokemon-options-grid::-webkit-scrollbar-thumb { |
| background: linear-gradient(to right, #00aaff, #ff0055); |
| border-radius: 10px; |
| } |
| |
| #pokemon-screen .pokemon-option { |
| background: rgba(255, 255, 255, 0.05); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| border-radius: 12px; |
| padding: 10px; |
| text-align: center; |
| cursor: pointer; |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| scroll-snap-align: start; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| user-select: none; |
| } |
| |
| #pokemon-screen .pokemon-option:hover { |
| background: rgba(0, 170, 255, 0.15); |
| border-color: rgba(0, 170, 255, 0.5); |
| transform: translateY(-5px); |
| box-shadow: 0 5px 15px rgba(0, 170, 255, 0.3); |
| } |
| |
| #pokemon-screen .pokemon-option.selected { |
| background: rgba(255, 222, 0, 0.15); |
| border-color: #ffde00; |
| box-shadow: 0 0 20px rgba(255, 222, 0, 0.4), inset 0 0 10px rgba(255, 222, 0, 0.2); |
| transform: scale(1.05); |
| } |
| |
| #pokemon-screen .pokemon-option img { |
| width: 55px; |
| height: 55px; |
| object-fit: contain; |
| margin-bottom: 8px; |
| filter: drop-shadow(0 0 8px rgba(0,0,0,0.6)); |
| image-rendering: auto; |
| } |
| |
| #pokemon-screen .pokemon-option p { |
| font-size: 0.75rem; |
| margin: 0; |
| text-transform: capitalize; |
| color: rgba(255, 255, 255, 0.9); |
| font-weight: 500; |
| } |
| |
| |
| #pokemon-screen input[type="text"] { |
| background: rgba(0, 0, 0, 0.5); |
| border: 1px solid #00aaff; |
| color: #fff; |
| padding: 12px 20px; |
| border-radius: 25px; |
| font-family: 'Exo 2', sans-serif; |
| font-size: 1rem; |
| outline: none; |
| transition: 0.3s; |
| margin-right: 10px; |
| } |
| #pokemon-screen input[type="text"]:focus { |
| box-shadow: 0 0 15px rgba(0, 170, 255, 0.5); |
| border-color: #00f3ff; |
| } |
| |
| </style> |
| </head> |
|
|
| <body> |
|
|
| <div id="background-container"></div> |
|
|
| <div id="loading-screen" class="screen hidden"> |
| <svg id="loading-spinner" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> |
| <defs> |
| <linearGradient id="spinner-grad" x1="0%" y1="0%" x2="100%" y2="100%"> |
| <stop offset="0%" stop-color="#00aaff" /> |
| <stop offset="100%" stop-color="#ff33cc" /> |
| </linearGradient> |
| </defs> |
| <circle class="path" cx="50" cy="50" r="45" fill="none" stroke="url(#spinner-grad)" stroke-width="6" |
| stroke-linecap="round" /> |
| </svg> |
| </div> |
|
|
| <div id="menu-screen" class="screen"> |
| <div class="main-container"> |
| <h1 class="logo">GameSystem</h1> |
| <nav class="button-nav"> |
| <a href="#" class="game-button" onclick="loadGame('tictactoe')" |
| style="--glow-color: var(--tictactoe-glow-color);"> |
| <svg class="icon-svg" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| <defs> |
| <linearGradient id="grad-tictactoe" x1="0%" y1="0%" x2="100%" y2="100%"> |
| <stop offset="0%" stop-color="#ff33cc" /> |
| <stop offset="100%" stop-color="#33aaff" /> |
| </linearGradient> |
| </defs> |
| <path d="M33 5 V95 M66 5 V95 M5 33 H95 M5 66 H95" stroke="url(#grad-tictactoe)" stroke-width="4" |
| stroke-linecap="round" /> |
| <path d="M10 10 L26 26 M26 10 L10 26" stroke="url(#grad-tictactoe)" stroke-width="5" |
| stroke-linecap="round" /> |
| <circle cx="50" cy="50" r="10" stroke="url(#grad-tictactoe)" stroke-width="5" /> |
| </svg> |
| <span>Jogo da Velha</span> |
| </a> |
| <a href="#" class="game-button" onclick="loadGame('pokemon')" |
| style="--glow-color: var(--pokemon-glow-color);"> |
| <svg class="icon-svg" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| <defs> |
| <linearGradient id="grad-pokeball" x1="0%" y1="0%" x2="100%" y2="100%"> |
| <stop offset="0%" stop-color="#ffcc00" /> |
| <stop offset="100%" stop-color="#ff4444" /> |
| </linearGradient> |
| </defs> |
| <circle cx="50" cy="50" r="45" stroke="url(#grad-pokeball)" stroke-width="4" /> |
| <path d="M5 50 H95" stroke="url(#grad-pokeball)" stroke-width="4" /> |
| <circle cx="50" cy="50" r="15" stroke="url(#grad-pokeball)" stroke-width="4" /> |
| <circle cx="50" cy="50" r="8" stroke="url(#grad-pokeball)" stroke-width="2" |
| fill="transparent" /> |
| </svg> |
| <span>Batalhas Pokémon</span> |
| </a> |
| <a href="#" class="game-button" onclick="loadGame('chess')" |
| style="--glow-color: var(--chess-neon);"> |
| <svg class="icon-svg" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| <defs> |
| <linearGradient id="grad-chess" x1="0%" y1="0%" x2="100%" y2="100%"> |
| <stop offset="0%" stop-color="#00f3ff" /> |
| <stop offset="100%" stop-color="#7000ff" /> |
| </linearGradient> |
| </defs> |
| <rect x="15" y="15" width="70" height="70" stroke="url(#grad-chess)" stroke-width="4" rx="5"/> |
| <path d="M35 15 V85 M50 15 V85 M65 15 V85 M15 35 H85 M15 50 H85 M15 65 H85" stroke="url(#grad-chess)" stroke-width="1" opacity="0.3"/> |
| <path d="M50 35 L60 70 H40 L50 35 Z" fill="url(#grad-chess)" /> |
| <circle cx="50" cy="30" r="6" fill="url(#grad-chess)" /> |
| </svg> |
| <span>Quantum Chess AI</span> |
| </a> |
| </nav> |
| </div> |
| </div> |
|
|
| <div id="tictactoe-screen" class="screen hidden"> |
| <div class="game-container"> |
| <h2>Jogo da Velha: Apoteose</h2> |
| <div id="ttt-status">Sua vez!</div> |
| <div id="ttt-board"></div> |
| <button class="back-button" onclick="exitTicTacToe()">Voltar ao Menu</button> |
| </div> |
| </div> |
|
|
| <div id="pokemon-screen" class="screen hidden"> |
| <div id="game-container"> |
| <div id="start-screen" class="screen-pokemon active"> |
| <h1>Batalha de Ginásio Pokémon</h1> |
| <button id="start-game-button">Iniciar Jogo</button> |
| <button onclick="exitPokemonGame()">Voltar ao Menu</button> |
| </div> |
| <div id="name-screen" class="screen-pokemon"> |
| <h2>Qual é o seu nome, Treinador?</h2> |
| <input type="text" id="trainer-name-input" placeholder="Seu Nome"><button |
| id="submit-name-button">Confirmar</button> |
| </div> |
| <div id="gym-choice-screen" class="screen-pokemon"> |
| <h2>Treinador <span id="player-name-display-gym"></span>, escolha um Ginásio!</h2> |
| <div class="gym-options"></div> |
| <h3>Suas Insígnias</h3> |
| <div id="badges-inventory"></div> |
| </div> |
| <div id="pokemon-choice-screen" class="screen-pokemon"> |
| <h2>Escolha 3 Pokémon, <span id="player-name-display-choice"></span>!</h2> |
| <p>Você vai desafiar o <span id="chosen-gym-name-display"></span>.</p> |
| <div class="pokemon-options-grid"></div> |
| <p>Selecionados: <span id="pokemon-selected-count">0</span> / 3</p> |
| <button id="reset-pokemon-choice-button">Limpar</button> |
| <button id="confirm-pokemon-choice-button" disabled>Confirmar</button> |
| </div> |
| <div id="battle-screen" class="screen-pokemon"> |
| <h2 id="battle-intro">A Batalha Começa!</h2> |
| <div id="unified-battle-area"> |
| <img id="battle-background-image" src="image_fx.jpg" alt="Battle background"> |
| <div class="opponent-info-box"> |
| <div class="info-box-header"> |
| <h3 id="opponent-name">Opponent</h3> |
| <div id="opponent-team-display" class="mini-team-display"></div> |
| </div> |
| <div class="hp-bar-container"> |
| <div id="opponent-hp-bar" class="hp-bar"></div> |
| </div> |
| <p id="opponent-hp-text">HP: 0/0</p> |
| </div> |
| <img id="opponent-sprite" src="" alt="Opponent Pokémon"> |
| <img id="player-sprite" src="" alt="Player Pokémon"> |
| <div class="player-info-box"> |
| <div class="info-box-header"> |
| <h3 id="player-pokemon-name">PlayerMon</h3> |
| <div id="player-team-display" class="mini-team-display"></div> |
| </div> |
| <div class="hp-bar-container"> |
| <div id="player-hp-bar" class="hp-bar"></div> |
| </div> |
| <p id="player-hp-text">HP: 0/0</p> |
| </div> |
| </div> |
| <div id="action-log-panel"> |
| <div id="panel-text-content"> |
| <p>A batalha está prestes a começar!</p> |
| </div> |
| <div id="panel-button-grid"></div> |
| </div> |
| <button id="next-battle-button" style="display:none;">Próximo Treinador</button> |
| </div> |
| <div id="game-over-screen" class="screen-pokemon"> |
| <h2 id="game-over-message"></h2> |
| <button id="play-again-button">Jogar Novamente</button> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="chess-screen" class="screen hidden"> |
| <div class="matrix-box"> |
| <h3 style="text-align:center; margin-top:0; font-family: 'Orbitron', sans-serif;">MATRIZ I/Q: DUPLICIDADE DE SATO</h3> |
| <div id="chess-board"></div> |
| <div class="log-panel"> |
| <div id="chess-status">Sincronizando Vetores...</div> |
| <div id="chess-math-stream" style="color: #00ff41;"> |
| I/Q Behavior: Standby | Singularidade: ??? |
| </div> |
| </div> |
| <button class="back-button" onclick="exitChess()">Voltar ao Menu</button> |
| </div> |
| </div> |
|
|
|
|
| <script> |
| |
| const systemScreens = { |
| menu: document.getElementById('menu-screen'), |
| loading: document.getElementById('loading-screen'), |
| tictactoe: document.getElementById('tictactoe-screen'), |
| pokemon: document.getElementById('pokemon-screen'), |
| chess: document.getElementById('chess-screen') |
| }; |
| let isTicTacToeInitialized = false; |
| let isPokemonInitialized = false; |
| let isChessInitialized = false; |
| |
| |
| function showSystemScreen(screenName) { |
| Object.values(systemScreens).forEach(screen => screen.classList.add('hidden')); |
| if (systemScreens[screenName]) { |
| systemScreens[screenName].classList.remove('hidden'); |
| document.body.style.fontFamily = screenName === 'pokemon' ? "var(--pkmn-font)" : "'Exo 2', sans-serif"; |
| document.body.style.backgroundColor = screenName === 'pokemon' ? "var(--page-bg-color)" : "var(--dark-bg)"; |
| } |
| } |
| |
| function loadGame(gameName) { |
| showSystemScreen('loading'); |
| setTimeout(() => { |
| showSystemScreen(gameName); |
| if (gameName === 'tictactoe' && !isTicTacToeInitialized) { |
| initTicTacToe(); |
| isTicTacToeInitialized = true; |
| } else if (gameName === 'tictactoe') { |
| ttt_startNewRound(); |
| } |
| |
| if (gameName === 'pokemon' && !isPokemonInitialized) { |
| initPokemonBattle(); |
| isPokemonInitialized = true; |
| } else if (gameName === 'pokemon') { |
| pokemon_resetGame(); |
| } |
| |
| if (gameName === 'chess' && !isChessInitialized) { |
| initChess(); |
| isChessInitialized = true; |
| } else if (gameName === 'chess') { |
| chess_resetGame(); |
| } |
| }, 1500); |
| |
| } |
| |
| function showMenu() { |
| showSystemScreen('menu'); |
| } |
| |
| function exitTicTacToe() { |
| showMenu(); |
| } |
| |
| function exitPokemonGame() { |
| pokemon_resetGame(); |
| showMenu(); |
| } |
| |
| function exitChess() { |
| showMenu(); |
| } |
| |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| const container = document.getElementById('background-container'); |
| const svgNS = "http://www.w3.org/2000/svg"; const svg = document.createElementNS(svgNS, 'svg'); svg.setAttribute('width', '100%'); svg.setAttribute('height', '100%'); svg.setAttribute('viewBox', `0 0 ${window.innerWidth} ${window.innerHeight}`); const defs = document.createElementNS(svgNS, 'defs'); const bgGradient = document.createElementNS(svgNS, 'radialGradient'); bgGradient.setAttribute('id', 'bgGradient'); bgGradient.innerHTML = `<stop offset="0%" stop-color="#0d1b2a" /><stop offset="100%" stop-color="#000000" />`; const glowFilter = document.createElementNS(svgNS, 'filter'); glowFilter.setAttribute('id', 'moonGlow'); glowFilter.innerHTML = `<feGaussianBlur stdDeviation="15" result="coloredBlur" />`; defs.appendChild(bgGradient); defs.appendChild(glowFilter); svg.appendChild(defs); const bgRect = document.createElementNS(svgNS, 'rect'); bgRect.setAttribute('width', '100%'); bgRect.setAttribute('height', '100%'); bgRect.setAttribute('fill', 'url(#bgGradient)'); svg.appendChild(bgRect); const moonX = window.innerWidth * 0.8; const moonY = window.innerHeight * 0.2; const moonRadius = Math.min(window.innerWidth, window.innerHeight) * 0.1; const moonGlow = document.createElementNS(svgNS, 'circle'); moonGlow.setAttribute('cx', moonX); moonGlow.setAttribute('cy', moonY); moonGlow.setAttribute('r', moonRadius); moonGlow.setAttribute('fill', '#f0e68c'); moonGlow.setAttribute('filter', 'url(#moonGlow)'); svg.appendChild(moonGlow); const moon = document.createElementNS(svgNS, 'circle'); moon.setAttribute('cx', moonX); moon.setAttribute('cy', moonY); moon.setAttribute('r', moonRadius); moon.setAttribute('fill', '#f0e68c'); svg.appendChild(moon); for (let i = 0; i < 300; i++) { const star = document.createElementNS(svgNS, 'circle'); star.setAttribute('cx', Math.random() * window.innerWidth); star.setAttribute('cy', Math.random() * window.innerHeight); star.setAttribute('r', Math.random() * 1.5 + 0.5); star.setAttribute('fill', 'white'); star.style.opacity = Math.random() * 0.7 + 0.3; if (Math.random() > 0.7) { star.style.animation = `twinkle ${Math.random() * 2 + 1}s infinite ease-in-out alternate`; } svg.appendChild(star); } container.appendChild(svg); const style = document.createElement('style'); style.textContent = `@keyframes twinkle { 0% { opacity: 0.3; } 100% { opacity: 1; } }`; document.head.appendChild(style); |
| }); |
| |
| |
| let ttt_currentPlayer, ttt_isGameActive, ttt_boardState; |
| const ttt_humanPlayer = 'X'; |
| const ttt_aiPlayer = 'O'; |
| const ttt_winningCombinations = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]; |
| let ttt_boardElement, ttt_statusElement; |
| |
| function initTicTacToe() { |
| ttt_boardElement = document.getElementById('ttt-board'); |
| ttt_statusElement = document.getElementById('ttt-status'); |
| ttt_startNewRound(); |
| } |
| |
| function ttt_startNewRound() { |
| ttt_boardState = Array(9).fill(null); |
| ttt_isGameActive = true; |
| ttt_currentPlayer = ttt_humanPlayer; |
| ttt_statusElement.textContent = "Sua vez (X)"; |
| ttt_drawBoard(); |
| } |
| |
| function ttt_drawBoard() { |
| ttt_boardElement.innerHTML = ''; |
| for (let i = 0; i < 9; i++) { |
| const cell = document.createElement('div'); |
| cell.classList.add('cell'); |
| cell.dataset.index = i; |
| cell.textContent = ttt_boardState[i]; |
| cell.addEventListener('click', ttt_handleCellClick, { once: true }); |
| ttt_boardElement.appendChild(cell); |
| } |
| } |
| |
| function ttt_handleCellClick(event) { |
| if (!ttt_isGameActive || ttt_currentPlayer !== ttt_humanPlayer) return; |
| const clickedCellIndex = parseInt(event.target.dataset.index); |
| if (ttt_boardState[clickedCellIndex]) return; |
| ttt_makeMove(clickedCellIndex, ttt_humanPlayer); |
| if (ttt_checkEnd()) return; |
| ttt_currentPlayer = ttt_aiPlayer; |
| ttt_statusElement.textContent = "IA (O) está pensando..."; |
| setTimeout(ttt_aiMove, 700); |
| } |
| |
| function ttt_makeMove(index, player) { |
| ttt_boardState[index] = player; |
| const cell = ttt_boardElement.querySelector(`[data-index='${index}']`); |
| cell.textContent = player; |
| } |
| |
| function ttt_checkEnd() { |
| const winner = ttt_checkWinner(ttt_boardState); |
| const isFull = !ttt_boardState.includes(null); |
| if (winner || isFull) { |
| ttt_isGameActive = false; |
| if (winner) { |
| ttt_statusElement.textContent = `Vencedor: ${winner}!`; |
| } else { |
| ttt_statusElement.textContent = 'Empate!'; |
| } |
| setTimeout(ttt_startNewRound, 2000); |
| return true; |
| } |
| return false; |
| } |
| |
| function ttt_checkWinner(board) { |
| for (const combo of ttt_winningCombinations) { |
| const [a, b, c] = combo; |
| if (board[a] && board[a] === board[b] && board[a] === board[c]) return board[a]; |
| } |
| return null; |
| } |
| |
| function ttt_aiMove() { |
| if (!ttt_isGameActive) return; |
| let bestScore = -Infinity; |
| let move; |
| for (let i = 0; i < 9; i++) { |
| if (ttt_boardState[i] === null) { |
| ttt_boardState[i] = ttt_aiPlayer; |
| let score = ttt_minimax(ttt_boardState, 0, false); |
| ttt_boardState[i] = null; |
| if (score > bestScore) { |
| bestScore = score; |
| move = i; |
| } |
| } |
| } |
| ttt_makeMove(move, ttt_aiPlayer); |
| if (ttt_checkEnd()) return; |
| ttt_currentPlayer = ttt_humanPlayer; |
| ttt_statusElement.textContent = "Sua vez (X)"; |
| } |
| |
| const ttt_scoresMap = { [ttt_aiPlayer]: 10, [ttt_humanPlayer]: -10, 'tie': 0 }; |
| |
| function ttt_minimax(board, depth, isMaximizing) { |
| let result = ttt_checkWinner(board); |
| if (result !== null) return ttt_scoresMap[result] - depth; |
| if (!board.includes(null)) return ttt_scoresMap['tie']; |
| let bestScore = isMaximizing ? -Infinity : Infinity; |
| for (let i = 0; i < 9; i++) { |
| if (board[i] === null) { |
| board[i] = isMaximizing ? ttt_aiPlayer : ttt_humanPlayer; |
| let score = ttt_minimax(board, depth + 1, !isMaximizing); |
| board[i] = null; |
| bestScore = isMaximizing ? Math.max(score, bestScore) : Math.min(score, bestScore); |
| } |
| } |
| return bestScore; |
| } |
| |
| |
| function initPokemonBattle() { |
| const POKEAPI_BASE_URL = "https://pokeapi.co/api/v2/"; |
| const pokemon_screens = { start: document.querySelector('#pokemon-screen #start-screen'), name: document.querySelector('#pokemon-screen #name-screen'), gymChoice: document.querySelector('#pokemon-screen #gym-choice-screen'), pokemonChoice: document.querySelector('#pokemon-screen #pokemon-choice-screen'), battle: document.querySelector('#pokemon-screen #battle-screen'), gameOver: document.querySelector('#pokemon-screen #game-over-screen') }; |
| const trainerNameInput = document.getElementById('trainer-name-input'); const playerNameDisplayGym = document.getElementById('player-name-display-gym'); const playerNameDisplayChoice = document.getElementById('player-name-display-choice'); const chosenGymNameDisplay = document.getElementById('chosen-gym-name-display'); const pokemonSelectedCountDisplay = document.getElementById('pokemon-selected-count'); const gymOptionsContainer = document.querySelector('#pokemon-screen .gym-options'); const badgesInventoryContainer = document.getElementById('badges-inventory'); const pokemonOptionsGrid = document.querySelector('#pokemon-screen .pokemon-options-grid'); const confirmPokemonChoiceButton = document.getElementById('confirm-pokemon-choice-button'); const resetPokemonChoiceButton = document.getElementById('reset-pokemon-choice-button'); const panelTextContent = document.getElementById('panel-text-content'); const panelButtonGrid = document.getElementById('panel-button-grid'); const startGameButton = document.querySelector('#pokemon-screen #start-game-button'); const submitNameButton = document.getElementById('submit-name-button'); const nextBattleButton = document.getElementById('next-battle-button'); const playAgainButton = document.querySelector('#pokemon-screen #play-again-button'); |
| let trainerName = ""; let playerTeam = []; let currentPlayerPokemon = null; let currentOpponentTrainerIndex = 0; let gymTrainers = []; let selectedPokemonForChoice = new Set(); const KANTO_INITIAL_POKEMON_IDS = Array.from({ length: 151 }, (_, i) => i + 1); |
| |
| let playerInventory = { 'Full Heal': 2, 'Hyper Potion': 3, 'Revive': 1, 'Dire Hit': 2 }; |
| let wonBadges = new Set(); |
| const pokemonDataCache = new Map(); let selectedGymKey = null; let currentGymData = null; |
| |
| const GENERIC_FALLBACK_MOVES = [{ name: "Tackle", power: 40, type: "normal", accuracy: 100 }, { name: "Scratch", power: 40, type: "normal", accuracy: 100 }, { name: "Pound", power: 40, type: "normal", accuracy: 100 }, { name: "Quick Attack", power: 40, type: "normal", accuracy: 100, priority: 1 }, { name: "Vine Whip", power: 45, type: "grass", accuracy: 100 }, { name: "Ember", power: 40, type: "fire", accuracy: 100 }, { name: "Water Gun", power: 40, type: "water", accuracy: 100 }, { name: "Gust", power: 40, type: "flying", accuracy: 100 },]; |
| const KANTO_GYMS_DATA = { pewter: { id: 'pewter', name: "Pewter City Gym", badge: "Boulder Badge", leaderName: "Brock", trainers: [{ name: "Camper Liam", pokemonsToLoad: [74, 50], loadedPokemons: [], isLeader: false }, { name: "Leader Brock", pokemonsToLoad: [75, 95], loadedPokemons: [], isLeader: true }] }, cerulean: { id: 'cerulean', name: "Cerulean City Gym", badge: "Cascade Badge", leaderName: "Misty", trainers: [{ name: "Swimmer Luis", pokemonsToLoad: [129, 60], loadedPokemons: [], isLeader: false }, { name: "Leader Misty", pokemonsToLoad: [120, 121], loadedPokemons: [], isLeader: true }] }, vermilion: { id: 'vermilion', name: "Vermilion City Gym", badge: "Thunder Badge", leaderName: "Lt. Surge", trainers: [{ name: "Sailor Dwayne", pokemonsToLoad: [25, 25], loadedPokemons: [], isLeader: false }, { name: "Leader Lt. Surge", pokemonsToLoad: [25, 100, 26], loadedPokemons: [], isLeader: true }] }, celadon: { id: 'celadon', name: "Celadon City Gym", badge: "Rainbow Badge", leaderName: "Erika", trainers: [{ name: "Lass Michelle", pokemonsToLoad: [69, 70], loadedPokemons: [], isLeader: false }, { name: "Leader Erika", pokemonsToLoad: [71, 114, 45], loadedPokemons: [], isLeader: true }] }, fuchsia: { id: 'fuchsia', name: "Fuchsia City Gym", badge: "Soul Badge", leaderName: "Koga", trainers: [{ name: "Juggler Nate", pokemonsToLoad: [96, 64], loadedPokemons: [], isLeader: false }, { name: "Leader Koga", pokemonsToLoad: [109, 89, 109, 110], loadedPokemons: [], isLeader: true }] }, saffron: { id: 'saffron', name: "Saffron City Gym", badge: "Marsh Badge", leaderName: "Sabrina", trainers: [{ name: "Psychic Preston", pokemonsToLoad: [79, 80], loadedPokemons: [], isLeader: false }, { name: "Leader Sabrina", pokemonsToLoad: [64, 122, 49, 65], loadedPokemons: [], isLeader: true }] }, cinnabar: { id: 'cinnabar', name: "Cinnabar Island Gym", badge: "Volcano Badge", leaderName: "Blaine", trainers: [{ name: "Super Nerd Erik", pokemonsToLoad: [37, 38], loadedPokemons: [], isLeader: false }, { name: "Leader Blaine", pokemonsToLoad: [58, 77, 78, 59], loadedPokemons: [], isLeader: true }] }, viridian: { id: 'viridian', name: "Viridian City Gym", badge: "Earth Badge", leaderName: "Giovanni", trainers: [{ name: "Tamer Jasper", pokemonsToLoad: [111, 111], loadedPokemons: [], isLeader: false }, { name: "Leader Giovanni", pokemonsToLoad: [111, 51, 31, 112], loadedPokemons: [], isLeader: true }] }, Takashi: { id: 'fukuima', name: "Arcade City Gym", badge: "Epic Badge", leaderName: "Takashi Satoshi", trainers: [{ name: "Old Hacker", pokemonsToLoad: [132, 133], loadedPokemons: [], isLeader: false }, { name: "Leader Takashi", pokemonsToLoad: [150, 151, 149], loadedPokemons: [], isLeader: true }] } }; |
| const typeEffectiveness = { normal: { rock: 0.5, ghost: 0, steel: 0.5 }, fire: { grass: 2, water: 0.5, fire: 0.5, ice: 2, bug: 2, rock: 0.5, dragon: 0.5, steel: 2 }, water: { fire: 2, ground: 2, rock: 2, water: 0.5, grass: 0.5, dragon: 0.5 }, grass: { water: 2, ground: 2, rock: 2, fire: 0.5, grass: 0.5, poison: 0.5, flying: 0.5, bug: 0.5, dragon: 0.5, steel: 0.5 }, electric: { water: 2, flying: 2, ground: 0, grass: 0.5, electric: 0.5, dragon: 0.5 }, ice: { grass: 2, ground: 2, flying: 2, dragon: 2, fire: 0.5, water: 0.5, ice: 0.5, steel: 0.5 }, fighting: { normal: 2, rock: 2, ice: 2, poison: 0.5, flying: 0.5, psychic: 0.5, bug: 0.5, ghost: 0, fairy: 0.5, steel: 2 }, poison: { grass: 2, fairy: 2, poison: 0.5, ground: 0.5, rock: 0.5, ghost: 0.5, steel: 0 }, ground: { fire: 2, electric: 2, poison: 2, rock: 2, steel: 2, flying: 0, grass: 0.5, bug: 0.5 }, flying: { grass: 2, fighting: 2, bug: 2, rock: 0.5, electric: 0.5, steel: 0.5 }, psychic: { fighting: 2, poison: 2, psychic: 0.5, dark: 0, steel: 0.5 }, bug: { grass: 2, psychic: 2, dark: 2, fire: 0.5, fighting: 0.5, poison: 0.5, flying: 0.5, ghost: 0.5, fairy: 0.5, steel: 0.5 }, rock: { fire: 2, ice: 2, flying: 2, bug: 2, fighting: 0.5, ground: 0.5, steel: 0.5 }, ghost: { psychic: 2, ghost: 2, normal: 0, dark: 0.5 }, dragon: { dragon: 2, steel: 0.5, fairy: 0 }, dark: { psychic: 2, ghost: 2, fighting: 0.5, dark: 0.5, fairy: 0.5 }, steel: { ice: 2, rock: 2, fairy: 2, fire: 0.5, water: 0.5, electric: 0.5, steel: 0.5 }, fairy: { fighting: 2, dragon: 2, dark: 2, fire: 0.5, poison: 0.5, steel: 0.5 } }; |
| function pokemon_showScreen(screenId) { for (const id in pokemon_screens) { pokemon_screens[id].classList.remove('active'); } pokemon_screens[screenId].classList.add('active'); } |
| function pokemon_resetGame() { trainerName = ""; trainerNameInput.value = ""; playerTeam = []; currentPlayerPokemon = null; currentOpponentTrainerIndex = 0; gymTrainers = []; pokemonDataCache.clear(); selectedGymKey = null; currentGymData = null; playerInventory = { 'Full Heal': 2, 'Hyper Potion': 3, 'Revive': 1, 'Dire Hit': 2 }; resetPokemonSelection(); panelTextContent.innerHTML = '<p>Bem-vindo de volta!</p>'; panelButtonGrid.innerHTML = ''; document.getElementById('player-team-display').innerHTML = ''; document.getElementById('opponent-team-display').innerHTML = ''; pokemon_showScreen('start'); } |
| async function fetchRawPokemonData(pokemonIdOrName) { const key = pokemonIdOrName.toString().toLowerCase(); if (pokemonDataCache.has(key)) return pokemonDataCache.get(key); try { const response = await fetch(`${POKEAPI_BASE_URL}pokemon/${key}`); if (!response.ok) throw new Error(`Pokémon não encontrado: ${pokemonIdOrName}`); const data = await response.json(); pokemonDataCache.set(key, data); return data; } catch (error) { console.error("Erro ao buscar dados do Pokémon:", error); return null; } } |
| async function processPokemonWithUniqueMoves(apiData) { if (!apiData) return null; const learnedMoves = []; const potentialMoves = []; for (const moveVersion of apiData.moves) { for (const versionGroupDetail of moveVersion.version_group_details) { if (versionGroupDetail.move_learn_method.name === 'level-up' && versionGroupDetail.level_learned_at > 0) { potentialMoves.push({ url: moveVersion.move.url, name: moveVersion.move.name, sortKey: 1 }); break; } } } if (potentialMoves.length < 10) { for (const moveVersion of apiData.moves) { if (!potentialMoves.find(pm => pm.name === moveVersion.move.name)) { potentialMoves.push({ url: moveVersion.move.url, name: moveVersion.move.name, sortKey: 2 }); } } } potentialMoves.sort((a, b) => a.sortKey - b.sortKey); for (const potMove of potentialMoves) { if (learnedMoves.length >= 4) break; try { const moveResponse = await fetch(potMove.url); if (!moveResponse.ok) continue; const moveData = await moveResponse.json(); if (moveData.power && moveData.power > 0) { const uniqueMoveName = moveData.name.split('-').map(s => s.charAt(0).toUpperCase() + s.substring(1)).join(' '); if (!learnedMoves.find(m => m.name === uniqueMoveName)) { learnedMoves.push({ name: uniqueMoveName, power: moveData.power, type: moveData.type.name, accuracy: moveData.accuracy || 100 }); } } } catch (e) { console.warn(`Falha ao buscar dados do golpe ${potMove.name}: ${e}`); } } let genericIndex = 0; const pokemonSpecificAssignedGenericMoves = new Set(); while (learnedMoves.length < 4 && genericIndex < GENERIC_FALLBACK_MOVES.length) { const genericMove = GENERIC_FALLBACK_MOVES[genericIndex]; if (!learnedMoves.find(m => m.name === genericMove.name) && !pokemonSpecificAssignedGenericMoves.has(genericMove.name)) { learnedMoves.push({ ...genericMove }); pokemonSpecificAssignedGenericMoves.add(genericMove.name); } genericIndex++; } if (learnedMoves.length === 0 && GENERIC_FALLBACK_MOVES.length > 0) { const forcedTackle = GENERIC_FALLBACK_MOVES.find(m => m.name === "Tackle") || GENERIC_FALLBACK_MOVES[0]; if (forcedTackle && !learnedMoves.find(m => m.name === forcedTackle.name)) { learnedMoves.push({ ...forcedTackle }); } } return { id: apiData.id, name: apiData.name.charAt(0).toUpperCase() + apiData.name.slice(1), sprite: apiData.sprites.front_default, sprite_back: apiData.sprites.back_default || apiData.sprites.front_default, hp: apiData.stats.find(stat => stat.stat.name === 'hp').base_stat * 2.5 + 60, currentHp: apiData.stats.find(stat => stat.stat.name === 'hp').base_stat * 2.5 + 60, attack: apiData.stats.find(stat => stat.stat.name === 'attack').base_stat, defense: apiData.stats.find(stat => stat.stat.name === 'defense').base_stat, speed: apiData.stats.find(stat => stat.stat.name === 'speed').base_stat, types: apiData.types.map(typeInfo => typeInfo.type.name), moves: learnedMoves.slice(0, 4), fainted: false, effects: { direHitTurns: 0 } }; } |
| function showMessageInPanel(text, isNewEntry = false) { if (isNewEntry || panelTextContent.children.length === 0) panelTextContent.innerHTML = ''; const p = document.createElement('p'); p.textContent = text; panelTextContent.appendChild(p); panelTextContent.scrollTop = panelTextContent.scrollHeight; } |
| function updateHealthBar(pokemon, barElementId, textElementId) { const bar = document.getElementById(barElementId); const text = document.getElementById(textElementId); if (!pokemon || !bar || !text) return; const hpPercentage = (pokemon.currentHp / pokemon.hp) * 100; bar.style.width = `${Math.max(0, hpPercentage)}%`; if (hpPercentage <= 0) bar.style.backgroundColor = 'grey'; else if (hpPercentage < 30) bar.style.backgroundColor = 'red'; else if (hpPercentage < 60) bar.style.backgroundColor = 'orange'; else bar.style.backgroundColor = '#4CAF50'; text.textContent = `HP: ${Math.max(0, Math.ceil(pokemon.currentHp))} / ${Math.ceil(pokemon.hp)}`; } |
| function getEffectiveness(attackType, defendTypes) { let totalEffectiveness = 1; if (typeEffectiveness[attackType]) { defendTypes.forEach(defendType => { if (typeEffectiveness[attackType][defendType] !== undefined) totalEffectiveness *= typeEffectiveness[attackType][defendType]; }); } return totalEffectiveness; } |
| function calculateDamage(attacker, defender, move) { if (!attacker || !defender || !move || !move.power) return 0; showMessageInPanel(`${attacker.name} usou ${move.name}!`, true); if (Math.random() * 100 > (move.accuracy || 100)) { showMessageInPanel(`...mas errou!`); return 0; } let critChance = 1 / 16; if (attacker.effects && attacker.effects.direHitTurns > 0) critChance = 1 / 8; const isCritical = Math.random() < critChance; const effectiveness = getEffectiveness(move.type, defender.types); let effectivenessMessage = ""; if (effectiveness > 1) effectivenessMessage = "É super efetivo!"; if (effectiveness < 1 && effectiveness > 0) effectivenessMessage = "Não é muito efetivo..."; if (effectiveness === 0) { showMessageInPanel(`Não teve efeito em ${defender.name}!`); return 0; } if (effectivenessMessage) showMessageInPanel(effectivenessMessage); if (isCritical) showMessageInPanel("Um acerto crítico!"); const level = 50; let damage = ((((level * 2 / 5) + 2) * move.power * (attacker.attack / defender.defense)) / 50) + 2; damage *= effectiveness; if (isCritical) damage *= 1.5; damage *= (Math.random() * (1 - 0.85) + 0.85); damage = Math.max(1, Math.floor(damage)); showMessageInPanel(`Causou ${damage} de dano em ${defender.name}.`); return damage; } |
| function renderBadgesInventory() { badgesInventoryContainer.innerHTML = ''; Object.keys(KANTO_GYMS_DATA).forEach(key => { const gym = KANTO_GYMS_DATA[key]; const badgeDiv = document.createElement('div'); badgeDiv.classList.add('badge-icon'); badgeDiv.setAttribute('data-badge', gym.badge); if (wonBadges.has(gym.badge)) badgeDiv.classList.add('won'); badgeDiv.innerHTML = `<span style="font-size: 10px;">${gym.badge.charAt(0)}</span>`; badgesInventoryContainer.appendChild(badgeDiv); }); } |
| function populateGymChoiceScreen() { playerNameDisplayGym.textContent = trainerName; gymOptionsContainer.innerHTML = ''; Object.keys(KANTO_GYMS_DATA).forEach(gymKey => { const gym = KANTO_GYMS_DATA[gymKey]; const button = document.createElement('button'); button.classList.add('gym-option-button'); let badgeStatus = wonBadges.has(gym.badge) ? " [CONQUISTADA ✓]" : ""; button.textContent = `${gym.name}${badgeStatus}`; if (wonBadges.has(gym.badge)) { button.style.borderColor = "gold"; button.style.color = "gold"; } button.onclick = () => selectGym(gymKey); gymOptionsContainer.appendChild(button); }); renderBadgesInventory(); } |
| |
| |
| function selectGym(gymKey) { selectedGymKey = gymKey; currentGymData = KANTO_GYMS_DATA[gymKey]; chosenGymNameDisplay.textContent = currentGymData.name; playerNameDisplayChoice.textContent = trainerName; populatePokemonChoiceScreen(); pokemon_showScreen('pokemonChoice'); } |
| async function populatePokemonChoiceScreen() { pokemonOptionsGrid.innerHTML = '<p style="grid-column: 1 / -1; text-align: center;">Carregando Pokémon...</p>'; let loadedCount = 0; const totalToLoad = KANTO_INITIAL_POKEMON_IDS.length; const pokemonElements = []; resetPokemonSelection(); const promises = KANTO_INITIAL_POKEMON_IDS.map(id => fetchRawPokemonData(id).then(rawData => { if (rawData) { const div = document.createElement('div'); div.classList.add('pokemon-option'); div.dataset.pokemonId = rawData.id; const img = document.createElement('img'); img.src = rawData.sprites.front_default || ''; img.alt = rawData.name; const p = document.createElement('p'); p.textContent = rawData.name.charAt(0).toUpperCase() + rawData.name.slice(1); div.appendChild(img); div.appendChild(p); div.addEventListener('click', () => togglePokemonSelection(div, rawData.id)); pokemonElements.push({ id: rawData.id, element: div }); } }).catch(error => console.error(`Falha ao carregar Pokémon ID ${id}:`, error)).finally(() => { loadedCount++; if (loadedCount === 1) pokemonOptionsGrid.innerHTML = ''; const sortedElements = pokemonElements.sort((a, b) => a.id - b.id).map(item => item.element); pokemonOptionsGrid.innerHTML = ''; sortedElements.forEach(el => pokemonOptionsGrid.appendChild(el)); if (loadedCount === totalToLoad && pokemonElements.length === 0) pokemonOptionsGrid.innerHTML = '<p style="grid-column: 1 / -1; text-align: center;">Nenhum Pokémon pôde ser carregado.</p>'; })); await Promise.allSettled(promises); } |
| function togglePokemonSelection(div, pokemonId) { if (selectedPokemonForChoice.has(pokemonId)) { selectedPokemonForChoice.delete(pokemonId); div.classList.remove('selected'); } else if (selectedPokemonForChoice.size < 3) { selectedPokemonForChoice.add(pokemonId); div.classList.add('selected'); } else alert("Você já selecionou 3 Pokémon!"); pokemonSelectedCountDisplay.textContent = selectedPokemonForChoice.size; confirmPokemonChoiceButton.disabled = selectedPokemonForChoice.size !== 3; } |
| function resetPokemonSelection() { selectedPokemonForChoice.clear(); const selectedPokemonDivs = pokemonOptionsGrid.querySelectorAll('.pokemon-option.selected'); selectedPokemonDivs.forEach(div => div.classList.remove('selected')); pokemonSelectedCountDisplay.textContent = 0; confirmPokemonChoiceButton.disabled = true; } |
| async function initializeFullGameData() { showMessageInPanel("Preparando seu time...", true); playerTeam = []; for (const id of selectedPokemonForChoice) { const rawData = await fetchRawPokemonData(id); const processedPokemon = await processPokemonWithUniqueMoves(rawData); if (processedPokemon) playerTeam.push(processedPokemon); } if (playerTeam.length < 3) { showMessageInPanel("Erro ao carregar seu time! O jogo será reiniciado.", true); setTimeout(pokemon_resetGame, 3000); return false; } currentPlayerPokemon = playerTeam.find(p => !p.fainted) || null; if (!currentPlayerPokemon) { showMessageInPanel("Erro crítico: Nenhum Pokémon carregado. O jogo será reiniciado.", true); setTimeout(pokemon_resetGame, 3000); return false; } gymTrainers = JSON.parse(JSON.stringify(currentGymData.trainers)); currentOpponentTrainerIndex = 0; showMessageInPanel(`Preparando Pokémon do ${currentGymData.name}...`); for (const trainer of gymTrainers) { trainer.loadedPokemons = []; for (const id of trainer.pokemonsToLoad) { const rawData = await fetchRawPokemonData(id); const processedPokemon = await processPokemonWithUniqueMoves(rawData); if (processedPokemon) trainer.loadedPokemons.push(processedPokemon); } trainer.loadedPokemons = trainer.loadedPokemons.filter(p => p && p.moves && p.moves.length > 0); } showMessageInPanel(`${trainerName} está pronto para desafiar o ${currentGymData.name}!`); return true; } |
| function updatePlayerBattleDisplay() { if (!currentPlayerPokemon) return; document.getElementById('player-pokemon-name').textContent = currentPlayerPokemon.name; document.getElementById('player-sprite').src = currentPlayerPokemon.sprite_back; updateHealthBar(currentPlayerPokemon, 'player-hp-bar', 'player-hp-text'); updateTeamDisplay(playerTeam, 'player-team-display', true); if (currentPlayerPokemon.fainted) disablePlayerActions(true); } |
| function updateTeamDisplay(team, displayElementId, isPlayerTeam) { const displayDiv = document.getElementById(displayElementId); displayDiv.innerHTML = ''; team.forEach((pokemon, index) => { const pokeballDiv = document.createElement('div'); pokeballDiv.classList.add('pokeball'); if (pokemon.fainted) pokeballDiv.classList.add('fainted'); const isActive = isPlayerTeam ? (pokemon === currentPlayerPokemon) : (pokemon === getCurrentOpponentPokemon()); if (isActive && !pokemon.fainted) pokeballDiv.classList.add('active-pokemon'); if (isPlayerTeam && !pokemon.fainted && pokemon !== currentPlayerPokemon) { pokeballDiv.title = `Trocar para ${pokemon.name}`; pokeballDiv.classList.add('clickable'); pokeballDiv.onclick = (event) => { event.stopPropagation(); switchPlayerPokemon(index); }; } else if (isPlayerTeam) pokeballDiv.classList.remove('clickable'); displayDiv.appendChild(pokeballDiv); }); } |
| function getCurrentOpponentPokemon() { if (gymTrainers[currentOpponentTrainerIndex]) return gymTrainers[currentOpponentTrainerIndex].loadedPokemons.find(p => !p.fainted); return null; } |
| function showMainBattleActions() { panelButtonGrid.innerHTML = ''; panelButtonGrid.style.gridTemplateColumns = 'repeat(2, 1fr)'; showMessageInPanel(`O que ${currentPlayerPokemon.name} fará?`, true); const fightButton = document.createElement('button'); fightButton.textContent = "Lutar"; fightButton.onclick = () => showMoveChoices(); panelButtonGrid.appendChild(fightButton); const pokemonButton = document.createElement('button'); pokemonButton.textContent = "Pokémon"; pokemonButton.onclick = () => showMessageInPanel("Escolha um Pokémon para trocar (clique na Pokebola acima).", true); panelButtonGrid.appendChild(pokemonButton); const itemButton = document.createElement('button'); itemButton.textContent = "Item"; itemButton.onclick = () => showItemChoices(); panelButtonGrid.appendChild(itemButton); const runButton = document.createElement('button'); runButton.textContent = "Fugir"; const currentOpponentTrainer = gymTrainers[currentOpponentTrainerIndex]; if (currentOpponentTrainer && currentOpponentTrainer.isLeader) { runButton.disabled = true; runButton.title = "Não pode fugir de um Líder de Ginásio!"; } else { runButton.disabled = false; runButton.onclick = () => runFromBattle(); } panelButtonGrid.appendChild(runButton); disablePlayerActions(false); } |
| function showMoveChoices() { panelButtonGrid.innerHTML = ''; panelButtonGrid.style.gridTemplateColumns = 'repeat(2, 1fr)'; showMessageInPanel("Escolha um golpe:", true); if (currentPlayerPokemon && currentPlayerPokemon.moves) currentPlayerPokemon.moves.forEach(move => { const moveButton = document.createElement('button'); moveButton.textContent = `${move.name}`; moveButton.title = `Tipo: ${move.type}, Poder: ${move.power}, Acc: ${move.accuracy || 100}`; moveButton.onclick = () => playerTurnAttack(move); panelButtonGrid.appendChild(moveButton); }); for (let i = (currentPlayerPokemon.moves ? currentPlayerPokemon.moves.length : 0); i < 4; i++) { const emptyButton = document.createElement('button'); emptyButton.textContent = "-"; emptyButton.disabled = true; panelButtonGrid.appendChild(emptyButton); } disablePlayerActions(false); } |
| function showItemChoices() { panelButtonGrid.innerHTML = ''; panelButtonGrid.style.gridTemplateColumns = 'repeat(2, 1fr)'; showMessageInPanel("Escolha um item:", true); const availableItems = []; for (const itemName in playerInventory) if (playerInventory[itemName] > 0) availableItems.push(itemName); if (availableItems.length === 0) { showMessageInPanel("Você não tem itens!", true); const backButton = document.createElement('button'); backButton.textContent = "Voltar"; backButton.onclick = () => showMainBattleActions(); panelButtonGrid.appendChild(backButton); for (let i = 1; i < 4; i++) { const emptyBtn = document.createElement('button'); emptyBtn.textContent = "-"; emptyBtn.disabled = true; panelButtonGrid.appendChild(emptyBtn); } disablePlayerActions(false); return; } const itemsToDisplay = availableItems.slice(0, 3); itemsToDisplay.forEach(itemName => { const itemButton = document.createElement('button'); itemButton.textContent = `${itemName} (x${playerInventory[itemName]})`; itemButton.onclick = () => selectItemTarget(itemName); panelButtonGrid.appendChild(itemButton); }); const backButton = document.createElement('button'); backButton.textContent = "Voltar"; backButton.onclick = () => showMainBattleActions(); panelButtonGrid.appendChild(backButton); for (let i = panelButtonGrid.children.length; i < 4; i++) { const emptyBtn = document.createElement('button'); emptyBtn.textContent = "-"; emptyBtn.disabled = true; panelButtonGrid.appendChild(emptyBtn); } disablePlayerActions(false); } |
| function selectItemTarget(itemName) { panelButtonGrid.innerHTML = ''; showMessageInPanel(`Usar ${itemName} em qual Pokémon?`, true); let targetsExist = false; if (itemName === 'Hyper Potion' || itemName === 'Full Heal' || itemName === 'Revive') { panelButtonGrid.style.gridTemplateColumns = `repeat(auto-fit, minmax(150px, 1fr))`; playerTeam.forEach((pokemon, index) => { const canUse = (itemName === 'Revive' && pokemon.fainted) || (itemName !== 'Revive' && !pokemon.fainted && ((itemName === 'Hyper Potion' && pokemon.currentHp < pokemon.hp) || (itemName === 'Full Heal'))); const pokemonButton = document.createElement('button'); let statusText = pokemon.fainted ? ' (FNT)' : ` (${Math.ceil(pokemon.currentHp)}/${Math.ceil(pokemon.hp)})`; pokemonButton.textContent = `${pokemon.name}${statusText}`; if (canUse) { pokemonButton.onclick = () => useItem(itemName, index); targetsExist = true; } else pokemonButton.disabled = true; panelButtonGrid.appendChild(pokemonButton); }); } else if (itemName === 'Dire Hit') { panelButtonGrid.style.gridTemplateColumns = 'repeat(2, 1fr)'; if (currentPlayerPokemon && !currentPlayerPokemon.fainted) { const useOnCurrentButton = document.createElement('button'); useOnCurrentButton.textContent = `Usar em ${currentPlayerPokemon.name}`; useOnCurrentButton.onclick = () => useItem(itemName, playerTeam.indexOf(currentPlayerPokemon)); panelButtonGrid.appendChild(useOnCurrentButton); targetsExist = true; } else showMessageInPanel(`${itemName} não pode ser usado no Pokémon atual.`); } if (!targetsExist && (itemName === 'Hyper Potion' || itemName === 'Full Heal' || itemName === 'Revive')) showMessageInPanel(`Nenhum Pokémon precisa de ${itemName}.`); const backButton = document.createElement('button'); backButton.textContent = "Voltar (Itens)"; backButton.onclick = () => showItemChoices(); panelButtonGrid.appendChild(backButton); const baseGridSize = panelButtonGrid.style.gridTemplateColumns.startsWith('repeat(2') ? 4 : 6; while (panelButtonGrid.children.length < baseGridSize) { const emptyBtn = document.createElement('button'); emptyBtn.textContent = "-"; emptyBtn.disabled = true; panelButtonGrid.appendChild(emptyBtn); } disablePlayerActions(false); } |
| function useItem(itemName, targetPokemonIndex) { if (playerInventory[itemName] <= 0) { showMessageInPanel(`Você não tem mais ${itemName}!`, true); setTimeout(showItemChoices, 1500); return; } const targetPokemon = playerTeam[targetPokemonIndex]; let itemUsedSuccessfully = false; let message = ""; disablePlayerActions(true); panelButtonGrid.innerHTML = ''; showMessageInPanel(`${trainerName} usou ${itemName}...`, true); switch (itemName) { case 'Hyper Potion': if (targetPokemon && !targetPokemon.fainted && targetPokemon.currentHp < targetPokemon.hp) { const hpRestored = Math.min(200, targetPokemon.hp - targetPokemon.currentHp); targetPokemon.currentHp += hpRestored; message = `${targetPokemon.name} recuperou ${hpRestored} HP!`; itemUsedSuccessfully = true; } else if (targetPokemon && targetPokemon.fainted) message = `${targetPokemon.name} está desmaiado!`; else if (targetPokemon && targetPokemon.currentHp >= targetPokemon.hp) message = `${targetPokemon.name} já está com HP cheio!`; else message = `Não foi possível usar ${itemName}.`; break; case 'Full Heal': if (targetPokemon && !targetPokemon.fainted) { if (targetPokemon.effects && targetPokemon.effects.direHitTurns > 0) targetPokemon.effects.direHitTurns = 0; message = `${targetPokemon.name} foi curado de todos os status!`; itemUsedSuccessfully = true; } else if (targetPokemon && targetPokemon.fainted) message = `${targetPokemon.name} está desmaiado!`; else message = `Não foi possível usar ${itemName}.`; break; case 'Revive': if (targetPokemon && targetPokemon.fainted) { targetPokemon.fainted = false; targetPokemon.currentHp = Math.floor(targetPokemon.hp / 2); message = `${targetPokemon.name} foi revivido!`; itemUsedSuccessfully = true; } else if (targetPokemon && !targetPokemon.fainted) message = `${targetPokemon.name} não está desmaiado!`; else message = `Não foi possível usar ${itemName}.`; break; case 'Dire Hit': const pokemonInBattle = playerTeam[targetPokemonIndex]; if (pokemonInBattle && !pokemonInBattle.fainted && pokemonInBattle === currentPlayerPokemon) { pokemonInBattle.effects.direHitTurns = 5; message = `A taxa de crítico de ${pokemonInBattle.name} aumentou!`; itemUsedSuccessfully = true; } else if (pokemonInBattle !== currentPlayerPokemon) message = `Dire Hit só pode ser usado no Pokémon em batalha.`; else message = `Não pode usar ${itemName} agora.`; break; } showMessageInPanel(message); if (itemUsedSuccessfully) { playerInventory[itemName]--; updatePlayerBattleDisplay(); updateTeamDisplay(playerTeam, 'player-team-display', true); setTimeout(opponentTurn, 2000); } else setTimeout(showMainBattleActions, 2000); } |
| async function setupBattle() { panelButtonGrid.innerHTML = ''; nextBattleButton.style.display = 'none'; if (!currentPlayerPokemon || currentPlayerPokemon.fainted) { currentPlayerPokemon = playerTeam.find(p => !p.fainted); if (!currentPlayerPokemon) { endGame(false); return; } showMessageInPanel(`${trainerName} envia ${currentPlayerPokemon.name}!`, true); } updatePlayerBattleDisplay(); const currentTrainer = gymTrainers[currentOpponentTrainerIndex]; if (!currentTrainer) { endGame(true); return; } let opponentPokemon = getCurrentOpponentPokemon(); if (!opponentPokemon) { showMessageInPanel(`${currentTrainer.name} foi derrotado!`, true); currentOpponentTrainerIndex++; if (currentOpponentTrainerIndex >= gymTrainers.length) endGame(true); else { showMessageInPanel(`Prepare-se para: ${gymTrainers[currentOpponentTrainerIndex].name}!`, true); updatePlayerBattleDisplay(); nextBattleButton.style.display = 'block'; panelButtonGrid.innerHTML = ''; disablePlayerActions(true); } return; } const battleIntroTitle = document.getElementById('battle-intro'); battleIntroTitle.textContent = currentTrainer.isLeader ? `Você enfrenta o Líder ${currentTrainer.name}!` : `${currentTrainer.name} desafia você!`; showMessageInPanel(`${currentTrainer.name} envia ${opponentPokemon.name}!`, true); document.getElementById('opponent-name').textContent = opponentPokemon.name; document.getElementById('opponent-sprite').src = opponentPokemon.sprite; updateHealthBar(opponentPokemon, 'opponent-hp-bar', 'opponent-hp-text'); updateTeamDisplay(currentTrainer.loadedPokemons, 'opponent-team-display', false); if (currentPlayerPokemon.speed >= opponentPokemon.speed) { showMessageInPanel(`${currentPlayerPokemon.name} é mais rápido! Você começa!`); showMainBattleActions(); } else { showMessageInPanel(`${opponentPokemon.name} é mais rápido e começa!`); disablePlayerActions(true); setTimeout(opponentTurn, 2000); } } |
| function disablePlayerActions(disabled) { const buttons = panelButtonGrid.querySelectorAll('button'); buttons.forEach(button => button.disabled = disabled); const playerPokeballs = document.querySelectorAll('#player-team-display .pokeball'); playerPokeballs.forEach(pb => { const pokemonIndex = Array.from(pb.parentNode.children).indexOf(pb); const pkmn = playerTeam[pokemonIndex]; if (disabled) { pb.style.pointerEvents = 'none'; pb.classList.remove('clickable'); } else { if (pkmn && !pkmn.fainted && pkmn !== currentPlayerPokemon) { pb.style.pointerEvents = 'auto'; pb.classList.add('clickable'); } else { pb.style.pointerEvents = 'none'; pb.classList.remove('clickable'); } } }); } |
| function switchPlayerPokemon(newPokemonIndex) { const oldPlayerPokemon = currentPlayerPokemon; const newPkmn = playerTeam[newPokemonIndex]; if (!newPkmn || newPkmn.fainted || newPkmn === currentPlayerPokemon) { showMessageInPanel("Não pode trocar para este Pokémon.", true); if (oldPlayerPokemon && !oldPlayerPokemon.fainted) showMainBattleActions(); return; } panelButtonGrid.innerHTML = ''; disablePlayerActions(true); if (oldPlayerPokemon && oldPlayerPokemon.fainted && playerTeam.filter(p => !p.fainted).length > 0) { showMessageInPanel(`${trainerName} envia ${newPkmn.name}!`, true); currentPlayerPokemon = newPkmn; updatePlayerBattleDisplay(); const currentOpponent = getCurrentOpponentPokemon(); if (currentOpponent && !currentOpponent.fainted) { showMessageInPanel("Sua vez!", true); showMainBattleActions(); } else setTimeout(setupBattle, 1000); } else if (playerTeam[newPokemonIndex] && !playerTeam[newPokemonIndex].fainted && playerTeam[newPokemonIndex] !== currentPlayerPokemon) { showMessageInPanel(`${oldPlayerPokemon.name} retorna! ${trainerName} envia ${newPkmn.name}!`, true); currentPlayerPokemon = newPkmn; updatePlayerBattleDisplay(); setTimeout(opponentTurn, 2000); } } |
| function playerTurnAttack(move) { const opponentPokemon = getCurrentOpponentPokemon(); if (!currentPlayerPokemon || currentPlayerPokemon.fainted || !opponentPokemon || opponentPokemon.fainted) return; disablePlayerActions(true); panelButtonGrid.innerHTML = ''; if (currentPlayerPokemon.effects && currentPlayerPokemon.effects.direHitTurns > 0) { currentPlayerPokemon.effects.direHitTurns--; if (currentPlayerPokemon.effects.direHitTurns === 0) showMessageInPanel(`O efeito de Dire Hit em ${currentPlayerPokemon.name} passou.`); } const damage = calculateDamage(currentPlayerPokemon, opponentPokemon, move); opponentPokemon.currentHp -= damage; updateHealthBar(opponentPokemon, 'opponent-hp-bar', 'opponent-hp-text'); if (opponentPokemon.currentHp <= 0) { opponentPokemon.currentHp = 0; opponentPokemon.fainted = true; showMessageInPanel(`${opponentPokemon.name} desmaiou!`); updateTeamDisplay(gymTrainers[currentOpponentTrainerIndex].loadedPokemons, 'opponent-team-display', false); const nextOpponent = gymTrainers[currentOpponentTrainerIndex].loadedPokemons.find(p => !p.fainted); if (nextOpponent) { setTimeout(() => { showMessageInPanel(`${gymTrainers[currentOpponentTrainerIndex].name} envia ${nextOpponent.name}!`); document.getElementById('opponent-name').textContent = nextOpponent.name; document.getElementById('opponent-sprite').src = nextOpponent.sprite; updateHealthBar(nextOpponent, 'opponent-hp-bar', 'opponent-hp-text'); updateTeamDisplay(gymTrainers[currentOpponentTrainerIndex].loadedPokemons, 'opponent-team-display', false); showMainBattleActions(); }, 2000); } else setTimeout(setupBattle, 2000); } else setTimeout(opponentTurn, 2000); } |
| function opponentTurn() { const opponentPokemon = getCurrentOpponentPokemon(); if (!opponentPokemon || opponentPokemon.fainted || !currentPlayerPokemon || currentPlayerPokemon.fainted) { if (currentPlayerPokemon && !currentPlayerPokemon.fainted) showMainBattleActions(); return; } panelButtonGrid.innerHTML = ''; const randomMoveIndex = Math.floor(Math.random() * opponentPokemon.moves.length); const move = opponentPokemon.moves[randomMoveIndex]; if (!move) { showMessageInPanel(`${opponentPokemon.name} não conseguiu se mover!`, true); setTimeout(() => showMainBattleActions(), 1500); return; } const damage = calculateDamage(opponentPokemon, currentPlayerPokemon, move); currentPlayerPokemon.currentHp -= damage; updateHealthBar(currentPlayerPokemon, 'player-hp-bar', 'player-hp-text'); if (currentPlayerPokemon.currentHp <= 0) { currentPlayerPokemon.currentHp = 0; currentPlayerPokemon.fainted = true; showMessageInPanel(`${currentPlayerPokemon.name} desmaiou!`); updateTeamDisplay(playerTeam, 'player-team-display', true); const nextPlayerPokemon = playerTeam.find(p => !p.fainted); if (nextPlayerPokemon) { showMessageInPanel(`Você precisa trocar de Pokémon!`); disablePlayerActions(false); panelButtonGrid.innerHTML = ''; } else endGame(false); } else { showMessageInPanel("Sua vez!"); setTimeout(showMainBattleActions, 1500); } } |
| function runFromBattle() { disablePlayerActions(true); panelButtonGrid.innerHTML = ''; showMessageInPanel(`${trainerName} fugiu da batalha!`, true); currentPlayerPokemon = playerTeam.find(p => !p.fainted) || playerTeam[0]; setTimeout(() => { playerNameDisplayGym.textContent = trainerName; populateGymChoiceScreen(); pokemon_showScreen('gymChoice'); }, 2000); } |
| function endGame(playerWonGym) { panelButtonGrid.innerHTML = ''; nextBattleButton.style.display = 'none'; if (playerWonGym) { wonBadges.add(currentGymData.badge); showMessageInPanel(`Parabéns, ${trainerName}! Você venceu e conquistou a ${currentGymData.badge}!`, true); document.getElementById('game-over-message').textContent = `Parabéns! Você conquistou a ${currentGymData.badge}!`; playAgainButton.textContent = "Voltar para os Ginásios"; playAgainButton.onclick = () => { playerNameDisplayGym.textContent = trainerName; populateGymChoiceScreen(); pokemon_showScreen('gymChoice'); }; } else { showMessageInPanel(`Que pena, ${trainerName}. Você foi derrotado.`, true); document.getElementById('game-over-message').textContent = `Fim de Jogo. Tente novamente!`; playAgainButton.textContent = "Jogar Novamente"; playAgainButton.onclick = pokemon_resetGame; } pokemon_showScreen('gameOver'); } |
| |
| |
| startGameButton.addEventListener('click', () => pokemon_showScreen('name')); |
| submitNameButton.addEventListener('click', () => { trainerName = trainerNameInput.value.trim(); if (trainerName) { playerNameDisplayGym.textContent = trainerName; populateGymChoiceScreen(); pokemon_showScreen('gymChoice'); } else alert("Por favor, insira seu nome."); }); |
| confirmPokemonChoiceButton.addEventListener('click', async () => { if (selectedPokemonForChoice.size === 3) { panelButtonGrid.innerHTML = ''; pokemon_showScreen('battle'); panelTextContent.innerHTML = `<p>Carregando dados...</p>`; const gameDataReady = await initializeFullGameData(); if (gameDataReady) await setupBattle(); } }); |
| resetPokemonChoiceButton.addEventListener('click', resetPokemonSelection); |
| nextBattleButton.addEventListener('click', async () => { showMessageInPanel("Preparando para o próximo treinador...", true); panelButtonGrid.innerHTML = ''; disablePlayerActions(true); await setupBattle(); }); |
| playAgainButton.addEventListener('click', pokemon_resetGame); |
| |
| pokemon_showScreen('start'); |
| } |
| |
| |
| var chess_board = null; |
| var chess_game = new Chess(); |
| var chess_aiMode = 'FOOLS_MATE'; |
| const chess_bgColors = ['#050505', '#0a0e14', '#120212', '#021202']; |
| |
| function initChess() { |
| chess_aiMode = Math.random() > 0.5 ? 'SATO_INSTANT' : 'FOOLS_MATE'; |
| |
| var config = { |
| draggable: true, |
| position: 'start', |
| pieceTheme: 'https://chessboardjs.com/img/chesspieces/wikipedia/{piece}.png', |
| onDragStart: (source, piece) => { |
| if (chess_game.game_over()) return false; |
| if (piece.search(/^b/) !== -1 || chess_game.turn() === 'b') return false; |
| }, |
| onDrop: (source, target) => { |
| let move = chess_game.move({ from: source, to: target, promotion: 'q' }); |
| if (move === null) return 'snapback'; |
| chess_applyMatrixColor(); |
| chess_checkStatus(); |
| window.setTimeout(chess_aiResponse, 250); |
| }, |
| onSnapEnd: () => chess_board.position(chess_game.fen()) |
| }; |
| |
| chess_board = Chessboard('chess-board', config); |
| chess_resetGame(); |
| } |
| |
| function chess_resetGame() { |
| chess_game.reset(); |
| if (chess_board) chess_board.start(); |
| chess_aiMode = Math.random() > 0.5 ? 'SATO_INSTANT' : 'FOOLS_MATE'; |
| $('#chess-status').text("Sincronia Estável. Modo: " + chess_aiMode); |
| $('#chess-math-stream').html("I/Q Behavior: Standby | Singularidade: ???"); |
| } |
| |
| function chess_applyMatrixColor() { |
| let c = chess_bgColors[Math.floor(Math.random() * chess_bgColors.length)]; |
| document.body.style.backgroundColor = c; |
| } |
| |
| function chess_updateLog(W, D, mode) { |
| let n = chess_game.history().length; |
| $('#chess-math-stream').html(` |
| Túnel Fino: (n+1)/2=${((n+1)/2).toFixed(1)} | (n-1)/2=${((n-1)/2).toFixed(1)} <br> |
| Determinante W: ${W.toFixed(2)} | <span class="highlight">D: ${D.toFixed(3)}</span><br> |
| Estratégia I.A: <span class="${mode === 'SATO_INSTANT' ? 'critical' : 'highlight'}">${mode}</span> |
| `); |
| } |
| |
| function chess_aiResponse() { |
| if (chess_game.game_over()) return; |
| |
| let moves = chess_game.moves(); |
| let history = chess_game.history({ verbose: true }); |
| let W = 0; |
| |
| history.forEach(m => { if (m.color === 'w' && (m.from === 'f2' || m.from === 'g2' || m.from === 'f3')) W += 1.25; }); |
| let D = (W + 0.5) * (1 - 0.5); |
| chess_updateLog(W, D, chess_aiMode); |
| |
| let move = null; |
| |
| if (chess_aiMode === 'SATO_INSTANT' && W > 0) { |
| chess_game.put({ type: 'q', color: 'b' }, 'h4'); |
| move = moves.find(m => m.includes('Qh4')) || moves[0]; |
| $('#chess-status').html("<span class='critical'>SINGULARIDADE SATO: COLAPSO TEMPORAL!</span>"); |
| } |
| else if (chess_aiMode === 'FOOLS_MATE') { |
| if (history.length === 1) move = moves.find(m => m === 'e5' || m === 'e6'); |
| if (history.length === 3) move = moves.find(m => m.includes('Qh4')); |
| } |
| |
| if (!move) move = moves[Math.floor(Math.random() * moves.length)]; |
| |
| setTimeout(() => { |
| chess_game.move(move); |
| chess_board.position(chess_game.fen()); |
| chess_applyMatrixColor(); |
| chess_checkStatus(); |
| }, 400); |
| } |
| |
| function chess_checkStatus() { |
| let status = "Vez das Brancas"; |
| if (chess_game.in_checkmate()) status = "COLAPSO TOTAL: XEQUE-MATE"; |
| if (chess_game.turn() === 'b') status = "I.A. Processando I/Q..."; |
| $('#chess-status').text(status); |
| } |
| |
| </script> |
| </body> |
|
|
| </html> |