From 85df0cc7fb4615285b13c60ad841f47cd3b3d614 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sat, 17 Feb 2024 12:59:30 -0800 Subject: [PATCH] add trading tiles to test script and app --- xwords4/common/board.c | 4 ++-- xwords4/common/dictnry.c | 2 ++ xwords4/common/model.c | 12 +++++----- xwords4/common/server.c | 3 ++- xwords4/linux/cursesboard.c | 34 ++++++++++++++++++++------- xwords4/linux/cursesboard.h | 2 +- xwords4/linux/cursesmain.c | 4 +++- xwords4/linux/scripts/netGamesTest.py | 5 ++-- 8 files changed, 45 insertions(+), 21 deletions(-) diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 41561b553..43ffc8c2f 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -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 nothing */ } else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board, xwe ) ) { - PerTurnInfo* pti = board->pti + selPlayer; + PerTurnInfo* pti = &board->pti[selPlayer]; if ( pti->tradeInProgress ) { TileBit traySelBits = pti->traySelBits; int count = 0; @@ -3539,7 +3539,7 @@ figureNextLoc( const BoardCtxt* board, XP_Key cursorKey, end = max; break; default: - XP_LOGF( "%s: odd cursor key: %d", __func__, cursorKey ); + XP_LOGFF( "odd cursor key: %d", cursorKey ); } if ( incr != 0 ) { diff --git a/xwords4/common/dictnry.c b/xwords4/common/dictnry.c index f7731b370..8720dce91 100644 --- a/xwords4/common/dictnry.c +++ b/xwords4/common/dictnry.c @@ -641,6 +641,8 @@ dict_tilesToString( const DictionaryCtxt* dict, const Tile* tiles, if ( !!bufp && bufp < end ) { *bufp = '\0'; result = bufp - buf; + } else { + XP_ASSERT(0); } return result; } /* dict_tilesToString */ diff --git a/xwords4/common/model.c b/xwords4/common/model.c index 071586f05..cb77d62b0 100644 --- a/xwords4/common/model.c +++ b/xwords4/common/model.c @@ -1521,15 +1521,14 @@ model_packTilesUtil( ModelCtxt* model, PoolContext* pool, const DictionaryCtxt* dict = model_getDictionary(model); XP_U16 nFaces = dict_numTileFaces( dict ); Tile blankFace = dict_getBlankTile( dict ); - Tile tile; XP_U16 nFacesAvail = 0; XP_ASSERT( nFaces <= *nUsed ); - for ( tile = 0; tile < nFaces; ++tile ) { + for ( Tile tile = 0; tile < nFaces; ++tile ) { if ( includeBlank ) { XP_ASSERT( !!pool ); - if ( pool_getNTilesLeftFor( pool, tile ) == 0 ) { + if ( 0 == pool_getNTilesLeftFor( pool, tile ) ) { continue; } } else if ( tile == blankFace ) { @@ -2310,7 +2309,7 @@ printMovePre( ModelCtxt* model, XWEnv xwe, XP_U16 XP_UNUSED(moveN), if ( entry->moveType != ASSIGN_TYPE ) { const XP_UCHAR* format; XP_UCHAR buf[64]; - XP_UCHAR traybuf[MAX_TRAY_TILES+1]; + XP_UCHAR traybuf[32]; MovePrintClosure* closure = (MovePrintClosure*)p_closure; XWStreamCtxt* stream = closure->stream; @@ -2388,14 +2387,15 @@ printMovePost( ModelCtxt* model, XWEnv xwe, XP_U16 XP_UNUSED(moveN), XP_U16 nTiles; XP_UCHAR buf[100]; - XP_UCHAR traybuf1[MAX_TRAY_TILES+1]; - XP_UCHAR traybuf2[MAX_TRAY_TILES+1]; + XP_UCHAR traybuf1[32]; + XP_UCHAR traybuf2[32]; const MoveInfo* mi; XP_S16 totalScore = model_getPlayerScore( model, entry->playerNum ); XP_Bool addCR = XP_FALSE; switch( entry->moveType ) { case TRADE_TYPE: + XP_ASSERT( entry->u.trade.oldTiles.nTiles == entry->u.trade.newTiles.nTiles ); formatTray( (const TrayTileSet*)&entry->u.trade.oldTiles, dict, traybuf1, sizeof(traybuf1), closure->keepHidden ); formatTray( (const TrayTileSet*) &entry->u.trade.newTiles, diff --git a/xwords4/common/server.c b/xwords4/common/server.c index 5f3d0ee59..521404ba6 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -2718,6 +2718,7 @@ fetchTiles( ServerCtxt* server, XWEnv xwe, XP_U16 playerNum, XP_U16 nToFetch, XP_U16 nLeftInPool = pool_getNTilesLeft( pool ); if ( nLeftInPool < nToFetch ) { + XP_LOGFF( "dropping nToFetch from %d to %d", nToFetch, nLeftInPool ); nToFetch = nLeftInPool; } @@ -3926,7 +3927,7 @@ server_commitTrade( ServerCtxt* server, XWEnv xwe, const TrayTileSet* oldTiles, if ( server->vol.gi->serverRole == SERVER_ISCLIENT ) { /* just send to server */ 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, HOST_DEVICE ); } diff --git a/xwords4/linux/cursesboard.c b/xwords4/linux/cursesboard.c index cd034d6c1..a288fb71b 100644 --- a/xwords4/linux/cursesboard.c +++ b/xwords4/linux/cursesboard.c @@ -718,23 +718,41 @@ cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, RematchOrder ro, } 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 = findOrOpenForGameID( cbState, gameID, NULL, NULL ); 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 ) { - CommonGlobals* cGlobals = &bGlobals->cGlobals; BoardCtxt* board = cGlobals->game.board; - success = board_canHint( board ); - if ( success ) { + if ( tryTrade && board_canTrade( board, NULL_XWE ) ) { + ModelCtxt* model = cGlobals->game.model; + + TrayTileSet oldTiles = *model_getPlayerTiles( model, turn ); + success = server_commitTrade( server, NULL_XWE, &oldTiles, NULL ); + } else { XP_Bool ignored; - success = board_requestHint( board, NULL_XWE, + if ( board_canHint( board ) + && board_requestHint( board, NULL_XWE, #ifdef XWFEATURE_SEARCHLIMIT - XP_FALSE, + XP_FALSE, #endif - XP_FALSE, &ignored ); - if ( !success ) { + XP_FALSE, &ignored ) ) { + /* nothing to do -- we have a hint */ + } else { XP_LOGFF( "unable to find hint; so PASSing" ); } success = board_commitTurn( board, NULL_XWE, XP_TRUE, XP_TRUE, diff --git a/xwords4/linux/cursesboard.h b/xwords4/linux/cursesboard.h index a2022aa4f..801bcdbb4 100644 --- a/xwords4/linux/cursesboard.h +++ b/xwords4/linux/cursesboard.h @@ -55,7 +55,7 @@ void cb_addInvites( CursesBoardState* cbState, XP_U32 gameID, XP_U16 nRemotes, XP_U16 forceChannels[], const CommsAddrRec destAddrs[] ); XP_Bool cb_makeRematch( CursesBoardState* cbState, XP_U32 gameID, 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 ); const CommonGlobals* cb_getForGameID( CursesBoardState* cbState, XP_U32 gameID ); diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index 0e31bf31e..e67ddc70a 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -1602,7 +1602,9 @@ static XP_Bool moveifFromArgs( CursesAppGlobals* aGlobals, cJSON* 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 diff --git a/xwords4/linux/scripts/netGamesTest.py b/xwords4/linux/scripts/netGamesTest.py index 62298507b..be24ed796 100755 --- a/xwords4/linux/scripts/netGamesTest.py +++ b/xwords4/linux/scripts/netGamesTest.py @@ -267,7 +267,8 @@ class Device(): gids = [game.gid for game in self._allGames() if not self.gameOver(game.gid)] random.shuffle(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) if moved: break return moved @@ -786,7 +787,7 @@ def mkParser(): # # echo " [--undo-pct ] \\" >&2 # 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('--without-sms', dest = 'WITH_SMS', default = False, action = 'store_false')