mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
266 lines
10 KiB
C
266 lines
10 KiB
C
/* -*- fill-column: 78; compile-command: "cd ../linux && make -j MEMDEBUG=TRUE"; -*- */
|
|
/*
|
|
* Copyright 1997 - 2009 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.
|
|
*/
|
|
|
|
#ifndef _MODEL_H_
|
|
#define _MODEL_H_
|
|
|
|
#include "comtypes.h"
|
|
#include "dictnry.h"
|
|
#include "mempool.h"
|
|
|
|
#ifdef CPLUS
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define MAX_ROWS 16
|
|
#define MAX_COLS 16
|
|
#define NUMCOLS_NBITS 4
|
|
|
|
#ifdef EIGHT_TILES
|
|
#define MAX_TRAY_TILES 8
|
|
#define NTILES_NBITS 4
|
|
#else
|
|
#define MAX_TRAY_TILES 7
|
|
#define NTILES_NBITS 3
|
|
#endif
|
|
|
|
/* Try making this 0, as some local rules, e.g. Spanish, allow. Will need to
|
|
* add UI to limit the number of tiles selected to that remaining in the pool.
|
|
*/
|
|
#define MIN_TRADE_TILES MAX_TRAY_TILES
|
|
|
|
/* apply to CellTile */
|
|
#define TILE_VALUE_MASK 0x003F
|
|
#define TILE_BLANK_BIT 0x0040
|
|
#define IS_BLANK(t) (((t)&TILE_BLANK_BIT)!= 0)
|
|
#define TILE_EMPTY_BIT 0x0080
|
|
#define TILE_PENDING_BIT 0x0100
|
|
#define PREV_MOVE_BIT 0x200
|
|
|
|
#define CELL_OWNER_MASK 0x0C00
|
|
#define CELL_OWNER_OFFSET 10
|
|
#define CELL_OWNER(t) (((t)&CELL_OWNER_MASK) >> CELL_OWNER_OFFSET)
|
|
|
|
#define MAX_UNIQUE_TILES 64 /* max tile non-blank faces */
|
|
#define MAX_NUM_BLANKS 4
|
|
|
|
/* Used by scoring code and engine as fast representation of moves. */
|
|
typedef struct MoveInfoTile {
|
|
XP_U8 varCoord; /* 5 bits ok (0-16 for 17x17 board) */
|
|
Tile tile; /* 6 bits will do */
|
|
} MoveInfoTile;
|
|
|
|
typedef struct MoveInfo {
|
|
XP_U8 nTiles; /* 4 bits: 0-7 */
|
|
XP_U8 commonCoord; /* 5 bits: 0-16 if 17x17 possible */
|
|
XP_Bool isHorizontal; /* 1 bit */
|
|
/* If this is to go on an undo stack, we need player num here, or the code
|
|
has to keep track of it *and* there must be exactly one entry per
|
|
player per turn. */
|
|
MoveInfoTile tiles[MAX_TRAY_TILES];
|
|
} MoveInfo;
|
|
|
|
typedef XP_U8 TrayTile;
|
|
typedef struct TrayTileSet {
|
|
XP_U8 nTiles;
|
|
TrayTile tiles[MAX_TRAY_TILES];
|
|
} TrayTileSet;
|
|
|
|
typedef struct BlankQueue {
|
|
XP_U16 nBlanks;
|
|
XP_U8 col[MAX_NUM_BLANKS];
|
|
XP_U8 row[MAX_NUM_BLANKS];
|
|
} BlankQueue;
|
|
|
|
typedef XP_U8 TileBit; /* bits indicating selection of tiles in tray */
|
|
#define ALLTILES ((TileBit)~(0xFF<<(MAX_TRAY_TILES)))
|
|
|
|
#define ILLEGAL_MOVE_SCORE (-1)
|
|
|
|
#define EMPTY_TILE TILE_EMPTY_BIT
|
|
#define TILE_IS_EMPTY(t) (((t)&TILE_EMPTY_BIT)!=0)
|
|
#define REVERSED_TILE TILE_PENDING_BIT /* reuse that bit for tile drawing
|
|
only */
|
|
|
|
|
|
ModelCtxt* model_make( MPFORMAL DictionaryCtxt* dict, XW_UtilCtxt* util,
|
|
XP_U16 nCols, XP_U16 nRows );
|
|
|
|
ModelCtxt* model_makeFromStream( MPFORMAL XWStreamCtxt* stream,
|
|
DictionaryCtxt* dict, XW_UtilCtxt* util );
|
|
|
|
void model_writeToStream( ModelCtxt* model, XWStreamCtxt* stream );
|
|
|
|
void model_init( ModelCtxt* model, XP_U16 nCols, XP_U16 nRows );
|
|
void model_destroy( ModelCtxt* model );
|
|
void model_setNPlayers( ModelCtxt* model, XP_U16 numPlayers );
|
|
|
|
void model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict );
|
|
DictionaryCtxt* model_getDictionary( ModelCtxt* model );
|
|
|
|
XP_Bool model_getTile( const ModelCtxt* model, XP_U16 col, XP_U16 row,
|
|
XP_Bool getPending, XP_S16 turn,
|
|
Tile* tile, XP_Bool* isBlank,
|
|
XP_Bool* isPending, XP_Bool* isRecent );
|
|
|
|
void model_listPlacedBlanks( ModelCtxt* model, XP_U16 turn,
|
|
XP_Bool includePending, BlankQueue* bcp );
|
|
|
|
XP_U16 model_getCellOwner( ModelCtxt* model, XP_U16 col, XP_U16 row );
|
|
|
|
void model_assignPlayerTiles( ModelCtxt* model, XP_S16 turn,
|
|
TrayTileSet* tiles );
|
|
Tile model_getPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index );
|
|
|
|
Tile model_removePlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index );
|
|
void model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index,
|
|
Tile tile );
|
|
void model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur,
|
|
XP_S16 indexNew );
|
|
|
|
/* 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 );
|
|
|
|
XP_U16 model_getNumTilesInTray( ModelCtxt* model, XP_S16 turn );
|
|
XP_U16 model_getNumTilesTotal( ModelCtxt* model, XP_S16 turn );
|
|
void model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
|
XP_U16 col, XP_U16 row, XP_U16 trayOffset );
|
|
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_S16 model_trayContains( ModelCtxt* model, XP_S16 turn, Tile tile );
|
|
|
|
|
|
XP_U16 model_numRows( const ModelCtxt* model );
|
|
XP_U16 model_numCols( const ModelCtxt* model );
|
|
|
|
/* XP_U16 model_numTilesCurrentTray( ModelCtxt* model ); */
|
|
/* Tile model_currentTrayTile( ModelCtxt* model, XP_U16 index ); */
|
|
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 );
|
|
|
|
void model_getCurrentMoveTile( ModelCtxt* model, XP_S16 turn, XP_S16* index,
|
|
Tile* tile, XP_U16* col, XP_U16* row,
|
|
XP_Bool* isBlank );
|
|
|
|
void model_commitTurn( ModelCtxt* model, XP_S16 player,
|
|
TrayTileSet* newTiles );
|
|
void model_commitRejectedPhony( ModelCtxt* model, XP_S16 player );
|
|
void model_makeTileTrade( ModelCtxt* model, XP_S16 player,
|
|
TrayTileSet* oldTiles, TrayTileSet* newTiles );
|
|
|
|
XP_Bool model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
|
|
XP_U16 nMovesSought, XP_U16* turn,
|
|
XP_S16* moveNum );
|
|
void model_rejectPreviousMove( ModelCtxt* model, PoolContext* pool,
|
|
XP_U16* turn );
|
|
|
|
void model_trayToStream( ModelCtxt* model, XP_S16 turn,
|
|
XWStreamCtxt* stream );
|
|
void model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
|
|
XWStreamCtxt* stream);
|
|
void model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
|
|
XWStreamCtxt* stream );
|
|
void model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
|
|
MoveInfo* newMove );
|
|
|
|
void model_resetCurrentTurn( ModelCtxt* model, XP_S16 turn );
|
|
|
|
/********************* notification ********************/
|
|
typedef void (*BoardListener)(void* data, XP_U16 turn, XP_U16 col,
|
|
XP_U16 row, XP_Bool added );
|
|
void model_setBoardListener( ModelCtxt* model, BoardListener bl,
|
|
void* data );
|
|
typedef void (*TrayListener)( void* data, XP_U16 turn,
|
|
XP_S16 index1, XP_S16 index2 );
|
|
void model_setTrayListener( ModelCtxt* model, TrayListener bl,
|
|
void* data );
|
|
typedef void (*DictListener)( void* data, const DictionaryCtxt* oldDict,
|
|
const DictionaryCtxt* newDict );
|
|
void model_setDictListener( ModelCtxt* model, DictListener dl,
|
|
void* data );
|
|
void model_foreachPendingCell( ModelCtxt* model, XP_S16 turn,
|
|
BoardListener bl, void* data );
|
|
void model_foreachPrevCell( ModelCtxt* model, BoardListener bl, void* data );
|
|
|
|
void model_writeGameHistory( ModelCtxt* model, XWStreamCtxt* stream,
|
|
ServerCtxt* server, /* for player names */
|
|
XP_Bool gameOver );
|
|
|
|
/* for the tile values dialog: total all the tiles in players trays and
|
|
tentatively placed on the board. */
|
|
void model_countAllTrayTiles( ModelCtxt* model, XP_U16* counts,
|
|
XP_S16 excludePlayer );
|
|
|
|
/********************* scoring ********************/
|
|
|
|
typedef XP_Bool (*WordNotifierProc)( XP_UCHAR* word, void* closure );
|
|
typedef struct WordNotifierInfo {
|
|
WordNotifierProc proc;
|
|
void* closure;
|
|
} WordNotifierInfo;
|
|
|
|
XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
|
|
XWStreamCtxt* stream, XP_S16* score );
|
|
XP_S16 model_getPlayerScore( ModelCtxt* model, XP_S16 player );
|
|
|
|
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
|
|
XP_UCHAR* expl, XP_U16* explLen );
|
|
|
|
/* Have there been too many passes (so game should end)? */
|
|
XP_Bool model_recentPassCountOk( ModelCtxt* model );
|
|
|
|
XP_Bool model_checkMoveLegal( ModelCtxt* model, XP_S16 player,
|
|
XWStreamCtxt* stream,
|
|
WordNotifierInfo* notifyInfo );
|
|
|
|
typedef struct _ScoresArray { XP_S16 arr[MAX_NUM_PLAYERS]; } ScoresArray;
|
|
void model_figureFinalScores( ModelCtxt* model, ScoresArray* scores,
|
|
ScoresArray* tilePenalties );
|
|
|
|
/* figureMoveScore is meant only for the engine's use */
|
|
XP_U16 figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo,
|
|
EngineCtxt* engine, XWStreamCtxt* stream,
|
|
WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord );
|
|
|
|
/********************* persistence ********************/
|
|
#ifdef INCLUDE_IO_SUPPORT
|
|
void model_load( ModelCtxt* model, XP_Stream* inStream );
|
|
void model_store( ModelCtxt* model, XP_Stream* outStream );
|
|
#endif
|
|
|
|
|
|
/* a utility function needed by server too. Not a clean design, this. */
|
|
void model_packTilesUtil( ModelCtxt* model, PoolContext* pool,
|
|
XP_Bool includeBlank,
|
|
XP_U16* nUsed, XP_UCHAR4* texts,
|
|
Tile* tiles );
|
|
|
|
|
|
#ifdef CPLUS
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|