1
0

Fix #10 -- minimum road length starts at 5

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-02-26 13:49:23 -08:00
parent 54e1a51c04
commit fed7bcea6c

View File

@ -228,11 +228,10 @@ const processGameOrder = (game, player, dice) => {
message = `Initial settlement placement has started!`; message = `Initial settlement placement has started!`;
game.direction = 'forward'; game.direction = 'forward';
game.turn = { game.turn = {
actions: [ 'place-settlement' ],
limits: { corners: getValidCorners(game) },
name: getPlayerName(game, players[0]), name: getPlayerName(game, players[0]),
color: getPlayerColor(game, players[0]) color: getPlayerColor(game, players[0])
}; };
placeSettlement(game, getValidCorners(game));
addChatMessage(game, null, message); addChatMessage(game, null, message);
message = `It is ${game.turn.name}'s turn to place a settlement.`; message = `It is ${game.turn.name}'s turn to place a settlement.`;
} else { } else {
@ -524,7 +523,7 @@ const loadGame = async (id) => {
} }
if (typeof game.turn !== 'object') { if (typeof game.turn !== 'object') {
delete game.turn; game.turn = {};
} }
if (!game.placements) { if (!game.placements) {
@ -563,8 +562,18 @@ const clearPlayer = (player) => {
delete player.orderStatus; delete player.orderStatus;
} }
const canGiveBuilding = (game) => {
if (!game.turn.roll) {
return `Admin cannot give a building until the dice have been rolled.`;
}
if (game.turn.actions && game.turn.actions.length !== 0) {
return `Admin cannot give a building while other actions in play: ${game.turn.actions.join(', ')}.`
}
return undefined;
}
const adminActions = (game, action, value) => { const adminActions = (game, action, value) => {
let color, player, parts, session; let color, player, parts, session, corners, error;
switch (action) { switch (action) {
case "debug": case "debug":
@ -585,25 +594,93 @@ const adminActions = (game, action, value) => {
break; break;
case "give": case "give":
parts = value.match(/^([^-]+)-(.*)$/); parts = value.match(/^([^-]+)(-(.*))?$/);
if (!parts) { if (!parts) {
return `Unable to parse give request.`; return `Unable to parse give request.`;
} }
const type = parts[1], card = parts[2]; const type = parts[1], card = parts[3];
for (let id in game.sessions) { for (let id in game.sessions) {
if (game.sessions[id].name === game.turn.name) { if (game.sessions[id].name === game.turn.name) {
session = game.sessions[id]; session = game.sessions[id];
} }
} }
if (!session) { if (!session) {
return `Unable to determine current player turn to give resources.`; return `Unable to determine current player turn to give resources.`;
} }
if ([ 'wheat', 'sheep', 'wood', 'stone', 'brick' ].indexOf(type) !== -1) { let done = true;
const count = parseInt(card); switch (type) {
session.player[type] += count; case 'road':
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`); error = canGiveBuilding(game);
if (error) {
return error;
}
if (session.player.roads === 0) {
return `Player ${game.turn.name} does not have any more roads to give.`;
}
let roads = getValidRoads(game, session.color);
if (roads.length === 0) {
return `There are no valid locations for ${game.turn.name} to place a road.`;
}
game.turn.free = true;
placeRoad(game, roads);
addChatMessage(game, null, `Admin gave a road to ${game.turn.name}.` +
`They must now place the road.`);
break;
case 'city':
error = canGiveBuilding(game);
if (error) {
return error;
}
if (session.player.cities === 0) {
return `Player ${game.turn.name} does not have any more cities to give.`;
}
corners = getValidCorners(game, session.color);
if (corners.length === 0) {
return `There are no valid locations for ${game.turn.name} to place a settlement.`;
}
corners = getValidCorners(game, session.color, 'settlement');
game.turn.free = true;
placeCity(game, corners);
addChatMessage(game, null, `Admin gave a city to ${game.turn.name}. ` +
`They must now place the city.`);
break;
case 'settlement':
error = canGiveBuilding(game);
if (error) {
return error;
}
if (session.player.settlements === 0) {
return `Player ${game.turn.name} does not have any more settlements to give.`;
}
corners = getValidCorners(game, session.color);
if (corners.length === 0) {
return `There are no valid locations for ${game.turn.name} to place a settlement.`;
}
game.turn.free = true;
placeSettlement(game, corners);
addChatMessage(game, null, `Admin gave a settlment to ${game.turn.name}. ` +
`They must now place the settlement.`);
break;
case 'wheat':
case 'sheep':
case 'wood':
case 'stone':
case 'brick':
const count = parseInt(card);
session.player[type] += count;
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`);
break;
default:
done = false;
break;
}
if (done) {
break; break;
} }
@ -1096,7 +1173,9 @@ const calculateRoadLengths = (game, session) => {
longestPlayers = [ key ]; longestPlayers = [ key ];
longestRoad = game.players[key].longestRoad; longestRoad = game.players[key].longestRoad;
} else if (game.players[key].longestRoad === longestRoad) { } else if (game.players[key].longestRoad === longestRoad) {
longestPlayers.push(key); if (longestRoad >= 5) {
longestPlayers.push(key);
}
} }
} }
@ -1385,6 +1464,21 @@ const offerToString = (offer) => {
offer.gets.map(item => `${item.count} ${item.type}`).join(', '); offer.gets.map(item => `${item.count} ${item.type}`).join(', ');
} }
const placeRoad = (game, limits) => {
game.turn.actions = [ 'place-road' ];
game.turn.limits = { roads: limits };
}
const placeCity = (game, limits) => {
game.turn.actions = [ 'place-city' ];
game.turn.limits = { corners: limits };
}
const placeSettlement = (game, limits) => {
game.turn.actions = [ 'place-settlement' ];
game.turn.limits = { corners: limits };
}
router.put("/:id/:action/:value?", async (req, res) => { router.put("/:id/:action/:value?", async (req, res) => {
const { action, id } = req.params, const { action, id } = req.params,
value = req.params.value ? req.params.value : ""; value = req.params.value ? req.params.value : "";
@ -1683,7 +1777,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
game.turn.placedRobber = true; game.turn.placedRobber = true;
pickRobber(game); pickRobber(game);
addChatMessage(game, session, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`); addChatMessage(game, null, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
let colors = []; let colors = [];
layout.tiles[robber].corners.forEach(cornerIndex => { layout.tiles[robber].corners.forEach(cornerIndex => {
@ -1701,7 +1795,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
game.turn.actions = []; game.turn.actions = [];
game.turn.robberInAction = false; game.turn.robberInAction = false;
delete game.turn.limits; delete game.turn.limits;
addChatMessage(game, session, `The dread robber ${game.robberName} was placed on a terrain with no other players, ` + addChatMessage(game, null, `The dread robber ${game.robberName} was placed on a terrain with no other players, ` +
`so ${game.turn.name} does not steal resources from anyone.`); `so ${game.turn.name} does not steal resources from anyone.`);
} }
@ -1877,7 +1971,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
game.turn.robberInAction = true; game.turn.robberInAction = true;
delete game.turn.placedRobber; delete game.turn.placedRobber;
addChatMessage(game, session, `The robber ${game.robberName} has fled before the power of the Knight, ` + addChatMessage(game, null, `The robber ${game.robberName} has fled before the power of the Knight, ` +
`but a new robber has returned and ${session.name} must now place them.`); `but a new robber has returned and ${session.name} must now place them.`);
game.turn.actions = [ 'place-robber' ]; game.turn.actions = [ 'place-robber' ];
game.turn.limits = { pips: [] }; game.turn.limits = { pips: [] };
@ -1989,8 +2083,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
error = `There are no valid locations for you to place a settlement.`; error = `There are no valid locations for you to place a settlement.`;
break; break;
} }
game.turn.actions = [ 'place-settlement' ]; placeSettlement(game, corners);
game.turn.limits = { corners };
addChatMessage(game, session, `${game.turn.name} is considering placing a settlement.`); addChatMessage(game, session, `${game.turn.name} is considering placing a settlement.`);
break; break;
@ -2024,24 +2117,33 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
if (game.state === 'normal') { if (game.state === 'normal') {
if (player.brick < 1 || player.wood < 1 || player.wheat < 1 || player.sheep < 1) { if (!game.turn.free) {
error = `You have insufficient resources to build a settlement.`; if (player.brick < 1 || player.wood < 1 || player.wheat < 1 || player.sheep < 1) {
break; error = `You have insufficient resources to build a settlement.`;
break;
}
} }
if (player.settlements < 1) { if (player.settlements < 1) {
error = `You have already built all of your settlements.`; error = `You have already built all of your settlements.`;
break; break;
} }
debugChat(game, 'Before settlement purchase'); debugChat(game, 'Before settlement purchase');
player.settlements--; player.settlements--;
player.brick--;
player.wood--; if (!game.turn.free) {
player.wheat--; player.brick--;
player.sheep--; player.wood--;
player.wheat--;
player.sheep--;
}
delete game.turn.free;
debugChat(game, 'After settlement purchase'); debugChat(game, 'After settlement purchase');
corner.color = session.color; corner.color = session.color;
corner.type = 'settlement'; corner.type = 'settlement';
let bankType = undefined;
if (layout.corners[index].banks.length) { if (layout.corners[index].banks.length) {
layout.corners[index].banks.forEach(bank => { layout.corners[index].banks.forEach(bank => {
const border = game.borderOrder[Math.floor(bank / 3)], const border = game.borderOrder[Math.floor(bank / 3)],
@ -2051,6 +2153,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
console.log(`Bank ${bank}`) console.log(`Bank ${bank}`)
return; return;
} }
bankType = (type === 'bank') ? '3:1' : type;
if (player.banks.indexOf(type) === -1) { if (player.banks.indexOf(type) === -1) {
player.banks.push(type); player.banks.push(type);
} }
@ -2058,7 +2161,11 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
game.turn.actions = []; game.turn.actions = [];
game.turn.limits = {}; game.turn.limits = {};
addChatMessage(game, session, `${name} placed a settlement.`); if (bankType) {
addChatMessage(game, session, `${name} placed a settlement by a maritime bank for ${bankType}.`);
} else {
addChatMessage(game, session, `${name} placed a settlement.`);
}
calculateRoadLengths(game, session); calculateRoadLengths(game, session);
} else if (game.state === 'initial-placement') { } else if (game.state === 'initial-placement') {
if (game.direction && game.direction === 'backward') { if (game.direction && game.direction === 'backward') {
@ -2083,8 +2190,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
player.settlements--; player.settlements--;
player.maritime = player.banks.map(bank => game.borders[Math.floor(bank / 3) + bank % 3]); player.maritime = player.banks.map(bank => game.borders[Math.floor(bank / 3) + bank % 3]);
game.turn.actions = ['place-road']; placeRoad(game, layout.corners[index].roads);
game.turn.limits = { roads: layout.corners[index].roads }; /* road placement is limited to be near this corner */
addChatMessage(game, session, `Placed a settlement. Next, they need to place a road.`); addChatMessage(game, session, `Placed a settlement. Next, they need to place a road.`);
} }
break; break;
@ -2121,8 +2227,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
error = `There are no valid locations for you to place a city.`; error = `There are no valid locations for you to place a city.`;
break; break;
} }
game.turn.actions = ['place-city']; placeCity(game, corners);
game.turn.limits = { corners };
addChatMessage(game, session, `${game.turn.name} is considering upgrading a settlement to a city.`); addChatMessage(game, session, `${game.turn.name} is considering upgrading a settlement to a city.`);
break; break;
@ -2154,22 +2259,29 @@ router.put("/:id/:action/:value?", async (req, res) => {
error = `This location already has a city!`; error = `This location already has a city!`;
break; break;
} }
if (player.wheat < 2 || player.stone < 3) { if (!game.turn.free) {
error = `You have insufficient resources to build a city.`; if (player.wheat < 2 || player.stone < 3) {
break; error = `You have insufficient resources to build a city.`;
break;
}
} }
if (player.city < 1) { if (player.city < 1) {
error = `You have already built all of your cities.`; error = `You have already built all of your cities.`;
break; break;
} }
corner.color = session.color; corner.color = session.color;
corner.type = 'city'; corner.type = 'city';
debugChat(game, 'Before city purchase'); debugChat(game, 'Before city purchase');
player.cities--; player.cities--;
player.settlements++; player.settlements++;
player.wheat -= 2; if (!game.turn.free) {
player.stone -= 3; player.wheat -= 2;
player.stone -= 3;
}
delete game.turn.free;
debugChat(game, 'After city purchase'); debugChat(game, 'After city purchase');
game.turn.actions = []; game.turn.actions = [];
game.turn.limits = {}; game.turn.limits = {};
@ -2208,8 +2320,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
error = `There are no valid locations for you to place a road.`; error = `There are no valid locations for you to place a road.`;
break; break;
} }
game.turn.actions = ['place-road']; placeRoad(game, roads);
game.turn.limits = { roads };
addChatMessage(game, session, `${game.turn.name} is considering building a road.`); addChatMessage(game, session, `${game.turn.name} is considering building a road.`);
break; break;
@ -2239,9 +2350,11 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
if (game.state === 'normal') { if (game.state === 'normal') {
if (player.brick < 1 || player.wood < 1) { if (!game.turn.free) {
error = `You have insufficient resources to build a road.`; if (player.brick < 1 || player.wood < 1) {
break; error = `You have insufficient resources to build a road.`;
break;
}
} }
if (player.roads < 1) { if (player.roads < 1) {
error = `You have already built all of your roads.`; error = `You have already built all of your roads.`;
@ -2251,8 +2364,11 @@ router.put("/:id/:action/:value?", async (req, res) => {
debugChat(game, 'Before road purchase'); debugChat(game, 'Before road purchase');
player.roads--; player.roads--;
player.brick--; if (!game.turn.free) {
player.wood--; player.brick--;
player.wood--;
}
delete game.turn.free;
debugChat(game, 'After road purchase'); debugChat(game, 'After road purchase');
road.color = session.color; road.color = session.color;
game.turn.actions = []; game.turn.actions = [];
@ -2281,11 +2397,10 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
if (next) { if (next) {
game.turn = { game.turn = {
actions: ['place-settlement'],
limits: { corners: getValidCorners(game) },
name: next, name: next,
color: getColorFromName(game, next) color: getColorFromName(game, next)
}; };
placeSettlement(game, getValidCorners(game));
calculateRoadLengths(game, session); calculateRoadLengths(game, session);
addChatMessage(game, null, `It is ${next}'s turn to place a settlement.`); addChatMessage(game, null, `It is ${next}'s turn to place a settlement.`);
} else { } else {
@ -2398,9 +2513,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
} }
resetGame(game); resetGame(game);
addChatMessage(game, null, `${name} requested to start the game.`);
message = `${name} requested to start the game.`; addChatMessage(game, null, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
addChatMessage(game, null, message);
game.state = state; game.state = state;
break; break;
} }
@ -2620,7 +2734,8 @@ const resetGame = (game) => {
wheat: 19, wheat: 19,
longestRoad: null, longestRoad: null,
largestArmy: null, largestArmy: null,
developmentCards: assetData.developmentCards.slice() developmentCards: assetData.developmentCards.slice(),
turn: {}
}); });
for (let key in game.players) { for (let key in game.players) {
@ -2666,8 +2781,6 @@ const resetGame = (game) => {
type: undefined type: undefined
}; };
} }
delete game.turn;
} }
const createGame = (id) => { const createGame = (id) => {