Subversion Repositories Kolibri OS

Rev

Rev 1805 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1805 yogev_ezra 1
#ifndef _HEADER_BOARD_H
2
#define _HEADER_BOARD_H
3
 
4
#include 
5
#include 
6
#include 
7
#include 
8
#include 
9
#include 
10
#include "position.h"
11
#include "history.h"
12
#include "gr-draw.h"
13
 
14
int ssf = 0;
15
 
16
struct TIntPoint
17
{
18
  TIntPoint() {}
19
  TIntPoint(int x, int y) : x(x), y(y) {}
20
  TIntPoint(const TIntPoint &p) : x(p.x), y(p.y) {}
21
 
22
  TIntPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;}
23
 
24
  int x, y;
25
};
26
 
27
struct TRealPoint
28
{
29
  TRealPoint() {}
30
  TRealPoint(double x, double y) : x(x), y(y) {}
31
  TRealPoint(const TRealPoint &p) : x(p.x), y(p.y) {}
32
  TRealPoint(const TIntPoint &p) : x(p.x), y(p.y) {}
33
 
34
  TRealPoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; return *this;}
35
  TRealPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;}
36
 
37
  TIntPoint Round() {return TIntPoint((int)floor(x+0.5), (int)floor(y+0.5));}
38
 
39
  double x, y;
40
};
41
 
42
struct TProjectivePoint
43
{
44
  TProjectivePoint() {}
45
  TProjectivePoint(const TProjectivePoint &p) : x(p.x), y(p.y), z(p.z) {}
46
  TProjectivePoint(double x, double y, double z = 1) : x(x), y(y), z(z) {}
47
  TProjectivePoint(const TIntPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {}
48
  TProjectivePoint(const TRealPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {}
49
 
50
  int IsCorrect() const {return fabs(x) > Eps || fabs(y) > Eps || fabs(z) > Eps;}
51
  int IsFinite() const;
52
  TRealPoint rpnt() const;
53
  int rpnt(TRealPoint &p) const;
54
  TIntPoint pnt() const;
55
  int pnt(TIntPoint &p) const;
56
 
57
  TProjectivePoint &operator=(const TProjectivePoint &p);
58
  TProjectivePoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; z = 1; return *this;}
59
  TProjectivePoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; z = 1; return *this;}
60
  TProjectivePoint &operator*=(int n) {x *= n; y *= n; z *= n; return *this;}
61
  friend TProjectivePoint operator*(const TProjectivePoint &p, int n)
62
                {return TProjectivePoint(p.x * n, p.y * n, p.z * n);}
63
  friend TProjectivePoint operator*(int n, const TProjectivePoint &p)
64
                {return TProjectivePoint(n * p.x, n * p.y, n * p.z);}
65
  TProjectivePoint &operator*=(double n) {x *= n; y *= n; z *= n; return *this;}
66
  friend TProjectivePoint operator*(const TProjectivePoint &p, double n)
67
                {return TProjectivePoint(p.x * n, p.y * n, p.z * n);}
68
  friend TProjectivePoint operator*(double n, const TProjectivePoint &p)
69
                {return TProjectivePoint(n * p.x, n * p.y, n * p.z);}
70
 
71
  double px() const {return x/z;}
72
  double py() const {return y/z;}
73
 
74
  double x, y, z;
75
 
76
  static const double Eps, FR;
77
};
78
 
79
const double TProjectivePoint::Eps = 1e-12;
80
const double TProjectivePoint::FR = 1e+4;
81
 
82
inline int TProjectivePoint::IsFinite() const
83
{
84
  double fz = fabs(z);
85
  return fz > Eps && fabs(x) < fz * FR && fabs(y) < fz * FR;
86
}
87
 
88
TRealPoint TProjectivePoint::rpnt() const
89
{
90
  if (!IsFinite()) return TRealPoint(0, 0);
91
  else return TRealPoint(x/z, y/z);
92
}
93
 
94
inline int TProjectivePoint::rpnt(TRealPoint &p) const
95
{
96
  if (!IsFinite()) {p.x = 0; p.y = 0; return 0;}
97
  else {p.x = x/z; p.y = y/z; return 1;}
98
}
99
 
100
inline TIntPoint TProjectivePoint::pnt() const
101
{
102
  if (!IsFinite()) return TIntPoint(INT_MIN, INT_MIN);
103
  else return TIntPoint((int)floor(x/z + 0.5), (int)floor(y/z + 0.5));
104
}
105
 
106
inline int TProjectivePoint::pnt(TIntPoint &p) const
107
{
108
  if (!IsFinite()) {p.x = INT_MIN; p.y = INT_MIN; return 0;}
109
  else
110
  {
111
    p.x = (int)floor(x/z + 0.5);
112
    p.y = (int)floor(y/z + 0.5);
113
    return 1;
114
  }
115
}
116
 
117
TProjectivePoint &TProjectivePoint::operator=(const TProjectivePoint &p)
118
{
119
  x = p.x; y = p.y; z = p.z;
120
  return *this;
121
}
122
 
123
 
124
class TProjectiveMap
125
{
126
public:
127
  TProjectiveMap() {}
128
  TProjectiveMap(int n) {p[0].x = p[1].y = p[2].z = n;
129
                p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0;}
130
  TProjectiveMap(const TProjectiveMap &map)
131
                {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2];}
132
  TProjectiveMap(const TProjectivePoint pnt[])
133
                {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2];}
134
  TProjectiveMap(const TProjectivePoint &p0, const TProjectivePoint &p1,
135
                 const TProjectivePoint &p2) {p[0] = p0; p[1] = p1; p[2] = p2;}
136
 
137
  TProjectiveMap &operator=(const TProjectiveMap &map)
138
                {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2]; return *this;}
139
  TProjectiveMap &operator=(const TProjectivePoint pnt[])
140
                {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2]; return *this;}
141
  TProjectiveMap &operator=(int n) {p[0].x = p[1].y = p[2].z = n;
142
                p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0; return *this;}
143
 
144
  TProjectivePoint operator()(const TProjectivePoint &point) const;
145
  friend TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b);
146
  TProjectiveMap &operator*=(const TProjectiveMap &b);
147
  TProjectiveMap &operator*=(int n) {p[0] *= n; p[1] *= n; p[2] *= n; return *this;}
148
  friend TProjectiveMap operator*(const TProjectiveMap &a, int n)
149
                       {return TProjectiveMap(a.p[0] * n, a.p[1] * n, a.p[2] * n);}
150
  friend TProjectiveMap operator*(int n, const TProjectiveMap &b)
151
                       {return TProjectiveMap(n * b.p[0], n * b.p[1], n * b.p[2]);}
152
  TProjectiveMap Reversed() const;
153
  TProjectiveMap &Reverse() {return (*this) = Reversed();}
154
  friend TProjectiveMap operator/(const TProjectiveMap &a, const TProjectiveMap &b)
155
                                 {return a * b.Reversed();}
156
  TProjectiveMap &operator/=(const TProjectiveMap &b) {return (*this) *= b.Reversed();}
157
  TProjectiveMap &operator/=(int n) {if (!n) (*this) = 0; return *this;}
158
  TProjectivePoint Reversed(const TProjectivePoint &point) const;
159
 
160
  TProjectivePoint operator()(double x, double y, double z = 1) const
161
                           {return (*this)(TProjectivePoint(x, y, z));}
162
  TProjectivePoint Reversed(double x, double y, double z = 1) const
163
                           {return Reversed(TProjectivePoint(x, y, z));}
164
 
165
  TProjectiveMap &Set4(const TProjectivePoint &a0, const TProjectivePoint &a1,
166
                       const TProjectivePoint &a2, const TProjectivePoint &a3);
167
  TProjectiveMap &Set4(const TProjectivePoint a[]) {return Set4(a[0], a[1], a[2], a[3]);}
168
  TProjectiveMap &Set4to4(const TProjectivePoint a[], const TProjectivePoint b[])
