/* -*- 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