From 42d076f21650964758c7a76194762ce8ce56d014 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 14 Mar 2022 00:07:50 -0700 Subject: [PATCH] Game seems to be working Signed-off-by: James Ketrenos --- client/src/Activities.js | 2 +- client/src/App.css | 11 +- client/src/App.js | 4 +- client/src/Trade.js | 2 +- client/src/ViewCard.js | 8 +- client/src/Winner.js | 154 +++++++++++++------ server/routes/games.js | 319 +++++++++++++++++++++++++-------------- 7 files changed, 331 insertions(+), 169 deletions(-) diff --git a/client/src/Activities.js b/client/src/Activities.js index 4a7a438..42f4518 100644 --- a/client/src/Activities.js +++ b/client/src/Activities.js @@ -141,7 +141,7 @@ const Activities = () => { placeRoad = placement && turn && turn.actions && turn.actions.indexOf('place-road') !== -1, mustStealResource = turn && turn.actions && turn.actions.indexOf('steal-resource') !== -1, rollForOrder = (state === 'game-order'); -console.log(`activities - `, state, turn); +console.log(`activities - `, state, turn, activities); let discarders = [], mustDiscard = false; for (let key in players) { const player = players[key]; diff --git a/client/src/App.css b/client/src/App.css index a3a24f4..6b09670 100755 --- a/client/src/App.css +++ b/client/src/App.css @@ -129,7 +129,16 @@ body { .Table .ViewCard { display: flex; - position: relative; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.Table .Winner { + display: flex; + position: absolute; top: 0; left: 0; right: 0; diff --git a/client/src/App.js b/client/src/App.js index eb6533c..42886f3 100755 --- a/client/src/App.js +++ b/client/src/App.js @@ -25,6 +25,7 @@ import { ViewCard } from "./ViewCard.js"; import { ChooseCard } from "./ChooseCard.js"; import { Hand } from "./Hand.js"; import { Trade } from "./Trade.js"; +import { Winner } from "./Winner.js"; import history from "./history.js"; import "./App.css"; @@ -305,8 +306,7 @@ const Table = () => { } { state === 'normal' && } { color && state === 'game-order' && } - - { /* state === 'winner' && */ } + diff --git a/client/src/Trade.js b/client/src/Trade.js index afaee90..7dbe3fe 100644 --- a/client/src/Trade.js +++ b/client/src/Trade.js @@ -384,7 +384,7 @@ const Trade = () => { } else { const found = activeTrades.find(item => item.name === turn.name); if (found) { - found.valid = !(color in found.offerRejected) && isCompatibleOffer(priv, found); + found.valid = !(color in found.offerRejected) && canMeetOffer(priv, found); } } diff --git a/client/src/ViewCard.js b/client/src/ViewCard.js index a40b714..a867ef0 100644 --- a/client/src/ViewCard.js +++ b/client/src/ViewCard.js @@ -84,8 +84,10 @@ const ViewCard = ({cardActive, setCardActive}) => { lookup = cardActive.type; } + let cardName = ''; switch (lookup) { case 'army': + cardName = 'Knight'; description = <>
When played, you must move the robber.
Steal 1 resource card from the owner of an adjacent settlement or city.
@@ -93,6 +95,7 @@ const ViewCard = ({cardActive, setCardActive}) => { knight or one progress card.; break; case 'vp': + cardName = `Victory Point: ${capitalize(cardActive.card)}`; description = <>
1 victory point.
You only reveal your victory point cards when the game is over, either when you or an opponent @@ -101,6 +104,7 @@ const ViewCard = ({cardActive, setCardActive}) => { break; case 'progress-road-1': case 'progress-road-2': + cardName = 'Road Building' description = <>
Play 2 new roads as if you had just built them.
This is still limited by the number of roads you have. If you do not have enough roads @@ -110,12 +114,14 @@ const ViewCard = ({cardActive, setCardActive}) => { ; break; case 'progress-monopoly': + cardName = 'Monopoly'; description = <>
When you play this card, you will select 1 type of resource. All other players must give you all their resource cards of that type.
; break; case 'progress-year-of-plenty': + cardName = 'Year of Plenty'; description = <>
Take any 2 resources from the bank. Add them to your hand. They can be 2 of the same resource or 1 of two differ resources.
@@ -159,7 +165,7 @@ const ViewCard = ({cardActive, setCardActive}) => { return (
-
{capitalize(cardActive.type)}
+
{cardName}
{description}
diff --git a/client/src/Winner.js b/client/src/Winner.js index dbbe44d..3976dd3 100644 --- a/client/src/Winner.js +++ b/client/src/Winner.js @@ -1,54 +1,95 @@ -import React from "react"; -import "./Winner.css"; +import React, { useState, useEffect, useContext, useRef, useMemo, useCallback } from "react"; +import equal from "fast-deep-equal"; + import Paper from '@material-ui/core/Paper'; import Button from '@material-ui/core/Button'; -import Resource from './Resource.js'; -import { getPlayerName } from './Common.js'; -import PlayerColor from './PlayerColor.js'; -const Winner = ({table, color}) => { - const quitClicked = (event) => { - table.setSelected(""); - } +import "./Winner.css"; - if (!table.game) { +import {Resource} from './Resource.js'; +import {PlayerColor} from './PlayerColor.js'; +import { GlobalContext } from "./GlobalContext.js"; + +const Winner = () => { + const { ws } = useContext(GlobalContext); + const [winner, setWinner] = useState(undefined); + const [state, setState] = useState(undefined); + const fields = useMemo(() => [ + 'winner', 'state' + ], []); + const onWsMessage = (event) => { + const data = JSON.parse(event.data); + switch (data.type) { + case 'game-update': + console.log(`winner - game update`, data.update); + if ('winner' in data.update && !equal(data.update.winner, winner)) { + setWinner(data.update.winner); + } + if ('state' in data.update && data.update.state !== state) { + if (data.update.state !== 'winner') { + setWinner(undefined); + } + setState(data.update.state); + } + break; + default: + break; + } + }; + const refWsMessage = useRef(onWsMessage); + useEffect(() => { refWsMessage.current = onWsMessage; }); + useEffect(() => { + if (!ws) { return; } + const cbMessage = e => refWsMessage.current(e); + ws.addEventListener('message', cbMessage); + return () => { + ws.removeEventListener('message', cbMessage); + } + }, [ws, refWsMessage]); + useEffect(() => { + if (!ws) { return; } + ws.send(JSON.stringify({ + type: 'get', + fields + })); + }, [ws, fields]); + + const quitClicked = useCallback((event) => { + ws.send(JSON.stringify({ + type: 'goto-lobby' + })); + }, [ws]); + + if (!winner) { return <>; } - const game = table.game; - - const name = getPlayerName(game.sessions, color), - player = game.players[color]; - let playerCount = 0; - for (let key in game.players) { - if (game.players[key].status !== 'Not active') { - playerCount++; - } - } - - let description = <> -
Congratulations, {name}!
-
{name} won the game with {player.points} after {Math.floor(game.turns / playerCount)} turns. - { Number(player.potential) !== 0 && <>They had {player.potential} unplayed Victory Point card(s).}
- ; - - for (let key in game.players) { - if (key === color) { + let losers = []; + for (let key in winner.players) { + if (key === winner.color || winner.players[key].status === 'Not active') { continue; } - let tmp = game.players[key]; - if (tmp.status === 'Not active') { - continue; - } - let line = <> {getPlayerName(game.sessions, key)} finished with {tmp.points} victory points. - { Number(tmp.potential) !== 0 && <>They had {tmp.potential} unplayed Victory Point card(s). }; - description = <>{description}
{line}
; + losers.push(winner.players[key]); } - if (game.robberStole) { + const turnCount = Math.floor(winner.turns / (losers.length + 1)); + + losers = losers.map(player => { + const averageSeconds = Math.floor(player.totalTime / turnCount / 1000), + average = `${Math.floor(averageSeconds / 60)}m:${averageSeconds % 60}s`; + return
+ {player.name} finished with {player.points} victory points. + { Number(player.potential) !== 0 && <>They had {player.potential} unplayed Victory Point card(s). } + Their average turn time was {average}. +
; + }); + + let robber = <>; + + if (winner.robberStole) { let stolen = <>; - for (let type in game.stolen) { - const resource = game.stolen[type]; + for (let type in winner.stolen) { + const resource = winner.stolen[type]; if (typeof resource === 'object') { /* player colors are also in 'game.stolen' */ continue; } @@ -56,22 +97,41 @@ const Winner = ({table, color}) => { ; } - description = <>{description}
- Throughout the game, the robber stole {game.robberStole} resources: + robber =
+ Throughout the game, the robber stole {winner.robberStole} resources:
{stolen}
-
; +
; } - description = <>{description}
If everyone goes back to the Lobby, you can play again.
; + const averageSeconds = Math.floor(winner.totalTime / turnCount / 1000), + average = `${Math.floor(averageSeconds / 60)}m:${averageSeconds % 60}s`; + + const seconds = winner.elapsedTime / 1000, + h = Math.floor(seconds / (60 * 60)), + m = Math.floor((seconds % (60 * 60)) / 60), + s = Math.floor((seconds % (60 * 60)) % 60); + const totalTime = `${h}h:${m}m:${s}s`; + + let vpType = ['market', 'university', 'library', 'palace']; + vpType = vpType[Math.floor(vpType.length * Math.random())]; return (
-
{name} has won with {player.points} victory points!
+
{winner.name} has won with {winner.points} victory points!
- +
- {description} +
Congratulations, {winner.name}!
+
+ {winner.name} won the game + with {winner.points} Victory Points after {turnCount} game turns. + { Number(winner.potential) !== 0 && <>They had {winner.potential} unplayed Victory Point card(s).} + Their average turn time was {average}. +
+ { losers } +
The game took {totalTime}.
+ { robber }
@@ -80,4 +140,4 @@ const Winner = ({table, color}) => { ); }; -export default Winner; \ No newline at end of file +export { Winner }; \ No newline at end of file diff --git a/server/routes/games.js b/server/routes/games.js index 21117a3..34b27ba 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -18,7 +18,7 @@ const debug = { audio: false, get: true, set: true, - update: true + update: false }; let gameDB; @@ -222,6 +222,7 @@ const roll = (game, session) => { if (player.order && player.orderRoll) { return `Player ${name} has already rolled for player order.`; } + game.startTime = Date.now(); const dice = Math.ceil(Math.random() * 6); addChatMessage(game, session, `${name} rolled ${dice}.`); return processGameOrder(game, player, dice); @@ -308,7 +309,7 @@ const distributeResources = (game, roll) => { session.player.resources += entry[type]; message.push(`${entry[type]} ${type}`); } else { - robberSteal(game, color, type); + robberSteal(game, color, type, entry[type]); robber.push(`${entry[type]} ${type}`); } } @@ -345,7 +346,7 @@ const processRoll = (game, session, dice) => { distributeResources(game, game.turn.roll); for (let id in game.sessions) { if (game.sessions[id].player) { - sendUpdateToPlayer(game.sessions[id], { + sendUpdateToPlayer(game, game.sessions[id], { private: game.sessions[id].player }); } @@ -394,7 +395,7 @@ const processRoll = (game, session, dice) => { addChatMessage(game, null, `The robber was rolled and ${player.name} must discard ${player.mustDiscard} resource cards!`); for (let key in game.sessions) { if (game.sessions[key].player === player) { - sendUpdateToPlayer(game.sessions[key], { + sendUpdateToPlayer(game, game.sessions[key], { private: player }); break; @@ -428,7 +429,9 @@ const newPlayer = (color) => { army: 0, development: [], color: color, - name: "" + name: "", + totalTime: 0, + turnStart: 0 }; } @@ -556,7 +559,7 @@ const loadGame = async (id) => { }; const clearPlayer = (player) => { - const { color } = player; + const color = player.color; for (let key in player) { delete player[key]; } @@ -729,8 +732,8 @@ const adminActions = (game, action, value) => { let name = game.turn.name; const next = getNextPlayer(game, name); game.turn = { - name: next, - color: getColorFromName(game, next) + name: next.player, + color: next.color }; game.turns++; addChatMessage(game, null, `The admin skipped ${name}'s turn.`); @@ -861,7 +864,7 @@ const setPlayerName = (game, session, name) => { } } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { name: session.name, color: session.color, live: session.live, @@ -940,7 +943,7 @@ const setPlayerColor = (game, session, color) => { addChatMessage(game, null, `There are no longer enough players to start a game.`); } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { name: session.name, color: '', live: session.live, @@ -993,7 +996,7 @@ const setPlayerColor = (game, session, color) => { update.active = game.active; } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { name: session.name, color: session.color, live: session.live, @@ -1070,17 +1073,22 @@ const getNextPlayer = (game, name) => { break; } } - if (!color) { - return name; - } + console.log(`current player is ${color}`); let index = game.playerOrder.indexOf(color); + console.log(`current player is ${color} ${index}`); index = (index + 1) % game.playerOrder.length; + console.log(`current player is ${color} ${index}`); + color = game.playerOrder[index]; + console.log(`current player is ${color} ${index}`); for (let id in game.sessions) { - if (game.sessions[id].color === game.playerOrder[index]) { - return game.sessions[id].name; + if (game.sessions[id].color === color) { + return game.sessions[id].player; } } - return name; + console.log(`nothing found... returning current player.`); + console.log(game.players); + + return player; } const getPrevPlayer = (game, name) => { @@ -1091,17 +1099,14 @@ const getPrevPlayer = (game, name) => { break; } } - if (!color) { - return name; - } let index = game.playerOrder.indexOf(color); index = (index - 1) % game.playerOrder.length; for (let id in game.sessions) { if (game.sessions[id].color === game.playerOrder[index]) { - return game.sessions[id].name; + return game.sessions[id].player; } } - return name; + return player; } const processCorner = (game, color, cornerIndex, placedCorner) => { @@ -1856,14 +1861,16 @@ const pass = (game, session) => { return `Robber is in action. Turn can not stop until all Robber tasks are resolved.`; } - const next = getNextPlayer(game, name); + const next = getNextPlayer(game, session.name); + session.player.totalTime += Date.now() - session.player.turnStart; game.turn = { - name: next, - color: getColorFromName(game, next) + name: next.name, + color: next.color }; + next.turnStart = Date.now(); game.turns++; addActivity(game, session, `${name} passed their turn.`); - addChatMessage(game, null, `It is ${next}'s turn.`); + addChatMessage(game, null, `It is ${next.name}'s turn.`); sendUpdateToPlayers(game, { turns: game.turns, @@ -1936,7 +1943,7 @@ const placeRobber = (game, session, robber) => { robberName: game.robberName, activities: game.activities }); - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); } @@ -1985,7 +1992,7 @@ const stealResource = (game, session, color) => { addChatMessage(game, session, `${session.name} randomly stole 1 ${type} from ` + `${victim.name}.`); - sendUpdateToPlayer(victim, { + sendUpdateToPlayer(game, victim, { private: victim.player }); } @@ -1993,7 +2000,7 @@ const stealResource = (game, session, color) => { game.turn.robberInAction = false; - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -2052,7 +2059,7 @@ const buyDevelopment = (game, session) => { activities: game.activities, players: getFilteredPlayers(game) }); - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); } @@ -2166,7 +2173,7 @@ const playCard = (game, session, card) => { } } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -2296,15 +2303,15 @@ const placeSettlement = (game, session, index) => { setForRoadPlacement(game, layout.corners[index].roads); } + sendUpdateToPlayer(game, session, { + private: session.player + }); sendUpdateToPlayers(game, { placements: game.placements, activities: game.activities, turn: game.turn, chat: game.chat }); - sendUpdateToPlayer(session, { - private: session.player - }); } const placeRoad = (game, session, index) => { @@ -2392,25 +2399,27 @@ const placeRoad = (game, session, index) => { let next; if (game.direction === 'forward' && getLastPlayerName(game) === session.name) { game.direction = 'backward'; - next = session.name; + next = session.player; } else if (game.direction === 'backward' && getFirstPlayerName(game) === session.name) { /* Done! */ delete game.direction; } else { if (game.direction === 'forward') { next = getNextPlayer(game, session.name); + console.log(`advance from ${session.name} to `, next); } else { next = getPrevPlayer(game, session.name); + console.log(`devance from ${session.name} to `, next); } } if (next) { game.turn = { - name: next, - color: getColorFromName(game, next) + name: next.name, + color: next.color }; setForSettlementPlacement(game, getValidCorners(game)); calculateRoadLengths(game, session); - addChatMessage(game, null, `It is ${next}'s turn to place a settlement.`); + addChatMessage(game, null, `It is ${next.name}'s turn to place a settlement.`); } else { game.turn = { actions: [], @@ -2418,6 +2427,7 @@ const placeRoad = (game, session, index) => { name: session.name, color: getColorFromName(game, session.name) }; + session.player.startTime = Date.now(); addChatMessage(game, null, `Everyone has placed their two settlements!`); @@ -2442,6 +2452,9 @@ const placeRoad = (game, session, index) => { for (let type in receives) { player[type] += receives[type]; player.resources += receives[type]; + sendUpdateToPlayer(game, session, { + private: player + }); message.push(`${receives[type]} ${type}`); } addChatMessage(game, session, `${session.name} receives ${message.join(', ')}.`); @@ -2451,7 +2464,7 @@ const placeRoad = (game, session, index) => { game.state = 'normal'; } } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -2511,7 +2524,7 @@ const discard = (game, session, discards) => { game.turn.limits.pips.push(i); } } - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: player }); sendUpdateToPlayers(game, { @@ -2624,7 +2637,7 @@ const selectResources = (game, session, cards) => { player[type] = 0; for (let key in game.sessions) { if (game.sessions[key].player === player) { - sendUpdateToPlayer(game.sessions[key], { + sendUpdateToPlayer(game, game.sessions[key], { private: game.sessions[key].player }); break; @@ -2652,7 +2665,7 @@ const selectResources = (game, session, cards) => { } delete game.turn.active; game.turn.actions = []; - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -2786,7 +2799,7 @@ const placeCity = (game, session, index) => { game.turn.actions = []; game.turn.limits = {}; addActivity(game, session, `${session.name} upgraded a settlement to a city!`); - sendUpdateToPlayer(session, { + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -3028,13 +3041,14 @@ const sendUpdateToPlayers = async (game, update) => { } } + calculatePoints(game, update); + if (debug.update) { console.log(`[ all ]: -> sendUpdateToPlayers - `, update); } else { const keys = Object.getOwnPropertyNames(update); console.log(`[ all ]: -> sendUpdateToPlayers - ${keys.join(',')}`); } - const message = JSON.stringify({ type: 'game-update', @@ -3050,7 +3064,7 @@ const sendUpdateToPlayers = async (game, update) => { await saveGame(game); } -const sendUpdateToPlayer = async (session, update) => { +const sendUpdateToPlayer = async (game, session, update) => { /* Ensure clearing of a field actually gets sent by setting * undefined to 'false' @@ -3061,6 +3075,8 @@ const sendUpdateToPlayer = async (session, update) => { } } + calculatePoints(game, update); + if (debug.update) { console.log(`${session.id}: -> sendUpdateToPlayer:${getName(session)} - `, update); } else { @@ -3136,6 +3152,123 @@ const getFilteredPlayers = (game) => { return filtered; }; +const calculatePoints = (game, update) => { + if (game.state === 'winner') { + return; + } + /* Calculate points and determine if there is a winner */ + for (let key in game.players) { + const player = game.players[key]; + if (player.status === 'Not active') { + continue; + } + player.points = 0; + if (key === game.longestRoad) { + player.points += 2; + } + if (key === game.largestArmy) { + player.points += 2; + } + player.points += MAX_SETTLEMENTS - player.settlements; + player.points += 2 * (MAX_CITIES - player.cities); + + player.unplayed = 0; + player.potential = 0; + player.development.forEach(card => { + if (card.type === 'vp') { + if (card.played) { + player.points++; + } else { + player.potential++; + } + } + if (!card.played) { + player.unplayed++; + } + }); + + /* This player has 10 points! Check if they are the current + * player and if so, declare victory! */ + if (player.points >= 10) { + console.log(`${info}: Whoa! ${player.name} has ${player.points}!`); + for (let key in game.sessions) { + if (game.sessions[key].color !== player.color + || game.sessions[key].status === 'Not active') { + continue; + } + const message = `Wahoo! ${player.name} has 10 points on their turn and has won!`; + addChatMessage(game, null, message) + console.log(`${info}: ${message}`); + update.winner = Object.assign({}, player, { + state: 'winner', + robberStole: game.robberStole, + stolen: game.stolen, + chat: game.chat, + turns: game.turns, + players: game.players, + elapsedTime: Date.now() - game.startTime + }); + game.winner = update.winner; + game.state = 'winner'; + game.waiting = []; + } + } + } + + /* If the game isn't in a win state, do not share development card information + * with other players */ + if (game.state !== 'winner') { + for (let key in game.players) { + const player = game.players[key]; + if (player.status === 'Not active') { + continue; + } + delete player.potential; + } + } +} + +const gotoLobby = (game, session) => { + if (!game.waiting) { + game.waiting = []; + } + const already = game.waiting.indexOf(session.name) !== -1; + + const waitingFor = []; + for (let key in game.sessions) { + if (game.sessions[key] === session) { + continue; + } + + if (game.sessions[key].player && game.waiting.indexOf(game.sessions[key].name) == -1) { + waitingFor.push(game.sessions[key].name); + } + } + + if (!already) { + game.waiting.push(session.name); + addChatMessage(game, null, `${session.name} has gone to the lobby.`); + } else if (waitingFor.length !== 0) { + return `You are already waiting in the lobby. ` + + `${waitingFor.join(',')} still needs to go to the lobby.`; + } + + if (waitingFor.length === 0) { + resetGame(game); + addChatMessage(game, null, `All players are back to the lobby.`); + addChatMessage(game, null, + `The game has been reset. You can play again with this board, or `+ + `click 'New board' to mix things up a bit.`); + sendGameToPlayers(game); + return; + } + + addChatMessage(game, null, `Waiting for ${waitingFor.join(',')} to go to lobby.`); + sendUpdateToPlayers(game, { + chat: game.chat + }); +} + router.ws("/ws/:id", async (ws, req) => { if (!req.cookies || !req.cookies.player) { ws.send({ type: 'error', error: `Unable to set session cookie` }); @@ -3361,7 +3494,7 @@ router.ws("/ws/:id", async (ws, req) => { break; } }); - sendUpdateToPlayer(session, update); + sendUpdateToPlayer(game, session, update); break; case 'chat': @@ -3501,7 +3634,15 @@ router.ws("/ws/:id", async (ws, req) => { if (warning) { sendWarning(session, warning); } else { - sendUpdateToPlayer(session, { + for (let key in game.sessions) { + const tmp = game.sessions[key]; + if (tmp.player) { + sendUpdateToPlayer(game, tmp, { + private: tmp.player + }); + } + } + sendUpdateToPlayer(game, session, { private: session.player }); sendUpdateToPlayers(game, { @@ -3512,6 +3653,13 @@ router.ws("/ws/:id", async (ws, req) => { }); } break; + case 'goto-lobby': + console.log(`${short}: <- goto-lobby:${getName(session)}`); + warning = gotoLobby(game, session); + if (warning) { + sendWarning(session, warning); + } + break; default: console.warn(`Unsupported request: ${data.type}`); break; @@ -3593,56 +3741,6 @@ const debugChat = (game, preamble) => { } const getFilteredGameForPlayer = (game, session) => { - /* Calculate points and determine if there is a winner */ - for (let key in game.players) { - const player = game.players[key]; - if (player.status === 'Not active') { - continue; - } - player.points = 0; - if (key === game.longestRoad) { - player.points += 2; - } - if (key === game.largestArmy) { - player.points += 2; - } - player.points += MAX_SETTLEMENTS - player.settlements; - player.points += 2 * (MAX_CITIES - player.cities); - - player.unplayed = 0; - player.potential = 0; - player.development.forEach(card => { - if (card.type === 'vp') { - if (card.played) { - player.points++; - } else { - player.potential++; - } - } - if (!card.played) { - player.unplayed++; - } - }); - - console.log(`${todo}: Move game win state to card play section`); - if (!game.winner && (player.points >= 10 && session.color === key)) { - game.winner = key; - game.state = 'winner'; - delete game.turn.roll; - } - } - - /* If the game isn't in a win state, do not share development card information - * with other players */ - if (game.state !== 'winner') { - for (let key in game.players) { - const player = game.players[key]; - if (player.status === 'Not active') { - continue; - } - delete player.potential; - } - } /* Shallow copy game, filling its sessions with a shallow copy of * sessions so we can then delete the player field from them */ @@ -3686,7 +3784,7 @@ const getFilteredGameForPlayer = (game, session) => { }); } -const robberSteal = (game, color, type) => { +const robberSteal = (game, color, type, count) => { if (!game.stolen) { game.stolen = {}; } @@ -3699,9 +3797,9 @@ const robberSteal = (game, color, type) => { if (!(type in game.stolen[color])) { game.stolen[color][type] = 0; } - game.robberStole = game.robberStole ? game.robberStole++ : 1; - game.stolen[type]++; - game.stolen[color][type]++; + game.robberStole = game.robberStole += count; + game.stolen[type] += count; + game.stolen[color][type] += count; } const resetGame = (game) => { @@ -3728,6 +3826,7 @@ const resetGame = (game) => { signature: game.signature, players: game.players, stolen: {}, + robberStole: 0, longestRoad: '', longestRoadLength: 0, largestArmy: '', @@ -3782,7 +3881,7 @@ const resetGame = (game) => { /* Reset all player data */ for (let color in game.players) { - clearPlayer(game.players[color]); + clearPlayer(game.players[color]); } /* Ensure sessions are connected to player objects */ @@ -3793,6 +3892,8 @@ const resetGame = (game) => { session.player.status = 'Active'; session.player.lastActive = Date.now(); session.player.live = session.live; + session.player.name = session.name; + session.player.color = session.color; } } } @@ -3838,20 +3939,6 @@ const createGame = (id) => { return game; }; -router.post("/", (req, res/*, next*/) => { - console.log("POST games/"); - const game = createGame(); - if (!req.session.player_id) { - req.session.player_id = crypto.randomBytes(16).toString('hex'); - console.log(`[${req.session.player_id.substring(0, 8)}]: https - New session connected`); - } else { - console.log(`[${req.session.player_id.substring(0, 8)}]: https - Existing session being used`); - } - const session = getSession(game, req.cookies.player); - saveGame(game); - return res.status(200).send(getFilteredGameForPlayer(game, session)); -}); - const setBeginnerGame = (game) => { pickRobber(game); shuffleArray(game.developmentCards);