1
0

Use "resources" instead of "haveResources"

Updated client to use private instead of player

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-12 15:30:03 -08:00
parent 27f143c6a0
commit dac755cad0
6 changed files with 225 additions and 256 deletions

View File

@ -1,52 +1,42 @@
import React, { useState, useEffect, useContext, useRef, useMemo } from "react"; import React, { useState, useEffect, useContext, useRef, useMemo } from "react";
import "./Actions.css";
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import { PlayerName } from './PlayerName.js'; import equal from "fast-deep-equal";
import "./Actions.css";
import { PlayerName } from './PlayerName.js';
import { GlobalContext } from "./GlobalContext.js"; import { GlobalContext } from "./GlobalContext.js";
const Actions = () => { const Actions = () => {
const { ws, gameId, name } = useContext(GlobalContext); const { ws, gameId, name } = useContext(GlobalContext);
const [state, setState] = useState('lobby'); const [state, setState] = useState('lobby');
const [color, setColor] = useState(undefined); const [color, setColor] = useState(undefined);
const [player, setPlayer] = useState(undefined); const [priv, setPriv] = useState(undefined);
const [players, setPlayers] = useState(undefined);
const [turn, setTurn] = useState({}); const [turn, setTurn] = useState({});
const [active, setActive] = useState(0); const [active, setActive] = useState(0);
const [edit, setEdit] = useState(name); const [edit, setEdit] = useState(name);
const fields = useMemo(() => [ const fields = useMemo(() => [
'state', 'turn', 'player', 'active', 'color' 'state', 'turn', 'private', 'active', 'color'
], []); ], []);
const onWsMessage = (event) => { const onWsMessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
switch (data.type) { switch (data.type) {
case 'game-update': case 'game-update':
if ('private' in data.update && !equal(data.update.private, priv)) {
setPriv(data.update.private);
}
if ('state' in data.update && data.update.state !== state) { if ('state' in data.update && data.update.state !== state) {
setState(data.update.state); setState(data.update.state);
} }
if ('color' in data.update && data.update.color !== color) { if ('color' in data.update && data.update.color !== color) {
setColor(data.update.color); setColor(data.update.color);
if (players && color in players) {
setPlayer(players[color]);
} else if (player) {
setPlayer(undefined);
}
} }
if ('name' in data.update && data.update.name !== edit) { if ('name' in data.update && data.update.name !== edit) {
setEdit(data.update.name); setEdit(data.update.name);
} }
if ('players' in data.update) { if ('turn' in data.update && !equal(data.update.turn, turn)) {
setPlayers(data.update.players);
if (color in data.update.players) {
setPlayer(data.update.players[color]);
} else if (player) {
setPlayer(undefined);
}
}
if ('turn' in data.update) {
setTurn(data.update.turn); setTurn(data.update.turn);
} }
if ('active' in data.update && data.update.active !== active) { if ('active' in data.update && data.update.active !== active) {
@ -143,11 +133,11 @@ const Actions = () => {
const inLobby = state === 'lobby', const inLobby = state === 'lobby',
inGame = state === 'normal', inGame = state === 'normal',
inGameOrder = state === 'game-order', inGameOrder = state === 'game-order',
hasGameOrderRolled = (player && player.orderRoll) ? true : false, hasGameOrderRolled = (priv && priv.orderRoll) ? true : false,
hasRolled = (turn && turn.roll) ? true : false, hasRolled = (turn && turn.roll) ? true : false,
isTurn = (turn && turn.color === color) ? true : false, isTurn = (turn && turn.color === color) ? true : false,
robberActions = (turn && turn.robberInAction), robberActions = (turn && turn.robberInAction),
haveResources = player ? player.haveResources : false, haveResources = priv ? priv.resources !== 0 : false,
placement = (state === 'initial-placement' || (turn && turn.active === 'road-building')), placement = (state === 'initial-placement' || (turn && turn.active === 'road-building')),
placeRoad = placement && turn && turn.actions && turn.actions.indexOf('place-road') !== -1; placeRoad = placement && turn && turn.actions && turn.actions.indexOf('place-road') !== -1;
@ -169,7 +159,7 @@ const Actions = () => {
} onClick={rollClick}>Roll Dice</Button> } onClick={rollClick}>Roll Dice</Button>
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button> <Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button>
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button> <Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button>
{ turn && turn.roll === 7 && player && player.mustDiscard > 0 && { turn && turn.roll === 7 && priv && priv.mustDiscard > 0 &&
<Button onClick={discardClick}>Discard</Button> <Button onClick={discardClick}>Discard</Button>
} }
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled} onClick={passClick}>Done</Button> <Button disabled={placeRoad || robberActions || !isTurn || !hasRolled} onClick={passClick}>Done</Button>

View File

@ -46,7 +46,6 @@ const Activities = () => {
const [activities, setActivities] = useState([]); const [activities, setActivities] = useState([]);
const [turn, setTurn] = useState(); const [turn, setTurn] = useState();
const [color, setColor] = useState(); const [color, setColor] = useState();
const [player, setPlayer] = useState(undefined);
const [players, setPlayers] = useState({}); const [players, setPlayers] = useState({});
const [timestamp, setTimestamp] = useState(0); const [timestamp, setTimestamp] = useState(0);
const [state, setState] = useState(''); const [state, setState] = useState('');
@ -99,11 +98,6 @@ const Activities = () => {
if ('players' in data.update if ('players' in data.update
&& !equal(data.update.players, players)) { && !equal(data.update.players, players)) {
setPlayers(data.update.players); setPlayers(data.update.players);
if ((color in data.update.players)
&& !equal(player, data.update.players[color])) {
setPlayer(data.update.players[color]);
requestUpdate('turn');
}
} }
if ('timestamp' in data.update if ('timestamp' in data.update
&& data.update.timestamp !== timestamp) { && data.update.timestamp !== timestamp) {
@ -111,11 +105,6 @@ const Activities = () => {
} }
if ('color' in data.update && data.update.color !== color) { if ('color' in data.update && data.update.color !== color) {
setColor(data.update.color); setColor(data.update.color);
if (players && (data.update.color in players)
&& !equal(player, players[data.update.color])) {
setPlayer(player);
requestUpdate('turn');
}
} }
break; break;
default: default:

View File

@ -51,54 +51,6 @@ const Board = () => {
'placements', 'turn', 'state', 'color', 'longestRoadLength' 'placements', 'turn', 'state', 'color', 'longestRoadLength'
], []); ], []);
/* Placements is a structure of roads and corners arrays
* indicating what is stored at each of the locations
*
* Corners consist of a type and color
* Roads consist of a color, and longestRoad
*
* See games.js resetGame, placeRoad, placeSettlement, placeCity,
* and calculateRoadLengths
*
* Returns: true === differences, false === same
*/
const comparePlacements = (A, B) => {
if (!A && !B) {
return false; /* same */
}
if ((A && !B)
|| (!A && B)) {
return true;
}
if ((A.roads.length !== B.roads.length)
|| (A.corners.length !== B.corners.length)) {
return true;
}
/* Roads compare color and longestRoad */
for (let i = 0; i < A.roads.length; i++) {
if (A.roads[i].color !== B.roads[i].color) {
return true;
}
if (A.roads[i].longestRoad !== B.roads[i].longestRoad) {
return true;
}
}
/* Corners compare type and color */
for (let i = 0; i < A.corners.length; i++) {
if (A.corners[i].type !== B.corners[i].type) {
return true;
}
if (A.corners[i].color !== B.corners[i].color) {
return true;
}
}
return false; /* same */
};
const onWsMessage = (event) => { const onWsMessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
switch (data.type) { switch (data.type) {
@ -132,7 +84,7 @@ const Board = () => {
} }
} }
if ('placement' in data.update) { if ('placements' in data.update) {
if (!equal(data.update.placements, placements)) { if (!equal(data.update.placements, placements)) {
console.log(`board - placements`, data.update.placements); console.log(`board - placements`, data.update.placements);
setPlacements(data.update.placements); setPlacements(data.update.placements);

View File

@ -1,7 +1,8 @@
import React, { useState, useEffect, useContext, useRef, useMemo } from "react"; import React, { useState, useEffect, useContext, useRef, useMemo } from "react";
import "./Actions.css";
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import equal from "fast-deep-equal";
import { Dice } from "./Dice.js"; import { Dice } from "./Dice.js";
import { PlayerColor } from "./PlayerColor.js"; import { PlayerColor } from "./PlayerColor.js";
@ -11,25 +12,23 @@ import { GlobalContext } from "./GlobalContext.js";
const GameOrder = () => { const GameOrder = () => {
const { ws } = useContext(GlobalContext); const { ws } = useContext(GlobalContext);
const [player, setPlayer] = useState(undefined);
const [players, setPlayers] = useState({}); const [players, setPlayers] = useState({});
const [color, setColor] = useState(undefined);
const fields = useMemo(() => [ const fields = useMemo(() => [
'player', 'players' 'players', 'color'
], []); ], []);
const color = player ? player.color : undefined;
const onWsMessage = (event) => { const onWsMessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
switch (data.type) { switch (data.type) {
case 'game-update': case 'game-update':
console.log(`GameOrder game-update: `, data.update); console.log(`GameOrder game-update: `, data.update);
if ('player' in data.update) { if ('players' in data.update && !equal(players, data.update.players)) {
setPlayer(data.update.player);
}
if ('players' in data.update) {
setPlayers(data.update.players); setPlayers(data.update.players);
} }
if ('color' in data.update && data.update.color !== color) {
setColor(data.update.color);
}
break; break;
default: default:
break; break;

View File

@ -458,11 +458,11 @@ const Trade = ({table}) => {
<div className="PlayerList"> <div className="PlayerList">
{ players } { players }
</div> </div>
{ !player.haveResources && <b>You have no resources to participate in this trade.</b> } { player.resources === 0 && <b>You have no resources to participate in this trade.</b> }
<Button disabled={isOfferSubmitted || !isOfferValid} <Button disabled={isOfferSubmitted || !isOfferValid}
onClick={offerClicked}>Offer</Button> onClick={offerClicked}>Offer</Button>
{ player.haveResources && { player.resources !== 0 &&
<div className="Transfers"> <div className="Transfers">
<div className="GiveGet"><div>Get</div><div>Give</div><div>Have</div></div> <div className="GiveGet"><div>Get</div><div>Give</div><div>Have</div></div>
{ transfers } { transfers }

View File

@ -202,7 +202,7 @@ const processGameOrder = (game, player, dice) => {
name: players[0].name, name: players[0].name,
color: players[0].color color: players[0].color
}; };
placeSettlement(game, getValidCorners(game)); getValidSettlementPlacements(game, getValidCorners(game));
addActivity(game, null, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`); addActivity(game, null, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
addChatMessage(game, null, `Initial settlement placement has started!`); addChatMessage(game, null, `Initial settlement placement has started!`);
addChatMessage(game, null, `It is ${game.turn.name}'s turn to place a settlement.`);4 addChatMessage(game, null, `It is ${game.turn.name}'s turn to place a settlement.`);4
@ -318,6 +318,7 @@ const distributeResources = (game, roll) => {
if (color !== 'robber') { if (color !== 'robber') {
session = sessionFromColor(game, color); session = sessionFromColor(game, color);
session.player[type] += entry[type]; session.player[type] += entry[type];
session.player.resources += entry[type];
message.push(`${entry[type]} ${type}`); message.push(`${entry[type]} ${type}`);
} else { } else {
robberSteal(game, color, type); robberSteal(game, color, type);
@ -414,6 +415,7 @@ const newPlayer = (color) => {
points: 0, points: 0,
status: "Not active", status: "Not active",
lastActive: 0, lastActive: 0,
resources: 0,
order: 0, order: 0,
stone: 0, stone: 0,
wheat: 0, wheat: 0,
@ -654,7 +656,7 @@ const adminActions = (game, action, value) => {
return `There are no valid locations for ${game.turn.name} to place a settlement.`; return `There are no valid locations for ${game.turn.name} to place a settlement.`;
} }
game.turn.free = true; game.turn.free = true;
placeSettlement(game, corners); getValidSettlementPlacements(game, corners);
addChatMessage(game, null, `Admin gave a settlment to ${game.turn.name}. ` + addChatMessage(game, null, `Admin gave a settlment to ${game.turn.name}. ` +
`They must now place the settlement.`); `They must now place the settlement.`);
break; break;
@ -665,6 +667,7 @@ const adminActions = (game, action, value) => {
case 'brick': case 'brick':
const count = parseInt(card); const count = parseInt(card);
session.player[type] += count; session.player[type] += count;
session.resources += count;
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`); addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`);
break; break;
default: default:
@ -1627,7 +1630,7 @@ const placeCity = (game, limits) => {
game.turn.limits = { corners: limits }; game.turn.limits = { corners: limits };
} }
const placeSettlement = (game, limits) => { const getValidSettlementPlacements = (game, limits) => {
game.turn.actions = [ 'place-settlement' ]; game.turn.actions = [ 'place-settlement' ];
game.turn.limits = { corners: limits }; game.turn.limits = { corners: limits };
} }
@ -1799,14 +1802,18 @@ const trade = (game, session, { offer, value }) => {
offer.gets.forEach(item => { offer.gets.forEach(item => {
if (target.name !== 'The bank') { if (target.name !== 'The bank') {
target[item.type] -= item.count; target[item.type] -= item.count;
target.resources -= item.count;
} }
player[item.type] += item.count; player[item.type] += item.count;
player.resources += item.count;
}); });
offer.gives.forEach(item => { offer.gives.forEach(item => {
if (target.name !== 'The bank') { if (target.name !== 'The bank') {
target[item.type] += item.count; target[item.type] += item.count;
target.resources += item.count;
} }
player[item.type] -= item.count; player[item.type] -= item.count;
player.resources -= item.count;
}); });
const from = (offer.name === 'The bank') ? 'the bank' : offer.name; const from = (offer.name === 'The bank') ? 'the bank' : offer.name;
@ -1943,7 +1950,9 @@ const stealResource = (game, session, value) => {
let index = Math.floor(Math.random() * cards.length), let index = Math.floor(Math.random() * cards.length),
type = cards[index]; type = cards[index];
victim[type]--; victim[type]--;
session.player[type]++ victim.resources--;
session.player[type]++;
session.player.resources++;
game.turn.actions = []; game.turn.actions = [];
game.turn.limits = {}; game.turn.limits = {};
addChatMessage(game, session, addChatMessage(game, session,
@ -1988,6 +1997,10 @@ const buyDevelopment = (game, session, value) => {
player.stone--; player.stone--;
player.wheat--; player.wheat--;
player.sheep--; player.sheep--;
player.resources = 0;
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(resource => {
player.resources += player[resource];
});
debugChat(game, 'After development purchase'); debugChat(game, 'After development purchase');
card = game.developmentCards.pop(); card = game.developmentCards.pop();
card.turn = game.turns; card.turn = game.turns;
@ -2104,6 +2117,131 @@ const playCard = (game, session, { card }) => {
} }
} }
const placeSettlement = (game, session, value) => {
const player = session.player;
if (game.state !== 'initial-placement' && game.state !== 'normal') {
return `You cannot place an item unless the game is active.`;
}
if (session.color !== game.turn.color) {
return `It is not your turn! It is ${game.turn.name}'s turn.`;
}
index = parseInt(value);
if (game.placements.corners[index] === undefined) {
return `You have requested to place a settlement illegally!`;
}
/* If this is not a valid road in the turn limits, discard it */
if (game.turn && game.turn.limits && game.turn.limits.corners && game.turn.limits.corners.indexOf(index) === -1) {
return `You tried to cheat! You should not try to break the rules.`;
}
corner = game.placements.corners[index];
if (corner.color) {
return `This location already has a settlement belonging to ${game.players[corner.color].name}!`;
}
if (!player.banks) {
player.banks = [];
}
if (game.state === 'normal') {
if (!game.turn.free) {
if (player.brick < 1 || player.wood < 1 || player.wheat < 1 || player.sheep < 1) {
return `You have insufficient resources to build a settlement.`;
}
}
if (player.settlements < 1) {
return `You have already built all of your settlements.`;
}
player.settlements--;
if (!game.turn.free) {
addChatMessage(game, session, `${session.name} spent 1 brick, 1 wood, 1 sheep, 1 wheat to purchase a settlement.`)
player.brick--;
player.wood--;
player.wheat--;
player.sheep--;
player.resources = 0;
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(resource => {
player.resources += player[resource];
});
}
delete game.turn.free;
corner.color = session.color;
corner.type = 'settlement';
let bankType = undefined;
if (layout.corners[index].banks.length) {
layout.corners[index].banks.forEach(bank => {
const border = game.borderOrder[Math.floor(bank / 3)],
type = game.borders[border][bank % 3];
console.log(`${session.id}: Bank ${bank} = ${type}`);
if (!type) {
console.log(`${session.id}: Bank ${bank}`)
return;
}
bankType = (type === 'bank')
? '3 of anything for 1 resource'
: `2 ${type} for 1 resource`;
if (player.banks.indexOf(type) === -1) {
player.banks.push(type);
}
});
}
game.turn.actions = [];
game.turn.limits = {};
if (bankType) {
addActivity(game, session,
`${session.name} placed a settlement by a maritime bank that trades ${bankType}.`);
} else {
addActivity(game, session, `${session.name} placed a settlement.`);
}
calculateRoadLengths(game, session);
} else if (game.state === 'initial-placement') {
if (game.direction && game.direction === 'backward') {
session.initialSettlement = index;
}
corner.color = session.color;
corner.type = 'settlement';
let bankType = undefined;
if (layout.corners[index].banks.length) {
layout.corners[index].banks.forEach(bank => {
const border = game.borderOrder[Math.floor(bank / 3)],
type = game.borders[border][bank % 3];
console.log(`${session.id}: Bank ${bank} = ${type}`);
if (!type) {
return;
}
bankType = (type === 'bank')
? '3 of anything for 1 resource'
: `2 ${type} for 1 resource`;
if (player.banks.indexOf(type) === -1) {
player.banks.push(type);
}
});
}
player.settlements--;
if (bankType) {
addActivity(game, session,
`${session.name} placed a settlement by a maritime bank that trades ${bankType}. ` +
`Next, they need to place a road.`);
} else {
addActivity(game, session, `${name} placed a settlement. ` +
`Next, they need to place a road.`);
}
placeRoad(game, layout.corners[index].roads);
}
sendUpdateToPlayers(game, {
placements: game.placements,
turn: game.turn,
});
sendUpdateToPlayer(session, {
private: game.player
});
}
const asdf = () => { const asdf = () => {
const game = 0, session = 0; const game = 0, session = 0;
switch (game) { switch (game) {
@ -2179,6 +2317,7 @@ const asdf = () => {
if (player[type]) { if (player[type]) {
gave.push(`${player.name} gave ${player[type]} ${type}`); gave.push(`${player.name} gave ${player[type]} ${type}`);
session.player[type] += player[type]; session.player[type] += player[type];
session.resources += player[type];
total += player[type]; total += player[type];
player[type] = 0; player[type] = 0;
} }
@ -2195,6 +2334,7 @@ const asdf = () => {
case 'year-of-plenty': case 'year-of-plenty':
cards.forEach(type => { cards.forEach(type => {
session.player[type]++; session.player[type]++;
session.player.resources++;
}); });
addChatMessage(game, session, `${session.name} player Year of Plenty.` + addChatMessage(game, session, `${session.name} player Year of Plenty.` +
`They chose to receive ${display.join(', ')} from the bank.`); `They chose to receive ${display.join(', ')} from the bank.`);
@ -2236,132 +2376,10 @@ const asdf = () => {
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;
} }
placeSettlement(game, corners); getValidSettlementPlacements(game, corners);
addActivity(game, session, `${game.turn.name} is considering placing a settlement.`); addActivity(game, session, `${game.turn.name} is considering placing a settlement.`);
break; break;
case 'place-settlement':
if (game.state !== 'initial-placement' && game.state !== 'normal') {
error = `You cannot place an item unless the game is active.`;
break;
}
if (session.color !== game.turn.color) {
error = `It is not your turn! It is ${game.turn.name}'s turn.`;
break;
}
index = parseInt(value);
if (game.placements.corners[index] === undefined) {
error = `You have requested to place a settlement illegally!`;
break;
}
/* If this is not a valid road in the turn limits, discard it */
if (game.turn && game.turn.limits && game.turn.limits.corners && game.turn.limits.corners.indexOf(index) === -1) {
error = `You tried to cheat! You should not try to break the rules.`;
break;
}
corner = game.placements.corners[index];
if (corner.color) {
error = `This location already has a settlement belonging to ${game.players[corner.color].name}!`;
break;
}
if (!player.banks) {
player.banks = [];
}
if (game.state === 'normal') {
if (!game.turn.free) {
if (player.brick < 1 || player.wood < 1 || player.wheat < 1 || player.sheep < 1) {
error = `You have insufficient resources to build a settlement.`;
break;
}
}
if (player.settlements < 1) {
error = `You have already built all of your settlements.`;
break;
}
debugChat(game, 'Before settlement purchase');
player.settlements--;
if (!game.turn.free) {
addChatMessage(game, session, `${session.name} spent 1 brick, 1 wood, 1 sheep, 1 wheat to purchase a settlement.`)
player.brick--;
player.wood--;
player.wheat--;
player.sheep--;
}
delete game.turn.free;
debugChat(game, 'After settlement purchase');
corner.color = session.color;
corner.type = 'settlement';
let bankType = undefined;
if (layout.corners[index].banks.length) {
layout.corners[index].banks.forEach(bank => {
const border = game.borderOrder[Math.floor(bank / 3)],
type = game.borders[border][bank % 3];
console.log(`Bank ${bank} = ${type}`);
if (!type) {
console.log(`Bank ${bank}`)
return;
}
bankType = (type === 'bank')
? '3 of anything for 1 resource'
: `2 ${type} for 1 resource`;
if (player.banks.indexOf(type) === -1) {
player.banks.push(type);
}
});
}
game.turn.actions = [];
game.turn.limits = {};
if (bankType) {
addActivity(game, session,
`${name} placed a settlement by a maritime bank that trades ${bankType}.`);
} else {
addActivity(game, session, `${name} placed a settlement.`);
}
calculateRoadLengths(game, session);
} else if (game.state === 'initial-placement') {
if (game.direction && game.direction === 'backward') {
session.initialSettlement = index;
}
corner.color = session.color;
corner.type = 'settlement';
let bankType = undefined;
if (layout.corners[index].banks.length) {
layout.corners[index].banks.forEach(bank => {
console.log(game.borderOrder);
console.log(game.borders);
const border = game.borderOrder[Math.floor(bank / 3)],
type = game.borders[border][bank % 3];
console.log(`Bank ${bank} = ${type}`);
if (!type) {
return;
}
bankType = (type === 'bank')
? '3 of anything for 1 resource'
: `2 ${type} for 1 resource`;
if (player.banks.indexOf(type) === -1) {
player.banks.push(type);
}
});
}
player.settlements--;
if (bankType) {
addActivity(game, session,
`${name} placed a settlement by a maritime bank that trades ${bankType}. ` +
`Next, they need to place a road.`);
} else {
addActivity(game, session, `${name} placed a settlement. ` +
`Next, they need to place a road.`);
}
placeRoad(game, layout.corners[index].roads);
}
break;
case 'buy-city': case 'buy-city':
if (game.state !== 'normal') { if (game.state !== 'normal') {
error = `You cannot purchase a city unless the game is active.`; error = `You cannot purchase a city unless the game is active.`;
@ -2447,6 +2465,10 @@ const asdf = () => {
addChatMessage(game, session, `${session.name} spent 2 wheat, 3 stone to upgrade to a city.`) addChatMessage(game, session, `${session.name} spent 2 wheat, 3 stone to upgrade to a city.`)
player.wheat -= 2; player.wheat -= 2;
player.stone -= 3; player.stone -= 3;
player.resources = 0;
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(resource => {
player.resources += player[resource];
});
} }
delete game.turn.free; delete game.turn.free;
@ -2536,6 +2558,10 @@ const asdf = () => {
addChatMessage(game, session, `${name} spent 1 brick, 1 wood to purchase a road.`) addChatMessage(game, session, `${name} spent 1 brick, 1 wood to purchase a road.`)
player.brick--; player.brick--;
player.wood--; player.wood--;
player.resources = 0;
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(resource => {
player.resources += player[resource];
});
} }
debugChat(game, 'After road purchase'); debugChat(game, 'After road purchase');
@ -2590,7 +2616,7 @@ const asdf = () => {
name: next, name: next,
color: getColorFromName(game, next) color: getColorFromName(game, next)
}; };
placeSettlement(game, getValidCorners(game)); getValidSettlementPlacements(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 {
@ -2623,6 +2649,7 @@ const asdf = () => {
let message = []; let message = [];
for (let type in receives) { for (let type in receives) {
player[type] += receives[type]; player[type] += receives[type];
player.resources += receives[type];
message.push(`${receives[type]} ${type}`); message.push(`${receives[type]} ${type}`);
} }
addChatMessage(game, session, `${session.name} receives ${message.join(', ')}.`); addChatMessage(game, session, `${session.name} receives ${message.join(', ')}.`);
@ -2653,8 +2680,10 @@ const asdf = () => {
break; break;
} }
for (let type in discards) { for (let type in discards) {
player[type] -= parseInt(discards[type]); const count = parseInt(discards[type]);
player.mustDiscard -= parseInt(discards[type]) player[type] -= count;
player.mustDiscard -= count;
player.resources -= count;
} }
addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`); addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`);
if (player.mustDiscard) { if (player.mustDiscard) {
@ -3002,6 +3031,24 @@ router.ws("/ws/:id", (ws, req) => {
}); });
}); });
const getFilteredPlayers = (game) => {
const filtered = {};
for (let color in game.players) {
const player = Object.assign({}, game.players[color]);
filtered[color] = player;
if (player.status === 'Not active') {
continue;
}
player.resources = 0;
[ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(resource => {
player.resources += player[resource];
delete player[resource];
});
delete player.development;
}
return filtered;
};
const wsConnect = async (ws, req) => { const wsConnect = async (ws, req) => {
const { id } = req.params; const { id } = req.params;
const gameId = id; const gameId = id;
@ -3179,6 +3226,10 @@ const wsConnect = async (ws, req) => {
update = {}; update = {};
data.fields.forEach((field) => { data.fields.forEach((field) => {
switch (field) { switch (field) {
case 'player':
sendWarning(session, `'player' is not a valid item. use 'private' instead`);
update.player = undefined;
break;
case 'id': case 'id':
case 'chat': case 'chat':
case 'startTime': case 'startTime':
@ -3191,8 +3242,11 @@ const wsConnect = async (ws, req) => {
case 'unselected': case 'unselected':
update.unselected = getFilteredUnselected(game); update.unselected = getFilteredUnselected(game);
break; break;
case 'private':
update.private = session.player;
break;
case 'players': case 'players':
update.players = game.players; update.players = getFilteredPlayers(game);
break; break;
case 'color': case 'color':
console.log(`${session.id}: -> Returning color as ${session.color} for ${getName(session)}`); console.log(`${session.id}: -> Returning color as ${session.color} for ${getName(session)}`);
@ -3343,14 +3397,6 @@ const debugChat = (game, preamble) => {
const sendGameToSession = (session, reducedSessions, game, reducedGame, error, res) => { const sendGameToSession = (session, reducedSessions, game, reducedGame, error, res) => {
const player = session.player ? session.player : undefined; const player = session.player ? session.player : undefined;
if (player) {
player.haveResources = player.wheat > 0 ||
player.brick > 0 ||
player.sheep > 0 ||
player.stone > 0 ||
player.wood > 0;
}
/* Strip out data that should not be shared with players */ /* Strip out data that should not be shared with players */
delete reducedGame.developmentCards; delete reducedGame.developmentCards;
@ -3577,14 +3623,6 @@ const getFilteredGameForPlayer = (game, session) => {
const player = session.player ? session.player : undefined; const player = session.player ? session.player : undefined;
if (player) {
player.haveResources = player.wheat > 0 ||
player.brick > 0 ||
player.sheep > 0 ||
player.stone > 0 ||
player.wood > 0;
}
/* Strip out data that should not be shared with players */ /* Strip out data that should not be shared with players */
delete reducedGame.developmentCards; delete reducedGame.developmentCards;
@ -3653,11 +3691,6 @@ const resetGame = (game) => {
longestRoad: undefined longestRoad: undefined
}); });
/* Reset all player data */
for (let color in game.players) {
clearPlayer(game.players[color]);
}
/* Populate the game corner and road placement data as cleared */ /* Populate the game corner and road placement data as cleared */
for (let i = 0; i < layout.corners.length; i++) { for (let i = 0; i < layout.corners.length; i++) {
game.placements.corners[i] = { game.placements.corners[i] = {
@ -3673,6 +3706,14 @@ const resetGame = (game) => {
}; };
} }
/* Put the robber back on the Desert */
for (let i = 0; i < game.pipOrder.length; i++) {
if (game.pipOrder[i] === 18) {
game.robber = i;
break;
}
}
/* Populate the game development cards with a fresh deck */ /* Populate the game development cards with a fresh deck */
for (let i = 1; i <= 14; i++) { for (let i = 1; i <= 14; i++) {
game.developmentCards.push({ game.developmentCards.push({
@ -3695,6 +3736,11 @@ const resetGame = (game) => {
shuffleArray(game.developmentCards); shuffleArray(game.developmentCards);
/* Reset all player data */
for (let color in game.players) {
clearPlayer(game.players[color]);
}
/* Ensure sessions are connected to player objects */ /* Ensure sessions are connected to player objects */
for (let key in game.sessions) { for (let key in game.sessions) {
const session = game.sessions[key]; const session = game.sessions[key];
@ -3702,14 +3748,7 @@ const resetGame = (game) => {
session.player = game.players[session.color]; session.player = game.players[session.color];
session.player.status = 'Active'; session.player.status = 'Active';
session.player.lastActive = Date.now(); session.player.lastActive = Date.now();
} session.player.live = session.live;
}
/* Put the robber back on the Desert */
for (let i = 0; i < game.pipOrder.length; i++) {
if (game.pipOrder[i] === 18) {
game.robber = i;
break;
} }
} }
} }