Better error handling, birthdays, startup otbs, resource caching.
This commit is contained in:
@@ -348,6 +348,7 @@ class PlayerSummary extends React.Component {
|
||||
<PlayerTurnContainer player={player}
|
||||
game={this.props.game}
|
||||
ui={this.props.ui}
|
||||
hideForLarge={this.props.hideForLarge}
|
||||
screen={this.props.screen}
|
||||
showScreen={this.props.showScreen}/>
|
||||
</GroupBox>
|
||||
@@ -426,7 +427,9 @@ class PlayerTurnContainer extends React.Component {
|
||||
<br />
|
||||
</>
|
||||
) : (<></>)}
|
||||
{view}
|
||||
<div className={this.props.hideForLarge ? 'hide-for-large' : ''}>
|
||||
{view}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -1885,7 +1888,7 @@ class Info extends React.Component {
|
||||
|
||||
const SCREENS = { summary: 'summary', misc: 'misc', farms: 'farms',
|
||||
cards: 'cards', trade: 'trade', loans: 'loans',
|
||||
action: 'action', info: 'info' };
|
||||
action: 'action', info: 'info', error: 'error' };
|
||||
|
||||
class BoardApp extends React.Component {
|
||||
iconToScreen = { user: SCREENS.summary, 'window-restore': SCREENS.cards,
|
||||
@@ -1948,6 +1951,10 @@ class BoardApp extends React.Component {
|
||||
.find(p => p.player.name === this.props.game.currentPlayer).player;
|
||||
this.setState({ currentPlayer });
|
||||
}
|
||||
|
||||
if (!prevProps.ui.exn && this.props.ui.exn) {
|
||||
this.setState({ screen: SCREENS.error });
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -2170,6 +2177,7 @@ class BoardApp extends React.Component {
|
||||
<PlayerSummary player={this.props.player}
|
||||
ui={this.props.ui}
|
||||
screen={this.state.screen}
|
||||
hideForLarge={true}
|
||||
game={this.props.game} showScreen={this.showScreen} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.action)}>
|
||||
@@ -2212,6 +2220,11 @@ class BoardApp extends React.Component {
|
||||
<div className={this.tabClass(SCREENS.info)}>
|
||||
<Info harvestTable={this.props.ui.harvestTable} game={this.props.game} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.error)}>
|
||||
<h3>Error</h3>
|
||||
<p>A server error occured.</p>
|
||||
<p><a href="/?reload-game=true">Reload game</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='static-tab-container show-for-large'>
|
||||
<div className='tab show'>
|
||||
|
||||
@@ -39,3 +39,4 @@ export const AUTO_SKIP = 'auto-skip'
|
||||
export const MESSAGE = 'message'
|
||||
export const SET_HARVEST_TABLE = 'set-harvest-table'
|
||||
export const SET_MOVING_SKIP = 'set-moving-skip'
|
||||
export const SERVER_ERROR = 'server-error'
|
||||
|
||||
@@ -21,13 +21,14 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
|
||||
MP_MOUSE, SET_MP_DIMS, MARK_ACTION_CHANGE_HANDLED, SET_NEXT_ACTION,
|
||||
MOVE_PLAYER, NEXT_UI_ACTION, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
|
||||
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR,
|
||||
SET_MOVING_SKIP } from './actionTypes.js'
|
||||
SET_MOVING_SKIP, SERVER_ERROR } from './actionTypes.js'
|
||||
|
||||
export { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
|
||||
spacePushPlayer, spaceClearPlayers, setOldMessages, setMessagePanelSpace,
|
||||
mpMouse, setMPDims, movePlayer, setNextAction, nextUIAction,
|
||||
markActionChangeHandled, nextUIActionSilent, alert, alertHandled,
|
||||
autoSkip, message, setHarvestTable, setCardError, setMovingSkip }
|
||||
autoSkip, message, setHarvestTable, setCardError, setMovingSkip,
|
||||
serverError }
|
||||
|
||||
function updateGame(update) {
|
||||
return { type: UPDATE_GAME,
|
||||
@@ -135,3 +136,7 @@ function setHarvestTable(table) {
|
||||
function setMovingSkip(skip) {
|
||||
return { type: SET_MOVING_SKIP, skip };
|
||||
}
|
||||
|
||||
function serverError(exn) {
|
||||
return { type: SERVER_ERROR, exn };
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import { updateGame, updatePlayer, gameState, setSelectedCard, setCards,
|
||||
movePlayer, setOldMessages, markActionChangeHandled,
|
||||
mpMouse, rolled, setNextAction, nextUIAction, nextUIActionSilent, alert,
|
||||
autoSkip, message, alertHandled, setHarvestTable,
|
||||
setCardError, setMovingSkip } from './actions.js'
|
||||
setCardError, setMovingSkip, serverError } from './actions.js'
|
||||
import { itemCard, fateCard } from 'game.js'
|
||||
|
||||
export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept,
|
||||
@@ -42,6 +42,7 @@ function handleMessage(evt) {
|
||||
|
||||
if (data.event === 'error') {
|
||||
console.log('error:' + data.exn);
|
||||
store.dispatch(serverError(data.exn));
|
||||
return;
|
||||
}
|
||||
batch(() => {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
|
||||
SET_MP_DIMS, MOVE_PLAYER, SET_NEXT_ACTION, NEXT_UI_ACTION,
|
||||
MARK_ACTION_CHANGE_HANDLED, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
|
||||
AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR,
|
||||
SET_MOVING_SKIP } from './actionTypes.js'
|
||||
SET_MOVING_SKIP, SERVER_ERROR } from './actionTypes.js'
|
||||
import { GAME_STATES } from '../../constants.js'
|
||||
import { spaceContent, corners } from 'game.js'
|
||||
|
||||
@@ -124,7 +124,8 @@ const initialState = {
|
||||
autoSkip: false,
|
||||
playerSpaces: {},
|
||||
movingSkip: false,
|
||||
harvestTable: false },
|
||||
harvestTable: false,
|
||||
exn: false },
|
||||
spaces: spaces,
|
||||
space: null,
|
||||
// message panel dimenions
|
||||
@@ -228,6 +229,8 @@ export default function(state = initialState, action) {
|
||||
return { ...state, ui: { ...state.ui, harvestTable: action.table }};
|
||||
case SET_MOVING_SKIP:
|
||||
return { ...state, ui: { ...state.ui, movingSkip: action.skip }};
|
||||
case SERVER_ERROR:
|
||||
return { ...state, ui: { ...state.ui, exn: action.exn }};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import LoginOrCreateAccount from '../login-or-create-account/LoginOrCreateAccoun
|
||||
import { startOrJoinGame } from '../start/actions.js'
|
||||
import { start } from '../app/actions.js'
|
||||
|
||||
import { itemCardShort } from 'game.js'
|
||||
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faArrowCircleLeft, faCog } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
@@ -63,6 +65,7 @@ class NewGame extends React.Component {
|
||||
auditThreshold: 250000,
|
||||
startingCash: 5000,
|
||||
startingDebt: 5000,
|
||||
startingOtbs: 2,
|
||||
trade: true,
|
||||
showLogin: false
|
||||
};
|
||||
@@ -71,10 +74,10 @@ class NewGame extends React.Component {
|
||||
handleInputChange = e => {
|
||||
const target = e.target,
|
||||
value = target.type === 'checkbox' && target.name !== 'trade'
|
||||
? target.name : target.value,
|
||||
? target.name : target.value,
|
||||
|
||||
name = target.type === 'checkbox' && target.name !== 'trade'
|
||||
? 'checkedColor' : target.name;
|
||||
? 'checkedColor' : target.name;
|
||||
|
||||
this.setState({
|
||||
[name]: value
|
||||
@@ -98,122 +101,129 @@ class NewGame extends React.Component {
|
||||
|
||||
render() {
|
||||
let titleBar = !this.props.hideBack ? (
|
||||
<Fragment>
|
||||
<a onClick={this.handleBack}>
|
||||
<Fragment>
|
||||
<a onClick={this.handleBack}>
|
||||
<FontAwesomeIcon icon={faArrowCircleLeft} />
|
||||
</a>
|
||||
{this.props.title}
|
||||
</Fragment>
|
||||
) : this.props.title,
|
||||
</a>
|
||||
{this.props.title}
|
||||
</Fragment>
|
||||
) : this.props.title,
|
||||
colors = this.props.colors.map(c => (
|
||||
<label key={c} className={'player player-selectable player-' + c + (this.state.checkedColor === c ? ' player-selected' : '')}>
|
||||
<input type='checkbox'
|
||||
checked={this.state.checkedColor === c}
|
||||
onChange={this.handleInputChange}
|
||||
name={c} />
|
||||
<input type='checkbox'
|
||||
checked={this.state.checkedColor === c}
|
||||
onChange={this.handleInputChange}
|
||||
name={c} />
|
||||
</label>
|
||||
)
|
||||
),
|
||||
),
|
||||
gameName = this.props.showGameName && (
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Game Name
|
||||
<input type='text' name='gameName' value={this.state.gameName}
|
||||
required
|
||||
onChange={this.handleInputChange} />
|
||||
</label>
|
||||
</Col>
|
||||
<Col width='12'>
|
||||
<label>Game Name
|
||||
<input type='text' name='gameName' value={this.state.gameName}
|
||||
required
|
||||
onChange={this.handleInputChange} />
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
settingsClass = this.state.showSettings ? '' : 'hidden',
|
||||
mainScreenClass = !this.state.showSettings ? '' : 'hidden';
|
||||
return (
|
||||
<GroupBox title={titleBar}>
|
||||
{this.props.user ? (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className={mainScreenClass}>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Your Color</label>
|
||||
{colors}
|
||||
<br /><br />
|
||||
</Col>
|
||||
</Row>
|
||||
{gameName}
|
||||
</div>
|
||||
<div className={settingsClass}>
|
||||
<InputRow label='Down Payment'
|
||||
name='downPayment'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.downPayment}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Loan Interest'
|
||||
name='loanInterest'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.loanInterest}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Maximum Debt'
|
||||
name='maxDebt'
|
||||
min={0}
|
||||
step={5000}
|
||||
value={this.state.maxDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Audit Threshold'
|
||||
name='auditThreshold'
|
||||
min={0}
|
||||
step={25000}
|
||||
value={this.state.auditThreshold}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Cash'
|
||||
name='startingCash'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingCash}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Debt'
|
||||
name='startingDebt'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>
|
||||
<input type='checkbox'
|
||||
checked={this.state.trade}
|
||||
onChange={this.handleInputChange}
|
||||
name='trade' />
|
||||
Enable Trading
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<div className='new-game-submit-container'>
|
||||
<Button type='submit'>{this.props.button} Game</Button>
|
||||
{this.props.showGameName ? (
|
||||
<a onClick={this.toggleSettings}>
|
||||
<FontAwesomeIcon icon={faCog} size='lg' />
|
||||
</a>
|
||||
) : (<Fragment />)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<span>Sign in or create account to continue</span>
|
||||
<LoginOrCreateAccount login={this.props.login}
|
||||
createAccount={this.props.createAccount}
|
||||
errors={this.props.errors}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{this.props.user ? (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className={mainScreenClass}>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>Your Color</label>
|
||||
{colors}
|
||||
<br /><br />
|
||||
</Col>
|
||||
</Row>
|
||||
{gameName}
|
||||
</div>
|
||||
<div className={settingsClass}>
|
||||
<InputRow label='Down Payment'
|
||||
name='downPayment'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.downPayment}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Loan Interest'
|
||||
name='loanInterest'
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
value={this.state.loanInterest}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Maximum Debt'
|
||||
name='maxDebt'
|
||||
min={0}
|
||||
step={5000}
|
||||
value={this.state.maxDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Audit Threshold'
|
||||
name='auditThreshold'
|
||||
min={0}
|
||||
step={25000}
|
||||
value={this.state.auditThreshold}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Cash'
|
||||
name='startingCash'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingCash}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label='Starting Debt'
|
||||
name='startingDebt'
|
||||
min={0}
|
||||
step={1000}
|
||||
value={this.state.startingDebt}
|
||||
onChange={this.handleInputChange} />
|
||||
<InputRow label={'Number of Starting ' + itemCardShort}
|
||||
name='startingOtbs'
|
||||
min={0}
|
||||
max={8}
|
||||
step={1}
|
||||
value={this.state.startingOtbs}
|
||||
onChange={this.handleInputChange} />
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<label>
|
||||
<input type='checkbox'
|
||||
checked={this.state.trade}
|
||||
onChange={this.handleInputChange}
|
||||
name='trade' />
|
||||
Enable Trading
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col width='12'>
|
||||
<div className='new-game-submit-container'>
|
||||
<Button type='submit'>{this.props.button} Game</Button>
|
||||
{this.props.showGameName ? (
|
||||
<a onClick={this.toggleSettings}>
|
||||
<FontAwesomeIcon icon={faCog} size='lg' />
|
||||
</a>
|
||||
) : (<Fragment />)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<span>Sign in or create account to continue</span>
|
||||
<LoginOrCreateAccount login={this.props.login}
|
||||
createAccount={this.props.createAccount}
|
||||
errors={this.props.errors}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</GroupBox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ const unsubscribeNewOrJoinGame = store.subscribe(() => {
|
||||
});
|
||||
|
||||
let autostart = new URL(window.location.href).searchParams.get('autostart');
|
||||
let rejoin = new URL(window.location.href).searchParams.get('reload-game');
|
||||
|
||||
function handleMessage(evt) {
|
||||
const data = JSON.parse(evt.data),
|
||||
@@ -86,6 +87,8 @@ function handleMessage(evt) {
|
||||
if (data.event === 'error') {
|
||||
console.log('error:' + data.exn);
|
||||
} else if (data.event === 'new-game-started') {
|
||||
history.replaceState({}, document.title, '/');
|
||||
console.log('clearing auto-reload');
|
||||
initialize(store, Ws.sendCommand);
|
||||
Ws.setMainOnMessage(handleMessageFarm);
|
||||
Ws.openSecondary('push-web-socket');
|
||||
@@ -111,6 +114,10 @@ function handleMessage(evt) {
|
||||
gameName: data.games.games[0].name }));
|
||||
}
|
||||
}
|
||||
if (rejoin) {
|
||||
store.dispatch(startOrJoinGame({ type: 'join-as-existing',
|
||||
gameId: false }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
;;; <https://www.gnu.org/licenses/>.
|
||||
|
||||
(import chicken scheme srfi-1 data-structures)
|
||||
(use http-session srfi-69 coops uri-common
|
||||
(use http-session srfi-69 coops coops-utils uri-common
|
||||
srfi-18 medea numbers spiffy spiffy-cookies
|
||||
intarweb pll sxml-transforms websockets miscmacros
|
||||
mailbox)
|
||||
@@ -156,7 +156,8 @@
|
||||
(audit-threshold . 250000)
|
||||
(starting-cash . 5000)
|
||||
(starting-debt . 5000)
|
||||
(trade . #t))
|
||||
(trade . #t)
|
||||
(starting-otbs . 2))
|
||||
accessor: game-settings)
|
||||
(mutex initform: (make-mutex 'game) accessor: game-mutex)))
|
||||
|
||||
@@ -169,8 +170,8 @@
|
||||
(mutex initform: (make-mutex 'app) accessor: app-mutex)))
|
||||
|
||||
(define (player->sexp player)
|
||||
`((cash . ,(player-cash player))
|
||||
(debt . ,(player-debt player))
|
||||
`((cash . ,(inexact->exact (round (player-cash player))))
|
||||
(debt . ,(inexact->exact (round (player-debt player))))
|
||||
(space . ,(player-space player))
|
||||
(previous-space . ,(player-previous-space player))
|
||||
(state . ,(player-state player))
|
||||
@@ -247,12 +248,54 @@
|
||||
'games (map sexp->game (alist-ref 'games x))
|
||||
'last-game-id (alist-ref 'last-game-id x)))
|
||||
|
||||
(define (save-app)
|
||||
(with-output-to-file "/home/tjhintz/app.scm"
|
||||
(lambda ()
|
||||
(write (app->sexp *app*)))))
|
||||
(define (validate-game g)
|
||||
(assert (instance-of? g <game>))
|
||||
(assert (number? (game-id g)))
|
||||
(assert (list? (game-players g)))
|
||||
(for-each (lambda (p)
|
||||
(assert (instance-of? p <player>))
|
||||
(assert (number? (player-cash p)))
|
||||
(assert (number? (player-display-cash p)))
|
||||
(assert (= (player-cash p) (player-display-cash p)))
|
||||
(assert (number? (player-debt p)))
|
||||
(assert (number? (player-space p)))
|
||||
(assert (number? (player-previous-space p)))
|
||||
(assert (symbol? (player-state p)))
|
||||
(assert (member (player-state p) '(turn-ended pre-turn mid-turn)))
|
||||
(assert (boolean? (player-finished p)))
|
||||
(assert (list? (player-assets p))) ;; TODO test assets
|
||||
(assert (list? (player-ridges p)))
|
||||
(assert (number? (player-harvest-mult p)))
|
||||
(assert (list? (player-otbs p)))
|
||||
(assert (list? (player-farmers-fates p)))
|
||||
(assert (list? (player-year-rules p)))
|
||||
(assert (list? (player-next-year-rules p)))
|
||||
(assert (symbol? (player-color p)))
|
||||
(assert (string? (player-name p)))
|
||||
(assert (number? (player-user-id p)))
|
||||
(assert (list? (player-trade p)))
|
||||
(assert (number? (player-last-cash p)))
|
||||
(assert (boolean? (player-harvesting p)))
|
||||
(assert (boolean? (player-hay-doubled p)))
|
||||
(assert (boolean? (player-corn-doubled p))))
|
||||
(game-players g))
|
||||
(assert (list? (game-otbs g)))
|
||||
(assert (list? (game-used-otbs g)))
|
||||
(assert (list? (game-farmers-fates g)))
|
||||
(assert (list? (game-operating-expenses g)))
|
||||
(assert (number? (game-operating-expense-index g)))
|
||||
(assert (list? (game-colors g)))
|
||||
(assert (or (instance-of? (game-called-audit g) <player>)
|
||||
(boolean? (game-called-audit g))))
|
||||
(assert (symbol? (game-state g))) ;; TODO test all symbols
|
||||
(assert (string? (game-name g)))
|
||||
(assert (number? (game-turn g)))
|
||||
(assert (or (instance-of? (game-current-player g) <player>)
|
||||
(boolean? (game-current-player g))))
|
||||
(assert (list? (game-settings g))))
|
||||
|
||||
(define (save-game game)
|
||||
(validate-game game)
|
||||
(db-update-game (game-id game) (symbol->string (game-state game))
|
||||
(game->sexp game)))
|
||||
|
||||
@@ -293,7 +336,9 @@
|
||||
(set-cookie! (session-cookie-name) sid))))
|
||||
(session-lifetime (* 60 60 24 7 4))
|
||||
|
||||
(access-log (current-output-port))
|
||||
;; (access-log (current-output-port))
|
||||
(access-log "access.log")
|
||||
(error-log "error.log")
|
||||
|
||||
(handle-not-found
|
||||
(let ((old-handler (handle-not-found)))
|
||||
@@ -577,14 +622,21 @@
|
||||
(lambda (p1 p2)
|
||||
(> (player-net-worth p1)
|
||||
(player-net-worth p2))))))
|
||||
(bonus (max (farming-round
|
||||
(* (- (player-net-worth richest)
|
||||
(player-net-worth player))
|
||||
0.2))
|
||||
2500)))
|
||||
;; (bonus (max (farming-round
|
||||
;; (inexact->exact
|
||||
;; (round
|
||||
;; (* (- (player-net-worth richest)
|
||||
;; (+ (player-net-worth player)
|
||||
;; ;; don't give a bonus for emergency debt
|
||||
;; (max 0 (- (player-debt player) (game-setting 'max-debt game)))))
|
||||
;; 0.2))))
|
||||
;; 2500))
|
||||
(bonus 5000)
|
||||
)
|
||||
(safe-set! (player-cash player)
|
||||
;; (+ (player-cash player) 5000)
|
||||
(+ (player-cash player) bonus))
|
||||
(+ (player-cash player) 5000)
|
||||
;; (+ (player-cash player) bonus)
|
||||
)
|
||||
(safe-set! (player-display-cash player) (player-cash player))
|
||||
(safe-set! (game-actions game)
|
||||
(cons `((?action . info)
|
||||
@@ -827,8 +879,8 @@
|
||||
#f)))
|
||||
|
||||
(define (call-audit game player)
|
||||
(if (game-called-audit game)
|
||||
(begin (safe-set! (game-called-audit game) player))))
|
||||
(if (not (game-called-audit game))
|
||||
(safe-set! (game-called-audit game) player)))
|
||||
|
||||
(define (player-net-worth player)
|
||||
(+ (* (+ (player-asset 'hay player) (player-asset 'grain player)) 2000)
|
||||
@@ -942,6 +994,17 @@
|
||||
rolls))
|
||||
(_make-rolls n 1 (list (next-roll -1))))
|
||||
|
||||
(define (log-error exn)
|
||||
(with-output-to-file (error-log)
|
||||
(lambda ()
|
||||
(print-call-chain)
|
||||
(print exn)
|
||||
(print-error-message exn))
|
||||
append:))
|
||||
|
||||
(define (log-msg msg)
|
||||
(log-to (error-log) "~A" msg))
|
||||
|
||||
(define (process-message player game type msg)
|
||||
(when player
|
||||
(safe-set! (player-last-cash player) (player-cash player)))
|
||||
@@ -1253,10 +1316,8 @@
|
||||
(begin (advance-turn game player)
|
||||
(handle-exceptions
|
||||
exn
|
||||
(begin (print-call-chain)
|
||||
(print exn)
|
||||
(print-error-message exn)
|
||||
(print "error saving app"))
|
||||
(begin (log-error exn)
|
||||
(log-msg "error saving app"))
|
||||
(save-game game))
|
||||
(if (eq? (game-state game) 'finished)
|
||||
(do-end-of-game game)
|
||||
@@ -1286,6 +1347,10 @@
|
||||
0))
|
||||
(starting-debt . ,(->i (alist-ref 'startingDebt msg)
|
||||
0))
|
||||
(starting-otbs . ,(min (max (->number (alist-ref 'startingOtbs msg)
|
||||
2)
|
||||
0)
|
||||
8))
|
||||
(trade . ,(or (alist-ref 'trade msg) #t)))))
|
||||
(player (add-player-to-game game
|
||||
color
|
||||
@@ -1301,7 +1366,7 @@
|
||||
(session-set! (sid) 'game-id (game-id game)))
|
||||
(*game* game)
|
||||
(*player* player)
|
||||
(set-startup-otbs game player 2)
|
||||
(set-startup-otbs game player (alist-ref 'starting-otbs (game-settings game)))
|
||||
;; (set-startup-otbs game ai-player 2)
|
||||
;; (thread-start! (make-ai-push-receiver game ai-player))
|
||||
(create-start-response "new-game-started")))
|
||||
@@ -1323,11 +1388,12 @@
|
||||
(db-add-user-game (alist-ref 'id user) (game-id game))
|
||||
(*game* game)
|
||||
(*player* player)
|
||||
(set-startup-otbs game player 2)
|
||||
(set-startup-otbs game player (alist-ref 'starting-otbs (game-settings game)))
|
||||
(message-players! game player '() type: "update")
|
||||
(create-start-response "new-game-started")))
|
||||
((string=? type "join-as-existing")
|
||||
(let* ((id (alist-ref 'gameId msg))
|
||||
(let* ((id (or (alist-ref 'gameId msg)
|
||||
(session-ref (sid) 'game-id)))
|
||||
(user-id (session-ref (sid) 'user-id))
|
||||
(game (find-game id))
|
||||
(player (find (lambda (p) (equal? (player-user-id p) user-id))
|
||||
@@ -1440,19 +1506,19 @@
|
||||
exn
|
||||
(send-message
|
||||
(json->string
|
||||
`((exn . ,(with-output-to-string
|
||||
(lambda ()
|
||||
(print-call-chain)
|
||||
(print-error-message exn))))
|
||||
`((exn . ,(begin (log-error exn)
|
||||
(conc "Server error: " (with-output-to-string
|
||||
(lambda ()
|
||||
(print-error-message exn))))))
|
||||
(event . "error"))))
|
||||
(send-message
|
||||
(json->string
|
||||
(handle-exceptions
|
||||
exn
|
||||
`((exn . ,(with-output-to-string
|
||||
(lambda ()
|
||||
(print-call-chain)
|
||||
(print-error-message exn))))
|
||||
`((exn . ,(begin (log-error exn)
|
||||
(conc "Server error: " (with-output-to-string
|
||||
(lambda ()
|
||||
(print-error-message exn))))))
|
||||
(event . "error"))
|
||||
(session-game)
|
||||
(let* ((game (*game*))
|
||||
@@ -1492,18 +1558,18 @@
|
||||
exn
|
||||
(send-message
|
||||
(json->string
|
||||
`((exn . ,(with-output-to-string
|
||||
(lambda ()
|
||||
(print-call-chain)
|
||||
(print-error-message exn)))))))
|
||||
`((exn . ,(begin (log-error exn)
|
||||
(conc "Server error: " (with-output-to-string
|
||||
(lambda ()
|
||||
(print-error-message exn)))))))))
|
||||
(send-message
|
||||
(json->string
|
||||
(handle-exceptions
|
||||
exn
|
||||
`((exn . ,(with-output-to-string
|
||||
(lambda ()
|
||||
(print-call-chain)
|
||||
(print-error-message exn))))
|
||||
`((exn . ,(begin (log-error exn)
|
||||
(conc "Server error: " (with-output-to-string
|
||||
(lambda ()
|
||||
(print-error-message exn))))))
|
||||
(event . "error"))
|
||||
(create-ws-response (*player*)
|
||||
(alist-ref 'type msg)
|
||||
@@ -2143,7 +2209,10 @@
|
||||
(let ((value (alist-ref '?value action)))
|
||||
(if (procedure? value)
|
||||
(value player)
|
||||
(apply (alist-ref (car value) *action-map*) player (cdr value)))))
|
||||
(let ((action-proc (alist-ref (car value) *action-map*)))
|
||||
(if (procedure? action-proc)
|
||||
(apply action-proc player (cdr value))
|
||||
(print (conc "unknown action value: " value)))))))
|
||||
((eq? a 'harvest-mult)
|
||||
(safe-set! (player-harvest-mult player)
|
||||
(* (player-harvest-mult player) (alist-ref '?value action))))
|
||||
@@ -2314,3 +2383,207 @@
|
||||
;; Error: (assv) bad argument type: #<coops instance of `<game>'>
|
||||
|
||||
;; when getting trade the name is wrong
|
||||
|
||||
;; error:
|
||||
;; Call history:
|
||||
|
||||
;; farm.scm:482: player-last-cash
|
||||
;; farm.scm:99: coops#slot-value
|
||||
;; farm.scm:483: player-hay-doubled
|
||||
;; farm.scm:99: coops#slot-value
|
||||
;; farm.scm:484: player-corn-doubled
|
||||
;; farm.scm:99: coops#slot-value
|
||||
;; farm.scm:513: list->vector
|
||||
;; farm.scm:517: game-called-audit
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:518: game-called-audit
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:518: player-name
|
||||
;; farm.scm:1450: k8469
|
||||
;; farm.scm:1450: g8473
|
||||
;; farm.scm:1452: with-output-to-string
|
||||
;; farm.scm:1454: print-call-chain <--
|
||||
|
||||
;; Error: (player-name) no method defined for given argument classes: (#t)
|
||||
|
||||
;; clicking roll button
|
||||
|
||||
|
||||
|
||||
;; start game with more otbs
|
||||
|
||||
|
||||
;; Error: (assv) bad argument type: #f
|
||||
|
||||
;; Call history:
|
||||
|
||||
;; numbers.scm:1672: scan-real
|
||||
;; numbers.scm:1671: scan-ureal
|
||||
;; numbers.scm:1603: scan-digits+hashes
|
||||
;; numbers.scm:1549: scan-digits
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1548: g1937
|
||||
;; numbers.scm:1720: %string->compnum
|
||||
;; numbers.scm:1672: scan-real
|
||||
;; numbers.scm:1671: scan-ureal
|
||||
;; numbers.scm:1603: scan-digits+hashes
|
||||
;; numbers.scm:1549: scan-digits
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1548: g1937
|
||||
;; farm.scm:50: expiration
|
||||
;; farm.scm:43: current-milliseconds
|
||||
;; farm.scm:44: http-session#session-lifetime
|
||||
;; farm.scm:44: numbers#*
|
||||
;; numbers.scm:382: %*
|
||||
;; farm.scm:44: numbers#floor
|
||||
;; farm.scm:44: numbers#inexact->exact
|
||||
;; numbers.scm:867: exact?
|
||||
;; farm.scm:43: numbers#+
|
||||
;; numbers.scm:295: %+
|
||||
;; farm.scm:50: spiffy#remote-address
|
||||
;; farm.scm:50: http-session#make-session-item
|
||||
;; farm.scm:1441: *game*
|
||||
;; farm.scm:1449: *game*
|
||||
;; farm.scm:1476: *game*
|
||||
;; farm.scm:1477: *player*
|
||||
;; farm.scm:1479: alist-ref
|
||||
;; farm.scm:1468: k8474
|
||||
;; farm.scm:1468: g8478
|
||||
;; farm.scm:1470: log-error
|
||||
;; farm.scm:954: spiffy#error-log
|
||||
;; farm.scm:954: with-output-to-file
|
||||
;; farm.scm:956: print-call-chain
|
||||
;; farm.scm:957: print
|
||||
;; farm.scm:958: print-error-message
|
||||
;; farm.scm:1471: with-output-to-string
|
||||
;; farm.scm:1473: print-error-message
|
||||
;; farm.scm:1471: conc
|
||||
;; farm.scm:1467: medea#json->string
|
||||
;; farm.scm:1466: websockets#send-message
|
||||
;; farm.scm:1455: k8462
|
||||
;; farm.scm:1455: g8466
|
||||
;; farm.scm:1461: log-error
|
||||
;; farm.scm:954: spiffy#error-log
|
||||
;; farm.scm:954: with-output-to-file
|
||||
;; farm.scm:956: print-call-chain <--
|
||||
;; #<condition: (exn i/o net)>
|
||||
|
||||
;; Error: cannot write to socket - Broken pipe: 7
|
||||
;; [Sat Apr 11 23:04:48 2020] "GET http://localhost:8080/websocket/web-socket HTTP/1.1" Uncaught exception:
|
||||
;; #<condition: (uncaught-exception)>
|
||||
|
||||
|
||||
|
||||
;; Call history:
|
||||
|
||||
;; farm.scm:164: game-settings
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:164: alist-ref
|
||||
;; farm.scm:164: game-settings
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:164: alist-ref
|
||||
;; farm.scm:164: game-settings
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:164: alist-ref
|
||||
;; farm.scm:164: game-settings
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:164: alist-ref
|
||||
;; farm.scm:164: game-settings
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:164: alist-ref
|
||||
;; farm.scm:866: append
|
||||
;; farm.scm:1483: game-last-updated
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:1483: numbers#+
|
||||
;; numbers.scm:295: %+
|
||||
;; farm.scm:1483: game-mutex
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:1483: dynamic-wind
|
||||
;; farm.scm:1483: mutex-lock!
|
||||
;; farm.scm:1483: ##sys#setter
|
||||
;; farm.scm:1483: g8506
|
||||
;; farm.scm:135: coops#set-slot-value!
|
||||
;; farm.scm:1483: mutex-unlock!
|
||||
;; farm.scm:1484: *player*
|
||||
;; farm.scm:1485: *player*
|
||||
;; farm.scm:1485: game-last-updated
|
||||
;; farm.scm:135: coops#slot-value
|
||||
;; farm.scm:1485: player-mutex
|
||||
;; farm.scm:99: coops#slot-value
|
||||
;; farm.scm:1485: dynamic-wind
|
||||
;; farm.scm:1485: mutex-lock!
|
||||
;; farm.scm:1485: ##sys#setter
|
||||
;; farm.scm:1485: g8526
|
||||
;; farm.scm:99: coops#set-slot-value!
|
||||
;; farm.scm:1485: mutex-unlock!
|
||||
;; tmp213217
|
||||
;; farm.scm:1469: k8475
|
||||
;; farm.scm:1469: g8479
|
||||
;; farm.scm:1468: medea#json->string
|
||||
;; farm.scm:1456: k8463
|
||||
;; farm.scm:1456: g8467
|
||||
;; farm.scm:1462: log-error
|
||||
;; farm.scm:955: spiffy#error-log
|
||||
;; farm.scm:955: with-output-to-file
|
||||
;; farm.scm:957: print-call-chain <--
|
||||
;; #<condition: (exn type)>
|
||||
|
||||
;; Error: (symbol->string) bad argument type - not a symbol: (contents . "\n<p>LEASE Marineris Ridge</p>\n<p>for 30 years at $20,000</p>\n<p>...
|
||||
|
||||
|
||||
;; rror: (assv) bad argument type: pre-turn
|
||||
|
||||
;; Call history:
|
||||
|
||||
;; sql-de-lite.scm:600: statement-ptr
|
||||
;; sql-de-lite.scm:609: statement-ptr
|
||||
;; sql-de-lite.scm:222: ##sys#block-set!
|
||||
;; sql-de-lite.scm:612: remove-active-statement!
|
||||
;; sql-de-lite.scm:202: hash-table-delete!
|
||||
;; sql-de-lite.scm:893: for-each-active-statement
|
||||
;; sql-de-lite.scm:204: hash-table-walk
|
||||
;; sql-de-lite.scm:172: ##sys#block-set!
|
||||
;; sql-de-lite.scm:897: object-release
|
||||
;; sql-de-lite.scm:172: ##sys#block-set!
|
||||
;; db.scm:28: alist-ref
|
||||
;; db.scm:27: with-input-from-string
|
||||
;; numbers.scm:1720: %string->compnum
|
||||
;; numbers.scm:1672: scan-real
|
||||
;; numbers.scm:1671: scan-ureal
|
||||
;; numbers.scm:1603: scan-digits+hashes
|
||||
;; numbers.scm:1549: scan-digits
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1548: g1937
|
||||
;; numbers.scm:1720: %string->compnum
|
||||
;; numbers.scm:1672: scan-real
|
||||
;; numbers.scm:1671: scan-ureal
|
||||
;; numbers.scm:1603: scan-digits+hashes
|
||||
;; numbers.scm:1549: scan-digits
|
||||
;; numbers.scm:1531: lp
|
||||
;; numbers.scm:1548: g1937
|
||||
;; farm.scm:50: expiration
|
||||
;; farm.scm:43: current-milliseconds
|
||||
;; farm.scm:44: http-session#session-lifetime
|
||||
;; farm.scm:44: numbers#*
|
||||
;; numbers.scm:382: %*
|
||||
;; farm.scm:44: numbers#floor
|
||||
;; farm.scm:44: numbers#inexact->exact
|
||||
;; numbers.scm:867: exact?
|
||||
;; farm.scm:43: numbers#+
|
||||
;; numbers.scm:295: %+
|
||||
;; farm.scm:50: spiffy#remote-address
|
||||
;; farm.scm:50: http-session#make-session-item
|
||||
;; farm.scm:1484: *game*
|
||||
;; farm.scm:1492: *game*
|
||||
;; farm.scm:1519: *game*
|
||||
;; farm.scm:1520: *player*
|
||||
;; farm.scm:1522: alist-ref
|
||||
;; farm.scm:1511: k8652
|
||||
;; farm.scm:1511: g8656
|
||||
;; farm.scm:1513: log-error
|
||||
;; farm.scm:997: spiffy#error-log
|
||||
;; farm.scm:997: with-output-to-file
|
||||
;; farm.scm:999: print-call-chain <--
|
||||
;; #<condition: (exn type)>
|
||||
|
||||
Reference in New Issue
Block a user