169
              {return Set4(b) /= TProjectiveMap().Set4(a);}
170
  TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1,
171
                          const TProjectivePoint &a2, const TProjectivePoint &a3,
172
                          const TProjectivePoint b[])
173
              {return Set4(b) /= TProjectiveMap().Set4(a0, a1, a2, a3);}
174
  TProjectiveMap &Set4to4(const TProjectivePoint a[],
175
                          const TProjectivePoint &b0, const TProjectivePoint &b1,
176
                          const TProjectivePoint &b2, const TProjectivePoint &b3)
177
              {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a);}
178
  TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1,
179
                          const TProjectivePoint &a2, const TProjectivePoint &a3,
180
                          const TProjectivePoint &b0, const TProjectivePoint &b1,
181
                          const TProjectivePoint &b2, const TProjectivePoint &b3)
182
              {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a0, a1, a2, a3);}
183
 
184
public:
185
  TProjectivePoint p[3];
186
};
187
 
188
TProjectivePoint TProjectiveMap::operator()(const TProjectivePoint &point) const
189
{
190
  return TProjectivePoint(p[0].x * point.x + p[1].x * point.y + p[2].x * point.z,
191
                          p[0].y * point.x + p[1].y * point.y + p[2].y * point.z,
192
                          p[0].z * point.x + p[1].z * point.y + p[2].z * point.z);
193
}
194
 
195
TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b)
196
{
197
  return TProjectiveMap(a(b.p[0]), a(b.p[1]), a(b.p[2]));
198
}
199
 
200
TProjectiveMap &TProjectiveMap::operator*=(const TProjectiveMap &b)
201
{
202
  TProjectivePoint p0 = (*this)(b.p[0]), p1 = (*this)(b.p[1]), p2 = (*this)(b.p[2]);
203
  p[0] = p0; p[1] = p1; p[2] = p2;
204
  return *this;
205
}
206
 
207
TProjectiveMap TProjectiveMap::Reversed() const
208
{
209
  return TProjectiveMap(TProjectivePoint(p[1].y * p[2].z - p[2].y * p[1].z,
210
           p[2].y * p[0].z - p[0].y * p[2].z, p[0].y * p[1].z - p[1].y * p[0].z),
211
                        TProjectivePoint(p[1].z * p[2].x - p[2].z * p[1].x,
212
           p[2].z * p[0].x - p[0].z * p[2].x, p[0].z * p[1].x - p[1].z * p[0].x),
213
                        TProjectivePoint(p[1].x * p[2].y - p[2].x * p[1].y,
214
           p[2].x * p[0].y - p[0].x * p[2].y, p[0].x * p[1].y - p[1].x * p[0].y));
215
}
216
 
217
TProjectivePoint TProjectiveMap::Reversed(const TProjectivePoint &point) const
218
{
219
  return TProjectivePoint((p[1].y * p[2].z - p[2].y * p[1].z) * point.x +
220
                          (p[1].z * p[2].x - p[2].z * p[1].x) * point.y +
221
                          (p[1].x * p[2].y - p[2].x * p[1].y) * point.z,
222
                 (p[2].y * p[0].z - p[0].y * p[2].z) * point.x +
223
                 (p[2].z * p[0].x - p[0].z * p[2].x) * point.y +
224
                 (p[2].x * p[0].y - p[0].x * p[2].y) * point.z,
225
        (p[0].y * p[1].z - p[1].y * p[0].z) * point.x +
226
        (p[0].z * p[1].x - p[1].z * p[0].x) * point.y +
227
        (p[0].x * p[1].y - p[1].x * p[0].y) * point.z);
228
}
229
 
230
TProjectiveMap &TProjectiveMap::Set4(const TProjectivePoint &a0,
231
   const TProjectivePoint &a1, const TProjectivePoint &a2, const TProjectivePoint &a3)
232
{
233
  p[0] = a0; p[1] = a1; p[2] = a2;
234
  TProjectivePoint K = Reversed(a3);
235
  p[0] *= K.x; p[1] *= K.y; p[2] *= K.z;
236
  return *this;
237
}
238
 
239
 
240
TRealPoint r_circle_pnt[13];
241
TRealPoint r_star_pnt[13];
242
const double r_star_large = 1.2, r_star_small = 0.8;
243
const double r_ch_lines[] = {0.8, 0.7, 0.6, 0.5};
244
 
245
void InitBoardData()
246
{
247
  int i, len;
248
  double a, r;
249
  len = NELEM(r_circle_pnt) - 1;
250
  for (i = 0; i < len; i++)
251
  {
252
    a = 2 * i * M_PI / len;
253
    r_circle_pnt[i].x = cos(a);
254
    r_circle_pnt[i].y = sin(a);
255
  }
256
  r_circle_pnt[len] = r_circle_pnt[0];
257
  len = sizeof(r_star_pnt) / sizeof(r_star_pnt[0]) - 1;
258
  for (i = 0; i < len; i++)
259
  {
260
    a = 2 * i * M_PI / len;
261
    r = (i % 2) ? r_star_small : r_star_large;
262
    r_star_pnt[i].x = cos(a) * r;
263
    r_star_pnt[i].y = sin(a) * r;
264
  }
265
  r_star_pnt[len] = r_star_pnt[0];
266
}
267
 
268
class TChBoard;
269
 
270
class TSomeDraw
271
{
272
public:
273
  TSomeDraw() {}
274
 
275
  virtual void Draw(TGraphDraw *drw, int w, int h) = 0;
276
  virtual void DrawB(TGraphDraw *drw, TChBoard &brd);
277
  virtual TIntPoint GetDSize(int w, int h) {return TIntPoint(INT_MIN, INT_MIN);}
278
};
279
 
280
class TChBoard
281
{
282
public:
283
  TChBoard(int id = 0);
284
 
285
  TProjectiveMap Get4PMap() const;
286
  int GetW() const {return width;}
287
  int GetH() const {return height;}
288
  void ClearWH() {width = -1; height = -1;}
289
  void Resize(int w, int h);
290
  void Resize(TIntPoint size) {Resize(size.x, size.y);}
291
 
292
  TIntPoint PlToWin(double x, double y) const;
293
  TIntPoint PlToWin(TRealPoint rp) const {return PlToWin(rp.x, rp.y);}
294
  TRealPoint WinToPl(int x, int y) const;
295
  TRealPoint WinToPl(TIntPoint p) const {return WinToPl(p.x, p.y);}
296
 
297
  void NewGame();
298
  int CanPlayerMove() const {return !IsPlayView && !game_end && !player[MainPos.wmove];}
299
 
300
  void Draw(TGraphDraw *drw);
301
  int ResizeDraw(TGraphDraw *drw, int w, int h);
302
  int CheckResize(TGraphDraw *drw);
303
  int HaveCheckResize() const {return check_resize;}
304
  void SetCheckResize(int cr) {check_resize = cr;}
305
  int MouseClick(TGraphDraw *drw, int x, int y);
306
  void UnMove(TGraphDraw *drw);
307
 
308
  int CMove(TGraphDraw *drw, int x, int y);
309
  int AutoMove(TGraphDraw *drw, int nmove = 0, int draw_check = 1);
310
 
311
  enum PKey {PNull, PEnter, PLeft, PRight, PUp, PDown};
312
  PKey GetKeySide(PKey key);
313
  int PKeyEvent(TGraphDraw *drw, PKey key = PEnter);
314
protected:
315
  enum TextLineType {TLT_Main, TLT_Move, TLT_Wait, TLT_GameEnd, TLT_WrongMove,
316
                     TLT_PlDidntMove, TLT_PlWrongMove, TLT_WrongColor,
317
                     TLT_WfCell, TLT_WnfCell, TLT_WMustEat, TLT_WMustEatMore,
318
                     TLT_WNoMove, TLT_WChBack, TLT_WNotDm, TLT_WOnlyDiag,
319
                     TLT_WEatYour, TLT_WMoreOne, TLT_WNotDmE, TLT_WMustEatMoreD,
320
                     TLT_WTurnBack};
321
  void GetTextLine(char str[]) const;
322
  void DrawTextLine(TGraphDraw *drw) const;
323
  void LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const;
324
  void DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt,
325
              int L = NELEM(r_ch_lines)) const;
