Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Palindrome Palace Builder</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- @keyframes glow {
- 0%, 100% { filter: drop-shadow(0 0 20px rgba(255, 0, 255, 0.5)); }
- 50% { filter: drop-shadow(0 0 40px rgba(0, 255, 255, 0.8)); }
- }
- @keyframes shake {
- 0%, 100% { transform: translateX(0); }
- 10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
- 20%, 40%, 60%, 80% { transform: translateX(5px); }
- }
- @keyframes collapse {
- 0% { transform: translateY(0) rotate(0deg); opacity: 1; }
- 100% { transform: translateY(500px) rotate(720deg); opacity: 0; }
- }
- @keyframes float {
- 0%, 100% { transform: translateY(0); }
- 50% { transform: translateY(-10px); }
- }
- body {
- min-height: 100vh;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #c471f5 75%, #667eea 100%);
- background-size: 400% 400%;
- animation: gradient 15s ease infinite;
- font-family: 'Courier New', monospace;
- display: flex;
- flex-direction: column;
- align-items: center;
- overflow-x: hidden;
- position: relative;
- }
- @keyframes gradient {
- 0%, 100% { background-position: 0% 50%; }
- 50% { background-position: 100% 50%; }
- }
- #stars {
- position: fixed;
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 0;
- }
- .star {
- position: absolute;
- width: 2px;
- height: 2px;
- background: white;
- border-radius: 50%;
- animation: twinkle 3s infinite;
- }
- @keyframes twinkle {
- 0%, 100% { opacity: 0; }
- 50% { opacity: 1; }
- }
- #gameContainer {
- width: 100%;
- max-width: 1200px;
- padding: 20px;
- position: relative;
- z-index: 1;
- }
- #header {
- text-align: center;
- color: white;
- margin-bottom: 30px;
- animation: glow 3s infinite;
- }
- h1 {
- font-size: 3em;
- text-shadow: 0 0 30px rgba(255, 255, 255, 0.5);
- margin-bottom: 10px;
- background: linear-gradient(45deg, #fff, #ff00ff, #00ffff, #fff);
- background-size: 200% 200%;
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- animation: gradient 3s ease infinite;
- }
- #stats {
- display: flex;
- justify-content: center;
- gap: 30px;
- margin-bottom: 20px;
- flex-wrap: wrap;
- }
- .stat {
- background: rgba(255, 255, 255, 0.1);
- backdrop-filter: blur(10px);
- border: 2px solid rgba(255, 255, 255, 0.3);
- border-radius: 20px;
- padding: 15px 25px;
- color: white;
- font-size: 1.1em;
- text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
- }
- .stat span {
- font-weight: bold;
- color: #00ffff;
- text-shadow: 0 0 15px #00ffff;
- }
- #inputArea {
- display: flex;
- gap: 15px;
- margin-bottom: 30px;
- justify-content: center;
- flex-wrap: wrap;
- }
- #palindromeInput {
- padding: 15px 25px;
- font-size: 1.2em;
- border: 3px solid rgba(255, 255, 255, 0.3);
- border-radius: 50px;
- background: rgba(0, 0, 0, 0.3);
- backdrop-filter: blur(10px);
- color: white;
- width: 400px;
- max-width: 90%;
- text-align: center;
- transition: all 0.3s;
- }
- #palindromeInput:focus {
- outline: none;
- border-color: #00ffff;
- box-shadow: 0 0 30px rgba(0, 255, 255, 0.5);
- }
- #palindromeInput::placeholder {
- color: rgba(255, 255, 255, 0.5);
- }
- button {
- padding: 15px 35px;
- font-size: 1.1em;
- border: none;
- border-radius: 50px;
- background: linear-gradient(45deg, #ff00ff, #00ffff);
- color: white;
- font-weight: bold;
- cursor: pointer;
- transition: all 0.3s;
- text-transform: uppercase;
- letter-spacing: 2px;
- position: relative;
- overflow: hidden;
- }
- button:before {
- content: '';
- position: absolute;
- top: 50%;
- left: 50%;
- width: 0;
- height: 0;
- border-radius: 50%;
- background: rgba(255, 255, 255, 0.5);
- transform: translate(-50%, -50%);
- transition: width 0.5s, height 0.5s;
- }
- button:hover:before {
- width: 300px;
- height: 300px;
- }
- button:hover {
- transform: translateY(-3px);
- box-shadow: 0 10px 30px rgba(0, 255, 255, 0.5);
- }
- button:disabled {
- opacity: 0.5;
- cursor: not-allowed;
- }
- #palace {
- min-height: 400px;
- display: flex;
- flex-direction: column;
- align-items: center;
- position: relative;
- padding: 20px;
- margin-top: 30px;
- }
- .floor {
- display: flex;
- justify-content: center;
- width: 100%;
- margin-bottom: 5px;
- position: relative;
- }
- .beam {
- padding: 15px 25px;
- margin: 0 5px;
- background: linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(200, 200, 255, 0.9));
- border: 2px solid rgba(255, 255, 255, 0.8);
- border-radius: 10px;
- font-weight: bold;
- font-size: 1.1em;
- color: #4a0080;
- box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
- transition: all 0.3s;
- cursor: pointer;
- position: relative;
- animation: float 3s ease-in-out infinite;
- animation-delay: calc(var(--beam-index) * 0.1s);
- }
- .beam:hover {
- transform: scale(1.05);
- box-shadow: 0 8px 30px rgba(255, 0, 255, 0.5);
- background: linear-gradient(135deg, rgba(255, 255, 255, 1), rgba(255, 200, 255, 1));
- }
- .beam.strong {
- background: linear-gradient(135deg, #ffd700, #ffed4e);
- border-color: #ffd700;
- box-shadow: 0 5px 30px rgba(255, 215, 0, 0.5);
- }
- .beam.medium {
- background: linear-gradient(135deg, #c0c0c0, #e8e8e8);
- border-color: #c0c0c0;
- }
- .beam.weak {
- background: linear-gradient(135deg, #cd7f32, #d4a574);
- border-color: #cd7f32;
- opacity: 0.9;
- }
- .beam.shaking {
- animation: shake 0.5s;
- }
- .beam.collapsing {
- animation: collapse 1s forwards;
- }
- .stability-indicator {
- position: absolute;
- top: -25px;
- right: -10px;
- background: rgba(0, 0, 0, 0.7);
- color: white;
- padding: 5px 10px;
- border-radius: 15px;
- font-size: 0.9em;
- font-weight: normal;
- }
- #foundation {
- width: 80%;
- max-width: 600px;
- height: 30px;
- background: linear-gradient(90deg, #8b7355, #a0826d);
- border: 3px solid #654321;
- border-radius: 10px;
- margin-top: 20px;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
- }
- #message {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: rgba(0, 0, 0, 0.9);
- color: white;
- padding: 30px 50px;
- border-radius: 20px;
- border: 3px solid;
- font-size: 1.5em;
- display: none;
- text-align: center;
- z-index: 1000;
- animation: glow 2s infinite;
- }
- #message.success {
- border-color: #00ff00;
- box-shadow: 0 0 50px rgba(0, 255, 0, 0.5);
- }
- #message.error {
- border-color: #ff0000;
- box-shadow: 0 0 50px rgba(255, 0, 0, 0.5);
- }
- #message.warning {
- border-color: #ffff00;
- box-shadow: 0 0 50px rgba(255, 255, 0, 0.5);
- }
- .tooltip {
- position: absolute;
- bottom: 100%;
- left: 50%;
- transform: translateX(-50%);
- background: rgba(0, 0, 0, 0.9);
- color: #00ffff;
- padding: 8px 15px;
- border-radius: 10px;
- font-size: 0.9em;
- white-space: nowrap;
- opacity: 0;
- pointer-events: none;
- transition: opacity 0.3s;
- z-index: 100;
- }
- .beam:hover .tooltip {
- opacity: 1;
- }
- </style>
- </head>
- <body>
- <div id="stars"></div>
- <div id="gameContainer">
- <div id="header">
- <h1>✨ Palindrome Palace Builder ✨</h1>
- <p style="color: #fff; font-size: 1.2em; margin-top: 10px;">Stack symmetric phrases to build your mystical tower!</p>
- </div>
- <div id="stats">
- <div class="stat">Height: <span id="height">0</span> floors</div>
- <div class="stat">Stability: <span id="stability">100</span>%</div>
- <div class="stat">Score: <span id="score">0</span></div>
- <div class="stat">Disaster Risk: <span id="disasterRisk">Low</span></div>
- </div>
- <div id="inputArea">
- <input type="text" id="palindromeInput" placeholder="Enter a word (e.g., 'racecar' or any noun/adverb!)" />
- <button id="addBeam">Add Beam</button>
- <button id="testDisaster">Test Disaster</button>
- </div>
- <div id="palace">
- <div id="foundation"></div>
- </div>
- </div>
- <div id="message"></div>
- <script>
- class PalindromePalace {
- constructor() {
- this.beams = [];
- this.score = 0;
- this.height = 0;
- this.stability = 100;
- this.disasterEffects = {
- 'Earthquake': { resistant: ['adverb'], prone: ['verb'] },
- 'Tornado': { resistant: ['palindrome'], prone: ['pronoun', 'misspelled'] },
- 'Tsunami': { resistant: ['verb'], prone: ['noun'] },
- 'Volcano': { resistant: ['noun'], prone: ['adverb'] },
- 'Meteor': { resistant: ['misspelled'], prone: ['palindrome'] },
- 'Flood': { resistant: ['pronoun'], prone: ['verb'] }
- };
- this.autoDisasterTimer = null;
- this.init();
- }
- init() {
- this.createStars();
- this.setupEventListeners();
- this.updateDisplay();
- this.scheduleNextDisaster();
- }
- createStars() {
- const starsContainer = document.getElementById('stars');
- for (let i = 0; i < 100; i++) {
- const star = document.createElement('div');
- star.className = 'star';
- star.style.left = Math.random() * 100 + '%';
- star.style.top = Math.random() * 100 + '%';
- star.style.animationDelay = Math.random() * 3 + 's';
- starsContainer.appendChild(star);
- }
- }
- setupEventListeners() {
- document.getElementById('addBeam').addEventListener('click', () => this.addBeam());
- document.getElementById('testDisaster').addEventListener('click', () => this.triggerRandomDisaster());
- document.getElementById('palindromeInput').addEventListener('keypress', (e) => {
- if (e.key === 'Enter') this.addBeam();
- });
- }
- isPalindrome(str) {
- const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
- return cleaned === cleaned.split('').reverse().join('');
- }
- getWordType(word) {
- const cleaned = word.toLowerCase().replace(/[^a-z0-9]/g, '');
- if (this.isPalindrome(word)) return 'palindrome';
- const pronouns = ['i', 'you', 'he', 'she', 'it', 'we', 'they', 'me', 'him', 'her', 'us', 'them'];
- if (pronouns.includes(cleaned)) return 'pronoun';
- if (word.toLowerCase().endsWith('ly')) return 'adverb';
- if (word.toLowerCase().endsWith('ing') || word.toLowerCase().endsWith('ed')) return 'verb';
- if (!/^[a-z]+$/i.test(word)) return 'misspelled';
- return 'noun';
- }
- calculateStrength(word) {
- const length = word.length;
- if (this.isPalindrome(word)) {
- if (length <= 5) return { strength: 90, class: 'strong' };
- if (length <= 10) return { strength: 70, class: 'medium' };
- return { strength: 50, class: 'weak' };
- } else {
- return { strength: 30, class: 'weak' };
- }
- }
- addBeam() {
- const input = document.getElementById('palindromeInput');
- const word = input.value.trim();
- if (!word) {
- this.showMessage('Enter a word!', 'error');
- return;
- }
- const wordType = this.getWordType(word);
- if (this.beams.some(beam => beam.text.toLowerCase() === word.toLowerCase())) {
- this.showMessage('This beam already exists! Use unique words!', 'warning');
- return;
- }
- const { strength, class: strengthClass } = this.calculateStrength(word);
- const beam = {
- text: word,
- strength: strength,
- class: strengthClass,
- points: word.length * 10,
- wordType: wordType
- };
- this.beams.push(beam);
- this.beams.sort((a, b) => b.text.length - a.text.length);
- this.rebuild(this.beams);
- this.score += beam.points;
- const baseChange = word.length;
- if (wordType === 'palindrome') {
- this.stability = Math.min(100, this.stability + baseChange);
- this.showMessage(`Symmetric beam added! +${beam.points} points! Stability increased!`, 'success');
- if (word.length % 2 === 0) {
- this.score += 50;
- this.showMessage('Perfect symmetry bonus! +50 points!', 'success');
- }
- } else {
- let decreaseFactor = 8; // 700% increase for general non-pal
- if (['pronoun', 'verb', 'misspelled'].includes(wordType)) {
- decreaseFactor = 14; // 1300% increase for special
- }
- this.stability = Math.max(0, this.stability - baseChange * decreaseFactor);
- this.showMessage(`Asymmetric beam added! +${beam.points} points, but stability decreased!`, 'warning');
- }
- input.value = '';
- this.updateDisplay();
- if (Math.random() < this.getDisasterChanceOnAdd()) {
- setTimeout(() => this.triggerRandomDisaster(), 500);
- }
- }
- getDisasterChanceOnAdd() {
- return 1 / (Math.floor(Math.random() * 7) + 6); // 1/6 to 1/12
- }
- renderBeam(beam) {
- const palace = document.getElementById('palace');
- let floor = palace.querySelector('.floor:first-child');
- if (!floor || floor.children.length >= 3) {
- floor = document.createElement('div');
- floor.className = 'floor';
- palace.insertBefore(floor, palace.firstChild);
- this.height++;
- }
- const beamElement = document.createElement('div');
- beamElement.className = `beam ${beam.class}`;
- beamElement.textContent = beam.text;
- beamElement.style.setProperty('--beam-index', this.beams.length);
- const tooltip = document.createElement('div');
- tooltip.className = 'tooltip';
- tooltip.textContent = `Strength: ${beam.strength}% | Type: ${beam.wordType}`;
- beamElement.appendChild(tooltip);
- floor.appendChild(beamElement);
- }
- scheduleNextDisaster() {
- let time = 30 - (this.beams.length * 0.5);
- time = Math.max(10, time + (Math.random() * 20 - 10));
- this.autoDisasterTimer = setTimeout(() => {
- if (this.beams.length > 0 && this.stability > 0) {
- this.triggerRandomDisaster();
- }
- this.scheduleNextDisaster();
- }, time * 1000);
- }
- pickDisaster() {
- const disasters = ['Earthquake', 'Tornado', 'Tsunami', 'Volcano', 'Meteor', 'Flood'];
- const causes = {
- Earthquake: ['noun'],
- Tornado: ['misspelled'],
- Tsunami: ['adverb'],
- Volcano: ['verb'],
- Meteor: ['pronoun'],
- Flood: ['palindrome']
- };
- let weights = disasters.map(() => 1);
- this.beams.forEach(beam => {
- disasters.forEach((d, i) => {
- if (causes[d].includes(beam.wordType)) weights[i]++;
- });
- });
- const total = weights.reduce((a, b) => a + b, 0);
- let rand = Math.random() * total;
- for (let i = 0; i < weights.length; i++) {
- rand -= weights[i];
- if (rand < 0) return disasters[i];
- }
- return disasters[disasters.length - 1];
- }
- triggerRandomDisaster() {
- const type = this.pickDisaster();
- this.triggerDisaster(type);
- }
- triggerDisaster(type) {
- if (this.beams.length === 0) {
- this.showMessage('No palace to test!', 'error');
- return;
- }
- const intensity = (100 - this.stability) + Math.random() * 20;
- this.showMessage(`${type}! Intensity: ${Math.round(intensity)}%`, 'warning');
- const beamElements = document.querySelectorAll('.beam');
- beamElements.forEach(el => el.classList.add('shaking'));
- setTimeout(() => {
- beamElements.forEach(el => el.classList.remove('shaking'));
- const survivingBeams = [];
- let collapsed = false;
- this.beams.forEach((beam, index) => {
- let survivalChance = beam.strength / 100;
- const effects = this.disasterEffects[type];
- if (effects) {
- if (effects.prone.includes(beam.wordType)) survivalChance *= 0.5;
- if (effects.resistant.includes(beam.wordType)) survivalChance *= 1.5;
- }
- survivalChance = Math.min(1, survivalChance);
- const survives = Math.random() < survivalChance || intensity < 50;
- if (!survives) {
- collapsed = true;
- beamElements[index].classList.add('collapsing');
- } else {
- survivingBeams.push(beam);
- }
- });
- if (collapsed) {
- setTimeout(() => this.rebuild(survivingBeams), 1000);
- } else {
- this.showMessage(`Your palace withstood the ${type}! Magnificent engineering!`, 'success');
- this.score += 100;
- this.updateDisplay();
- }
- }, 1000);
- }
- rebuild(survivingBeams) {
- survivingBeams.sort((a, b) => b.text.length - a.text.length);
- const lostBeams = this.beams.length - survivingBeams.length;
- let lostStability = 0;
- const removedBeams = this.beams.filter(b => !survivingBeams.includes(b));
- removedBeams.forEach(beam => {
- if (beam.wordType === 'palindrome') {
- lostStability += 20;
- } else {
- lostStability += 5;
- }
- });
- this.stability = Math.max(0, this.stability - lostStability);
- this.showMessage(`${lostBeams} beams collapsed! Rebuilding...`, 'error');
- const palace = document.getElementById('palace');
- palace.innerHTML = '<div id="foundation"></div>';
- this.beams = [];
- this.height = 0;
- survivingBeams.forEach(beam => {
- this.beams.push(beam);
- this.renderBeam(beam);
- });
- this.updateDisplay();
- }
- shake(element) {
- element.style.animation = 'shake 0.5s';
- setTimeout(() => element.style.animation = '', 500);
- }
- showMessage(text, type) {
- const message = document.getElementById('message');
- message.textContent = text;
- message.className = type;
- message.style.display = 'block';
- setTimeout(() => {
- message.style.display = 'none';
- }, 2500);
- }
- updateDisplay() {
- document.getElementById('height').textContent = this.height;
- document.getElementById('stability').textContent = this.stability;
- document.getElementById('score').textContent = this.score;
- const riskElement = document.getElementById('disasterRisk');
- if (this.stability > 75) {
- riskElement.textContent = 'Low';
- riskElement.style.color = '#00ff00';
- } else if (this.stability > 50) {
- riskElement.textContent = 'Medium';
- riskElement.style.color = '#ffff00';
- } else {
- riskElement.textContent = 'High';
- riskElement.style.color = '#ff0000';
- }
- if (this.stability <= 0) {
- this.gameOver();
- }
- }
- gameOver() {
- this.showMessage(`Stability reached 0%! Palace destroyed! Final Score: ${this.score}`, 'error');
- setTimeout(() => this.resetGame(), 3000);
- }
- resetGame() {
- this.beams = [];
- this.score = 0;
- this.stability = 100;
- this.height = 0;
- const palace = document.getElementById('palace');
- palace.innerHTML = '<div id="foundation"></div>';
- this.updateDisplay();
- }
- }
- // Initialize the game
- const game = new PalindromePalace();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment