Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
data_object
CSS Explorer
arrow_outward
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
data_array
Python Editor
New
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Save
account_circle
Login
settings
Settings
expand_more
14
px
Live mode
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pokémon Battle Simulator V3</title> <style> :root { /* Color Palette (iOS Inspired) */ --primary-color: #007aff; /* Blue */ --secondary-color: #6c757d; /* Gray */ --success-color: #34c759; /* Green */ --warning-color: #ffcc00; /* Yellow */ --danger-color: #ff3b30; /* Red */ --info-color: #5ac8fa; /* Teal */ --light-gray: #f2f2f7; --medium-gray: #e5e5ea; --dark-gray: #1c1c1e; --text-light: #ffffff; --text-dark: #1d1d1f; /* Fonts */ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-mono: "SF Mono", "Consolas", "Monaco", "Courier New", monospace; /* Type Colors */ --type-normal: #a8a77a; --type-normal-text: white; --type-fire: #f57d31; --type-fire-text: white; --type-water: #6390f0; --type-water-text: white; --type-electric: #f7d02c; --type-electric-text: var(--text-dark); --type-grass: #7ac74c; --type-grass-text: white; --type-ice: #96d9d6; --type-ice-text: var(--text-dark); --type-fighting: #c22e28; --type-fighting-text: white; --type-poison: #a33ea1; --type-poison-text: white; --type-ground: #e2bf65; --type-ground-text: var(--text-dark); --type-flying: #a98ff3; --type-flying-text: white; --type-psychic: #f95587; --type-psychic-text: white; --type-bug: #a6b91a; --type-bug-text: white; --type-rock: #b6a136; --type-rock-text: white; --type-ghost: #735797; --type-ghost-text: white; --type-dragon: #6f35fc; --type-dragon-text: white; --type-dark: #705746; --type-dark-text: white; --type-steel: #b7b7ce; --type-steel-text: var(--text-dark); --type-fairy: #d685ad; --type-fairy-text: white; --type-status: #8a8a8d; --type-status-text: white; /* Status Colors */ --status-par-bg: var(--warning-color); --status-par-text: var(--text-dark); --status-brn-bg: var(--danger-color); --status-brn-text: white; --status-psn-bg: var(--type-poison); --status-psn-text: white; --status-slp-bg: var(--secondary-color); --status-slp-text: white; --status-frz-bg: var(--info-color); --status-frz-text: var(--text-dark); } *, *::before, *::after { box-sizing: border-box; } html { font-size: 16px; } body { font-family: var(--font-sans); background-color: var(--light-gray); background-image: linear-gradient(45deg, rgba(0,0,0,0.02) 25%, transparent 25%, transparent 75%, rgba(0,0,0,0.02) 75%, rgba(0,0,0,0.02)), linear-gradient(45deg, rgba(0,0,0,0.02) 25%, transparent 25%, transparent 75%, rgba(0,0,0,0.02) 75%, rgba(0,0,0,0.02)); background-size: 60px 60px; background-position: 0 0, 30px 30px; margin: 0; padding: 1rem; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--text-dark); line-height: 1.6; min-height: 100vh; overflow-x: hidden; /* Prevent horizontal scroll during animations */ } .battle-container { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 700px; /* Slightly wider */ gap: 1rem; } .battlefield { background: rgba(255, 255, 255, 0.95); /* More opaque */ backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); /* Safari */ border: 1px solid rgba(0,0,0,0.08); border-radius: 28px; /* Even more rounded */ box-shadow: 0 15px 40px rgba(0,0,0,0.12), 0 5px 15px rgba(0,0,0,0.08); width: 100%; padding: 1.5rem 2rem; /* More padding */ position: relative; overflow: hidden; transition: transform 0.3s ease-out; /* For screen shake */ } .battlefield.shake { animation: screen-shake 0.3s linear; } @keyframes screen-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 50% { transform: translateX(4px); } 75% { transform: translateX(-4px); } } .side { display: flex; align-items: flex-end; gap: 1rem; margin-bottom: 3rem; /* Increased space between sides */ min-height: 120px; /* Taller */ position: relative; } .side:last-child { margin-bottom: 0; } .left { justify-content: flex-start; } .right { justify-content: flex-end; text-align: right;} .avatar-container { width: 120px; /* Larger avatar */ height: 120px; position: relative; flex-shrink: 0; /* Prevent shrinking */ transform: translateY(100%); opacity: 0; transition: transform 0.7s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.6s ease-out; } .avatar-container.enter { transform: translateY(0); opacity: 1; } .avatar { width: 100%; height: 100%; background: var(--medium-gray); border-radius: 16px; /* More rounded */ border: 4px solid transparent; display: flex; align-items: center; justify-content: center; overflow: hidden; image-rendering: pixelated; /* Keep pixel art sharp */ image-rendering: crisp-edges; /* Better compatibility */ transition: transform 0.3s ease-out, filter 0.5s ease-out, border-color 0.3s ease; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .avatar img { width: 100%; height: 100%; object-fit: contain; transition: transform 0.15s ease-in-out, opacity 0.5s ease-out; opacity: 0; /* Start hidden, fade in via JS */ } .avatar.placeholder { border: 4px dashed #a0a0a5; background: var(--light-gray); } /* Active/Idle state */ .active .avatar { animation: active-bounce 1.3s infinite ease-in-out; } @keyframes active-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px) scale(1.02); } } /* Stat Change Indicator */ .stat-change-indicator { position: absolute; top: -12px; /* Slightly higher */ left: 50%; transform: translateX(-50%); font-size: 1.8rem; /* Larger */ font-weight: bold; opacity: 0; animation: stat-float 1.3s ease-out forwards; /* Longer duration */ z-index: 5; text-shadow: 0 2px 4px rgba(0,0,0,0.3); } .stat-up { color: var(--success-color); } .stat-down { color: var(--danger-color); } @keyframes stat-float { 0% { opacity: 1; transform: translate(-50%, 10px) scale(0.8); } 20% { transform: translate(-50%, -15px) scale(1.1); } /* Bounce up */ 100% { opacity: 0; transform: translate(-50%, -40px) scale(0.6); } /* Fade out higher */ } /* Hit animation */ .hit .avatar img { animation: hit-shake 0.3s linear; } .opponent.hit .avatar img { animation: hit-shake-opponent 0.3s linear; } /* Use specific class for opponent */ @keyframes hit-shake { /* Player (sprite faces right, needs scaleX(-1)) */ 0%, 100% { transform: translateX(0) scaleX(-1); } 25%, 75% { transform: translateX(-7px) scaleX(-1); } 50% { transform: translateX(7px) scaleX(-1); } } @keyframes hit-shake-opponent { /* Opponent (sprite faces left) */ 0%, 100% { transform: translateX(0); } 25%, 75% { transform: translateX(7px); } /* Opposite direction shake */ 50% { transform: translateX(-7px); } } /* Faint animation */ .fainted .avatar-container { animation: faint-fall 1.1s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards; } /* EaseInBack */ .fainted .avatar img { filter: grayscale(1) opacity(0.4); transition: filter 0.9s ease-out; } @keyframes faint-fall { 0% { transform: translateY(0) rotate(0deg); opacity: 1; } 100% { transform: translateY(70px) rotate(-20deg); opacity: 0; } } .info { display: flex; flex-direction: column; gap: 0.5rem; font-size: 1rem; flex-grow: 1; padding-bottom: 8px; position: relative; /* For stat indicator positioning */ } /* Position stat indicator relative to info box instead of name */ .info .stat-change-indicator { top: -15px; /* Adjust position relative to info box top */ left: 50%; } .right .info .stat-change-indicator { left: 50%; /* Keep centered */ } .name-status { display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.3rem; /* position: relative; Remove relative positioning here */ } .right .name-status { justify-content: flex-end; } .name { font-weight: 700; /* Bolder */ font-size: 1.4rem; } .status-badge { font-size: 0.8rem; font-weight: bold; padding: 0.2rem 0.6rem; border-radius: 8px; text-transform: uppercase; color: var(--text-light); box-shadow: 0 1px 3px rgba(0,0,0,0.25); transition: opacity 0.4s ease, transform 0.4s ease; opacity: 1; transform: scale(1); } .status-badge.hidden { opacity: 0; transform: scale(0.7); pointer-events: none; } .status-PAR { background-color: var(--status-par-bg); color: var(--status-par-text); } .status-BRN { background-color: var(--status-brn-bg); color: var(--status-brn-text); } .status-PSN { background-color: var(--status-psn-bg); color: var(--status-psn-text); } .status-SLP { background-color: var(--status-slp-bg); color: var(--status-slp-text); } .status-FRZ { background-color: var(--status-frz-bg); color: var(--status-frz-text); } .level { font-size: 0.9rem; color: var(--secondary-color); } .hp-bar { background: var(--medium-gray); border-radius: 999px; overflow: hidden; height: 16px; /* Thicker */ width: 100%; max-width: 240px; /* Max width */ border: 1px solid #bbb; /* Slightly darker border */ position: relative; box-shadow: inset 0 1px 3px rgba(0,0,0,0.15); } .right .hp-bar { margin-left: auto; } .hp-fill { background: var(--success-color); height: 100%; transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.5s ease-out; border-radius: 999px; position: relative; } .hp-bar::before { content: 'HP'; position: absolute; left: 8px; top: 50%; transform: translateY(-50%); font-size: 10px; font-weight: bold; color: rgba(0,0,0,0.7); line-height: 1; z-index: 1; } .hp-text { font-size: 0.9rem; color: var(--secondary-color); font-weight: 600; margin-top: 0.3rem; } .right .hp-text { text-align: right; } .console { background: var(--dark-gray); border-radius: 16px; color: var(--text-light); padding: 1.25rem; font-family: var(--font-mono); font-size: 0.95rem; min-height: 150px; max-height: 350px; overflow-y: auto; line-height: 1.6; width: 100%; box-shadow: inset 0 4px 8px rgba(0,0,0,0.4); border: 1px solid #444; scrollbar-width: thin; scrollbar-color: var(--primary-color) #3a3a3c; scroll-behavior: smooth; /* Smooth scrolling */ } .console::-webkit-scrollbar { width: 8px; } .console::-webkit-scrollbar-track { background: #3a3a3c; border-radius: 4px;} .console::-webkit-scrollbar-thumb { background-color: var(--primary-color); border-radius: 4px; border: 2px solid #3a3a3c; } .console > div { padding-bottom: 0.4rem; margin-bottom: 0.4rem; border-bottom: 1px solid #4a4a4c; /* Lighter separator */ transition: background-color 0.5s ease; } .console > div:last-child { border-bottom: none; } .console > div.highlight { background-color: rgba(255, 255, 255, 0.1); } .console .effectiveness { font-style: italic; color: #a0a0a5; } .console .critical { font-weight: bold; color: var(--warning-color); animation: pulse-yellow 0.8s ease-in-out; } .console .status-change { color: var(--info-color); font-style: italic; } .console .stat-change { color: #b0b0b0; font-style: italic; } .console .turn-divider { text-align: center; font-weight: bold; color: var(--info-color); margin: 1rem 0; padding-bottom: 1rem; letter-spacing: 1.5px; border-color: var(--info-color) !important; } .console .game-over { text-align: center; font-weight: bold; font-size: 1.2rem; margin-top: 1.2rem; color: var(--success-color); animation: pulse-green 1s infinite; } .console .player-prompt { font-weight: bold; color: var(--primary-color); } .console .player-choice { color: #87cefa; } /* LightSkyBlue */ .console .opponent-choice { color: #ff7f7f; } /* LightCoral */ .console .immune { font-style: italic; color: var(--secondary-color); } @keyframes pulse-yellow { 0%, 100% { text-shadow: 0 0 5px var(--warning-color); } 50% { text-shadow: 0 0 15px var(--warning-color); } } @keyframes pulse-green { 0%, 100% { text-shadow: 0 0 5px var(--success-color); } 50% { text-shadow: 0 0 15px var(--success-color); } } .attack-icon { position: absolute; font-size: 45px; /* Even larger */ pointer-events: none; z-index: 10; opacity: 1; transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.8s ease-out; /* EaseOutBack */ text-shadow: 0 4px 6px rgba(0,0,0,0.3); will-change: transform, opacity; /* Performance hint */ } /* Player Controls */ .player-controls { background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); /* Safari */ border: 1px solid rgba(0,0,0,0.07); border-radius: 20px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); padding: 1.25rem; width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem; transition: opacity 0.5s ease-out, transform 0.5s ease-out; position: relative; will-change: opacity, transform; /* Performance hint */ } .player-controls.hidden { opacity: 0; transform: translateY(40px); pointer-events: none; } .move-button { padding: 0.8rem 1.1rem; font-size: 1rem; font-weight: 600; border: none; border-radius: 14px; background-color: var(--medium-gray); color: var(--text-dark); cursor: pointer; text-align: center; transition: all 0.25s ease; position: relative; overflow: hidden; box-shadow: 0 3px 6px rgba(0,0,0,0.08); border: 1px solid rgba(0,0,0,0.1); } .move-button:hover:not(:disabled) { box-shadow: 0 6px 12px rgba(0,0,0,0.12); transform: translateY(-3px); filter: brightness(1.05); /* Slight brighten */ } .move-button:active:not(:disabled) { transform: scale(0.95) translateY(0); box-shadow: 0 2px 4px rgba(0,0,0,0.1); filter: brightness(0.95); /* Slight darken */ } .move-button:disabled { opacity: 0.4; cursor: not-allowed; background-color: var(--medium-gray) !important; /* Ensure override */ box-shadow: none; color: var(--secondary-color) !important; /* Ensure override */ filter: grayscale(50%); } .move-button:disabled .move-pp { color: var(--secondary-color) !important; } .move-pp { font-size: 0.75rem; color: rgba(0,0,0,0.55); display: block; margin-top: 4px; font-weight: 500; } /* Type-specific button styling (using CSS variables for text color) */ .move-button[data-type="Normal"] { background-color: var(--type-normal); color: var(--type-normal-text); --button-text-color: var(--type-normal-text); } .move-button[data-type="Fire"] { background-color: var(--type-fire); color: var(--type-fire-text); --button-text-color: var(--type-fire-text); } .move-button[data-type="Water"] { background-color: var(--type-water); color: var(--type-water-text); --button-text-color: var(--type-water-text); } .move-button[data-type="Electric"] { background-color: var(--type-electric); color: var(--type-electric-text); --button-text-color: var(--type-electric-text); } .move-button[data-type="Grass"] { background-color: var(--type-grass); color: var(--type-grass-text); --button-text-color: var(--type-grass-text); } .move-button[data-type="Ice"] { background-color: var(--type-ice); color: var(--type-ice-text); --button-text-color: var(--type-ice-text); } .move-button[data-type="Fighting"] { background-color: var(--type-fighting); color: var(--type-fighting-text); --button-text-color: var(--type-fighting-text); } .move-button[data-type="Poison"] { background-color: var(--type-poison); color: var(--type-poison-text); --button-text-color: var(--type-poison-text); } .move-button[data-type="Ground"] { background-color: var(--type-ground); color: var(--type-ground-text); --button-text-color: var(--type-ground-text); } .move-button[data-type="Flying"] { background-color: var(--type-flying); color: var(--type-flying-text); --button-text-color: var(--type-flying-text); } .move-button[data-type="Psychic"] { background-color: var(--type-psychic); color: var(--type-psychic-text); --button-text-color: var(--type-psychic-text); } .move-button[data-type="Bug"] { background-color: var(--type-bug); color: var(--type-bug-text); --button-text-color: var(--type-bug-text); } .move-button[data-type="Rock"] { background-color: var(--type-rock); color: var(--type-rock-text); --button-text-color: var(--type-rock-text); } .move-button[data-type="Ghost"] { background-color: var(--type-ghost); color: var(--type-ghost-text); --button-text-color: var(--type-ghost-text); } .move-button[data-type="Dragon"] { background-color: var(--type-dragon); color: var(--type-dragon-text); --button-text-color: var(--type-dragon-text); } .move-button[data-type="Dark"] { background-color: var(--type-dark); color: var(--type-dark-text); --button-text-color: var(--type-dark-text); } .move-button[data-type="Steel"] { background-color: var(--type-steel); color: var(--type-steel-text); --button-text-color: var(--type-steel-text); } .move-button[data-type="Fairy"] { background-color: var(--type-fairy); color: var(--type-fairy-text); --button-text-color: var(--type-fairy-text); } .move-button[data-category="Status"] { background-color: var(--type-status); color: var(--type-status-text); --button-text-color: var(--type-status-text); } /* Use text color variable for PP */ .move-button[data-type] .move-pp, .move-button[data-category="Status"] .move-pp { color: color-mix(in srgb, var(--button-text-color, black) 65%, transparent); } .restart-button { margin-top: 1.5rem; padding: 0.9rem 1.8rem; font-size: 1.1rem; font-weight: 600; border: none; border-radius: 14px; background-color: var(--primary-color); color: white; cursor: pointer; transition: all 0.25s ease; box-shadow: 0 5px 12px rgba(0, 122, 255, 0.35); display: inline-block; /* Allow margin top */ } .restart-button:hover { background-color: #005fcc; /* Darker blue */ box-shadow: 0 7px 15px rgba(0, 122, 255, 0.45); transform: translateY(-2px); } .restart-button:active { background-color: #004080; transform: translateY(0); box-shadow: 0 3px 7px rgba(0, 122, 255, 0.25); } .restart-button.hidden { display: none; } /* Media Query for smaller screens */ @media (max-width: 640px) { body { padding: 0.5rem; } .battle-container { gap: 0.75rem; } .battlefield { padding: 1rem 1.25rem; border-radius: 20px;} .side { margin-bottom: 2rem; gap: 0.75rem; min-height: 100px;} .avatar-container { width: 100px; height: 100px;} .avatar { border-radius: 12px; border-width: 3px;} .info { gap: 0.3rem; padding-bottom: 5px;} .name { font-size: 1.2rem; } .level { font-size: 0.8rem; } .hp-bar { height: 14px; max-width: 190px; border-width: 1px;} .hp-bar::before { font-size: 9px; left: 6px;} .hp-text { font-size: 0.8rem; } .console { min-height: 120px; max-height: 250px; font-size: 0.85rem; padding: 1rem; border-radius: 12px; } .player-controls { padding: 1rem; gap: 0.75rem; grid-template-columns: repeat(2, 1fr); border-radius: 16px;} .move-button { padding: 0.7rem 0.9rem; font-size: 0.9rem; border-radius: 12px; } .move-pp { font-size: 0.7rem;} .attack-icon { font-size: 35px; } .restart-button { padding: 0.8rem 1.5rem; font-size: 1rem; margin-top: 1rem;} } </style> </head> <body> <div class="battle-container"> <div class="battlefield" id="battlefield"> <!-- Opponent Side --> <div class="side right opponent" id="opponent-side"> <div class="info"> <div class="name-status"> <span class="status-badge hidden" id="pokemon1-status"></span> <div class="name" id="pokemon1-name">Opponent</div> </div> <div class="level" id="pokemon1-level">Lv. ?</div> <div class="hp-bar"><div class="hp-fill" id="pokemon1-hp"></div></div> <div class="hp-text" id="pokemon1-hp-text">? / ? HP</div> </div> <div class="avatar-container" id="pokemon1-avatar-container"> <div class="avatar placeholder" id="pokemon1-avatar"></div> </div> </div> <!-- Player Side --> <div class="side left player" id="player-side"> <div class="avatar-container" id="pokemon2-avatar-container"> <div class="avatar placeholder" id="pokemon2-avatar"></div> </div> <div class="info"> <div class="name-status"> <div class="name" id="pokemon2-name">Player</div> <span class="status-badge hidden" id="pokemon2-status"></span> </div> <div class="level" id="pokemon2-level">Lv. ?</div> <div class="hp-bar"><div class="hp-fill" id="pokemon2-hp"></div></div> <div class="hp-text" id="pokemon2-hp-text">? / ? HP</div> </div> </div> </div> <div class="console" id="console">Initializing Battle Environment...</div> <div class="player-controls hidden" id="player-controls"> <!-- Move buttons will be generated here --> </div> <button id="restart-button" class="restart-button hidden">Battle Again!</button> </div> <script> // ********* MODULE: GLOBAL STATE & CONSTANTS ************** const BATTLE_STATE = { playerPokemon: null, opponentPokemon: null, isPlayerTurn: false, waitingForPlayer: false, gameOver: false, playerMoveResolver: null, // Promise resolver for player input turnCounter: 0, battleLog: [], // Keep track of log messages if needed later isProcessing: false, // Flag to prevent multiple actions during animations/processing }; const STATUS_EFFECTS = { PAR: { name: 'PAR', badgeText: 'PAR', cssClass: 'status-PAR', turnStartEffect: true }, BRN: { name: 'BRN', badgeText: 'BRN', cssClass: 'status-BRN', turnEndEffect: true }, PSN: { name: 'PSN', badgeText: 'PSN', cssClass: 'status-PSN', turnEndEffect: true }, SLP: { name: 'SLP', badgeText: 'SLP', cssClass: 'status-SLP', turnStartEffect: true }, // Counter handled in Pokemon class FRZ: { name: 'FRZ', badgeText: 'FRZ', cssClass: 'status-FRZ', turnStartEffect: true }, }; const ANIMATION_DELAY = { SHORT: 400, MEDIUM: 700, LONG: 900, HP_BAR: 600, ATTACK_ICON: 800, FAINT: 1100, TURN_TRANSITION: 600, STATUS_EFFECT: 800, STAT_CHANGE: 1300, // Increased to match new animation duration ENTRY: 700, // Corresponds to avatar-container transition }; // Accuracy/Evasion Stages (Simplified: Multiplier applied to move accuracy) const ACC_EVA_MULTIPLIERS = { '-6': 3/9, '-5': 3/8, '-4': 3/7, '-3': 3/6, '-2': 3/5, '-1': 3/4, '0': 1, '1': 4/3, '2': 5/3, '3': 6/3, '4': 7/3, '5': 8/3, '6': 9/3 }; // Stat Stage Multipliers (Atk, Def, SpA, SpD, Spe) const STAT_STAGE_MULTIPLIERS = { '-6': 2/8, '-5': 2/7, '-4': 2/6, '-3': 2/5, '-2': 2/4, '-1': 2/3, '0': 1, '1': 3/2, '2': 4/2, '3': 5/2, '4': 6/2, '5': 7/2, '6': 8/2 }; // Simplified Type Chart (Gen VI+) const TYPE_CHART = { Normal: { Rock: 0.5, Ghost: 0, Steel: 0.5 }, Fire: { Fire: 0.5, Water: 0.5, Grass: 2, Ice: 2, Bug: 2, Rock: 0.5, Dragon: 0.5, Steel: 2 }, Water: { Fire: 2, Water: 0.5, Grass: 0.5, Ground: 2, Rock: 2, Dragon: 0.5 }, Electric: { Water: 2, Electric: 0.5, Grass: 0.5, Ground: 0, Flying: 2, Dragon: 0.5 }, Grass: { Fire: 0.5, Water: 2, Grass: 0.5, Poison: 0.5, Ground: 2, Flying: 0.5, Bug: 0.5, Rock: 2, Dragon: 0.5, Steel: 0.5 }, Ice: { Fire: 0.5, Water: 0.5, Grass: 2, Ice: 0.5, Ground: 2, Flying: 2, Dragon: 2, Steel: 0.5 }, Fighting: { Normal: 2, Flying: 0.5, Poison: 0.5, Rock: 2, Bug: 0.5, Ghost: 0, Psychic: 0.5, Ice: 2, Dark: 2, Steel: 2, Fairy: 0.5 }, Poison: { Grass: 2, Poison: 0.5, Ground: 0.5, Rock: 0.5, Ghost: 0.5, Steel: 0, Fairy: 2 }, Ground: { Fire: 2, Electric: 2, Grass: 0.5, Poison: 2, Flying: 0, Bug: 0.5, Rock: 2, Steel: 2 }, Flying: { Electric: 0.5, Grass: 2, Fighting: 2, Bug: 2, Rock: 0.5, Steel: 0.5 }, Psychic: { Fighting: 2, Poison: 2, Psychic: 0.5, Dark: 0, Steel: 0.5 }, Bug: { Fire: 0.5, Grass: 2, Fighting: 0.5, Poison: 0.5, Flying: 0.5, Psychic: 2, Ghost: 0.5, Dark: 2, Steel: 0.5, Fairy: 0.5 }, Rock: { Fire: 2, Ice: 2, Fighting: 0.5, Ground: 0.5, Flying: 2, Bug: 2, Steel: 0.5 }, Ghost: { Normal: 0, Psychic: 2, Ghost: 2, Dark: 0.5 }, Dragon: { Dragon: 2, Steel: 0.5, Fairy: 0 }, Dark: { Fighting: 0.5, Psychic: 2, Ghost: 2, Dark: 0.5, Fairy: 0.5 }, Steel: { Normal: 1, Fire: 0.5, Water: 0.5, Electric: 0.5, Grass: 1, Ice: 2, Fighting: 1, Poison: 1, Ground: 1, Flying: 1, Psychic: 1, Bug: 1, Rock: 2, Ghost: 1, Dragon: 1, Dark: 1, Steel: 0.5, Fairy: 2 }, Fairy: { Fire: 0.5, Fighting: 2, Poison: 0.5, Dragon: 2, Dark: 2, Steel: 0.5 } }; const ATTACK_ICONS = { Fire: '
.lw { font-size: 60px; }
Check out the new AI-powered Python Playground
×