326
  void DrawIL(TGraphDraw *drw, double x0, double y0, int L) const;
327
  void MoveErase();
328
  void CurPointClear(TGraphDraw *drw) const;
329
  void RenewMPos() {if (MainPlay.GetPos(MainPos, CurMoveN) < 0) MainPos.Init();}
330
  void PrintLMove();
331
  void SetNoMove(TGraphDraw *drw = 0, int force = 1);
332
  TextLineType GetTLTfromA(int s) const;
333
  void ChangeTLT(TGraphDraw *drw, TextLineType t);
334
  TextLineType GetSimpleTLT() const;
335
public:
336
  void ResetTextLine(TGraphDraw *drw);
337
  TChPlayer *GetPlayer(int k) const {return player[k];}
338
  void SetPlayer(int k, TChPlayer *pl) {player[k] = pl;}
339
  int GetBottomColor() const {return BottomColor;}
340
  void SetBottomColor(int c) {BottomColor = c & 1;}
341
public:
342
  enum {textlineh = 14, min_brd = 120, max_delt = 20, min_brdsize = 70};
343
  int GetTextLineY() const;
344
  TSomeDraw *GetSomeDraw() const {return some_draw;}
345
  void SetSomeDraw(TSomeDraw *drw) {some_draw = drw;}
346
  TIntPoint GetMinWSize() const {return min_wsize;}
347
  void SetMinWSize(TIntPoint mws) {min_wsize = mws; Resize(width, height);}
348
  void SetMinWSize(int w, int h) {SetMinWSize(TIntPoint(w, h));}
349
  void DrawTimer(TGraphDraw *drw, double t, int wh = 0) const;
350
  int GetNumMove() const {return MainPlay.GetN() - 1;}
351
  int GetCurMoveN() const {return CurMoveN;}
352
  int SetCurMoveN(int n, TGraphDraw *drw = 0);
353
  int SetPlay(const PlayWrite &play);
354
  PlayWrite GetPlay() const {return MainPlay;}
355
  int GetPViewStatus() const {return IsPlayView;}
356
  void SetPViewStatus(int pv) {IsPlayView = pv;}
357
  void GoToCurMove();
358
  int GetGameEnd() const {return game_end;}
359
  void EraseHistory() {hist_inited = 0;}
360
  int ReinitHistory();
361
protected:
362
  double dw_delt, dw_cell;
363
  int width, height;
364
  TProjectiveMap PoleMap;
365
  Position MainPos;
366
  int BottomColor;
367
  unsigned char TheMove[NUM_CELL];
368
  unsigned char Eaten[NUM_CELL];
369
  unsigned char BecameD;
370
  TIntPoint CurPoint;
371
  int game_end;
372
  int check_resize;
373
  TIntPoint delta_size;
374
  TextLineType text_line_type;
375
  PlayWrite MainPlay;
376
  TChPlayer *player[2];
377
  TSomeDraw *some_draw;
378
  TIntPoint min_wsize;
379
  int CurMoveN, IsPlayView;
380
  THistory history;
381
  int hist_inited;
382
};
383
 
384
inline void TSomeDraw::DrawB(TGraphDraw *drw, TChBoard &brd)
385
{
386
  Draw(drw, brd.GetW(), brd.GetH());
387
}
388
 
389
void TChBoard::MoveErase()
390
{
391
  TheMove[0] = 0;
392
  Eaten[0] = 0;
393
  BecameD = 0;
394
}
395
 
396
TChBoard::TChBoard(int id) : history(id)
397
{
398
  InitBoardData();
399
  player[0] = player[1] = 0;
400
  dw_delt = 0.3;
401
  dw_cell = 1;
402
  BottomColor = 0;
403
  check_resize = 0;
404
  delta_size.x = 0; delta_size.y = 0;
405
  some_draw = 0;
406
  min_wsize.x = 80; min_wsize.y = 80;
407
  ClearWH();
408
  Resize(400, 400);
409
  NewGame();
410
}
411
 
412
TProjectiveMap TChBoard::Get4PMap() const
413
{
414
  return TProjectiveMap().Set4(TRealPoint(-dw_delt, -dw_delt),
415
                  TRealPoint(NW_CELL*dw_cell + dw_delt, -dw_delt),
416
                  TRealPoint(NW_CELL*dw_cell + dw_delt, NW_CELL*dw_cell + dw_delt),
417
                  TRealPoint(-dw_delt, NW_CELL*dw_cell + dw_delt));
418
}
419
 
420
void TChBoard::Resize(int w, int h)
421
{
422
  width = w; height = h;
423
  if (width < min_wsize.x) width = min_wsize.x;
424
  if (height < min_wsize.y) height = min_wsize.y;
425
  for (;;)
426
  {
427
    if (some_draw)
428
    {
429
      TIntPoint dsz = some_draw->GetDSize(width, height);
430
      if (dsz.x >= 0 && dsz.y >= 0) delta_size = dsz;
431
    }
432
    int change = 0;
433
    if (width < delta_size.x + min_brdsize)
434
    {
435
      width = delta_size.x + min_brdsize;
436
      change++;
437
    }
438
    if (height < delta_size.y + min_brdsize + textlineh)
439
    {
440
      height = delta_size.y + min_brdsize + textlineh;
441
      change++;
442
    }
443
    if (!some_draw || !change) break;
444
  }
445
  double sx = max_delt, dx = width - 2*sx - delta_size.x;
446
  double sy = max_delt, dy = height - 2*sy - delta_size.y - textlineh;
447
  if (dy < min_brd)
448
  {
449
    double d = (min_brd - dy) / 2;
450
    if (d > sy) d = sy;
451
    sy -= d; dy += 2*d;
452
  }
453
  if (dx < min_brd)
454
  {
455
    double d = (min_brd - dx) / 2;
456
    if (d > sx) d = sx;
457
    sx -= d; dx += 2*d;
458
  }
459
  if (dy > dx) {sy += (dy - dx) / 2; dy = dx;}
460
  double tx = (dx - dy * dy / dx) / 3;
461
  PoleMap.Set4(TRealPoint(sx, sy + dy - 70*ssf), TRealPoint(sx + dx, sy + dy),
462
               TRealPoint(sx + dx - tx, sy), TRealPoint(sx + tx, sy + 40*ssf));
463
  PoleMap /= Get4PMap();
464
}
465
 
466
TIntPoint TChBoard::PlToWin(double x, double y) const
467
{
468
  if (BottomColor == 1) y = NW_CELL*dw_cell - y;
469
  else x = NW_CELL*dw_cell - x;
470
  /**/if (ssf) y += 0.6 * sin(x);/**/
471
  return PoleMap(x, y).pnt();
472
}
473
 
474
TRealPoint TChBoard::WinToPl(int x, int y) const
475
{
476
  TRealPoint rpnt;
477
  if (PoleMap.Reversed(x, y).rpnt(rpnt))
478
  {
479
    /**/if (ssf) rpnt.y -= 0.6 * sin(rpnt.x);/**/
480
    if (BottomColor == 1) rpnt.y = NW_CELL*dw_cell - rpnt.y;
481
    else rpnt.x = NW_CELL*dw_cell - rpnt.x;
482
    return rpnt;
483
  }
484
  else return TRealPoint(-dw_cell - dw_delt, -dw_cell - dw_delt);
485
}
486
 
