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"; -*- */ /* -*- 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. * reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -2573,7 +2573,7 @@ setContains( const TrayTileSet* tiles, Tile tile )
#ifdef DEBUG #ifdef DEBUG
static void static void
assertDiffTurn( ModelCtxt* model, XP_U16 XP_UNUSED(turn), assertDiffTurn( ModelCtxt* model, XP_U16 XP_UNUSED(turn),
const StackEntry* entry, void* closure) const StackEntry* entry, void* closure )
{ {
if ( 1 < model->nPlayers ) { if ( 1 < model->nPlayers ) {
DiffTurnState* state = (DiffTurnState*)closure; DiffTurnState* state = (DiffTurnState*)closure;

View file

@ -132,7 +132,7 @@ struct ServerCtxt {
#define NPASSES_OK(s) model_recentPassCountOk((s)->vol.model) #define NPASSES_OK(s) model_recentPassCountOk((s)->vol.model)
/******************************* prototypes *******************************/ /******************************* prototypes *******************************/
static void assignTilesToAll( ServerCtxt* server ); static XP_Bool assignTilesToAll( ServerCtxt* server );
static void makePoolOnce( ServerCtxt* server ); static void makePoolOnce( ServerCtxt* server );
static void resetEngines( ServerCtxt* server ); static void resetEngines( ServerCtxt* server );
@ -777,7 +777,7 @@ handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
XP_ASSERT( ii == playersInMsg ); /* otherwise malformed */ XP_ASSERT( ii == playersInMsg ); /* otherwise malformed */
setStreamVersion( server ); setStreamVersion( server );
checkResizeBoard( server ); checkResizeBoard( server );
assignTilesToAll( server ); (void)assignTilesToAll( server );
SETSTATE( server, XWSTATE_RECEIVED_ALL_REG ); SETSTATE( server, XWSTATE_RECEIVED_ALL_REG );
} }
informMissing( server ); informMissing( server );
@ -1057,6 +1057,8 @@ void
server_tilesPicked( ServerCtxt* server, XP_U16 player, server_tilesPicked( ServerCtxt* server, XP_U16 player,
const TrayTileSet* newTilesP ) const TrayTileSet* newTilesP )
{ {
XP_ASSERT( 0 == model_getNumTilesInTray( server->vol.model, player ) );
TrayTileSet newTiles = *newTilesP; TrayTileSet newTiles = *newTilesP;
pool_removeTiles( server->pool, &newTiles ); pool_removeTiles( server->pool, &newTiles );
@ -1089,28 +1091,6 @@ informNeedPickTiles( ServerCtxt* server, XP_Bool initial, XP_U16 turn,
nToPick, nFaces, faces, counts ); 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 XP_Bool
server_do( ServerCtxt* server ) server_do( ServerCtxt* server )
{ {
@ -1126,8 +1106,7 @@ server_do( ServerCtxt* server )
case XWSTATE_BEGIN: case XWSTATE_BEGIN:
if ( server->nv.pendingRegistrations == 0 ) { /* all players on if ( server->nv.pendingRegistrations == 0 ) { /* all players on
device */ device */
if ( !askedForTiles( server ) ) { if ( assignTilesToAll( server ) ) {
assignTilesToAll( server );
SETSTATE( server, XWSTATE_INTURN ); SETSTATE( server, XWSTATE_INTURN );
setTurn( server, 0 ); setTurn( server, 0 );
moreToDo = XP_TRUE; moreToDo = XP_TRUE;
@ -1941,15 +1920,17 @@ makePoolOnce( ServerCtxt* server )
} }
} }
static void static XP_Bool
assignTilesToAll( ServerCtxt* server ) assignTilesToAll( ServerCtxt* server )
{ {
XP_Bool allDone = XP_TRUE;
XP_U16 numAssigned; XP_U16 numAssigned;
XP_U16 ii; XP_U16 ii;
ModelCtxt* model = server->vol.model; 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 ); makePoolOnce( server );
XP_STATUSF( "assignTilesToAll" ); XP_STATUSF( "assignTilesToAll" );
@ -1960,15 +1941,27 @@ assignTilesToAll( ServerCtxt* server )
if ( numAssigned > MAX_TRAY_TILES ) { if ( numAssigned > MAX_TRAY_TILES ) {
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 ) { for ( ii = 0; ii < nPlayers; ++ii ) {
if ( 0 == model_getNumTilesInTray( model, 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}; TrayTileSet newTiles = {0};
fetchTiles( server, ii, numAssigned, NULL, &newTiles ); fetchTiles( server, ii, numAssigned, NULL, &newTiles );
model_assignPlayerTiles( model, ii, &newTiles ); model_assignPlayerTiles( model, ii, &newTiles );
} }
sortTilesIf( server, ii ); sortTilesIf( server, ii );
} }
return allDone;
} /* assignTilesToAll */ } /* assignTilesToAll */
#ifndef XWFEATURE_STANDALONE_ONLY #ifndef XWFEATURE_STANDALONE_ONLY