#ifndef BOARDWIDGET_H #define BOARDWIDGET_H #include <tqwidget.h> #include <tqevent.h> #include <krandomsequence.h> #include "KmTypes.h" #include "Tileset.h" #include "Background.h" #include "BoardLayout.h" typedef struct gamedata { int allow_undo; int allow_redo; UCHAR Board[BoardLayout::depth][BoardLayout::height][BoardLayout::width]; USHORT TileNum; USHORT MaxTileNum; UCHAR Mask[BoardLayout::depth][BoardLayout::height][BoardLayout::width]; UCHAR hilighted[BoardLayout::depth][BoardLayout::height][BoardLayout::width]; POSITION MoveList[BoardLayout::maxTiles]; void putTile( short e, short y, short x, UCHAR f ) { Board[e][y][x] = Board[e][y+1][x] = Board[e][y+1][x+1] = Board[e][y][x+1] = f; } void putTile( POSITION& pos ) { putTile( pos.e, pos.y, pos.x, pos.f ); } bool tilePresent(int z, int y, int x) { return(Board[z][y][x]!=0 && Mask[z][y][x] == '1'); } bool partTile(int z, int y, int x) { return (Board[z][y][x] != 0); } int shadowHeight(int z, int y, int x) { if ((z>=BoardLayout::depth||y>=BoardLayout::height||x>=BoardLayout::width)) return 0; if ((y < 0) || (x < 0)) return 0; int h=0; for (int e=z; e<BoardLayout::depth; e++) { if (Board[e][y][x] && Mask[e][y][x]) { h++; } else { return h; } } return h; } } GAMEDATA; #define ANIMSPEED 200 // tiles symbol names: #define TILE_OFFSET 2 #define TILE_CHARACTER ( 0 + TILE_OFFSET) #define TILE_BAMBOO ( 9 + TILE_OFFSET) #define TILE_ROD (18 + TILE_OFFSET) #define TILE_SEASON (27 + TILE_OFFSET) #define TILE_WIND (31 + TILE_OFFSET) #define TILE_DRAGON (36 + TILE_OFFSET) #define TILE_FLOWER (39 + TILE_OFFSET) #define ID_GAME_TIMER 999 /** * @author Mathias Mueller */ class BoardWidget : public TQWidget { Q_OBJECT public: BoardWidget( TQWidget* parent = 0, const char *name = 0 ); ~BoardWidget(); void calculateNewGame(int num = -1 ); int undoMove(); void redoMove(); void startDemoMode(); void stopDemoMode(); void pause(); void gameLoaded(); void animateMoveList(); void setShowMatch( bool ); void tileSizeChanged(); long getGameNum() {return gameGenerationNum;} TQString &getBoardName(){return theBoardLayout.getFilename();} TQString &getLayoutName() {return theBoardLayout.getFilename();} public slots: void loadSettings(); void saveSettings(); void shuffle(); void helpMove(); void helpMoveTimeout(); void helpMoveStop(); void demoMoveTimeout(); void matchAnimationTimeout(); void setDisplayedWidth(); bool loadTileset ( const TQString & ); bool loadBoardLayout( const TQString& ); bool loadBoard ( ); void updateScaleMode (); void drawBoard(bool deferUpdate = true); bool loadBackground ( const TQString&, bool bShowError = true ); signals: void statusTextChanged ( const TQString&, long ); void tileNumberChanged ( int iMaximum, int iCurrent, int iLeft ); void demoModeChanged ( bool bActive ); void gameCalculated(); void gameOver(unsigned short removed, unsigned short cheats); protected: void getFileOrDefault(TQString filename, TQString type, TQString &res); void shadowArea(int z, int y, int x, int sx, int sy, int rx, int ry, TQPixmap *src); void shadowTopLeft(int depth, int sx, int sy, int rx, int ry,TQPixmap *src, bool flag); void shadowBotRight(int depth, int sx, int sy, int rx, int ry,TQPixmap *src, bool flag); void paintEvent ( TQPaintEvent* ); void mousePressEvent ( TQMouseEvent* ); void setStatusText ( const TQString& ); void cancelUserSelectedTiles(); void drawTileNumber(); void hilightTile ( POSITION&, bool on=true, bool refresh=true ); void putTile ( POSITION& , bool refresh = true); void removeTile ( POSITION& , bool refresh = true); void setRemovedTilePair(POSITION &a, POSITION &b); void clearRemovedTilePair(POSITION &a, POSITION &b); void transformPointToPosition( const TQPoint&, POSITION& ); bool isMatchingTile( POSITION&, POSITION& ); bool generateStartPosition2(); bool findMove( POSITION&, POSITION& ); int moveCount( ); short findAllMatchingTiles( POSITION& ); void stopMatchAnimation(); void stackTiles(unsigned char t, unsigned short h, unsigned short x,unsigned short y); void initialiseRemovedTiles(); int requiredWidth(); int requiredHeight(); void calcShadow(int e, int y, int x, int &left, int &right, int &corn); // new bits for game generation void randomiseFaces(); int tilesAllocated; int tilesUsed; void getFaces(POSITION &a, POSITION &b); UCHAR tilePair[144]; KRandomSequence random; Tileset theTiles; Background theBackground; BoardLayout theBoardLayout; int iPosCount; // count of valid positions in PosTable POSITION PosTable[BoardLayout::maxTiles]; // Table of all possible positions POSITION MouseClickPos1, MouseClickPos2; POSITION TimerPos1, TimerPos2; enum STATES { Stop, Demo, Help, Animation, Match } TimerState; int iTimerStep; short matchCount; bool showMatch; bool showHelp; TQTimer *timer; // offscreen draw area. TQPixmap backBuffer; // pixmap to render to bool updateBackBuffer; // does board need redrawing. Not if it is just a repaint bool gamePaused; // storage for hiscore claculation unsigned short cheatsUsed; // seed for the random number generator used for this game long gameGenerationNum; // storage to keep track of removed tiles unsigned char removedCharacter[9]; unsigned char removedBamboo[9]; unsigned char removedRod[9]; unsigned char removedDragon[3]; unsigned char removedWind[9]; unsigned char removedFlower[4]; unsigned char removedSeason[4]; // new bits for new game generation, with solvability int numTiles; POSITION tilePositions[BoardLayout::maxTiles]; DEPENDENCY positionDepends[BoardLayout::maxTiles]; void generateTilePositions(); void generatePositionDepends(); int tileAt(int x, int y, int z); bool generateSolvableGame(); bool onlyFreeInLine(int position); int selectPosition(int lastPosition); void placeTile(int position, int tile); void updateDepend(int position); public: GAMEDATA Game; }; #endif // BOARDWIDGET_H