1
0

Lots of fixes to trading

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-03 17:48:24 -08:00
parent 3ed87d270e
commit 589187db38
3 changed files with 88 additions and 38 deletions

View File

@ -135,12 +135,7 @@
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: row; flex-direction: row;
}
.Trade .TradeLine .TradeText > div {
display: flex;
align-items: center; align-items: center;
flex-wrap: wrap;
} }
/* /*
.Trade .TradeLine > div { .Trade .TradeLine > div {

View File

@ -1,4 +1,4 @@
import React, { useState, useCallback } from "react"; import React, { useState, useCallback, useEffect } from "react";
import "./Trade.css"; import "./Trade.css";
import { getPlayerName } from './Common.js'; import { getPlayerName } from './Common.js';
import PlayerColor from './PlayerColor.js'; import PlayerColor from './PlayerColor.js';
@ -65,6 +65,19 @@ const Trade = ({table}) => {
</div>; </div>;
}, [ gives, gets, transfer, player]); }, [ gives, gets, transfer, player]);
useEffect(useCallback(() => {
if (table.game && table.game.player && table.game.player.gives) {
const _gives = {};
table.game.player.gives.forEach(give => _gives[give.type] = give.count);
setGives(Object.assign({}, empty, _gives));
}
if (table.game && table.game.player && table.game.player.gets) {
const _gets = {};
table.game.player.gets.forEach(get => _gets[get.type] = get.count);
setGets(Object.assign({}, empty, _gets));
}
}), [ setGets, setGives, table.game ]);
const agreeClicked = useCallback((offer) => { const agreeClicked = useCallback((offer) => {
const trade = { const trade = {
gives: offer.gets.slice(), gives: offer.gets.slice(),
@ -84,7 +97,7 @@ const Trade = ({table}) => {
transfers = [ 'brick', 'wood', 'wheat', 'sheep', 'stone' ].map(resource => { return createTransfer(resource); }); transfers = [ 'brick', 'wood', 'wheat', 'sheep', 'stone' ].map(resource => { return createTransfer(resource); });
if (!table.game || !player) { if (!table.game || !player || !table.game.player) {
return <></>; return <></>;
} }
@ -218,7 +231,9 @@ const Trade = ({table}) => {
trade.gives.push({ type, count: gets[type]}); trade.gives.push({ type, count: gets[type]});
} }
} }
const isOfferSubmitted = isCompatibleOffer(table.game.player, trade), const isOfferSubmitted = isCompatibleOffer(table.game.player, trade),
isNegiatorSubmitted = table.game.turn && table.game.turn.offer && isCompatibleOffer(table.game.player, table.game.turn.offer),
isOfferValid = trade.gives.length && trade.gets.length; isOfferValid = trade.gives.length && trade.gets.length;
if (isTurn && table.game.player && table.game.player.banks) { if (isTurn && table.game.player && table.game.player.banks) {
@ -244,7 +259,7 @@ const Trade = ({table}) => {
if (table.game.turn.offer) { if (table.game.turn.offer) {
if (isTurn) { if (isTurn) {
players.forEach(trade => trade.valid = isCompatibleOffer(table.game.turn.offer, trade)); players.forEach(trade => trade.valid = canMeetOffer(player, trade));
} else { } else {
const found = players.find(item => item.name === table.game.turn.name); const found = players.find(item => item.name === table.game.turn.name);
if (found) { if (found) {
@ -269,45 +284,58 @@ const Trade = ({table}) => {
youRejectedOffer = player.offerRejected; youRejectedOffer = player.offerRejected;
} }
const _gets = item.gets.length ? item.gets.map((get, index) => <div key={`get-${get.type}-${index}`}> let isNewOffer = item.self && !isOfferSubmitted;
console.log(`Trade from ${item.name} is new self: ${item.self}, new offer: ${isNewOffer}`);
let source;
if (item.self) {
/* Order direction is reversed for self */
source = {
gets: trade.gives,
gives: trade.gets
};
} else {
source = item;
}
const _gets = source.gets.length ? source.gets.map((get, index) => <div key={`get-${get.type}-${index}`}>
{ get.type === 'bank' && <div key={`get-bank-${index}`}><b>4</b> of any resource</div>} { get.type === 'bank' && <div key={`get-bank-${index}`}><b>4</b> of any resource</div>}
{ get.type !== 'bank' && <Resource key={`get-${get.type}-${index}`} disabled label type={get.type} count={get.count}/> } { get.type !== 'bank' && <Resource key={`get-${get.type}-${index}`} disabled label type={get.type} count={get.count}/> }
</div>) : undefined, </div>) : 'nothing',
_gives = item.gives.length ? item.gives.map((give, index) => <div key={`give-${give.type}-${index}`}> _gives = source.gives.length ? source.gives.map((give, index) => <div key={`give-${give.type}-${index}`}>
{ give.type === '*' && <><b>1</b> of any resource</>} { give.type === '*' && <><b>1</b> of any resource</>}
{ give.type !== '*' && <Resource disabled label type={give.type} count={give.count}/> } { give.type !== '*' && <Resource disabled label type={give.type} count={give.count}/> }
</div>) : undefined </div>) : 'nothing';
return ( return (
<div className="TradeLine" key={`player-${item.name}-${index}`}> <div className="TradeLine" key={`player-${item.name}-${index}`}>
<PlayerColor color={item.color}/> <PlayerColor color={item.color}/>
<div className="TradeText"> <div className="TradeText">
{ item.self && <div> { item.self && <>
{ youWereRejected && <>Your offer to give {_gets} in exchange for {_gives} was rejected.</> } { youWereRejected && !isNewOffer && <>Your offer was rejected.&nbsp;</> }
{ !youWereRejected && _gets && _gives && <>You want {_gets} and will give {_gives}.</> } { (!youWereRejected || isNewOffer) && (_gets !== 'nothing' || _gives !== 'nothing') && <>
{ !youWereRejected && (_gets === undefined || _gives === undefined) && <> You want {_gets} and will give {_gives}.&nbsp;
You have not submitted a trade offer. </> }
{ !youWereRejected && _gets === 'nothing' && _gives === 'nothing' && <>
You have not started a trade offer.&nbsp;
</>} </>}
</div> } </> }
{ !item.self && <> { !item.self && <>
<div> { !youRejectedOffer && _gets !== 'nothing' && _gives !== 'nothing' && <>
{ !youRejectedOffer && _gets && _gives && <> {item.name} wants {_gets} and will give {_gives}.&nbsp;
{item.name} wants {_gets} and will give {_gives}.
</> } </> }
{ (_gets === undefined || _gives === undefined) && { (_gets === 'nothing' || _gives === 'nothing') &&
<>{item.name} has not submitted a trade offer.</> <>{item.name} has not submitted a trade offer.&nbsp;</>
} }
{ youRejectedOffer && <> { youRejectedOffer && <>
You rejected {item.name}'s offer to receive {_gets} in exchange for {_gives}. You rejected {item.name}'s offer.&nbsp;
</> } </> }
</div>
{ youWereRejected && <div> { youWereRejected && <>
{item.name} rejected your offer. {item.name} rejected your offer.&nbsp;
</div>} </>}
</>} </>}
</div> </div>
@ -318,7 +346,7 @@ const Trade = ({table}) => {
} }
{ !isTurn && item.color === table.game.turn.color && { !isTurn && item.color === table.game.turn.color &&
<Button disabled={!item.valid} <Button disabled={!item.valid || isNegiatorSubmitted}
onClick={() => agreeClicked(item)}>agree</Button> onClick={() => agreeClicked(item)}>agree</Button>
} }

View File

@ -1296,6 +1296,16 @@ const getValidRoads = (game, color) => {
return limits; return limits;
} }
const canMeetOffer = (player, offer) => {
for (let i = 0; i < offer.gets.length; i++) {
const get = offer.gets[i];
if (player[get.type] < get.count) {
return false;
}
}
return true;
};
const isCompatibleOffer = (game, player, offer) => { const isCompatibleOffer = (game, player, offer) => {
const isBank = offer.name === 'The bank'; const isBank = offer.name === 'The bank';
let valid = player.gets.length === offer.gives.length && let valid = player.gets.length === offer.gives.length &&
@ -1370,9 +1380,10 @@ const isSameOffer = (player, offer) => {
/* Verifies player can make the offer */ /* Verifies player can make the offer */
const checkPlayerOffer = (game, player, offer) => { const checkPlayerOffer = (game, player, offer) => {
let error = undefined; let error = undefined;
const name = getPlayerName(game, player);
console.log({ console.log({
name: getPlayerName(game, player), name: name,
gets: offer.gets, gets: offer.gets,
gives: offer.gives, gives: offer.gives,
sheep: player.sheep, sheep: player.sheep,
@ -1393,12 +1404,12 @@ const checkPlayerOffer = (game, player, offer) => {
} }
if (player[give.type] < give.count) { if (player[give.type] < give.count) {
error = `You do not have ${give.count} ${give.type}!`; error = `${name} does do not have ${give.count} ${give.type}!`;
return; return;
} }
if (offer.gets.find(get => give.type === get.type)) { if (offer.gets.find(get => give.type === get.type)) {
error = `You can not give and get the same resource type!`; error = `${name} can not give and get the same resource type!`;
return; return;
} }
}); });
@ -1408,7 +1419,7 @@ const checkPlayerOffer = (game, player, offer) => {
return; return;
} }
if (offer.gives.find(give => get.type === give.type)) { if (offer.gives.find(give => get.type === give.type)) {
error = `You can not give and get the same resource type!`; error = `${name} can not give and get the same resource type!`;
}; };
}) })
@ -1600,7 +1611,9 @@ router.put("/:id/:action/:value?", async (req, res) => {
session.player.gives = offer.gives; session.player.gives = offer.gives;
session.player.gets = offer.gets; session.player.gets = offer.gets;
delete session.player.offerRejected; /* This offer is new for the negotiator, but don't clear the flag indicating
* if this player regected the negotiator's offer */
/* delete session.player.offerRejected; */
delete session.player.negotiatorRejectedOffer; delete session.player.negotiatorRejectedOffer;
if (game.turn.name === name) { if (game.turn.name === name) {
@ -1647,6 +1660,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
const offer = req.body; const offer = req.body;
let target; let target;
console.log(offer);
error = checkPlayerOffer(game, session.player, offer); error = checkPlayerOffer(game, session.player, offer);
if (error) { if (error) {
break; break;
@ -1671,31 +1686,43 @@ router.put("/:id/:action/:value?", async (req, res) => {
mismatch = true; mismatch = true;
} }
}); });
if (mismatch) { if (mismatch) {
error = `Unfortunately, trades were re-negotiated in transit and the deal is invalid!`; error = `Unfortunately, trades were re-negotiated in transit and the deal is invalid!`;
break; break;
} }
error = checkPlayerOffer(game, target, offer);
if (error) {
break;
}
if (!canMeetOffer(target, player)) {
error = `${playerNameFromColor(game, offer.color)} cannot meet the terms.`;
break;
}
} else { } else {
target = offer; target = offer;
} }
/* Verify the requesting offer wasn't jacked --\ /* Verify the requesting offer wasn't jacked --\
* make sure the target.gives === player.gets and target.gives === player.gets */ * make sure the target.gives === player.gets and target.gives === player.gets */
if (!isCompatibleOffer(game, player, target)) { if (!canMeetOffer(player, target)) {
error = `The requested offer does not match the negotiated terms!`; error = `You cannot meet these terms!`;
break; break;
} }
debugChat(game, 'Before trade'); debugChat(game, 'Before trade');
/* Transfer goods */ /* Transfer goods */
player.gets.forEach(item => { target.gives.forEach(item => {
if (target.name !== 'The bank') { if (target.name !== 'The bank') {
target[item.type] -= item.count; target[item.type] -= item.count;
} }
player[item.type] += item.count; player[item.type] += item.count;
}); });
player.gives.forEach(item => { target.gets.forEach(item => {
if (target.name !== 'The bank') { if (target.name !== 'The bank') {
target[item.type] += item.count; target[item.type] += item.count;
} }