1
0

Settlement restriction on initial-placement for Volcano

Improved admin-command for roll

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-05-25 16:08:59 -07:00
parent 1c69cd23e9
commit 68e43fa3f7
2 changed files with 82 additions and 34 deletions

View File

@ -6,10 +6,17 @@ if [[ "${ADMIN}" == "" ]]; then
fi fi
id=$1 id=$1
color=$2 shift
color=$1
shift
dice1=$1
shift
if [[ "$1" != "" ]]; then
dice2=",$1"
fi
if [[ "${id}" == "" ]] || [[ "${color}" == "" ]]; then if [[ "${id}" == "" ]] || [[ "${color}" == "" ]] || [[ "$dice1" == "" ]]; then
echo "Usage: roll GAME-ID (red|white|blue|orange)-DICE" echo "Usage: roll GAME-ID (red|white|blue|orange) DICE [DICE]"
exit 1 exit 1
fi fi
@ -17,6 +24,6 @@ curl --noproxy '*' -s -L \
--request PUT \ --request PUT \
--header "PRIVATE-TOKEN: ${ADMIN}" \ --header "PRIVATE-TOKEN: ${ADMIN}" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
http://localhost:8930/ketr.ketran/api/v1/games/${id}/roll/${color} | http://localhost:8930/ketr.ketran/api/v1/games/${id}/roll/${color}?dice=${dice1}${dice2}
jq -r .status # | jq -r .status

View File

