mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-28 07:58:08 +01:00
Merge branch 'android_branch' into send_in_background
Conflicts: xwords4/linux/linuxutl.h
This commit is contained in:
commit
d37424ad7f
96 changed files with 1293 additions and 573 deletions
|
@ -1,15 +1,19 @@
|
|||
Here's how I'm building crosswords for Android.
|
||||
|
||||
First, my working directory is XWords within this (android/)
|
||||
directory. And note that local.properties, also there, needs to be
|
||||
edited so that sdk.dir points to where your sdk is installed.
|
||||
First, the build process requires a file called local.properties that
|
||||
must be generated locally. Generate it before your first build by
|
||||
running ./scripts/setup_local_props.sh.
|
||||
|
||||
The working directory is XWords4 within this (android/) directory.
|
||||
Run the following commands from there.
|
||||
|
||||
Build the jni library (the cross-platform code):
|
||||
# ../scripts/ndkbuild.sh
|
||||
|
||||
Then build the app for the emulator
|
||||
# ant install
|
||||
Then build the app for the emulator (assuming it's running)
|
||||
# ant debug install
|
||||
|
||||
Build for a device (requires you've set up your keys. I did this too
|
||||
long ago to remember how but the info's easy to find):
|
||||
# ant release
|
||||
(The above command not yet verified for new SDK I installed on 11/19/11)
|
||||
|
|
|
@ -2,69 +2,86 @@
|
|||
<project name="XWords4" default="release">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked in in Version
|
||||
Control Systems. -->
|
||||
<exec dir=".." executable="./scripts/setup_local_props.sh" output="ant_out.txt" />
|
||||
<property file="local.properties" />
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<loadproperties srcFile="local.properties" />
|
||||
|
||||
<!-- The build.properties file can be created by you and is never touched
|
||||
by the 'android' tool. This is the place to change some of the default property values
|
||||
used by the Ant rules.
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
application.package
|
||||
the name of your application package as defined in the manifest. Used by the
|
||||
'uninstall' rule.
|
||||
source.dir
|
||||
the name of the source directory. Default is 'src'.
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
the name of the output directory. Default is 'bin'.
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
Properties related to the SDK location or the project target should be updated
|
||||
using the 'android' tool with the 'update' action.
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems.
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="build.properties" />
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The default.properties file is created and updated by the 'android' tool, as well
|
||||
as ADT.
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems. -->
|
||||
<property file="default.properties" />
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
<!-- Custom Android task to deal with the project target, and import the proper rules.
|
||||
This requires ant 1.6.0 or above. -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
|
||||
</path>
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
<taskdef name="setup"
|
||||
classname="com.android.ant.SetupTask"
|
||||
classpathref="android.antlibs" />
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<exec dir=".." executable="./scripts/genvers.sh" output="ant_out.txt" />
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!-- Execute the Android Setup task that will setup some properties specific to the target,
|
||||
and import the build rules files.
|
||||
|
||||
The rules file is imported from
|
||||
<SDK>/platforms/<target_platform>/templates/android_rules.xml
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
|
||||
To customize some build steps for your project:
|
||||
- copy the content of the main node <project> from android_rules.xml
|
||||
- paste it in this build.xml below the <setup /> task.
|
||||
- disable the import by changing the setup task below to <setup import="false" />
|
||||
<target name="-pre-build">
|
||||
<exec dir=".." executable="./scripts/genvers.sh" output="ant_out.txt" />
|
||||
</target>
|
||||
<!--
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
This will ensure that the properties are setup correctly but that your customized
|
||||
build steps are used.
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<setup />
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
# Project target. 4 == 1.6, but I need that for the SMS APIs. Later
|
||||
# set it back to android-3 and figure out how to gracefully degrade.
|
||||
target=android-4
|
|
@ -26,12 +26,14 @@ local_DEFINES += \
|
|||
-DDISABLE_TILE_SEL \
|
||||
-DXWFEATURE_BOARDWORDS \
|
||||
-DXWFEATURE_WALKDICT \
|
||||
-DXWFEATURE_WALKDICT_FILTER \
|
||||
-DXWFEATURE_DICTSANITY \
|
||||
-DFEATURE_TRAY_EDIT \
|
||||
-DNODE_CAN_4 \
|
||||
-DRELAY_ROOM_DEFAULT=\"\"\
|
||||
-D__LITTLE_ENDIAN \
|
||||
|
||||
|
||||
local_SRC_FILES += \
|
||||
xwjni.c \
|
||||
utilwrapper.c \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* -*-mode: C; compile-command: "../../scripts/ndkbuild.sh"; -*- */
|
||||
/* -*- compile-command: "../../scripts/ndkbuild.sh"; -*- */
|
||||
/*
|
||||
* Copyright © 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
* Copyright © 2009 - 2011 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 as
|
||||
|
@ -45,7 +45,7 @@ typedef struct _AndDictionaryCtxt {
|
|||
} AndDictionaryCtxt;
|
||||
|
||||
#define CHECK_PTR(p,c,e) \
|
||||
if ( ((p)+(c)) >= (e) ) { \
|
||||
if ( ((p)+(c)) > (e) ) { \
|
||||
XP_LOGF( "%s (line %d); out of bytes", __func__, __LINE__ ); \
|
||||
goto error; \
|
||||
}
|
||||
|
@ -568,14 +568,15 @@ makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jstring jname,
|
|||
XP_U32 numEdges;
|
||||
XP_Bool parses = parseDict( anddict, (XP_U8*)anddict->bytes,
|
||||
bytesSize, &numEdges );
|
||||
if ( !parses || (check && !checkSanity( &anddict->super, numEdges ) ) ) {
|
||||
if ( !parses || (check && !checkSanity( &anddict->super,
|
||||
numEdges ) ) ) {
|
||||
and_dictionary_destroy( (DictionaryCtxt*)anddict );
|
||||
anddict = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (DictionaryCtxt*)anddict;
|
||||
}
|
||||
} /* makeDict */
|
||||
|
||||
void
|
||||
destroyDicts( PlayerDicts* dicts )
|
||||
|
|
|
@ -77,10 +77,11 @@ and_util_makeStreamFromAddr( XW_UtilCtxt* uc, XP_PlayerAddr channelNo )
|
|||
}
|
||||
|
||||
static XWBonusType and_util_getSquareBonus( XW_UtilCtxt* XP_UNUSED(uc),
|
||||
const ModelCtxt* XP_UNUSED(model),
|
||||
XP_U16 boardSize,
|
||||
XP_U16 col, XP_U16 row )
|
||||
{
|
||||
static const int s_buttsBoard[8][8] = {
|
||||
#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 },
|
||||
|
||||
|
@ -94,10 +95,12 @@ static XWBonusType and_util_getSquareBonus( XW_UtilCtxt* XP_UNUSED(uc),
|
|||
{ BONUS_TRIPLE_WORD, BONUS_NONE, BONUS_NONE,BONUS_DOUBLE_LETTER,BONUS_NONE,BONUS_NONE,BONUS_NONE,BONUS_DOUBLE_WORD },
|
||||
}; /* buttsBoard */
|
||||
|
||||
int half = 15 / 2; /* remove 15!!!! PENDING */
|
||||
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];
|
||||
#undef BONUS_DIM
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1310,13 +1310,11 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1init
|
|||
data->vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
|
||||
data->jniutil = jniutil;
|
||||
data->dict = dict;
|
||||
data->depth = 2;
|
||||
#ifdef MEM_DEBUG
|
||||
data->mpool = mpool;
|
||||
#endif
|
||||
closure = (int)data;
|
||||
|
||||
dict_initIter( data->dict, &data->iter );
|
||||
(void)dict_firstWord( &data->iter );
|
||||
} else {
|
||||
destroyJNIUtil( &jniutil );
|
||||
XP_FREE( mpool, data );
|
||||
|
@ -1327,6 +1325,63 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1init
|
|||
return closure;
|
||||
}
|
||||
|
||||
static void
|
||||
freeIndices( DictIterData* data )
|
||||
{
|
||||
IndexData* idata = &data->idata;
|
||||
if ( !!idata->prefixes ) {
|
||||
XP_FREE( data->mpool, idata->prefixes );
|
||||
idata->prefixes = NULL;
|
||||
}
|
||||
if( !!idata->indices ) {
|
||||
XP_FREE( data->mpool, idata->indices );
|
||||
idata->indices = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
makeIndex( DictIterData* data )
|
||||
{
|
||||
XP_U16 nFaces = dict_numTileFaces( data->dict );
|
||||
XP_U16 ii;
|
||||
XP_U16 count;
|
||||
for ( count = 1, ii = 0; ii < data->depth; ++ii ) {
|
||||
count *= nFaces;
|
||||
}
|
||||
|
||||
freeIndices( data );
|
||||
|
||||
IndexData* idata = &data->idata;
|
||||
idata->prefixes = XP_MALLOC( data->mpool, count * data->depth
|
||||
* sizeof(*idata->prefixes) );
|
||||
idata->indices = XP_MALLOC( data->mpool,
|
||||
count * sizeof(*idata->indices) );
|
||||
idata->count = count;
|
||||
|
||||
dict_makeIndex( &data->iter, data->depth, idata );
|
||||
if ( 0 < idata->count ) {
|
||||
idata->prefixes = XP_REALLOC( data->mpool, idata->prefixes,
|
||||
idata->count * data->depth *
|
||||
sizeof(*idata->prefixes) );
|
||||
idata->indices = XP_REALLOC( data->mpool, idata->indices,
|
||||
idata->count * sizeof(*idata->indices) );
|
||||
} else {
|
||||
freeIndices( data );
|
||||
}
|
||||
} /* makeIndex */
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1setMinMax
|
||||
( JNIEnv* env, jclass C, jint closure, jint min, jint max )
|
||||
{
|
||||
DictIterData* data = (DictIterData*)closure;
|
||||
if ( NULL != data ) {
|
||||
dict_initIter( &data->iter, data->dict, min, max );
|
||||
makeIndex( data );
|
||||
(void)dict_firstWord( &data->iter );
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1destroy
|
||||
( JNIEnv* env, jclass C, jint closure )
|
||||
|
@ -1338,12 +1393,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1destroy
|
|||
#endif
|
||||
dict_destroy( data->dict );
|
||||
destroyJNIUtil( &data->jniutil );
|
||||
if ( !!data->idata.indices ) {
|
||||
XP_FREE( mpool, data->idata.indices );
|
||||
}
|
||||
if ( !!data->idata.prefixes ) {
|
||||
XP_FREE( mpool, data->idata.prefixes );
|
||||
}
|
||||
freeIndices( data );
|
||||
vtmgr_destroy( MPPARM(mpool) data->vtMgr );
|
||||
XP_FREE( mpool, data );
|
||||
#ifdef MEM_DEBUG
|
||||
|
@ -1364,37 +1414,24 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1wordCount
|
|||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1makeIndex
|
||||
( JNIEnv* env, jclass C, jint closure )
|
||||
JNIEXPORT jintArray JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1getCounts
|
||||
(JNIEnv* env, jclass C, jint closure )
|
||||
{
|
||||
jintArray result = NULL;
|
||||
DictIterData* data = (DictIterData*)closure;
|
||||
if ( NULL != data ) {
|
||||
data->depth = 2; /* for now */
|
||||
XP_U16 nFaces = dict_numTileFaces( data->dict );
|
||||
XP_U16 ii;
|
||||
XP_U16 count;
|
||||
for ( count = 1, ii = 0; ii < data->depth; ++ii ) {
|
||||
count *= nFaces;
|
||||
DictIter iter;
|
||||
dict_initIter( &iter, data->dict, 0, MAX_COLS_DICT );
|
||||
|
||||
LengthsArray lens;
|
||||
if ( 0 < dict_countWords( &iter, &lens ) ) {
|
||||
XP_ASSERT( sizeof(jint) == sizeof(lens.lens[0]) );
|
||||
result = makeIntArray( env, VSIZE(lens.lens), (jint*)&lens.lens );
|
||||
(*env)->DeleteLocalRef( env, result );
|
||||
}
|
||||
|
||||
IndexData* idata = &data->idata;
|
||||
XP_ASSERT( !idata->prefixes );
|
||||
idata->prefixes = XP_MALLOC( data->mpool, count * data->depth
|
||||
* sizeof(*idata->prefixes) );
|
||||
XP_ASSERT( !idata->indices );
|
||||
idata->indices = XP_MALLOC( data->mpool,
|
||||
count * sizeof(*idata->indices) );
|
||||
idata->count = count;
|
||||
|
||||
dict_makeIndex( &data->iter, data->depth, idata );
|
||||
|
||||
idata->prefixes = XP_REALLOC( data->mpool, idata->prefixes,
|
||||
idata->count * data->depth *
|
||||
sizeof(*idata->prefixes) );
|
||||
idata->indices = XP_REALLOC( data->mpool, idata->indices,
|
||||
idata->count * sizeof(*idata->indices) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
|
|
|
@ -35,4 +35,30 @@
|
|||
android:drawSelectorOnTop="false"
|
||||
/>
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<TextView android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/min_len"
|
||||
/>
|
||||
<Spinner android:id="@+id/wordlen_min"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawSelectorOnTop="true"
|
||||
android:prompt="@string/prompt_min_len"
|
||||
/>
|
||||
<TextView android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/max_len"
|
||||
/>
|
||||
<Spinner android:id="@+id/wordlen_max"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawSelectorOnTop="true"
|
||||
android:prompt="@string/prompt_max_len"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -1784,10 +1784,20 @@
|
|||
<string name="cur_tilesf">Tile picker\n(so far: %s)</string>
|
||||
<string name="pick_faceup">Pick tiles face-up</string>
|
||||
|
||||
<string name="dict_browse_titlef">%1$s (%2$d words)</string>
|
||||
<string name="dict_browse_titlef">%1$s (%2$d words using %3$d-%4$d
|
||||
tiles)</string>
|
||||
<string name="dict_browse_title1f">%1$s (%2$d words using %3$d
|
||||
tiles)</string>
|
||||
<string name="dict_browse_nowordsf">No word in %1$s starts with
|
||||
%2$s.</string>
|
||||
<string name="not_again_browse">This button opens the wordlist
|
||||
browser on the current player\'s wordlist.</string>
|
||||
<string name="alert_empty_dictf">The wordlist %s contains only
|
||||
tile information. There are no words to browse.</string>
|
||||
|
||||
<string name="min_len">Min len</string>
|
||||
<string name="max_len">Max len</string>
|
||||
<string name="prompt_min_len">Words no shorter than</string>
|
||||
<string name="prompt_max_len">Words no longer than</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2011 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009 - 2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
@ -27,12 +27,16 @@ import android.os.Bundle;
|
|||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.SectionIndexer;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import java.util.Arrays;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
@ -41,15 +45,27 @@ import org.eehouse.android.xw4.jni.JNIUtilsImpl;
|
|||
import org.eehouse.android.xw4.jni.XwJNI;
|
||||
|
||||
public class DictBrowseActivity extends XWListActivity
|
||||
implements View.OnClickListener {
|
||||
implements View.OnClickListener, OnItemSelectedListener {
|
||||
|
||||
public static final String DICT_NAME = "DICT_NAME";
|
||||
public static final String DICT_MIN = "DICT_MIN";
|
||||
public static final String DICT_MAX = "DICT_MAX";
|
||||
public static final String DICT_COUNTS = "DICT_COUNTS";
|
||||
|
||||
private static final int MIN_LEN = 2;
|
||||
private static final int FINISH_ACTION = 1;
|
||||
|
||||
private int m_dictClosure = 0;
|
||||
private int m_lang;
|
||||
private String m_name;
|
||||
private int m_nWords;
|
||||
private float m_textSize;
|
||||
private Spinner m_minSpinner;
|
||||
private Spinner m_maxSpinner;
|
||||
private int m_minShown;
|
||||
private int m_maxShown;
|
||||
private int m_minAvail;
|
||||
private int m_maxAvail;
|
||||
private int[] m_counts;
|
||||
|
||||
|
||||
// - Steps to reproduce the problem:
|
||||
// Create ListView, set custom adapter which implements ListAdapter and
|
||||
|
@ -62,15 +78,30 @@ public class DictBrowseActivity extends XWListActivity
|
|||
|
||||
private String[] m_prefixes;
|
||||
private int[] m_indices;
|
||||
private int m_nWords;
|
||||
|
||||
public DictListAdapter()
|
||||
{
|
||||
super();
|
||||
|
||||
XwJNI.dict_iter_setMinMax( m_dictClosure, m_minShown, m_maxShown );
|
||||
m_nWords = XwJNI.dict_iter_wordCount( m_dictClosure );
|
||||
|
||||
int format = m_minShown == m_maxShown ?
|
||||
R.string.dict_browse_title1f : R.string.dict_browse_titlef;
|
||||
setTitle( Utils.format( DictBrowseActivity.this, format,
|
||||
m_name, m_nWords, m_minShown, m_maxShown ));
|
||||
}
|
||||
|
||||
public Object getItem( int position )
|
||||
{
|
||||
TextView text = new TextView( DictBrowseActivity.this );
|
||||
TextView text =
|
||||
(TextView)Utils.inflate( DictBrowseActivity.this,
|
||||
android.R.layout.simple_list_item_1 );
|
||||
String str = XwJNI.dict_iter_nthWord( m_dictClosure, position );
|
||||
if ( null != str ) {
|
||||
text.setText( str );
|
||||
text.setOnClickListener( DictBrowseActivity.this );
|
||||
text.setTextSize( m_textSize );
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
@ -125,33 +156,44 @@ public class DictBrowseActivity extends XWListActivity
|
|||
m_name = name;
|
||||
m_lang = DictLangCache.getDictLangCode( this, name );
|
||||
|
||||
m_textSize = 2.0f + new TextView( this ).getTextSize();
|
||||
|
||||
String[] names = { name };
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( this, names );
|
||||
m_dictClosure = XwJNI.dict_iter_init( pairs.m_bytes[0],
|
||||
pairs.m_paths[0],
|
||||
JNIUtilsImpl.get() );
|
||||
m_nWords = XwJNI.dict_iter_wordCount( m_dictClosure );
|
||||
|
||||
setTitle( Utils.format( this, R.string.dict_browse_titlef,
|
||||
name, m_nWords ) );
|
||||
m_counts = intent.getIntArrayExtra( DICT_COUNTS );
|
||||
if ( null == m_counts ) {
|
||||
m_counts = XwJNI.dict_iter_getCounts( m_dictClosure );
|
||||
}
|
||||
if ( null == m_counts ) {
|
||||
// empty dict? Just close down for now. Later if
|
||||
// this is extended to include tile info -- it should
|
||||
// be -- then use an empty list elem and disable
|
||||
// search/minmax stuff.
|
||||
String msg = Utils.format( this, R.string.alert_empty_dictf,
|
||||
name );
|
||||
showOKOnlyDialogThen( msg, FINISH_ACTION );
|
||||
} else {
|
||||
figureMinMax();
|
||||
|
||||
Utils.logf( "calling makeIndex" );
|
||||
XwJNI.dict_iter_makeIndex( m_dictClosure );
|
||||
Utils.logf( "makeIndex done" );
|
||||
setContentView( R.layout.dict_browser );
|
||||
|
||||
setContentView( R.layout.dict_browser );
|
||||
setListAdapter( new DictListAdapter() );
|
||||
getListView().setFastScrollEnabled( true );
|
||||
Button button = (Button)findViewById( R.id.search_button );
|
||||
button.setOnClickListener( new View.OnClickListener() {
|
||||
public void onClick( View view )
|
||||
{
|
||||
findButtonClicked();
|
||||
}
|
||||
} );
|
||||
|
||||
Button button = (Button)findViewById( R.id.search_button );
|
||||
button.setOnClickListener( new View.OnClickListener() {
|
||||
public void onClick( View view )
|
||||
{
|
||||
findButtonClicked();
|
||||
}
|
||||
} );
|
||||
m_minShown = intent.getIntExtra( DICT_MIN, m_minAvail );
|
||||
m_maxShown = intent.getIntExtra( DICT_MAX, m_maxAvail );
|
||||
setUpSpinners();
|
||||
|
||||
setListAdapter( new DictListAdapter() );
|
||||
getListView().setFastScrollEnabled( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +229,36 @@ public class DictBrowseActivity extends XWListActivity
|
|||
launchLookup( words, m_lang, true );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// AdapterView.OnItemSelectedListener interface
|
||||
//////////////////////////////////////////////////
|
||||
public void onItemSelected( AdapterView<?> parent, View view,
|
||||
int position, long id )
|
||||
{
|
||||
TextView text = (TextView)view;
|
||||
int newval = Integer.parseInt( text.getText().toString() );
|
||||
if ( parent == m_minSpinner ) {
|
||||
setMinMax( newval, m_maxShown );
|
||||
} else if ( parent == m_maxSpinner ) {
|
||||
setMinMax( m_minShown, newval );
|
||||
}
|
||||
}
|
||||
|
||||
public void onNothingSelected( AdapterView<?> parent )
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// DlgDelegate.DlgClickNotify interface
|
||||
//////////////////////////////////////////////////
|
||||
@Override
|
||||
public void dlgButtonClicked( int id, int which )
|
||||
{
|
||||
Assert.assertTrue( FINISH_ACTION == id );
|
||||
finish();
|
||||
}
|
||||
|
||||
private void findButtonClicked()
|
||||
{
|
||||
EditText edit = (EditText)findViewById( R.id.word_edit );
|
||||
|
@ -202,6 +274,75 @@ public class DictBrowseActivity extends XWListActivity
|
|||
}
|
||||
}
|
||||
|
||||
private void setMinMax( int min, int max )
|
||||
{
|
||||
// I can't make a second call to setListAdapter() work, nor
|
||||
// does notifyDataSetChanged do anything toward refreshing the
|
||||
// adapter/making it recognized a changed dataset. So, as a
|
||||
// workaround, relaunch the activity with different
|
||||
// parameters.
|
||||
if ( m_minShown != min || m_maxShown != max ) {
|
||||
Intent intent = getIntent();
|
||||
intent.putExtra( DICT_MIN, min );
|
||||
intent.putExtra( DICT_MAX, max );
|
||||
intent.putExtra( DICT_COUNTS, m_counts );
|
||||
startActivity( intent );
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void figureMinMax()
|
||||
{
|
||||
Assert.assertTrue( m_counts.length == XwJNI.MAX_COLS_DICT + 1 );
|
||||
m_minAvail = 0;
|
||||
while ( 0 == m_counts[m_minAvail] ) {
|
||||
++m_minAvail;
|
||||
}
|
||||
m_maxAvail = XwJNI.MAX_COLS_DICT;
|
||||
while ( 0 == m_counts[m_maxAvail] ) { //
|
||||
--m_maxAvail;
|
||||
}
|
||||
}
|
||||
|
||||
private void makeAdapter( Spinner spinner, int min, int max, int cur )
|
||||
{
|
||||
int sel = -1;
|
||||
String[] nums = new String[max - min + 1];
|
||||
for ( int ii = 0; ii < nums.length; ++ii ) {
|
||||
int val = min + ii;
|
||||
if ( val == cur ) {
|
||||
sel = ii;
|
||||
}
|
||||
nums[ii] = String.format( "%d", min + ii );
|
||||
}
|
||||
ArrayAdapter<String> adapter = new
|
||||
ArrayAdapter<String>( this,
|
||||
//android.R.layout.simple_spinner_dropdown_item,
|
||||
android.R.layout.simple_spinner_item,
|
||||
nums );
|
||||
adapter.setDropDownViewResource( android.R.layout.
|
||||
simple_spinner_dropdown_item );
|
||||
spinner.setAdapter( adapter );
|
||||
spinner.setSelection( sel );
|
||||
}
|
||||
|
||||
private void setUpSpinners()
|
||||
{
|
||||
// Min and max-length spinners. To avoid empty lists,
|
||||
// don't allow min to exceed max. Do that by making the
|
||||
// current max the largest min allowed, and the current
|
||||
// min the smallest max allowed.
|
||||
m_minSpinner = (Spinner)findViewById( R.id.wordlen_min );
|
||||
makeAdapter( m_minSpinner, m_minAvail, m_maxShown, m_minShown );
|
||||
m_minSpinner.setOnItemSelectedListener( this );
|
||||
|
||||
m_maxSpinner = (Spinner)findViewById( R.id.wordlen_max );
|
||||
makeAdapter( m_maxSpinner, m_minShown, m_maxAvail, m_maxShown );
|
||||
m_maxSpinner.setOnItemSelectedListener( this );
|
||||
}
|
||||
|
||||
|
||||
public static void launch( Context caller, String name )
|
||||
{
|
||||
Intent intent = new Intent( caller, DictBrowseActivity.class );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009 - 2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
@ -160,7 +160,7 @@ public class DlgDelegate {
|
|||
// showNotAgainDlgThen() is called
|
||||
// FALLTHRU
|
||||
case DIALOG_OKONLY:
|
||||
ad.setMessage( m_activity.getString(m_msgID) );
|
||||
ad.setMessage( m_msg );
|
||||
break;
|
||||
case CONFIRM_THEN:
|
||||
ad.getButton(AlertDialog.BUTTON_POSITIVE).
|
||||
|
@ -170,10 +170,19 @@ public class DlgDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
public void showOKOnlyDialog( String msg, int callbackID )
|
||||
{
|
||||
m_msg = msg;
|
||||
if ( 0 != callbackID ) {
|
||||
Assert.assertTrue( 0 == m_cbckID );
|
||||
m_cbckID = callbackID;
|
||||
}
|
||||
m_activity.showDialog( DIALOG_OKONLY );
|
||||
}
|
||||
|
||||
public void showOKOnlyDialog( int msgID )
|
||||
{
|
||||
m_msgID = msgID;
|
||||
m_activity.showDialog( DIALOG_OKONLY );
|
||||
showOKOnlyDialog( m_activity.getString( msgID ), 0 );
|
||||
}
|
||||
|
||||
public void showDictGoneFinish()
|
||||
|
@ -289,11 +298,15 @@ public class DlgDelegate {
|
|||
|
||||
private Dialog createOKDialog()
|
||||
{
|
||||
return new AlertDialog.Builder( m_activity )
|
||||
Dialog dialog = new AlertDialog.Builder( m_activity )
|
||||
.setTitle( R.string.info_title )
|
||||
.setMessage( m_msgID )
|
||||
.setMessage( m_msg )
|
||||
.setPositiveButton( R.string.button_ok, null )
|
||||
.create();
|
||||
if ( 0 != m_cbckID ) {
|
||||
dialog = setCallbackDismissListener( dialog );
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private Dialog createNotAgainDialog()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// /* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
// /* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
// /*
|
||||
// * Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
// * reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 - 2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 - 2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
* Copyright 2010 - 2011 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 as
|
||||
|
@ -122,6 +122,16 @@ public class XWListActivity extends ListActivity
|
|||
m_delegate.showNotAgainDlgThen( msgID, prefsKey );
|
||||
}
|
||||
|
||||
protected void showOKOnlyDialogThen( String msg, int action )
|
||||
{
|
||||
m_delegate.showOKOnlyDialog( msg, action );
|
||||
}
|
||||
|
||||
protected void showOKOnlyDialog( String msg )
|
||||
{
|
||||
m_delegate.showOKOnlyDialog( msg, 0 );
|
||||
}
|
||||
|
||||
protected void showOKOnlyDialog( int msgID )
|
||||
{
|
||||
m_delegate.showOKOnlyDialog( msgID );
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2010 - 2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
|
||||
/* -*- compile-command: "cd ../../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
|
@ -244,12 +244,15 @@ public class XwJNI {
|
|||
public static native int dict_getTileValue( int dictPtr, int tile );
|
||||
|
||||
// Dict iterator
|
||||
public final static int MAX_COLS_DICT = 15; // from dictiter.h
|
||||
public static native int dict_iter_init( byte[] dict, String path,
|
||||
JNIUtils jniu );
|
||||
public static native void dict_iter_setMinMax( int closure,
|
||||
int min, int max );
|
||||
public static native void dict_iter_destroy( int closure );
|
||||
public static native int dict_iter_wordCount( int closure );
|
||||
public static native int[] dict_iter_getCounts( int closure );
|
||||
public static native String dict_iter_nthWord( int closure, int nn );
|
||||
public static native void dict_iter_makeIndex( int closure );
|
||||
public static native String[] dict_iter_getPrefixes( int closure );
|
||||
public static native int[] dict_iter_getIndices( int closure );
|
||||
public static native int dict_iter_getStartsWith( int closure,
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo $0
|
||||
|
||||
cd $(dirname $0)
|
||||
cd ../XWords4
|
||||
|
||||
if [ ! -e local.properties ]; then
|
||||
ANDROID="$(which android)"
|
||||
SDK_DIR=$(dirname $ANDROID)
|
||||
SDK_DIR=$(dirname $SDK_DIR)
|
||||
echo "# generated by $0" > local.properties
|
||||
echo "sdk.dir=$SDK_DIR" >> local.properties
|
||||
fi
|
||||
# create local.properties for 1.6 sdk (target id 4). Use 'android
|
||||
# list targets' to get the full set.
|
||||
android update project --path . --target 4
|
||||
|
||||
echo "local.properties looks like this:"
|
||||
echo ""
|
||||
cat local.properties
|
||||
echo ""
|
||||
exit 0
|
||||
|
|
|
@ -1002,8 +1002,7 @@ timerFiredForPen( BoardCtxt* board )
|
|||
#endif
|
||||
if ( !listWords ) {
|
||||
XWBonusType bonus;
|
||||
bonus = util_getSquareBonus( board->util, board->model,
|
||||
col, row );
|
||||
bonus = model_getSquareBonus( board->model, col, row );
|
||||
if ( bonus != BONUS_NONE ) {
|
||||
#ifdef XWFEATURE_MINIWIN
|
||||
text = draw_getMiniWText( board->draw,
|
||||
|
@ -1198,7 +1197,7 @@ invalPerimeter( BoardCtxt* board )
|
|||
ScrollData* hsd = &board->sd[SCROLL_H];
|
||||
XP_U16 firstCol = hsd->offset;
|
||||
XP_U16 lastCol = hsd->lastVisible;
|
||||
XP_U16 firstAndLast = (1 << lastCol) | (1 << firstCol);
|
||||
RowFlags firstAndLast = (1 << lastCol) | (1 << firstCol);
|
||||
ScrollData* vsd = &board->sd[SCROLL_V];
|
||||
XP_U16 firstRow = vsd->offset;
|
||||
XP_U16 lastRow = vsd->lastVisible;
|
||||
|
@ -1588,7 +1587,7 @@ invalReflection( BoardCtxt* board )
|
|||
|
||||
while ( nRows-- ) {
|
||||
XP_U16 nCols;
|
||||
XP_U16 redrawFlag = board->redrawFlags[nRows];
|
||||
RowFlags redrawFlag = board->redrawFlags[nRows];
|
||||
if ( !redrawFlag ) {
|
||||
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.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -299,11 +299,11 @@ drawBoard( BoardCtxt* board )
|
|||
|
||||
nVisCols = model_numCols( model ) - board->zoomCount;
|
||||
for ( row = vsd->offset; row <= vsd->lastVisible; ++row ) {
|
||||
XP_U16 rowFlags = board->redrawFlags[row];
|
||||
RowFlags rowFlags = board->redrawFlags[row];
|
||||
if ( rowFlags != 0 ) {
|
||||
XP_U16 failedBits = 0;
|
||||
RowFlags failedBits = 0;
|
||||
for ( col = 0; col < nVisCols; ++col ) {
|
||||
XP_U16 colMask = 1 << (col + hsd->offset);
|
||||
RowFlags colMask = 1 << (col + hsd->offset);
|
||||
if ( 0 != (rowFlags & colMask) ) {
|
||||
if ( !drawCell( board, col + hsd->offset,
|
||||
row, XP_TRUE )) {
|
||||
|
@ -331,7 +331,7 @@ drawBoard( BoardCtxt* board )
|
|||
XWBonusType bonus;
|
||||
HintAtts hintAtts;
|
||||
CellFlags flags = CELL_NONE;
|
||||
bonus = util_getSquareBonus( board->util, model, col, row );
|
||||
bonus = model_getSquareBonus( model, col, row );
|
||||
hintAtts = figureHintAtts( board, col, row );
|
||||
#ifdef KEYBOARD_NAV
|
||||
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 );
|
||||
}
|
||||
}
|
||||
bonus = util_getSquareBonus( board->util, model, col, row );
|
||||
bonus = model_getSquareBonus( model, col, row );
|
||||
hintAtts = figureHintAtts( board, col, row );
|
||||
|
||||
if ( (col==board->star_row) && (row==board->star_row) ) {
|
||||
|
|
|
@ -157,7 +157,7 @@ struct BoardCtxt {
|
|||
XP_S16 timerStoppedTurn;
|
||||
#endif
|
||||
|
||||
XP_U16 redrawFlags[MAX_ROWS];
|
||||
RowFlags redrawFlags[MAX_ROWS];
|
||||
|
||||
XP_Rect boardBounds;
|
||||
XP_U16 heightAsSet;
|
||||
|
|
|
@ -42,6 +42,37 @@
|
|||
|
||||
#define VSIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||
|
||||
#if MAX_COLS > 16
|
||||
# define STREAM_VERS_BIGBOARD 0x12
|
||||
#endif
|
||||
#define STREAM_SAVE_PREVWORDS 0x11
|
||||
#define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10
|
||||
#define STREAM_VERS_PLAYERDICTS 0x0F
|
||||
#define STREAM_SAVE_PREVMOVE 0x0E /* server saves prev move explanation */
|
||||
#define STREAM_VERS_ROBOTIQ STREAM_SAVE_PREVMOVE /* robots have different smarts */
|
||||
#define STREAM_VERS_DICTLANG 0x0D /* save dict lang code in CurGameInfo */
|
||||
#define STREAM_VERS_NUNDONE 0x0C /* save undone tile in model */
|
||||
#define STREAM_VERS_GAMESECONDS 0x0B /* save gameSeconds whether or not
|
||||
timer's enabled */
|
||||
#define STREAM_VERS_4YOFFSET 0x0A /* 4 bits for yOffset on board */
|
||||
#define STREAM_VERS_CHANNELSEED 0x09 /* new short in relay connect must be
|
||||
saved in comms */
|
||||
#define STREAM_VERS_UTF8 0x08
|
||||
#define STREAM_VERS_ALWAYS_MULTI 0x07 /* stream format same for multi and
|
||||
one-device game builds */
|
||||
#define STREAM_VERS_MODEL_NO_DICT 0x06
|
||||
#define STREAM_VERS_BLUETOOTH 0x05
|
||||
#define STREAM_VERS_KEYNAV 0x04
|
||||
#define STREAM_VERS_RELAY 0x03
|
||||
#define STREAM_VERS_41B4 0x02
|
||||
#define STREAM_VERS_405 0x01
|
||||
|
||||
#if MAX_COLS > 16
|
||||
# define CUR_STREAM_VERS STREAM_VERS_BIGBOARD
|
||||
#else
|
||||
# define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS
|
||||
#endif
|
||||
|
||||
typedef struct XP_Rect {
|
||||
XP_S16 left;
|
||||
XP_S16 top;
|
||||
|
@ -115,7 +146,9 @@ typedef enum {
|
|||
} XWTimerReason;
|
||||
|
||||
#define MAX_NUM_PLAYERS 4
|
||||
#define MAX_ROWS 16
|
||||
#ifndef MAX_ROWS
|
||||
# define MAX_ROWS 16
|
||||
#endif
|
||||
#define MAX_COLS MAX_ROWS
|
||||
#ifdef EIGHT_TILES
|
||||
# define MAX_TRAY_TILES 8
|
||||
|
@ -127,6 +160,24 @@ typedef enum {
|
|||
#define NPLAYERS_NBITS 3
|
||||
#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
|
||||
* 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
|
||||
|
|
|
@ -38,10 +38,33 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct _EdgeArray {
|
||||
array_edge* edges[MAX_COLS];
|
||||
array_edge* edges[MAX_COLS_DICT];
|
||||
XP_U16 nEdges;
|
||||
} EdgeArray;
|
||||
|
||||
static XP_Bool prevWord( DictIter* iter );
|
||||
|
||||
#ifdef XWFEATURE_WALKDICT_FILTER
|
||||
#define LENOK( iter, nEdges ) \
|
||||
(iter)->min <= (nEdges) && (nEdges) <= (iter)->max
|
||||
|
||||
static XP_Bool
|
||||
_isAccepting( DictIter* iter, XP_U16 nEdges )
|
||||
{
|
||||
return ISACCEPTING( iter->dict, iter->edges[nEdges-1] )
|
||||
&& LENOK( iter, nEdges );
|
||||
}
|
||||
# define ACCEPT_ITER( iter, nEdges) _isAccepting( iter, nEdges )
|
||||
# define ACCEPT_NODE( iter, node, nEdges ) \
|
||||
ISACCEPTING( iter->dict, node ) && LENOK(iter,nEdges)
|
||||
# define FILTER_TEST(iter,nEdges) ((nEdges) <= (iter)->max)
|
||||
#else
|
||||
# define ACCEPT_ITER(iter, nEdges) \
|
||||
ISACCEPTING( (iter)->dict, (iter)->edges[(nEdges)-1] )
|
||||
# define ACCEPT_NODE( iter, node, nEdges ) ISACCEPTING( iter->dict, node )
|
||||
# define FILTER_TEST(iter, nEdges) XP_TRUE
|
||||
#endif
|
||||
|
||||
/* On entry and exit, edge at end of array should be ACCEPTING. The job of
|
||||
* this function is to iterate from one such edge to the next. Steps are: 1)
|
||||
* try to follow the edge, to expand to a longer word with the last one as a
|
||||
|
@ -53,15 +76,17 @@ static XP_Bool
|
|||
nextWord( DictIter* iter )
|
||||
{
|
||||
const DictionaryCtxt* dict = iter->dict;
|
||||
XP_U16 nEdges = iter->nEdges;
|
||||
XP_Bool success = XP_FALSE;
|
||||
XP_U16 nEdges = iter->nEdges;
|
||||
while ( 0 < nEdges && ! success ) {
|
||||
array_edge* next = dict_follow( dict, iter->edges[nEdges-1] );
|
||||
if ( !!next ) {
|
||||
iter->edges[nEdges++] = next;
|
||||
success = ISACCEPTING( dict, next );
|
||||
continue; /* try with longer word */
|
||||
}
|
||||
if ( FILTER_TEST( iter, nEdges ) ) {
|
||||
array_edge* next = dict_follow( dict, iter->edges[nEdges-1] );
|
||||
if ( !!next ) {
|
||||
iter->edges[nEdges++] = next;
|
||||
success = ACCEPT_NODE( iter, next, nEdges );
|
||||
continue; /* try with longer word */
|
||||
}
|
||||
}
|
||||
|
||||
while ( IS_LAST_EDGE( dict, iter->edges[nEdges-1] )
|
||||
&& 0 < --nEdges ) {
|
||||
|
@ -69,10 +94,9 @@ nextWord( DictIter* iter )
|
|||
|
||||
if ( 0 < nEdges ) {
|
||||
iter->edges[nEdges-1] += dict->nodeSize;
|
||||
success = ISACCEPTING( dict, iter->edges[nEdges-1] );
|
||||
success = ACCEPT_NODE( iter, iter->edges[nEdges-1], nEdges );
|
||||
}
|
||||
}
|
||||
|
||||
iter->nEdges = nEdges;
|
||||
return success;
|
||||
}
|
||||
|
@ -88,48 +112,60 @@ isFirstEdge( const DictionaryCtxt* dict, array_edge* edge )
|
|||
}
|
||||
|
||||
static XP_Bool
|
||||
lastEdges( DictIter* iter )
|
||||
lastEdges( DictIter* iter, XP_U16* nEdgesP )
|
||||
{
|
||||
const DictionaryCtxt* dict = iter->dict;
|
||||
array_edge* edge = iter->edges[iter->nEdges-1];
|
||||
XP_U16 nEdges = *nEdgesP;
|
||||
array_edge* edge = iter->edges[nEdges-1];
|
||||
for ( ; ; ) {
|
||||
while ( !IS_LAST_EDGE( dict, edge ) ) {
|
||||
edge += dict->nodeSize;
|
||||
}
|
||||
iter->edges[iter->nEdges-1] = edge;
|
||||
iter->edges[nEdges-1] = edge;
|
||||
|
||||
edge = dict_follow( dict, edge );
|
||||
if ( NULL == edge ) {
|
||||
break;
|
||||
}
|
||||
++iter->nEdges;
|
||||
if ( !FILTER_TEST( iter, nEdges + 1 ) ) {
|
||||
break;
|
||||
}
|
||||
++nEdges;
|
||||
}
|
||||
return ISACCEPTING( dict, iter->edges[iter->nEdges-1] );
|
||||
*nEdgesP = nEdges;
|
||||
return ACCEPT_ITER( iter, nEdges );
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
prevWord( DictIter* iter )
|
||||
{
|
||||
const DictionaryCtxt* dict = iter->dict;
|
||||
XP_U16 nEdges = iter->nEdges;
|
||||
XP_Bool success = XP_FALSE;
|
||||
while ( 0 < iter->nEdges && ! success ) {
|
||||
if ( isFirstEdge( dict, iter->edges[iter->nEdges-1] ) ) {
|
||||
--iter->nEdges;
|
||||
success = 0 < iter->nEdges
|
||||
&& ISACCEPTING( dict, iter->edges[iter->nEdges-1] );
|
||||
while ( 0 < nEdges && ! success ) {
|
||||
if ( isFirstEdge( dict, iter->edges[nEdges-1] ) ) {
|
||||
--nEdges;
|
||||
success = 0 < nEdges
|
||||
&& ACCEPT_NODE( iter, iter->edges[nEdges-1], nEdges );
|
||||
continue;
|
||||
}
|
||||
iter->edges[iter->nEdges-1] -= dict->nodeSize;
|
||||
array_edge* next = dict_follow( dict, iter->edges[iter->nEdges-1] );
|
||||
if ( NULL != next ) {
|
||||
iter->edges[iter->nEdges++] = next;
|
||||
success = lastEdges( iter );
|
||||
if ( success ) {
|
||||
continue;
|
||||
|
||||
iter->edges[nEdges-1] -= dict->nodeSize;
|
||||
|
||||
if ( FILTER_TEST( iter, nEdges ) ) {
|
||||
array_edge* next = dict_follow( dict, iter->edges[nEdges-1] );
|
||||
if ( NULL != next ) {
|
||||
iter->edges[nEdges++] = next;
|
||||
success = lastEdges( iter, &nEdges );
|
||||
if ( success ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
success = ISACCEPTING( dict, iter->edges[iter->nEdges-1] );
|
||||
|
||||
success = ACCEPT_NODE( iter, iter->edges[nEdges-1], nEdges );
|
||||
}
|
||||
iter->nEdges = nEdges;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -137,19 +173,28 @@ static XP_Bool
|
|||
findStartsWith( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
|
||||
{
|
||||
const DictionaryCtxt* dict = iter->dict;
|
||||
XP_Bool success = XP_TRUE;
|
||||
array_edge* edge = dict_getTopEdge( dict );
|
||||
iter->nEdges = 0;
|
||||
|
||||
while ( nTiles-- > 0 ) {
|
||||
while ( FILTER_TEST( iter, iter->nEdges ) && nTiles > 0 ) {
|
||||
Tile tile = *tiles++;
|
||||
edge = dict_edge_with_tile( dict, edge, tile );
|
||||
if ( NULL == edge ) {
|
||||
success = XP_FALSE;
|
||||
break;
|
||||
}
|
||||
iter->edges[iter->nEdges++] = edge;
|
||||
edge = dict_follow( dict, edge );
|
||||
--nTiles;
|
||||
}
|
||||
return 0 == nTiles;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
startsWith( const DictIter* iter, const Tile* tiles, XP_U16 nTiles )
|
||||
{
|
||||
XP_Bool success = nTiles <= iter->nEdges;
|
||||
while ( success && nTiles-- ) {
|
||||
success = tiles[nTiles] == EDGETILE( iter->dict, iter->edges[nTiles] );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -159,9 +204,9 @@ findWordStartsWith( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
|
|||
{
|
||||
XP_Bool found = XP_FALSE;
|
||||
if ( findStartsWith( iter, tiles, nTiles ) ) {
|
||||
found = ISACCEPTING( iter->dict, iter->edges[iter->nEdges-1] );
|
||||
found = ACCEPT_ITER( iter, iter->nEdges );
|
||||
if ( !found ) {
|
||||
found = nextWord( iter );
|
||||
found = nextWord( iter ) && startsWith( iter, tiles, nTiles );
|
||||
}
|
||||
}
|
||||
return found;
|
||||
|
@ -178,38 +223,73 @@ wordsEqual( const DictIter* word1, const DictIter* word2 )
|
|||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
dict_initIterFrom( DictIter* dest, const DictIter* src )
|
||||
{
|
||||
dict_initIter( dest, src->dict,
|
||||
#ifdef XWFEATURE_WALKDICT_FILTER
|
||||
src->min, src->max
|
||||
#else
|
||||
0, 0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
firstWord( DictIter* iter )
|
||||
{
|
||||
iter->nEdges = 1;
|
||||
iter->edges[0] = dict_getTopEdge( iter->dict );
|
||||
return ISACCEPTING( iter->dict, iter->edges[0] ) || nextWord( iter );
|
||||
array_edge* top = dict_getTopEdge( iter->dict );
|
||||
XP_Bool success = !!top;
|
||||
if ( success ) {
|
||||
iter->nEdges = 1;
|
||||
iter->edges[0] = top;
|
||||
success = ACCEPT_ITER( iter, 1 ) || nextWord( iter );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
XP_U32
|
||||
dict_countWords( const DictionaryCtxt* dict )
|
||||
dict_countWords( const DictIter* iter, LengthsArray* lens )
|
||||
{
|
||||
XP_U32 count = 0;
|
||||
DictIter iter;
|
||||
dict_initIter( dict, &iter );
|
||||
DictIter counter;
|
||||
dict_initIterFrom( &counter, iter );
|
||||
|
||||
if ( NULL != lens ) {
|
||||
XP_MEMSET( lens, 0, sizeof(*lens) );
|
||||
}
|
||||
|
||||
XP_U32 count;
|
||||
XP_Bool ok;
|
||||
for ( ok = firstWord( &iter ); ok; ok = nextWord( &iter ) ) {
|
||||
for ( count = 0, ok = firstWord( &counter );
|
||||
ok; ok = nextWord( &counter) ) {
|
||||
++count;
|
||||
|
||||
if ( NULL != lens ) {
|
||||
++lens->lens[counter.nEdges];
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#define GUARD_VALUE 0x12345678
|
||||
#define ASSERT_INITED( iter ) XP_ASSERT( (iter)->guard == GUARD_VALUE )
|
||||
|
||||
void
|
||||
dict_initIter( const DictionaryCtxt* dict, DictIter* iter )
|
||||
dict_initIter( DictIter* iter, const DictionaryCtxt* dict,
|
||||
XP_U16 min, XP_U16 max )
|
||||
{
|
||||
XP_MEMSET( iter, 0, sizeof(*iter) );
|
||||
iter->dict = dict;
|
||||
#ifdef DEBUG
|
||||
iter->guard = GUARD_VALUE;
|
||||
#endif
|
||||
#ifdef XWFEATURE_WALKDICT_FILTER
|
||||
iter->min = min;
|
||||
iter->max = max;
|
||||
#else
|
||||
XP_USE( min );
|
||||
XP_USE( max );
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -221,7 +301,7 @@ copyIter( DictIter* dest, const DictIter* src )
|
|||
}
|
||||
|
||||
static DictPosition
|
||||
placeWordClose( DictIter* iter, DictPosition position, XP_U16 depth,
|
||||
placeWordClose( DictIter* iter, const DictPosition position, XP_U16 depth,
|
||||
const IndexData* data )
|
||||
{
|
||||
XP_S16 low = 0;
|
||||
|
@ -283,7 +363,7 @@ indexOne( XP_U16 depth, Tile* tiles, IndexData* data, DictIter* prevIter,
|
|||
DictPosition* prevIndex )
|
||||
{
|
||||
DictIter curIter;
|
||||
dict_initIter( prevIter->dict, &curIter );
|
||||
dict_initIterFrom( &curIter, prevIter );
|
||||
if ( findWordStartsWith( &curIter, tiles, depth ) ) {
|
||||
while ( !wordsEqual( &curIter, prevIter ) ) {
|
||||
++*prevIndex;
|
||||
|
@ -324,7 +404,7 @@ dict_makeIndex( const DictIter* iter, XP_U16 depth, IndexData* data )
|
|||
{
|
||||
ASSERT_INITED( iter );
|
||||
const DictionaryCtxt* dict = iter->dict;
|
||||
XP_ASSERT( depth < MAX_COLS );
|
||||
XP_ASSERT( depth < MAX_COLS_DICT );
|
||||
XP_U16 ii, needCount;
|
||||
const XP_U16 nFaces = dict_numTileFaces( dict );
|
||||
XP_U16 nNonBlankFaces = nFaces;
|
||||
|
@ -352,7 +432,7 @@ dict_makeIndex( const DictIter* iter, XP_U16 depth, IndexData* data )
|
|||
*/
|
||||
data->count = 0;
|
||||
DictIter prevIter;
|
||||
dict_initIter( dict, &prevIter );
|
||||
dict_initIterFrom( &prevIter, iter );
|
||||
if ( firstWord( &prevIter ) ) {
|
||||
DictPosition prevIndex = 0;
|
||||
Tile prefix[depth];
|
||||
|
@ -371,7 +451,7 @@ dict_makeIndex( const DictIter* iter, XP_U16 depth, IndexData* data )
|
|||
static void
|
||||
initWord( DictIter* iter )
|
||||
{
|
||||
iter->nWords = dict_getWordCount( iter->dict );
|
||||
iter->nWords = dict_countWords( iter, NULL );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
|
@ -405,7 +485,7 @@ dict_lastWord( DictIter* iter )
|
|||
iter->nEdges = 1;
|
||||
iter->edges[0] = dict_getTopEdge( iter->dict );
|
||||
|
||||
XP_Bool success = lastEdges( iter );
|
||||
XP_Bool success = lastEdges( iter, &iter->nEdges ) || prevWord( iter );
|
||||
if ( success ) {
|
||||
initWord( iter );
|
||||
iter->position = iter->nWords - 1;
|
||||
|
@ -438,7 +518,7 @@ dict_getNthWord( DictIter* iter, DictPosition position, XP_U16 depth,
|
|||
XP_Bool validWord = 0 < iter->nEdges;
|
||||
if ( validWord ) { /* uninitialized */
|
||||
wordCount = iter->nWords;
|
||||
XP_ASSERT( wordCount == dict_getWordCount( dict ) );
|
||||
XP_ASSERT( wordCount == dict_countWords( iter, NULL ) );
|
||||
} else {
|
||||
wordCount = dict_getWordCount( dict );
|
||||
}
|
||||
|
@ -516,12 +596,12 @@ dict_findStartsWith( DictIter* iter, const IndexData* data,
|
|||
XP_LOGF( "%s: not using data", __func__ );
|
||||
|
||||
DictIter targetIter;
|
||||
dict_initIter( iter->dict, &targetIter );
|
||||
dict_initIterFrom( &targetIter, iter );
|
||||
if ( findWordStartsWith( &targetIter, prefix, len ) ) {
|
||||
|
||||
DictPosition result = 0;
|
||||
DictIter iterZero;
|
||||
dict_initIter( iter->dict, &iterZero );
|
||||
dict_initIterFrom( &iterZero, iter );
|
||||
if ( !firstWord( &iterZero ) ) {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
|
|
|
@ -33,10 +33,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_COLS_DICT 15
|
||||
|
||||
/* API for iterating over a dict */
|
||||
typedef XP_S32 DictPosition;
|
||||
typedef struct _DictIter {
|
||||
XP_U16 nEdges;
|
||||
array_edge* edges[MAX_COLS_DICT];
|
||||
#ifdef XWFEATURE_WALKDICT_FILTER
|
||||
XP_U16 min;
|
||||
XP_U16 max;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
XP_U32 guard;
|
||||
#endif
|
||||
|
@ -44,8 +51,6 @@ typedef struct _DictIter {
|
|||
XP_U32 nWords;
|
||||
|
||||
DictPosition position;
|
||||
XP_U16 nEdges;
|
||||
array_edge* edges[MAX_COLS];
|
||||
} DictIter;
|
||||
|
||||
typedef struct _IndexData {
|
||||
|
@ -54,8 +59,13 @@ typedef struct _IndexData {
|
|||
XP_U16 count; /* in-out: must indicate others are large enough */
|
||||
} IndexData;
|
||||
|
||||
XP_U32 dict_countWords( const DictionaryCtxt* dict );
|
||||
void dict_initIter( const DictionaryCtxt* dict, DictIter* iter );
|
||||
typedef struct _LengthsArray {
|
||||
XP_U32 lens[MAX_COLS_DICT+1];
|
||||
} LengthsArray;
|
||||
|
||||
void dict_initIter( DictIter* iter, const DictionaryCtxt* dict,
|
||||
XP_U16 min, XP_U16 max );
|
||||
XP_U32 dict_countWords( const DictIter* iter, LengthsArray* lens );
|
||||
void dict_makeIndex( const DictIter* iter, XP_U16 depth, IndexData* data );
|
||||
XP_Bool dict_firstWord( DictIter* iter );
|
||||
XP_Bool dict_lastWord( DictIter* iter );
|
||||
|
|
|
@ -481,7 +481,9 @@ dict_getWordCount( const DictionaryCtxt* dict )
|
|||
XP_U32 nWords = dict->nWords;
|
||||
#ifdef XWFEATURE_WALKDICT
|
||||
if ( 0 == nWords ) {
|
||||
nWords = dict_countWords( dict );
|
||||
DictIter iter;
|
||||
dict_initIter( &iter, dict, 0, MAX_COLS_DICT );
|
||||
nWords = dict_countWords( &iter, NULL );
|
||||
}
|
||||
#endif
|
||||
return nWords;
|
||||
|
@ -705,36 +707,38 @@ checkSanity( DictionaryCtxt* dict, const XP_U32 numEdges )
|
|||
{
|
||||
XP_U32 ii;
|
||||
XP_Bool passed = XP_TRUE;
|
||||
XP_U16 nFaces = dict_numTileFaces( dict );
|
||||
|
||||
array_edge* edge = dict->base;
|
||||
Tile prevTile = 0;
|
||||
for ( ii = 0; ii < numEdges && passed; ++ii ) {
|
||||
Tile tile = EDGETILE( dict, edge );
|
||||
if ( tile < prevTile || tile >= nFaces ) {
|
||||
XP_LOGF( "%s: node %ld (out of %ld) has too-large or "
|
||||
"out-of-order tile", __func__, ii, numEdges );
|
||||
passed = XP_FALSE;
|
||||
break;
|
||||
}
|
||||
prevTile = tile;
|
||||
if ( NULL != edge ) { /* not empty dict */
|
||||
XP_U16 nFaces = dict_numTileFaces( dict );
|
||||
Tile prevTile = 0;
|
||||
for ( ii = 0; ii < numEdges && passed; ++ii ) {
|
||||
Tile tile = EDGETILE( dict, edge );
|
||||
if ( tile < prevTile || tile >= nFaces ) {
|
||||
XP_LOGF( "%s: node %ld (out of %ld) has too-large or "
|
||||
"out-of-order tile", __func__, ii, numEdges );
|
||||
passed = XP_FALSE;
|
||||
break;
|
||||
}
|
||||
prevTile = tile;
|
||||
|
||||
unsigned long index = dict_index_from( dict, edge );
|
||||
if ( index >= numEdges ) {
|
||||
XP_LOGF( "%s: node %ld (out of %ld) has too-high index %ld", __func__,
|
||||
ii, numEdges, index );
|
||||
passed = XP_FALSE;
|
||||
break;
|
||||
unsigned long index = dict_index_from( dict, edge );
|
||||
if ( index >= numEdges ) {
|
||||
XP_LOGF( "%s: node %ld (out of %ld) has too-high index %ld",
|
||||
__func__, ii, numEdges, index );
|
||||
passed = XP_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( IS_LAST_EDGE( dict, edge ) ) {
|
||||
prevTile = 0;
|
||||
}
|
||||
edge += dict->nodeSize;
|
||||
}
|
||||
|
||||
if ( IS_LAST_EDGE( dict, edge ) ) {
|
||||
prevTile = 0;
|
||||
if ( passed ) {
|
||||
passed = 0 == prevTile; /* last edge seen was a LAST_EDGE */
|
||||
}
|
||||
edge += dict->nodeSize;
|
||||
}
|
||||
|
||||
if ( passed ) {
|
||||
passed = 0 == prevTile; /* last edge seen was a LAST_EDGE */
|
||||
}
|
||||
|
||||
XP_LOGF( "%s(numEdges=%ld)=>%d", __func__, numEdges, passed );
|
||||
|
|
|
@ -39,16 +39,6 @@ extern "C" {
|
|||
|
||||
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 {
|
||||
INTRADE_MW_TEXT = BONUS_LAST
|
||||
} XWMiniTextType;
|
||||
|
|
|
@ -426,13 +426,18 @@ gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
|
|||
XP_U16 ii;
|
||||
XP_UCHAR* str;
|
||||
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 );
|
||||
replaceStringIfDifferent( mpool, &gi->dictName, str );
|
||||
XP_FREEP( mpool, &str );
|
||||
|
||||
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->hintsNotAllowed = stream_getBits( stream, 1 );
|
||||
if ( strVersion < STREAM_VERS_ROBOTIQ ) {
|
||||
|
@ -491,10 +496,19 @@ gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi )
|
|||
const LocalPlayer* pl;
|
||||
XP_U16 ii;
|
||||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
XP_U16 strVersion = stream_getVersion( stream );
|
||||
XP_ASSERT( STREAM_SAVE_PREVWORDS <= strVersion );
|
||||
XP_U16 nColsNBits = STREAM_VERS_BIGBOARD > strVersion ? 4 : NUMCOLS_NBITS;
|
||||
#else
|
||||
XP_U16 nColsNBits = NUMCOLS_NBITS;
|
||||
#endif
|
||||
|
||||
|
||||
stringToStream( stream, gi->dictName );
|
||||
|
||||
stream_putBits( stream, NPLAYERS_NBITS, gi->nPlayers );
|
||||
stream_putBits( stream, 4, gi->boardSize );
|
||||
stream_putBits( stream, nColsNBits, gi->boardSize );
|
||||
stream_putBits( stream, 2, gi->serverRole );
|
||||
stream_putBits( stream, 1, gi->hintsNotAllowed );
|
||||
stream_putBits( stream, 2, gi->phoniesAction );
|
||||
|
|
|
@ -31,30 +31,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STREAM_SAVE_PREVWORDS 0x11
|
||||
#define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10
|
||||
#define STREAM_VERS_PLAYERDICTS 0x0F
|
||||
#define STREAM_SAVE_PREVMOVE 0x0E /* server saves prev move explanation */
|
||||
#define STREAM_VERS_ROBOTIQ STREAM_SAVE_PREVMOVE /* robots have different smarts */
|
||||
#define STREAM_VERS_DICTLANG 0x0D /* save dict lang code in CurGameInfo */
|
||||
#define STREAM_VERS_NUNDONE 0x0C /* save undone tile in model */
|
||||
#define STREAM_VERS_GAMESECONDS 0x0B /* save gameSeconds whether or not
|
||||
timer's enabled */
|
||||
#define STREAM_VERS_4YOFFSET 0x0A /* 4 bits for yOffset on board */
|
||||
#define STREAM_VERS_CHANNELSEED 0x09 /* new short in relay connect must be
|
||||
saved in comms */
|
||||
#define STREAM_VERS_UTF8 0x08
|
||||
#define STREAM_VERS_ALWAYS_MULTI 0x07 /* stream format same for multi and
|
||||
one-device game builds */
|
||||
#define STREAM_VERS_MODEL_NO_DICT 0x06
|
||||
#define STREAM_VERS_BLUETOOTH 0x05
|
||||
#define STREAM_VERS_KEYNAV 0x04
|
||||
#define STREAM_VERS_RELAY 0x03
|
||||
#define STREAM_VERS_41B4 0x02
|
||||
#define STREAM_VERS_405 0x01
|
||||
|
||||
#define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS
|
||||
|
||||
typedef struct LocalPlayer {
|
||||
XP_UCHAR* name;
|
||||
XP_UCHAR* password;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
|
||||
/*
|
||||
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 2000-2011 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
|
||||
|
@ -88,7 +89,9 @@ model_make( MPFORMAL DictionaryCtxt* dict,
|
|||
const PlayerDicts* dicts, XW_UtilCtxt* util, XP_U16 nCols,
|
||||
XP_U16 nRows )
|
||||
{
|
||||
ModelCtxt* result = (ModelCtxt*)XP_MALLOC( mpool, sizeof( *result ) );
|
||||
ModelCtxt* result;
|
||||
XP_U16 size = sizeof(*result) + TILES_SIZE(result, nCols);
|
||||
result = (ModelCtxt*)XP_MALLOC( mpool, size );
|
||||
if ( result != NULL ) {
|
||||
XP_MEMSET( result, 0, sizeof(*result) );
|
||||
MPASSIGN(result->vol.mpool, mpool);
|
||||
|
@ -115,15 +118,21 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
{
|
||||
ModelCtxt* model;
|
||||
XP_U16 nCols, nRows;
|
||||
short i;
|
||||
XP_U16 ii;
|
||||
XP_Bool hasDict;
|
||||
XP_U16 nPlayers;
|
||||
XP_U16 nColsNBits;
|
||||
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 );
|
||||
|
||||
nCols = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
nRows = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
nCols = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
nRows = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
|
||||
hasDict = (version >= STREAM_VERS_MODEL_NO_DICT)
|
||||
? XP_FALSE : stream_getBits( stream, 1 );
|
||||
|
@ -138,6 +147,20 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
model = model_make( MPPARM(mpool) dict, dicts, util, nCols, nRows );
|
||||
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 );
|
||||
|
||||
buildModelFromStack( model, model->vol.stack, XP_FALSE, 0,
|
||||
|
@ -145,10 +168,10 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
|
||||
NULL );
|
||||
|
||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
||||
loadPlayerCtxt( stream, version, &model->players[i] );
|
||||
setPendingCounts( model, i );
|
||||
invalidateScore( model, i );
|
||||
for ( ii = 0; ii < model->nPlayers; ++ii ) {
|
||||
loadPlayerCtxt( stream, version, &model->players[ii] );
|
||||
setPendingCounts( model, ii );
|
||||
invalidateScore( model, ii );
|
||||
}
|
||||
|
||||
return model;
|
||||
|
@ -157,7 +180,7 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
void
|
||||
model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream )
|
||||
{
|
||||
short i;
|
||||
XP_U16 ii;
|
||||
|
||||
stream_putBits( stream, NUMCOLS_NBITS, model->nCols );
|
||||
stream_putBits( stream, NUMCOLS_NBITS, model->nRows );
|
||||
|
@ -165,10 +188,17 @@ model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream )
|
|||
/* we have two bits for nPlayers, so range must be 0..3, not 1..4 */
|
||||
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 );
|
||||
|
||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
||||
writePlayerCtxt( stream, &model->players[i] );
|
||||
for ( ii = 0; ii < model->nPlayers; ++ii ) {
|
||||
writePlayerCtxt( stream, &model->players[ii] );
|
||||
}
|
||||
} /* model_writeToStream */
|
||||
|
||||
|
@ -220,7 +250,7 @@ model_init( ModelCtxt* model, XP_U16 nCols, XP_U16 nRows )
|
|||
|
||||
XP_ASSERT( model != NULL );
|
||||
XP_MEMSET( model, 0, sizeof( *model ) );
|
||||
XP_MEMSET( &model->tiles, TILE_EMPTY_BIT, sizeof(model->tiles) );
|
||||
XP_MEMSET( &model->tiles, TILE_EMPTY_BIT, TILES_SIZE(model, nCols) );
|
||||
|
||||
model->nCols = nCols;
|
||||
model->nRows = nRows;
|
||||
|
@ -240,9 +270,90 @@ model_destroy( ModelCtxt* model )
|
|||
{
|
||||
stack_destroy( model->vol.stack );
|
||||
/* is this it!? */
|
||||
if ( !!model->bonuses ) {
|
||||
XP_FREE( model->vol.mpool, model->bonuses );
|
||||
}
|
||||
XP_FREE( model->vol.mpool, model );
|
||||
} /* 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
|
||||
modelAddEntry( ModelCtxt* model, XP_U16 indx, const StackEntry* entry,
|
||||
XP_Bool useStack, XWStreamCtxt* stream,
|
||||
|
@ -581,17 +692,23 @@ model_getCellOwner( ModelCtxt* model, XP_U16 col, XP_U16 row )
|
|||
static void
|
||||
setModelTileRaw( ModelCtxt* model, XP_U16 col, XP_U16 row, CellTile tile )
|
||||
{
|
||||
XP_ASSERT( col < MAX_COLS );
|
||||
XP_ASSERT( row < MAX_ROWS );
|
||||
model->tiles[col][row] = tile;
|
||||
XP_ASSERT( col < model->nCols );
|
||||
XP_ASSERT( row < model->nRows );
|
||||
model->tiles[(row*model->nCols) + col] = tile;
|
||||
} /* model_setTile */
|
||||
|
||||
static CellTile
|
||||
getModelTileRaw( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
XP_ASSERT( col < MAX_COLS );
|
||||
XP_ASSERT( row < MAX_ROWS );
|
||||
return model->tiles[col][row];
|
||||
CellTile tile;
|
||||
XP_U16 nCols = model->nCols;
|
||||
XP_ASSERT( model->nRows == nCols );
|
||||
if ( col < nCols && row < nCols ) {
|
||||
tile = model->tiles[(row*nCols) + col];
|
||||
} else {
|
||||
tile = TILE_EMPTY_BIT;
|
||||
}
|
||||
return tile;
|
||||
} /* getModelTileRaw */
|
||||
|
||||
static void
|
||||
|
@ -815,6 +932,12 @@ model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
|||
{
|
||||
PlayerCtxt* player;
|
||||
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 );
|
||||
player = &model->players[turn];
|
||||
|
@ -831,8 +954,8 @@ model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
|||
&col, &row, &isBlank );
|
||||
XP_ASSERT( numTiles >= 0 );
|
||||
stream_putBits( stream, TILE_NBITS, tile );
|
||||
stream_putBits( stream, NUMCOLS_NBITS, col );
|
||||
stream_putBits( stream, NUMCOLS_NBITS, row );
|
||||
stream_putBits( stream, nColsNBits, col );
|
||||
stream_putBits( stream, nColsNBits, row );
|
||||
stream_putBits( stream, 1, isBlank );
|
||||
}
|
||||
} /* model_currentMoveToStream */
|
||||
|
@ -847,8 +970,15 @@ void
|
|||
model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
||||
XWStreamCtxt* stream )
|
||||
{
|
||||
XP_U16 numTiles;
|
||||
XP_U16 numTiles, ii;
|
||||
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 );
|
||||
|
||||
|
@ -856,12 +986,12 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
|||
|
||||
XP_LOGF( "%s: numTiles=%d", __func__, numTiles );
|
||||
|
||||
while ( numTiles-- ) {
|
||||
for ( ii = 0; ii < numTiles; ++ii ) {
|
||||
XP_S16 foundAt;
|
||||
Tile moveTile;
|
||||
Tile tileFace = (Tile)stream_getBits( stream, TILE_NBITS );
|
||||
XP_U16 col = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
XP_U16 row = (XP_U16)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
XP_U16 col = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
XP_U16 row = (XP_U16)stream_getBits( stream, nColsNBits );
|
||||
XP_Bool isBlank = stream_getBits( stream, 1 );
|
||||
|
||||
/* This code gets called both for the server, which has all the
|
||||
|
@ -1931,6 +2061,7 @@ makeTmpModel( ModelCtxt* model, XWStreamCtxt* stream,
|
|||
model->vol.util, model_numCols(model),
|
||||
model_numRows(model));
|
||||
model_setNPlayers( tmpModel, model->nPlayers );
|
||||
borrowSquareBonuses( tmpModel, model );
|
||||
|
||||
buildModelFromStack( tmpModel, model->vol.stack, XP_FALSE, 0, stream,
|
||||
(WordNotifierInfo*)NULL, mpf_pre, mpf_post, closure );
|
||||
|
@ -1952,6 +2083,7 @@ model_writeGameHistory( ModelCtxt* model, XWStreamCtxt* stream,
|
|||
|
||||
tmpModel = makeTmpModel( model, stream, printMovePre, printMovePost,
|
||||
&closure );
|
||||
returnSquareBonuses( tmpModel );
|
||||
model_destroy( tmpModel );
|
||||
|
||||
if ( gameOver ) {
|
||||
|
@ -2215,6 +2347,11 @@ loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc )
|
|||
{
|
||||
PendingTile* pt;
|
||||
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 );
|
||||
|
||||
|
@ -2230,8 +2367,8 @@ loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc )
|
|||
nTiles = pc->nPending + pc->nUndone;
|
||||
for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) {
|
||||
XP_U16 nBits;
|
||||
pt->col = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
pt->row = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
|
||||
pt->col = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||
pt->row = (XP_U8)stream_getBits( stream, nColsNBits );
|
||||
|
||||
nBits = (version <= STREAM_VERS_RELAY) ? 6 : 7;
|
||||
pt->tile = (Tile)stream_getBits( stream, nBits );
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NUMCOLS_NBITS 4
|
||||
#if MAX_COLS <= 16
|
||||
# define NUMCOLS_NBITS 4
|
||||
#elif MAX_COLS <= 32
|
||||
# define NUMCOLS_NBITS 5
|
||||
#endif
|
||||
|
||||
#ifdef EIGHT_TILES
|
||||
# define NTILES_NBITS 4
|
||||
|
@ -265,6 +269,13 @@ void model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
|||
/* Have there been too many passes (so game should end)? */
|
||||
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
||||
|
||||
XWBonusType model_getSquareBonus( const ModelCtxt* model,
|
||||
XP_U16 col, XP_U16 row );
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses,
|
||||
XP_U16 nBonuses );
|
||||
#endif
|
||||
|
||||
XP_Bool model_checkMoveLegal( ModelCtxt* model, XP_S16 player,
|
||||
XWStreamCtxt* stream,
|
||||
WordNotifierInfo* notifyInfo );
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
|
||||
/*
|
||||
* Copyright 2000 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 2000 - 2011 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
|
||||
|
@ -70,14 +71,18 @@ struct ModelCtxt {
|
|||
|
||||
ModelVolatiles vol;
|
||||
|
||||
CellTile tiles[MAX_COLS][MAX_ROWS];
|
||||
|
||||
PlayerCtxt players[MAX_NUM_PLAYERS];
|
||||
XP_U16 nPlayers;
|
||||
XP_U16 nCols;
|
||||
XP_U16 nRows;
|
||||
XP_U16 nBonuses;
|
||||
XWBonusType* bonuses;
|
||||
|
||||
CellTile tiles[];
|
||||
};
|
||||
|
||||
#define TILES_SIZE(m,nc) ((nc) * (nc) * sizeof((m)->tiles[0]))
|
||||
|
||||
void invalidateScore( ModelCtxt* model, XP_S16 player );
|
||||
XP_Bool tilesInLine( ModelCtxt* model, XP_S16 turn, XP_Bool* isHorizontal );
|
||||
void normalizeMoves( ModelCtxt* model, XP_S16 turn,
|
||||
|
|
|
@ -526,7 +526,7 @@ figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* moveInfo,
|
|||
static XP_U16
|
||||
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 ) {
|
||||
case BONUS_DOUBLE_WORD:
|
||||
return 2;
|
||||
|
@ -540,8 +540,7 @@ word_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
|||
static XP_U16
|
||||
tile_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 ) {
|
||||
case BONUS_DOUBLE_LETTER:
|
||||
return 2;
|
||||
|
|
|
@ -60,6 +60,9 @@ typedef struct ServerPlayer {
|
|||
|
||||
typedef struct RemoteAddress {
|
||||
XP_PlayerAddr channelNo;
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
XP_U8 streamVersion;
|
||||
#endif
|
||||
} RemoteAddress;
|
||||
|
||||
/* 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_Bool showRobotScores;
|
||||
XP_Bool sortNewTiles;
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
XP_U8 streamVersion;
|
||||
#endif
|
||||
#ifdef XWFEATURE_SLOW_ROBOT
|
||||
XP_U16 robotThinkMin, robotThinkMax; /* not saved (yet) */
|
||||
#endif
|
||||
|
@ -139,12 +145,14 @@ static XWStreamCtxt* messageStreamWithHeader( ServerCtxt* server,
|
|||
XP_U16 devIndex, XW_Proto code );
|
||||
static XP_Bool handleRegistrationMsg( ServerCtxt* server,
|
||||
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 sendBadWordMsgs( ServerCtxt* server );
|
||||
static XP_Bool handleIllegalWord( ServerCtxt* server,
|
||||
XWStreamCtxt* incoming );
|
||||
static void tellMoveWasLegal( ServerCtxt* server );
|
||||
static void writeProto( const ServerCtxt* server, XWStreamCtxt* stream,
|
||||
XW_Proto proto );
|
||||
#endif
|
||||
|
||||
#define PICK_NEXT -1
|
||||
|
@ -230,6 +238,9 @@ initServer( ServerCtxt* server )
|
|||
syncPlayers( server );
|
||||
|
||||
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 */
|
||||
|
||||
ServerCtxt*
|
||||
|
@ -280,7 +291,18 @@ getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
|||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
nv->addresses[ii].channelNo =
|
||||
(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 */
|
||||
|
||||
static void
|
||||
|
@ -301,7 +323,14 @@ putNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
|
|||
|
||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||
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 */
|
||||
|
||||
static XWStreamCtxt*
|
||||
|
@ -515,7 +544,7 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
if ( server->nv.gameState == XWSTATE_NONE ) {
|
||||
stream_open( stream );
|
||||
|
||||
stream_putBits( stream, XWPROTO_NBITS, XWPROTO_DEVICE_REGISTRATION );
|
||||
writeProto( server, stream, XWPROTO_DEVICE_REGISTRATION );
|
||||
|
||||
nPlayers = gi->nPlayers;
|
||||
XP_ASSERT( nPlayers > 0 );
|
||||
|
@ -531,8 +560,8 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
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
|
||||
doesn't matter when for SERVER_ISCLIENT. */
|
||||
name = emptyStringIfNull(lp->name);
|
||||
|
@ -543,6 +572,10 @@ server_initClientConnection( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
stream_putBits( stream, NAME_LEN_NBITS, len );
|
||||
stream_putBytes( stream, name, len );
|
||||
}
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
stream_putU8( stream, CUR_STREAM_VERS );
|
||||
#endif
|
||||
|
||||
} else {
|
||||
XP_LOGF( "%s: wierd state %s; dropping message", __func__,
|
||||
getStateStr(server->nv.gameState) );
|
||||
|
@ -593,11 +626,32 @@ callTurnChangeListener( ServerCtxt* server )
|
|||
} /* callTurnChangeListener */
|
||||
|
||||
#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
|
||||
handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_Bool success = XP_TRUE;
|
||||
XP_U16 playersInMsg, i;
|
||||
XP_U16 playersInMsg;
|
||||
XP_S8 clientIndex;
|
||||
XP_U16 ii = 0;
|
||||
LOG_FUNC();
|
||||
|
||||
/* code will have already been consumed */
|
||||
|
@ -608,21 +662,41 @@ handleRegistrationMsg( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
util_userError( server->vol.util, ERR_REG_UNEXPECTED_USER );
|
||||
success = XP_FALSE;
|
||||
} else {
|
||||
for ( i = 0; i < playersInMsg; ++i ) {
|
||||
registerRemotePlayer( server, stream );
|
||||
XP_S8 prevIndex = -1;
|
||||
for ( ; ii < playersInMsg; ++ii ) {
|
||||
clientIndex = registerRemotePlayer( server, stream );
|
||||
|
||||
/* This is abusing the semantics of turn change -- at least in the
|
||||
case where there is another device yet to register -- but we
|
||||
need to let the board know to redraw the scoreboard with more
|
||||
players there. */
|
||||
callTurnChangeListener( server );
|
||||
XP_ASSERT( ii == 0 || prevIndex == clientIndex );
|
||||
prevIndex = clientIndex;
|
||||
}
|
||||
|
||||
if ( server->nv.pendingRegistrations == 0 ) {
|
||||
assignTilesToAll( server );
|
||||
SETSTATE( server, XWSTATE_RECEIVED_ALL_REG );
|
||||
}
|
||||
|
||||
#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 ) {
|
||||
XP_ASSERT( ii == playersInMsg ); /* otherwise malformed */
|
||||
setStreamVersion( server );
|
||||
assignTilesToAll( server );
|
||||
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;
|
||||
} /* handleRegistrationMsg */
|
||||
#endif
|
||||
|
@ -1005,7 +1079,7 @@ findFirstPending( ServerCtxt* server, ServerPlayer** playerP )
|
|||
return lp;
|
||||
} /* findFirstPending */
|
||||
|
||||
static void
|
||||
static XP_S8
|
||||
registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_S8 deviceIndex;
|
||||
|
@ -1045,10 +1119,13 @@ registerRemotePlayer( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
|
||||
XP_ASSERT( channelNo != 0 );
|
||||
addr->channelNo = channelNo;
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
addr->streamVersion = STREAM_SAVE_PREVWORDS;
|
||||
#endif
|
||||
}
|
||||
|
||||
player->deviceIndex = deviceIndex;
|
||||
|
||||
return deviceIndex;
|
||||
} /* registerRemotePlayer */
|
||||
|
||||
static void
|
||||
|
@ -1102,6 +1179,7 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
|
|||
|
||||
/* version; any dependencies here? */
|
||||
XP_U8 streamVersion = stream_getU8( stream );
|
||||
XP_LOGF( "%s: set streamVersion to %d", __func__, streamVersion );
|
||||
stream_setVersion( stream, streamVersion );
|
||||
|
||||
gameID = stream_getU32( stream );
|
||||
|
@ -1240,10 +1318,8 @@ server_sendInitialMessage( ServerCtxt* server )
|
|||
DictionaryCtxt* dict = model_getDictionary(model);
|
||||
XP_ASSERT( !!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 );
|
||||
|
||||
XP_LOGF( "putting gameID %lx into msg", gameID );
|
||||
|
@ -1329,6 +1405,7 @@ printCode(char* intro, XW_Proto code)
|
|||
caseStr( str, XWPROTO_MOVE_CONFIRM );
|
||||
caseStr( str, XWPROTO_CLIENT_REQ_END_GAME );
|
||||
caseStr( str, XWPROTO_END_GAME );
|
||||
caseStr( str, XWPROTO_NEW_PROTO );
|
||||
}
|
||||
|
||||
XP_STATUSF( "\t%s for %s", intro, str );
|
||||
|
@ -1347,9 +1424,11 @@ messageStreamWithHeader( ServerCtxt* server, XP_U16 devIndex, XW_Proto code )
|
|||
printCode("making", code);
|
||||
|
||||
stream = util_makeStreamFromAddr( server->vol.util, channelNo );
|
||||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
stream_setVersion( stream, server->nv.streamVersion );
|
||||
#endif
|
||||
stream_open( stream );
|
||||
stream_putBits( stream, XWPROTO_NBITS, code );
|
||||
writeProto( server, stream, code );
|
||||
|
||||
return stream;
|
||||
} /* messageStreamWithHeader */
|
||||
|
@ -2446,15 +2525,46 @@ server_handleUndo( ServerCtxt* server )
|
|||
} /* server_handleUndo */
|
||||
|
||||
#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
|
||||
server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
|
||||
{
|
||||
XW_Proto code;
|
||||
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 );
|
||||
|
||||
if ( code == XWPROTO_DEVICE_REGISTRATION ) {
|
||||
/* This message is special: doesn't have the header that's possible
|
||||
|
@ -2541,7 +2651,8 @@ server_receiveMessage( ServerCtxt* server, XWStreamCtxt* incoming )
|
|||
accepted = XP_TRUE;
|
||||
break;
|
||||
default:
|
||||
XP_WARNF( "Unknown code on incoming message: %d\n", code );
|
||||
XP_WARNF( "%s: Unknown code on incoming message: %d\n",
|
||||
__func__, code );
|
||||
break;
|
||||
} /* switch */
|
||||
}
|
||||
|
|
|
@ -99,8 +99,7 @@ typedef struct UtilVtable {
|
|||
XP_PlayerAddr channelNo );
|
||||
#endif
|
||||
|
||||
XWBonusType (*m_util_getSquareBonus)( XW_UtilCtxt* uc,
|
||||
const ModelCtxt* model,
|
||||
XWBonusType (*m_util_getSquareBonus)( XW_UtilCtxt* uc, XP_U16 boardSize,
|
||||
XP_U16 col, XP_U16 row );
|
||||
void (*m_util_userError)( XW_UtilCtxt* uc, UtilErrID id );
|
||||
|
||||
|
@ -201,8 +200,8 @@ struct XW_UtilCtxt {
|
|||
#define util_makeStreamFromAddr(uc,a) \
|
||||
(uc)->vtable->m_util_makeStreamFromAddr((uc),(a))
|
||||
|
||||
#define util_getSquareBonus(uc,m,c,r) \
|
||||
(uc)->vtable->m_util_getSquareBonus((uc),(m),(c),(r))
|
||||
#define util_getSquareBonus(uc,b,c,r) \
|
||||
(uc)->vtable->m_util_getSquareBonus((uc),(b),(c),(r))
|
||||
|
||||
#define 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_CLIENT_REQ_END_GAME /* non-server wants to end the game */
|
||||
,XWPROTO_END_GAME /* server says to end game */
|
||||
|
||||
,XWPROTO_NEW_PROTO
|
||||
} XW_Proto;
|
||||
|
||||
#define XWPROTO_NBITS 4
|
||||
|
|
|
@ -92,7 +92,9 @@ DEFINES += -DDISABLE_TILE_SEL
|
|||
DEFINES += -DSET_GAMESEED
|
||||
DEFINES += -DTEXT_MODEL
|
||||
DEFINES += -DXWFEATURE_WALKDICT
|
||||
DEFINES += -DXWFEATURE_WALKDICT_FILTER
|
||||
DEFINES += -DXWFEATURE_DICTSANITY
|
||||
#DEFINES += -DMAX_ROWS=32
|
||||
|
||||
ifdef CURSES_CELL_HT
|
||||
DEFINES += -DCURSES_CELL_HT=$(CURSES_CELL_HT)
|
||||
|
|
|
@ -1570,15 +1570,16 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height )
|
|||
XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth;
|
||||
BoardCtxt* board = globals->cGlobals.game.board;
|
||||
int remWidth = width;
|
||||
int nRows = globals->cGlobals.params->gi.boardSize;
|
||||
|
||||
cellWidth = CURSES_CELL_WIDTH;
|
||||
cellHt = CURSES_CELL_HT;
|
||||
board_setPos( board, BOARD_OFFSET, BOARD_OFFSET,
|
||||
cellWidth * MAX_COLS, cellHt * MAX_ROWS,
|
||||
cellWidth * nRows, cellHt * nRows,
|
||||
cellWidth, XP_FALSE );
|
||||
/* board_setScale( board, cellWidth, cellHt ); */
|
||||
scoreLeft = (cellWidth * MAX_COLS);// + BOARD_SCORE_PADDING;
|
||||
remWidth -= cellWidth * MAX_COLS;
|
||||
scoreLeft = (cellWidth * nRows);// + BOARD_SCORE_PADDING;
|
||||
remWidth -= cellWidth * nRows;
|
||||
|
||||
/* If the scoreboard will right of the board, put it there. Otherwise try
|
||||
to fit it below the boards. */
|
||||
|
@ -1592,8 +1593,9 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height )
|
|||
trayTop = 8;
|
||||
} else {
|
||||
trayLeft = BOARD_OFFSET;
|
||||
trayTop = BOARD_OFFSET + (cellHt * MAX_ROWS);
|
||||
trayTop = BOARD_OFFSET + (cellHt * nRows);
|
||||
if ( trayTop + trayHt > height ) {
|
||||
XP_ASSERT( height > trayTop );
|
||||
trayHt = height - trayTop;
|
||||
}
|
||||
}
|
||||
|
@ -1819,7 +1821,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
#endif
|
||||
|
||||
model_setDictionary( g_globals.cGlobals.game.model, params->dict );
|
||||
|
||||
setSquareBonuses( &g_globals.cGlobals );
|
||||
positionSizeStuff( &g_globals, width, height );
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
|
|
|
@ -486,6 +486,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
|||
}
|
||||
#endif
|
||||
model_setDictionary( globals->cGlobals.game.model, params->dict );
|
||||
setSquareBonuses( &globals->cGlobals );
|
||||
model_setPlayerDicts( globals->cGlobals.game.model, ¶ms->dicts );
|
||||
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
|
@ -528,6 +529,8 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
|||
gint trayTop;
|
||||
gint boardTop = 0;
|
||||
XP_U16 netStatWidth = 0;
|
||||
gint nCols = globals->cGlobals.params->gi.boardSize;
|
||||
gint nRows = nCols;
|
||||
|
||||
if ( globals->draw == NULL ) {
|
||||
createOrLoadObjects( globals );
|
||||
|
@ -541,25 +544,23 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
|||
bdHeight = widget->allocation.height - (GTK_TOP_MARGIN + GTK_BOTTOM_MARGIN)
|
||||
- GTK_MIN_TRAY_SCALEV - GTK_BOTTOM_MARGIN;
|
||||
|
||||
hscale = bdWidth / GTK_NUM_COLS;
|
||||
hscale = bdWidth / nCols;
|
||||
if ( 0 != globals->cGlobals.params->nHidden ) {
|
||||
vscale = hscale;
|
||||
} else {
|
||||
vscale = (bdHeight / (GTK_NUM_ROWS + GTK_TRAY_HT_ROWS)); /* makd tray
|
||||
height 3x cell
|
||||
height */
|
||||
vscale = (bdHeight / (nCols + GTK_TRAY_HT_ROWS)); /* makd tray height
|
||||
3x cell height */
|
||||
}
|
||||
|
||||
if ( !globals->cGlobals.params->verticalScore ) {
|
||||
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 */
|
||||
trayTop -= vscale * globals->cGlobals.params->nHidden;
|
||||
board_setPos( globals->cGlobals.game.board, GTK_BOARD_LEFT, boardTop,
|
||||
hscale*GTK_NUM_COLS, vscale * GTK_NUM_ROWS,
|
||||
hscale * 2, XP_FALSE );
|
||||
hscale * nCols, vscale * nRows, hscale * 2, XP_FALSE );
|
||||
/* board_setScale( globals->cGlobals.game.board, hscale, vscale ); */
|
||||
globals->gridOn = XP_TRUE;
|
||||
|
||||
|
@ -569,16 +570,16 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event),
|
|||
|
||||
timerTop = GTK_TIMER_TOP;
|
||||
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,
|
||||
timerLeft,
|
||||
GTK_VERT_SCORE_TOP,
|
||||
GTK_VERT_SCORE_WIDTH,
|
||||
vscale*GTK_NUM_COLS,
|
||||
vscale*nCols,
|
||||
XP_FALSE );
|
||||
|
||||
} else {
|
||||
timerLeft = GTK_BOARD_LEFT + (hscale*GTK_NUM_COLS)
|
||||
timerLeft = GTK_BOARD_LEFT + (hscale*nCols)
|
||||
- GTK_TIMER_WIDTH - netStatWidth;
|
||||
board_setScoreboardLoc( globals->cGlobals.game.board,
|
||||
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 );
|
||||
|
||||
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 );
|
||||
|
||||
setCtrlsForTray( globals );
|
||||
|
@ -1251,7 +1252,8 @@ handle_hide_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
|||
XP_Bool draw = XP_FALSE;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
if ( nHidden != 0 ) {
|
||||
XP_U16 pageSize = GTK_NUM_ROWS;
|
||||
XP_U16 pageSize = nRows;
|
||||
|
||||
if ( state == TRAY_HIDDEN ) { /* we recover what tray covers */
|
||||
nHidden -= GTK_TRAY_HT_ROWS;
|
||||
|
@ -1373,7 +1375,8 @@ gtk_util_yOffsetChange( XW_UtilCtxt* uc, XP_U16 maxOffset,
|
|||
{
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
||||
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;
|
||||
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
|
||||
needed later */
|
||||
GtkWidget* vscrollbar;
|
||||
gint nRows = globals.cGlobals.params->gi.boardSize;
|
||||
globals.adjustment = (GtkAdjustment*)
|
||||
gtk_adjustment_new( 0, 0, GTK_NUM_ROWS, 1, 2,
|
||||
GTK_NUM_ROWS-globals.cGlobals.params->nHidden );
|
||||
gtk_adjustment_new( 0, 0, nRows, 1, 2,
|
||||
nRows - globals.cGlobals.params->nHidden );
|
||||
vscrollbar = gtk_vscrollbar_new( globals.adjustment );
|
||||
g_signal_connect( GTK_OBJECT(globals.adjustment), "value_changed",
|
||||
G_CALLBACK(scroll_value_changed), &globals );
|
||||
|
|
|
@ -132,8 +132,6 @@ typedef struct GtkAppGlobals {
|
|||
/* DictionaryCtxt* gtk_dictionary_make(); */
|
||||
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_TRAY_SCALEH 24
|
||||
|
@ -156,7 +154,7 @@ int gtkmain( LaunchParams* params, int argc, char *argv[] );
|
|||
#define GTK_TIMER_WIDTH 40
|
||||
#define GTK_NETSTAT_WIDTH 20
|
||||
#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_BOARD_TOP (GTK_SCORE_TOP + GTK_SCORE_HEIGHT \
|
||||
|
|
|
@ -370,6 +370,7 @@ initFromDictFile( LinuxDictionaryCtxt* dctx, const char* fileName )
|
|||
} else {
|
||||
dctx->super.base = NULL;
|
||||
dctx->super.topEdge = NULL;
|
||||
numEdges = 0;
|
||||
}
|
||||
|
||||
dctx->super.name = copyString( dctx->super.mpool, fileName );
|
||||
|
|
|
@ -379,6 +379,7 @@ typedef enum {
|
|||
#ifdef XWFEATURE_WALKDICT
|
||||
,CMD_TESTDICT
|
||||
,CMD_TESTPRFX
|
||||
,CMD_TESTMINMAX
|
||||
#endif
|
||||
,CMD_PLAYERDICT
|
||||
,CMD_SEED
|
||||
|
@ -458,6 +459,7 @@ static CmdInfoRec CmdInfoRecs[] = {
|
|||
#ifdef XWFEATURE_WALKDICT
|
||||
,{ CMD_TESTDICT, true, "test-dict", "dictionary to be used for iterator test" }
|
||||
,{ CMD_TESTPRFX, true, "test-prefix", "list first word starting with this" }
|
||||
,{ CMD_TESTMINMAX, true, "test-minmax", "M:M -- include only words whose len in range" }
|
||||
#endif
|
||||
,{ CMD_PLAYERDICT, true, "player-dict", "dictionary name for player (in sequence)" }
|
||||
,{ CMD_SEED, true, "seed", "random seed" }
|
||||
|
@ -1036,28 +1038,35 @@ tmp_noop_sigintterm( int XP_UNUSED(sig) )
|
|||
//# define PRINT_ALL
|
||||
static void
|
||||
testGetNthWord( const DictionaryCtxt* dict, char** words,
|
||||
XP_U16 depth, IndexData* data )
|
||||
XP_U16 depth, IndexData* data, XP_U16 min, XP_U16 max )
|
||||
{
|
||||
XP_U32 half = dict_getWordCount( dict ) / 2;
|
||||
XP_UCHAR buf[64];
|
||||
XP_U32 ii, jj;
|
||||
DictIter iter;
|
||||
XP_U32 interval = 1000;
|
||||
|
||||
dict_initIter( dict, &iter );
|
||||
dict_initIter( &iter, dict, min, max );
|
||||
XP_U32 half = dict_countWords( &iter, NULL ) / 2;
|
||||
XP_U32 interval = half / 100;
|
||||
if ( interval == 0 ) {
|
||||
++interval;
|
||||
}
|
||||
|
||||
for ( ii = 0, jj = half; ii < half; ii += interval, jj += interval ) {
|
||||
if ( dict_getNthWord( &iter, ii, depth, data ) ) {
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
XP_ASSERT( 0 == strcmp( buf, words[ii] ) );
|
||||
// XP_LOGF( "%s: word[%ld]: %s", __func__, ii, buf );
|
||||
# ifdef PRINT_ALL
|
||||
XP_LOGF( "%s: word[%ld]: %s", __func__, ii, buf );
|
||||
# endif
|
||||
} else {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
if ( dict_getNthWord( &iter, jj, depth, data ) ) {
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
XP_ASSERT( 0 == strcmp( buf, words[jj] ) );
|
||||
// XP_LOGF( "%s: word[%ld]: %s", __func__, jj, buf );
|
||||
# ifdef PRINT_ALL
|
||||
XP_LOGF( "%s: word[%ld]: %s", __func__, jj, buf );
|
||||
# endif
|
||||
} else {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
|
@ -1066,7 +1075,7 @@ testGetNthWord( const DictionaryCtxt* dict, char** words,
|
|||
|
||||
static void
|
||||
walk_dict_test( const LaunchParams* params, const DictionaryCtxt* dict,
|
||||
GSList* testPrefixes )
|
||||
GSList* testPrefixes, const char* testMinMax )
|
||||
{
|
||||
/* This is just to test that the dict-iterating code works. The words are
|
||||
meant to be printed e.g. in a scrolling dialog on Android. */
|
||||
|
@ -1074,139 +1083,147 @@ walk_dict_test( const LaunchParams* params, const DictionaryCtxt* dict,
|
|||
long jj;
|
||||
XP_Bool gotOne;
|
||||
|
||||
XP_U32 count = dict_getWordCount( dict );
|
||||
XP_ASSERT( count > 0 );
|
||||
XP_ASSERT( count == dict_countWords( dict ) );
|
||||
char** words = g_malloc( count * sizeof(char*) );
|
||||
XP_ASSERT( !!words );
|
||||
|
||||
/* if ( dict_firstWord( dict, &word ) */
|
||||
/* && dict_getNextWord( dict, &word ) */
|
||||
/* && dict_getPrevWord( dict, &word ) ) { */
|
||||
/* fprintf( stderr, "yay!: dict_getPrevWord returned\n" ); */
|
||||
/* } */
|
||||
/* exit( 0 ); */
|
||||
|
||||
dict_initIter( dict, &iter );
|
||||
for ( jj = 0, gotOne = dict_firstWord( &iter );
|
||||
gotOne;
|
||||
++jj, gotOne = dict_getNextWord( &iter ) ) {
|
||||
XP_ASSERT( dict_getPosition( &iter ) == jj );
|
||||
XP_UCHAR buf[64];
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
# ifdef PRINT_ALL
|
||||
fprintf( stderr, "%.6ld: %s\n", jj, buf );
|
||||
# endif
|
||||
if ( !!words ) {
|
||||
words[jj] = g_strdup( buf );
|
||||
}
|
||||
XP_U16 min, max;
|
||||
if ( !testMinMax || !parsePair( testMinMax, &min, &max ) ) {
|
||||
min = 0;
|
||||
max = MAX_COLS_DICT;
|
||||
}
|
||||
XP_ASSERT( count == jj );
|
||||
|
||||
for ( jj = 0, gotOne = dict_lastWord( &iter );
|
||||
gotOne;
|
||||
++jj, gotOne = dict_getPrevWord( &iter ) ) {
|
||||
XP_ASSERT( dict_getPosition(&iter) == count-jj-1 );
|
||||
XP_UCHAR buf[64];
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
dict_initIter( &iter, dict, min, max );
|
||||
LengthsArray lens;
|
||||
XP_U32 count = dict_countWords( &iter, &lens );
|
||||
|
||||
XP_U32 sum = 0;
|
||||
for ( jj = 0; jj < VSIZE(lens.lens); ++jj ) {
|
||||
sum += lens.lens[jj];
|
||||
XP_LOGF( "%ld words of length %ld", lens.lens[jj], jj );
|
||||
}
|
||||
XP_ASSERT( sum == count );
|
||||
|
||||
if ( count > 0 ) {
|
||||
char** words = g_malloc( count * sizeof(char*) );
|
||||
XP_ASSERT( !!words );
|
||||
|
||||
for ( jj = 0, gotOne = dict_firstWord( &iter );
|
||||
gotOne;
|
||||
gotOne = dict_getNextWord( &iter ) ) {
|
||||
XP_ASSERT( dict_getPosition( &iter ) == jj );
|
||||
XP_UCHAR buf[64];
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
# ifdef PRINT_ALL
|
||||
fprintf( stderr, "%.6ld: %s\n", jj, buf );
|
||||
fprintf( stderr, "%.6ld: %s\n", jj, buf );
|
||||
# endif
|
||||
if ( !!words ) {
|
||||
if ( strcmp( buf, words[count-jj-1] ) ) {
|
||||
fprintf( stderr, "failure at %ld: %s going forward; %s "
|
||||
"going backward\n", jj, words[count-jj-1], buf );
|
||||
break;
|
||||
if ( !!words ) {
|
||||
words[jj] = g_strdup( buf );
|
||||
}
|
||||
++jj;
|
||||
}
|
||||
}
|
||||
XP_ASSERT( count == jj );
|
||||
XP_LOGF( "finished comparing runs in both directions" );
|
||||
XP_ASSERT( count == jj );
|
||||
|
||||
XP_LOGF( "testing getNth" );
|
||||
testGetNthWord( dict, words, 0, NULL );
|
||||
|
||||
XP_U16 depth = 2;
|
||||
XP_U16 maxCount = dict_numTileFaces( dict );
|
||||
IndexData data;
|
||||
data.count = maxCount * maxCount;
|
||||
data.indices = XP_MALLOC( params->util->mpool,
|
||||
data.count * depth * sizeof(data.indices[0]) );
|
||||
data.prefixes = XP_MALLOC( params->util->mpool,
|
||||
depth * data.count * sizeof(data.prefixes[0]) );
|
||||
|
||||
XP_LOGF( "making index..." );
|
||||
dict_makeIndex( &iter, depth, &data );
|
||||
XP_LOGF( "DONE making index" );
|
||||
|
||||
data.indices = XP_REALLOC( params->util->mpool, data.indices,
|
||||
data.count * depth * sizeof(*data.indices) );
|
||||
data.prefixes = XP_REALLOC( params->util->mpool, data.prefixes,
|
||||
depth * data.count * sizeof(*data.prefixes) );
|
||||
#if 0
|
||||
for ( ii = 0; ii < nIndices; ++ii ) {
|
||||
if ( !dict_getNthWord( dict, &word, indices[ii] ) ) {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
XP_ASSERT( word.index == indices[ii] );
|
||||
XP_UCHAR buf1[64];
|
||||
dict_wordToString( dict, &word, buf1, VSIZE(buf1) );
|
||||
XP_UCHAR buf2[64] = {0};
|
||||
if ( ii > 0 && dict_getNthWord( dict, &word, indices[ii]-1 ) ) {
|
||||
dict_wordToString( dict, &word, buf2, VSIZE(buf2) );
|
||||
}
|
||||
char prfx[8];
|
||||
dict_tilesToString( dict, &prefixes[depth*ii], depth, prfx, VSIZE(prfx) );
|
||||
fprintf( stderr, "%d: index: %ld; prefix: %s; word: %s (prev: %s)\n",
|
||||
ii, indices[ii], prfx, buf1, buf2 );
|
||||
}
|
||||
#endif
|
||||
|
||||
XP_LOGF( "testing getNth WITH INDEXING" );
|
||||
testGetNthWord( dict, words, depth, &data );
|
||||
|
||||
if ( !!testPrefixes ) {
|
||||
int ii;
|
||||
guint count = g_slist_length( testPrefixes );
|
||||
for ( ii = 0; ii < count; ++ii ) {
|
||||
gchar* prefix = (gchar*)g_slist_nth_data( testPrefixes, ii );
|
||||
Tile tiles[MAX_COLS];
|
||||
XP_U16 nTiles = VSIZE(tiles);
|
||||
if ( dict_tilesForString( dict, prefix, tiles, &nTiles ) ) {
|
||||
if ( dict_findStartsWith( &iter, NULL, tiles, nTiles ) ) {
|
||||
XP_UCHAR buf[32];
|
||||
XP_UCHAR bufPrev[32] = {0};
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
|
||||
XP_ASSERT( 0 == strncmp( buf, prefix, strlen(prefix) ) );
|
||||
|
||||
DictPosition pos = dict_getPosition( &iter );
|
||||
XP_ASSERT( 0 == strcmp( buf, words[pos] ) );
|
||||
if ( pos > 0 ) {
|
||||
if ( !dict_getNthWord( &iter, pos-1, depth, &data ) ) {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
dict_wordToString( &iter, bufPrev, VSIZE(bufPrev) );
|
||||
XP_ASSERT( 0 == strcmp( bufPrev, words[pos-1] ) );
|
||||
}
|
||||
XP_LOGF( "dict_getStartsWith(%s) => %s (prev=%s)",
|
||||
prefix, buf, bufPrev );
|
||||
} else {
|
||||
XP_LOGF( "nothing starts with %s", prefix );
|
||||
for ( jj = 0, gotOne = dict_lastWord( &iter );
|
||||
gotOne;
|
||||
++jj, gotOne = dict_getPrevWord( &iter ) ) {
|
||||
XP_ASSERT( dict_getPosition(&iter) == count-jj-1 );
|
||||
XP_UCHAR buf[64];
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
# ifdef PRINT_ALL
|
||||
fprintf( stderr, "%.6ld: %s\n", jj, buf );
|
||||
# endif
|
||||
if ( !!words ) {
|
||||
if ( strcmp( buf, words[count-jj-1] ) ) {
|
||||
fprintf( stderr, "failure at %ld: %s going forward; %s "
|
||||
"going backward\n", jj, words[count-jj-1], buf );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
XP_ASSERT( count == jj );
|
||||
XP_LOGF( "finished comparing runs in both directions" );
|
||||
|
||||
XP_LOGF( "testing getNth" );
|
||||
testGetNthWord( dict, words, 0, NULL, min, max );
|
||||
|
||||
XP_U16 depth = 2;
|
||||
XP_U16 maxCount = dict_numTileFaces( dict );
|
||||
IndexData data;
|
||||
data.count = maxCount * maxCount;
|
||||
data.indices = XP_MALLOC( params->util->mpool,
|
||||
data.count * depth * sizeof(data.indices[0]) );
|
||||
data.prefixes = XP_MALLOC( params->util->mpool,
|
||||
depth * data.count * sizeof(data.prefixes[0]) );
|
||||
|
||||
XP_LOGF( "making index..." );
|
||||
dict_makeIndex( &iter, depth, &data );
|
||||
XP_LOGF( "DONE making index" );
|
||||
|
||||
data.indices = XP_REALLOC( params->util->mpool, data.indices,
|
||||
data.count * depth * sizeof(*data.indices) );
|
||||
data.prefixes = XP_REALLOC( params->util->mpool, data.prefixes,
|
||||
depth * data.count * sizeof(*data.prefixes) );
|
||||
#if 0
|
||||
for ( ii = 0; ii < nIndices; ++ii ) {
|
||||
if ( !dict_getNthWord( dict, &word, indices[ii] ) ) {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
XP_ASSERT( word.index == indices[ii] );
|
||||
XP_UCHAR buf1[64];
|
||||
dict_wordToString( dict, &word, buf1, VSIZE(buf1) );
|
||||
XP_UCHAR buf2[64] = {0};
|
||||
if ( ii > 0 && dict_getNthWord( dict, &word, indices[ii]-1 ) ) {
|
||||
dict_wordToString( dict, &word, buf2, VSIZE(buf2) );
|
||||
}
|
||||
char prfx[8];
|
||||
dict_tilesToString( dict, &prefixes[depth*ii], depth, prfx, VSIZE(prfx) );
|
||||
fprintf( stderr, "%d: index: %ld; prefix: %s; word: %s (prev: %s)\n",
|
||||
ii, indices[ii], prfx, buf1, buf2 );
|
||||
}
|
||||
#endif
|
||||
|
||||
XP_LOGF( "testing getNth WITH INDEXING" );
|
||||
testGetNthWord( dict, words, depth, &data, min, max );
|
||||
|
||||
if ( !!testPrefixes ) {
|
||||
int ii;
|
||||
guint count = g_slist_length( testPrefixes );
|
||||
for ( ii = 0; ii < count; ++ii ) {
|
||||
gchar* prefix = (gchar*)g_slist_nth_data( testPrefixes, ii );
|
||||
Tile tiles[MAX_COLS_DICT];
|
||||
XP_U16 nTiles = VSIZE(tiles);
|
||||
if ( dict_tilesForString( dict, prefix, tiles, &nTiles ) ) {
|
||||
if ( dict_findStartsWith( &iter, NULL, tiles, nTiles ) ) {
|
||||
XP_UCHAR buf[32];
|
||||
XP_UCHAR bufPrev[32] = {0};
|
||||
dict_wordToString( &iter, buf, VSIZE(buf) );
|
||||
|
||||
XP_ASSERT( 0 == strncmp( buf, prefix, strlen(prefix) ) );
|
||||
|
||||
DictPosition pos = dict_getPosition( &iter );
|
||||
XP_ASSERT( 0 == strcmp( buf, words[pos] ) );
|
||||
if ( pos > 0 ) {
|
||||
if ( !dict_getNthWord( &iter, pos-1, depth, &data ) ) {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
dict_wordToString( &iter, bufPrev, VSIZE(bufPrev) );
|
||||
XP_ASSERT( 0 == strcmp( bufPrev, words[pos-1] ) );
|
||||
}
|
||||
XP_LOGF( "dict_getStartsWith(%s) => %s (prev=%s)",
|
||||
prefix, buf, bufPrev );
|
||||
} else {
|
||||
XP_LOGF( "nothing starts with %s", prefix );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
XP_FREE( params->util->mpool, data.indices );
|
||||
XP_FREE( params->util->mpool, data.prefixes );
|
||||
}
|
||||
XP_LOGF( "done" );
|
||||
|
||||
XP_FREE( params->util->mpool, data.indices );
|
||||
XP_FREE( params->util->mpool, data.prefixes );
|
||||
} /* walk_dict_test */
|
||||
}
|
||||
|
||||
static void
|
||||
walk_dict_test_all( const LaunchParams* params, GSList* testDicts,
|
||||
GSList* testPrefixes )
|
||||
GSList* testPrefixes, const char* testMinMax )
|
||||
{
|
||||
int ii;
|
||||
guint count = g_slist_length( testDicts );
|
||||
|
@ -1217,7 +1234,7 @@ walk_dict_test_all( const LaunchParams* params, GSList* testDicts,
|
|||
params->useMmap );
|
||||
if ( NULL != dict ) {
|
||||
XP_LOGF( "walk_dict_test(%s)", name );
|
||||
walk_dict_test( params, dict, testPrefixes );
|
||||
walk_dict_test( params, dict, testPrefixes, testMinMax );
|
||||
dict_destroy( dict );
|
||||
}
|
||||
}
|
||||
|
@ -1242,6 +1259,7 @@ main( int argc, char** argv )
|
|||
#ifdef XWFEATURE_WALKDICT
|
||||
GSList* testDicts = NULL;
|
||||
GSList* testPrefixes = NULL;
|
||||
char* testMinMax = NULL;
|
||||
#endif
|
||||
|
||||
/* install a no-op signal handler. Later curses- or gtk-specific code
|
||||
|
@ -1366,6 +1384,9 @@ main( int argc, char** argv )
|
|||
case CMD_TESTPRFX:
|
||||
testPrefixes = g_slist_prepend( testPrefixes, g_strdup(optarg) );
|
||||
break;
|
||||
case CMD_TESTMINMAX:
|
||||
testMinMax = optarg;
|
||||
break;
|
||||
#endif
|
||||
case CMD_PLAYERDICT:
|
||||
mainParams.gi.players[nPlayerDicts++].dictName = optarg;
|
||||
|
@ -1631,7 +1652,7 @@ main( int argc, char** argv )
|
|||
/* } */
|
||||
#ifdef XWFEATURE_WALKDICT
|
||||
if ( !!testDicts ) {
|
||||
walk_dict_test_all( &mainParams, testDicts, testPrefixes );
|
||||
walk_dict_test_all( &mainParams, testDicts, testPrefixes, testMinMax );
|
||||
exit( 0 );
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -80,6 +80,63 @@ linux_util_makeEmptyDict( XW_UtilCtxt* XP_UNUSED_DBG(uctx) )
|
|||
#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->params->gi.boardSize, &nBonuses );
|
||||
if ( !!bonuses ) {
|
||||
model_setSquareBonuses( cGlobals->game.model, bonuses, nBonuses );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static XWBonusType*
|
||||
parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
||||
{
|
||||
|
@ -146,14 +203,13 @@ parseBonusFile( XP_U16 nCols, const char* bonusFile )
|
|||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
static XWBonusType* parsedFile = NULL;
|
||||
XWBonusType result = EM;
|
||||
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
XP_U16 nCols = model_numCols( model );
|
||||
if ( NULL == parsedFile && NULL != cGlobals->params->bonusFile ) {
|
||||
if ( !parsedFile ) {
|
||||
parsedFile = parseBonusFile( nCols, cGlobals->params->bonusFile );
|
||||
|
@ -162,25 +218,12 @@ linux_util_getSquareBonus( XW_UtilCtxt* uc, const ModelCtxt* model,
|
|||
if ( NULL != parsedFile ) {
|
||||
result = parsedFile[(row*nCols) + col];
|
||||
} else {
|
||||
XP_U16 nEntries;
|
||||
XWBonusType* scrabbleBoard = bonusesFor( 15, &nEntries );
|
||||
|
||||
XP_U16 index, ii;
|
||||
/* This must be static or won't compile under multilink (for Palm).
|
||||
Fix! */
|
||||
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 > (nCols/2) ) col = nCols - 1 - col;
|
||||
if ( row > (nCols/2) ) row = nCols - 1 - row;
|
||||
if ( col > row ) {
|
||||
XP_U16 tmp = col;
|
||||
col = row;
|
||||
|
@ -191,8 +234,8 @@ linux_util_getSquareBonus( XW_UtilCtxt* uc, const ModelCtxt* model,
|
|||
index += ii;
|
||||
}
|
||||
|
||||
if ( index < VSIZE(scrabbleBoard) ) {
|
||||
result = (XWBonusType)scrabbleBoard[index];
|
||||
if ( index < nEntries) {
|
||||
result = scrabbleBoard[index];
|
||||
}
|
||||
}
|
||||
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.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -47,4 +47,10 @@ XP_Bool storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len,
|
|||
const XP_UCHAR* relayID );
|
||||
void writeNoConnMsgs( CommonGlobals* cGlobals, int fd );
|
||||
|
||||
#ifdef STREAM_VERS_BIGBOARD
|
||||
void setSquareBonuses( const CommonGlobals* cGlobals );
|
||||
#else
|
||||
# define setSquareBonuses( cg )
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue