mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-07 05:24:46 +01:00
when a move comes in whose hash doesn't match the top of the move
stack, go down the stack looking for a match. If it's found, pop down to that point then apply the move. This fixes stalls in the test engine when undo is enabled, and so I assume that undos and turns are somehow coming in out-of-order. Should be rare that this happens.
This commit is contained in:
parent
dd242c3ff5
commit
02d5d26c60
3 changed files with 63 additions and 4 deletions
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
|
||||
/*
|
||||
* Copyright 2000-2011 by Eric House (xwords@eehouse.org). All rights
|
||||
* Copyright 2000-2015 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -342,6 +342,56 @@ model_hashMatches( const ModelCtxt* model, const XP_U32 hash )
|
|||
return matches;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
model_revertToHash( ModelCtxt* model, const XP_U32 hash, PoolContext* pool )
|
||||
{
|
||||
XP_U16 nPopped = 0;
|
||||
StackCtxt* stack = model->vol.stack;
|
||||
const XP_U16 nEntries = stack_getNEntries( stack );
|
||||
StackEntry entries[nEntries];
|
||||
#ifdef DEBUG
|
||||
XP_U32 hashes[nEntries];
|
||||
#endif
|
||||
XP_S16 foundAt = -1;
|
||||
|
||||
for ( XP_U16 ii = 0; ii < nEntries; ++ii ) {
|
||||
XP_U32 thisHash =
|
||||
#ifdef DEBUG
|
||||
hashes[ii] =
|
||||
#endif
|
||||
stack_getHash( stack );
|
||||
if ( hash == thisHash ) {
|
||||
foundAt = ii;
|
||||
break;
|
||||
}
|
||||
if ( ! stack_popEntry( stack, &entries[ii] ) ) {
|
||||
break;
|
||||
}
|
||||
++nPopped;
|
||||
}
|
||||
|
||||
for ( XP_S16 ii = nPopped - 1; ii >= 0; --ii ) {
|
||||
stack_redo( stack, &entries[ii] );
|
||||
/* Assert not needed for long */
|
||||
XP_ASSERT( hashes[ii] = stack_getHash( stack ) );
|
||||
}
|
||||
|
||||
XP_Bool found = -1 != foundAt;
|
||||
if ( found ) {
|
||||
XP_LOGF( "%s: undoing %d turns to match hash %X", __func__,
|
||||
foundAt, hash );
|
||||
#ifdef DEBUG
|
||||
XP_Bool success =
|
||||
#endif
|
||||
model_undoLatestMoves( model, pool, foundAt, NULL, NULL );
|
||||
XP_ASSERT( success );
|
||||
/* Assert not needed for long */
|
||||
XP_ASSERT( hash == stack_getHash( model->vol.stack ) );
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void
|
||||
model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses, XP_U16 nBonuses )
|
||||
|
|
|
@ -124,6 +124,9 @@ void model_setSize( ModelCtxt* model, XP_U16 boardSize );
|
|||
void model_destroy( ModelCtxt* model );
|
||||
XP_U32 model_getHash( const ModelCtxt* model, XP_U16 version );
|
||||
XP_Bool model_hashMatches( const ModelCtxt* model, XP_U32 hash );
|
||||
XP_Bool model_revertToHash( ModelCtxt* model, const XP_U32 hash,
|
||||
PoolContext* pool );
|
||||
|
||||
void model_setNPlayers( ModelCtxt* model, XP_U16 numPlayers );
|
||||
XP_U16 model_getNPlayers( const ModelCtxt* model );
|
||||
|
||||
|
|
|
@ -2086,11 +2086,17 @@ readMoveInfo( ServerCtxt* server, XWStreamCtxt* stream,
|
|||
#ifdef STREAM_VERS_BIGBOARD
|
||||
if ( STREAM_VERS_BIGBOARD <= stream_getVersion( stream ) ) {
|
||||
XP_U32 hashReceived = stream_getU32( stream );
|
||||
success = model_hashMatches( server->vol.model, hashReceived );
|
||||
success = model_hashMatches( server->vol.model, hashReceived )
|
||||
|| model_revertToHash( server->vol.model, hashReceived,
|
||||
server->pool );
|
||||
// XP_ASSERT( success ); /* I need to understand when this can fail */
|
||||
if ( !success ) {
|
||||
XP_LOGF( "%s: hash mismatch",__func__);
|
||||
#ifdef DEBUG_HASHING
|
||||
if ( success ) {
|
||||
XP_LOGF( "%s: hash match: %X",__func__, hashReceived );
|
||||
} else {
|
||||
XP_LOGF( "%s: hash mismatch: %X not found",__func__, hashReceived );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if ( success ) {
|
||||
|
|
Loading…
Reference in a new issue