Subversion Repositories Kolibri OS

Rev

Rev 1805 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _HEADER_BOARD_H
  2. #define _HEADER_BOARD_H
  3.  
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <time.h>
  8. #include <math.h>
  9. #include <limits.h>
  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.  
  528. #ifdef LANG_RUS
  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
  1409.