Lots of tweaks and fixes
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
1fcad2f21f
commit
e865133cc1
@ -545,7 +545,6 @@ class Table extends React.Component {
|
||||
this.setPlayerName = this.setPlayerName.bind(this);
|
||||
this.setSelected = this.setSelected.bind(this);
|
||||
this.updateMessage = this.updateMessage.bind(this);
|
||||
this.gameSignature = this.gameSignature.bind(this);
|
||||
this.sendAction = this.sendAction.bind(this);
|
||||
this.buildClicked = this.buildClicked.bind(this);
|
||||
this.closeCard = this.closeCard.bind(this);
|
||||
@ -821,21 +820,9 @@ class Table extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
gameSignature(game) {
|
||||
if (!game) {
|
||||
return "";
|
||||
}
|
||||
const signature =
|
||||
game.borderOrder.map(border => Number(border).toString(16)).join('') + '-' +
|
||||
game.pipOrder.map(pip => Number(pip).toString(16)).join('') + '-' +
|
||||
game.tileOrder.map(tile => Number(tile).toString(16)).join('');
|
||||
|
||||
return signature;
|
||||
};
|
||||
|
||||
updateGame(game) {
|
||||
if (this.state.signature !== this.gameSignature(game)) {
|
||||
game.signature = this.gameSignature(game);
|
||||
if (this.state.signature !== game.signature) {
|
||||
game.signature = game.signature;
|
||||
}
|
||||
// console.log("Update Game", game);
|
||||
this.setState( { game: game });
|
||||
@ -854,7 +841,7 @@ class Table extends React.Component {
|
||||
case 'lobby':
|
||||
message = <>{message}You are in the lobby as <b>{name}</b>.</>;
|
||||
if (!this.game.color) {
|
||||
message = <>{message}You need to pick your color.</>;
|
||||
message = <>{message}You select one of the <b>Available</b> colors below.</>;
|
||||
} else {
|
||||
message = <>{message}You have selected <PlayerColor color={this.game.color}/>.</>;
|
||||
}
|
||||
|
@ -35,3 +35,11 @@
|
||||
width: 10em; /* 5x7 aspect ratio */
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.Winner .PlayerColor {
|
||||
display: inline-flex;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ 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) => {
|
||||
@ -24,8 +25,8 @@ const Winner = ({table, color}) => {
|
||||
}
|
||||
|
||||
let description = <>Congratulations, <b>{name}</b>!
|
||||
They have won the game! The game played
|
||||
for {Math.floor(table.game.turns / playerCount)} turns.
|
||||
<p><PlayerColor color={color}/> {name} won the game after {Math.floor(table.game.turns / playerCount)} turns. They
|
||||
had <b>{player.potential}</b> unplayed Victory Point card(s).</p>
|
||||
</>;
|
||||
for (let key in table.game.players) {
|
||||
if (key === color) {
|
||||
@ -35,7 +36,8 @@ const Winner = ({table, color}) => {
|
||||
if (tmp.status === 'Not active') {
|
||||
continue;
|
||||
}
|
||||
let line = <>{getPlayerName(table.game.sessions, key)} finished with {tmp.points} victory points.</>
|
||||
let line = <><PlayerColor color={key}/> {getPlayerName(table.game.sessions, key)} finished with {tmp.points} victory points.
|
||||
They had <b>{player.potential}</b> unplayed Victory Point card(s).</>
|
||||
description = <>{description}<p>{line}</p></>;
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,6 @@ const express = require("express"),
|
||||
accessSync = fs.accessSync,
|
||||
randomWords = require("random-words");
|
||||
|
||||
const { clear } = require("console");
|
||||
const { corners } = require("./layout.js");
|
||||
const layout = require('./layout.js');
|
||||
|
||||
const MAX_SETTLEMENTS = 5;
|
||||
@ -552,6 +550,14 @@ const adminActions = (game, action, value) => {
|
||||
let color, player, parts, session;
|
||||
|
||||
switch (action) {
|
||||
case "debug":
|
||||
if (parseInt(value) === 0 || value === 'false') {
|
||||
delete game.debug;
|
||||
} else {
|
||||
game.debug = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case "state":
|
||||
switch (value) {
|
||||
case 'game-order':
|
||||
@ -988,7 +994,7 @@ const calculateRoadLengths = (game, session) => {
|
||||
|
||||
/* Clear out player longest road counts */
|
||||
for (let key in game.players) {
|
||||
game.players[key].length = 0;
|
||||
game.players[key].longestRoad = 0;
|
||||
}
|
||||
|
||||
/* Build a set of connected road graphs. Once all graphs are
|
||||
@ -1070,7 +1076,7 @@ const calculateRoadLengths = (game, session) => {
|
||||
if (game.players[key].longestRoad > longestRoad) {
|
||||
longestPlayers = [ key ];
|
||||
longestRoad = game.players[key].longestRoad;
|
||||
} else if (game.players[key].longestRoad == longestRoad && checkForTies) {
|
||||
} else if (game.players[key].longestRoad === longestRoad) {
|
||||
longestPlayers.push(key);
|
||||
}
|
||||
}
|
||||
@ -1314,6 +1320,46 @@ const checkOffer = (player, offer) => {
|
||||
return error;
|
||||
};
|
||||
|
||||
const gameSignature = (game) => {
|
||||
if (!game) {
|
||||
return "";
|
||||
}
|
||||
const salt = 251;
|
||||
const signature =
|
||||
game.borderOrder.map(border => `00${(Number(border)^salt).toString(16)}`.slice(-2)).join('') + '-' +
|
||||
game.pipOrder.map((pip, index) => `00${(Number(pip)^salt^(salt*index)).toString(16)}`.slice(-2)).join('') + '-' +
|
||||
game.tileOrder.map((tile, index) => `00${(Number(tile)^salt^(salt*index)).toString(16)}`.slice(-2)).join('');
|
||||
|
||||
return signature;
|
||||
};
|
||||
|
||||
const setGameFromSignature = (game, border, pip, tile) => {
|
||||
const salt = 251;
|
||||
const borders = [], pips = [], tiles = [];
|
||||
for (let i = 0; i < 6; i++) {
|
||||
borders[i] = parseInt(border.slice(i * 2, (i * 2) + 2), 16)^salt;
|
||||
if (borders[i] > 6) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < 19; i++) {
|
||||
pips[i] = parseInt(pip.slice(i * 2, (i * 2) + 2), 16)^salt^(salt*i) % 256;
|
||||
if (pips[i] > 18) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < 19; i++) {
|
||||
tiles[i] = parseInt(tile.slice(i * 2, (i * 2) + 2), 16)^salt^(salt*i) % 256;
|
||||
if (tiles[i] > 18) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
game.borderOrder = borders;
|
||||
game.pipOrder = pips;
|
||||
game.tileOrder = tiles;
|
||||
return true;
|
||||
}
|
||||
|
||||
const offerToString = (offer) => {
|
||||
return offer.gives.map(item => `${item.count} ${item.type}`).join(', ') +
|
||||
' in exchange for ' +
|
||||
@ -1354,6 +1400,28 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
case 'chat':
|
||||
const chat = req.body;
|
||||
addChatMessage(game, session, chat.message);
|
||||
/* Chat messages can set game flags and fields */
|
||||
const parts = chat.message.match(/^set +([^ ]*) +(.*)$/i);
|
||||
if (parts && parts.length === 3) {
|
||||
switch (parts[1].toLowerCase()) {
|
||||
case 'game':
|
||||
if (parts[2].trim().match(/^beginner('?s)?( +layout)?/i)) {
|
||||
setBeginnerGame(game);
|
||||
addChatMessage(game, session, `${session.name} set game board to the Beginner's Layout.`);
|
||||
break;
|
||||
}
|
||||
const signature = parts[2].match(/^([0-9a-f]{12})-([0-9a-f]{38})-([0-9a-f]{38})/i);
|
||||
if (signature) {
|
||||
if (setGameFromSignature(game, signature[1], signature[2], signature[3])) {
|
||||
game.signature = parts[2];
|
||||
addChatMessage(game, session, `${session.name} set game board to ${parts[2]}.`);
|
||||
} else {
|
||||
addChatMessage(game, session, `${session.name} requested an invalid game board.`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sendGame(req, res, game);
|
||||
}
|
||||
|
||||
@ -1540,7 +1608,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
}
|
||||
if (!error) {
|
||||
shuffleBoard(game);
|
||||
const message = `${name} requested a new board.`;
|
||||
const message = `${name} requested a new board. New board signature: ${game.signature}.`;
|
||||
addChatMessage(game, null, message);
|
||||
console.log(message);
|
||||
}
|
||||
@ -2328,7 +2396,11 @@ const debugChat = (game, preamble) => {
|
||||
playerInventory += `nothing, `;
|
||||
}
|
||||
}
|
||||
addChatMessage(game, null, playerInventory.replace(/, $/, '').trim());
|
||||
if (game.debug) {
|
||||
addChatMessage(game, null, playerInventory.replace(/, $/, '').trim());
|
||||
} else {
|
||||
console.log(playerInventory.replace(/, $/, '').trim());
|
||||
}
|
||||
}
|
||||
|
||||
const getActiveCount = (game) => {
|
||||
@ -2413,9 +2485,13 @@ const sendGame = async (req, res, game, error) => {
|
||||
player.points += 2 * (MAX_CITIES - player.cities);
|
||||
|
||||
player.unplayed = 0;
|
||||
player.potential = 0;
|
||||
player.development.forEach(card => {
|
||||
if (card.type === 'vp' && card.played) {
|
||||
player.points++;
|
||||
if (card.type === 'vp') {
|
||||
player.potential++;
|
||||
if (card.played) {
|
||||
player.points++;
|
||||
}
|
||||
}
|
||||
if (!card.played) {
|
||||
player.unplayed++;
|
||||
@ -2428,8 +2504,18 @@ const sendGame = async (req, res, game, error) => {
|
||||
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
|
||||
@ -2482,7 +2568,6 @@ const sendGame = async (req, res, game, error) => {
|
||||
sessions: reducedSessions,
|
||||
layout: layout
|
||||
});
|
||||
|
||||
return res.status(200).send(playerGame);
|
||||
}
|
||||
|
||||
@ -2518,8 +2603,21 @@ const resetGame = (game) => {
|
||||
cities: MAX_CITIES,
|
||||
settlements: MAX_SETTLEMENTS,
|
||||
points: 0,
|
||||
development: []
|
||||
development: [],
|
||||
banks: [],
|
||||
maritime: [],
|
||||
army: 0,
|
||||
playedCard: 0,
|
||||
haveResources: false,
|
||||
unplayed: 0,
|
||||
longestRoad: 0,
|
||||
mustDiscard: 0,
|
||||
gives: [],
|
||||
gets: []
|
||||
});
|
||||
game.players[key].order = 0;
|
||||
delete game.players[key].orderRoll;
|
||||
delete game.players[key].orderStatus;
|
||||
}
|
||||
|
||||
shuffle(game.developmentCards);
|
||||
@ -2538,19 +2636,13 @@ const resetGame = (game) => {
|
||||
};
|
||||
}
|
||||
|
||||
for (let key in game.players) {
|
||||
game.players[key].order = 0;
|
||||
delete game.players[key].orderRoll;
|
||||
delete game.players[key].orderStatus;
|
||||
}
|
||||
|
||||
delete game.turn;
|
||||
}
|
||||
|
||||
const createGame = (id) => {
|
||||
/* Look for a new game with random words that does not already exist */
|
||||
while (!id) {
|
||||
id = randomWords(4).join('_');
|
||||
id = randomWords(4).join('-');
|
||||
console.log(`Looking for ${id}`);
|
||||
try {
|
||||
/* If file can be read, it already exists so look for a new name */
|
||||
@ -2586,7 +2678,9 @@ const createGame = (id) => {
|
||||
id: id
|
||||
};
|
||||
|
||||
addChatMessage(game, null, `New game started for ${id}`);
|
||||
console.log(`New game created with Beginner's Layout: ${game.id}`);
|
||||
addChatMessage(game, null,
|
||||
`New game created with Beginner's Layout: ${game.id}`);
|
||||
|
||||
[ "pips", "borders", "tiles" ].forEach((field) => {
|
||||
game[field] = assetData[field]
|
||||
@ -2595,8 +2689,7 @@ const createGame = (id) => {
|
||||
resetGame(game);
|
||||
|
||||
games[game.id] = game;
|
||||
shuffleBoard(game);
|
||||
console.log(`New game created: ${game.id}`);
|
||||
setBeginnerGame(game);
|
||||
return game;
|
||||
};
|
||||
|
||||
@ -2614,16 +2707,40 @@ router.post("/:id?", (req, res/*, next*/) => {
|
||||
return sendGame(req, res, game);
|
||||
});
|
||||
|
||||
const shuffleBoard = (game) => {
|
||||
const setBeginnerGame = (game) => {
|
||||
game.gender = Math.random() > 0.5 ? 'male' : 'female';
|
||||
shuffle(game.developmentCards);
|
||||
game.borderOrder = [];
|
||||
for (let i = 0; i < 6; i++) {
|
||||
game.borderOrder.push(i);
|
||||
}
|
||||
game.tileOrder = [
|
||||
9, 12, 1,
|
||||
5, 16, 13, 17,
|
||||
6, 2, 0, 3, 10,
|
||||
4, 11, 7, 14,
|
||||
18, 8, 15
|
||||
];
|
||||
game.pipOrder = [
|
||||
5, 1, 6,
|
||||
7, 2, 9, 11,
|
||||
12, 8, 18, 3, 4,
|
||||
10, 16, 13, 0,
|
||||
14, 15, 17
|
||||
];
|
||||
game.signature = gameSignature(game);
|
||||
}
|
||||
|
||||
const shuffleBoard = (game, beginnersGame) => {
|
||||
game.gender = Math.random() > 0.5 ? 'male' : 'female';
|
||||
|
||||
const seq = [];
|
||||
for (let i = 0; i < 6; i++) {
|
||||
seq.push(i);
|
||||
}
|
||||
shuffle(seq);
|
||||
|
||||
game.gender = Math.random() > 0.5 ? 'male' : 'female';
|
||||
|
||||
game.borderOrder = seq.slice();
|
||||
|
||||
for (let i = 6; i < 19; i++) {
|
||||
seq.push(i);
|
||||
}
|
||||
@ -2665,6 +2782,8 @@ const shuffleBoard = (game) => {
|
||||
}
|
||||
|
||||
shuffle(game.developmentCards);
|
||||
|
||||
game.signature = gameSignature(game);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user