بازی منچ کیهانی - نسخه نهایی با هکر
by FrostGlider129154 lines462.1 KB
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="UTF-8">
<title>بازی منچ کیهانی - نسخه نهایی با هکر</title>
<link rel="icon" type="image/x-icon" href="https://cdn.imgurl.ir/uploads/j397930_5705207034868026831.png">
<style>
* {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: Tahoma, sans-serif;
text-align: center;
background: #0a0f1e;
margin: 0;
padding: 10px;
color: #333;
min-height: 100vh;
box-sizing: border-box;
position: relative;
overflow-x: hidden;
touch-action: manipulation;
}
body.main-menu-active {
background: url('https://cdn.imgurl.ir/uploads/s216024_2559706372457842178.png') no-repeat center center fixed;
background-size: cover;
}
.ludo-start-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('https://cdn.imgurl.ir/uploads/a47422_7298355863979471005.png') no-repeat center center fixed;
background-size: cover;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 20000;
transition: opacity 0.5s;
overflow-y: auto;
padding: 20px;
}
.ludo-container {
max-width: 1400px;
margin: 20px auto;
background: url('https://cdn.imgurl.ir/uploads/f9134_6061316258892629884.png') no-repeat center center;
background-size: cover;
border-radius: 20px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
display: grid;
grid-template-columns: 1fr 3fr 1fr;
grid-template-rows: auto auto auto;
gap: 20px;
overflow: visible;
}
.ludo-board {
width: 700px;
height: 700px;
background: white;
border: 10px solid #5D4037;
border-radius: 10px;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(10, 1fr);
gap: 1px;
margin: 0 auto;
position: relative;
grid-column: 2;
grid-row: 2 / span 2;
}
.floating-planets-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
}
.bg-planet {
position: absolute;
font-size: 60px;
filter: drop-shadow(0 0 15px rgba(255,255,255,0.3));
animation: bgFloat 20s ease-in-out infinite;
opacity: 0.4;
}
@keyframes bgFloat {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-30px) rotate(10deg); }
}
.bg-planet:nth-child(1) { top: 10%; left: 5%; animation-duration: 25s; font-size: 70px; }
.bg-planet:nth-child(2) { top: 70%; left: 85%; animation-duration: 18s; font-size: 50px; animation-delay: -5s; }
.bg-planet:nth-child(3) { top: 40%; left: 15%; animation-duration: 30s; font-size: 40px; animation-delay: -10s; }
.bg-planet:nth-child(4) { top: 80%; left: 20%; animation-duration: 22s; font-size: 55px; animation-delay: -2s; }
.bg-planet:nth-child(5) { top: 20%; left: 75%; animation-duration: 28s; font-size: 45px; animation-delay: -15s; }
.bg-planet:nth-child(6) { top: 50%; left: 50%; animation-duration: 35s; font-size: 80px; animation-delay: -7s; opacity: 0.2; }
.bg-planet:nth-child(7) { top: 85%; left: 55%; animation-duration: 20s; font-size: 35px; animation-delay: -12s; }
.bg-planet:nth-child(8) { top: 15%; left: 45%; animation-duration: 26s; font-size: 48px; animation-delay: -3s; }
.math-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.1;
background-image:
radial-gradient(circle at 15% 25%, #2196F3 1px, transparent 2px),
radial-gradient(circle at 85% 75%, #4CAF50 1px, transparent 2px),
radial-gradient(circle at 75% 20%, #FF9800 1px, transparent 2px),
radial-gradient(circle at 25% 80%, #9C27B0 1px, transparent 2px);
background-size: 120px 120px, 150px 150px, 180px 180px, 100px 100px;
}
#mainMenu {
display: block;
margin-top: 80px;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
max-width: 800px;
margin-left: auto;
margin-right: auto;
border: 3px solid #0D47A1;
position: relative;
z-index: 10;
}
#ludoScreen {
display: none;
position: relative;
width: 100%;
height: 100%;
background: #f5f5f5;
color: #333;
overflow-y: auto;
}
.explosion-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 20000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.explosion-content {
background: linear-gradient(135deg, #ff6b6b, #f44336, #d32f2f, #b71c1c);
width: 95%;
max-width: 700px;
padding: 40px;
border-radius: 40px;
text-align: center;
box-shadow: 0 30px 80px rgba(244, 67, 54, 0.8), 0 0 50px #ff9800;
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
border: 8px solid #ff8c00;
animation: explosionPulse 1.5s infinite, explosionGlow 2s infinite;
color: white;
transform-origin: center;
}
@keyframes explosionPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
@keyframes explosionGlow {
0%, 100% { box-shadow: 0 30px 80px rgba(244, 67, 54, 0.8), 0 0 50px #ff9800; }
50% { box-shadow: 0 40px 100px rgba(255, 87, 34, 1), 0 0 80px #ff5722; }
}
.explosion-title {
font-size: 52px;
font-weight: bold;
color: white;
text-shadow: 0 0 20px #ff0, 0 0 40px #f00, 3px 3px 0 #000;
margin-bottom: 20px;
animation: titleShake 0.5s infinite;
}
@keyframes titleShake {
0%, 100% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(5px, 5px) rotate(2deg); }
75% { transform: translate(-5px, -5px) rotate(-2deg); }
}
.explosion-warning {
font-size: 28px;
color: #ffeb3b;
margin: 30px 0;
text-shadow: 0 0 15px #ff9800, 2px 2px 0 #000;
background: rgba(0,0,0,0.5);
padding: 25px;
border-radius: 50px;
border: 4px dashed #ff0;
animation: warningBlink 1s infinite;
}
@keyframes warningBlink {
0%, 100% { opacity: 1; border-color: #ff0; }
50% { opacity: 0.8; border-color: #f00; }
}
.explosion-buttons {
display: flex;
justify-content: center;
gap: 30px;
margin: 40px 0;
}
.explosion-btn {
padding: 20px 50px;
font-size: 28px;
border-radius: 60px;
cursor: pointer;
font-weight: bold;
border: 5px solid white;
transition: all 0.3s;
min-width: 200px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.explosion-confirm {
background: linear-gradient(to right, #f44336, #d32f2f);
color: white;
animation: confirmPulse 1s infinite;
}
.explosion-confirm:hover {
transform: scale(1.1) translateY(-5px);
box-shadow: 0 15px 40px #f00;
}
.explosion-cancel {
background: linear-gradient(to right, #4caf50, #2e7d32);
color: white;
}
.explosion-cancel:hover {
transform: scale(1.1) translateY(-5px);
box-shadow: 0 15px 40px #0f0;
}
@keyframes confirmPulse {
0%, 100% { box-shadow: 0 10px 30px #f00; }
50% { box-shadow: 0 20px 50px #ff0; }
}
.explosion-animation-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 25000;
display: none;
overflow: hidden;
}
.explosion-flash {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at var(--x, 50%) var(--y, 50%), white, orange, red, black);
animation: flashEffect 1.5s ease-out forwards;
opacity: 0;
}
@keyframes flashEffect {
0% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(5); }
}
.explosion-fireball {
position: absolute;
width: 150px;
height: 150px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #fff, #ff0, #f90, #f00, #300);
box-shadow: 0 0 100px #f90, 0 0 200px #f00;
transform: translate(-50%, -50%);
animation: fireballExpand 1s ease-out forwards;
filter: blur(10px);
}
@keyframes fireballExpand {
0% { width: 50px; height: 50px; opacity: 1; }
50% { width: 500px; height: 500px; opacity: 0.9; }
100% { width: 800px; height: 800px; opacity: 0; }
}
.lava-ball {
position: absolute;
width: 30px;
height: 30px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #ffeb3b, #ff9800, #f44336, #8b0000);
box-shadow: 0 0 40px #ff4500, 0 0 80px #ff0000;
transform: translate(-50%, -50%);
z-index: 26000;
pointer-events: none;
animation: lavaGlow 0.3s infinite alternate;
filter: blur(2px);
}
@keyframes lavaGlow {
0% { box-shadow: 0 0 40px #ff4500, 0 0 80px #ff0000; }
100% { box-shadow: 0 0 60px #ffeb3b, 0 0 120px #ff4500; }
}
.lava-trail {
position: absolute;
width: 15px;
height: 15px;
border-radius: 50%;
background: radial-gradient(circle, #ffeb3b, #ff9800);
transform: translate(-50%, -50%);
z-index: 25999;
pointer-events: none;
animation: trailFade 0.5s forwards;
}
@keyframes trailFade {
0% { opacity: 1; width: 25px; height: 25px; }
100% { opacity: 0; width: 8px; height: 8px; }
}
.impact-effect {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
background: radial-gradient(circle, #fff, #ff0, #f90);
transform: translate(-50%, -50%);
animation: impactRing 0.6s ease-out forwards;
z-index: 27000;
pointer-events: none;
}
@keyframes impactRing {
0% { width: 30px; height: 30px; opacity: 1; }
100% { width: 300px; height: 300px; opacity: 0; }
}
.ludo-explosion-cell {
background: linear-gradient(135deg, #000000, #8b0000, #ff4500, #ff0000) !important;
border: 5px solid #ff0 !important;
color: white;
font-weight: bold;
box-shadow: 0 0 30px #f00, inset 0 0 20px #ff0;
animation: explosionCellPulse 1s infinite;
position: relative;
overflow: hidden;
}
.ludo-explosion-cell::before {
content: '💥';
position: absolute;
font-size: 40px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
text-shadow: 0 0 20px #ff0;
animation: explosionIcon 0.5s infinite;
z-index: 2;
}
.ludo-explosion-cell::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(255, 215, 0, 0.3) 10px,
rgba(255, 69, 0, 0.3) 20px
);
animation: explosionBgMove 3s linear infinite;
}
@keyframes explosionCellPulse {
0%, 100% { box-shadow: 0 0 30px #f00, inset 0 0 20px #ff0; }
50% { box-shadow: 0 0 60px #ff0, inset 0 0 40px #f00; }
}
@keyframes explosionIcon {
0%, 100% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.3); }
}
@keyframes explosionBgMove {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(25%, 25%) rotate(45deg); }
}
.ludo-explosion-text {
position: absolute;
top: 5px;
left: 5px;
font-size: 14px;
color: white;
font-weight: bold;
text-shadow: 0 0 10px #000;
z-index: 3;
background: rgba(0,0,0,0.5);
padding: 2px 5px;
border-radius: 5px;
}
.menu-btn {
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
border: none;
padding: 18px 40px;
margin: 20px;
font-size: 22px;
border-radius: 60px;
cursor: pointer;
box-shadow: 0 6px 12px rgba(33, 150, 243, 0.4);
transition: all 0.3s;
display: block;
width: 260px;
margin-left: auto;
margin-right: auto;
}
.menu-btn:hover {
transform: translateY(-5px);
box-shadow: 0 10px 18px rgba(33, 150, 243, 0.6);
}
.creator-credit {
font-size: 15px;
color: #666;
margin-top: 20px;
padding-top: 15px;
border-top: 2px dashed #ddd;
}
.ludo-start-btn {
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
border: none;
padding: 25px 50px;
font-size: 28px;
border-radius: 60px;
cursor: pointer;
box-shadow: 0 10px 25px rgba(33, 150, 243, 0.5);
transition: all 0.3s;
font-weight: bold;
margin-top: 30px;
min-width: 300px;
}
.ludo-start-btn:hover {
transform: translateY(-5px) scale(1.05);
box-shadow: 0 15px 30px rgba(33, 150, 243, 0.6);
background: linear-gradient(to right, #0D47A1, #1565C0);
}
.ludo-start-screen.hidden {
opacity: 0;
pointer-events: none;
}
.ludo-cell {
border: 1px solid #ddd;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: bold;
background: #FFF8E1;
position: relative;
cursor: pointer;
}
.ludo-path-cell {
background: #FFF8E1;
border: 1px solid #FFD54F;
}
.ludo-winner-cell {
background: linear-gradient(45deg, #FFD700, #FFA500) !important;
border: 3px solid #FF8C00 !important;
font-weight: bold;
color: #5D4037;
}
.ludo-danger-cell {
background: linear-gradient(45deg, #FF6B6B, #FF4757) !important;
border: 3px solid #FF3838 !important;
color: white;
font-weight: bold;
}
.ludo-danger-cell::after {
content: '☠️';
position: absolute;
font-size: 20px;
bottom: 5px;
right: 5px;
}
.ludo-question-cell {
background: linear-gradient(45deg, #2196F3, #0D47A1) !important;
border: 3px solid #0D47A1 !important;
color: white;
font-weight: bold;
}
.ludo-question-cell::after {
content: '?';
position: absolute;
font-size: 24px;
font-weight: bold;
bottom: 5px;
left: 5px;
color: white;
}
.ludo-luck-cell {
background: linear-gradient(45deg, #4CAF50, #2E7D32) !important;
border: 3px solid #1B5E20 !important;
color: white;
font-weight: bold;
box-shadow: 0 0 15px rgba(76, 175, 80, 0.5);
animation: luckPulse 2s infinite;
}
@keyframes luckPulse {
0%, 100% { box-shadow: 0 0 15px rgba(76, 175, 80, 0.5); }
50% { box-shadow: 0 0 25px rgba(255, 215, 0, 0.8); }
}
.ludo-luck-cell::after {
content: '🎲';
position: absolute;
font-size: 24px;
font-weight: bold;
bottom: 5px;
left: 5px;
color: gold;
text-shadow: 0 0 5px rgba(255, 215, 0, 0.5);
}
.ludo-luck-cell::before {
content: 'شانس';
position: absolute;
font-size: 12px;
top: 5px;
left: 50%;
transform: translateX(-50%);
color: gold;
font-weight: bold;
text-shadow: 0 0 5px black;
}
.ludo-rainbow-cell {
background: linear-gradient(45deg, #FF0000, #FF7F00, #FFFF00, #00FF00, #0000FF, #4B0082, #8B00FF) !important;
background-size: 400% 400% !important;
border: 5px solid white !important;
color: white;
font-weight: bold;
animation: rainbowBG 3s ease infinite, rainbowPulse 1.5s infinite;
position: relative;
overflow: hidden;
}
@keyframes rainbowBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
@keyframes rainbowPulse {
0%, 100% { box-shadow: 0 0 20px rgba(255, 0, 0, 0.5), inset 0 0 10px rgba(255, 255, 255, 0.3); }
50% { box-shadow: 0 0 40px rgba(0, 255, 255, 0.8), inset 0 0 20px rgba(255, 255, 255, 0.6); }
}
.ludo-rainbow-cell::after {
content: '🌈';
position: absolute;
font-size: 32px;
bottom: 5px;
left: 5px;
filter: drop-shadow(0 0 5px white);
}
.ludo-rainbow-cell::before {
content: 'رنگینکمان';
position: absolute;
font-size: 11px;
top: 5px;
left: 50%;
transform: translateX(-50%);
color: white;
font-weight: bold;
text-shadow: 0 0 5px black;
background: rgba(0,0,0,0.5);
padding: 2px 6px;
border-radius: 10px;
white-space: nowrap;
}
.ludo-jail-cell {
background: radial-gradient(circle at 30% 20%, #1a1a1a, #0a0a0a, #000000) !important;
border: 3px solid #ff6600 !important;
border-radius: 15px !important;
box-shadow: 0 0 30px rgba(255, 102, 0, 0.8), inset 0 0 20px rgba(255, 100, 0, 0.5) !important;
position: relative;
overflow: hidden;
animation: jailGlowPulse 1s infinite alternate;
}
@keyframes jailGlowPulse {
0% { box-shadow: 0 0 20px rgba(255, 102, 0, 0.6), inset 0 0 15px rgba(255, 100, 0, 0.3); }
100% { box-shadow: 0 0 50px rgba(255, 102, 0, 1), inset 0 0 30px rgba(255, 140, 0, 0.7); }
}
.ludo-jail-cell::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: repeating-linear-gradient(
to right,
transparent,
transparent 12px,
rgba(180, 180, 180, 0.6) 12px,
rgba(120, 120, 120, 0.8) 14px,
transparent 14px,
transparent 25px
);
pointer-events: none;
z-index: 2;
}
.ludo-jail-cell::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at 20% 80%, rgba(255, 100, 0, 0.3) 2px, transparent 4px);
background-size: 18px 18px;
pointer-events: none;
z-index: 2;
animation: jailBubbles 3s linear infinite;
}
@keyframes jailBubbles {
0% { background-position: 0 0; opacity: 0.4; }
100% { background-position: 20px 20px; opacity: 0.9; }
}
.ludo-jail-cell .jail-fire {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 15px;
background: linear-gradient(to top, #ff6600, #ff3300, transparent);
animation: jailFire 0.4s infinite alternate;
z-index: 3;
border-radius: 0 0 12px 12px;
}
@keyframes jailFire {
0% { height: 8px; opacity: 0.7; }
100% { height: 18px; opacity: 1; }
}
.jail-tag {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
background: linear-gradient(45deg, #ffcc00, #ff6600);
color: #000;
font-size: 12px;
font-weight: bold;
padding: 4px 10px;
border-radius: 20px;
white-space: nowrap;
z-index: 150;
border: 2px solid #fff;
box-shadow: 0 0 15px gold;
animation: jailTagBlink 0.8s infinite;
text-shadow: 0 0 3px white;
}
@keyframes jailTagBlink {
0%, 100% { opacity: 1; background: linear-gradient(45deg, #ffcc00, #ff8800); }
50% { opacity: 0.8; background: linear-gradient(45deg, #ffaa00, #ff4400); }
}
.ludo-jail-piece {
filter: drop-shadow(0 0 12px #ff9900) brightness(1.2);
animation: jailPieceShake 0.5s infinite alternate;
}
@keyframes jailPieceShake {
0% { transform: translateY(0px); }
100% { transform: translateY(-3px); }
}
.rainbow-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 30000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.rainbow-content {
background: linear-gradient(135deg, #FF0000, #FF7F00, #FFFF00, #00FF00, #0000FF, #4B0082, #8B00FF);
background-size: 400% 400%;
animation: rainbowBG 2s ease infinite;
width: 95%;
max-width: 700px;
padding: 40px;
border-radius: 40px;
text-align: center;
box-shadow: 0 30px 80px rgba(255, 255, 255, 0.5), 0 0 50px #ff00ff;
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
border: 8px solid white;
color: white;
}
.rainbow-title {
font-size: 48px;
font-weight: bold;
color: white;
text-shadow: 0 0 20px #ff0, 0 0 40px #f0f, 3px 3px 0 #000;
margin-bottom: 30px;
animation: rainbowTitleShake 0.8s infinite;
}
@keyframes rainbowTitleShake {
0%, 100% { transform: rotate(0deg) scale(1); }
25% { transform: rotate(5deg) scale(1.05); }
75% { transform: rotate(-5deg) scale(1.05); }
}
.rainbow-warning {
font-size: 28px;
color: #FFFF00;
margin: 30px 0;
text-shadow: 0 0 15px #ff00ff, 2px 2px 0 #000;
background: rgba(0,0,0,0.6);
padding: 25px;
border-radius: 30px;
border: 3px dashed white;
}
.rainbow-buttons {
display: flex;
justify-content: center;
gap: 30px;
margin: 30px 0;
}
.rainbow-btn {
padding: 20px 50px;
font-size: 28px;
border-radius: 60px;
cursor: pointer;
font-weight: bold;
border: 5px solid white;
transition: all 0.3s;
min-width: 200px;
}
.rainbow-continue {
background: linear-gradient(to right, #00ff00, #008000);
color: white;
animation: rainbowBtnPulse 1s infinite;
}
.rainbow-cancel {
background: linear-gradient(to right, #ff0000, #800000);
color: white;
}
@keyframes rainbowBtnPulse {
0%, 100% { box-shadow: 0 0 20px #00ff00; }
50% { box-shadow: 0 0 50px #ffff00; }
}
.rainbow-animation-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 31000;
display: none;
overflow: hidden;
}
.rainbow-main {
position: absolute;
width: 200px;
height: 200px;
background: radial-gradient(circle, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #8b00ff);
border-radius: 50%;
box-shadow: 0 0 100px rgba(255,255,255,0.8);
animation: rainbowMainPulse 0.5s infinite;
transform: translate(-50%, -50%);
}
@keyframes rainbowMainPulse {
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.8; }
}
.rainbow-tentacle {
position: absolute;
width: 10px;
height: 10px;
background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #8b00ff);
border-radius: 50%;
box-shadow: 0 0 20px rgba(255,255,255,0.8);
transform-origin: center;
}
.piece-captured {
filter: drop-shadow(0 0 15px gold) brightness(1.3);
transition: all 0.3s;
}
.ludo-deal-cell {
background: #FFFFFF !important;
border: 5px solid #000000 !important;
color: #000000;
font-weight: bold;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3), inset 0 0 10px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
animation: dealPulse 2s infinite;
}
@keyframes dealPulse {
0%, 100% { box-shadow: 0 0 20px rgba(0, 0, 0, 0.3), inset 0 0 10px rgba(0, 0, 0, 0.1); }
50% { box-shadow: 0 0 30px rgba(0, 0, 0, 0.5), inset 0 0 15px rgba(0, 0, 0, 0.2); }
}
.ludo-deal-cell::before {
content: '💰';
position: absolute;
font-size: 24px;
top: 5px;
left: 5px;
color: #000;
text-shadow: 0 0 5px #fff;
z-index: 2;
}
.ludo-deal-cell::after {
content: 'معامله';
position: absolute;
font-size: 14px;
bottom: 5px;
right: 5px;
color: #000;
font-weight: bold;
background: rgba(255, 255, 255, 0.8);
padding: 2px 5px;
border-radius: 3px;
border: 1px solid #000;
z-index: 2;
}
.ludo-start-cell {
background: #FF9800;
color: white;
border: 4px solid #F57C00;
font-size: 18px;
font-weight: bold;
}
.ludo-transfer-cell {
background: linear-gradient(45deg, #9C27B0, #7B1FA2) !important;
border: 3px solid #7B1FA2 !important;
color: white;
font-weight: bold;
}
.ludo-transfer-cell::after {
content: '⇄';
position: absolute;
font-size: 20px;
bottom: 5px;
right: 5px;
color: white;
}
.ludo-ghost-cell {
background: radial-gradient(circle at 30% 20%, #1a0a2e, #0d001a, #000000) !important;
border: 4px solid #8b00ff !important;
border-radius: 12px !important;
box-shadow: 0 0 40px rgba(139, 0, 255, 0.8), inset 0 0 30px rgba(139, 0, 255, 0.4), 0 0 80px rgba(200, 0, 255, 0.3) !important;
position: relative;
overflow: hidden;
animation: ghostGlowPulse 1.5s infinite alternate;
color: white;
font-weight: bold;
text-shadow: 0 0 10px #8b00ff;
}
@keyframes ghostGlowPulse {
0% { box-shadow: 0 0 30px rgba(139, 0, 255, 0.6), inset 0 0 20px rgba(139, 0, 255, 0.3), 0 0 60px rgba(200, 0, 255, 0.2); }
100% { box-shadow: 0 0 60px rgba(139, 0, 255, 1), inset 0 0 40px rgba(139, 0, 255, 0.6), 0 0 100px rgba(200, 0, 255, 0.5); }
}
.ludo-ghost-cell::before {
content: '👻';
position: absolute;
font-size: 45px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
text-shadow: 0 0 30px #8b00ff, 0 0 60px #ff00ff;
animation: ghostIconFloat 2s ease-in-out infinite;
z-index: 2;
}
@keyframes ghostIconFloat {
0%, 100% { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
50% { transform: translate(-50%, -60%) scale(1.2) rotate(5deg); }
}
.ludo-ghost-cell::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 15px,
rgba(139, 0, 255, 0.2) 15px,
rgba(200, 0, 255, 0.1) 25px,
transparent 25px,
transparent 40px
);
animation: ghostBgMove 8s linear infinite;
z-index: 1;
}
@keyframes ghostBgMove {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(50%, 50%) rotate(45deg); }
}
.ludo-ghost-cell .ghost-text {
position: absolute;
bottom: 3px;
left: 50%;
transform: translateX(-50%);
font-size: 11px;
color: #cc99ff;
background: rgba(0,0,0,0.7);
padding: 2px 8px;
border-radius: 10px;
border: 1px solid #8b00ff;
z-index: 3;
white-space: nowrap;
font-weight: bold;
text-shadow: 0 0 10px #8b00ff;
animation: ghostTextPulse 1s infinite alternate;
}
@keyframes ghostTextPulse {
0% { color: #cc99ff; border-color: #8b00ff; }
100% { color: #ff66ff; border-color: #ff00ff; }
}
.ghost-jumpscare-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
display: none;
justify-content: center;
align-items: center;
pointer-events: none;
background: rgba(0, 0, 0, 0.3);
}
.ghost-jumpscare-overlay.active {
display: flex;
animation: jumpscareAppear 0.1s ease-out;
}
@keyframes jumpscareAppear {
0% { opacity: 0; transform: scale(0.5); }
100% { opacity: 1; transform: scale(1); }
}
.ghost-jumpscare-image {
max-width: 90%;
max-height: 90vh;
border-radius: 20px;
box-shadow: 0 0 100px rgba(200, 0, 255, 0.8), 0 0 200px rgba(139, 0, 255, 0.5);
animation: jumpscareShake 0.3s infinite;
border: 8px solid #8b00ff;
}
@keyframes jumpscareShake {
0%, 100% { transform: translate(0, 0) scale(1); }
25% { transform: translate(-10px, 5px) scale(1.02); }
75% { transform: translate(10px, -5px) scale(1.02); }
}
.ghost-piece {
position: absolute;
width: 45px;
height: 45px;
z-index: 500;
pointer-events: none;
font-size: 40px;
display: flex;
align-items: center;
justify-content: center;
filter: drop-shadow(0 0 20px rgba(139, 0, 255, 0.9)) drop-shadow(0 0 40px rgba(200, 0, 255, 0.5));
animation: ghostFloat 0.5s ease-in-out infinite alternate;
transition: left 0.12s linear, top 0.12s linear;
}
.ghost-piece img {
width: 100%;
height: 100%;
object-fit: contain;
filter: drop-shadow(0 0 30px rgba(139, 0, 255, 0.8));
}
@keyframes ghostFloat {
0% { transform: translateY(-3px) scale(1); }
100% { transform: translateY(3px) scale(1.05); }
}
.ludo-player-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 20px;
border-radius: 15px;
background: rgba(255, 255, 255, 0.9);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
height: fit-content;
}
.ludo-red-section {
grid-column: 1;
grid-row: 2;
justify-self: start;
border: 3px solid #F44336;
}
.ludo-blue-section {
grid-column: 3;
grid-row: 2;
justify-self: end;
border: 3px solid #2196F3;
}
.ludo-pieces-layer {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 15px;
background: #FFF3E0;
padding: 25px;
border-radius: 15px;
border: 3px solid #FF9800;
width: 200px;
height: 200px;
position: relative;
}
.ludo-piece-in-home {
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: white;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
border: 4px solid white;
font-size: 22px;
cursor: pointer;
transition: all 0.3s;
position: relative;
}
.ludo-piece-in-home:hover {
transform: scale(1.1);
}
.ludo-blue-piece-home {
background: linear-gradient(135deg, #2196F3, #0D47A1);
border-color: #0D47A1;
}
.ludo-red-piece-home {
background: linear-gradient(135deg, #F44336, #B71C1C);
border-color: #B71C1C;
}
.ludo-piece-label {
padding: 12px 25px;
border-radius: 12px;
font-weight: bold;
border: 3px solid;
font-size: 18px;
width: 100%;
text-align: center;
}
.ludo-blue-label {
color: #0D47A1;
border-color: #2196F3;
}
.ludo-red-label {
color: #B71C1C;
border-color: #F44336;
}
.ludo-dice-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
margin-top: 20px;
}
.ludo-dice-box {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.ludo-dice {
width: 80px;
height: 80px;
background: white;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
font-weight: bold;
cursor: pointer;
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
user-select: none;
transition: all 0.3s;
border: 5px solid;
}
.ludo-blue-dice {
border-color: #2196F3;
background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
}
.ludo-red-dice {
border-color: #F44336;
background: linear-gradient(135deg, #FFEBEE, #FFCDD2);
}
.ludo-golden-dice {
width: 120px !important;
height: 120px !important;
background: linear-gradient(135deg, #FFD700, #FFA500) !important;
border: 8px solid #FF8C00 !important;
color: #fff !important;
font-size: 50px !important;
font-weight: bold;
cursor: pointer;
border-radius: 20px;
box-shadow: 0 0 30px rgba(255, 215, 0, 0.8);
animation: goldenShine 1.5s infinite;
margin: 0 auto;
}
@keyframes goldenShine {
0%, 100% { box-shadow: 0 0 30px rgba(255, 215, 0, 0.8); transform: scale(1); }
50% { box-shadow: 0 0 50px rgba(255, 215, 0, 1); transform: scale(1.05); }
}
.ludo-dice.disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
}
.ludo-dice.locked {
pointer-events: none;
}
.ludo-dice:hover:not(.disabled):not(.locked) {
transform: scale(1.1);
}
.ludo-dice.rolling {
animation: ludoRollDice 0.8s ease-in-out;
pointer-events: none;
}
@keyframes ludoRollDice {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(180deg) scale(1.2); }
50% { transform: rotate(360deg) scale(1); }
75% { transform: rotate(540deg) scale(1.2); }
}
.ludo-dice.negative {
background: linear-gradient(135deg, #FFEBEE, #FFCDD2);
color: #F44336;
}
.ludo-dice-label {
font-weight: bold;
font-size: 18px;
background: white;
padding: 8px 20px;
border-radius: 10px;
border: 3px solid;
}
.ludo-dice-blue-label {
color: #2196F3;
border-color: #2196F3;
}
.ludo-dice-red-label {
color: #F44336;
border-color: #F44336;
}
/* ===== کانتینر دکمهها ===== */
.ludo-save-container {
margin-top: 15px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.ludo-save-row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
width: 100%;
}
.ludo-save-btn {
padding: 12px 25px;
border-radius: 12px;
font-size: 18px;
font-weight: bold;
border: 4px solid;
cursor: pointer;
transition: all 0.3s;
min-width: 140px;
text-align: center;
background: #f5f5f5;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.ludo-save-btn.disabled {
opacity: 0.4;
cursor: not-allowed;
transform: none !important;
}
.ludo-save-btn:not(.disabled):hover {
transform: scale(1.05);
box-shadow: 0 6px 18px rgba(0,0,0,0.25);
}
.ludo-save-btn-blue {
border-color: #2196F3;
color: #0D47A1;
}
.ludo-save-btn-blue:not(.disabled):hover {
background: #E3F2FD;
}
.ludo-save-btn-red {
border-color: #F44336;
color: #B71C1C;
}
.ludo-save-btn-red:not(.disabled):hover {
background: #FFEBEE;
}
.ludo-save-btn.ludo-thunder-btn {
background: linear-gradient(135deg, #4FC3F7, #0D47A1) !important;
color: #fff !important;
border-color: #0D47A1 !important;
animation: thunderPulse 1.5s infinite;
}
.ludo-save-btn.ludo-thunder-btn:not(.disabled):hover {
background: linear-gradient(135deg, #29B6F6, #0D47A1) !important;
box-shadow: 0 0 30px rgba(79, 195, 247, 0.8);
}
@keyframes thunderPulse {
0%, 100% { box-shadow: 0 0 20px rgba(79, 195, 247, 0.4); }
50% { box-shadow: 0 0 40px rgba(33, 150, 243, 0.8); }
}
.ludo-save-btn.ludo-thunder-btn.disabled {
opacity: 0.3 !important;
}
/* ===== دکمه هکر (بالای دکمه ذخیره) ===== */
.ludo-hacker-btn {
padding: 6px 14px;
border-radius: 8px;
font-size: 14px;
font-weight: bold;
border: 3px solid;
cursor: pointer;
transition: all 0.3s;
min-width: 60px;
text-align: center;
background: #1a1a2e;
color: #00ff41;
border-color: #00ff41;
box-shadow: 0 0 15px rgba(0, 255, 65, 0.25);
font-family: 'Courier New', monospace;
position: relative;
overflow: hidden;
}
.ludo-hacker-btn::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 8px,
rgba(0, 255, 65, 0.08) 8px,
rgba(0, 255, 65, 0.04) 16px
);
animation: hackerBtnBg 3s linear infinite;
}
@keyframes hackerBtnBg {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(20px, 20px) rotate(45deg); }
}
.ludo-hacker-btn:not(.disabled):hover {
transform: scale(1.1);
box-shadow: 0 0 30px rgba(0, 255, 65, 0.5);
}
.ludo-hacker-btn.disabled {
opacity: 0.3;
cursor: not-allowed;
transform: none !important;
box-shadow: none !important;
}
/* ===== فیلدهای هکر بعد از موفقیت ===== */
.ludo-hacker-fields {
display: flex;
flex-direction: row;
align-items: center;
gap: 6px;
flex-wrap: wrap;
justify-content: center;
}
.ludo-hacker-field {
width: 40px;
height: 34px;
font-size: 14px;
text-align: center;
border: 2px solid #00ff41;
border-radius: 6px;
background: #0a0f1e;
color: #00ff41;
font-weight: bold;
font-family: 'Courier New', monospace;
outline: none;
transition: all 0.3s;
}
.ludo-hacker-field:focus {
border-color: #00ffaa;
box-shadow: 0 0 15px rgba(0, 255, 65, 0.25);
}
.ludo-hacker-field:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.ludo-hacker-field::placeholder {
color: #00ff41;
opacity: 0.3;
font-size: 10px;
}
.ludo-hacker-confirm-btn {
padding: 3px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: bold;
border: 2px solid #00ff41;
cursor: pointer;
background: #0a0f1e;
color: #00ff41;
transition: all 0.3s;
font-family: 'Courier New', monospace;
height: 34px;
}
.ludo-hacker-confirm-btn:not(:disabled):hover {
transform: scale(1.1);
box-shadow: 0 0 15px rgba(0, 255, 65, 0.3);
}
.ludo-hacker-confirm-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.ludo-hacker-counter {
font-size: 11px;
color: #00ff41;
font-family: 'Courier New', monospace;
font-weight: bold;
background: rgba(0, 0, 0, 0.5);
padding: 2px 6px;
border-radius: 4px;
border: 1px solid #00ff41;
height: 34px;
display: flex;
align-items: center;
}
/* ===== آیتم هکینگ دیوایس در خانه ===== */
.ludo-hacker-device-cell {
position: relative;
overflow: hidden;
}
.ludo-hacker-device-cell .hacker-device-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 18px;
z-index: 5;
animation: hackerDevicePulse 1.5s ease-in-out infinite;
filter: drop-shadow(0 0 12px #00ff41);
}
.ludo-hacker-device-cell .hacker-device-text {
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
font-size: 7px;
color: #00ff41;
font-family: 'Courier New', monospace;
background: rgba(0, 0, 0, 0.8);
padding: 1px 5px;
border-radius: 3px;
border: 1px solid #00ff41;
white-space: nowrap;
z-index: 5;
animation: hackerDeviceTextPulse 1s infinite alternate;
}
@keyframes hackerDevicePulse {
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; }
50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
}
@keyframes hackerDeviceTextPulse {
0% { color: #00ff41; border-color: #00ff41; }
100% { color: #00ffaa; border-color: #00ffaa; }
}
.thunder-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99998;
pointer-events: none;
display: none;
}
.thunder-overlay.active {
display: block;
}
.thunder-flash {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
opacity: 0;
animation: thunderFlash 0.8s ease-out forwards;
}
@keyframes thunderFlash {
0% { opacity: 1; }
30% { opacity: 0; }
60% { opacity: 0.8; }
100% { opacity: 0; }
}
.thunder-bolt {
position: absolute;
background: linear-gradient(180deg, #fff, #4FC3F7, #2196F3, #0D47A1);
width: 8px;
height: 150px;
transform-origin: top center;
animation: thunderBoltStrike 0.5s ease-out forwards;
filter: drop-shadow(0 0 30px #4FC3F7) drop-shadow(0 0 60px #2196F3) drop-shadow(0 0 90px #0D47A1);
border-radius: 4px;
}
@keyframes thunderBoltStrike {
0% { transform: scaleY(0); opacity: 0; }
40% { transform: scaleY(1.3); opacity: 1; }
70% { transform: scaleY(0.8); opacity: 1; }
100% { transform: scaleY(1); opacity: 0; }
}
.thunder-bolt-large {
position: absolute;
background: linear-gradient(180deg, #fff, #4FC3F7, #2196F3, #0D47A1);
width: 12px;
height: 250px;
transform-origin: top center;
animation: thunderBoltLargeStrike 0.7s ease-out forwards;
filter: drop-shadow(0 0 50px #4FC3F7) drop-shadow(0 0 80px #2196F3) drop-shadow(0 0 120px #0D47A1);
border-radius: 6px;
clip-path: polygon(50% 0%, 40% 30%, 55% 25%, 45% 50%, 60% 40%, 50% 70%, 65% 55%, 55% 85%, 45% 75%, 50% 100%, 35% 85%, 40% 95%, 25% 80%, 30% 75%, 15% 55%, 20% 45%, 5% 25%, 10% 15%, 0% 10%, 10% 15%);
}
@keyframes thunderBoltLargeStrike {
0% { transform: scaleY(0) scaleX(0.5); opacity: 0; }
30% { transform: scaleY(1.4) scaleX(1.2); opacity: 1; }
60% { transform: scaleY(0.7) scaleX(0.8); opacity: 0.8; }
100% { transform: scaleY(1) scaleX(1); opacity: 0; }
}
.thunder-spark {
position: absolute;
width: 15px;
height: 15px;
border-radius: 50%;
background: radial-gradient(circle, #fff, #4FC3F7, #2196F3);
animation: thunderSparkExplode 0.6s ease-out forwards;
filter: blur(2px);
}
@keyframes thunderSparkExplode {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(6); opacity: 0; }
}
.thunder-particles {
position: absolute;
width: 5px;
height: 5px;
border-radius: 50%;
background: #4FC3F7;
animation: thunderParticlesFly 0.8s ease-out forwards;
filter: blur(1px);
}
@keyframes thunderParticlesFly {
0% { transform: translate(0, 0) scale(1); opacity: 1; }
100% { transform: translate(var(--tx), var(--ty)) scale(0); opacity: 0; }
}
.thunder-ring {
position: absolute;
border: 4px solid #4FC3F7;
border-radius: 50%;
animation: thunderRingExpand 0.8s ease-out forwards;
box-shadow: 0 0 50px rgba(79, 195, 247, 0.6), 0 0 80px rgba(33, 150, 243, 0.4);
}
@keyframes thunderRingExpand {
0% { width: 20px; height: 20px; opacity: 1; }
100% { width: 350px; height: 350px; opacity: 0; }
}
.thunder-target {
position: absolute;
border: 6px solid #4FC3F7;
border-radius: 50%;
animation: thunderTargetPulse 0.3s infinite alternate;
box-shadow: 0 0 60px rgba(79, 195, 247, 0.9), 0 0 120px rgba(33, 150, 243, 0.5);
pointer-events: none;
z-index: 99999;
background: rgba(79, 195, 247, 0.2);
}
@keyframes thunderTargetPulse {
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.7; border-color: #4FC3F7; }
100% { transform: translate(-50%, -50%) scale(1.5); opacity: 1; border-color: #0D47A1; }
}
.thunder-delete-effect {
position: fixed;
z-index: 99999;
pointer-events: none;
border-radius: 50%;
animation: thunderDelete 0.8s ease-out forwards;
}
@keyframes thunderDelete {
0% { transform: scale(0.5); opacity: 1; background: radial-gradient(circle, #fff, #4FC3F7, #2196F3, #0D47A1); box-shadow: 0 0 100px #4FC3F7, 0 0 200px #2196F3, 0 0 300px #0D47A1; }
50% { transform: scale(3); opacity: 0.8; background: radial-gradient(circle, #fff, #4FC3F7, #0D47A1); box-shadow: 0 0 150px #4FC3F7, 0 0 250px #2196F3, 0 0 400px #0D47A1; }
100% { transform: scale(0); opacity: 0; background: radial-gradient(circle, #fff, #4FC3F7); box-shadow: 0 0 0px transparent; }
}
.ludo-cell-number {
font-size: 12px;
color: #666;
position: absolute;
top: 2px;
left: 2px;
}
.ludo-piece-on-board {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid white;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: white;
font-size: 16px;
cursor: pointer;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.ludo-piece-on-board:hover {
transform: scale(1.1);
box-shadow: 0 6px 18px rgba(0,0,0,0.3);
}
.ludo-blue-on-board {
background: linear-gradient(135deg, #2196F3, #0D47A1);
border-color: #0D47A1;
}
.ludo-red-on-board {
background: linear-gradient(135deg, #F44336, #B71C1C);
border-color: #B71C1C;
}
.ludo-shield-effect {
position: absolute;
width: 60px;
height: 60px;
border-radius: 50%;
border: 4px solid #00FFFF;
box-shadow: 0 0 20px cyan, inset 0 0 15px cyan;
animation: shieldPulse 1s infinite;
z-index: 101;
pointer-events: none;
}
@keyframes shieldPulse {
0%, 100% { transform: scale(1); opacity: 0.7; }
50% { transform: scale(1.2); opacity: 1; }
}
.ludo-game-info {
display: flex;
justify-content: space-around;
background: rgba(255, 255, 255, 0.95);
padding: 15px;
border-radius: 12px;
border: 3px solid #FF9800;
margin: 20px auto;
max-width: 600px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
grid-column: 1 / -1;
}
.ludo-info-box {
text-align: center;
padding: 10px;
min-width: 120px;
}
.ludo-info-value {
font-size: 28px;
font-weight: bold;
margin: 5px 0;
}
.ludo-blue-info-value {
color: #2196F3;
}
.ludo-red-info-value {
color: #F44336;
}
.ludo-turn-indicator {
font-size: 24px;
font-weight: bold;
padding: 15px 30px;
border-radius: 15px;
margin: 15px auto;
text-align: center;
max-width: 500px;
animation: ludoPulse 1.5s infinite;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
border: 3px solid #0D47A1;
grid-column: 1 / -1;
}
@keyframes ludoPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.ludo-red-turn {
background: linear-gradient(to right, #F44336, #B71C1C);
border-color: #B71C1C;
}
.ludo-message-box {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
padding: 15px 30px;
border-radius: 15px;
font-size: 16px;
z-index: 1000;
display: none;
min-width: 300px;
text-align: center;
border: 2px solid #0D47A1;
box-shadow: 0 10px 25px rgba(0,0,0,0.5);
animation: ludoSlideUp 0.3s ease-out;
}
@keyframes ludoSlideUp {
from { transform: translateX(-50%) translateY(50px); opacity: 0; }
to { transform: translateX(-50%) translateY(0); opacity: 1; }
}
.ludo-highlight {
animation: ludoHighlightPiece 0.5s ease-in-out infinite alternate;
box-shadow: 0 0 20px gold, 0 0 40px gold !important;
transform: scale(1.1);
}
@keyframes ludoHighlightPiece {
from { transform: scale(1.1); }
to { transform: scale(1.2); }
}
.ludo-audio-control {
position: fixed;
top: 20px;
right: 20px;
background: white;
padding: 10px 15px;
border-radius: 10px;
border: 2px solid #2196F3;
cursor: pointer;
z-index: 1000;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
display: flex;
align-items: center;
gap: 10px;
min-width: 120px;
}
.ludo-occupied-winner-cell {
position: relative;
}
.ludo-occupied-winner-cell::after {
content: '🔒';
position: absolute;
font-size: 18px;
bottom: 5px;
left: 5px;
}
.ludo-golden-dice-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
z-index: 5000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.ludo-golden-dice-content {
background: linear-gradient(135deg, #FFD700, #FFA500);
width: 95%;
max-width: 600px;
padding: 30px;
border-radius: 30px;
text-align: center;
box-shadow: 0 25px 60px rgba(255, 215, 0, 0.6);
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
border: 10px solid #FF8C00;
animation: modalGlow 2s infinite;
}
@keyframes modalGlow {
0%, 100% { box-shadow: 0 25px 60px rgba(255, 215, 0, 0.6); }
50% { box-shadow: 0 25px 80px rgba(255, 215, 0, 0.9); }
}
.ludo-golden-title {
font-size: 36px;
font-weight: bold;
color: white;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
margin-bottom: 20px;
}
.ludo-golden-subtitle {
font-size: 20px;
color: rgba(255,255,255,0.9);
margin-bottom: 30px;
text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
.ludo-golden-dice-container {
display: flex;
justify-content: center;
align-items: center;
margin: 30px 0;
}
.ludo-deal-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 20000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.ludo-deal-content {
background: linear-gradient(135deg, #ffffff, #f0f0f0);
width: 95%;
max-width: 1400px;
padding: 30px;
border-radius: 30px;
text-align: center;
box-shadow: 0 25px 60px rgba(0,0,0,0.6);
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
border: 10px solid #000;
}
.ludo-deal-title {
font-size: 48px;
font-weight: bold;
color: #000;
margin-bottom: 30px;
text-shadow: 0 0 10px #fff;
animation: dealTitlePulse 1.5s infinite;
}
@keyframes dealTitlePulse {
0%, 100% { text-shadow: 0 0 10px #fff; }
50% { text-shadow: 0 0 20px #000; }
}
.ludo-deal-split {
display: flex;
justify-content: space-between;
gap: 30px;
margin: 20px 0;
position: relative;
}
.ludo-deal-split::before {
content: '⚡';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 60px;
color: #000;
text-shadow: 0 0 20px #fff;
z-index: 10;
animation: dealLightning 2s infinite;
}
@keyframes dealLightning {
0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(1); }
50% { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
}
.ludo-deal-side {
flex: 1;
border-radius: 20px;
padding: 20px;
min-height: 600px;
display: flex;
flex-direction: column;
gap: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.ludo-deal-red-side {
background: linear-gradient(135deg, #ffcdd2, #ef9a9a);
border: 5px solid #f44336;
}
.ludo-deal-blue-side {
background: linear-gradient(135deg, #bbdefb, #90caf9);
border: 5px solid #2196F3;
}
.ludo-deal-side-header {
font-size: 32px;
font-weight: bold;
padding: 15px;
border-radius: 15px;
margin-bottom: 20px;
text-align: center;
color: white;
}
.ludo-deal-red-header {
background: #f44336;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.ludo-deal-blue-header {
background: #2196F3;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.ludo-deal-option {
background: white;
border-radius: 15px;
padding: 15px;
cursor: pointer;
transition: all 0.3s;
border: 3px solid transparent;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
text-align: right;
display: flex;
flex-direction: column;
gap: 10px;
}
.ludo-deal-option:hover:not(.disabled) {
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(0,0,0,0.3);
}
.ludo-deal-option.selected {
border-color: #ff9800;
background: linear-gradient(135deg, #fff3e0, #ffe0b2);
box-shadow: 0 0 20px #ff9800;
}
.ludo-deal-option.disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.ludo-deal-option.disabled:hover {
transform: none;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.ludo-deal-option-title {
font-size: 18px;
font-weight: bold;
color: #333;
display: flex;
align-items: center;
gap: 10px;
}
.ludo-deal-piece-selector {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 10px;
flex-wrap: wrap;
}
.ludo-deal-piece-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: 3px solid;
font-size: 20px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
}
.ludo-deal-piece-btn:hover:not(.disabled) {
transform: scale(1.15);
}
.ludo-deal-piece-btn.selected {
box-shadow: 0 0 20px #ff9800;
transform: scale(1.1);
}
.ludo-deal-piece-btn.disabled {
opacity: 0.3;
cursor: not-allowed;
}
.ludo-deal-piece-btn.disabled:hover {
transform: none;
}
.ludo-deal-red-piece {
background: linear-gradient(135deg, #f44336, #b71c1c);
border-color: #b71c1c;
color: white;
}
.ludo-deal-blue-piece {
background: linear-gradient(135deg, #2196F3, #0D47A1);
border-color: #0D47A1;
color: white;
}
.ludo-deal-custom-input {
display: none;
align-items: center;
justify-content: center;
gap: 15px;
margin: 10px 0;
flex-wrap: wrap;
}
.ludo-deal-custom-input.visible {
display: flex;
}
.ludo-deal-custom-input input {
width: 80px;
height: 45px;
font-size: 24px;
text-align: center;
border: 3px solid #000;
border-radius: 10px;
font-weight: bold;
background: white;
color: #000;
-moz-appearance: textfield;
}
.ludo-deal-custom-input input::-webkit-outer-spin-button,
.ludo-deal-custom-input input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.ludo-deal-custom-input input:focus {
outline: none;
border-color: #ff9800;
box-shadow: 0 0 15px rgba(255, 152, 0, 0.5);
}
.ludo-deal-custom-input input::placeholder {
color: #999;
font-size: 16px;
}
.ludo-deal-custom-input .range-label {
font-size: 18px;
font-weight: bold;
color: #333;
}
.ludo-deal-custom-input .range-value {
font-size: 28px;
font-weight: bold;
color: #ff9800;
min-width: 40px;
}
.ludo-deal-buttons {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 30px;
}
.ludo-deal-btn {
padding: 20px 50px;
font-size: 28px;
border-radius: 60px;
cursor: pointer;
font-weight: bold;
border: 5px solid;
transition: all 0.3s;
min-width: 200px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.ludo-deal-execute-btn {
background: linear-gradient(to right, #4CAF50, #2E7D32);
color: white;
border-color: #2E7D32;
}
.ludo-deal-execute-btn:hover:not(:disabled) {
transform: scale(1.1) translateY(-5px);
box-shadow: 0 15px 40px #4CAF50;
}
.ludo-deal-execute-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
transform: none;
}
.ludo-deal-cancel-btn {
background: linear-gradient(to right, #f44336, #b71c1c);
color: white;
border-color: #b71c1c;
}
.ludo-deal-cancel-btn:hover {
transform: scale(1.1) translateY(-5px);
box-shadow: 0 15px 40px #f44336;
}
.ludo-question-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
z-index: 2000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.ludo-question-content {
background: linear-gradient(135deg, #ffffff, #f5f7fa);
width: 95%;
max-width: 1100px;
padding: 25px;
border-radius: 18px;
text-align: center;
box-shadow: 0 25px 60px rgba(0,0,0,0.6);
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
}
.ludo-question-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 3px solid #2196F3;
}
.ludo-question-title {
font-size: 26px;
color: #2196F3;
font-weight: bold;
text-align: right;
flex: 1;
}
.ludo-question-info {
display: flex;
gap: 20px;
align-items: center;
}
.ludo-question-count {
background: #f0f8ff;
padding: 10px 18px;
border-radius: 10px;
font-weight: bold;
color: #2196F3;
border: 2px solid #2196F3;
font-size: 15px;
}
.ludo-timer {
font-size: 30px;
font-weight: bold;
color: #F44336;
padding: 12px 22px;
background: #FFEBEE;
border-radius: 10px;
display: inline-block;
border: 3px solid #F44336;
min-width: 90px;
}
.ludo-question-formula {
background: linear-gradient(135deg, #4CAF50, #2E7D32);
color: white;
padding: 18px;
border-radius: 15px;
margin: 20px auto;
font-family: 'Courier New', monospace;
font-size: 26px;
font-weight: bold;
max-width: 650px;
box-shadow: 0 10px 20px rgba(76, 175, 80, 0.3);
border: 5px solid #2E7D32;
}
.ludo-question-instruction {
font-size: 18px;
color: #5D4037;
margin-bottom: 25px;
font-weight: bold;
background: #FFF3E0;
padding: 12px;
border-radius: 10px;
border: 2px solid #FF9800;
}
.ludo-options-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin: 25px 0;
max-width: 1000px;
margin-left: auto;
margin-right: auto;
}
.ludo-option {
background: white;
padding: 15px;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s;
border: 3px solid transparent;
box-shadow: 0 6px 15px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 120px;
}
.ludo-option:hover:not(.disabled) {
transform: translateY(-3px);
border-color: #2196F3;
box-shadow: 0 10px 20px rgba(0,0,0,0.15);
}
.ludo-option.disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
border-color: #ccc;
}
.ludo-option-text {
font-size: 20px;
font-weight: bold;
color: #333;
padding: 20px;
text-align: center;
line-height: 1.5;
}
.ludo-option-label {
font-weight: bold;
font-size: 18px;
color: #333;
margin-top: 10px;
padding: 8px 20px;
border-radius: 8px;
background: #f5f5f5;
width: 100%;
text-align: center;
}
.ludo-result-message {
font-size: 22px;
font-weight: bold;
margin: 20px 0;
padding: 18px;
border-radius: 10px;
display: none;
animation: ludoSlideIn 0.5s ease-out;
}
@keyframes ludoSlideIn {
from { transform: translateY(50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.ludo-correct {
background: linear-gradient(135deg, #4CAF50, #2E7D32);
color: white;
border: 3px solid #2E7D32;
}
.ludo-wrong {
background: linear-gradient(135deg, #F44336, #B71C1C);
color: white;
border: 3px solid #B71C1C;
}
.ludo-question-level {
position: absolute;
top: 15px;
left: 15px;
padding: 6px 12px;
border-radius: 8px;
font-weight: bold;
color: white;
font-size: 14px;
}
.ludo-level-easy { background: #4CAF50; }
.ludo-level-medium { background: #FF9800; }
.ludo-level-hard { background: #F44336; }
.ludo-piece-missing {
opacity: 0.3;
transform: scale(0.8);
}
.ludo-end-game-buttons {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 30px;
padding: 20px;
}
.ludo-return-btn {
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
border: none;
padding: 15px 40px;
font-size: 20px;
border-radius: 12px;
cursor: pointer;
font-weight: bold;
box-shadow: 0 5px 15px rgba(33, 150, 243, 0.4);
transition: all 0.3s;
}
.ludo-return-btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(33, 150, 243, 0.6);
}
.ludo-shield-tag {
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
background: cyan;
color: black;
font-size: 12px;
padding: 2px 8px;
border-radius: 10px;
border: 2px solid blue;
font-weight: bold;
white-space: nowrap;
z-index: 102;
animation: shieldTagPulse 1s infinite;
}
@keyframes shieldTagPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.instructions-page {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 99999;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.instructions-page.active {
display: flex;
}
.instructions-content {
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
width: 95%;
max-width: 900px;
padding: 40px;
border-radius: 30px;
box-shadow: 0 30px 80px rgba(0,0,0,0.8), 0 0 50px rgba(33, 150, 243, 0.3);
max-height: 90vh;
overflow-y: auto;
border: 3px solid #2196F3;
color: #fff;
text-align: right;
}
.instructions-content h2 {
color: #FFD700;
font-size: 36px;
text-align: center;
margin-bottom: 30px;
text-shadow: 0 0 20px rgba(255, 215, 0, 0.3);
}
.instructions-content h3 {
color: #4FC3F7;
font-size: 24px;
margin-top: 25px;
margin-bottom: 15px;
border-bottom: 2px solid rgba(79, 195, 247, 0.3);
padding-bottom: 10px;
}
.instructions-content ul {
list-style: none;
padding: 0;
}
.instructions-content ul li {
padding: 10px 15px;
margin: 8px 0;
background: rgba(255,255,255,0.05);
border-radius: 10px;
border-right: 3px solid #2196F3;
font-size: 17px;
line-height: 1.8;
}
.instructions-content ul li strong {
color: #FFD700;
}
.instructions-content .close-instructions {
display: block;
margin: 30px auto 0;
padding: 15px 50px;
font-size: 22px;
border-radius: 60px;
cursor: pointer;
font-weight: bold;
border: none;
background: linear-gradient(to right, #2196F3, #0D47A1);
color: white;
box-shadow: 0 10px 30px rgba(33, 150, 243, 0.4);
transition: all 0.3s;
}
.instructions-content .close-instructions:hover {
transform: scale(1.05);
box-shadow: 0 15px 40px rgba(33, 150, 243, 0.6);
}
.instructions-content .rule-icon {
font-size: 24px;
margin-left: 10px;
}
/* ===== استایل خانه شبیهسازی ===== */
.ludo-simulation-cell {
background: radial-gradient(circle at 30% 30%, #0a0a2a, #1a0a3a, #000000) !important;
border: 4px solid #00ffff !important;
border-radius: 15px !important;
box-shadow: 0 0 40px rgba(0, 255, 255, 0.6), inset 0 0 30px rgba(0, 255, 255, 0.3), 0 0 80px rgba(0, 255, 255, 0.2) !important;
position: relative;
overflow: hidden;
animation: simulationCellGlow 1.5s infinite alternate;
color: white;
font-weight: bold;
}
@keyframes simulationCellGlow {
0% { box-shadow: 0 0 30px rgba(0, 255, 255, 0.4), inset 0 0 20px rgba(0, 255, 255, 0.2), 0 0 60px rgba(0, 255, 255, 0.1); }
100% { box-shadow: 0 0 60px rgba(0, 255, 255, 0.8), inset 0 0 40px rgba(0, 255, 255, 0.5), 0 0 100px rgba(0, 255, 255, 0.4); }
}
.ludo-simulation-cell::before {
content: '🧬';
position: absolute;
font-size: 45px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #00ffff;
text-shadow: 0 0 30px #00ffff, 0 0 60px #00ffff;
animation: simulationIconPulse 1.5s ease-in-out infinite;
z-index: 2;
}
@keyframes simulationIconPulse {
0%, 100% { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
50% { transform: translate(-50%, -50%) scale(1.2) rotate(10deg); }
}
.ludo-simulation-cell::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 20px,
rgba(0, 255, 255, 0.1) 20px,
rgba(0, 200, 255, 0.15) 30px,
transparent 30px,
transparent 50px
);
animation: simulationBgMove 6s linear infinite;
z-index: 1;
}
@keyframes simulationBgMove {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(50%, 50%) rotate(90deg); }
}
.ludo-simulation-cell .simulation-text {
position: absolute;
bottom: 3px;
left: 50%;
transform: translateX(-50%);
font-size: 11px;
color: #00ffff;
background: rgba(0, 0, 0, 0.7);
padding: 2px 8px;
border-radius: 10px;
border: 1px solid #00ffff;
z-index: 3;
white-space: nowrap;
font-weight: bold;
text-shadow: 0 0 10px #00ffff;
animation: simulationTextPulse 1s infinite alternate;
}
@keyframes simulationTextPulse {
0% { color: #00ffff; border-color: #00ffff; box-shadow: 0 0 5px #00ffff; }
100% { color: #00ffaa; border-color: #00ffaa; box-shadow: 0 0 15px #00ffaa; }
}
.ludo-simulation-cell .simulation-lock {
position: absolute;
top: 3px;
right: 3px;
font-size: 16px;
color: #ff4444;
text-shadow: 0 0 10px #ff0000;
z-index: 4;
animation: lockPulse 1s infinite;
}
@keyframes lockPulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(0.8); }
}
/* ===== استایل مهرههای شبیهسازی ===== */
.ludo-simulation-piece {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid rgba(255, 255, 255, 0.5);
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
cursor: pointer !important;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0,0,0,0.2), 0 0 15px rgba(0, 255, 255, 0.2);
animation: simulationPieceFloat 2s ease-in-out infinite;
}
.ludo-simulation-piece:hover {
transform: scale(1.15) !important;
box-shadow: 0 0 30px rgba(0, 255, 255, 0.4) !important;
}
.ludo-simulation-piece-blue {
background: linear-gradient(135deg, rgba(33, 150, 243, 0.5), rgba(13, 71, 161, 0.5));
border-color: rgba(33, 150, 243, 0.3);
}
.ludo-simulation-piece-red {
background: linear-gradient(135deg, rgba(244, 67, 54, 0.5), rgba(183, 28, 28, 0.5));
border-color: rgba(244, 67, 54, 0.3);
}
@keyframes simulationPieceFloat {
0%, 100% { transform: translateY(0px) scale(1); }
50% { transform: translateY(-5px) scale(1.02); }
}
.ludo-simulation-piece .sim-tag {
position: absolute;
top: -18px;
left: 50%;
transform: translateX(-50%);
font-size: 10px;
background: rgba(0, 0, 0, 0.7);
color: #00ffff;
padding: 1px 6px;
border-radius: 8px;
border: 1px solid #00ffff;
white-space: nowrap;
font-weight: bold;
}
.ludo-simulation-piece.ludo-highlight {
animation: ludoHighlightPiece 0.5s ease-in-out infinite alternate;
box-shadow: 0 0 20px gold, 0 0 40px gold !important;
transform: scale(1.1);
}
/* ===== انیمیشن شبیهسازی ===== */
.simulation-animation-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 40000;
display: none;
overflow: hidden;
background: rgba(0, 0, 0, 0.7);
}
.simulation-animation-container.active {
display: block;
}
.simulation-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at center, rgba(0, 255, 255, 0.1), rgba(0, 0, 0, 0.8));
animation: simOverlayPulse 1s infinite alternate;
}
@keyframes simOverlayPulse {
0% { opacity: 0.5; }
100% { opacity: 1; }
}
.simulation-particle {
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background: #00ffff;
box-shadow: 0 0 20px #00ffff;
animation: simParticleFly 2s ease-in-out infinite;
}
@keyframes simParticleFly {
0% { transform: translate(0, 0) scale(1); opacity: 1; }
100% { transform: translate(var(--tx), var(--ty)) scale(0); opacity: 0; }
}
.simulation-dna {
position: absolute;
width: 4px;
height: 200px;
background: linear-gradient(to bottom, #00ffff, #ff00ff, #00ffff);
border-radius: 2px;
animation: simDNA 1s ease-in-out infinite;
transform-origin: center;
}
@keyframes simDNA {
0%, 100% { transform: rotate(0deg); opacity: 0.5; }
50% { transform: rotate(180deg); opacity: 1; }
}
.simulation-spiral {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
border: 3px solid #00ffff;
border-top-color: transparent;
animation: simSpiral 1.5s linear infinite;
box-shadow: 0 0 30px rgba(0, 255, 255, 0.3);
}
@keyframes simSpiral {
0% { transform: translate(-50%, -50%) rotate(0deg) scale(0.5); opacity: 1; }
100% { transform: translate(-50%, -50%) rotate(720deg) scale(2); opacity: 0; }
}
/* ===== افکتهای ماتریکسی اضافی ===== */
.simulation-matrix-rain {
position: absolute;
color: #00ff41;
font-family: 'Courier New', monospace;
font-size: 20px;
opacity: 0.7;
animation: matrixRain 1.5s linear infinite;
text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41;
}
@keyframes matrixRain {
0% { transform: translateY(-100vh); opacity: 0.7; }
100% { transform: translateY(100vh); opacity: 0; }
}
.simulation-matrix-code {
position: absolute;
color: #00ff41;
font-family: 'Courier New', monospace;
font-size: 16px;
opacity: 0.5;
animation: matrixCode 2s ease-in-out infinite;
text-shadow: 0 0 5px #00ff41;
}
@keyframes matrixCode {
0%, 100% { opacity: 0.2; transform: scale(0.8); }
50% { opacity: 0.8; transform: scale(1.2); }
}
.simulation-flash-line {
position: absolute;
width: 100%;
height: 2px;
background: linear-gradient(to right, transparent, #00ffff, transparent);
animation: flashLine 1s ease-in-out infinite;
}
@keyframes flashLine {
0% { transform: translateY(-50vh) scaleX(0); opacity: 0; }
50% { transform: translateY(0) scaleX(1); opacity: 1; }
100% { transform: translateY(50vh) scaleX(0); opacity: 0; }
}
.simulation-ring-wave {
position: absolute;
border: 2px solid #00ffff;
border-radius: 50%;
animation: ringWave 1.5s ease-out infinite;
}
@keyframes ringWave {
0% { width: 20px; height: 20px; opacity: 1; }
100% { width: 300px; height: 300px; opacity: 0; }
}
.simulation-data-stream {
position: absolute;
width: 3px;
height: 100px;
background: linear-gradient(to bottom, transparent, #00ffff, transparent);
animation: dataStream 1s linear infinite;
}
@keyframes dataStream {
0% { transform: translateY(-100px); opacity: 0; }
50% { opacity: 1; }
100% { transform: translateY(100px); opacity: 0; }
}
/* ===== عکسهای شبیهسازی ===== */
.simulation-image-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 35000;
display: none;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.9);
pointer-events: none;
}
.simulation-image-overlay.active {
display: flex;
}
.simulation-image-box {
max-width: 90%;
max-height: 90vh;
border-radius: 20px;
border: 5px solid #00ffff;
box-shadow: 0 0 50px rgba(0, 255, 255, 0.5), 0 0 100px rgba(0, 255, 255, 0.2);
animation: simImagePulse 0.5s ease-in-out;
}
@keyframes simImagePulse {
0% { transform: scale(0.5); opacity: 0; }
50% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); opacity: 1; }
}
.simulation-image-flash {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
opacity: 0;
animation: simFlash 0.3s ease-out forwards;
}
@keyframes simFlash {
0% { opacity: 0.8; }
100% { opacity: 0; }
}
/* ===== استایل چالش هکر ===== */
.hacker-challenge-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 45000;
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}
.hacker-challenge-modal.active {
display: flex;
}
.hacker-challenge-content {
background: linear-gradient(135deg, #0a0f1e, #1a1a2e, #0f3460);
width: 95%;
max-width: 800px;
padding: 40px;
border-radius: 30px;
text-align: center;
box-shadow: 0 0 60px rgba(0, 255, 65, 0.3), 0 0 120px rgba(0, 255, 65, 0.1);
max-height: 90vh;
overflow-y: auto;
margin: auto;
position: relative;
border: 3px solid #00ff41;
}
.hacker-challenge-title {
font-size: 32px;
font-weight: bold;
color: #00ff41;
font-family: 'Courier New', monospace;
text-shadow: 0 0 20px rgba(0, 255, 65, 0.5);
margin-bottom: 20px;
}
.hacker-number-display {
font-size: 48px;
font-weight: bold;
color: #00ff41;
font-family: 'Courier New', monospace;
text-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
background: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 15px;
border: 2px solid #00ff41;
margin: 20px 0;
letter-spacing: 8px;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.hacker-number-display .hacker-timer {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 28px;
color: #ff4444;
text-shadow: 0 0 20px rgba(255, 68, 68, 0.5);
background: rgba(0, 0, 0, 0.5);
padding: 5px 15px;
border-radius: 10px;
border: 2px solid #ff4444;
}
.hacker-input-display {
font-size: 36px;
font-weight: bold;
color: #00ff41;
font-family: 'Courier New', monospace;
background: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 15px;
border: 2px solid #00ff41;
margin: 20px 0;
min-height: 60px;
letter-spacing: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.hacker-buttons-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 15px;
margin: 20px 0;
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
.hacker-digit-btn {
padding: 20px;
font-size: 28px;
font-weight: bold;
font-family: 'Courier New', monospace;
border: 2px solid #00ff41;
border-radius: 12px;
background: rgba(0, 0, 0, 0.3);
color: #00ff41;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 0 10px rgba(0, 255, 65, 0.1);
}
.hacker-digit-btn:hover:not(:disabled) {
transform: scale(1.1);
background: rgba(0, 255, 65, 0.1);
box-shadow: 0 0 30px rgba(0, 255, 65, 0.3);
}
.hacker-digit-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
transform: none !important;
}
.hacker-digit-btn.correct-flash {
background: #00ff41;
color: #000;
transform: scale(1.1);
box-shadow: 0 0 40px #00ff41;
}
.hacker-digit-btn.wrong-flash {
background: #ff4444;
color: #fff;
transform: scale(1.1);
box-shadow: 0 0 40px #ff4444;
}
.hacker-result-message {
font-size: 24px;
font-weight: bold;
padding: 20px;
border-radius: 15px;
margin: 20px 0;
display: none;
font-family: 'Courier New', monospace;
}
.hacker-result-message.success {
display: block;
color: #00ff41;
background: rgba(0, 255, 65, 0.2);
border: 2px solid #00ff41;
animation: hackerSuccessPulse 0.5s ease-in-out;
}
.hacker-result-message.fail {
display: block;
color: #ff4444;
background: rgba(255, 68, 68, 0.2);
border: 2px solid #ff4444;
animation: hackerFailPulse 0.5s ease-in-out;
}
@keyframes hackerSuccessPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes hackerFailPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
/* ===== انیمیشن هکری ===== */
.hacker-animation-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 50000;
display: none;
overflow: hidden;
background: rgba(0, 0, 0, 0.95);
}
.hacker-animation-container.active {
display: block;
}
.hacker-animation-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
overflow: hidden;
}
.hacker-matrix-rain {
position: absolute;
color: #00ff41;
font-family: 'Courier New', monospace;
font-size: 18px;
opacity: 0.6;
animation: hackerMatrixRain 2s linear infinite;
text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41;
}
@keyframes hackerMatrixRain {
0% { transform: translateY(-100vh); opacity: 0.6; }
100% { transform: translateY(100vh); opacity: 0; }
}
.hacker-matrix-code {
position: absolute;
color: #00ff41;
font-family: 'Courier New', monospace;
font-size: 14px;
opacity: 0.4;
animation: hackerMatrixCode 3s ease-in-out infinite;
text-shadow: 0 0 5px #00ff41;
}
@keyframes hackerMatrixCode {
0%, 100% { opacity: 0.2; transform: scale(0.8); }
50% { opacity: 0.8; transform: scale(1.2); }
}
.hacker-flash-line {
position: absolute;
width: 100%;
height: 2px;
background: linear-gradient(to right, transparent, #00ff41, transparent);
animation: hackerFlashLine 1.5s ease-in-out infinite;
}
@keyframes hackerFlashLine {
0% { transform: translateY(-50vh) scaleX(0); opacity: 0; }
50% { transform: translateY(0) scaleX(1); opacity: 1; }
100% { transform: translateY(50vh) scaleX(0); opacity: 0; }
}
.hacker-ring-wave {
position: absolute;
border: 2px solid #00ff41;
border-radius: 50%;
animation: hackerRingWave 1.5s ease-out infinite;
opacity: 0.3;
}
@keyframes hackerRingWave {
0% { width: 20px; height: 20px; opacity: 0.3; }
100% { width: 300px; height: 300px; opacity: 0; }
}
.hacker-data-stream {
position: absolute;
width: 3px;
height: 80px;
background: linear-gradient(to bottom, transparent, #00ff41, transparent);
animation: hackerDataStream 1.2s linear infinite;
opacity: 0.5;
}
@keyframes hackerDataStream {
0% { transform: translateY(-80px); opacity: 0; }
50% { opacity: 0.5; }
100% { transform: translateY(80px); opacity: 0; }
}
.hacker-animation-images {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
pointer-events: none;
}
.hacker-animation-image {
max-width: 80%;
max-height: 70vh;
border-radius: 20px;
border: 3px solid #00ff41;
box-shadow: 0 0 60px rgba(0, 255, 65, 0.3), 0 0 120px rgba(0, 255, 65, 0.1);
opacity: 0;
transition: opacity 0.3s ease-in-out;
animation: hackerImageShake 0.5s ease-in-out infinite;
position: absolute;
}
.hacker-animation-image.active {
opacity: 1;
}
@keyframes hackerImageShake {
0%, 100% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(-5px, 5px) rotate(1deg); }
75% { transform: translate(5px, -5px) rotate(-1deg); }
}
@media (max-width: 1200px) {
.ludo-container {
grid-template-columns: 1fr;
grid-template-rows: auto;
max-width: 95%;
}
.ludo-board {
width: 90vw;
height: 90vw;
max-width: 700px;
max-height: 700px;
grid-column: 1;
grid-row: 3;
}
.ludo-player-section {
grid-column: 1;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: 100%;
}
.ludo-red-section {
grid-row: 2;
justify-self: center;
}
.ludo-blue-section {
grid-row: 4;
justify-self: center;
}
.ludo-question-content {
padding: 20px;
}
.ludo-options-container {
grid-template-columns: 1fr;
gap: 12px;
}
.ludo-deal-split {
flex-direction: column;
}
.ludo-deal-split::before {
display: none;
}
.ludo-deal-content {
padding: 15px;
}
.ludo-deal-option-title {
font-size: 16px;
}
.hacker-number-display {
font-size: 32px;
flex-direction: column;
gap: 10px;
padding: 15px;
}
.hacker-number-display .hacker-timer {
position: static;
transform: none;
}
.hacker-buttons-grid {
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.hacker-digit-btn {
padding: 15px;
font-size: 22px;
}
}
@media (max-width: 768px) {
.ludo-container {
padding: 10px;
gap: 10px;
}
.ludo-turn-indicator {
font-size: 18px;
padding: 10px 20px;
}
.ludo-question-header {
flex-direction: column;
gap: 10px;
}
.ludo-question-formula {
font-size: 22px;
padding: 15px;
}
.ludo-timer {
font-size: 26px;
padding: 10px 20px;
}
.ludo-question-info {
flex-direction: column;
gap: 10px;
}
.ludo-pieces-layer {
width: 150px;
height: 150px;
padding: 15px;
}
.ludo-piece-in-home {
width: 45px;
height: 45px;
font-size: 18px;
}
.ludo-dice {
width: 60px;
height: 60px;
font-size: 30px;
}
.ludo-game-info {
flex-direction: column;
gap: 10px;
}
.ludo-info-box {
min-width: 100px;
}
.ludo-save-btn {
min-width: 100px;
font-size: 14px;
padding: 8px 15px;
}
.ludo-deal-custom-input input {
width: 60px;
height: 40px;
font-size: 20px;
}
.ludo-hacker-btn {
font-size: 12px;
padding: 5px 10px;
min-width: 50px;
}
.ludo-hacker-field {
width: 34px;
height: 30px;
font-size: 12px;
}
.hacker-number-display {
font-size: 26px;
}
.hacker-buttons-grid {
grid-template-columns: repeat(5, 1fr);
gap: 8px;
}
.hacker-digit-btn {
padding: 12px;
font-size: 18px;
}
}
</style>
</head>
<body class="main-menu-active" id="mainBody">
<!-- ===== فلوتینگ سیارات ===== -->
<div class="floating-planets-bg">
<div class="bg-planet">🌍</div>
<div class="bg-planet">🪐</div>
<div class="bg-planet">🌕</div>
<div class="bg-planet">☄️</div>
<div class="bg-planet">⭐</div>
<div class="bg-planet">🌙</div>
<div class="bg-planet">✨</div>
<div class="bg-planet">🪐</div>
</div>
<div class="math-background"></div>
<!-- ===== منوی اصلی ===== -->
<div id="mainMenu">
<div style="margin-top: 80px; background: rgba(255, 255, 255, 0.95); border-radius: 20px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); max-width: 800px; margin-left: auto; margin-right: auto; border: 3px solid #0D47A1;">
<div style="width: 200px; height: 200px; margin: 20px auto; border-radius: 20px; display: flex; align-items: center; justify-content: center; border: 8px solid white; box-shadow: 0 10px 25px rgba(0,0,0,0.3); overflow: hidden; background: white;">
<img src="https://cdn.imgurl.ir/uploads/s826320_6831470285209814334.png" alt="بازی منچ کیهانی" style="width:100%; height:100%; object-fit:cover;">
</div>
<div style="background: linear-gradient(to right, #FFF3E0, #FFECB3); border-radius: 15px; padding: 15px; margin: 20px auto; max-width: 600px; text-align: center; font-size: 16px; color: #5D4037; box-shadow: 0 5px 15px rgba(255, 152, 0, 0.2);">
<div style="font-size: 24px; margin-bottom: 10px;">⚠️</div>
<strong>توجه:</strong> لطفاً اینترنت خود را برای بارگذاری تصاویر و صداها روشن کنید.
<br>در صورت بروز مشکل در لود تصاویر، بازی را مجدداً بارگذاری کنید.
</div>
<h1 style="color: #0D47A1; font-size: 3.2em; margin-bottom: 20px;">🎲 بازی منچ کیهانی</h1>
<button class="menu-btn" onclick="startLudoGame()" style="background: linear-gradient(to right, #FF9800, #F57C00);">
🎲 ورود به بخش منچ کیهانی
</button>
<button class="menu-btn" style="background: linear-gradient(to right, #757575, #424242);" onclick="showInstructionsPage()">
📖 آموزش بازی
</button>
<div style="font-size: 15px; color: #666; margin-top: 50px; padding-top: 15px; border-top: 2px dashed #ddd;">
🎮 سازنده:peru000
</div>
</div>
</div>
<!-- ===== صفحه آموزش ===== -->
<div class="instructions-page" id="instructionsPage">
<div class="instructions-content">
<h2>📚 قوانین بازی منچ کیهانی</h2>
<h3>🎯 هدف بازی</h3>
<ul>
<li><span class="rule-icon">🏆</span> هر تیم باید <strong>۳ مهره</strong> از رنگ خود را به خانههای طلایی (۱۱۷ تا ۱۲۰) برساند</li>
<li><span class="rule-icon">🤝</span> اگر هر تیم ۲ مهره بگذارد، بازی <strong>مساوی</strong> میشود</li>
</ul>
<h3>🎲 شروع بازی</h3>
<ul>
<li><span class="rule-icon">🔵</span> بازی با <strong>تیم آبی</strong> شروع میشود</li>
<li><span class="rule-icon">🎲</span> اگر عدد <strong>۶</strong> بیاورید، یک نوبت اضافه میگیرید</li>
<li><span class="rule-icon">➖</span> اعداد منفی باعث <strong>حرکت به عقب</strong> میشوند</li>
<li><span class="rule-icon">6️⃣</span> عدد <strong>۶</strong> با صدای مخصوص همراه است</li>
<li><span class="rule-icon">➖2️⃣</span> عدد <strong>منفی ۲</strong> با صدای مخصوص همراه است</li>
</ul>
<h3>🏠 خانههای ویژه</h3>
<ul>
<li><span class="rule-icon">☠️</span> <strong>خطر (۸ عدد):</strong> مهره حذف شده و به خانه اول برمیگردد</li>
<li><span class="rule-icon">❓</span> <strong>سوال (۱۰ عدد):</strong> سوال اطلاعات عمومی با زمان ۲۰ ثانیه<br>پاسخ صحیح = حرکت کامل، پاسخ اشتباه = ۲ نوبت پنالتی</li>
<li><span class="rule-icon">🎲</span> <strong>شانس (۳ عدد):</strong> تاس طلایی با اعداد ۱۰، ۲۰، ۳۰، ۴۰، ۵۰، ۱۰-، ۲۰-</li>
<li><span class="rule-icon">💥</span> <strong>انفجار (۲ عدد):</strong> انفجار اتمی با ۱۵ گوی گدازه</li>
<li><span class="rule-icon">💰</span> <strong>معامله (۳ عدد):</strong> هر تیم یک گزینه برای طرف مقابل انتخاب میکند</li>
<li><span class="rule-icon">🌈</span> <strong>رنگینکمان (۲ عدد):</strong> چرخش هیجانی مهرهها به خانههای ۱ تا ۱۲۰ (به جز مهرههای زندانی)</li>
<li><span class="rule-icon">👻</span> <strong>روح (فقط ۱ عدد):</strong> جامپ اسکر ترسناک + ۴ روح متحرک به مدت ۲۰ ثانیه</li>
<li><span class="rule-icon">⇄</span> <strong>انتقال (۲ عدد):</strong> خانه ۷ → ۵۸ و خانه ۷۶ → ۹۶</li>
<li><span class="rule-icon">🔒</span> <strong>زندان (خانههای ۵ و ۱۱۳):</strong> زندانی شدن ۳ دقیقهای با افکت آتش و حباب</li>
<li><span class="rule-icon">🧬</span> <strong>شبیهسازی (۲ عدد):</strong> شبیهسازی مهرههای حریف با افکتهای ویژه</li>
</ul>
<h3>🧬 خانه شبیهسازی (ویژه)</h3>
<ul>
<li><span class="rule-icon">🧬</span> <strong>۲ عدد</strong> در کل تخته</li>
<li><span class="rule-icon">📸</span> نمایش ۲ عکس به صورت ماتریکسی با صدای لودینگ و افکتهای ویژه</li>
<li><span class="rule-icon">🧬</span> انیمیشن شبیهسازی خفن به مدت ۵ ثانیه با افکتهای ماتریکسی</li>
<li><span class="rule-icon">🎯</span> از مهره روی خانه، به تعداد مهرههای حریف در تخته (به جز زندان، خانه طلایی، خانه ۱ و ۲) شبیهساز ساخته میشود</li>
<li><span class="rule-icon">📍</span> هر شبیهساز ۲ خانه پشت یکی از مهرههای حریف قرار میگیرد</li>
<li><span class="rule-icon">🎨</span> مهرههای شبیهساز کمرنگتر از رنگ اصلی هستند</li>
<li><span class="rule-icon">⏱️</span> به مدت <strong>۸ راند</strong> در بازی حضور دارند</li>
<li><span class="rule-icon">🚫</span> از خانههای ویژه اثری نمیپذیرند (خطر، سوال، شانس، انفجار، معامله، رنگینکمان، روح، طلایی)</li>
<li><span class="rule-icon">⚔️</span> میتوانند مهرههای حریف را حذف کنند (مثل مهرههای عادی)</li>
<li><span class="rule-icon">🔒</span> خانههای شبیهسازی تا پایان ۸ راند قفل میشوند</li>
<li><span class="rule-icon">🔄</span> در ابتدای بازی قفل هستند و با شرایط خاص فعال میشوند</li>
<li><span class="rule-icon">🎮</span> مهرههای شبیهساز مانند مهرههای عادی با تاس حرکت میکنند</li>
<li><span class="rule-icon">🚶</span> حتی زمانی که خانه شبیهسازی قفل است، مهرهها میتوانند روی آن بروند اما هیچ اتفاقی نمیافتد</li>
</ul>
<h3>👻 خانه روح (ویژه)</h3>
<ul>
<li><span class="rule-icon">👻</span> <strong>فقط ۱ عدد</strong> در کل تخته</li>
<li><span class="rule-icon">💀</span> مهره روی آن برود → جامپ اسکر با تصویر روح و صدای ترسناک</li>
<li><span class="rule-icon">👻</span> سپس <strong>۴ روح</strong> به مدت ۲۰ ثانیه حرکت میکنند</li>
<li><span class="rule-icon">⚡</span> هر مهرهای که روح از روی آن عبور کند، <strong>حذف</strong> میشود</li>
<li><span class="rule-icon">🛡️</span> <strong>استثناها:</strong> مهرههای خانه طلایی و مهرههای با سپر <strong>محافظت</strong> میشوند</li>
<li><span class="rule-icon">🔒</span> در طول ۲۰ ثانیه، <strong>تاسها قفل</strong> میشوند</li>
</ul>
<h3>🛡️ سپر محافظ</h3>
<ul>
<li><span class="rule-icon">🛡️</span> از مهره در برابر <strong>حذف، انفجار، خطر و روح</strong> محافظت میکند</li>
<li><span class="rule-icon">💰</span> در صفحه <strong>معامله</strong> قابل دریافت است</li>
</ul>
<h3>⚡ گزینه ذخیره و رعد و برق شکن</h3>
<ul>
<li><span class="rule-icon">💾</span> هر تیم یک گزینه <strong>ذخیره:n</strong> در پایین تاس خود دارد</li>
<li><span class="rule-icon">🔒</span> این گزینه در ابتدا <strong>قفل</strong> است</li>
<li><span class="rule-icon">6️⃣</span> هر بار که تاس <strong>۶</strong> بیاورید، گزینه برای <strong>همان تیم</strong> فعال میشود</li>
<li><span class="rule-icon">💾</span> با کلیک روی آن، عدد ذخیره <strong>۱</strong> واحد افزایش مییابد و دوباره قفل میشود</li>
<li><span class="rule-icon">📈</span> این عدد تا <strong>۵</strong> قابل افزایش است</li>
<li><span class="rule-icon">⚡</span> وقتی عدد به <strong>۵</strong> رسید، گزینه به <strong>رعد و برق شکن</strong> تبدیل میشود</li>
<li><span class="rule-icon">⚡</span> <strong>رعد و برق شکن:</strong> یک بار مصرف، یک مهره تصادفی از هر دو تیم را حذف میکند</li>
<li><span class="rule-icon">⚡</span> حتی مهرههای خانه طلایی، سپر دار و زندانی هم ممکن است حذف شوند</li>
<li><span class="rule-icon">⚡</span> اگر هیچ مهرهای در تخته نباشد، این گزینه <strong>قفل</strong> میشود</li>
<li><span class="rule-icon">⚡</span> رعد و برق شکن فقط در نوبت خود تیم قابل استفاده است</li>
<li><span class="rule-icon">⚡</span> هر تیم فقط یک بار میتواند از رعد و برق شکن استفاده کند</li>
</ul>
<h3>🖥️ گزینه هکر (ویژه جدید)</h3>
<ul>
<li><span class="rule-icon">💻</span> <strong>فقط ۱ عدد آیتم هکینگ دیوایس</strong> در کل بازی</li>
<li><span class="rule-icon">📍</span> در <strong>خانههای معمولی</strong> (نه ویژه، نه زندان، نه طلایی، نه شبیهسازی، نه انتقال، نه روح)</li>
<li><span class="rule-icon">🎲</span> کاملاً <strong>رندوم</strong> در ابتدای بازی</li>
<li><span class="rule-icon">⏹️</span> وقتی مهره روی خانه بمونه (نه عبور)، آیتم رو میگیره</li>
<li><span class="rule-icon">🗑️</span> بعد از برداشتن، آیتم از اون خانه حذف میشه</li>
<li><span class="rule-icon">🔓</span> <strong>دکمه هکر</strong> برای همون تیم فعال میشه</li>
<li><span class="rule-icon">🕹️</span> فقط در نوبت خودش قابل استفاده، در نوبت حریف قفل میشه</li>
<li><span class="rule-icon">🎬</span> انیمیشن هکری با ۴ عکس (هر کدام ۲ ثانیه) + ۸ ثانیه فلش (۱۶ ثانیه کل)</li>
<li><span class="rule-icon">🔢</span> چالش هکری: عدد ۱۰ رقمی رندوم + تایمر ۲۰ ثانیه + ۱۰ گزینه رندوم</li>
<li><span class="rule-icon">✅</span> موفقیت: دکمه هکر ناپدید میشه و ۲ فیلد + دکمه تایید ظاهر میشه</li>
<li><span class="rule-icon">❌</span> شکست: همه مهرههای اون تیم حذف میشن (هیچ استثنایی نداره)</li>
<li><span class="rule-icon">🔄</span> <strong>۴ بار</strong> قابلیت استفاده بعد از هک موفق</li>
<li><span class="rule-icon">🎯</span> فیلد اول: عدد تاس حریف (۱ تا ۵ یا 1n/2n) - فیلد دوم: مهره حریف (۱ تا ۴)</li>
<li><span class="rule-icon">⛔</span> مهرههای زندان، طلایی، شبیهسازی و خارج از بازی قابل انتخاب نیستن</li>
<li><span class="rule-icon">📊</span> بعد از ۴ بار استفاده، فیلدها ناپدید میشن</li>
<li><span class="rule-icon">🤖</span> حرکت مهره اجباری <strong>خودکار</strong> انجام میشه (بدون کلیک)</li>
<li><span class="rule-icon">🔢</span> در فیلد تاس میتوان <strong>1n</strong> (منفی ۱) و <strong>2n</strong> (منفی ۲) نوشت</li>
<li><span class="rule-icon">🎲</span> روی تاس بازی، اعداد منفی به صورت <strong>-1</strong> و <strong>-2</strong> نمایش داده میشوند</li>
</ul>
<h3>🎮 نکات پایانی</h3>
<ul>
<li><span class="rule-icon">🔊</span> صدای بازی قابل <strong>فعال/غیرفعال</strong> کردن است</li>
<li><span class="rule-icon">📱</span> بازی کاملاً <strong>واکنشگرا (Responsive)</strong> است</li>
<li><span class="rule-icon">🏆</span> پس از پایان بازی، دکمه <strong>بازگشت</strong> نمایش داده میشود</li>
</ul>
<button class="close-instructions" onclick="closeInstructionsPage()">✅ بستن آموزش</button>
</div>
</div>
<!-- ===== صفحه بازی ===== -->
<div id="ludoScreen">
<div class="ludo-start-screen" id="ludoStartScreen">
<h1 style="color: white; font-size: 48px; margin-bottom: 30px; text-shadow: 2px 2px 4px rgba(0,0,0,0.5);">🎲 بخش منچ کیهانی</h1>
<p style="color: white; font-size: 22px; margin-bottom: 50px; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); max-width: 800px; line-height: 1.6;">
یک بازی دو نفره جذاب با چالشهای متنوع!<br>
در این بازی شما باید مهرههای خود را به خانههای طلایی برسانید<br>
و با پاسخ به سوالات اطلاعات عمومی مهارت خود را تقویت کنید.
</p>
<button class="ludo-start-btn" onclick="startLudoGameDirectly()">🎮 ورود به بخش منچ کیهانی</button>
</div>
<div id="ludoGameContainer" style="display: none;">
<!-- ===== کنترل صدا ===== -->
<div class="ludo-audio-control" onclick="toggleLudoBackgroundSound()">
<span id="ludoBgSoundIcon">🎵</span>
<span>صدای بازی</span>
</div>
<div class="ludo-container">
<h1>🎲 بازی منچ کیهانی</h1>
<div class="ludo-turn-indicator" id="ludoTurnIndicator">نوبت: تیم آبی</div>
<div class="ludo-game-info">
<div class="ludo-info-box">
<div>خانههای برنده آبی</div>
<div class="ludo-info-value ludo-blue-info-value" id="ludoBlueWinnerHouses">0</div>
<div>(هدف: 3 مهره)</div>
</div>
<div class="ludo-info-box">
<div>تاس فعلی</div>
<div class="ludo-info-value" id="ludoCurrentDiceValue">0</div>
<div>عدد تاس</div>
</div>
<div class="ludo-info-box">
<div>خانههای برنده قرمز</div>
<div class="ludo-info-value ludo-red-info-value" id="ludoRedWinnerHouses">0</div>
<div>(هدف: 3 مهره)</div>
</div>
</div>
<!-- ===== تخته بازی ===== -->
<div class="ludo-board" id="ludoBoard"></div>
<!-- ===== بخش بازیکن قرمز ===== -->
<div class="ludo-player-section ludo-red-section">
<div class="ludo-pieces-layer" id="ludoRedPiecesContainer">
<div class="ludo-piece-in-home ludo-red-piece-home" onclick="ludoSelectPiece('red', 1)">1</div>
<div class="ludo-piece-in-home ludo-red-piece-home" onclick="ludoSelectPiece('red', 2)">2</div>
<div class="ludo-piece-in-home ludo-red-piece-home" onclick="ludoSelectPiece('red', 3)">3</div>
<div class="ludo-piece-in-home ludo-red-piece-home" onclick="ludoSelectPiece('red', 4)">4</div>
</div>
<div class="ludo-piece-label ludo-red-label">مهرههای قرمز</div>
<div class="ludo-dice-container">
<div class="ludo-dice-box">
<div class="ludo-dice ludo-red-dice" id="ludoRedDice" onclick="ludoRollDice('red')">🎲</div>
<div class="ludo-dice-label ludo-dice-red-label">تاس قرمز</div>
</div>
</div>
<!-- ===== دکمههای قرمز: هکر (بالا) + ذخیره (پایین) ===== -->
<div class="ludo-save-container">
<!-- ردیف اول: دکمه هکر -->
<div class="ludo-save-row">
<button class="ludo-hacker-btn disabled" id="ludoRedHackerBtn" onclick="ludoUseHacker('red')">
💻 هکر
</button>
</div>
<!-- ردیف دوم: دکمه ذخیره -->
<div class="ludo-save-row">
<button class="ludo-save-btn ludo-save-btn-red disabled" id="ludoRedSaveBtn" onclick="ludoHandleSave('red')">
ذخیره: 0
</button>
</div>
<!-- ردیف سوم: فیلدهای هکر -->
<div class="ludo-save-row" id="ludoRedHackerFieldsContainer" style="display: none;">
<div class="ludo-hacker-fields">
<input type="text" class="ludo-hacker-field" id="ludoRedHackerField1" placeholder="تاس" disabled oninput="ludoValidateHackerField('red')" maxlength="2">
<input type="text" class="ludo-hacker-field" id="ludoRedHackerField2" placeholder="مهره" disabled oninput="ludoValidateHackerField('red')" maxlength="1">
<button class="ludo-hacker-confirm-btn" id="ludoRedHackerConfirmBtn" disabled onclick="ludoConfirmHacker('red')">✔</button>
<span class="ludo-hacker-counter" id="ludoRedHackerCounter">4</span>
</div>
</div>
</div>
</div>
<!-- ===== بخش بازیکن آبی ===== -->
<div class="ludo-player-section ludo-blue-section">
<div class="ludo-pieces-layer" id="ludoBluePiecesContainer">
<div class="ludo-piece-in-home ludo-blue-piece-home" onclick="ludoSelectPiece('blue', 1)">1</div>
<div class="ludo-piece-in-home ludo-blue-piece-home" onclick="ludoSelectPiece('blue', 2)">2</div>
<div class="ludo-piece-in-home ludo-blue-piece-home" onclick="ludoSelectPiece('blue', 3)">3</div>
<div class="ludo-piece-in-home ludo-blue-piece-home" onclick="ludoSelectPiece('blue', 4)">4</div>
</div>
<div class="ludo-piece-label ludo-blue-label">مهرههای آبی</div>
<div class="ludo-dice-container">
<div class="ludo-dice-box">
<div class="ludo-dice ludo-blue-dice" id="ludoBlueDice" onclick="ludoRollDice('blue')">🎲</div>
<div class="ludo-dice-label ludo-dice-blue-label">تاس آبی</div>
</div>
</div>
<!-- ===== دکمههای آبی: هکر (بالا) + ذخیره (پایین) ===== -->
<div class="ludo-save-container">
<!-- ردیف اول: دکمه هکر -->
<div class="ludo-save-row">
<button class="ludo-hacker-btn disabled" id="ludoBlueHackerBtn" onclick="ludoUseHacker('blue')">
💻 هکر
</button>
</div>
<!-- ردیف دوم: دکمه ذخیره -->
<div class="ludo-save-row">
<button class="ludo-save-btn ludo-save-btn-blue disabled" id="ludoBlueSaveBtn" onclick="ludoHandleSave('blue')">
ذخیره: 0
</button>
</div>
<!-- ردیف سوم: فیلدهای هکر -->
<div class="ludo-save-row" id="ludoBlueHackerFieldsContainer" style="display: none;">
<div class="ludo-hacker-fields">
<input type="text" class="ludo-hacker-field" id="ludoBlueHackerField1" placeholder="تاس" disabled oninput="ludoValidateHackerField('blue')" maxlength="2">
<input type="text" class="ludo-hacker-field" id="ludoBlueHackerField2" placeholder="مهره" disabled oninput="ludoValidateHackerField('blue')" maxlength="1">
<button class="ludo-hacker-confirm-btn" id="ludoBlueHackerConfirmBtn" disabled onclick="ludoConfirmHacker('blue')">✔</button>
<span class="ludo-hacker-counter" id="ludoBlueHackerCounter">4</span>
</div>
</div>
</div>
</div>
<!-- ===== مودالها ===== -->
<div class="ludo-golden-dice-modal" id="ludoGoldenDiceModal">
<div class="ludo-golden-dice-content">
<div class="ludo-golden-title">🎲 تاس طلایی شانس 🎲</div>
<div class="ludo-golden-subtitle">روی تاس کلیک کنید تا شانس خود را امتحان کنید!</div>
<div class="ludo-golden-dice-container">
<div class="ludo-dice ludo-golden-dice" id="ludoGoldenDice" onclick="ludoRollGoldenDice()">🎲</div>
</div>
<div style="color: white; margin-top: 20px; font-size: 16px; background: rgba(0,0,0,0.5); padding: 10px; border-radius: 10px;">
⏱️ عدد تاس به مدت 3 ثانیه نمایش داده میشود
</div>
</div>
</div>
<div class="ludo-deal-modal" id="ludoDealModal">
<div class="ludo-deal-content">
<div class="ludo-deal-title">💰 صفحه معامله 💰</div>
<div class="ludo-deal-split">
<div class="ludo-deal-side ludo-deal-red-side" id="ludoDealRedSide">
<div class="ludo-deal-side-header ludo-deal-red-header">تیم قرمز انتخاب میکند (برای تیم آبی)</div>
<div class="ludo-deal-option" data-side="red" data-option="9" data-target="blue" onclick="selectDealOption('red', 9)">
<div class="ludo-deal-option-title"><span>🎲 گزینه ۹: تیم آبی X راند تاس بندازد (عدد ۱ تا ۱۰)</span></div>
<div class="ludo-deal-custom-input" id="red-deal-custom-9">
<input type="number" id="red-deal-input-9" min="1" max="10" placeholder="" onchange="updateDealCustomValue('red', 9)" oninput="updateDealCustomValue('red', 9)" inputmode="numeric">
<span class="range-label">راند</span>
</div>
</div>
<div class="ludo-deal-option" data-side="red" data-option="10" data-target="blue" onclick="selectDealOption('red', 10)">
<div class="ludo-deal-option-title"><span>🛡️ گزینه ۱۰: سپر محافظ X راند برای مهرههای آبی (عدد ۱ تا ۱۵)</span></div>
<div class="ludo-deal-piece-selector" id="red-deal-pieces-10" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('red', 10, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('red', 10, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('red', 10, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('red', 10, 4)">4</div>
</div>
<div class="ludo-deal-custom-input" id="red-deal-custom-10">
<input type="number" id="red-deal-input-10" min="1" max="15" placeholder="" onchange="updateDealCustomValue('red', 10)" oninput="updateDealCustomValue('red', 10)" inputmode="numeric">
<span class="range-label">راند</span>
</div>
</div>
<div class="ludo-deal-option" data-side="red" data-option="4" data-target="blue" onclick="selectDealOption('red', 4)">
<div class="ludo-deal-option-title"><span>💀 گزینه ۴: حذف مهرههای آبی (چند مهره)</span></div>
<div class="ludo-deal-piece-selector" id="red-deal-pieces-4" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('red', 4, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('red', 4, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('red', 4, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('red', 4, 4)">4</div>
</div>
</div>
<div class="ludo-deal-option" data-side="red" data-option="6" data-target="blue" onclick="selectDealOption('red', 6)">
<div class="ludo-deal-option-title"><span>🏠 گزینه ۶: آوردن مهرههای آبی به داخل بازی (چند مهره)</span></div>
<div class="ludo-deal-piece-selector" id="red-deal-pieces-6" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('red', 6, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('red', 6, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('red', 6, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-blue-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('red', 6, 4)">4</div>
</div>
</div>
</div>
<div class="ludo-deal-side ludo-deal-blue-side" id="ludoDealBlueSide">
<div class="ludo-deal-side-header ludo-deal-blue-header">تیم آبی انتخاب میکند (برای تیم قرمز)</div>
<div class="ludo-deal-option" data-side="blue" data-option="9" data-target="red" onclick="selectDealOption('blue', 9)">
<div class="ludo-deal-option-title"><span>🎲 گزینه ۹: تیم قرمز X راند تاس بندازد (عدد ۱ تا ۱۰)</span></div>
<div class="ludo-deal-custom-input" id="blue-deal-custom-9">
<input type="number" id="blue-deal-input-9" min="1" max="10" placeholder="" onchange="updateDealCustomValue('blue', 9)" oninput="updateDealCustomValue('blue', 9)" inputmode="numeric">
<span class="range-label">راند</span>
</div>
</div>
<div class="ludo-deal-option" data-side="blue" data-option="10" data-target="red" onclick="selectDealOption('blue', 10)">
<div class="ludo-deal-option-title"><span>🛡️ گزینه ۱۰: سپر محافظ X راند برای مهرههای قرمز (عدد ۱ تا ۱۵)</span></div>
<div class="ludo-deal-piece-selector" id="blue-deal-pieces-10" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('blue', 10, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('blue', 10, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('blue', 10, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('blue', 10, 4)">4</div>
</div>
<div class="ludo-deal-custom-input" id="blue-deal-custom-10">
<input type="number" id="blue-deal-input-10" min="1" max="15" placeholder="" onchange="updateDealCustomValue('blue', 10)" oninput="updateDealCustomValue('blue', 10)" inputmode="numeric">
<span class="range-label">راند</span>
</div>
</div>
<div class="ludo-deal-option" data-side="blue" data-option="4" data-target="red" onclick="selectDealOption('blue', 4)">
<div class="ludo-deal-option-title"><span>💀 گزینه ۴: حذف مهرههای قرمز (چند مهره)</span></div>
<div class="ludo-deal-piece-selector" id="blue-deal-pieces-4" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('blue', 4, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('blue', 4, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('blue', 4, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('blue', 4, 4)">4</div>
</div>
</div>
<div class="ludo-deal-option" data-side="blue" data-option="6" data-target="red" onclick="selectDealOption('blue', 6)">
<div class="ludo-deal-option-title"><span>🏠 گزینه ۶: آوردن مهرههای قرمز به داخل بازی (چند مهره)</span></div>
<div class="ludo-deal-piece-selector" id="blue-deal-pieces-6" style="display: none;">
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="1" onclick="event.stopPropagation(); selectDealPiece('blue', 6, 1)">1</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="2" onclick="event.stopPropagation(); selectDealPiece('blue', 6, 2)">2</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="3" onclick="event.stopPropagation(); selectDealPiece('blue', 6, 3)">3</div>
<div class="ludo-deal-piece-btn ludo-deal-red-piece" data-piece="4" onclick="event.stopPropagation(); selectDealPiece('blue', 6, 4)">4</div>
</div>
</div>
</div>
</div>
<div class="ludo-deal-buttons">
<button class="ludo-deal-btn ludo-deal-execute-btn" id="ludoDealExecuteBtn" onclick="executeDeal()" disabled>⚡ انجام معامله ⚡</button>
<button class="ludo-deal-btn ludo-deal-cancel-btn" onclick="cancelDeal()">❌ لغو معامله</button>
</div>
</div>
</div>
<div class="explosion-modal" id="explosionModal">
<div class="explosion-content">
<div class="explosion-title">💥 انفجار اتمی 💥</div>
<div class="explosion-warning">⚠️ آیا از انفجار مطمئن هستید؟ ⚠️<br>ممکن است مهره خودتان هم نابود شود!</div>
<div class="explosion-buttons">
<button class="explosion-btn explosion-confirm" onclick="confirmExplosion()">🔥 ادامه انفجار 🔥</button>
<button class="explosion-btn explosion-cancel" onclick="cancelExplosion()">✅ لغو</button>
</div>
</div>
</div>
<div class="rainbow-modal" id="rainbowModal">
<div class="rainbow-content">
<div class="rainbow-title">🌈 رنگینکمان هیجان انگیز 🌈</div>
<div class="rainbow-warning">⚠️ آیا از چرخش هیجانی مطمئن هستید؟ ⚠️<br>مهره خودتان هم چرخش میخورد!</div>
<div class="rainbow-buttons">
<button class="rainbow-btn rainbow-continue" onclick="confirmRainbow()">🌈 ادامه چرخش 🌈</button>
<button class="rainbow-btn rainbow-cancel" onclick="cancelRainbow()">✅ لغو</button>
</div>
</div>
</div>
<div class="explosion-animation-container" id="explosionAnimationContainer"></div>
<div class="rainbow-animation-container" id="rainbowAnimationContainer"></div>
<div class="thunder-overlay" id="thunderOverlay"></div>
<div class="simulation-image-overlay" id="simulationImageOverlay">
<div class="simulation-image-box" id="simulationImageBox">
<img id="simulationImageDisplay" src="" alt="شبیهسازی" style="width:100%; height:100%; object-fit:contain; border-radius:20px;">
</div>
</div>
<div class="simulation-animation-container" id="simulationAnimationContainer"></div>
<div class="hacker-animation-container" id="hackerAnimationContainer"></div>
<div class="hacker-challenge-modal" id="hackerChallengeModal">
<div class="hacker-challenge-content">
<div class="hacker-challenge-title">💻 چالش هکری 💻</div>
<div class="hacker-number-display" id="hackerNumberDisplay">
<span id="hackerNumberText">1234567890</span>
<span class="hacker-timer" id="hackerTimer">20</span>
</div>
<div class="hacker-input-display" id="hackerInputDisplay"></div>
<div class="hacker-buttons-grid" id="hackerButtonsGrid"></div>
<div class="hacker-result-message" id="hackerResultMessage"></div>
</div>
</div>
<div class="ludo-end-game-buttons" id="ludoEndGameButtons" style="display: none; grid-column: 1 / -1;">
<button class="ludo-return-btn" onclick="returnToMainMenu()">🏠 بازگشت به منوی اصلی</button>
</div>
</div>
</div>
<!-- ===== مودال سوالات ===== -->
<div class="ludo-question-modal" id="ludoQuestionModal">
<div class="ludo-question-content">
<div class="ludo-question-level" id="ludoQuestionLevel"></div>
<div class="ludo-question-header">
<div class="ludo-question-title" id="ludoQuestionTitle">سوال اطلاعات عمومی</div>
<div class="ludo-question-info">
<div class="ludo-question-count" id="ludoQuestionCount">سوال 1 از 150</div>
<div class="ludo-timer" id="ludoQuestionTimer">20</div>
</div>
</div>
<div class="ludo-question-formula" id="ludoQuestionFormula">سوال چیست؟</div>
<div class="ludo-question-instruction" id="ludoQuestionInstruction">گزینه صحیح را انتخاب کنید:</div>
<div class="ludo-options-container" id="ludoOptionsContainer"></div>
<div class="ludo-result-message" id="ludoResultMessage"></div>
</div>
</div>
<div class="ludo-message-box" id="ludoMessageBox"></div>
</div>
<!-- ===== اوورلی روح ===== -->
<div class="ghost-jumpscare-overlay" id="ghostJumpscareOverlay">
<img class="ghost-jumpscare-image" id="ghostJumpscareImage" src="https://cdn.imgurl.ir/uploads/v43255_nody-----1624648639.png" alt="روح">
</div>
<!-- ===== صداها ===== -->
<audio id="ludoDiceSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/j133750_rpg-dice-rolling-95182_1.mp3" type="audio/mpeg">
</audio>
<audio id="ludoBackgroundSound" preload="auto" loop>
<source src="https://cdn.imgurl.ir/uploads/m803020_aleftab_school_8_1.mp3" type="audio/mpeg">
</audio>
<audio id="explosionSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/g323421_big_exosion_sfx_1.mp3" type="audio/mpeg">
</audio>
<audio id="rainbowMainSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/v65603_rainbow-sound_4.mp3" type="audio/mpeg">
</audio>
<audio id="rainbowTentacleSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/v476556_rainbow-sound_2.mp3" type="audio/mpeg">
</audio>
<audio id="questionSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/p509327_Question_Sound_Effect.mp3" type="audio/mpeg">
</audio>
<audio id="dealSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/t439700_Cash_Register_Kaching_-_Sound_Effect.mp3" type="audio/mpeg">
</audio>
<audio id="dangerSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/b464_Game-Over-Sound-Effect-2.mp3" type="audio/mpeg">
</audio>
<audio id="goldenDiceSpinSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/l82215_Prize_Wheel_Spin.mp3" type="audio/mpeg">
</audio>
<audio id="jailDoorSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/d838479_metal_jail_door.mp3" type="audio/mpeg">
</audio>
<audio id="ghostJumpscareSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/i84179_1641236173_7f01f48f2b8a43a.mp3" type="audio/mpeg">
</audio>
<audio id="ghostAppearSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/p243135_1641235199_7a17db255f4f2f9.mp3" type="audio/mpeg">
</audio>
<audio id="diceSixSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/k351200_alpha_6a3264b54726a7.05453572.wav" type="audio/wav">
</audio>
<audio id="diceMinusTwoSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/y030641_alpha_6a326493f029b3.97466443.wav" type="audio/wav">
</audio>
<audio id="thunderSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/l0933_trimmed_audio_1781774533064.mp3" type="audio/mpeg">
</audio>
<audio id="simulationSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/d820783_Loading_sfx_2.mp3" type="audio/mpeg">
</audio>
<audio id="hackerSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/g556264_VideoCutter_363e8315f6cb036087a2cdbec0d4d36156750741-480p_.mp3" type="audio/mpeg">
</audio>
<audio id="hackerTypingSound" preload="auto">
<source src="https://cdn.imgurl.ir/uploads/h95966_Keyboard_Typing_Sound___Free_Sound_Effects___Home_and_Office_Sounds.mp3" type="audio/mpeg">
</audio>
<script>
// ==============================
// ===== STATE =====
// ==============================
let ludoGameState = {
currentTurn: 'blue',
diceRolled: false,
currentDiceValue: 0,
extraTurn: false,
selectedPiece: null,
backgroundSoundEnabled: false,
inQuestionMode: false,
questionTimer: null,
timeLeft: 20,
diceLocked: false,
isMovingPiece: false,
pendingQuestionMove: null,
goldenDiceActive: false,
goldenDiceMoveInfo: null,
penaltyQueue: [],
currentPenalty: null,
inDealMode: false,
dealMoveInfo: null,
selectedDealOptions: { red: null, blue: null },
selectedDealPieces: { red: { 4: [], 6: [], 10: [] }, blue: { 4: [], 6: [], 10: [] } },
dealCustomValues: { red: { 9: null, 10: null }, blue: { 9: null, 10: null } },
shieldEffects: [],
pendingRainbowMove: null,
rainbowCells: [],
rainbowActive: false,
ghostCell: null,
ghostActive: false,
ghostPieces: [],
ghostTimer: null,
pendingGhostMove: null,
bluePieces: [{ id: 1, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 2, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 3, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 4, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false }],
redPieces: [{ id: 1, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 2, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 3, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false },
{ id: 4, position: -1, isOnBoard: false, inWinnerCell: false, isInHome: true, jailRemainingSeconds: 0, jailTimerInterval: null, isSimulation: false }],
winnerCells: [{ number: 117, occupied: false, occupiedBy: null },
{ number: 118, occupied: false, occupiedBy: null },
{ number: 119, occupied: false, occupiedBy: null },
{ number: 120, occupied: false, occupiedBy: null }],
dangerCells: [],
questionCells: [],
luckCells: [],
explosionCells: [],
dealCells: [],
jailCells: [5, 113],
transferCells: { 7: 58, 76: 96 },
blueWinnerCount: 0,
redWinnerCount: 0,
boardSize: 120,
boardElements: [],
pieceElements: [],
generalQuestions: [],
usedQuestions: new Set(),
currentQuestion: null,
totalQuestions: 150,
answeredQuestions: 0,
gameEnded: false,
justCameFromQuestion: false,
isInPenaltyMode: false,
penaltyTurns: 0,
penaltyTeam: null,
isDrawGame: false,
pendingExplosionMove: null,
questionAnswered: false,
saveCount: { blue: 0, red: 0 },
saveLocked: { blue: true, red: true },
thunderUsed: { blue: false, red: false },
thunderActive: { blue: false, red: false },
thunderProcessing: { blue: false, red: false },
justRolledSix: { blue: false, red: false },
canSaveAfterRoll: { blue: false, red: false },
// متغیرهای شبیهسازی
simulationCells: [],
simulationLocked: true,
simulationRoundsLeft: 0,
simulationPieces: [],
simulationActive: false,
simulationUsed: false,
pendingSimulationMove: null,
simulationMoveInfo: null,
simulationRoundsElapsed: 0,
selectedSimulationPiece: null,
simulationCellLockedVisit: false,
// متغیرهای هکر
hackerDeviceCell: null,
hackerDeviceCollected: { blue: false, red: false },
hackerDeviceTeam: null,
hackerUsed: { blue: false, red: false },
hackerDone: false,
hackerFieldsVisible: { blue: false, red: false },
hackerField1Value: { blue: null, red: null },
hackerField2Value: { blue: null, red: null },
hackerField1RawValue: { blue: null, red: null },
hackerConfirmLocked: { blue: false, red: false },
hackerUsesLeft: { blue: 4, red: 4 },
hackerForcingActive: { blue: false, red: false },
hackerForcingTeam: null,
hackerForcedDiceValue: null,
hackerForcedPieceId: null,
hackerForcedTargetTeam: null,
hackerAnimating: false,
hackerChallengeActive: false,
hackerChallengeNumber: '',
hackerChallengeIndex: 0,
hackerChallengeTimer: null,
hackerChallengeTimeLeft: 20,
hackerChallengeLocked: false,
hackerChallengeButtons: [],
hackerChallengeShuffled: [],
hackerChallengeSoundPlaying: false,
hackerChallengeTypingSoundPlaying: false,
hackerForcingActiveCheck: false,
// برای حرکت خودکار مهره اجباری
autoMoveInProgress: false
};
// ==============================
// ===== صداها =====
// ==============================
function ludoPlayDiceSound() { const diceSound = document.getElementById('ludoDiceSound'); if(diceSound){ diceSound.volume = 0.5; diceSound.currentTime = 0; diceSound.play().catch(e=>console.log("خطا در پخش صدای تاس:", e)); } }
function ludoPlayExplosionSound() { const explosionSound = document.getElementById('explosionSound'); if(explosionSound){ explosionSound.volume = 1.0; explosionSound.currentTime = 0; explosionSound.play().catch(e=>console.log("خطا در پخش صدای انفجار:", e)); } }
function ludoPlayBackgroundSound() { if (ludoGameState.backgroundSoundEnabled) { const bgSound = document.getElementById('ludoBackgroundSound'); if(bgSound){ bgSound.volume = 0.3; bgSound.play().catch(e=>console.log("خطا در پخش صدای پسزمینه:", e)); } } }
function ludoPauseBackgroundSound() { const bgSound = document.getElementById('ludoBackgroundSound'); if(bgSound) bgSound.pause(); }
function ludoPlayQuestionSound() { const qSound = document.getElementById('questionSound'); if(qSound){ qSound.volume = 0.6; qSound.currentTime = 0; qSound.play().catch(e=>console.log("خطا در پخش صدای سوال:", e)); } }
function ludoPlayDealSound() { const dSound = document.getElementById('dealSound'); if(dSound){ dSound.volume = 0.7; dSound.currentTime = 0; dSound.play().catch(e=>console.log("خطا در پخش صدای معامله:", e)); } }
function ludoPlayDangerSound() { const danSound = document.getElementById('dangerSound'); if(danSound){ danSound.volume = 0.8; danSound.currentTime = 0; danSound.play().catch(e=>console.log("خطا در پخش صدای حذف:", e)); } }
function ludoPlayGoldenDiceSpinSound() { const spinSound = document.getElementById('goldenDiceSpinSound'); if(spinSound){ spinSound.volume = 0.6; spinSound.currentTime = 0; spinSound.play().catch(e=>console.log("خطا در پخش صدای چرخش تاس طلایی:", e)); } }
function ludoPlayJailSound() { const jailSound = document.getElementById('jailDoorSound'); if(jailSound){ jailSound.volume = 0.8; jailSound.currentTime = 0; jailSound.play().catch(e=>console.log("خطا در پخش صدای زندان:", e)); } }
function ludoPlayDiceSixSound() { const sound = document.getElementById('diceSixSound'); if(sound){ sound.volume = 0.8; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای ۶:", e)); } }
function ludoPlayDiceMinusTwoSound() { const sound = document.getElementById('diceMinusTwoSound'); if(sound){ sound.volume = 0.8; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای منفی ۲:", e)); } }
function ludoPlayGhostJumpscareSound() { const sound = document.getElementById('ghostJumpscareSound'); if(sound){ sound.volume = 1.0; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای جامپ اسکر روح:", e)); } }
function ludoPlayGhostAppearSound() { const sound = document.getElementById('ghostAppearSound'); if(sound){ sound.volume = 0.8; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای ظهور روح:", e)); } }
function ludoPlayThunderSound() { const sound = document.getElementById('thunderSound'); if(sound){ sound.volume = 1.0; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای رعد و برق:", e)); } }
function ludoPlaySimulationSound() { const sound = document.getElementById('simulationSound'); if(sound){ sound.volume = 0.8; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای شبیهسازی:", e)); } }
function ludoPlayHackerSound() { const sound = document.getElementById('hackerSound'); if(sound){ sound.volume = 0.8; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای هکر:", e)); } }
function ludoStopHackerSound() { const sound = document.getElementById('hackerSound'); if(sound){ sound.pause(); sound.currentTime = 0; } }
function ludoPlayHackerTypingSound() { const sound = document.getElementById('hackerTypingSound'); if(sound){ sound.volume = 0.5; sound.loop = true; sound.currentTime = 0; sound.play().catch(e=>console.log("خطا در پخش صدای تایپ هکر:", e)); } }
function ludoStopHackerTypingSound() { const sound = document.getElementById('hackerTypingSound'); if(sound){ sound.pause(); sound.currentTime = 0; } }
function toggleLudoBackgroundSound() {
ludoGameState.backgroundSoundEnabled = !ludoGameState.backgroundSoundEnabled;
const bgSoundIcon = document.getElementById('ludoBgSoundIcon');
bgSoundIcon.textContent = ludoGameState.backgroundSoundEnabled ? '🎵' : '🔇';
if (ludoGameState.backgroundSoundEnabled) { ludoPlayBackgroundSound(); ludoShowMessage('🎵 صدای بازی فعال شد', 'info'); }
else { ludoPauseBackgroundSound(); ludoShowMessage('🔇 صدای بازی غیرفعال شد', 'info'); }
}
// ==============================
// ===== منو و راهنما =====
// ==============================
function showInstructionsPage() {
document.getElementById('instructionsPage').classList.add('active');
document.getElementById('instructionsPage').style.display = 'flex';
}
function closeInstructionsPage() {
document.getElementById('instructionsPage').classList.remove('active');
document.getElementById('instructionsPage').style.display = 'none';
}
// ==============================
// ===== سوالات =====
// ==============================
const generalKnowledgeQuestions = [
{ question: "پرچم کدام کشور به ترتیب سه رنگ سبز، سفید و نارنجی است؟", options: ["ایرلند", "ایتالیا", "ساحل عاج", "هلند"], correct: 0 },
{ question: "گوشی هوشمند اکسپریا ساخت کدام کشور است؟", options: ["نوکیا", "سامسونگ", "موتورولا", "سونی"], correct: 3 },
{ question: "دروازه براندنبورگ در کدام شهر قرار دارد؟", options: ["وین", "زوریخ", "برلین", "ونیز"], correct: 2 },
{ question: "کدام یک از موارد زیر میوه نیست؟", options: ["ریواس", "گوجه فرنگی", "آووکادو", "خیار"], correct: 0 },
{ question: "آرنولد شوارتزنگر با یکی از اعضای کدام خانواده سیاسی مشهور ایالات متحده ازدواج کرده بود؟", options: ["کندیها", "بوشها", "راکفلرها", "اوباماها"], correct: 0 },
{ question: "اولین مورد ثبت شده آنفولانزای اسپانیایی کجا بود؟", options: ["یونان", "ایالات متحده آمریکا", "اسپانیا", "مکزیک"], correct: 1 },
{ question: "قوی ترین ماهیچه بدن انسان کدام است؟", options: ["بازو", "قلب", "گلوت", "فک"], correct: 3 },
{ question: "کدام یک از زبانهای زیر طولانیترین الفبا را دارد؟", options: ["یونانی", "هندی", "روسی", "عربی"], correct: 2 },
{ question: "کدام ماموریت آپولو بود که برای اولین بار در تاریخ بشر، انسان را با موفقیت روی ماه قرار داد؟", options: ["آپولو ۱۲", "آپولو ۱۳", "آپولو ۱۰", "آپولو ۱۱"], correct: 3 },
{ question: "رایجترین رنگ دستمال توالت در فرانسه چه رنگی است؟", options: ["صورتی", "آبی", "سفید", "زرد"], correct: 3 },
{ question: "قدیمیترین آدامس دنیا چند ساله است؟", options: ["۱۰۰ سال", "۶۰۰ سال", "۵۷۰۰ سال", "۶۹۰۰ سال"], correct: 2 },
{ question: "جعبه سیاه معروف هواپیما چه رنگی است؟", options: ["آبی", "مشکی", "سفید", "نارنجی"], correct: 3 },
{ question: "آیفون برای اولین بار در چه سالی عرضه شد؟", options: ["۲۰۰۷", "۲۰۰۸", "۲۰۰۹", "۲۰۱۰"], correct: 0 },
{ question: "جغد سبز آیکون (لوگوی) کدام برنامه است؟", options: ["اسپاتیفای", "دولینگو", "تیندر", "ساندکلاود"], correct: 1 },
{ question: "تابلوی مونالیزا چند بار دزدیده شده است؟", options: ["یک بار", "سه بار", "پنج بار", "هفت بار"], correct: 0 },
{ question: "در روم باستان چند روز در هفته وجود داشت؟", options: ["پنج روز", "شش روز", "هفت روز", "هشت روز"], correct: 3 },
{ question: "نام اصلی شهر نیویورک چه بود؟", options: ["نیو لیورپول", "نیو آمستردام", "نیوزلند", "نیوبروکس"], correct: 1 },
{ question: "چند رئیس جمهور آمریکا در دوران ریاست جمهوری خود ترور شدهاند؟", options: ["سه", "چهار", "پنج", "شش"], correct: 1 },
{ question: "چه کسی شعر حماسی بهشت گمشده را سروده است؟", options: ["ویلیام شکسپیر", "مری شلی", "جان میلتون", "آندره ژید"], correct: 2 },
{ question: "کدام نویسنده با فروش دو میلیارد دلار کتاب پرفروشترین نویسنده زن تمام دوران است؟", options: ["آگاتا کریستی", "جی.کی. رولینگ", "مری شلی", "انید بلیتون"], correct: 0 },
{ question: "اولین میوهای که در ماه خورده شد چه بود؟", options: ["هلو", "سیب", "شلیل", "انگور"], correct: 0 },
{ question: "اولین بار پیتزا در کدام شهر ایتالیا درست شد؟", options: ["رم", "ونیز", "ناپل", "پالرمو"], correct: 2 },
{ question: "کدام دو ادویه بیشترین میزان صادرات را در جهان دارند؟", options: ["فلفل و خردل", "زنجبیل و دارچین", "نمک و پونه کوهی", "پونه کوهی و خردل"], correct: 1 },
{ question: "یک انسان بالغ چند استخوان دارد؟", options: ["۲۰۶", "۲۰۷", "۲۰۸", "۲۱۰"], correct: 0 },
{ question: "کدام یک از موارد زیر را یک فضانورد نمیتواند در فضا انجام دهد؟", options: ["خندیدن", "گریه کردن", "غذا خوردن", "کتاب خواندن"], correct: 1 },
{ question: "کدام سیاره ۱۴۵ قمر دارد؟", options: ["عطارد", "مریخ", "زحل", "زهره"], correct: 2 },
{ question: "کوسهها در بدن خود چند استخوان دارند؟", options: ["صفر", "۵۲", "۱۲۵", "۱۸۶"], correct: 0 },
{ question: "تاکنون چند انسان روی ماه راه رفتهاند؟", options: ["۱۸", "۱۶", "۱۴", "۱۲"], correct: 3 },
{ question: "بازی شطرنج در کدام کشور اختراع شد؟", options: ["چین", "یونان", "ایران", "هند"], correct: 3 },
{ question: "چند درصد سطح زمین را آب پوشانده است؟", options: ["۹۱ درصد", "۸۱ درصد", "۷۱ درصد", "۶۱ درصد"], correct: 2 },
{ question: "چه کسی فیلم «فهرست شیندلر» را کارگردانی کرد؟", options: ["استیون اسپیلبرگ", "مارتین اسکورسیزی", "کریستوفر نولان", "مایکل جکسون"], correct: 0 },
{ question: "کدام فیلم انیمیشن پرفروشترین فیلم تاریخ است؟", options: ["داستان اسباب بازی", "شیر شاه", "منجمد ۲", "آواتار"], correct: 1 },
{ question: "جنگ جهانی دوم در چه سالی پایان یافت؟", options: ["۱۹۴۳", "۱۹۴۴", "۱۹۴۵", "۱۹۴۶"], correct: 2 },
{ question: "گل ملی ژاپن چیست؟", options: ["شکوفه گیلاس", "رز", "لیلی", "ارکیده"], correct: 0 },
{ question: "پایتخت برزیل کدام شهر است؟", options: ["ریودژانریو", "سائوپائولو", "بونوس آیرس", "برازیلیا"], correct: 3 },
{ question: "کدام شهر ایتالیا به \"شهر کانالها\" معروف است؟", options: ["رم", "ونیز", "ناپل", "میلان"], correct: 1 },
{ question: "کدام سیارهی منظومه شمسی به \"سیارهی آبی\" معروف است؟", options: ["مریخ", "اورانوس", "نپتون", "زمین"], correct: 3 },
{ question: "چه کسی نقش تونی استارک را در دنیای سینمایی مارول بازی کرد؟", options: ["کریس همسورث", "رابرت داونی جونیور", "کریس ایوانز", "مارک روفالو"], correct: 1 },
{ question: "در فیلم \"فارست گامپ\"، مادر گامپ زندگی را به چه چیزی تشبیه کرد؟", options: ["یک جعبه شکلات", "یک پازل", "یک ترن هوایی", "یک سفر"], correct: 0 },
{ question: "اولین امپراتور شناخته شده چین که به خاطر ارتش سفالیاش معروف بود چه کسی بود؟", options: ["چنگیز خان", "امپراتور هان", "امپراتور وو", "کین شی هوانگ"], correct: 3 },
{ question: "دیوار برلین نماد پایان جنگ سرد در چه سالی فروریخت؟", options: ["۱۹۸۹", "۱۹۸۵", "۱۹۷۹", "۱۹۷۵"], correct: 0 },
{ question: "کدام دو کشور آمریکای جنوبی با برزیل مرز مشترک ندارند؟", options: ["آرژانتین و شیلی", "پرو و اکوادور", "ونزوئلا و کلمبیا", "اروگوئه و پاراگوئه"], correct: 2 },
{ question: "نام تونل فرضی که دو نقطه مجزا در فضازمان را به هم متصل میکند و امکان سفر سریعتر از نور را فراهم میکند چیست؟", options: ["گرداب زمان", "کرمچاله", "سیاهچاله", "جهش کوانتومی"], correct: 1 },
{ question: "کدام کشور به خاطر لالههایش معروف است؟", options: ["ایتالیا", "هلند", "ژاپن", "اسپانیا"], correct: 1 },
{ question: "فتومتر (Fathometer) برای اندازهگیری کدام مورد استفاده میشود؟", options: ["زلزله", "شدت صدا", "باران", "عمق اقیانوس"], correct: 3 },
{ question: "کدام کشور است که ۶ ماه روز و ۶ ماه شب دارد؟", options: ["ایسلند", "نروژ", "سوئد", "فنلاند"], correct: 1 },
{ question: "\"یک مردم، یک دولت، یک رهبر\" سیاست که بود؟", options: ["پوتین", "استالین", "هیتلر", "موسولینی"], correct: 2 },
{ question: "سردترین سیارهی منظومه شمسی کدام است؟", options: ["نپتون", "پلوتون", "اورانوس", "عطارد"], correct: 0 },
{ question: "انقلاب کبیر سوسیالیستی اکتبر در چه سالی رخ داد؟", options: ["۱۹۱۷", "۱۹۱۹", "۱۹۲۱", "۱۹۲۳"], correct: 0 },
{ question: "بزرگترین دریاچه جهان کدام است؟", options: ["خزر", "بایکال", "سوپریور", "انتاریو"], correct: 1 },
{ question: "رمان \"جنگ و صلح\" را چه کسی نوشت؟", options: ["آنتوان چخوف", "فئودور داسایفسکی", "ایوران تورگنیف", "لئو تولستوی"], correct: 3 },
{ question: "برای خاموش کردن آتش از چه گازی استفاده میشود؟", options: ["اکسیژن", "نیتروژن", "دی اکسید کربن", "هیدروژن"], correct: 2 },
{ question: "نماد ملی استرالیا کدام حیوان است؟", options: ["کانگورو", "کوالا", "تمساح", "عقاب"], correct: 0 },
{ question: "کدام یک از سیارات زیر در منظومهی شمسی غول گازی نیست؟", options: ["زحل", "مشتری", "مریخ", "اورانوس"], correct: 2 },
{ question: "گالیله به کدام شهرت دارد؟", options: ["توسعه تلسکوپ", "کشف چهار قمر مشتری", "کشف این که حرکت نوسانی آونگ منجر به اندازهگیری زمان ثابت میشود.", "هر سه گزینه"], correct: 3 },
{ question: "بزرگترین جزیرهی دنیا کدام است؟", options: ["ایسلند", "گرینلند", "هاوایی", "آندامان نیکوبار"], correct: 1 },
{ question: "غذای موردعلاقه کوآلاها چیست؟", options: ["بامبو", "اکالیپتوس", "آلوئه ورا", "موز"], correct: 1 },
{ question: "محبوبترین نان در میان مردم فرانسه چیست؟", options: ["نان باگت", "نان سفید", "نان تست", "سیاباتا"], correct: 0 },
{ question: "کدام یک از کشورهای زیر در آفریقا نیست؟", options: ["سودان", "الجزایر", "یمن", "مراکش"], correct: 2 },
{ question: "رمان \"گتسبی بزرگ\" را چه کسی نوشت؟", options: ["لئو تولستوی", "ارنست همینگوی", "استیون کینگ", "اف. اسکات فیتزجرالد"], correct: 3 },
{ question: "ثروتمندترین کشور دنیا کدام است؟", options: ["قطر", "روسیه", "امارات", "ایالات متحده آمریکا"], correct: 0 },
{ question: "کدام شهر بزرگترین تولیدکننده قهوه است؟", options: ["اسپانیا", "هند", "برزیل", "اتیوپی"], correct: 2 },
{ question: "چه زمانی بیشترین عضلات صورت شما درگیر میشوند؟", options: ["هنگام خواب", "هنگام اخم کردن", "هنگام خندیدن", "هنگام صحبت کردن"], correct: 1 },
{ question: "کتاب \"جنایات و مکافات\" را کدام نویسنده نوشتهاست؟", options: ["لئو تولستوی", "ایوان تورگنیف", "آنتوان چخوف", "فئودور داستایوفسکی"], correct: 3 },
{ question: "\"شهر بادها\" لقب کدام شهر است؟", options: ["شیکاگو", "سیاتل", "تگزاس", "واشنگتن"], correct: 0 },
{ question: "کدام حیوان نماد صلح و بی طرفی است؟", options: ["خرس قطبی", "درنای سفید", "شیر سفید", "ببر سفید"], correct: 1 },
{ question: "شورترین دریای روی زمین کدام دریا است؟", options: ["دریای سرخ", "دریای مدیترانه", "دریای مرده", "دریای سیاه"], correct: 2 },
{ question: "کدام عضو بدن انسان مسئول ترشح صفرا است؟", options: ["کبد", "کلیهها", "طحال", "معده"], correct: 0 },
{ question: "کدام سیاره در منظومه شمسی به عنوان \"ستاره صبح\" یا \"ستاره عصر\" شناخته میشود؟", options: ["مریخ", "زهره", "عطارد", "اورانوس"], correct: 1 },
{ question: "کدام اقیانوس بین آفریقا و استرالیا است؟", options: ["اقیانوس آرام", "اقیانوس اطلس", "قطب شمال", "اقیانوس هند"], correct: 3 },
{ question: "بیشتر اتمسفر مریخ را کدام عنصر شیمیایی تشکیل میدهد؟", options: ["کربن دی اکسید", "اکسیژن", "نیتروژن", "هیدروژن"], correct: 0 },
{ question: "از کدام عنصر شیمیایی برای سرد و منجمد کردن مواد غذایی استفاده میشود؟", options: ["سدیم", "هیدروژن", "نیتروژن", "اکسیژن"], correct: 2 },
{ question: "کدام کشور به اهرام و ابوالهول معروف است؟", options: ["هند", "چین", "مکزیک", "مصر"], correct: 3 },
{ question: "کدام دریا بین آسیا و آفریقا قرار دارد؟", options: ["خزر", "سرخ", "مدیترانه", "مرده"], correct: 1 },
{ question: "در ساخت شیشه از چه عنصر شیمیایی استفاده میشود؟", options: ["نقره", "سدیم", "سیلیکون", "اکسیژن"], correct: 2 },
{ question: "در تابلوی معروف ادوارد مونک \"جیغ\" کدام ساز به تصویر کشیده شده است؟", options: ["فلوت", "ویولونسل", "کلارینت", "پیانو"], correct: 1 },
{ question: "کدام سیاره منظومه شمسی به نام \"سیاره عشق\" شناخته میشود؟", options: ["زهره", "زمین", "عطارد", "زحل"], correct: 0 },
{ question: "برای پر کردن بالن و کشتی هوایی از کدام گاز استفاده میشود؟", options: ["هیدروژن", "اکسیژن", "هلیوم", "نئون"], correct: 2 },
{ question: "برای ایجاد رنگین کمان در تلویزیون و مانیتور کامپیوتر از چه عنصر شیمیایی استفاده میشود؟", options: ["نئون", "هلیوم", "اکسیژن", "هیدروژن"], correct: 0 },
{ question: "در کدام فصل بدن انسان نیاز به چربی بیشتر دارد؟", options: ["پاییز", "زمستان", "بهار", "تابستان"], correct: 1 },
{ question: "هر طرف زمین بازی بسکتبال چند بازیکن دارد؟", options: ["۴", "۵", "۶", "۷"], correct: 1 },
{ question: "جنگ صد ساله بین کدام کشورها رخ داد؟", options: ["فرانسه و انگلستان", "یونان و ایران", "آلمان و انگلستان", "آلمان و روسیه"], correct: 0 },
{ question: "نماد شجاعت در فرهنگ چین کدام حیوان است؟", options: ["اسب", "عقاب", "خرس", "اژدها"], correct: 3 },
{ question: "نماد چین کدام حیوان است؟", options: ["پاندا", "فیل", "ببر", "شیر"], correct: 0 },
{ question: "کدام ویتامین را به نام \"ویتامین آفتاب\" میشناسند؟", options: ["ویتامین A", "ویتامین B", "ویتامین C", "ویتامین D"], correct: 3 },
{ question: "چه رویدادی منجر به جنگ جهانی دوم شد؟", options: ["سقوط دیوار برلین", "حمله به پرل هاربر", "امضای معاهده ورسای", "تصرف کریمه توسط آلمان"], correct: 1 },
{ question: "نام طولانیترین رودخانه روسیه چیست؟", options: ["لنا", "ولگا", "نوا", "آمور"], correct: 0 },
{ question: "اولین رئیس جمهور آمریکا چه کسی بود؟", options: ["جورج واشنگتن", "جان آدامز", "توماس جفرسون", "جیمز مدیسون"], correct: 0 },
{ question: "زادگاه بازیهای المپیک کدام کشور بود؟", options: ["یونان", "رم", "مصر", "چین"], correct: 0 },
{ question: "کدام کانال دریاهای سرخ و مدیترانه را به هم متصل میکند؟", options: ["سوئز", "پاناما", "تونل گوتارد", "تنگه بسفر"], correct: 0 },
{ question: "برای مشاهده محتوا در واقعیت مجازی از چه وسیلهای استفاده میشود؟", options: ["تلفن هوشمند", "عینک سه بعدی", "هدست VR", "تبلت"], correct: 2 },
{ question: "اولین بمب اتمی در کدام شهر ژاپنی پرتاب شد؟", options: ["ناکازاکی", "فوکوشیما", "هیروشیما", "کاگوشیما"], correct: 2 },
{ question: "اولین فرودگاه ایران در کدام شهر ساخته شد؟", options: ["تهران", "مسجد سلیمان", "لار", "اصفهان"], correct: 1 },
{ question: "در زمان کدام پادشاه، افغانستان از ایران جدا شد؟", options: ["محمد علی شاه", "ناصرالدین شاه", "احمد شاه", "مظفرالدین شاه"], correct: 1 },
{ question: "کدام کشور خاورمیانهای بیابان ندارد؟", options: ["ایران", "کویت", "قطر", "لبنان"], correct: 3 },
{ question: "فدراسیون جهانی فیبا مربوط به کدام ورزش است؟", options: ["بوکس", "بسکتبال", "بیسبال", "کبدی"], correct: 1 },
{ question: "پرچم کدام کشور مستطیل شکل نیست؟", options: ["کامبوج", "اریتره", "مالزی", "نپال"], correct: 3 },
{ question: "کدام حیوان ناشنوا است؟", options: ["مار", "سگ", "روباه", "خفاش"], correct: 0 },
{ question: "کدام قسمت از چشم انسان هیچ خونی ندارد؟", options: ["پلک", "مردمک", "قرنیه", "شبکیه"], correct: 2 },
{ question: "زیر خز سفید رنگش، پوست خرس قطبی چه رنگی است؟", options: ["سفید", "سیاه سفید", "قهوهای", "مشکی"], correct: 3 },
{ question: "پایتخت ایران کدام است؟", options: ["اصفهان", "شیراز", "تهران", "مشهد"], correct: 2 },
{ question: "بزرگترین اقیانوس جهان کدام است؟", options: ["اقیانوس هند", "اقیانوس منجمد شمالی", "اقیانوس آرام", "اقیانوس اطلس"], correct: 2 },
{ question: "کدام یک از موارد زیر از عناصر جدول تناوبی است؟", options: ["آب", "اکسیژن", "نمک", "شکر"], correct: 1 },
{ question: "نویسنده کتاب 'شازده کوچولو' کیست؟", options: ["آنتوان دو سنت اگزوپری", "ویکتور هوگو", "چارلز دیکنز", "جبران خلیل جبران"], correct: 0 },
{ question: "بزرگترین سیاره منظومه شمسی کدام است؟", options: ["زمین", "مریخ", "زحل", "مشتری"], correct: 3 },
{ question: "کدام کشور دارای بیشترین جمعیت جهان است؟", options: ["هند", "آمریکا", "چین", "اندونزی"], correct: 2 },
{ question: "سلول خورشیدی چه نوع انرژی را تولید میکند؟", options: ["حرارتی", "الکتریکی", "مکانیکی", "شیمیایی"], correct: 1 },
{ question: "نقاشی معروف 'مونالیزا' اثر کدام هنرمند است؟", options: ["ون گوگ", "پابلو پیکاسو", "لئوناردو داوینچی", "میکل آنژ"], correct: 2 },
{ question: "طولانیترین رود جهان کدام است؟", options: ["آمازون", "نیل", "می سی سی پی", "یانگ تسه"], correct: 1 },
{ question: "کدام یک از موارد زیر یک عنصر شیمیایی نیست؟", options: ["طلا", "نقره", "برنج", "مس"], correct: 2 },
{ question: "کدام سیاره به سیاره سرخ معروف است؟", options: ["زهره", "مریخ", "مشتری", "زحل"], correct: 1 },
{ question: "مخترع تلفن چه کسی بود؟", options: ["توماس ادیسون", "الکساندر گراهام بل", "نیکولا تسلا", "آلبرت انیشتین"], correct: 1 },
{ question: "کدام کشور بیشترین جزایر را دارد؟", options: ["اندونزی", "سوئد", "نروژ", "کانادا"], correct: 1 },
{ question: "بلندترین ساختمان جهان کدام است؟", options: ["برج خلیفه", "برج شانگهای", "برج آزادی", "برج توکیو"], correct: 0 },
{ question: "کدام یک از موارد زیر یک سیاره کوتوله است؟", options: ["پلوتون", "مریخ", "زهره", "مشتری"], correct: 0 },
{ question: "کدام کشور به عنوان 'سرزمین آفتاب طلوع' معروف است؟", options: ["چین", "کره جنوبی", "ژاپن", "تایلند"], correct: 2 },
{ question: "کدام حیوان میتواند تا ۳۰ سال بدون غذا زنده بماند؟", options: ["شتر", "عنکبوت", "عقرب", "کرم"], correct: 2 }
];
function shuffleGeneralQuestions() {
for (let i = generalKnowledgeQuestions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[generalKnowledgeQuestions[i], generalKnowledgeQuestions[j]] = [generalKnowledgeQuestions[j], generalKnowledgeQuestions[i]];
}
}
shuffleGeneralQuestions();
function ludoGetRandomGeneralQuestion() {
if(ludoGameState.answeredQuestions >= ludoGameState.totalQuestions){
return null;
}
const availableQuestions = generalKnowledgeQuestions.filter((_, idx) => !ludoGameState.usedQuestions.has(idx));
if (availableQuestions.length === 0) {
shuffleGeneralQuestions();
ludoGameState.usedQuestions.clear();
if(generalKnowledgeQuestions.length > 0) return generalKnowledgeQuestions[0];
else return null;
}
const randomIndex = Math.floor(Math.random() * availableQuestions.length);
const originalIndex = generalKnowledgeQuestions.findIndex(q => q === availableQuestions[randomIndex]);
ludoGameState.usedQuestions.add(originalIndex);
ludoGameState.answeredQuestions++;
return availableQuestions[randomIndex];
}
// ==============================
// ===== توابع ذخیره و رعد و برق =====
// ==============================
function ludoUpdateSaveButtons() {
const blueBtn = document.getElementById('ludoBlueSaveBtn');
const redBtn = document.getElementById('ludoRedSaveBtn');
const isBlueTurn = ludoGameState.currentTurn === 'blue';
const isRedTurn = ludoGameState.currentTurn === 'red';
const hasPiecesOnBoard = ludoHasAnyPieceOnBoard();
const blueProcessing = ludoGameState.thunderProcessing.blue;
const redProcessing = ludoGameState.thunderProcessing.red;
if (ludoGameState.thunderUsed.blue) {
blueBtn.textContent = '⚡ رعد و برق شکن (استفاده شده)';
blueBtn.className = 'ludo-save-btn ludo-save-btn-blue disabled';
blueBtn.disabled = true;
} else if (ludoGameState.saveCount.blue >= 5) {
const isActive = isBlueTurn && hasPiecesOnBoard && !blueProcessing;
blueBtn.textContent = '⚡ رعد و برق شکن';
blueBtn.className = `ludo-save-btn ludo-thunder-btn ${isActive ? '' : 'disabled'}`;
blueBtn.disabled = !isActive;
ludoGameState.thunderActive.blue = true;
} else {
const isActive = isBlueTurn && !ludoGameState.saveLocked.blue && !blueProcessing;
blueBtn.textContent = `ذخیره: ${ludoGameState.saveCount.blue}`;
blueBtn.className = `ludo-save-btn ludo-save-btn-blue ${isActive ? '' : 'disabled'}`;
blueBtn.disabled = !isActive;
ludoGameState.thunderActive.blue = false;
}
if (ludoGameState.thunderUsed.red) {
redBtn.textContent = '⚡ رعد و برق شکن (استفاده شده)';
redBtn.className = 'ludo-save-btn ludo-save-btn-red disabled';
redBtn.disabled = true;
} else if (ludoGameState.saveCount.red >= 5) {
const isActive = isRedTurn && hasPiecesOnBoard && !redProcessing;
redBtn.textContent = '⚡ رعد و برق شکن';
redBtn.className = `ludo-save-btn ludo-thunder-btn ${isActive ? '' : 'disabled'}`;
redBtn.disabled = !isActive;
ludoGameState.thunderActive.red = true;
} else {
const isActive = isRedTurn && !ludoGameState.saveLocked.red && !redProcessing;
redBtn.textContent = `ذخیره: ${ludoGameState.saveCount.red}`;
redBtn.className = `ludo-save-btn ludo-save-btn-red ${isActive ? '' : 'disabled'}`;
redBtn.disabled = !isActive;
ludoGameState.thunderActive.red = false;
}
ludoUpdateHackerButtons();
ludoUpdateHackerFields();
}
function ludoHasAnyPieceOnBoard() {
const allPieces = [...ludoGameState.bluePieces, ...ludoGameState.redPieces, ...ludoGameState.simulationPieces];
return allPieces.some(p => p.isOnBoard);
}
function ludoRemovePieceCompletely(team, piece, userTeam) {
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (!pieceEl) {
ludoForceRemovePiece(team, piece);
return;
}
pieceEl.style.transition = 'all 1.5s cubic-bezier(0.4, 0, 0.2, 1)';
pieceEl.style.opacity = '0';
pieceEl.style.transform = 'scale(0.2) rotate(720deg)';
pieceEl.style.filter = 'brightness(0) drop-shadow(0 0 0px transparent)';
const shieldIndex = ludoGameState.shieldEffects.findIndex(s => s.team === team && s.pieceId === piece.id);
if (shieldIndex !== -1) {
ludoGameState.shieldEffects.splice(shieldIndex, 1);
const shieldEl = pieceEl.querySelector('.ludo-shield-effect');
if (shieldEl) shieldEl.remove();
const shieldTag = pieceEl.querySelector('.ludo-shield-tag');
if (shieldTag) shieldTag.remove();
}
clearJailTimer(piece);
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === team && w.occupiedBy.pieceId === piece.id);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (team === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
piece.inWinnerCell = false;
ludoUpdateWinnerCellsDisplay();
}
if (userTeam === 'blue') {
ludoGameState.thunderUsed.blue = true;
ludoGameState.thunderActive.blue = false;
ludoGameState.thunderProcessing.blue = false;
} else {
ludoGameState.thunderUsed.red = true;
ludoGameState.thunderActive.red = false;
ludoGameState.thunderProcessing.red = false;
}
setTimeout(() => {
if (pieceEl.parentNode) {
pieceEl.parentNode.removeChild(pieceEl);
}
ludoForceRemovePiece(team, piece);
ludoUpdateDisplay();
ludoUpdateSaveButtons();
ludoCheckWinner();
ludoShowMessage(`⚡ رعد و برق شکن مهره ${piece.id} تیم ${team === 'blue' ? 'آبی' : 'قرمز'} را نابود کرد!`, 'error');
}, 1500);
}
function ludoForceRemovePiece(team, piece) {
piece.position = -1;
piece.isOnBoard = false;
piece.isInHome = true;
piece.inWinnerCell = false;
piece.jailRemainingSeconds = 0;
clearJailTimer(piece);
ludoUpdateHomeDisplay(team, piece.id, true);
ludoGameState.pieceElements = ludoGameState.pieceElements.filter(p => !(p.team === team && p.pieceId === piece.id));
const element = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (element && element.parentNode) {
element.parentNode.removeChild(element);
}
}
function ludoHandleSave(team) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) {
ludoShowMessage('🎮 بازی تمام شده است!', 'warning');
return;
}
if (ludoGameState.currentTurn !== team) {
ludoShowMessage(`❌ الان نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} است!`, 'error');
return;
}
if (ludoGameState.inQuestionMode || ludoGameState.isMovingPiece || ludoGameState.inDealMode || ludoGameState.rainbowActive || ludoGameState.ghostActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) {
ludoShowMessage('⏳ در حال انجام عملیات دیگر...', 'warning');
return;
}
if (team === 'blue' && ludoGameState.thunderProcessing.blue) {
ludoShowMessage('⏳ لطفاً صبر کنید... رعد و برق شکن در حال پردازش است.', 'warning');
return;
}
if (team === 'red' && ludoGameState.thunderProcessing.red) {
ludoShowMessage('⏳ لطفاً صبر کنید... رعد و برق شکن در حال پردازش است.', 'warning');
return;
}
if (ludoGameState.thunderActive[team] && !ludoGameState.thunderUsed[team]) {
if (!ludoHasAnyPieceOnBoard()) {
ludoShowMessage('⚡ هیچ مهرهای در تخته نیست! نمیتوان از رعد و برق شکن استفاده کرد.', 'error');
return;
}
if (team === 'blue') {
ludoGameState.thunderProcessing.blue = true;
} else {
ludoGameState.thunderProcessing.red = true;
}
ludoUpdateSaveButtons();
const allPiecesOnBoard = [];
ludoGameState.bluePieces.forEach(piece => {
if (piece.isOnBoard) {
allPiecesOnBoard.push({ piece: piece, team: 'blue' });
}
});
ludoGameState.redPieces.forEach(piece => {
if (piece.isOnBoard) {
allPiecesOnBoard.push({ piece: piece, team: 'red' });
}
});
if (allPiecesOnBoard.length === 0) {
if (team === 'blue') {
ludoGameState.thunderProcessing.blue = false;
} else {
ludoGameState.thunderProcessing.red = false;
}
ludoUpdateSaveButtons();
ludoShowMessage('⚡ هیچ مهرهای در تخته نیست!', 'error');
return;
}
const randomIndex = Math.floor(Math.random() * allPiecesOnBoard.length);
const selected = allPiecesOnBoard[randomIndex];
const selectedTeam = selected.team;
const selectedPiece = selected.piece;
ludoShowThunderAnimation(selectedTeam, selectedPiece, team);
return;
}
const isLocked = team === 'blue' ? ludoGameState.saveLocked.blue : ludoGameState.saveLocked.red;
if (isLocked) {
ludoShowMessage(`❌ گزینه ذخیره قفل است! برای فعال شدن باید تاس ۶ بیاورید.`, 'error');
return;
}
const currentCount = team === 'blue' ? ludoGameState.saveCount.blue : ludoGameState.saveCount.red;
if (currentCount >= 5) {
ludoShowMessage('⚠️ ذخیره به ۵ رسیده! باید از رعد و برق شکن استفاده کنید.', 'warning');
return;
}
if (team === 'blue') {
ludoGameState.saveCount.blue++;
} else {
ludoGameState.saveCount.red++;
}
ludoShowMessage(`✅ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} یک واحد ذخیره کرد! (${team === 'blue' ? ludoGameState.saveCount.blue : ludoGameState.saveCount.red})`, 'success');
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
}
ludoUpdateSaveButtons();
const newCount = team === 'blue' ? ludoGameState.saveCount.blue : ludoGameState.saveCount.red;
if (newCount >= 5) {
ludoShowMessage(`⚡ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} به ۵ ذخیره رسید! گزینه رعد و برق شکن فعال شد.`, 'success');
ludoUpdateSaveButtons();
}
ludoGameState.extraTurn = false;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
document.getElementById('ludoBlueDice').classList.add('disabled');
document.getElementById('ludoRedDice').classList.add('disabled');
setTimeout(() => {
ludoNextTurn();
}, 500);
}
function ludoShowThunderAnimation(targetTeam, targetPiece, userTeam) {
const pieceEl = document.querySelector(`.ludo-${targetTeam}-on-board[data-piece-id="${targetPiece.id}"]`);
if (!pieceEl) {
if (userTeam === 'blue') {
ludoGameState.thunderProcessing.blue = false;
} else {
ludoGameState.thunderProcessing.red = false;
}
ludoUpdateSaveButtons();
ludoShowMessage('⚠️ خطا در پیدا کردن مهره!', 'error');
return;
}
const board = document.getElementById('ludoBoard');
const boardRect = board.getBoundingClientRect();
const pieceRect = pieceEl.getBoundingClientRect();
const targetX = ((pieceRect.left + pieceRect.width/2) - boardRect.left) / boardRect.width * 100;
const targetY = ((pieceRect.top + pieceRect.height/2) - boardRect.top) / boardRect.height * 100;
ludoPlayThunderSound();
const overlay = document.getElementById('thunderOverlay');
overlay.innerHTML = '';
overlay.classList.add('active');
const flash = document.createElement('div');
flash.className = 'thunder-flash';
overlay.appendChild(flash);
setTimeout(() => {
const mainBolt = document.createElement('div');
mainBolt.className = 'thunder-bolt-large';
mainBolt.style.left = targetX + '%';
mainBolt.style.top = (targetY - 20) + '%';
mainBolt.style.transform = 'translateX(-50%) scaleY(1)';
overlay.appendChild(mainBolt);
setTimeout(() => { if (mainBolt.parentNode) mainBolt.remove(); }, 800);
}, 100);
setTimeout(() => {
for (let i = 0; i < 12; i++) {
setTimeout(() => {
const bolt = document.createElement('div');
bolt.className = 'thunder-bolt';
const angle = Math.random() * 360;
const length = 80 + Math.random() * 200;
const startX = targetX + (Math.random() - 0.5) * 40;
const startY = targetY + (Math.random() - 0.5) * 40;
bolt.style.left = startX + '%';
bolt.style.top = startY + '%';
bolt.style.transform = `rotate(${angle}deg)`;
bolt.style.height = length + 'px';
bolt.style.width = (4 + Math.random() * 10) + 'px';
overlay.appendChild(bolt);
setTimeout(() => { if (bolt.parentNode) bolt.remove(); }, 600);
}, i * 80);
}
}, 200);
setTimeout(() => {
for (let i = 0; i < 8; i++) {
setTimeout(() => {
const ring = document.createElement('div');
ring.className = 'thunder-ring';
ring.style.left = targetX + '%';
ring.style.top = targetY + '%';
ring.style.transform = 'translate(-50%, -50%)';
ring.style.width = (20 + i * 50) + 'px';
ring.style.height = (20 + i * 50) + 'px';
overlay.appendChild(ring);
setTimeout(() => { if (ring.parentNode) ring.remove(); }, 800);
}, i * 120);
}
}, 400);
setTimeout(() => {
const target = document.createElement('div');
target.className = 'thunder-target';
target.style.left = targetX + '%';
target.style.top = targetY + '%';
target.style.transform = 'translate(-50%, -50%)';
target.style.width = '100px';
target.style.height = '100px';
overlay.appendChild(target);
setTimeout(() => { if (target.parentNode) target.remove(); }, 1500);
}, 300);
setTimeout(() => {
for (let i = 0; i < 50; i++) {
const particle = document.createElement('div');
particle.className = 'thunder-particles';
const angle = Math.random() * 360;
const distance = 50 + Math.random() * 200;
const tx = Math.cos(angle * Math.PI / 180) * distance;
const ty = Math.sin(angle * Math.PI / 180) * distance;
particle.style.left = targetX + '%';
particle.style.top = targetY + '%';
particle.style.setProperty('--tx', tx + 'px');
particle.style.setProperty('--ty', ty + 'px');
const colors = ['#4FC3F7', '#2196F3', '#fff', '#0D47A1', '#29B6F6', '#64B5F6'];
particle.style.background = colors[Math.floor(Math.random() * colors.length)];
particle.style.width = (3 + Math.random() * 6) + 'px';
particle.style.height = (3 + Math.random() * 6) + 'px';
overlay.appendChild(particle);
setTimeout(() => { if (particle.parentNode) particle.remove(); }, 900);
}
}, 500);
setTimeout(() => {
const deleteEffect = document.createElement('div');
deleteEffect.className = 'thunder-delete-effect';
const rect = pieceEl.getBoundingClientRect();
deleteEffect.style.left = (rect.left + rect.width/2) + 'px';
deleteEffect.style.top = (rect.top + rect.height/2) + 'px';
deleteEffect.style.width = '80px';
deleteEffect.style.height = '80px';
deleteEffect.style.transform = 'translate(-50%, -50%)';
document.body.appendChild(deleteEffect);
pieceEl.style.transition = 'all 0.2s ease-in';
pieceEl.style.transform = 'scale(2)';
pieceEl.style.opacity = '0';
pieceEl.style.filter = 'brightness(3) drop-shadow(0 0 30px #4FC3F7)';
setTimeout(() => {
if (deleteEffect.parentNode) deleteEffect.remove();
}, 1000);
}, 600);
setTimeout(() => {
overlay.classList.remove('active');
overlay.innerHTML = '';
}, 3000);
setTimeout(() => {
ludoRemovePieceCompletely(targetTeam, targetPiece, userTeam);
}, 1500);
}
// ==============================
// ===== توابع هکر =====
// ==============================
function ludoUpdateHackerButtons() {
const blueBtn = document.getElementById('ludoBlueHackerBtn');
const redBtn = document.getElementById('ludoRedHackerBtn');
const isBlueTurn = ludoGameState.currentTurn === 'blue';
const isRedTurn = ludoGameState.currentTurn === 'red';
if (ludoGameState.hackerDone || ludoGameState.gameEnded || ludoGameState.isDrawGame) {
blueBtn.className = 'ludo-hacker-btn disabled';
blueBtn.disabled = true;
redBtn.className = 'ludo-hacker-btn disabled';
redBtn.disabled = true;
return;
}
// دکمه آبی
if (!ludoGameState.hackerDeviceCollected.blue && !ludoGameState.hackerDeviceCollected.red) {
blueBtn.className = 'ludo-hacker-btn disabled';
blueBtn.disabled = true;
} else if (ludoGameState.hackerDeviceCollected.blue) {
const isActive = isBlueTurn && !ludoGameState.hackerUsed.blue && !ludoGameState.hackerAnimating && !ludoGameState.hackerChallengeActive && !ludoGameState.inQuestionMode && !ludoGameState.isMovingPiece && !ludoGameState.inDealMode && !ludoGameState.rainbowActive && !ludoGameState.ghostActive && !ludoGameState.simulationActive && !ludoGameState.autoMoveInProgress;
blueBtn.className = `ludo-hacker-btn ${isActive ? '' : 'disabled'}`;
blueBtn.disabled = !isActive;
} else {
blueBtn.className = 'ludo-hacker-btn disabled';
blueBtn.disabled = true;
}
// دکمه قرمز
if (!ludoGameState.hackerDeviceCollected.red && !ludoGameState.hackerDeviceCollected.blue) {
redBtn.className = 'ludo-hacker-btn disabled';
redBtn.disabled = true;
} else if (ludoGameState.hackerDeviceCollected.red) {
const isActive = isRedTurn && !ludoGameState.hackerUsed.red && !ludoGameState.hackerAnimating && !ludoGameState.hackerChallengeActive && !ludoGameState.inQuestionMode && !ludoGameState.isMovingPiece && !ludoGameState.inDealMode && !ludoGameState.rainbowActive && !ludoGameState.ghostActive && !ludoGameState.simulationActive && !ludoGameState.autoMoveInProgress;
redBtn.className = `ludo-hacker-btn ${isActive ? '' : 'disabled'}`;
redBtn.disabled = !isActive;
} else {
redBtn.className = 'ludo-hacker-btn disabled';
redBtn.disabled = true;
}
}
function ludoUpdateHackerFields() {
const blueContainer = document.getElementById('ludoBlueHackerFieldsContainer');
const redContainer = document.getElementById('ludoRedHackerFieldsContainer');
const blueField1 = document.getElementById('ludoBlueHackerField1');
const blueField2 = document.getElementById('ludoBlueHackerField2');
const blueConfirm = document.getElementById('ludoBlueHackerConfirmBtn');
const blueCounter = document.getElementById('ludoBlueHackerCounter');
const redField1 = document.getElementById('ludoRedHackerField1');
const redField2 = document.getElementById('ludoRedHackerField2');
const redConfirm = document.getElementById('ludoRedHackerConfirmBtn');
const redCounter = document.getElementById('ludoRedHackerCounter');
const isBlueTurn = ludoGameState.currentTurn === 'blue';
const isRedTurn = ludoGameState.currentTurn === 'red';
// آبی
if (ludoGameState.hackerDone && ludoGameState.hackerFieldsVisible.blue && ludoGameState.hackerUsesLeft.blue > 0) {
blueContainer.style.display = 'flex';
// فقط قبل از تاس انداختن فعال باشه (یعنی وقتی diceRolled == false)
const isActive = isBlueTurn && !ludoGameState.hackerConfirmLocked.blue && !ludoGameState.inQuestionMode && !ludoGameState.isMovingPiece && !ludoGameState.inDealMode && !ludoGameState.rainbowActive && !ludoGameState.ghostActive && !ludoGameState.simulationActive && !ludoGameState.hackerAnimating && !ludoGameState.hackerChallengeActive && !ludoGameState.diceRolled && !ludoGameState.autoMoveInProgress;
blueField1.disabled = !isActive;
blueField2.disabled = !isActive;
// بررسی مهرههای قابل انتخاب
const targetTeam = 'red';
const targetPieces = ludoGameState.redPieces.filter(p => p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
const hasValidPieces = targetPieces.length > 0;
if (!hasValidPieces) {
blueField2.disabled = true;
blueField2.value = '';
ludoGameState.hackerField2Value.blue = null;
} else {
// اعتبارسنجی مقدار فعلی
const currentVal = parseInt(blueField2.value);
if (currentVal && !targetPieces.some(p => p.id === currentVal)) {
blueField2.value = '';
ludoGameState.hackerField2Value.blue = null;
}
}
// بررسی پر بودن هر دو فیلد برای فعال کردن دکمه تایید
const field1Val = blueField1.value.trim();
const field2Val = blueField2.value.trim();
const canConfirm = isActive && field1Val !== '' && field2Val !== '' && !blueField1.disabled && !blueField2.disabled && ludoGameState.hackerUsesLeft.blue > 0;
blueConfirm.disabled = !canConfirm;
blueCounter.textContent = ludoGameState.hackerUsesLeft.blue;
} else {
blueContainer.style.display = 'none';
}
// قرمز
if (ludoGameState.hackerDone && ludoGameState.hackerFieldsVisible.red && ludoGameState.hackerUsesLeft.red > 0) {
redContainer.style.display = 'flex';
const isActive = isRedTurn && !ludoGameState.hackerConfirmLocked.red && !ludoGameState.inQuestionMode && !ludoGameState.isMovingPiece && !ludoGameState.inDealMode && !ludoGameState.rainbowActive && !ludoGameState.ghostActive && !ludoGameState.simulationActive && !ludoGameState.hackerAnimating && !ludoGameState.hackerChallengeActive && !ludoGameState.diceRolled && !ludoGameState.autoMoveInProgress;
redField1.disabled = !isActive;
redField2.disabled = !isActive;
const targetTeam = 'blue';
const targetPieces = ludoGameState.bluePieces.filter(p => p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
const hasValidPieces = targetPieces.length > 0;
if (!hasValidPieces) {
redField2.disabled = true;
redField2.value = '';
ludoGameState.hackerField2Value.red = null;
} else {
const currentVal = parseInt(redField2.value);
if (currentVal && !targetPieces.some(p => p.id === currentVal)) {
redField2.value = '';
ludoGameState.hackerField2Value.red = null;
}
}
const field1Val = redField1.value.trim();
const field2Val = redField2.value.trim();
const canConfirm = isActive && field1Val !== '' && field2Val !== '' && !redField1.disabled && !redField2.disabled && ludoGameState.hackerUsesLeft.red > 0;
redConfirm.disabled = !canConfirm;
redCounter.textContent = ludoGameState.hackerUsesLeft.red;
} else {
redContainer.style.display = 'none';
}
}
function ludoValidateHackerField(team) {
const field1 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField1`);
const field2 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField2`);
// فیلد تاس - قبول 1, 2, 3, 4, 5, 1n, 2n
if (field1) {
let val = field1.value.trim().toLowerCase();
if (val !== '') {
// چک کردن 1n و 2n
if (val === '1n') {
field1.value = '1n';
ludoGameState.hackerField1Value[team] = -1;
ludoGameState.hackerField1RawValue[team] = '1n';
} else if (val === '2n') {
field1.value = '2n';
ludoGameState.hackerField1Value[team] = -2;
ludoGameState.hackerField1RawValue[team] = '2n';
} else {
let num = parseInt(val);
if (isNaN(num) || num < 1) {
field1.value = '1';
ludoGameState.hackerField1Value[team] = 1;
ludoGameState.hackerField1RawValue[team] = '1';
} else if (num > 5) {
field1.value = '5';
ludoGameState.hackerField1Value[team] = 5;
ludoGameState.hackerField1RawValue[team] = '5';
} else {
field1.value = num;
ludoGameState.hackerField1Value[team] = num;
ludoGameState.hackerField1RawValue[team] = String(num);
}
}
} else {
ludoGameState.hackerField1Value[team] = null;
ludoGameState.hackerField1RawValue[team] = null;
}
}
// فیلد مهره - فقط 1 تا 4 و فقط مهرههای داخل تخته
if (field2) {
let val = field2.value.trim();
if (val !== '') {
let num = parseInt(val);
const targetTeam = team === 'blue' ? 'red' : 'blue';
const targetPieces = targetTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const validPieces = targetPieces.filter(p => p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
const validIds = validPieces.map(p => p.id);
if (isNaN(num) || num < 1) {
field2.value = '1';
ludoGameState.hackerField2Value[team] = 1;
} else if (num > 4) {
field2.value = '4';
ludoGameState.hackerField2Value[team] = 4;
} else if (!validIds.includes(num)) {
// اگر مهره در تخته نیست، فیلد را پاک کن
field2.value = '';
ludoGameState.hackerField2Value[team] = null;
ludoShowMessage(`❌ مهره ${num} در تخته نیست یا در زندان/طلایی/شبیهسازی است!`, 'error');
} else {
field2.value = num;
ludoGameState.hackerField2Value[team] = num;
}
} else {
ludoGameState.hackerField2Value[team] = null;
}
}
// بروزرسانی دکمه تایید
ludoUpdateHackerFields();
}
function ludoUseHacker(team) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) {
ludoShowMessage('🎮 بازی تمام شده است!', 'warning');
return;
}
if (ludoGameState.currentTurn !== team) {
ludoShowMessage(`❌ الان نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} است!`, 'error');
return;
}
if (ludoGameState.hackerUsed[team] || ludoGameState.hackerDone) {
ludoShowMessage('❌ هکر قبلاً استفاده شده یا تمام شده!', 'error');
return;
}
if (ludoGameState.inQuestionMode || ludoGameState.isMovingPiece || ludoGameState.inDealMode || ludoGameState.rainbowActive || ludoGameState.ghostActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) {
ludoShowMessage('⏳ در حال انجام عملیات دیگر...', 'warning');
return;
}
// قبل از تاس انداختن باید باشه
if (ludoGameState.diceRolled) {
ludoShowMessage('❌ شما قبلاً تاس انداختهاید! باید قبل از تاس انداختن از هکر استفاده کنید.', 'error');
return;
}
if (team === 'blue' && !ludoGameState.hackerDeviceCollected.blue) {
ludoShowMessage('❌ تیم آبی آیتم هکینگ دیوایس را ندارد!', 'error');
return;
}
if (team === 'red' && !ludoGameState.hackerDeviceCollected.red) {
ludoShowMessage('❌ تیم قرمز آیتم هکینگ دیوایس را ندارد!', 'error');
return;
}
ludoGameState.hackerUsed[team] = true;
ludoGameState.hackerAnimating = true;
ludoShowMessage(`💻 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} شروع به هک کرد...`, 'info');
ludoPlayHackerSound();
ludoShowHackerAnimation(team);
}
function ludoShowHackerAnimation(team) {
const container = document.getElementById('hackerAnimationContainer');
container.innerHTML = '';
container.classList.add('active');
// پسزمینه ماتریکسی
const bg = document.createElement('div');
bg.className = 'hacker-animation-bg';
container.appendChild(bg);
// باران ماتریکسی
const chars = '01アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
for (let i = 0; i < 40; i++) {
const rain = document.createElement('div');
rain.className = 'hacker-matrix-rain';
rain.style.left = (Math.random() * 95) + '%';
rain.style.top = '-10%';
rain.style.fontSize = (12 + Math.random() * 20) + 'px';
rain.style.animationDuration = (1.5 + Math.random() * 2) + 's';
rain.style.animationDelay = (Math.random() * 1.5) + 's';
let text = '';
for (let j = 0; j < 10 + Math.random() * 15; j++) {
text += chars[Math.floor(Math.random() * chars.length)];
}
rain.textContent = text;
bg.appendChild(rain);
}
// کدهای ثابت
for (let i = 0; i < 25; i++) {
const code = document.createElement('div');
code.className = 'hacker-matrix-code';
code.style.left = (Math.random() * 95) + '%';
code.style.top = (Math.random() * 95) + '%';
code.style.fontSize = (10 + Math.random() * 16) + 'px';
code.style.animationDuration = (1.5 + Math.random() * 2) + 's';
code.style.animationDelay = (Math.random() * 2) + 's';
let text = '';
for (let j = 0; j < 4 + Math.random() * 7; j++) {
text += chars[Math.floor(Math.random() * chars.length)];
}
code.textContent = text;
bg.appendChild(code);
}
// خطوط فلش
for (let i = 0; i < 10; i++) {
const line = document.createElement('div');
line.className = 'hacker-flash-line';
line.style.left = (Math.random() * 95) + '%';
line.style.animationDuration = (1 + Math.random() * 1.5) + 's';
line.style.animationDelay = (Math.random() * 2) + 's';
bg.appendChild(line);
}
// حلقههای موجی
for (let i = 0; i < 8; i++) {
const ring = document.createElement('div');
ring.className = 'hacker-ring-wave';
ring.style.left = (20 + Math.random() * 60) + '%';
ring.style.top = (20 + Math.random() * 60) + '%';
ring.style.animationDuration = (1 + Math.random() * 1.5) + 's';
ring.style.animationDelay = (Math.random() * 2) + 's';
bg.appendChild(ring);
}
// جریان داده
for (let i = 0; i < 15; i++) {
const stream = document.createElement('div');
stream.className = 'hacker-data-stream';
stream.style.left = (Math.random() * 95) + '%';
stream.style.top = '-10%';
stream.style.animationDuration = (1 + Math.random() * 1.5) + 's';
stream.style.animationDelay = (Math.random() * 2) + 's';
stream.style.height = (40 + Math.random() * 80) + 'px';
bg.appendChild(stream);
}
// عکسها
const imagesContainer = document.createElement('div');
imagesContainer.className = 'hacker-animation-images';
container.appendChild(imagesContainer);
const imageUrls = [
'https://cdn.imgurl.ir/uploads/u081053_tech-savvy-hacker-stockcake.jpg',
'https://cdn.imgurl.ir/uploads/t79810_neon-hacker-infiltrates-stockcake.jpg',
'https://cdn.imgurl.ir/uploads/l146298_sacred-digital-hacker-stockcake.jpg',
'https://cdn.imgurl.ir/uploads/w82100_matrix-code-hacker-stockcake.jpg'
];
const imageElements = [];
imageUrls.forEach((url, index) => {
const img = document.createElement('img');
img.src = url;
img.className = 'hacker-animation-image';
img.style.zIndex = index + 1;
img.style.animationDelay = (index * 0.1) + 's';
imagesContainer.appendChild(img);
imageElements.push(img);
});
// نمایش عکسها به صورت ترتیبی
let currentImageIndex = 0;
let phase = 0; // 0 = هر کدام 2 ثانیه، 1 = فلش 1 ثانیهای
let flashCount = 0;
const totalFlashRounds = 2; // 2 دور کامل
const flashPerRound = 4;
const maxFlash = totalFlashRounds * flashPerRound;
function showNextImage() {
// مخفی کردن همه
imageElements.forEach(img => img.classList.remove('active'));
// نمایش عکس فعلی
imageElements[currentImageIndex].classList.add('active');
if (phase === 0) {
// فاز اول: هر کدام 2 ثانیه
if (currentImageIndex < imageElements.length - 1) {
currentImageIndex++;
setTimeout(showNextImage, 2000);
} else {
// رفتن به فاز فلش
phase = 1;
flashCount = 0;
currentImageIndex = 0;
setTimeout(showNextImage, 2000);
}
} else {
// فاز فلش: هر کدام 1 ثانیه
flashCount++;
if (flashCount >= maxFlash) {
// پایان انیمیشن
setTimeout(() => {
container.classList.remove('active');
container.innerHTML = '';
ludoGameState.hackerAnimating = false;
ludoStopHackerSound();
ludoShowHackerChallenge(team);
}, 1000);
return;
}
currentImageIndex = (currentImageIndex + 1) % imageElements.length;
setTimeout(showNextImage, 1000);
}
}
// شروع انیمیشن
setTimeout(showNextImage, 100);
}
function ludoShowHackerChallenge(team) {
ludoGameState.hackerChallengeActive = true;
ludoGameState.hackerChallengeLocked = false;
ludoGameState.hackerChallengeIndex = 0;
ludoGameState.hackerChallengeTimeLeft = 20;
// تولید عدد ۱۰ رقمی رندوم
let number = '';
for (let i = 0; i < 10; i++) {
number += Math.floor(Math.random() * 10);
}
ludoGameState.hackerChallengeNumber = number;
// تولید گزینههای رندوم ۰ تا ۹
let buttons = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = buttons.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[buttons[i], buttons[j]] = [buttons[j], buttons[i]];
}
ludoGameState.hackerChallengeButtons = buttons;
ludoGameState.hackerChallengeShuffled = [...buttons];
const modal = document.getElementById('hackerChallengeModal');
const numberText = document.getElementById('hackerNumberText');
const timerElement = document.getElementById('hackerTimer');
const inputDisplay = document.getElementById('hackerInputDisplay');
const buttonsGrid = document.getElementById('hackerButtonsGrid');
const resultMessage = document.getElementById('hackerResultMessage');
numberText.textContent = number;
timerElement.textContent = '20';
inputDisplay.textContent = '';
resultMessage.className = 'hacker-result-message';
resultMessage.textContent = '';
buttonsGrid.innerHTML = '';
ludoGameState.hackerChallengeButtons.forEach((digit, index) => {
const btn = document.createElement('button');
btn.className = 'hacker-digit-btn';
btn.textContent = digit;
btn.dataset.digit = digit;
btn.dataset.index = index;
btn.onclick = function() {
if (ludoGameState.hackerChallengeLocked) return;
ludoHandleHackerDigitClick(digit, team);
};
buttonsGrid.appendChild(btn);
});
modal.classList.add('active');
modal.style.display = 'flex';
// شروع تایمر
ludoGameState.hackerChallengeTimer = setInterval(() => {
ludoGameState.hackerChallengeTimeLeft--;
timerElement.textContent = ludoGameState.hackerChallengeTimeLeft;
if (ludoGameState.hackerChallengeTimeLeft <= 5) {
timerElement.style.color = '#ff4444';
timerElement.style.animation = 'hackerFailPulse 0.5s infinite';
}
if (ludoGameState.hackerChallengeTimeLeft <= 0) {
clearInterval(ludoGameState.hackerChallengeTimer);
ludoGameState.hackerChallengeTimer = null;
ludoHackerChallengeFail(team);
}
}, 1000);
// پخش صدای تایپ
ludoPlayHackerTypingSound();
}
function ludoHandleHackerDigitClick(digit, team) {
if (ludoGameState.hackerChallengeLocked) return;
const expectedDigit = parseInt(ludoGameState.hackerChallengeNumber[ludoGameState.hackerChallengeIndex]);
const inputDisplay = document.getElementById('hackerInputDisplay');
const buttonsGrid = document.getElementById('hackerButtonsGrid');
const resultMessage = document.getElementById('hackerResultMessage');
if (digit === expectedDigit) {
// درست
const btns = buttonsGrid.querySelectorAll('.hacker-digit-btn');
btns.forEach(btn => {
if (parseInt(btn.dataset.digit) === digit) {
btn.classList.add('correct-flash');
setTimeout(() => btn.classList.remove('correct-flash'), 1000);
}
});
inputDisplay.textContent += digit;
ludoGameState.hackerChallengeIndex++;
if (ludoGameState.hackerChallengeIndex >= 10) {
// موفقیت
ludoGameState.hackerChallengeLocked = true;
clearInterval(ludoGameState.hackerChallengeTimer);
ludoGameState.hackerChallengeTimer = null;
ludoStopHackerTypingSound();
resultMessage.className = 'hacker-result-message success';
resultMessage.textContent = '✅ هک با موفقیت انجام شد!';
setTimeout(() => {
document.getElementById('hackerChallengeModal').classList.remove('active');
document.getElementById('hackerChallengeModal').style.display = 'none';
ludoGameState.hackerChallengeActive = false;
ludoHackerSuccess(team);
}, 1500);
}
} else {
// اشتباه
const btns = buttonsGrid.querySelectorAll('.hacker-digit-btn');
btns.forEach(btn => {
if (parseInt(btn.dataset.digit) === digit) {
btn.classList.add('wrong-flash');
setTimeout(() => btn.classList.remove('wrong-flash'), 1000);
}
});
// پاک کردن همه اعداد
inputDisplay.textContent = '';
ludoGameState.hackerChallengeIndex = 0;
// لرزش فیلد ورودی
inputDisplay.style.animation = 'hackerFailPulse 0.3s ease-in-out';
setTimeout(() => {
inputDisplay.style.animation = '';
}, 300);
}
}
function ludoHackerChallengeFail(team) {
if (ludoGameState.hackerChallengeLocked) return;
ludoGameState.hackerChallengeLocked = true;
ludoStopHackerTypingSound();
const resultMessage = document.getElementById('hackerResultMessage');
resultMessage.className = 'hacker-result-message fail';
resultMessage.textContent = '❌ هک ناموفق! همه مهرهها حذف شدند.';
setTimeout(() => {
document.getElementById('hackerChallengeModal').classList.remove('active');
document.getElementById('hackerChallengeModal').style.display = 'none';
ludoGameState.hackerChallengeActive = false;
ludoHackerFail(team);
}, 1500);
}
function ludoHackerSuccess(team) {
ludoShowMessage(`✅ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} هک را با موفقیت انجام داد!`, 'success');
ludoGameState.hackerDone = true;
ludoGameState.hackerUsed[team] = true;
ludoGameState.hackerFieldsVisible[team] = true;
ludoGameState.hackerUsesLeft[team] = 4;
ludoGameState.hackerConfirmLocked[team] = false;
// ناپدید شدن دکمه هکر برای هر دو تیم
document.getElementById('ludoBlueHackerBtn').style.display = 'none';
document.getElementById('ludoRedHackerBtn').style.display = 'none';
// نمایش فیلدها
ludoUpdateHackerFields();
ludoUpdateSaveButtons();
ludoShowMessage(`💻 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} ۴ بار فرصت استفاده از هک دارد!`, 'success');
}
function ludoHackerFail(team) {
ludoShowMessage(`❌ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} در هک شکست خورد! همه مهرهها حذف شدند.`, 'error');
ludoGameState.hackerUsed[team] = true;
ludoGameState.hackerDone = true;
// حذف همه مهرههای تیم
const pieces = team === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
pieces.forEach(piece => {
if (piece.isOnBoard || piece.inWinnerCell || piece.jailRemainingSeconds > 0) {
// حذف از خانه طلایی
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === team && w.occupiedBy.pieceId === piece.id);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (team === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
piece.inWinnerCell = false;
}
clearJailTimer(piece);
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
pieceEl.style.transition = 'all 1s ease-in';
pieceEl.style.opacity = '0';
pieceEl.style.transform = 'scale(0) rotate(720deg)';
setTimeout(() => {
if (pieceEl.parentNode) pieceEl.parentNode.removeChild(pieceEl);
}, 1000);
}
piece.position = -1;
piece.isOnBoard = false;
piece.isInHome = true;
piece.inWinnerCell = false;
piece.jailRemainingSeconds = 0;
// حذف سپر
const shieldIndex = ludoGameState.shieldEffects.findIndex(s => s.team === team && s.pieceId === piece.id);
if (shieldIndex !== -1) {
ludoGameState.shieldEffects.splice(shieldIndex, 1);
}
}
});
// حذف مهرههای شبیهسازی تیم
const simPiecesToRemove = ludoGameState.simulationPieces.filter(p => p.team === team);
simPiecesToRemove.forEach(simPiece => {
const el = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (el && el.parentNode) el.parentNode.removeChild(el);
});
ludoGameState.simulationPieces = ludoGameState.simulationPieces.filter(p => p.team !== team);
ludoUpdateWinnerCellsDisplay();
ludoUpdateDisplay();
ludoUpdateSaveButtons();
// ناپدید شدن دکمه هکر برای هر دو تیم
document.getElementById('ludoBlueHackerBtn').style.display = 'none';
document.getElementById('ludoRedHackerBtn').style.display = 'none';
// بررسی پایان بازی
ludoCheckWinner();
setTimeout(() => {
ludoNextTurn();
}, 1500);
}
function ludoConfirmHacker(team) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) {
ludoShowMessage('🎮 بازی تمام شده است!', 'warning');
return;
}
if (ludoGameState.currentTurn !== team) {
ludoShowMessage(`❌ الان نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} است!`, 'error');
return;
}
if (ludoGameState.diceRolled) {
ludoShowMessage('❌ شما قبلاً تاس انداختهاید! باید قبل از تاس انداختن تایید کنید.', 'error');
return;
}
if (ludoGameState.hackerConfirmLocked[team]) {
ludoShowMessage('❌ این بار استفاده شده!', 'error');
return;
}
if (ludoGameState.hackerUsesLeft[team] <= 0) {
ludoShowMessage('❌ تعداد دفعات استفاده تمام شده!', 'error');
return;
}
const field1 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField1`);
const field2 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField2`);
// دریافت مقدار فیلد تاس (میتونه 1n یا 2n باشه)
const rawVal1 = field1.value.trim().toLowerCase();
let val1;
if (rawVal1 === '1n') {
val1 = -1;
} else if (rawVal1 === '2n') {
val1 = -2;
} else {
val1 = parseInt(rawVal1);
}
const val2 = parseInt(field2.value);
if (isNaN(val1) || (val1 < -2 || val1 > 5) || val1 === 0) {
ludoShowMessage('❌ عدد تاس باید ۱ تا ۵ یا 1n یا 2n باشد!', 'error');
return;
}
if (isNaN(val2) || val2 < 1 || val2 > 4) {
ludoShowMessage('❌ شماره مهره باید بین ۱ تا ۴ باشد!', 'error');
return;
}
const targetTeam = team === 'blue' ? 'red' : 'blue';
const targetPieces = targetTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const targetPiece = targetPieces.find(p => p.id === val2 && p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
if (!targetPiece) {
ludoShowMessage(`❌ مهره ${val2} در تخته نیست یا در زندان/طلایی/شبیهسازی است!`, 'error');
return;
}
// ثبت نهایی
ludoGameState.hackerField1Value[team] = val1;
ludoGameState.hackerField2Value[team] = val2;
ludoGameState.hackerConfirmLocked[team] = true;
ludoGameState.hackerUsesLeft[team]--;
ludoGameState.hackerForcingActive[team] = true;
ludoGameState.hackerForcingTeam = team;
ludoGameState.hackerForcedTargetTeam = targetTeam;
ludoGameState.hackerForcedDiceValue = val1;
ludoGameState.hackerForcedPieceId = val2;
field1.disabled = true;
field2.disabled = true;
let displayVal = val1;
if (val1 === -1) displayVal = '1n';
else if (val1 === -2) displayVal = '2n';
ludoShowMessage(`✅ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} ثبت کرد: تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} باید تاس ${displayVal} بیاورد و مهره ${val2} را حرکت دهد! (${ludoGameState.hackerUsesLeft[team]} بار باقی مانده)`, 'success');
ludoUpdateHackerFields();
ludoUpdateSaveButtons();
// نوبت عوض نمیشه! خودش میتونه تاس بزنه
ludoShowMessage(`🎲 حالا نوبت شماست! تاس خود را بزنید.`, 'info');
// فعال کردن تاس خودش
const dice = document.getElementById('ludo' + team.charAt(0).toUpperCase() + team.slice(1) + 'Dice');
dice.classList.remove('disabled');
}
function ludoCheckHackerForcing(team) {
for (let t of ['blue', 'red']) {
if (ludoGameState.hackerForcingActive[t] && ludoGameState.hackerForcedTargetTeam === team) {
return t;
}
}
return null;
}
function ludoGetForcedDiceValue(team) {
for (let t of ['blue', 'red']) {
if (ludoGameState.hackerForcingActive[t] && ludoGameState.hackerForcedTargetTeam === team) {
return ludoGameState.hackerField1Value[t];
}
}
return null;
}
function ludoGetForcedPieceId(team) {
for (let t of ['blue', 'red']) {
if (ludoGameState.hackerForcingActive[t] && ludoGameState.hackerForcedTargetTeam === team) {
return ludoGameState.hackerField2Value[t];
}
}
return null;
}
function ludoClearHackerForcing(team) {
for (let t of ['blue', 'red']) {
if (ludoGameState.hackerForcingActive[t] && ludoGameState.hackerForcedTargetTeam === team) {
ludoGameState.hackerForcingActive[t] = false;
ludoGameState.hackerForcingTeam = null;
ludoGameState.hackerForcedTargetTeam = null;
ludoGameState.hackerForcedDiceValue = null;
ludoGameState.hackerForcedPieceId = null;
ludoGameState.hackerConfirmLocked[t] = false;
// فعال کردن فیلدها برای استفاده مجدد
const field1 = document.getElementById(`ludo${t.charAt(0).toUpperCase() + t.slice(1)}HackerField1`);
const field2 = document.getElementById(`ludo${t.charAt(0).toUpperCase() + t.slice(1)}HackerField2`);
if (field1) {
field1.disabled = false;
field1.value = '';
}
if (field2) {
field2.disabled = false;
field2.value = '';
}
ludoGameState.hackerField1Value[t] = null;
ludoGameState.hackerField2Value[t] = null;
ludoGameState.hackerField1RawValue[t] = null;
ludoUpdateHackerFields();
ludoUpdateSaveButtons();
ludoShowMessage(`🔓 اجبار هکر برای تیم ${team === 'blue' ? 'آبی' : 'قرمز'} پایان یافت.`, 'info');
return;
}
}
}
function ludoIsPieceForced(team, pieceId) {
const forcedId = ludoGetForcedPieceId(team);
return forcedId === pieceId;
}
function ludoIsDiceForced(team) {
return ludoGetForcedDiceValue(team) !== null;
}
// ===== حرکت خودکار مهره اجباری =====
function ludoAutoMoveForcedPiece(team) {
const forcedPieceId = ludoGetForcedPieceId(team);
if (forcedPieceId === null) return false;
const pieces = team === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const forcedPiece = pieces.find(p => p.id === forcedPieceId);
if (!forcedPiece || !forcedPiece.isOnBoard || forcedPiece.inWinnerCell || forcedPiece.jailRemainingSeconds > 0) {
ludoShowMessage(`⚠️ مهره اجباری ${forcedPieceId} در تخته نیست یا در زندان/طلایی است! اجبار لغو شد.`, 'warning');
ludoClearHackerForcing(team);
return false;
}
const diceValue = ludoGameState.currentDiceValue;
const forcedValue = ludoGetForcedDiceValue(team);
if (diceValue !== forcedValue) {
ludoShowMessage(`⚠️ خطا: عدد تاس ${diceValue} با عدد اجباری ${forcedValue} مطابقت ندارد!`, 'error');
return false;
}
ludoGameState.autoMoveInProgress = true;
ludoShowMessage(`🤖 حرکت خودکار مهره ${forcedPieceId} تیم ${team === 'blue' ? 'آبی' : 'قرمز'} شروع شد...`, 'info');
const newPosition = forcedPiece.position + diceValue;
if (newPosition < 1) {
ludoShowMessage(`❌ نمیتوانید از خانه 1 عقبتر بروید!`, 'error');
ludoGameState.autoMoveInProgress = false;
ludoClearHackerForcing(team);
setTimeout(() => { ludoNextTurn(); }, 500);
return false;
}
if (newPosition > 120) {
ludoShowMessage(`❌ نمیتوانید از خانه 120 فراتر بروید!`, 'error');
ludoGameState.autoMoveInProgress = false;
ludoClearHackerForcing(team);
setTimeout(() => { ludoNextTurn(); }, 500);
return false;
}
// چک کردن خانههای ویژه
const moveInfo = { team: team, piece: forcedPiece, newPosition: newPosition, oldPosition: forcedPiece.position };
// حرکت خودکار با انیمیشن
ludoAutoAnimatePieceMove(team, forcedPiece, newPosition, moveInfo);
return true;
}
function ludoAutoAnimatePieceMove(team, piece, newPosition, moveInfo) {
const oldPosition = piece.position;
const steps = Math.abs(ludoGameState.currentDiceValue);
let currentStep = 0;
const direction = ludoGameState.currentDiceValue > 0 ? 1 : -1;
const pieceElement = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (!pieceElement) {
piece.position = newPosition;
ludoGameState.autoMoveInProgress = false;
ludoCheckSpecialCellsAuto(team, piece, newPosition, moveInfo);
return;
}
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
function moveStep() {
if (currentStep >= steps) {
piece.position = newPosition;
ludoGameState.autoMoveInProgress = false;
ludoCheckSpecialCellsAuto(team, piece, newPosition, moveInfo);
return;
}
currentStep++;
const tempPosition = oldPosition + (currentStep * direction);
const tempCell = ludoGameState.boardElements[tempPosition];
if (tempCell) {
const rect = tempCell.getBoundingClientRect();
const offsetX = Math.random() * 20 + 5;
const offsetY = Math.random() * 20 + 5;
pieceElement.style.left = (rect.left - boardRect.left + offsetX) + 'px';
pieceElement.style.top = (rect.top - boardRect.top + offsetY) + 'px';
pieceElement.style.transition = 'all 0.3s ease-in-out';
setTimeout(moveStep, 300);
} else {
setTimeout(moveStep, 300);
}
}
moveStep();
}
function ludoCheckSpecialCellsAuto(team, piece, position, moveInfo) {
// ۱. چک کردن سوال
if (ludoGameState.questionCells.includes(position)) {
ludoGameState.pendingQuestionMove = moveInfo;
ludoPlayQuestionSound();
ludoGameState.questionAnswered = false;
setTimeout(() => {
ludoShowGeneralQuestion(moveInfo);
ludoGameState.pendingQuestionMove = null;
}, 500);
return;
}
// ۲. چک کردن شانس (تاس طلایی)
if (ludoGameState.luckCells.includes(position)) {
setTimeout(() => {
ludoShowGoldenDice(team, piece, moveInfo.oldPosition);
}, 500);
return;
}
// ۳. چک کردن انفجار
if (ludoGameState.explosionCells.includes(position)) {
setTimeout(() => {
ludoShowExplosionConfirmation(moveInfo);
}, 500);
return;
}
// ۴. چک کردن معامله
if (ludoGameState.dealCells.includes(position)) {
ludoPlayDealSound();
setTimeout(() => {
ludoShowDealScreen(moveInfo);
}, 500);
return;
}
// ۵. چک کردن رنگینکمان
if (ludoGameState.rainbowCells.includes(position)) {
setTimeout(() => {
ludoShowRainbowConfirmation(moveInfo);
}, 500);
return;
}
// ۶. چک کردن روح
if (ludoGameState.ghostCell === position) {
setTimeout(() => {
ludoShowGhostHouse(moveInfo);
}, 500);
return;
}
// ۷. چک کردن شبیهسازی
if (ludoGameState.simulationCells.includes(position)) {
if (ludoGameState.simulationLocked || ludoGameState.simulationActive) {
ludoShowMessage(`🧬 مهره روی خانه شبیهسازی قفل شده رفت. هیچ اتفاقی نمیافتد.`, 'info');
ludoAutoFinishMove(team, piece);
} else {
ludoShowSimulationEffect(moveInfo);
}
return;
}
// ۸. چک کردن زندان
if (ludoGameState.jailCells.includes(position)) {
if (piece.jailRemainingSeconds === 0) {
piece.jailRemainingSeconds = 180;
clearJailTimer(piece);
startJailTimer(piece, team);
ludoPlayJailSound();
ludoShowMessage(`🔒 مهره ${piece.id} ${team === 'blue' ? 'آبی' : 'قرمز'} به زندان افتاد! به مدت ۳ دقیقه زندانی شد.`, 'warning');
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
pieceEl.classList.add('ludo-jail-piece');
const minutes = Math.floor(180 / 60);
const seconds = 180 % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
let jailTag = pieceEl.querySelector('.jail-tag');
if (!jailTag) {
jailTag = document.createElement('div');
jailTag.className = 'jail-tag';
pieceEl.appendChild(jailTag);
}
jailTag.textContent = `زندان: ${timeString}`;
}
}
ludoAutoFinishMove(team, piece);
return;
}
// ۹. چک کردن خطر
if (ludoGameState.dangerCells.includes(position)) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === team && s.pieceId === piece.id);
if (hasShield) {
ludoShowMessage(`🛡️ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} توسط سپر از خانه خطر محافظت شد!`, 'success');
} else {
ludoPlayDangerSound();
ludoShowMessage(`☠️ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} روی خانه خطر افتاد! به خانه اول بازگشت.`, 'warning');
ludoReturnPieceToHome(team, piece, true);
ludoAutoFinishMove(team, piece);
return;
}
}
// ۱۰. چک کردن انتقال
if (ludoGameState.transferCells[position]) {
const transferTo = ludoGameState.transferCells[position];
ludoShowMessage(`⇄ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} روی خانه انتقال افتاد! به خانه ${transferTo} منتقل شد.`, 'info');
ludoCheckAndRemoveOpponentPiece(team, transferTo, position);
piece.position = transferTo;
ludoUpdatePiecePosition(team, piece);
setTimeout(() => { ludoCheckSpecialCellsAuto(team, piece, transferTo, moveInfo); }, 500);
return;
}
// ۱۱. چک کردن خانه برنده
const winnerCell = ludoGameState.winnerCells.find(w => w.number === position);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
piece.position -= ludoGameState.currentDiceValue;
ludoUpdatePiecePosition(team, piece);
ludoAutoFinishMove(team, piece);
return;
} else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: team, pieceId: piece.id };
piece.inWinnerCell = true;
if (team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
// ۱۲. چک کردن حذف مهره حریف
ludoCheckAndRemoveOpponentPiece(team, position, piece.position - ludoGameState.currentDiceValue);
ludoAutoFinishMove(team, piece);
}
function ludoAutoFinishMove(team, piece) {
reduceShieldTurns();
ludoUpdateDisplay();
// پاک کردن اجبار هکر
ludoClearHackerForcing(team);
ludoShowMessage(`✅ حرکت خودکار مهره ${piece.id} تیم ${team === 'blue' ? 'آبی' : 'قرمز'} انجام شد.`, 'success');
// چک کردن برد
ludoCheckWinner();
setTimeout(() => {
ludoNextTurn();
}, 1000);
}
// ==============================
// ===== توابع تولید خانهها =====
// ==============================
function ludoGenerateDangerCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.dangerCells = [];
while (ludoGameState.dangerCells.length < 8) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.dangerCells.push(randomCell);
}
}
}
function ludoGenerateQuestionCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.questionCells = [];
while (ludoGameState.questionCells.length < 10) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.questionCells.push(randomCell);
}
}
}
function ludoGenerateLuckCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.luckCells = [];
while (ludoGameState.luckCells.length < 3) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.luckCells.push(randomCell);
}
}
}
function ludoGenerateExplosionCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.explosionCells = [];
while (ludoGameState.explosionCells.length < 2) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.explosionCells.push(randomCell);
}
}
}
function ludoGenerateDealCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.dealCells = [];
while (ludoGameState.dealCells.length < 3) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.dealCells.push(randomCell);
}
}
}
function ludoGenerateRainbowCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
ludoGameState.rainbowCells = [];
while (ludoGameState.rainbowCells.length < 2) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) && !ludoGameState.dangerCells.includes(randomCell) && !ludoGameState.questionCells.includes(randomCell) && !ludoGameState.luckCells.includes(randomCell) && !ludoGameState.explosionCells.includes(randomCell) && !ludoGameState.dealCells.includes(randomCell) && !ludoGameState.rainbowCells.includes(randomCell) && randomCell !== ludoGameState.ghostCell && randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.rainbowCells.push(randomCell);
}
}
}
function ludoGenerateGhostCell() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
let attempts = 0;
let ghostCell = null;
while (attempts < 200) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) &&
!ludoGameState.dangerCells.includes(randomCell) &&
!ludoGameState.questionCells.includes(randomCell) &&
!ludoGameState.luckCells.includes(randomCell) &&
!ludoGameState.explosionCells.includes(randomCell) &&
!ludoGameState.dealCells.includes(randomCell) &&
!ludoGameState.rainbowCells.includes(randomCell) &&
randomCell !== ludoGameState.hackerDeviceCell) {
ghostCell = randomCell;
break;
}
attempts++;
}
if (ghostCell === null) {
ghostCell = 50;
}
ludoGameState.ghostCell = ghostCell;
return ghostCell;
}
function ludoGenerateSimulationCells() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells];
ludoGameState.simulationCells = [];
while (ludoGameState.simulationCells.length < 2) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) &&
!ludoGameState.dangerCells.includes(randomCell) &&
!ludoGameState.questionCells.includes(randomCell) &&
!ludoGameState.luckCells.includes(randomCell) &&
!ludoGameState.explosionCells.includes(randomCell) &&
!ludoGameState.dealCells.includes(randomCell) &&
!ludoGameState.rainbowCells.includes(randomCell) &&
randomCell !== ludoGameState.ghostCell &&
randomCell !== ludoGameState.hackerDeviceCell) {
ludoGameState.simulationCells.push(randomCell);
}
}
ludoGameState.simulationLocked = true;
ludoGameState.simulationUsed = false;
}
function ludoGenerateHackerDeviceCell() {
const excludedCells = [1, 7, 58, 76, 96, 117, 118, 119, 120, ...ludoGameState.jailCells, ...ludoGameState.simulationCells];
let attempts = 0;
let hackerCell = null;
while (attempts < 300) {
const randomCell = Math.floor(Math.random() * 120) + 1;
if (!excludedCells.includes(randomCell) &&
!ludoGameState.dangerCells.includes(randomCell) &&
!ludoGameState.questionCells.includes(randomCell) &&
!ludoGameState.luckCells.includes(randomCell) &&
!ludoGameState.explosionCells.includes(randomCell) &&
!ludoGameState.dealCells.includes(randomCell) &&
!ludoGameState.rainbowCells.includes(randomCell) &&
randomCell !== ludoGameState.ghostCell &&
!ludoGameState.transferCells[randomCell]) {
hackerCell = randomCell;
break;
}
attempts++;
}
if (hackerCell === null) {
hackerCell = 10;
}
ludoGameState.hackerDeviceCell = hackerCell;
ludoGameState.hackerDeviceCollected = { blue: false, red: false };
ludoGameState.hackerDeviceTeam = null;
return hackerCell;
}
// ==============================
// ===== ساخت تخته =====
// ==============================
function ludoCreateBoard() {
const board = document.getElementById('ludoBoard');
const rows = 10;
const cols = 12;
let cellNumber = 1;
board.innerHTML = '';
ludoGameState.boardElements = [];
ludoGameState.pieceElements = [];
board.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
board.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
ludoGenerateGhostCell();
ludoGenerateSimulationCells();
ludoGenerateHackerDeviceCell();
for (let row = 1; row <= rows; row++) {
for (let col = 1; col <= cols; col++) {
const cell = document.createElement('div');
cell.className = 'ludo-cell ludo-path-cell';
cell.dataset.cellNumber = cellNumber;
const numberSpan = document.createElement('span');
numberSpan.className = 'ludo-cell-number';
numberSpan.textContent = cellNumber;
cell.appendChild(numberSpan);
cell.style.gridColumn = col;
cell.style.gridRow = row;
const winnerCell = ludoGameState.winnerCells.find(w => w.number === cellNumber);
if (winnerCell) { cell.classList.add('ludo-winner-cell'); cell.innerHTML += `<div style="position: absolute; bottom: 2px; right: 2px; font-size: 10px;">🏆</div>`; }
if (ludoGameState.dangerCells.includes(cellNumber)) {
cell.classList.add('ludo-danger-cell');
const dangerText = document.createElement('div');
dangerText.style.position = 'absolute';
dangerText.style.top = '5px';
dangerText.style.left = '5px';
dangerText.style.fontSize = '10px';
dangerText.style.color = 'white';
dangerText.textContent = 'حذف';
cell.appendChild(dangerText);
}
if (ludoGameState.questionCells.includes(cellNumber)) {
cell.classList.add('ludo-question-cell');
const questionText = document.createElement('div');
questionText.style.position = 'absolute';
questionText.style.top = '5px';
questionText.style.left = '5px';
questionText.style.fontSize = '10px';
questionText.style.color = 'white';
questionText.textContent = 'سوال';
cell.appendChild(questionText);
}
if (ludoGameState.luckCells.includes(cellNumber)) {
cell.classList.add('ludo-luck-cell');
const luckText = document.createElement('div');
luckText.style.position = 'absolute';
luckText.style.top = '5px';
luckText.style.left = '5px';
luckText.style.fontSize = '10px';
luckText.style.color = 'gold';
luckText.textContent = 'شانس';
cell.appendChild(luckText);
}
if (ludoGameState.explosionCells.includes(cellNumber)) {
cell.classList.add('ludo-explosion-cell');
const explosionText = document.createElement('div');
explosionText.className = 'ludo-explosion-text';
explosionText.textContent = 'انفجار';
cell.appendChild(explosionText);
}
if (ludoGameState.dealCells.includes(cellNumber)) {
cell.classList.add('ludo-deal-cell');
const dealText = document.createElement('div');
dealText.style.position = 'absolute';
dealText.style.top = '5px';
dealText.style.left = '5px';
dealText.style.fontSize = '10px';
dealText.style.color = 'black';
dealText.style.background = 'white';
dealText.style.padding = '2px 5px';
dealText.style.borderRadius = '3px';
dealText.style.border = '1px solid black';
dealText.textContent = 'معامله';
cell.appendChild(dealText);
}
if (ludoGameState.rainbowCells.includes(cellNumber)) {
cell.classList.add('ludo-rainbow-cell');
const rainbowText = document.createElement('div');
rainbowText.style.position = 'absolute';
rainbowText.style.top = '5px';
rainbowText.style.left = '5px';
rainbowText.style.fontSize = '10px';
rainbowText.style.color = 'white';
rainbowText.style.background = 'rgba(0,0,0,0.5)';
rainbowText.style.padding = '2px 5px';
rainbowText.style.borderRadius = '3px';
rainbowText.textContent = 'رنگینکمان';
cell.appendChild(rainbowText);
}
if (ludoGameState.simulationCells.includes(cellNumber)) {
cell.classList.add('ludo-simulation-cell');
const simText = document.createElement('div');
simText.className = 'simulation-text';
simText.textContent = '🧬 شبیهسازی';
cell.appendChild(simText);
const lockIcon = document.createElement('div');
lockIcon.className = 'simulation-lock';
lockIcon.textContent = '🔒';
lockIcon.id = `sim-lock-${cellNumber}`;
cell.appendChild(lockIcon);
}
if (ludoGameState.ghostCell === cellNumber) {
cell.classList.add('ludo-ghost-cell');
const ghostText = document.createElement('div');
ghostText.className = 'ghost-text';
ghostText.textContent = '👻 روح';
cell.appendChild(ghostText);
}
if (ludoGameState.hackerDeviceCell === cellNumber) {
cell.classList.add('ludo-hacker-device-cell');
const iconSpan = document.createElement('span');
iconSpan.className = 'hacker-device-icon';
iconSpan.textContent = '💻';
cell.appendChild(iconSpan);
const textSpan = document.createElement('span');
textSpan.className = 'hacker-device-text';
textSpan.textContent = 'هکینگ دیوایس';
cell.appendChild(textSpan);
}
if (ludoGameState.jailCells.includes(cellNumber)) {
cell.classList.add('ludo-jail-cell');
const jailText = document.createElement('div');
jailText.style.position = 'absolute';
jailText.style.top = '5px';
jailText.style.right = '5px';
jailText.style.fontSize = '10px';
jailText.style.color = '#ffcc00';
jailText.style.background = '#000';
jailText.style.padding = '2px 5px';
jailText.style.borderRadius = '3px';
jailText.textContent = 'زندان ۳ دقیقهای';
cell.appendChild(jailText);
const fireDiv = document.createElement('div');
fireDiv.className = 'jail-fire';
cell.appendChild(fireDiv);
}
if (ludoGameState.transferCells[cellNumber]) {
cell.classList.add('ludo-transfer-cell');
const transferText = document.createElement('div');
transferText.style.position = 'absolute';
transferText.style.top = '5px';
transferText.style.left = '5px';
transferText.style.fontSize = '10px';
transferText.style.color = 'white';
transferText.textContent = `به ${ludoGameState.transferCells[cellNumber]}`;
cell.appendChild(transferText);
}
if (cellNumber === 1) {
cell.classList.add('ludo-start-cell');
cell.innerHTML = '<div style="font-size: 16px; font-weight: bold;">شروع<br><span style="font-size: 14px;">(1)</span></div>';
}
board.appendChild(cell);
ludoGameState.boardElements[cellNumber] = cell;
cellNumber++;
}
}
ludoUpdateSimulationLocks();
ludoUpdateSaveButtons();
}
function ludoUpdateSimulationLocks() {
ludoGameState.simulationCells.forEach(cellNum => {
const cell = ludoGameState.boardElements[cellNum];
if (cell) {
const lockIcon = cell.querySelector('.simulation-lock');
if (lockIcon) {
if (ludoGameState.simulationLocked || ludoGameState.simulationActive || ludoGameState.gameEnded) {
lockIcon.textContent = '🔒';
lockIcon.style.color = '#ff4444';
lockIcon.style.display = 'block';
} else {
lockIcon.style.display = 'none';
}
}
}
});
}
function ludoCheckSimulationConditions() {
const blueValid = ludoGameState.bluePieces.some(p => p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && p.position > 2 && !p.isSimulation);
const redValid = ludoGameState.redPieces.some(p => p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && p.position > 2 && !p.isSimulation);
const wasLocked = ludoGameState.simulationLocked;
if (ludoGameState.simulationPieces.length > 0) {
ludoGameState.simulationLocked = true;
} else if (blueValid && redValid && !ludoGameState.gameEnded) {
ludoGameState.simulationLocked = false;
} else {
if (!ludoGameState.gameEnded) {
ludoGameState.simulationLocked = true;
}
}
if (wasLocked !== ludoGameState.simulationLocked) {
ludoUpdateSimulationLocks();
if (!ludoGameState.simulationLocked) {
ludoShowMessage('🧬 خانههای شبیهسازی فعال شدند!', 'success');
} else if (ludoGameState.simulationPieces.length === 0) {
ludoShowMessage('🔒 خانههای شبیهسازی قفل شدند!', 'warning');
}
}
}
// ==============================
// ===== توابع تاس =====
// ==============================
function ludoRollSpecialDice() {
const random = Math.random();
if (random < 0.10) return -1;
else if (random < 0.15) return -2;
else return Math.floor(Math.random() * 6) + 1;
}
function ludoRollDice(team) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) { ludoShowMessage('🎮 بازی تمام شده است! برای شروع جدید بازی را ریست کنید.', 'warning'); return; }
if (ludoGameState.currentTurn !== team || ludoGameState.inQuestionMode || ludoGameState.isMovingPiece || ludoGameState.inDealMode || ludoGameState.rainbowActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) return;
if (ludoGameState.diceLocked) { ludoShowMessage('⏳ تاس در حال چرخش است...', 'warning'); return; }
// چک کردن اینکه آیا این تیم تحت اجبار هکر هست یا نه
const isForced = ludoGetForcedDiceValue(team) !== null;
const forcedValue = ludoGetForcedDiceValue(team);
// اگر تحت اجبار هستیم و قبلاً تاس ریخته شده و حرکت خودکار انجام شده، اجازه نده دوباره تاس بزنه
if (isForced && ludoGameState.diceRolled && ludoGameState.autoMoveInProgress) {
ludoShowMessage('⏳ حرکت خودکار در حال انجام است...', 'warning');
return;
}
if (ludoGameState.isInPenaltyMode) ludoGameState.diceRolled = false;
else if (ludoGameState.diceRolled && !ludoGameState.extraTurn && !ludoGameState.justCameFromQuestion) {
ludoShowMessage('❌ قبلاً تاس انداختهاید! مهرهای انتخاب کنید.', 'error');
return;
}
const dice = document.getElementById('ludo' + team.charAt(0).toUpperCase() + team.slice(1) + 'Dice');
dice.classList.add('rolling', 'locked');
dice.textContent = '...';
ludoGameState.diceLocked = true;
ludoPlayDiceSound();
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
}
ludoUpdateSaveButtons();
setTimeout(() => {
let diceValue;
// اگر تحت اجبار هکر هستیم، عدد اجباری رو برگردون
if (isForced) {
diceValue = forcedValue;
let displayVal = diceValue;
if (diceValue === -1) displayVal = '-1';
else if (diceValue === -2) displayVal = '-2';
ludoShowMessage(`🎲 تاس ${team === 'blue' ? 'آبی' : 'قرمز'} عدد ${displayVal} آورد (اجباری از هکر)`, 'warning');
} else {
diceValue = ludoRollSpecialDice();
if (diceValue < 0) ludoShowMessage(`🎲 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} عدد ${diceValue} آورد! (برگشت به عقب)`, 'warning');
else ludoShowMessage(`🎲 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} عدد ${diceValue} آورد.`, 'info');
}
ludoGameState.currentDiceValue = diceValue;
ludoGameState.diceRolled = true;
ludoGameState.justCameFromQuestion = false;
dice.classList.remove('rolling', 'locked');
// نمایش عدد روی تاس (برای اعداد منفی -1 و -2 نمایش داده شود)
let displayVal = diceValue;
if (diceValue === -1) displayVal = '-1';
else if (diceValue === -2) displayVal = '-2';
dice.textContent = displayVal;
if (diceValue < 0) dice.classList.add('negative');
else dice.classList.remove('negative');
if (diceValue === 6 && !isForced) {
ludoPlayDiceSixSound();
if (team === 'blue') {
ludoGameState.saveLocked.blue = false;
ludoGameState.canSaveAfterRoll.blue = true;
ludoGameState.justRolledSix.blue = true;
} else {
ludoGameState.saveLocked.red = false;
ludoGameState.canSaveAfterRoll.red = true;
ludoGameState.justRolledSix.red = true;
}
ludoShowMessage(`🎲 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} ۶ آورد! گزینه ذخیره فعال شد.`, 'success');
ludoUpdateSaveButtons();
} else if (diceValue === -2 && !isForced) {
ludoPlayDiceMinusTwoSound();
}
ludoUpdateDisplay();
if (diceValue === 6 && !isForced) {
ludoGameState.extraTurn = true;
ludoShowMessage('✨ شش آوردید! یک نوبت اضافه دارید.', 'success');
} else {
ludoGameState.extraTurn = false;
}
// اگر تحت اجبار هکر هستیم، حرکت خودکار انجام بده
if (isForced) {
// فیلدها و دکمه تایید رو ببند
const field1 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField1`);
const field2 = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerField2`);
const confirmBtn = document.getElementById(`ludo${team.charAt(0).toUpperCase() + team.slice(1)}HackerConfirmBtn`);
if (field1) field1.disabled = true;
if (field2) field2.disabled = true;
if (confirmBtn) confirmBtn.disabled = true;
// حرکت خودکار مهره اجباری
setTimeout(() => {
ludoAutoMoveForcedPiece(team);
}, 500);
} else {
// حالت عادی - هایلایت مهرهها
ludoHighlightAvailablePieces(team);
if (!ludoHasMovablePieces(team)) {
ludoShowMessage('⚠️ هیچ مهرهای قابل حرکت نیست! نوبت عوض میشود.', 'warning');
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
}
ludoUpdateSaveButtons();
setTimeout(() => { ludoNextTurn(); }, 1500);
}
}
ludoGameState.diceLocked = false;
}, 800);
}
function ludoRollGoldenDice() {
if (ludoGameState.goldenDiceActive && ludoGameState.goldenDiceMoveInfo) {
const goldenDice = document.getElementById('ludoGoldenDice');
goldenDice.classList.add('rolling');
goldenDice.textContent = '...';
ludoPlayGoldenDiceSpinSound();
setTimeout(() => {
const possibleValues = [10, 20, 30, 40, 50, -10, -20];
const diceValue = possibleValues[Math.floor(Math.random() * possibleValues.length)];
goldenDice.classList.remove('rolling');
goldenDice.textContent = diceValue;
if (diceValue < 0) goldenDice.classList.add('negative');
else goldenDice.classList.remove('negative');
ludoShowMessage(`🎲 تاس طلایی عدد ${diceValue} آورد!`, diceValue < 0 ? 'warning' : 'success');
setTimeout(() => {
document.getElementById('ludoGoldenDiceModal').style.display = 'none';
ludoGameState.goldenDiceActive = false;
const moveInfo = ludoGameState.goldenDiceMoveInfo;
let newPosition = moveInfo.piece.position + diceValue;
if (newPosition < 1) {
ludoShowMessage(`❌ عدد ${diceValue} باعث میشود مهره از خانه 1 خارج شود! حرکت انجام نشد.`, 'error');
ludoGameState.goldenDiceMoveInfo = null;
ludoNextTurn();
return;
}
if (newPosition > 120) {
ludoShowMessage(`❌ عدد ${diceValue} باعث میشود مهره از خانه 120 خارج شود! حرکت انجام نشد.`, 'error');
ludoGameState.goldenDiceMoveInfo = null;
ludoNextTurn();
return;
}
const passesWinnerCells = (diceValue > 0) && ((moveInfo.piece.position < 117 && newPosition > 117) || (moveInfo.piece.position < 118 && newPosition > 118) || (moveInfo.piece.position < 119 && newPosition > 119) || (moveInfo.piece.position < 120 && newPosition > 120));
if (passesWinnerCells) {
ludoShowMessage(`❌ عدد ${diceValue} باعث عبور از خانههای برنده میشود! شانس از دست رفت.`, 'error');
ludoGameState.goldenDiceMoveInfo = null;
ludoNextTurn();
return;
}
const oldPosition = moveInfo.piece.position;
moveInfo.piece.position = newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, newPosition, oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
ludoGameState.goldenDiceMoveInfo = null;
ludoUpdateDisplay();
ludoCheckSpecialCells(moveInfo.team, moveInfo.piece, newPosition);
setTimeout(() => { ludoNextTurn(); }, 1000);
}, 3000);
}, 6000);
}
}
// ==============================
// ===== انیمیشنهای ویژه =====
// ==============================
async function showExplosionAnimation(explosionX, explosionY) {
return new Promise((resolve) => {
const container = document.getElementById('explosionAnimationContainer');
container.innerHTML = '';
container.style.display = 'block';
ludoPlayExplosionSound();
const flash = document.createElement('div');
flash.className = 'explosion-flash';
flash.style.setProperty('--x', explosionX + '%');
flash.style.setProperty('--y', explosionY + '%');
container.appendChild(flash);
const fireball = document.createElement('div');
fireball.className = 'explosion-fireball';
fireball.style.left = explosionX + '%';
fireball.style.top = explosionY + '%';
container.appendChild(fireball);
const lavaBalls = [];
const directions = [];
for (let i = 0; i < 15; i++) { directions.push({ angle: Math.random() * 360, speed: 2 + Math.random() * 6 }); }
const ludoBoard = document.getElementById('ludoBoard');
const boardRect = ludoBoard.getBoundingClientRect();
const boardLeft = (boardRect.left / window.innerWidth) * 100;
const boardRight = (boardRect.right / window.innerWidth) * 100;
const boardTop = (boardRect.top / window.innerHeight) * 100;
const boardBottom = (boardRect.bottom / window.innerHeight) * 100;
for (let i = 0; i < 15; i++) {
const lava = document.createElement('div');
lava.className = 'lava-ball';
lava.style.left = explosionX + '%';
lava.style.top = explosionY + '%';
const lavaData = { element: lava, x: parseFloat(explosionX), y: parseFloat(explosionY), vx: Math.cos(directions[i].angle * Math.PI / 180) * directions[i].speed, vy: Math.sin(directions[i].angle * Math.PI / 180) * directions[i].speed - 5, gravity: 0.3, active: true, boardLeft: boardLeft, boardRight: boardRight, boardTop: boardTop, boardBottom: boardBottom };
container.appendChild(lava);
lavaBalls.push(lavaData);
}
const lavaInterval = setInterval(() => {
let allInactive = true;
lavaBalls.forEach(lava => {
if (lava.active) {
allInactive = false;
lava.x += lava.vx;
lava.y += lava.vy;
lava.vy += lava.gravity;
lava.x += Math.sin(Date.now() * 0.02 + lava.y * 0.1) * 0.3;
if (lava.x >= lava.boardRight - 1) { lava.x = lava.boardRight - 1; lava.vx = -lava.vx * 0.7; }
else if (lava.x <= lava.boardLeft + 1) { lava.x = lava.boardLeft + 1; lava.vx = -lava.vx * 0.7; }
if (lava.y >= lava.boardBottom - 1) { lava.y = lava.boardBottom - 1; lava.vy = -lava.vy * 0.7; lava.active = false; createImpactEffect(lava.x, lava.y); checkLavaCollisionWithPieces(lava.x, lava.y); setTimeout(() => { if (lava.element && lava.element.parentNode) lava.element.remove(); }, 500); return; }
else if (lava.y <= lava.boardTop + 1) { lava.y = lava.boardTop + 1; lava.vy = -lava.vy * 0.7; }
createLavaTrail(lava.x, lava.y);
lava.element.style.left = lava.x + '%';
lava.element.style.top = lava.y + '%';
lava.element.style.transform = `translate(-50%, -50%) rotate(${Date.now() * 0.1}deg)`;
checkLavaCollisionWithPieces(lava.x, lava.y);
}
});
if (allInactive) { clearInterval(lavaInterval); setTimeout(() => { container.style.display = 'none'; container.innerHTML = ''; resolve(); }, 1000); }
}, 30);
});
}
function createLavaTrail(x, y) {
const container = document.getElementById('explosionAnimationContainer');
const trail = document.createElement('div');
trail.className = 'lava-trail';
trail.style.left = x + '%';
trail.style.top = y + '%';
container.appendChild(trail);
setTimeout(() => { if (trail.parentNode) trail.remove(); }, 500);
}
function createImpactEffect(x, y) {
const container = document.getElementById('explosionAnimationContainer');
const impact = document.createElement('div');
impact.className = 'impact-effect';
impact.style.left = x + '%';
impact.style.top = y + '%';
container.appendChild(impact);
setTimeout(() => { if (impact.parentNode) impact.remove(); }, 600);
}
function checkLavaCollisionWithPieces(lavaX, lavaY) {
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
const lavaScreenX = boardRect.left + (boardRect.width * lavaX / 100);
const lavaScreenY = boardRect.top + (boardRect.height * lavaY / 100);
ludoGameState.bluePieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === 'blue' && s.pieceId === piece.id);
const pieceEl = document.querySelector(`.ludo-blue-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const pieceRect = pieceEl.getBoundingClientRect();
const dx = lavaScreenX - (pieceRect.left + pieceRect.width/2);
const dy = lavaScreenY - (pieceRect.top + pieceRect.height/2);
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 60) { if (hasShield) ludoShowMessage(`🛡️ مهره آبی ${piece.id} توسط سپر محافظت شد!`, 'success'); else { ludoShowMessage(`💥 مهره آبی ${piece.id} توسط گدازه نابود شد!`, 'error'); ludoReturnPieceToHome('blue', piece); } }
}
}
});
ludoGameState.redPieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === 'red' && s.pieceId === piece.id);
const pieceEl = document.querySelector(`.ludo-red-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const pieceRect = pieceEl.getBoundingClientRect();
const dx = lavaScreenX - (pieceRect.left + pieceRect.width/2);
const dy = lavaScreenY - (pieceRect.top + pieceRect.height/2);
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 60) { if (hasShield) ludoShowMessage(`🛡️ مهره قرمز ${piece.id} توسط سپر محافظت شد!`, 'success'); else { ludoShowMessage(`💥 مهره قرمز ${piece.id} توسط گدازه نابود شد!`, 'error'); ludoReturnPieceToHome('red', piece); } }
}
}
});
}
function showGhostJumpscare() {
return new Promise((resolve) => {
const overlay = document.getElementById('ghostJumpscareOverlay');
const image = document.getElementById('ghostJumpscareImage');
ludoPlayGhostJumpscareSound();
overlay.classList.add('active');
overlay.style.display = 'flex';
setTimeout(() => {
overlay.classList.remove('active');
overlay.style.display = 'none';
resolve();
}, 500);
});
}
function startGhostPieces() {
ludoPlayGhostAppearSound();
const board = document.getElementById('ludoBoard');
const boardRect = board.getBoundingClientRect();
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
const ghostPositions = [];
for (let i = 0; i < 4; i++) {
let attempts = 0;
let ghostX, ghostY;
let validPosition = false;
while (!validPosition && attempts < 50) {
ghostX = 5 + Math.random() * 90;
ghostY = 5 + Math.random() * 90;
validPosition = true;
for (let pos of ghostPositions) {
if (Math.abs(pos.x - ghostX) < 15 && Math.abs(pos.y - ghostY) < 15) {
validPosition = false;
break;
}
}
attempts++;
}
ghostPositions.push({ x: ghostX, y: ghostY });
const ghostEl = document.createElement('div');
ghostEl.className = 'ghost-piece';
ghostEl.dataset.ghostIndex = i;
ghostEl.style.left = ghostX + '%';
ghostEl.style.top = ghostY + '%';
ghostEl.innerHTML = `<img src="https://cdn.imgurl.ir/uploads/j472124_1778685183203.png" alt="روح">`;
board.appendChild(ghostEl);
const direction = {
dx: (Math.random() - 0.5) * 1.2,
dy: (Math.random() - 0.5) * 1.2
};
const speed = Math.sqrt(direction.dx * direction.dx + direction.dy * direction.dy);
if (speed > 0) {
direction.dx = (direction.dx / speed) * (3 + Math.random() * 3);
direction.dy = (direction.dy / speed) * (3 + Math.random() * 3);
} else {
direction.dx = (Math.random() - 0.5) * 5;
direction.dy = (Math.random() - 0.5) * 5;
}
ludoGameState.ghostPieces.push({
element: ghostEl,
x: ghostX,
y: ghostY,
dx: direction.dx,
dy: direction.dy,
index: i
});
}
ludoGameState.ghostActive = true;
document.getElementById('ludoBlueDice').classList.add('disabled');
document.getElementById('ludoRedDice').classList.add('disabled');
let elapsed = 0;
const ghostInterval = setInterval(() => {
if (!ludoGameState.ghostActive) {
clearInterval(ghostInterval);
return;
}
elapsed += 0.1;
ludoGameState.ghostPieces.forEach(ghost => {
if (Math.random() < 0.04) {
ghost.dx += (Math.random() - 0.5) * 0.6;
ghost.dy += (Math.random() - 0.5) * 0.6;
const currentSpeed = Math.sqrt(ghost.dx * ghost.dx + ghost.dy * ghost.dy);
if (currentSpeed > 0) {
const targetSpeed = 3 + Math.random() * 3;
ghost.dx = (ghost.dx / currentSpeed) * targetSpeed;
ghost.dy = (ghost.dy / currentSpeed) * targetSpeed;
}
}
ghost.x += ghost.dx * 0.4;
ghost.y += ghost.dy * 0.4;
if (ghost.x < 0) { ghost.x = 0; ghost.dx = Math.abs(ghost.dx); }
if (ghost.x > 95) { ghost.x = 95; ghost.dx = -Math.abs(ghost.dx); }
if (ghost.y < 0) { ghost.y = 0; ghost.dy = Math.abs(ghost.dy); }
if (ghost.y > 95) { ghost.y = 95; ghost.dy = -Math.abs(ghost.dy); }
ghost.element.style.left = ghost.x + '%';
ghost.element.style.top = ghost.y + '%';
checkGhostCollision(ghost);
});
if (elapsed >= 20) {
clearInterval(ghostInterval);
endGhostPieces();
}
}, 120);
}
function checkGhostCollision(ghost) {
const board = document.getElementById('ludoBoard');
const boardRect = board.getBoundingClientRect();
const ghostScreenX = boardRect.left + (boardRect.width * ghost.x / 100);
const ghostScreenY = boardRect.top + (boardRect.height * ghost.y / 100);
ludoGameState.bluePieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === 'blue' && s.pieceId === piece.id);
const pieceEl = document.querySelector(`.ludo-blue-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const pieceRect = pieceEl.getBoundingClientRect();
const dx = ghostScreenX - (pieceRect.left + pieceRect.width/2);
const dy = ghostScreenY - (pieceRect.top + pieceRect.height/2);
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 40) {
if (hasShield) {
ludoShowMessage(`🛡️ مهره آبی ${piece.id} توسط سپر از روح محافظت شد!`, 'success');
} else {
ludoShowMessage(`👻 مهره آبی ${piece.id} توسط روح حذف شد!`, 'error');
ludoReturnPieceToHome('blue', piece);
}
}
}
}
});
ludoGameState.redPieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === 'red' && s.pieceId === piece.id);
const pieceEl = document.querySelector(`.ludo-red-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const pieceRect = pieceEl.getBoundingClientRect();
const dx = ghostScreenX - (pieceRect.left + pieceRect.width/2);
const dy = ghostScreenY - (pieceRect.top + pieceRect.height/2);
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 40) {
if (hasShield) {
ludoShowMessage(`🛡️ مهره قرمز ${piece.id} توسط سپر از روح محافظت شد!`, 'success');
} else {
ludoShowMessage(`👻 مهره قرمز ${piece.id} توسط روح حذف شد!`, 'error');
ludoReturnPieceToHome('red', piece);
}
}
}
}
});
}
function endGhostPieces() {
ludoGameState.ghostActive = false;
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
if (!ludoGameState.gameEnded && !ludoGameState.isDrawGame) {
document.getElementById('ludoBlueDice').classList.remove('disabled');
document.getElementById('ludoRedDice').classList.remove('disabled');
}
ludoShowMessage('👻 روحها ناپدید شدند! بازی ادامه مییابد.', 'info');
const moveInfo = ludoGameState.pendingGhostMove;
if (moveInfo) {
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
} else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
ludoGameState.pendingGhostMove = null;
setTimeout(() => { ludoNextTurn(); }, 1000);
} else {
setTimeout(() => { ludoNextTurn(); }, 500);
}
}
function ludoShowGhostHouse(moveInfo) {
ludoGameState.pendingGhostMove = moveInfo;
ludoShowMessage('👻 مهره روی خانه روح افتاد! جامپ اسکر...', 'warning');
showGhostJumpscare().then(() => {
startGhostPieces();
});
}
// ==============================
// ===== انیمیشن شبیهسازی =====
// ==============================
function showSimulationImages() {
return new Promise((resolve) => {
const overlay = document.getElementById('simulationImageOverlay');
const imgDisplay = document.getElementById('simulationImageDisplay');
ludoPlaySimulationSound();
let imageIndex = 0;
const images = [
'https://cdn.imgurl.ir/uploads/t27210_----.jpg',
'https://cdn.imgurl.ir/uploads/32074_images_1.jpg'
];
overlay.classList.add('active');
overlay.style.display = 'flex';
const matrixContainer = document.createElement('div');
matrixContainer.style.position = 'absolute';
matrixContainer.style.top = '0';
matrixContainer.style.left = '0';
matrixContainer.style.width = '100%';
matrixContainer.style.height = '100%';
matrixContainer.style.pointerEvents = 'none';
matrixContainer.style.overflow = 'hidden';
matrixContainer.style.zIndex = '0';
const chars = '01アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
for (let i = 0; i < 30; i++) {
const rain = document.createElement('div');
rain.className = 'simulation-matrix-rain';
rain.style.left = (Math.random() * 95) + '%';
rain.style.top = '-10%';
rain.style.fontSize = (14 + Math.random() * 20) + 'px';
rain.style.animationDuration = (1.5 + Math.random() * 2) + 's';
rain.style.animationDelay = (Math.random() * 1.5) + 's';
let text = '';
for (let j = 0; j < 15 + Math.random() * 20; j++) {
text += chars[Math.floor(Math.random() * chars.length)];
}
rain.textContent = text;
matrixContainer.appendChild(rain);
}
for (let i = 0; i < 20; i++) {
const code = document.createElement('div');
code.className = 'simulation-matrix-code';
code.style.left = (Math.random() * 95) + '%';
code.style.top = (Math.random() * 95) + '%';
code.style.fontSize = (12 + Math.random() * 18) + 'px';
code.style.animationDuration = (1.5 + Math.random() * 2) + 's';
code.style.animationDelay = (Math.random() * 2) + 's';
let text = '';
for (let j = 0; j < 5 + Math.random() * 8; j++) {
text += chars[Math.floor(Math.random() * chars.length)];
}
code.textContent = text;
matrixContainer.appendChild(code);
}
for (let i = 0; i < 8; i++) {
const line = document.createElement('div');
line.className = 'simulation-flash-line';
line.style.left = (Math.random() * 95) + '%';
line.style.animationDuration = (1 + Math.random() * 1.5) + 's';
line.style.animationDelay = (Math.random() * 2) + 's';
matrixContainer.appendChild(line);
}
for (let i = 0; i < 6; i++) {
const ring = document.createElement('div');
ring.className = 'simulation-ring-wave';
ring.style.left = (20 + Math.random() * 60) + '%';
ring.style.top = (20 + Math.random() * 60) + '%';
ring.style.animationDuration = (1 + Math.random() * 1.5) + 's';
ring.style.animationDelay = (Math.random() * 2) + 's';
ring.style.borderColor = ['#00ffff', '#00ffaa', '#00ccff', '#66ffcc'][Math.floor(Math.random() * 4)];
matrixContainer.appendChild(ring);
}
for (let i = 0; i < 10; i++) {
const stream = document.createElement('div');
stream.className = 'simulation-data-stream';
stream.style.left = (Math.random() * 95) + '%';
stream.style.top = '-10%';
stream.style.animationDuration = (1 + Math.random() * 1.5) + 's';
stream.style.animationDelay = (Math.random() * 2) + 's';
stream.style.height = (50 + Math.random() * 100) + 'px';
matrixContainer.appendChild(stream);
}
overlay.appendChild(matrixContainer);
imgDisplay.src = images[0];
imgDisplay.style.animation = 'simImagePulse 0.5s ease-in-out';
imgDisplay.style.position = 'relative';
imgDisplay.style.zIndex = '1';
setTimeout(() => {
imgDisplay.src = images[1];
imgDisplay.style.animation = 'simImagePulse 0.5s ease-in-out';
setTimeout(() => {
let flashCount = 0;
const flashInterval = setInterval(() => {
if (flashCount >= 10) {
clearInterval(flashInterval);
if (matrixContainer.parentNode) matrixContainer.remove();
overlay.classList.remove('active');
overlay.style.display = 'none';
resolve();
return;
}
if (flashCount % 2 === 0) {
imgDisplay.src = images[0];
} else {
imgDisplay.src = images[1];
}
imgDisplay.style.animation = 'simImagePulse 0.2s ease-in-out';
flashCount++;
}, 400);
}, 2000);
}, 2000);
});
}
function showSimulationAnimation() {
return new Promise((resolve) => {
const container = document.getElementById('simulationAnimationContainer');
container.innerHTML = '';
container.classList.add('active');
const overlay = document.createElement('div');
overlay.className = 'simulation-overlay';
container.appendChild(overlay);
for (let i = 0; i < 50; i++) {
const particle = document.createElement('div');
particle.className = 'simulation-particle';
const x = Math.random() * 100;
const y = Math.random() * 100;
const tx = (Math.random() - 0.5) * 300;
const ty = (Math.random() - 0.5) * 300;
particle.style.left = x + '%';
particle.style.top = y + '%';
particle.style.setProperty('--tx', tx + 'px');
particle.style.setProperty('--ty', ty + 'px');
particle.style.animationDuration = (1 + Math.random() * 2) + 's';
particle.style.animationDelay = (Math.random() * 1) + 's';
particle.style.width = (5 + Math.random() * 10) + 'px';
particle.style.height = (5 + Math.random() * 10) + 'px';
const colors = ['#00ffff', '#00ffaa', '#00ccff', '#66ffcc', '#99ff99'];
particle.style.background = colors[Math.floor(Math.random() * colors.length)];
container.appendChild(particle);
}
for (let i = 0; i < 8; i++) {
const dna = document.createElement('div');
dna.className = 'simulation-dna';
const x = 20 + Math.random() * 60;
const y = 10 + Math.random() * 80;
dna.style.left = x + '%';
dna.style.top = y + '%';
dna.style.height = (100 + Math.random() * 100) + 'px';
dna.style.animationDelay = (i * 0.2) + 's';
dna.style.animationDuration = (0.8 + Math.random() * 0.4) + 's';
dna.style.opacity = 0.3 + Math.random() * 0.4;
container.appendChild(dna);
}
for (let i = 0; i < 15; i++) {
setTimeout(() => {
const spiral = document.createElement('div');
spiral.className = 'simulation-spiral';
const x = 20 + Math.random() * 60;
const y = 20 + Math.random() * 60;
spiral.style.left = x + '%';
spiral.style.top = y + '%';
spiral.style.width = (50 + Math.random() * 100) + 'px';
spiral.style.height = (50 + Math.random() * 100) + 'px';
spiral.style.borderColor = ['#00ffff', '#00ffaa', '#00ccff', '#66ffcc'][Math.floor(Math.random() * 4)];
spiral.style.animationDuration = (1 + Math.random()) + 's';
container.appendChild(spiral);
}, i * 100);
}
const chars2 = '01アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
for (let i = 0; i < 20; i++) {
const code = document.createElement('div');
code.className = 'simulation-matrix-code';
code.style.left = (Math.random() * 95) + '%';
code.style.top = (Math.random() * 95) + '%';
code.style.fontSize = (12 + Math.random() * 18) + 'px';
code.style.animationDuration = (1.5 + Math.random() * 2) + 's';
code.style.animationDelay = (Math.random() * 2) + 's';
let text = '';
for (let j = 0; j < 5 + Math.random() * 8; j++) {
text += chars2[Math.floor(Math.random() * chars2.length)];
}
code.textContent = text;
container.appendChild(code);
}
setTimeout(() => {
container.classList.remove('active');
container.innerHTML = '';
resolve();
}, 5000);
});
}
function createSimulationPieces(team, sourcePiece, targetPieces) {
const simPieces = [];
targetPieces.forEach((targetPiece, index) => {
let targetPos = targetPiece.position - 2;
if (targetPos < 1) targetPos = 1;
if (targetPiece.position <= 2) return;
const simPiece = {
id: sourcePiece.id,
team: team,
position: targetPos,
isOnBoard: true,
isInHome: false,
inWinnerCell: false,
isSimulation: true,
originalId: sourcePiece.id,
targetPieceId: targetPiece.id,
targetTeam: targetPiece.team,
roundsLeft: 8,
index: index,
pieceId: sourcePiece.id
};
simPieces.push(simPiece);
ludoGameState.simulationPieces.push(simPiece);
});
return simPieces;
}
function ludoShowSimulationEffect(moveInfo) {
const team = moveInfo.team;
const sourcePiece = moveInfo.piece;
const opponentTeam = team === 'blue' ? 'red' : 'blue';
const opponentPieces = opponentTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const validTargets = opponentPieces.filter(p =>
p.isOnBoard &&
!p.inWinnerCell &&
p.jailRemainingSeconds === 0 &&
p.position > 2 &&
!p.isSimulation
);
if (validTargets.length === 0) {
ludoShowMessage('❌ هیچ مهرهای برای شبیهسازی وجود ندارد! حرکت لغو شد.', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(team, moveInfo.piece);
setTimeout(() => { ludoNextTurn(); }, 1000);
return;
}
ludoGameState.simulationMoveInfo = moveInfo;
ludoGameState.simulationActive = true;
ludoGameState.simulationRoundsLeft = 8;
ludoGameState.simulationRoundsElapsed = 0;
ludoGameState.simulationLocked = true;
ludoUpdateSimulationLocks();
ludoShowMessage(`🧬 شروع شبیهسازی! ${validTargets.length} مهره شبیهسازی میشوند.`, 'success');
showSimulationImages().then(async () => {
await showSimulationAnimation();
const simPieces = createSimulationPieces(team, sourcePiece, validTargets);
simPieces.forEach(simPiece => {
ludoCreateSimulationPiece(simPiece);
});
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(team, moveInfo.piece);
} else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
ludoGameState.simulationActive = false;
ludoGameState.simulationMoveInfo = null;
ludoShowMessage(`🧬 ${simPieces.length} مهره شبیهسازی شدند! ${ludoGameState.simulationRoundsLeft} راند باقی مانده.`, 'success');
setTimeout(() => {
ludoCheckSimulationConditions();
}, 500);
setTimeout(() => { ludoNextTurn(); }, 1500);
});
}
function ludoCreateSimulationPiece(simPiece) {
const cell = ludoGameState.boardElements[simPiece.position];
if (!cell) return;
const pieceEl = document.createElement('div');
const className = `ludo-simulation-piece ludo-simulation-piece-${simPiece.team}`;
pieceEl.className = className;
pieceEl.textContent = simPiece.id;
pieceEl.dataset.simId = `sim-${simPiece.team}-${simPiece.id}-${simPiece.index}`;
pieceEl.dataset.simPiece = JSON.stringify(simPiece);
const tag = document.createElement('div');
tag.className = 'sim-tag';
tag.textContent = `🧬 ${simPiece.roundsLeft}`;
pieceEl.appendChild(tag);
pieceEl.onclick = function(e) {
e.stopPropagation();
ludoSelectSimulationPiece(simPiece.team, simPiece);
};
const rect = cell.getBoundingClientRect();
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
const offsetX = Math.random() * 20 + 5;
const offsetY = Math.random() * 20 + 5;
pieceEl.style.left = (rect.left - boardRect.left + offsetX) + 'px';
pieceEl.style.top = (rect.top - boardRect.top + offsetY) + 'px';
document.getElementById('ludoBoard').appendChild(pieceEl);
}
function ludoUpdateSimulationRounds() {
if (ludoGameState.simulationPieces.length === 0) return;
ludoGameState.simulationRoundsElapsed++;
const toRemove = [];
ludoGameState.simulationPieces.forEach((simPiece, index) => {
simPiece.roundsLeft--;
const pieceEl = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (pieceEl) {
const tag = pieceEl.querySelector('.sim-tag');
if (tag) {
tag.textContent = `🧬 ${simPiece.roundsLeft}`;
}
}
if (simPiece.roundsLeft <= 0) {
toRemove.push(index);
}
});
toRemove.sort((a, b) => b - a).forEach(index => {
const simPiece = ludoGameState.simulationPieces[index];
const pieceEl = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (pieceEl && pieceEl.parentNode) {
pieceEl.style.transition = 'all 0.5s ease-in';
pieceEl.style.opacity = '0';
pieceEl.style.transform = 'scale(0) rotate(180deg)';
setTimeout(() => {
if (pieceEl.parentNode) pieceEl.parentNode.removeChild(pieceEl);
}, 500);
}
ludoGameState.simulationPieces.splice(index, 1);
});
if (ludoGameState.simulationPieces.length === 0) {
ludoGameState.simulationActive = false;
ludoGameState.simulationLocked = false;
ludoUpdateSimulationLocks();
ludoCheckSimulationConditions();
ludoShowMessage('🧬 تمام مهرههای شبیهسازی ناپدید شدند!', 'info');
} else {
ludoShowMessage(`🧬 ${ludoGameState.simulationPieces.length} مهره شبیهسازی باقی مانده (${ludoGameState.simulationPieces[0].roundsLeft} راند)`, 'info');
}
}
function ludoMoveSimulationPiece(simPiece, newPosition) {
const oldPosition = simPiece.position;
simPiece.position = newPosition;
const pieceEl = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (pieceEl) {
const cell = ludoGameState.boardElements[newPosition];
if (cell) {
const rect = cell.getBoundingClientRect();
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
pieceEl.style.left = (rect.left - boardRect.left + 10) + 'px';
pieceEl.style.top = (rect.top - boardRect.top + 10) + 'px';
pieceEl.style.transition = 'all 0.3s ease-in-out';
}
}
const opponentTeam = simPiece.team === 'blue' ? 'red' : 'blue';
const opponentPieces = opponentTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const targetPiece = opponentPieces.find(p => p.position === newPosition && p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
if (targetPiece) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === opponentTeam && s.pieceId === targetPiece.id);
if (hasShield) {
ludoShowMessage(`🛡️ مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${targetPiece.id} توسط سپر از مهره شبیهساز محافظت شد!`, 'success');
} else {
ludoShowMessage(`💥 مهره شبیهساز ${simPiece.team === 'blue' ? 'آبی' : 'قرمز'} ${simPiece.id} مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${targetPiece.id} را حذف کرد!`, 'error');
ludoReturnPieceToHome(opponentTeam, targetPiece);
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === opponentTeam && w.occupiedBy.pieceId === targetPiece.id);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (opponentTeam === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
targetPiece.inWinnerCell = false;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
}
}
function ludoGetSimulationPiecesForTeam(team) {
return ludoGameState.simulationPieces.filter(p => p.team === team);
}
// ==============================
// ===== انتخاب و حرکت مهرههای شبیهساز =====
// ==============================
function ludoSelectSimulationPiece(team, simPiece) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) { ludoShowMessage('🎮 بازی تمام شده است!', 'warning'); return; }
if (ludoGameState.currentTurn !== team || ludoGameState.inQuestionMode || ludoGameState.isMovingPiece || ludoGameState.inDealMode || ludoGameState.rainbowActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) {
ludoShowMessage(`❌ الان نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} است!`, 'error');
return;
}
if (!ludoGameState.diceRolled) { ludoShowMessage('❌ ابتدا تاس بیندازید!', 'error'); return; }
if (simPiece.roundsLeft <= 0) { ludoShowMessage('❌ این مهره شبیهساز تمام شده است!', 'error'); return; }
if (!ludoCanMoveSimulationPiece(simPiece)) {
ludoShowMessage('❌ این مهره شبیهساز قابل حرکت نیست!', 'error');
return;
}
ludoMoveSimulationPieceOnBoard(simPiece);
}
function ludoCanMoveSimulationPiece(simPiece) {
if (ludoGameState.currentDiceValue === 0) return false;
if (simPiece.roundsLeft <= 0) return false;
const diceValue = ludoGameState.currentDiceValue;
if (diceValue < 0) {
if (simPiece.position === 1) return false;
const newPosition = simPiece.position + diceValue;
return newPosition >= 1;
}
const newPosition = simPiece.position + diceValue;
if (newPosition > 120) return false;
if (newPosition < 1) return false;
const winnerCell = ludoGameState.winnerCells.find(w => w.number === newPosition);
if (winnerCell) return false;
return true;
}
function ludoMoveSimulationPieceOnBoard(simPiece) {
const diceValue = ludoGameState.currentDiceValue;
const newPosition = simPiece.position + diceValue;
if (newPosition < 1) { ludoShowMessage('❌ نمیتوانید از خانه 1 عقبتر بروید!', 'error'); return; }
if (newPosition > 120) { ludoShowMessage('❌ نمیتوانید از خانه 120 فراتر بروید!', 'error'); return; }
const winnerCell = ludoGameState.winnerCells.find(w => w.number === newPosition);
if (winnerCell) { ludoShowMessage('❌ مهره شبیهساز نمیتواند وارد خانه برنده شود!', 'error'); return; }
const oldPosition = simPiece.position;
const pieceEl = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
const steps = Math.abs(diceValue);
let currentStep = 0;
const direction = diceValue > 0 ? 1 : -1;
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
function moveStep() {
if (currentStep >= steps) {
simPiece.position = newPosition;
ludoShowMessage(`🧬 مهره شبیهساز ${simPiece.team === 'blue' ? 'آبی' : 'قرمز'} از ${oldPosition} به ${newPosition} حرکت کرد.`, 'info');
const opponentTeam = simPiece.team === 'blue' ? 'red' : 'blue';
const opponentPieces = opponentTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const targetPiece = opponentPieces.find(p => p.position === newPosition && p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
if (targetPiece) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === opponentTeam && s.pieceId === targetPiece.id);
if (hasShield) {
ludoShowMessage(`🛡️ مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${targetPiece.id} توسط سپر محافظت شد!`, 'success');
} else {
ludoShowMessage(`💥 مهره شبیهساز ${simPiece.team === 'blue' ? 'آبی' : 'قرمز'} ${simPiece.id} مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${targetPiece.id} را حذف کرد!`, 'error');
ludoReturnPieceToHome(opponentTeam, targetPiece);
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === opponentTeam && w.occupiedBy.pieceId === targetPiece.id);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (opponentTeam === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
targetPiece.inWinnerCell = false;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
}
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
if (ludoGameState.extraTurn) {
ludoGameState.extraTurn = false;
ludoGameState.diceRolled = false;
ludoUpdateDisplay();
ludoShowMessage(`🎲 نوبت اضافه! دوباره تاس بزنید.`, 'info');
} else {
setTimeout(() => { ludoNextTurn(); }, 500);
}
ludoUpdateDisplay();
return;
}
currentStep++;
const tempPosition = oldPosition + (currentStep * direction);
const tempCell = ludoGameState.boardElements[tempPosition];
if (tempCell && pieceEl) {
const rect = tempCell.getBoundingClientRect();
pieceEl.style.left = (rect.left - boardRect.left + 10) + 'px';
pieceEl.style.top = (rect.top - boardRect.top + 10) + 'px';
pieceEl.style.transition = 'all 0.3s ease-in-out';
setTimeout(moveStep, 300);
} else {
simPiece.position = newPosition;
if (pieceEl) {
const cell = ludoGameState.boardElements[newPosition];
if (cell) {
const rect = cell.getBoundingClientRect();
pieceEl.style.left = (rect.left - boardRect.left + 10) + 'px';
pieceEl.style.top = (rect.top - boardRect.top + 10) + 'px';
}
}
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
setTimeout(() => { ludoNextTurn(); }, 500);
ludoUpdateDisplay();
}
}
if (pieceEl) {
moveStep();
} else {
simPiece.position = newPosition;
ludoShowMessage(`🧬 مهره شبیهساز ${simPiece.team === 'blue' ? 'آبی' : 'قرمز'} از ${oldPosition} به ${newPosition} حرکت کرد.`, 'info');
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
setTimeout(() => { ludoNextTurn(); }, 500);
ludoUpdateDisplay();
}
}
// ==============================
// ===== توابع اصلی بازی =====
// ==============================
function ludoHighlightAvailablePieces(team) {
const pieces = team === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const containerId = 'ludo' + team.charAt(0).toUpperCase() + team.slice(1) + 'PiecesContainer';
const container = document.getElementById(containerId);
container.querySelectorAll('.ludo-piece-in-home').forEach(piece => { piece.classList.remove('ludo-highlight'); });
document.querySelectorAll(`.ludo-${team}-on-board`).forEach(piece => { piece.classList.remove('ludo-highlight'); });
document.querySelectorAll(`.ludo-simulation-piece`).forEach(piece => { piece.classList.remove('ludo-highlight'); });
// چک کردن اجبار هکر
const forcedPieceId = ludoGetForcedPieceId(team);
const isForced = forcedPieceId !== null;
// اگر تحت اجبار هستیم، فقط مهره اجباری قابل انتخاب باشه
pieces.forEach(piece => {
// اگر تحت اجبار هستیم و این مهره اجباری نیست، هایلایت نشود
if (isForced && forcedPieceId !== piece.id) {
return;
}
if (ludoCanMovePiece(piece, team)) {
if (piece.isInHome && !piece.isOnBoard) {
const pieceEl = container.querySelector(`.ludo-piece-in-home:nth-child(${piece.id})`);
if (pieceEl) pieceEl.classList.add('ludo-highlight');
}
else if (piece.isOnBoard) {
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) pieceEl.classList.add('ludo-highlight');
}
}
});
const simPieces = ludoGetSimulationPiecesForTeam(team);
simPieces.forEach(simPiece => {
if (ludoCanMoveSimulationPiece(simPiece)) {
const pieceEl = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (pieceEl) pieceEl.classList.add('ludo-highlight');
}
});
}
function ludoCanMovePiece(piece, team) {
if (piece.jailRemainingSeconds > 0) {
const minutes = Math.floor(piece.jailRemainingSeconds / 60);
const seconds = piece.jailRemainingSeconds % 60;
ludoShowMessage(`🔒 مهره ${piece.id} تیم ${team === 'blue' ? 'آبی' : 'قرمز'} به مدت ${minutes}:${seconds.toString().padStart(2,'0')} در زندان است!`, 'warning');
return false;
}
if (piece.isSimulation) return false;
// چک کردن اجبار هکر - فقط مهره اجباری قابل حرکت
const forcedPieceId = ludoGetForcedPieceId(team);
if (forcedPieceId !== null && forcedPieceId !== piece.id) {
return false;
}
const diceValue = ludoGameState.currentDiceValue;
if (diceValue < 0) {
if (piece.isInHome && !piece.isOnBoard) return false;
if (piece.position === 1) return false;
if (piece.inWinnerCell) return false;
const newPosition = piece.position + diceValue;
return newPosition >= 1;
}
if (piece.isInHome && !piece.isOnBoard) return diceValue === 6;
if (piece.inWinnerCell) return false;
if (!piece.isOnBoard) return false;
const newPosition = piece.position + diceValue;
if (newPosition > 120) return false;
const winnerCell = ludoGameState.winnerCells.find(w => w.number === newPosition);
if (winnerCell && winnerCell.occupied) return false;
if (ludoGameState.jailCells.includes(newPosition)) {
const jailCell = newPosition;
const occupant = [...ludoGameState.bluePieces, ...ludoGameState.redPieces].find(p => p.position === jailCell && p.isOnBoard && p !== piece && !p.isSimulation);
if (occupant) {
ludoShowMessage(`🔒 خانه زندان ${jailCell} پر است! نمیتوانید وارد شوید.`, 'error');
return false;
}
}
return true;
}
function ludoHasMovablePieces(team) {
const pieces = team === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const hasNormalMove = pieces.some(piece => ludoCanMovePiece(piece, team));
const simPieces = ludoGetSimulationPiecesForTeam(team);
const hasSimMove = simPieces.some(simPiece => ludoCanMoveSimulationPiece(simPiece));
return hasNormalMove || hasSimMove;
}
function ludoSelectPiece(team, pieceId) {
if (ludoGameState.gameEnded || ludoGameState.isDrawGame) { ludoShowMessage('🎮 بازی تمام شده است! برای شروع جدید بازی را ریست کنید.', 'warning'); return; }
if (ludoGameState.currentTurn !== team || ludoGameState.inQuestionMode || ludoGameState.isMovingPiece || ludoGameState.inDealMode || ludoGameState.rainbowActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) { ludoShowMessage(`❌ الان نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} است!`, 'error'); return; }
if (!ludoGameState.diceRolled) { ludoShowMessage('❌ ابتدا تاس بیندازید!', 'error'); return; }
// چک کردن اجبار هکر
const forcedPieceId = ludoGetForcedPieceId(team);
if (forcedPieceId !== null && forcedPieceId !== pieceId) {
ludoShowMessage(`❌ شما فقط میتوانید مهره ${forcedPieceId} را حرکت دهید! (اجبار هکر)`, 'error');
return;
}
const pieces = team === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const piece = pieces.find(p => p.id === pieceId);
if (!piece) { ludoShowMessage('❌ مهره پیدا نشد!', 'error'); return; }
if (piece.jailRemainingSeconds > 0) { ludoShowMessage(`🔒 مهره ${pieceId} ${team === 'blue' ? 'آبی' : 'قرمز'} در زندان است!`, 'warning'); return; }
if (piece.isInHome && !piece.isOnBoard) {
if (ludoGameState.currentDiceValue === 6) {
ludoEnterPieceToBoard(team, piece);
} else {
ludoShowMessage('❌ فقط با عدد ۶ میتوانید مهره وارد کنید!', 'error');
}
return;
}
if (!piece.isOnBoard) { ludoShowMessage('❌ این مهره هنوز وارد بازی نشده است!', 'error'); return; }
if (!ludoCanMovePiece(piece, team)) { ludoShowMessage('❌ این مهره قابل حرکت نیست!', 'error'); return; }
ludoGameState.selectedPiece = { team, pieceId };
ludoMovePieceOnBoard(team, piece);
}
function ludoEnterPieceToBoard(team, piece) {
piece.isInHome = false;
piece.isOnBoard = true;
piece.position = 1;
ludoUpdateHomeDisplay(team, piece.id, false);
ludoCreatePieceOnBoard(team, piece);
ludoShowMessage(`✅ مهره ${piece.id} ${team === 'blue' ? 'آبی' : 'قرمز'} وارد بازی شد.`, 'success');
ludoHighlightAvailablePieces(team);
ludoCheckAndRemoveOpponentPiece(team, 1, 0);
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
ludoGameState.justRolledSix.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
ludoGameState.justRolledSix.red = false;
}
ludoUpdateSaveButtons();
if (ludoGameState.extraTurn && !ludoGameState.justCameFromQuestion) {
ludoGameState.diceRolled = false;
ludoGameState.extraTurn = false;
ludoUpdateDisplay();
ludoShowMessage(`🎲 چون ۶ آوردهاید، دوباره میتوانید تاس بیندازید!`, 'info');
}
else ludoNextTurn();
ludoUpdateDisplay();
}
function ludoMovePieceOnBoard(team, piece) {
const diceValue = ludoGameState.currentDiceValue;
const newPosition = piece.position + diceValue;
if (newPosition < 1) { ludoShowMessage('❌ نمیتوانید از خانه 1 عقبتر بروید!', 'error'); return; }
if (newPosition > 120) { ludoShowMessage('❌ نمیتوانید از خانه 120 فراتر بروید!', 'error'); return; }
if (ludoGameState.jailCells.includes(newPosition)) {
const jailCell = newPosition;
const occupant = [...ludoGameState.bluePieces, ...ludoGameState.redPieces].find(p => p.position === jailCell && p.isOnBoard && p !== piece && !p.isSimulation);
if (occupant) {
ludoShowMessage(`🔒 خانه زندان ${jailCell} توسط مهره ${occupant.id} تیم ${occupant.team === 'blue' ? 'آبی' : 'قرمز'} اشغال شده است! حرکت این مهره کنسل شد.`, 'error');
if (ludoHasMovablePieces(team)) {
ludoShowMessage(`⚠️ تیم ${team === 'blue' ? 'آبی' : 'قرمز'} مهرههای دیگری دارد که میتوانند حرکت کنند. تاس تغییر نمیکند.`, 'warning');
ludoHighlightAvailablePieces(team);
} else {
ludoShowMessage(`❌ هیچ مهره قابل حرکت دیگری نیست! نوبت به حریف میرسد.`, 'error');
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
ludoGameState.justRolledSix.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
ludoGameState.justRolledSix.red = false;
}
ludoUpdateSaveButtons();
setTimeout(() => { ludoNextTurn(); }, 1500);
}
return;
}
}
if (team === 'blue') {
ludoGameState.saveLocked.blue = true;
ludoGameState.canSaveAfterRoll.blue = false;
ludoGameState.justRolledSix.blue = false;
} else {
ludoGameState.saveLocked.red = true;
ludoGameState.canSaveAfterRoll.red = false;
ludoGameState.justRolledSix.red = false;
}
ludoUpdateSaveButtons();
const moveInfo = { team: team, piece: piece, newPosition: newPosition, oldPosition: piece.position };
// چک کردن خانه هکینگ دیوایس
if (ludoGameState.hackerDeviceCell === newPosition && !ludoGameState.hackerDeviceCollected.blue && !ludoGameState.hackerDeviceCollected.red) {
const collectedTeam = team;
ludoGameState.hackerDeviceCollected[team] = true;
ludoGameState.hackerDeviceTeam = team;
// حذف آیتم از خانه
const cell = ludoGameState.boardElements[newPosition];
if (cell) {
const icon = cell.querySelector('.hacker-device-icon');
const text = cell.querySelector('.hacker-device-text');
if (icon) icon.remove();
if (text) text.remove();
cell.classList.remove('ludo-hacker-device-cell');
}
ludoShowMessage(`💻 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} آیتم هکینگ دیوایس را پیدا کرد! گزینه هکر فعال شد.`, 'success');
ludoUpdateSaveButtons();
}
if (ludoGameState.simulationCells.includes(newPosition)) {
if (ludoGameState.simulationLocked || ludoGameState.simulationActive) {
ludoShowMessage(`🧬 مهره روی خانه شبیهسازی قفل شده رفت. هیچ اتفاقی نمیافتد.`, 'info');
ludoAnimatePieceMove(team, piece, newPosition, false, false, false, false, false, false, false);
return;
} else {
const opponentTeam = team === 'blue' ? 'red' : 'blue';
const opponentPieces = opponentTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const validTargets = opponentPieces.filter(p =>
p.isOnBoard &&
!p.inWinnerCell &&
p.jailRemainingSeconds === 0 &&
p.position > 2 &&
!p.isSimulation
);
if (validTargets.length === 0) {
ludoShowMessage('❌ هیچ مهرهای برای شبیهسازی وجود ندارد! حرکت کنسل شد.', 'error');
if (ludoHasMovablePieces(team)) {
ludoHighlightAvailablePieces(team);
} else {
ludoShowMessage('❌ هیچ مهره قابل حرکت دیگری نیست! نوبت به حریف میرسد.', 'error');
setTimeout(() => { ludoNextTurn(); }, 1500);
}
return;
}
ludoAnimatePieceMove(team, piece, newPosition, false, false, false, false, false, false, true);
return;
}
}
if (ludoGameState.questionCells.includes(newPosition)) { ludoGameState.pendingQuestionMove = moveInfo; ludoAnimatePieceMove(team, piece, newPosition, true); }
else if (ludoGameState.luckCells.includes(newPosition)) ludoAnimatePieceMove(team, piece, newPosition, false, true);
else if (ludoGameState.explosionCells.includes(newPosition)) ludoAnimatePieceMove(team, piece, newPosition, false, false, true);
else if (ludoGameState.dealCells.includes(newPosition)) ludoAnimatePieceMove(team, piece, newPosition, false, false, false, true);
else if (ludoGameState.rainbowCells.includes(newPosition)) ludoAnimatePieceMove(team, piece, newPosition, false, false, false, false, true);
else if (ludoGameState.ghostCell === newPosition) ludoAnimatePieceMove(team, piece, newPosition, false, false, false, false, false, true);
else ludoAnimatePieceMove(team, piece, newPosition, false, false);
}
function ludoAnimatePieceMove(team, piece, newPosition, isQuestionCell = false, isLuckCell = false, isExplosionCell = false, isDealCell = false, isRainbowCell = false, isGhostCell = false, isSimulationCell = false) {
ludoGameState.isMovingPiece = true;
const oldPosition = piece.position;
const steps = Math.abs(ludoGameState.currentDiceValue);
let currentStep = 0;
const direction = ludoGameState.currentDiceValue > 0 ? 1 : -1;
const pieceElement = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (!pieceElement) {
piece.position = newPosition;
ludoGameState.isMovingPiece = false;
if (isSimulationCell) {
ludoShowSimulationEffect({ team, piece, newPosition, oldPosition });
} else {
ludoCheckSpecialCells(team, piece, newPosition);
}
return;
}
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
function moveStep() {
if (currentStep >= steps) {
piece.position = newPosition;
ludoGameState.isMovingPiece = false;
if (isSimulationCell) {
ludoShowSimulationEffect({ team, piece, newPosition, oldPosition });
return;
}
if (isQuestionCell && ludoGameState.pendingQuestionMove) {
ludoPlayQuestionSound();
ludoGameState.questionAnswered = false;
setTimeout(() => { ludoShowGeneralQuestion(ludoGameState.pendingQuestionMove); ludoGameState.pendingQuestionMove = null; }, 500);
return;
}
else if (isLuckCell) {
setTimeout(() => { ludoShowGoldenDice(team, piece, oldPosition); }, 500);
return;
}
else if (isExplosionCell) {
setTimeout(() => { ludoShowExplosionConfirmation({ team, piece, newPosition, oldPosition }); }, 500);
return;
}
else if (isDealCell) {
ludoPlayDealSound();
setTimeout(() => { ludoShowDealScreen({ team, piece, newPosition, oldPosition }); }, 500);
return;
}
else if (isRainbowCell) {
setTimeout(() => { ludoShowRainbowConfirmation({ team, piece, newPosition, oldPosition }); }, 500);
return;
}
else if (isGhostCell) {
setTimeout(() => { ludoShowGhostHouse({ team, piece, newPosition, oldPosition }); }, 500);
return;
}
ludoCheckSpecialCells(team, piece, newPosition);
ludoShowMessage(`➡️ مهره ${piece.id} ${team === 'blue' ? 'آبی' : 'قرمز'} به خانه ${newPosition} رفت.`, 'info');
return;
}
currentStep++;
const tempPosition = oldPosition + (currentStep * direction);
const tempCell = ludoGameState.boardElements[tempPosition];
if (tempCell) {
const rect = tempCell.getBoundingClientRect();
const offsetX = Math.random() * 20 + 5;
const offsetY = Math.random() * 20 + 5;
pieceElement.style.left = (rect.left - boardRect.left + offsetX) + 'px';
pieceElement.style.top = (rect.top - boardRect.top + offsetY) + 'px';
pieceElement.style.transition = 'all 0.3s ease-in-out';
setTimeout(moveStep, 300);
} else {
setTimeout(moveStep, 300);
}
}
moveStep();
}
// ==============================
// ===== توابع خانههای ویژه =====
// ==============================
function ludoShowGoldenDice(team, piece, oldPosition) {
ludoShowMessage(`🎲 تیم ${team === 'blue' ? 'آبی' : 'قرمز'} روی خانه شانس افتاد! تاس طلایی ظاهر شد.`, 'success');
ludoGameState.goldenDiceActive = true;
ludoGameState.goldenDiceMoveInfo = { team: team, piece: piece, oldPosition: oldPosition };
const goldenDiceModal = document.getElementById('ludoGoldenDiceModal');
const goldenDice = document.getElementById('ludoGoldenDice');
goldenDice.textContent = '🎲';
goldenDice.classList.remove('negative');
goldenDiceModal.style.display = 'flex';
}
function updateDealCustomValue(side, optionNumber) {
const input = document.getElementById(`${side}-deal-input-${optionNumber}`);
if (!input) return;
let value = input.value.trim();
if (value === '') {
ludoGameState.dealCustomValues[side][optionNumber] = null;
checkDealExecuteButton();
return;
}
let numValue = parseInt(value);
if (isNaN(numValue)) {
input.value = '';
ludoGameState.dealCustomValues[side][optionNumber] = null;
checkDealExecuteButton();
return;
}
const min = optionNumber === 9 ? 1 : 1;
const max = optionNumber === 9 ? 10 : 15;
if (numValue < min) numValue = min;
if (numValue > max) numValue = max;
input.value = numValue;
ludoGameState.dealCustomValues[side][optionNumber] = numValue;
const optionElement = document.querySelector(`.ludo-deal-option[data-side="${side}"][data-option="${optionNumber}"]`);
if (optionElement && optionElement.classList.contains('selected')) {
checkDealExecuteButton();
}
}
function ludoShowDealScreen(moveInfo) {
ludoGameState.inDealMode = true;
ludoGameState.dealMoveInfo = moveInfo;
ludoGameState.selectedDealOptions = { red: null, blue: null };
ludoGameState.selectedDealPieces = { red: { 4: [], 6: [], 10: [] }, blue: { 4: [], 6: [], 10: [] } };
ludoGameState.dealCustomValues = { red: { 9: null, 10: null }, blue: { 9: null, 10: null } };
document.querySelectorAll('.ludo-deal-option').forEach(opt => {
opt.classList.remove('selected', 'disabled');
});
document.querySelectorAll('.ludo-deal-piece-selector').forEach(selector => {
selector.style.display = 'none';
});
document.querySelectorAll('.ludo-deal-custom-input').forEach(input => {
input.classList.remove('visible');
});
document.querySelectorAll('.ludo-deal-custom-input input').forEach(input => {
input.value = '';
});
document.getElementById('ludoDealExecuteBtn').disabled = true;
document.getElementById('ludoDealModal').style.display = 'flex';
ludoShowMessage(`💰 تیم ${moveInfo.team === 'blue' ? 'آبی' : 'قرمز'} روی خانه معامله افتاد! هر دو تیم یک گزینه انتخاب کنند.`, 'info');
}
function selectDealOption(side, optionNumber) {
if (ludoGameState.selectedDealOptions[side] !== null) {
const oldOption = ludoGameState.selectedDealOptions[side];
if (oldOption !== optionNumber) {
if ([4,6,10].includes(oldOption)) {
const prevSelectorId = `${side}-deal-pieces-${oldOption}`;
const prevSelector = document.getElementById(prevSelectorId);
if (prevSelector) prevSelector.style.display = 'none';
ludoGameState.selectedDealPieces[side][oldOption] = [];
document.querySelectorAll(`#${prevSelectorId} .ludo-deal-piece-btn`).forEach(btn => btn.classList.remove('selected'));
}
if (oldOption === 9 || oldOption === 10) {
const prevCustomId = `${side}-deal-custom-${oldOption}`;
const prevCustom = document.getElementById(prevCustomId);
if (prevCustom) prevCustom.classList.remove('visible');
const prevInput = document.getElementById(`${side}-deal-input-${oldOption}`);
if (prevInput) {
prevInput.value = '';
ludoGameState.dealCustomValues[side][oldOption] = null;
}
}
const prevOptionElement = document.querySelector(`.ludo-deal-option[data-side="${side}"][data-option="${oldOption}"]`);
if (prevOptionElement) prevOptionElement.classList.remove('selected');
}
}
ludoGameState.selectedDealOptions[side] = optionNumber;
const optionElement = document.querySelector(`.ludo-deal-option[data-side="${side}"][data-option="${optionNumber}"]`);
if (optionElement) optionElement.classList.add('selected');
if (optionNumber === 9 || optionNumber === 10) {
const customId = `${side}-deal-custom-${optionNumber}`;
const custom = document.getElementById(customId);
if (custom) custom.classList.add('visible');
const input = document.getElementById(`${side}-deal-input-${optionNumber}`);
if (input) {
input.focus();
const min = optionNumber === 9 ? 1 : 1;
const max = optionNumber === 9 ? 10 : 15;
input.placeholder = `${min}-${max}`;
}
}
if (optionNumber === 4 || optionNumber === 6 || optionNumber === 10) {
const selectorId = `${side}-deal-pieces-${optionNumber}`;
const selector = document.getElementById(selectorId);
if (selector) {
selector.style.display = 'flex';
const targetTeam = side === 'blue' ? 'red' : 'blue';
const pieces = targetTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const pieceBtns = selector.querySelectorAll('.ludo-deal-piece-btn');
pieceBtns.forEach(btn => {
const pieceId = parseInt(btn.dataset.piece);
const piece = pieces.find(p => p.id === pieceId);
btn.classList.remove('disabled');
if (optionNumber === 6) {
if (!(piece.isInHome && !piece.isOnBoard) || piece.inWinnerCell) btn.classList.add('disabled');
}
else if (optionNumber === 10) {
if (!piece.isOnBoard || piece.inWinnerCell || piece.isInHome) btn.classList.add('disabled');
const hasShield = ludoGameState.shieldEffects.some(s => s.team === targetTeam && s.pieceId === pieceId);
if (hasShield) btn.classList.add('disabled');
}
else {
if (!piece.isOnBoard || piece.inWinnerCell || piece.isInHome) btn.classList.add('disabled');
}
if (piece.jailRemainingSeconds > 0) btn.classList.add('disabled');
});
}
}
ludoShowMessage(`✅ تیم ${side === 'blue' ? 'آبی' : 'قرمز'} گزینه ${optionNumber} را انتخاب کرد.`, 'success');
checkDealExecuteButton();
}
function selectDealPiece(side, optionNumber, pieceId) {
if (ludoGameState.selectedDealOptions[side] !== optionNumber) {
ludoShowMessage(`❌ ابتدا گزینه ${optionNumber} را انتخاب کنید!`, 'error');
return;
}
const targetTeam = side === 'blue' ? 'red' : 'blue';
const pieces = targetTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const piece = pieces.find(p => p.id === pieceId);
if (piece.jailRemainingSeconds > 0) {
ludoShowMessage(`🔒 مهره ${pieceId} در زندان است و نمیتوان آن را انتخاب کرد!`, 'error');
return;
}
if (optionNumber === 6) {
if (!(piece.isInHome && !piece.isOnBoard)) {
ludoShowMessage(`❌ مهره ${pieceId} در خانه نیست!`, 'error');
return;
}
}
else if (optionNumber === 10) {
if (!piece.isOnBoard || piece.isInHome) {
ludoShowMessage(`❌ مهره ${pieceId} داخل بازی نیست!`, 'error');
return;
}
const hasShield = ludoGameState.shieldEffects.some(s => s.team === targetTeam && s.pieceId === pieceId);
if (hasShield) {
ludoShowMessage(`❌ مهره ${pieceId} قبلاً سپر دارد!`, 'error');
return;
}
}
else {
if (!piece.isOnBoard || piece.isInHome) {
ludoShowMessage(`❌ مهره ${pieceId} داخل بازی نیست!`, 'error');
return;
}
}
if (piece.inWinnerCell) {
ludoShowMessage(`❌ مهره ${pieceId} در خانه برنده است!`, 'error');
return;
}
const selectorId = `${side}-deal-pieces-${optionNumber}`;
const selector = document.getElementById(selectorId);
const pieceBtn = selector.querySelector(`.ludo-deal-piece-btn[data-piece="${pieceId}"]`);
if (ludoGameState.selectedDealPieces[side][optionNumber].includes(pieceId)) {
ludoGameState.selectedDealPieces[side][optionNumber] = ludoGameState.selectedDealPieces[side][optionNumber].filter(id => id !== pieceId);
pieceBtn.classList.remove('selected');
ludoShowMessage(`❌ مهره ${pieceId} از لیست حذف شد.`, 'info');
} else {
ludoGameState.selectedDealPieces[side][optionNumber].push(pieceId);
pieceBtn.classList.add('selected');
ludoShowMessage(`✅ مهره ${pieceId} به لیست اضافه شد.`, 'success');
}
checkDealExecuteButton();
}
function checkDealExecuteButton() {
const executeBtn = document.getElementById('ludoDealExecuteBtn');
if (ludoGameState.selectedDealOptions.red === null || ludoGameState.selectedDealOptions.blue === null) {
executeBtn.disabled = true;
return;
}
const sides = ['red', 'blue'];
for (let side of sides) {
const option = ludoGameState.selectedDealOptions[side];
if (option === 4 || option === 6 || option === 10) {
if (ludoGameState.selectedDealPieces[side][option].length === 0) {
executeBtn.disabled = true;
return;
}
}
if (option === 9 || option === 10) {
const input = document.getElementById(`${side}-deal-input-${option}`);
if (input) {
const value = input.value.trim();
if (value === '') {
executeBtn.disabled = true;
return;
}
const numValue = parseInt(value);
if (isNaN(numValue)) {
executeBtn.disabled = true;
return;
}
const min = option === 9 ? 1 : 1;
const max = option === 9 ? 10 : 15;
if (numValue < min || numValue > max) {
executeBtn.disabled = true;
return;
}
ludoGameState.dealCustomValues[side][option] = numValue;
}
}
}
executeBtn.disabled = false;
}
function executeDeal() {
const moveInfo = ludoGameState.dealMoveInfo;
if (!moveInfo) return;
const penaltyQueue = [];
const sides = ['red', 'blue'];
let dicePenalties = [];
for (let side of sides) {
const option = ludoGameState.selectedDealOptions[side];
const targetTeam = side === 'blue' ? 'red' : 'blue';
const targetPieces = targetTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const customValue = ludoGameState.dealCustomValues[side] ? ludoGameState.dealCustomValues[side][option] : 1;
switch(option) {
case 9:
const turns = Math.min(Math.max(customValue, 1), 10);
dicePenalties.push({
team: targetTeam,
turns: turns,
sourceSide: side,
sourceMessage: `🎲 تیم ${side === 'blue' ? 'آبی' : 'قرمز'} باعث شد تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} ${turns} راند تاس بندازد!`
});
break;
case 10:
const shieldTurns = Math.min(Math.max(customValue, 1), 15);
const piecesToShield = ludoGameState.selectedDealPieces[side][10];
piecesToShield.forEach(pieceId => {
const piece = targetPieces.find(p => p.id === pieceId);
if (piece && piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const existingShield = ludoGameState.shieldEffects.find(s => s.team === targetTeam && s.pieceId === pieceId);
if (!existingShield) {
ludoGameState.shieldEffects.push({ team: targetTeam, pieceId: pieceId, turnsLeft: shieldTurns });
const pieceEl = document.querySelector(`.ludo-${targetTeam}-on-board[data-piece-id="${pieceId}"]`);
if (pieceEl) {
const shieldEl = document.createElement('div');
shieldEl.className = 'ludo-shield-effect';
shieldEl.id = `shield-${targetTeam}-${pieceId}`;
pieceEl.appendChild(shieldEl);
const shieldTag = document.createElement('div');
shieldTag.className = 'ludo-shield-tag';
shieldTag.textContent = `🛡️ ${shieldTurns}`;
pieceEl.appendChild(shieldTag);
}
ludoShowMessage(`🛡️ مهره ${pieceId} تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} به مدت ${shieldTurns} راند سپر محافظ گرفت!`, 'success');
}
}
});
break;
case 4:
const piecesToRemove = ludoGameState.selectedDealPieces[side][4];
piecesToRemove.forEach(pieceId => {
const piece = targetPieces.find(p => p.id === pieceId);
if (piece && piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === targetTeam && s.pieceId === pieceId);
if (hasShield) ludoShowMessage(`🛡️ مهره ${pieceId} تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} توسط سپر محافظت شد!`, 'success');
else {
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === targetTeam && w.occupiedBy.pieceId === pieceId);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (targetTeam === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
piece.inWinnerCell = false;
ludoUpdateWinnerCellsDisplay();
}
ludoReturnPieceToHome(targetTeam, piece);
ludoShowMessage(`💀 مهره ${pieceId} تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} حذف شد.`, 'error');
}
}
});
break;
case 6:
const piecesToEnter = ludoGameState.selectedDealPieces[side][6];
piecesToEnter.forEach(pieceId => {
const piece = targetPieces.find(p => p.id === pieceId);
if (piece && piece.isInHome && !piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0) {
piece.isInHome = false;
piece.isOnBoard = true;
piece.position = 1;
ludoUpdateHomeDisplay(targetTeam, pieceId, false);
ludoCreatePieceOnBoard(targetTeam, piece);
ludoCheckAndRemoveOpponentPiece(targetTeam, 1, 0);
ludoShowMessage(`🏠 مهره ${pieceId} تیم ${targetTeam === 'blue' ? 'آبی' : 'قرمز'} وارد بازی شد!`, 'success');
}
});
break;
}
}
if (dicePenalties.length === 2) {
const penalty1 = dicePenalties[0];
const penalty2 = dicePenalties[1];
if (penalty1.turns > penalty2.turns) {
ludoShowMessage(`⚡ تیم ${penalty1.team === 'blue' ? 'آبی' : 'قرمز'} با ${penalty1.turns} راند اول تاس میندازد.`, 'info');
penaltyQueue.push({ type: 'penalty', team: penalty1.team, turns: penalty1.turns, message: penalty1.sourceMessage });
penaltyQueue.push({ type: 'penalty', team: penalty2.team, turns: penalty2.turns, message: penalty2.sourceMessage });
} else if (penalty2.turns > penalty1.turns) {
ludoShowMessage(`⚡ تیم ${penalty2.team === 'blue' ? 'آبی' : 'قرمز'} با ${penalty2.turns} راند اول تاس میندازد.`, 'info');
penaltyQueue.push({ type: 'penalty', team: penalty2.team, turns: penalty2.turns, message: penalty2.sourceMessage });
penaltyQueue.push({ type: 'penalty', team: penalty1.team, turns: penalty1.turns, message: penalty1.sourceMessage });
} else {
const randomOrder = Math.random() < 0.5;
if (randomOrder) {
ludoShowMessage(`⚡ اعداد مساوی! تیم ${penalty1.team === 'blue' ? 'آبی' : 'قرمز'} به صورت شانسی اول شد.`, 'info');
penaltyQueue.push({ type: 'penalty', team: penalty1.team, turns: penalty1.turns, message: penalty1.sourceMessage });
penaltyQueue.push({ type: 'penalty', team: penalty2.team, turns: penalty2.turns, message: penalty2.sourceMessage });
} else {
ludoShowMessage(`⚡ اعداد مساوی! تیم ${penalty2.team === 'blue' ? 'آبی' : 'قرمز'} به صورت شانسی اول شد.`, 'info');
penaltyQueue.push({ type: 'penalty', team: penalty2.team, turns: penalty2.turns, message: penalty2.sourceMessage });
penaltyQueue.push({ type: 'penalty', team: penalty1.team, turns: penalty1.turns, message: penalty1.sourceMessage });
}
}
} else {
dicePenalties.forEach(penalty => {
penaltyQueue.push({ type: 'penalty', team: penalty.team, turns: penalty.turns, message: penalty.sourceMessage });
});
}
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
document.getElementById('ludoDealModal').style.display = 'none';
ludoGameState.inDealMode = false;
ludoShowMessage('💰 معامله با موفقیت انجام شد!', 'success');
if (penaltyQueue.length > 0) {
ludoGameState.penaltyQueue = penaltyQueue;
ludoProcessNextPenalty();
}
else {
setTimeout(() => { ludoNextTurn(); }, 1500);
}
}
function cancelDeal() {
const moveInfo = ludoGameState.dealMoveInfo;
if (!moveInfo) return;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
document.getElementById('ludoDealModal').style.display = 'none';
ludoGameState.inDealMode = false;
ludoShowMessage('❌ معامله لغو شد.', 'info');
setTimeout(() => { ludoNextTurn(); }, 1000);
}
function ludoCheckSpecialCells(team, piece, position) {
if (piece.isSimulation) {
return;
}
if (ludoGameState.jailCells.includes(position)) {
if (piece.jailRemainingSeconds === 0) {
piece.jailRemainingSeconds = 180;
clearJailTimer(piece);
startJailTimer(piece, team);
ludoPlayJailSound();
ludoShowMessage(`🔒 مهره ${piece.id} ${team === 'blue' ? 'آبی' : 'قرمز'} به زندان افتاد! به مدت ۳ دقیقه زندانی شد.`, 'warning');
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
pieceEl.classList.add('ludo-jail-piece');
const minutes = Math.floor(180 / 60);
const seconds = 180 % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
let jailTag = pieceEl.querySelector('.jail-tag');
if (!jailTag) {
jailTag = document.createElement('div');
jailTag.className = 'jail-tag';
pieceEl.appendChild(jailTag);
}
jailTag.textContent = `زندان: ${timeString}`;
}
} else {
ludoShowMessage(`🔒 مهره ${piece.id} در زندان است و نمیتواند حرکت کند!`, 'error');
}
ludoContinueAfterMove(team);
return;
}
if (ludoGameState.dangerCells.includes(position)) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === team && s.pieceId === piece.id);
if (hasShield) ludoShowMessage(`🛡️ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} توسط سپر از خانه خطر محافظت شد!`, 'success');
else {
ludoPlayDangerSound();
ludoShowMessage(`☠️ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} روی خانه خطر افتاد! به خانه اول بازگشت.`, 'warning');
ludoReturnPieceToHome(team, piece, true);
return;
}
}
if (ludoGameState.transferCells[position]) {
const transferTo = ludoGameState.transferCells[position];
ludoShowMessage(`⇄ مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id} روی خانه انتقال افتاد! به خانه ${transferTo} منتقل شد.`, 'info');
ludoCheckAndRemoveOpponentPiece(team, transferTo, position);
piece.position = transferTo;
ludoUpdatePiecePosition(team, piece);
setTimeout(() => { ludoCheckSpecialCells(team, piece, transferTo); }, 500);
return;
}
const winnerCell = ludoGameState.winnerCells.find(w => w.number === position);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
piece.position -= ludoGameState.currentDiceValue;
ludoUpdatePiecePosition(team, piece);
ludoContinueAfterMove(team);
return;
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: team, pieceId: piece.id };
piece.inWinnerCell = true;
if (team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
ludoCheckAndRemoveOpponentPiece(team, position, piece.position - ludoGameState.currentDiceValue);
ludoContinueAfterMove(team);
}
function ludoContinueAfterMove(team) {
ludoHighlightAvailablePieces(team);
reduceShieldTurns();
if (ludoGameState.justCameFromQuestion) {
ludoGameState.justCameFromQuestion = false;
ludoNextTurn();
return;
}
if (ludoGameState.extraTurn) {
ludoGameState.diceRolled = false;
ludoGameState.extraTurn = false;
ludoUpdateDisplay();
ludoShowMessage(`🎲 چون ۶ آوردهاید، دوباره میتوانید تاس بیندازید!`, 'info');
}
else ludoNextTurn();
ludoUpdateDisplay();
}
function reduceShieldTurns() {
const newShieldEffects = [];
ludoGameState.shieldEffects.forEach(shield => {
shield.turnsLeft--;
if (shield.turnsLeft > 0) {
newShieldEffects.push(shield);
const pieceEl = document.querySelector(`.ludo-${shield.team}-on-board[data-piece-id="${shield.pieceId}"]`);
if (pieceEl) {
const shieldTag = pieceEl.querySelector('.ludo-shield-tag');
if (shieldTag) shieldTag.textContent = `🛡️ ${shield.turnsLeft}`;
}
} else {
const pieceEl = document.querySelector(`.ludo-${shield.team}-on-board[data-piece-id="${shield.pieceId}"]`);
if (pieceEl) {
const shieldEl = pieceEl.querySelector('.ludo-shield-effect');
if (shieldEl) shieldEl.remove();
const shieldTag = pieceEl.querySelector('.ludo-shield-tag');
if (shieldTag) shieldTag.remove();
}
ludoShowMessage(`🛡️ سپر مهره ${shield.pieceId} تیم ${shield.team === 'blue' ? 'آبی' : 'قرمز'} تمام شد!`, 'info');
}
});
ludoGameState.shieldEffects = newShieldEffects;
}
function ludoProcessNextPenalty() {
if (ludoGameState.penaltyQueue.length === 0) {
return;
}
const penalty = ludoGameState.penaltyQueue.shift();
if (penalty.type === 'penalty') {
ludoGameState.penaltyTurns = penalty.turns;
ludoGameState.penaltyTeam = penalty.team;
ludoGameState.isInPenaltyMode = true;
ludoGameState.currentTurn = penalty.team;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoShowMessage(penalty.message, 'warning');
ludoShowMessage(`🎮 تیم ${penalty.team === 'blue' ? 'آبی' : 'قرمز'} ${penalty.turns} راند پنالتی دارد.`, 'warning');
ludoUpdateDisplay();
}
}
function ludoNextTurn() {
if (ludoGameState.simulationPieces.length > 0) {
ludoUpdateSimulationRounds();
}
if (ludoGameState.penaltyTurns > 0) {
ludoGameState.penaltyTurns--;
if (ludoGameState.penaltyTurns === 0) {
ludoGameState.currentTurn = ludoGameState.currentTurn === 'blue' ? 'red' : 'blue';
ludoGameState.penaltyTeam = null;
ludoGameState.isInPenaltyMode = false;
if (ludoGameState.penaltyQueue.length > 0) {
ludoProcessNextPenalty();
} else {
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoUpdateDisplay();
ludoShowMessage(`🎮 نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'}. تاس را بزنید.`, 'info');
}
return;
}
ludoGameState.isInPenaltyMode = true;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoUpdateDisplay();
ludoShowMessage(`🎮 نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} (${ludoGameState.penaltyTurns} راند پنالتی باقی مانده). تاس را بزنید.`, 'warning');
return;
}
ludoGameState.currentTurn = ludoGameState.currentTurn === 'blue' ? 'red' : 'blue';
ludoGameState.isInPenaltyMode = false;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoUpdateDisplay();
ludoCheckSimulationConditions();
ludoShowMessage(`🎮 نوبت تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'}. تاس را بزنید.`, 'info');
}
function ludoCheckAndRemoveOpponentPiece(team, newPosition, oldPosition) {
const opponentTeam = team === 'blue' ? 'red' : 'blue';
const opponentPieces = opponentTeam === 'blue' ? ludoGameState.bluePieces : ludoGameState.redPieces;
const opponentPiece = opponentPieces.find(p => p.position === newPosition && p.isOnBoard && !p.inWinnerCell && p.jailRemainingSeconds === 0 && !p.isSimulation);
if (opponentPiece) {
const hasShield = ludoGameState.shieldEffects.some(s => s.team === opponentTeam && s.pieceId === opponentPiece.id);
if (hasShield) ludoShowMessage(`🛡️ مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${opponentPiece.id} توسط سپر از حذف محافظت شد!`, 'success');
else {
ludoShowMessage(`⚡ مهره ${opponentTeam === 'blue' ? 'آبی' : 'قرمز'} ${opponentPiece.id} حذف شد!`, 'warning');
ludoReturnPieceToHome(opponentTeam, opponentPiece);
const winnerCell = ludoGameState.winnerCells.find(w => w.occupiedBy && w.occupiedBy.team === opponentTeam && w.occupiedBy.pieceId === opponentPiece.id);
if (winnerCell) {
winnerCell.occupied = false;
winnerCell.occupiedBy = null;
if (opponentTeam === 'blue') ludoGameState.blueWinnerCount--;
else ludoGameState.redWinnerCount--;
opponentPiece.inWinnerCell = false;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
}
}
function ludoReturnPieceToHome(team, piece, changeTurn = false) {
ludoRemovePieceFromBoard(team, piece.id);
const shieldIndex = ludoGameState.shieldEffects.findIndex(s => s.team === team && s.pieceId === piece.id);
if (shieldIndex !== -1) ludoGameState.shieldEffects.splice(shieldIndex, 1);
clearJailTimer(piece);
piece.position = -1;
piece.isOnBoard = false;
piece.isInHome = true;
piece.inWinnerCell = false;
piece.jailRemainingSeconds = 0;
ludoUpdateHomeDisplay(team, piece.id, true);
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const jailTag = pieceEl.querySelector('.jail-tag');
if (jailTag) jailTag.remove();
pieceEl.classList.remove('ludo-jail-piece');
}
if (changeTurn) {
setTimeout(() => {
if (!ludoGameState.gameEnded && !ludoGameState.isDrawGame) {
ludoNextTurn();
}
}, 1000);
}
}
function ludoUpdateHomeDisplay(team, pieceId, isInHome) {
const containerId = 'ludo' + team.charAt(0).toUpperCase() + team.slice(1) + 'PiecesContainer';
const container = document.getElementById(containerId);
const pieceElement = container.querySelector(`.ludo-piece-in-home:nth-child(${pieceId})`);
if (pieceElement) {
if (isInHome) {
pieceElement.classList.remove('ludo-piece-missing');
pieceElement.style.opacity = '1';
pieceElement.style.transform = 'scale(1)';
pieceElement.style.cursor = 'pointer';
}
else {
pieceElement.classList.add('ludo-piece-missing');
pieceElement.style.opacity = '0.3';
pieceElement.style.transform = 'scale(0.8)';
pieceElement.style.cursor = 'not-allowed';
}
}
}
function ludoCreatePieceOnBoard(team, piece) {
const cell = ludoGameState.boardElements[piece.position];
if (!cell) return;
const pieceEl = document.createElement('div');
pieceEl.className = `ludo-piece-on-board ludo-${team}-on-board`;
pieceEl.textContent = piece.id;
pieceEl.dataset.pieceId = piece.id;
pieceEl.title = `مهره ${team === 'blue' ? 'آبی' : 'قرمز'} ${piece.id}`;
pieceEl.onclick = () => ludoSelectPiece(team, piece.id);
const rect = cell.getBoundingClientRect();
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
const offsetX = Math.random() * 20 + 5;
const offsetY = Math.random() * 20 + 5;
pieceEl.style.left = (rect.left - boardRect.left + offsetX) + 'px';
pieceEl.style.top = (rect.top - boardRect.top + offsetY) + 'px';
document.getElementById('ludoBoard').appendChild(pieceEl);
ludoGameState.pieceElements.push({ team, pieceId: piece.id, element: pieceEl });
const shield = ludoGameState.shieldEffects.find(s => s.team === team && s.pieceId === piece.id);
if (shield) {
const shieldEl = document.createElement('div');
shieldEl.className = 'ludo-shield-effect';
shieldEl.id = `shield-${team}-${piece.id}`;
pieceEl.appendChild(shieldEl);
const shieldTag = document.createElement('div');
shieldTag.className = 'ludo-shield-tag';
shieldTag.textContent = `🛡️ ${shield.turnsLeft}`;
pieceEl.appendChild(shieldTag);
}
if (piece.jailRemainingSeconds > 0) {
pieceEl.classList.add('ludo-jail-piece');
const minutes = Math.floor(piece.jailRemainingSeconds / 60);
const seconds = piece.jailRemainingSeconds % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
let jailTag = pieceEl.querySelector('.jail-tag');
if (!jailTag) {
jailTag = document.createElement('div');
jailTag.className = 'jail-tag';
pieceEl.appendChild(jailTag);
}
jailTag.textContent = `زندان: ${timeString}`;
}
}
function ludoUpdatePiecePosition(team, piece) {
ludoRemovePieceFromBoard(team, piece.id);
if (piece.isOnBoard && piece.position >= 1 && piece.position <= 120 && !piece.isSimulation) ludoCreatePieceOnBoard(team, piece);
}
function ludoRemovePieceFromBoard(team, pieceId) {
const pieceElement = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${pieceId}"]`);
if (pieceElement && pieceElement.parentNode) pieceElement.parentNode.removeChild(pieceElement);
ludoGameState.pieceElements = ludoGameState.pieceElements.filter(p => !(p.team === team && p.pieceId === pieceId));
}
function startJailTimer(piece, team) {
if (piece.jailTimerInterval) clearInterval(piece.jailTimerInterval);
piece.jailTimerInterval = setInterval(() => {
if (piece.jailRemainingSeconds > 0) {
piece.jailRemainingSeconds--;
const minutes = Math.floor(piece.jailRemainingSeconds / 60);
const seconds = piece.jailRemainingSeconds % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
let jailTag = pieceEl.querySelector('.jail-tag');
if (!jailTag) {
jailTag = document.createElement('div');
jailTag.className = 'jail-tag';
pieceEl.appendChild(jailTag);
}
jailTag.textContent = `زندان: ${timeString}`;
}
if (piece.jailRemainingSeconds === 0) {
clearInterval(piece.jailTimerInterval);
piece.jailTimerInterval = null;
ludoShowMessage(`🔓 مهره ${piece.id} تیم ${team === 'blue' ? 'آبی' : 'قرمز'} از زندان آزاد شد!`, 'success');
const pieceEl = document.querySelector(`.ludo-${team}-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) {
const jailTag = pieceEl.querySelector('.jail-tag');
if (jailTag) jailTag.remove();
pieceEl.classList.remove('ludo-jail-piece');
}
}
}
}, 1000);
}
function clearJailTimer(piece) {
if (piece.jailTimerInterval) {
clearInterval(piece.jailTimerInterval);
piece.jailTimerInterval = null;
}
}
// ==============================
// ===== انیمیشن رنگینکمان =====
// ==============================
async function startRainbowAnimation() {
return new Promise(async (resolve) => {
const container = document.getElementById('rainbowAnimationContainer');
container.innerHTML = '';
container.style.display = 'block';
const rainbowMainSound = document.getElementById('rainbowMainSound');
if (rainbowMainSound) { rainbowMainSound.currentTime = 0; rainbowMainSound.play().catch(e => console.log("خطا در پخش صدای رنگین کمان اصلی:", e)); }
const board = document.getElementById('ludoBoard');
const boardRect = board.getBoundingClientRect();
const centerX = (boardRect.left + boardRect.right) / 2;
const centerY = (boardRect.top + boardRect.bottom) / 2;
const centerPercentX = ((centerX - boardRect.left) / boardRect.width) * 100;
const centerPercentY = ((centerY - boardRect.top) / boardRect.height) * 100;
const mainRainbow = document.createElement('div');
mainRainbow.className = 'rainbow-main';
mainRainbow.style.left = centerPercentX + '%';
mainRainbow.style.top = centerPercentY + '%';
container.appendChild(mainRainbow);
await new Promise(r => setTimeout(r, 800));
const allPieces = [];
ludoGameState.bluePieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const pieceEl = document.querySelector(`.ludo-blue-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) allPieces.push({ piece, team: 'blue', element: pieceEl, position: piece.position });
}
});
ludoGameState.redPieces.forEach(piece => {
if (piece.isOnBoard && !piece.inWinnerCell && piece.jailRemainingSeconds === 0 && !piece.isSimulation) {
const pieceEl = document.querySelector(`.ludo-red-on-board[data-piece-id="${piece.id}"]`);
if (pieceEl) allPieces.push({ piece, team: 'red', element: pieceEl, position: piece.position });
}
});
const rainbowTentacleSound = document.getElementById('rainbowTentacleSound');
if (rainbowTentacleSound) { rainbowTentacleSound.currentTime = 0; rainbowTentacleSound.play().catch(e => console.log("خطا در پخش صدای شاخک رنگین کمان:", e)); }
const tentacles = [];
for (let i = 0; i < allPieces.length; i++) {
const pieceData = allPieces[i];
const pieceRect = pieceData.element.getBoundingClientRect();
const piecePercentX = ((pieceRect.left + pieceRect.width/2 - boardRect.left) / boardRect.width) * 100;
const piecePercentY = ((pieceRect.top + pieceRect.height/2 - boardRect.top) / boardRect.height) * 100;
const tentacle = document.createElement('div');
tentacle.className = 'rainbow-tentacle';
tentacle.style.left = centerPercentX + '%';
tentacle.style.top = centerPercentY + '%';
container.appendChild(tentacle);
tentacles.push({ element: tentacle, targetX: piecePercentX, targetY: piecePercentY, progress: 0, pieceData: pieceData });
}
const animateTentacles = setInterval(() => {
let allDone = true;
tentacles.forEach(t => {
if (t.progress < 1) {
allDone = false;
t.progress += 0.05;
const easeOut = 1 - Math.pow(1 - t.progress, 3);
const currentX = centerPercentX + (t.targetX - centerPercentX) * easeOut;
const currentY = centerPercentY + (t.targetY - centerPercentY) * easeOut;
t.element.style.left = currentX + '%';
t.element.style.top = currentY + '%';
t.element.style.width = (10 + t.progress * 20) + 'px';
t.element.style.height = (10 + t.progress * 20) + 'px';
} else {
t.element.style.left = t.targetX + '%';
t.element.style.top = t.targetY + '%';
}
});
if (allDone) {
clearInterval(animateTentacles);
setTimeout(async () => {
allPieces.forEach(p => { p.element.classList.add('piece-captured'); });
await new Promise(r => setTimeout(r, 500));
const spinDuration = 2000;
const spinStart = Date.now();
const spinInterval = setInterval(() => {
allPieces.forEach(p => {
const angle = (Date.now() - spinStart) * 0.01;
p.element.style.transform = `rotate(${angle}deg) scale(1.2)`;
p.element.style.transition = 'transform 0.05s linear';
});
}, 50);
await new Promise(r => setTimeout(r, spinDuration));
clearInterval(spinInterval);
allPieces.forEach(p => {
const newPosition = Math.floor(Math.random() * 120) + 1;
const oldPosition = p.position;
p.piece.position = newPosition;
ludoUpdatePiecePosition(p.team, p.piece);
ludoCheckAndRemoveOpponentPiece(p.team, newPosition, oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === newPosition);
if (winnerCell && !winnerCell.occupied && newPosition !== oldPosition) {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: p.team, pieceId: p.piece.id };
p.piece.inWinnerCell = true;
if (p.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
p.element.style.transform = '';
p.element.classList.remove('piece-captured');
});
container.innerHTML = '';
container.style.display = 'none';
resolve();
}, 500);
}
}, 20);
});
}
function ludoShowRainbowConfirmation(moveInfo) {
ludoGameState.pendingRainbowMove = moveInfo;
document.getElementById('rainbowModal').style.display = 'flex';
ludoShowMessage('🌈 روی خانه رنگینکمان افتادید! آیا از چرخش هیجانی مطمئن هستید؟ مهره خودتان هم چرخش میخورد.', 'warning');
}
function confirmRainbow() {
document.getElementById('rainbowModal').style.display = 'none';
const moveInfo = ludoGameState.pendingRainbowMove;
if (!moveInfo) return;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) { ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error'); moveInfo.piece.position = moveInfo.oldPosition; ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece); ludoGameState.pendingRainbowMove = null; setTimeout(() => { ludoNextTurn(); }, 1000); return; }
else { winnerCell.occupied = true; winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id }; moveInfo.piece.inWinnerCell = true; if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++; else ludoGameState.redWinnerCount++; ludoUpdateWinnerCellsDisplay(); ludoCheckWinner(); }
}
startRainbowAnimation().then(() => {
ludoGameState.pendingRainbowMove = null;
setTimeout(() => { ludoNextTurn(); }, 1500);
});
}
function cancelRainbow() {
document.getElementById('rainbowModal').style.display = 'none';
const moveInfo = ludoGameState.pendingRainbowMove;
if (!moveInfo) return;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) { ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error'); moveInfo.piece.position = moveInfo.oldPosition; ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece); }
else { winnerCell.occupied = true; winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id }; moveInfo.piece.inWinnerCell = true; if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++; else ludoGameState.redWinnerCount++; ludoUpdateWinnerCellsDisplay(); ludoCheckWinner(); }
}
ludoGameState.pendingRainbowMove = null;
ludoShowMessage('✅ چرخش هیجانی لغو شد. مهره در خانه رنگینکمان باقی ماند.', 'info');
setTimeout(() => { ludoNextTurn(); }, 1000);
}
// ==============================
// ===== توابع انفجار =====
// ==============================
function ludoShowExplosionConfirmation(moveInfo) {
ludoGameState.pendingExplosionMove = moveInfo;
document.getElementById('explosionModal').style.display = 'flex';
ludoShowMessage('⚠️ روی خانه انفجاری افتادید! آیا مطمئن هستید؟', 'warning');
}
function confirmExplosion() {
document.getElementById('explosionModal').style.display = 'none';
const moveInfo = ludoGameState.pendingExplosionMove;
if (!moveInfo) return;
const explosionCell = ludoGameState.boardElements[moveInfo.newPosition];
if (!explosionCell) return;
const rect = explosionCell.getBoundingClientRect();
const boardRect = document.getElementById('ludoBoard').getBoundingClientRect();
const explosionX = ((rect.left - boardRect.left) / boardRect.width) * 100;
const explosionY = ((rect.top - boardRect.top) / boardRect.height) * 100;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
showExplosionAnimation(explosionX, explosionY).then(() => {
ludoGameState.pendingExplosionMove = null;
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) { ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error'); moveInfo.piece.position = moveInfo.oldPosition; ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece); }
else { winnerCell.occupied = true; winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id }; moveInfo.piece.inWinnerCell = true; if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++; else ludoGameState.redWinnerCount++; ludoUpdateWinnerCellsDisplay(); ludoCheckWinner(); }
}
setTimeout(() => { ludoNextTurn(); }, 1500);
});
}
function cancelExplosion() {
document.getElementById('explosionModal').style.display = 'none';
const moveInfo = ludoGameState.pendingExplosionMove;
if (!moveInfo) return;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) { ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error'); moveInfo.piece.position = moveInfo.oldPosition; ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece); }
else { winnerCell.occupied = true; winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id }; moveInfo.piece.inWinnerCell = true; if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++; else ludoGameState.redWinnerCount++; ludoUpdateWinnerCellsDisplay(); ludoCheckWinner(); }
}
ludoGameState.pendingExplosionMove = null;
ludoShowMessage('✅ انفجار لغو شد. مهره در خانه انفجاری باقی ماند.', 'info');
setTimeout(() => { ludoNextTurn(); }, 1000);
}
// ==============================
// ===== توابع سوالات =====
// ==============================
function ludoShowGeneralQuestion(moveInfo) {
ludoGameState.currentQuestion = ludoGetRandomGeneralQuestion();
if (!ludoGameState.currentQuestion) {
ludoShowMessage('🎉 تمام سوالات تمام شد! بازی ادامه مییابد.', 'success');
ludoGameState.justCameFromQuestion = true;
ludoContinueAfterMove(moveInfo.team);
return;
}
ludoGameState.inQuestionMode = true;
ludoGameState.questionAnswered = false;
ludoGameState.timeLeft = 20;
const modal = document.getElementById('ludoQuestionModal');
const questionFormula = document.getElementById('ludoQuestionFormula');
const optionsContainer = document.getElementById('ludoOptionsContainer');
const timerElement = document.getElementById('ludoQuestionTimer');
const resultMessage = document.getElementById('ludoResultMessage');
const questionCount = document.getElementById('ludoQuestionCount');
const questionLevel = document.getElementById('ludoQuestionLevel');
modal.style.display = 'flex';
resultMessage.style.display = 'none';
questionFormula.textContent = ludoGameState.currentQuestion.question;
questionCount.textContent = `سوال ${ludoGameState.answeredQuestions + 1} از 150`;
questionLevel.textContent = `سطح: اطلاعات عمومی`;
questionLevel.className = 'ludo-question-level ludo-level-medium';
optionsContainer.innerHTML = '';
ludoGameState.currentQuestion.options.forEach((opt, idx) => {
const optionDiv = document.createElement('div');
optionDiv.className = 'ludo-option';
optionDiv.dataset.index = idx;
optionDiv.innerHTML = `<div class="ludo-option-text">${opt}</div><div class="ludo-option-label">گزینه ${String.fromCharCode(65 + idx)}</div>`;
optionDiv.onclick = function() {
if (ludoGameState.questionAnswered) {
ludoShowMessage('❌ شما قبلاً به این سوال پاسخ دادهاید!', 'error');
return;
}
ludoCheckGeneralAnswer(idx === ludoGameState.currentQuestion.correct, moveInfo);
};
optionsContainer.appendChild(optionDiv);
});
clearInterval(ludoGameState.questionTimer);
ludoGameState.questionTimer = setInterval(() => {
ludoGameState.timeLeft--;
timerElement.textContent = ludoGameState.timeLeft;
if (ludoGameState.timeLeft <= 5) timerElement.style.color = '#FF0000';
if (ludoGameState.timeLeft <= 0) {
clearInterval(ludoGameState.questionTimer);
if (!ludoGameState.questionAnswered) {
ludoShowGeneralResult(false, '⏰ وقت تمام شد!', moveInfo);
}
}
}, 1000);
setTimeout(() => { modal.scrollIntoView({ behavior: 'smooth', block: 'center' }); }, 100);
}
function ludoCheckGeneralAnswer(isCorrect, moveInfo) {
if (ludoGameState.questionAnswered) {
return;
}
ludoGameState.questionAnswered = true;
clearInterval(ludoGameState.questionTimer);
document.querySelectorAll('.ludo-option').forEach(opt => {
opt.classList.add('disabled');
});
const resultMessage = document.getElementById('ludoResultMessage');
resultMessage.style.display = 'block';
if (isCorrect) {
resultMessage.textContent = '✅ پاسخ شما صحیح است! حرکت تکمیل میشود و نوبت به حریف میرسد.';
resultMessage.className = 'ludo-result-message ludo-correct';
ludoGameState.justCameFromQuestion = true;
setTimeout(() => {
document.getElementById('ludoQuestionModal').style.display = 'none';
ludoGameState.inQuestionMode = false;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
setTimeout(() => { ludoNextTurn(); }, 1000);
}, 2000);
} else {
resultMessage.textContent = '❌ پاسخ شما اشتباه است! حریف ۲ نوبت کامل میگیرد.';
resultMessage.className = 'ludo-result-message ludo-wrong';
setTimeout(() => {
document.getElementById('ludoQuestionModal').style.display = 'none';
ludoGameState.inQuestionMode = false;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
const opponent = moveInfo.team === 'blue' ? 'red' : 'blue';
if (ludoGameState.penaltyQueue.length === 0 && ludoGameState.penaltyTurns === 0) {
ludoGameState.penaltyTurns = 2;
ludoGameState.penaltyTeam = opponent;
ludoGameState.currentTurn = opponent;
ludoGameState.isInPenaltyMode = true;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoShowMessage(`❌ پاسخ اشتباه! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت کامل میگیرد.`, 'error');
ludoUpdateDisplay();
} else {
ludoGameState.penaltyQueue.push({
type: 'penalty',
team: opponent,
turns: 2,
message: `🚫 تیم ${moveInfo.team === 'blue' ? 'آبی' : 'قرمز'} پاسخ اشتباه داد! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت پنالتی میگیرد.`
});
ludoShowMessage(`❌ پاسخ اشتباه! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت پنالتی در صف قرار گرفت.`, 'error');
}
}, 2000);
}
}
function ludoShowGeneralResult(isCorrect, message, moveInfo) {
if (ludoGameState.questionAnswered) {
return;
}
ludoGameState.questionAnswered = true;
clearInterval(ludoGameState.questionTimer);
document.querySelectorAll('.ludo-option').forEach(opt => {
opt.classList.add('disabled');
});
const resultMessage = document.getElementById('ludoResultMessage');
resultMessage.style.display = 'block';
resultMessage.textContent = message;
resultMessage.className = `ludo-result-message ${isCorrect ? 'ludo-correct' : 'ludo-wrong'}`;
if (isCorrect) {
setTimeout(() => {
document.getElementById('ludoQuestionModal').style.display = 'none';
ludoGameState.inQuestionMode = false;
ludoGameState.justCameFromQuestion = true;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
setTimeout(() => { ludoNextTurn(); }, 1000);
}, 2000);
} else {
setTimeout(() => {
document.getElementById('ludoQuestionModal').style.display = 'none';
ludoGameState.inQuestionMode = false;
moveInfo.piece.position = moveInfo.newPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
ludoCheckAndRemoveOpponentPiece(moveInfo.team, moveInfo.newPosition, moveInfo.oldPosition);
const winnerCell = ludoGameState.winnerCells.find(w => w.number === moveInfo.newPosition);
if (winnerCell) {
if (winnerCell.occupied) {
ludoShowMessage('❌ این خانه برنده قبلاً اشغال شده است!', 'error');
moveInfo.piece.position = moveInfo.oldPosition;
ludoUpdatePiecePosition(moveInfo.team, moveInfo.piece);
}
else {
winnerCell.occupied = true;
winnerCell.occupiedBy = { team: moveInfo.team, pieceId: moveInfo.piece.id };
moveInfo.piece.inWinnerCell = true;
if (moveInfo.team === 'blue') ludoGameState.blueWinnerCount++;
else ludoGameState.redWinnerCount++;
ludoUpdateWinnerCellsDisplay();
ludoCheckWinner();
}
}
const opponent = moveInfo.team === 'blue' ? 'red' : 'blue';
if (ludoGameState.penaltyQueue.length === 0 && ludoGameState.penaltyTurns === 0) {
ludoGameState.penaltyTurns = 2;
ludoGameState.penaltyTeam = opponent;
ludoGameState.currentTurn = opponent;
ludoGameState.isInPenaltyMode = true;
ludoGameState.diceRolled = false;
ludoGameState.currentDiceValue = 0;
ludoGameState.selectedPiece = null;
ludoGameState.extraTurn = false;
ludoShowMessage(`❌ پاسخ اشتباه! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت کامل میگیرد.`, 'error');
ludoUpdateDisplay();
} else {
ludoGameState.penaltyQueue.push({
type: 'penalty',
team: opponent,
turns: 2,
message: `🚫 تیم ${moveInfo.team === 'blue' ? 'آبی' : 'قرمز'} پاسخ اشتباه داد! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت پنالتی میگیرد.`
});
ludoShowMessage(`❌ پاسخ اشتباه! تیم ${opponent === 'blue' ? 'آبی' : 'قرمز'} ۲ نوبت پنالتی در صف قرار گرفت.`, 'error');
}
}, 2000);
}
}
// ==============================
// ===== توابع برنده و نمایش =====
// ==============================
function ludoCheckWinner() {
document.getElementById('ludoBlueWinnerHouses').textContent = ludoGameState.blueWinnerCount;
document.getElementById('ludoRedWinnerHouses').textContent = ludoGameState.redWinnerCount;
if (ludoGameState.blueWinnerCount >= 3) {
ludoGameState.gameEnded = true;
ludoGameState.isDrawGame = false;
ludoGameState.simulationLocked = true;
ludoUpdateSimulationLocks();
if (ludoGameState.ghostActive) {
ludoGameState.ghostActive = false;
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
}
ludoGameState.simulationPieces.forEach(simPiece => {
const el = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (el && el.parentNode) el.parentNode.removeChild(el);
});
ludoGameState.simulationPieces = [];
ludoGameState.simulationActive = false;
setTimeout(() => {
alert(`🏆 تیم آبی برنده شد!\nتعداد مهرههای آبی در خانههای طلایی: ${ludoGameState.blueWinnerCount}\nتعداد مهرههای قرمز در خانههای طلایی: ${ludoGameState.redWinnerCount}`);
ludoShowMessage('🎉 تیم آبی برنده شد! بازی تمام شد.', 'success');
document.getElementById('ludoEndGameButtons').style.display = 'flex';
document.getElementById('ludoBlueDice').classList.add('disabled');
document.getElementById('ludoRedDice').classList.add('disabled');
ludoPauseBackgroundSound();
}, 1000);
} else if (ludoGameState.redWinnerCount >= 3) {
ludoGameState.gameEnded = true;
ludoGameState.isDrawGame = false;
ludoGameState.simulationLocked = true;
ludoUpdateSimulationLocks();
if (ludoGameState.ghostActive) {
ludoGameState.ghostActive = false;
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
}
ludoGameState.simulationPieces.forEach(simPiece => {
const el = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (el && el.parentNode) el.parentNode.removeChild(el);
});
ludoGameState.simulationPieces = [];
ludoGameState.simulationActive = false;
setTimeout(() => {
alert(`🏆 تیم قرمز برنده شد!\nتعداد مهرههای قرمز در خانههای طلایی: ${ludoGameState.redWinnerCount}\nتعداد مهرههای آبی در خانههای طلایی: ${ludoGameState.blueWinnerCount}`);
ludoShowMessage('🎉 تیم قرمز برنده شد! بازی تمام شد.', 'success');
document.getElementById('ludoEndGameButtons').style.display = 'flex';
document.getElementById('ludoBlueDice').classList.add('disabled');
document.getElementById('ludoRedDice').classList.add('disabled');
ludoPauseBackgroundSound();
}, 1000);
} else if (ludoGameState.blueWinnerCount >= 2 && ludoGameState.redWinnerCount >= 2) {
ludoGameState.gameEnded = true;
ludoGameState.isDrawGame = true;
ludoGameState.simulationLocked = true;
ludoUpdateSimulationLocks();
if (ludoGameState.ghostActive) {
ludoGameState.ghostActive = false;
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
}
ludoGameState.simulationPieces.forEach(simPiece => {
const el = document.querySelector(`[data-sim-id="sim-${simPiece.team}-${simPiece.id}-${simPiece.index}"]`);
if (el && el.parentNode) el.parentNode.removeChild(el);
});
ludoGameState.simulationPieces = [];
ludoGameState.simulationActive = false;
setTimeout(() => {
alert(`🤝 بازی مساوی شد!\nهر دو تیم ۲ مهره در خانههای طلایی دارند.\nتیم آبی: ${ludoGameState.blueWinnerCount} - تیم قرمز: ${ludoGameState.redWinnerCount}`);
ludoShowMessage('🤝 بازی مساوی شد! هر دو تیم ۲ مهره در خانههای طلایی دارند.', 'warning');
document.getElementById('ludoEndGameButtons').style.display = 'flex';
document.getElementById('ludoBlueDice').classList.add('disabled');
document.getElementById('ludoRedDice').classList.add('disabled');
ludoPauseBackgroundSound();
}, 1000);
}
}
function ludoUpdateWinnerCellsDisplay() {
ludoGameState.winnerCells.forEach(winnerCell => {
const cellElement = ludoGameState.boardElements[winnerCell.number];
if (cellElement) {
if (winnerCell.occupied) {
cellElement.classList.add('ludo-occupied-winner-cell');
if (winnerCell.occupiedBy.team === 'blue') {
cellElement.style.background = 'linear-gradient(45deg, #2196F3, #0D47A1, #FFD700)';
cellElement.style.borderColor = '#0D47A1';
}
else {
cellElement.style.background = 'linear-gradient(45deg, #F44336, #B71C1C, #FFD700)';
cellElement.style.borderColor = '#B71C1C';
}
} else {
cellElement.classList.remove('ludo-occupied-winner-cell');
cellElement.style.background = 'linear-gradient(45deg, #FFD700, #FFA500)';
cellElement.style.borderColor = '#FF8C00';
}
}
});
}
function ludoUpdateDisplay() {
const indicator = document.getElementById('ludoTurnIndicator');
if (ludoGameState.gameEnded) {
if (ludoGameState.isDrawGame) {
indicator.textContent = '🤝 بازی مساوی شد!';
indicator.style.background = 'linear-gradient(to right, #FFD700, #FFA500)';
indicator.style.borderColor = '#FF8C00';
}
else {
indicator.textContent = '🎮 بازی تمام شد! برای شروع جدید بازی را ریست کنید.';
indicator.style.background = 'linear-gradient(to right, #FFD700, #FFA500)';
indicator.style.borderColor = '#FF8C00';
}
} else if (ludoGameState.penaltyTurns > 0) {
indicator.textContent = `نوبت: تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'} (پنالتی ${ludoGameState.penaltyTurns} راند باقی مانده)`;
indicator.className = `ludo-turn-indicator ${ludoGameState.currentTurn === 'blue' ? '' : 'ludo-red-turn'}`;
} else {
indicator.textContent = `نوبت: تیم ${ludoGameState.currentTurn === 'blue' ? 'آبی' : 'قرمز'}`;
indicator.className = `ludo-turn-indicator ${ludoGameState.currentTurn === 'blue' ? '' : 'ludo-red-turn'}`;
}
document.getElementById('ludoCurrentDiceValue').textContent = ludoGameState.currentDiceValue !== 0 ? ludoGameState.currentDiceValue : '۰';
const blueDice = document.getElementById('ludoBlueDice');
const redDice = document.getElementById('ludoRedDice');
if (ludoGameState.gameEnded || ludoGameState.isDrawGame || ludoGameState.ghostActive || ludoGameState.simulationActive || ludoGameState.hackerAnimating || ludoGameState.hackerChallengeActive || ludoGameState.autoMoveInProgress) {
blueDice.classList.add('disabled');
redDice.classList.add('disabled');
} else if (ludoGameState.isMovingPiece || ludoGameState.diceLocked || ludoGameState.inQuestionMode || ludoGameState.goldenDiceActive || ludoGameState.inDealMode || ludoGameState.rainbowActive) {
blueDice.classList.add('disabled');
redDice.classList.add('disabled');
} else {
if (ludoGameState.currentTurn === 'blue') {
blueDice.classList.remove('disabled');
redDice.classList.add('disabled');
if (ludoGameState.diceRolled && !ludoGameState.extraTurn && ludoGameState.penaltyTurns === 0 && !ludoGameState.justCameFromQuestion && !ludoGameState.isInPenaltyMode) blueDice.classList.add('disabled');
}
else {
redDice.classList.remove('disabled');
blueDice.classList.add('disabled');
if (ludoGameState.diceRolled && !ludoGameState.extraTurn && ludoGameState.penaltyTurns === 0 && !ludoGameState.justCameFromQuestion && !ludoGameState.isInPenaltyMode) redDice.classList.add('disabled');
}
}
ludoGameState.bluePieces.forEach(piece => { if (piece.isOnBoard && !piece.isSimulation) ludoUpdatePiecePosition('blue', piece); });
ludoGameState.redPieces.forEach(piece => { if (piece.isOnBoard && !piece.isSimulation) ludoUpdatePiecePosition('red', piece); });
ludoGameState.bluePieces.forEach(piece => { ludoUpdateHomeDisplay('blue', piece.id, piece.isInHome && !piece.isOnBoard); });
ludoGameState.redPieces.forEach(piece => { ludoUpdateHomeDisplay('red', piece.id, piece.isInHome && !piece.isOnBoard); });
document.getElementById('ludoBlueWinnerHouses').textContent = ludoGameState.blueWinnerCount;
document.getElementById('ludoRedWinnerHouses').textContent = ludoGameState.redWinnerCount;
ludoUpdateWinnerCellsDisplay();
ludoUpdateSaveButtons();
ludoUpdateSimulationLocks();
}
function ludoShowMessage(text, type = 'info') {
const messageBox = document.getElementById('ludoMessageBox');
messageBox.textContent = text;
messageBox.style.display = 'block';
if (type === 'error') {
messageBox.style.background = 'linear-gradient(to right, #F44336, #B71C1C)';
messageBox.style.borderColor = '#F44336';
}
else if (type === 'success') {
messageBox.style.background = 'linear-gradient(to right, #4CAF50, #2E7D32)';
messageBox.style.borderColor = '#4CAF50';
}
else if (type === 'warning') {
messageBox.style.background = 'linear-gradient(to right, #FF9800, #F57C00)';
messageBox.style.borderColor = '#FF9800';
}
else {
messageBox.style.background = 'linear-gradient(to right, #2196F3, #0D47A1)';
messageBox.style.borderColor = '#2196F3';
}
setTimeout(() => { messageBox.style.display = 'none'; }, 3000);
}
// ==============================
// ===== مقداردهی اولیه بازی =====
// ==============================
function ludoInitGame() {
ludoGameState.saveCount = { blue: 0, red: 0 };
ludoGameState.saveLocked = { blue: true, red: true };
ludoGameState.thunderUsed = { blue: false, red: false };
ludoGameState.thunderActive = { blue: false, red: false };
ludoGameState.thunderProcessing = { blue: false, red: false };
ludoGameState.justRolledSix = { blue: false, red: false };
ludoGameState.canSaveAfterRoll = { blue: false, red: false };
ludoGameState.ghostCell = null;
ludoGameState.ghostActive = false;
ludoGameState.ghostPieces = [];
ludoGameState.pendingGhostMove = null;
ludoGameState.questionAnswered = false;
ludoGameState.simulationCells = [];
ludoGameState.simulationLocked = true;
ludoGameState.simulationRoundsLeft = 0;
ludoGameState.simulationPieces = [];
ludoGameState.simulationActive = false;
ludoGameState.simulationUsed = false;
ludoGameState.pendingSimulationMove = null;
ludoGameState.simulationMoveInfo = null;
ludoGameState.simulationRoundsElapsed = 0;
ludoGameState.selectedSimulationPiece = null;
// ریست هکر
ludoGameState.hackerDeviceCell = null;
ludoGameState.hackerDeviceCollected = { blue: false, red: false };
ludoGameState.hackerDeviceTeam = null;
ludoGameState.hackerUsed = { blue: false, red: false };
ludoGameState.hackerDone = false;
ludoGameState.hackerFieldsVisible = { blue: false, red: false };
ludoGameState.hackerField1Value = { blue: null, red: null };
ludoGameState.hackerField2Value = { blue: null, red: null };
ludoGameState.hackerField1RawValue = { blue: null, red: null };
ludoGameState.hackerConfirmLocked = { blue: false, red: false };
ludoGameState.hackerUsesLeft = { blue: 4, red: 4 };
ludoGameState.hackerForcingActive = { blue: false, red: false };
ludoGameState.hackerForcingTeam = null;
ludoGameState.hackerForcedDiceValue = null;
ludoGameState.hackerForcedPieceId = null;
ludoGameState.hackerForcedTargetTeam = null;
ludoGameState.hackerAnimating = false;
ludoGameState.hackerChallengeActive = false;
ludoGameState.hackerChallengeNumber = '';
ludoGameState.hackerChallengeIndex = 0;
ludoGameState.hackerChallengeTimer = null;
ludoGameState.hackerChallengeTimeLeft = 20;
ludoGameState.hackerChallengeLocked = false;
ludoGameState.hackerChallengeButtons = [];
ludoGameState.hackerChallengeShuffled = [];
ludoGameState.hackerChallengeSoundPlaying = false;
ludoGameState.hackerChallengeTypingSoundPlaying = false;
ludoGameState.autoMoveInProgress = false;
document.getElementById('ludoBlueHackerBtn').style.display = 'block';
document.getElementById('ludoRedHackerBtn').style.display = 'block';
document.getElementById('ludoBlueHackerFieldsContainer').style.display = 'none';
document.getElementById('ludoRedHackerFieldsContainer').style.display = 'none';
document.getElementById('hackerAnimationContainer').classList.remove('active');
document.getElementById('hackerAnimationContainer').innerHTML = '';
document.getElementById('hackerChallengeModal').classList.remove('active');
document.getElementById('hackerChallengeModal').style.display = 'none';
document.querySelectorAll('.ludo-simulation-piece').forEach(el => el.remove());
ludoGameState.bluePieces.forEach(p => { p.isSimulation = false; });
ludoGameState.redPieces.forEach(p => { p.isSimulation = false; });
ludoGenerateDangerCells();
ludoGenerateQuestionCells();
ludoGenerateLuckCells();
ludoGenerateExplosionCells();
ludoGenerateDealCells();
ludoGenerateRainbowCells();
ludoCreateBoard();
ludoUpdateDisplay();
ludoShowMessage('🎮 بازی شروع شد! نوبت تیم آبی. تاس را بزنید.', 'info');
ludoGameState.gameEnded = false;
ludoGameState.isDrawGame = false;
ludoGameState.justCameFromQuestion = false;
ludoGameState.isInPenaltyMode = false;
ludoGameState.backgroundSoundEnabled = true;
ludoGameState.usedQuestions.clear();
ludoGameState.answeredQuestions = 0;
ludoGameState.penaltyTurns = 0;
ludoGameState.penaltyTeam = null;
ludoGameState.blueWinnerCount = 0;
ludoGameState.redWinnerCount = 0;
ludoGameState.bluePieces.forEach(p => { clearJailTimer(p); p.position = -1; p.isOnBoard = false; p.inWinnerCell = false; p.isInHome = true; p.jailRemainingSeconds = 0; });
ludoGameState.redPieces.forEach(p => { clearJailTimer(p); p.position = -1; p.isOnBoard = false; p.inWinnerCell = false; p.isInHome = true; p.jailRemainingSeconds = 0; });
ludoGameState.winnerCells.forEach(w => { w.occupied = false; w.occupiedBy = null; });
ludoGameState.shieldEffects = [];
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
document.getElementById('ghostJumpscareOverlay').style.display = 'none';
document.getElementById('ghostJumpscareOverlay').classList.remove('active');
document.getElementById('thunderOverlay').innerHTML = '';
document.getElementById('thunderOverlay').classList.remove('active');
document.getElementById('ludoEndGameButtons').style.display = 'none';
document.getElementById('simulationImageOverlay').classList.remove('active');
document.getElementById('simulationImageOverlay').style.display = 'none';
document.getElementById('simulationAnimationContainer').classList.remove('active');
document.getElementById('simulationAnimationContainer').innerHTML = '';
ludoPlayBackgroundSound();
setTimeout(() => {
ludoCheckSimulationConditions();
}, 500);
ludoUpdateSaveButtons();
}
function startLudoGame() {
document.getElementById('mainMenu').style.display = 'none';
document.getElementById('ludoScreen').style.display = 'block';
document.getElementById('mainBody').classList.remove('main-menu-active');
document.getElementById('ludoStartScreen').classList.remove('hidden');
document.getElementById('ludoGameContainer').style.display = 'none';
}
function startLudoGameDirectly() {
document.getElementById('ludoStartScreen').classList.add('hidden');
setTimeout(() => {
document.getElementById('ludoStartScreen').style.display = 'none';
document.getElementById('ludoGameContainer').style.display = 'block';
ludoInitGame();
window.scrollTo(0, 0);
}, 500);
}
function returnToMainMenu() {
if (ludoGameState.ghostActive) {
ludoGameState.ghostActive = false;
document.querySelectorAll('.ghost-piece').forEach(el => el.remove());
ludoGameState.ghostPieces = [];
}
document.getElementById('ghostJumpscareOverlay').style.display = 'none';
document.getElementById('ghostJumpscareOverlay').classList.remove('active');
document.getElementById('thunderOverlay').innerHTML = '';
document.getElementById('thunderOverlay').classList.remove('active');
document.getElementById('simulationImageOverlay').classList.remove('active');
document.getElementById('simulationImageOverlay').style.display = 'none';
document.getElementById('simulationAnimationContainer').classList.remove('active');
document.getElementById('simulationAnimationContainer').innerHTML = '';
document.querySelectorAll('.ludo-simulation-piece').forEach(el => el.remove());
ludoGameState.simulationPieces = [];
ludoGameState.simulationActive = false;
document.getElementById('hackerAnimationContainer').classList.remove('active');
document.getElementById('hackerAnimationContainer').innerHTML = '';
document.getElementById('hackerChallengeModal').classList.remove('active');
document.getElementById('hackerChallengeModal').style.display = 'none';
ludoPauseBackgroundSound();
document.getElementById('ludoScreen').style.display = 'none';
document.getElementById('mainBody').classList.add('main-menu-active');
document.getElementById('mainMenu').style.display = 'block';
document.getElementById('ludoEndGameButtons').style.display = 'none';
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('mainMenu').style.display = 'block';
document.getElementById('ludoScreen').style.display = 'none';
document.getElementById('mainBody').classList.add('main-menu-active');
});
</script>
</body>
</html>Game Source: بازی منچ کیهانی - نسخه نهایی با هکر
Creator: FrostGlider12
Libraries: none
Complexity: complex (9154 lines, 462.1 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-frostglider12" to link back to the original. Then publish at arcadelab.ai/publish.