add trading tiles to test script and app

This commit is contained in:
Eric House 2024-02-17 12:59:30 -08:00
parent 660584e4ee
commit 85df0cc7fb
8 changed files with 45 additions and 21 deletions

View file

@ -1092,7 +1092,7 @@ board_commitTurn( BoardCtxt* board, XWEnv xwe, XP_Bool phoniesConfirmed,
/* game's over but still undoable so turn hasn't changed; do /* game's over but still undoable so turn hasn't changed; do
nothing */ nothing */
} else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board, xwe ) ) { } else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board, xwe ) ) {
PerTurnInfo* pti = board->pti + selPlayer; PerTurnInfo* pti = &board->pti[selPlayer];
if ( pti->tradeInProgress ) { if ( pti->tradeInProgress ) {
TileBit traySelBits = pti->traySelBits; TileBit traySelBits = pti->traySelBits;
int count = 0; int count = 0;
@ -3539,7 +3539,7 @@ figureNextLoc( const BoardCtxt* board, XP_Key cursorKey,
end = max; end = max;
break; break;
default: default:
XP_LOGF( "%s: odd cursor key: %d", __func__, cursorKey ); XP_LOGFF( "odd cursor key: %d", cursorKey );
} }
if ( incr != 0 ) { if ( incr != 0 ) {

View file

@ -641,6 +641,8 @@ dict_tilesToString( const DictionaryCtxt* dict, const Tile* tiles,
if ( !!bufp && bufp < end ) { if ( !!bufp && bufp < end ) {
*bufp = '\0'; *bufp = '\0';
result = bufp - buf; result = bufp - buf;
} else {
XP_ASSERT(0);
} }
return result; return result;
} /* dict_tilesToString */ } /* dict_tilesToString */

View file

@ -1521,15 +1521,14 @@ model_packTilesUtil( ModelCtxt* model, PoolContext* pool,
const DictionaryCtxt* dict = model_getDictionary(model); const DictionaryCtxt* dict = model_getDictionary(model);
XP_U16 nFaces = dict_numTileFaces( dict ); XP_U16 nFaces = dict_numTileFaces( dict );
Tile blankFace = dict_getBlankTile( dict ); Tile blankFace = dict_getBlankTile( dict );
Tile tile;
XP_U16 nFacesAvail = 0; XP_U16 nFacesAvail = 0;
XP_ASSERT( nFaces <= *nUsed ); XP_ASSERT( nFaces <= *nUsed );
for ( tile = 0; tile < nFaces; ++tile ) { for ( Tile tile = 0; tile < nFaces; ++tile ) {
if ( includeBlank ) { if ( includeBlank ) {
XP_ASSERT( !!pool ); XP_ASSERT( !!pool );
if ( pool_getNTilesLeftFor( pool, tile ) == 0 ) { if ( 0 == pool_getNTilesLeftFor( pool, tile ) ) {
continue; continue;
} }
} else if ( tile == blankFace ) { } else if ( tile == blankFace ) {
@ -2310,7 +2309,7 @@ printMovePre( ModelCtxt* model, XWEnv xwe, XP_U16 XP_UNUSED(moveN),
if ( entry->moveType != ASSIGN_TYPE ) { if ( entry->moveType != ASSIGN_TYPE ) {
const XP_UCHAR* format; const XP_UCHAR* format;
XP_UCHAR buf[64]; XP_UCHAR buf[64];
XP_UCHAR traybuf[MAX_TRAY_TILES+1]; XP_UCHAR traybuf[32];
MovePrintClosure* closure = (MovePrintClosure*)p_closure; MovePrintClosure* closure = (MovePrintClosure*)p_closure;
XWStreamCtxt* stream = closure->stream; XWStreamCtxt* stream = closure->stream;
@ -2388,14 +2387,15 @@ printMovePost( ModelCtxt* model, XWEnv xwe, XP_U16 XP_UNUSED(moveN),
XP_U16 nTiles; XP_U16 nTiles;
XP_UCHAR buf[100]; XP_UCHAR buf[100];
XP_UCHAR traybuf1[MAX_TRAY_TILES+1]; XP_UCHAR traybuf1[32];
XP_UCHAR traybuf2[MAX_TRAY_TILES+1]; XP_UCHAR traybuf2[32];
const MoveInfo* mi; const MoveInfo* mi;
XP_S16 totalScore = model_getPlayerScore( model, entry->playerNum ); XP_S16 totalScore = model_getPlayerScore( model, entry->playerNum );
XP_Bool addCR = XP_FALSE; XP_Bool addCR = XP_FALSE;
switch( entry->moveType ) { switch( entry->moveType ) {
case TRADE_TYPE: case TRADE_TYPE:
XP_ASSERT( entry->u.trade.oldTiles.nTiles == entry->u.trade.newTiles.nTiles );
formatTray( (const TrayTileSet*)&entry->u.trade.oldTiles, formatTray( (const TrayTileSet*)&entry->u.trade.oldTiles,
dict, traybuf1, sizeof(traybuf1), closure->keepHidden ); dict, traybuf1, sizeof(traybuf1), closure->keepHidden );
formatTray( (const TrayTileSet*) &entry->u.trade.newTiles, formatTray( (const TrayTileSet*) &entry->u.trade.newTiles,

View file

@ -2718,6 +2718,7 @@ fetchTiles( ServerCtxt* server, XWEnv xwe, XP_U16 playerNum, XP_U16 nToFetch,
XP_U16 nLeftInPool = pool_getNTilesLeft( pool ); XP_U16 nLeftInPool = pool_getNTilesLeft( pool );
if ( nLeftInPool < nToFetch ) { if ( nLeftInPool < nToFetch ) {
XP_LOGFF( "dropping nToFetch from %d to %d", nToFetch, nLeftInPool );
nToFetch = nLeftInPool; nToFetch = nLeftInPool;
} }
@ -3926,7 +3927,7 @@ server_commitTrade( ServerCtxt* server, XWEnv xwe, const TrayTileSet* oldTiles,
if ( server->vol.gi->serverRole == SERVER_ISCLIENT ) { if ( server->vol.gi->serverRole == SERVER_ISCLIENT ) {
/* just send to server */ /* just send to server */
sendMoveTo(server, xwe, HOST_DEVICE, turn, XP_TRUE, &newTiles, oldTiles); sendMoveTo(server, xwe, HOST_DEVICE, turn, XP_TRUE, &newTiles, oldTiles);
} else { } else if ( server->vol.gi->serverRole == SERVER_ISHOST ) {
sendMoveToClientsExcept( server, xwe, turn, XP_TRUE, &newTiles, oldTiles, sendMoveToClientsExcept( server, xwe, turn, XP_TRUE, &newTiles, oldTiles,
HOST_DEVICE ); HOST_DEVICE );
} }

View file

@ -718,23 +718,41 @@ cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, RematchOrder ro,
} }
XP_Bool XP_Bool
cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID ) cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID, XP_Bool tryTrade )
{ {
XP_LOGFF( "(tryTrade: %s)", boolToStr(tryTrade));
CursesBoardGlobals* bGlobals = CursesBoardGlobals* bGlobals =
findOrOpenForGameID( cbState, gameID, NULL, NULL ); findOrOpenForGameID( cbState, gameID, NULL, NULL );
XP_Bool success = !!bGlobals; XP_Bool success = !!bGlobals;
CommonGlobals* cGlobals;
ServerCtxt* server;
XP_S16 turn = -1;
if ( success ) {
cGlobals = &bGlobals->cGlobals;
server = cGlobals->game.server;
XP_Bool isLocal;
turn = server_getCurrentTurn( server, &isLocal );
success = 0 <= turn && isLocal;
}
if ( success ) { if ( success ) {
CommonGlobals* cGlobals = &bGlobals->cGlobals;
BoardCtxt* board = cGlobals->game.board; BoardCtxt* board = cGlobals->game.board;
success = board_canHint( board ); if ( tryTrade && board_canTrade( board, NULL_XWE ) ) {
if ( success ) { ModelCtxt* model = cGlobals->game.model;
TrayTileSet oldTiles = *model_getPlayerTiles( model, turn );
success = server_commitTrade( server, NULL_XWE, &oldTiles, NULL );
} else {
XP_Bool ignored; XP_Bool ignored;
success = board_requestHint( board, NULL_XWE, if ( board_canHint( board )
&& board_requestHint( board, NULL_XWE,
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
XP_FALSE, XP_FALSE,
#endif #endif
XP_FALSE, &ignored ); XP_FALSE, &ignored ) ) {
if ( !success ) { /* nothing to do -- we have a hint */
} else {
XP_LOGFF( "unable to find hint; so PASSing" ); XP_LOGFF( "unable to find hint; so PASSing" );
} }
success = board_commitTurn( board, NULL_XWE, XP_TRUE, XP_TRUE, success = board_commitTurn( board, NULL_XWE, XP_TRUE, XP_TRUE,

View file

@ -55,7 +55,7 @@ void cb_addInvites( CursesBoardState* cbState, XP_U32 gameID, XP_U16 nRemotes,
XP_U16 forceChannels[], const CommsAddrRec destAddrs[] ); XP_U16 forceChannels[], const CommsAddrRec destAddrs[] );
XP_Bool cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, XP_Bool cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID,
RematchOrder ro, XP_U32* newGameID ); RematchOrder ro, XP_U32* newGameID );
XP_Bool cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID ); XP_Bool cb_makeMoveIf( CursesBoardState* cbState, XP_U32 gameID, XP_Bool tryTrade );
XP_Bool cb_sendChat( CursesBoardState* cbState, XP_U32 gameID, const char* msg ); XP_Bool cb_sendChat( CursesBoardState* cbState, XP_U32 gameID, const char* msg );
const CommonGlobals* cb_getForGameID( CursesBoardState* cbState, XP_U32 gameID ); const CommonGlobals* cb_getForGameID( CursesBoardState* cbState, XP_U32 gameID );

View file

@ -1602,7 +1602,9 @@ static XP_Bool
moveifFromArgs( CursesAppGlobals* aGlobals, cJSON* args ) moveifFromArgs( CursesAppGlobals* aGlobals, cJSON* args )
{ {
XP_U32 gameID = gidFromObject( args ); XP_U32 gameID = gidFromObject( args );
return cb_makeMoveIf( aGlobals->cbState, gameID ); cJSON* tmp = cJSON_GetObjectItem( args, "tryTrade" );
XP_Bool tryTrade = !!tmp && cJSON_IsTrue( tmp );
return cb_makeMoveIf( aGlobals->cbState, gameID, tryTrade );
} }
static XP_Bool static XP_Bool

View file

@ -267,7 +267,8 @@ class Device():
gids = [game.gid for game in self._allGames() if not self.gameOver(game.gid)] gids = [game.gid for game in self._allGames() if not self.gameOver(game.gid)]
random.shuffle(gids) random.shuffle(gids)
for gid in gids: for gid in gids:
response = self._sendWaitReply('moveIf', gid=gid) tryTrade = random.randint(0, 99) < self.args.TRADE_PCT
response = self._sendWaitReply('moveIf', gid=gid, tryTrade=tryTrade)
moved = response.get('success', False) moved = response.get('success', False)
if moved: break if moved: break
return moved return moved
@ -786,7 +787,7 @@ def mkParser():
# # echo " [--undo-pct <int>] \\" >&2 # # echo " [--undo-pct <int>] \\" >&2
# parser.add_argument('--undo-pct', dest = 'UNDO_PCT', default = 0, type = int) # parser.add_argument('--undo-pct', dest = 'UNDO_PCT', default = 0, type = int)
# parser.add_argument('--trade-pct', dest = 'TRADE_PCT', default = 10, type = int) parser.add_argument('--trade-pct', dest = 'TRADE_PCT', default = 10, type = int)
parser.add_argument('--with-sms', dest = 'WITH_SMS', action = 'store_true') parser.add_argument('--with-sms', dest = 'WITH_SMS', action = 'store_true')
parser.add_argument('--without-sms', dest = 'WITH_SMS', default = False, action = 'store_false') parser.add_argument('--without-sms', dest = 'WITH_SMS', default = False, action = 'store_false')