487
void TChBoard::NewGame()
488
{
489
  int k;
490
  MoveErase();
491
  MainPos.Init();
492
  MainPlay.Clear();
493
  for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[k] = 1;
494
  for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[NUM_CELL - k - 1] = 2;
495
  MainPlay.Add(0, MainPos);
496
  CurMoveN = 0;
497
  text_line_type = TLT_Main;
498
  game_end = 0;
499
  CurPoint.x = -1; CurPoint.y = -1;
500
  IsPlayView = 0;
501
  printf("\nCheckers: New game.\n");
502
  EraseHistory();
503
}
504
 
505
int TChBoard::GetTextLineY() const
506
{
507
  int y = height - (max_delt + textlineh + delta_size.y);
508
  int i, j;
509
  for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++)
510
  {
511
    TRealPoint corner;
512
    corner.x = (2*i - 1) * dw_delt + i * NW_CELL * dw_cell;
513
    corner.y = (2*j - 1) * dw_delt + j * NW_CELL * dw_cell;
514
    TIntPoint wcr = PlToWin(corner);
515
    if (wcr.x != INT_MIN && wcr.y != INT_MIN)
516
    {
517
      if (y < wcr.y) y = wcr.y;
518
    }
519
  }
520
  y -= textlineh;
521
  if (y > height - delta_size.y - 2*textlineh)
522
  {
523
    y = height - delta_size.y - 2*textlineh;
524
  }
525
  return (y + height - delta_size.y) / 2;
526
}
527
 
5123 clevermous 528
#ifdef LANG_RUS
1805 yogev_ezra 529
#define aCheckersGame   "ˆ£à  ¢ è èª¨."
530
#define aRedMoves       "Šà á­ë¥ 室ïâ."
531
#define aBlueMoves      "‘¨­¨¥ 室ïâ."
532
#define aWait           "®¤®¦¤¨â¥."
533
#define aRedWins        "Šà á­ë¥ ¢ë¨£à «¨."
534
#define aBlueWins       "‘¨­¨¥ ¢ë¨£à «¨."
535
#define aDraw           "¨çìï."
536
#define aRed            "Šà á­ë¥ "
537
#define aBlue           "‘¨­¨¥ "
538
#define aMadeWrongMove  "ᤥ« «¨ ­¥¯à ¢¨«ì­ë© 室."
539
#define aNoMove         "­¥ ᬮ£«¨ ᤥ« âì 室."
540
#define aEndGame        "Š®­¥æ ¨£àë."
541
#define aYouWin         " (‚ë ¢ë¨£à «¨)"
542
#define aYouLose        " (‚ë ¯à®¨£à «¨)"
543
#define aRedWin         " (Šà á­ë¥ ¢ë¨£à «¨)"
544
#define aBlueWin        " (‘¨­¨¥ ¢ë¨£à «¨)"
545
#define aWrongMove      "¥¢¥à­ë© 室."
546
#define aNotYourChecker "â® ­¥ ¢ è  è èª ."
547
#define aFreeCell       "â  ª«¥âª  ¯ãáâ ï."
548
#define aNotFreeCell    "˜ èª¨ ¬®£ãâ 室¨âì ⮫쪮 ­  ᢮¡®¤­ë¥ ª«¥âª¨."
549
#define aMustEat        "‚ë ¤®«¦­ë ¢§ïâì è èªã."
550
#define aMustEatMore    "‚ë ¤®«¦­ë ¢§ïâì ¥éñ è èªã."
551
#define aCheckerNoMove  "“ í⮩ è èª¨ ­¥â 室®¢."
552
#define aNoBack         "˜ èª¨ ­¥ 室ïâ ­ § ¤."
553
#define aNotDamka       "â® ­¥ ¤ ¬ª ."
554
#define aOnlyDiag       "˜ èª¨ 室ïâ ⮫쪮 ¯® ¤¨ £®­ «¨."
555
#define aEatYour        "˜ èª¨ ­¥ ¬®£ãâ ¥áâì ᢮¨å."
556
#define aMoreOne        "‚ë ­¥ ¬®¦¥â¥ ¢§ïâì ¡®«¥¥ ®¤­®© è èª¨ §  à §."
557
#define aNoTurnBack     "˜ èª¨ ­¥ ¬®£ãâ à §¢®à ç¨¢ âìáï ­ § ¤ ¯à¨ ¢§ï⨨."
558
#else
559
#define aCheckersGame   "The checkers game."
560
#define aRedMoves       "Red moves."
561
#define aBlueMoves      "Blue moves."
562
#define aWait           "Please wait."
563
#define aRedWins        "Red wins."
564
#define aBlueWins       "Blue wins."
565
#define aDraw           "Draw."
566
#define aRed            "Red "
567
#define aBlue           "Blue "
568
#define aMadeWrongMove  "make a wrong move."
569
#define aNoMove         "could not make a move."
570
#define aEndGame        "End of the game."
571
#define aYouWin         " (You win)"
572
#define aYouLose        " (You lose)"
573
#define aRedWin         " (Red win)"
574
#define aBlueWin        " (Blue win)"
575
#define aWrongMove      "Wrong move."
576
#define aNotYourChecker "It isn't your checker."
577
#define aFreeCell       "The cell is free."
578
#define aNotFreeCell    "Checkers may be moved only on a free cell."
579
#define aMustEat        "You must eat a checker."
580
#define aMustEatMore    "You must eat more checkers."
581
#define aCheckerNoMove  "The checker have no moves."
582
#define aNoBack         "Checkers may not be moved back."
583
#define aNotDamka       "It is not a damka."
584
#define aOnlyDiag       "Checkers may be moved only along diagonal."
585
#define aEatYour        "You may not eat your checkers."
586
#define aMoreOne        "You may not eat more than one checker at a time."
587
#define aNoTurnBack     "Checkers may not turn back when eating."
588
#endif
589
 
590
void TChBoard::GetTextLine(char str[]) const
591
{
592
  str[0] = 0;
593
  int g = (game_end - 1) % 2, h = 0;
594
  switch(text_line_type)
595
  {
596
  case TLT_Main:
597
    strcpy(str, aCheckersGame);
598
    break;
599
  case TLT_Move:
600
    if (MainPos.wmove == 0)
601
    {
602
      strcpy(str, aRedMoves);
603
    }
604
    else strcpy(str, aBlueMoves);
605
    break;
606
  case TLT_Wait:
607
    strcpy(str, aWait);
608
    break;
609
  case TLT_GameEnd:
610
  case TLT_PlDidntMove:
611
  case TLT_PlWrongMove:
612
    if (!game_end) break;
613
    if (text_line_type == TLT_GameEnd)
614
    {
615
      if (game_end == 1) strcpy(str, aRedWins);
616
      else if (game_end == 2) strcpy(str, aBlueWins);
617
      else if (game_end == 5) strcpy(str, aDraw);
618
    }
619
    if (!str[0])
620
    {
621
      if (game_end >= 1 && game_end <= 4)
622
      {
623
        if (g == 0) strcpy(str, aRed);
624
        else strcpy(str, aBlue);
625
        if (text_line_type == TLT_PlWrongMove)
626
        {
627
          strcat(str, aMadeWrongMove);
628
        }
629
        else strcat(str, aNoMove);
630
        h = 1;
631
      }
632
      else strcpy(str, aEndGame);
633
    }
634
    if (game_end >= 1 && game_end <= 4)
635
    {
636
      if (!IsPlayView && player[1-g] && !player[g])
637
      {
638
        strcat(str, aYouWin);
639
      }
640
      else if (!IsPlayView && player[g] && !player[1-g])
641
      {
642
        strcat(str, aYouLose);
643
      }
644
      else if (h && g == 0) strcat(str, aRedWin);
645
      else if (h && g == 1) strcat(str, aBlueWin);
646
    }
647
    break;
648
  case TLT_WrongMove:
649
    strcpy(str, aWrongMove);
650
    break;
651
  case TLT_WrongColor:
652
    strcpy(str, aNotYourChecker);
653
    break;
654
  case TLT_WfCell:
655
    strcpy(str, aFreeCell);
656
    break;
657
  case TLT_WnfCell:
658
    strcpy(str, aNotFreeCell);
659
    break;
660
  case TLT_WMustEat:
661
    strcpy(str, aMustEat);
662
    break;
663
  case TLT_WMustEatMore:
664
  case TLT_WMustEatMoreD:
665
    strcpy(str, aMustEatMore);
666
    break;
667
  case TLT_WNoMove:
668
    strcpy(str, aCheckerNoMove);
669
    break;
670
  case TLT_WChBack:
671
    strcpy(str, aNoBack);
672
    break;
673
  case TLT_WNotDm:
674
  case TLT_WNotDmE:
675
    strcpy(str, aNotDamka);
676
    break;
677
  case TLT_WOnlyDiag:
678
    strcpy(str, aOnlyDiag);
679
    break;
680
  case TLT_WEatYour:
681
    strcpy(str, aEatYour);
682
    break;
683
  case TLT_WMoreOne:
684
    strcpy(str, aMoreOne);
685
    break;
686
  case TLT_WTurnBack:
687
    strcpy(str, aNoTurnBack);
688
    break;
689
  }
690
}
691
 
