Merge branch 'android_branch' of ssh://xwords.git.sourceforge.net/gitroot/xwords/xwords into android_branch

This commit is contained in:
Eric House 2011-04-04 16:16:09 -07:00
commit 0ce963336a
20 changed files with 213 additions and 91 deletions

View file

@ -382,7 +382,8 @@ and_draw_objFinished( DrawCtx* dctx, BoardObjectType typ,
}
static void
and_draw_dictChanged( DrawCtx* dctx, const DictionaryCtxt* dict )
and_draw_dictChanged( DrawCtx* dctx, XP_S16 playerNum,
const DictionaryCtxt* dict )
{
AndDraw* draw = (AndDraw*)dctx;
if ( NULL != draw->jdraw ) {

View file

@ -230,8 +230,8 @@ Java_org_eehouse_android_xw4_jni_XwJNI_gi_1from_1stream
CurGameInfo gi;
XP_MEMSET( &gi, 0, sizeof(gi) );
if ( game_makeFromStream( MPPARM(mpool) stream, NULL,
&gi, NULL, NULL, NULL, NULL, NULL ) ) {
if ( game_makeFromStream( MPPARM(mpool) stream, NULL,
&gi, NULL, NULL, NULL, NULL, NULL, NULL ) ) {
setJGI( env, jgi, &gi );
} else {
XP_LOGF( "%s: game_makeFromStream failed", __func__ );
@ -458,7 +458,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream
CommonPrefs cp;
loadCommonPrefs( env, &cp, jcp );
result = game_makeFromStream( MPPARM(mpool) stream, &state->game,
globals->gi, dict,
globals->gi, dict, NULL,
globals->util, globals->dctx, &cp,
globals->xportProcs );
stream_destroy( stream );

View file

@ -84,7 +84,8 @@ static void boardCellChanged( void* board, XP_U16 turn, XP_U16 col,
XP_U16 row, XP_Bool added );
static void boardTilesChanged( void* board, XP_U16 turn, XP_S16 index1,
XP_S16 index2 );
static void dictChanged( void* p_board, const DictionaryCtxt* oldDict,
static void dictChanged( void* p_board, XP_S16 playerNum,
const DictionaryCtxt* oldDict,
const DictionaryCtxt* newDict );
static void boardTurnChanged( void* board );
@ -1708,14 +1709,14 @@ board_requestHint( BoardCtxt* board,
}
}
#endif
searchComplete = engine_findMove(engine, model,
model_getDictionary(model),
tiles, nTiles, usePrev,
searchComplete =
engine_findMove( engine, model, selPlayer,
tiles, nTiles, usePrev,
#ifdef XWFEATURE_SEARCHLIMIT
lp, useTileLimits,
lp, useTileLimits,
#endif
0, /* 0: not a robot */
&canMove, &newMove );
0, /* 0: not a robot */
&canMove, &newMove );
board_popTimerSave( board );
if ( searchComplete && canMove ) {
@ -3324,13 +3325,13 @@ boardTilesChanged( void* p_board, XP_U16 turn, XP_S16 index1, XP_S16 index2 )
} /* boardTilesChanged */
static void
dictChanged( void* p_board, const DictionaryCtxt* oldDict,
dictChanged( void* p_board, XP_S16 playerNum, const DictionaryCtxt* oldDict,
const DictionaryCtxt* newDict )
{
BoardCtxt* board = (BoardCtxt*)p_board;
if ( !!board->draw ) {
if ( (NULL == oldDict) || (oldDict != newDict) ) {
draw_dictChanged( board->draw, newDict );
draw_dictChanged( board->draw, playerNum, newDict );
}
}
}

View file

@ -138,6 +138,10 @@ typedef struct CommonPrefs {
XP_Bool allowPeek; /* applies to all games */
} CommonPrefs;
typedef struct _PlayerDicts {
DictionaryCtxt* dicts[MAX_NUM_PLAYERS];
} PlayerDicts;
#ifdef XWFEATURE_BLUETOOTH
/* temporary debugging hack */

View file

@ -113,7 +113,7 @@ typedef struct DrawCtxVTable {
void DRAW_VTABLE_NAME(destroyCtxt) ( DrawCtx* dctx );
void DRAW_VTABLE_NAME(dictChanged)( DrawCtx* dctx,
void DRAW_VTABLE_NAME(dictChanged)( DrawCtx* dctx, XP_S16 playerNum,
const DictionaryCtxt* dict );
XP_Bool DRAW_VTABLE_NAME(boardBegin) ( DrawCtx* dctx,
@ -252,7 +252,7 @@ struct DrawCtx {
#endif
#define draw_destroyCtxt(dc) CALL_DRAW_NAME0(destroyCtxt, dc)
#define draw_dictChanged( dc, d ) CALL_DRAW_NAME1(dictChanged, (dc), (d))
#define draw_dictChanged( dc, n, d ) CALL_DRAW_NAME2(dictChanged, (dc), (n), (d))
#define draw_boardBegin( dc,r,h,v,f ) CALL_DRAW_NAME4(boardBegin, (dc),\
(r),(h),(v),(f))
#define draw_objFinished( dc, t, r, d ) CALL_DRAW_NAME3(objFinished, (dc), (t), (r), (d))

View file

@ -84,6 +84,7 @@ struct EngineCtxt {
const ModelCtxt* model;
const DictionaryCtxt* dict;
XW_UtilCtxt* util;
XP_U16 turn;
Engine_rack rack;
Tile blankTile;
@ -407,7 +408,7 @@ normalizeIQ( EngineCtxt* engine, XP_U16 iq )
*/
XP_Bool
engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
const DictionaryCtxt* dict, const Tile* tiles,
XP_U16 turn, const Tile* tiles,
XP_U16 nTiles, XP_Bool usePrev,
#ifdef XWFEATURE_SEARCHLIMIT
const BdHintLimits* searchLimits,
@ -448,9 +449,10 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
#endif
engine->model = model;
engine->dict = dict;
engine->dict = model_getPlayerDict( model, turn );
engine->turn = turn;
engine->usePrev = usePrev;
engine->blankTile = dict_getBlankTile( dict );
engine->blankTile = dict_getBlankTile( engine->dict );
engine->returnNOW = XP_FALSE;
#ifdef XWFEATURE_SEARCHLIMIT
engine->searchLimits = searchLimits;
@ -465,8 +467,8 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
dictionary's emtpy or there are no tiles, still return TRUE so we don't
get scheduled again. Fixes infinite loop with empty dict and a
robot. */
*canMoveP = dict_getTopEdge(dict) != NULL && initTray( engine, tiles,
nTiles );
*canMoveP = NULL != dict_getTopEdge(engine->dict)
&& initTray( engine, tiles, nTiles );
if ( *canMoveP ) {
util_engineStarting( engine->util,
@ -1116,7 +1118,7 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
if ( blanksLeft == 0 ) {
XP_U16 score;
score = figureMoveScore( engine->model,
score = figureMoveScore( engine->model, engine->turn,
&posmove->moveInfo,
engine, (XWStreamCtxt*)NULL,
(WordNotifierInfo*)NULL, NULL, 0 );

View file

@ -49,7 +49,7 @@ void engine_reset( EngineCtxt* ctxt );
void engine_destroy( EngineCtxt* ctxt );
XP_Bool engine_findMove( EngineCtxt* ctxt, const ModelCtxt* model,
const DictionaryCtxt* dict, const Tile* tiles,
XP_U16 turn, const Tile* tiles,
XP_U16 nTiles, XP_Bool usePrev,
#ifdef XWFEATURE_SEARCHLIMIT
const BdHintLimits* boardLimits,

View file

@ -85,7 +85,7 @@ game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
}
gi->gameID = gameID;
game->model = model_make( MPPARM(mpool) (DictionaryCtxt*)NULL, util,
game->model = model_make( MPPARM(mpool) (DictionaryCtxt*)NULL, NULL, util,
gi->boardSize, gi->boardSize );
#ifndef XWFEATURE_STANDALONE_ONLY
@ -170,6 +170,7 @@ game_reset( MPFORMAL XWGame* game, CurGameInfo* gi,
XP_Bool
game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
CurGameInfo* gi, DictionaryCtxt* dict,
const PlayerDicts* dicts,
XW_UtilCtxt* util, DrawCtx* draw, CommonPrefs* cp,
const TransportProcs* procs )
{
@ -217,8 +218,8 @@ game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
game->comms = NULL;
}
XP_ASSERT( !!dict );
game->model = model_makeFromStream( MPPARM(mpool) stream, dict, util );
game->model = model_makeFromStream( MPPARM(mpool) stream, dict,
dicts, util );
game->server = server_makeFromStream( MPPARM(mpool) stream,
game->model, game->comms,
@ -230,7 +231,7 @@ game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
server_prefsChanged( game->server, cp );
board_prefsChanged( game->board, cp );
if ( !!draw ) {
draw_dictChanged( draw, dict );
draw_dictChanged( draw, -1, dict );
}
success = XP_TRUE;
} while( XP_FALSE );
@ -288,10 +289,7 @@ game_dispose( XWGame* game )
}
#endif
if ( !!game->model ) {
DictionaryCtxt* dict = model_getDictionary( game->model );
if ( !!dict ) {
dict_destroy( dict );
}
model_destroyDicts( game->model );
model_destroy( game->model );
game->model = NULL;
}
@ -417,7 +415,7 @@ void
gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
{
LocalPlayer* pl;
XP_U16 i;
XP_U16 ii;
XP_UCHAR* str;
XP_U16 strVersion = stream_getVersion( stream );
@ -458,7 +456,7 @@ gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
gi->gameSeconds = stream_getU16( stream );
}
for ( pl = gi->players, i = 0; i < gi->nPlayers; ++pl, ++i ) {
for ( pl = gi->players, ii = 0; ii < gi->nPlayers; ++pl, ++ii ) {
str = stringFromStream( mpool, stream );
replaceStringIfDifferent( mpool, &pl->name, str );
if ( !!str ) {
@ -471,6 +469,14 @@ gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
XP_FREE( mpool, str );
}
if ( strVersion >= STREAM_VERS_PLAYERDICTS ) {
str = stringFromStream( mpool, stream );
replaceStringIfDifferent( mpool, &pl->dictName, str );
if ( !!str ) {
XP_FREE( mpool, str );
}
}
pl->secondsUsed = stream_getU16( stream );
pl->robotIQ = ( strVersion < STREAM_VERS_ROBOTIQ )
? (XP_U8)stream_getBits( stream, 1 )
@ -483,7 +489,7 @@ void
gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi )
{
const LocalPlayer* pl;
XP_U16 i;
XP_U16 ii;
stringToStream( stream, gi->dictName );
@ -500,10 +506,11 @@ gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi )
stream_putU16( stream, gi->gameID );
stream_putU8( stream, gi->dictLang );
stream_putU16( stream, gi->gameSeconds );
for ( pl = gi->players, i = 0; i < gi->nPlayers; ++pl, ++i ) {
for ( pl = gi->players, ii = 0; ii < gi->nPlayers; ++pl, ++ii ) {
stringToStream( stream, pl->name );
stringToStream( stream, pl->password );
stringToStream( stream, pl->dictName );
stream_putU16( stream, pl->secondsUsed );
stream_putU8( stream, pl->robotIQ );
stream_putBits( stream, 1, pl->isLocal );

View file

@ -31,6 +31,7 @@
extern "C" {
#endif
#define STREAM_VERS_PLAYERDICTS 0x0F
#define STREAM_SAVE_PREVMOVE 0x0E /* server saves prev move explanation */
#define STREAM_VERS_ROBOTIQ STREAM_SAVE_PREVMOVE /* robots have different smarts */
#define STREAM_VERS_DICTLANG 0x0D /* save dict lang code in CurGameInfo */
@ -50,11 +51,12 @@ extern "C" {
#define STREAM_VERS_41B4 0x02
#define STREAM_VERS_405 0x01
#define CUR_STREAM_VERS STREAM_SAVE_PREVMOVE
#define CUR_STREAM_VERS STREAM_VERS_PLAYERDICTS
typedef struct LocalPlayer {
XP_UCHAR* name;
XP_UCHAR* password;
XP_UCHAR* dictName;
XP_U16 secondsUsed;
XP_Bool isLocal;
XP_U8 robotIQ; /* 0 means not a robot; 1-100 means how
@ -110,8 +112,8 @@ void game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
CommonPrefs* cp, const TransportProcs* procs );
XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
CurGameInfo* gi,
DictionaryCtxt* dict, XW_UtilCtxt* util,
CurGameInfo* gi, DictionaryCtxt* dict,
const PlayerDicts* dicts, XW_UtilCtxt* util,
DrawCtx* draw, CommonPrefs* cp,
const TransportProcs* procs );

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights reserved.
*
@ -50,7 +50,8 @@ static void notifyBoardListeners( ModelCtxt* model, XP_U16 turn,
XP_U16 col, XP_U16 row, XP_Bool added );
static void notifyTrayListeners( ModelCtxt* model, XP_U16 turn,
XP_S16 index1, XP_S16 index2 );
static void notifyDictListeners( ModelCtxt* model, DictionaryCtxt* oldDict,
static void notifyDictListeners( ModelCtxt* model, XP_S16 playerNum,
DictionaryCtxt* oldDict,
DictionaryCtxt* newDict );
static CellTile getModelTileRaw( const ModelCtxt* model, XP_U16 col,
@ -80,7 +81,8 @@ static XP_U16 model_getRecentPassCount( ModelCtxt* model );
*
****************************************************************************/
ModelCtxt*
model_make( MPFORMAL DictionaryCtxt* dict, XW_UtilCtxt* util, XP_U16 nCols,
model_make( MPFORMAL DictionaryCtxt* dict,
const PlayerDicts* dicts, XW_UtilCtxt* util, XP_U16 nCols,
XP_U16 nRows )
{
ModelCtxt* result = (ModelCtxt*)XP_MALLOC( mpool, sizeof( *result ) );
@ -96,6 +98,7 @@ model_make( MPFORMAL DictionaryCtxt* dict, XW_UtilCtxt* util, XP_U16 nCols,
result->vol.gi = util->gameInfo;
model_setDictionary( result, dict );
model_setPlayerDicts( result, dicts );
}
return result;
@ -103,7 +106,7 @@ model_make( MPFORMAL DictionaryCtxt* dict, XW_UtilCtxt* util, XP_U16 nCols,
ModelCtxt*
model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
XW_UtilCtxt* util )
const PlayerDicts* dicts, XW_UtilCtxt* util )
{
ModelCtxt* model;
XP_U16 nCols, nRows;
@ -112,7 +115,7 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
XP_U16 nPlayers;
XP_U16 version = stream_getVersion( stream );
XP_ASSERT( !!dict );
XP_ASSERT( !!dict || !!dicts );
nCols = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
nRows = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
@ -127,7 +130,7 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
dict_destroy( savedDict );
}
model = model_make( MPPARM(mpool) dict, util, nCols, nRows );
model = model_make( MPPARM(mpool) dict, dicts, util, nCols, nRows );
model->nPlayers = nPlayers;
stack_loadFromStream( model->vol.stack, stream );
@ -263,6 +266,16 @@ model_getNPlayers( const ModelCtxt* model )
return model->nPlayers;
}
static void
setStackBits( ModelCtxt* model, const DictionaryCtxt* dict )
{
if ( NULL != dict ) {
XP_U16 nFaces = dict_numTileFaces( dict );
XP_ASSERT( !!model->vol.stack );
stack_setBitsPerTile( model->vol.stack, nFaces <= 32? 5 : 6 );
}
}
void
model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict )
{
@ -270,21 +283,72 @@ model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict )
model->vol.dict = dict;
if ( !!dict ) {
XP_U16 nFaces = dict_numTileFaces( dict );
XP_ASSERT( !!model->vol.stack );
stack_setBitsPerTile( model->vol.stack, nFaces <= 32? 5 : 6 );
notifyDictListeners( model, oldDict, dict );
setStackBits( model, dict );
notifyDictListeners( model, -1, oldDict, dict );
}
} /* model_setDictionary */
void
model_setPlayerDicts( ModelCtxt* model, const PlayerDicts* dicts )
{
if ( !!dicts ) {
XP_U16 ii;
DictionaryCtxt* gameDict = model_getDictionary( model );
for ( ii = 0; ii < VSIZE(dicts->dicts); ++ii ) {
DictionaryCtxt* oldDict = model->vol.dicts.dicts[ii];
DictionaryCtxt* newDict = dicts->dicts[ii];
if ( oldDict != newDict ) {
XP_ASSERT( NULL == newDict || NULL == gameDict
|| dict_tilesAreSame( gameDict, newDict ) );
model->vol.dicts.dicts[ii] = newDict;
notifyDictListeners( model, ii, oldDict, newDict );
setStackBits( model, newDict );
}
}
}
}
DictionaryCtxt*
model_getDictionary( const ModelCtxt* model )
{
/* XP_ASSERT( !!model->vol.dict ); */
return model->vol.dict;
XP_U16 ii;
DictionaryCtxt* result = model->vol.dict;
for ( ii = 0; !result && ii < VSIZE(model->vol.dicts.dicts); ++ii ) {
result = model->vol.dicts.dicts[ii];
}
return result;
} /* model_getDictionary */
DictionaryCtxt*
model_getPlayerDict( const ModelCtxt* model, XP_U16 playerNum )
{
DictionaryCtxt* dict = model->vol.dicts.dicts[playerNum];
if ( NULL == dict ) {
dict = model->vol.dict;
}
XP_ASSERT( !!dict );
return dict;
}
static void
destroyNotNull( DictionaryCtxt** dictp )
{
if ( !!*dictp ) {
dict_destroy( *dictp );
*dictp = NULL;
}
}
void
model_destroyDicts( ModelCtxt* model )
{
XP_U16 ii;
for ( ii = 0; ii < VSIZE(model->vol.dicts.dicts); ++ii ) {
destroyNotNull( &model->vol.dicts.dicts[ii] );
}
destroyNotNull( &model->vol.dict );
}
static XP_Bool
getPendingTileFor( const ModelCtxt* model, XP_U16 turn, XP_U16 col, XP_U16 row,
CellTile* cellTile )
@ -717,7 +781,7 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
XWStreamCtxt* stream )
{
XP_U16 numTiles;
Tile blank = dict_getBlankTile( model->vol.dict );
Tile blank = dict_getBlankTile( model_getDictionary(model) );
model_resetCurrentTurn( model, playerNum );
@ -766,7 +830,7 @@ model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
Tile blank;
XP_U16 numTiles;
blank = dict_getBlankTile( model->vol.dict );
blank = dict_getBlankTile( model_getDictionary( model ) );
numTiles = newMove->nTiles;
col = row = newMove->commonCoord; /* just assign both */
@ -799,8 +863,7 @@ model_countAllTrayTiles( ModelCtxt* model, XP_U16* counts,
XP_S16 i;
Tile blank;
XP_ASSERT( !!model->vol.dict );
blank = dict_getBlankTile( model->vol.dict );
blank = dict_getBlankTile( model_getDictionary(model) );
for ( i = 0, player = model->players; i < nPlayers; ++i, ++player ) {
if ( i != excludePlayer ) {
@ -925,7 +988,7 @@ model_packTilesUtil( ModelCtxt* model, PoolContext* pool,
XP_U16* nUsed, const XP_UCHAR** texts,
Tile* tiles )
{
DictionaryCtxt* dict = model->vol.dict;
DictionaryCtxt* dict = model_getDictionary(model);
XP_U16 nFaces = dict_numTileFaces( dict );
Tile blankFace = dict_getBlankTile( dict );
Tile tile;
@ -986,7 +1049,7 @@ model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col, XP_U16 row,
Tile tile = model_removePlayerTile( model, turn, tileIndex );
if ( tile == dict_getBlankTile(model->vol.dict) ) {
if ( tile == dict_getBlankTile(model_getDictionary(model)) ) {
if ( blankFace != EMPTY_TILE ) {
tile = blankFace;
} else {
@ -1038,7 +1101,7 @@ model_redoPendingTiles( ModelCtxt* model, XP_S16 turn )
XP_S16 foundAt;
if ( isBlank ) {
tile = dict_getBlankTile( model->vol.dict );
tile = dict_getBlankTile( model_getDictionary(model) );
}
foundAt = model_trayContains( model, turn, tile );
XP_ASSERT( foundAt >= 0 );
@ -1082,7 +1145,7 @@ model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
tile = pt->tile;
if ( (tile & TILE_BLANK_BIT) != 0 ) {
tile = dict_getBlankTile( model->vol.dict );
tile = dict_getBlankTile( model_getDictionary(model) );
}
model_addPlayerTile( model, turn, trayOffset, tile );
@ -1551,13 +1614,13 @@ notifyTrayListeners( ModelCtxt* model, XP_U16 turn, XP_S16 index1,
} /* notifyTrayListeners */
static void
notifyDictListeners( ModelCtxt* model, DictionaryCtxt* oldDict,
DictionaryCtxt* newDict )
notifyDictListeners( ModelCtxt* model, XP_S16 playerNum,
DictionaryCtxt* oldDict, DictionaryCtxt* newDict )
{
XP_ASSERT( !!newDict );
if ( model->vol.dictListenerFunc != NULL ) {
(*model->vol.dictListenerFunc)( model->vol.dictListenerData, oldDict,
newDict );
(*model->vol.dictListenerFunc)( model->vol.dictListenerData, playerNum,
oldDict, newDict );
}
} /* notifyDictListeners */
@ -1751,7 +1814,7 @@ makeTmpModel( ModelCtxt* model, XWStreamCtxt* stream,
void* closure )
{
ModelCtxt* tmpModel = model_make( MPPARM(model->vol.mpool)
model_getDictionary(model),
model_getDictionary(model), NULL,
model->vol.util, model_numCols(model),
model_numRows(model));
model_setNPlayers( tmpModel, model->nPlayers );
@ -1811,7 +1874,7 @@ scoreLastMove( ModelCtxt* model, MoveInfo* moveInfo, XP_U16 howMany,
XP_ASSERT( 0 );
}
score = figureMoveScore( tmpModel, moveInfo, (EngineCtxt*)NULL,
score = figureMoveScore( tmpModel, turn, moveInfo, (EngineCtxt*)NULL,
(XWStreamCtxt*)NULL, (WordNotifierInfo*)NULL,
wordBuf, VSIZE(wordBuf) );

View file

@ -100,11 +100,12 @@ typedef XP_U8 TileBit; /* bits indicating selection of tiles in tray */
only */
ModelCtxt* model_make( MPFORMAL DictionaryCtxt* dict, XW_UtilCtxt* util,
XP_U16 nCols, XP_U16 nRows );
ModelCtxt* model_make( MPFORMAL DictionaryCtxt* dict, const PlayerDicts* dicts,
XW_UtilCtxt* util, XP_U16 nCols, XP_U16 nRows );
ModelCtxt* model_makeFromStream( MPFORMAL XWStreamCtxt* stream,
DictionaryCtxt* dict, XW_UtilCtxt* util );
DictionaryCtxt* dict, const PlayerDicts* dicts,
XW_UtilCtxt* util );
void model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream );
@ -116,6 +117,10 @@ XP_U16 model_getNPlayers( const ModelCtxt* model );
void model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict );
DictionaryCtxt* model_getDictionary( const ModelCtxt* model );
void model_setPlayerDicts( ModelCtxt* model, const PlayerDicts* dicts );
DictionaryCtxt* model_getPlayerDict( const ModelCtxt* model, XP_U16 playerNum );
void model_destroyDicts( ModelCtxt* model );
XP_Bool model_getTile( const ModelCtxt* model, XP_U16 col, XP_U16 row,
XP_Bool getPending, XP_S16 turn,
Tile* tile, XP_Bool* isBlank,
@ -209,7 +214,8 @@ typedef void (*TrayListener)( void* data, XP_U16 turn,
XP_S16 index1, XP_S16 index2 );
void model_setTrayListener( ModelCtxt* model, TrayListener bl,
void* data );
typedef void (*DictListener)( void* data, const DictionaryCtxt* oldDict,
typedef void (*DictListener)( void* data, XP_S16 playerNum,
const DictionaryCtxt* oldDict,
const DictionaryCtxt* newDict );
void model_setDictListener( ModelCtxt* model, DictListener dl,
void* data );
@ -253,7 +259,7 @@ void model_figureFinalScores( ModelCtxt* model, ScoresArray* scores,
ScoresArray* tilePenalties );
/* figureMoveScore is meant only for the engine's use */
XP_U16 figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo,
XP_U16 figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* mvInfo,
EngineCtxt* engine, XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord,
XP_U16 mainWordLen );

View file

@ -47,6 +47,7 @@ typedef struct ModelVolatiles {
XW_UtilCtxt* util;
struct CurGameInfo* gi;
DictionaryCtxt* dict;
PlayerDicts dicts;
BoardListener boardListenerFunc;
StackCtxt* stack;
void* boardListenerData;

View file

@ -40,7 +40,7 @@ static XP_U16 find_start( const ModelCtxt* model, XP_U16 col, XP_U16 row,
static XP_S16 checkScoreMove( ModelCtxt* model, XP_S16 turn,
EngineCtxt* engine, XWStreamCtxt* stream,
XP_Bool silent, WordNotifierInfo* notifyInfo );
static XP_U16 scoreWord( const ModelCtxt* model, MoveInfo* movei,
static XP_U16 scoreWord( const ModelCtxt* model, XP_U16 turn, MoveInfo* movei,
EngineCtxt* engine, XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord,
XP_U16 mainWordLen );
@ -102,7 +102,7 @@ adjustScoreForUndone( ModelCtxt* model, MoveInfo* mi, XP_U16 turn )
if ( mi->nTiles == 0 ) {
moveScore = 0;
} else {
moveScore = figureMoveScore( model, mi, (EngineCtxt*)NULL,
moveScore = figureMoveScore( model, turn, mi, (EngineCtxt*)NULL,
(XWStreamCtxt*)NULL,
(WordNotifierInfo*)NULL, NULL, 0 );
}
@ -240,7 +240,7 @@ checkScoreMove( ModelCtxt* model, XP_S16 turn, EngineCtxt* engine,
normalizeMoves( model, turn, isHorizontal, &moveInfo );
if ( isLegalMove( model, &moveInfo, silent ) ) {
score = figureMoveScore( model, &moveInfo, engine, stream,
score = figureMoveScore( model, turn, &moveInfo, engine, stream,
notifyInfo, NULL, 0 );
}
} else if ( !silent ) { /* tiles out of line */
@ -443,7 +443,7 @@ isLegalMove( ModelCtxt* model, MoveInfo* mInfo, XP_Bool silent )
} /* isLegalMove */
XP_U16
figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo,
figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* moveInfo,
EngineCtxt* engine, XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord,
XP_U16 mainWordLen )
@ -474,7 +474,7 @@ figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo,
moveMultiplier *= multipliers[i] = word_multiplier( model, col, row );
}
oneScore = scoreWord( model, moveInfo, (EngineCtxt*)NULL, stream,
oneScore = scoreWord( model, turn, moveInfo, (EngineCtxt*)NULL, stream,
notifyInfo, mainWord, mainWordLen );
if ( !!stream ) {
formatWordScore( stream, oneScore, moveMultiplier );
@ -500,7 +500,7 @@ figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo,
tmpMI.commonCoord = tiles->varCoord;
tmpMI.tiles[0].tile = tiles->tile;
oneScore = scoreWord( model, &tmpMI, engine, stream,
oneScore = scoreWord( model, turn, &tmpMI, engine, stream,
notifyInfo, mainWord, mainWordLen );
if ( !!stream ) {
formatWordScore( stream, oneScore, multipliers[i] );
@ -557,7 +557,8 @@ tile_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
} /* tile_multiplier */
static XP_U16
scoreWord( const ModelCtxt* model, MoveInfo* movei, /* new tiles */
scoreWord( const ModelCtxt* model, XP_U16 turn,
MoveInfo* movei, /* new tiles */
EngineCtxt* engine,/* for crosswise caching */
XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo,
@ -574,7 +575,7 @@ scoreWord( const ModelCtxt* model, MoveInfo* movei, /* new tiles */
XP_U16 col, row;
MoveInfoTile* tiles = movei->tiles;
XP_U16 firstCoord = tiles->varCoord;
DictionaryCtxt* dict = model->vol.dict;
DictionaryCtxt* dict = model_getPlayerDict( model, turn );
if ( movei->isHorizontal ) {
row = movei->commonCoord;

View file

@ -692,8 +692,8 @@ makeRobotMove( ServerCtxt* server )
XP_ASSERT( !!server_getEngineFor( server, turn ) );
searchComplete = engine_findMove( server_getEngineFor( server, turn ),
model, model_getDictionary( model ),
tileSet->tiles, tileSet->nTiles, XP_FALSE,
model, turn, tileSet->tiles,
tileSet->nTiles, XP_FALSE,
#ifdef XWFEATURE_SEARCHLIMIT
NULL, XP_FALSE,
#endif

View file

@ -86,7 +86,8 @@ curses_draw_destroyCtxt( DrawCtx* XP_UNUSED(p_dctx) )
} /* draw_setup */
static void
curses_draw_dictChanged( DrawCtx* XP_UNUSED(p_dctx),
curses_draw_dictChanged( DrawCtx* XP_UNUSED(p_dctx),
XP_S16 XP_UNUSED(playerNum),
const DictionaryCtxt* XP_UNUSED(dict) )
{
}

View file

@ -1443,7 +1443,6 @@ void
cursesmain( XP_Bool isServer, LaunchParams* params )
{
int piperesult;
DictionaryCtxt* dict;
int width, height;
memset( &g_globals, 0, sizeof(g_globals) );
@ -1466,8 +1465,6 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
g_globals.cGlobals.cp.robotThinkMax = params->robotThinkMax;
#endif
dict = params->dict;
setupCursesUtilCallbacks( &g_globals, params->util );
#ifdef XWFEATURE_RELAY
@ -1519,7 +1516,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
&g_globals );
(void)game_makeFromStream( MEMPOOL stream, &g_globals.cGlobals.game,
&params->gi, dict, params->util,
&params->gi, params->dict, &params->dicts,
params->util,
(DrawCtx*)g_globals.draw,
&g_globals.cGlobals.cp, &procs );

View file

@ -369,6 +369,7 @@ gtk_draw_destroyCtxt( DrawCtx* p_dctx )
static void
gtk_draw_dictChanged( DrawCtx* XP_UNUSED(p_dctx),
XP_S16 XP_UNUSED(playerNum),
const DictionaryCtxt* XP_UNUSED(dict) )
{
}

View file

@ -419,7 +419,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
opened = game_makeFromStream( MEMPOOL stream, &globals->cGlobals.game,
&globals->cGlobals.params->gi,
params->dict, params->util,
params->dict, &params->dicts, params->util,
(DrawCtx*)globals->draw,
&globals->cGlobals.cp, &procs );
@ -485,8 +485,8 @@ createOrLoadObjects( GtkAppGlobals* globals )
}
#endif
model_setDictionary( globals->cGlobals.game.model, params->dict );
model_setPlayerDicts( globals->cGlobals.game.model, &params->dicts );
/* params->gi.phoniesAction = PHONIES_DISALLOW; */
#ifdef XWFEATURE_SEARCHLIMIT
params->gi.allowHintRect = params->allowHintRect;
#endif

View file

@ -198,8 +198,8 @@ read_pipe_then_close( CommonGlobals* cGlobals )
XP_Bool opened = game_makeFromStream( MPPARM(cGlobals->params->util->mpool)
stream, &cGlobals->game,
&params->gi,
params->dict, params->util,
&params->gi, params->dict,
&params->dicts, params->util,
NULL /*draw*/,
&cGlobals->cp, NULL );
XP_ASSERT( opened );
@ -245,6 +245,7 @@ typedef enum {
,CMD_SHOW_OTHERSCORES
,CMD_HOSTIP
,CMD_DICT
,CMD_PLAYERDICT
,CMD_SEED
,CMD_GAMEFILE
,CMD_PRINTHISORY
@ -283,6 +284,7 @@ typedef enum {
,CMD_ROOMNAME
,CMD_ADVERTISEROOM
,CMD_JOINADVERTISED
,CMD_PHONIES
#endif
#ifdef XWFEATURE_BLUETOOTH
,CMD_BTADDR
@ -313,7 +315,8 @@ static CmdInfoRec CmdInfoRecs[] = {
,{ CMD_SHOW_OTHERSCORES, false, "no-show-other",
"do not show robot and remote scores" }
,{ CMD_HOSTIP, true, "hostip", "remote host ip address (for direct connect)" }
,{ CMD_DICT, true, "dict", "dictionary name" }
,{ CMD_DICT, true, "game-dict", "dictionary name for game" }
,{ CMD_PLAYERDICT, true, "player-dict", "dictionary name for player (in sequence)" }
,{ CMD_SEED, true, "seed", "random seed" }
,{ CMD_GAMEFILE, true, "file", "file to save to/read from" }
,{ CMD_PRINTHISORY, false, "print-history", "print history on game over" }
@ -352,6 +355,7 @@ static CmdInfoRec CmdInfoRecs[] = {
,{ CMD_ROOMNAME, true, "room", "name of room on relay" }
,{ CMD_ADVERTISEROOM, false, "make-public", "make room public on relay" }
,{ CMD_JOINADVERTISED, false, "join-public", "look for a public room" }
,{ CMD_PHONIES, true, "phonies", "ignore (0, default), warn (1) or lose turn (2)" }
#endif
#ifdef XWFEATURE_BLUETOOTH
,{ CMD_BTADDR, true, "btaddr", "bluetooth address of host" }
@ -874,7 +878,9 @@ main( int argc, char** argv )
XP_Bool closeStdin = XP_FALSE;
unsigned int seed = defaultRandomSeed();
LaunchParams mainParams;
XP_U16 nPlayerDicts = 0;
XP_U16 robotCount = 0;
XP_U16 ii;
/* install a no-op signal handler. Later curses- or gtk-specific code
will install one that does the right thing in that context */
@ -990,6 +996,9 @@ main( int argc, char** argv )
mainParams.gi.dictName = copyString( mainParams.util->mpool,
(XP_UCHAR*)optarg );
break;
case CMD_PLAYERDICT:
mainParams.gi.players[nPlayerDicts++].dictName = optarg;
break;
case CMD_SEED:
seed = atoi(optarg);
break;
@ -1092,6 +1101,20 @@ main( int argc, char** argv )
case CMD_JOINADVERTISED:
mainParams.connInfo.relay.seeksPublicRoom = true;
break;
case CMD_PHONIES:
switch( atoi(optarg) ) {
case 0:
mainParams.gi.phoniesAction = PHONIES_IGNORE;
break;
case 1:
mainParams.gi.phoniesAction = PHONIES_WARN;
break;
case 2:
mainParams.gi.phoniesAction = PHONIES_DISALLOW;
break;
default:
usage( argv[0], "phonies takes 0 or 1 or 2" );
}
#endif
case CMD_CLOSESTDIN:
closeStdin = XP_TRUE;
@ -1190,7 +1213,9 @@ main( int argc, char** argv )
XP_WARNF( "no dictionary provided: using English stub dict\n" );
mainParams.gi.dictLang = dict_getLangCode( mainParams.dict );
#else
mainParams.needsNewGame = XP_TRUE;
if ( 0 == nPlayerDicts ) {
mainParams.needsNewGame = XP_TRUE;
}
#endif
} else if ( robotCount > 0 ) {
mainParams.needsNewGame = XP_TRUE;
@ -1201,6 +1226,14 @@ main( int argc, char** argv )
mainParams.needsNewGame = XP_TRUE;
}
for ( ii = 0; ii < nPlayerDicts; ++ii ) {
XP_UCHAR* name = mainParams.gi.players[ii].dictName;
if ( !!name ) {
mainParams.dicts.dicts[ii] =
linux_dictionary_make( MPPARM(mainParams.util->mpool) name );
}
}
/* if ( !isServer ) { */
/* if ( mainParams.info.serverInfo.nRemotePlayers > 0 ) { */
/* mainParams.needsNewGame = XP_TRUE; */

View file

@ -47,6 +47,7 @@ typedef struct LaunchParams {
XW_UtilCtxt* util;
DictionaryCtxt* dict;
CurGameInfo gi;
PlayerDicts dicts;
char* fileName;
char* pipe;
VTableMgr* vtMgr;