fix assertion around out-of-order tile assignment

Got a crash opening games where tile pick was on and first player was a
robot. Cause: non-robot player's tiles were being assigned before the
robot's, and the move stack didn't like the out-of-order assignments.
Now we assign tiles in order as before, but pause each time we find a
non-robot that needs to pick its own.
This commit is contained in:
Eric House 2017-03-09 21:40:19 -08:00
parent 6e5973c55b
commit 1cd863b877
2 changed files with 25 additions and 32 deletions

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2000-2015 by Eric House (xwords@eehouse.org). All rights
* Copyright 2000 - 2017 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -2573,7 +2573,7 @@ setContains( const TrayTileSet* tiles, Tile tile )
#ifdef DEBUG
static void
assertDiffTurn( ModelCtxt* model, XP_U16 XP_UNUSED(turn),
const StackEntry* entry, void* closure)
const StackEntry* entry, void* closure )
{
if ( 1 < model->nPlayers ) {
DiffTurnState* state = (DiffTurnState*)closure;

View file

@ -132,7 +132,7 @@ struct ServerCtxt {
#define NPASSES_OK(s) model_recentPassCountOk((s)->vol.model)
/******************************* prototypes *******************************/
static void assignTilesToAll( ServerCtxt* server );
static XP_Bool assignTilesToAll( ServerCtxt* server );
static void makePoolOnce( ServerCtxt* server );
static void resetEngines( ServerCtxt* server );
@ -777,7 +777,7 @@ handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
XP_ASSERT( ii == playersInMsg ); /* otherwise malformed */
setStreamVersion( server );
checkResizeBoard( server );
assignTilesToAll( server );
(void)assignTilesToAll( server );
SETSTATE( server, XWSTATE_RECEIVED_ALL_REG );
}
informMissing( server );
@ -1057,6 +1057,8 @@ void
server_tilesPicked( ServerCtxt* server, XP_U16 player,
const TrayTileSet* newTilesP )
{
XP_ASSERT( 0 == model_getNumTilesInTray( server->vol.model, player ) );
TrayTileSet newTiles = *newTilesP;
pool_removeTiles( server->pool, &newTiles );
@ -1089,28 +1091,6 @@ informNeedPickTiles( ServerCtxt* server, XP_Bool initial, XP_U16 turn,
nToPick, nFaces, faces, counts );
}
static XP_Bool
askedForTiles( ServerCtxt* server )
{
XP_Bool asked = XP_FALSE;
CurGameInfo* gi = server->vol.gi;
if ( gi->serverRole == SERVER_STANDALONE && gi->allowPickTiles ) {
XP_U16 nPlayers = gi->nPlayers;
ModelCtxt* model = server->vol.model;
makePoolOnce( server );
for ( XP_U16 turn = 0; !asked && turn < nPlayers; ++turn ) {
LocalPlayer* player = &gi->players[turn];
XP_U16 nTiles = model_getNumTilesInTray( model, turn );
if ( nTiles == 0 && !LP_IS_ROBOT(player) ) {
informNeedPickTiles( server, XP_TRUE, turn, MAX_TRAY_TILES );
asked = XP_TRUE;
}
}
}
LOG_RETURNF( "%s", boolToStr(asked));
return asked;
}
XP_Bool
server_do( ServerCtxt* server )
{
@ -1126,8 +1106,7 @@ server_do( ServerCtxt* server )
case XWSTATE_BEGIN:
if ( server->nv.pendingRegistrations == 0 ) { /* all players on
device */
if ( !askedForTiles( server ) ) {
assignTilesToAll( server );
if ( assignTilesToAll( server ) ) {
SETSTATE( server, XWSTATE_INTURN );
setTurn( server, 0 );
moreToDo = XP_TRUE;
@ -1941,15 +1920,17 @@ makePoolOnce( ServerCtxt* server )
}
}
static void
static XP_Bool
assignTilesToAll( ServerCtxt* server )
{
XP_Bool allDone = XP_TRUE;
XP_U16 numAssigned;
XP_U16 ii;
ModelCtxt* model = server->vol.model;
XP_U16 nPlayers = server->vol.gi->nPlayers;
CurGameInfo* gi = server->vol.gi;
XP_U16 nPlayers = gi->nPlayers;
XP_ASSERT( server->vol.gi->serverRole != SERVER_ISCLIENT );
XP_ASSERT( gi->serverRole != SERVER_ISCLIENT );
makePoolOnce( server );
XP_STATUSF( "assignTilesToAll" );
@ -1960,15 +1941,27 @@ assignTilesToAll( ServerCtxt* server )
if ( numAssigned > MAX_TRAY_TILES ) {
numAssigned = MAX_TRAY_TILES;
}
/* Loop through all the players. If picking tiles is on, stop for each
local player that doesn't have tiles yet. Return TRUE if we get all the
way through without doing that. */
XP_Bool pickingTiles = gi->serverRole == SERVER_STANDALONE
&& gi->allowPickTiles;
for ( ii = 0; ii < nPlayers; ++ii ) {
if ( 0 == model_getNumTilesInTray( model, ii ) ) {
if ( pickingTiles && !LP_IS_ROBOT(&gi->players[ii]) ) {
informNeedPickTiles( server, XP_TRUE, ii, MAX_TRAY_TILES );
allDone = XP_FALSE;
break;
}
TrayTileSet newTiles = {0};
fetchTiles( server, ii, numAssigned, NULL, &newTiles );
model_assignPlayerTiles( model, ii, &newTiles );
}
sortTilesIf( server, ii );
}
return allDone;
} /* assignTilesToAll */
#ifndef XWFEATURE_STANDALONE_ONLY