@ -117,6 +117,7 @@ const processTies = (players) => {
}); });
let ties = false, position = 1; let ties = false, position = 1;
const irstify = (position) => { const irstify = (position) => {
switch (position) { switch (position) {
case 1: return `1st`; case 1: return `1st`;
@ -126,7 +127,7 @@ const processTies = (players) => {
default: return position; default: return position;
} }
} }
console.log(`Slots: `, slots);
/* Reverse from high to low */ /* Reverse from high to low */
slots.reverse().forEach((slot) => { slots.reverse().forEach((slot) => {
if (slot.length !== 1) { if (slot.length !== 1) {
@ -217,22 +218,24 @@ const processGameOrder = (game, player, dice) => {
}); });
} }
const roll = (game, session) => { const roll = (game, session, dice) => {
const player = session.player, const player = session.player,
name = session.name ? session.name : "Unnamed"; name = session.name ? session.name : "Unnamed";
if (!dice) {
dice = [ Math.ceil(Math.random() * 6), Math.ceil(Math.random() * 6) ];
}
switch (game.state) { switch (game.state) {
case "lobby": /* currently not available as roll is only after color is case "lobby": /* currently not available as roll is only after color is
* set for players */ * set for players */
addChatMessage(game, session, `${name} rolled ${Math.ceil(Math.random() * 6)}.`); addChatMessage(game, session, `${name} rolled ${dice[0]}.`);
sendUpdateToPlayers(game, { chat: game.chat }); sendUpdateToPlayers(game, { chat: game.chat });
return; return;
case "game-order": case "game-order":
game.startTime = Date.now(); game.startTime = Date.now();
const dice = Math.ceil(Math.random() * 6); addChatMessage(game, session, `${name} rolled ${dice[0]}.`);
addChatMessage(game, session, `${name} rolled ${dice}.`); return processGameOrder(game, player, dice[0]);
return processGameOrder(game, player, dice);
case "normal": case "normal":
if (game.turn.color !== session.color) { if (game.turn.color !== session.color) {
@ -241,10 +244,21 @@ const roll = (game, session) => {
if (game.turn.roll) { if (game.turn.roll) {
return `You already rolled this turn.`; return `You already rolled this turn.`;
} }
processRoll(game, session, [ Math.ceil(Math.random() * 6), Math.ceil(Math.random() * 6) ]); processRoll(game, session, dice);
sendUpdateToPlayers(game, { chat: game.chat }); sendUpdateToPlayers(game, { chat: game.chat });
return; return;
case 'volcano-resource':
if (game.turn.color !== session.color) {
return `It is not your turn.`;
}
if (game.turn.volcano) {
return `You already rolled for the Volcano!`;
}
processVolcano(game, session, dice);
sendUpdateToPlayers(game, { chat: game.chat });
return;
default: default:
return `Invalid game state (${game.state}) in roll.`; return `Invalid game state (${game.state}) in roll.`;
} }
@ -621,7 +635,7 @@ const canGiveBuilding = (game) => {
} }
} }
const adminActions = (game, action, value) => { const adminActions = (game, action, value, query) => {
let color, player, parts, session, corners, error; let color, player, parts, session, corners, error;
switch (action) { switch (action) {
@ -745,32 +759,47 @@ const adminActions = (game, action, value) => {
return results; return results;
case "roll": case "roll":
parts = value.match(/^([1-6])(-([1-6]))?$/); let dice = (query.dice || '').split(',');
if (!parts) { dice = dice.map(die => parseInt(die));
if (!value) {
return `Unable to parse roll request.`; return `Unable to parse roll request.`;
} }
let dice = [ parseInt(parts[1]) ];
if (parts[3]) { switch (value) {
dice.push(parseInt(parts[3])); case 'orange': color = 'O'; break;
case 'red': color = 'R'; break;
case 'blue': color = 'B'; break;
case 'white': color = 'W'; break;
} }
for (let id in game.sessions) { if (!color) {
if (game.sessions[id].name === game.turn.name) { return `Unable to find player ${value}`
session = game.sessions[id]; }
const rollingPlayer = (color) => {
for (let id in game.sessions) {
if ((color
&& game.sessions[id].player
&& game.sessions[id].player.color === color)
|| (game.sessions[id].name === game.turn.name)) {
return game.sessions[id];
}
} }
return undefined;
};
addChatMessage(game, null,
`Admin rolling ${dice.join(', ')} for ${value}.`);
if (game.state === 'game-order') {
session = rollingPlayer(color);
} else {
session = rollingPlayer();
} }
if (!session) { if (!session) {
return `Unable to determine current player turn for admin roll.`; return `Unable to determine current player turn for admin roll.`;
} }
console.log(dice, parts); let warning = roll(game, session, dice);
addChatMessage(game, null, `Admin rolling ${dice.join(', ')} for ${game.turn.name}.`); if (warning) {
switch (game.state) { sendWarning(session, warning);
case 'game-order':
addActivity(game, session, `${game.turn.name} rolled ${dice[0]}.`);
processGameOrder(game, session.player, dice[0]);
break;
case 'normal':
processRoll(game, session, dice);
break;
} }
break; break;
@ -1401,9 +1430,14 @@ const getValidCorners = (game, color, type) => {
* *
* If we are limiting based on active player, a corner is only valid * If we are limiting based on active player, a corner is only valid
* if it connects to a road that is owned by that player. * if it connects to a road that is owned by that player.
*
* If no color is set, walk each road that leaves that corner and * If no color is set, walk each road that leaves that corner and
* check to see if there is a settlement placed at the end of that road * check to see if there is a settlement placed at the end of that road
*
* If so, this location cannot have a settlement. * If so, this location cannot have a settlement.
*
* If still valid, and we are in initial settlement placement, and if
* Volcano is enabled, verify the tile is not the Volcano.
*/ */
layout.corners.forEach((corner, cornerIndex) => { layout.corners.forEach((corner, cornerIndex) => {
const placement = game.placements.corners[cornerIndex]; const placement = game.placements.corners[cornerIndex];
@ -1431,7 +1465,8 @@ const getValidCorners = (game, color, type) => {
for (let r = 0; valid && r < corner.roads.length; r++) { for (let r = 0; valid && r < corner.roads.length; r++) {
const road = layout.roads[corner.roads[r]]; const road = layout.roads[corner.roads[r]];
for (let c = 0; valid && c < road.corners.length; c++) { for (let c = 0; valid && c < road.corners.length; c++) {
/* This side of the road is pointing to the corner being validated. Skip it. */ /* This side of the road is pointing to the corner being validated.
* Skip it. */
if (road.corners[c] === cornerIndex) { if (road.corners[c] === cornerIndex) {
continue; continue;
} }
@ -1443,7 +1478,11 @@ const getValidCorners = (game, color, type) => {
} }
} }
if (valid) { if (valid) {
limits.push(cornerIndex); if (game.state !== 'initial-placement'
|| (isRuleEnabled(game, 'volcano')
&& layout.tiles[game.robber].corners.indexOf(cornerIndex) === -1)) {
limits.push(cornerIndex);
}
} }
}); });
@ -1701,10 +1740,12 @@ router.put("/:id/:action/:value?", async (req, res) => {
if (req.headers['private-token'] !== req.app.get('admin')) { if (req.headers['private-token'] !== req.app.get('admin')) {
error = `Invalid admin credentials.`; error = `Invalid admin credentials.`;
} else { } else {
error = adminActions(game, action, value); error = adminActions(game, action, value, req.query);
} }
if (!error) { if (!error) {
sendGameToPlayers(game); sendGameToPlayers(game);
} else {
console.log(`admin-action error: ${error}`);
} }
} }