mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
Merge branch 'android_branch' into android_browsedict
Conflicts: xwords4/android/XWords4/jni/anddict.c
This commit is contained in:
commit
4760ceda5a
25 changed files with 518 additions and 176 deletions
|
@ -439,9 +439,9 @@ and_dictionary_destroy( DictionaryCtxt* dict )
|
||||||
XP_FREE( ctxt->super.mpool, ctxt->super.bitmaps );
|
XP_FREE( ctxt->super.mpool, ctxt->super.bitmaps );
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_FREE( ctxt->super.mpool, ctxt->super.faces );
|
XP_FREEP( ctxt->super.mpool, &ctxt->super.faces );
|
||||||
XP_FREE( ctxt->super.mpool, ctxt->super.facePtrs );
|
XP_FREEP( ctxt->super.mpool, &ctxt->super.facePtrs );
|
||||||
XP_FREE( ctxt->super.mpool, ctxt->super.countsAndValues );
|
XP_FREEP( ctxt->super.mpool, &ctxt->super.countsAndValues );
|
||||||
XP_FREEP( ctxt->super.mpool, &ctxt->super.name );
|
XP_FREEP( ctxt->super.mpool, &ctxt->super.name );
|
||||||
XP_FREEP( ctxt->super.mpool, &ctxt->super.langName );
|
XP_FREEP( ctxt->super.mpool, &ctxt->super.langName );
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ and_dictionary_destroy( DictionaryCtxt* dict )
|
||||||
(*env)->DeleteGlobalRef( env, ctxt->byteArray );
|
(*env)->DeleteGlobalRef( env, ctxt->byteArray );
|
||||||
}
|
}
|
||||||
XP_FREE( ctxt->super.mpool, ctxt );
|
XP_FREE( ctxt->super.mpool, ctxt );
|
||||||
}
|
} /* and_dictionary_destroy */
|
||||||
|
|
||||||
jobject
|
jobject
|
||||||
and_dictionary_getChars( JNIEnv* env, DictionaryCtxt* dict )
|
and_dictionary_getChars( JNIEnv* env, DictionaryCtxt* dict )
|
||||||
|
@ -524,37 +524,41 @@ DictionaryCtxt*
|
||||||
makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jstring jname,
|
makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jstring jname,
|
||||||
jbyteArray jbytes, jstring jpath, jstring jlangname, jboolean check )
|
jbyteArray jbytes, jstring jpath, jstring jlangname, jboolean check )
|
||||||
{
|
{
|
||||||
AndDictionaryCtxt* anddict = (AndDictionaryCtxt*)
|
jbyte* bytes = NULL;
|
||||||
and_dictionary_make_empty( MPPARM(mpool) env, jniutil );
|
jbyteArray byteArray = NULL;
|
||||||
|
off_t bytesSize = 0;
|
||||||
jsize len = 0;
|
|
||||||
|
|
||||||
if ( NULL == jpath ) {
|
if ( NULL == jpath ) {
|
||||||
len = (*env)->GetArrayLength( env, jbytes );
|
bytesSize = (*env)->GetArrayLength( env, jbytes );
|
||||||
anddict->byteArray = (*env)->NewGlobalRef( env, jbytes );
|
byteArray = (*env)->NewGlobalRef( env, jbytes );
|
||||||
anddict->bytes =
|
bytes = (*env)->GetByteArrayElements( env, byteArray, NULL );
|
||||||
(*env)->GetByteArrayElements( env, anddict->byteArray, NULL );
|
|
||||||
} else {
|
} else {
|
||||||
XP_ASSERT( NULL == anddict->byteArray );
|
|
||||||
const char* path = (*env)->GetStringUTFChars( env, jpath, NULL );
|
const char* path = (*env)->GetStringUTFChars( env, jpath, NULL );
|
||||||
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if ( 0 == stat( path, &statbuf ) ) {
|
if ( 0 == stat( path, &statbuf ) && 0 < statbuf.st_size ) {
|
||||||
int fd = open( path, O_RDONLY );
|
int fd = open( path, O_RDONLY );
|
||||||
if ( fd >= 0 ) {
|
if ( fd >= 0 ) {
|
||||||
anddict->bytes = mmap( NULL, statbuf.st_size,
|
void* ptr = mmap( NULL, statbuf.st_size, PROT_READ,
|
||||||
PROT_READ, MAP_PRIVATE,
|
MAP_PRIVATE, fd, 0 );
|
||||||
fd, 0 );
|
|
||||||
close( fd );
|
close( fd );
|
||||||
|
if ( MAP_FAILED != ptr ) {
|
||||||
anddict->bytesSize = statbuf.st_size;
|
bytes = ptr;
|
||||||
len = statbuf.st_size;
|
bytesSize = statbuf.st_size;
|
||||||
XP_ASSERT( MAP_FAILED != anddict->bytes );
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*env)->ReleaseStringUTFChars( env, jpath, path );
|
(*env)->ReleaseStringUTFChars( env, jpath, path );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AndDictionaryCtxt* anddict = NULL;
|
||||||
|
if ( NULL != bytes ) {
|
||||||
|
anddict = (AndDictionaryCtxt*)
|
||||||
|
and_dictionary_make_empty( MPPARM(mpool) env, jniutil );
|
||||||
|
anddict->bytes = bytes;
|
||||||
|
anddict->byteArray = byteArray;
|
||||||
|
anddict->bytesSize = bytesSize;
|
||||||
|
|
||||||
anddict->super.destructor = and_dictionary_destroy;
|
anddict->super.destructor = and_dictionary_destroy;
|
||||||
|
|
||||||
/* copy the name */
|
/* copy the name */
|
||||||
|
@ -563,11 +567,12 @@ makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jstring jname,
|
||||||
|
|
||||||
XP_U32 numEdges;
|
XP_U32 numEdges;
|
||||||
XP_Bool parses = parseDict( anddict, (XP_U8*)anddict->bytes,
|
XP_Bool parses = parseDict( anddict, (XP_U8*)anddict->bytes,
|
||||||
len, &numEdges );
|
bytesSize, &numEdges );
|
||||||
if ( !parses || (check && !checkSanity( &anddict->super, numEdges ) ) ) {
|
if ( !parses || (check && !checkSanity( &anddict->super, numEdges ) ) ) {
|
||||||
and_dictionary_destroy( (DictionaryCtxt*)anddict );
|
and_dictionary_destroy( (DictionaryCtxt*)anddict );
|
||||||
anddict = NULL;
|
anddict = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (DictionaryCtxt*)anddict;
|
return (DictionaryCtxt*)anddict;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,8 +280,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo
|
||||||
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, NULL,
|
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, NULL,
|
||||||
jDictBytes, jpath, NULL, check );
|
jDictBytes, jpath, NULL, check );
|
||||||
if ( NULL != dict ) {
|
if ( NULL != dict ) {
|
||||||
|
if ( NULL != jinfo ) {
|
||||||
setInt( env, jinfo, "langCode", dict_getLangCode( dict ) );
|
setInt( env, jinfo, "langCode", dict_getLangCode( dict ) );
|
||||||
setInt( env, jinfo, "wordCount", dict_getWordCount( dict ) );
|
setInt( env, jinfo, "wordCount", dict_getWordCount( dict ) );
|
||||||
|
}
|
||||||
dict_destroy( dict );
|
dict_destroy( dict );
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,18 +64,19 @@ public class DictLangCache {
|
||||||
|
|
||||||
public static String annotatedDictName( Context context, DictAndLoc dal )
|
public static String annotatedDictName( Context context, DictAndLoc dal )
|
||||||
{
|
{
|
||||||
|
String result = null;
|
||||||
DictInfo info = getInfo( context, dal );
|
DictInfo info = getInfo( context, dal );
|
||||||
|
if ( null != info ) {
|
||||||
int wordCount = info.wordCount;
|
int wordCount = info.wordCount;
|
||||||
|
|
||||||
String langName = getLangName( context, dal.name );
|
String langName = getLangName( context, dal.name );
|
||||||
String result;
|
|
||||||
if ( 0 == wordCount ) {
|
if ( 0 == wordCount ) {
|
||||||
result = String.format( "%s (%s)", dal.name, langName );
|
result = String.format( "%s (%s)", dal.name, langName );
|
||||||
} else {
|
} else {
|
||||||
result = String.format( "%s (%s/%d)", dal.name, langName,
|
result = String.format( "%s (%s/%d)", dal.name, langName,
|
||||||
wordCount );
|
wordCount );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ public class DictLangCache {
|
||||||
DictAndLoc[] dals = DictUtils.dictList( context );
|
DictAndLoc[] dals = DictUtils.dictList( context );
|
||||||
for ( DictAndLoc dal : dals ) {
|
for ( DictAndLoc dal : dals ) {
|
||||||
DictInfo info = getInfo( context, dal );
|
DictInfo info = getInfo( context, dal );
|
||||||
if ( code == info.langCode ) {
|
if ( null != info && code == info.langCode ) {
|
||||||
al.add( info );
|
al.add( info );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ public class DictLangCache {
|
||||||
DictAndLoc[] dals = DictUtils.dictList( context );
|
DictAndLoc[] dals = DictUtils.dictList( context );
|
||||||
for ( DictAndLoc dal : dals ) {
|
for ( DictAndLoc dal : dals ) {
|
||||||
DictInfo info = getInfo( context, dal );
|
DictInfo info = getInfo( context, dal );
|
||||||
if ( code == info.langCode ) {
|
if ( null != info && code == info.langCode ) {
|
||||||
al.add( dal );
|
al.add( dal );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,6 +374,12 @@ public class DictLangCache {
|
||||||
|
|
||||||
info = new DictInfo();
|
info = new DictInfo();
|
||||||
|
|
||||||
|
// It should not be possible for dict_getInfo to fail
|
||||||
|
// unless DictUtils.dictList() isn't doing its job and
|
||||||
|
// puts unchecked dicts on the list. Should probably
|
||||||
|
// assert that this returns true. Open question: do I
|
||||||
|
// always trust dicts in the BUILTIN and INTERNAL
|
||||||
|
// locations? Files can get damaged....
|
||||||
if ( XwJNI.dict_getInfo( pairs.m_bytes[0], pairs.m_paths[0],
|
if ( XwJNI.dict_getInfo( pairs.m_bytes[0], pairs.m_paths[0],
|
||||||
JNIUtilsImpl.get(),
|
JNIUtilsImpl.get(),
|
||||||
DictUtils.DictLoc.DOWNLOAD == dal.loc,
|
DictUtils.DictLoc.DOWNLOAD == dal.loc,
|
||||||
|
|
|
@ -121,7 +121,7 @@ public class DictUtils {
|
||||||
String[] list = dir.list();
|
String[] list = dir.list();
|
||||||
if ( null != list ) {
|
if ( null != list ) {
|
||||||
for ( String file : list ) {
|
for ( String file : list ) {
|
||||||
if ( isDict( file, strict ) ) {
|
if ( isDict( file, strict? dir : null ) ) {
|
||||||
al.add( new DictAndLoc( removeDictExtn( file ), loc ) );
|
al.add( new DictAndLoc( removeDictExtn( file ), loc ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,14 +135,14 @@ public class DictUtils {
|
||||||
ArrayList<DictAndLoc> al = new ArrayList<DictAndLoc>();
|
ArrayList<DictAndLoc> al = new ArrayList<DictAndLoc>();
|
||||||
|
|
||||||
for ( String file : getAssets( context ) ) {
|
for ( String file : getAssets( context ) ) {
|
||||||
if ( isDict( file, false ) ) {
|
if ( isDict( file, null ) ) {
|
||||||
al.add( new DictAndLoc( removeDictExtn( file ),
|
al.add( new DictAndLoc( removeDictExtn( file ),
|
||||||
DictLoc.BUILT_IN ) );
|
DictLoc.BUILT_IN ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( String file : context.fileList() ) {
|
for ( String file : context.fileList() ) {
|
||||||
if ( isDict( file, false ) ) {
|
if ( isDict( file, null ) ) {
|
||||||
al.add( new DictAndLoc( removeDictExtn( file ),
|
al.add( new DictAndLoc( removeDictExtn( file ),
|
||||||
DictLoc.INTERNAL ) );
|
DictLoc.INTERNAL ) );
|
||||||
}
|
}
|
||||||
|
@ -464,11 +464,13 @@ public class DictUtils {
|
||||||
return file.endsWith( XWConstants.GAME_EXTN );
|
return file.endsWith( XWConstants.GAME_EXTN );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDict( String file, boolean strictTest )
|
private static boolean isDict( String file, File dir )
|
||||||
{
|
{
|
||||||
boolean ok = file.endsWith( XWConstants.DICT_EXTN );
|
boolean ok = file.endsWith( XWConstants.DICT_EXTN );
|
||||||
if ( ok && strictTest ) {
|
if ( ok && null != dir ) {
|
||||||
Utils.logf( "isDict: not really checking %s yet", file );
|
String fullPath = new File( dir, file ).getPath();
|
||||||
|
ok = XwJNI.dict_getInfo( null, fullPath, JNIUtilsImpl.get(),
|
||||||
|
true, null );
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1002,8 +1002,7 @@ timerFiredForPen( BoardCtxt* board )
|
||||||
#endif
|
#endif
|
||||||
if ( !listWords ) {
|
if ( !listWords ) {
|
||||||
XWBonusType bonus;
|
XWBonusType bonus;
|
||||||
bonus = util_getSquareBonus( board->util, board->model,
|
bonus = model_getSquareBonus( board->model, col, row );
|
||||||
col, row );
|
|
||||||
if ( bonus != BONUS_NONE ) {
|
if ( bonus != BONUS_NONE ) {
|
||||||
#ifdef XWFEATURE_MINIWIN
|
#ifdef XWFEATURE_MINIWIN
|
||||||
text = draw_getMiniWText( board->draw,
|
text = draw_getMiniWText( board->draw,
|
||||||
|
@ -1198,7 +1197,7 @@ invalPerimeter( BoardCtxt* board )
|
||||||
ScrollData* hsd = &board->sd[SCROLL_H];
|
ScrollData* hsd = &board->sd[SCROLL_H];
|
||||||
XP_U16 firstCol = hsd->offset;
|
XP_U16 firstCol = hsd->offset;
|
||||||
XP_U16 lastCol = hsd->lastVisible;
|
XP_U16 lastCol = hsd->lastVisible;
|
||||||
XP_U16 firstAndLast = (1 << lastCol) | (1 << firstCol);
|
RowFlags firstAndLast = (1 << lastCol) | (1 << firstCol);
|
||||||
ScrollData* vsd = &board->sd[SCROLL_V];
|
ScrollData* vsd = &board->sd[SCROLL_V];
|
||||||
XP_U16 firstRow = vsd->offset;
|
XP_U16 firstRow = vsd->offset;
|
||||||
XP_U16 lastRow = vsd->lastVisible;
|
XP_U16 lastRow = vsd->lastVisible;
|
||||||
|
@ -1588,7 +1587,7 @@ invalReflection( BoardCtxt* board )
|
||||||
|
|
||||||
while ( nRows-- ) {
|
while ( nRows-- ) {
|
||||||
XP_U16 nCols;
|
XP_U16 nCols;
|
||||||
XP_U16 redrawFlag = board->redrawFlags[nRows];
|
RowFlags redrawFlag = board->redrawFlags[nRows];
|
||||||
if ( !redrawFlag ) {
|
if ( !redrawFlag ) {
|
||||||
continue; /* nothing set this row */
|
continue; /* nothing set this row */
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*-mode: C; fill-column: 78; compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */
|
/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE -j3"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 1997 - 2010 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 1997 - 2011 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -299,11 +299,11 @@ drawBoard( BoardCtxt* board )
|
||||||
|
|
||||||
nVisCols = model_numCols( model ) - board->zoomCount;
|
nVisCols = model_numCols( model ) - board->zoomCount;
|
||||||
for ( row = vsd->offset; row <= vsd->lastVisible; ++row ) {
|
for ( row = vsd->offset; row <= vsd->lastVisible; ++row ) {
|
||||||
XP_U16 rowFlags = board->redrawFlags[row];
|
RowFlags rowFlags = board->redrawFlags[row];
|
||||||
if ( rowFlags != 0 ) {
|
if ( rowFlags != 0 ) {
|
||||||
XP_U16 failedBits = 0;
|
RowFlags failedBits = 0;
|
||||||
for ( col = 0; col < nVisCols; ++col ) {
|
for ( col = 0; col < nVisCols; ++col ) {
|
||||||
XP_U16 colMask = 1 << (col + hsd->offset);
|
RowFlags colMask = 1 << (col + hsd->offset);
|
||||||
if ( 0 != (rowFlags & colMask) ) {
|
if ( 0 != (rowFlags & colMask) ) {
|
||||||
if ( !drawCell( board, col + hsd->offset,
|
if ( !drawCell( board, col + hsd->offset,
|
||||||
row, XP_TRUE )) {
|
row, XP_TRUE )) {
|
||||||
|
@ -331,7 +331,7 @@ drawBoard( BoardCtxt* board )
|
||||||
XWBonusType bonus;
|
XWBonusType bonus;
|
||||||
HintAtts hintAtts;
|
HintAtts hintAtts;
|
||||||
CellFlags flags = CELL_NONE;
|
CellFlags flags = CELL_NONE;
|
||||||
bonus = util_getSquareBonus( board->util, model, col, row );
|
bonus = model_getSquareBonus( model, col, row );
|
||||||
hintAtts = figureHintAtts( board, col, row );
|
hintAtts = figureHintAtts( board, col, row );
|
||||||
#ifdef KEYBOARD_NAV
|
#ifdef KEYBOARD_NAV
|
||||||
if ( cellFocused( board, col, row ) ) {
|
if ( cellFocused( board, col, row ) ) {
|
||||||
|
@ -436,7 +436,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
|
||||||
textP = dict_getTileString( dict, tile );
|
textP = dict_getTileString( dict, tile );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bonus = util_getSquareBonus( board->util, model, col, row );
|
bonus = model_getSquareBonus( model, col, row );
|
||||||
hintAtts = figureHintAtts( board, col, row );
|
hintAtts = figureHintAtts( board, col, row );
|
||||||
|
|
||||||
if ( (col==board->star_row) && (row==board->star_row) ) {
|
if ( (col==board->star_row) && (row==board->star_row) ) {
|
||||||
|
|
|
@ -157,7 +157,7 @@ struct BoardCtxt {
|
||||||
XP_S16 timerStoppedTurn;
|
XP_S16 timerStoppedTurn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XP_U16 redrawFlags[MAX_ROWS];
|
RowFlags redrawFlags[MAX_ROWS];
|
||||||
|
|
||||||
XP_Rect boardBounds;
|
XP_Rect boardBounds;
|
||||||
XP_U16 heightAsSet;
|
XP_U16 heightAsSet;
|
||||||
|
|
|
@ -115,7 +115,9 @@ typedef enum {
|
||||||
} XWTimerReason;
|
} XWTimerReason;
|
||||||
|
|
||||||
#define MAX_NUM_PLAYERS 4
|
#define MAX_NUM_PLAYERS 4
|
||||||
|
#ifndef MAX_ROWS
|
||||||
# define MAX_ROWS 16
|
# define MAX_ROWS 16
|
||||||
|
#endif
|
||||||
#define MAX_COLS MAX_ROWS
|
#define MAX_COLS MAX_ROWS
|
||||||
#ifdef EIGHT_TILES
|
#ifdef EIGHT_TILES
|
||||||
# define MAX_TRAY_TILES 8
|
# define MAX_TRAY_TILES 8
|
||||||
|
@ -127,6 +129,24 @@ typedef enum {
|
||||||
#define NPLAYERS_NBITS 3
|
#define NPLAYERS_NBITS 3
|
||||||
#define EMPTIED_TRAY_BONUS 50
|
#define EMPTIED_TRAY_BONUS 50
|
||||||
|
|
||||||
|
#if MAX_ROWS <= 16
|
||||||
|
typedef XP_U16 RowFlags;
|
||||||
|
#elif MAX_ROWS <= 32
|
||||||
|
typedef XP_U32 RowFlags;
|
||||||
|
#else
|
||||||
|
error
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BONUS_NONE,
|
||||||
|
BONUS_DOUBLE_LETTER,
|
||||||
|
BONUS_DOUBLE_WORD,
|
||||||
|
BONUS_TRIPLE_LETTER,
|
||||||
|
BONUS_TRIPLE_WORD,
|
||||||
|
|
||||||
|
BONUS_LAST
|
||||||
|
} XWBonusType;
|
||||||
|
|
||||||
/* I need a way to communiate prefs to common/ code. For now, though, I'll
|
/* I need a way to communiate prefs to common/ code. For now, though, I'll
|
||||||
* leave storage of these values up to the platforms. First, because I don't
|
* leave storage of these values up to the platforms. First, because I don't
|
||||||
* want to deal with versioning in the common code. Second, becuase they
|
* want to deal with versioning in the common code. Second, becuase they
|
||||||
|
|
|
@ -39,16 +39,6 @@ extern "C" {
|
||||||
|
|
||||||
typedef XP_U8 XP_LangCode;
|
typedef XP_U8 XP_LangCode;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
BONUS_NONE,
|
|
||||||
BONUS_DOUBLE_LETTER,
|
|
||||||
BONUS_DOUBLE_WORD,
|
|
||||||
BONUS_TRIPLE_LETTER,
|
|
||||||
BONUS_TRIPLE_WORD,
|
|
||||||
|
|
||||||
BONUS_LAST
|
|
||||||
} XWBonusType;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
INTRADE_MW_TEXT = BONUS_LAST
|
INTRADE_MW_TEXT = BONUS_LAST
|
||||||
} XWMiniTextType;
|
} XWMiniTextType;
|
||||||
|
|
|
@ -426,13 +426,18 @@ gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
|
||||||
XP_U16 ii;
|
XP_U16 ii;
|
||||||
XP_UCHAR* str;
|
XP_UCHAR* str;
|
||||||
XP_U16 strVersion = stream_getVersion( stream );
|
XP_U16 strVersion = stream_getVersion( stream );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U16 nColsNBits = STREAM_VERS_BIGBOARD > strVersion ? 4 : NUMCOLS_NBITS;
|
||||||
|
#else
|
||||||
|
XP_U16 nColsNBits = NUMCOLS_NBITS;
|
||||||
|
#endif
|
||||||
|
|
||||||
str = stringFromStream( mpool, stream );
|
str = stringFromStream( mpool, stream );
|
||||||
replaceStringIfDifferent( mpool, &gi->dictName, str );
|
replaceStringIfDifferent( mpool, &gi->dictName, str );
|
||||||
XP_FREEP( mpool, &str );
|
XP_FREEP( mpool, &str );
|
||||||
|
|
||||||
gi->nPlayers = (XP_U8)stream_getBits( stream, NPLAYERS_NBITS );
|
gi->nPlayers = (XP_U8)stream_getBits( stream, NPLAYERS_NBITS );
|
||||||
gi->boardSize = (XP_U8)stream_getBits( stream, 4 );
|
gi->boardSize = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||||
gi->serverRole = (DeviceRole)stream_getBits( stream, 2 );
|
gi->serverRole = (DeviceRole)stream_getBits( stream, 2 );
|
||||||
gi->hintsNotAllowed = stream_getBits( stream, 1 );
|
gi->hintsNotAllowed = stream_getBits( stream, 1 );
|
||||||
if ( strVersion < STREAM_VERS_ROBOTIQ ) {
|
if ( strVersion < STREAM_VERS_ROBOTIQ ) {
|
||||||
|
@ -494,7 +499,7 @@ gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi )
|
||||||
stringToStream( stream, gi->dictName );
|
stringToStream( stream, gi->dictName );
|
||||||
|
|
||||||
stream_putBits( stream, NPLAYERS_NBITS, gi->nPlayers );
|
stream_putBits( stream, NPLAYERS_NBITS, gi->nPlayers );
|
||||||
stream_putBits( stream, 4, gi->boardSize );
|
stream_putBits( stream, NUMCOLS_NBITS, gi->boardSize );
|
||||||
stream_putBits( stream, 2, gi->serverRole );
|
stream_putBits( stream, 2, gi->serverRole );
|
||||||
stream_putBits( stream, 1, gi->hintsNotAllowed );
|
stream_putBits( stream, 1, gi->hintsNotAllowed );
|
||||||
stream_putBits( stream, 2, gi->phoniesAction );
|
stream_putBits( stream, 2, gi->phoniesAction );
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MAX_COLS > 16
|
||||||
|
# define STREAM_VERS_BIGBOARD 0x12
|
||||||
|
#endif
|
||||||
#define STREAM_SAVE_PREVWORDS 0x11
|
#define STREAM_SAVE_PREVWORDS 0x11
|
||||||
#define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10
|
#define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10
|
||||||
#define STREAM_VERS_PLAYERDICTS 0x0F
|
#define STREAM_VERS_PLAYERDICTS 0x0F
|
||||||
|
@ -53,7 +56,11 @@ extern "C" {
|
||||||
#define STREAM_VERS_41B4 0x02
|
#define STREAM_VERS_41B4 0x02
|
||||||
#define STREAM_VERS_405 0x01
|
#define STREAM_VERS_405 0x01
|
||||||
|
|
||||||
|
#if MAX_COLS > 16
|
||||||
|
# define CUR_STREAM_VERS STREAM_VERS_BIGBOARD
|
||||||
|
#else
|
||||||
# define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS
|
# define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct LocalPlayer {
|
typedef struct LocalPlayer {
|
||||||
XP_UCHAR* name;
|
XP_UCHAR* name;
|
||||||
|
|
|
@ -115,15 +115,21 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
||||||
{
|
{
|
||||||
ModelCtxt* model;
|
ModelCtxt* model;
|
||||||
XP_U16 nCols, nRows;
|
XP_U16 nCols, nRows;
|
||||||
short i;
|
XP_U16 ii;
|
||||||
XP_Bool hasDict;
|
XP_Bool hasDict;
|
||||||
XP_U16 nPlayers;
|
XP_U16 nPlayers;
|
||||||
|
XP_U16 nColsNBits;
|
||||||
XP_U16 version = stream_getVersion( stream );
|
XP_U16 version = stream_getVersion( stream );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
nColsNBits = STREAM_VERS_BIGBOARD > version ? 4 : NUMCOLS_NBITS;
|
||||||
|
#else
|
||||||
|
nColsNBits = NUMCOLS_NBITS;
|
||||||
|
#endif
|
||||||
|
|
||||||
XP_ASSERT( !!dict || !!dicts );
|
XP_ASSERT( !!dict || !!dicts );
|
||||||
|
|
||||||
nCols = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
nCols = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||||
nRows = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
nRows = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||||
|
|
||||||
hasDict = (version >= STREAM_VERS_MODEL_NO_DICT)
|
hasDict = (version >= STREAM_VERS_MODEL_NO_DICT)
|
||||||
? XP_FALSE : stream_getBits( stream, 1 );
|
? XP_FALSE : stream_getBits( stream, 1 );
|
||||||
|
@ -138,6 +144,20 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
||||||
model = model_make( MPPARM(mpool) dict, dicts, util, nCols, nRows );
|
model = model_make( MPPARM(mpool) dict, dicts, util, nCols, nRows );
|
||||||
model->nPlayers = nPlayers;
|
model->nPlayers = nPlayers;
|
||||||
|
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
if ( STREAM_VERS_BIGBOARD <= version ) {
|
||||||
|
model->nBonuses = stream_getBits( stream, 7 );
|
||||||
|
if ( 0 < model->nBonuses ) {
|
||||||
|
model->bonuses =
|
||||||
|
XP_MALLOC( model->vol.mpool,
|
||||||
|
model->nBonuses * sizeof( model->bonuses[0] ) );
|
||||||
|
for ( ii = 0; ii < model->nBonuses; ++ii ) {
|
||||||
|
model->bonuses[ii] = stream_getBits( stream, 4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
stack_loadFromStream( model->vol.stack, stream );
|
stack_loadFromStream( model->vol.stack, stream );
|
||||||
|
|
||||||
buildModelFromStack( model, model->vol.stack, XP_FALSE, 0,
|
buildModelFromStack( model, model->vol.stack, XP_FALSE, 0,
|
||||||
|
@ -145,10 +165,10 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
||||||
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
|
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
for ( ii = 0; ii < model->nPlayers; ++ii ) {
|
||||||
loadPlayerCtxt( stream, version, &model->players[i] );
|
loadPlayerCtxt( stream, version, &model->players[ii] );
|
||||||
setPendingCounts( model, i );
|
setPendingCounts( model, ii );
|
||||||
invalidateScore( model, i );
|
invalidateScore( model, ii );
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
@ -157,7 +177,7 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
||||||
void
|
void
|
||||||
model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream )
|
model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
short i;
|
XP_U16 ii;
|
||||||
|
|
||||||
stream_putBits( stream, NUMCOLS_NBITS, model->nCols );
|
stream_putBits( stream, NUMCOLS_NBITS, model->nCols );
|
||||||
stream_putBits( stream, NUMCOLS_NBITS, model->nRows );
|
stream_putBits( stream, NUMCOLS_NBITS, model->nRows );
|
||||||
|
@ -165,10 +185,17 @@ model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream )
|
||||||
/* we have two bits for nPlayers, so range must be 0..3, not 1..4 */
|
/* we have two bits for nPlayers, so range must be 0..3, not 1..4 */
|
||||||
stream_putBits( stream, NPLAYERS_NBITS, model->nPlayers );
|
stream_putBits( stream, NPLAYERS_NBITS, model->nPlayers );
|
||||||
|
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
stream_putBits( stream, 7, model->nBonuses );
|
||||||
|
for ( ii = 0; ii < model->nBonuses; ++ii ) {
|
||||||
|
stream_putBits( stream, 4, model->bonuses[ii] );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
stack_writeToStream( model->vol.stack, stream );
|
stack_writeToStream( model->vol.stack, stream );
|
||||||
|
|
||||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
for ( ii = 0; ii < model->nPlayers; ++ii ) {
|
||||||
writePlayerCtxt( stream, &model->players[i] );
|
writePlayerCtxt( stream, &model->players[ii] );
|
||||||
}
|
}
|
||||||
} /* model_writeToStream */
|
} /* model_writeToStream */
|
||||||
|
|
||||||
|
@ -240,9 +267,90 @@ model_destroy( ModelCtxt* model )
|
||||||
{
|
{
|
||||||
stack_destroy( model->vol.stack );
|
stack_destroy( model->vol.stack );
|
||||||
/* is this it!? */
|
/* is this it!? */
|
||||||
|
if ( !!model->bonuses ) {
|
||||||
|
XP_FREE( model->vol.mpool, model->bonuses );
|
||||||
|
}
|
||||||
XP_FREE( model->vol.mpool, model );
|
XP_FREE( model->vol.mpool, model );
|
||||||
} /* model_destroy */
|
} /* model_destroy */
|
||||||
|
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
void
|
||||||
|
model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses, XP_U16 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->bonuses ) {
|
||||||
|
XP_FREE( model->vol.mpool, model->bonuses );
|
||||||
|
}
|
||||||
|
model->bonuses = XP_MALLOC( model->vol.mpool,
|
||||||
|
nBonuses * sizeof(model->bonuses[0]) );
|
||||||
|
XP_MEMCPY( model->bonuses, bonuses, nBonuses * sizeof(model->bonuses[0]) );
|
||||||
|
model->nBonuses = nBonuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
borrowSquareBonuses( ModelCtxt* dest, const ModelCtxt* src )
|
||||||
|
{
|
||||||
|
XP_ASSERT( !dest->bonuses );
|
||||||
|
dest->bonuses = src->bonuses;
|
||||||
|
dest->nBonuses = src->nBonuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
returnSquareBonuses( ModelCtxt* dest )
|
||||||
|
{
|
||||||
|
dest->bonuses = NULL;
|
||||||
|
dest->nBonuses = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define borrowSquareBonuses(d,s)
|
||||||
|
# define returnSquareBonuses(d)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XWBonusType
|
||||||
|
model_getSquareBonus( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||||
|
{
|
||||||
|
XWBonusType result = BONUS_NONE;
|
||||||
|
|
||||||
|
if ( 0 ) {
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
} else if ( !!model->bonuses ) {
|
||||||
|
XP_U16 nCols = model_numCols( model );
|
||||||
|
XP_U16 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;
|
||||||
|
}
|
||||||
|
for ( ii = 1; ii <= row; ++ii ) {
|
||||||
|
col += ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( col < model->nBonuses ) {
|
||||||
|
result = model->bonuses[col];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
result = util_getSquareBonus( model->vol.util, model_numRows(model),
|
||||||
|
col, row );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
modelAddEntry( ModelCtxt* model, XP_U16 indx, const StackEntry* entry,
|
modelAddEntry( ModelCtxt* model, XP_U16 indx, const StackEntry* entry,
|
||||||
XP_Bool useStack, XWStreamCtxt* stream,
|
XP_Bool useStack, XWStreamCtxt* stream,
|
||||||
|
@ -815,6 +923,12 @@ model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
||||||
{
|
{
|
||||||
PlayerCtxt* player;
|
PlayerCtxt* player;
|
||||||
XP_S16 numTiles;
|
XP_S16 numTiles;
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U16 version = stream_getVersion( stream );
|
||||||
|
XP_U16 nColsNBits = STREAM_VERS_BIGBOARD > version ? 4 : NUMCOLS_NBITS;
|
||||||
|
#else
|
||||||
|
XP_U16 nColsNBits = NUMCOLS_NBITS;
|
||||||
|
#endif
|
||||||
|
|
||||||
XP_ASSERT( turn >= 0 );
|
XP_ASSERT( turn >= 0 );
|
||||||
player = &model->players[turn];
|
player = &model->players[turn];
|
||||||
|
@ -831,8 +945,8 @@ model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
||||||
&col, &row, &isBlank );
|
&col, &row, &isBlank );
|
||||||
XP_ASSERT( numTiles >= 0 );
|
XP_ASSERT( numTiles >= 0 );
|
||||||
stream_putBits( stream, TILE_NBITS, tile );
|
stream_putBits( stream, TILE_NBITS, tile );
|
||||||
stream_putBits( stream, NUMCOLS_NBITS, col );
|
stream_putBits( stream, nColsNBits, col );
|
||||||
stream_putBits( stream, NUMCOLS_NBITS, row );
|
stream_putBits( stream, nColsNBits, row );
|
||||||
stream_putBits( stream, 1, isBlank );
|
stream_putBits( stream, 1, isBlank );
|
||||||
}
|
}
|
||||||
} /* model_currentMoveToStream */
|
} /* model_currentMoveToStream */
|
||||||
|
@ -847,8 +961,15 @@ void
|
||||||
model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
||||||
XWStreamCtxt* stream )
|
XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
XP_U16 numTiles;
|
XP_U16 numTiles, ii;
|
||||||
Tile blank = dict_getBlankTile( model_getDictionary(model) );
|
Tile blank = dict_getBlankTile( model_getDictionary(model) );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U16 version = stream_getVersion( stream );
|
||||||
|
XP_U16 nColsNBits = STREAM_VERS_BIGBOARD > version ? 4 : NUMCOLS_NBITS;
|
||||||
|
#else
|
||||||
|
XP_U16 nColsNBits = NUMCOLS_NBITS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
model_resetCurrentTurn( model, playerNum );
|
model_resetCurrentTurn( model, playerNum );
|
||||||
|
|
||||||
|
@ -856,12 +977,12 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
||||||
|
|
||||||
XP_LOGF( "%s: numTiles=%d", __func__, numTiles );
|
XP_LOGF( "%s: numTiles=%d", __func__, numTiles );
|
||||||
|
|
||||||
while ( numTiles-- ) {
|
for ( ii = 0; ii < numTiles; ++ii ) {
|
||||||
XP_S16 foundAt;
|
XP_S16 foundAt;
|
||||||
Tile moveTile;
|
Tile moveTile;
|
||||||
Tile tileFace = (Tile)stream_getBits( stream, TILE_NBITS );
|
Tile tileFace = (Tile)stream_getBits( stream, TILE_NBITS );
|
||||||
XP_U16 col = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
XP_U16 col = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||||
XP_U16 row = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
XP_U16 row = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||||
XP_Bool isBlank = stream_getBits( stream, 1 );
|
XP_Bool isBlank = stream_getBits( stream, 1 );
|
||||||
|
|
||||||
/* This code gets called both for the server, which has all the
|
/* This code gets called both for the server, which has all the
|
||||||
|
@ -1931,6 +2052,7 @@ makeTmpModel( ModelCtxt* model, XWStreamCtxt* stream,
|
||||||
model->vol.util, model_numCols(model),
|
model->vol.util, model_numCols(model),
|
||||||
model_numRows(model));
|
model_numRows(model));
|
||||||
model_setNPlayers( tmpModel, model->nPlayers );
|
model_setNPlayers( tmpModel, model->nPlayers );
|
||||||
|
borrowSquareBonuses( tmpModel, model );
|
||||||
|
|
||||||
buildModelFromStack( tmpModel, model->vol.stack, XP_FALSE, 0, stream,
|
buildModelFromStack( tmpModel, model->vol.stack, XP_FALSE, 0, stream,
|
||||||
(WordNotifierInfo*)NULL, mpf_pre, mpf_post, closure );
|
(WordNotifierInfo*)NULL, mpf_pre, mpf_post, closure );
|
||||||
|
@ -1952,6 +2074,7 @@ model_writeGameHistory( ModelCtxt* model, XWStreamCtxt* stream,
|
||||||
|
|
||||||
tmpModel = makeTmpModel( model, stream, printMovePre, printMovePost,
|
tmpModel = makeTmpModel( model, stream, printMovePre, printMovePost,
|
||||||
&closure );
|
&closure );
|
||||||
|
returnSquareBonuses( tmpModel );
|
||||||
model_destroy( tmpModel );
|
model_destroy( tmpModel );
|
||||||
|
|
||||||
if ( gameOver ) {
|
if ( gameOver ) {
|
||||||
|
@ -2215,6 +2338,11 @@ loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc )
|
||||||
{
|
{
|
||||||
PendingTile* pt;
|
PendingTile* pt;
|
||||||
XP_U16 nTiles;
|
XP_U16 nTiles;
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U16 nColsNBits = STREAM_VERS_BIGBOARD > version ? 4 : NUMCOLS_NBITS;
|
||||||
|
#else
|
||||||
|
XP_U16 nColsNBits = NUMCOLS_NBITS;
|
||||||
|
#endif
|
||||||
|
|
||||||
pc->curMoveValid = stream_getBits( stream, 1 );
|
pc->curMoveValid = stream_getBits( stream, 1 );
|
||||||
|
|
||||||
|
@ -2230,8 +2358,8 @@ loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc )
|
||||||
nTiles = pc->nPending + pc->nUndone;
|
nTiles = pc->nPending + pc->nUndone;
|
||||||
for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) {
|
for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) {
|
||||||
XP_U16 nBits;
|
XP_U16 nBits;
|
||||||
pt->col = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
|
pt->col = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||||
pt->row = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
|
pt->row = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||||
|
|
||||||
nBits = (version <= STREAM_VERS_RELAY) ? 6 : 7;
|
nBits = (version <= STREAM_VERS_RELAY) ? 6 : 7;
|
||||||
pt->tile = (Tile)stream_getBits( stream, nBits );
|
pt->tile = (Tile)stream_getBits( stream, nBits );
|
||||||
|
|
|
@ -29,7 +29,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MAX_COLS <= 16
|
||||||
# define NUMCOLS_NBITS 4
|
# define NUMCOLS_NBITS 4
|
||||||
|
#elif MAX_COLS <= 32
|
||||||
|
# define NUMCOLS_NBITS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EIGHT_TILES
|
#ifdef EIGHT_TILES
|
||||||
# define NTILES_NBITS 4
|
# define NTILES_NBITS 4
|
||||||
|
@ -265,6 +269,11 @@ void model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||||
/* Have there been too many passes (so game should end)? */
|
/* Have there been too many passes (so game should end)? */
|
||||||
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
||||||
|
|
||||||
|
XWBonusType model_getSquareBonus( const ModelCtxt* model,
|
||||||
|
XP_U16 col, XP_U16 row );
|
||||||
|
void model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses,
|
||||||
|
XP_U16 nBonuses );
|
||||||
|
|
||||||
XP_Bool model_checkMoveLegal( ModelCtxt* model, XP_S16 player,
|
XP_Bool model_checkMoveLegal( ModelCtxt* model, XP_S16 player,
|
||||||
XWStreamCtxt* stream,
|
XWStreamCtxt* stream,
|
||||||
WordNotifierInfo* notifyInfo );
|
WordNotifierInfo* notifyInfo );
|
||||||
|
|
|
@ -76,6 +76,8 @@ struct ModelCtxt {
|
||||||
XP_U16 nPlayers;
|
XP_U16 nPlayers;
|
||||||
XP_U16 nCols;
|
XP_U16 nCols;
|
||||||
XP_U16 nRows;
|
XP_U16 nRows;
|
||||||
|
XP_U16 nBonuses;
|
||||||
|
XWBonusType* bonuses;
|
||||||
};
|
};
|
||||||
|
|
||||||
void invalidateScore( ModelCtxt* model, XP_S16 player );
|
void invalidateScore( ModelCtxt* model, XP_S16 player );
|
||||||
|
|
|
@ -526,7 +526,7 @@ figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* moveInfo,
|
||||||
static XP_U16
|
static XP_U16
|
||||||
word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||||
{
|
{
|
||||||
XWBonusType bonus = util_getSquareBonus( model->vol.util, model, col, row );
|
XWBonusType bonus = model_getSquareBonus( model, col, row );
|
||||||
switch ( bonus ) {
|
switch ( bonus ) {
|
||||||
case BONUS_DOUBLE_WORD:
|
case BONUS_DOUBLE_WORD:
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -540,8 +540,7 @@ word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||||
static XP_U16
|
static XP_U16
|
||||||
tile_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
tile_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||||
{
|
{
|
||||||
XWBonusType bonus = util_getSquareBonus( model->vol.util, model,
|
XWBonusType bonus = model_getSquareBonus( model, col, row );
|
||||||
col, row );
|
|
||||||
switch ( bonus ) {
|
switch ( bonus ) {
|
||||||
case BONUS_DOUBLE_LETTER:
|
case BONUS_DOUBLE_LETTER:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
|
@ -60,6 +60,9 @@ typedef struct ServerPlayer {
|
||||||
|
|
||||||
typedef struct RemoteAddress {
|
typedef struct RemoteAddress {
|
||||||
XP_PlayerAddr channelNo;
|
XP_PlayerAddr channelNo;
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U8 streamVersion;
|
||||||
|
#endif
|
||||||
} RemoteAddress;
|
} RemoteAddress;
|
||||||
|
|
||||||
/* These are the parts of the server's state that needs to be preserved
|
/* These are the parts of the server's state that needs to be preserved
|
||||||
|
@ -84,6 +87,9 @@ typedef struct ServerNonvolatiles {
|
||||||
XP_U8 pendingRegistrations;
|
XP_U8 pendingRegistrations;
|
||||||
XP_Bool showRobotScores;
|
XP_Bool showRobotScores;
|
||||||
XP_Bool sortNewTiles;
|
XP_Bool sortNewTiles;
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_U8 streamVersion;
|
||||||
|
#endif
|
||||||
#ifdef XWFEATURE_SLOW_ROBOT
|
#ifdef XWFEATURE_SLOW_ROBOT
|
||||||
XP_U16 robotThinkMin, robotThinkMax; /* not saved (yet) */
|
XP_U16 robotThinkMin, robotThinkMax; /* not saved (yet) */
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,12 +145,14 @@ static XWStreamCtxt* messageStreamWithHeader( ServerCtxt* server,
|
||||||
XP_U16 devIndex, XW_Proto code );
|
XP_U16 devIndex, XW_Proto code );
|
||||||
static XP_Bool handleRegistrationMsg( ServerCtxt* server,
|
static XP_Bool handleRegistrationMsg( ServerCtxt* server,
|
||||||
XWStreamCtxt* stream );
|
XWStreamCtxt* stream );
|
||||||
static void registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream );
|
static XP_S8 registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream );
|
||||||
static void server_sendInitialMessage( ServerCtxt* server );
|
static void server_sendInitialMessage( ServerCtxt* server );
|
||||||
static void sendBadWordMsgs( ServerCtxt* server );
|
static void sendBadWordMsgs( ServerCtxt* server );
|
||||||
static XP_Bool handleIllegalWord( ServerCtxt* server,
|
static XP_Bool handleIllegalWord( ServerCtxt* server,
|
||||||
XWStreamCtxt* incoming );
|
XWStreamCtxt* incoming );
|
||||||
static void tellMoveWasLegal( ServerCtxt* server );
|
static void tellMoveWasLegal( ServerCtxt* server );
|
||||||
|
static void writeProto( const ServerCtxt* server, XWStreamCtxt* stream,
|
||||||
|
XW_Proto proto );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PICK_NEXT -1
|
#define PICK_NEXT -1
|
||||||
|
@ -230,6 +238,9 @@ initServer( ServerCtxt* server )
|
||||||
syncPlayers( server );
|
syncPlayers( server );
|
||||||
|
|
||||||
server->nv.nDevices = 1; /* local device (0) is always there */
|
server->nv.nDevices = 1; /* local device (0) is always there */
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
server->nv.streamVersion = STREAM_SAVE_PREVWORDS; /* default to old */
|
||||||
|
#endif
|
||||||
} /* initServer */
|
} /* initServer */
|
||||||
|
|
||||||
ServerCtxt*
|
ServerCtxt*
|
||||||
|
@ -280,7 +291,18 @@ getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
||||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||||
nv->addresses[ii].channelNo =
|
nv->addresses[ii].channelNo =
|
||||||
(XP_PlayerAddr)stream_getBits( stream, 16 );
|
(XP_PlayerAddr)stream_getBits( stream, 16 );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
if ( STREAM_VERS_BIGBOARD <= version ) {
|
||||||
|
nv->addresses[ii].streamVersion = stream_getBits( stream, 8 );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
if ( STREAM_SAVE_PREVWORDS < version ) {
|
||||||
|
nv->streamVersion = stream_getU8 ( stream );
|
||||||
|
}
|
||||||
|
XP_LOGF( "%s: read streamVersion: 0x%x", __func__, nv->streamVersion );
|
||||||
|
#endif
|
||||||
} /* getNV */
|
} /* getNV */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -301,7 +323,14 @@ putNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
||||||
|
|
||||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||||
stream_putBits( stream, 16, nv->addresses[ii].channelNo );
|
stream_putBits( stream, 16, nv->addresses[ii].channelNo );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
stream_putBits( stream, 8, nv->addresses[ii].streamVersion );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
stream_putU8( stream, nv->streamVersion );
|
||||||
|
XP_LOGF( "%s: wrote streamVersion: 0x%x", __func__, nv->streamVersion );
|
||||||
|
#endif
|
||||||
} /* putNV */
|
} /* putNV */
|
||||||
|
|
||||||
static XWStreamCtxt*
|
static XWStreamCtxt*
|
||||||
|
@ -515,7 +544,7 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
if ( server->nv.gameState == XWSTATE_NONE ) {
|
if ( server->nv.gameState == XWSTATE_NONE ) {
|
||||||
stream_open( stream );
|
stream_open( stream );
|
||||||
|
|
||||||
stream_putBits( stream, XWPROTO_NBITS, XWPROTO_DEVICE_REGISTRATION );
|
writeProto( server, stream, XWPROTO_DEVICE_REGISTRATION );
|
||||||
|
|
||||||
nPlayers = gi->nPlayers;
|
nPlayers = gi->nPlayers;
|
||||||
XP_ASSERT( nPlayers > 0 );
|
XP_ASSERT( nPlayers > 0 );
|
||||||
|
@ -531,8 +560,8 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_putBits( stream, 1, LP_IS_ROBOT(lp) ); /* better not to send this */
|
stream_putBits( stream, 1, LP_IS_ROBOT(lp) ); /* better not to
|
||||||
|
send this */
|
||||||
/* The first nPlayers players are the ones we'll use. The local flag
|
/* The first nPlayers players are the ones we'll use. The local flag
|
||||||
doesn't matter when for SERVER_ISCLIENT. */
|
doesn't matter when for SERVER_ISCLIENT. */
|
||||||
name = emptyStringIfNull(lp->name);
|
name = emptyStringIfNull(lp->name);
|
||||||
|
@ -543,6 +572,10 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
stream_putBits( stream, NAME_LEN_NBITS, len );
|
stream_putBits( stream, NAME_LEN_NBITS, len );
|
||||||
stream_putBytes( stream, name, len );
|
stream_putBytes( stream, name, len );
|
||||||
}
|
}
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
stream_putU8( stream, CUR_STREAM_VERS );
|
||||||
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
XP_LOGF( "%s: wierd state %s; dropping message", __func__,
|
XP_LOGF( "%s: wierd state %s; dropping message", __func__,
|
||||||
getStateStr(server->nv.gameState) );
|
getStateStr(server->nv.gameState) );
|
||||||
|
@ -593,11 +626,32 @@ callTurnChangeListener( ServerCtxt* server )
|
||||||
} /* callTurnChangeListener */
|
} /* callTurnChangeListener */
|
||||||
|
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
|
# ifdef STREAM_VERS_BIGBOARD
|
||||||
|
static void
|
||||||
|
setStreamVersion( ServerCtxt* server )
|
||||||
|
{
|
||||||
|
XP_U16 devIndex;
|
||||||
|
XP_U8 streamVersion = CUR_STREAM_VERS;
|
||||||
|
for ( devIndex = 1; devIndex < server->nv.nDevices; ++devIndex ) {
|
||||||
|
XP_U8 devVersion = server->nv.addresses[devIndex].streamVersion;
|
||||||
|
if ( devVersion < streamVersion ) {
|
||||||
|
streamVersion = devVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XP_LOGF( "%s: setting streamVersion: %d", __func__, streamVersion );
|
||||||
|
server->nv.streamVersion = streamVersion;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# define setStreamVersion(s)
|
||||||
|
# endif
|
||||||
|
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
|
handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
XP_Bool success = XP_TRUE;
|
XP_Bool success = XP_TRUE;
|
||||||
XP_U16 playersInMsg, i;
|
XP_U16 playersInMsg;
|
||||||
|
XP_S8 clientIndex;
|
||||||
|
XP_U16 ii = 0;
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
|
|
||||||
/* code will have already been consumed */
|
/* code will have already been consumed */
|
||||||
|
@ -608,21 +662,41 @@ handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
util_userError( server->vol.util, ERR_REG_UNEXPECTED_USER );
|
util_userError( server->vol.util, ERR_REG_UNEXPECTED_USER );
|
||||||
success = XP_FALSE;
|
success = XP_FALSE;
|
||||||
} else {
|
} else {
|
||||||
for ( i = 0; i < playersInMsg; ++i ) {
|
XP_S8 prevIndex = -1;
|
||||||
registerRemotePlayer( server, stream );
|
for ( ; ii < playersInMsg; ++ii ) {
|
||||||
|
clientIndex = registerRemotePlayer( server, stream );
|
||||||
|
|
||||||
/* This is abusing the semantics of turn change -- at least in the
|
/* This is abusing the semantics of turn change -- at least in the
|
||||||
case where there is another device yet to register -- but we
|
case where there is another device yet to register -- but we
|
||||||
need to let the board know to redraw the scoreboard with more
|
need to let the board know to redraw the scoreboard with more
|
||||||
players there. */
|
players there. */
|
||||||
callTurnChangeListener( server );
|
callTurnChangeListener( server );
|
||||||
|
XP_ASSERT( ii == 0 || prevIndex == clientIndex );
|
||||||
|
prevIndex = clientIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
if ( 0 < stream_getSize(stream) ) {
|
||||||
|
XP_U8 streamVersion = stream_getU8( stream );
|
||||||
|
if ( streamVersion >= STREAM_VERS_BIGBOARD ) {
|
||||||
|
XP_LOGF( "%s: upping device %d streamVersion to %d",
|
||||||
|
__func__, clientIndex, streamVersion );
|
||||||
|
server->nv.addresses[clientIndex].streamVersion = streamVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( server->nv.pendingRegistrations == 0 ) {
|
if ( server->nv.pendingRegistrations == 0 ) {
|
||||||
|
XP_ASSERT( ii == playersInMsg ); /* otherwise malformed */
|
||||||
|
setStreamVersion( server );
|
||||||
assignTilesToAll( server );
|
assignTilesToAll( server );
|
||||||
SETSTATE( server, XWSTATE_RECEIVED_ALL_REG );
|
SETSTATE( server, XWSTATE_RECEIVED_ALL_REG );
|
||||||
}
|
}
|
||||||
}
|
/* now set server's streamVersion if all remote players have the higher one. */
|
||||||
|
/* But first need to pass it in the strramx */
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
} /* handleRegistrationMsg */
|
} /* handleRegistrationMsg */
|
||||||
#endif
|
#endif
|
||||||
|
@ -999,7 +1073,7 @@ findFirstPending( ServerCtxt* server, ServerPlayer** playerP )
|
||||||
return lp;
|
return lp;
|
||||||
} /* findFirstPending */
|
} /* findFirstPending */
|
||||||
|
|
||||||
static void
|
static XP_S8
|
||||||
registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream )
|
registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
XP_S8 deviceIndex;
|
XP_S8 deviceIndex;
|
||||||
|
@ -1039,10 +1113,13 @@ registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
|
|
||||||
XP_ASSERT( channelNo != 0 );
|
XP_ASSERT( channelNo != 0 );
|
||||||
addr->channelNo = channelNo;
|
addr->channelNo = channelNo;
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
addr->streamVersion = STREAM_SAVE_PREVWORDS;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
player->deviceIndex = deviceIndex;
|
player->deviceIndex = deviceIndex;
|
||||||
|
return deviceIndex;
|
||||||
} /* registerRemotePlayer */
|
} /* registerRemotePlayer */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1096,6 +1173,7 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
|
|
||||||
/* version; any dependencies here? */
|
/* version; any dependencies here? */
|
||||||
XP_U8 streamVersion = stream_getU8( stream );
|
XP_U8 streamVersion = stream_getU8( stream );
|
||||||
|
XP_LOGF( "%s: set streamVersion to %d", __func__, streamVersion );
|
||||||
stream_setVersion( stream, streamVersion );
|
stream_setVersion( stream, streamVersion );
|
||||||
|
|
||||||
gameID = stream_getU32( stream );
|
gameID = stream_getU32( stream );
|
||||||
|
@ -1234,10 +1312,8 @@ server_sendInitialMessage( ServerCtxt* server )
|
||||||
DictionaryCtxt* dict = model_getDictionary(model);
|
DictionaryCtxt* dict = model_getDictionary(model);
|
||||||
XP_ASSERT( !!stream );
|
XP_ASSERT( !!stream );
|
||||||
stream_open( stream );
|
stream_open( stream );
|
||||||
stream_putBits( stream, XWPROTO_NBITS, XWPROTO_CLIENT_SETUP );
|
writeProto( server, stream, XWPROTO_CLIENT_SETUP );
|
||||||
|
|
||||||
/* write version for server's benefit; use old version until format
|
|
||||||
changes */
|
|
||||||
stream_putU8( stream, CUR_STREAM_VERS );
|
stream_putU8( stream, CUR_STREAM_VERS );
|
||||||
|
|
||||||
XP_LOGF( "putting gameID %lx into msg", gameID );
|
XP_LOGF( "putting gameID %lx into msg", gameID );
|
||||||
|
@ -1323,6 +1399,7 @@ printCode(char* intro, XW_Proto code)
|
||||||
caseStr( str, XWPROTO_MOVE_CONFIRM );
|
caseStr( str, XWPROTO_MOVE_CONFIRM );
|
||||||
caseStr( str, XWPROTO_CLIENT_REQ_END_GAME );
|
caseStr( str, XWPROTO_CLIENT_REQ_END_GAME );
|
||||||
caseStr( str, XWPROTO_END_GAME );
|
caseStr( str, XWPROTO_END_GAME );
|
||||||
|
caseStr( str, XWPROTO_NEW_PROTO );
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_STATUSF( "\t%s for %s", intro, str );
|
XP_STATUSF( "\t%s for %s", intro, str );
|
||||||
|
@ -1341,9 +1418,11 @@ messageStreamWithHeader( ServerCtxt* server, XP_U16 devIndex, XW_Proto code )
|
||||||
printCode("making", code);
|
printCode("making", code);
|
||||||
|
|
||||||
stream = util_makeStreamFromAddr( server->vol.util, channelNo );
|
stream = util_makeStreamFromAddr( server->vol.util, channelNo );
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
stream_setVersion( stream, server->nv.streamVersion );
|
||||||
|
#endif
|
||||||
stream_open( stream );
|
stream_open( stream );
|
||||||
stream_putBits( stream, XWPROTO_NBITS, code );
|
writeProto( server, stream, code );
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
} /* messageStreamWithHeader */
|
} /* messageStreamWithHeader */
|
||||||
|
@ -2440,13 +2519,44 @@ server_handleUndo( ServerCtxt* server )
|
||||||
} /* server_handleUndo */
|
} /* server_handleUndo */
|
||||||
|
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
|
static void
|
||||||
|
writeProto( const ServerCtxt* server, XWStreamCtxt* stream, XW_Proto proto )
|
||||||
|
{
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
XP_ASSERT( server->nv.streamVersion > 0 );
|
||||||
|
if ( STREAM_SAVE_PREVWORDS < server->nv.streamVersion ) {
|
||||||
|
stream_putBits( stream, XWPROTO_NBITS, XWPROTO_NEW_PROTO );
|
||||||
|
stream_putBits( stream, 8, CUR_STREAM_VERS );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
XP_USE(server);
|
||||||
|
#endif
|
||||||
|
stream_putBits( stream, XWPROTO_NBITS, proto );
|
||||||
|
}
|
||||||
|
|
||||||
|
static XW_Proto
|
||||||
|
readProto( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
|
{
|
||||||
|
XW_Proto proto = (XW_Proto)stream_getBits( stream, XWPROTO_NBITS );
|
||||||
|
XP_U8 version = STREAM_SAVE_PREVWORDS; /* version prior to fmt change */
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
if ( XWPROTO_NEW_PROTO == proto ) {
|
||||||
|
version = stream_getBits( stream, 8 );
|
||||||
|
proto = (XW_Proto)stream_getBits( stream, XWPROTO_NBITS );
|
||||||
|
}
|
||||||
|
server->nv.streamVersion = version;
|
||||||
|
#else
|
||||||
|
XP_USE(server);
|
||||||
|
#endif
|
||||||
|
stream_setVersion( stream, version );
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
|
server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
|
||||||
{
|
{
|
||||||
XW_Proto code;
|
|
||||||
XP_Bool accepted = XP_FALSE;
|
XP_Bool accepted = XP_FALSE;
|
||||||
|
XW_Proto code = readProto( server, incoming );
|
||||||
code = (XW_Proto)stream_getBits( incoming, XWPROTO_NBITS );
|
|
||||||
|
|
||||||
printCode( "Receiving", code );
|
printCode( "Receiving", code );
|
||||||
|
|
||||||
|
@ -2535,7 +2645,8 @@ server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
|
||||||
accepted = XP_TRUE;
|
accepted = XP_TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XP_WARNF( "Unknown code on incoming message: %d\n", code );
|
XP_WARNF( "%s: Unknown code on incoming message: %d\n",
|
||||||
|
__func__, code );
|
||||||
break;
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,7 @@ typedef struct UtilVtable {
|
||||||
XP_PlayerAddr channelNo );
|
XP_PlayerAddr channelNo );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XWBonusType (*m_util_getSquareBonus)( XW_UtilCtxt* uc,
|
XWBonusType (*m_util_getSquareBonus)( XW_UtilCtxt* uc, XP_U16 boardSize,
|
||||||
const ModelCtxt* model,
|
|
||||||
XP_U16 col, XP_U16 row );
|
XP_U16 col, XP_U16 row );
|
||||||
void (*m_util_userError)( XW_UtilCtxt* uc, UtilErrID id );
|
void (*m_util_userError)( XW_UtilCtxt* uc, UtilErrID id );
|
||||||
|
|
||||||
|
@ -201,8 +200,8 @@ struct XW_UtilCtxt {
|
||||||
#define util_makeStreamFromAddr(uc,a) \
|
#define util_makeStreamFromAddr(uc,a) \
|
||||||
(uc)->vtable->m_util_makeStreamFromAddr((uc),(a))
|
(uc)->vtable->m_util_makeStreamFromAddr((uc),(a))
|
||||||
|
|
||||||
#define util_getSquareBonus(uc,m,c,r) \
|
#define util_getSquareBonus(uc,b,c,r) \
|
||||||
(uc)->vtable->m_util_getSquareBonus((uc),(m),(c),(r))
|
(uc)->vtable->m_util_getSquareBonus((uc),(b),(c),(r))
|
||||||
|
|
||||||
#define util_userError(uc,err) \
|
#define util_userError(uc,err) \
|
||||||
(uc)->vtable->m_util_userError((uc),(err))
|
(uc)->vtable->m_util_userError((uc),(err))
|
||||||
|
|
|
@ -44,6 +44,8 @@ typedef enum {
|
||||||
//XWPROTO_MOVEMADE_INFO, /* info about tiles placed and received */
|
//XWPROTO_MOVEMADE_INFO, /* info about tiles placed and received */
|
||||||
,XWPROTO_CLIENT_REQ_END_GAME /* non-server wants to end the game */
|
,XWPROTO_CLIENT_REQ_END_GAME /* non-server wants to end the game */
|
||||||
,XWPROTO_END_GAME /* server says to end game */
|
,XWPROTO_END_GAME /* server says to end game */
|
||||||
|
|
||||||
|
,XWPROTO_NEW_PROTO
|
||||||
} XW_Proto;
|
} XW_Proto;
|
||||||
|
|
||||||
#define XWPROTO_NBITS 4
|
#define XWPROTO_NBITS 4
|
||||||
|
|
|
@ -94,6 +94,7 @@ DEFINES += -DTEXT_MODEL
|
||||||
DEFINES += -DXWFEATURE_WALKDICT
|
DEFINES += -DXWFEATURE_WALKDICT
|
||||||
DEFINES += -DXWFEATURE_WALKDICT_FILTER
|
DEFINES += -DXWFEATURE_WALKDICT_FILTER
|
||||||
DEFINES += -DXWFEATURE_DICTSANITY
|
DEFINES += -DXWFEATURE_DICTSANITY
|
||||||
|
#DEFINES += -DMAX_ROWS=32
|
||||||
|
|
||||||
ifdef CURSES_CELL_HT
|
ifdef CURSES_CELL_HT
|
||||||
DEFINES += -DCURSES_CELL_HT=$(CURSES_CELL_HT)
|
DEFINES += -DCURSES_CELL_HT=$(CURSES_CELL_HT)
|
||||||
|
|
|
@ -1569,15 +1569,16 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height )
|
||||||
XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth;
|
XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth;
|
||||||
BoardCtxt* board = globals->cGlobals.game.board;
|
BoardCtxt* board = globals->cGlobals.game.board;
|
||||||
int remWidth = width;
|
int remWidth = width;
|
||||||
|
int nRows = globals->cGlobals.params->gi.boardSize;
|
||||||
|
|
||||||
cellWidth = CURSES_CELL_WIDTH;
|
cellWidth = CURSES_CELL_WIDTH;
|
||||||
cellHt = CURSES_CELL_HT;
|
cellHt = CURSES_CELL_HT;
|
||||||
board_setPos( board, BOARD_OFFSET, BOARD_OFFSET,
|
board_setPos( board, BOARD_OFFSET, BOARD_OFFSET,
|
||||||
cellWidth * MAX_COLS, cellHt * MAX_ROWS,
|
cellWidth * nRows, cellHt * nRows,
|
||||||
cellWidth, XP_FALSE );
|
cellWidth, XP_FALSE );
|
||||||
/* board_setScale( board, cellWidth, cellHt ); */
|
/* board_setScale( board, cellWidth, cellHt ); */
|
||||||
scoreLeft = (cellWidth * MAX_COLS);// + BOARD_SCORE_PADDING;
|
scoreLeft = (cellWidth * nRows);// + BOARD_SCORE_PADDING;
|
||||||
remWidth -= cellWidth * MAX_COLS;
|
remWidth -= cellWidth * nRows;
|
||||||
|
|
||||||
/* If the scoreboard will right of the board, put it there. Otherwise try
|
/* If the scoreboard will right of the board, put it there. Otherwise try
|
||||||
to fit it below the boards. */
|
to fit it below the boards. */
|
||||||
|
@ -1591,8 +1592,9 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height )
|
||||||
trayTop = 8;
|
trayTop = 8;
|
||||||
} else {
|
} else {
|
||||||
trayLeft = BOARD_OFFSET;
|
trayLeft = BOARD_OFFSET;
|
||||||
trayTop = BOARD_OFFSET + (cellHt * MAX_ROWS);
|
trayTop = BOARD_OFFSET + (cellHt * nRows);
|
||||||
if ( trayTop + trayHt > height ) {
|
if ( trayTop + trayHt > height ) {
|
||||||
|
XP_ASSERT( height > trayTop );
|
||||||
trayHt = height - trayTop;
|
trayHt = height - trayTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1805,7 +1807,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
model_setDictionary( g_globals.cGlobals.game.model, params->dict );
|
model_setDictionary( g_globals.cGlobals.game.model, params->dict );
|
||||||
|
setSquareBonuses( &g_globals.cGlobals );
|
||||||
positionSizeStuff( &g_globals, width, height );
|
positionSizeStuff( &g_globals, width, height );
|
||||||
|
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
|
|
|
@ -486,6 +486,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
model_setDictionary( globals->cGlobals.game.model, params->dict );
|
model_setDictionary( globals->cGlobals.game.model, params->dict );
|
||||||
|
setSquareBonuses( &globals->cGlobals );
|
||||||
model_setPlayerDicts( globals->cGlobals.game.model, ¶ms->dicts );
|
model_setPlayerDicts( globals->cGlobals.game.model, ¶ms->dicts );
|
||||||
|
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
|
@ -528,6 +529,8 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
||||||
gint trayTop;
|
gint trayTop;
|
||||||
gint boardTop = 0;
|
gint boardTop = 0;
|
||||||
XP_U16 netStatWidth = 0;
|
XP_U16 netStatWidth = 0;
|
||||||
|
gint nCols = globals->cGlobals.params->gi.boardSize;
|
||||||
|
gint nRows = nCols;
|
||||||
|
|
||||||
if ( globals->draw == NULL ) {
|
if ( globals->draw == NULL ) {
|
||||||
createOrLoadObjects( globals );
|
createOrLoadObjects( globals );
|
||||||
|
@ -541,25 +544,23 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
||||||
bdHeight = widget->allocation.height - (GTK_TOP_MARGIN + GTK_BOTTOM_MARGIN)
|
bdHeight = widget->allocation.height - (GTK_TOP_MARGIN + GTK_BOTTOM_MARGIN)
|
||||||
- GTK_MIN_TRAY_SCALEV - GTK_BOTTOM_MARGIN;
|
- GTK_MIN_TRAY_SCALEV - GTK_BOTTOM_MARGIN;
|
||||||
|
|
||||||
hscale = bdWidth / GTK_NUM_COLS;
|
hscale = bdWidth / nCols;
|
||||||
if ( 0 != globals->cGlobals.params->nHidden ) {
|
if ( 0 != globals->cGlobals.params->nHidden ) {
|
||||||
vscale = hscale;
|
vscale = hscale;
|
||||||
} else {
|
} else {
|
||||||
vscale = (bdHeight / (GTK_NUM_ROWS + GTK_TRAY_HT_ROWS)); /* makd tray
|
vscale = (bdHeight / (nCols + GTK_TRAY_HT_ROWS)); /* makd tray height
|
||||||
height 3x cell
|
3x cell height */
|
||||||
height */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !globals->cGlobals.params->verticalScore ) {
|
if ( !globals->cGlobals.params->verticalScore ) {
|
||||||
boardTop += GTK_HOR_SCORE_HEIGHT;
|
boardTop += GTK_HOR_SCORE_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
trayTop = boardTop + (vscale * GTK_NUM_ROWS);
|
trayTop = boardTop + (vscale * nRows);
|
||||||
/* move tray up if part of board's meant to be hidden */
|
/* move tray up if part of board's meant to be hidden */
|
||||||
trayTop -= vscale * globals->cGlobals.params->nHidden;
|
trayTop -= vscale * globals->cGlobals.params->nHidden;
|
||||||
board_setPos( globals->cGlobals.game.board, GTK_BOARD_LEFT, boardTop,
|
board_setPos( globals->cGlobals.game.board, GTK_BOARD_LEFT, boardTop,
|
||||||
hscale*GTK_NUM_COLS, vscale * GTK_NUM_ROWS,
|
hscale * nCols, vscale * nRows, hscale * 2, XP_FALSE );
|
||||||
hscale * 2, XP_FALSE );
|
|
||||||
/* board_setScale( globals->cGlobals.game.board, hscale, vscale ); */
|
/* board_setScale( globals->cGlobals.game.board, hscale, vscale ); */
|
||||||
globals->gridOn = XP_TRUE;
|
globals->gridOn = XP_TRUE;
|
||||||
|
|
||||||
|
@ -569,16 +570,16 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
||||||
|
|
||||||
timerTop = GTK_TIMER_TOP;
|
timerTop = GTK_TIMER_TOP;
|
||||||
if ( globals->cGlobals.params->verticalScore ) {
|
if ( globals->cGlobals.params->verticalScore ) {
|
||||||
timerLeft = GTK_BOARD_LEFT + (hscale*GTK_NUM_COLS) + 1;
|
timerLeft = GTK_BOARD_LEFT + (hscale*nCols) + 1;
|
||||||
board_setScoreboardLoc( globals->cGlobals.game.board,
|
board_setScoreboardLoc( globals->cGlobals.game.board,
|
||||||
timerLeft,
|
timerLeft,
|
||||||
GTK_VERT_SCORE_TOP,
|
GTK_VERT_SCORE_TOP,
|
||||||
GTK_VERT_SCORE_WIDTH,
|
GTK_VERT_SCORE_WIDTH,
|
||||||
vscale*GTK_NUM_COLS,
|
vscale*nCols,
|
||||||
XP_FALSE );
|
XP_FALSE );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
timerLeft = GTK_BOARD_LEFT + (hscale*GTK_NUM_COLS)
|
timerLeft = GTK_BOARD_LEFT + (hscale*nCols)
|
||||||
- GTK_TIMER_WIDTH - netStatWidth;
|
- GTK_TIMER_WIDTH - netStatWidth;
|
||||||
board_setScoreboardLoc( globals->cGlobals.game.board,
|
board_setScoreboardLoc( globals->cGlobals.game.board,
|
||||||
GTK_BOARD_LEFT, GTK_HOR_SCORE_TOP,
|
GTK_BOARD_LEFT, GTK_HOR_SCORE_TOP,
|
||||||
|
@ -598,7 +599,7 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
||||||
GTK_TIMER_WIDTH, GTK_HOR_SCORE_HEIGHT );
|
GTK_TIMER_WIDTH, GTK_HOR_SCORE_HEIGHT );
|
||||||
|
|
||||||
board_setTrayLoc( globals->cGlobals.game.board, GTK_TRAY_LEFT, trayTop,
|
board_setTrayLoc( globals->cGlobals.game.board, GTK_TRAY_LEFT, trayTop,
|
||||||
hscale * GTK_NUM_COLS, vscale * GTK_TRAY_HT_ROWS + 10,
|
hscale * nCols, vscale * GTK_TRAY_HT_ROWS + 10,
|
||||||
GTK_DIVIDER_WIDTH );
|
GTK_DIVIDER_WIDTH );
|
||||||
|
|
||||||
setCtrlsForTray( globals );
|
setCtrlsForTray( globals );
|
||||||
|
@ -1251,7 +1252,8 @@ handle_hide_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||||
XP_Bool draw = XP_FALSE;
|
XP_Bool draw = XP_FALSE;
|
||||||
|
|
||||||
if ( globals->cGlobals.params->nHidden > 0 ) {
|
if ( globals->cGlobals.params->nHidden > 0 ) {
|
||||||
globals->adjustment->page_size = GTK_NUM_ROWS;
|
gint nRows = globals->cGlobals.params->gi.boardSize;
|
||||||
|
globals->adjustment->page_size = nRows;
|
||||||
globals->adjustment->value = 0.0;
|
globals->adjustment->value = 0.0;
|
||||||
|
|
||||||
gtk_signal_emit_by_name( GTK_OBJECT(globals->adjustment), "changed" );
|
gtk_signal_emit_by_name( GTK_OBJECT(globals->adjustment), "changed" );
|
||||||
|
@ -1341,7 +1343,7 @@ setCtrlsForTray( GtkAppGlobals* XP_UNUSED(globals) )
|
||||||
XP_S16 nHidden = globals->cGlobals.params->nHidden;
|
XP_S16 nHidden = globals->cGlobals.params->nHidden;
|
||||||
|
|
||||||
if ( nHidden != 0 ) {
|
if ( nHidden != 0 ) {
|
||||||
XP_U16 pageSize = GTK_NUM_ROWS;
|
XP_U16 pageSize = nRows;
|
||||||
|
|
||||||
if ( state == TRAY_HIDDEN ) { /* we recover what tray covers */
|
if ( state == TRAY_HIDDEN ) { /* we recover what tray covers */
|
||||||
nHidden -= GTK_TRAY_HT_ROWS;
|
nHidden -= GTK_TRAY_HT_ROWS;
|
||||||
|
@ -1373,7 +1375,8 @@ gtk_util_yOffsetChange( XW_UtilCtxt* uc, XP_U16 maxOffset,
|
||||||
{
|
{
|
||||||
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
||||||
if ( !!globals->adjustment ) {
|
if ( !!globals->adjustment ) {
|
||||||
globals->adjustment->page_size = GTK_NUM_ROWS - maxOffset;
|
gint nRows = globals->cGlobals.params->gi.boardSize;
|
||||||
|
globals->adjustment->page_size = nRows - maxOffset;
|
||||||
globals->adjustment->value = newOffset;
|
globals->adjustment->value = newOffset;
|
||||||
gtk_adjustment_value_changed( GTK_ADJUSTMENT(globals->adjustment) );
|
gtk_adjustment_value_changed( GTK_ADJUSTMENT(globals->adjustment) );
|
||||||
}
|
}
|
||||||
|
@ -2317,9 +2320,10 @@ gtkmain( LaunchParams* params, int argc, char *argv[] )
|
||||||
/* install scrollbar even if not needed -- since zooming can make it
|
/* install scrollbar even if not needed -- since zooming can make it
|
||||||
needed later */
|
needed later */
|
||||||
GtkWidget* vscrollbar;
|
GtkWidget* vscrollbar;
|
||||||
|
gint nRows = globals.cGlobals.params->gi.boardSize;
|
||||||
globals.adjustment = (GtkAdjustment*)
|
globals.adjustment = (GtkAdjustment*)
|
||||||
gtk_adjustment_new( 0, 0, GTK_NUM_ROWS, 1, 2,
|
gtk_adjustment_new( 0, 0, nRows, 1, 2,
|
||||||
GTK_NUM_ROWS-globals.cGlobals.params->nHidden );
|
nRows - globals.cGlobals.params->nHidden );
|
||||||
vscrollbar = gtk_vscrollbar_new( globals.adjustment );
|
vscrollbar = gtk_vscrollbar_new( globals.adjustment );
|
||||||
g_signal_connect( GTK_OBJECT(globals.adjustment), "value_changed",
|
g_signal_connect( GTK_OBJECT(globals.adjustment), "value_changed",
|
||||||
G_CALLBACK(scroll_value_changed), &globals );
|
G_CALLBACK(scroll_value_changed), &globals );
|
||||||
|
|
|
@ -132,8 +132,6 @@ typedef struct GtkAppGlobals {
|
||||||
/* DictionaryCtxt* gtk_dictionary_make(); */
|
/* DictionaryCtxt* gtk_dictionary_make(); */
|
||||||
int gtkmain( LaunchParams* params, int argc, char *argv[] );
|
int gtkmain( LaunchParams* params, int argc, char *argv[] );
|
||||||
|
|
||||||
#define GTK_NUM_COLS 15
|
|
||||||
#define GTK_NUM_ROWS 15
|
|
||||||
#define GTK_MIN_SCALE 12 /* was 14 */
|
#define GTK_MIN_SCALE 12 /* was 14 */
|
||||||
|
|
||||||
#define GTK_MIN_TRAY_SCALEH 24
|
#define GTK_MIN_TRAY_SCALEH 24
|
||||||
|
@ -156,7 +154,7 @@ int gtkmain( LaunchParams* params, int argc, char *argv[] );
|
||||||
#define GTK_TIMER_WIDTH 40
|
#define GTK_TIMER_WIDTH 40
|
||||||
#define GTK_NETSTAT_WIDTH 20
|
#define GTK_NETSTAT_WIDTH 20
|
||||||
#define GTK_TIMER_TOP GTK_HOR_SCORE_TOP
|
#define GTK_TIMER_TOP GTK_HOR_SCORE_TOP
|
||||||
#define GTK_HOR_SCORE_WIDTH ((GTK_MIN_SCALE*MAX_COLS)-GTK_TIMER_PAD)
|
#define GTK_HOR_SCORE_WIDTH ((GTK_MIN_SCALE*20)-GTK_TIMER_PAD)
|
||||||
#define GTK_VERT_SCORE_WIDTH 40
|
#define GTK_VERT_SCORE_WIDTH 40
|
||||||
|
|
||||||
#define GTK_BOARD_TOP (GTK_SCORE_TOP + GTK_SCORE_HEIGHT \
|
#define GTK_BOARD_TOP (GTK_SCORE_TOP + GTK_SCORE_HEIGHT \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2009 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 1997 - 2011 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -219,7 +219,7 @@ initFromDictFile( LinuxDictionaryCtxt* dctx, const char* fileName )
|
||||||
const XP_U8* ptr;
|
const XP_U8* ptr;
|
||||||
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if ( 0 != stat( fileName, &statbuf ) ) {
|
if ( 0 != stat( fileName, &statbuf ) || 0 == statbuf.st_size ) {
|
||||||
goto closeAndExit;
|
goto closeAndExit;
|
||||||
}
|
}
|
||||||
dctx->dictLength = statbuf.st_size;
|
dctx->dictLength = statbuf.st_size;
|
||||||
|
|
|
@ -80,6 +80,63 @@ linux_util_makeEmptyDict( XW_UtilCtxt* XP_UNUSED_DBG(uctx) )
|
||||||
#define TL BONUS_TRIPLE_LETTER
|
#define TL BONUS_TRIPLE_LETTER
|
||||||
#define TW BONUS_TRIPLE_WORD
|
#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->params->gi.boardSize, &nBonuses );
|
||||||
|
if ( !!bonuses ) {
|
||||||
|
model_setSquareBonuses( cGlobals->game.model, bonuses, nBonuses );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static XWBonusType*
|
static XWBonusType*
|
||||||
parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
||||||
{
|
{
|
||||||
|
@ -146,14 +203,13 @@ parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
||||||
}
|
}
|
||||||
|
|
||||||
static XWBonusType
|
static XWBonusType
|
||||||
linux_util_getSquareBonus( XW_UtilCtxt* uc, const ModelCtxt* model,
|
linux_util_getSquareBonus( XW_UtilCtxt* uc, XP_U16 nCols,
|
||||||
XP_U16 col, XP_U16 row )
|
XP_U16 col, XP_U16 row )
|
||||||
{
|
{
|
||||||
static XWBonusType* parsedFile = NULL;
|
static XWBonusType* parsedFile = NULL;
|
||||||
XWBonusType result = EM;
|
XWBonusType result = EM;
|
||||||
|
|
||||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||||
XP_U16 nCols = model_numCols( model );
|
|
||||||
if ( NULL == parsedFile && NULL != cGlobals->params->bonusFile ) {
|
if ( NULL == parsedFile && NULL != cGlobals->params->bonusFile ) {
|
||||||
if ( !parsedFile ) {
|
if ( !parsedFile ) {
|
||||||
parsedFile = parseBonusFile( nCols, cGlobals->params->bonusFile );
|
parsedFile = parseBonusFile( nCols, cGlobals->params->bonusFile );
|
||||||
|
@ -162,25 +218,12 @@ linux_util_getSquareBonus( XW_UtilCtxt* uc, const ModelCtxt* model,
|
||||||
if ( NULL != parsedFile ) {
|
if ( NULL != parsedFile ) {
|
||||||
result = parsedFile[(row*nCols) + col];
|
result = parsedFile[(row*nCols) + col];
|
||||||
} else {
|
} else {
|
||||||
|
XP_U16 nEntries;
|
||||||
|
XWBonusType* scrabbleBoard = bonusesFor( 15, &nEntries );
|
||||||
|
|
||||||
XP_U16 index, ii;
|
XP_U16 index, ii;
|
||||||
/* This must be static or won't compile under multilink (for Palm).
|
if ( col > (nCols/2) ) col = nCols - 1 - col;
|
||||||
Fix! */
|
if ( row > (nCols/2) ) row = nCols - 1 - row;
|
||||||
static char scrabbleBoard[8*8] = {
|
|
||||||
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 */
|
|
||||||
|
|
||||||
if ( col > 7 ) col = 14 - col;
|
|
||||||
if ( row > 7 ) row = 14 - row;
|
|
||||||
if ( col > row ) {
|
if ( col > row ) {
|
||||||
XP_U16 tmp = col;
|
XP_U16 tmp = col;
|
||||||
col = row;
|
col = row;
|
||||||
|
@ -191,8 +234,8 @@ linux_util_getSquareBonus( XW_UtilCtxt* uc, const ModelCtxt* model,
|
||||||
index += ii;
|
index += ii;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( index < VSIZE(scrabbleBoard) ) {
|
if ( index < nEntries) {
|
||||||
result = (XWBonusType)scrabbleBoard[index];
|
result = scrabbleBoard[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2008 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 2000 - 2011 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
#include "xptypes.h"
|
#include "xptypes.h"
|
||||||
#include "dictnry.h"
|
#include "dictnry.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void linux_debugf(const char*, ...)
|
void linux_debugf(const char*, ...)
|
||||||
|
@ -41,4 +42,10 @@ const XP_UCHAR* linux_getErrString( UtilErrID id, XP_Bool* silent );
|
||||||
void formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles, char* buf,
|
void formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles, char* buf,
|
||||||
XP_U16 buflen );
|
XP_U16 buflen );
|
||||||
|
|
||||||
|
#ifdef STREAM_VERS_BIGBOARD
|
||||||
|
void setSquareBonuses( const CommonGlobals* cGlobals );
|
||||||
|
#else
|
||||||
|
# define setSquareBonuses( cg )
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue