handle two-letter tiles better

Choose the two-letter tile where possible. Not sure though if this is
always the right move.
This commit is contained in:
Eric House 2020-12-26 20:45:34 -08:00
parent dc4fcada2a
commit d0f5d9949a

View file

@ -258,35 +258,56 @@ parseCounts( ParseState* ps, int elemIndex )
} }
typedef struct _FoundData { typedef struct _FoundData {
PatErr err; const DictionaryCtxt* dict;
int nCalls; int nCalls;
PatElem* elem; int nChars;
Tile tile;
} FoundData; } FoundData;
static XP_Bool static XP_Bool
onFoundTiles( void* closure, const Tile* tiles, int len ) onFoundTiles( void* closure, const Tile* tiles, int nTiles )
{ {
XP_ASSERT( len == 1 );
FoundData* data = (FoundData*)closure; FoundData* data = (FoundData*)closure;
if ( 1 == len ) { if ( 1 == nTiles ) {
XP_ASSERT( 0 == data->nCalls ); XP_UCHAR buf[16];
XP_U16 len = dict_tilesToString( data->dict, tiles, nTiles,
buf, VSIZE(buf), NULL );
if ( 0 == data->nCalls || data->nChars < len ) {
data->nChars = len;
data->tile = tiles[0];
}
++data->nCalls; ++data->nCalls;
for ( int ii = 0; ii < len; ++ii ) { }
Tile tile = tiles[ii]; return XP_TRUE;
}
static PatErr
checkData( FoundData* data, ParseState* ps )
{
PatErr result = PatErrBogusTiles;
if ( 1 <= data->nCalls ) {
result = PatErrNone;
Tile tile = data->tile;
PatElem* elem = &ps->elems[ps->elemIndex];
#ifdef MULTI_SET #ifdef MULTI_SET
++data->elem->u.child.tiles.cnts[tile]; ++elem->u.child.tiles.cnts[tile];
#else #else
TileSet mask = 1 << tile; TileSet mask = 1 << tile;
if ( 0 == (data->elem->u.child.tiles & mask ) ) { if ( 0 == (elem->u.child.tiles & mask ) ) {
data->elem->u.child.tiles |= mask; elem->u.child.tiles |= mask;
} else { } else {
data->err = PatErrDupInSet; result = PatErrDupInSet;
break;
} }
#endif #endif
} }
if ( PatErrNone == result ) {
ps->patIndex += data->nChars;
} }
return 1 == len && PatErrNone == data->err;
return result;
} }
static PatErr static PatErr
@ -317,18 +338,14 @@ parseTile( ParseState* ps )
} else { } else {
err = PatErrBogusTiles; /* in case we fail */ err = PatErrBogusTiles; /* in case we fail */
XP_U16 maxLen = XP_STRLEN( &ps->pat[ps->patIndex] ); XP_U16 maxLen = XP_STRLEN( &ps->pat[ps->patIndex] );
FoundData data = { .dict = ps->dict };
for ( int nChars = 1; nChars <= maxLen; ++nChars ) { for ( int nChars = 1; nChars <= maxLen; ++nChars ) {
FoundData data = { .err = PatErrNone, XP_UCHAR buf[24];
.elem = &ps->elems[ps->elemIndex], XP_MEMCPY( buf, &ps->pat[ps->patIndex], nChars * sizeof(buf[0]) );
.nCalls = 0, buf[nChars] = '\0';
}; dict_tilesForString( ps->dict, buf, nChars, onFoundTiles, &data );
dict_tilesForString( ps->dict, &ps->pat[ps->patIndex], nChars, onFoundTiles, &data );
if ( 1 == data.nCalls ) { /* found something? We can proceed */
ps->patIndex += nChars;
err = PatErrNone;
break;
}
} }
err = checkData( &data, ps );
} }
return err; /* nothing can go wrong? */ return err; /* nothing can go wrong? */