166 lines
12 KiB
JavaScript
166 lines
12 KiB
JavaScript
// Monopoly — static data. No Phaser, no state.
|
||
|
||
export const BOARD_SIZE = 840;
|
||
export const CORNER_SIZE = 105;
|
||
export const SPACE_W = 70;
|
||
export const BAND_H = 18;
|
||
|
||
export const GROUP_COLORS = {
|
||
brown: 0x9B5524,
|
||
lightblue:0x00B3E8,
|
||
pink: 0xD63384,
|
||
orange: 0xE77A2C,
|
||
red: 0xDC3545,
|
||
yellow: 0xE8C12C,
|
||
green: 0x1F8C3B,
|
||
darkblue: 0x003580,
|
||
};
|
||
|
||
export const GROUP_HEX = {
|
||
brown: '#9B5524',
|
||
lightblue:'#00B3E8',
|
||
pink: '#D63384',
|
||
orange: '#E77A2C',
|
||
red: '#DC3545',
|
||
yellow: '#E8C12C',
|
||
green: '#1F8C3B',
|
||
darkblue: '#003580',
|
||
};
|
||
|
||
// 40 spaces, index 0–39, clockwise starting from Go.
|
||
// rent[]: [base, monopoly, 1house, 2h, 3h, 4h, hotel]
|
||
export const SPACES = [
|
||
{ type:'go', name:'GO' },
|
||
{ type:'property', name:'Mediterranean Ave', group:'brown', price:60, rent:[2,4,10,30,90,160,250], houseCost:50, mortgage:30 },
|
||
{ type:'community_chest', name:'Community Chest' },
|
||
{ type:'property', name:'Baltic Ave', group:'brown', price:60, rent:[4,8,20,60,180,320,450], houseCost:50, mortgage:30 },
|
||
{ type:'tax', name:'Income Tax', amount:200 },
|
||
{ type:'railroad', name:'Reading Railroad', price:200, mortgage:100 },
|
||
{ type:'property', name:'Oriental Ave', group:'lightblue',price:100, rent:[6,12,30,90,270,400,550], houseCost:50, mortgage:50 },
|
||
{ type:'chance', name:'Chance' },
|
||
{ type:'property', name:'Vermont Ave', group:'lightblue',price:100, rent:[6,12,30,90,270,400,550], houseCost:50, mortgage:50 },
|
||
{ type:'property', name:'Connecticut Ave', group:'lightblue',price:120, rent:[8,16,40,100,300,450,600], houseCost:50, mortgage:60 },
|
||
{ type:'jail', name:'Jail / Just Visiting' },
|
||
{ type:'property', name:'St. Charles Place', group:'pink', price:140, rent:[10,20,50,150,450,625,750], houseCost:100, mortgage:70 },
|
||
{ type:'utility', name:'Electric Company', price:150, mortgage:75 },
|
||
{ type:'property', name:'States Ave', group:'pink', price:140, rent:[10,20,50,150,450,625,750], houseCost:100, mortgage:70 },
|
||
{ type:'property', name:'Virginia Ave', group:'pink', price:160, rent:[12,24,60,180,500,700,900], houseCost:100, mortgage:80 },
|
||
{ type:'railroad', name:'Pennsylvania Railroad',price:200, mortgage:100 },
|
||
{ type:'property', name:'St. James Place', group:'orange', price:180, rent:[14,28,70,200,550,750,950], houseCost:100, mortgage:90 },
|
||
{ type:'community_chest', name:'Community Chest' },
|
||
{ type:'property', name:'Tennessee Ave', group:'orange', price:180, rent:[14,28,70,200,550,750,950], houseCost:100, mortgage:90 },
|
||
{ type:'property', name:'New York Ave', group:'orange', price:200, rent:[16,32,80,220,600,800,1000], houseCost:100, mortgage:100 },
|
||
{ type:'freeparking', name:'Free Parking' },
|
||
{ type:'property', name:'Kentucky Ave', group:'red', price:220, rent:[18,36,90,250,700,875,1050], houseCost:150, mortgage:110 },
|
||
{ type:'chance', name:'Chance' },
|
||
{ type:'property', name:'Indiana Ave', group:'red', price:220, rent:[18,36,90,250,700,875,1050], houseCost:150, mortgage:110 },
|
||
{ type:'property', name:'Illinois Ave', group:'red', price:240, rent:[20,40,100,300,750,925,1100], houseCost:150, mortgage:120 },
|
||
{ type:'railroad', name:'B&O Railroad', price:200, mortgage:100 },
|
||
{ type:'property', name:'Atlantic Ave', group:'yellow', price:260, rent:[22,44,110,330,800,975,1150], houseCost:150, mortgage:130 },
|
||
{ type:'property', name:'Ventnor Ave', group:'yellow', price:260, rent:[22,44,110,330,800,975,1150], houseCost:150, mortgage:130 },
|
||
{ type:'utility', name:'Water Works', price:150, mortgage:75 },
|
||
{ type:'property', name:'Marvin Gardens', group:'yellow', price:280, rent:[24,48,120,360,850,1025,1200], houseCost:150, mortgage:140 },
|
||
{ type:'gotojail', name:'Go To Jail' },
|
||
{ type:'property', name:'Pacific Ave', group:'green', price:300, rent:[26,52,130,390,900,1100,1275], houseCost:200, mortgage:150 },
|
||
{ type:'property', name:'North Carolina Ave', group:'green', price:300, rent:[26,52,130,390,900,1100,1275], houseCost:200, mortgage:150 },
|
||
{ type:'community_chest', name:'Community Chest' },
|
||
{ type:'property', name:'Pennsylvania Ave', group:'green', price:320, rent:[28,56,150,450,1000,1200,1400], houseCost:200, mortgage:160 },
|
||
{ type:'railroad', name:'Short Line Railroad', price:200, mortgage:100 },
|
||
{ type:'chance', name:'Chance' },
|
||
{ type:'property', name:'Park Place', group:'darkblue',price:350, rent:[35,70,175,500,1100,1300,1500], houseCost:200, mortgage:175 },
|
||
{ type:'tax', name:'Luxury Tax', amount:100 },
|
||
{ type:'property', name:'Boardwalk', group:'darkblue',price:400, rent:[50,100,200,600,1400,1700,2000], houseCost:200, mortgage:200 },
|
||
];
|
||
|
||
export const RAILROADS = [5, 15, 25, 35];
|
||
export const UTILITIES = [12, 28];
|
||
export const PURCHASABLE = SPACES.reduce((a,sp,i) =>
|
||
(sp.type==='property'||sp.type==='railroad'||sp.type==='utility') ? [...a,i] : a, []);
|
||
|
||
export const GROUPS = {
|
||
brown: [1, 3],
|
||
lightblue:[6, 8, 9],
|
||
pink: [11, 13, 14],
|
||
orange: [16, 18, 19],
|
||
red: [21, 23, 24],
|
||
yellow: [26, 27, 29],
|
||
green: [31, 32, 34],
|
||
darkblue: [37, 39],
|
||
};
|
||
|
||
export const PLAYER_COLORS = [0xE53935, 0x1565C0, 0x2E7D32, 0xF57F17];
|
||
export const PLAYER_COLOR_HEX = ['#E53935', '#1565C0', '#2E7D32', '#F57F17'];
|
||
|
||
// Chance cards (16)
|
||
export const CHANCE_CARDS = [
|
||
{ text:'Advance to GO.\nCollect $200.', effect:'advance_to', target:0 },
|
||
{ text:'Advance to Illinois Ave.\nIf you pass GO, collect $200.', effect:'advance_to', target:24 },
|
||
{ text:'Advance to St. Charles Place.\nIf you pass GO, collect $200.', effect:'advance_to', target:11 },
|
||
{ text:'Advance to the nearest Railroad.\nIf unowned, you may buy it.\nIf owned, pay double rent.', effect:'nearest_railroad', doubleRent:true },
|
||
{ text:'Advance to the nearest Railroad.\nIf unowned, you may buy it.\nIf owned, pay double rent.', effect:'nearest_railroad', doubleRent:true },
|
||
{ text:'Advance to the nearest Utility.\nIf unowned, you may buy it.\nIf owned, pay 10× your dice.', effect:'nearest_utility' },
|
||
{ text:'Bank pays you a dividend of $50.', effect:'collect', amount:50 },
|
||
{ text:'Get Out of Jail Free.\nKeep this card until needed.', effect:'goojf' },
|
||
{ text:'Go back 3 spaces.', effect:'back3' },
|
||
{ text:'Go directly to Jail.\nDo not pass GO. Do not collect $200.', effect:'go_to_jail' },
|
||
{ text:'Make general repairs on all your property.\n$25 per house · $100 per hotel.', effect:'repairs', house:25, hotel:100 },
|
||
{ text:'Pay a poor tax of $15.', effect:'pay', amount:15 },
|
||
{ text:'Take a trip to Reading Railroad.\nIf you pass GO, collect $200.', effect:'advance_to', target:5 },
|
||
{ text:'Advance to Boardwalk.', effect:'advance_to', target:39 },
|
||
{ text:'You have been elected Chairman of the Board.\nPay each player $50.', effect:'pay_each', amount:50 },
|
||
{ text:'Your building and loan matures.\nCollect $150.', effect:'collect', amount:150 },
|
||
];
|
||
|
||
// Community Chest cards (16)
|
||
export const CC_CARDS = [
|
||
{ text:'Advance to GO.\nCollect $200.', effect:'advance_to', target:0 },
|
||
{ text:'Bank error in your favor.\nCollect $200.', effect:'collect', amount:200 },
|
||
{ text:"Doctor's fee.\nPay $50.", effect:'pay', amount:50 },
|
||
{ text:'From sale of stock you get $50.', effect:'collect', amount:50 },
|
||
{ text:'Get Out of Jail Free.\nKeep this card until needed.', effect:'goojf' },
|
||
{ text:'Go directly to Jail.\nDo not pass GO. Do not collect $200.', effect:'go_to_jail' },
|
||
{ text:'Grand Opera Night.\nCollect $50 from every player.', effect:'collect_each', amount:50 },
|
||
{ text:'Holiday fund matures.\nCollect $100.', effect:'collect', amount:100 },
|
||
{ text:'Income tax refund.\nCollect $20.', effect:'collect', amount:20 },
|
||
{ text:'It is your birthday!\nCollect $10 from every player.', effect:'collect_each', amount:10 },
|
||
{ text:'Life insurance matures.\nCollect $100.', effect:'collect', amount:100 },
|
||
{ text:'Pay hospital fees of $100.', effect:'pay', amount:100 },
|
||
{ text:'Pay school fees of $150.', effect:'pay', amount:150 },
|
||
{ text:'Receive $25 consultancy fee.', effect:'collect', amount:25 },
|
||
{ text:'You are assessed for street repairs.\n$40 per house · $115 per hotel.', effect:'repairs', house:40, hotel:115 },
|
||
{ text:'You have won second prize in a beauty contest.\nCollect $10.', effect:'collect', amount:10 },
|
||
];
|
||
|
||
// Board-relative space geometry (add boardLeft, boardTop in scene)
|
||
export function spaceGeometry(idx) {
|
||
const C = CORNER_SIZE, W = SPACE_W, S = BOARD_SIZE;
|
||
if (idx === 0) return { x:S-C, y:S-C, w:C, h:C, isCorner:true };
|
||
if (idx === 10) return { x:0, y:S-C, w:C, h:C, isCorner:true };
|
||
if (idx === 20) return { x:0, y:0, w:C, h:C, isCorner:true };
|
||
if (idx === 30) return { x:S-C, y:0, w:C, h:C, isCorner:true };
|
||
if (idx >= 1 && idx <= 9) return { x:S-C-W*idx, y:S-C, w:W, h:C, bandEdge:'top', rotation:0 };
|
||
if (idx >= 11 && idx <= 19) return { x:0, y:S-C-W*(idx-10), w:C, h:W, bandEdge:'right', rotation:-Math.PI/2 };
|
||
if (idx >= 21 && idx <= 29) return { x:C+W*(idx-21), y:0, w:W, h:C, bandEdge:'bottom', rotation:Math.PI };
|
||
if (idx >= 31 && idx <= 39) return { x:S-C, y:C+W*(idx-31),w:C, h:W, bandEdge:'left', rotation:Math.PI/2 };
|
||
}
|
||
|
||
export function spaceCenter(idx) {
|
||
const g = spaceGeometry(idx);
|
||
return { x: g.x + g.w / 2, y: g.y + g.h / 2 };
|
||
}
|
||
|
||
export function nearestRailroad(pos) {
|
||
for (const r of RAILROADS) if (r > pos) return r;
|
||
return RAILROADS[0];
|
||
}
|
||
|
||
export function nearestUtility(pos) {
|
||
for (const u of UTILITIES) if (u > pos) return u;
|
||
return UTILITIES[0];
|
||
}
|
||
|
||
// Pawn spritesheet: frame = seat index (0-3), 80×80 px cells
|
||
export const PAWN_FRAME = (seat) => seat;
|
||
// Card spritesheet: frame 0 = Chance, frame 1 = Community Chest, 200×300 px cells
|
||
export const CARD_FRAME = { chance: 0, community_chest: 1 };
|