692
void TChBoard::DrawTextLine(TGraphDraw *drw) const
693
{
694
  if (!drw || !drw->IsDraw()) return;
695
  char str[100];
696
  GetTextLine(str);
697
  if (str[0]) drw->DrawText(10, GetTextLineY(), str);
698
}
699
 
700
void TChBoard::ResetTextLine(TGraphDraw *drw)
701
{
702
  if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move);
703
}
704
 
705
void TChBoard::LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const
706
{
707
  if (!drw || !drw->IsDraw()) return;
708
  TIntPoint p1 = PlToWin(x1, y1), p2 = PlToWin(x2, y2);
709
  if (p1.x != INT_MIN && p1.y != INT_MIN && p2.x != INT_MIN && p2.y != INT_MIN)
710
  {
711
    drw->DrawLine(p1.x, p1.y, p2.x, p2.y);
712
  }
713
}
714
 
715
void TChBoard::DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, int L) const
716
{
717
  if (!drw || !drw->IsDraw()) return;
718
  int i, j;
719
  for (j = 0; j < L; j++)
720
  {
721
    for (i = 0; i < npnt - 1; i++)
722
    {
723
      LineB(drw, x0 + pnt[i].x * dw_cell * r_ch_lines[j] / 2,
724
                 y0 + pnt[i].y * dw_cell * r_ch_lines[j] / 2,
725
                 x0 + pnt[i+1].x * dw_cell * r_ch_lines[j] / 2,
726
                 y0 + pnt[i+1].y * dw_cell * r_ch_lines[j] / 2);
727
    }
728
  }
729
}
730
 
731
void TChBoard::DrawIL(TGraphDraw *drw, double x0, double y0, int L) const
732
{
733
  if (!drw || !drw->IsDraw()) return;
734
  int i, j;
735
  if (L == 0 || L == 1)
736
  {
737
    const int numDST[2] = {2, 4};
738
    const double DST[2][4] = {{0.96, 0.88}, {0.8, 0.76, 0.72, 0.68}};
739
    const int MULT[4][4] = {{-1, -1, -1, 1}, {-1, 1, 1, 1},
740
                            {-1, -1, 1, -1}, {1, -1, 1, 1}};
741
    for (i = 0; i < numDST[L]; i++) for (j = 0; j < 4; j++)
742
    {
743
      LineB(drw, x0 + dw_cell * DST[L][i] * MULT[j][0] / 2,
744
                 y0 + dw_cell * DST[L][i] * MULT[j][1] / 2,
745
                 x0 + dw_cell * DST[L][i] * MULT[j][2] / 2,
746
                 y0 + dw_cell * DST[L][i] * MULT[j][3] / 2);
747
    }
748
  }
749
  else if (L == 2)
750
  {
751
    const double DP[] = {0.85, 0.90, 0.95};
752
    const int numDP = NELEM(DP);
753
    for (i = 0; i < numDP; i++) for (j = -1; j <= 1; j += 2)
754
    {
755
      LineB(drw, x0 - j * dw_cell * DP[i] / 2,
756
                 y0 - dw_cell * DP[numDP - i - 1] / 2,
757
                 x0 + j * dw_cell * DP[numDP - i - 1] / 2,
758
                 y0 + dw_cell * DP[i] / 2);
759
    }
760
  }
761
}
762
 
763
void TChBoard::Draw(TGraphDraw *drw)
764
{
765
  if (!drw || !drw->IsDraw()) return;
766
  if (CheckResize(drw)) drw->DrawClear();
767
  int i, j, k, kn;
768
  unsigned long black = drw->GetBlackColor();
769
  unsigned long red = drw->CreateColor(65535u, 0, 0);
770
  unsigned long green = drw->CreateColor(0, 49151u, 0);
771
  unsigned long blue = drw->CreateColor(0, 0, 65535u);
772
  drw->SetColor(black);
773
  for (i = -1; i <= NW_CELL + 1; i++) for (j = -1; j <= NW_CELL; j++)
774
  {
775
    if (i < 0 || i > NW_CELL || j >= 0 && j < NW_CELL)
776
    {
777
      double mval = dw_cell * NW_CELL + dw_delt;
778
      double x, y0, y1;
779
      if (i < 0) x = -dw_delt;
780
      else if (i > NW_CELL) x = mval;
781
      else x = i * dw_cell;
782
      if (j < 0) y0 = -dw_delt;
783
      else if (j > NW_CELL) y0 = mval;
784
      else y0 = j * dw_cell;
785
      if ((j+1) < 0) y1 = -dw_delt;
786
      else if ((j+1) > NW_CELL) y1 = mval;
787
      else y1 = (j+1) * dw_cell;
788
      LineB(drw, x, y0, x, y1);
789
    }
790
  }
791
  for (i = -1; i <= NW_CELL; i++) for (j = -1; j <= NW_CELL + 1; j++)
792
  {
793
    if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL)
794
    {
795
      double mval = dw_cell * NW_CELL + dw_delt;
796
      double x0, x1, y;
797
      if (i < 0) x0 = -dw_delt;
798
      else if (i > NW_CELL) x0 = mval;
799
      else x0 = i * dw_cell;
800
      if ((i+1) < 0) x1 = -dw_delt;
801
      else if ((i+1) > NW_CELL) x1 = mval;
802
      else x1 = (i+1) * dw_cell;
803
      if (j < 0) y = -dw_delt;
804
      else if (j > NW_CELL) y = mval;
805
      else y = j * dw_cell;
806
      LineB(drw, x0, y, x1, y);
807
    }
808
  }
809
  for (i = -1; i <= 1; i += 2)
810
  {
811
    drw->SetColor((i < 0) ? red : blue);
812
    for (j = -1; j <= 1; j += 2)
813
    {
814
      double c = dw_cell * NW_CELL / 2;
815
      double d = (dw_cell/2 > dw_delt) ? dw_delt : dw_cell/2;
816
      LineB(drw, c + j * (c + 0.5*d), c + i * (c - 0.5*d),
817
                  c + j * (c + 0.5*d), c + i * (c - 3.5*d));
818
      LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d),
819
                  c + j * (c + 0.2*d), c + i * (c - 2.5*d));
820
      LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d),
821
                  c + j * (c + 0.8*d), c + i * (c - 2.5*d));
822
      LineB(drw, c + j * (c + 0.2*d), c + i * (c - 2.5*d),
823
                  c + j * (c + 0.8*d), c + i * (c - 2.5*d));
824
    }
825
  }
826
  for (i = 0; i < NW_CELL; i++) for (j = 0; j < NW_CELL; j++)
