1
0

Added Velocirobber

Fixed several robber and admin related commands

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-02-26 02:57:08 -08:00
parent 1e51512ee8
commit 54e1a51c04
4 changed files with 124 additions and 72 deletions

View File

@ -43,14 +43,30 @@
transform: translate(-50%, -50%);
}
.Pip.Option {
filter: brightness(150%);
}
.Pip.Active {
filter: drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
}
.Pip.Option:hover,
.Pip:hover {
filter: brightness(100%);
}
.Pip.Active:hover {
filter: drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
}
.Pip.Active.Option {
filter: brightness(150%) drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
}
.Pips[disabled],
.Tiles[disabled],
.Roads[disabled],
@ -121,6 +137,7 @@
top: 0px;
bottom: 0px;
clip-path: circle(50%);
pointer-events: none;
}
.Tile-Shape {
@ -139,37 +156,38 @@
filter: brightness(115%);
}
.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 */
.Robber .Pip-Shape {
top: -2em;
left: -2em;
clip-path: circle(50%);
transform: scale(0.45);
background-color:#e7c099;
background-size: contain;
background-position: center;
border: 0.2em solid #8c471f;
border-radius: 50%;
}
.Roberta .Pip-Shape:hover,
.Roberta .Pip-Shape {
top: -2em;
left: -2em;
clip-path: circle(50%);
transform: scale(0.45);
background-image:url("./assets/woman-robber.png");
}
.Robert .Pip-Shape:hover,
.Robert .Pip-Shape {
top: -2em;
left: -2em;
clip-path: circle(50%);
transform: scale(0.45);
background-image:url("./assets/man-robber.png");
}
.Velocirobber .Pip-Shape {
background-image:url("./assets/raptor-robber.png");
}
.Tile-Shape:hover,
.Corner-Shape:hover,
.Road-Shape:hover {

View File

@ -481,18 +481,19 @@ const Board = ({ table, game }) => {
}
if (game) {
let robberClass = game.gender === 'female' ? 'Roberta' : 'Robert';
let nodes = document.querySelectorAll(`.Pip.Robber`);
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.remove('Robber');
nodes[i].classList.remove(robberClass);
[ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
nodes[i].classList.remove(robberName)
);
}
if (game.robber) {
if (game.robber !== undefined) {
const el = document.querySelector(`.Pip[data-index="${game.robber}"]`);
if (el) {
el.classList.add('Robber');
el.classList.add(robberClass);
el.classList.add(game.robberName);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -304,7 +304,7 @@ const distributeResources = (game, roll) => {
let index = game.pipOrder[i];
if (assetData.pips[index].roll === roll) {
if (game.robber === i) {
addChatMessage(game, null, `That pesky Robber stole resources!`);
addChatMessage(game, null, `That pesky ${game.robberName} Roberson stole resources!`);
} else {
tiles.push(i);
}
@ -350,6 +350,21 @@ const distributeResources = (game, roll) => {
}
}
const pickRobber = (game) => {
const selection = Math.floor(Math.random() * 3);
switch (selection) {
case 0:
game.robberName = 'Robert';
break;
case 1:
game.robberName = 'Roberta';
break;
case 2:
game.robberName = 'Velocirobber';
break;
}
}
const processRoll = (game, dice) => {
let session;
for (let id in game.sessions) {
@ -365,38 +380,40 @@ const processRoll = (game, dice) => {
addChatMessage(game, session, `${session.name} rolled ${game.dice[0]}, ${game.dice[1]}.`);
game.turn.roll = game.dice[0] + game.dice[1];
if (game.turn.roll === 7) {
addChatMessage(game, null, `ROBBER! ${game.gender === 'female' ? 'Roberta' : 'Robert'} Robber Roberson!`);
game.turn.robberInAction = true;
delete game.turn.placedRobber;
const mustDiscard = [];
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.`);
mustDiscard.push(player);
} 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.
*/
if (mustDiscard.length === 0) {
addChatMessage(game, null, `ROBBER! ${game.robberName} Robber Roberson has fled, and no one had to discard!`);
addChatMessage(game, null, `But drat! A new robber has arrived and must be placed by ${game.turn.name}.`);
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);
}
} else {
mustDiscard.forEach(player =>
addChatMessage(game, null, `${getPlayerName(game, player)} must discard ${player.mustDiscard} resource cards the robber steals while fleeing!`)
);
}
} else {
distributeResources(game, game.turn.roll);
}
@ -582,20 +599,22 @@ const adminActions = (game, action, value) => {
if (!session) {
return `Unable to determine current player turn to give resources.`;
}
if (type in session.player) {
if ([ 'wheat', 'sheep', 'wood', 'stone', 'brick' ].indexOf(type) !== -1) {
const count = parseInt(card);
session.player[card] += count;
session.player[type] += count;
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`);
break;
}
const index = game.developmentCards.findIndex(item =>
item.card === card && item.type === type);
item.card.toString() === card && item.type === type);
if (index === -1) {
console.log({ card, type}, game.developmentCards);
return `Unable to find ${type}-${card} in the current deck of development cards.`;
}
let tmp = game.developmentCards.splice(index, 1)[0];
tmp.turn = game.turns ? game.turns - 1 : 0;
session.player.development.push(tmp);
@ -1203,7 +1222,7 @@ const getValidRoads = (game, color) => {
return limits;
}
const isCompatibleOffer = (player, offer) => {
const isCompatibleOffer = (game, player, offer) => {
const isBank = offer.name === 'The bank';
let valid = player.gets.length === offer.gives.length &&
player.gives.length === offer.gets.length;
@ -1214,7 +1233,7 @@ const isCompatibleOffer = (player, offer) => {
}
console.log({
player: getPlayerName(player),
player: getPlayerName(game, player),
gets: player.gets,
gives: player.gives
}, {
@ -1274,11 +1293,11 @@ const isSameOffer = (player, offer) => {
return same;
};
const checkOffer = (player, offer) => {
const checkOffer = (game, player, offer) => {
let error = undefined;
console.log({
player: getPlayerName(player),
player: getPlayerName(game, player),
gets: player.gets,
gives: player.gives
}, {
@ -1476,7 +1495,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
if (value === 'offer') {
const offer = req.body;
error = checkOffer(session.player, offer);
error = checkOffer(game, session.player, offer);
if (error) {
break;
}
@ -1519,7 +1538,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
const offer = req.body;
let target;
error = checkOffer(session.player, offer);
error = checkOffer(game, session.player, offer);
if (error) {
break;
}
@ -1553,7 +1572,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
/* Verify the requesting offer wasn't jacked --\
* make sure the target.gives === player.gets and target.gives === player.gets */
if (!isCompatibleOffer(player, target)) {
if (!isCompatibleOffer(game, player, target)) {
error = `The requested offer does not match the negotiated terms!`;
break;
}
@ -1662,7 +1681,9 @@ router.put("/:id/:action/:value?", async (req, res) => {
}
game.robber = robber;
game.turn.placedRobber = true;
addChatMessage(game, session, `Robber has been moved!`);
pickRobber(game);
addChatMessage(game, session, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
let colors = [];
layout.tiles[robber].corners.forEach(cornerIndex => {
@ -1680,7 +1701,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
game.turn.actions = [];
game.turn.robberInAction = false;
delete game.turn.limits;
addChatMessage(game, session, `The Robber was moved to a terrain with no other players.`);
addChatMessage(game, session, `The dread robber ${game.robberName} was placed on a terrain with no other players, ` +
`so ${game.turn.name} does not steal resources from anyone.`);
}
break;
@ -1855,7 +1877,16 @@ router.put("/:id/:action/:value?", async (req, res) => {
game.turn.robberInAction = true;
delete game.turn.placedRobber;
addChatMessage(game, session, `${session.name} must now move the robber.`);
addChatMessage(game, session, `The robber ${game.robberName} has fled before the power of the Knight, ` +
`but a new robber has returned and ${session.name} must now place them.`);
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);
}
}
break;
@ -2323,7 +2354,29 @@ router.put("/:id/:action/:value?", async (req, res) => {
addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`);
if (player.mustDiscard) {
addChatMessage(game, null, `${session.name} must discard ${player.mustDiscard} more cards.`);
break;
}
let move = true;
for (let color in game.players) {
const discard = game.players[color].mustDiscard;
if (discard) {
move = false;
}
}
if (move) {
addChatMessage(game, null, `Drat! A new robber has arrived and must be placed by ${game.turn.name}!`);
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);
}
}
break;
case "state":
@ -2423,28 +2476,6 @@ const sendGame = async (req, res, game, error) => {
}
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 && game.turn.robberInAction) {
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 */
let session;
if (req.session) {
@ -2708,7 +2739,7 @@ router.post("/:id?", (req, res/*, next*/) => {
});
const setBeginnerGame = (game) => {
game.gender = Math.random() > 0.5 ? 'male' : 'female';
pickRobber(game);
shuffle(game.developmentCards);
game.borderOrder = [];
for (let i = 0; i < 6; i++) {
@ -2721,6 +2752,8 @@ const setBeginnerGame = (game) => {
4, 11, 7, 14,
18, 8, 15
];
game.robber = 9;
game.pipOrder = [
5, 1, 6,
7, 2, 9, 11,
@ -2732,7 +2765,7 @@ const setBeginnerGame = (game) => {
}
const shuffleBoard = (game, beginnersGame) => {
game.gender = Math.random() > 0.5 ? 'male' : 'female';
pickRobber(game);
const seq = [];
for (let i = 0; i < 6; i++) {