1 | /* **************************************************************************** |
2 | Copyright 2012 Ian Wadham <iandw.au@gmail.com> |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or |
7 | (at your option) any later version. |
8 | |
9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | **************************************************************************** */ |
18 | #ifndef AI_BOX_H |
19 | #define AI_BOX_H |
20 | |
21 | #include "ai_globals.h" // Include Player enum. |
22 | |
23 | #include <QObject> |
24 | #include <QList> |
25 | |
26 | /** |
27 | * Class AI_Box |
28 | * |
29 | * @short The Box AI algorithms |
30 | */ |
31 | |
32 | // Minimum and maximum size of cube box. Must be consistent with settings.ui. |
33 | const int minSide = 3; |
34 | const int maxSide = 15; |
35 | |
36 | class AI_Box : public QObject |
37 | { |
38 | Q_OBJECT |
39 | public: |
40 | /** |
41 | * The KJumpingCube AI_Box constructor. |
42 | */ |
43 | AI_Box (QObject * parent = 0, int side = 5); |
44 | virtual ~AI_Box(); |
45 | |
46 | int side() const { return m_side; } |
47 | Player owner (int index) const |
48 | { return (((index >= 0) && (index < m_nCubes)) ? |
49 | m_owners [index] : Nobody); } |
50 | int value (int index) const |
51 | { return (((index >= 0) && (index < m_nCubes)) ? |
52 | m_values [index] : 1); } |
53 | int maxValue (int index) const |
54 | { return (((index >= 0) && (index < m_nCubes)) ? |
55 | m_maxValues [index] : 4); } |
56 | |
57 | // For performance, avoid setOwner() and setValue() in the game engine (AI). |
58 | // However, they are good to use when loading a saved game, for example. |
59 | void setOwner (int index, Player owner) |
60 | { if ((index >= 0) && (index < m_nCubes) && |
61 | (owner >= Nobody) && (owner <= Two)) { |
62 | if (owner != m_owners [index]) { |
63 | m_cubesToWin [m_owners [index]] ++; |
64 | m_cubesToWin [owner] --; |
65 | } |
66 | m_owners [index] = owner; |
67 | } |
68 | } |
69 | void setValue (int index, int value) |
70 | { if ((index >= 0) && (index < m_nCubes) && |
71 | (value >= 1)) { |
72 | m_values [index] = value; |
73 | } |
74 | } |
75 | |
76 | // This struct is passed to doMove() and is used to store |
77 | // everything that is needed by undoMove() to actually undo it. |
78 | struct MoveUndodata { |
79 | Player oldPlayer; // The player previously to move in the position |
80 | int oldCubesToWin[3]; |
81 | quint16 changedCubes[maxSide * maxSide]; // 8 bits index, 4 bits owner and 4 bits value |
82 | // end with 0xffff |
83 | }; |
84 | |
85 | bool doMove (Player player, int index, |
86 | MoveUndodata * undodata = 0, QList<int> * steps = 0); |
87 | void undoMove (MoveUndodata * undodata); |
88 | #if AILog > 0 |
89 | void printBox(); |
90 | #endif |
91 | |
92 | void copyPosition (Player player, bool isAI, int index); |
93 | bool undoPosition (Player & player, bool & isAI, int & index); |
94 | bool undoPosition (Player & player); |
95 | bool redoPosition (Player & player, bool & isAI, int & index); |
96 | void initPosition (const AI_Box * box, Player player, bool isAI); |
97 | |
98 | void clear(); |
99 | |
100 | protected: |
101 | int m_side; |
102 | int m_nCubes; |
103 | Player * m_owners; |
104 | int * m_values; |
105 | int * m_maxValues; |
106 | int * m_neighbors; |
107 | |
108 | void resizeBox (int side); |
109 | |
110 | private: |
111 | typedef struct { |
112 | Player player; |
113 | bool isAI; |
114 | int index; |
115 | int nCubes; |
116 | Player * owners; |
117 | int * values; |
118 | } Position; |
119 | |
120 | int m_cubesToWin [3]; |
121 | int * m_stack; |
122 | int m_stackPtr; |
123 | |
124 | QList<Position *> m_undoList; |
125 | int m_undoIndex; |
126 | int m_redoLimit; |
127 | |
128 | void indexNeighbors(); |
129 | |
130 | void save (Position * position, Player player, bool isAI); |
131 | void restore (Position * position); |
132 | void discard (Position * position); |
133 | Position * emptyPosition (int nCubes); |
134 | void createBox (int side); |
135 | void destroyBox(); |
136 | |
137 | QObject * m_parent; // IDW test. |
138 | }; |
139 | |
140 | #endif // AI_BOX_H |
141 | |