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:
parent
27f143c6a0
commit
dac755cad0
@ -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,14 +133,14 @@ 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;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="Actions">
|
<Paper className="Actions">
|
||||||
{ edit === "" && <PlayerName name={name} setName={setName}/> }
|
{ edit === "" && <PlayerName name={name} setName={setName}/> }
|
||||||
@ -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>
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 }
|
||||||
|
@ -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;
|
||||||
@ -1933,7 +1940,7 @@ const stealResource = (game, session, value) => {
|
|||||||
|
|
||||||
debugChat(game, 'Before steal');
|
debugChat(game, 'Before steal');
|
||||||
|
|
||||||
if (cards.length === 0) {
|
if (cards.length === 0) {
|
||||||
addChatMessage(game, session,
|
addChatMessage(game, session,
|
||||||
`${victim.name} ` +
|
`${victim.name} ` +
|
||||||
`did not have any cards for ${session.name} to steal.`);
|
`did not have any cards for ${session.name} to steal.`);
|
||||||
@ -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;
|
||||||
|
|
||||||
@ -2535,7 +2557,11 @@ const asdf = () => {
|
|||||||
if (!game.turn.free) {
|
if (!game.turn.free) {
|
||||||
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({
|
||||||
@ -3694,6 +3735,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) {
|
||||||
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user