mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-03 23:04:08 +01:00
toward making tile picking work through rotations
Make face-up tile picker util method return void and add mechanism for passing in selected tiles asynchronously, as has been done recently with the rest of the once-blocking util callbacks. Works perfectly in the gtk case. Likely crashes in curses (if picking face-up option is on.) In java all the callbacks are there but rather than put up a UI we pretend the user says "pick 'em for me" each time. Putting up a UI is next.
This commit is contained in:
parent
70b3aaa263
commit
6e5973c55b
19 changed files with 385 additions and 131 deletions
|
@ -1869,16 +1869,32 @@ public class BoardDelegate extends DelegateBase
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int userPickTileTray( int playerNum, String[] texts,
|
public void informNeedPickTiles( final boolean isInitial,
|
||||||
String[] curTiles, int nPicked )
|
final int playerNum, int nToPick,
|
||||||
|
String[] texts, int[] counts )
|
||||||
{
|
{
|
||||||
String curTilesStr = TextUtils.join( ", ", curTiles );
|
post( new Runnable() {
|
||||||
boolean canUndoTiles = 0 < nPicked;
|
@Override
|
||||||
waitBlockingDialog( DlgID.PICK_TILE_REQUESTTRAY_BLK,
|
public void run() {
|
||||||
UtilCtxt.PICKER_PICKALL, texts, curTilesStr,
|
int[] noNewTiles = new int[0];
|
||||||
canUndoTiles );
|
if ( isInitial ) {
|
||||||
return m_resultCode;
|
handleViaThread( JNICmd.CMD_TILES_PICKED, playerNum, noNewTiles );
|
||||||
|
} else {
|
||||||
|
handleViaThread( JNICmd.CMD_COMMIT, true, true, noNewTiles );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
// public int userPickTileTray( int playerNum, String[] texts,
|
||||||
|
// String[] curTiles, int nPicked )
|
||||||
|
// {
|
||||||
|
// String curTilesStr = TextUtils.join( ", ", curTiles );
|
||||||
|
// boolean canUndoTiles = 0 < nPicked;
|
||||||
|
// waitBlockingDialog( DlgID.PICK_TILE_REQUESTTRAY_BLK,
|
||||||
|
// UtilCtxt.PICKER_PICKALL, texts, curTilesStr,
|
||||||
|
// canUndoTiles );
|
||||||
|
// return m_resultCode;
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informNeedPassword( int player, String name )
|
public void informNeedPassword( int player, String name )
|
||||||
|
|
|
@ -72,6 +72,7 @@ public class JNIThread extends Thread {
|
||||||
CMD_KEYUP,
|
CMD_KEYUP,
|
||||||
CMD_TIMER_FIRED,
|
CMD_TIMER_FIRED,
|
||||||
CMD_COMMIT,
|
CMD_COMMIT,
|
||||||
|
CMD_TILES_PICKED,
|
||||||
CMD_JUGGLE,
|
CMD_JUGGLE,
|
||||||
CMD_FLIP,
|
CMD_FLIP,
|
||||||
CMD_TOGGLE_TRAY,
|
CMD_TOGGLE_TRAY,
|
||||||
|
@ -552,9 +553,17 @@ public class JNIThread extends Thread {
|
||||||
? false : (Boolean)args[0];
|
? false : (Boolean)args[0];
|
||||||
boolean turnConfirmed = args.length < 2
|
boolean turnConfirmed = args.length < 2
|
||||||
? false : (Boolean)args[1];
|
? false : (Boolean)args[1];
|
||||||
|
int[] newTiles = args.length < 3 ? null : (int[])args[2];
|
||||||
draw = XwJNI.board_commitTurn( m_jniGamePtr, phoniesConfirmed,
|
draw = XwJNI.board_commitTurn( m_jniGamePtr, phoniesConfirmed,
|
||||||
turnConfirmed );
|
turnConfirmed, newTiles );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_TILES_PICKED:
|
||||||
|
int playerNum = (Integer)args[0];
|
||||||
|
int[] tiles = (int[])args[1];
|
||||||
|
XwJNI.server_tilesPicked( m_jniGamePtr, playerNum, tiles );
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_JUGGLE:
|
case CMD_JUGGLE:
|
||||||
draw = XwJNI.board_juggleTray( m_jniGamePtr );
|
draw = XwJNI.board_juggleTray( m_jniGamePtr );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,8 +38,9 @@ public interface UtilCtxt {
|
||||||
public static final int PICKER_BACKUP = -2;
|
public static final int PICKER_BACKUP = -2;
|
||||||
|
|
||||||
void notifyPickTileBlank( int playerNum, int col, int row, String[] texts );
|
void notifyPickTileBlank( int playerNum, int col, int row, String[] texts );
|
||||||
int userPickTileTray( int playerNum, String[] tiles,
|
|
||||||
String[] curTiles, int nPicked );
|
void informNeedPickTiles( boolean isInitial, int playerNum, int nToPick,
|
||||||
|
String[] texts, int[] counts );
|
||||||
|
|
||||||
void informNeedPassword( int player, String name );
|
void informNeedPassword( int player, String name );
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,10 @@ public class UtilCtxtImpl implements UtilCtxt {
|
||||||
subclassOverride( "userPickTileBlank" );
|
subclassOverride( "userPickTileBlank" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int userPickTileTray( int playerNum, String[] texts,
|
public void informNeedPickTiles( boolean isInitial, int playerNum, int nToPick,
|
||||||
String[] curTiles, int nPicked )
|
String[] texts, int[] counts )
|
||||||
{
|
{
|
||||||
subclassOverride( "userPickTileTray" );
|
subclassOverride( "informNeedPickTiles" );
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void informNeedPassword( int player, String name )
|
public void informNeedPassword( int player, String name )
|
||||||
|
|
|
@ -300,7 +300,8 @@ public class XwJNI {
|
||||||
public static native boolean board_toggle_showValues( GamePtr gamePtr );
|
public static native boolean board_toggle_showValues( GamePtr gamePtr );
|
||||||
public static native boolean board_commitTurn( GamePtr gamePtr,
|
public static native boolean board_commitTurn( GamePtr gamePtr,
|
||||||
boolean phoniesConfirmed,
|
boolean phoniesConfirmed,
|
||||||
boolean turnConfirmed );
|
boolean turnConfirmed,
|
||||||
|
int[] newTiles );
|
||||||
|
|
||||||
public static native boolean board_flip( GamePtr gamePtr );
|
public static native boolean board_flip( GamePtr gamePtr );
|
||||||
public static native boolean board_replaceTiles( GamePtr gamePtr );
|
public static native boolean board_replaceTiles( GamePtr gamePtr );
|
||||||
|
@ -358,6 +359,8 @@ public class XwJNI {
|
||||||
public static native void server_reset( GamePtr gamePtr );
|
public static native void server_reset( GamePtr gamePtr );
|
||||||
public static native void server_handleUndo( GamePtr gamePtr );
|
public static native void server_handleUndo( GamePtr gamePtr );
|
||||||
public static native boolean server_do( GamePtr gamePtr );
|
public static native boolean server_do( GamePtr gamePtr );
|
||||||
|
public static native void server_tilesPicked( GamePtr gamePtr, int player, int[] tiles );
|
||||||
|
|
||||||
public static native String server_formatDictCounts( GamePtr gamePtr, int nCols );
|
public static native String server_formatDictCounts( GamePtr gamePtr, int nCols );
|
||||||
public static native boolean server_getGameIsOver( GamePtr gamePtr );
|
public static native boolean server_getGameIsOver( GamePtr gamePtr );
|
||||||
public static native String server_writeFinalScores( GamePtr gamePtr );
|
public static native String server_writeFinalScores( GamePtr gamePtr );
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*-mode: C; compile-command: "cd ..; ../scripts/ndkbuild.sh -j3"; -*- */
|
/* -*-mode: C; compile-command: "find-and-gradle.sh insXwdDeb"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
|
/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2014 by Eric House (xwords@eehouse.org). All rights
|
* Copyright 2001 - 2017 by Eric House (xwords@eehouse.org). All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -162,24 +162,23 @@ and_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||||
UTIL_CBK_TAIL();
|
UTIL_CBK_TAIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
static XP_S16
|
static void
|
||||||
and_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
|
and_util_informNeedPickTiles( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||||
XP_U16 playerNum, const XP_UCHAR** tileFaces,
|
XP_U16 player, XP_U16 nToPick,
|
||||||
XP_U16 nTiles )
|
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||||
|
const XP_U16* counts )
|
||||||
{
|
{
|
||||||
XP_S16 result = -1;
|
UTIL_CBK_HEADER("informNeedPickTiles",
|
||||||
UTIL_CBK_HEADER("userPickTileTray",
|
"(ZII[Ljava/lang/String;[I)V" );
|
||||||
"(I[Ljava/lang/String;[Ljava/lang/String;I)I" );
|
jobject jtexts = makeStringArray( env, nFaces, faces );
|
||||||
jobject jtexts = makeStringArray( env, nTiles, tileFaces );
|
jobject jcounts = makeIntArray( env, nFaces, counts );
|
||||||
jobject jcurtiles = makeStringArray( env, pi->nCurTiles, pi->curTiles );
|
|
||||||
result = (*env)->CallIntMethod( env, util->jutil, mid,
|
(*env)->CallVoidMethod( env, util->jutil, mid, isInitial, player,
|
||||||
playerNum, jtexts, jcurtiles,
|
nToPick, jtexts, jcounts );
|
||||||
pi->thisPick );
|
|
||||||
deleteLocalRefs( env, jtexts, jcurtiles, DELETE_NO_REF );
|
deleteLocalRefs( env, jtexts, jcounts, DELETE_NO_REF );
|
||||||
|
|
||||||
UTIL_CBK_TAIL();
|
UTIL_CBK_TAIL();
|
||||||
return result;
|
} /* and_util_informNeedPickTiles */
|
||||||
} /* and_util_userPickTile */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
and_util_informNeedPassword( XW_UtilCtxt* uc, XP_U16 player,
|
and_util_informNeedPassword( XW_UtilCtxt* uc, XP_U16 player,
|
||||||
|
@ -707,7 +706,7 @@ makeUtil( MPFORMAL EnvThreadInfo* ti, jobject jutil, CurGameInfo* gi,
|
||||||
SET_PROC(notifyMove);
|
SET_PROC(notifyMove);
|
||||||
SET_PROC(notifyTrade);
|
SET_PROC(notifyTrade);
|
||||||
SET_PROC(notifyPickTileBlank);
|
SET_PROC(notifyPickTileBlank);
|
||||||
SET_PROC(userPickTileTray);
|
SET_PROC(informNeedPickTiles);
|
||||||
SET_PROC(informNeedPassword);
|
SET_PROC(informNeedPassword);
|
||||||
SET_PROC(trayHiddenChange);
|
SET_PROC(trayHiddenChange);
|
||||||
SET_PROC(yOffsetChange);
|
SET_PROC(yOffsetChange);
|
||||||
|
|
|
@ -220,6 +220,21 @@ envForMe( EnvThreadInfo* ti, const char* caller )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tilesArrayToTileSet( JNIEnv* env, jintArray jtiles, TrayTileSet* tset )
|
||||||
|
{
|
||||||
|
if ( jtiles != NULL ) {
|
||||||
|
jsize nTiles = (*env)->GetArrayLength( env, jtiles );
|
||||||
|
int tmp[MAX_TRAY_TILES];
|
||||||
|
getIntsFromArray( env, tmp, jtiles, nTiles, XP_FALSE );
|
||||||
|
|
||||||
|
tset->nTiles = nTiles;
|
||||||
|
for ( int ii = 0; ii < nTiles; ++ii ) {
|
||||||
|
tset->tiles[ii] = tmp[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GAMEPTR_IS_OBJECT
|
#ifdef GAMEPTR_IS_OBJECT
|
||||||
static JNIState*
|
static JNIState*
|
||||||
getState( JNIEnv* env, GamePtrType gamePtr )
|
getState( JNIEnv* env, GamePtrType gamePtr )
|
||||||
|
@ -1282,13 +1297,21 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1toggle_1showValues
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1commitTurn
|
Java_org_eehouse_android_xw4_jni_XwJNI_board_1commitTurn
|
||||||
(JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean phoniesConfirmed,
|
( JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean phoniesConfirmed,
|
||||||
jboolean turnConfirmed)
|
jboolean turnConfirmed, jintArray jNewTiles )
|
||||||
{
|
{
|
||||||
jboolean result;
|
jboolean result;
|
||||||
XWJNI_START();
|
XWJNI_START();
|
||||||
|
TrayTileSet* newTilesP = NULL;
|
||||||
|
TrayTileSet newTiles;
|
||||||
|
|
||||||
|
if ( jNewTiles != NULL ) {
|
||||||
|
tilesArrayToTileSet( env, jNewTiles, &newTiles );
|
||||||
|
newTilesP = &newTiles;
|
||||||
|
}
|
||||||
|
|
||||||
result = board_commitTurn( state->game.board, phoniesConfirmed,
|
result = board_commitTurn( state->game.board, phoniesConfirmed,
|
||||||
turnConfirmed );
|
turnConfirmed, newTilesP );
|
||||||
XWJNI_END();
|
XWJNI_END();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1356,6 +1379,17 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1do
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_org_eehouse_android_xw4_jni_XwJNI_server_1tilesPicked
|
||||||
|
( JNIEnv* env, jclass C, GamePtrType gamePtr, jint player, jintArray jNewTiles )
|
||||||
|
{
|
||||||
|
XWJNI_START();
|
||||||
|
TrayTileSet newTiles;
|
||||||
|
tilesArrayToTileSet( env, jNewTiles, &newTiles );
|
||||||
|
server_tilesPicked( state->game.server, player, &newTiles );
|
||||||
|
XWJNI_END();
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_org_eehouse_android_xw4_jni_XwJNI_board_1resetEngine
|
Java_org_eehouse_android_xw4_jni_XwJNI_board_1resetEngine
|
||||||
(JNIEnv* env, jclass C, GamePtrType gamePtr )
|
(JNIEnv* env, jclass C, GamePtrType gamePtr )
|
||||||
|
|
|
@ -1026,17 +1026,19 @@ boardNotifyTrade( BoardCtxt* board, const TrayTileSet* tiles )
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||||
XP_Bool turnConfirmed /* includes trade */ )
|
XP_Bool turnConfirmed /* includes trade */,
|
||||||
|
TrayTileSet* newTiles )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
XP_Bool result = XP_FALSE;
|
||||||
const XP_S16 turn = server_getCurrentTurn( board->server, NULL );
|
const XP_S16 turn = server_getCurrentTurn( board->server, NULL );
|
||||||
PerTurnInfo* pti = board->pti + turn;
|
PerTurnInfo* pti = board->pti + turn;
|
||||||
|
ModelCtxt* model = board->model;
|
||||||
|
|
||||||
if ( board->gameOver || turn < 0 ) {
|
if ( board->gameOver || turn < 0 ) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
} else if ( turn != board->selPlayer ) {
|
} else if ( turn != board->selPlayer ) {
|
||||||
util_userError( board->util, ERR_NOT_YOUR_TURN );
|
util_userError( board->util, ERR_NOT_YOUR_TURN );
|
||||||
} else if ( 0 == model_getNumTilesTotal( board->model, turn ) ) {
|
} else if ( 0 == model_getNumTilesTotal( model, turn ) ) {
|
||||||
/* game's over but still undoable so turn hasn't changed; do
|
/* game's over but still undoable so turn hasn't changed; do
|
||||||
nothing */
|
nothing */
|
||||||
} else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board ) ) {
|
} else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board ) ) {
|
||||||
|
@ -1051,11 +1053,15 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||||
TrayTileSet selTiles;
|
TrayTileSet selTiles;
|
||||||
getSelTiles( board, traySelBits, &selTiles );
|
getSelTiles( board, traySelBits, &selTiles );
|
||||||
if ( turnConfirmed ) {
|
if ( turnConfirmed ) {
|
||||||
/* server_commitTrade() changes selPlayer, so board_endTrade
|
if ( !server_askPickTiles( board->server, turn, newTiles,
|
||||||
must be called first() */
|
selTiles.nTiles ) ) {
|
||||||
(void)board_endTrade( board );
|
/* server_commitTrade() changes selPlayer, so board_endTrade
|
||||||
|
must be called first() */
|
||||||
|
(void)board_endTrade( board );
|
||||||
|
|
||||||
(void)server_commitTrade( board->server, &selTiles );
|
(void)server_commitTrade( board->server, &selTiles,
|
||||||
|
newTiles );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
boardNotifyTrade( board, &selTiles );
|
boardNotifyTrade( board, &selTiles );
|
||||||
}
|
}
|
||||||
|
@ -1081,13 +1087,13 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||||
info.proc = saveBadWords;
|
info.proc = saveBadWords;
|
||||||
info.closure = &bwl;
|
info.closure = &bwl;
|
||||||
}
|
}
|
||||||
legal = model_checkMoveLegal( board->model, turn, stream,
|
legal = model_checkMoveLegal( model, turn, stream,
|
||||||
warn? &info:(WordNotifierInfo*)NULL);
|
warn? &info:(WordNotifierInfo*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 0 < bwl.bwi.nWords && !phoniesConfirmed ) {
|
if ( 0 < bwl.bwi.nWords && !phoniesConfirmed ) {
|
||||||
bwl.bwi.dictName =
|
bwl.bwi.dictName =
|
||||||
dict_getShortName( model_getPlayerDict( board->model, turn ) );
|
dict_getShortName( model_getPlayerDict( model, turn ) );
|
||||||
util_notifyIllegalWords( board->util, &bwl.bwi, turn, XP_FALSE );
|
util_notifyIllegalWords( board->util, &bwl.bwi, turn, XP_FALSE );
|
||||||
} else {
|
} else {
|
||||||
/* Hide the tray so no peeking. Leave it hidden even if user
|
/* Hide the tray so no peeking. Leave it hidden even if user
|
||||||
|
@ -1099,14 +1105,20 @@ board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( board->skipCommitConfirm || turnConfirmed ) {
|
if ( board->skipCommitConfirm || turnConfirmed ) {
|
||||||
result = server_commitMove( board->server ) || result;
|
XP_U16 nToPick = MAX_TRAY_TILES -
|
||||||
/* invalidate all tiles in case we'll be drawing this tray
|
model_getNumTilesInTray( model, turn );
|
||||||
again rather than some other -- as is the case in a
|
if ( !server_askPickTiles( board->server, turn, newTiles,
|
||||||
two-player game where one's a robot. We really only
|
nToPick ) ) {
|
||||||
need the selected tiles and the rightmost (in case it's
|
result = server_commitMove( board->server, newTiles )
|
||||||
showing points-this-turn), but this is easier. */
|
|| result;
|
||||||
board_invalTrayTiles( board, ALLTILES );
|
/* invalidate all tiles in case we'll be drawing this tray
|
||||||
pti->traySelBits = 0x00;
|
again rather than some other -- as is the case in a
|
||||||
|
two-player game where one's a robot. We really only
|
||||||
|
need the selected tiles and the rightmost (in case it's
|
||||||
|
showing points-this-turn), but this is easier. */
|
||||||
|
board_invalTrayTiles( board, ALLTILES );
|
||||||
|
pti->traySelBits = 0x00;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
util_notifyMove( board->util, stream );
|
util_notifyMove( board->util, stream );
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ XP_Bool board_setBlankValue( BoardCtxt* board, XP_U16 XP_UNUSED(player),
|
||||||
void board_resetEngine( BoardCtxt* board );
|
void board_resetEngine( BoardCtxt* board );
|
||||||
|
|
||||||
XP_Bool board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
XP_Bool board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
|
||||||
XP_Bool turnConfirmed );
|
XP_Bool turnConfirmed, TrayTileSet* newTiles );
|
||||||
|
|
||||||
void board_pushTimerSave( BoardCtxt* board );
|
void board_pushTimerSave( BoardCtxt* board );
|
||||||
void board_popTimerSave( BoardCtxt* board );
|
void board_popTimerSave( BoardCtxt* board );
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
|
#include "dbgutil.h"
|
||||||
|
|
||||||
#include "LocalizedStrIncludes.h"
|
#include "LocalizedStrIncludes.h"
|
||||||
|
|
||||||
|
@ -132,6 +133,8 @@ struct ServerCtxt {
|
||||||
|
|
||||||
/******************************* prototypes *******************************/
|
/******************************* prototypes *******************************/
|
||||||
static void assignTilesToAll( ServerCtxt* server );
|
static void assignTilesToAll( ServerCtxt* server );
|
||||||
|
static void makePoolOnce( ServerCtxt* server );
|
||||||
|
|
||||||
static void resetEngines( ServerCtxt* server );
|
static void resetEngines( ServerCtxt* server );
|
||||||
static void nextTurn( ServerCtxt* server, XP_S16 nxtTurn );
|
static void nextTurn( ServerCtxt* server, XP_S16 nxtTurn );
|
||||||
|
|
||||||
|
@ -142,6 +145,9 @@ static void badWordMoveUndoAndTellUser( ServerCtxt* server,
|
||||||
static XP_Bool tileCountsOk( const ServerCtxt* server );
|
static XP_Bool tileCountsOk( const ServerCtxt* server );
|
||||||
static void setTurn( ServerCtxt* server, XP_S16 turn );
|
static void setTurn( ServerCtxt* server, XP_S16 turn );
|
||||||
static XWStreamCtxt* mkServerStream( ServerCtxt* server );
|
static XWStreamCtxt* mkServerStream( ServerCtxt* server );
|
||||||
|
static void fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
||||||
|
const TrayTileSet* tradedTiles,
|
||||||
|
TrayTileSet* resultTiles );
|
||||||
|
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
static XWStreamCtxt* messageStreamWithHeader( ServerCtxt* server,
|
static XWStreamCtxt* messageStreamWithHeader( ServerCtxt* server,
|
||||||
|
@ -900,7 +906,7 @@ makeRobotMove( ServerCtxt* server )
|
||||||
if ( trade ) {
|
if ( trade ) {
|
||||||
TrayTileSet oldTiles = *model_getPlayerTiles( model, turn );
|
TrayTileSet oldTiles = *model_getPlayerTiles( model, turn );
|
||||||
XP_LOGF( "%s: robot trading %d tiles", __func__, oldTiles.nTiles );
|
XP_LOGF( "%s: robot trading %d tiles", __func__, oldTiles.nTiles );
|
||||||
result = server_commitTrade( server, &oldTiles );
|
result = server_commitTrade( server, &oldTiles, NULL );
|
||||||
|
|
||||||
/* Quick hack to fix gremlin bug where all-robot game seen none
|
/* Quick hack to fix gremlin bug where all-robot game seen none
|
||||||
able to trade for tiles to move and blowing the undo stack.
|
able to trade for tiles to move and blowing the undo stack.
|
||||||
|
@ -933,7 +939,7 @@ makeRobotMove( ServerCtxt* server )
|
||||||
server->nv.prevMoveStream = stream;
|
server->nv.prevMoveStream = stream;
|
||||||
server->nv.prevWordsStream = wordsStream;
|
server->nv.prevWordsStream = wordsStream;
|
||||||
}
|
}
|
||||||
result = server_commitMove( server );
|
result = server_commitMove( server, NULL );
|
||||||
} else {
|
} else {
|
||||||
result = XP_FALSE;
|
result = XP_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1047,6 +1053,64 @@ showPrevScore( ServerCtxt* server )
|
||||||
SETSTATE( server, server->nv.stateAfterShow );
|
SETSTATE( server, server->nv.stateAfterShow );
|
||||||
} /* showPrevScore */
|
} /* showPrevScore */
|
||||||
|
|
||||||
|
void
|
||||||
|
server_tilesPicked( ServerCtxt* server, XP_U16 player,
|
||||||
|
const TrayTileSet* newTilesP )
|
||||||
|
{
|
||||||
|
TrayTileSet newTiles = *newTilesP;
|
||||||
|
pool_removeTiles( server->pool, &newTiles );
|
||||||
|
|
||||||
|
fetchTiles( server, player, MAX_TRAY_TILES, NULL, &newTiles );
|
||||||
|
model_assignPlayerTiles( server->vol.model, player, &newTiles );
|
||||||
|
|
||||||
|
util_requestTime( server->vol.util );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
informNeedPickTiles( ServerCtxt* server, XP_Bool initial, XP_U16 turn,
|
||||||
|
XP_U16 nToPick )
|
||||||
|
{
|
||||||
|
ModelCtxt* model = server->vol.model;
|
||||||
|
DictionaryCtxt* dict = model_getDictionary(model);
|
||||||
|
XP_U16 nFaces = dict_numTileFaces( dict );
|
||||||
|
XP_U16 counts[MAX_UNIQUE_TILES];
|
||||||
|
const XP_UCHAR* faces[MAX_UNIQUE_TILES];
|
||||||
|
|
||||||
|
XP_U16 nLeft = pool_getNTilesLeft( server->pool );
|
||||||
|
if ( nLeft < nToPick ) {
|
||||||
|
nToPick = nLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Tile tile = 0; tile < nFaces; ++tile ) {
|
||||||
|
faces[tile] = dict_getTileString( dict, tile );
|
||||||
|
counts[tile] = pool_getNTilesLeftFor( server->pool, tile );
|
||||||
|
}
|
||||||
|
util_informNeedPickTiles( server->vol.util, initial, turn,
|
||||||
|
nToPick, nFaces, faces, counts );
|
||||||
|
}
|
||||||
|
|
||||||
|
static XP_Bool
|
||||||
|
askedForTiles( ServerCtxt* server )
|
||||||
|
{
|
||||||
|
XP_Bool asked = XP_FALSE;
|
||||||
|
CurGameInfo* gi = server->vol.gi;
|
||||||
|
if ( gi->serverRole == SERVER_STANDALONE && gi->allowPickTiles ) {
|
||||||
|
XP_U16 nPlayers = gi->nPlayers;
|
||||||
|
ModelCtxt* model = server->vol.model;
|
||||||
|
makePoolOnce( server );
|
||||||
|
for ( XP_U16 turn = 0; !asked && turn < nPlayers; ++turn ) {
|
||||||
|
LocalPlayer* player = &gi->players[turn];
|
||||||
|
XP_U16 nTiles = model_getNumTilesInTray( model, turn );
|
||||||
|
if ( nTiles == 0 && !LP_IS_ROBOT(player) ) {
|
||||||
|
informNeedPickTiles( server, XP_TRUE, turn, MAX_TRAY_TILES );
|
||||||
|
asked = XP_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_RETURNF( "%s", boolToStr(asked));
|
||||||
|
return asked;
|
||||||
|
}
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
server_do( ServerCtxt* server )
|
server_do( ServerCtxt* server )
|
||||||
{
|
{
|
||||||
|
@ -1062,10 +1126,12 @@ server_do( ServerCtxt* server )
|
||||||
case XWSTATE_BEGIN:
|
case XWSTATE_BEGIN:
|
||||||
if ( server->nv.pendingRegistrations == 0 ) { /* all players on
|
if ( server->nv.pendingRegistrations == 0 ) { /* all players on
|
||||||
device */
|
device */
|
||||||
assignTilesToAll( server );
|
if ( !askedForTiles( server ) ) {
|
||||||
SETSTATE( server, XWSTATE_INTURN );
|
assignTilesToAll( server );
|
||||||
setTurn( server, 0 );
|
SETSTATE( server, XWSTATE_INTURN );
|
||||||
moreToDo = XP_TRUE;
|
setTurn( server, 0 );
|
||||||
|
moreToDo = XP_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1359,8 +1425,8 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
dict_unref( newDict ); /* new owner will have ref'd */
|
dict_unref( newDict ); /* new owner will have ref'd */
|
||||||
|
|
||||||
XP_ASSERT( !server->pool );
|
XP_ASSERT( !server->pool );
|
||||||
pool = server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
makePoolOnce( server );
|
||||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
pool = server->pool;
|
||||||
|
|
||||||
/* now read the assigned tiles for each player from the stream, and
|
/* now read the assigned tiles for each player from the stream, and
|
||||||
remove them from the newly-created local pool. */
|
remove them from the newly-created local pool. */
|
||||||
|
@ -1755,6 +1821,23 @@ curTrayAsTexts( ServerCtxt* server, XP_U16 turn, const TrayTileSet* notInTray,
|
||||||
*nUsedP = nUsed;
|
*nUsedP = nUsed;
|
||||||
} /* curTrayAsTexts */
|
} /* curTrayAsTexts */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true (after calling util_informPickTiles()) IFF allowPickTiles is
|
||||||
|
* TRUE and the tile set passed in is NULL. If it doesn't contain as many
|
||||||
|
* tiles as are needed that's cool: server code will later interpret that as
|
||||||
|
* meaning the remainder should be assigned randomly as usual.
|
||||||
|
*/
|
||||||
|
XP_Bool
|
||||||
|
server_askPickTiles( ServerCtxt* server, XP_U16 turn, TrayTileSet* newTiles,
|
||||||
|
XP_U16 nToPick )
|
||||||
|
{
|
||||||
|
XP_Bool asked = newTiles == NULL && server->vol.gi->allowPickTiles;
|
||||||
|
if ( asked ) {
|
||||||
|
informNeedPickTiles( server, XP_FALSE, turn, nToPick );
|
||||||
|
}
|
||||||
|
return asked;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get tiles for one user. If picking is available, let user pick until
|
/* Get tiles for one user. If picking is available, let user pick until
|
||||||
* cancels. Otherwise, and after cancel, pick for 'im.
|
* cancels. Otherwise, and after cancel, pick for 'im.
|
||||||
*/
|
*/
|
||||||
|
@ -1763,7 +1846,7 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
||||||
const TrayTileSet* tradedTiles, TrayTileSet* resultTiles )
|
const TrayTileSet* tradedTiles, TrayTileSet* resultTiles )
|
||||||
{
|
{
|
||||||
XP_Bool ask;
|
XP_Bool ask;
|
||||||
XP_U16 nSoFar = 0;
|
XP_U16 nSoFar = resultTiles->nTiles;
|
||||||
XP_U16 nLeft;
|
XP_U16 nLeft;
|
||||||
PoolContext* pool = server->pool;
|
PoolContext* pool = server->pool;
|
||||||
TrayTileSet oneTile;
|
TrayTileSet oneTile;
|
||||||
|
@ -1796,17 +1879,17 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
||||||
|
|
||||||
#ifdef FEATURE_TRAY_EDIT /* good compiler would note ask==0, but... */
|
#ifdef FEATURE_TRAY_EDIT /* good compiler would note ask==0, but... */
|
||||||
/* First ask until cancelled */
|
/* First ask until cancelled */
|
||||||
for ( nSoFar = 0; ask && nSoFar < nToFetch; ) {
|
for ( ; ask && nSoFar < nToFetch; ) {
|
||||||
const XP_UCHAR* texts[MAX_UNIQUE_TILES];
|
const XP_UCHAR* texts[MAX_UNIQUE_TILES];
|
||||||
Tile tiles[MAX_UNIQUE_TILES];
|
Tile tiles[MAX_UNIQUE_TILES];
|
||||||
XP_S16 chosen;
|
XP_S16 chosen;
|
||||||
XP_U16 nUsed = MAX_UNIQUE_TILES;
|
XP_U16 nUsed = MAX_UNIQUE_TILES;
|
||||||
|
// XP_ASSERT(0); /* should no longer happen!!! */
|
||||||
model_packTilesUtil( server->vol.model, pool,
|
model_packTilesUtil( server->vol.model, pool,
|
||||||
XP_TRUE, &nUsed, texts, tiles );
|
XP_TRUE, &nUsed, texts, tiles );
|
||||||
|
|
||||||
chosen = util_userPickTileTray( server->vol.util, &pi, playerNum,
|
chosen = PICKER_PICKALL; /*util_userPickTileTray( server->vol.util,
|
||||||
texts, nUsed );
|
&pi, playerNum, texts, nUsed );*/
|
||||||
|
|
||||||
if ( chosen == PICKER_PICKALL ) {
|
if ( chosen == PICKER_PICKALL ) {
|
||||||
ask = XP_FALSE;
|
ask = XP_FALSE;
|
||||||
|
@ -1846,6 +1929,18 @@ fetchTiles( ServerCtxt* server, XP_U16 playerNum, XP_U16 nToFetch,
|
||||||
resultTiles->nTiles = (XP_U8)nSoFar;
|
resultTiles->nTiles = (XP_U8)nSoFar;
|
||||||
} /* fetchTiles */
|
} /* fetchTiles */
|
||||||
|
|
||||||
|
static void
|
||||||
|
makePoolOnce( ServerCtxt* server )
|
||||||
|
{
|
||||||
|
ModelCtxt* model = server->vol.model;
|
||||||
|
XP_ASSERT( model_getDictionary(model) != NULL );
|
||||||
|
if ( server->pool == NULL ) {
|
||||||
|
server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
||||||
|
XP_STATUSF( "initing pool" );
|
||||||
|
pool_initFromDict( server->pool, model_getDictionary(model));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assignTilesToAll( ServerCtxt* server )
|
assignTilesToAll( ServerCtxt* server )
|
||||||
{
|
{
|
||||||
|
@ -1855,12 +1950,7 @@ assignTilesToAll( ServerCtxt* server )
|
||||||
XP_U16 nPlayers = server->vol.gi->nPlayers;
|
XP_U16 nPlayers = server->vol.gi->nPlayers;
|
||||||
|
|
||||||
XP_ASSERT( server->vol.gi->serverRole != SERVER_ISCLIENT );
|
XP_ASSERT( server->vol.gi->serverRole != SERVER_ISCLIENT );
|
||||||
XP_ASSERT( model_getDictionary(model) != NULL );
|
makePoolOnce( server );
|
||||||
if ( server->pool == NULL ) {
|
|
||||||
server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) );
|
|
||||||
XP_STATUSF( "initing pool" );
|
|
||||||
pool_initFromDict( server->pool, model_getDictionary(model));
|
|
||||||
}
|
|
||||||
|
|
||||||
XP_STATUSF( "assignTilesToAll" );
|
XP_STATUSF( "assignTilesToAll" );
|
||||||
|
|
||||||
|
@ -1871,9 +1961,11 @@ assignTilesToAll( ServerCtxt* server )
|
||||||
numAssigned = MAX_TRAY_TILES;
|
numAssigned = MAX_TRAY_TILES;
|
||||||
}
|
}
|
||||||
for ( ii = 0; ii < nPlayers; ++ii ) {
|
for ( ii = 0; ii < nPlayers; ++ii ) {
|
||||||
TrayTileSet newTiles;
|
if ( 0 == model_getNumTilesInTray( model, ii ) ) {
|
||||||
fetchTiles( server, ii, numAssigned, NULL, &newTiles );
|
TrayTileSet newTiles = {0};
|
||||||
model_assignPlayerTiles( model, ii, &newTiles );
|
fetchTiles( server, ii, numAssigned, NULL, &newTiles );
|
||||||
|
model_assignPlayerTiles( model, ii, &newTiles );
|
||||||
|
}
|
||||||
sortTilesIf( server, ii );
|
sortTilesIf( server, ii );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2345,16 +2437,20 @@ reflectMove( ServerCtxt* server, XWStreamCtxt* stream )
|
||||||
* if it was legal -- but only if DISALLOW is set.
|
* if it was legal -- but only if DISALLOW is set.
|
||||||
*/
|
*/
|
||||||
XP_Bool
|
XP_Bool
|
||||||
server_commitMove( ServerCtxt* server )
|
server_commitMove( ServerCtxt* server, TrayTileSet* newTilesP )
|
||||||
{
|
{
|
||||||
XP_S16 turn = server->nv.currentTurn;
|
XP_S16 turn = server->nv.currentTurn;
|
||||||
ModelCtxt* model = server->vol.model;
|
ModelCtxt* model = server->vol.model;
|
||||||
CurGameInfo* gi = server->vol.gi;
|
CurGameInfo* gi = server->vol.gi;
|
||||||
TrayTileSet newTiles;
|
TrayTileSet newTiles = {0};
|
||||||
XP_U16 nTilesMoved;
|
XP_U16 nTilesMoved;
|
||||||
XP_Bool isLegalMove = XP_TRUE;
|
XP_Bool isLegalMove = XP_TRUE;
|
||||||
XP_Bool isClient = gi->serverRole == SERVER_ISCLIENT;
|
XP_Bool isClient = gi->serverRole == SERVER_ISCLIENT;
|
||||||
|
|
||||||
|
if ( !!newTilesP ) {
|
||||||
|
newTiles = *newTilesP;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if ( LP_IS_ROBOT( &gi->players[turn] ) ) {
|
if ( LP_IS_ROBOT( &gi->players[turn] ) ) {
|
||||||
XP_ASSERT( model_checkMoveLegal( model, turn, (XWStreamCtxt*)NULL,
|
XP_ASSERT( model_checkMoveLegal( model, turn, (XWStreamCtxt*)NULL,
|
||||||
|
@ -2408,9 +2504,13 @@ server_commitMove( ServerCtxt* server )
|
||||||
} /* server_commitMove */
|
} /* server_commitMove */
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles )
|
server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles,
|
||||||
|
TrayTileSet* newTilesP )
|
||||||
{
|
{
|
||||||
TrayTileSet newTiles;
|
TrayTileSet newTiles = {0};
|
||||||
|
if ( !!newTilesP ) {
|
||||||
|
newTiles = *newTilesP;
|
||||||
|
}
|
||||||
XP_U16 turn = server->nv.currentTurn;
|
XP_U16 turn = server->nv.currentTurn;
|
||||||
|
|
||||||
fetchTiles( server, turn, oldTiles->nTiles, oldTiles, &newTiles );
|
fetchTiles( server, turn, oldTiles->nTiles, oldTiles, &newTiles );
|
||||||
|
|
|
@ -102,12 +102,18 @@ XP_U32 server_getLastMoveTime( const ServerCtxt* server );
|
||||||
/* Signed in case no dictionary available */
|
/* Signed in case no dictionary available */
|
||||||
XP_S16 server_countTilesInPool( ServerCtxt* server );
|
XP_S16 server_countTilesInPool( ServerCtxt* server );
|
||||||
|
|
||||||
|
XP_Bool server_askPickTiles( ServerCtxt* server, XP_U16 player,
|
||||||
|
TrayTileSet* newTiles, XP_U16 nToPick );
|
||||||
|
void server_tilesPicked( ServerCtxt* server, XP_U16 player,
|
||||||
|
const TrayTileSet* newTiles );
|
||||||
|
|
||||||
XP_U16 server_getPendingRegs( const ServerCtxt* server );
|
XP_U16 server_getPendingRegs( const ServerCtxt* server );
|
||||||
|
|
||||||
XP_Bool server_do( ServerCtxt* server );
|
XP_Bool server_do( ServerCtxt* server );
|
||||||
|
|
||||||
XP_Bool server_commitMove( ServerCtxt* server );
|
XP_Bool server_commitMove( ServerCtxt* server, TrayTileSet* newTiles );
|
||||||
XP_Bool server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles );
|
XP_Bool server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles,
|
||||||
|
TrayTileSet* newTiles );
|
||||||
|
|
||||||
/* call this when user wants to end the game */
|
/* call this when user wants to end the game */
|
||||||
void server_endGame( ServerCtxt* server );
|
void server_endGame( ServerCtxt* server );
|
||||||
|
|
|
@ -460,7 +460,7 @@ handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
|
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
|
||||||
result = board_commitTurn( board, XP_FALSE, XP_FALSE );
|
result = board_commitTurn( board, XP_FALSE, XP_FALSE, NULL );
|
||||||
#if defined XWFEATURE_TRAYUNDO_ALL
|
#if defined XWFEATURE_TRAYUNDO_ALL
|
||||||
} else if ( index < 0 ) { /* other empty area */
|
} else if ( index < 0 ) { /* other empty area */
|
||||||
/* it better be true */
|
/* it better be true */
|
||||||
|
|
|
@ -101,14 +101,14 @@ typedef struct UtilVtable {
|
||||||
void (*m_util_notifyMove)( XW_UtilCtxt* uc, XWStreamCtxt* stream );
|
void (*m_util_notifyMove)( XW_UtilCtxt* uc, XWStreamCtxt* stream );
|
||||||
void (*m_util_notifyTrade)( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
|
void (*m_util_notifyTrade)( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
|
||||||
XP_U16 nTiles );
|
XP_U16 nTiles );
|
||||||
/* return of < 0 means computer should pick */
|
|
||||||
void (*m_util_notifyPickTileBlank)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
void (*m_util_notifyPickTileBlank)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||||
XP_U16 col, XP_U16 row,
|
XP_U16 col, XP_U16 row,
|
||||||
const XP_UCHAR** tileFaces,
|
const XP_UCHAR** tileFaces,
|
||||||
XP_U16 nTiles );
|
XP_U16 nTiles );
|
||||||
XP_S16 (*m_util_userPickTileTray)( XW_UtilCtxt* uc, const PickInfo* pi,
|
void (*m_util_informNeedPickTiles)( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||||
XP_U16 playerNum,
|
XP_U16 player, XP_U16 nToPick,
|
||||||
const XP_UCHAR** texts, XP_U16 nTiles );
|
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||||
|
const XP_U16* counts );
|
||||||
|
|
||||||
void (*m_util_informNeedPassword)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
void (*m_util_informNeedPassword)( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||||
const XP_UCHAR* name );
|
const XP_UCHAR* name );
|
||||||
|
@ -236,9 +236,11 @@ struct XW_UtilCtxt {
|
||||||
(uc)->vtable->m_util_notifyTrade((uc), (tx), (nt))
|
(uc)->vtable->m_util_notifyTrade((uc), (tx), (nt))
|
||||||
|
|
||||||
#define util_notifyPickTileBlank( uc, c, r, n, tx, nt ) \
|
#define util_notifyPickTileBlank( uc, c, r, n, tx, nt ) \
|
||||||
(uc)->vtable->m_util_notifyPickTileBlank( (uc), (c), (r), (n), (tx), (nt) )
|
(uc)->vtable->m_util_notifyPickTileBlank( (uc), (c), (r), (n), (tx), (nt) )
|
||||||
#define util_userPickTileTray( uc, w, n, tx, nt ) \
|
|
||||||
(uc)->vtable->m_util_userPickTileTray( (uc), (w), (n), (tx), (nt) )
|
#define util_informNeedPickTiles( uc, ii, pl, np, nt, fc, cn ) \
|
||||||
|
(uc)->vtable->m_util_informNeedPickTiles( (uc), (ii), (pl), (np), (nt), (fc), (cn) )
|
||||||
|
|
||||||
#define util_informNeedPassword( uc, pn, n ) \
|
#define util_informNeedPassword( uc, pn, n ) \
|
||||||
(uc)->vtable->m_util_informNeedPassword( (uc), (pn), (n) )
|
(uc)->vtable->m_util_informNeedPassword( (uc), (pn), (n) )
|
||||||
|
|
||||||
|
|
|
@ -243,22 +243,26 @@ curses_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum,
|
||||||
// return index;
|
// return index;
|
||||||
} /* util_userPickTile */
|
} /* util_userPickTile */
|
||||||
|
|
||||||
static XP_S16
|
static void
|
||||||
curses_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* XP_UNUSED(pi),
|
curses_util_informNeedPickTiles( XW_UtilCtxt* XP_UNUSED(uc),
|
||||||
XP_U16 playerNum, const XP_UCHAR** texts,
|
XP_Bool XP_UNUSED(isInitial),
|
||||||
XP_U16 nTiles )
|
XP_U16 XP_UNUSED(player),
|
||||||
|
XP_U16 XP_UNUSED(nToPick),
|
||||||
|
XP_U16 XP_UNUSED(nFaces),
|
||||||
|
const XP_UCHAR** XP_UNUSED(faces),
|
||||||
|
const XP_U16* XP_UNUSED(counts) )
|
||||||
{
|
{
|
||||||
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
|
/* CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure; */
|
||||||
char query[128];
|
/* char query[128]; */
|
||||||
XP_S16 index;
|
/* XP_S16 index; */
|
||||||
char* playerName = globals->cGlobals.gi->players[playerNum].name;
|
/* char* playerName = globals->cGlobals.gi->players[playerNum].name; */
|
||||||
|
|
||||||
snprintf( query, sizeof(query),
|
/* snprintf( query, sizeof(query), */
|
||||||
"Pick tile for %s! (Tab or type letter to select "
|
/* "Pick tile for %s! (Tab or type letter to select " */
|
||||||
"then hit <cr>.)", playerName );
|
/* "then hit <cr>.)", playerName ); */
|
||||||
|
|
||||||
index = curses_askLetter( globals, query, texts, nTiles );
|
/* index = curses_askLetter( globals, query, texts, nTiles ); */
|
||||||
return index;
|
/* return index; */
|
||||||
} /* util_userPickTile */
|
} /* util_userPickTile */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -620,7 +624,7 @@ static XP_Bool
|
||||||
handleCommit( CursesAppGlobals* globals )
|
handleCommit( CursesAppGlobals* globals )
|
||||||
{
|
{
|
||||||
globals->doDraw = board_commitTurn( globals->cGlobals.game.board,
|
globals->doDraw = board_commitTurn( globals->cGlobals.game.board,
|
||||||
XP_FALSE, XP_FALSE );
|
XP_FALSE, XP_FALSE, NULL );
|
||||||
return XP_TRUE;
|
return XP_TRUE;
|
||||||
} /* handleCommit */
|
} /* handleCommit */
|
||||||
|
|
||||||
|
@ -1456,7 +1460,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
|
||||||
util->vtable->m_util_notifyMove = curses_util_notifyMove;
|
util->vtable->m_util_notifyMove = curses_util_notifyMove;
|
||||||
util->vtable->m_util_notifyTrade = curses_util_notifyTrade;
|
util->vtable->m_util_notifyTrade = curses_util_notifyTrade;
|
||||||
util->vtable->m_util_notifyPickTileBlank = curses_util_notifyPickTileBlank;
|
util->vtable->m_util_notifyPickTileBlank = curses_util_notifyPickTileBlank;
|
||||||
util->vtable->m_util_userPickTileTray = curses_util_userPickTileTray;
|
util->vtable->m_util_informNeedPickTiles = curses_util_informNeedPickTiles;
|
||||||
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
|
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
|
||||||
util->vtable->m_util_informMove = curses_util_informMove;
|
util->vtable->m_util_informMove = curses_util_informMove;
|
||||||
util->vtable->m_util_informUndo = curses_util_informUndo;
|
util->vtable->m_util_informUndo = curses_util_informUndo;
|
||||||
|
|
|
@ -1445,7 +1445,8 @@ handle_trade_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
static void
|
static void
|
||||||
handle_done_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
handle_done_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
{
|
{
|
||||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
|
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE,
|
||||||
|
XP_FALSE, NULL ) ) {
|
||||||
board_draw( globals->cGlobals.game.board );
|
board_draw( globals->cGlobals.game.board );
|
||||||
disenable_buttons( globals );
|
disenable_buttons( globals );
|
||||||
}
|
}
|
||||||
|
@ -1543,7 +1544,8 @@ handle_hide_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
static void
|
static void
|
||||||
handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
{
|
{
|
||||||
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
|
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE,
|
||||||
|
XP_FALSE, NULL ) ) {
|
||||||
board_draw( globals->cGlobals.game.board );
|
board_draw( globals->cGlobals.game.board );
|
||||||
}
|
}
|
||||||
} /* handle_commit_button */
|
} /* handle_commit_button */
|
||||||
|
@ -1693,7 +1695,7 @@ ask_blank( gpointer data )
|
||||||
|
|
||||||
XP_UCHAR* name = globals->cGlobals.gi->players[cGlobals->selPlayer].name;
|
XP_UCHAR* name = globals->cGlobals.gi->players[cGlobals->selPlayer].name;
|
||||||
XP_S16 result = gtkletterask( NULL, XP_FALSE, name,
|
XP_S16 result = gtkletterask( NULL, XP_FALSE, name,
|
||||||
cGlobals->nTiles, cGlobals->tiles );
|
cGlobals->nTiles, cGlobals->tiles, NULL );
|
||||||
|
|
||||||
for ( int ii = 0; ii < cGlobals->nTiles; ++ii ) {
|
for ( int ii = 0; ii < cGlobals->nTiles; ++ii ) {
|
||||||
g_free( (gpointer)cGlobals->tiles[ii] );
|
g_free( (gpointer)cGlobals->tiles[ii] );
|
||||||
|
@ -1725,18 +1727,78 @@ gtk_util_notifyPickTileBlank( XW_UtilCtxt* uc, XP_U16 playerNum, XP_U16 col,
|
||||||
(void)g_idle_add( ask_blank, globals );
|
(void)g_idle_add( ask_blank, globals );
|
||||||
}
|
}
|
||||||
|
|
||||||
static XP_S16
|
static gint
|
||||||
gtk_util_userPickTileTray( XW_UtilCtxt* uc, const PickInfo* pi,
|
ask_tiles( gpointer data )
|
||||||
XP_U16 playerNum, const XP_UCHAR** texts,
|
|
||||||
XP_U16 nTiles )
|
|
||||||
{
|
{
|
||||||
XP_S16 chosen;
|
GtkGameGlobals* globals = (GtkGameGlobals*)data;
|
||||||
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
|
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||||
XP_UCHAR* name = globals->cGlobals.gi->players[playerNum].name;
|
|
||||||
|
|
||||||
chosen = gtkletterask( pi, XP_TRUE, name, nTiles, texts );
|
TrayTileSet newTiles = {0};
|
||||||
return chosen;
|
XP_UCHAR* name = cGlobals->gi->players[cGlobals->selPlayer].name;
|
||||||
} /* gtk_util_userPickTile */
|
for ( XP_Bool done = XP_FALSE; !done; ) {
|
||||||
|
XP_S16 picked = gtkletterask( &newTiles, XP_TRUE, name,
|
||||||
|
cGlobals->nTiles, cGlobals->tiles,
|
||||||
|
cGlobals->tileCounts );
|
||||||
|
switch ( picked ) {
|
||||||
|
case PICKER_PICKALL:
|
||||||
|
done = XP_TRUE;
|
||||||
|
break;
|
||||||
|
case PICKER_BACKUP:
|
||||||
|
if ( newTiles.nTiles > 0 ) {
|
||||||
|
Tile backed = newTiles.tiles[--newTiles.nTiles];
|
||||||
|
++cGlobals->tileCounts[backed];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
XP_ASSERT( picked >= 0 && picked < cGlobals->nTiles );
|
||||||
|
--cGlobals->tileCounts[picked];
|
||||||
|
newTiles.tiles[newTiles.nTiles++] = picked;
|
||||||
|
done = newTiles.nTiles == cGlobals->nToPick;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int ii = 0; ii < cGlobals->nTiles; ++ii ) {
|
||||||
|
g_free( (gpointer)cGlobals->tiles[ii] );
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardCtxt* board = cGlobals->game.board;
|
||||||
|
XP_Bool draw = XP_TRUE;
|
||||||
|
if ( cGlobals->pickIsInitial ) {
|
||||||
|
server_tilesPicked( cGlobals->game.server, cGlobals->selPlayer,
|
||||||
|
&newTiles );
|
||||||
|
} else {
|
||||||
|
draw = board_commitTurn( cGlobals->game.board, XP_TRUE, XP_TRUE,
|
||||||
|
&newTiles );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( draw ) {
|
||||||
|
board_draw( board );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_util_informNeedPickTiles( XW_UtilCtxt* uc, XP_Bool isInitial,
|
||||||
|
XP_U16 player, XP_U16 nToPick,
|
||||||
|
XP_U16 nFaces, const XP_UCHAR** faces,
|
||||||
|
const XP_U16* counts )
|
||||||
|
{
|
||||||
|
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
|
||||||
|
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||||
|
cGlobals->selPlayer = player;
|
||||||
|
cGlobals->pickIsInitial = isInitial;
|
||||||
|
|
||||||
|
cGlobals->nToPick = nToPick;
|
||||||
|
cGlobals->nTiles = nFaces;
|
||||||
|
for ( int ii = 0; ii < nFaces; ++ii ) {
|
||||||
|
cGlobals->tiles[ii] = g_strdup( faces[ii] );
|
||||||
|
cGlobals->tileCounts[ii] = counts[ii];
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)g_idle_add( ask_tiles, globals );
|
||||||
|
} /* gtk_util_informNeedPickTiles */
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
ask_password( gpointer data )
|
ask_password( gpointer data )
|
||||||
|
@ -2125,7 +2187,7 @@ ask_bad_words( gpointer data )
|
||||||
|
|
||||||
if ( GTK_RESPONSE_YES == gtkask( globals->window, cGlobals->question,
|
if ( GTK_RESPONSE_YES == gtkask( globals->window, cGlobals->question,
|
||||||
GTK_BUTTONS_YES_NO, NULL ) ) {
|
GTK_BUTTONS_YES_NO, NULL ) ) {
|
||||||
board_commitTurn( cGlobals->game.board, XP_TRUE, XP_FALSE );
|
board_commitTurn( cGlobals->game.board, XP_TRUE, XP_FALSE, NULL );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2275,7 +2337,7 @@ ask_move( gpointer data )
|
||||||
gint chosen = gtkask( globals->window, cGlobals->question, buttons, NULL );
|
gint chosen = gtkask( globals->window, cGlobals->question, buttons, NULL );
|
||||||
if ( GTK_RESPONSE_OK == chosen || chosen == GTK_RESPONSE_YES ) {
|
if ( GTK_RESPONSE_OK == chosen || chosen == GTK_RESPONSE_YES ) {
|
||||||
BoardCtxt* board = cGlobals->game.board;
|
BoardCtxt* board = cGlobals->game.board;
|
||||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
|
if ( board_commitTurn( board, XP_TRUE, XP_TRUE, NULL ) ) {
|
||||||
board_draw( board );
|
board_draw( board );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2314,7 +2376,7 @@ ask_trade( gpointer data )
|
||||||
cGlobals->question,
|
cGlobals->question,
|
||||||
GTK_BUTTONS_YES_NO, NULL ) ) {
|
GTK_BUTTONS_YES_NO, NULL ) ) {
|
||||||
BoardCtxt* board = cGlobals->game.board;
|
BoardCtxt* board = cGlobals->game.board;
|
||||||
if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
|
if ( board_commitTurn( board, XP_TRUE, XP_TRUE, NULL ) ) {
|
||||||
board_draw( board );
|
board_draw( board );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2466,7 +2528,7 @@ setupGtkUtilCallbacks( GtkGameGlobals* globals, XW_UtilCtxt* util )
|
||||||
util->vtable->m_util_notifyTrade = gtk_util_notifyTrade;
|
util->vtable->m_util_notifyTrade = gtk_util_notifyTrade;
|
||||||
util->vtable->m_util_getVTManager = gtk_util_getVTManager;
|
util->vtable->m_util_getVTManager = gtk_util_getVTManager;
|
||||||
util->vtable->m_util_notifyPickTileBlank = gtk_util_notifyPickTileBlank;
|
util->vtable->m_util_notifyPickTileBlank = gtk_util_notifyPickTileBlank;
|
||||||
util->vtable->m_util_userPickTileTray = gtk_util_userPickTileTray;
|
util->vtable->m_util_informNeedPickTiles = gtk_util_informNeedPickTiles;
|
||||||
util->vtable->m_util_informNeedPassword = gtk_util_informNeedPassword;
|
util->vtable->m_util_informNeedPassword = gtk_util_informNeedPassword;
|
||||||
util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange;
|
util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange;
|
||||||
util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange;
|
util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange;
|
||||||
|
|
|
@ -42,8 +42,8 @@ abort_button_event( GtkWidget* XP_UNUSED(widget), gpointer XP_UNUSED(closure) )
|
||||||
#define BUTTONS_PER_ROW 13
|
#define BUTTONS_PER_ROW 13
|
||||||
|
|
||||||
XP_S16
|
XP_S16
|
||||||
gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
gtkletterask( const TrayTileSet* curPick, XP_Bool forTray, const XP_UCHAR* name,
|
||||||
XP_U16 nTiles, const XP_UCHAR** texts )
|
XP_U16 nTiles, const XP_UCHAR** texts, const XP_U16* counts )
|
||||||
{
|
{
|
||||||
GtkWidget* dialog;
|
GtkWidget* dialog;
|
||||||
GtkWidget* label;
|
GtkWidget* label;
|
||||||
|
@ -70,7 +70,9 @@ gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
||||||
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
|
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
|
||||||
g_signal_connect( button, "clicked",
|
g_signal_connect( button, "clicked",
|
||||||
G_CALLBACK(set_bool_and_quit), &results[ii] );
|
G_CALLBACK(set_bool_and_quit), &results[ii] );
|
||||||
gtk_widget_show( button );
|
|
||||||
|
/* disable if we don't have any tiles! */
|
||||||
|
gtk_widget_set_sensitive( button, !counts || counts[ii] > 0 );
|
||||||
|
|
||||||
if ( ii+1 == nTiles || (ii % BUTTONS_PER_ROW == 0) ) {
|
if ( ii+1 == nTiles || (ii % BUTTONS_PER_ROW == 0) ) {
|
||||||
gtk_widget_show( hbox );
|
gtk_widget_show( hbox );
|
||||||
|
@ -118,9 +120,10 @@ gtkletterask( const PickInfo* pi, XP_Bool forTray, const XP_UCHAR* name,
|
||||||
char curTilesBuf[64];
|
char curTilesBuf[64];
|
||||||
int len = snprintf( curTilesBuf, sizeof(curTilesBuf), "%s",
|
int len = snprintf( curTilesBuf, sizeof(curTilesBuf), "%s",
|
||||||
"Tiles so far: " );
|
"Tiles so far: " );
|
||||||
for ( ii = 0; ii < pi->nCurTiles; ++ii ) {
|
for ( ii = 0; ii < curPick->nTiles; ++ii ) {
|
||||||
|
Tile tile = curPick->tiles[ii];
|
||||||
len += snprintf( &curTilesBuf[len], sizeof(curTilesBuf) - len, "%s ",
|
len += snprintf( &curTilesBuf[len], sizeof(curTilesBuf) - len, "%s ",
|
||||||
pi->curTiles[ii] );
|
texts[tile] );
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* curTilesLabel = gtk_label_new( curTilesBuf );
|
GtkWidget* curTilesLabel = gtk_label_new( curTilesBuf );
|
||||||
|
|
|
@ -26,9 +26,10 @@
|
||||||
|
|
||||||
#include "gtkboard.h"
|
#include "gtkboard.h"
|
||||||
|
|
||||||
XP_S16 gtkletterask( const PickInfo* pi, XP_Bool forTray,
|
XP_S16 gtkletterask( const TrayTileSet* curPick, XP_Bool forTray,
|
||||||
const XP_UCHAR* name,
|
const XP_UCHAR* name,
|
||||||
XP_U16 nTiles, const XP_UCHAR** texts );
|
XP_U16 nTiles, const XP_UCHAR** texts,
|
||||||
|
const XP_U16* counts );
|
||||||
|
|
||||||
|
|
||||||
#endif /* _GTKLETTERASK_H_ */
|
#endif /* _GTKLETTERASK_H_ */
|
||||||
|
|
|
@ -220,10 +220,13 @@ struct CommonGlobals {
|
||||||
char question[256*4];
|
char question[256*4];
|
||||||
const XP_UCHAR* askPassName;
|
const XP_UCHAR* askPassName;
|
||||||
XP_U16 nTiles;
|
XP_U16 nTiles;
|
||||||
|
XP_U16 nToPick;
|
||||||
XP_U16 blankCol;
|
XP_U16 blankCol;
|
||||||
XP_U16 blankRow;
|
XP_U16 blankRow;
|
||||||
|
XP_Bool pickIsInitial;
|
||||||
|
|
||||||
const XP_UCHAR* tiles[MAX_UNIQUE_TILES];
|
const XP_UCHAR* tiles[MAX_UNIQUE_TILES];
|
||||||
|
XP_U16 tileCounts[MAX_UNIQUE_TILES];
|
||||||
|
|
||||||
#ifdef XWFEATURE_RELAY
|
#ifdef XWFEATURE_RELAY
|
||||||
int relaySocket; /* tcp connection to relay */
|
int relaySocket; /* tcp connection to relay */
|
||||||
|
|
Loading…
Reference in a new issue