Show IFS card buying errors and allow buying with emergency loan.

logins
Thomas Hintz 5 years ago
parent 89e67b3150
commit 93cc806eb2

@ -40,7 +40,7 @@ import Tractor from '../tractor/Tractor.jsx'
import { GAME_STATES, ALERTS } from '../../constants.js' import { GAME_STATES, ALERTS } from '../../constants.js'
import { itemCard, itemCardShort, fateCard, ridgeNames } from 'game.js' import { itemCard, itemCardShort, fateCard, ridgeNames } from 'game.js'
import { setSelectedCard, setMessagePanelSpace, setMPDims, movePlayer, import { setSelectedCard, setMessagePanelSpace, setMPDims, movePlayer,
nextUIAction, alert, alertHandled } from './actions.js' nextUIAction, alert, alertHandled, setCardError } from './actions.js'
import { buy, roll, endTurn, loan, trade, submitTradeAccept, import { buy, roll, endTurn, loan, trade, submitTradeAccept,
submitTradeDeny, submitTradeCancel, audit, submitTradeDeny, submitTradeCancel, audit,
buyUncleBert, skip } from './interface.js' buyUncleBert, skip } from './interface.js'
@ -1673,20 +1673,23 @@ class BoardApp extends React.Component {
</div> </div>
<div className={this.tabClass(SCREENS.cards)}> <div className={this.tabClass(SCREENS.cards)}>
<Row> <Row>
<div className='cell medium-auto'> <Col width="12">
<CardList ui={this.props.ui} cardId={this.state.card.id} <div>
setCard={this.setCard} /> <CardList ui={this.props.ui} cardId={this.state.card.id}
</div> setCard={this.setCard} />
<div className='cell medium-auto'> </div>
<Card ui={this.props.ui} <div>
playerCash={this.props.player.cash} <Card ui={this.props.ui}
playerDebt={this.props.player.debt} setCardError={this.props.setCardError}
card={this.state.card} playerCash={this.props.player.cash}
cost={this.state.card.total / 1000} playerDebt={this.props.player.debt}
min={(this.state.card.total * this.props.game.settings.downPayment) / 1000} card={this.state.card}
max={Math.floor(Math.min(this.props.player.cash / 1000, this.state.card.total / 1000))} cost={this.state.card.total / 1000}
cash={(this.state.card.total * this.props.game.settings.downPayment) / 1000} /> min={(this.state.card.total * this.props.game.settings.downPayment) / 1000}
</div> max={Math.floor(Math.min(this.props.player.cash / 1000, this.state.card.total / 1000))}
cash={(this.state.card.total * this.props.game.settings.downPayment) / 1000} />
</div>
</Col>
</Row> </Row>
</div> </div>
<div className={this.tabClass(SCREENS.loans)}> <div className={this.tabClass(SCREENS.loans)}>
@ -1730,7 +1733,7 @@ class BoardApp extends React.Component {
export default connect( export default connect(
state => state.farm, state => state.farm,
{ setMessagePanelSpace, setMPDims, nextUIAction, movePlayer, alert, alertHandled } { setMessagePanelSpace, setMPDims, nextUIAction, movePlayer, alert, alertHandled, setCardError }
)(BoardApp) )(BoardApp)
class Card extends React.Component { class Card extends React.Component {
@ -1755,6 +1758,7 @@ class Card extends React.Component {
parseInt(target.value)), this.props.max); parseInt(target.value)), this.props.max);
if (isNaN(value)) { value = this.props.min; } if (isNaN(value)) { value = this.props.min; }
this.setState({ cash: value }); this.setState({ cash: value });
this.props.setCardError(false);
} }
handleSubmit = e => { handleSubmit = e => {
@ -1799,6 +1803,13 @@ class Card extends React.Component {
</div> </div>
</Col> </Col>
</Row> </Row>
{this.props.ui.cardError ? (
<Row>
<Col width="12">
<span className="error">{this.props.ui.cardError}</span>
</Col>
</Row>
) : (<></>)}
</form> </form>
</div>); break; </div>); break;
@ -1831,9 +1842,9 @@ class CardListComp extends React.Component {
cards = ui.cards, cards = ui.cards,
cardOps = cards.map((c, i) => cardOps = cards.map((c, i) =>
(<li key={i} className={c.id == this.props.cardId ? 'card-select-selected' : ''} (<li key={i} className={c.id == this.props.cardId ? 'card-select-selected' : ''}
onClick={() => this.props.setCard(c)}> onClick={() => { this.props.setCard(c); this.props.setCardError(false); }}>
{c.summary} {c.summary}
</li>)); </li>));
return ( return (
<GroupBox title='Cards'> <GroupBox title='Cards'>
@ -1847,5 +1858,5 @@ class CardListComp extends React.Component {
const CardList = connect( const CardList = connect(
null, null,
{ setSelectedCard } { setSelectedCard, setCardError }
)(CardListComp) )(CardListComp)

@ -21,6 +21,7 @@ export const UPDATE_PLAYER = 'update-player';
export const GAME_STATE = 'game-state'; export const GAME_STATE = 'game-state';
export const SET_SELECTED_CARD = 'set-selected-card'; export const SET_SELECTED_CARD = 'set-selected-card';
export const SET_CARDS = 'set-cards'; export const SET_CARDS = 'set-cards';
export const SET_CARD_ERROR = 'set-card-error';
export const SPACE_PUSH_PLAYER = 'space-push-player'; export const SPACE_PUSH_PLAYER = 'space-push-player';
export const SPACE_CLEAR_PLAYERS = 'space-clear-players'; export const SPACE_CLEAR_PLAYERS = 'space-clear-players';
export const SET_OLD_MESSAGES = 'set-old-messages'; export const SET_OLD_MESSAGES = 'set-old-messages';

@ -20,13 +20,13 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
SPACE_PUSH_PLAYER, SPACE_CLEAR_PLAYERS, SET_OLD_MESSAGES, MESSAGE_PANEL_SPACE, SPACE_PUSH_PLAYER, SPACE_CLEAR_PLAYERS, SET_OLD_MESSAGES, MESSAGE_PANEL_SPACE,
MP_MOUSE, SET_MP_DIMS, MARK_ACTION_CHANGE_HANDLED, SET_NEXT_ACTION, MP_MOUSE, SET_MP_DIMS, MARK_ACTION_CHANGE_HANDLED, SET_NEXT_ACTION,
MOVE_PLAYER, NEXT_UI_ACTION, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED, MOVE_PLAYER, NEXT_UI_ACTION, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE } from './actionTypes.js' AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR } from './actionTypes.js'
export { updateGame, updatePlayer, gameState, setSelectedCard, setCards, export { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
spacePushPlayer, spaceClearPlayers, setOldMessages, setMessagePanelSpace, spacePushPlayer, spaceClearPlayers, setOldMessages, setMessagePanelSpace,
mpMouse, setMPDims, movePlayer, setNextAction, nextUIAction, mpMouse, setMPDims, movePlayer, setNextAction, nextUIAction,
markActionChangeHandled, nextUIActionSilent, alert, alertHandled, markActionChangeHandled, nextUIActionSilent, alert, alertHandled,
autoSkip, message, setHarvestTable } autoSkip, message, setHarvestTable, setCardError }
function updateGame(update) { function updateGame(update) {
return { type: UPDATE_GAME, return { type: UPDATE_GAME,
@ -54,6 +54,10 @@ function setCards(cards) {
cards }; cards };
} }
function setCardError(error) {
return { type: SET_CARD_ERROR, error };
}
function spacePushPlayer(id, player) { function spacePushPlayer(id, player) {
return { type: SPACE_PUSH_PLAYER, return { type: SPACE_PUSH_PLAYER,
id, id,

@ -24,7 +24,7 @@ import * as websocket from '../../websocket.js'
import { updateGame, updatePlayer, gameState, setSelectedCard, setCards, import { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
movePlayer, setOldMessages, markActionChangeHandled, movePlayer, setOldMessages, markActionChangeHandled,
mpMouse, rolled, setNextAction, nextUIAction, nextUIActionSilent, alert, mpMouse, rolled, setNextAction, nextUIAction, nextUIActionSilent, alert,
autoSkip, message, alertHandled, setHarvestTable } from './actions.js' autoSkip, message, alertHandled, setHarvestTable, setCardError } from './actions.js'
import { itemCard, fateCard } from 'game.js' import { itemCard, fateCard } from 'game.js'
export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept, export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept,
@ -63,6 +63,9 @@ function handleMessage(evt) {
store.dispatch(setNextAction(false, false)); store.dispatch(setNextAction(false, false));
store.dispatch(nextUIAction()); store.dispatch(nextUIAction());
} }
if (data.event === 'buy' && data.error) {
store.dispatch(setCardError(data.error));
}
store.dispatch(updatePlayer(data.player)); store.dispatch(updatePlayer(data.player));
if (data.event === 'init') { if (data.event === 'init') {
store.dispatch(movePlayer(data.player.space, 0, data.player.color)); store.dispatch(movePlayer(data.player.space, 0, data.player.color));

@ -21,7 +21,7 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
SET_OLD_MESSAGES, MESSAGE_PANEL_SPACE, MP_MOUSE, SET_OLD_MESSAGES, MESSAGE_PANEL_SPACE, MP_MOUSE,
SET_MP_DIMS, MOVE_PLAYER, SET_NEXT_ACTION, NEXT_UI_ACTION, SET_MP_DIMS, MOVE_PLAYER, SET_NEXT_ACTION, NEXT_UI_ACTION,
MARK_ACTION_CHANGE_HANDLED, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED, MARK_ACTION_CHANGE_HANDLED, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE } from './actionTypes.js' AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR } from './actionTypes.js'
import { GAME_STATES } from '../../constants.js' import { GAME_STATES } from '../../constants.js'
import { spaceContent, corners } from 'game.js' import { spaceContent, corners } from 'game.js'
@ -107,6 +107,7 @@ const initialState = {
}, },
ui: { card: { type: 'no-card', contents: '', total: 0 }, ui: { card: { type: 'no-card', contents: '', total: 0 },
cards: [], cards: [],
cardError: false,
action: false, action: false,
actionValue: null, actionValue: null,
nextAction: false, nextAction: false,
@ -140,6 +141,8 @@ export default function(state = initialState, action) {
return { ...state, ui: { ...state.ui, card: action.card }}; return { ...state, ui: { ...state.ui, card: action.card }};
case SET_CARDS: case SET_CARDS:
return { ...state, ui: { ...state.ui, cards: action.cards }}; return { ...state, ui: { ...state.ui, cards: action.cards }};
case SET_CARD_ERROR:
return { ...state, ui: { ...state.ui, cardError: action.error }};
case MOVE_PLAYER: case MOVE_PLAYER:
return { ...state, spaces: state.spaces return { ...state, spaces: state.spaces
.map((item, index) => { .map((item, index) => {

@ -375,28 +375,20 @@
(ridges '(ridge1 ridge2 ridge3 ridge4))) (ridges '(ridge1 ridge2 ridge3 ridge4)))
(cond ((and (member unnormalized-crop ridges) (cond ((and (member unnormalized-crop ridges)
(not (ridge-available? game unnormalized-crop))) (not (ridge-available? game unnormalized-crop)))
(push-message player (conc "Ridge already leased.")) "Ridge already leased.")
#f)
((> (player-space player) 14) ((> (player-space player) 14)
(push-message player (conc "Crops may only be bought in winter.")) "Crops may only be bought in winter.")
#f)
((> cash-value (player-cash player)) ((> cash-value (player-cash player))
(push-message player (conc "Could not buy " unnormalized-crop ". Not enough cash.")) (conc "Could not buy " unnormalized-crop ". Not enough cash."))
#f)
((< cash-value (* total-cost (game-setting 'down-payment game))) ((< cash-value (* total-cost (game-setting 'down-payment game)))
(push-message player (conc "Could not buy " unnormalized-crop ". Not enough down payment."))
(conc "Could not buy " unnormalized-crop ". Not enough down payment.")) ((> (- total-cost cash-value) (max 0 (- (game-setting 'max-debt game) (player-debt player))))
#f) (conc "Could not buy " unnormalized-crop ". Not enough credit."))
((> (- total-cost cash-value) (- (game-setting 'max-debt game) (player-debt player)))
(push-message player
(conc "Could not buy " unnormalized-crop ". Not enough credit."))
#f)
((and (eq? unnormalized-crop 'cows) ((and (eq? unnormalized-crop 'cows)
(= (- (player-asset 'cows player) (= (- (player-asset 'cows player)
(fold + 0 (map cdr (player-ridges player)))) (fold + 0 (map cdr (player-ridges player))))
20)) 20))
(push-message player (conc "Could not buy " unnormalized-crop " because it would exceed maximum allowed on farm.")) (conc "Could not buy " unnormalized-crop " because it would exceed maximum allowed on farm."))
#f)
(else (else
(let ((assets (player-assets player))) (let ((assets (player-assets player)))
(safe-set! (safe-set!
@ -408,7 +400,6 @@
(when (member unnormalized-crop ridges) (when (member unnormalized-crop ridges)
(safe-set! (player-ridges player) (safe-set! (player-ridges player)
(alist-update unnormalized-crop amount (player-ridges player)))) (alist-update unnormalized-crop amount (player-ridges player))))
(push-message player (conc "You bought " amount " " crop "."))
#t))))) #t)))))
(define (make-player-year-rule id rule) (define (make-player-year-rule id rule)
@ -880,26 +871,29 @@
((string=? type "buy") ((string=? type "buy")
(let* ((id (alist-ref 'id msg)) (let* ((id (alist-ref 'id msg))
(otb (find (lambda (x) (= id (alist-ref 'id x))) (otb (find (lambda (x) (= id (alist-ref 'id x)))
(player-otbs player)))) (player-otbs player)))
(when (buy-crop (normalize-crop (bought-crop (buy-crop (normalize-crop
(string->symbol (alist-ref 'crop otb))) (string->symbol (alist-ref 'crop otb)))
(string->symbol (alist-ref 'crop otb)) (string->symbol (alist-ref 'crop otb))
(alist-ref 'amount otb) (alist-ref 'amount otb)
(* (or (and (number? (alist-ref 'cash msg)) (* (or (and (number? (alist-ref 'cash msg))
(alist-ref 'cash msg)) (alist-ref 'cash msg))
0) 0)
1000) 1000)
player player
game) game)))
(safe-set! (game-otbs game) (if (eq? bought-crop #t)
(append (game-otbs game) (begin
(filter (lambda (x) (= id (alist-ref 'id x))) (safe-set! (game-otbs game)
(player-otbs player)))) (append (game-otbs game)
(safe-set! (player-otbs player) (filter (lambda (x) (= id (alist-ref 'id x)))
(filter (lambda (x) (not (= id (alist-ref 'id x)))) (player-otbs player))))
(player-otbs player))))) (safe-set! (player-otbs player)
(message-players! game player '() type: "update") (filter (lambda (x) (not (= id (alist-ref 'id x))))
(create-ws-response player "buy" '())) (player-otbs player)))
(message-players! game player '() type: "update")
(create-ws-response player "buy" '()))
(create-ws-response player "buy" `((error . ,bought-crop))))))
((string=? type "buy-uncle-bert") ((string=? type "buy-uncle-bert")
(safe-set! (player-cash player) (- (player-cash player) 10000)) (safe-set! (player-cash player) (- (player-cash player) 10000))
(safe-set! (player-assets player) (safe-set! (player-assets player)
@ -1873,7 +1867,6 @@
;; mark spaces ;; mark spaces
;; support trading farmers fates
;; test tractor/harvester a lot better
;; trade notification keeps popping up ;; trade notification keeps popping up
;; you can see how much money you make before you harvest

@ -558,7 +558,7 @@ $tab-margin: 0.3rem;
flex-grow: 2; flex-grow: 2;
} }
@include breakpoint(large) { @include breakpoint(large) {
width: 40rem; width: 26rem;
} }
} }
@ -804,3 +804,8 @@ $intro-time: 6s;
bottom: 0; bottom: 0;
opacity: 0.5; opacity: 0.5;
right: 4px; } right: 4px; }
.error {
font-size: 1.2rem;
color: red;
font-weight: bold }

@ -46,8 +46,7 @@ module.exports = {
chunkFilename: '[id].css', chunkFilename: '[id].css',
}), }),
new CopyPlugin([ new CopyPlugin([
{ from: './src/server/farm.scm', to: './farm.scm' }, { from: './src/server/', to: './' },
{ from: './src/server/farm', to: './farm' },
{ from: './assets/game/', to: './assets/game/' } { from: './assets/game/', to: './assets/game/' }
]), ]),
new webpack.LoaderOptionsPlugin({ new webpack.LoaderOptionsPlugin({

Loading…
Cancel
Save