mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-04 20:46:28 +01:00
When pen held on committed tile on board, cons up list of all words
played that include that tile and pass to new util_cellSquareHeld() method. In java implementation of that method, use existing lookup activity code to display list of words. Enabled on the C side by a compile-time flag in case it has problems. Right now the time spent saving a game before launching the lookup activity, and reloading it after, is pretty apparent, but that's in emulator which is slow.
This commit is contained in:
parent
7449923328
commit
0e6b4d749f
13 changed files with 201 additions and 26 deletions
|
@ -23,6 +23,7 @@ local_DEFINES += \
|
|||
-DDROP_BITMAPS \
|
||||
-DDISABLE_EMPTYTRAY_UNDO \
|
||||
-DDISABLE_TILE_SEL \
|
||||
-DXWFEATURE_BOARDWORDS \
|
||||
-DNODE_CAN_4 \
|
||||
-DRELAY_ROOM_DEFAULT=\"\"\
|
||||
-D__LITTLE_ENDIAN \
|
||||
|
|
|
@ -422,6 +422,21 @@ and_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
static void
|
||||
and_util_cellSquareHeld( XW_UtilCtxt* uc, XWStreamCtxt* words )
|
||||
{
|
||||
if ( NULL != words ) {
|
||||
UTIL_CBK_HEADER( "cellSquareHeld", "(Ljava/lang/String;)V" );
|
||||
jstring jwords =
|
||||
streamToJString( MPPARM(util->util.mpool) env, words );
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid, jwords );
|
||||
(*env)->DeleteLocalRef( env, jwords );
|
||||
UTIL_CBK_TAIL();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
static void
|
||||
and_util_addrChange( XW_UtilCtxt* uc, const CommsAddrRec* oldAddr,
|
||||
|
@ -512,6 +527,10 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
|
|||
SET_PROC(playerScoreHeld);
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
SET_PROC(cellSquareHeld);
|
||||
#endif
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
SET_PROC(addrChange);
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* Copyright 2009-2011 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -993,6 +993,16 @@ public class BoardActivity extends XWActivity
|
|||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cellSquareHeld( final String words )
|
||||
{
|
||||
post( new Runnable() {
|
||||
public void run() {
|
||||
launchLookup( wordsToArray( words ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void setTimer( int why, int when, int handle )
|
||||
{
|
||||
if ( null != m_timers[why] ) {
|
||||
|
|
|
@ -49,6 +49,7 @@ public interface UtilCtxt {
|
|||
|
||||
void bonusSquareHeld( int bonus );
|
||||
void playerScoreHeld( int player );
|
||||
void cellSquareHeld( String words );
|
||||
|
||||
static final int STRD_ROBOT_TRADED = 1;
|
||||
static final int STR_ROBOT_MOVED = 2;
|
||||
|
|
|
@ -91,6 +91,10 @@ public class UtilCtxtImpl implements UtilCtxt {
|
|||
{
|
||||
}
|
||||
|
||||
public void cellSquareHeld( String words )
|
||||
{
|
||||
}
|
||||
|
||||
public String getUserString( int stringCode )
|
||||
{
|
||||
int id = 0;
|
||||
|
|
|
@ -726,7 +726,12 @@ hideMiniWindow( BoardCtxt* board, XP_Bool destroy, MiniWindowType winType )
|
|||
#endif
|
||||
|
||||
static XP_Bool
|
||||
warnBadWords( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
|
||||
warnBadWords( const XP_UCHAR* word, XP_Bool isLegal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* XP_UNUSED(movei),
|
||||
XP_U16 XP_UNUSED(start), XP_U16 XP_UNUSED(end),
|
||||
#endif
|
||||
void* closure )
|
||||
{
|
||||
XP_Bool ok = XP_TRUE;
|
||||
if ( !isLegal ) {
|
||||
|
@ -965,15 +970,37 @@ timerFiredForPen( BoardCtxt* board )
|
|||
draw = dragDropSetAdd( board );
|
||||
#endif
|
||||
} else {
|
||||
XWBonusType bonus;
|
||||
bonus = util_getSquareBonus( board->util, board->model,
|
||||
col, row );
|
||||
if ( bonus != BONUS_NONE ) {
|
||||
#ifdef XWFEATURE_MINIWIN
|
||||
text = draw_getMiniWText( board->draw, (XWMiniTextType)bonus );
|
||||
#else
|
||||
util_bonusSquareHeld( board->util, bonus );
|
||||
XP_Bool listWords = XP_FALSE;
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
XP_U16 modelCol, modelRow;
|
||||
flipIf( board, col, row, &modelCol, &modelRow );
|
||||
listWords = model_getTile( board->model, modelCol, modelRow,
|
||||
XP_TRUE, board->selPlayer, NULL,
|
||||
NULL, NULL, NULL );
|
||||
if ( listWords ) {
|
||||
XWStreamCtxt* stream =
|
||||
mem_stream_make( MPPARM(board->mpool)
|
||||
util_getVTManager(board->util), NULL,
|
||||
CHANNEL_NONE,
|
||||
(MemStreamCloseCallback)NULL );
|
||||
model_listWordsThrough( board->model, modelCol, modelRow,
|
||||
stream );
|
||||
util_cellSquareHeld( board->util, stream );
|
||||
stream_destroy( stream );
|
||||
}
|
||||
#endif
|
||||
if ( !listWords ) {
|
||||
XWBonusType bonus;
|
||||
bonus = util_getSquareBonus( board->util, board->model,
|
||||
col, row );
|
||||
if ( bonus != BONUS_NONE ) {
|
||||
#ifdef XWFEATURE_MINIWIN
|
||||
text = draw_getMiniWText( board->draw,
|
||||
(XWMiniTextType)bonus );
|
||||
#else
|
||||
util_bonusSquareHeld( board->util, bonus );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
board->penTimerFired = XP_TRUE;
|
||||
|
|
|
@ -75,7 +75,11 @@ static void loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version,
|
|||
PlayerCtxt* pc );
|
||||
static void writePlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc );
|
||||
static XP_U16 model_getRecentPassCount( ModelCtxt* model );
|
||||
static XP_Bool recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* clsur );
|
||||
static XP_Bool recordWord( const XP_UCHAR* word, XP_Bool isLegal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* movei, XP_U16 start, XP_U16 end,
|
||||
#endif
|
||||
void* clsur );
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
@ -1948,7 +1952,11 @@ typedef struct _FirstWordData {
|
|||
} FirstWordData;
|
||||
|
||||
static XP_Bool
|
||||
getFirstWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
|
||||
getFirstWord( const XP_UCHAR* word, XP_Bool isLegal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start), XP_U16 XP_UNUSED(end),
|
||||
#endif
|
||||
void* closure )
|
||||
{
|
||||
LOG_FUNC();
|
||||
if ( isLegal ) {
|
||||
|
@ -2035,16 +2043,26 @@ model_recentPassCountOk( ModelCtxt* model )
|
|||
return count < okCount;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
recordWord( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal), void* closure )
|
||||
static void
|
||||
appendWithCR( XWStreamCtxt* stream, const XP_UCHAR* word, XP_U16* counter )
|
||||
{
|
||||
RecordWordsInfo* info = (RecordWordsInfo*)closure;
|
||||
XWStreamCtxt* stream = info->stream;
|
||||
XP_LOGF( "%s(%s)", __func__, word );
|
||||
if ( 0 < info->nWords++ ) {
|
||||
if ( 0 < (*counter)++ ) {
|
||||
stream_putU8( stream, '\n' );
|
||||
}
|
||||
stream_catString( stream, word );
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
recordWord( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start),
|
||||
XP_U16 XP_UNUSED(end),
|
||||
#endif
|
||||
void* closure )
|
||||
|
||||
{
|
||||
RecordWordsInfo* info = (RecordWordsInfo*)closure;
|
||||
appendWithCR( info->stream, word, &info->nWords );
|
||||
return XP_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2085,6 +2103,65 @@ model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns, XWStreamCtxt* stream )
|
|||
stack_destroy( tmpStack );
|
||||
}
|
||||
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
|
||||
typedef struct _ListWordsThroughInfo {
|
||||
XWStreamCtxt* stream;
|
||||
XP_U16 col, row;
|
||||
XP_U16 nWords;
|
||||
} ListWordsThroughInfo;
|
||||
|
||||
static XP_Bool
|
||||
listWordsThrough( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
|
||||
const MoveInfo* movei, XP_U16 start, XP_U16 end,
|
||||
void* closure )
|
||||
{
|
||||
ListWordsThroughInfo* info = (ListWordsThroughInfo*)closure;
|
||||
|
||||
XP_Bool contained = XP_FALSE;
|
||||
if ( movei->isHorizontal && movei->commonCoord == info->row ) {
|
||||
contained = start <= info->col && end >= info->col;
|
||||
} else if ( !movei->isHorizontal && movei->commonCoord == info->col ) {
|
||||
contained = start <= info->row && end >= info->row;
|
||||
}
|
||||
|
||||
if ( contained ) {
|
||||
appendWithCR( info->stream, word, &info->nWords );
|
||||
}
|
||||
|
||||
return XP_TRUE;
|
||||
}
|
||||
|
||||
/* List every word played that includes the tile on {col,row}.
|
||||
*
|
||||
* How? Undo backwards until we find the move that placed that tile.*/
|
||||
void
|
||||
model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||
XWStreamCtxt* stream )
|
||||
{
|
||||
XP_ASSERT( !!stream );
|
||||
StackCtxt* stack = model->vol.stack;
|
||||
StackCtxt* tmpStack = stack_copy( stack );
|
||||
|
||||
XP_U16 nPlayers = model->nPlayers;
|
||||
XP_U16 nEntries = stack_getNEntries( stack ) - nPlayers; /* skip assignments */
|
||||
|
||||
if ( model_undoLatestMoves( model, NULL, nEntries, NULL, NULL ) ) {
|
||||
ListWordsThroughInfo lwtInfo = { .stream = stream, .col = col,
|
||||
.row = row, .nWords = 0,
|
||||
};
|
||||
WordNotifierInfo ni = { .proc = listWordsThrough, .closure = &lwtInfo };
|
||||
/* Now push the undone moves back into the model one at a time.
|
||||
recordWord() will add each played word to the stream as it's
|
||||
scored */
|
||||
buildModelFromStack( model, tmpStack, XP_TRUE, nPlayers,
|
||||
(XWStreamCtxt*)NULL, &ni, (MovePrintFuncPre)NULL,
|
||||
(MovePrintFuncPost)NULL, NULL );
|
||||
}
|
||||
stack_destroy( tmpStack );
|
||||
}
|
||||
#endif
|
||||
|
||||
XP_Bool
|
||||
model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
||||
XP_UCHAR* expl, XP_U16* explLen )
|
||||
|
|
|
@ -239,6 +239,10 @@ void model_countAllTrayTiles( ModelCtxt* model, XP_U16* counts,
|
|||
/********************* scoring ********************/
|
||||
|
||||
typedef XP_Bool (*WordNotifierProc)( const XP_UCHAR* word, XP_Bool isLegal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* movei, XP_U16 start,
|
||||
XP_U16 end,
|
||||
#endif
|
||||
void* closure );
|
||||
typedef struct WordNotifierInfo {
|
||||
WordNotifierProc proc;
|
||||
|
@ -254,6 +258,10 @@ XP_Bool model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
|||
XP_UCHAR* expl, XP_U16* explLen );
|
||||
void model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns,
|
||||
XWStreamCtxt* stream );
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
void model_listWordsThrough( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||
XWStreamCtxt* stream );
|
||||
#endif
|
||||
|
||||
/* Have there been too many passes (so game should end)? */
|
||||
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
||||
|
|
|
@ -40,9 +40,9 @@ static XP_U16 find_start( const ModelCtxt* model, XP_U16 col, XP_U16 row,
|
|||
static XP_S16 checkScoreMove( ModelCtxt* model, XP_S16 turn,
|
||||
EngineCtxt* engine, XWStreamCtxt* stream,
|
||||
XP_Bool silent, WordNotifierInfo* notifyInfo );
|
||||
static XP_U16 scoreWord( const ModelCtxt* model, XP_U16 turn, MoveInfo* movei,
|
||||
EngineCtxt* engine, XWStreamCtxt* stream,
|
||||
WordNotifierInfo* notifyInfo );
|
||||
static XP_U16 scoreWord( const ModelCtxt* model, XP_U16 turn,
|
||||
const MoveInfo* movei, EngineCtxt* engine,
|
||||
XWStreamCtxt* stream, WordNotifierInfo* notifyInfo );
|
||||
|
||||
/* for formatting when caller wants an explanation of the score. These live
|
||||
in separate function called only when stream != NULL so that they'll have
|
||||
|
@ -553,7 +553,7 @@ tile_multiplier( const ModelCtxt* model, XP_U16 col, XP_U16 row )
|
|||
|
||||
static XP_U16
|
||||
scoreWord( const ModelCtxt* model, XP_U16 turn,
|
||||
MoveInfo* movei, /* new tiles */
|
||||
const MoveInfo* movei, /* new tiles */
|
||||
EngineCtxt* engine,/* for crosswise caching */
|
||||
XWStreamCtxt* stream,
|
||||
WordNotifierInfo* notifyInfo )
|
||||
|
@ -567,7 +567,7 @@ scoreWord( const ModelCtxt* model, XP_U16 turn,
|
|||
XP_U16 start, end;
|
||||
XP_U16* incr;
|
||||
XP_U16 col, row;
|
||||
MoveInfoTile* tiles = movei->tiles;
|
||||
const MoveInfoTile* tiles = movei->tiles;
|
||||
XP_U16 firstCoord = tiles->varCoord;
|
||||
DictionaryCtxt* dict = model_getPlayerDict( model, turn );
|
||||
|
||||
|
@ -671,7 +671,11 @@ scoreWord( const ModelCtxt* model, XP_U16 turn,
|
|||
XP_UCHAR buf[(MAX_ROWS*2)+1];
|
||||
dict_tilesToString( dict, checkWordBuf, len, buf,
|
||||
sizeof(buf) );
|
||||
(void)(*notifyInfo->proc)( buf, legal, notifyInfo->closure );
|
||||
(void)(*notifyInfo->proc)( buf, legal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
movei, start, end,
|
||||
#endif
|
||||
notifyInfo->closure );
|
||||
}
|
||||
|
||||
if ( !!stream ) {
|
||||
|
|
|
@ -1734,7 +1734,12 @@ server_setGameOverListener( ServerCtxt* server, GameOverListener gol,
|
|||
} /* server_setGameOverListener */
|
||||
|
||||
static XP_Bool
|
||||
storeBadWords( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
|
||||
storeBadWords( const XP_UCHAR* word, XP_Bool isLegal,
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start),
|
||||
XP_U16 XP_UNUSED(end),
|
||||
#endif
|
||||
void* closure )
|
||||
{
|
||||
if ( !isLegal ) {
|
||||
ServerCtxt* server = (ServerCtxt*)closure;
|
||||
|
|
|
@ -162,6 +162,9 @@ typedef struct UtilVtable {
|
|||
void (*m_util_bonusSquareHeld)( XW_UtilCtxt* uc, XWBonusType bonus );
|
||||
void (*m_util_playerScoreHeld)( XW_UtilCtxt* uc, XP_U16 player );
|
||||
#endif
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
void (*m_util_cellSquareHeld)( XW_UtilCtxt* uc, XWStreamCtxt* words );
|
||||
#endif
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
void (*m_util_addrChange)( XW_UtilCtxt* uc, const CommsAddrRec* oldAddr,
|
||||
|
@ -271,7 +274,10 @@ struct XW_UtilCtxt {
|
|||
# define util_playerScoreHeld( uc, player ) \
|
||||
(uc)->vtable->m_util_playerScoreHeld( (uc), (player) )
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
#define util_cellSquareHeld(uc, s) \
|
||||
(uc)->vtable->m_util_cellSquareHeld( (uc), (s) )
|
||||
#endif
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
# define util_addrChange( uc, addro, addrn ) \
|
||||
(uc)->vtable->m_util_addrChange((uc), (addro), (addrn))
|
||||
|
|
|
@ -38,6 +38,7 @@ ifdef CURSES_SMALL_SCREEN
|
|||
DO_CURSES += -DCURSES_SMALL_SCREEN
|
||||
endif
|
||||
DO_GTK = -DPLATFORM_GTK
|
||||
DO_GTK += -DXWFEATURE_BOARDWORDS
|
||||
# DO_GTK += -DUSE_CAIRO
|
||||
|
||||
# uncomment for standalone build
|
||||
|
|
|
@ -1730,6 +1730,15 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
static void
|
||||
gtk_util_cellSquareHeld( XW_UtilCtxt* uc, XWStreamCtxt* words )
|
||||
{
|
||||
XP_USE( uc );
|
||||
XP_USE( words );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gtk_util_userError( XW_UtilCtxt* uc, UtilErrID id )
|
||||
{
|
||||
|
@ -1952,6 +1961,9 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
|
|||
util->vtable->m_util_bonusSquareHeld = gtk_util_bonusSquareHeld;
|
||||
util->vtable->m_util_playerScoreHeld = gtk_util_playerScoreHeld;
|
||||
#endif
|
||||
#ifdef XWFEATURE_BOARDWORDS
|
||||
util->vtable->m_util_cellSquareHeld = gtk_util_cellSquareHeld;
|
||||
#endif
|
||||
|
||||
util->closure = globals;
|
||||
} /* setupGtkUtilCallbacks */
|
||||
|
|
Loading…
Add table
Reference in a new issue