summaryrefslogtreecommitdiffstats
path: root/kenolaba/Board.h
blob: b07a9d65621c2ef97f7571525c88af218e3925e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* Class Board - represents a game state
 *
 * Josef Weidendorfer, 28.8.97
*/

#ifndef _BOARD_H_
#define _BOARD_H_

#include <tqobject.h>
#include <krandomsequence.h>
#include "Move.h"

class KConfig;
class EvalScheme;

/* Class for best moves so far */
class PrincipalVariation
{
public:
	PrincipalVariation()
	  { clear(1); }

	enum { maxDepth = 10 };

	bool hasMove(int d)
	  {  return (d>actMaxDepth) ?
		    false : (move[0][d].type != Move::none); }

	Move& operator[](int i)
	  { return (i<0 || i>=maxDepth) ? move[0][0] : move[0][i]; }

	void update(int d, Move& m);
	void clear(int d);
	void setMaxDepth(int d)
	  { actMaxDepth = (d>maxDepth) ? maxDepth-1 : d; }

private:
	Move move[maxDepth][maxDepth];
	int actMaxDepth;

};


class Board : public TQObject
{
  Q_OBJECT
  TQ_OBJECT

 public:
  Board();
  ~Board() {}

  /* different states of one field */
  enum {
    out = 10, free = 0,
    color1, color2, color1bright, color2bright
  };
  enum { AllFields = 121, /* visible + ring of unvisible around */
         RealFields = 61, /* number of visible fields */
         MvsStored = 100 };

  int debug;

  /* fill Board with defined values */
  void begin(int startColor);  /* start of a game */
  void clear();                /* empty board     */

  /* fields can't be changed ! */
  int operator[](int no) const;

  int actColor() const
    { return color; }

  /* Generate list of allowed moves for player with <color>
   * Returns a calculated value for actual position */
  void generateMoves(MoveList& list);

  /* Functions handling moves
   * played moves can be taken back (<MvsStored> moves are remembered) */
  void playMove(const Move& m);
  bool takeBack();    /* if not remembered, do nothing */
  int movesStored();  /* return how many moves are remembered */

  Move& lastMove()
    { return storedMove[storedLast]; }

  void showHist();

  /* Evaluation Scheme to use */
  void setEvalScheme( EvalScheme* scheme = 0);
  EvalScheme* evalScheme() { return _evalScheme; }

  /* Calculate a value for actual position
   * (greater if better for color1) */
  int calcEvaluation();

  /* Evalution is based on values which can be changed
   * a little (so computer's moves aren't always the same) */
  void changeEvaluation();

  void setActColor(int c) { color=c; }
  void setColor1Count(int c) { color1Count = c; }
  void setColor2Count(int c) { color2Count = c; }
  void setField(int i, int v) { field[i] = v; }

  void setSpyLevel(int);

  int getColor1Count() 	  { return color1Count; }
  int getColor2Count() 	  { return color2Count; }

  enum { empty=0, valid, invalid };
  int validState();
  bool isValid() { return (color1Count>8 && color2Count>8); }

  /* Check that color1Count & color2Count is consisten with board */
  bool isConsistent();

  /* Searching best move: alpha/beta search */
  void setDepth(int d)
    { realMaxDepth = d+1; }
  Move& bestMove();

  /* next move in main combination */
  Move& nextMove() { return pv[1]; }

  Move randomMove();
  void stopSearch() { breakOut = true; }

  /* Compressed ASCII representation */
  TQString getState(int);
  int setState(TQString&);

  /* Readable ASCII representation */
  TQString getASCIIState(int);
  int setASCIIState(const TQString&);

  void updateSpy(bool b) { bUpdateSpy = b; }

  /* simple terminal view of position */
  void print(int);

  static int fieldDiffOfDir(int d) { return direction[d]; }

 signals:
  void searchBreak();
  void updateBestMove(Move&,int);

  void update(int,int,Move&,bool);
  void updateBest(int,int,Move&,bool);

 private:
  void setFieldValues();

  /* helper function for generateMoves */
  void generateFieldMoves(int, MoveList&);
  /* helper function for calcValue */
  void countFrom(int,int, MoveTypeCounter&, InARowCounter&);
  /* helper functions for bestMove (recursive search!) */
  int search(int, int, int);
  int search2(int, int, int);

  KRandomSequence random;       /* random generator */

  int field[AllFields];         /* actual board */
  int color1Count, color2Count;
  int color;                    /* actual color */
  Move storedMove[MvsStored];   /* stored moves */
  int storedFirst, storedLast;  /* stored in ring puffer manner */

  /* for search */
  PrincipalVariation pv;
  Move _bestMove;
  bool breakOut, inPrincipalVariation, show, bUpdateSpy;
  int maxDepth, realMaxDepth;

  int spyLevel, spyDepth;
  EvalScheme* _evalScheme;

  /* ratings; semi constant - are rotated by changeRating() */
  static int fieldValue[RealFields];

  /* constant arrays */
  static int startBoard[AllFields];
  static int order[RealFields];
  static int direction[8];

  //  static int stoneValue[6];
  //  static int moveValue[Move::typeCount];
  //  static int connectValue[ConnectCounter::connectCount];
  //  static int ringValue[5], ringDiff[5];
};


inline int Board::operator[](int no) const
{
  return (no<12 || no>120) ? out : field[no];
}

#endif