Added more Robber processing
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
e264f0ae8d
commit
37467c7377
@ -33,13 +33,15 @@
|
|||||||
background-size: 600% auto; /* pip-numbers is a 6x6 grid of pip images */
|
background-size: 600% auto; /* pip-numbers is a 6x6 grid of pip images */
|
||||||
width: 2em;
|
width: 2em;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Pip.Active {
|
.Pip.Active {
|
||||||
filter: drop-shadow(0px 0px 5px rgba(255, 255, 0, 0.9));
|
filter: drop-shadow(0px 0px 5px rgba(255, 255, 0, 0.9));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Pips[disabled],
|
||||||
|
.Tiles[disabled],
|
||||||
.Roads[disabled],
|
.Roads[disabled],
|
||||||
.Corners[disabled] {
|
.Corners[disabled] {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -107,19 +109,40 @@
|
|||||||
right: 0px;
|
right: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
clip-path: circle(50%);
|
/* clip-path: circle(50%);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Tile-Shape {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
clip-path: polygon(25% 0%,75% 0%,100% 50%,75% 100%,25% 100%,0% 50%);
|
||||||
|
}
|
||||||
|
|
||||||
.Option {
|
.Option {
|
||||||
|
cursor: pointer;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Option .Pip-Shape,
|
||||||
|
.Option .Tile-Shape,
|
||||||
.Option .Corner-Shape,
|
.Option .Corner-Shape,
|
||||||
.Option .Road-Shape {
|
.Option .Road-Shape {
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Robber .Pip-Shape,
|
||||||
|
.Pip-Shape:hover {
|
||||||
|
clip-path: circle(45%); /* show through the border */
|
||||||
|
background-size: contain;
|
||||||
|
background-position: center;
|
||||||
|
background-image:url("./assets/woman-robber.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.Tile-Shape:hover,
|
||||||
.Corner-Shape:hover,
|
.Corner-Shape:hover,
|
||||||
.Road-Shape:hover {
|
.Road-Shape:hover {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
@ -47,8 +47,8 @@ const Board = ({ table, game }) => {
|
|||||||
height: `${tileImageHeight}px`,
|
height: `${tileImageHeight}px`,
|
||||||
backgroundImage: `url(${assetsPath}/gfx/tiles-${tile.type}.png)`,
|
backgroundImage: `url(${assetsPath}/gfx/tiles-${tile.type}.png)`,
|
||||||
backgroundPositionY: `-${tile.card*tileHeight}px`
|
backgroundPositionY: `-${tile.card*tileHeight}px`
|
||||||
}}
|
}}
|
||||||
/>;
|
><div className="Tile-Shape"/></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Road = ({road}) => {
|
const Road = ({road}) => {
|
||||||
@ -85,6 +85,27 @@ const Board = ({ table, game }) => {
|
|||||||
><div className="Corner-Shape"/></div>;
|
><div className="Corner-Shape"/></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Pip = ({pip}) => {
|
||||||
|
const onClick = (event) => {
|
||||||
|
console.log(`Pip ${pip.index}:`, game.layout.corners[pip.index]);
|
||||||
|
table.placeRobber(pip.index);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
return <div className={`Pip${pip.robber ? ' Robber' : ''}`}
|
||||||
|
onClick={onClick}
|
||||||
|
data-roll={pip.roll}
|
||||||
|
data-index={pip.index}
|
||||||
|
style={{
|
||||||
|
top: `${pip.top}px`,
|
||||||
|
left: `${pip.left}px`,
|
||||||
|
backgroundImage: `url(${assetsPath}/gfx/pip-numbers.png)`,
|
||||||
|
backgroundPositionX: `${ 100. * (pip.order % 6) / 5.}%`,
|
||||||
|
backgroundPositionY: `${ 100 * Math.floor(pip.order / 6) / 5. }%`
|
||||||
|
}}
|
||||||
|
><div className="Pip-Shape"/></div>;
|
||||||
|
};
|
||||||
|
|
||||||
const generateRoads = () => {
|
const generateRoads = () => {
|
||||||
let row = 0, rowCount = 0;
|
let row = 0, rowCount = 0;
|
||||||
let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
@ -229,20 +250,21 @@ const Board = ({ table, game }) => {
|
|||||||
let row = 0, rowCount = 0;
|
let row = 0, rowCount = 0;
|
||||||
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||||
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
||||||
|
let index = 0;
|
||||||
|
let pip;
|
||||||
return game.pipOrder.map(order => {
|
return game.pipOrder.map(order => {
|
||||||
const pip = game.pips[order];
|
pip = {
|
||||||
const div = <div
|
roll: game.pips[order].roll,
|
||||||
data-roll={pip.roll}
|
robber: index === game.robber,
|
||||||
|
index: index++,
|
||||||
|
top: y,
|
||||||
|
left: x,
|
||||||
|
order: order
|
||||||
|
};
|
||||||
|
const div = <Pip
|
||||||
|
pip={pip}
|
||||||
key={`pip-${order}`}
|
key={`pip-${order}`}
|
||||||
className="Pip"
|
/>;
|
||||||
style={{
|
|
||||||
top: `${y}px`,
|
|
||||||
left: `${x}px`,
|
|
||||||
backgroundImage: `url(${assetsPath}/gfx/pip-numbers.png)`,
|
|
||||||
backgroundPositionX: `${ 100. * (order % 6) / 5.}%`,
|
|
||||||
backgroundPositionY: `${ 100 * Math.floor(order / 6) / 5. }%`
|
|
||||||
}}
|
|
||||||
><div className="Pip-Shape"/></div>;
|
|
||||||
|
|
||||||
if (++rowCount === rows[row]) {
|
if (++rowCount === rows[row]) {
|
||||||
row++;
|
row++;
|
||||||
@ -389,10 +411,11 @@ const Board = ({ table, game }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
/* Clear all 'Option' targets */
|
/* Clear all 'Option' targets */
|
||||||
const nodes = document.querySelectorAll(`.Option`);
|
let nodes = document.querySelectorAll(`.Option`);
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
nodes[i].classList.remove('Option');
|
nodes[i].classList.remove('Option');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add 'Option' based on game.turn.limits */
|
/* Add 'Option' based on game.turn.limits */
|
||||||
if (game.turn && game.turn.limits) {
|
if (game.turn && game.turn.limits) {
|
||||||
if (game.turn.limits['roads']) {
|
if (game.turn.limits['roads']) {
|
||||||
@ -413,6 +436,38 @@ const Board = ({ table, game }) => {
|
|||||||
el.classList.add('Option');
|
el.classList.add('Option');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (game.turn.limits['tiles']) {
|
||||||
|
game.turn.limits['tiles'].forEach(index => {
|
||||||
|
const el = document.querySelector(`.Tile[data-index="${index}"]`);
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
el.classList.add('Option');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (game.turn.limits['pips']) {
|
||||||
|
game.turn.limits['pips'].forEach(index => {
|
||||||
|
const el = document.querySelector(`.Pip[data-index="${index}"]`);
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
el.classList.add('Option');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game) {
|
||||||
|
let nodes = document.querySelectorAll(`.Pip .Robber`);
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
nodes[i].classList.remove('Robber');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.robber) {
|
||||||
|
const el = document.querySelector(`.Pip[data-index="${game.robber}"]`);
|
||||||
|
if (el) {
|
||||||
|
el.classList.add('Robber');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,9 +479,13 @@ const Board = ({ table, game }) => {
|
|||||||
<div className="Board">
|
<div className="Board">
|
||||||
<div className="BoardBox">
|
<div className="BoardBox">
|
||||||
{ borders }
|
{ borders }
|
||||||
{ tiles }
|
|
||||||
{ pips }
|
|
||||||
{ game && <>
|
{ game && <>
|
||||||
|
<div className="Tiles" disabled>
|
||||||
|
{ tiles }
|
||||||
|
</div>
|
||||||
|
<div className="Pips" disabled={!canAction('place-robber') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
||||||
|
{ pips }
|
||||||
|
</div>
|
||||||
<div className="Corners" disabled={!canAction('place-settlement') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
<div className="Corners" disabled={!canAction('place-settlement') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
||||||
{ corners }
|
{ corners }
|
||||||
</div>
|
</div>
|
||||||
|
@ -306,9 +306,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Hand {
|
.Hand {
|
||||||
|
display: flex;
|
||||||
min-height: calc(7.2em + 0.5em);
|
min-height: calc(7.2em + 0.5em);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Hand > button {
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
.Hand:hover .Stack:hover > *:not(:first-child) {
|
.Hand:hover .Stack:hover > *:not(:first-child) {
|
||||||
margin-left: -2em;
|
margin-left: -2em;
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,7 @@ const Resource = ({ type, count }) => {
|
|||||||
<div className="Stack">
|
<div className="Stack">
|
||||||
{ React.Children.map(array, i => (
|
{ React.Children.map(array, i => (
|
||||||
<div className="Resource"
|
<div className="Resource"
|
||||||
|
data-type={type}
|
||||||
onClick={select}
|
onClick={select}
|
||||||
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
||||||
</div>
|
</div>
|
||||||
@ -336,6 +337,16 @@ const GameOrder = ({table}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Action = ({ table }) => {
|
const Action = ({ table }) => {
|
||||||
|
const discardClick = (event) => {
|
||||||
|
const nodes = document.querySelectorAll('.Hand .Selected'),
|
||||||
|
discarding = { wheat: 0, brick: 0, sheep: 0, stone: 0, wood: 0 };
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
discarding[nodes[i].getAttribute("data-type")]++;
|
||||||
|
nodes[i].classList.remove('Selected');
|
||||||
|
}
|
||||||
|
return table.discard(discarding);
|
||||||
|
}
|
||||||
|
|
||||||
const newTableClick = (event) => {
|
const newTableClick = (event) => {
|
||||||
return table.shuffleTable();
|
return table.shuffleTable();
|
||||||
};
|
};
|
||||||
@ -357,7 +368,9 @@ const Action = ({ table }) => {
|
|||||||
return (<Paper className="Action"/>);
|
return (<Paper className="Action"/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inLobby = table.game.state === 'lobby';
|
const inLobby = table.game.state === 'lobby',
|
||||||
|
player = table.game ? table.game.player : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="Action">
|
<Paper className="Action">
|
||||||
{ inLobby && <>
|
{ inLobby && <>
|
||||||
@ -368,6 +381,9 @@ const Action = ({ table }) => {
|
|||||||
<Button disabled={(table.game.turn.color !== table.game.color || table.game.turn.roll) ? true : false} onClick={rollClick}>Roll Dice</Button>
|
<Button disabled={(table.game.turn.color !== table.game.color || table.game.turn.roll) ? true : false} onClick={rollClick}>Roll Dice</Button>
|
||||||
<Button disabled>Trade</Button>
|
<Button disabled>Trade</Button>
|
||||||
<Button disabled>Build</Button>
|
<Button disabled>Build</Button>
|
||||||
|
{ table.game.turn.roll === 7 && player && player.mustDiscard > 0 &&
|
||||||
|
<Button onClick={discardClick}>Discard</Button>
|
||||||
|
}
|
||||||
<Button disabled={(table.game.turn.color !== table.game.color || !table.game.turn.roll) ? true : false} onClick={passClick}>Done</Button>
|
<Button disabled={(table.game.turn.color !== table.game.color || !table.game.turn.roll) ? true : false} onClick={passClick}>Done</Button>
|
||||||
</> }
|
</> }
|
||||||
{ !inLobby &&
|
{ !inLobby &&
|
||||||
@ -493,6 +509,7 @@ class Table extends React.Component {
|
|||||||
this.rollDice = this.rollDice.bind(this);
|
this.rollDice = this.rollDice.bind(this);
|
||||||
this.setGameState = this.setGameState.bind(this);
|
this.setGameState = this.setGameState.bind(this);
|
||||||
this.shuffleTable = this.shuffleTable.bind(this);
|
this.shuffleTable = this.shuffleTable.bind(this);
|
||||||
|
this.discard = this.discard.bind(this);
|
||||||
this.passTurn = this.passTurn.bind(this);
|
this.passTurn = this.passTurn.bind(this);
|
||||||
this.updateGame = this.updateGame.bind(this);
|
this.updateGame = this.updateGame.bind(this);
|
||||||
this.setPlayerName = this.setPlayerName.bind(this);
|
this.setPlayerName = this.setPlayerName.bind(this);
|
||||||
@ -577,6 +594,10 @@ class Table extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
discard(resources) {
|
||||||
|
return this.sendAction('discard', undefined, resources);
|
||||||
|
}
|
||||||
|
|
||||||
passTurn() {
|
passTurn() {
|
||||||
return this.sendAction('pass');
|
return this.sendAction('pass');
|
||||||
};
|
};
|
||||||
@ -662,6 +683,10 @@ class Table extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
placeRobber(robber) {
|
||||||
|
return this.sendAction('place-robber', robber);
|
||||||
|
};
|
||||||
|
|
||||||
placeSettlement(settlement) {
|
placeSettlement(settlement) {
|
||||||
return this.sendAction('place-settlement', settlement);
|
return this.sendAction('place-settlement', settlement);
|
||||||
}
|
}
|
||||||
@ -813,6 +838,24 @@ class Table extends React.Component {
|
|||||||
case '':
|
case '':
|
||||||
message = <>{message}The game is in a wonky state. Sorry :(</>;
|
message = <>{message}The game is in a wonky state. Sorry :(</>;
|
||||||
break;
|
break;
|
||||||
|
case 'normal':
|
||||||
|
if (this.game && this.game.turn) {
|
||||||
|
if (this.game.turn.roll === 7) {
|
||||||
|
message = <>{message}Robber was rolled!</>;
|
||||||
|
let move = true;
|
||||||
|
for (let color in this.game.players) {
|
||||||
|
const discard = this.game.players[color].mustDiscard;
|
||||||
|
if (discard) {
|
||||||
|
move = false;
|
||||||
|
message = <>{message}<PlayerColor color={color}/> needs to discard {discard} resources.</>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (move) {
|
||||||
|
message = <>{message}<PlayerColor color={this.game.turn.color}/> {this.game.turn.name} needs to move the robber.</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
message = <>{message}Game state is: {this.game.state}</>;
|
message = <>{message}Game state is: {this.game.state}</>;
|
||||||
break;
|
break;
|
||||||
@ -909,15 +952,16 @@ class Table extends React.Component {
|
|||||||
<div className="Table">
|
<div className="Table">
|
||||||
|
|
||||||
<div style={{display: "inline-flex", flex: 1, flexDirection: "column"}}>
|
<div style={{display: "inline-flex", flex: 1, flexDirection: "column"}}>
|
||||||
<Board table={this} game={game}/>
|
<Board table={this} game={game}/>
|
||||||
{ player !== undefined && <div className="Hand'">
|
{ player !== undefined && <div className="Hand">
|
||||||
<Resource type="wood" count={player.wood}/>
|
<Resource type="wood" count={player.wood}/>
|
||||||
<Resource type="wheat" count={player.wheat}/>
|
<Resource type="wheat" count={player.wheat}/>
|
||||||
<Resource type="stone" count={player.stone}/>
|
<Resource type="stone" count={player.stone}/>
|
||||||
<Resource type="brick" count={player.brick}/>
|
<Resource type="brick" count={player.brick}/>
|
||||||
<Resource type="sheep" count={player.sheep}/>
|
<Resource type="sheep" count={player.sheep}/>
|
||||||
</div> }
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ game && <div className={'Game ' + game.state}>
|
{ game && <div className={'Game ' + game.state}>
|
||||||
<Paper className="Message">{ this.state.message }</Paper>
|
<Paper className="Message">{ this.state.message }</Paper>
|
||||||
{(this.state.pickName || !game.name) && <PlayerName table={this}/> }
|
{(this.state.pickName || !game.name) && <PlayerName table={this}/> }
|
||||||
@ -934,7 +978,7 @@ class Table extends React.Component {
|
|||||||
|
|
||||||
{ game && game.turn && game.turn.color !== game.color &&
|
{ game && game.turn && game.turn.color !== game.color &&
|
||||||
(game.state === 'initial-placement' || game.state === 'normal') &&
|
(game.state === 'initial-placement' || game.state === 'normal') &&
|
||||||
<WaitingForPlayer table={this}/>
|
(!game.player || !game.player.mustDiscard) && <WaitingForPlayer table={this}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
{ game && game.showCards &&
|
{ game && game.showCards &&
|
||||||
|
BIN
client/src/assets/man-robber.png
Executable file
BIN
client/src/assets/man-robber.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
client/src/assets/woman-robber.png
Executable file
BIN
client/src/assets/woman-robber.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -291,7 +291,11 @@ const distributeResources = (game, roll) => {
|
|||||||
for (let i = 0; i < game.pipOrder.length; i++) {
|
for (let i = 0; i < game.pipOrder.length; i++) {
|
||||||
let index = game.pipOrder[i];
|
let index = game.pipOrder[i];
|
||||||
if (assetData.pips[index].roll === roll) {
|
if (assetData.pips[index].roll === roll) {
|
||||||
tiles.push(i);
|
if (game.robber === i) {
|
||||||
|
addChatMessage(game, null, `That pesky Robber stole resources!`);
|
||||||
|
} else {
|
||||||
|
tiles.push(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,10 +354,40 @@ const processRoll = (game, dice) => {
|
|||||||
game.turn.roll = game.dice[0] + game.dice[1];
|
game.turn.roll = game.dice[0] + game.dice[1];
|
||||||
if (game.turn.roll === 7) {
|
if (game.turn.roll === 7) {
|
||||||
addChatMessage(game, null, `ROBBER! ROBBER! ROBBER!`);
|
addChatMessage(game, null, `ROBBER! ROBBER! ROBBER!`);
|
||||||
|
for (let id in game.sessions) {
|
||||||
|
const player = game.sessions[id].player;
|
||||||
|
if (player) {
|
||||||
|
let discard = player.stone + player.wheat + player.brick + player.wood + player.sheep;
|
||||||
|
if (discard > 7) {
|
||||||
|
discard = Math.floor(discard / 2);
|
||||||
|
|
||||||
|
player.mustDiscard = discard;
|
||||||
|
addChatMessage(game, null, `${game.sessions[id].name} must discard ${discard} resource cards.`);
|
||||||
|
} else {
|
||||||
|
delete player.mustDiscard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if you roll a 7, no one receives any resource cards.
|
||||||
|
instead, every player who has more than 7 resource cards must select
|
||||||
|
half (rounded down) of their
|
||||||
|
resource cards and return them to the bank.
|
||||||
|
then you muyst move the robber:
|
||||||
|
1. you must move the robber immediately to the number token of any other
|
||||||
|
terrain ohex or to the desert hex,
|
||||||
|
2. you then steal 1 (random) resourcde card from an opponent who has a settlement or city
|
||||||
|
adjacent to the target terrain hex. the player who is robbed holds their resource cards
|
||||||
|
face down. you then take 1 card at random. if the target hex is adjacent to 2 or
|
||||||
|
more player's settlements or cities, you choose which one you want to steal from.
|
||||||
|
If the production number for the hex containing the robber is rolled, the owners of
|
||||||
|
adjacent settlements and citieis do not receive resourcres. The robber prevents it.
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
distributeResources(game, game.turn.roll);
|
distributeResources(game, game.turn.roll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPlayer = (game, color) => {
|
const getPlayer = (game, color) => {
|
||||||
if (!game) {
|
if (!game) {
|
||||||
return {
|
return {
|
||||||
@ -846,6 +880,34 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
addChatMessage(game, null, `It is ${next}'s turn.`);
|
addChatMessage(game, null, `It is ${next}'s turn.`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'place-robber':
|
||||||
|
if (game.state !== 'normal' && game.turn.roll !== 7) {
|
||||||
|
error = `You cannot place robber unless 7 was rolled!`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (game.turn.name !== name) {
|
||||||
|
error = `You cannot place the robber when it isn't your turn.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (let color in game.players) {
|
||||||
|
if (game.players[color].status === 'Not active') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (game.players[color].mustDiscard > 0) {
|
||||||
|
error = `You cannot place the robber until everyone has discarded!`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const robber = parseInt(value);
|
||||||
|
if (game.robber === robber) {
|
||||||
|
error = `You must move the robber to a new location!`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
game.robber = robber;
|
||||||
|
game.turn.placedRobber = true;
|
||||||
|
addChatMessage(game, session, `Robber has been moved!`);
|
||||||
|
addChatMessage(game, null, 'TODO: Look up which players are on tile, then allow robber-roller to select which player to steal from.');
|
||||||
|
break;
|
||||||
case 'place-settlement':
|
case 'place-settlement':
|
||||||
if (game.state !== 'initial-placement' && game.state !== 'normal') {
|
if (game.state !== 'initial-placement' && game.state !== 'normal') {
|
||||||
error = `You cannot place an item unless the game is active.`;
|
error = `You cannot place an item unless the game is active.`;
|
||||||
@ -979,6 +1041,33 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
case 'place-city':
|
case 'place-city':
|
||||||
error = `City placement not yet implemented!`;
|
error = `City placement not yet implemented!`;
|
||||||
break;
|
break;
|
||||||
|
case 'discard':
|
||||||
|
if (game.turn.roll !== 7) {
|
||||||
|
error = `You can only discard due to the Robber!`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const discards = req.body, player = session.player;
|
||||||
|
let sum = 0;
|
||||||
|
for (let type in discards) {
|
||||||
|
if (player[type] < parseInt(discards[type])) {
|
||||||
|
error = `You have requested to discard more ${type} than you have.`
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sum += parseInt(discards[type]);
|
||||||
|
}
|
||||||
|
if (sum > player.mustDiscard) {
|
||||||
|
error = `You have requested to discard more cards than you are allowed!`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (let type in discards) {
|
||||||
|
player[type] -= parseInt(discards[type]);
|
||||||
|
player.mustDiscard -= parseInt(discards[type])
|
||||||
|
}
|
||||||
|
addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`);
|
||||||
|
if (player.mustDiscard) {
|
||||||
|
addChatMessage(game, null, `${session.name} must discard ${player.mustDiscard} more cards.`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "state":
|
case "state":
|
||||||
const state = value;
|
const state = value;
|
||||||
if (!state) {
|
if (!state) {
|
||||||
@ -1048,6 +1137,28 @@ const sendGame = async (req, res, game, error) => {
|
|||||||
}
|
}
|
||||||
game.active = active;
|
game.active = active;
|
||||||
|
|
||||||
|
/* If the current turn is a robber placement, and everyone has
|
||||||
|
* discarded, set the limits for where the robber can be placed */
|
||||||
|
if (game.turn.roll === 7) {
|
||||||
|
let move = true;
|
||||||
|
for (let color in game.players) {
|
||||||
|
const discard = game.players[color].mustDiscard;
|
||||||
|
if (discard) {
|
||||||
|
move = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (move && !game.turn.placedRobber) {
|
||||||
|
game.turn.actions = [ 'place-robber' ];
|
||||||
|
game.turn.limits = { pips: [] };
|
||||||
|
for (let i = 0; i < 19; i++) {
|
||||||
|
if (i === game.robber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
game.turn.limits.pips.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the session lastActive clock */
|
/* Update the session lastActive clock */
|
||||||
let session;
|
let session;
|
||||||
if (req.session) {
|
if (req.session) {
|
||||||
@ -1117,6 +1228,14 @@ const resetGame = (game) => {
|
|||||||
roads: []
|
roads: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (let key in game.players) {
|
||||||
|
game.players[key].wheat =
|
||||||
|
game.players[key].sheep =
|
||||||
|
game.players[key].stone =
|
||||||
|
game.players[key].brick =
|
||||||
|
game.players[key].wood = 0;
|
||||||
|
}
|
||||||
|
|
||||||
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] = {
|
||||||
color: undefined,
|
color: undefined,
|
||||||
@ -1247,6 +1366,7 @@ const shuffleBoard = (game) => {
|
|||||||
* the target pip value to the currently incremeneting
|
* the target pip value to the currently incremeneting
|
||||||
* pip value. */
|
* pip value. */
|
||||||
if (game.tiles[game.tileOrder[target]].type === 'desert') {
|
if (game.tiles[game.tileOrder[target]].type === 'desert') {
|
||||||
|
game.robber = target;
|
||||||
game.pipOrder[target] = 18;
|
game.pipOrder[target] = 18;
|
||||||
} else {
|
} else {
|
||||||
game.pipOrder[target] = p++;
|
game.pipOrder[target] = p++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user