827
  {
828
    if (!PoleCpos(i, j))
829
    {
830
      drw->SetColor(black);
831
      LineB(drw, (i+0.33) * dw_cell, j * dw_cell, (i+0.33) * dw_cell, (j+1) * dw_cell);
832
      LineB(drw, (i+0.67) * dw_cell, j * dw_cell, (i+0.67) * dw_cell, (j+1) * dw_cell);
833
      LineB(drw, i * dw_cell, (j+0.33) * dw_cell, (i+1) * dw_cell, (j+0.33) * dw_cell);
834
      LineB(drw, i * dw_cell, (j+0.67) * dw_cell, (i+1) * dw_cell, (j+0.67) * dw_cell);
835
      LineB(drw, i * dw_cell, j * dw_cell, (i+1) * dw_cell, (j+1) * dw_cell);
836
      LineB(drw, (i+1) * dw_cell, j * dw_cell, i * dw_cell, (j+1) * dw_cell);
837
    }
838
    else
839
    {
840
      k = PoleToNum(i, j);
841
      kn = MainPos.SH[k];
842
      if (TheMove[0] > 0 && k == TheMove[1])
843
      {
844
        if (kn == 1 || kn == 2) kn = 5;
845
        else if (kn == 3 || kn == 4) kn = 6;
846
      }
847
      if (TheMove[0] > 0 && k == TheMove[TheMove[0]])
848
      {
849
        kn = MainPos.SH[TheMove[1]];
850
        if (kn <= 2 && BecameD) kn += 2;
851
      }
852
      if (kn == 1)
853
      {
854
        drw->SetColor(red);
855
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
856
                     r_circle_pnt, NELEM(r_circle_pnt));
857
      }
858
      else if (kn == 2)
859
      {
860
        drw->SetColor(blue);
861
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
862
                     r_circle_pnt, NELEM(r_circle_pnt));
863
      }
864
      else if (kn == 3)
865
      {
866
        drw->SetColor(red);
867
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
868
                     r_star_pnt, NELEM(r_star_pnt));
869
      }
870
      else if (kn == 4)
871
      {
872
        drw->SetColor(blue);
873
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
874
                     r_star_pnt, NELEM(r_star_pnt));
875
      }
876
      else if (kn == 5)
877
      {
878
        drw->SetColor(green);
879
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
880
                  r_circle_pnt, NELEM(r_circle_pnt), 2);
881
      }
882
      else if (kn == 6)
883
      {
884
        drw->SetColor(green);
885
        DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell,
886
                  r_circle_pnt, NELEM(r_circle_pnt), 2);
887
      }
888
    }
889
  }
890
  for (k = 1; k <= Eaten[0]; k++)
891
  {
892
    if (TheMove[0] <= 0 || Eaten[k] != TheMove[TheMove[0]])
893
    {
894
      NumToPole(Eaten[k], i, j);
895
      kn = MainPos.SH[Eaten[k]];
896
      if (kn)
897
      {
898
        if (kn == 1 || kn == 3) drw->SetColor(blue);
899
        else if (kn == 2 || kn == 4) drw->SetColor(red);
900
        DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 2);
901
      }
902
    }
903
  }
904
  if (TheMove[0] > 0)
905
  {
906
    NumToPole(TheMove[TheMove[0]], i, j);
907
    drw->SetColor(green);
908
    DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 1);
909
  }
910
  if (CurPoint.x >= 0 && CurPoint.y >= 0)
911
  {
912
    drw->SetColor(green);
913
    DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0);
914
  }
915
  drw->SetColor(black);
916
  DrawTextLine(drw);
917
  if (some_draw) some_draw->DrawB(drw, *this);
918
  drw->FreeColor(red);
919
  drw->FreeColor(green);
920
  drw->FreeColor(blue);
921
}
922
 
923
int TChBoard::ResizeDraw(TGraphDraw *drw, int w, int h)
924
{
925
  int w0 = width, h0 = height;
926
  Resize(w, h);
927
  if (drw && drw->IsDraw() && (width != w0 || height != h0))
928
  {
929
    drw->DrawClear();
930
    Draw(drw);
931
    return 1;
932
  }
933
  else return 0;
934
}
935
 
936
int TChBoard::CheckResize(TGraphDraw *drw)
937
{
938
  if (!drw || !check_resize) return 0;
939
  int w, h;
940
  drw->GetSize(w, h);
941
  if (w < 0 || h < 0) return 0;
942
  int w0 = width, h0 = height;
943
  Resize(w, h);
944
  return width != w0 || height != h0;
945
}
946
 
947
void TChBoard::CurPointClear(TGraphDraw *drw) const
948
{
949
  if (!drw || !drw->IsDraw()) return;
950
  drw->SetColor(drw->GetWhiteColor());
951
  DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0);
952
}
953
 
954
int TChBoard::MouseClick(TGraphDraw *drw, int x, int y)
955
{
956
  TRealPoint rpnt = WinToPl(x, y);
957
  if (rpnt.x < -dw_delt || rpnt.y < -dw_delt ||
958
      rpnt.x > NW_CELL*dw_cell + dw_delt ||
959
      rpnt.y > NW_CELL*dw_cell + dw_delt) return -1;
960
  if (CurPoint.x >= 0 && CurPoint.y >= 0)
961
  {
962
    CurPointClear(drw);
963
    CurPoint.x = -1; CurPoint.y = -1;
964
    Draw(drw);
965
  }
966
  ResetTextLine(drw);
967
  if (AutoMove(drw)) return 3;
968
  if (!CanPlayerMove()) return 0;
969
  int i = (int)floor(rpnt.x / dw_cell), j = (int)floor(rpnt.y / dw_cell);
970
  if (i < 0 || j < 0 || i >= NW_CELL || j >= NW_CELL) return 0;
971
  if (!PoleCpos(i, j)) return 1;
972
  return 2 + CMove(drw, i, j);
973
}
974
 
975
TChBoard::PKey TChBoard::GetKeySide(PKey key)
976
{
977
  if (key != PLeft && key != PRight && key != PUp && key != PDown) return key;
978
  TIntPoint a0 = PlToWin(4*dw_cell, 0);
979
  TIntPoint a1 = PlToWin(4*dw_cell, 8*dw_cell);
980
  TIntPoint b0 = PlToWin(0, 4*dw_cell);
981
  TIntPoint b1 = PlToWin(8*dw_cell, 4*dw_cell);
982
  double ax = a0.x - a1.x, ay = a0.y - a1.y;
983
  double bx = b0.x - b1.x, by = b0.y - b1.y;
984
  double t;
985
  if (a0.x == INT_MIN || a0.y == INT_MIN || a1.x == INT_MIN ||
986
      a1.y == INT_MIN || fabs(ax) < 0.5 && fabs(ay) < 0.5)
987
  {
988
    ax = 0, ay = 1;
989
  }
990
  if (b0.x == INT_MIN || b0.y == INT_MIN || b1.x == INT_MIN ||
991
      b1.y == INT_MIN || fabs(bx) < 0.5 && fabs(by) < 0.5)
992
  {
993
    bx = 1, by = 0;
994
  }
995
  t = fabs(ax) + fabs(ay); ax /= t; ay /= t;
996
  t = fabs(bx) + fabs(by); bx /= t; by /= t;
997
  if (fabs(ax) <= fabs(bx))
998
  {
999
    if (key == PLeft) return (bx > 0) ? PRight : PLeft;
1000
    if (key == PRight) return (bx > 0) ? PLeft : PRight;
1001
    if (key == PUp) return (ay > 0) ? PDown : PUp;
1002
    if (key == PDown) return (ay > 0) ? PUp : PDown;
1003
  }
1004
  else
1005
  {
1006
    if (key == PLeft) return (ax > 0) ? PDown : PUp;
1007
    if (key == PRight) return (ax > 0) ? PUp : PDown;
1008
    if (key == PUp) return (by > 0) ? PRight : PLeft;
1009
    if (key == PDown) return (by > 0) ? PLeft : PRight;
1010
  }
1011
  return PNull;
1012
}
1013
 
