Cari Blog Ini
import React, { useState, useEffect } from 'react';
import { Trophy, Coins, MapPin, Dice6, HelpCircle, CheckCircle2, Users, Zap, ShieldAlert, Info, Home, Building2, Landmark, ArrowRight, Gavel, Wallet, PieChart } from 'lucide-react';
const BOARD_SIZE = 40;
const INITIAL_MONEY = 20000000; // Rp 20.000.000
const PASS_START_BONUS = 2000000; // Rp 2.000.000
const LOGO_URL = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhnIQw80ymfYM-Na9tDHiK9mwSXyXvWqPezA&s";
const PLAYERS_CONFIG = [
{ id: 0, name: "Kelompok 1", color: "bg-blue-600", border: "border-blue-600", text: "text-blue-600", shadow: "shadow-blue-200" },
{ id: 1, name: "Kelompok 2", color: "bg-red-600", border: "border-red-600", text: "text-red-600", shadow: "shadow-red-200" },
{ id: 2, name: "Kelompok 3", color: "bg-green-600", border: "border-green-600", text: "text-green-600", shadow: "shadow-green-200" },
{ id: 3, name: "Kelompok 4", color: "bg-yellow-500", border: "border-yellow-500", text: "text-yellow-600", shadow: "shadow-yellow-200" },
];
const BUPATI_LIST = [
{ period: "1960-1963", name: "Andi Tjatjo Gelar Datuk Wiharja" },
{ period: "1963-1964", name: "Damus Managing Frans" },
{ period: "1964-1965", name: "E.N. Zakaria Mas Tronojoyo" },
{ period: "1965-1972", name: "Kol.Pol.H.Asnawi Arbain" },
{ period: "1972-1985", name: "Kol.H.Soetadji" },
{ period: "1985-1990", name: "Kol.Soelarsono" },
{ period: "1990-1995", name: "Kol.Inf.H.Yususf Dali" },
{ period: "1995-2000", name: "Kol.Art.R.A. Bessing" },
{ period: "2000-2005", name: "H. Anang Dachlan Djauhari" },
{ period: "2005", name: "H. Abdussamad" },
{ period: "2005-2015", name: "Drs.H.Budiman Arifin,M.Si" },
{ period: "2015-2016", name: "Ir. H. Syaiful Herman, M.AP" },
{ period: "2016-2021", name: "H. Sudjati, SH" },
{ period: "2021-sekarang", name: "Syarwani, SPd, MSi" }
];
const BOARD_DATA = [
{ id: 0, name: "START", type: "special", price: 0 },
{ id: 1, name: "Sungai Urang", type: "property", price: 1000000, q: "Sungai Urang merupakan wilayah di Tanjung Palas Hilir yang menghubungkan jalan poros Malinau dengan...?", options: ["A. Kec. Tanjung Palas", "B. Kec. Bunyu", "C. Kec. Sekatak", "D. Kec. Peso"], a: 0 },
{ id: 2, name: "Batu Tumpuk", type: "property", price: 1100000, q: "Batu Tumpuk merupakan objek wisata di daerah...?", options: ["A. Tanjung Palas Utara", "B. Bunyu", "C. Sekatak", "D. Peso Hilir"], a: 0 },
{ id: 3, name: "Antutan", type: "property", price: 1200000, q: "Untuk menuju Desa Antutan yang memiliki pasar buah, urutan desa yang dilewati dari Tj. Selor adalah...?", options: ["A. Pejalai - Silva Rahayu", "B. Jelarai - Pejalin", "C. Gunung Seriang - Pimping", "D. Long Beluah - Long Bia"], a: 1 },
{ id: 4, name: "Pemandian Rainbow", type: "property", price: 1500000, q: "Pemandian Rainbow merupakan destinasi wisata keluarga yang terletak di wilayah...?", options: ["A. Tanjung Selor", "B. Tanjung Palas Tengah", "C. Tanjung Palas Barat", "D. Tanjung Palas Timur"], a: 2 },
{ id: 5, name: "Pajak Konsumsi", type: "special_tax", price: 500000 },
{ id: 6, name: "Kec. Peso", type: "property", price: 1500000, q: "Kecamatan Peso secara geografis berada di wilayah mana dalam peta Kabupaten Bulungan?", options: ["A. Pesisir Timur", "B. Kepulauan Utara", "C. Hulu/Pedalaman Barat", "D. Dataran Rendah Selatan"], a: 2 },
{ id: 7, name: "Pemandian G. Seriang", type: "property", price: 1600000, q: "Daya tarik utama wisata Gunung Seriang selain kolam pemandiannya adalah...?", options: ["A. Gua Alam dan Stalaktit", "B. Kawah Lumpur", "C. Pasir Putih Pantai", "D. Hutan Mangrove"], a: 0 },
{ id: 8, name: "Kec. Peso Hilir", type: "property", price: 1500000, q: "Peso Hilir resmi menjadi kecamatan hasil pemekaran dari kecamatan induk yaitu...?", options: ["A. Peso", "B. Sekatak", "C. Tanjung Palas", "D. Tanjung Selor"], a: 0 },
{ id: 9, name: "Kec. Sekatak", type: "property", price: 1800000, q: "Potensi sumber daya alam yang paling menonjol dan menjadi mata pencaharian di Sekatak adalah...?", options: ["A. Perkebunan Kopi", "B. Pertambangan Emas", "C. Budidaya Rumput Laut", "D. Industri Tekstil"], a: 1 },
{ id: 10, name: "PENJARA", type: "special", price: 0 },
{ id: 11, name: "Tanjung Palas", type: "property", price: 2200000, q: "Tanjung Palas memiliki nilai sejarah tinggi sebagai...?", options: ["A. Pelabuhan Internasional", "B. Pusat Kesultanan Bulungan", "C. Kota Industri Kayu", "D. Desa Tertua di Kalimantan"], a: 1 },
{ id: 12, name: "Air Terjun Kilo 28", type: "utility", price: 2500000, q: "Siapa nama Bupati Bulungan yang menjabat pada periode 1990-1995?", options: ["A. Kol.Pol.H.Asnawi Arbain", "B. Kol.Inf.H.Yusuf Dali", "C. Kol.H.Soetadji", "D. Drs.H.Budiman Arifin"], a: 1 },
{ id: 13, name: "Tanjung Palas Barat", type: "property", price: 2200000, q: "Salah satu desa yang menjadi pusat administrasi di Tanjung Palas Barat adalah...?", options: ["A. Long Beluah", "B. Tanah Kuning", "C. Mangkupadi", "D. Salimbatu"], a: 0 },
{ id: 14, name: "Tanjung Palas Tengah", type: "property", price: 2400000, q: "Suku asli yang mendiami dan memberi nama wilayah Bulungan berasal dari kelompok...?", options: ["A. Suku Banjar", "B. Suku Bulungan", "C. Suku Tidung", "D. Suku Dayak Kenyah"], a: 1 },
{ id: 15, name: "Bandara Harapan", type: "transport", price: 2000000, q: "Siapa tokoh yang menjabat sebagai Bupati Bulungan pada masa transisi tahun 2005?", options: ["A. Drs.H.Budiman Arifin", "B. H. Abdussamad", "C. H. Sudjati, SH", "D. Syarwani, SPd"], a: 1 },
{ id: 16, name: "Tanjung Palas Timur", type: "property", price: 2800000, q: "Destinasi wisata Pantai Tanah Kuning yang terkenal berada di wilayah kecamatan...?", options: ["A. Tanjung Palas Timur", "B. Tanjung Palas Tengah", "C. Pulau Bunyu", "D. Tanjung Selor"], a: 0 },
{ id: 17, name: "Taman Tepian", type: "property", price: 2900000, q: "Sungai yang membelah Tanjung Selor dan Tanjung Palas yang di tepinya dibangun Taman Tepian adalah...?", options: ["A. Sungai Kayan", "B. Sungai Mahakam", "C. Sungai Bahau", "D. Sungai Segah"], a: 0 },
{ id: 18, name: "Tanjung Palas Utara", type: "property", price: 2800000, q: "Kecamatan Tanjung Palas Utara berbatasan langsung di sebelah utara dengan kabupaten...?", options: ["A. Berau", "B. Tana Tidung", "C. Nunukan", "D. Malinau"], a: 1 },
{ id: 19, name: "Tugu Cinta Damai", type: "property", price: 3000000, q: "Tugu Cinta Damai (TCD) sebagai simbol kerukunan terletak di jantung kota...?", options: ["A. Tanjung Selor", "B. Tarakan", "C. Malinau", "D. Tideng Pale"], a: 0 },
{ id: 20, name: "PARKIR BEBAS", type: "special", price: 0 },
{ id: 21, name: "Pulau Bunyu", type: "property", price: 3500000, q: "Pulau Bunyu merupakan wilayah strategis di Bulungan yang menjadi sumber utama...?", options: ["A. Padi dan Palawija", "B. Minyak Bumi dan Gas", "C. Kayu Gaharu", "D. Peternakan Sapi"], a: 1 },
{ id: 22, name: "Tugu Lemlai Suri", type: "property", price: 3600000, q: "Nama 'Lemlai Suri' pada tugu ikonik di Tanjung Selor diambil dari nama...?", options: ["A. Istri Sultan Pertama", "B. Tokoh Legendaris/Putri Bangsawan", "C. Pahlawan Perang Dunia II", "D. Gunung Tertinggi"], a: 1 },
{ id: 23, name: "PLTMG Tj. Selor", type: "property", price: 3500000, q: "Fasilitas PLTMG di Tanjung Selor menggunakan sumber energi utama berupa...?", options: ["A. Aliran Air", "B. Gas Alam", "C. Batubara", "D. Cahaya Matahari"], a: 1 },
{ id: 24, name: "Kulteka", type: "property", price: 3800000, q: "Akronim dari pusat kuliner 'Kulteka' yang populer di Tanjung Selor adalah...?", options: ["A. Kuliner Tepi Kayan", "B. Kuliner Tetap Kaya", "C. Kumpulan Tekad Kami", "D. Kuliner Tengah Kota"], a: 0 },
{ id: 25, name: "Pelabuhan Bunyu", type: "transport", price: 2000000, q: "Siapa Bupati Bulungan yang menjabat paling lama (13 tahun) antara 1972-1985?", options: ["A. Kol.Pol.H.Asnawi Arbain", "B. Kol.H.Soetadji", "C. Kol.Soelarsono", "D. Andi Tjatjo"], a: 1 },
{ id: 26, name: "Pemandian Kelubir", type: "property", price: 4200000, q: "Desa Kelubir yang memiliki potensi agrowisata dan pemandian berada di kecamatan...?", options: ["A. Tanjung Palas Utara", "B. Tanjung Palas Tengah", "C. Sekatak", "D. Peso Hilir"], a: 0 },
{ id: 27, name: "Wisata G. Putih", type: "property", price: 4200000, q: "Gunung Putih di Tanjung Palas merupakan formasi batuan jenis...?", options: ["A. Batuan Kapur/Kapurit", "B. Batuan Beku Vulkanik", "C. Pasir Silika", "D. Tanah Liat"], a: 0 },
{ id: 28, name: "PLTA Kayan", type: "utility", price: 2500000, q: "Siapa nama Bupati Bulungan pertama (periode 1960-1963)?", options: ["A. Damus Managing Frans", "B. Andi Tjatjo Gelar Datuk Wiharja", "C. E.N. Zakaria", "D. H. Asnawi Arbain"], a: 1 },
{ id: 29, name: "Wisata G. Seriang", type: "property", price: 4500000, q: "Salah satu daya tarik spesifik dari objek wisata Gunung Seriang adalah...?", options: ["A. Pantai Berpasir", "B. Pemandian dan Area Camping", "C. Perkebunan Teh", "D. Museum Keramik"], a: 1 },
{ id: 30, name: "KE PENJARA", type: "special", price: 0 },
{ id: 31, name: "Kec. Tanjung Selor", type: "property", price: 5000000, q: "Tanjung Selor saat ini memegang peranan ganda sebagai ibukota kabupaten dan...?", options: ["A. Ibukota Provinsi Kaltara", "B. Kawasan Ekonomi Khusus", "C. Pusat Militer Nasional", "D. Kota Pelabuhan Bebas"], a: 0 },
{ id: 32, name: "Air Terjun Long Pin", type: "property", price: 5000000, q: "Air Terjun Long Pin terletak di kawasan pedalaman yang asri di wilayah...?", options: ["A. Tanjung Selor", "B. Hulu Sungai Kayan (Peso)", "C. Bunyu", "D. Tanjung Palas Timur"], a: 1 },
{ id: 33, name: "Pajak Tanah", type: "special_tax", price: 1000000 },
{ id: 34, name: "Hutan Bundayati", type: "property", price: 5500000, q: "Nama 'Bundayati' pada Hutan Kota di Tanjung Selor merupakan akronim dari...?", options: ["A. Bulungan Damai Nyaman dan Hati", "B. Bulungan Berdaya Berkarya dan Bakti", "C. Bulungan Berdaulat dan Nyaman di Hati", "D. Bulungan Berbudaya dan Sejati"], a: 2 },
{ id: 35, name: "Kawasan KIPI", type: "transport", price: 2000000, q: "Siapa Bupati Bulungan yang saat ini menjabat (periode 2021-sekarang)?", options: ["A. Drs.H.Budiman Arifin", "B. H. Sudjati, SH", "C. Syarwani, SPd, MSi", "D. Ingkong Ala"], a: 2 },
{ id: 36, name: "Pantai T. Kuning", type: "property", price: 6000000, q: "Pasir di Pantai Tanah Kuning memiliki karakteristik unik yaitu...?", options: ["A. Hitam Pekat", "B. Putih Kecokelatan", "C. Merah Muda", "D. Hijau Lumut"], a: 1 },
{ id: 37, name: "Balai Adat Dayak", type: "property", price: 6500000, q: "Upacara adat 'Meja Panjang' merupakan tradisi khas suku Dayak di Bulungan yang melambangkan...?", options: ["A. Persiapan Perang", "B. Kebersamaan dan Rasa Syukur", "C. Ritual Pemakaman", "D. Pernikahan Bangsawan"], a: 1 },
{ id: 38, name: "Balai Adat Tidung", type: "property", price: 6500000, q: "Selain sebagai tempat upacara adat, Balai Adat Tidung di Bulungan sering digunakan untuk festival...?", options: ["A. Birau", "B. Erau", "C. Cap Go Meh", "D. Sekaten"], a: 0 },
{ id: 39, name: "Museum Kesultanan", type: "property", price: 8000000, q: "Benda bersejarah apa yang menjadi koleksi utama di Museum Kesultanan Bulungan?", options: ["A. Meriam Bertuah dan Singgasana", "B. Kerangka Dinosaurus", "C. Pesawat Tempur", "D. Arca Hindu Budha"], a: 0 },
];
const Dice3D = ({ value, rolling }) => {
const rotations = {
1: 'rotateX(0deg) rotateY(0deg)',
2: 'rotateX(-90deg) rotateY(0deg)',
3: 'rotateX(0deg) rotateY(-90deg)',
4: 'rotateX(0deg) rotateY(90deg)',
5: 'rotateX(90deg) rotateY(0deg)',
6: 'rotateX(180deg) rotateY(0deg)',
};
return (
);
};
const App = () => {
const [players, setPlayers] = useState([
{ id: 0, money: INITIAL_MONEY, pos: 0, owned: {}, inJail: false, jailTurns: 0 },
{ id: 1, money: INITIAL_MONEY, pos: 0, owned: {}, inJail: false, jailTurns: 0 },
{ id: 2, money: INITIAL_MONEY, pos: 0, owned: {}, inJail: false, jailTurns: 0 },
{ id: 3, money: INITIAL_MONEY, pos: 0, owned: {}, inJail: false, jailTurns: 0 },
]);
const [turn, setTurn] = useState(0);
const [hasRolled, setHasRolled] = useState(false);
const [isRolling, setIsRolling] = useState(false);
const [dices, setDices] = useState([1, 1]);
const [message, setMessage] = useState("Kelompok 1, kocok dadu untuk memulai!");
const [modal, setModal] = useState({ show: false, type: '', data: null });
const fmt = (num) => "Rp" + new Intl.NumberFormat('id-ID').format(num);
const getOwnerIdx = (tileIdx) => {
return players.findIndex(p => p.owned && p.owned[tileIdx] !== undefined);
};
const calculateWealth = (player) => {
let assetsValue = 0;
Object.keys(player.owned).forEach(tileIdx => {
const tile = BOARD_DATA[tileIdx];
const buildingCost = player.owned[tileIdx].buildingPrice || 0;
assetsValue += (tile.price + buildingCost);
});
return player.money + assetsValue;
};
const nextTurn = () => {
setTurn((prev) => (prev + 1) % 4);
setHasRolled(false);
setMessage(`Sekarang giliran ${PLAYERS_CONFIG[(turn + 1) % 4].name}.`);
};
const rollDice = () => {
if (isRolling || modal.show || hasRolled) return;
const player = players[turn];
if (player.inJail) {
handleJailChallenge();
return;
}
setIsRolling(true);
setHasRolled(true);
setMessage("Mengocok dadu...");
let count = 0;
const interval = setInterval(() => {
setDices([Math.floor(Math.random() * 6) + 1, Math.floor(Math.random() * 6) + 1]);
count++;
if (count > 12) {
clearInterval(interval);
const d1 = Math.floor(Math.random() * 6) + 1;
const d2 = Math.floor(Math.random() * 6) + 1;
setDices([d1, d2]);
movePlayer(d1 + d2);
}
}, 100);
};
const handleJailChallenge = () => {
const randomIdx = Math.floor(Math.random() * BUPATI_LIST.length);
const bupati = BUPATI_LIST[randomIdx];
let opts = [bupati.name];
while(opts.length < 4) {
const rand = BUPATI_LIST[Math.floor(Math.random() * BUPATI_LIST.length)].name;
if(!opts.includes(rand)) opts.push(rand);
}
opts.sort(() => Math.random() - 0.5);
setModal({
show: true,
type: 'JAIL_QUIZ',
data: {
period: bupati.period,
correct: bupati.name,
options: opts,
turnCount: players[turn].jailTurns + 1
}
});
};
const handleJailQuizResult = (isCorrect) => {
let updatedPlayers = [...players];
const currentJailTurn = updatedPlayers[turn].jailTurns + 1;
if (isCorrect) {
updatedPlayers[turn].inJail = false;
updatedPlayers[turn].jailTurns = 0;
setPlayers(updatedPlayers);
setMessage("Jawaban BENAR! Anda bebas.");
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
} else {
updatedPlayers[turn].jailTurns = currentJailTurn;
setPlayers(updatedPlayers);
if (currentJailTurn >= 3) {
setModal({ show: true, type: 'JAIL_FINAL_FAIL', data: null });
} else {
setMessage(`Jawaban SALAH! Kesempatan ${currentJailTurn}/3 terpakai.`);
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
}
}
};
const releaseOnProbation = () => {
let updatedPlayers = [...players];
updatedPlayers[turn].inJail = false;
updatedPlayers[turn].jailTurns = 0;
setPlayers(updatedPlayers);
setMessage("Bebas Bersyarat!");
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
};
const movePlayer = (steps) => {
let updatedPlayers = [...players];
const oldPos = updatedPlayers[turn].pos;
const newPos = (oldPos + steps) % BOARD_SIZE;
if (newPos < oldPos) {
updatedPlayers[turn].money += PASS_START_BONUS;
}
updatedPlayers[turn].pos = newPos;
setPlayers(updatedPlayers);
setIsRolling(false);
setTimeout(() => handleLanding(newPos, updatedPlayers), 600);
};
const handleLanding = (pos, currentPlayers) => {
const tile = BOARD_DATA[pos];
if (tile.type === "property" || tile.type === "transport" || tile.type === "utility") {
const ownerIdx = getOwnerIdx(pos);
if (ownerIdx === -1) {
setModal({
show: true,
type: 'QUIZ_BUY',
data: {
tileIdx: pos,
name: tile.name,
price: tile.price,
q: tile.q,
options: tile.options,
a: tile.a ?? 0
}
});
} else if (ownerIdx === turn) {
setModal({
show: true,
type: 'QUIZ_BUILD',
data: {
tileIdx: pos,
name: tile.name,
price: tile.price,
q: tile.q,
options: tile.options,
a: tile.a ?? 0
}
});
} else {
const assetValue = tile.price + (currentPlayers[ownerIdx].owned[pos].buildingPrice || 0);
const rent = Math.floor(assetValue * 0.2);
let updated = [...currentPlayers];
updated[turn].money -= rent;
updated[ownerIdx].money += rent;
setPlayers(updated);
setMessage(`Mendarat di aset ${PLAYERS_CONFIG[ownerIdx].name}. Bayar sewa ${fmt(rent)}`);
setTimeout(nextTurn, 2500);
}
} else if (tile.type === "tax" || tile.type === "special_tax") {
let updated = [...currentPlayers];
updated[turn].money -= tile.price;
setPlayers(updated);
setMessage(`${tile.name}! Bayar denda ${fmt(tile.price)}`);
setTimeout(nextTurn, 2500);
} else if (pos === 30) {
let updated = [...currentPlayers];
updated[turn].pos = 10;
updated[turn].inJail = true;
updated[turn].jailTurns = 0;
setPlayers(updated);
setMessage("MASUK PENJARA!");
setTimeout(nextTurn, 2500);
} else {
setMessage(`Berhenti di ${tile.name}.`);
setTimeout(nextTurn, 1500);
}
};
const handleQuizResult = (isCorrect) => {
const tileData = modal.data;
if (!isCorrect) {
setMessage(`Jawaban salah! ${PLAYERS_CONFIG[turn].name} kehilangan kesempatan.`);
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
return;
}
setModal({ show: true, type: modal.type === 'QUIZ_BUY' ? 'CONFIRM_BUY' : 'CONFIRM_BUILD', data: tileData });
};
const executeBuy = (tileData) => {
const pos = tileData.tileIdx;
const tile = BOARD_DATA[pos];
let updated = [...players];
if (updated[turn].money >= tile.price) {
updated[turn].money -= tile.price;
updated[turn].owned = { ...updated[turn].owned, [pos]: { level: 0, buildingPrice: 0 } };
setPlayers(updated);
setMessage(`${tile.name} dibeli oleh ${PLAYERS_CONFIG[turn].name}!`);
}
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
};
const executeBuild = (tileData) => {
const pos = tileData.tileIdx;
const tile = BOARD_DATA[pos];
const buildCost = Math.floor(tile.price * 0.8);
let updated = [...players];
if (updated[turn].money >= buildCost) {
updated[turn].money -= buildCost;
const currentAsset = updated[turn].owned[pos];
updated[turn].owned[pos] = {
...currentAsset,
level: currentAsset.level + 1,
buildingPrice: (currentAsset.buildingPrice || 0) + buildCost
};
setPlayers(updated);
setMessage(`Gedung dibangun di ${tile.name}!`);
}
setModal({ show: false, type: '', data: null });
setTimeout(nextTurn, 1500);
};
const skipAction = () => {
setModal({ show: false, type: '', data: null });
setMessage("Aksi dilewati.");
setTimeout(nextTurn, 1500);
};
return (
{[...Array(6)].map((_, i) => )}
{[...Array(4)].map((_, i) => )}
{/* HEADER DENGAN LOGO DI ATAS */}
{ e.target.style.display = 'none'; }}
/>
{/* KONTROL DADU */}
{/* PAPAN PERMAINAN */}
{/* MODAL KUIS & AKSI */}
{modal.show && (
{modal.type.includes('JAIL') ?
{modal.type === 'JAIL_QUIZ' && modal.data && (
<>
)}
{modal.type === 'CONFIRM_BUY' && (
)}
{modal.type === 'CONFIRM_BUILD' && (
)}
)}
{/* FOOTER INFORMASI */}
Lewat Start: +2 Juta
Sewa: 20% Nilai Aset
Penjara: 3x Jawab Kuis
);
};
export default App;MONOPOLI KABUPATEN BULUNGAN
{players.map((p, i) => (
Modal
{fmt(p.money)}
Total Aset
{fmt(calculateWealth(p))}
{p.inJail && (
DI PENJARA ({p.jailTurns}/3)
)}
))}
{PLAYERS_CONFIG[i].name}
{/* Tanda air (watermark) tetap ada namun sangat samar */}
BULUNGAN
"{message}"
{BOARD_DATA.map((tile, i) => {
const ownerIdx = getOwnerIdx(i);
const level = ownerIdx !== -1 ? players[ownerIdx].owned[i].level : 0;
let x = 0, y = 0;
if (i <= 10) { x = 10 - i; y = 10; }
else if (i <= 20) { x = 0; y = 10 - (i - 10); }
else if (i <= 30) { x = i - 20; y = 0; }
else { x = 10; y = i - 30; }
return (
p.pos === i) ? 'z-30 scale-110 shadow-2xl ring-4 ring-slate-900 border-none' : ''}
${tile.type === 'special' ? 'bg-slate-100 font-black' : ''}
`}>
);
})}
{tile.name}
{tile.price > 0 && ownerIdx === -1 && {fmt(tile.price)}}
{ownerIdx !== -1 && }
{[...Array(level)].map((_, idx) => )}
{players.map((p, idx) => p.pos === i && (
))}
{modal.type.includes('JAIL') ? : }
{PLAYERS_CONFIG[turn].name}
{modal.type === 'JAIL_QUIZ' && modal.data && (
<>
Kuis Penjara - {modal.data.turnCount}/3
Siapa Bupati Bulungan periode {modal.data.period}?
{modal.data.options.map((opt, idx) => (
))}
)}
{(modal.type === 'QUIZ_BUY' || modal.type === 'QUIZ_BUILD') && modal.data && (
<>
Kuis Wilayah: {modal.data.name}
{modal.data.q}
{modal.data.options.map((opt, idx) => (
))}
)}
{modal.type === 'JAIL_FINAL_FAIL' && (
Gagal 3x!
Anda diberikan Bebas Bersyarat.
BENAR!
Beli {modal.data?.name} seharga {fmt(modal.data?.price)}?
BANGUN?
Biaya: {fmt(Math.floor(modal.data?.price * 0.8))}
games