Visual card trading.

master
Thomas Hintz 5 years ago
parent c34fc7dcbe
commit bea133bee4

@ -32,9 +32,9 @@ import ReactDOM from 'react-dom'
import { connect } from 'react-redux'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faUser, faUsers, faTractor, faWindowRestore,
faDollarSign, faTimes, faAsterisk, faExchangeAlt,
faDollarSign, faTimes, faExchangeAlt,
faInfoCircle, faArrowUp, faArrowDown, faAward,
faTimesCircle, faBan } from '@fortawesome/free-solid-svg-icons'
faBan, faArrowCircleLeft } from '@fortawesome/free-solid-svg-icons'
import { GroupBox, Row, Col, Button } from '../widgets.jsx'
import SpaceNode from './SpaceNode.jsx'
@ -48,7 +48,7 @@ import { setSelectedCard, setMessagePanelSpace, setMPDims, movePlayer,
import { buy, roll, endTurn, loan, trade, submitTradeAccept,
submitTradeDeny, submitTradeCancel, audit,
buyUncleBert, skip, endAiTurn, startGame, readyToStart,
leaveGame, kickPlayer } from './interface.js'
leaveGame, kickPlayer, toggleRevealForTrade } from './interface.js'
function netWorth(player) {
return ((player.assets.hay + player.assets.grain) * 2000) +
@ -65,116 +65,6 @@ function assetsValue(player) {
((player.assets.harvester + player.assets.tractor) * 10000);
}
function getElementValue(id) {
return document.getElementById(id).value;
}
function getString(id) {
return getElementValue(id);
}
function getInt(id) {
const i = parseInt(getElementValue(id));
return isNaN(i) ? 0 : i;
}
function getChecked(id) {
return document.getElementById(id).checked;
}
function getOption(id) {
let options = document.getElementById(id).selectedOptions;
if (options.length > 0) {
return options[0].value;
} else {
return false;
}
}
function submitTrade() {
trade({ hay: getInt('trade-hay'), grain: getInt('trade-grain'),
fruit: getInt('trade-fruit'), cows: getInt('trade-cows'),
harvester: getInt('trade-harvesters'),
tractor: getInt('trade-tractors'),
ridge1: getChecked('trade-ridge1'),
ridge2: getChecked('trade-ridge2'),
ridge3: getChecked('trade-ridge3'),
ridge4: getChecked('trade-ridge4'),
player: getOption('trade-player'),
money: getInt('trade-money'), cards: getString('trade-cards') });
}
function tradeString(player, invert) {
var r = '';
let mult = invert ? -1 : 1;
for (var k in player.trade) {
if (k !== 'player' && k !== 'originator' && k !== 'cards' && k !== 'trade-number') {
r += (player.trade[k] === true ? '' : player.trade[k] * mult) + ' ' + k + ', ';
} else if (k === 'cards') {
r += 'cards: ' + player.trade[k] + ', ';
}
}
return r.slice(0, -2); // remove last ", "
}
class PlayerTradeProposed extends React.Component {
render () {
if (this.props.player.trade.error) {
return (<p><b>ERROR:</b> {this.props.player.trade.error}</p>);
} else if (this.props.player.trade.player === undefined) {
return (<p>You GAIN something if it is POSITIVE and you GIVE something if it is NEGATIVE.</p>);
} else if (this.props.player.trade.originator === this.props.player.name) {
return (<p>You proposed a trade with <b>{this.props.player.trade.player}</b> for
{'\u00A0'}<b>{tradeString(this.props.player, false)}</b>.</p>);
} else {
return (<p><b>{this.props.player.trade.originator}</b> proposed a trade for
{'\u00A0'}<b>{tradeString(this.props.player, true)}</b>.</p>);
}
}
}
function tradeFormSubmit(e, player) {
e.preventDefault();
if (player.trade.player === undefined) {
submitTrade();
} else if (player.trade.originator === player.name) {
submitTradeCancel();
} else {
submitTradeAccept();
}
return false;
}
class PlayerTradeButton extends React.Component {
tradeDeny = e => {
e.preventDefault();
submitTradeDeny();
}
render() {
var text = '';
var receiver = false;
if (this.props.player.trade.player === undefined) {
text = 'Propose';
} else if (this.props.player.trade.originator === this.props.player.name) {
text = 'Cancel';
} else {
text = 'Accept';
receiver = true;
}
if (!receiver) {
return (<Button className='tiny' type='submit'>{text} Trade</Button>);
} else {
return (<Fragment>
<Button className='tiny' type='submit'>{text} Trade</Button>
<Button className='tiny' onClick={this.tradeDeny}>
Deny Trade
</Button>
</Fragment>);
}
}
}
class ResourceUnit extends React.Component {
render () {
const hslString = 'hsl(' + this.props.h + ', ' + this.props.s;
@ -197,61 +87,6 @@ class ResourceUnit extends React.Component {
}
}
class PlayerTradeResources extends React.Component {
render () {
let player = this.props.player;
return (
<form onSubmit={e => tradeFormSubmit(e, player)}>
<div className='player-trade-resources'>
<ResourceUnit img={HayImg} h='120' s='100' label='acres of Hay' amount={''}>
<input type='number' id='trade-hay' defaultValue='0' />
</ResourceUnit> {' '}
<ResourceUnit img={WheatImg} h='41' s='100' label='acres of Grain' amount={''}>
<input type='number' id='trade-grain' defaultValue='0' />
</ResourceUnit> {' '}
<ResourceUnit img={FruitImg} h='0' s='100' label='acres of Fruit' amount={''}>
<input type='number' id='trade-fruit' defaultValue='0' />
</ResourceUnit> {' '}
<ResourceUnit img={CowImg} h='0' s='59' label='head of Cows' amount={''}>
<input type='number' id='trade-cows' defaultValue='0' />
</ResourceUnit> {' '}
<ResourceUnit img={HarvesterImg} h='240' s='100' label='Harvesters' amount={''}>
<input type='number' id='trade-harvesters' defaultValue='0' />
</ResourceUnit> {' '}
<ResourceUnit img={TractorImg} h='240' s='100' label='Tractors' amount={''}>
<input type='number' id='trade-tractors' defaultValue='0' />
</ResourceUnit>
<br />
<b>Ridges</b>: <b>{ridgeNames[0][0]}</b>: <input type='checkbox' id='trade-ridge1' />{'\u00A0'}
<b>R</b>: <input type='checkbox' id='trade-ridge2' />{'\u00A0'}
<b>C</b>: <input type='checkbox' id='trade-ridge3' />{'\u00A0'}
<b>T</b>: <input type='checkbox' id='trade-ridge4' />{'\u00A0'}
<br /><br />
<Row>
<Col width='4 column-no-padding'>
<label htmlFor='trade-player'><b>Player</b>:</label>
<select id='trade-player'>
{this.props.otherPlayers.map(p => (
<option key={p.player.name} value={p.player.name}>{p.player.name}</option>
))}
</select>
</Col>
<Col width='4 column-no-padding'>
<label htmlFor='trade-money'><b>Money</b>: </label>
<input type='number' id='trade-money' defaultValue='0' />
</Col>
<Col width='4 column-no-padding'>
<label htmlFor='trade-cards'><b>Cards</b>: </label>
<input type='text' id='trade-cards' placeholder="12 46" />
</Col>
</Row>
<PlayerTradeProposed player={this.props.player} />
<PlayerTradeButton player={this.props.player} />
</div>
</form>);
}
}
class PlayerResources extends React.Component {
render () {
const player = this.props.player;
@ -495,13 +330,75 @@ class FarmsContainer extends React.Component {
}
}
class TradeContainer extends React.Component {
class TradeCard extends React.Component {
render () {
const card = this.props.card;
let action = (null);
if (card.type === 'no-card') {
action = (<span></span>);
} else {
action = (
<div className='card-action'>
<Row>
<Col width="12">
<Button onClick={() => this.props.tradeCard(card)}>Trade Card</Button>
</Col>
</Row>
</div>
);
}
return (
<div className='game-card'>
<GroupBox title={card.title}>
<div className='card'
dangerouslySetInnerHTML={{__html: card.contents}} />
{action}
</GroupBox>
</div>
);
}
}
const makeEmptyCard = () => { return { type: 'no-card', contents: '', total: 0, id: -1 }; }
class TradeCards extends React.Component {
state = {
selectedCard: makeEmptyCard()
}
componentDidMount() {
if (this.props.player.cards.length > 0) {
this.setState({ selectedCard: this.props.player.cards[0] });
}
}
render() {
const { player, cardsBeingTraded } = this.props;
const isMe = this.props.me.name === player.name;
return (
<GroupBox title='Trade'>
<PlayerTradeResources otherPlayers={this.props.game.otherPlayers}
player={this.props.player} />
</GroupBox>
<>
<CardListComp ui={player}
title={(
<>
<a onClick={this.props.goBack}>
<FontAwesomeIcon icon={faArrowCircleLeft} />
</a>
{isMe ? (
<>Your Cards</>
) : (
<>{player.name}'s Cards</>
)}
</>
)}
visibleCards={isMe ? player.cards.filter(c => !cardsBeingTraded.includes(c.id)).map(c => c.id) :
player.revealedCards.filter(c => !cardsBeingTraded.includes(c))}
cardId={this.state.selectedCard.id}
setCard={(c) => this.setState({ selectedCard: c })}
setCardError={() => 'nothing'}
/>
<TradeCard card={this.state.selectedCard}
tradeCard={this.props.tradeCard} />
</>
);
}
}
@ -531,7 +428,16 @@ const makeDefaultToTrade = () => {
};
}
class TradeContainer2 extends React.Component {
/* <Row>
* <Col width="12">
* <input type="text" placeholder="Cards"
* defaultValue={toTrade.cards}
* onChange={e => this.tradeAsset('cards', e.target.value)} />
* </Col>
* </Row> */
class TradeContainer extends React.Component {
resources = [{ img: HayImg,
h: '120',
s: '100',
@ -584,11 +490,16 @@ class TradeContainer2 extends React.Component {
state = {
otherPlayer: findPlayer(this.props.game, this.props.game.otherPlayers.length > 0 ? this.props.game.otherPlayers[0].player.name : ''),
toTrade: makeDefaultToTrade()
toTrade: makeDefaultToTrade(),
showCards: false,
showCardsPlayer: false,
sendCards: [],
receiveCards: []
}
selectPlayer = e => {
this.setState({ otherPlayer: findPlayer(this.props.game, e.target.value) });
this.setState({ otherPlayer: findPlayer(this.props.game, e.target.value),
receiveCards: [] });
}
componentDidUpdate(prevProps) {
@ -596,8 +507,10 @@ class TradeContainer2 extends React.Component {
prevProps.game.otherPlayers.length !== this.props.game.otherPlayers.length) {
this.setState({ otherPlayer: findPlayer(this.props.game,
this.props.game.otherPlayers.length > 0 ? this.props.game.otherPlayers[0].player.name : '') });
} else if (this.state.otherPlayer && this.state.otherPlayer.name !== findPlayer(this.props.game, this.state.otherPlayer.name).name) {
this.setState({ otherPlayer: findPlayer(this.props.game, this.state.otherPlayer.name) });
} else if (this.state.otherPlayer && this.state.otherPlayer !== findPlayer(this.props.game, this.state.otherPlayer.name)) {
this.setState({ otherPlayer: findPlayer(this.props.game, this.state.otherPlayer.name),
receiveCards: [],
sendCards: [] });
}
if (prevProps.player.trade.originator && !this.props.player.trade.originator) {
this.setState({ otherPlayer: findPlayer(this.props.game,
@ -624,14 +537,22 @@ class TradeContainer2 extends React.Component {
} else {
tradeObj = this.props.player.trade;
}
const cards = tradeObj.cards.split(' ').map(i => parseInt(i)),
myCards = this.props.player.cards.filter(c => cards.includes(c.id)),
myCardsIds = myCards.map(c => c.id);
console.log(cards);
console.log(myCards)
const otherPlayer = findPlayer(this.props.game, isOriginator ?
this.props.player.trade.player : this.props.player.trade.originator);
this.setState({
toTrade: {
...makeDefaultToTrade(),
...tradeObj,
money: tradeObj.money ? tradeObj.money / 1000 : 0
},
otherPlayer: findPlayer(this.props.game, isOriginator ?
this.props.player.trade.player : this.props.player.trade.originator)
receiveCards: otherPlayer.cards.filter(c => cards.includes(c.id) && !myCardsIds.includes(c.id)),
sendCards: myCards,
otherPlayer
});
}
}
@ -659,11 +580,35 @@ class TradeContainer2 extends React.Component {
propose = () => {
trade({ ...this.state.toTrade,
cards: this.state.sendCards.map(c => c.id).concat(this.state.receiveCards.map(c => c.id)).join(' '),
money: this.state.toTrade.money * 1000,
player: this.state.otherPlayer.name
})
}
viewPlayerCards = (e, player) => {
e.preventDefault();
this.setState(state => {
return { showCards: !state.showCards,
showCardsPlayer: player };
});
}
tradeCard = (card) => {
if (this.props.player === this.state.showCardsPlayer) {
this.setState({ sendCards: [...this.state.sendCards, card],
showCards: false });
} else {
this.setState({ receiveCards: [...this.state.receiveCards, card],
showCards: false });
}
}
unTradeCard = (id) => {
this.setState({ sendCards: this.state.sendCards.filter(c => c.id !== id),
receiveCards: this.state.receiveCards.filter(c => c.id !== id) });
}
render() {
const player = this.props.player,
otherPlayer = this.state.otherPlayer,
@ -671,59 +616,78 @@ class TradeContainer2 extends React.Component {
tradeProposed = !!player.trade.originator;
return (
<GroupBox title='Trade'>
<Row>
<Col width="12">
<div className="trade-player-container">
<h4>{player.name}</h4>
{Object.keys(player.ridges).map((ridge, idx) => (
<Fragment key={'player-trade' + ridge}>
{!tradeProposed && (player.ridges[ridge] > 0) && !toTrade[ridge] ? (
<Button className="tiny"
onClick={() => this.tradeAsset(ridge, player.ridges[ridge], true)}>
<FontAwesomeIcon icon={faArrowDown} /> {ridgeNames[idx]} {'('}{player.ridges[ridge]} cows{')'}
</Button>
) : (<></>)}
{' '}
</Fragment>
))}
<div className='resource-unit-container'>
{this.resources.map((o, i) => {
let amount = o.key === 'money' ? Math.floor(player.cash / 1000) : player.assets[o.key];
if (o.key === 'cows') { amount = player.assets.cows - playerRidgeCows(player); }
return (
<ResourceUnit img={o.img ? o.img : false} h={o.h} s={o.s} label={o.label}
key={i}
className={o.key === 'money' ? 'double-width' : false}
amount={amount + Math.min(0, toTrade[o.key])}
>
{o.icon ? (
<>
<FontAwesomeIcon icon={o.icon} />(K)
<br />
</>
) : ''}
{amount + Math.min(0, toTrade[o.key])}
{o.icon ? (<br />) : ''}
{!tradeProposed && ((amount + Math.min(0, toTrade[o.key])) > 0 || toTrade[o.key] > 0) ? (
<>
<Button className="tiny"
onClick={() => this.tradeAsset(o.key, o.amount * -1)}>
<FontAwesomeIcon icon={faArrowDown} />
</Button>
{o.key === 'money' && (amount + Math.min(0, toTrade[o.key])) >= 10 ? (
<Button className="tiny"
onClick={() => this.tradeAsset(o.key, o.amount * -10)}>
<FontAwesomeIcon icon={faArrowDown} />
<FontAwesomeIcon icon={faArrowDown} />
</Button>
) : ''}
</>
) : (<></>)}
</ResourceUnit>
);
})}
</div>
</div>
{this.state.showCards ? (
<TradeCards player={this.state.showCardsPlayer}
me={player}
tradeCard={this.tradeCard}
goBack={this.viewPlayerCards}
cardsBeingTraded={this.state.sendCards.map(c => c.id).concat(this.state.receiveCards.map(c => c.id))}
/>
) : (
<>
<Row>
<Col width="12">
<div className="trade-player-container">
<h4>
{player.name}
{player.cards.length > 0 ? (
<>
{' - '}
<a onClick={e => this.viewPlayerCards(e, player)}>
<FontAwesomeIcon icon={faWindowRestore} /> Trade Cards
</a>
</>
) : (<></>)}
</h4>
{Object.keys(player.ridges).map((ridge, idx) => (
<Fragment key={'player-trade' + ridge}>
{!tradeProposed && (player.ridges[ridge] > 0) && !toTrade[ridge] ? (
<Button className="tiny"
onClick={() => this.tradeAsset(ridge, player.ridges[ridge], true)}>
<FontAwesomeIcon icon={faArrowDown} /> {ridgeNames[idx]} {'('}{player.ridges[ridge]} cows{')'}
</Button>
) : (<></>)}
{' '}
</Fragment>
))}
<div className='resource-unit-container'>
{this.resources.map((o, i) => {
let amount = o.key === 'money' ? Math.floor(player.cash / 1000) : player.assets[o.key];
if (o.key === 'cows') { amount = player.assets.cows - playerRidgeCows(player); }
return (
<ResourceUnit img={o.img ? o.img : false} h={o.h} s={o.s} label={o.label}
key={i}
className={o.key === 'money' ? 'double-width' : false}
amount={amount + Math.min(0, toTrade[o.key])}
>
{o.icon ? (
<>
<FontAwesomeIcon icon={o.icon} />(K)
<br />
</>
) : ''}
{amount + Math.min(0, toTrade[o.key])}
{o.icon ? (<br />) : ''}
{!tradeProposed && ((amount + Math.min(0, toTrade[o.key])) > 0 || toTrade[o.key] > 0) ? (
<>
<Button className="tiny"
onClick={() => this.tradeAsset(o.key, o.amount * -1)}>
<FontAwesomeIcon icon={faArrowDown} />
</Button>
{o.key === 'money' && (amount + Math.min(0, toTrade[o.key])) >= 10 ? (
<Button className="tiny"
onClick={() => this.tradeAsset(o.key, o.amount * -10)}>
<FontAwesomeIcon icon={faArrowDown} />
<FontAwesomeIcon icon={faArrowDown} />
</Button>
) : ''}
</>
) : (<></>)}
</ResourceUnit>
);
})}
</div>
</div>
</Col>
</Row>
<Row>
@ -739,6 +703,13 @@ class TradeContainer2 extends React.Component {
{' '}
</Fragment>
))}
{this.state.receiveCards.map((card, idx) => (
<Button className="tiny"
key={idx}
onClick={() => this.unTradeCard(card.id)}>
{card.summary}
</Button>
))}
</Col>
</Row>
<Row>
@ -769,6 +740,13 @@ class TradeContainer2 extends React.Component {
{' '}
</Fragment>
))}
{this.state.sendCards.map((card, idx) => (
<Button className="tiny"
key={idx}
onClick={() => this.unTradeCard(card.id)}>
{card.summary}
</Button>
))}
</Col>
</Row>
<Row>
@ -825,24 +803,21 @@ class TradeContainer2 extends React.Component {
</Fragment>
))}
<select onChange={this.selectPlayer}
value={otherPlayer.name}
defaultValue={otherPlayer.name}>
value={otherPlayer.name}>
{this.props.game.otherPlayers.map(p => (
<option key={p.player.name} value={p.player.name}>
{p.player.name}
</option>
))}
</select>
{otherPlayer && otherPlayer.revealedCards.length > 0 ? (
<a onClick={e => this.viewPlayerCards(e, otherPlayer)}>
<FontAwesomeIcon icon={faWindowRestore} /> Trade Cards
</a>
) : (<></>)}
</div>
</Col>
</Row>
<Row>
<Col width="12">
<input type="text" placeholder="Cards"
defaultValue={toTrade.cards}
onChange={e => this.tradeAsset('cards', e.target.value)} />
</Col>
</Row>
<Row>
<Col width="12">
{player.trade.error ? (
@ -862,6 +837,7 @@ class TradeContainer2 extends React.Component {
) : (<></>)}
</Col>
</Row>
</>)}
</GroupBox>
);
}
@ -1988,7 +1964,7 @@ const SCREENS = { summary: 'summary', misc: 'misc', farms: 'farms',
class BoardApp extends React.Component {
iconToScreen = { user: SCREENS.summary, 'window-restore': SCREENS.cards,
'dollar-sign': SCREENS.loans, users: SCREENS.farms,
'exchange-alt': SCREENS.trade, asterisk: SCREENS.misc,
'exchange-alt': SCREENS.trade,
tractor: SCREENS.action, 'info-circle': SCREENS.info }
unsubscribeAlert = () => null
@ -2293,6 +2269,7 @@ class BoardApp extends React.Component {
setCardError={this.props.setCardError}
playerCash={this.props.player.displayCash}
playerDebt={this.props.player.debt}
revealedCards={this.props.player.revealedCards}
card={this.state.card}
cost={this.state.card.total / 1000}
min={(this.state.card.total * this.props.game.settings.downPayment) / 1000}
@ -2310,7 +2287,7 @@ class BoardApp extends React.Component {
otherPlayers={this.props.game.otherPlayers} />
</div>
<div className={this.tabClass(SCREENS.trade) + ' trade-tab'}>
<TradeContainer2 player={this.props.player} game={this.props.game} />
<TradeContainer player={this.props.player} game={this.props.game} />
</div>
<div className={this.tabClass(SCREENS.misc)}>
<Misc />
@ -2419,7 +2396,11 @@ class Card extends React.Component {
) : (<></>)}
<Row collapse='true'>
<Col width="12">
<label className="small-text"><input type="checkbox" /> Reveal for trading</label>
<label className="small-text">
<input type="checkbox"
onChange={() => toggleRevealForTrade(card.id)}
checked={this.props.revealedCards.includes(card.id)} /> Reveal for trading
</label>
</Col>
</Row>
@ -2451,7 +2432,7 @@ class CardListComp extends React.Component {
case 'fruit': return '5 acres Fruit';
case 'grain': return '10 acres Grain'}};
const ui = this.props.ui,
cards = ui.cards,
cards = ui.cards.filter(this.props.visibleCards ? (c) => this.props.visibleCards.includes(c.id) : (c) => c),
cardOps = cards.map((c, i) =>
(<li key={i} className={c.id == this.props.cardId ? 'card-select-selected' : ''}
onClick={() => { this.props.setCard(c); this.props.setCardError(false); }}>
@ -2459,7 +2440,7 @@ class CardListComp extends React.Component {
</li>));
return (
<GroupBox title='Cards'>
<GroupBox title={this.props.title ? this.props.title : 'Cards'}>
<ul className='card-select'>
{cardOps}
</ul>

@ -31,7 +31,7 @@ import { itemCard, fateCard } from 'game.js'
export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept,
submitTradeDeny, submitTradeCancel, audit, handleMessage,
nextAction, buyUncleBert, actionsFinished, skip, endAiTurn,
startGame, readyToStart, leaveGame, kickPlayer }
startGame, readyToStart, leaveGame, kickPlayer, toggleRevealForTrade }
let store;
let movingTimer = 0;
@ -217,6 +217,10 @@ function kickPlayer(name) {
sendCommand({ type: 'kick-player', name });
}
function toggleRevealForTrade(id) {
sendCommand({ type: 'toggle-reveal-for-trading', id });
}
// TODO share with Board.jsx
// http://stackoverflow.com/questions/149055
function formatMoney(n) {

@ -91,6 +91,8 @@ const initialState = {
assets: { hay: 10, grain: 10, fruit: 0, cows: 0, harvester: 0, tractor: 0, birthday: 0 },
color: '',
name: '',
cards: [],
revealedCards: [],
ridges: { ridge1: 0, ridge2: 0, ridge3: 0, ridge4: 0 },
space: 0,
hayDoubled: false,

@ -86,7 +86,7 @@ class JoinGame extends React.Component {
return (
<GroupBox title={(
<Fragment>
<a href="#" onClick={this.handleBack}>
<a onClick={this.handleBack}>
<FontAwesomeIcon icon={faArrowCircleLeft} />
</a>
Join Game

@ -115,6 +115,7 @@
(harvest-mult initform: 1 accessor: player-harvest-mult)
(otbs initform: '() accessor: player-otbs)
(farmers-fates initform: '() accessor: player-farmers-fates)
(revealed-cards initform: '() accessor: player-revealed-cards)
(year-rules initform: '() accessor: player-year-rules)
(next-year-rules initform: '() accessor: player-next-year-rules)
(color initform: #f accessor: player-color)
@ -182,7 +183,8 @@
(harvest-mult . ,(player-harvest-mult player))
(otbs . ,(player-otbs player))
(farmers-fates . ,(map (cut alist-ref 'id <>) (player-farmers-fates player)))
(year-rules . ,(player-year-rules player)) ;; TODO check if all are serializable
(revealed-cards . ,(player-revealed-cards player))
(year-rules . ,(player-year-rules player))
(next-year-rules . ,(player-next-year-rules player))
(color . ,(player-color player))
(name . ,(player-name player))
@ -306,18 +308,21 @@
(set! *app* (sexp->app (read))))))
(define (sexp->player x)
(apply make <player>
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
(list-copy
(filter (lambda (card)
(member (alist-ref 'id card) ffs))
*farmers-fates-cards*)))
(fold (lambda (k r) (cons k (cons (alist-ref k x) r)))
'()
'(cash debt space previous-space state assets ridges
harvest-mult otbs user-id
year-rules next-year-rules hay-doubled corn-doubled
color name trade last-updated last-cash))))
(let ((p (apply make <player>
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
(list-copy
(filter (lambda (card)
(member (alist-ref 'id card) ffs))
*farmers-fates-cards*)))
(fold (lambda (k r) (cons k (cons (alist-ref k x) r)))
'()
'(cash debt space previous-space state assets ridges
harvest-mult otbs user-id revealed-cards
year-rules next-year-rules hay-doubled corn-doubled
color name trade last-updated last-cash)))))
(when (not (player-revealed-cards p))
(safe-set! (player-revealed-cards p) '()))
p))
(define (shuffle l)
(map cdr
@ -521,6 +526,7 @@
(state . ,(symbol->string (player-state p)))
(cards . ,(list->vector (append (player-farmers-fates p)
(player-otbs p))))
(revealedCards . ,(list->vector (player-revealed-cards p)))
(color . ,(symbol->string (player-color p)))
(name . ,(player-name p))
(user-id . ,(player-user-id p))
@ -1334,6 +1340,16 @@
(message-players! game player '() type: "update"))
(create-ws-response player "update" '()))
(begin (create-ws-response player "update" '()))))
((string=? type "toggle-reveal-for-trading")
(let ((id (alist-ref 'id msg)))
(if (member id (player-revealed-cards player))
(safe-set! (player-revealed-cards player)
(filter (lambda (cid) (not (eqv? cid id)))
(player-revealed-cards player)))
(safe-set! (player-revealed-cards player)
(cons id (player-revealed-cards player)))))
(message-players! game player '() type: "update")
(create-ws-response player "update" '()))
;;;;;;;;;;;;;;;;;;;;; start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((string=? type "main-init")
(create-start-response "start-init"))
@ -2384,3 +2400,4 @@
;; TODO
;; make sure two players can't have the same name
;; "your turn to roll" showing up on mobile when on action screen
;; trade cards better

Loading…
Cancel
Save