1014
int TChBoard::PKeyEvent(TGraphDraw *drw, PKey key)
1015
{
1016
  ResetTextLine(drw);
1017
  if (AutoMove(drw)) return 3;
1018
  if (!CanPlayerMove()) return 0;
1019
  key = GetKeySide(key);
1020
  if (CurPoint.x < 0 || CurPoint.y < 0 ||
1021
      CurPoint.x >= NW_CELL || CurPoint.y >= NW_CELL)
1022
  {
1023
    CurPoint.x = NW_CELL / 2;
1024
    CurPoint.y = NW_CELL / 2;
1025
    Draw(drw);
1026
    return 1;
1027
  }
1028
  if (key == PEnter) return 2 + CMove(drw, CurPoint.x, CurPoint.y);
1029
  if (drw && drw->IsDraw() && CheckResize(drw))
1030
  {
1031
    drw->DrawClear();
1032
    Draw(drw);
1033
  }
1034
  if (key == PLeft)
1035
  {
1036
    if (CurPoint.x == 0) return 0;
1037
    CurPointClear(drw);
1038
    CurPoint.x--;
1039
    Draw(drw);
1040
    return 1;
1041
  }
1042
  else if (key == PRight)
1043
  {
1044
    if (CurPoint.x == NW_CELL - 1) return 0;
1045
    CurPointClear(drw);
1046
    CurPoint.x++;
1047
    Draw(drw);
1048
    return 1;
1049
  }
1050
  else if (key == PUp)
1051
  {
1052
    if (CurPoint.y == 0) return 0;
1053
    CurPointClear(drw);
1054
    CurPoint.y--;
1055
    Draw(drw);
1056
    return 1;
1057
  }
1058
  else if (key == PDown)
1059
  {
1060
    if (CurPoint.y == NW_CELL - 1) return 0;
1061
    CurPointClear(drw);
1062
    CurPoint.y++;
1063
    Draw(drw);
1064
    return 1;
1065
  }
1066
  else return 0;
1067
}
1068
 
1069
void TChBoard::UnMove(TGraphDraw *drw)
1070
{
1071
  MoveErase();
1072
  if (drw && drw->IsDraw())
1073
  {
1074
    drw->DrawClear();
1075
    Draw(drw);
1076
  }
1077
}
1078
 
1079
TChBoard::TextLineType TChBoard::GetTLTfromA(int s) const
1080
{
1081
  if (s >= 0) return TLT_Main;
1082
  switch(s)
1083
  {
1084
    case Position::AWColor: return TLT_WrongColor;
1085
    case Position::AfCell: return TLT_WfCell;
1086
    case Position::AnfCell: return TLT_WnfCell;
1087
    case Position::AMustEat: return TLT_WMustEat;
1088
    case Position::AMustEatMore: return TLT_WMustEatMore;
1089
    case Position::AMustEatMoreD: return TLT_WMustEatMoreD;
1090
    case Position::ANoMove: return TLT_WNoMove;
1091
    case Position::AChBack: return TLT_WChBack;
1092
    case Position::ANotDm: return TLT_WNotDm;
1093
    case Position::ANotDmE: return TLT_WNotDmE;
1094
    case Position::AOnlyDiag: return TLT_WOnlyDiag;
1095
    case Position::AEatYour: return TLT_WEatYour;
1096
    case Position::AMoreOne: return TLT_WMoreOne;
1097
    case Position::ATurnBack: return TLT_WTurnBack;
1098
    default: return TLT_WrongMove;
1099
  }
1100
}
1101
 
1102
void TChBoard::ChangeTLT(TGraphDraw *drw, TextLineType t)
1103
{
1104
  if (text_line_type == t) return;
1105
  if (drw && drw->IsDraw())
1106
  {
1107
    drw->SetColor(drw->GetWhiteColor());
1108
    DrawTextLine(drw);
1109
  }
1110
  text_line_type = t;
1111
  if (drw && drw->IsDraw())
1112
  {
1113
    drw->SetColor(drw->GetBlackColor());
1114
    DrawTextLine(drw);
1115
  }
1116
}
1117
 
1118
TChBoard::TextLineType TChBoard::GetSimpleTLT() const
1119
{
1120
  if (game_end && CurMoveN >= MainPlay.GetN() - 1) return TLT_GameEnd;
1121
  else return TLT_Move;
1122
}
1123
 
1124
inline int TChBoard::ReinitHistory()
1125
{
1126
  if (history.Play(MainPlay)) {hist_inited = 1; return 1;}
1127
  else {hist_inited = 0; return 0;}
1128
}
1129
 
1130
void TChBoard::PrintLMove()
1131
{
1132
  PlayWrite::PMv pmv;
1133
  if (MainPlay.GetMoveL(pmv.mv) >= 0)
1134
  {
1135
    MainPlay.GetPosL(pmv.pos, 1);
1136
    char *s = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)];
1137
    if (s)
1138
    {
1139
      pmv.pos.WriteMvEx(pmv.mv, s, 11);
1140
      printf("Checkers: %s%s\n", (pmv.pos.wmove == 1) ? "..." : "", s);
1141
      delete[] s;
1142
    }
1143
    if (!hist_inited) ReinitHistory();
1144
    else history.Move(pmv.pos, pmv.mv, MainPlay.GetN() - 1);
1145
  }
1146
}
1147
 
1148
int TChBoard::CMove(TGraphDraw *drw, int x, int y)
1149
{
1150
  if (AutoMove(drw)) return 1;
1151
  if (!CanPlayerMove()) return 0;
1152
  if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move);
1153
  int k = PoleToNum(x, y), s;
1154
  if (TheMove[0] > 0)
1155
  {
1156
    if (!PoleCpos(x, y) || k == TheMove[TheMove[0]]) {UnMove(drw); return 1;}
1157
    int e = 1;
1158
    s = MainPos.AMove(TheMove, k, e);
1159
    if (s < 0)
1160
    {
1161
      ChangeTLT(drw, GetTLTfromA(s));
1162
      return 0;
1163
    }
1164
    if (s < NUM_CELL) Eaten[++Eaten[0]] = (unsigned char)s;
1165
    TheMove[++TheMove[0]] = (unsigned char)k;
1166
    BecameD = BecameD || MainPos.BecameD(k, MainPos.SH[TheMove[1]]);
1167
    if (e == 0)
1168
    {
1169
      if (MainPlay.Add(TheMove) != 0)
1170
      {
1171
        ChangeTLT(drw, TLT_WrongMove);
1172
        return 0;
1173
      }
1174
      CurMoveN = MainPlay.GetN() - 1;
1175
      MoveErase();
1176
      RenewMPos();
1177
      PrintLMove();
1178
      if (AutoMove(drw)) return 1;
1179
    }
1180
    if (drw && drw->IsDraw())
1181
    {
1182
      drw->DrawClear();
1183
      Draw(drw);
1184
    }
1185
    return 1;
1186
  }
1187
  else
1188
  {
1189
    if (!PoleCpos(x, y)) return 0;
1190
    s = MainPos.AChCell(k);
1191
    if (s != 1)
1192
    {
1193
      ChangeTLT(drw, GetTLTfromA(s));
1194
      return 0;
1195
    }
1196
    TheMove[0] = 1;
1197
    TheMove[1] = (unsigned char)k;
1198
    Draw(drw);
1199
    return 1;
1200
  }
1201
}
1202
 
1203
void TChBoard::SetNoMove(TGraphDraw *drw, int force)
1204
{
1205
  if (!force && CurPoint.x < 0 && CurPoint.y < 0 && TheMove[0] == 0 && Eaten[0] == 0)
1206
  {
1207
    return;
1208
  }
1209
  CurPoint.x = -1; CurPoint.y = -1;
1210
  MoveErase();
1211
  if (drw && drw->IsDraw())
1212
  {
1213
    drw->DrawClear();
1214
    Draw(drw);
1215
  }
1216
}
1217
 
