diff --git a/client/src/Board.css b/client/src/Board.css
index 35c75cf..335fa3b 100644
--- a/client/src/Board.css
+++ b/client/src/Board.css
@@ -40,6 +40,10 @@
filter: drop-shadow(0px 0px 5px rgba(255, 255, 0, 0.9));
}
+.Pip.Active.Option {
+ filter: brightness(150%) drop-shadow(0px 0px 5px rgba(255, 255, 0, 0.9));
+}
+
.Pips[disabled],
.Tiles[disabled],
.Roads[disabled],
@@ -71,6 +75,7 @@
bottom: 0px;
}
+.Corner:not([data-type]) .Corner-Shape,
.Corner[data-type="settlement"] .Corner-Shape {
clip-path: polygon(50% 0%,70% 15%,70% 2%,90% 2%,90% 30%,100% 40%,100% 100%,65% 100%,65% 65%,35% 65%,35% 100%,0% 100%,0% 40%);
}
@@ -128,6 +133,13 @@
filter: brightness(150%);
}
+.Option .Pip-Shape,
+.Option .Tile-Shape,
+.Option .Corner-Shape,
+.Option .Road-Shape {
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
.Robber .Pip-Shape,
.Pip-Shape:hover {
clip-path: circle(45%); /* show through the border */
@@ -140,7 +152,7 @@
.Tile-Shape:hover,
.Corner-Shape:hover,
.Road-Shape:hover {
-/* background-color: white;*/
+ background-color: white;
filter: brightness(150%);
}
diff --git a/client/src/Table.css b/client/src/Table.css
index 8873a54..d85b7af 100755
--- a/client/src/Table.css
+++ b/client/src/Table.css
@@ -12,6 +12,7 @@
display: flex;
margin-right: 40vw;
justify-content: space-between;
+ align-items: flex-end;
}
.WaitingForPlayer {
@@ -81,6 +82,60 @@
margin: 0 0.25em;
}
+.SelectPlayer {
+ display: flex;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ justify-content: center;
+ align-items: center;
+ background: rgba(0,0,0,0.5);
+ z-index: 1000;
+}
+
+.SelectPlayer .Title {
+ align-self: center;
+ padding: 2px;
+ font-weight: bold;
+}
+
+.SelectPlayer .SelectPlayerList {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ padding: 0.5em;
+ background-color:rgba(224, 224, 224);
+ margin: 0.5em 0;
+}
+
+.SelectPlayer > * {
+ width: 20em;
+ display: inline-flex;
+ padding: 0.5em;
+ flex-direction: column;
+}
+
+.SelectPlayer .PlayerColor {
+ width: 1em;
+ height: 1em;
+}
+
+.SelectPlayer .SelectPlayerItem {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ align-items: center;
+ padding: 2px 0;
+ cursor: pointer;
+}
+
+.SelectPlayer > * {
+ margin: 0 0.25em;
+}
+
+
.Display {
display: inline-block;
position: absolute;
diff --git a/client/src/Table.js b/client/src/Table.js
index 7180e97..d21d2d0 100755
--- a/client/src/Table.js
+++ b/client/src/Table.js
@@ -336,6 +336,41 @@ const GameOrder = ({table}) => {
);
};
+const SelectPlayer = ({table, players}) => {
+ const playerClick = (event) => {
+ table.stealResource(event.currentTarget.getAttribute('data-color'));
+ }
+
+ if (!table.game) {
+ return (<>>);
+ }
+
+ let list = players.map(color => {
+ let item = {
+ color: color,
+ name: getPlayerName(table.game.sessions, color)
+ };
+ return
;
+ });
+
+ return (
+
+ { table.game &&
+ Select Player to Steal From
+
+ { list }
+
+ }
+
+ );
+};
+
const Action = ({ table }) => {
const discardClick = (event) => {
const nodes = document.querySelectorAll('.Hand .Selected'),
@@ -695,6 +730,10 @@ class Table extends React.Component {
return this.sendAction('place-road', road);
}
+ stealResource(color) {
+ return this.sendAction('steal-resource', color);
+ }
+
throwDice() {
return this.rollDice();
@@ -856,7 +895,7 @@ class Table extends React.Component {
message = <>{message} {name} needs to discard {discard} resources.>;
}
}
- if (move) {
+ if (move && (this.game.turn && !this.game.turn.placedRobber)) {
message = <>{message} {this.game.turn.name} needs to move the robber.>
}
}
@@ -992,6 +1031,13 @@ class Table extends React.Component {
}
+ { game && game.state === 'normal' &&
+ game.turn &&
+ game.turn.color == game.color &&
+ game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1 &&
+
+ }
+
{ game && game.turn && game.turn.color !== game.color &&
(game.state === 'initial-placement' || game.state === 'normal') &&
(!game.player || !game.player.mustDiscard) &&
diff --git a/server/routes/games.js b/server/routes/games.js
index 78e3532..3eaaae9 100755
--- a/server/routes/games.js
+++ b/server/routes/games.js
@@ -354,6 +354,7 @@ const processRoll = (game, dice) => {
game.turn.roll = game.dice[0] + game.dice[1];
if (game.turn.roll === 7) {
addChatMessage(game, null, `ROBBER! ROBBER! ROBBER!`);
+ delete game.turn.placedRobber;
for (let id in game.sessions) {
const player = game.sessions[id].player;
if (player) {
@@ -906,7 +907,54 @@ router.put("/:id/:action/:value?", async (req, res) => {
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.');
+
+ let colors = [];
+ layout.tiles[robber].corners.forEach(cornerIndex => {
+ const active = game.placements.corners[cornerIndex];
+ if (active && active.color && active.color !== game.turn.color && colors.indexOf(active.color) == -1) {
+ colors.push(active.color);
+ }
+ });
+
+ if (colors.length) {
+ game.turn.actions = [ 'steal-resource' ],
+ game.turn.limits = { players: colors };
+ addChatMessage(game, session, `${session.name} must select player to steal resource from.`);
+ } else {
+ game.turn.actions = [];
+ delete game.turn.limits;
+ addChatMessage(game, session, `The Robber was moved to a terrain with no other players.`);
+ }
+
+ break;
+ case 'steal-resource':
+ if (game.turn.actions.indexOf('steal-resource') === -1) {
+ error = `You can only steal a resource when it is valid to do so!`;
+ break;
+ }
+ if (game.turn.limits.players.indexOf(value) === -1) {
+ error = `You can only steal a resource from a player on this terrain!`;
+ break;
+ }
+ let victim = game.players[value];
+ const cards = [];
+ [ 'wheat', 'brick', 'sheep', 'stone', 'wood' ].forEach(field => {
+ for (let i = 0; i < victim[field]; i++) {
+ cards.push(field);
+ }
+ });
+ if (cards.length === 0) {
+ addChatMessage(game, session, `Victim did not have any cards to steal.`);
+ } else {
+ let index = Math.floor(Math.random() * cards.length),
+ type = cards[index];
+ victim[type]--;
+ session.player[type]++
+ game.turn.actions = [];
+ game.turn.limits = {};
+ addChatMessage(game, session,
+ `${session.name} randomly stole ${type} from ${playerNameFromColor(game, value)}.`);
+ }
break;
case 'place-settlement':
if (game.state !== 'initial-placement' && game.state !== 'normal') {
@@ -1157,8 +1205,10 @@ const sendGame = async (req, res, game, error) => {
game.turn.limits.pips.push(i);
}
} else {
+/*
game.turn.limits = {};
game.turn.actions = [];
+*/
}
}