mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
bring in changes to make larger boards work for linux
Includes making tile sets vary with board size, calculated from 15x15 unless present in the wordlist. Likely breaks android.
This commit is contained in:
commit
5d6d8c7499
24 changed files with 342 additions and 398 deletions
|
@ -210,7 +210,6 @@ board_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, ModelCtxt* model
|
|||
XP_U16 nPlayers )
|
||||
{
|
||||
BoardCtxt* board;
|
||||
XP_U16 ii;
|
||||
XP_U16 version = stream_getVersion( stream );
|
||||
XP_U16 nColsNBits;
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
|
@ -223,11 +222,11 @@ board_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, ModelCtxt* model
|
|||
board_setCallbacks( board, xwe );
|
||||
|
||||
if ( version >= STREAM_VERS_4YOFFSET) {
|
||||
board->sd[SCROLL_H].offset = (XP_U16)stream_getBits( stream, 4 );
|
||||
board->zoomCount = (XP_U16)stream_getBits( stream, 4 );
|
||||
board->sd[SCROLL_H].offset = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
board->zoomCount = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
}
|
||||
board->sd[SCROLL_V].offset = (XP_U16)
|
||||
stream_getBits( stream, (version < STREAM_VERS_4YOFFSET) ? 2 : 4 );
|
||||
stream_getBits( stream, (version < STREAM_VERS_4YOFFSET) ? 2 : nColsNBits );
|
||||
board->isFlipped = (XP_Bool)stream_getBits( stream, 1 );
|
||||
board->gameOver = (XP_Bool)stream_getBits( stream, 1 );
|
||||
board->showColors = (XP_Bool)stream_getBits( stream, 1 );
|
||||
|
@ -249,7 +248,7 @@ board_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, ModelCtxt* model
|
|||
|
||||
XP_ASSERT( !!server );
|
||||
|
||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
for ( int ii = 0; ii < nPlayers; ++ii ) {
|
||||
PerTurnInfo* pti = &board->pti[ii];
|
||||
BoardArrow* arrow = &pti->boardArrow;
|
||||
arrow->col = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||
|
@ -324,10 +323,9 @@ board_writeToStream( const BoardCtxt* board, XWStreamCtxt* stream )
|
|||
nColsNBits = NUMCOLS_NBITS_4;
|
||||
#endif
|
||||
|
||||
|
||||
stream_putBits( stream, 4, board->sd[SCROLL_H].offset );
|
||||
stream_putBits( stream, 4, board->zoomCount );
|
||||
stream_putBits( stream, 4, board->sd[SCROLL_V].offset );
|
||||
stream_putBits( stream, nColsNBits, board->sd[SCROLL_H].offset );
|
||||
stream_putBits( stream, nColsNBits, board->zoomCount );
|
||||
stream_putBits( stream, nColsNBits, board->sd[SCROLL_V].offset );
|
||||
stream_putBits( stream, 1, board->isFlipped );
|
||||
stream_putBits( stream, 1, board->gameOver );
|
||||
stream_putBits( stream, 1, board->showColors );
|
||||
|
@ -1371,7 +1369,7 @@ timerFiredForPen( BoardCtxt* board, XWEnv xwe )
|
|||
#endif
|
||||
if ( !listWords ) {
|
||||
XWBonusType bonus;
|
||||
bonus = model_getSquareBonus( board->model, xwe, col, row );
|
||||
bonus = model_getSquareBonus( board->model, col, row );
|
||||
if ( bonus != BONUS_NONE ) {
|
||||
#ifdef XWFEATURE_MINIWIN
|
||||
text = draw_getMiniWText( board->draw,
|
||||
|
|
|
@ -339,7 +339,7 @@ drawBoard( BoardCtxt* board, XWEnv xwe )
|
|||
XWBonusType bonus;
|
||||
HintAtts hintAtts;
|
||||
CellFlags flags = CELL_NONE;
|
||||
bonus = model_getSquareBonus( model, xwe, col, row );
|
||||
bonus = model_getSquareBonus( model, col, row );
|
||||
hintAtts = figureHintAtts( board, col, row );
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( cellFocused( board, col, row ) ) {
|
||||
|
@ -438,7 +438,7 @@ drawCell( BoardCtxt* board, XWEnv xwe, const XP_U16 col,
|
|||
}
|
||||
textP = dict_getTileString( dict, tile );
|
||||
}
|
||||
bonus = model_getSquareBonus( model, xwe, col, row );
|
||||
bonus = model_getSquareBonus( model, col, row );
|
||||
hintAtts = figureHintAtts( board, col, row );
|
||||
|
||||
if ( (col==board->star_row) && (row==board->star_row) ) {
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
# define MAX_ROWS 16
|
||||
#endif
|
||||
#define MAX_COLS MAX_ROWS
|
||||
#define MIN_COLS 11
|
||||
|
||||
#define STREAM_VERS_SMALLCOMMS 0x1F
|
||||
#define STREAM_VERS_NINETILES 0x1E
|
||||
|
@ -212,6 +213,8 @@ typedef enum {
|
|||
BONUS_DOUBLE_WORD,
|
||||
BONUS_TRIPLE_LETTER,
|
||||
BONUS_TRIPLE_WORD,
|
||||
BONUS_QUAD_LETTER,
|
||||
BONUS_QUAD_WORD,
|
||||
|
||||
BONUS_LAST
|
||||
} XWBonusType;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE -j3"; -*- */
|
||||
/*
|
||||
* Copyright 1997-2011 by Eric House (xwords@eehouse.org). All rights
|
||||
* Copyright 1997 - 2022 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -41,6 +41,7 @@ extern "C" {
|
|||
****************************************************************************/
|
||||
|
||||
static XP_Bool makeBitmap( XP_U8 const** ptrp, const XP_U8* end );
|
||||
static XP_U8* getCountsFor( const DictionaryCtxt* dict, XP_U16 nCols );
|
||||
|
||||
const DictionaryCtxt*
|
||||
p_dict_ref( const DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe)
|
||||
|
@ -99,14 +100,12 @@ dict_unref_all( PlayerDicts* pd, XWEnv xwe )
|
|||
}
|
||||
|
||||
static XP_UCHAR*
|
||||
getNullTermParam( DictionaryCtxt* XP_UNUSED_DBG(dctx), const XP_U8** ptr,
|
||||
XP_U16* headerLen )
|
||||
getNullTermParam( DictionaryCtxt* XP_UNUSED_DBG(dctx), const XP_U8** ptr )
|
||||
{
|
||||
XP_U16 len = 1 + XP_STRLEN( (XP_UCHAR*)*ptr );
|
||||
XP_UCHAR* result = XP_MALLOC( dctx->mpool, len );
|
||||
XP_MEMCPY( result, *ptr, len );
|
||||
*ptr += len;
|
||||
*headerLen -= len;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -234,44 +233,78 @@ parseCommon( DictionaryCtxt* dctx, XWEnv xwe, const XP_U8** ptrp, const XP_U8* e
|
|||
XP_U8 numFaceBytes, numFaces;
|
||||
|
||||
if ( hasHeader ) {
|
||||
XP_U16 headerLen;
|
||||
const XP_U8* headerEnd;
|
||||
{
|
||||
XP_U16 headerLen;
|
||||
XP_MEMCPY( &headerLen, ptr, sizeof(headerLen) );
|
||||
ptr += sizeof(headerLen);
|
||||
headerLen = XP_NTOHS( headerLen );
|
||||
headerEnd = ptr + headerLen;
|
||||
}
|
||||
|
||||
XP_U32 wordCount;
|
||||
|
||||
XP_MEMCPY( &headerLen, ptr, sizeof(headerLen) );
|
||||
ptr += sizeof(headerLen);
|
||||
headerLen = XP_NTOHS( headerLen );
|
||||
|
||||
XP_MEMCPY( &wordCount, ptr, sizeof(wordCount) );
|
||||
ptr += sizeof(wordCount);
|
||||
headerLen -= sizeof(wordCount);
|
||||
dctx->nWords = XP_NTOHL( wordCount );
|
||||
XP_DEBUGF( "dict contains %d words", dctx->nWords );
|
||||
|
||||
if ( 0 < headerLen ) {
|
||||
dctx->desc = getNullTermParam( dctx, &ptr, &headerLen );
|
||||
} else {
|
||||
XP_LOGF( "%s: no note", __func__ );
|
||||
if ( ptr == headerEnd ) {
|
||||
XP_LOGFF( "no note" );
|
||||
goto done;
|
||||
}
|
||||
if ( 0 < headerLen ) {
|
||||
dctx->md5Sum = getNullTermParam( dctx, &ptr, &headerLen );
|
||||
} else {
|
||||
XP_LOGF( "%s: no md5Sum", __func__ );
|
||||
XP_ASSERT( ptr < headerEnd );
|
||||
dctx->desc = getNullTermParam( dctx, &ptr );
|
||||
|
||||
if ( ptr == headerEnd ) {
|
||||
XP_LOGFF( "no md5Sum" );
|
||||
goto done;
|
||||
}
|
||||
XP_ASSERT( ptr < headerEnd );
|
||||
dctx->md5Sum = getNullTermParam( dctx, &ptr );
|
||||
|
||||
XP_U16 headerFlags = 0;
|
||||
if ( sizeof(headerFlags) <= headerLen ) {
|
||||
XP_MEMCPY( &headerFlags, ptr, sizeof(headerFlags) );
|
||||
headerFlags = XP_NTOHS( headerFlags );
|
||||
ptr += sizeof(headerFlags);
|
||||
headerLen -= sizeof(headerFlags);
|
||||
if ( ptr + sizeof(headerFlags) > headerEnd ) {
|
||||
goto done;
|
||||
}
|
||||
XP_MEMCPY( &headerFlags, ptr, sizeof(headerFlags) );
|
||||
headerFlags = XP_NTOHS( headerFlags );
|
||||
ptr += sizeof(headerFlags);
|
||||
|
||||
XP_LOGFF( "setting headerFlags: 0x%x", headerFlags );
|
||||
dctx->headerFlags = headerFlags;
|
||||
|
||||
if ( 0 < headerLen ) {
|
||||
XP_LOGFF( "skipping %d bytes of header", headerLen );
|
||||
if ( ptr == headerEnd ) {
|
||||
goto done;
|
||||
}
|
||||
ptr += headerLen;
|
||||
XP_UCHAR* langName = getNullTermParam( dctx, &ptr );
|
||||
if ( ptr == headerEnd ) {
|
||||
goto done;
|
||||
}
|
||||
XP_UCHAR* langCode = getNullTermParam( dctx, &ptr );
|
||||
XP_LOGFF( "got langName: %s; langCode: %s", langName, langCode );
|
||||
XP_FREE( dctx->mpool, langName );
|
||||
XP_FREE( dctx->mpool, langCode );
|
||||
|
||||
if ( ptr == headerEnd ) {
|
||||
goto done;
|
||||
}
|
||||
XP_U8 otherLen = *ptr++;
|
||||
XP_LOGFF( "otherLen: %d", otherLen );
|
||||
if ( 0 < otherLen ) {
|
||||
XP_ASSERT( ptr + otherLen <= headerEnd );
|
||||
if ( ptr + otherLen <= headerEnd ) {
|
||||
dctx->otherCounts = XP_MALLOC( dctx->mpool, otherLen );
|
||||
dctx->otherCountsEnd = dctx->otherCounts + otherLen;
|
||||
XP_MEMCPY( dctx->otherCounts, ptr, otherLen );
|
||||
ptr += otherLen;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if ( ptr < headerEnd ) {
|
||||
XP_LOGFF( "skipping %zu bytes of header", headerEnd - ptr );
|
||||
}
|
||||
ptr = headerEnd;
|
||||
}
|
||||
|
||||
if ( isUTF8 ) {
|
||||
|
@ -301,7 +334,10 @@ parseCommon( DictionaryCtxt* dctx, XWEnv xwe, const XP_U8** ptrp, const XP_U8* e
|
|||
|
||||
dctx->nFaces = numFaces;
|
||||
|
||||
dctx->countsAndValues = XP_MALLOC( dctx->mpool, numFaces * 2 );
|
||||
dctx->values = XP_MALLOC( dctx->mpool, numFaces);
|
||||
XP_U8* counts15 = XP_MALLOC( dctx->mpool, numFaces); /* leaking */
|
||||
dctx->counts[15>>1] = counts15;
|
||||
|
||||
XP_U16 facesSize = numFaceBytes;
|
||||
if ( !isUTF8 ) {
|
||||
facesSize /= 2;
|
||||
|
@ -316,8 +352,11 @@ parseCommon( DictionaryCtxt* dctx, XWEnv xwe, const XP_U8** ptrp, const XP_U8* e
|
|||
unsigned short xloc;
|
||||
XP_MEMCPY( &xloc, ptr, sizeof(xloc) );
|
||||
ptr += sizeof(xloc);
|
||||
XP_MEMCPY( dctx->countsAndValues, ptr, numFaces*2 );
|
||||
ptr += numFaces*2;
|
||||
|
||||
for ( int ii = 0; ii < numFaces; ++ii ) {
|
||||
counts15[ii] = *ptr++;
|
||||
dctx->values[ii] = *ptr++;
|
||||
}
|
||||
|
||||
dctx->langCode = xloc & 0x7F;
|
||||
}
|
||||
|
@ -413,7 +452,7 @@ dict_getBlankTile( const DictionaryCtxt* dict )
|
|||
} /* dict_getBlankTile */
|
||||
|
||||
XP_U16
|
||||
dict_getTileValue( const DictionaryCtxt* dict, Tile tile )
|
||||
dict_getTileValue( const DictionaryCtxt* dict, const Tile tile )
|
||||
{
|
||||
XP_ASSERT( !!dict );
|
||||
if ( (tile & TILE_VALUE_MASK) != tile ) {
|
||||
|
@ -421,9 +460,8 @@ dict_getTileValue( const DictionaryCtxt* dict, Tile tile )
|
|||
tile == dict_getBlankTile( dict ) );
|
||||
}
|
||||
XP_ASSERT( tile < dict->nFaces );
|
||||
tile *= 2;
|
||||
XP_ASSERT( !!dict->countsAndValues );
|
||||
return dict->countsAndValues[tile+1];
|
||||
XP_ASSERT( !!dict->values );
|
||||
return dict->values[tile];
|
||||
} /* dict_getTileValue */
|
||||
|
||||
static const XP_UCHAR*
|
||||
|
@ -477,11 +515,57 @@ dict_getNextTileString( const DictionaryCtxt* dict, Tile tile,
|
|||
}
|
||||
|
||||
XP_U16
|
||||
dict_numTiles( const DictionaryCtxt* dict, Tile tile )
|
||||
dict_numTilesForSize( const DictionaryCtxt* dict, Tile tile, XP_U16 nCols )
|
||||
{
|
||||
tile *= 2;
|
||||
return dict->countsAndValues[tile];
|
||||
} /* dict_numTiles */
|
||||
XP_U8* counts = getCountsFor( dict, nCols );
|
||||
return counts[tile];
|
||||
}
|
||||
|
||||
/* Older wordlists are built assuming 15x15 boards. Different sized boards
|
||||
need different numbers of tiles. The wordlist might provide for the size we
|
||||
have, in which case we use it. Otherwise we extrapolate.
|
||||
*/
|
||||
static XP_U8*
|
||||
getCountsFor( const DictionaryCtxt* dict, XP_U16 nCols )
|
||||
{
|
||||
int offset = nCols >> 1;
|
||||
XP_U8* counts = dict->counts[offset];
|
||||
if ( !counts ) {
|
||||
counts = XP_MALLOC( dict->mpool, dict->nFaces );
|
||||
((DictionaryCtxt*)dict)->counts[offset] = counts;
|
||||
|
||||
XP_U8* ptr = dict->otherCounts;
|
||||
XP_Bool found = XP_FALSE;
|
||||
while ( !found && !!ptr && ptr < dict->otherCountsEnd ) {
|
||||
XP_U8 siz = *ptr++;
|
||||
found = siz == nCols;
|
||||
if ( found ) {
|
||||
XP_MEMCPY( counts, ptr, dict->nFaces );
|
||||
} else {
|
||||
ptr += dict->nFaces;
|
||||
}
|
||||
}
|
||||
|
||||
/* don't have it in the wordlist? Extrapolate */
|
||||
if ( !found ) {
|
||||
XP_U16 pct = (nCols * nCols * 100) / (15 * 15);
|
||||
XP_U8* src15 = dict->counts[15>>1];
|
||||
XP_ASSERT( !!src15 );
|
||||
|
||||
for ( int ii = 0; ii < dict->nFaces; ++ii ) {
|
||||
XP_U16 count = src15[ii];
|
||||
XP_U16 newCount = count * pct / 100;
|
||||
if ( 50 < (count * pct) % 100 ) {
|
||||
++newCount;
|
||||
}
|
||||
counts[ii] = newCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XP_LOGFF( "(tile=%d, ncols=%d) => %d", tile, nCols, count );
|
||||
return counts;
|
||||
} /* getCountsFor */
|
||||
|
||||
XP_U16
|
||||
dict_numTileFaces( const DictionaryCtxt* dict )
|
||||
|
@ -631,7 +715,7 @@ dict_tilesAreSame( const DictionaryCtxt* dict1, const DictionaryCtxt* dict2 )
|
|||
} else if ( 0 != XP_STRCMP( face1, face2 ) ) {
|
||||
break;
|
||||
}
|
||||
if ( dict_numTiles( dict1, ii ) != dict_numTiles( dict2, ii ) ) {
|
||||
if ( dict_numTilesForSize( dict1, ii, 15 ) != dict_numTilesForSize( dict2, ii, 15 ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -641,33 +725,14 @@ dict_tilesAreSame( const DictionaryCtxt* dict1, const DictionaryCtxt* dict2 )
|
|||
} /* dict_tilesAreSame */
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
static void
|
||||
ucharsToNarrow( const DictionaryCtxt* dict, XP_UCHAR* buf, XP_U16* bufsizep )
|
||||
{
|
||||
XP_U16 ii;
|
||||
XP_U16 nUsed = 0;
|
||||
XP_U16 bufsize = *bufsizep;
|
||||
for ( ii = 0; ii < dict->nFaces; ++ii ) {
|
||||
const XP_UCHAR* facep = dict_getTileStringRaw( dict, ii );
|
||||
if ( IS_SPECIAL(*facep) ) {
|
||||
buf[nUsed++] = *facep;
|
||||
} else {
|
||||
nUsed += XP_SNPRINTF( &buf[nUsed], bufsize - nUsed, "%s", facep );
|
||||
}
|
||||
XP_ASSERT( nUsed < bufsize );
|
||||
}
|
||||
buf[nUsed] = 0;
|
||||
*bufsizep = nUsed;
|
||||
}
|
||||
|
||||
/* Summarize tile info in a way it can be presented to users */
|
||||
void
|
||||
dict_writeTilesInfo( const DictionaryCtxt* dict, XWStreamCtxt* stream )
|
||||
dict_writeTilesInfo( const DictionaryCtxt* dict, XP_U16 boardSize, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_U16 nFaces = dict_numTileFaces( dict );
|
||||
for ( Tile tile = 0; tile < nFaces; ++tile ) {
|
||||
XP_U16 val = dict_getTileValue( dict, tile );
|
||||
XP_U16 count = dict_numTiles( dict, tile );
|
||||
XP_U16 count = dict_numTilesForSize( dict, tile, boardSize );
|
||||
const XP_UCHAR* face = dict_getTileString( dict, tile );
|
||||
XP_UCHAR buf[32];
|
||||
XP_SNPRINTF( buf, VSIZE(buf), "%s\t%d\t%d\n", face, count, val );
|
||||
|
@ -676,60 +741,63 @@ dict_writeTilesInfo( const DictionaryCtxt* dict, XWStreamCtxt* stream )
|
|||
}
|
||||
|
||||
void
|
||||
dict_writeToStream( const DictionaryCtxt* dict, XWStreamCtxt* stream )
|
||||
dict_writeToStream( const DictionaryCtxt* XP_UNUSED(dict),
|
||||
XWStreamCtxt* XP_UNUSED(stream) )
|
||||
{
|
||||
XP_U16 maxCount = 0;
|
||||
XP_U16 maxValue = 0;
|
||||
XP_U16 ii, nSpecials;
|
||||
XP_U16 maxCountBits, maxValueBits;
|
||||
XP_UCHAR buf[64];
|
||||
XP_U16 nBytes;
|
||||
XP_ASSERT(0);
|
||||
/* XP_U16 maxCount = 0; */
|
||||
/* XP_U16 maxValue = 0; */
|
||||
/* XP_U16 ii, nSpecials; */
|
||||
/* XP_U16 maxCountBits, maxValueBits; */
|
||||
/* XP_UCHAR buf[64]; */
|
||||
/* XP_U16 nBytes; */
|
||||
|
||||
stream_putBits( stream, 6, dict->nFaces );
|
||||
/* stream_putBits( stream, 6, dict->nFaces ); */
|
||||
|
||||
for ( ii = 0; ii < dict->nFaces*2; ii+=2 ) {
|
||||
XP_U16 count, value;
|
||||
/* XP_ASSERT(0); /\* if this fires, need to fix for per-boardSize counts *\/ */
|
||||
/* for ( ii = 0; ii < dict->nFaces*2; ii+=2 ) { */
|
||||
/* XP_U16 count, value; */
|
||||
|
||||
count = dict->countsAndValues[ii];
|
||||
if ( maxCount < count ) {
|
||||
maxCount = count;
|
||||
}
|
||||
/* count = dict->countsAndValues[ii]; */
|
||||
/* if ( maxCount < count ) { */
|
||||
/* maxCount = count; */
|
||||
/* } */
|
||||
|
||||
value = dict->countsAndValues[ii+1];
|
||||
if ( maxValue < value ) {
|
||||
maxValue = value;
|
||||
}
|
||||
}
|
||||
/* value = dict->countsAndValues[ii+1]; */
|
||||
/* if ( maxValue < value ) { */
|
||||
/* maxValue = value; */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
maxCountBits = bitsForMax( maxCount );
|
||||
maxValueBits = bitsForMax( maxValue );
|
||||
/* maxCountBits = bitsForMax( maxCount ); */
|
||||
/* maxValueBits = bitsForMax( maxValue ); */
|
||||
|
||||
stream_putBits( stream, 3, maxCountBits ); /* won't be bigger than 5 */
|
||||
stream_putBits( stream, 3, maxValueBits );
|
||||
/* stream_putBits( stream, 3, maxCountBits ); /\* won't be bigger than 5 *\/ */
|
||||
/* stream_putBits( stream, 3, maxValueBits ); */
|
||||
|
||||
for ( ii = 0; ii < dict->nFaces*2; ii+=2 ) {
|
||||
stream_putBits( stream, maxCountBits, dict->countsAndValues[ii] );
|
||||
stream_putBits( stream, maxValueBits, dict->countsAndValues[ii+1] );
|
||||
}
|
||||
/* for ( ii = 0; ii < dict->nFaces; ++ii ) { */
|
||||
/* stream_putBits( stream, maxCountBits, counts[ii] ); */
|
||||
/* stream_putBits( stream, maxValueBits, dict->values[ii] ); */
|
||||
/* } */
|
||||
|
||||
/* Stream format of the faces is unchanged: chars run together, which
|
||||
* happens to equal utf-8 for ascii. But now there may be more than one
|
||||
* byte per face. Old code assumes that, but compatibility is ensured by
|
||||
* the caller which will not accept an incoming message if the version's
|
||||
* too new. And utf-8 dicts are flagged as newer by the sender.
|
||||
*/
|
||||
/* /\* Stream format of the faces is unchanged: chars run together, which */
|
||||
/* * happens to equal utf-8 for ascii. But now there may be more than one */
|
||||
/* * byte per face. Old code assumes that, but compatibility is ensured by */
|
||||
/* * the caller which will not accept an incoming message if the version's */
|
||||
/* * too new. And utf-8 dicts are flagged as newer by the sender. */
|
||||
/* *\/ */
|
||||
|
||||
nBytes = sizeof(buf);
|
||||
ucharsToNarrow( dict, buf, &nBytes );
|
||||
stream_putU8( stream, nBytes );
|
||||
stream_putBytes( stream, buf, nBytes );
|
||||
/* nBytes = sizeof(buf); */
|
||||
/* ucharsToNarrow( dict, buf, &nBytes ); */
|
||||
/* stream_putU8( stream, nBytes ); */
|
||||
/* stream_putBytes( stream, buf, nBytes ); */
|
||||
|
||||
for ( nSpecials = ii = 0; ii < dict->nFaces; ++ii ) {
|
||||
const XP_UCHAR* facep = dict_getTileStringRaw( dict, (Tile)ii );
|
||||
if ( IS_SPECIAL( *facep ) ) {
|
||||
stringToStream( stream, dict->chars[nSpecials++] );
|
||||
}
|
||||
}
|
||||
/* for ( nSpecials = ii = 0; ii < dict->nFaces; ++ii ) { */
|
||||
/* const XP_UCHAR* facep = dict_getTileStringRaw( dict, (Tile)ii ); */
|
||||
/* if ( IS_SPECIAL( *facep ) ) { */
|
||||
/* stringToStream( stream, dict->chars[nSpecials++] ); */
|
||||
/* } */
|
||||
/* } */
|
||||
} /* dict_writeToStream */
|
||||
#endif
|
||||
|
||||
|
@ -763,7 +831,11 @@ common_destructor( DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe) )
|
|||
{
|
||||
freeSpecials( dict );
|
||||
|
||||
XP_FREE( dict->mpool, dict->countsAndValues );
|
||||
XP_FREE( dict->mpool, dict->values );
|
||||
for ( int ii = 0; ii < VSIZE(dict->counts); ++ii ) {
|
||||
XP_FREEP( dict->mpool, &dict->counts[ii] );
|
||||
}
|
||||
XP_FREE( dict->mpool, dict->otherCounts );
|
||||
XP_FREE( dict->mpool, dict->faces );
|
||||
XP_FREE( dict->mpool, dict->facePtrs );
|
||||
|
||||
|
@ -774,6 +846,7 @@ common_destructor( DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe) )
|
|||
void
|
||||
dict_loadFromStream( DictionaryCtxt* dict, XWEnv xwe, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_ASSERT(0); /* if this fires, need to fix for per-boardSize counts */
|
||||
XP_U8 nFaces, nFaceBytes;
|
||||
XP_U16 maxCountBits, maxValueBits;
|
||||
XP_U16 ii, nSpecials;
|
||||
|
@ -792,15 +865,14 @@ dict_loadFromStream( DictionaryCtxt* dict, XWEnv xwe, XWStreamCtxt* stream )
|
|||
|
||||
dict->nFaces = nFaces;
|
||||
|
||||
dict->countsAndValues =
|
||||
(XP_U8*)XP_MALLOC( dict->mpool,
|
||||
sizeof(dict->countsAndValues[0]) * nFaces * 2 );
|
||||
dict->values = (XP_U8*)XP_MALLOC( dict->mpool,
|
||||
sizeof(dict->values[0]) * nFaces );
|
||||
XP_U8* counts = dict->counts[15>>1]
|
||||
= (XP_U8*)XP_MALLOC( dict->mpool, sizeof(dict->values[0]) * nFaces );
|
||||
|
||||
for ( ii = 0; ii < dict->nFaces*2; ii+=2 ) {
|
||||
dict->countsAndValues[ii] = (XP_U8)stream_getBits( stream,
|
||||
maxCountBits );
|
||||
dict->countsAndValues[ii+1] = (XP_U8)stream_getBits( stream,
|
||||
maxValueBits );
|
||||
for ( ii = 0; ii < dict->nFaces; ++ii ) {
|
||||
counts[ii] = (XP_U8)stream_getBits( stream, maxCountBits );
|
||||
dict->values[ii] = (XP_U8)stream_getBits( stream, maxValueBits );
|
||||
}
|
||||
|
||||
nFaceBytes = (XP_U8)stream_getU8( stream );
|
||||
|
@ -1028,7 +1100,7 @@ make_stubbed_dict( MPFORMAL_NOCOMMA )
|
|||
setBlankTile( dict );
|
||||
|
||||
return dict;
|
||||
} /* make_subbed_dict */
|
||||
} /* make_stubbed_dict */
|
||||
|
||||
#endif /* STUBBED_DICT */
|
||||
|
||||
|
@ -1123,6 +1195,21 @@ dict_super_init( MPFORMAL DictionaryCtxt* dict )
|
|||
pthread_mutex_init( &dict->mutex, NULL );
|
||||
} /* dict_super_init */
|
||||
|
||||
void
|
||||
dict_super_destroy( DictionaryCtxt* dict )
|
||||
{
|
||||
XP_FREEP( dict->mpool, &dict->desc );
|
||||
XP_FREEP( dict->mpool, &dict->md5Sum );
|
||||
XP_FREEP( dict->mpool, &dict->values );
|
||||
for ( int ii = 0; ii < VSIZE(dict->counts); ++ii ) {
|
||||
XP_FREEP( dict->mpool, &dict->counts[ii] );
|
||||
}
|
||||
XP_FREEP( dict->mpool, &dict->otherCounts );
|
||||
XP_FREEP( dict->mpool, &dict->faces );
|
||||
XP_FREEP( dict->mpool, &dict->facePtrs );
|
||||
XP_FREEP( dict->mpool, &dict->name );
|
||||
}
|
||||
|
||||
const XP_UCHAR*
|
||||
dict_getLangName( const DictionaryCtxt* ctxt )
|
||||
{
|
||||
|
|
|
@ -86,7 +86,11 @@ struct DictionaryCtxt {
|
|||
XP_UCHAR* desc;
|
||||
XP_UCHAR* md5Sum;
|
||||
const XP_UCHAR** facePtrs; /* elems point into faces, above */
|
||||
XP_U8* countsAndValues;
|
||||
XP_U8* counts[(MAX_COLS>>1) + 1];
|
||||
XP_U8* values;
|
||||
|
||||
XP_U8* otherCounts;
|
||||
XP_U8* otherCountsEnd;
|
||||
|
||||
SpecialBitmaps* bitmaps;
|
||||
XP_UCHAR** chars;
|
||||
|
@ -177,7 +181,7 @@ XP_Bool dict_tilesAreSame( const DictionaryCtxt* dict1,
|
|||
XP_Bool dict_hasBlankTile( const DictionaryCtxt* dict );
|
||||
Tile dict_getBlankTile( const DictionaryCtxt* dict );
|
||||
XP_U16 dict_getTileValue( const DictionaryCtxt* ctxt, Tile tile );
|
||||
XP_U16 dict_numTiles( const DictionaryCtxt* ctxt, Tile tile );
|
||||
XP_U16 dict_numTilesForSize( const DictionaryCtxt* ctxt, Tile tile, XP_U16 nCols );
|
||||
XP_U16 dict_numTileFaces( const DictionaryCtxt* ctxt );
|
||||
XP_U16 dict_getMaxTileChars( const DictionaryCtxt* ctxt );
|
||||
|
||||
|
@ -207,7 +211,8 @@ const XP_UCHAR* dict_getDesc( const DictionaryCtxt* dict );
|
|||
const XP_UCHAR* dict_getMd5Sum( const DictionaryCtxt* dict );
|
||||
XP_Bool dict_hasDuplicates( const DictionaryCtxt* dict );
|
||||
|
||||
void dict_writeTilesInfo( const DictionaryCtxt* ctxt, XWStreamCtxt* stream );
|
||||
void dict_writeTilesInfo( const DictionaryCtxt* ctxt, XP_U16 boardSize,
|
||||
XWStreamCtxt* stream );
|
||||
|
||||
void dict_writeToStream( const DictionaryCtxt* ctxt, XWStreamCtxt* stream );
|
||||
void dict_loadFromStream( DictionaryCtxt* dict, XWEnv xwe, XWStreamCtxt* stream );
|
||||
|
@ -232,6 +237,8 @@ XP_Bool checkSanity( DictionaryCtxt* dict, XP_U32 numEdges );
|
|||
|
||||
/* To be called only by subclasses!!! */
|
||||
void dict_super_init( MPFORMAL DictionaryCtxt* ctxt );
|
||||
void dict_super_destroy( DictionaryCtxt* ctxt );
|
||||
|
||||
/* Must be implemented by subclasses */
|
||||
void dict_splitFaces( DictionaryCtxt* dict, XWEnv xwe, const XP_U8* bytes,
|
||||
XP_U16 nBytes, XP_U16 nFaceos );
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/* -*- compile-command: "cd ../linux && make -j5 MEMDEBUG=TRUE"; -*- */
|
||||
/*
|
||||
* Copyright 1997 - 2003 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 1997 - 2022 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -296,6 +297,7 @@ default_draw_score_pendingScore( DrawCtx* dctx,
|
|||
draw_setClip( dctx, &oldClip, NULL );
|
||||
} /* default_draw_score_pendingScore */
|
||||
|
||||
#ifdef XWFEATURE_MINIWIN
|
||||
static const XP_UCHAR*
|
||||
default_draw_getMiniWText( DrawCtx* XP_UNUSED(dctx), XWMiniTextType textHint )
|
||||
{
|
||||
|
@ -310,6 +312,10 @@ default_draw_getMiniWText( DrawCtx* XP_UNUSED(dctx), XWMiniTextType textHint )
|
|||
str = "Triple letter"; break;
|
||||
case BONUS_TRIPLE_WORD:
|
||||
str = "Triple word"; break;
|
||||
case BONUS_QUAD_LETTER:
|
||||
str = "Quad letter"; break;
|
||||
case BONUS_QUAD_WORD:
|
||||
str = "Quad word"; break;
|
||||
case INTRADE_MW_TEXT:
|
||||
str = "Trading tiles;\nclick D when done"; break;
|
||||
default:
|
||||
|
@ -343,6 +349,7 @@ default_draw_drawMiniWindow( DrawCtx* dctx, const XP_UCHAR* text,
|
|||
|
||||
draw_setClip( dctx, &oldClip, NULL );
|
||||
} /* default_draw_drawMiniWindow */
|
||||
#endif
|
||||
|
||||
void
|
||||
InitDrawDefaults( DrawCtxVTable* vtable )
|
||||
|
|
|
@ -375,31 +375,69 @@ model_popToHash( ModelCtxt* model, XWEnv xwe, const XP_U32 hash, PoolContext* po
|
|||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void
|
||||
model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses, XP_U16 nBonuses )
|
||||
model_setSquareBonuses( ModelCtxt* XP_UNUSED(model), XWBonusType* XP_UNUSED(bonuses),
|
||||
XP_U16 XP_UNUSED(nBonuses) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
XP_U16 nCols = (1 + model_numCols( model )) / 2;
|
||||
XP_ASSERT( 0 < nCols );
|
||||
XP_U16 wantLen = 0;
|
||||
while ( nCols > 0 ) {
|
||||
wantLen += nCols--;
|
||||
}
|
||||
XP_ASSERT( wantLen == nBonuses );
|
||||
#endif
|
||||
|
||||
if ( !!model->vol.bonuses ) {
|
||||
XP_FREE( model->vol.mpool, model->vol.bonuses );
|
||||
}
|
||||
model->vol.bonuses = XP_MALLOC( model->vol.mpool,
|
||||
nBonuses * sizeof(model->vol.bonuses[0]) );
|
||||
XP_MEMCPY( model->vol.bonuses, bonuses,
|
||||
nBonuses * sizeof(model->vol.bonuses[0]) );
|
||||
model->vol.nBonuses = nBonuses;
|
||||
XP_LOGFF( "doing nothing" );
|
||||
}
|
||||
#endif
|
||||
|
||||
#define EM BONUS_NONE
|
||||
#define DL BONUS_DOUBLE_LETTER
|
||||
#define DW BONUS_DOUBLE_WORD
|
||||
#define TL BONUS_TRIPLE_LETTER
|
||||
#define TW BONUS_TRIPLE_WORD
|
||||
#define QL BONUS_QUAD_LETTER
|
||||
#define QW BONUS_QUAD_WORD
|
||||
|
||||
static XWBonusType sTwentyOne[] = {
|
||||
QW,
|
||||
EM, DW,
|
||||
EM, EM, DW,
|
||||
DL, EM, EM, TW,
|
||||
EM, TL, EM, EM, DW,
|
||||
EM, EM, QL, EM, EM, DW,
|
||||
EM, EM, EM, DL, EM, EM, DW,
|
||||
TW, EM, EM, EM, EM, EM, EM, DW,
|
||||
EM, DW, EM, EM, TL, EM, EM, EM, TL,
|
||||
EM, EM, DW, EM, EM, DL, EM, EM, EM, DL,
|
||||
DL, EM, EM, TW, EM, EM, DL, EM, EM, EM, DW,
|
||||
}; /* sTwentyOne */
|
||||
|
||||
static XWBonusType
|
||||
getSquareBonus( XP_U16 nCols, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
if ( col > (nCols/2) ) {
|
||||
col = nCols - 1 - col;
|
||||
}
|
||||
if ( row > (nCols/2) ) {
|
||||
row = nCols - 1 - row;
|
||||
}
|
||||
if ( col > row ) {
|
||||
XP_U16 tmp = col;
|
||||
col = row;
|
||||
row = tmp;
|
||||
}
|
||||
|
||||
/* For a smaller board, skip the outer "rings" */
|
||||
XP_U16 adj = (21 - nCols) / 2;
|
||||
col += adj;
|
||||
row += adj;
|
||||
|
||||
XP_U16 index = col;
|
||||
for ( XP_U16 ii = 1; ii <= row; ++ii ) {
|
||||
index += ii;
|
||||
}
|
||||
|
||||
XWBonusType result = BONUS_NONE;
|
||||
if ( index < VSIZE(sTwentyOne)) {
|
||||
result = sTwentyOne[index];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
XWBonusType
|
||||
model_getSquareBonus( const ModelCtxt* model, XWEnv xwe, XP_U16 col, XP_U16 row )
|
||||
model_getSquareBonus( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
XWBonusType result = BONUS_NONE;
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
|
@ -431,9 +469,7 @@ model_getSquareBonus( const ModelCtxt* model, XWEnv xwe, XP_U16 col, XP_U16 row
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
result = util_getSquareBonus( model->vol.util, xwe,
|
||||
model_numRows(model),
|
||||
col, row );
|
||||
result = getSquareBonus( model_numRows(model), col, row );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ XP_Bool model_listWordsThrough( ModelCtxt* model, XWEnv xwe, XP_U16 col,
|
|||
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
||||
|
||||
XWBonusType model_getSquareBonus( const ModelCtxt* model,
|
||||
XWEnv xwe, XP_U16 col, XP_U16 row );
|
||||
XP_U16 col, XP_U16 row );
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses,
|
||||
XP_U16 nBonuses );
|
||||
|
|
|
@ -34,8 +34,7 @@ extern "C" {
|
|||
/****************************** prototypes ******************************/
|
||||
static XP_Bool isLegalMove( ModelCtxt* model, XWEnv xwe, MoveInfo* moves,
|
||||
XP_Bool silent );
|
||||
static XP_U16 word_multiplier( const ModelCtxt* model, XWEnv xwe,
|
||||
XP_U16 col, XP_U16 row );
|
||||
static XP_U16 word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row );
|
||||
static XP_U16 find_end( const ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||
XP_Bool isHorizontal );
|
||||
static XP_U16 find_start( const ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||
|
@ -43,7 +42,7 @@ static XP_U16 find_start( const ModelCtxt* model, XP_U16 col, XP_U16 row,
|
|||
static XP_S16 checkScoreMove( ModelCtxt* model, XWEnv xwe, XP_S16 turn,
|
||||
EngineCtxt* engine, XWStreamCtxt* stream,
|
||||
XP_Bool silent, WordNotifierInfo* notifyInfo );
|
||||
static XP_U16 scoreWord( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
||||
static XP_U16 scoreWord( const ModelCtxt* model, XP_U16 turn,
|
||||
const MoveInfo* movei, EngineCtxt* engine,
|
||||
XWStreamCtxt* stream, WordNotifierInfo* notifyInfo );
|
||||
|
||||
|
@ -555,10 +554,10 @@ figureMoveScore( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
|||
for ( ii = 0; ii < nTiles; ++ii ) {
|
||||
*incr = moveInfo->tiles[ii].varCoord;
|
||||
moveMultiplier *= multipliers[ii] =
|
||||
word_multiplier( model, xwe, col, row );
|
||||
word_multiplier( model, col, row );
|
||||
}
|
||||
|
||||
oneScore = scoreWord( model, xwe, turn, moveInfo, (EngineCtxt*)NULL,
|
||||
oneScore = scoreWord( model, turn, moveInfo, (EngineCtxt*)NULL,
|
||||
stream, notifyInfo );
|
||||
if ( !!stream ) {
|
||||
formatWordScore( stream, oneScore, moveMultiplier );
|
||||
|
@ -576,7 +575,7 @@ figureMoveScore( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
|||
tmpMI.commonCoord = tiles->varCoord;
|
||||
tmpMI.tiles[0].tile = tiles->tile;
|
||||
|
||||
oneScore = scoreWord( model, xwe, turn, &tmpMI, engine, stream, notifyInfo );
|
||||
oneScore = scoreWord( model, turn, &tmpMI, engine, stream, notifyInfo );
|
||||
if ( !!stream ) {
|
||||
formatWordScore( stream, oneScore, multipliers[ii] );
|
||||
}
|
||||
|
@ -612,35 +611,39 @@ figureMoveScore( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
|||
} /* figureMoveScore */
|
||||
|
||||
static XP_U16
|
||||
word_multiplier( const ModelCtxt* model, XWEnv xwe, XP_U16 col, XP_U16 row )
|
||||
word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
XWBonusType bonus = model_getSquareBonus( model, xwe, col, row );
|
||||
XWBonusType bonus = model_getSquareBonus( model, col, row );
|
||||
switch ( bonus ) {
|
||||
case BONUS_DOUBLE_WORD:
|
||||
return 2;
|
||||
case BONUS_TRIPLE_WORD:
|
||||
return 3;
|
||||
case BONUS_QUAD_WORD:
|
||||
return 4;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} /* word_multiplier */
|
||||
|
||||
static XP_U16
|
||||
tile_multiplier( const ModelCtxt* model, XWEnv xwe, XP_U16 col, XP_U16 row )
|
||||
tile_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
XWBonusType bonus = model_getSquareBonus( model, xwe, col, row );
|
||||
XWBonusType bonus = model_getSquareBonus( model, col, row );
|
||||
switch ( bonus ) {
|
||||
case BONUS_DOUBLE_LETTER:
|
||||
return 2;
|
||||
case BONUS_TRIPLE_LETTER:
|
||||
return 3;
|
||||
case BONUS_QUAD_LETTER:
|
||||
return 4;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} /* tile_multiplier */
|
||||
|
||||
static XP_U16
|
||||
scoreWord( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
||||
scoreWord( const ModelCtxt* model, XP_U16 turn,
|
||||
const MoveInfo* movei, /* new tiles */
|
||||
EngineCtxt* engine,/* for crosswise caching */
|
||||
XWStreamCtxt* stream,
|
||||
|
@ -689,7 +692,7 @@ scoreWord( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
|||
thisTileValue = dict_getTileValue( dict, tile );
|
||||
|
||||
XP_ASSERT( *incr == tiles[0].varCoord );
|
||||
thisTileValue *= tile_multiplier( model, xwe, col, row );
|
||||
thisTileValue *= tile_multiplier( model, col, row );
|
||||
|
||||
XP_ASSERT( engine == NULL || nTiles == 1 );
|
||||
|
||||
|
@ -725,7 +728,7 @@ scoreWord( const ModelCtxt* model, XWEnv xwe, XP_U16 turn,
|
|||
* mode, as the blank won't be known there. (Assert will
|
||||
* fail.) */
|
||||
|
||||
tileMultiplier = tile_multiplier( model, xwe, col, row );
|
||||
tileMultiplier = tile_multiplier( model, col, row );
|
||||
++tiles;
|
||||
--nTiles;
|
||||
} else { /* placed on the board before this move */
|
||||
|
|
|
@ -242,7 +242,7 @@ pool_getNTilesLeftFor( const PoolContext* pool, Tile tile )
|
|||
} /* pool_remainingTileCount */
|
||||
|
||||
void
|
||||
pool_initFromDict( PoolContext* pool, const DictionaryCtxt* dict )
|
||||
pool_initFromDict( PoolContext* pool, const DictionaryCtxt* dict, XP_U16 nCols )
|
||||
{
|
||||
const XP_U16 numFaces = dict_numTileFaces( dict );
|
||||
|
||||
|
@ -253,9 +253,9 @@ pool_initFromDict( PoolContext* pool, const DictionaryCtxt* dict )
|
|||
numFaces * sizeof(pool->lettersLeft[0]) );
|
||||
pool->numTilesLeft = 0;
|
||||
|
||||
for ( Tile ii = 0; ii < numFaces; ++ii ) {
|
||||
XP_U16 numTiles = dict_numTiles( dict, ii );
|
||||
pool->lettersLeft[ii] = (XP_U8)numTiles;
|
||||
for ( Tile tile = 0; tile < numFaces; ++tile ) {
|
||||
XP_U16 numTiles = dict_numTilesForSize( dict, tile, nCols );
|
||||
pool->lettersLeft[tile] = (XP_U8)numTiles;
|
||||
pool->numTilesLeft += numTiles;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ XP_U16 pool_getNTilesLeftFor( const PoolContext* pool, Tile tile );
|
|||
PoolContext* pool_make( MPFORMAL_NOCOMMA );
|
||||
|
||||
void pool_destroy( PoolContext* pool );
|
||||
void pool_initFromDict( PoolContext* pool, const DictionaryCtxt* dict );
|
||||
void pool_initFromDict( PoolContext* pool, const DictionaryCtxt* dict,
|
||||
XP_U16 nCols );
|
||||
|
||||
void pool_writeToStream( PoolContext* pool, XWStreamCtxt* stream );
|
||||
PoolContext* pool_makeFromStream( MPFORMAL XWStreamCtxt* stream );
|
||||
|
|
|
@ -2573,7 +2573,8 @@ makePoolOnce( ServerCtxt* server )
|
|||
if ( server->pool == NULL ) {
|
||||
server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
||||
XP_STATUSF( "%s(): initing pool", __func__ );
|
||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
||||
pool_initFromDict( server->pool, model_getDictionary(model),
|
||||
server->vol.gi->boardSize );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4330,12 +4331,12 @@ server_formatDictCounts( ServerCtxt* server, XWEnv xwe, XWStreamCtxt* stream,
|
|||
stream_catString( stream, buf );
|
||||
|
||||
nChars = dict_numTileFaces( dict );
|
||||
|
||||
XP_U16 boardSize = server->vol.gi->boardSize;
|
||||
for ( tile = 0, nPrinted = 0; ; ) {
|
||||
XP_UCHAR buf[128];
|
||||
XP_U16 count, value;
|
||||
|
||||
count = dict_numTiles( dict, tile );
|
||||
count = dict_numTilesForSize( dict, tile, boardSize );
|
||||
|
||||
if ( count > 0 ) {
|
||||
const XP_UCHAR* face = NULL;
|
||||
|
|
|
@ -89,9 +89,6 @@ typedef struct UtilVtable {
|
|||
XWStreamCtxt* (*m_util_makeStreamFromAddr)(XW_UtilCtxt* uc, XWEnv xwe,
|
||||
XP_PlayerAddr channelNo );
|
||||
#endif
|
||||
|
||||
XWBonusType (*m_util_getSquareBonus)( XW_UtilCtxt* uc, XWEnv xwe, XP_U16 boardSize,
|
||||
XP_U16 col, XP_U16 row );
|
||||
void (*m_util_userError)( XW_UtilCtxt* uc, XWEnv xwe, UtilErrID id );
|
||||
|
||||
void (*m_util_notifyMove)( XW_UtilCtxt* uc, XWEnv xwe, XWStreamCtxt* stream );
|
||||
|
@ -221,9 +218,6 @@ struct XW_UtilCtxt {
|
|||
#define util_makeStreamFromAddr(uc,e,a) \
|
||||
(uc)->vtable->m_util_makeStreamFromAddr((uc), (e),(a))
|
||||
|
||||
#define util_getSquareBonus(uc,e,b,c,r) \
|
||||
(uc)->vtable->m_util_getSquareBonus((uc), (e),(b),(c),(r))
|
||||
|
||||
#define util_userError(uc,e,err) \
|
||||
(uc)->vtable->m_util_userError((uc),(e),(err))
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
XWLANG=BasEnglish
|
||||
LANGCODE=en_US
|
||||
LANGCODE=en
|
||||
DICT2DAWGARGS = -r -nosort
|
||||
DICTNOTE = "Wordlist created in the 1930s for language learners"
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ DICTNOTE = "Words on a list at www.wordfrequency.info"
|
|||
include ../Makefile.langcommon
|
||||
|
||||
ENGLISH = $(XWDICTPATH)/English
|
||||
SOURCEDICT ?= $(ENGLISH)/CSW.dict.gz
|
||||
SOURCEDICT ?= $(ENGLISH)/CSW19.dict
|
||||
|
||||
# I have permission to download the "top 5000" wordlist but not
|
||||
# necessarily to distribute it. And it contains words, especially
|
||||
|
@ -35,7 +35,7 @@ $(XWLANG)Main.dict.gz: $(SOURCEDICT) $(ENGLISH)/Top_5000.dict.gz
|
|||
zcat $(ENGLISH)/Top_5000.dict.gz | \
|
||||
sed 's/[[:lower:]]*/\U&/' | \
|
||||
sort > /tmp/Top_5000.dict
|
||||
zcat $< | tr -d '\r' | \
|
||||
cat $< | tr -d '\r' | \
|
||||
sed 's/[[:lower:]]*/\U&/' | \
|
||||
grep -e "^[A-Z]\{2,15\}$$" | \
|
||||
sort > /tmp/$$(basename $<)
|
||||
|
|
|
@ -137,7 +137,7 @@ DEFINES += -DNLI_VERSION=1
|
|||
# DEFINES += -DRELAY_VIA_HTTP
|
||||
|
||||
# MAX_ROWS controls STREAM_VERS_BIGBOARD and with it move hashing
|
||||
DEFINES += -DMAX_ROWS=32
|
||||
DEFINES += -DMAX_ROWS=23
|
||||
|
||||
ifdef CURSES_CELL_HT
|
||||
DEFINES += -DCURSES_CELL_HT=$(CURSES_CELL_HT)
|
||||
|
|
|
@ -418,6 +418,10 @@ curses_draw_drawCell( DrawCtx* p_dctx, XWEnv XP_UNUSED(xwe), const XP_Rect* rect
|
|||
ch = '^'; break;
|
||||
case BONUS_TRIPLE_WORD:
|
||||
ch = '#'; break;
|
||||
case BONUS_QUAD_LETTER:
|
||||
ch = '%'; break;
|
||||
case BONUS_QUAD_WORD:
|
||||
ch = '&'; break;
|
||||
default:
|
||||
break;
|
||||
} /* switch */
|
||||
|
|
|
@ -1326,7 +1326,6 @@ gtk_draw_getMiniWText( DrawCtx* XP_UNUSED(p_dctx), XWEnv XP_UNUSED(xwe),
|
|||
{
|
||||
/* GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx; */
|
||||
XP_UCHAR* str;
|
||||
|
||||
switch( textHint ) {
|
||||
case BONUS_DOUBLE_LETTER:
|
||||
str = "Double letter"; break;
|
||||
|
@ -1334,6 +1333,10 @@ gtk_draw_getMiniWText( DrawCtx* XP_UNUSED(p_dctx), XWEnv XP_UNUSED(xwe),
|
|||
str = "Double word"; break;
|
||||
case BONUS_TRIPLE_LETTER:
|
||||
str = "Triple letter"; break;
|
||||
case BONUS_QUAD_WORD:
|
||||
str = "Quad word"; break;
|
||||
case BONUS_QUAD_LETTER:
|
||||
str = "Quad letter"; break;
|
||||
case BONUS_TRIPLE_WORD:
|
||||
str = "Triple word"; break;
|
||||
case INTRADE_MW_TEXT:
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include "gtkutils.h"
|
||||
#include "gtkask.h"
|
||||
|
||||
#define MAX_SIZE_CHOICES 32
|
||||
|
||||
#define BINGO_THRESHOLD "Bingo threshold"
|
||||
#define TRAY_SIZE "Tray size"
|
||||
|
||||
|
@ -168,7 +166,7 @@ size_combo_changed( GtkComboBox* combo, gpointer gp )
|
|||
GtkNewGameState* state = (GtkNewGameState*)gp;
|
||||
gint index = gtk_combo_box_get_active( GTK_COMBO_BOX(combo) );
|
||||
if ( index >= 0 ) {
|
||||
state->nCols = MAX_COLS - index;
|
||||
state->nCols = MIN_COLS + (index * 2);
|
||||
XP_LOGF( "set nCols = %d", state->nCols );
|
||||
}
|
||||
} /* size_combo_changed */
|
||||
|
@ -348,14 +346,16 @@ addSizesRow( GtkNewGameState* state, GtkWidget* parent )
|
|||
gtk_widget_set_sensitive( boardSizeCombo, FALSE );
|
||||
}
|
||||
|
||||
for ( int ii = 0; ii < MAX_SIZE_CHOICES; ++ii ) {
|
||||
int curEntry = 0;
|
||||
for ( int siz = MIN_COLS; siz <= MAX_COLS; siz += 2 ) {
|
||||
char buf[10];
|
||||
XP_U16 siz = MAX_COLS - ii;
|
||||
// XP_U16 siz = MAX_COLS - ii;
|
||||
snprintf( buf, sizeof(buf), "%dx%d", siz, siz );
|
||||
gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT(boardSizeCombo), buf );
|
||||
if ( siz == state->nCols ) {
|
||||
gtk_combo_box_set_active( GTK_COMBO_BOX(boardSizeCombo), ii );
|
||||
gtk_combo_box_set_active( GTK_COMBO_BOX(boardSizeCombo), curEntry );
|
||||
}
|
||||
++curEntry;
|
||||
}
|
||||
|
||||
g_signal_connect( boardSizeCombo, "changed",
|
||||
|
|
|
@ -48,7 +48,6 @@ typedef struct LinuxDictionaryCtxt {
|
|||
XP_Bool useMMap;
|
||||
} LinuxDictionaryCtxt;
|
||||
|
||||
|
||||
/************************ Prototypes ***********************/
|
||||
static XP_Bool initFromDictFile( LinuxDictionaryCtxt* dctx,
|
||||
const LaunchParams* params,
|
||||
|
@ -279,13 +278,8 @@ linux_dictionary_destroy( DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe) )
|
|||
}
|
||||
}
|
||||
|
||||
/* super's destructor should do this!!!! */
|
||||
XP_FREEP( dict->mpool, &ctxt->super.desc );
|
||||
XP_FREEP( dict->mpool, &ctxt->super.md5Sum );
|
||||
XP_FREEP( dict->mpool, &ctxt->super.countsAndValues );
|
||||
XP_FREEP( dict->mpool, &ctxt->super.faces );
|
||||
XP_FREEP( dict->mpool, &ctxt->super.facePtrs );
|
||||
XP_FREEP( dict->mpool, &ctxt->super.name );
|
||||
dict_super_destroy( &ctxt->super );
|
||||
|
||||
XP_FREE( dict->mpool, ctxt );
|
||||
} /* linux_dictionary_destroy */
|
||||
|
||||
|
|
|
@ -249,8 +249,6 @@ linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs,
|
|||
}
|
||||
}
|
||||
|
||||
setSquareBonuses( cGlobals );
|
||||
|
||||
/* Need to save in order to have a valid selRow for the first send */
|
||||
linuxSaveGame( cGlobals );
|
||||
savedGame = true;
|
||||
|
|
|
@ -110,173 +110,6 @@ linux_util_makeEmptyDict( XW_UtilCtxt* XP_UNUSED_DBG(uctx), XWEnv xwe )
|
|||
return linux_dictionary_make( MPPARM(uctx->mpool) xwe, NULL, NULL, XP_FALSE );
|
||||
} /* linux_util_makeEmptyDict */
|
||||
|
||||
#define EM BONUS_NONE
|
||||
#define DL BONUS_DOUBLE_LETTER
|
||||
#define DW BONUS_DOUBLE_WORD
|
||||
#define TL BONUS_TRIPLE_LETTER
|
||||
#define TW BONUS_TRIPLE_WORD
|
||||
|
||||
static XWBonusType*
|
||||
bonusesFor( XP_U16 boardSize, XP_U16* len )
|
||||
{
|
||||
static XWBonusType scrabbleBoard[] = {
|
||||
TW,//EM,EM,DL,EM,EM,EM,TW,
|
||||
EM,DW,//EM,EM,EM,TL,EM,EM,
|
||||
|
||||
EM,EM,DW,//EM,EM,EM,DL,EM,
|
||||
DL,EM,EM,DW,//EM,EM,EM,DL,
|
||||
|
||||
EM,EM,EM,EM,DW,//EM,EM,EM,
|
||||
EM,TL,EM,EM,EM,TL,//EM,EM,
|
||||
|
||||
EM,EM,DL,EM,EM,EM,DL,//EM,
|
||||
TW,EM,EM,DL,EM,EM,EM,DW,
|
||||
}; /* scrabbleBoard */
|
||||
|
||||
static XWBonusType seventeen[] = {
|
||||
TW,//EM,EM,DL,EM,EM,EM,TW,
|
||||
EM,DW,//EM,EM,EM,TL,EM,EM,
|
||||
|
||||
EM,EM,DW,//EM,EM,EM,DL,EM,
|
||||
DL,EM,EM,DW,//EM,EM,EM,DL,
|
||||
|
||||
EM,EM,EM,EM,DW,//EM,EM,EM,
|
||||
EM,TL,EM,EM,EM,TL,//EM,EM,
|
||||
|
||||
EM,EM,DL,EM,EM,EM,DL,//EM,
|
||||
TW,EM,EM,DL,EM,EM,EM,DW,
|
||||
TW,EM,EM,DL,EM,EM,EM,DW,DW,
|
||||
}; /* scrabbleBoard */
|
||||
|
||||
XWBonusType* result = NULL;
|
||||
if ( boardSize == 15 ) {
|
||||
result = scrabbleBoard;
|
||||
*len = VSIZE(scrabbleBoard);
|
||||
} else if ( boardSize == 17 ) {
|
||||
result = seventeen;
|
||||
*len = VSIZE(seventeen);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void
|
||||
setSquareBonuses( const CommonGlobals* cGlobals )
|
||||
{
|
||||
XP_U16 nBonuses;
|
||||
XWBonusType* bonuses =
|
||||
bonusesFor( cGlobals->gi->boardSize, &nBonuses );
|
||||
if ( !!bonuses ) {
|
||||
model_setSquareBonuses( cGlobals->game.model, bonuses, nBonuses );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static XWBonusType*
|
||||
parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
||||
{
|
||||
XWBonusType* result = NULL;
|
||||
FILE* file = fopen( bonusFile, "r" );
|
||||
if ( !!file ) {
|
||||
XP_U16 row = 0;
|
||||
XP_U16 col;
|
||||
result = malloc( nCols * nCols * sizeof(*result) );
|
||||
char line[1024];
|
||||
while ( line == fgets( line, sizeof(line), file ) && row < nCols ) {
|
||||
bool inComment = false;
|
||||
char* ch;
|
||||
XWBonusType bonus;
|
||||
col = 0;
|
||||
for ( ch = line; '\0' != *ch; ++ch ) {
|
||||
switch( *ch ) {
|
||||
case '#': /* comment; line is done */
|
||||
inComment = true;
|
||||
break;
|
||||
case '+':
|
||||
bonus = BONUS_DOUBLE_LETTER;
|
||||
break;
|
||||
case '*':
|
||||
bonus = BONUS_DOUBLE_WORD;
|
||||
break;
|
||||
case '^':
|
||||
bonus = BONUS_TRIPLE_LETTER;
|
||||
break;
|
||||
case '!':
|
||||
bonus = BONUS_TRIPLE_WORD;
|
||||
break;
|
||||
case '.':
|
||||
case ' ':
|
||||
bonus = BONUS_NONE;
|
||||
break;
|
||||
case '\n':
|
||||
case '\a':
|
||||
break;
|
||||
default:
|
||||
if ( !inComment ) {
|
||||
fprintf( stderr, "unexpected char '%c' in %s\n", *ch, bonusFile );
|
||||
exit( 1 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( !inComment && col < nCols ) {
|
||||
result[(row * nCols) + col] = bonus;
|
||||
++col;
|
||||
/* Let's just allow anything to follow the 15 letters we
|
||||
care about, e.g. comments */
|
||||
if ( col >= nCols ) {
|
||||
inComment = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( col > 0 && row < nCols - 1) {
|
||||
++row;
|
||||
}
|
||||
}
|
||||
fclose( file );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static XWBonusType
|
||||
linux_util_getSquareBonus( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe), XP_U16 nCols,
|
||||
XP_U16 col, XP_U16 row )
|
||||
{
|
||||
static XWBonusType* parsedFile = NULL;
|
||||
XWBonusType result = EM;
|
||||
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
if ( NULL == parsedFile && NULL != cGlobals->params->bonusFile ) {
|
||||
if ( !parsedFile ) {
|
||||
parsedFile = parseBonusFile( nCols, cGlobals->params->bonusFile );
|
||||
}
|
||||
}
|
||||
if ( NULL != parsedFile ) {
|
||||
result = parsedFile[(row*nCols) + col];
|
||||
} else {
|
||||
XP_U16 nEntries;
|
||||
XWBonusType* scrabbleBoard = bonusesFor( 15, &nEntries );
|
||||
|
||||
XP_U16 index, ii;
|
||||
if ( col > (nCols/2) ) col = nCols - 1 - col;
|
||||
if ( row > (nCols/2) ) row = nCols - 1 - row;
|
||||
if ( col > row ) {
|
||||
XP_U16 tmp = col;
|
||||
col = row;
|
||||
row = tmp;
|
||||
}
|
||||
index = col;
|
||||
for ( ii = 1; ii <= row; ++ii ) {
|
||||
index += ii;
|
||||
}
|
||||
|
||||
if ( index < nEntries) {
|
||||
result = scrabbleBoard[index];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} /* linux_util_getSquareBonus */
|
||||
|
||||
static const DictionaryCtxt*
|
||||
linux_util_getDict( XW_UtilCtxt* uc, XWEnv xwe,
|
||||
XP_LangCode XP_UNUSED(lang), const XP_UCHAR* dictName )
|
||||
|
@ -316,7 +149,6 @@ linux_util_vt_init( MPFORMAL XW_UtilCtxt* util )
|
|||
util->vtable = XP_MALLOC( mpool, sizeof(UtilVtable) );
|
||||
|
||||
util->vtable->m_util_makeEmptyDict = linux_util_makeEmptyDict;
|
||||
util->vtable->m_util_getSquareBonus = linux_util_getSquareBonus;
|
||||
util->vtable->m_util_getDict = linux_util_getDict;
|
||||
util->vtable->m_util_getInviteeName = linux_util_getInviteeName;
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
I installed emcc via
|
||||
# git clone https://github.com/emscripten-core/emsdk.git
|
||||
then
|
||||
# cd emsdk
|
||||
# git checkout 3.1.0
|
||||
|
||||
But I have no particular reason to believe that tag's better than a
|
||||
later one when it comes along.
|
||||
# ./emsdk install latest
|
||||
# ./emsdk activate latest
|
||||
|
||||
|
|
|
@ -45,32 +45,6 @@ wasm_util_makeStreamFromAddr( XW_UtilCtxt* uc, XWEnv xwe, XP_PlayerAddr channelN
|
|||
return stream;
|
||||
}
|
||||
|
||||
static XWBonusType
|
||||
wasm_util_getSquareBonus( XW_UtilCtxt* uc, XWEnv xwe, XP_U16 boardSize,
|
||||
XP_U16 col, XP_U16 row )
|
||||
{
|
||||
#define BONUS_DIM 8
|
||||
static const int s_buttsBoard[BONUS_DIM][BONUS_DIM] = {
|
||||
{ BONUS_TRIPLE_WORD, BONUS_NONE, BONUS_NONE,BONUS_DOUBLE_LETTER,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_TRIPLE_WORD },
|
||||
{ BONUS_NONE, BONUS_DOUBLE_WORD, BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_TRIPLE_LETTER,BONUS_NONE,BONUS_NONE },
|
||||
|
||||
{ BONUS_NONE, BONUS_NONE, BONUS_DOUBLE_WORD,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_LETTER,BONUS_NONE },
|
||||
{ BONUS_DOUBLE_LETTER,BONUS_NONE, BONUS_NONE,BONUS_DOUBLE_WORD,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_LETTER },
|
||||
|
||||
{ BONUS_NONE, BONUS_NONE, BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_WORD,BONUS_NONE,BONUS_NONE,BONUS_NONE },
|
||||
{ BONUS_NONE, BONUS_TRIPLE_LETTER,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_TRIPLE_LETTER,BONUS_NONE,BONUS_NONE },
|
||||
|
||||
{ BONUS_NONE, BONUS_NONE, BONUS_DOUBLE_LETTER,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_LETTER,BONUS_NONE },
|
||||
{ BONUS_TRIPLE_WORD, BONUS_NONE, BONUS_NONE,BONUS_DOUBLE_LETTER,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_WORD },
|
||||
}; /* buttsBoard */
|
||||
|
||||
int half = boardSize / 2;
|
||||
if ( col > half ) { col = (half*2) - col; }
|
||||
if ( row > half ) { row = (half*2) - row; }
|
||||
XP_ASSERT( col < BONUS_DIM && row < BONUS_DIM );
|
||||
return s_buttsBoard[row][col];
|
||||
}
|
||||
|
||||
static const XP_UCHAR*
|
||||
wasm_getErrString( UtilErrID id, XP_Bool* silent )
|
||||
{
|
||||
|
@ -628,7 +602,6 @@ wasm_util_make( MPFORMAL CurGameInfo* gi, XW_DUtilCtxt* dctxt, GameState* closur
|
|||
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_userError, wasm );
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_makeStreamFromAddr, wasm );
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_getSquareBonus, wasm );
|
||||
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_notifyMove, wasm );
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_notifyTrade, wasm );
|
||||
|
|
Loading…
Reference in a new issue