Merge branch 'android_branch' of ssh://xwords.git.sourceforge.net/gitroot/xwords/xwords into android_branch
|
@ -22,7 +22,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.eehouse.android.xw4"
|
||||
android:versionCode="6"
|
||||
android:versionName="4.4 beta 12"
|
||||
android:versionName="4.4 beta 13"
|
||||
>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
|
|
@ -15,8 +15,9 @@ local_DEFINES += \
|
|||
$(local_DEBUG) \
|
||||
-DXWFEATURE_RELAY \
|
||||
-DXWFEATURE_TURNCHANGENOTIFY \
|
||||
-DXWFEATURE_CROSSHAIRS \
|
||||
-DSHOW_PROGRESS \
|
||||
-DKEY_SUPPORT \
|
||||
-DXWFEATURE_CROSSHAIRS \
|
||||
-DPOINTER_SUPPORT \
|
||||
-DSCROLL_DRAG_THRESHHOLD=1 \
|
||||
-DDROP_BITMAPS \
|
||||
|
|
|
@ -197,10 +197,12 @@ and_util_yOffsetChange(XW_UtilCtxt* uc, XP_U16 maxOffset,
|
|||
static void
|
||||
and_util_turnChanged(XW_UtilCtxt* uc)
|
||||
{
|
||||
/* don't log; this is getting called a lot */
|
||||
UTIL_CBK_HEADER( "turnChanged", "()V" );
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid );
|
||||
UTIL_CBK_TAIL();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
and_util_notifyGameOver( XW_UtilCtxt* uc )
|
||||
{
|
||||
|
@ -378,13 +380,17 @@ and_util_getTraySearchLimits(XW_UtilCtxt* uc, XP_U16* min, XP_U16* max )
|
|||
static void
|
||||
and_util_engineStarting( XW_UtilCtxt* uc, XP_U16 nBlanks )
|
||||
{
|
||||
LOG_FUNC();
|
||||
UTIL_CBK_HEADER("engineStarting", "(I)V" );
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid, nBlanks );
|
||||
UTIL_CBK_TAIL();
|
||||
}
|
||||
|
||||
static void
|
||||
and_util_engineStopping( XW_UtilCtxt* uc )
|
||||
{
|
||||
LOG_FUNC();
|
||||
UTIL_CBK_HEADER("engineStopping", "()V" );
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid );
|
||||
UTIL_CBK_TAIL();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ loadCommonPrefs( JNIEnv* env, CommonPrefs* cp, jobject j_cp )
|
|||
cp->skipCommitConfirm = getBool( env, j_cp, "skipCommitConfirm" );
|
||||
cp->showColors = getBool( env, j_cp, "showColors" );
|
||||
cp->sortNewTiles = getBool( env, j_cp, "sortNewTiles" );
|
||||
cp->allowPeek = getBool( env, j_cp, "allowPeek" );
|
||||
}
|
||||
|
||||
static XWStreamCtxt*
|
||||
|
@ -694,6 +695,17 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1replaceTiles
|
|||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1redoReplacedTiles
|
||||
( JNIEnv* env, jclass C, jint gamePtr )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
result = board_redoReplacedTiles( state->game.board );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_server_1handleUndo
|
||||
(JNIEnv* env, jclass C, jint gamePtr)
|
||||
|
@ -726,7 +738,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1resetEngine
|
|||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1requestHint
|
||||
( JNIEnv* env, jclass C, jint gamePtr, jboolean useLimits,
|
||||
jbooleanArray workRemains )
|
||||
jboolean goBack, jbooleanArray workRemains )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
|
@ -735,7 +747,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1requestHint
|
|||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
useLimits,
|
||||
#endif
|
||||
&tmpbool );
|
||||
goBack, &tmpbool );
|
||||
/* If passed need to do workRemains[0] = tmpbool */
|
||||
if ( workRemains ) {
|
||||
jboolean jbool = tmpbool;
|
||||
|
@ -1024,6 +1036,51 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1focusChanged
|
|||
}
|
||||
#endif
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1visTileCount
|
||||
( JNIEnv* env, jclass C, jint gamePtr )
|
||||
{
|
||||
jint result;
|
||||
XWJNI_START();
|
||||
result = board_visTileCount( state->game.board );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1canHint
|
||||
( JNIEnv* env, jclass C, jint gamePtr )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
result = board_canHint( state->game.board );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1canShuffle
|
||||
( JNIEnv* env, jclass C, jint gamePtr )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
result = board_canShuffle( state->game.board );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1canTogglePending
|
||||
( JNIEnv* env, jclass C, jint gamePtr )
|
||||
{
|
||||
jboolean result;
|
||||
XWJNI_START();
|
||||
result = board_canTogglePending( state->game.board );
|
||||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1handleKey
|
||||
( JNIEnv* env, jclass C, jint gamePtr, jobject jkey, jboolean jup,
|
||||
|
@ -1044,6 +1101,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1handleKey
|
|||
XWJNI_END();
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_game_1hasComms
|
||||
|
|
BIN
xwords4/android/XWords4/res/drawable/flip.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
xwords4/android/XWords4/res/drawable/next_hint.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
xwords4/android/XWords4/res/drawable/prev_hint.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
xwords4/android/XWords4/res/drawable/shuffle.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
xwords4/android/XWords4/res/drawable/undo.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
xwords4/android/XWords4/res/drawable/values.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
xwords4/android/XWords4/res/drawable/zoom.png
Normal file
After Width: | Height: | Size: 16 KiB |
|
@ -6,38 +6,24 @@
|
|||
>
|
||||
|
||||
<TextView android:id="@+id/version_string"
|
||||
android:layout_marginLeft="5sp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF"
|
||||
style="@style/about_items"
|
||||
/>
|
||||
|
||||
<TextView android:layout_marginLeft="5sp"
|
||||
android:layout_marginTop="5sp"
|
||||
android:layout_marginBottom="5sp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
<TextView style="@style/about_items"
|
||||
android:text="@string/about_copyright"
|
||||
android:textColor="#FFFFFFFF"
|
||||
/>
|
||||
|
||||
<TextView android:layout_marginLeft="5sp"
|
||||
android:layout_marginTop="5sp"
|
||||
android:layout_marginBottom="5sp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_web"
|
||||
android:textColor="#FFFFFFFF"
|
||||
<TextView style="@style/about_items"
|
||||
android:text="@string/about_web"
|
||||
android:autoLink="all"
|
||||
/>
|
||||
|
||||
<TextView android:id="@+id/about_xlator"
|
||||
android:layout_marginLeft="5sp"
|
||||
android:layout_marginTop="5sp"
|
||||
android:layout_marginBottom="5sp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF"
|
||||
style="@style/about_items"
|
||||
/>
|
||||
|
||||
<TextView style="@style/about_items"
|
||||
android:text="@string/about_credits"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingLeft="3dp"
|
||||
|
@ -9,14 +9,90 @@
|
|||
android:paddingTop="3dp"
|
||||
>
|
||||
|
||||
<org.eehouse.android.xw4.BoardView
|
||||
android:id="@+id/board_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:longClickable="true"
|
||||
android:drawSelectorOnTop="false"/>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<org.eehouse.android.xw4.BoardView
|
||||
android:id="@+id/board_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:longClickable="true"
|
||||
android:drawSelectorOnTop="false"/>
|
||||
|
||||
<LinearLayout android:id="@+id/toolbar_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<ImageButton android:id="@+id/prevhint_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/prev_hint"
|
||||
/>
|
||||
<ImageButton android:id="@+id/nexthint_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/next_hint"
|
||||
/>
|
||||
<ImageButton android:id="@+id/shuffle_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/shuffle"
|
||||
/>
|
||||
<ImageButton android:id="@+id/flip_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/flip"
|
||||
/>
|
||||
<ImageButton android:id="@+id/zoom_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/zoom"
|
||||
/>
|
||||
<ImageButton android:id="@+id/values_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/values"
|
||||
/>
|
||||
<ImageButton android:id="@+id/undo_button_horizontal"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/undo"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:id="@+id/toolbar_vertical"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<ImageButton android:id="@+id/prevhint_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/prev_hint"
|
||||
/>
|
||||
<ImageButton android:id="@+id/nexthint_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/next_hint"
|
||||
/>
|
||||
<ImageButton android:id="@+id/shuffle_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/shuffle"
|
||||
/>
|
||||
<ImageButton android:id="@+id/flip_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/flip"
|
||||
/>
|
||||
<ImageButton android:id="@+id/zoom_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/zoom"
|
||||
/>
|
||||
<ImageButton android:id="@+id/values_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/values"
|
||||
/>
|
||||
<ImageButton android:id="@+id/undo_button_vertical"
|
||||
style="@style/toolbar_button"
|
||||
android:src="@drawable/undo"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -11,4 +11,20 @@
|
|||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:longClickable="true"
|
||||
android:background="@android:drawable/list_selector_background"
|
||||
/>
|
||||
>
|
||||
<TextView android:id="@+id/text_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
|
||||
<ImageButton android:id="@+id/hint_button_horizontal"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@android:drawable/ic_delete"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
</org.eehouse.android.xw4.XWListItem>
|
||||
|
|
|
@ -1,53 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/board_menu_juggle"
|
||||
android:title="@string/board_menu_juggle"
|
||||
android:alphabeticShortcut="J"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_trade"
|
||||
android:title="@string/board_menu_trade"
|
||||
android:alphabeticShortcut="T"
|
||||
/>
|
||||
<item android:title="@string/board_submenu_hint">
|
||||
<menu>
|
||||
<item android:id="@+id/board_menu_hint_next"
|
||||
android:title="@string/board_menu_hint_next"
|
||||
android:alphabeticShortcut="H"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_hint"
|
||||
android:title="@string/board_menu_hint"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_values"
|
||||
android:title="@string/board_menu_values"
|
||||
android:alphabeticShortcut="V"
|
||||
/>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:title="@string/board_submenu_undo">
|
||||
<menu>
|
||||
<item android:id="@+id/board_menu_undo_current"
|
||||
android:title="@string/board_menu_undo_current"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_undo_last"
|
||||
android:title="@string/board_menu_undo_last"
|
||||
android:alphabeticShortcut="U"
|
||||
/>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:id="@+id/board_menu_tray"
|
||||
android:title="@string/board_menu_tray"
|
||||
android:alphabeticShortcut="H"
|
||||
/>
|
||||
<!-- <item android:id="@+id/board_menu_juggle" -->
|
||||
<!-- android:title="@string/board_menu_juggle" -->
|
||||
<!-- android:alphabeticShortcut="J" -->
|
||||
<!-- /> -->
|
||||
|
||||
<item android:id="@+id/board_menu_done"
|
||||
android:title="@string/board_menu_done"
|
||||
android:alphabeticShortcut="D"
|
||||
/>
|
||||
|
||||
<item android:id="@+id/board_menu_flip"
|
||||
android:title="@string/board_menu_flip"
|
||||
android:alphabeticShortcut="F"
|
||||
<item android:id="@+id/board_menu_trade"
|
||||
android:title="@string/board_menu_trade"
|
||||
android:alphabeticShortcut="T"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_undo_last"
|
||||
android:title="@string/board_menu_undo_last"
|
||||
android:alphabeticShortcut="U"
|
||||
/>
|
||||
|
||||
<item android:id="@+id/board_menu_tray"
|
||||
android:title="@string/board_menu_tray"
|
||||
android:alphabeticShortcut="H"
|
||||
/>
|
||||
<!-- <item android:id="@+id/board_menu_flip" -->
|
||||
<!-- android:title="@string/board_menu_flip" -->
|
||||
<!-- android:alphabeticShortcut="F" -->
|
||||
<!-- /> -->
|
||||
|
||||
<item android:id="@+id/board_menu_values"
|
||||
android:title="@string/board_menu_values"
|
||||
android:alphabeticShortcut="V"
|
||||
/>
|
||||
|
||||
<item android:title="@string/board_submenu_game">
|
||||
|
@ -64,6 +48,19 @@
|
|||
android:title="@string/board_menu_game_resend" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:title="@string/board_submenu_hint">
|
||||
<menu>
|
||||
<item android:id="@+id/board_menu_hint"
|
||||
android:title="@string/board_menu_hint"
|
||||
/>
|
||||
<item android:id="@+id/board_menu_hint_next"
|
||||
android:title="@string/board_menu_hint_next"
|
||||
android:alphabeticShortcut="H"
|
||||
/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item android:id="@+id/board_menu_file_prefs"
|
||||
android:title="@string/menu_prefs"
|
||||
android:alphabeticShortcut="P"
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
<item android:id="@+id/dicts_item_select"
|
||||
android:title="@string/dicts_item_select"
|
||||
/>
|
||||
<item android:id="@+id/dicts_item_delete"
|
||||
android:title="@string/dicts_item_delete"
|
||||
/>
|
||||
<item android:id="@+id/dicts_item_details"
|
||||
android:title="@string/dicts_item_details"
|
||||
/>
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- <item android:id="@+id/list_item_open" -->
|
||||
<!-- android:title="@string/list_item_open" -->
|
||||
<!-- /> -->
|
||||
<item android:id="@+id/player_list_item_delete"
|
||||
android:title="@string/list_item_delete"
|
||||
/>
|
||||
<item android:id="@+id/player_list_item_up"
|
||||
android:title="@string/list_item_up"
|
||||
/>
|
||||
<item android:id="@+id/player_list_item_down"
|
||||
android:title="@string/list_item_down"
|
||||
/>
|
||||
</menu>
|
|
@ -19,13 +19,14 @@
|
|||
<string name="menu_insert">Afegeix una partida</string>
|
||||
<string name="button_new_game">Afegeix una partida</string>
|
||||
|
||||
<string name="list_item_play">Vés a la partida</string>
|
||||
<string name="list_item_config">Configura</string>
|
||||
<string name="list_item_hide">Amaga</string>
|
||||
<string name="list_item_delete">Suprimeix</string>
|
||||
<string name="list_item_copy">Copia</string>
|
||||
<string name="list_item_reset">Reinicialitza</string>
|
||||
|
||||
<string name="list_item_new_from">Nova des de</string>
|
||||
<string name="list_item_new_from">Nova</string>
|
||||
<string name="list_item_move_up">Mou amunt</string>
|
||||
<string name="list_item_move_down">Mou avall</string>
|
||||
<string name="list_item_move_to_top">Mou amunt de tot</string>
|
||||
|
@ -185,8 +186,18 @@
|
|||
<string name="explain_robot_summary">Mostra el resum de la jugada dels jugadors robot</string>
|
||||
<string name="skip_confirm_turn">Omet la confirmació de la jugada</string>
|
||||
<string name="skip_confirm_turn_summary">No mostra el resum de la jugada dels jugadors humans</string>
|
||||
<string name="title_sort_tiles">Ordena les fitxes noves</string>
|
||||
<string name="summary_sort_tiles">Ordena el faristol en agafar noves fitxes</string>
|
||||
<string name="ringer_zoom">Zoom amb els botons de volum</string>
|
||||
<string name="ringer_zoom_summary">Apropa o allunya el tauler fent servir les tecles de volum.</string>
|
||||
<string name="click_launches">Clic per a jugar</string>
|
||||
<string name="click_launches_summary">obre la partida en fer-hi clic al llistat de partides, en compte d\'obrir un menú d\'opcions</string>
|
||||
|
||||
<string name="hide_title">Amaga la capçalera</string>
|
||||
<string name="hide_title_summary">Permet que el tauler sigui una mica més gran</string>
|
||||
|
||||
<string name="show_bonussum">Mostra les bonificacions</string>
|
||||
<string name="show_bonussum_summary">Mostra el text com "2P" a les caselles bonificadores lliures</string>
|
||||
|
||||
<string name="role_standalone">Solitari</string>
|
||||
<string name="role_host">Amfitrió</string>
|
||||
|
@ -215,7 +226,13 @@
|
|||
|
||||
<string name="prefs_defaults">Valors predeterminats per a partides noves</string>
|
||||
<string name="prefs_defaults_summary">Paràmetres predeterminats per a partides noves</string>
|
||||
<string name="default_dict">Diccionari de la partida</string>
|
||||
|
||||
<string name="prefs_appearance">Aspecte</string>
|
||||
<string name="prefs_appearance_summary">Paràmetres que controlen l\'aspecte</string>
|
||||
<string name="prefs_behavior">Comportament</string>
|
||||
<string name="prefs_behavior_summary">Paràmetres que controlen el comportament de l\'aplicació</string>
|
||||
|
||||
<string name="default_dict">Diccionari arbitral</string>
|
||||
<string name="default_phonies">Paraules fora del dicc.</string>
|
||||
<string name="board_size">Mida del tauler</string>
|
||||
<string name="default_timerenabled">Usa el rellotge</string>
|
||||
|
@ -232,9 +249,15 @@
|
|||
<string name="bonus_l3x">Triple de lletra</string>
|
||||
<string name="bonus_w2x">Doble de paraula</string>
|
||||
<string name="bonus_w3x">Triple de paraula</string>
|
||||
<string name="bonus_l2x_summary">2L</string>
|
||||
<string name="bonus_w2x_summary">2P</string>
|
||||
<string name="bonus_l3x_summary">3L</string>
|
||||
<string name="bonus_w3x_summary">3P</string>
|
||||
<string name="pts">pts</string>
|
||||
<string name="trading_text">Canvi de fitxes. Pitgeu\n\'Fet\' quan hagueu acabat.</string>
|
||||
<string name="tile_back">Fons de la fitxa</string>
|
||||
<string name="empty">Cel·la buida/fons</string>
|
||||
<string name="clr_crosshairs">Creu d\'ubicació</string>
|
||||
<string name="focus">Color del focus</string>
|
||||
<string name="advanced">Avançat</string>
|
||||
<string name="advanced_summary">No hauríeu de necessitar canviar això</string>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<string name="key_explain_robot">key_explain_robot</string>
|
||||
<string name="key_skip_confirm">key_skip_confirm</string>
|
||||
<string name="key_sort_tiles">key_sort_tiles</string>
|
||||
<string name="key_peek_other">key_peek_other</string>
|
||||
<string name="key_hide_values">key_hide_values</string>
|
||||
<string name="key_ringer_zoom">key_ringer_zoom</string>
|
||||
<string name="key_click_launches">key_click_launches</string>
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
<string name="board_menu_undo_last">Undo last</string>
|
||||
<string name="board_submenu_hint">Hint</string>
|
||||
<string name="board_menu_hint_next">Next hint</string>
|
||||
<string name="board_menu_hint">Hint</string>
|
||||
<string name="board_menu_hint">First hint</string>
|
||||
<string name="board_menu_values">Show values</string>
|
||||
<string name="board_submenu_game">Game</string>
|
||||
<string name="board_menu_game_counts">Counts and values</string>
|
||||
|
@ -135,7 +135,7 @@
|
|||
<string name="str_too_few_tiles_left_to_trade">Too few tiles left to exchange.</string>
|
||||
<string name="str_cant_undo_tileassign">Tile assignment can't be undone.</string>
|
||||
<string name="str_cant_hint_while_disabled">The hint feature is disabled for this game. Enable it for a new game using the Settings dialog.</string>
|
||||
<string name="str_no_peek_remote_tiles">No peeking at remote players' tiles!</string>
|
||||
<string name="str_no_peek_remote_tiles">No peeking at remote players\' tiles!</string>
|
||||
<string name="str_reg_unexpected_user">Refused attempt to register unexpected user[s]</string>
|
||||
<string name="str_server_dict_wins">Conflict between Host and Guest dictionaries; Host wins.</string>
|
||||
<string name="str_reg_server_sans_remote">At least one player must be marked \"Remote\" for a game started as Host.</string>
|
||||
|
@ -180,6 +180,7 @@
|
|||
delete all games? This action cannot be undone.</string>
|
||||
|
||||
<string name="hints_allowed">Allow hints</string>
|
||||
<string name="progress_title">Searching for moves</string>
|
||||
<string name="use_timer">Enable game timer</string>
|
||||
<string name="color_tiles">Color tiles</string>
|
||||
<string name="color_tiles_summary">Draw tiles using color of
|
||||
|
@ -197,16 +198,16 @@
|
|||
<string name="summary_sort_tiles">Sort trays whenever new tiles
|
||||
are added</string>
|
||||
<string name="ringer_zoom">Volume keys zoom</string>
|
||||
<string name="ringer_zoom_summary">Zoom board using volume keys
|
||||
rather than on-screen buttons</string>
|
||||
<string name="ringer_zoom_summary">Zoom board using volume keys</string>
|
||||
<string name="click_launches">Tap to play</string>
|
||||
<string name="click_launches_summary">Tapping on game in games
|
||||
list opens it rather than dropping a menu</string>
|
||||
|
||||
<string name="hide_title">Hide titlebar</string>
|
||||
<string name="hide_title_summary">Hiding the game name lets the
|
||||
board be slightly larger</string>
|
||||
|
||||
<string name="peek_other">View tiles out-of-turn</string>
|
||||
<string name="peek_other_summary">Tapping on scoreboard name shows
|
||||
that player\'s tiles</string>
|
||||
<string name="show_bonussum">Show bonus values</string>
|
||||
<string name="show_bonussum_summary">Include text like "2W" on
|
||||
empty bonus squares</string>
|
||||
|
@ -339,6 +340,9 @@
|
|||
<!-- fill this in other than in English -->
|
||||
<string name="xlator"></string>
|
||||
|
||||
<string name="about_credits">Toolbar icons by Sarah Chu; other
|
||||
credits pending permission.</string>
|
||||
|
||||
<string name="downloading_dictf">Downloading Crosswords
|
||||
dictionary %s...</string>
|
||||
<string name="no_dict_title">Dictionary not found</string>
|
||||
|
|
|
@ -37,5 +37,20 @@
|
|||
<item name="android:ems">3</item>
|
||||
</style>
|
||||
|
||||
<style name="toolbar_button">
|
||||
<item name="android:layout_width">48dp</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
</style>
|
||||
|
||||
<style name="about_items">
|
||||
<item name="android:layout_marginLeft">5sp</item>
|
||||
<item name="android:layout_marginTop">5sp</item>
|
||||
<item name="android:layout_marginBottom">5sp</item>
|
||||
<item name="android:layout_width">fill_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textColor">#FFFFFFFF</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
|
|
|
@ -152,6 +152,11 @@
|
|||
android:summary="@string/click_launches_summary"
|
||||
android:defaultValue="false"
|
||||
/>
|
||||
<CheckBoxPreference android:key="@string/key_peek_other"
|
||||
android:title="@string/peek_other"
|
||||
android:summary="@string/peek_other_summary"
|
||||
android:defaultValue="false"
|
||||
/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/advanced"
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.eehouse.android.xw4;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MenuInflater;
|
||||
|
@ -35,7 +36,9 @@ import java.util.concurrent.Semaphore;
|
|||
import android.net.Uri;
|
||||
import android.app.Dialog;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
@ -67,6 +70,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
private TimerRunnable[] m_timers;
|
||||
private String m_path;
|
||||
private int m_currentOrient;
|
||||
private Toolbar m_toolbar;
|
||||
|
||||
private String m_dlgBytes = null;
|
||||
private EditText m_passwdEdit = null;
|
||||
|
@ -84,6 +88,8 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
private Thread m_blockingThread;
|
||||
private JNIThread m_jniThread;
|
||||
|
||||
private ProgressDialog m_progress;
|
||||
|
||||
public class TimerRunnable implements Runnable {
|
||||
private int m_why;
|
||||
private int m_when;
|
||||
|
@ -253,7 +259,6 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
|
||||
m_view = (BoardView)findViewById( R.id.board_view );
|
||||
m_volKeysZoom = CommonPrefs.getVolKeysZoom( this );
|
||||
m_view.setUseZoomControl( !m_volKeysZoom );
|
||||
|
||||
Intent intent = getIntent();
|
||||
Uri uri = intent.getData();
|
||||
|
@ -343,7 +348,6 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
m_jniThread.handle( JNIThread.JNICmd.CMD_PREFS_CHANGE );
|
||||
}
|
||||
}
|
||||
m_view.setUseZoomControl( !m_volKeysZoom );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,6 +355,11 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
public void onConfigurationChanged( Configuration newConfig )
|
||||
{
|
||||
m_currentOrient = newConfig.orientation;
|
||||
if ( null != m_toolbar ) {
|
||||
boolean landscape =
|
||||
m_currentOrient == Configuration.ORIENTATION_LANDSCAPE;
|
||||
m_toolbar.orientChanged( landscape );
|
||||
}
|
||||
super.onConfigurationChanged( newConfig );
|
||||
}
|
||||
|
||||
|
@ -368,7 +377,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
if ( m_volKeysZoom ) {
|
||||
int zoomBy = KeyEvent.KEYCODE_VOLUME_DOWN == keyCode
|
||||
? -1 : 1;
|
||||
? -2 : 2;
|
||||
handled = doZoom( zoomBy );
|
||||
}
|
||||
break;
|
||||
|
@ -406,21 +415,21 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
case R.id.board_menu_done:
|
||||
cmd = JNIThread.JNICmd.CMD_COMMIT;
|
||||
break;
|
||||
case R.id.board_menu_juggle:
|
||||
cmd = JNIThread.JNICmd.CMD_JUGGLE;
|
||||
break;
|
||||
case R.id.board_menu_flip:
|
||||
cmd = JNIThread.JNICmd.CMD_FLIP;
|
||||
break;
|
||||
// case R.id.board_menu_juggle:
|
||||
// cmd = JNIThread.JNICmd.CMD_JUGGLE;
|
||||
// break;
|
||||
// case R.id.board_menu_flip:
|
||||
// cmd = JNIThread.JNICmd.CMD_FLIP;
|
||||
// break;
|
||||
case R.id.board_menu_trade:
|
||||
cmd = JNIThread.JNICmd.CMD_TOGGLE_TRADE;
|
||||
break;
|
||||
case R.id.board_menu_tray:
|
||||
cmd = JNIThread.JNICmd.CMD_TOGGLE_TRAY;
|
||||
break;
|
||||
case R.id.board_menu_undo_current:
|
||||
cmd = JNIThread.JNICmd.CMD_UNDO_CUR;
|
||||
break;
|
||||
// case R.id.board_menu_undo_current:
|
||||
// cmd = JNIThread.JNICmd.CMD_UNDO_CUR;
|
||||
// break;
|
||||
case R.id.board_menu_undo_last:
|
||||
cmd = JNIThread.JNICmd.CMD_UNDO_LAST;
|
||||
break;
|
||||
|
@ -687,6 +696,8 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
case JNIThread.QUERY_ENDGAME:
|
||||
showDialog( QUERY_ENDGAME );
|
||||
break;
|
||||
case JNIThread.TOOLBAR_STATES:
|
||||
m_toolbar.update( msg.arg1, msg.arg2 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
@ -698,11 +709,80 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
}
|
||||
m_jniThread.handle( JNICmd.CMD_START );
|
||||
|
||||
setTitle( GameUtils.gameName( this, m_path ) );
|
||||
// setTitle( GameUtils.gameName( this, m_path ) );
|
||||
m_toolbar =
|
||||
new Toolbar( this, findViewById( R.id.toolbar_horizontal ),
|
||||
findViewById( R.id.toolbar_vertical ) );
|
||||
|
||||
boolean isLandscape =
|
||||
getResources().getConfiguration().orientation
|
||||
== Configuration.ORIENTATION_LANDSCAPE;
|
||||
m_toolbar.orientChanged( isLandscape );
|
||||
populateToolbar();
|
||||
}
|
||||
}
|
||||
} // loadGame
|
||||
|
||||
private void populateToolbar()
|
||||
{
|
||||
m_toolbar.setListener( Toolbar.BUTTON_HINT_PREV,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_PREV_HINT );
|
||||
}
|
||||
} );
|
||||
m_toolbar.setListener( Toolbar.BUTTON_HINT_NEXT,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_NEXT_HINT );
|
||||
}
|
||||
} );
|
||||
m_toolbar.setListener( Toolbar.BUTTON_JUGGLE,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_JUGGLE );
|
||||
}
|
||||
} );
|
||||
m_toolbar.setListener( Toolbar.BUTTON_FLIP,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_FLIP );
|
||||
}
|
||||
} );
|
||||
m_toolbar.setListener( Toolbar.BUTTON_ZOOM,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_TOGGLEZOOM );
|
||||
}
|
||||
} );
|
||||
m_toolbar.setListener( Toolbar.BUTTON_UNDO,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_UNDO_CUR );
|
||||
}
|
||||
}) ;
|
||||
m_toolbar.setListener( Toolbar.BUTTON_VALUES,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_jniThread.handle( JNIThread.JNICmd
|
||||
.CMD_VALUES );
|
||||
}
|
||||
}) ;
|
||||
} // populateToolbar
|
||||
|
||||
private DialogInterface.OnDismissListener makeODLforBlocking()
|
||||
{
|
||||
return new DialogInterface.OnDismissListener() {
|
||||
|
@ -794,11 +874,44 @@ public class BoardActivity extends Activity implements UtilCtxt {
|
|||
return result;
|
||||
}
|
||||
|
||||
public void turnChanged()
|
||||
{
|
||||
m_jniThread.handle( JNIThread.JNICmd.CMD_ZOOM, -8 );
|
||||
}
|
||||
|
||||
public boolean engineProgressCallback()
|
||||
{
|
||||
return ! m_jniThread.busy();
|
||||
}
|
||||
|
||||
public void engineStarting( int nBlanks )
|
||||
{
|
||||
Utils.logf( "engineStarting(%d)", nBlanks );
|
||||
if ( nBlanks > 0 ) {
|
||||
m_handler.post( new Runnable() {
|
||||
public void run() {
|
||||
String title = getString( R.string.progress_title );
|
||||
m_progress = ProgressDialog.show( BoardActivity.this,
|
||||
title, null, true,
|
||||
true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public void engineStopping()
|
||||
{
|
||||
Utils.logf( "engineStopping" );
|
||||
m_handler.post( new Runnable() {
|
||||
public void run() {
|
||||
if ( null != m_progress ) {
|
||||
m_progress.cancel();
|
||||
m_progress = null;
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public String getUserString( int stringCode )
|
||||
{
|
||||
int id = 0;
|
||||
|
|
|
@ -33,9 +33,7 @@ import android.view.MotionEvent;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Paint.FontMetricsInt;
|
||||
import android.widget.ZoomButtonsController;
|
||||
import android.os.Handler;
|
||||
import java.util.HashMap;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
@ -117,9 +115,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
private int[] m_playerColors;
|
||||
private int[] m_otherColors;
|
||||
private String[] m_bonusSummaries;
|
||||
private ZoomButtonsController m_zoomButtons;
|
||||
private boolean m_useZoomControl;
|
||||
private boolean m_canZoom;
|
||||
|
||||
// called when inflating xml
|
||||
public BoardView( Context context, AttributeSet attrs )
|
||||
|
@ -132,15 +127,13 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
{
|
||||
int action = event.getAction();
|
||||
int xx = (int)event.getX() - m_left;
|
||||
int yy = (int)event.getY() - getCurTop();
|
||||
int yy = (int)event.getY() - m_top;
|
||||
|
||||
switch ( action ) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
enableZoomControlsIf();
|
||||
m_jniThread.handle( JNIThread.JNICmd.CMD_PEN_DOWN, xx, yy );
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
enableZoomControlsIf();
|
||||
m_jniThread.handle( JNIThread.JNICmd.CMD_PEN_MOVE, xx, yy );
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
|
@ -160,18 +153,11 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
{
|
||||
synchronized( this ) {
|
||||
if ( layoutBoardOnce() ) {
|
||||
canvas.drawBitmap( m_bitmap, m_left, getCurTop(), m_drawPaint );
|
||||
canvas.drawBitmap( m_bitmap, m_left, m_top, m_drawPaint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow()
|
||||
{
|
||||
m_zoomButtons.setVisible( false );
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
private void init( Context context )
|
||||
{
|
||||
m_context = context;
|
||||
|
@ -215,33 +201,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
}
|
||||
|
||||
m_viewHandler = new Handler();
|
||||
m_zoomButtons = new ZoomButtonsController( this );
|
||||
ZoomButtonsController.OnZoomListener lstnr =
|
||||
new ZoomButtonsController.OnZoomListener(){
|
||||
public void onVisibilityChanged( boolean visible ){}
|
||||
public void onZoom( boolean zoomIn )
|
||||
{
|
||||
if ( null != m_jniThread ) {
|
||||
int zoomBy = zoomIn ? 1 : -1;
|
||||
m_jniThread.handle( JNIThread.JNICmd.CMD_ZOOM, zoomBy );
|
||||
}
|
||||
}
|
||||
};
|
||||
m_zoomButtons.setOnZoomListener( lstnr );
|
||||
m_zoomButtons.setZoomSpeed( 100 ); // milliseconds
|
||||
}
|
||||
|
||||
protected void setUseZoomControl( boolean useZoomControl )
|
||||
{
|
||||
m_useZoomControl = useZoomControl;
|
||||
if ( !useZoomControl ) {
|
||||
m_zoomButtons.setVisible( false );
|
||||
}
|
||||
}
|
||||
|
||||
private int getCurTop()
|
||||
{
|
||||
return m_useZoomControl ? 0 : m_top;
|
||||
}
|
||||
|
||||
private BoardDims figureBoardDims( int width, int height,
|
||||
|
@ -309,9 +268,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
m_letterRect = null;
|
||||
m_valRect = null;
|
||||
|
||||
// We hide zoom on change in orientation
|
||||
m_zoomButtons.setVisible( false );
|
||||
|
||||
BoardDims dims = figureBoardDims( width, height, m_gi );
|
||||
m_left = dims.left;
|
||||
m_top = dims.top;
|
||||
|
@ -329,15 +285,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
return layoutDone;
|
||||
} // layoutBoardOnce
|
||||
|
||||
private void enableZoomControlsIf()
|
||||
{
|
||||
if ( m_useZoomControl && m_canZoom ) {
|
||||
if ( m_layoutWidth <= m_layoutHeight ) {
|
||||
m_zoomButtons.setVisible( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BoardHandler interface implementation
|
||||
public void startHandling( JNIThread thread, int gamePtr, CurGameInfo gi )
|
||||
{
|
||||
|
@ -375,17 +322,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
}
|
||||
}
|
||||
|
||||
public void zoomChanged( final boolean[] canZoom )
|
||||
{
|
||||
m_viewHandler.post( new Runnable() {
|
||||
public void run() {
|
||||
m_zoomButtons.setZoomInEnabled( canZoom[0] );
|
||||
m_zoomButtons.setZoomOutEnabled( canZoom[1] );
|
||||
m_canZoom = canZoom[0] || canZoom[1];
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// DrawCtxt interface implementation
|
||||
public boolean scoreBegin( Rect rect, int numPlayers, int[] scores,
|
||||
int remCount, int dfs )
|
||||
|
@ -550,7 +486,9 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
|
|||
m_origin.draw( m_canvas );
|
||||
} else if ( null != bonusStr ) {
|
||||
m_fillPaint.setColor( GREY );
|
||||
drawCentered( bonusStr, rect, m_fontDims );
|
||||
Rect brect = new Rect( rect );
|
||||
brect.inset( 0, (brect.height() - m_defaultFontHt)/2 );
|
||||
drawCentered( bonusStr, brect, m_fontDims );
|
||||
}
|
||||
} else {
|
||||
m_fillPaint.setColor( foreColor );
|
||||
|
|
|
@ -39,7 +39,8 @@ import android.content.SharedPreferences;
|
|||
import junit.framework.Assert;
|
||||
|
||||
public class DictsActivity extends ListActivity
|
||||
implements View.OnClickListener {
|
||||
implements View.OnClickListener,
|
||||
XWListItem.DeleteCallback {
|
||||
String[] m_dicts;
|
||||
|
||||
private class DictListAdapter extends XWListAdapter {
|
||||
|
@ -58,6 +59,12 @@ public class DictsActivity extends ListActivity
|
|||
= (XWListItem)factory.inflate( R.layout.list_item, null );
|
||||
view.setPosition( position );
|
||||
view.setText( m_dicts[position] );
|
||||
|
||||
if ( !GameUtils.dictIsBuiltin( DictsActivity.this,
|
||||
m_dicts[position] ) ) {
|
||||
view.setDeleteCallback( DictsActivity.this );
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
@ -88,8 +95,8 @@ public class DictsActivity extends ListActivity
|
|||
|
||||
@Override
|
||||
public void onCreateContextMenu( ContextMenu menu, View view,
|
||||
ContextMenuInfo menuInfo ) {
|
||||
|
||||
ContextMenuInfo menuInfo )
|
||||
{
|
||||
super.onCreateContextMenu( menu, view, menuInfo );
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
|
@ -97,12 +104,6 @@ public class DictsActivity extends ListActivity
|
|||
|
||||
AdapterView.AdapterContextMenuInfo info
|
||||
= (AdapterView.AdapterContextMenuInfo)menuInfo;
|
||||
|
||||
String dict = m_dicts[info.position];
|
||||
if ( GameUtils.dictIsBuiltin( this, dict ) ) {
|
||||
MenuItem item = menu.findItem( R.id.dicts_item_delete );
|
||||
item.setVisible( false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,11 +128,6 @@ public class DictsActivity extends ListActivity
|
|||
editor.putString( key, m_dicts[info.position] );
|
||||
editor.commit();
|
||||
break;
|
||||
case R.id.dicts_item_delete:
|
||||
GameUtils.deleteDict( this, m_dicts[info.position] );
|
||||
mkListAdapter();
|
||||
handled = true;
|
||||
break;
|
||||
case R.id.dicts_item_details:
|
||||
Utils.notImpl( this );
|
||||
break;
|
||||
|
@ -140,6 +136,13 @@ public class DictsActivity extends ListActivity
|
|||
return handled;
|
||||
}
|
||||
|
||||
// DeleteCallback interface
|
||||
public void deleteCalled( int myPosition )
|
||||
{
|
||||
GameUtils.deleteDict( this, m_dicts[myPosition] );
|
||||
mkListAdapter();
|
||||
}
|
||||
|
||||
private void mkListAdapter()
|
||||
{
|
||||
m_dicts = GameUtils.dictList( this );
|
||||
|
|
|
@ -41,8 +41,6 @@ import android.content.DialogInterface;
|
|||
import android.view.LayoutInflater;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.Spinner;
|
||||
|
@ -56,7 +54,8 @@ import junit.framework.Assert;
|
|||
import org.eehouse.android.xw4.jni.*;
|
||||
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
||||
|
||||
public class GameConfig extends Activity implements View.OnClickListener {
|
||||
public class GameConfig extends Activity implements View.OnClickListener,
|
||||
XWListItem.DeleteCallback {
|
||||
|
||||
private static final int PLAYER_EDIT = 1;
|
||||
private static final int ROLE_EDIT_RELAY = 2;
|
||||
|
@ -453,42 +452,12 @@ public class GameConfig extends Activity implements View.OnClickListener {
|
|||
setTitle( String.format( fmt, GameUtils.gameName( this, m_path ) ) );
|
||||
} // onCreate
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu( ContextMenu menu, View view,
|
||||
ContextMenuInfo menuInfo ) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate( R.menu.players_list_item_menu, menu );
|
||||
m_whichPlayer = ((XWListItem)view).getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected( MenuItem item )
|
||||
// DeleteCallback interface
|
||||
public void deleteCalled( int myPosition )
|
||||
{
|
||||
boolean handled = true;
|
||||
boolean changed = false;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
// case R.id.player_list_item_edit:
|
||||
// showDialog( PLAYER_EDIT );
|
||||
// break;
|
||||
case R.id.player_list_item_delete:
|
||||
changed = m_gi.delete( m_whichPlayer );
|
||||
break;
|
||||
case R.id.player_list_item_up:
|
||||
changed = m_gi.moveUp( m_whichPlayer );
|
||||
break;
|
||||
case R.id.player_list_item_down:
|
||||
changed = m_gi.moveDown( m_whichPlayer );
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
}
|
||||
|
||||
if ( changed ) {
|
||||
if ( m_gi.delete( myPosition ) ) {
|
||||
loadPlayers();
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public void onClick( View view )
|
||||
|
@ -560,8 +529,11 @@ public class GameConfig extends Activity implements View.OnClickListener {
|
|||
view.setPosition( ii );
|
||||
view.setText( names[ii] );
|
||||
view.setGravity( Gravity.CENTER );
|
||||
// only enable delete if one will remain
|
||||
if ( 1 < names.length ) {
|
||||
view.setDeleteCallback( this );
|
||||
}
|
||||
|
||||
registerForContextMenu( view );
|
||||
view.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
|
@ -576,6 +548,13 @@ public class GameConfig extends Activity implements View.OnClickListener {
|
|||
m_playerLayout.addView( divider );
|
||||
}
|
||||
|
||||
m_addPlayerButton
|
||||
.setVisibility( names.length >= CurGameInfo.MAX_NUM_PLAYERS?
|
||||
View.GONE : View.VISIBLE );
|
||||
m_jugglePlayersButton
|
||||
.setVisibility( names.length <= 1 ?
|
||||
View.GONE : View.VISIBLE );
|
||||
|
||||
if ( DeviceRole.SERVER_ISSERVER == m_gi.serverRole
|
||||
&& 0 == m_gi.remoteCount() ) {
|
||||
showDialog( FORCE_REMOTE );
|
||||
|
|
138
xwords4/android/XWords4/src/org/eehouse/android/xw4/Toolbar.java
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 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
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
package org.eehouse.android.xw4;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ImageButton;
|
||||
//import android.view.LayoutInflater;
|
||||
//import java.util.HashMap;
|
||||
//import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
|
||||
public class Toolbar {
|
||||
|
||||
private static class TBButtonInfo {
|
||||
public TBButtonInfo( int... ids ) {
|
||||
m_ids = ids;
|
||||
}
|
||||
public int m_ids[];
|
||||
}
|
||||
|
||||
public static final int BUTTON_HINT_PREV = 0;
|
||||
public static final int BUTTON_HINT_NEXT = 1;
|
||||
public static final int BUTTON_FLIP = 2;
|
||||
public static final int BUTTON_JUGGLE = 3;
|
||||
public static final int BUTTON_ZOOM = 4;
|
||||
public static final int BUTTON_UNDO = 5;
|
||||
public static final int BUTTON_VALUES = 6;
|
||||
|
||||
private static TBButtonInfo[] s_buttonInfo = {
|
||||
// BUTTON_HINT_PREV
|
||||
new TBButtonInfo(R.id.prevhint_button_horizontal,
|
||||
R.id.prevhint_button_vertical),
|
||||
// BUTTON_HINT_NEXT
|
||||
new TBButtonInfo(R.id.nexthint_button_horizontal,
|
||||
R.id.nexthint_button_vertical),
|
||||
// BUTTON_FLIP
|
||||
new TBButtonInfo(R.id.flip_button_horizontal,
|
||||
R.id.flip_button_vertical),
|
||||
// BUTTON_JUGGLE
|
||||
new TBButtonInfo( R.id.shuffle_button_horizontal,
|
||||
R.id.shuffle_button_vertical ),
|
||||
// BUTTON_ZOOM
|
||||
new TBButtonInfo( R.id.zoom_button_horizontal,
|
||||
R.id.zoom_button_vertical ),
|
||||
// BUTTON_UNDO
|
||||
new TBButtonInfo( R.id.undo_button_horizontal,
|
||||
R.id.undo_button_vertical ),
|
||||
// BUTTON_VALUES
|
||||
new TBButtonInfo( R.id.values_button_horizontal,
|
||||
R.id.values_button_vertical ),
|
||||
};
|
||||
|
||||
private Activity m_activity;
|
||||
private LinearLayout m_horLayout;
|
||||
private LinearLayout m_vertLayout;
|
||||
|
||||
private enum ORIENTATION { ORIENT_UNKNOWN,
|
||||
ORIENT_PORTRAIT,
|
||||
ORIENT_LANDSCAPE,
|
||||
};
|
||||
private ORIENTATION m_curOrient = ORIENTATION.ORIENT_UNKNOWN;
|
||||
|
||||
public Toolbar( Activity activity, View horLayout, View vertLayout )
|
||||
{
|
||||
m_activity = activity;
|
||||
m_horLayout = (LinearLayout)horLayout;
|
||||
m_vertLayout = (LinearLayout)vertLayout;
|
||||
}
|
||||
|
||||
public void setListener( int index, View.OnClickListener listener )
|
||||
{
|
||||
TBButtonInfo info = s_buttonInfo[index];
|
||||
for ( int id : info.m_ids ) {
|
||||
ImageButton button = (ImageButton)m_activity.findViewById( id );
|
||||
button.setOnClickListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
public void orientChanged( boolean landscape )
|
||||
{
|
||||
if ( landscape && m_curOrient == ORIENTATION.ORIENT_LANDSCAPE ) {
|
||||
// do nothing
|
||||
} else if ( !landscape && m_curOrient == ORIENTATION.ORIENT_PORTRAIT ) {
|
||||
// do nothing
|
||||
} else {
|
||||
LinearLayout prevLayout, nextLayout;
|
||||
if ( landscape ) {
|
||||
m_curOrient = ORIENTATION.ORIENT_LANDSCAPE;
|
||||
prevLayout = m_horLayout;
|
||||
nextLayout = m_vertLayout;
|
||||
} else {
|
||||
m_curOrient = ORIENTATION.ORIENT_PORTRAIT;
|
||||
prevLayout = m_vertLayout;
|
||||
nextLayout = m_horLayout;
|
||||
}
|
||||
|
||||
prevLayout.setVisibility( View.GONE );
|
||||
nextLayout.setVisibility( View.VISIBLE );
|
||||
}
|
||||
}
|
||||
|
||||
public void update( int index, int enable )
|
||||
{
|
||||
boolean show = enable!=0;
|
||||
TBButtonInfo info = s_buttonInfo[index];
|
||||
int vis = enable != 0 ? View.VISIBLE : View.GONE;
|
||||
|
||||
ImageButton button;
|
||||
for ( int id : info.m_ids ) {
|
||||
button = (ImageButton)m_activity.findViewById( id );
|
||||
button.setVisibility( vis );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,5 +23,5 @@ package org.eehouse.android.xw4;
|
|||
public interface XWConstants {
|
||||
public static final String GAME_EXTN = ".xwg";
|
||||
public static final String DICT_EXTN = ".xwd";
|
||||
public static final String VERSION_STR = "4.4 beta 12";
|
||||
public static final String VERSION_STR = "4.4 beta 13";
|
||||
}
|
||||
|
|
|
@ -20,18 +20,48 @@
|
|||
|
||||
package org.eehouse.android.xw4;
|
||||
|
||||
import android.widget.LinearLayout;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ImageButton;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class XWListItem extends TextView {
|
||||
public class XWListItem extends LinearLayout {
|
||||
private int m_position;
|
||||
private ImageButton m_button;
|
||||
private Context m_context;
|
||||
DeleteCallback m_cb;
|
||||
|
||||
public interface DeleteCallback {
|
||||
void deleteCalled( int myPosition );
|
||||
}
|
||||
|
||||
public XWListItem( Context cx, AttributeSet as ) {
|
||||
super( cx, as );
|
||||
m_context = cx;
|
||||
}
|
||||
|
||||
public int getPosition() { return m_position; }
|
||||
public void setPosition( int indx ) { m_position = indx; }
|
||||
|
||||
public void setText( String text )
|
||||
{
|
||||
TextView view = (TextView)getChildAt( 0 );
|
||||
view.setText( text );
|
||||
}
|
||||
|
||||
public void setDeleteCallback( DeleteCallback cb )
|
||||
{
|
||||
m_cb = cb;
|
||||
ImageButton button = (ImageButton)getChildAt( 1 );
|
||||
button.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View view ) {
|
||||
m_cb.deleteCalled( m_position );
|
||||
}
|
||||
} );
|
||||
button.setVisibility( View.VISIBLE );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ public class CommonPrefs {
|
|||
public boolean skipCommitConfirm;
|
||||
public boolean showColors;
|
||||
public boolean sortNewTiles;
|
||||
public boolean allowPeek;
|
||||
|
||||
public int[] playerColors;
|
||||
public int[] bonusColors;
|
||||
|
@ -78,6 +79,7 @@ public class CommonPrefs {
|
|||
R.string.key_skip_confirm, false );
|
||||
showColors = getBoolean( context, sp, R.string.key_color_tiles, true );
|
||||
sortNewTiles = getBoolean( context, sp, R.string.key_sort_tiles, true );
|
||||
allowPeek = getBoolean( context, sp, R.string.key_peek_other, false );
|
||||
|
||||
int ids[] = { R.string.key_player0,
|
||||
R.string.key_player1,
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eehouse.android.xw4.R;
|
|||
import org.eehouse.android.xw4.BoardDims;
|
||||
import org.eehouse.android.xw4.GameUtils;
|
||||
import org.eehouse.android.xw4.DBUtils;
|
||||
import org.eehouse.android.xw4.Toolbar;
|
||||
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
||||
|
||||
public class JNIThread extends Thread {
|
||||
|
@ -63,6 +64,8 @@ public class JNIThread extends Thread {
|
|||
CMD_UNDO_LAST,
|
||||
CMD_HINT,
|
||||
CMD_ZOOM,
|
||||
CMD_TOGGLEZOOM,
|
||||
CMD_PREV_HINT,
|
||||
CMD_NEXT_HINT,
|
||||
CMD_VALUES,
|
||||
CMD_COUNTS_VALUES,
|
||||
|
@ -79,6 +82,7 @@ public class JNIThread extends Thread {
|
|||
public static final int DRAW = 2;
|
||||
public static final int DIALOG = 3;
|
||||
public static final int QUERY_ENDGAME = 4;
|
||||
public static final int TOOLBAR_STATES = 5;
|
||||
|
||||
private boolean m_stopped = false;
|
||||
private int m_jniGamePtr;
|
||||
|
@ -196,6 +200,31 @@ public class JNIThread extends Thread {
|
|||
{
|
||||
boolean draw = false;
|
||||
return draw;
|
||||
} // processKeyEvent
|
||||
|
||||
private void checkButtons()
|
||||
{
|
||||
int visTileCount = XwJNI.board_visTileCount( m_jniGamePtr );
|
||||
int canFlip = visTileCount > 1 ? 1 : 0;
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_FLIP,
|
||||
canFlip ).sendToTarget();
|
||||
int canValues = visTileCount > 0 ? 1 : 0;
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_VALUES,
|
||||
canValues ).sendToTarget();
|
||||
|
||||
int canShuffle = XwJNI.board_canShuffle( m_jniGamePtr ) ? 1 : 0;
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_JUGGLE,
|
||||
canShuffle ).sendToTarget();
|
||||
|
||||
int canRedo = XwJNI.board_canTogglePending( m_jniGamePtr ) ? 1 : 0;
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_UNDO,
|
||||
canRedo ).sendToTarget();
|
||||
|
||||
int canHint = XwJNI.board_canHint( m_jniGamePtr ) ? 1 : 0;
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_HINT_PREV,
|
||||
canHint ).sendToTarget();
|
||||
Message.obtain( m_handler, TOOLBAR_STATES, Toolbar.BUTTON_HINT_NEXT,
|
||||
canHint ).sendToTarget();
|
||||
}
|
||||
|
||||
public void run()
|
||||
|
@ -321,7 +350,8 @@ public class JNIThread extends Thread {
|
|||
draw = XwJNI.board_beginTrade( m_jniGamePtr );
|
||||
break;
|
||||
case CMD_UNDO_CUR:
|
||||
draw = XwJNI.board_replaceTiles( m_jniGamePtr );
|
||||
draw = XwJNI.board_replaceTiles( m_jniGamePtr )
|
||||
|| XwJNI.board_redoReplacedTiles( m_jniGamePtr );
|
||||
break;
|
||||
case CMD_UNDO_LAST:
|
||||
XwJNI.server_handleUndo( m_jniGamePtr );
|
||||
|
@ -330,19 +360,37 @@ public class JNIThread extends Thread {
|
|||
|
||||
case CMD_HINT:
|
||||
XwJNI.board_resetEngine( m_jniGamePtr );
|
||||
// fallthru
|
||||
handle( JNICmd.CMD_NEXT_HINT );
|
||||
break;
|
||||
|
||||
case CMD_NEXT_HINT:
|
||||
draw = XwJNI.board_requestHint( m_jniGamePtr, false, barr );
|
||||
case CMD_PREV_HINT:
|
||||
if ( nextSame( elem.m_cmd ) ) {
|
||||
continue;
|
||||
}
|
||||
draw = XwJNI.board_requestHint( m_jniGamePtr, false,
|
||||
JNICmd.CMD_PREV_HINT==elem.m_cmd,
|
||||
barr );
|
||||
if ( barr[0] ) {
|
||||
handle( JNICmd.CMD_NEXT_HINT );
|
||||
handle( elem.m_cmd );
|
||||
draw = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_TOGGLEZOOM:
|
||||
XwJNI.board_zoom( m_jniGamePtr, 0 , barr );
|
||||
int zoomBy = 0;
|
||||
if ( barr[1] ) { // always go out if possible
|
||||
zoomBy = -4;
|
||||
} else if ( barr[0] ) {
|
||||
zoomBy = 4;
|
||||
}
|
||||
draw = XwJNI.board_zoom( m_jniGamePtr, zoomBy, barr );
|
||||
break;
|
||||
case CMD_ZOOM:
|
||||
draw = XwJNI.board_zoom( m_jniGamePtr,
|
||||
((Integer)args[0]).intValue(),
|
||||
barr );
|
||||
m_drawer.zoomChanged( barr );
|
||||
break;
|
||||
|
||||
case CMD_VALUES:
|
||||
|
@ -433,6 +481,8 @@ public class JNIThread extends Thread {
|
|||
// main UI thread has to invalidate view as it created
|
||||
// it.
|
||||
Message.obtain( m_handler, DRAW ).sendToTarget();
|
||||
|
||||
checkButtons();
|
||||
}
|
||||
}
|
||||
Utils.logf( "run exiting" );
|
||||
|
@ -444,4 +494,5 @@ public class JNIThread extends Thread {
|
|||
// Utils.logf( "adding: " + cmd.toString() );
|
||||
m_queue.add( elem );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,5 +25,4 @@ import android.graphics.Rect;
|
|||
public interface SyncedDraw {
|
||||
void doJNIDraw();
|
||||
void doIconDraw( int resID, final Rect rect );
|
||||
void zoomChanged( boolean[] canZoom );
|
||||
}
|
||||
|
|
|
@ -32,8 +32,11 @@ public interface UtilCtxt {
|
|||
int playerNum, String[] texts );
|
||||
|
||||
String askPassword( String name );
|
||||
void turnChanged();
|
||||
|
||||
boolean engineProgressCallback();
|
||||
void engineStarting( int nBlanks );
|
||||
void engineStopping();
|
||||
|
||||
// Values for why; should be enums
|
||||
public static final int TIMER_PENDOWN = 1;
|
||||
|
|
|
@ -137,14 +137,21 @@ public class XwJNI {
|
|||
public static native boolean board_commitTurn( int gamePtr );
|
||||
public static native boolean board_flip( int gamePtr );
|
||||
public static native boolean board_replaceTiles( int gamePtr );
|
||||
public static native boolean board_redoReplacedTiles( int gamePtr );
|
||||
public static native void board_resetEngine( int gamePtr );
|
||||
public static native boolean board_requestHint( int gamePtr,
|
||||
boolean useTileLimits,
|
||||
boolean goBackwards,
|
||||
boolean[] workRemains );
|
||||
public static native boolean board_beginTrade( int gamePtr );
|
||||
|
||||
public static native String board_formatRemainingTiles( int gamePtr );
|
||||
|
||||
public static native int board_visTileCount( int gamePtr );
|
||||
public static native boolean board_canHint( int gamePtr );
|
||||
public static native boolean board_canShuffle( int gamePtr );
|
||||
public static native boolean board_canTogglePending( int gamePtr );
|
||||
|
||||
public enum XP_Key {
|
||||
XP_KEY_NONE,
|
||||
XP_CURSOR_KEY_DOWN,
|
||||
|
|
|
@ -72,8 +72,6 @@
|
|||
# define MAX_BOARD_ZOOM 4
|
||||
#endif
|
||||
|
||||
#define BOARD_ZOOMBY 2
|
||||
|
||||
#ifdef CPLUS
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -424,6 +422,7 @@ board_prefsChanged( BoardCtxt* board, CommonPrefs* cp )
|
|||
board->hideValsInTray = cp->hideTileValues;
|
||||
board->skipCommitConfirm = cp->skipCommitConfirm;
|
||||
board->showColors = cp->showColors;
|
||||
board->allowPeek = cp->allowPeek;
|
||||
|
||||
if ( showArrowChanged ) {
|
||||
showArrowChanged = setArrowVisible( board, XP_FALSE );
|
||||
|
@ -537,6 +536,38 @@ board_getYOffset( const BoardCtxt* board )
|
|||
return vsd->offset;
|
||||
} /* board_getYOffset */
|
||||
|
||||
XP_U16
|
||||
board_visTileCount( const BoardCtxt* board )
|
||||
{
|
||||
return model_visTileCount( board->model, board->selPlayer,
|
||||
TRAY_REVEALED == board->trayVisState );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
board_canShuffle( const BoardCtxt* board )
|
||||
{
|
||||
return model_canShuffle( board->model, board->selPlayer,
|
||||
TRAY_REVEALED == board->trayVisState );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
board_canTogglePending( const BoardCtxt* board )
|
||||
{
|
||||
return TRAY_REVEALED == board->trayVisState
|
||||
&& model_canTogglePending( board->model, board->selPlayer );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
board_canHint( const BoardCtxt* board )
|
||||
{
|
||||
XP_Bool canHint = !board->gi->hintsNotAllowed;
|
||||
if ( canHint ) {
|
||||
LocalPlayer* lp = &board->gi->players[board->selPlayer];
|
||||
canHint = lp->isLocal && !lp->isRobot;
|
||||
}
|
||||
return canHint;
|
||||
}
|
||||
|
||||
static XP_U16
|
||||
adjustOffset( XP_U16 curOffset, XP_S16 zoomBy )
|
||||
{
|
||||
|
@ -561,20 +592,13 @@ canZoomIn( const BoardCtxt* board, XP_S16 newCount )
|
|||
}
|
||||
|
||||
XP_Bool
|
||||
board_zoom( BoardCtxt* board, XP_S16 zoomDir, XP_Bool* canInOut )
|
||||
board_zoom( BoardCtxt* board, XP_S16 zoomBy, XP_Bool* canInOut )
|
||||
{
|
||||
XP_S16 zoomBy = 0;
|
||||
XP_Bool changed;
|
||||
XP_S16 zoomCount = board->zoomCount;
|
||||
ScrollData* hsd = &board->sd[SCROLL_H];
|
||||
ScrollData* vsd = &board->sd[SCROLL_V];
|
||||
|
||||
if ( zoomDir > 0 ) {
|
||||
zoomBy = BOARD_ZOOMBY;
|
||||
} else if ( zoomDir < 0 ) {
|
||||
zoomBy = -BOARD_ZOOMBY;
|
||||
}
|
||||
|
||||
XP_U16 maxCount = model_numCols( board->model ) - MAX_BOARD_ZOOM;
|
||||
if ( board->boardBounds.width > board->boardBounds.height ) {
|
||||
XP_U16 ratio = board->boardBounds.width / board->boardBounds.height;
|
||||
|
@ -592,8 +616,11 @@ board_zoom( BoardCtxt* board, XP_S16 zoomDir, XP_Bool* canInOut )
|
|||
|
||||
/* If we're zooming in, make sure we'll stay inside the limit */
|
||||
if ( changed && zoomBy > 0 ) {
|
||||
changed = canZoomIn( board, zoomCount );
|
||||
while ( zoomCount > 0 && !canZoomIn( board, zoomCount ) ) {
|
||||
--zoomCount;
|
||||
}
|
||||
}
|
||||
changed = zoomCount != board->zoomCount;
|
||||
|
||||
if ( changed ) {
|
||||
/* Try to distribute the zoom */
|
||||
|
@ -788,15 +815,17 @@ board_commitTurn( BoardCtxt* board )
|
|||
* singletons that may have to be hidden or shown.
|
||||
*/
|
||||
static void
|
||||
selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal )
|
||||
selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal,
|
||||
XP_Bool canPeek )
|
||||
{
|
||||
if ( !board->gameOver && server_getCurrentTurn(board->server) < 0 ) {
|
||||
XP_S16 curTurn = server_getCurrentTurn(board->server);
|
||||
if ( !board->gameOver && curTurn < 0 ) {
|
||||
/* game not started yet; do nothing */
|
||||
} else if ( board->selPlayer == newPlayer ) {
|
||||
if ( reveal ) {
|
||||
checkRevealTray( board );
|
||||
}
|
||||
} else {
|
||||
} else if ( canPeek || newPlayer == curTurn ) {
|
||||
PerTurnInfo* newInfo = &board->pti[newPlayer];
|
||||
XP_U16 oldPlayer = board->selPlayer;
|
||||
model_foreachPendingCell( board->model, newPlayer,
|
||||
|
@ -846,9 +875,9 @@ selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal )
|
|||
} /* selectPlayerImpl */
|
||||
|
||||
void
|
||||
board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer )
|
||||
board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer, XP_Bool canSwitch )
|
||||
{
|
||||
selectPlayerImpl( board, newPlayer, XP_TRUE );
|
||||
selectPlayerImpl( board, newPlayer, XP_TRUE, canSwitch );
|
||||
} /* board_selectPlayer */
|
||||
|
||||
void
|
||||
|
@ -1577,6 +1606,12 @@ board_replaceTiles( BoardCtxt* board )
|
|||
return result;
|
||||
} /* board_replaceTiles */
|
||||
|
||||
XP_Bool
|
||||
board_redoReplacedTiles( BoardCtxt* board )
|
||||
{
|
||||
return model_redoPendingTiles( board->model, board->selPlayer );
|
||||
}
|
||||
|
||||
/* There are a few conditions that must be true for any of several actions
|
||||
to be allowed. Check them here. */
|
||||
static XP_Bool
|
||||
|
@ -1597,7 +1632,7 @@ board_requestHint( BoardCtxt* board,
|
|||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
XP_Bool useTileLimits,
|
||||
#endif
|
||||
XP_Bool* workRemainsP )
|
||||
XP_Bool usePrev, XP_Bool* workRemainsP )
|
||||
{
|
||||
XP_Bool result = XP_FALSE;
|
||||
XP_Bool redraw = XP_FALSE;
|
||||
|
@ -1669,7 +1704,7 @@ board_requestHint( BoardCtxt* board,
|
|||
#endif
|
||||
searchComplete = engine_findMove(engine, model,
|
||||
model_getDictionary(model),
|
||||
tiles, nTiles,
|
||||
tiles, nTiles, usePrev,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
lp, useTileLimits,
|
||||
#endif
|
||||
|
@ -1730,8 +1765,8 @@ figureHScale( BoardCtxt* board )
|
|||
ScrollData* hsd;
|
||||
|
||||
while ( !canZoomIn( board, board->zoomCount ) ) {
|
||||
XP_ASSERT( board->zoomCount >= BOARD_ZOOMBY );
|
||||
board->zoomCount -= BOARD_ZOOMBY;
|
||||
XP_ASSERT( board->zoomCount >= 1 );
|
||||
--board->zoomCount;
|
||||
}
|
||||
|
||||
nCols = model_numCols( board->model );
|
||||
|
@ -3276,7 +3311,7 @@ boardTurnChanged( void* p_board )
|
|||
nextPlayer = chooseBestSelPlayer( board );
|
||||
if ( nextPlayer >= 0 ) {
|
||||
XP_U16 nHumans = gi_countLocalHumans( board->gi );
|
||||
selectPlayerImpl( board, nextPlayer, nHumans <= 1 );
|
||||
selectPlayerImpl( board, nextPlayer, nHumans <= 1, XP_TRUE );
|
||||
}
|
||||
|
||||
setTimerIf( board );
|
||||
|
|
|
@ -78,6 +78,11 @@ void board_reset( BoardCtxt* board );
|
|||
XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 newOffset );
|
||||
XP_U16 board_getYOffset( const BoardCtxt* board );
|
||||
|
||||
XP_U16 board_visTileCount( const BoardCtxt* board );
|
||||
XP_Bool board_canShuffle( const BoardCtxt* board );
|
||||
XP_Bool board_canTogglePending( const BoardCtxt* board );
|
||||
XP_Bool board_canHint( const BoardCtxt* board );
|
||||
|
||||
/* zoomBy: >0: zoom in; < 0: zoom out; 0: query only */
|
||||
XP_Bool board_zoom( BoardCtxt* board, XP_S16 zoomBy, XP_Bool* canInOut );
|
||||
|
||||
|
@ -98,12 +103,13 @@ XP_Bool board_flip( BoardCtxt* board );
|
|||
XP_Bool board_get_showValues( const BoardCtxt* board );
|
||||
XP_Bool board_toggle_showValues( BoardCtxt* board );
|
||||
XP_Bool board_replaceTiles( BoardCtxt* board );
|
||||
XP_Bool board_redoReplacedTiles( BoardCtxt* board );
|
||||
|
||||
XP_Bool board_requestHint( BoardCtxt* board,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
XP_Bool useTileLimits,
|
||||
#endif
|
||||
XP_Bool* workRemainsP );
|
||||
XP_Bool usePrev, XP_Bool* workRemainsP );
|
||||
|
||||
XP_Bool board_prefsChanged( BoardCtxt* board, CommonPrefs* cp );
|
||||
|
||||
|
|
|
@ -58,11 +58,12 @@ typedef struct _DragState {
|
|||
DragType dtype;
|
||||
XP_Bool didMove; /* there was change during the drag; not a
|
||||
tap */
|
||||
XP_Bool cellChanged; /* nothing dragged but movement happened */
|
||||
XP_Bool scrollTimerSet;
|
||||
XP_Bool isBlank; /* cache rather than lookup in model */
|
||||
Tile tile; /* cache rather than lookup in model */
|
||||
DragObjInfo start;
|
||||
DragObjInfo cur;
|
||||
DragObjInfo cur; /* where dragged object (not pen) is */
|
||||
#ifdef XWFEATURE_RAISETILE
|
||||
XP_U16 yyAdd;
|
||||
#endif
|
||||
|
@ -172,6 +173,7 @@ struct BoardCtxt {
|
|||
XP_Bool disableArrow;
|
||||
XP_Bool hideValsInTray;
|
||||
XP_Bool skipCommitConfirm;
|
||||
XP_Bool allowPeek; /* Can look at non-turn player's rack */
|
||||
|
||||
XP_Bool eraseTray;
|
||||
XP_Bool boardObscuresTray;
|
||||
|
@ -245,7 +247,7 @@ void figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect );
|
|||
XP_Bool rectsIntersect( const XP_Rect* rect1, const XP_Rect* rect2 );
|
||||
XP_S16 pointToTileIndex( BoardCtxt* board, XP_U16 x, XP_U16 y,
|
||||
XP_Bool* onDividerP );
|
||||
void board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer );
|
||||
void board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer, XP_Bool canPeek );
|
||||
void flipIf( const BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||
XP_U16* fCol, XP_U16* fRow );
|
||||
XP_Bool pointOnSomething( BoardCtxt* board, XP_U16 x, XP_U16 y,
|
||||
|
|
|
@ -135,6 +135,7 @@ typedef struct CommonPrefs {
|
|||
XP_U16 robotThinkMin, robotThinkMax;
|
||||
#endif
|
||||
XP_Bool showColors; /* applies to all games */
|
||||
XP_Bool allowPeek; /* applies to all games */
|
||||
} CommonPrefs;
|
||||
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
|
|
|
@ -63,7 +63,16 @@ dragDropInProgress( const BoardCtxt* board )
|
|||
XP_Bool
|
||||
dragDropHasMoved( const BoardCtxt* board )
|
||||
{
|
||||
return dragDropInProgress(board) && board->dragState.didMove;
|
||||
XP_Bool moved = dragDropInProgress( board );
|
||||
if ( moved ) {
|
||||
if ( board->dragState.didMove ) {
|
||||
/* something was dragged; do nothing */
|
||||
} else {
|
||||
const DragState* ds = &board->dragState;
|
||||
moved = ds->cellChanged; /* did non-drag movement happen? */
|
||||
}
|
||||
}
|
||||
return moved;
|
||||
} /* dragDropHasMoved */
|
||||
|
||||
static XP_Bool
|
||||
|
@ -490,14 +499,20 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
|
|||
} else if ( ds->dtype == DT_BOARD ) {
|
||||
if ( newInfo.obj == OBJ_BOARD ) {
|
||||
XP_S16 diff = newInfo.u.board.col - ds->cur.u.board.col;
|
||||
if ( !ds->cellChanged && 0 != diff ) {
|
||||
ds->cellChanged = XP_TRUE;
|
||||
}
|
||||
diff /= SCROLL_DRAG_THRESHHOLD;
|
||||
moving = adjustXOffset( board, diff );
|
||||
|
||||
diff = newInfo.u.board.row - ds->cur.u.board.row;
|
||||
if ( !ds->cellChanged && 0 != diff ) {
|
||||
ds->cellChanged = XP_TRUE;
|
||||
}
|
||||
diff /= SCROLL_DRAG_THRESHHOLD;
|
||||
moving = adjustYOffset( board, diff ) || moving;
|
||||
}
|
||||
} else {
|
||||
} else if ( ds->dtype == DT_TILE ) {
|
||||
if ( newInfo.obj == OBJ_BOARD ) {
|
||||
moving = (newInfo.u.board.col != ds->cur.u.board.col)
|
||||
|| (newInfo.u.board.row != ds->cur.u.board.row)
|
||||
|
@ -537,6 +552,8 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
|
|||
XP_MEMCPY( &ds->cur, &newInfo, sizeof(ds->cur) );
|
||||
startScrollTimerIf( board );
|
||||
}
|
||||
} else {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
|
||||
if ( moving ) {
|
||||
|
|
|
@ -31,7 +31,9 @@ extern "C" {
|
|||
|
||||
typedef XP_U8 Engine_rack[MAX_UNIQUE_TILES+1];
|
||||
|
||||
#define NUM_SAVED_MOVES 10
|
||||
#ifndef NUM_SAVED_ENGINE_MOVES
|
||||
# define NUM_SAVED_ENGINE_MOVES 10
|
||||
#endif
|
||||
|
||||
typedef struct BlankTuple {
|
||||
short col;
|
||||
|
@ -48,11 +50,30 @@ typedef struct PossibleMove {
|
|||
blanks */
|
||||
} PossibleMove;
|
||||
|
||||
/* MoveIterationData is a cache of moves so that next and prev searches don't
|
||||
* always trigger an actual search. Instead we save up to
|
||||
* NUM_SAVED_ENGINE_MOVES moves that sort together; then iteration is just
|
||||
* returning the next or previous in the cache. The cache, savedMoves[], is
|
||||
* sorted in increasing order, with any unused entries at the low end (since
|
||||
* they sort as if score == 0). nInMoveCache is the actual number of entries.
|
||||
* curCacheIndex is the index of the move most recently returned, or outside
|
||||
* the range if nothing's been returned yet from the current cache.
|
||||
*
|
||||
* The cache is empty if nInMoveCache == 0, or if curCacheIndex is in a
|
||||
* position that, given engine->usePrev, indicates it's been walked through
|
||||
* the cache already rather than being poised to enter it.
|
||||
*/
|
||||
|
||||
typedef struct MoveIterationData {
|
||||
PossibleMove savedMoves[NUM_SAVED_MOVES];
|
||||
XP_U16 lowestSavedScore;
|
||||
/* savedMoves: if any entries are unused (because result set doesn't fill,
|
||||
they're at the low end (where sort'll put 'em) */
|
||||
PossibleMove savedMoves[NUM_SAVED_ENGINE_MOVES];
|
||||
//XP_U16 lowestSavedScore;
|
||||
PossibleMove lastSeenMove;
|
||||
XP_U16 leftInMoveCache;
|
||||
XP_U16 nInMoveCache; /* num entries,
|
||||
0 <= nInMoveCache < NUM_SAVED_ENGINE_MOVES */
|
||||
XP_U16 bottom; /* lowest non-0 entry */
|
||||
XP_S16 curCacheIndex; /* what we last returned */
|
||||
} MoveIterationData;
|
||||
|
||||
/* one bit per tile that's possible here *\/ */
|
||||
|
@ -66,6 +87,7 @@ struct EngineCtxt {
|
|||
|
||||
Engine_rack rack;
|
||||
Tile blankTile;
|
||||
XP_Bool usePrev;
|
||||
XP_Bool searchInProgress;
|
||||
XP_Bool searchHorizontal;
|
||||
XP_Bool isRobot;
|
||||
|
@ -130,7 +152,10 @@ static void considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
|
|||
BlankTuple* usedBlanks,
|
||||
XP_U16 usedBlanksCount );
|
||||
static void saveMoveIfQualifies( EngineCtxt* engine, PossibleMove* posmove );
|
||||
|
||||
static XP_Bool move_cache_empty( const EngineCtxt* engine );
|
||||
static void init_move_cache( EngineCtxt* engine );
|
||||
static PossibleMove* next_from_cache( EngineCtxt* engine );
|
||||
static void set_search_limits( EngineCtxt* engine );
|
||||
|
||||
|
||||
#if defined __LITTLE_ENDIAN
|
||||
|
@ -221,8 +246,9 @@ engine_makeFromStream( MPFORMAL XWStreamCtxt* XP_UNUSED_DBG(stream),
|
|||
void
|
||||
engine_reset( EngineCtxt* engine )
|
||||
{
|
||||
XP_MEMSET( &engine->miData, 0, sizeof(engine->miData) );
|
||||
engine->miData.lastSeenMove.score = 0xffff; /* max possible */
|
||||
XP_MEMSET( &engine->miData, 0, sizeof(engine->miData) );
|
||||
/* set last score to max possible */
|
||||
engine->miData.lastSeenMove.score = engine->usePrev? 0 : 0xffff;
|
||||
engine->searchInProgress = XP_FALSE;
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
engine->tileLimitsKnown = XP_FALSE; /* indicates not set */
|
||||
|
@ -273,11 +299,33 @@ cmpMoves( PossibleMove* m1, PossibleMove* m2 )
|
|||
} /* cmpMoves */
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
print_savedMoves( const EngineCtxt* engine, const char* label )
|
||||
{
|
||||
int ii;
|
||||
int pos = 0;
|
||||
char buf[(NUM_SAVED_ENGINE_MOVES*10) + 3] = {0};
|
||||
for ( ii = 0; ii < NUM_SAVED_ENGINE_MOVES; ++ii ) {
|
||||
if ( 0 < engine->miData.savedMoves[ii].score ) {
|
||||
pos += XP_SNPRINTF( &buf[pos], VSIZE(buf)-pos, "[%d]: %d; ",
|
||||
ii, engine->miData.savedMoves[ii].score );
|
||||
}
|
||||
}
|
||||
XP_LOGF( "%s: %s", label, buf );
|
||||
}
|
||||
#else
|
||||
# define print_savedMoves( engine, label )
|
||||
#endif
|
||||
|
||||
static XP_Bool
|
||||
chooseMove( EngineCtxt* engine, PossibleMove** move )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_U16 ii;
|
||||
PossibleMove* chosen;
|
||||
XP_Bool result;
|
||||
|
||||
print_savedMoves( engine, "unsorted moves" );
|
||||
|
||||
/* First, sort 'em. Put the higher-scoring moves at the top where they'll
|
||||
get picked up first. Don't sort if we're working for a robot; we've
|
||||
|
@ -286,53 +334,40 @@ chooseMove( EngineCtxt* engine, PossibleMove** move )
|
|||
if ( engine->isRobot ) {
|
||||
chosen = &engine->miData.savedMoves[0];
|
||||
} else {
|
||||
while ( engine->miData.leftInMoveCache == 0 ) {
|
||||
XP_Bool done = XP_TRUE;
|
||||
for ( i = 0; i < NUM_SAVED_MOVES-1; ++i ) {
|
||||
if ( CMPMOVES( &engine->miData.savedMoves[i],
|
||||
&engine->miData.savedMoves[i+1]) > 0 ) {
|
||||
XP_Bool done = !move_cache_empty( engine );
|
||||
while ( !done ) { /* while so can break */
|
||||
done = XP_TRUE;
|
||||
PossibleMove* cur = engine->miData.savedMoves;
|
||||
for ( ii = 0; ii < NUM_SAVED_ENGINE_MOVES-1; ++ii ) {
|
||||
PossibleMove* next = cur + 1;
|
||||
if ( CMPMOVES( cur, next ) > 0 ) {
|
||||
PossibleMove tmp;
|
||||
XP_MEMCPY( &tmp, &engine->miData.savedMoves[i],
|
||||
sizeof(tmp) );
|
||||
XP_MEMCPY( &engine->miData.savedMoves[i],
|
||||
&engine->miData.savedMoves[i+1],
|
||||
sizeof(engine->miData.savedMoves[i]) );
|
||||
XP_MEMCPY( &engine->miData.savedMoves[i+1], &tmp,
|
||||
sizeof(engine->miData.savedMoves[i+1]) );
|
||||
XP_MEMCPY( &tmp, cur, sizeof(tmp) );
|
||||
XP_MEMCPY( cur, next, sizeof(*cur) );
|
||||
XP_MEMCPY( next, &tmp, sizeof(*next) );
|
||||
done = XP_FALSE;
|
||||
}
|
||||
cur = next;
|
||||
}
|
||||
if ( done ) {
|
||||
engine->miData.leftInMoveCache = NUM_SAVED_MOVES;
|
||||
init_move_cache( engine );
|
||||
print_savedMoves( engine, "sorted moves" );
|
||||
}
|
||||
#if 0
|
||||
XP_DEBUGF( "sorted moves; scores are: " );
|
||||
for ( i = 0; i < NUM_SAVED_MOVES; ++i ) {
|
||||
XP_DEBUGF( "%d; ", engine->miData.savedMoves[i].score );
|
||||
}
|
||||
XP_DEBUGF( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* now pick the one we're supposed to return */
|
||||
chosen = &engine->miData.savedMoves[--engine->miData.leftInMoveCache];
|
||||
chosen = next_from_cache( engine );
|
||||
}
|
||||
|
||||
*move = chosen; /* set either way */
|
||||
|
||||
if ( chosen->score > 0 ) {
|
||||
result = (NULL != chosen) && (chosen->score > 0);
|
||||
|
||||
if ( engine->miData.leftInMoveCache == 0 ) {
|
||||
XP_MEMCPY( &engine->miData.lastSeenMove,
|
||||
&engine->miData.savedMoves[0],
|
||||
sizeof(engine->miData.lastSeenMove) );
|
||||
engine->miData.lowestSavedScore = 0;
|
||||
}
|
||||
|
||||
return XP_TRUE;
|
||||
} else {
|
||||
if ( !result ) {
|
||||
engine_reset( engine );
|
||||
return XP_FALSE;
|
||||
}
|
||||
LOG_RETURNF( "%d", result );
|
||||
return result;
|
||||
} /* chooseMove */
|
||||
|
||||
/* Return of XP_TRUE means that we ran to completion. XP_FALSE means we were
|
||||
|
@ -342,7 +377,7 @@ chooseMove( EngineCtxt* engine, PossibleMove** move )
|
|||
XP_Bool
|
||||
engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
|
||||
const DictionaryCtxt* dict, const Tile* tiles,
|
||||
XP_U16 nTiles,
|
||||
XP_U16 nTiles, XP_Bool usePrev,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
const BdHintLimits* searchLimits,
|
||||
XP_Bool useTileLimits,
|
||||
|
@ -384,6 +419,7 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
|
|||
|
||||
engine->model = model;
|
||||
engine->dict = dict;
|
||||
engine->usePrev = usePrev;
|
||||
engine->blankTile = dict_getBlankTile( dict );
|
||||
engine->returnNOW = XP_FALSE;
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
|
@ -408,7 +444,8 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
|
|||
|
||||
engine->targetScore = targetScore;
|
||||
|
||||
if ( engine->miData.leftInMoveCache == 0 ) {
|
||||
if ( move_cache_empty( engine ) ) {
|
||||
set_search_limits( engine );
|
||||
|
||||
XP_MEMSET( engine->miData.savedMoves, 0,
|
||||
sizeof(engine->miData.savedMoves) );
|
||||
|
@ -476,12 +513,11 @@ engine_findMove( EngineCtxt* engine, const ModelCtxt* model,
|
|||
result = XP_FALSE;
|
||||
} else {
|
||||
PossibleMove* move;
|
||||
|
||||
result = XP_TRUE;
|
||||
|
||||
(void)chooseMove( engine, &move );
|
||||
XP_ASSERT( !!newMove );
|
||||
XP_MEMCPY( newMove, &move->moveInfo, sizeof(*newMove) );
|
||||
result = chooseMove( engine, &move );
|
||||
if ( result ) {
|
||||
XP_ASSERT( !!newMove );
|
||||
XP_MEMCPY( newMove, &move->moveInfo, sizeof(*newMove) );
|
||||
}
|
||||
}
|
||||
|
||||
util_engineStopping( engine->util );
|
||||
|
@ -1043,7 +1079,7 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
|
|||
XP_U16 lastRow, BlankTuple* usedBlanks,
|
||||
XP_U16 usedBlanksCount )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_U16 ii;
|
||||
|
||||
if ( blanksLeft == 0 ) {
|
||||
XP_U16 score;
|
||||
|
@ -1059,11 +1095,11 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
|
|||
if ( scoreQualifies( engine, score ) ) {
|
||||
posmove->score = score;
|
||||
XP_MEMSET( &posmove->blankVals, 0, sizeof(posmove->blankVals) );
|
||||
for ( i = 0; i < usedBlanksCount; ++i ) {
|
||||
short col = usedBlanks[i].col;
|
||||
posmove->blankVals[col] = usedBlanks[i].tile;
|
||||
for ( ii = 0; ii < usedBlanksCount; ++ii ) {
|
||||
short col = usedBlanks[ii].col;
|
||||
posmove->blankVals[col] = usedBlanks[ii].tile;
|
||||
}
|
||||
XP_ASSERT( posmove->moveInfo.isHorizontal==
|
||||
XP_ASSERT( posmove->moveInfo.isHorizontal ==
|
||||
engine->searchHorizontal );
|
||||
posmove->moveInfo.commonCoord = (XP_U8)lastRow;
|
||||
saveMoveIfQualifies( engine, posmove );
|
||||
|
@ -1078,18 +1114,18 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
|
|||
bt = &usedBlanks[usedBlanksCount++];
|
||||
|
||||
/* for each letter for which the blank might be standing in... */
|
||||
for ( i = 0; i < posmove->moveInfo.nTiles; ++i ) {
|
||||
CellTile tile = posmove->moveInfo.tiles[i].tile;
|
||||
for ( ii = 0; ii < posmove->moveInfo.nTiles; ++ii ) {
|
||||
CellTile tile = posmove->moveInfo.tiles[ii].tile;
|
||||
if ( (tile & TILE_VALUE_MASK) == bTile && !IS_BLANK(tile) ) {
|
||||
posmove->moveInfo.tiles[i].tile |= TILE_BLANK_BIT;
|
||||
bt->col = i;
|
||||
posmove->moveInfo.tiles[ii].tile |= TILE_BLANK_BIT;
|
||||
bt->col = ii;
|
||||
bt->tile = bTile;
|
||||
considerScoreWordHasBlanks( engine, blanksLeft,
|
||||
posmove, lastRow,
|
||||
usedBlanks,
|
||||
usedBlanksCount );
|
||||
/* now put things back */
|
||||
posmove->moveInfo.tiles[i].tile &= ~TILE_BLANK_BIT;
|
||||
posmove->moveInfo.tiles[ii].tile &= ~TILE_BLANK_BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1098,24 +1134,32 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft,
|
|||
static void
|
||||
saveMoveIfQualifies( EngineCtxt* engine, PossibleMove* posmove )
|
||||
{
|
||||
XP_S16 lowest = 0;
|
||||
XP_S16 mostest = 0;
|
||||
XP_S16 cmpVal;
|
||||
XP_Bool usePrev = engine->usePrev;
|
||||
XP_Bool foundEmpty = XP_FALSE;
|
||||
|
||||
if ( !engine->isRobot ) { /* robot doesn't ask for next hint.... */
|
||||
|
||||
mostest = -1;
|
||||
/* we're not interested if we've seen this */
|
||||
if ( CMPMOVES( posmove, &engine->miData.lastSeenMove ) >= 0 ) {
|
||||
lowest = -1;
|
||||
cmpVal = CMPMOVES( posmove, &engine->miData.lastSeenMove );
|
||||
if ( !usePrev && cmpVal >= 0 ) {
|
||||
/* XP_LOGF( "%s: dropping %d: higher than %d", __func__, */
|
||||
/* posmove->score, engine->miData.lastSeenMove.score ); */
|
||||
} else if ( usePrev && cmpVal <= 0 ) {
|
||||
/* XP_LOGF( "%s: dropping %d: lower than %d", __func__, */
|
||||
/* posmove->score, engine->miData.lastSeenMove.score ); */
|
||||
} else {
|
||||
XP_S16 i;
|
||||
/* terminate i at 1 because lowest starts at 0 */
|
||||
for ( lowest = NUM_SAVED_MOVES-1, i = lowest - 1; i >= 0; --i ) {
|
||||
/* Find the lowest value move and overwrite it. Note that
|
||||
XP_S16 ii;
|
||||
/* terminate i at 1 because mostest starts at 0 */
|
||||
for ( ii = 0; ii < NUM_SAVED_ENGINE_MOVES; ++ii ) {
|
||||
/* Find the mostest value move and overwrite it. Note that
|
||||
there might not be one, as all may have the same or higher
|
||||
scores and those that have the same score may compare
|
||||
higher.
|
||||
|
||||
<eeh> can't have this asssertion until I start noting the
|
||||
lowest saved score (setting miData.lowestSavedScore)
|
||||
mostest saved score (setting miData.mostestSavedScore)
|
||||
below. */
|
||||
/* 1/20/2001 I don't see that this assertion is valid. I
|
||||
simply don't understand why it isn't tripped all the time
|
||||
|
@ -1124,52 +1168,174 @@ saveMoveIfQualifies( EngineCtxt* engine, PossibleMove* posmove )
|
|||
/* || (engine->miData.savedMoves[i].score */
|
||||
/* <= posmove->score) ); */
|
||||
|
||||
if ( CMPMOVES( &engine->miData.savedMoves[lowest],
|
||||
&engine->miData.savedMoves[i] ) > 0 ) {
|
||||
lowest = i;
|
||||
if ( 0 == engine->miData.savedMoves[ii].score ) {
|
||||
foundEmpty = XP_TRUE;
|
||||
mostest = ii;
|
||||
break;
|
||||
} else if ( -1 == mostest ) {
|
||||
mostest = ii;
|
||||
} else {
|
||||
cmpVal = CMPMOVES( &engine->miData.savedMoves[mostest],
|
||||
&engine->miData.savedMoves[ii] );
|
||||
if ( !usePrev && cmpVal > 0 ) {
|
||||
mostest = ii;
|
||||
} else if ( usePrev && cmpVal < 0 ) {
|
||||
mostest = ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( lowest >= 0) {
|
||||
|
||||
while ( mostest >= 0 ) { /* while: so we can break */
|
||||
/* record the score we're dumping. No point in considering any scores
|
||||
lower than this for the rest of this round. */
|
||||
engine->miData.lowestSavedScore =
|
||||
engine->miData.savedMoves[lowest].score;
|
||||
/* engine->miData.lowestSavedScore = */
|
||||
/* engine->miData.savedMoves[lowest].score; */
|
||||
/* XP_DEBUGF( "lowestSavedScore now %d\n", */
|
||||
/* engine->miData.lowestSavedScore ); */
|
||||
if ( CMPMOVES( posmove, &engine->miData.savedMoves[lowest]) > 0 ) {
|
||||
XP_MEMCPY( &engine->miData.savedMoves[lowest], posmove,
|
||||
sizeof(engine->miData.savedMoves[lowest]) );
|
||||
/* XP_DEBUGF( "just saved move with score %d\n", */
|
||||
/* engine->miData.savedMoves[lowest].score ); */
|
||||
if ( foundEmpty ) {
|
||||
/* we're good */
|
||||
} else {
|
||||
cmpVal = CMPMOVES( posmove, &engine->miData.savedMoves[mostest]);
|
||||
if ( !usePrev && cmpVal <= 0 ) {
|
||||
break;
|
||||
} else if ( usePrev && cmpVal >= 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* XP_LOGF( "saving move with score %d at %d (replacing %d)\n", */
|
||||
/* posmove->score, mostest, */
|
||||
/* engine->miData.savedMoves[mostest].score ); */
|
||||
XP_MEMCPY( &engine->miData.savedMoves[mostest], posmove,
|
||||
sizeof(engine->miData.savedMoves[mostest]) );
|
||||
break;
|
||||
}
|
||||
} /* saveMoveIfQualifies */
|
||||
|
||||
static void
|
||||
set_search_limits( EngineCtxt* engine )
|
||||
{
|
||||
/* If we're going to be searching backwards we want our highest cached
|
||||
move as the limit; otherwise the lowest */
|
||||
if ( 0 < engine->miData.nInMoveCache ) {
|
||||
XP_U16 srcIndx = engine->usePrev
|
||||
? NUM_SAVED_ENGINE_MOVES-1 : engine->miData.bottom;
|
||||
XP_MEMCPY( &engine->miData.lastSeenMove,
|
||||
&engine->miData.savedMoves[srcIndx],
|
||||
sizeof(engine->miData.lastSeenMove) );
|
||||
XP_LOGF( "%s: saved limit move with score: %d", __func__,
|
||||
engine->miData.lastSeenMove.score );
|
||||
//engine->miData.lowestSavedScore = 0;
|
||||
} else {
|
||||
/* we're doing this for first time */
|
||||
engine_reset( engine );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_move_cache( EngineCtxt* engine )
|
||||
{
|
||||
XP_U16 nInMoveCache = NUM_SAVED_ENGINE_MOVES;
|
||||
XP_U16 ii;
|
||||
|
||||
for ( ii = 0; ii < NUM_SAVED_ENGINE_MOVES; ++ii ) {
|
||||
if ( 0 == engine->miData.savedMoves[ii].score ) {
|
||||
--nInMoveCache;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
engine->miData.nInMoveCache = nInMoveCache;
|
||||
engine->miData.bottom = NUM_SAVED_ENGINE_MOVES - nInMoveCache;
|
||||
|
||||
if ( engine->usePrev ) {
|
||||
engine->miData.curCacheIndex =
|
||||
NUM_SAVED_ENGINE_MOVES - nInMoveCache - 1;
|
||||
} else {
|
||||
engine->miData.curCacheIndex = NUM_SAVED_ENGINE_MOVES;
|
||||
}
|
||||
XP_LOGF( "%s: set curCacheIndex to %d", __func__,
|
||||
engine->miData.curCacheIndex );
|
||||
}
|
||||
|
||||
static PossibleMove*
|
||||
next_from_cache( EngineCtxt* engine )
|
||||
{
|
||||
PossibleMove* move;
|
||||
if ( move_cache_empty( engine ) ) {
|
||||
move = NULL;
|
||||
} else {
|
||||
if ( engine->usePrev ) {
|
||||
++engine->miData.curCacheIndex;
|
||||
} else {
|
||||
--engine->miData.curCacheIndex;
|
||||
}
|
||||
move = &engine->miData.savedMoves[engine->miData.curCacheIndex];
|
||||
XP_LOGF( "%s: curCacheIndex now %d", __func__,
|
||||
engine->miData.curCacheIndex );
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
move_cache_empty( const EngineCtxt* engine )
|
||||
{
|
||||
XP_Bool empty;
|
||||
const MoveIterationData* miData = &engine->miData;
|
||||
XP_LOGF( "%s: usePrev: %d; curCacheIndex: %d; nInMoveCache: %d",
|
||||
__func__, engine->usePrev, miData->curCacheIndex,
|
||||
miData->nInMoveCache );
|
||||
|
||||
if ( 0 == miData->nInMoveCache ) {
|
||||
empty = XP_TRUE;
|
||||
} else if ( engine->usePrev ) {
|
||||
empty = miData->curCacheIndex >= NUM_SAVED_ENGINE_MOVES - 1;
|
||||
} else {
|
||||
empty = miData->curCacheIndex <= miData->bottom;
|
||||
}
|
||||
LOG_RETURNF( "%d", empty );
|
||||
return empty;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
scoreQualifies( EngineCtxt* engine, XP_U16 score )
|
||||
{
|
||||
XP_Bool qualifies = XP_FALSE;
|
||||
XP_Bool usePrev = engine->usePrev;
|
||||
|
||||
if ( (score > engine->miData.lastSeenMove.score)
|
||||
|| (score > engine->targetScore)
|
||||
|| (score < engine->miData.lowestSavedScore) ) {
|
||||
/* do nothing */
|
||||
if ( score > engine->targetScore ) {
|
||||
/* drop it */
|
||||
} else if ( usePrev && score < engine->miData.lastSeenMove.score ) {
|
||||
/* drop it */
|
||||
} else if ( !usePrev && score > engine->miData.lastSeenMove.score
|
||||
/* || (score < engine->miData.lowestSavedScore) */ ) {
|
||||
/* drop it */
|
||||
} else {
|
||||
XP_S16 i;
|
||||
XP_S16 ii;
|
||||
PossibleMove* savedMoves = engine->miData.savedMoves;
|
||||
/* Look at each saved score, and return true as soon as one's found
|
||||
with a lower or equal score to this. <eeh> As an optimization,
|
||||
consider remembering what the lowest score is *once there are
|
||||
NUM_SAVED_MOVES moves in here* and doing a quick test on that. Or
|
||||
better, keeping the list in sorted order. */
|
||||
for ( i = engine->isRobot? 0: NUM_SAVED_MOVES-1; i >= 0; --i ) {
|
||||
if ( score >= engine->miData.savedMoves[i].score ) {
|
||||
NUM_SAVED_ENGINE_MOVES moves in here* and doing a quick test on
|
||||
that. Or better, keeping the list in sorted order. */
|
||||
for ( ii = 0, savedMoves = engine->miData.savedMoves;
|
||||
ii < NUM_SAVED_ENGINE_MOVES; ++ii, ++savedMoves ) {
|
||||
if ( savedMoves->score == 0 ) { /* empty slot */
|
||||
qualifies = XP_TRUE;
|
||||
} else if ( usePrev && score <= savedMoves->score ) {
|
||||
qualifies = XP_TRUE;
|
||||
break;
|
||||
} else if ( !usePrev && score >= savedMoves->score ) {
|
||||
qualifies = XP_TRUE;
|
||||
break;
|
||||
}
|
||||
if ( engine->isRobot ) { /* we look at only one for robot */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//XP_LOGF( "%s(%d)->%d", __func__, score, qualifies );
|
||||
return qualifies;
|
||||
} /* scoreQualifies */
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void engine_destroy( EngineCtxt* ctxt );
|
|||
#define NO_SCORE_LIMIT 10000 /* for targetScore */
|
||||
XP_Bool engine_findMove( EngineCtxt* ctxt, const ModelCtxt* model,
|
||||
const DictionaryCtxt* dict, const Tile* tiles,
|
||||
XP_U16 nTiles,
|
||||
XP_U16 nTiles, XP_Bool usePrev,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
const BdHintLimits* boardLimits,
|
||||
XP_Bool useTileLimits,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
|
@ -46,7 +47,7 @@ extern "C" {
|
|||
#define STREAM_VERS_41B4 0x02
|
||||
#define STREAM_VERS_405 0x01
|
||||
|
||||
#define CUR_STREAM_VERS STREAM_VERS_GAMESECONDS
|
||||
#define CUR_STREAM_VERS STREAM_VERS_NUNDONE
|
||||
|
||||
typedef struct LocalPlayer {
|
||||
XP_UCHAR* name;
|
||||
|
|
|
@ -70,7 +70,8 @@ static void buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
|
|||
MovePrintFuncPost mpfpo,
|
||||
void* closure );
|
||||
static void setPendingCounts( ModelCtxt* model, XP_S16 turn );
|
||||
static void loadPlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc );
|
||||
static void loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version,
|
||||
PlayerCtxt* pc );
|
||||
static void writePlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc );
|
||||
static XP_U16 model_getRecentPassCount( ModelCtxt* model );
|
||||
|
||||
|
@ -136,7 +137,7 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
|
|||
(MovePrintFuncPost)NULL, NULL );
|
||||
|
||||
for ( i = 0; i < model->nPlayers; ++i ) {
|
||||
loadPlayerCtxt( stream, &model->players[i] );
|
||||
loadPlayerCtxt( stream, version, &model->players[i] );
|
||||
setPendingCounts( model, i );
|
||||
invalidateScore( model, i );
|
||||
}
|
||||
|
@ -480,13 +481,14 @@ undoFromMoveInfo( ModelCtxt* model, XP_U16 turn, Tile blankTile, MoveInfo* mi )
|
|||
|
||||
setModelTileRaw( model, col, row, EMPTY_TILE );
|
||||
notifyBoardListeners( model, turn, col, row, XP_FALSE );
|
||||
--model->vol.nTilesOnBoard;
|
||||
|
||||
if ( IS_BLANK(tile) ) {
|
||||
tile = blankTile;
|
||||
}
|
||||
model_addPlayerTile( model, turn, -1, tile );
|
||||
}
|
||||
|
||||
XP_LOGF( "%s: %d tiles on board", __func__, model->vol.nTilesOnBoard );
|
||||
adjustScoreForUndone( model, mi, turn );
|
||||
} /* undoFromMoveInfo */
|
||||
|
||||
|
@ -842,9 +844,9 @@ model_trayContains( ModelCtxt* model, XP_S16 turn, Tile tile )
|
|||
} /* model_trayContains */
|
||||
|
||||
XP_U16
|
||||
model_getCurrentMoveCount( ModelCtxt* model, XP_S16 turn )
|
||||
model_getCurrentMoveCount( const ModelCtxt* model, XP_S16 turn )
|
||||
{
|
||||
PlayerCtxt* player;
|
||||
const PlayerCtxt* player;
|
||||
XP_ASSERT( turn >= 0 );
|
||||
player = &model->players[turn];
|
||||
return player->nPending;
|
||||
|
@ -989,6 +991,7 @@ model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col, XP_U16 row,
|
|||
invalLastMove( model );
|
||||
}
|
||||
|
||||
player->nUndone = 0;
|
||||
pt = &player->pendingTiles[player->nPending++];
|
||||
XP_ASSERT( player->nPending <= MAX_TRAY_TILES );
|
||||
|
||||
|
@ -1002,6 +1005,40 @@ model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col, XP_U16 row,
|
|||
notifyBoardListeners( model, turn, col, row, XP_TRUE );
|
||||
} /* model_moveTrayToBoard */
|
||||
|
||||
XP_Bool
|
||||
model_redoPendingTiles( ModelCtxt* model, XP_S16 turn )
|
||||
{
|
||||
XP_Bool changed = XP_FALSE;
|
||||
|
||||
PlayerCtxt* player = &model->players[turn];
|
||||
XP_U16 nUndone = player->nUndone;
|
||||
changed = nUndone > 0;
|
||||
if ( changed ) {
|
||||
PendingTile pendingTiles[nUndone];
|
||||
PendingTile* pt = pendingTiles;
|
||||
|
||||
XP_MEMCPY( pendingTiles, &player->pendingTiles[player->nPending],
|
||||
nUndone * sizeof(pendingTiles[0]) );
|
||||
|
||||
/* Now we have info about each tile, but don't know where in the
|
||||
tray they are. So find 'em. */
|
||||
for ( pt = pendingTiles; nUndone-- > 0; ++pt ) {
|
||||
Tile tile = pt->tile;
|
||||
XP_Bool isBlank = 0 != (tile & TILE_BLANK_BIT);
|
||||
XP_S16 foundAt;
|
||||
|
||||
if ( isBlank ) {
|
||||
tile = dict_getBlankTile( model->vol.dict );
|
||||
}
|
||||
foundAt = model_trayContains( model, turn, tile );
|
||||
XP_ASSERT( foundAt >= 0 );
|
||||
model_moveTrayToBoard( model, turn, pt->col, pt->row,
|
||||
foundAt, pt->tile & ~TILE_BLANK_BIT );
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
||||
XP_U16 col, XP_U16 row, XP_U16 trayOffset )
|
||||
|
@ -1024,6 +1061,7 @@ model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
|||
/* if we're called from putBackOtherPlayersTiles there may be nothing
|
||||
here */
|
||||
if ( index < player->nPending ) {
|
||||
PendingTile tmpPending;
|
||||
decrPendingTileCountAt( model, col, row );
|
||||
notifyBoardListeners( model, turn, col, row, XP_FALSE );
|
||||
|
||||
|
@ -1035,9 +1073,14 @@ model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
|||
model_addPlayerTile( model, turn, trayOffset, tile );
|
||||
|
||||
--player->nPending;
|
||||
tmpPending = player->pendingTiles[index];
|
||||
for ( i = index; i < player->nPending; ++i ) {
|
||||
player->pendingTiles[i] = player->pendingTiles[i+1];
|
||||
}
|
||||
player->pendingTiles[player->nPending] = tmpPending;
|
||||
|
||||
++player->nUndone;
|
||||
//XP_LOGF( "%s: nUndone(%d): %d", __func__, turn, player->nUndone );
|
||||
|
||||
if ( player->nPending == 0 ) {
|
||||
invalLastMove( model );
|
||||
|
@ -1104,6 +1147,30 @@ model_getNMoves( const ModelCtxt* model )
|
|||
return result;
|
||||
}
|
||||
|
||||
XP_U16
|
||||
model_visTileCount( const ModelCtxt* model, XP_U16 turn, XP_Bool trayVisible )
|
||||
{
|
||||
XP_U16 count = model->vol.nTilesOnBoard;
|
||||
if ( trayVisible ) {
|
||||
count += model_getCurrentMoveCount( model, turn );
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
model_canShuffle( const ModelCtxt* model, XP_U16 turn, XP_Bool trayVisible )
|
||||
{
|
||||
return trayVisible
|
||||
&& model_getPlayerTiles( model, turn )->nTiles > 1;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
model_canTogglePending( const ModelCtxt* model, XP_U16 turn )
|
||||
{
|
||||
const PlayerCtxt* player = &model->players[turn];
|
||||
return 0 < player->nPending || 0 < player->nUndone;
|
||||
}
|
||||
|
||||
static void
|
||||
incrPendingTileCountAt( ModelCtxt* model, XP_U16 col, XP_U16 row )
|
||||
{
|
||||
|
@ -1229,6 +1296,8 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
|||
setModelTileRaw( model, col, row, tile );
|
||||
|
||||
notifyBoardListeners( model, turn, col, row, XP_FALSE );
|
||||
|
||||
++model->vol.nTilesOnBoard;
|
||||
}
|
||||
|
||||
(void)getCurrentMoveScoreIfLegal( model, turn, stream, &score );
|
||||
|
@ -1241,12 +1310,14 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
|
|||
}
|
||||
|
||||
player->nPending = 0;
|
||||
player->nUndone = 0;
|
||||
|
||||
newTilesP = newTiles->tiles;
|
||||
while ( nTiles-- ) {
|
||||
model_addPlayerTile( model, turn, -1, *newTilesP++ );
|
||||
}
|
||||
|
||||
XP_LOGF( "%s: %d tiles on board", __func__, model->vol.nTilesOnBoard );
|
||||
return score;
|
||||
} /* commitTurn */
|
||||
|
||||
|
@ -1303,9 +1374,9 @@ model_getPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
|||
} /* model_getPlayerTile */
|
||||
|
||||
const TrayTileSet*
|
||||
model_getPlayerTiles( ModelCtxt* model, XP_S16 turn )
|
||||
model_getPlayerTiles( const ModelCtxt* model, XP_S16 turn )
|
||||
{
|
||||
PlayerCtxt* player = &model->players[turn];
|
||||
const PlayerCtxt* player = &model->players[turn];
|
||||
|
||||
return (const TrayTileSet*)&player->trayTiles;
|
||||
} /* model_getPlayerTile */
|
||||
|
@ -1823,23 +1894,29 @@ model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
|||
} /* model_getPlayersLastScore */
|
||||
|
||||
static void
|
||||
loadPlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc )
|
||||
loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc )
|
||||
{
|
||||
XP_U16 i;
|
||||
PendingTile* pt;
|
||||
XP_U16 nTiles;
|
||||
|
||||
pc->curMoveValid = stream_getBits( stream, 1 );
|
||||
|
||||
traySetFromStream( stream, &pc->trayTiles );
|
||||
|
||||
pc->nPending = (XP_U8)stream_getBits( stream, NTILES_NBITS );
|
||||
if ( STREAM_VERS_NUNDONE <= version ) {
|
||||
pc->nUndone = (XP_U8)stream_getBits( stream, NTILES_NBITS );
|
||||
} else {
|
||||
XP_ASSERT( 0 == pc->nUndone );
|
||||
}
|
||||
|
||||
for ( i = 0; i < pc->nPending; ++i ) {
|
||||
PendingTile* pt = &pc->pendingTiles[i];
|
||||
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 );
|
||||
|
||||
nBits = (stream_getVersion( stream ) <= STREAM_VERS_RELAY) ? 6 : 7;
|
||||
nBits = (version <= STREAM_VERS_RELAY) ? 6 : 7;
|
||||
pt->tile = (Tile)stream_getBits( stream, nBits );
|
||||
}
|
||||
|
||||
|
@ -1848,21 +1925,22 @@ loadPlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc )
|
|||
static void
|
||||
writePlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_U16 nTiles;
|
||||
PendingTile* pt;
|
||||
|
||||
stream_putBits( stream, 1, pc->curMoveValid );
|
||||
|
||||
traySetToStream( stream, &pc->trayTiles );
|
||||
|
||||
stream_putBits( stream, NTILES_NBITS, pc->nPending );
|
||||
stream_putBits( stream, NTILES_NBITS, pc->nUndone );
|
||||
|
||||
for ( i = 0; i < pc->nPending; ++i ) {
|
||||
PendingTile* pt = &pc->pendingTiles[i];
|
||||
nTiles = pc->nPending + pc->nUndone;
|
||||
for ( pt = pc->pendingTiles; nTiles-- > 0; ++pt ) {
|
||||
stream_putBits( stream, NUMCOLS_NBITS, pt->col );
|
||||
stream_putBits( stream, NUMCOLS_NBITS, pt->row );
|
||||
stream_putBits( stream, 7, pt->tile );
|
||||
}
|
||||
|
||||
} /* writePlayerCtxt */
|
||||
|
||||
#ifdef CPLUS
|
||||
|
|
|
@ -137,7 +137,7 @@ void model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur,
|
|||
|
||||
/* As an optimization, return a pointer to the model's array of tiles for a
|
||||
player. Don't even think about modifying the array!!!! */
|
||||
const TrayTileSet* model_getPlayerTiles( ModelCtxt* model, XP_S16 turn );
|
||||
const TrayTileSet* model_getPlayerTiles( const ModelCtxt* model, XP_S16 turn );
|
||||
|
||||
void model_sortTiles( ModelCtxt* model, XP_S16 turn );
|
||||
XP_U16 model_getNumTilesInTray( ModelCtxt* model, XP_S16 turn );
|
||||
|
@ -148,6 +148,8 @@ void model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col,
|
|||
XP_U16 row, XP_S16 tileIndex, Tile blankFace );
|
||||
XP_Bool model_moveTileOnBoard( ModelCtxt* model, XP_S16 turn, XP_U16 colCur,
|
||||
XP_U16 rowCur, XP_U16 colNew, XP_U16 rowNew );
|
||||
XP_Bool model_redoPendingTiles( ModelCtxt* model, XP_S16 turn );
|
||||
|
||||
|
||||
XP_S16 model_trayContains( ModelCtxt* model, XP_S16 turn, Tile tile );
|
||||
|
||||
|
@ -160,7 +162,7 @@ XP_U16 model_numCols( const ModelCtxt* model );
|
|||
void model_addToCurrentMove( ModelCtxt* model, XP_S16 turn,
|
||||
XP_U16 col, XP_U16 row,
|
||||
Tile tile, XP_Bool isBlank );
|
||||
XP_U16 model_getCurrentMoveCount( ModelCtxt* model, XP_S16 turn );
|
||||
XP_U16 model_getCurrentMoveCount( const ModelCtxt* model, XP_S16 turn );
|
||||
|
||||
void model_getCurrentMoveTile( ModelCtxt* model, XP_S16 turn, XP_S16* index,
|
||||
Tile* tile, XP_U16* col, XP_U16* row,
|
||||
|
@ -190,6 +192,13 @@ void model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
|
|||
void model_resetCurrentTurn( ModelCtxt* model, XP_S16 turn );
|
||||
XP_S16 model_getNMoves( const ModelCtxt* model );
|
||||
|
||||
/* Are there two or more tiles visible */
|
||||
XP_U16 model_visTileCount( const ModelCtxt* model, XP_U16 turn,
|
||||
XP_Bool trayVisible );
|
||||
XP_Bool model_canShuffle( const ModelCtxt* model, XP_U16 turn,
|
||||
XP_Bool trayVisible );
|
||||
XP_Bool model_canTogglePending( const ModelCtxt* model, XP_U16 turn );
|
||||
|
||||
/********************* notification ********************/
|
||||
typedef void (*BoardListener)(void* data, XP_U16 turn, XP_U16 col,
|
||||
XP_U16 row, XP_Bool added );
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct PlayerCtxt {
|
|||
XP_Bool curMoveValid;
|
||||
TrayTileSet trayTiles;
|
||||
XP_U8 nPending; /* still in tray but "on board" */
|
||||
XP_U8 nUndone; /* tiles above nPending we can reuse */
|
||||
PendingTile pendingTiles[MAX_TRAY_TILES];
|
||||
} PlayerCtxt;
|
||||
|
||||
|
@ -53,6 +54,7 @@ typedef struct ModelVolatiles {
|
|||
void* trayListenerData;
|
||||
DictListener dictListenerFunc;
|
||||
void* dictListenerData;
|
||||
XP_U16 nTilesOnBoard;
|
||||
MPSLOT
|
||||
} ModelVolatiles;
|
||||
|
||||
|
|
|
@ -324,7 +324,7 @@ handlePenUpScore( BoardCtxt* board, XP_U16 xx, XP_U16 yy )
|
|||
if ( rectNum == CURSOR_LOC_REM ) {
|
||||
util_remSelected( board->util );
|
||||
} else if ( --rectNum >= 0 ) {
|
||||
board_selectPlayer( board, rectNum );
|
||||
board_selectPlayer( board, rectNum, board->allowPeek );
|
||||
} else {
|
||||
result = XP_FALSE;
|
||||
}
|
||||
|
|
|
@ -676,7 +676,7 @@ makeRobotMove( ServerCtxt* server )
|
|||
XP_ASSERT( !!server_getEngineFor( server, turn ) );
|
||||
finished = engine_findMove( server_getEngineFor( server, turn ),
|
||||
model, model_getDictionary( model ),
|
||||
tileSet->tiles, tileSet->nTiles,
|
||||
tileSet->tiles, tileSet->nTiles, XP_FALSE,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
NULL, XP_FALSE,
|
||||
#endif
|
||||
|
|
|
@ -544,7 +544,7 @@ handleHint( CursesAppGlobals* globals )
|
|||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
XP_FALSE,
|
||||
#endif
|
||||
&redo );
|
||||
XP_FALSE, &redo );
|
||||
return XP_TRUE;
|
||||
} /* handleHint */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
||||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
|
||||
/*
|
||||
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
|
@ -68,6 +68,7 @@ static void setCtrlsForTray( GtkAppGlobals* globals );
|
|||
static void new_game( GtkWidget* widget, GtkAppGlobals* globals );
|
||||
static void new_game_impl( GtkAppGlobals* globals, XP_Bool fireConnDlg );
|
||||
static void setZoomButtons( GtkAppGlobals* globals, XP_Bool* inOut );
|
||||
static void disenable_buttons( GtkAppGlobals* globals );
|
||||
|
||||
|
||||
#define GTK_TRAY_HT_ROWS 3
|
||||
|
@ -128,6 +129,7 @@ button_press_event( GtkWidget* XP_UNUSED(widget), GdkEventButton *event,
|
|||
event->x, event->y, &handled );
|
||||
if ( redraw ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
disenable_buttons( globals );
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
@ -146,6 +148,7 @@ motion_notify_event( GtkWidget* XP_UNUSED(widget), GdkEventMotion *event,
|
|||
event->y );
|
||||
if ( handled ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
disenable_buttons( globals );
|
||||
}
|
||||
} else {
|
||||
handled = XP_FALSE;
|
||||
|
@ -168,6 +171,7 @@ button_release_event( GtkWidget* XP_UNUSED(widget), GdkEventMotion *event,
|
|||
event->y );
|
||||
if ( redraw ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
disenable_buttons( globals );
|
||||
}
|
||||
globals->mouseDown = XP_FALSE;
|
||||
}
|
||||
|
@ -991,6 +995,16 @@ makeMenus( GtkAppGlobals* globals, int XP_UNUSED(argc),
|
|||
return menubar;
|
||||
} /* makeMenus */
|
||||
|
||||
static void
|
||||
disenable_buttons( GtkAppGlobals* globals )
|
||||
{
|
||||
XP_Bool canFlip = 1 < board_visTileCount( globals->cGlobals.game.board );
|
||||
gtk_widget_set_sensitive( globals->flip_button, canFlip );
|
||||
|
||||
XP_Bool canToggle = board_canTogglePending( globals->cGlobals.game.board );
|
||||
gtk_widget_set_sensitive( globals->toggle_undo_button, canToggle );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_flip_button( GtkWidget* XP_UNUSED(widget), gpointer _globals )
|
||||
{
|
||||
|
@ -1012,18 +1026,31 @@ handle_value_button( GtkWidget* XP_UNUSED(widget), gpointer closure )
|
|||
} /* handle_value_button */
|
||||
|
||||
static void
|
||||
handle_hint_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||
handle_hint_button( GtkAppGlobals* globals, XP_Bool prev )
|
||||
{
|
||||
XP_Bool redo;
|
||||
if ( board_requestHint( globals->cGlobals.game.board,
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
XP_FALSE,
|
||||
#endif
|
||||
&redo ) ) {
|
||||
prev, &redo ) ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
disenable_buttons( globals );
|
||||
}
|
||||
} /* handle_hint_button */
|
||||
|
||||
static void
|
||||
handle_prevhint_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||
{
|
||||
handle_hint_button( globals, XP_TRUE );
|
||||
} /* handle_prevhint_button */
|
||||
|
||||
static void
|
||||
handle_nexthint_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||
{
|
||||
handle_hint_button( globals, XP_FALSE );
|
||||
} /* handle_nexthint_button */
|
||||
|
||||
static void
|
||||
handle_nhint_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||
{
|
||||
|
@ -1034,7 +1061,7 @@ handle_nhint_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
|||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
XP_TRUE,
|
||||
#endif
|
||||
&redo ) ) {
|
||||
XP_FALSE, &redo ) ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
}
|
||||
} /* handle_nhint_button */
|
||||
|
@ -1071,6 +1098,16 @@ handle_redo_button( GtkWidget* XP_UNUSED(widget),
|
|||
{
|
||||
} /* handle_redo_button */
|
||||
|
||||
static void
|
||||
handle_toggle_undo( GtkWidget* XP_UNUSED(widget),
|
||||
GtkAppGlobals* globals )
|
||||
{
|
||||
BoardCtxt* board = globals->cGlobals.game.board;
|
||||
if ( board_redoReplacedTiles( board ) || board_replaceTiles( board ) ) {
|
||||
board_draw( board );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_trade_button( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||
{
|
||||
|
@ -1670,13 +1707,17 @@ makeVerticalBar( GtkAppGlobals* globals, GtkWidget* XP_UNUSED(window) )
|
|||
button = makeShowButtonFromBitmap( globals, "../flip.xpm", "f",
|
||||
G_CALLBACK(handle_flip_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
globals->flip_button = button;
|
||||
|
||||
button = makeShowButtonFromBitmap( globals, "../value.xpm", "v",
|
||||
G_CALLBACK(handle_value_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
|
||||
button = makeShowButtonFromBitmap( globals, "../hint.xpm", "?",
|
||||
G_CALLBACK(handle_hint_button) );
|
||||
button = makeShowButtonFromBitmap( globals, "../hint.xpm", "?-",
|
||||
G_CALLBACK(handle_prevhint_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
button = makeShowButtonFromBitmap( globals, "../hint.xpm", "?+",
|
||||
G_CALLBACK(handle_nexthint_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
|
||||
button = makeShowButtonFromBitmap( globals, "../hintNum.xpm", "n",
|
||||
|
@ -1688,13 +1729,18 @@ makeVerticalBar( GtkAppGlobals* globals, GtkWidget* XP_UNUSED(window) )
|
|||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
|
||||
/* undo and redo buttons */
|
||||
button = makeShowButtonFromBitmap( globals, "../undo.xpm", "u",
|
||||
button = makeShowButtonFromBitmap( globals, "../undo.xpm", "U",
|
||||
G_CALLBACK(handle_undo_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
button = makeShowButtonFromBitmap( globals, "../redo.xpm", "r",
|
||||
button = makeShowButtonFromBitmap( globals, "../redo.xpm", "R",
|
||||
G_CALLBACK(handle_redo_button) );
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
|
||||
button = makeShowButtonFromBitmap( globals, "", "u/r",
|
||||
G_CALLBACK(handle_toggle_undo) );
|
||||
globals->toggle_undo_button = button;
|
||||
gtk_box_pack_start( GTK_BOX(vbox), button, FALSE, TRUE, 0 );
|
||||
|
||||
/* the four buttons that on palm are beside the tray */
|
||||
button = makeShowButtonFromBitmap( globals, "../juggle.xpm", "j",
|
||||
G_CALLBACK(handle_juggle_button) );
|
||||
|
@ -2058,6 +2104,7 @@ gtkmain( LaunchParams* params, int argc, char *argv[] )
|
|||
globals.cp.skipCommitConfirm = params->skipCommitConfirm;
|
||||
globals.cp.sortNewTiles = params->sortNewTiles;
|
||||
globals.cp.showColors = params->showColors;
|
||||
globals.cp.allowPeek = params->allowPeek;
|
||||
globals.cp.showRobotScores = params->showRobotScores;
|
||||
#ifdef XWFEATURE_SLOW_ROBOT
|
||||
globals.cp.robotThinkMin = params->robotThinkMin;
|
||||
|
|
|
@ -87,8 +87,10 @@ typedef struct GtkAppGlobals {
|
|||
/* GdkPixmap* pixmap; */
|
||||
GtkWidget* drawing_area;
|
||||
|
||||
GtkWidget* flip_button;
|
||||
GtkWidget* zoomin_button;
|
||||
GtkWidget* zoomout_button;
|
||||
GtkWidget* toggle_undo_button;
|
||||
|
||||
EngineCtxt* engine;
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ usage( char* appName, char* msg )
|
|||
"\t [-k] # ask for parameters via \"new games\" dlg\n"
|
||||
"\t [-h numRowsHidden] \n"
|
||||
# ifdef XWFEATURE_SEARCHLIMIT
|
||||
"\t [-I] # don't support hint rect dragging\n"
|
||||
"\t [-I] # support hint rect dragging\n"
|
||||
# endif
|
||||
#endif
|
||||
"\t [-f file] # use this file to save/load game\n"
|
||||
|
@ -788,10 +788,11 @@ main( int argc, char** argv )
|
|||
mainParams.nHidden = 0;
|
||||
mainParams.needsNewGame = XP_FALSE;
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
mainParams.allowHintRect = XP_TRUE;
|
||||
mainParams.allowHintRect = XP_FALSE;
|
||||
#endif
|
||||
mainParams.skipCommitConfirm = XP_TRUE;
|
||||
mainParams.showColors = XP_TRUE;
|
||||
mainParams.allowPeek = XP_TRUE;
|
||||
|
||||
/* serverName = mainParams.info.clientInfo.serverName = "localhost"; */
|
||||
|
||||
|
@ -869,7 +870,7 @@ main( int argc, char** argv )
|
|||
break;
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
case 'I':
|
||||
mainParams.allowHintRect = XP_FALSE;
|
||||
mainParams.allowHintRect = XP_TRUE;
|
||||
break;
|
||||
#endif
|
||||
case 'K':
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct LaunchParams {
|
|||
XP_Bool verticalScore;
|
||||
XP_Bool hideValues;
|
||||
XP_Bool showColors;
|
||||
XP_Bool allowPeek;
|
||||
XP_Bool sortNewTiles;
|
||||
XP_Bool skipCommitConfirm;
|
||||
XP_Bool needsNewGame;
|
||||
|
|
|
@ -762,14 +762,21 @@ CookieRef::increasePlayerCounts( const CRefEvent* evt, bool reconn )
|
|||
if ( reconn ) {
|
||||
if ( nPlayersS > 0 ) {
|
||||
if ( 0 != m_nPlayersSought ) {
|
||||
logf( XW_LOGERROR,
|
||||
"already have m_nPlayersSought: %d but new value %d",
|
||||
m_nPlayersSought, nPlayersS );
|
||||
goto drop;
|
||||
}
|
||||
m_nPlayersSought = nPlayersS;
|
||||
}
|
||||
m_nPlayersHere += nPlayersH;
|
||||
if ( 0 != m_nPlayersSought && m_nPlayersHere > m_nPlayersSought ) {
|
||||
if ( 0 != m_nPlayersSought &&
|
||||
m_nPlayersHere + nPlayersH > m_nPlayersSought ) {
|
||||
logf( XW_LOGERROR, "too many new players provided: %d > %d",
|
||||
m_nPlayersHere + nPlayersH, m_nPlayersSought );
|
||||
goto drop;
|
||||
}
|
||||
|
||||
m_nPlayersHere += nPlayersH;
|
||||
if ( m_nPlayersHere == m_nPlayersSought ) {
|
||||
newevt.type = XWE_ALLHERE;
|
||||
} else {
|
||||
|
@ -777,8 +784,11 @@ CookieRef::increasePlayerCounts( const CRefEvent* evt, bool reconn )
|
|||
}
|
||||
addHost = true;
|
||||
} else if ( nPlayersS > 0 ) { /* a host; init values */
|
||||
assert( m_nPlayersSought == 0 );
|
||||
assert( m_nPlayersHere == 0 );
|
||||
if ( m_nPlayersSought != 0 || m_nPlayersHere != 0 ) {
|
||||
logf( XW_LOGERROR, "cref in bad state: m_nPlayersSought: %d; "
|
||||
"m_nPlayersHere: %d", m_nPlayersSought, m_nPlayersHere );
|
||||
goto drop;
|
||||
}
|
||||
m_nPlayersHere = nPlayersH;
|
||||
m_nPlayersSought = nPlayersS;
|
||||
addHost = true;
|
||||
|
|