1218
int TChBoard::AutoMove(TGraphDraw *drw, int nmove, int draw_check)
1219
{
1220
  if (game_end || IsPlayView) {SetNoMove(drw, 0); return 0;}
1221
  if (CurMoveN < MainPlay.GetN() - 1)
1222
  {
1223
    CurMoveN = MainPlay.GetN() - 1;
1224
    RenewMPos();
1225
    SetNoMove(drw);
1226
    return 2;
1227
  }
1228
  if (!MainPos.AllCanEat() && !MainPos.AllCanMove())
1229
  {
1230
    game_end = 2 - MainPos.wmove;
1231
    ChangeTLT(drw, TLT_GameEnd);
1232
    if (!player[game_end - 1]) printf("Checkers: You win.\n");
1233
    else printf("Checkers: You lose.\n");
1234
    SetNoMove(drw);
1235
    return 3;
1236
  }
1237
  else if (draw_check > 0 && MainPlay.IsDraw())
1238
  {
1239
    game_end = 5;
1240
    ChangeTLT(drw, TLT_GameEnd);
1241
    printf("Checkers: Draw.\n");
1242
    SetNoMove(drw);
1243
    return 3;
1244
  }
1245
  if (!player[MainPos.wmove]) return 0;
1246
  TIntPoint CurP0 = CurPoint;
1247
  if (CurPoint.x >= 0 && CurPoint.y >= 0)
1248
  {
1249
    if (drw) CurPointClear(drw);
1250
    CurPoint.x = -1; CurPoint.y = -1;
1251
  }
1252
  MoveErase();
1253
  int k;
1254
  for (k = 0; player[MainPos.wmove] && (k < nmove || nmove == 0); k++)
1255
  {
1256
    TChPlayer::PMv pmv;
1257
    pmv.pos = MainPos;
1258
    Position::SetNullMv(pmv.mv);
1259
    MainPlay.GetMoveL(pmv.mv);
1260
    text_line_type = TLT_Move;
1261
    if (!player[MainPos.wmove]->Move(pmv))
1262
    {
1263
      text_line_type = TLT_PlDidntMove;
1264
      game_end = 4 - MainPos.wmove;
1265
      break;
1266
    }
1267
    if (MainPlay.Add(pmv.mv) != 0)
1268
    {
1269
      text_line_type = TLT_PlWrongMove;
1270
      game_end = 4 - MainPos.wmove;
1271
      break;
1272
    }
1273
    CurMoveN = MainPlay.GetN() - 1;
1274
    MoveErase();
1275
    RenewMPos();
1276
    PrintLMove();
1277
    if (!MainPos.AllCanEat() && !MainPos.AllCanMove())
1278
    {
1279
      game_end = 2 - MainPos.wmove;
1280
      text_line_type = TLT_GameEnd;
1281
      if (!player[game_end - 1]) printf("Checkers: You win.\n");
1282
      else printf("Checkers: You lose.\n");
1283
      break;
1284
    }
1285
    else if (draw_check >= 0 && MainPlay.IsDraw())
1286
    {
1287
      game_end = 5;
1288
      text_line_type = TLT_GameEnd;
1289
      printf("Checkers: Draw.\n");
1290
      break;
1291
    }
1292
  }
1293
  if (!game_end)
1294
  {
1295
    text_line_type = TLT_Move;
1296
    CurPoint = CurP0;
1297
  }
1298
  if (drw && drw->IsDraw())
1299
  {
1300
    drw->DrawClear();
1301
    Draw(drw);
1302
  }
1303
  return 1;
1304
}
1305
 
1306
void TChBoard::DrawTimer(TGraphDraw *drw, double t, int wh) const
1307
{
1308
  if (!drw || !drw->IsDraw()) return;
1309
  if (wh) drw->SetColor(drw->GetWhiteColor());
1310
  else drw->SetColor(drw->GetBlackColor());
1311
  double r1 = dw_delt * 0.4, r2 = dw_delt * 0.45;
1312
  double x = t * dw_cell * NW_CELL, y = -dw_delt / 2;
1313
  if (MainPos.wmove == 1)
1314
  {
1315
    x = dw_cell * NW_CELL - x;
1316
    y = dw_cell * NW_CELL - y;
1317
  }
1318
  LineB(drw, x - r1, y - r2, x + r2, y + r1);
1319
  LineB(drw, x - r2, y - r1, x + r1, y + r2);
1320
  LineB(drw, x - r1, y + r2, x + r2, y - r1);
1321
  LineB(drw, x - r2, y + r1, x + r1, y - r2);
1322
  if (wh)
1323
  {
1324
    int i, j, jj;
1325
    drw->SetColor(drw->GetBlackColor());
1326
    for (i = -1; i <= NW_CELL; i++)
1327
    {
1328
      double mval = dw_cell * NW_CELL + dw_delt;
1329
      double x0, x1, y;
1330
      if (i < 0) x0 = -dw_delt;
1331
      else if (i > NW_CELL) x0 = mval;
1332
      else x0 = i * dw_cell;
1333
      if ((i+1) < 0) x1 = -dw_delt;
1334
      else if ((i+1) > NW_CELL) x1 = mval;
1335
      else x1 = (i+1) * dw_cell;
1336
      if (fabs(x0 - x) < dw_delt || fabs(x1 - x) < dw_delt)
1337
      {
1338
        for (jj = 0; jj <= 1; jj++)
1339
        {
1340
          if (MainPos.wmove == 1) j = NW_CELL + jj;
1341
          else j = -jj;
1342
          if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL)
1343
          {
1344
            if (j < 0) y = -dw_delt;
1345
            else if (j > NW_CELL) y = mval;
1346
            else y = j * dw_cell;
1347
            LineB(drw, x0, y, x1, y);
1348
          }
1349
        }
1350
      }
1351
    }
1352
  }
1353
}
1354
 
1355
int TChBoard::SetCurMoveN(int n, TGraphDraw *drw)
1356
{
1357
  int nmove = MainPlay.GetN() - 1;
1358
  if (n > nmove) n = nmove;
1359
  if (n < 0) n = 0;
1360
  if (CurMoveN != n)
1361
  {
1362
    CurMoveN = n;
1363
    RenewMPos();
1364
    if (n < nmove)
1365
    {
1366
      MoveErase();
1367
      CurPoint.x = -1; CurPoint.y = -1;
1368
    }
1369
    text_line_type = GetSimpleTLT();
1370
    if (drw && drw->IsDraw())
1371
    {
1372
      drw->DrawClear();
1373
      Draw(drw);
1374
    }
1375
    return 1;
1376
  }
1377
  else return 0;
1378
}
1379
 
1380
int TChBoard::SetPlay(const PlayWrite &play)
1381
{
1382
  if (play.GetN() <= 0) return 0;
1383
  MainPlay = play;
1384
  MoveErase();
1385
  CurPoint.x = -1; CurPoint.y = -1;
1386
  CurMoveN = INT_MIN;
1387
  SetCurMoveN(play.GetN());
1388
  if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) game_end = 2 - MainPos.wmove;
1389
  else if (MainPlay.IsDraw()) game_end = 5;
1390
  else game_end = 0;
1391
  text_line_type = GetSimpleTLT();
1392
  IsPlayView = 1;
1393
  EraseHistory();
1394
  return 1;
1395
}
1396
 
1397
void TChBoard::GoToCurMove()
1398
{
1399
  if (!MainPos.AllCanEat() && !MainPos.AllCanMove() ||
1400
       MainPlay.IsDraw(CurMoveN + 1)) return;
1401
  MainPlay.ClearFrom(CurMoveN + 1);
1402
  MoveErase();
1403
  game_end = 0;
1404
  text_line_type = GetSimpleTLT();
1405
  IsPlayView = 0;
1406
}
1407
 
1408
#endif  //_HEADER_BOARD_H