summaryrefslogtreecommitdiffstats
path: root/qnetchess/src/gameboard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qnetchess/src/gameboard.cpp')
-rw-r--r--qnetchess/src/gameboard.cpp1987
1 files changed, 1987 insertions, 0 deletions
diff --git a/qnetchess/src/gameboard.cpp b/qnetchess/src/gameboard.cpp
new file mode 100644
index 00000000..ca07e3b8
--- /dev/null
+++ b/qnetchess/src/gameboard.cpp
@@ -0,0 +1,1987 @@
+/*
+ * $Id: gameboard.cpp,v 1.1 2005/03/26 11:24:13 denis Exp $
+ *
+ * Author: Denis Kozadaev (denis@tambov.ru)
+ * Description:
+ *
+ * See also: style(9)
+ *
+ * Hacked by:
+ * Fixed the mate checker (big thanks to knyaz@RusNet)
+ */
+
+#include <ntqpainter.h>
+#include <ntqfontmetrics.h>
+#include <ntqmessagebox.h>
+#include <ntqcursor.h>
+#include <ntqfiledialog.h>
+#include <stdlib.h>
+
+#include "gameboard.h"
+#include "gamesocket.h"
+
+#include "xpm/black_bishop.xpm"
+#include "xpm/black_castle.xpm"
+#include "xpm/black_king.xpm"
+#include "xpm/black_knight.xpm"
+#include "xpm/black_pawn.xpm"
+#include "xpm/black_queen.xpm"
+#include "xpm/white_bishop.xpm"
+#include "xpm/white_castle.xpm"
+#include "xpm/white_king.xpm"
+#include "xpm/white_knight.xpm"
+#include "xpm/white_pawn.xpm"
+#include "xpm/white_queen.xpm"
+
+const int
+ cell_size = 40,
+ XSize = 640,
+ YSize = 480;
+
+TQColor cb, cw;
+
+bool
+Figure::hasMyFigure(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int x, int y, bool mirror)
+{
+ int n;
+ bool res;
+
+ n = map2map(gt, x, y, mirror);
+
+ if (gt == GameBoard::WHITE)
+ switch (map[n]) {
+ case GameBoard::DUMMY:
+ case GameBoard::WHITE_PAWN:
+ case GameBoard::WHITE_CASTLE:
+ case GameBoard::WHITE_BISHOP:
+ case GameBoard::WHITE_KING:
+ case GameBoard::WHITE_QUEEN:
+ case GameBoard::WHITE_KNIGHT:
+ res = TRUE;
+ break;
+ default:
+ res = FALSE;
+ }
+ else if (gt == GameBoard::BLACK)
+ switch (map[n]) {
+ case GameBoard::DUMMY:
+ case GameBoard::BLACK_PAWN:
+ case GameBoard::BLACK_CASTLE:
+ case GameBoard::BLACK_BISHOP:
+ case GameBoard::BLACK_KING:
+ case GameBoard::BLACK_QUEEN:
+ case GameBoard::BLACK_KNIGHT:
+ res = TRUE;
+ break;
+ default:
+ res = FALSE;
+ }
+ else
+ res = FALSE;
+
+ return (res);
+}
+
+
+int
+Figure::hasEnemyFigure(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int x, int y, bool mirror)
+{
+ int n;
+ int res;
+
+ n = map2map(gt, x, y, mirror);
+
+ if (gt == GameBoard::BLACK)
+ switch (map[n]) {
+ case GameBoard::WHITE_PAWN:
+ case GameBoard::WHITE_CASTLE:
+ case GameBoard::WHITE_BISHOP:
+ case GameBoard::WHITE_QUEEN:
+ case GameBoard::WHITE_KNIGHT:
+ res = 1;
+ break;
+ case GameBoard::WHITE_KING:
+ res = 2;
+ break;
+ case GameBoard::DUMMY:
+ default:
+ res = 0;
+ }
+ else if (gt == GameBoard::WHITE)
+ switch (map[n]) {
+ case GameBoard::BLACK_PAWN:
+ case GameBoard::BLACK_CASTLE:
+ case GameBoard::BLACK_BISHOP:
+ case GameBoard::BLACK_QUEEN:
+ case GameBoard::BLACK_KNIGHT:
+ res = 1;
+ break;
+ case GameBoard::BLACK_KING:
+ res = 2;
+ break;
+ case GameBoard::DUMMY:
+ default:
+ res = 0;
+ }
+ else
+ res = 0;
+
+ return (res);
+}
+
+
+bool
+Figure::hasFigure(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int x, int y, bool mirror)
+{
+ int n;
+
+ n = map2map(gt, x, y, mirror);
+
+ return (map[n] != GameBoard::NONE);
+}
+
+
+int
+Figure::map2map(GameBoard::GameType gt, int x, int y, bool mirror)
+{
+ int n = -1;
+
+ if (gt == GameBoard::WHITE)
+ if (mirror)
+ n = (y - 1) * 8 + (8 - x);
+ else
+ n = (8 - y) * 8 + (x - 1);
+ else if (gt == GameBoard::BLACK)
+ if (mirror)
+ n = (8 - y) * 8 + (x - 1);
+ else
+ n = (y - 1) * 8 + (8 - x);
+
+ return (n);
+}
+
+
+QString
+Figure::map2str(int x, int y)
+{
+ QString s;
+
+ s = TQString(TQChar('a' + x - 1)) + TQString::number(y);
+ return (s);
+}
+
+
+void
+Figure::str2map(const TQString &coo, int *x, int *y)
+{
+
+ *x = coo[0] - 'a' + 1;
+ *y = coo[1] - '0';
+}
+
+
+int
+Figure::validMove(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int fx, int fy, int tx, int ty, bool mirror)
+{
+ TQPointArray vl;
+ int res, f, t;
+
+ moveList(vl, gt, map, fx, fy, mirror);
+ res = hasPoint(vl, tx, ty);
+ f = map2map(gt, fx, fy, mirror);
+ switch (map[f]) {
+ case GameBoard::WHITE_PAWN:
+ if (res && (ty == 8))
+ res++;
+ break;
+ case GameBoard::BLACK_PAWN:
+ if (res && (ty == 1))
+ res++;
+ break;
+ default:;
+ }
+ if (res) {
+ t = map2map(gt, tx, ty, mirror);
+ map[t] = map[f];
+ map[f] = GameBoard::NONE;
+ if (mirror) {
+ vl.resize(0);
+ t = checkKing(gt, map, mirror, vl, FALSE);
+ switch (t) {
+ case 1:
+ res |= 0x10;
+ break;
+ case 2:
+ res |= 0x20;
+ break;
+ case 3:
+ res |= 0x40;
+ break;
+ default:;
+ }
+ }
+ }
+
+ return (res);
+}
+
+
+/*
+ * 0 - nothing
+ * 1 - check
+ * 2 - mate
+ * 3 - stalemate
+ */
+int
+Figure::checkKing(GameBoard::GameType gt, GameBoard::FigureType *map,
+ bool mirror, TQPointArray &vl, bool co)
+{
+ TQPointArray tmp;
+ GameBoard::FigureType myking, map1[64];
+ GameBoard::GameType mytype;
+ int res, x, y, p, xk, yk, pk;
+ bool hp;
+
+ if (gt == GameBoard::WHITE) {
+ myking = GameBoard::BLACK_KING;
+ mytype = GameBoard::BLACK;
+ } else if (gt == GameBoard::BLACK) {
+ myking = GameBoard::WHITE_KING;
+ mytype = GameBoard::WHITE;
+ } else {
+ myking = GameBoard::NONE;
+ mytype = GameBoard::NOGAME;
+ }
+ xk = yk = -1;
+ res = 0; p = -1;
+
+ for (y = 1; y < 9; ++y)
+ for (x = 1; x < 9; ++x)
+ /* check enemy figures */
+ if (hasMyFigure(gt, map, x, y, mirror))
+ moveList(vl, gt, map, x, y, mirror);
+ else if (p == -1) {
+ p = map2map(mytype, x, y, !mirror);
+ if (map[p] == myking) {
+ xk = x;
+ yk = y;
+ } else
+ p = -1;
+ }
+
+ hp = hasPoint(vl, xk, yk);
+ if (hp) {
+ res++;
+ if (!co) {
+ vl.resize(0);
+ for (y = 1; y < 9; ++y)
+ for (x = 1; x < 9; ++x)
+ if (hasMyFigure(mytype, map,
+ x, y, !mirror))
+ moveList(vl, mytype, map,
+ x, y, !mirror);
+ memmove(map1, map, sizeof(map1));
+ pk = map2map(mytype, xk, yk, !mirror);
+ for (x = vl.size() - 1; x >= 0; --x) {
+ p = map2map(mytype, vl.point(x).x(),
+ vl.point(x).y(), !mirror);
+ if (p != pk)
+ map1[p] = GameBoard::DUMMY;
+ }
+ if (checkKing(gt, map1, mirror, vl, TRUE) != 0) {
+ vl.resize(0);
+ moveListKing(vl, mytype, map, xk, yk, !mirror);
+ memmove(map1, map, sizeof(map1));
+ for (y = 0, x = vl.size() - 1; x >= 0; --x) {
+ p = map2map(mytype, vl.point(x).x(),
+ vl.point(x).y(), !mirror);
+ map1[p] = myking;
+ map1[pk] = GameBoard::NONE;
+ if (checkKing(gt, map1, mirror,
+ tmp, TRUE) == 1)
+ ++y;
+ map1[pk] = map[pk];
+ map1[p] = map[p];
+ }
+ if (y == (int)vl.size())
+ res++;
+ }
+ }
+ } else if (!co) {
+ vl.resize(0);
+ for (y = 1; y < 9; ++y)
+ for (x = 1; x < 9; ++x)
+ if (hasMyFigure(mytype, map, x, y, !mirror))
+ moveList(vl, mytype, map, x, y,
+ !mirror);
+ if (vl.size() == 0)
+ res = 3;
+ }
+
+ return (res);
+}
+
+
+void
+Figure::moveList(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+ int n;
+
+ n = map2map(gt, x, y, mirror);
+ switch (map[n]) {
+ case GameBoard::WHITE_PAWN:
+ moveListWhitePawn(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::WHITE_CASTLE:
+ case GameBoard::BLACK_CASTLE:
+ moveListCastle(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::WHITE_BISHOP:
+ case GameBoard::BLACK_BISHOP:
+ moveListBishop(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::WHITE_KING:
+ case GameBoard::BLACK_KING:
+ moveListKing(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::WHITE_QUEEN:
+ case GameBoard::BLACK_QUEEN:
+ moveListQueen(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::WHITE_KNIGHT:
+ case GameBoard::BLACK_KNIGHT:
+ moveListKnight(vl, gt, map, x, y, mirror);
+ break;
+
+ case GameBoard::BLACK_PAWN:
+ moveListBlackPawn(vl, gt, map, x, y, mirror);
+ break;
+
+
+ default:;
+ }
+}
+
+
+void
+Figure::moveListWhitePawn(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+
+ if (validPoint(gt, map, x, y + 1, mirror) &&
+ !hasFigure(gt, map, x, y + 1, mirror)) {
+ vl.putPoints(vl.size(), 1, x, y + 1);
+ if ((y == 2) && validPoint(gt, map, x, y + 2, mirror))
+ vl.putPoints(vl.size(), 1, x, y + 2);
+ }
+ if (validPoint(gt, map, x + 1, y + 1, mirror) &&
+ hasEnemyFigure(gt, map, x + 1, y + 1, mirror))
+ vl.putPoints(vl.size(), 1, x + 1, y + 1);
+ if (validPoint(gt, map, x - 1, y + 1, mirror) &&
+ hasEnemyFigure(gt, map, x - 1, y + 1, mirror))
+ vl.putPoints(vl.size(), 1, x - 1, y + 1);
+}
+
+
+void
+Figure::moveListBlackPawn(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+
+ if (validPoint(gt, map, x, y - 1, mirror) &&
+ !hasFigure(gt, map, x, y - 1, mirror)) {
+ vl.putPoints(vl.size(), 1, x, y - 1);
+ if ((y == 7) && validPoint(gt, map, x, y - 2, mirror))
+ vl.putPoints(vl.size(), 1, x, y - 2);
+ }
+ if (validPoint(gt, map, x + 1, y - 1, mirror) &&
+ hasEnemyFigure(gt, map, x + 1, y - 1, mirror))
+ vl.putPoints(vl.size(), 1, x + 1, y - 1);
+ if (validPoint(gt, map, x - 1, y - 1, mirror) &&
+ hasEnemyFigure(gt, map, x - 1, y - 1, mirror))
+ vl.putPoints(vl.size(), 1, x - 1, y - 1);
+}
+
+
+void
+Figure::moveListCastle(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+ int i;
+
+ for (i = x + 1; i < 9; i++) {
+ if (!hasFigure(gt, map, i, y, mirror)) {
+ vl.putPoints(vl.size(), 1, i, y);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, y, mirror))
+ vl.putPoints(vl.size(), 1, i, y);
+ break;
+ }
+ for (i = x - 1; i > 0; i--) {
+ if (!hasFigure(gt, map, i, y, mirror)) {
+ vl.putPoints(vl.size(), 1, i, y);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, y, mirror))
+ vl.putPoints(vl.size(), 1, i, y);
+ break;
+ }
+ for (i = y + 1; i < 9; i++) {
+ if (!hasFigure(gt, map, x, i, mirror)) {
+ vl.putPoints(vl.size(), 1, x, i);
+ continue;
+ } else if (hasEnemyFigure(gt, map, x, i, mirror))
+ vl.putPoints(vl.size(), 1, x, i);
+ break;
+ }
+ for (i = y - 1; i > 0; i--) {
+ if (!hasFigure(gt, map, x, i, mirror)) {
+ vl.putPoints(vl.size(), 1, x, i);
+ continue;
+ } else if (hasEnemyFigure(gt, map, x, i, mirror))
+ vl.putPoints(vl.size(), 1, x, i);
+ break;
+ }
+}
+
+
+void
+Figure::moveListBishop(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+ int i, j;
+
+ for (i = x + 1, j = y + 1; (i < 9) && (j < 9); i++, j++) {
+ if (!hasFigure(gt, map, i, j, mirror)) {
+ vl.putPoints(vl.size(), 1, i, j);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, j, mirror))
+ vl.putPoints(vl.size(), 1, i, j);
+ break;
+ }
+ for (i = x - 1, j = y + 1; (i > 0) && (j < 9); i--, j++) {
+ if (!hasFigure(gt, map, i, j, mirror)) {
+ vl.putPoints(vl.size(), 1, i, j);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, j, mirror))
+ vl.putPoints(vl.size(), 1, i, j);
+ break;
+ }
+ for (i = x - 1, j = y - 1; (i > 0) && (j > 0); i--, j--) {
+ if (!hasFigure(gt, map, i, j, mirror)) {
+ vl.putPoints(vl.size(), 1, i, j);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, j, mirror))
+ vl.putPoints(vl.size(), 1, i, j);
+ break;
+ }
+ for (i = x + 1, j = y - 1; (i < 9) && (j > 0); i++, j--) {
+ if (!hasFigure(gt, map, i, j, mirror)) {
+ vl.putPoints(vl.size(), 1, i, j);
+ continue;
+ } else if (hasEnemyFigure(gt, map, i, j, mirror))
+ vl.putPoints(vl.size(), 1, i, j);
+ break;
+ }
+}
+
+
+void
+Figure::moveListKing(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+ int x1, x2, y1, y2;
+
+ x1 = x - 1; x2 = x + 1;
+ y1 = y - 1; y2 = y + 1;
+ if (validPoint(gt, map, x1, y2, mirror) &&
+ !hasKingsMeeting(gt, map, x1, y2, mirror))
+ vl.putPoints(vl.size(), 1, x1, y2);
+ if (validPoint(gt, map, x, y2, mirror) &&
+ !hasKingsMeeting(gt, map, x, y2, mirror))
+ vl.putPoints(vl.size(), 1, x, y2);
+ if (validPoint(gt, map, x2, y2, mirror) &&
+ !hasKingsMeeting(gt, map, x2, y2, mirror))
+ vl.putPoints(vl.size(), 1, x2, y2);
+ if (validPoint(gt, map, x1, y, mirror) &&
+ !hasKingsMeeting(gt, map, x1, y, mirror))
+ vl.putPoints(vl.size(), 1, x1, y);
+ if (validPoint(gt, map, x2, y, mirror) &&
+ !hasKingsMeeting(gt, map, x2, y, mirror))
+ vl.putPoints(vl.size(), 1, x2, y);
+ if (validPoint(gt, map, x1, y1, mirror) &&
+ !hasKingsMeeting(gt, map, x1, y1, mirror))
+ vl.putPoints(vl.size(), 1, x1, y1);
+ if (validPoint(gt, map, x, y1, mirror) &&
+ !hasKingsMeeting(gt, map, x, y1, mirror))
+ vl.putPoints(vl.size(), 1, x, y1);
+ if (validPoint(gt, map, x2, y1, mirror) &&
+ !hasKingsMeeting(gt, map, x2, y1, mirror))
+ vl.putPoints(vl.size(), 1, x2, y1);
+}
+
+
+void
+Figure::moveListQueen(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+
+ moveListBishop(vl, gt, map, x, y, mirror);
+ moveListCastle(vl, gt, map, x, y, mirror);
+}
+
+
+void
+Figure::moveListKnight(TQPointArray &vl, GameBoard::GameType gt,
+ GameBoard::FigureType *map, int x, int y, bool mirror)
+{
+ int x1, x2, x3, x4,
+ y1, y2, y3, y4;
+
+ x1 = x + 1;
+ x2 = x1 + 1;
+ x3 = x - 1;
+ x4 = x3 - 1;
+ y1 = y + 1;
+ y2 = y1 + 1;
+ y3 = y - 1;
+ y4 = y3 - 1;
+ if (validPoint(gt, map, x3, y2, mirror))
+ vl.putPoints(vl.size(), 1, x3, y2);
+ if (validPoint(gt, map, x1, y2, mirror))
+ vl.putPoints(vl.size(), 1, x1, y2);
+ if (validPoint(gt, map, x4, y1, mirror))
+ vl.putPoints(vl.size(), 1, x4, y1);
+ if (validPoint(gt, map, x2, y1, mirror))
+ vl.putPoints(vl.size(), 1, x2, y1);
+ if (validPoint(gt, map, x4, y3, mirror))
+ vl.putPoints(vl.size(), 1, x4, y3);
+ if (validPoint(gt, map, x2, y3, mirror))
+ vl.putPoints(vl.size(), 1, x2, y3);
+ if (validPoint(gt, map, x3, y4, mirror))
+ vl.putPoints(vl.size(), 1, x3, y4);
+ if (validPoint(gt, map, x1, y4, mirror))
+ vl.putPoints(vl.size(), 1, x1, y4);
+}
+
+
+bool
+Figure::hasKingsMeeting(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int x, int y, bool mirror)
+{
+ int x1, x2, y1, y2;
+ bool res;
+
+ x1 = x - 1; x2 = x + 1;
+ y1 = y - 1; y2 = y + 1;
+ res = FALSE;
+
+ if (validPoint(gt, map, x1, y2, mirror))
+ res = (hasEnemyFigure(gt, map, x1, y2, mirror) == 2);
+ if (! res && validPoint(gt, map, x, y2, mirror))
+ res = (hasEnemyFigure(gt, map, x, y2, mirror) == 2);
+ if (!res && validPoint(gt, map, x2, y2, mirror))
+ res = (hasEnemyFigure(gt, map, x2, y2, mirror) == 2);
+ if (!res && validPoint(gt, map, x1, y, mirror))
+ res = (hasEnemyFigure(gt, map, x1, y, mirror) == 2);
+ if (!res && validPoint(gt, map, x2, y, mirror))
+ res = (hasEnemyFigure(gt, map, x2, y, mirror) == 2);
+ if (!res && validPoint(gt, map, x1, y1, mirror))
+ res = (hasEnemyFigure(gt, map, x1, y1, mirror) == 2);
+ if (!res && validPoint(gt, map, x, y1, mirror))
+ res = (hasEnemyFigure(gt, map, x, y1, mirror) == 2);
+ if (!res && validPoint(gt, map, x2, y1, mirror))
+ res = (hasEnemyFigure(gt, map, x2, y1, mirror) == 2);
+
+ return (res);
+}
+
+
+bool
+Figure::hasPoint(const TQPointArray &vl, int x, int y)
+{
+ int i, xp, yp, cnt;
+ bool res = FALSE;
+
+ cnt = vl.count();
+ for (i = 0; i < cnt; ++i) {
+ vl.point(i, &xp, &yp);
+ if ((xp == x) && (yp == y)) {
+ res = TRUE;
+ break;
+ }
+ }
+
+ return (res);
+}
+
+
+bool
+Figure::validPoint(GameBoard::GameType gt, GameBoard::FigureType *map,
+ int x, int y, bool mirror)
+{
+ bool res;
+
+ res = ((x >0) && (x < 9) && (y >0) && (y < 9));
+ if (res)
+ res = !hasMyFigure(gt, map, x, y, mirror);
+
+ return (res);
+}
+
+//-----------------------------------------------------------------------------
+
+GameBoard::GameBoard(GameType g, const TQString &h, TQWidget *parent,
+ const char *name)
+ :TQWidget(parent, name, TQt::WResizeNoErase |
+ TQt::WRepaintNoErase | TQt::WDestructiveClose)
+{
+ TQString str;
+
+ gt = g; hst = h;
+ setCursor(TQCursor(TQt::WaitCursor));
+ if (gt == WHITE)
+ str = tr("White");
+ else if (gt == BLACK)
+ str = tr("Black");
+ str += ' ' + tr("game with") + ' ';
+ setCaption(str + hst);
+ setIcon(TQPixmap((const char **)white_knight));
+ map = new FigureType[64];
+ initMap();
+
+ sock = new TQSocket(this);
+ drw = new Drawer(map, &gt, this);
+ drw->setEnabled(FALSE);
+ drw->setFocusPolicy(NoFocus);
+ box = new TQGroupBox(tr("Game chat"), this);
+ lst = new TQListBox(box);
+ lst->setFocusPolicy(NoFocus);
+ lst->setVScrollBarMode(TQScrollView::AlwaysOff);
+ lst->setSelectionMode(TQListBox::NoSelection);
+ edt = new TQLineEdit(box);
+ edt->setEnabled(FALSE);
+ setFocusProxy(edt);
+ hist = new TQGroupBox(tr("History"), this);
+ hist->setAlignment(TQt::AlignHCenter);
+ hist->setFocusPolicy(NoFocus);
+ hw = new TQListBox(hist);
+ hw->setSelectionMode(TQListBox::NoSelection);
+ hw->setPaletteBackgroundColor(cw);
+ hb = new TQListBox(hist);
+ hb->setSelectionMode(TQListBox::NoSelection);
+ hb->setPaletteBackgroundColor(cb);
+ tmr = new TQTimer(this);
+ sock_tout = SOCK_WAIT;
+ my_stat = tr("Looking up the host") + ' ' + hst + "...";
+ TQObject::connect(sock, SIGNAL(hostFound()),
+ this, SLOT(showHostFound()));
+ TQObject::connect(sock, SIGNAL(connected()),
+ this, SLOT(sockConnected()));
+ TQObject::connect(sock, SIGNAL(readyRead()),
+ this, SLOT(sockRead()));
+ TQObject::connect(sock, SIGNAL(connectionClosed()),
+ this, SLOT(sockClosed()));
+ TQObject::connect(sock, SIGNAL(error(int)),
+ this, SLOT(sockError(int)));
+ TQObject::connect(drw, SIGNAL(moved(const TQString&)),
+ this, SLOT(sendMove(const TQString&)));
+ TQObject::connect(drw, SIGNAL(newFigure(const TQString&,
+ GameBoard::FigureType)),
+ this, SLOT(sendFigure(const TQString&, GameBoard::FigureType)));
+ TQObject::connect(drw, SIGNAL(gameover(int)),
+ this, SLOT(gameover(int)));
+ TQObject::connect(edt, SIGNAL(returnPressed()),
+ this, SLOT(sendText()));
+ TQObject::connect(tmr, SIGNAL(timeout()), this, SLOT(sockTest()));
+
+ resize(XSize, YSize);
+ setMinimumSize(size());
+ setMaximumSize(size());
+ sock->connectToHost(hst, GAME_PORT);
+ tmr->start(1000);
+}
+
+GameBoard::GameBoard(int sfd, TQWidget *parent, const char *name)
+ :TQWidget(parent, name, TQt::WResizeNoErase | TQt::WRepaintNoErase |
+ TQt::WDestructiveClose)
+{
+
+ gt = NOGAME;
+ setCursor(TQCursor(TQt::WaitCursor));
+ setIcon(TQPixmap((const char **)white_knight));
+ map = new FigureType[64];
+ memset(map, NONE, 64 * sizeof(*map));
+
+ sock = new TQSocket(this);
+ drw = new Drawer(map, &gt, this);
+ drw->setEnabled(FALSE);
+ drw->setFocusPolicy(NoFocus);
+ box = new TQGroupBox(tr("Game chat"), this);
+ lst = new TQListBox(box);
+ lst->setFocusPolicy(NoFocus);
+ lst->setVScrollBarMode(TQScrollView::AlwaysOff);
+ lst->setSelectionMode(TQListBox::NoSelection);
+ edt = new TQLineEdit(box);
+ setFocusProxy(edt);
+ hist = new TQGroupBox(tr("History"), this);
+ hist->setAlignment(TQt::AlignHCenter);
+ hist->setFocusPolicy(NoFocus);
+ hw = new TQListBox(hist);
+ hw->setSelectionMode(TQListBox::NoSelection);
+ hw->setPaletteBackgroundColor(cw);
+ hb = new TQListBox(hist);
+ hb->setSelectionMode(TQListBox::NoSelection);
+ hb->setPaletteBackgroundColor(cb);
+ tmr = new TQTimer(this);
+ sock->setSocket(sfd);
+ sock_tout = SOCK_WAIT;
+ my_stat = tr("Accepted a new connection");
+ TQObject::connect(sock, SIGNAL(hostFound()),
+ this, SLOT(showHostFound()));
+ TQObject::connect(sock, SIGNAL(connected()),
+ this, SLOT(sockConnected()));
+ TQObject::connect(sock, SIGNAL(readyRead()),
+ this, SLOT(sockRead()));
+ TQObject::connect(sock, SIGNAL(connectionClosed()),
+ this, SLOT(sockClosed()));
+ TQObject::connect(sock, SIGNAL(error(int)),
+ this, SLOT(sockError(int)));
+ TQObject::connect(drw, SIGNAL(moved(const TQString&)),
+ this, SLOT(sendMove(const TQString&)));
+ TQObject::connect(drw, SIGNAL(newFigure(const TQString&,
+ GameBoard::FigureType)),
+ this, SLOT(sendFigure(const TQString&, GameBoard::FigureType)));
+ TQObject::connect(drw, SIGNAL(gameover(int)),
+ this, SLOT(gameover(int)));
+ TQObject::connect(edt, SIGNAL(returnPressed()),
+ this, SLOT(sendText()));
+ TQObject::connect(tmr, SIGNAL(timeout()), this, SLOT(sockTest()));
+ resize(XSize, YSize);
+ setMinimumSize(size());
+ setMaximumSize(size());
+ tmr->start(1000);
+}
+
+GameBoard::~GameBoard()
+{
+
+ GameProtocol::sendQuit(sock);
+ delete tmr;
+ delete hb;
+ delete hw;
+ delete hist;
+ delete edt;
+ delete lst;
+ delete box;
+ delete drw;
+ delete sock;
+ delete map;
+}
+
+
+void
+GameBoard::resizeEvent(TQResizeEvent *e)
+{
+ TQFontMetrics fm(font());
+ int w = e->size().width(),
+ h = e->size().height(),
+ fh = fm.lineSpacing() + 4;
+
+ TQWidget::resizeEvent(e);
+ drw->move(0, 0);
+ box->move(drw->x(), drw->y() + drw->height());
+ box->resize(w, h - box->y());
+ edt->move(2, box->height() - fh - 2);
+ edt->resize(box->width() - edt->x() * 2, fh);
+ lst->move(edt->x(), fm.lineSpacing());
+ lst->resize(edt->width(), edt->y() - lst->y());
+ hist->move(drw->x() + drw->width(), drw->y());
+ hist->resize(w - hist->x(), box->y());
+ hw->move(2, TQFontMetrics(hist->font()).lineSpacing());
+ hw->resize((hist->width() - hw->x()) / 2,
+ hist->height() - hw->y() - 2);
+ hb->move(hw->x() + hw->width(), hw->y());
+ hb->resize(hw->size());
+}
+
+
+void
+GameBoard::focusInEvent(TQFocusEvent *e)
+{
+
+ TQWidget::focusInEvent(e);
+ emit showStatus(my_stat);
+}
+
+
+void
+GameBoard::initMap()
+{
+
+ memset(map, NONE, 64 * sizeof(*map));
+ if (gt == WHITE) {
+ map[0] = BLACK_CASTLE;
+ map[1] = BLACK_KNIGHT;
+ map[2] = BLACK_BISHOP;
+ map[3] = BLACK_QUEEN;
+ map[4] = BLACK_KING;
+ map[5] = BLACK_BISHOP;
+ map[6] = BLACK_KNIGHT;
+ map[7] = BLACK_CASTLE;
+ map[8] = BLACK_PAWN;
+ map[9] = BLACK_PAWN;
+ map[10] = BLACK_PAWN;
+ map[11] = BLACK_PAWN;
+ map[12] = BLACK_PAWN;
+ map[13] = BLACK_PAWN;
+ map[14] = BLACK_PAWN;
+ map[15] = BLACK_PAWN;
+ map[48] = WHITE_PAWN;
+ map[49] = WHITE_PAWN;
+ map[50] = WHITE_PAWN;
+ map[51] = WHITE_PAWN;
+ map[52] = WHITE_PAWN;
+ map[53] = WHITE_PAWN;
+ map[54] = WHITE_PAWN;
+ map[55] = WHITE_PAWN;
+ map[56] = WHITE_CASTLE;
+ map[57] = WHITE_KNIGHT;
+ map[58] = WHITE_BISHOP;
+ map[59] = WHITE_QUEEN;
+ map[60] = WHITE_KING;
+ map[61] = WHITE_BISHOP;
+ map[62] = WHITE_KNIGHT;
+ map[63] = WHITE_CASTLE;
+ } else {
+ map[0] = WHITE_CASTLE;
+ map[1] = WHITE_KNIGHT;
+ map[2] = WHITE_BISHOP;
+ map[3] = WHITE_KING;
+ map[4] = WHITE_QUEEN;
+ map[5] = WHITE_BISHOP;
+ map[6] = WHITE_KNIGHT;
+ map[7] = WHITE_CASTLE;
+ map[8] = WHITE_PAWN;
+ map[9] = WHITE_PAWN;
+ map[10] = WHITE_PAWN;
+ map[11] = WHITE_PAWN;
+ map[12] = WHITE_PAWN;
+ map[13] = WHITE_PAWN;
+ map[14] = WHITE_PAWN;
+ map[15] = WHITE_PAWN;
+ map[48] = BLACK_PAWN;
+ map[49] = BLACK_PAWN;
+ map[50] = BLACK_PAWN;
+ map[51] = BLACK_PAWN;
+ map[52] = BLACK_PAWN;
+ map[53] = BLACK_PAWN;
+ map[54] = BLACK_PAWN;
+ map[55] = BLACK_PAWN;
+ map[56] = BLACK_CASTLE;
+ map[57] = BLACK_KNIGHT;
+ map[58] = BLACK_BISHOP;
+ map[59] = BLACK_KING;
+ map[60] = BLACK_QUEEN;
+ map[61] = BLACK_BISHOP;
+ map[62] = BLACK_KNIGHT;
+ map[63] = BLACK_CASTLE;
+ }
+}
+
+
+void
+GameBoard::showHostFound()
+{
+
+ my_stat = tr("The host found");
+ emit showStatus(my_stat);
+}
+
+
+void
+GameBoard::sockConnected()
+{
+
+ my_stat = tr("Connected to the host");
+ emit showStatus(my_stat);
+ GameProtocol::setGameType(sock, gt);
+ edt->setEnabled(TRUE);
+}
+
+
+void
+GameBoard::sockRead()
+{
+ TQString str;
+
+ if (sock->canReadLine()) {
+ str = sock->readLine();
+ str.remove(EOL);
+ str.remove('\r');
+ parseString(str);
+ sock_tout = SOCK_WAIT;
+ }
+}
+
+
+void
+GameBoard::sockClosed()
+{
+
+ close();
+}
+
+
+void
+GameBoard::sockError(int err)
+{
+ TQString e;
+
+ TQMessageBox::critical(this, tr("Socket Error..."),
+ tr("You have a socket error number") + ' ' +
+ TQString::number(err));
+}
+
+
+void
+GameBoard::parseString(const TQString &str)
+{
+ TQStringList lst(TQStringList::split(SEP, str));
+ TQString s(lst[0].lower());
+ int id;
+
+ if (s == "game") {
+ s = lst[1].lower();
+ if (s == "mate") {
+ updateHistory(GAMEOVER_TXT, TRUE);
+ gt = NOGAME;
+ gameover(0);
+ close();
+ } else if (s == "stalemate") {
+ gt = NOGAME;
+ gameover(3);
+ close();
+ } else if (s != "accept") {
+ if (s == "white") {
+ gt = BLACK;
+ s = tr("White");
+ } else if (s == "black") {
+ gt = WHITE;
+ s = tr("Black");
+ drw->setEnabled(TRUE);
+ setCursor(TQCursor(TQt::ArrowCursor));
+ }
+ s += ' ' + tr("game from") + ' ';
+ my_stat = tr("Accepted the") + ' ' + s;
+ hst = sock->peerName();
+ if (hst.isEmpty())
+ hst = sock->peerAddress().toString() + ':' +
+ TQString::number(sock->peerPort());
+ initMap();
+ drw->repaint(TRUE);
+ GameProtocol::acceptGame(sock);
+ setCaption(s + hst);
+ my_stat += hst;
+ emit showStatus(my_stat);
+ } else if (gt == WHITE) {
+ drw->setEnabled(TRUE);
+ setCursor(TQCursor(TQt::ArrowCursor));
+ }
+ } else if (s == "move") {
+ if (!drw->isEnabled()) {
+ drw->setEnabled(TRUE);
+ s = lst[1].lower();
+ updateHistory(s, TRUE);
+ drw->makeMove(s);
+ setCursor(TQCursor(TQt::ArrowCursor));
+ my_stat = tr("Your move...");
+ emit showStatus(my_stat);
+ }
+ } else if (s == "quit") {
+ gt = NOGAME;
+ sockClosed();
+ } else if (s == "chat") {
+ s = str.right(str.length() - 5);
+ updateChat('>' + s);
+ } else if (s == "figure") {
+ s = lst[1].lower();
+ id = lst[2].toInt();
+ drw->newFigure(s, id);
+ updateHistory(id, TRUE);
+ }
+}
+
+
+void
+GameBoard::sendMove(const TQString &str)
+{
+
+ GameProtocol::sendMove(sock, str);
+ drw->setEnabled(FALSE);
+ setCursor(TQCursor(TQt::WaitCursor));
+ updateHistory(str, FALSE);
+ sock_tout = SOCK_WAIT;
+ my_stat = tr("Waiting a move...");
+ emit showStatus(my_stat);
+}
+
+
+void
+GameBoard::closeEvent(TQCloseEvent *e)
+{
+ int res;
+
+ if (gt != NOGAME) {
+ res = TQMessageBox::question(this, tr("End the game"),
+ tr("Want you to end the game?\nYou will lose it"),
+ tr("Yes, end"), tr("No, continue"), TQString::null, 1);
+ if (res == 0)
+ TQWidget::closeEvent(e);
+ } else
+ TQWidget::closeEvent(e);
+}
+
+
+void
+GameBoard::sendText()
+{
+ TQString s;
+
+ s = edt->text().utf8();
+ if (!s.isEmpty()) {
+ updateChat(s);
+ GameProtocol::sendText(sock, s.ascii());
+ }
+ edt->clear();
+}
+
+
+void
+GameBoard::updateChat(const TQString &s)
+{
+ int fh, h;
+
+ lst->insertItem(TQString::fromUtf8(s.ascii()));
+ h = lst->height();
+ fh = TQFontMetrics(lst->font()).lineSpacing();
+ if ((int)lst->count() * fh >= lst->visibleHeight())
+ lst->removeItem(0);
+}
+
+
+void
+GameBoard::updateHistory(const TQString &st, bool t)
+{
+ TQString s;
+
+ if (st.length() == 3) {
+ if (st[0] == '@')
+ s = "O-O";
+ else
+ s = st;
+ } else
+ s = st.left(2) + " - " + st.right(2);
+ if (t) {
+ if (gt == WHITE)
+ hb->insertItem(s);
+ else if (gt == BLACK)
+ hw->insertItem(s);
+ } else {
+ if (gt == WHITE)
+ hw->insertItem(s);
+ else if (gt == BLACK)
+ hb->insertItem(s);
+ }
+}
+
+
+void
+GameBoard::updateHistory(int id, bool t)
+{
+ TQString s("; "), s1;
+
+ switch (id) {
+ case 3:
+ s += tr("B");
+ break;
+ case 4:
+ s += tr("K");
+ break;
+ case 5:
+ s += tr("C");
+ break;
+ case 10:
+ s += tr("Q");
+ break;
+ default:
+ s += tr("Error!");
+ }
+ if (t) {
+ if (gt == WHITE) {
+ id = hb->count() - 1;
+ s1 = hb->text(id);
+ hb->changeItem(s1 + s, id);
+ } else if (gt == BLACK) {
+ id = hw->count() - 1;
+ s1 = hw->text(id);
+ hw->changeItem(s1 + s, id);
+ }
+ } else {
+ if (gt == WHITE) {
+ id = hw->count() - 1;
+ s1 = hw->text(id);
+ hw->changeItem(s1 + s, id);
+ } else if (gt == BLACK) {
+ id = hb->count() - 1;
+ s1 = hb->text(id);
+ hb->changeItem(s1 + s, id);
+ }
+ }
+}
+
+
+void
+GameBoard::sendFigure(const TQString &coo, GameBoard::FigureType ft)
+{
+ int id = -1;
+
+ switch (ft) {
+ case BLACK_CASTLE:
+ case WHITE_CASTLE:
+ id = 5;
+ break;
+
+ case BLACK_BISHOP:
+ case WHITE_BISHOP:
+ id = 3;
+ break;
+
+ case BLACK_KNIGHT:
+ case WHITE_KNIGHT:
+ id = 4;
+ break;
+
+ case BLACK_QUEEN:
+ case WHITE_QUEEN:
+ id = 10;
+ break;
+ default:
+ id = -1;
+ }
+ if (id != -1) {
+ GameProtocol::sendFigure(sock, coo, id);
+ updateHistory(id, FALSE);
+ }
+}
+
+
+void
+GameBoard::sockTest()
+{
+
+ --sock_tout;
+ if (sock_tout < 0) {
+ tmr->stop();
+ HAXEP:
+ gt = NOGAME;
+ sockClosed();
+ } else if ((sock->state() == TQSocket::HostLookup) &&
+ (sock_tout + 60 < SOCK_WAIT)) {
+ tmr->stop();
+ TQMessageBox::critical(this, tr("Lookup Error"),
+ tr("The host") + ' ' + hst + ' ' + tr("not found."));
+ goto HAXEP;
+ }
+
+}
+
+
+void
+GameBoard::saveImage()
+{
+ TQString fn;
+
+ fn = TQFileDialog::getSaveFileName(TQString::null, "*.png", this, NULL,
+ tr("Save image"));
+
+ if (!fn.isEmpty()) {
+ if (fn.findRev(".png") < (int)(fn.length() - 4))
+ fn += ".png";
+ TQPixmap::grabWidget(this).save(fn, "PNG");
+ }
+}
+
+
+void
+GameBoard::gameover(int type)
+{
+ bool save = FALSE;
+
+ TQString s('\n' + tr("Do you want to save the image?")),
+ yes(tr("Yes, save")),
+ no(tr("No, don't save")),
+ go(tr("Game over"));
+
+ if (type == 0) {
+ save = (TQMessageBox::question(this, go,
+ tr("You scored the game") + s, yes, no) == 0);
+ } else if (type == 2) {
+ updateHistory(GAMEOVER_TXT, FALSE);
+ GameProtocol::sendGameover(sock, "MATE");
+ save = (TQMessageBox::question(this, go,
+ tr("You have a mate.\nYou lost the game.") + s,
+ yes, no) == 0);
+ } else if (type == 3) {
+ GameProtocol::sendGameover(sock, "STALEMATE");
+ save = (TQMessageBox::question(this, go,
+ tr("You have a stalemate") + s, yes, no) == 0);
+ }
+
+ if (save)
+ saveImage();
+}
+
+//-----------------------------------------------------------------------------
+
+Drawer::Drawer(GameBoard::FigureType *ft, GameBoard::GameType *g,
+ TQWidget *parent, const char *name)
+ :TQWidget(parent, name, TQt::WResizeNoErase | TQt::WRepaintNoErase)
+{
+ TQFontMetrics fm(font());
+ int i;
+
+ map = ft; gt = g;
+ kk = rcm = lcm = km = FALSE;
+ cs = cell_size * 8;
+ top_margin = 5;
+ for (left_margin = 0, i = 0; i < 8; i++)
+ left_margin = MAX(fm.width(QString::number(i)), left_margin);
+ left_margin += top_margin;
+ hl = fm.lineSpacing() + 2;
+ setPaletteBackgroundColor(TQt::white);
+ i = MAX(cs + left_margin + top_margin, cs + top_margin + hl);
+ resize(i, i);
+ x_brd = i - cs - 6;
+ y_brd = 4;
+ tfx = tfy = -1;
+ fig[0] = TQPixmap((const char **)black_bishop);
+ fig[1] = TQPixmap((const char **)black_castle);
+ fig[2] = TQPixmap((const char **)black_knight);
+ fig[3] = TQPixmap((const char **)black_pawn);
+ fig[4] = TQPixmap((const char **)black_king);
+ fig[5] = TQPixmap((const char **)black_queen);
+ fig[6] = TQPixmap((const char **)white_bishop);
+ fig[7] = TQPixmap((const char **)white_castle);
+ fig[8] = TQPixmap((const char **)white_knight);
+ fig[9] = TQPixmap((const char **)white_pawn);
+ fig[10] = TQPixmap((const char **)white_king);
+ fig[11] = TQPixmap((const char **)white_queen);
+}
+
+Drawer::~Drawer()
+{
+}
+
+
+void
+Drawer::paintEvent(TQPaintEvent *e)
+{
+ TQPainter *p;
+ int w, y;
+
+ w = width();
+ y = w - 4;
+ TQWidget::paintEvent(e);
+ p = new TQPainter(this);
+ p->setPen(TQt::black);
+ p->drawRect(0, 0, w, w);
+ p->drawRect(2, 2, y, y);
+ p->drawLine(2, y, x_brd, cs + 4);
+ drawBoard(p, x_brd, y_brd);
+ drawMap(p, x_brd, y_brd);
+ delete p;
+}
+
+
+void
+Drawer::drawBoard(TQPainter *p, int x, int y)
+{
+ int i, j, cs, x1, r, k;
+ char c, st;
+
+ cs = Drawer::cs + 2;
+ p->setPen(TQt::black);
+ p->drawRect(x, y, cs, cs);
+ c = 'a'; st = 1;
+ r = (*gt == GameBoard::BLACK);
+ if (r) {
+ c += 7;
+ st = -st;
+ k = 1;
+ r ^= 1;
+ } else
+ k = 8;
+ x1 = x + 1;
+ for (j = 0, y++; j < 8; j++, y += cell_size, r ^= 1) {
+ for (i = 0, x = x1; i < 8; i++, x += cell_size) {
+ r ^= 1;
+ if (r) {
+ p->setPen(cw);
+ p->setBrush(cw);
+ } else {
+ p->setPen(cb);
+ p->setBrush(cb);
+ }
+ p->drawRect(x, y, cell_size, cell_size);
+ if (j == 7) {
+ p->setPen(Qt::black);
+ p->drawText(x, cs + 2, cell_size, hl,
+ TQt::AlignCenter, TQChar(c));
+ c += st;
+ }
+ }
+ p->setPen(TQt::black);
+ p->drawText(x1 - left_margin, y, left_margin, cell_size,
+ TQt::AlignCenter, TQString::number(k));
+ k -= st;
+ }
+ if ((tfx != -1) && (tfy != -1)) {
+ map2win(tfx, tfy, x, y);
+ p->setPen(TQPen(TQt::red, 2));
+ p->setBrush(TQt::NoBrush);
+ p->drawRect(x, y, cell_size, cell_size);
+ }
+}
+
+
+void
+Drawer::drawMap(TQPainter *p, int x, int y)
+{
+ int i, j, x1, n;
+ TQPixmap *xpm;
+
+ x1 = x + 1; y++;
+ for (n = j = 0; j < 8; j++, y += cell_size) {
+ for (i = 0, x = x1; i < 8; i++, x += cell_size) {
+ switch (map[n++]) {
+ case GameBoard::WHITE_PAWN:
+ xpm = &fig[9];
+ break;
+ case GameBoard::WHITE_CASTLE:
+ xpm = &fig[7];
+ break;
+ case GameBoard::WHITE_BISHOP:
+ xpm = &fig[6];
+ break;
+ case GameBoard::WHITE_KING:
+ xpm = &fig[10];
+ break;
+ case GameBoard::WHITE_QUEEN:
+ xpm = &fig[11];
+ break;
+ case GameBoard::WHITE_KNIGHT:
+ xpm = &fig[8];
+ break;
+ case GameBoard::BLACK_PAWN:
+ xpm = &fig[3];
+ break;
+ case GameBoard::BLACK_CASTLE:
+ xpm = &fig[1];
+ break;
+ case GameBoard::BLACK_BISHOP:
+ xpm = &fig[0];
+ break;
+ case GameBoard::BLACK_KING:
+ xpm = &fig[4];
+ break;
+ case GameBoard::BLACK_QUEEN:
+ xpm = &fig[5];
+ break;
+ case GameBoard::BLACK_KNIGHT:
+ xpm = &fig[2];
+ break;
+ default:
+ xpm = NULL;
+ }
+ if (xpm != NULL)
+ p->drawPixmap(x, y, *xpm);
+ }
+ }
+}
+
+
+void
+Drawer::mousePressEvent(TQMouseEvent *e)
+{
+ int x = e->x() - x_brd,
+ y = e->y() - y_brd;
+
+ if ((x >= 0) && (x <= cs) && (y >= 0) && (y <= cs)) {
+ win2map(x, y);
+ if (hasTakenFigure()) {
+ if ((tfx == x) && (tfy == y)) {
+ tfx = tfy = -1;
+ repaint(FALSE);
+ } else
+ makeMove(*gt, tfx, tfy, x, y, FALSE, FALSE);
+ } else if (canTake(x, y)) {
+ takeFigure(x, y);
+ emit touchFigure(x, y);
+ }
+ }
+}
+
+
+bool
+Drawer::canTake(int x, int y)
+{
+
+ return (Figure::hasMyFigure(*gt, map, x, y, FALSE));
+}
+
+
+void
+Drawer::win2map(int &x, int &y)
+{
+
+ if (*gt == GameBoard::WHITE) {
+ x /= cell_size;
+ y = 8 - y / cell_size;
+ x++;
+ } else if (*gt == GameBoard::BLACK) {
+ x = 8 - x / cell_size;
+ y /= cell_size;
+ y++;
+ }
+}
+
+
+void
+Drawer::map2win(int mx, int my, int &x, int &y)
+{
+
+ if (*gt == GameBoard::WHITE) {
+ x = (mx - 1) * cell_size + x_brd + 1;
+ y = (8 - my) * cell_size + y_brd + 1;
+ } else if (*gt == GameBoard::BLACK) {
+ x = (8 - mx) * cell_size + x_brd + 1;
+ y = (my - 1) * cell_size + y_brd + 1;
+ } else {
+ x = mx;
+ y = my;
+ }
+}
+
+
+void
+Drawer::takeFigure(int x, int y)
+{
+
+ if ((tfx == x) && (tfy == y))
+ tfx = tfy = -1;
+ else {
+ tfx = x;
+ tfy = y;
+ }
+ repaint(FALSE);
+}
+
+
+bool
+Drawer::hasTakenFigure()
+{
+
+ return ((tfx != -1) && (tfy != -1));
+}
+
+
+void
+Drawer::newFigure(const TQString &coo, int id)
+{
+ GameBoard::FigureType ft;
+ int x, y, n;
+
+ ft = GameBoard::NONE; n = -1;
+ Figure::str2map(coo, &x, &y);
+ if (*gt == GameBoard::WHITE) {
+ n = Figure::map2map(GameBoard::BLACK, x, y, TRUE);
+ switch (id) {
+ case 3:
+ ft = GameBoard::BLACK_BISHOP;
+ break;
+ case 4:
+ ft = GameBoard::BLACK_KNIGHT;
+ break;
+ case 5:
+ ft = GameBoard::BLACK_CASTLE;
+ break;
+ case 10:
+ ft = GameBoard::BLACK_QUEEN;
+ break;
+ default:
+ ft = GameBoard::NONE;
+ }
+ } else if (*gt == GameBoard::BLACK) {
+ n = Figure::map2map(GameBoard::WHITE, x, y, TRUE);
+ switch (id) {
+ case 3:
+ ft = GameBoard::WHITE_BISHOP;
+ break;
+ case 4:
+ ft = GameBoard::WHITE_KNIGHT;
+ break;
+ case 5:
+ ft = GameBoard::WHITE_CASTLE;
+ break;
+ case 10:
+ ft = GameBoard::WHITE_QUEEN;
+ break;
+ default:
+ ft = GameBoard::NONE;
+ }
+ }
+
+ if (ft != GameBoard::NONE) {
+ map[n] = ft;
+ repaint(FALSE);
+ }
+}
+
+
+void
+Drawer::makeMove(const TQString &txt)
+{
+ int fx, fy, tx, ty;
+ GameBoard::GameType et;
+
+ if (*gt == GameBoard::WHITE)
+ et = GameBoard::BLACK;
+ else if (*gt == GameBoard::BLACK)
+ et = GameBoard::WHITE;
+ else
+ et = GameBoard::NOGAME;
+ if (txt == LONG_XCHG) {
+ if (et == GameBoard::BLACK)
+ makeMove(et, 1, 8, 4, 8, TRUE, TRUE);
+ else if (et == GameBoard::WHITE)
+ makeMove(et, 1, 1, 4, 1, TRUE, TRUE);
+ } else if (txt == SHORT_XCHG) {
+ if (et == GameBoard::BLACK)
+ makeMove(et, 8, 8, 6, 8, TRUE, TRUE);
+ else if (et == GameBoard::WHITE)
+ makeMove(et, 8, 1, 6, 1, TRUE, TRUE);
+ } else {
+ Figure::str2map(txt.left(2), &fx, &fy);
+ Figure::str2map(txt.right(2), &tx, &ty);
+ makeMove(et, fx, fy, tx, ty, TRUE, FALSE);
+ }
+}
+
+
+void
+Drawer::makeMove(GameBoard::GameType gt, int fx, int fy, int tx, int ty,
+ bool mirror, bool xc)
+{
+ GameBoard::GameType et;
+ GameBoard::FigureType fo, old;
+ int res, nf, nt;
+ FigureDialog *dlg;
+ bool x;
+ TQPointArray vl;
+
+ et = GameBoard::NOGAME;
+ nf = Figure::map2map(gt, fx, fy, mirror);
+ fo = map[nf];
+ nt = Figure::map2map(gt, tx, ty, mirror);
+ old = map[nt];
+ res = Figure::validMove(gt, map, fx, fy, tx, ty, mirror);
+ if (res) {
+ if (!mirror) {
+ x = FALSE;
+ if (gt == GameBoard::WHITE)
+ et = GameBoard::BLACK;
+ else if (gt == GameBoard::BLACK)
+ et = GameBoard::WHITE;
+ if (Figure::checkKing(et, map, mirror, vl, TRUE) !=
+ 0) {
+ map[nf] = map[nt];
+ map[nt] = old;
+ tfx = tfy = -1;
+ TQMessageBox::information(this,
+ tr("Error moving"), tr("You cannot "
+ "move this figure because the king "
+ "is in check") + '.');
+ goto HAXEP;
+ } else
+ kk = FALSE;
+ if (!km && (!lcm || !rcm) && !kk)
+ x = xchg(fo, map[nt], fx, fy, tx, ty);
+ else
+ x = TRUE;
+ if (x)
+ emit moved(Figure::map2str(fx, fy) +
+ Figure::map2str(tx, ty));
+ if ((res & 0xF) == 2) {
+ dlg = new FigureDialog(fig, gt, this);
+ dlg->exec();
+ fo = dlg->figure();
+ delete dlg;
+ map[nt] = fo;
+ emit newFigure(Figure::map2str(tx, ty), fo);
+ }
+ tfx = tfy = -1;
+ } else if (xc) {
+ if (gt == GameBoard::BLACK)
+ checkBlackCastle(fx, fy, tx, ty, TRUE);
+ else if (gt == GameBoard::WHITE)
+ checkWhiteCastle(fx, fy, tx, ty, TRUE);
+ }
+ if (mirror && (res & 0x10)) {
+ kk = TRUE;
+ } else if (res & 0x20) {
+ repaint(FALSE);
+ emit gameover(2);
+ return;
+ } else if (res & 0x40) {
+ repaint(FALSE);
+ emit gameover(3);
+ return;
+ }
+ HAXEP:
+ repaint(FALSE);
+ }
+}
+
+
+bool
+Drawer::xchg(GameBoard::FigureType o, GameBoard::FigureType n,
+ int fx, int fy, int tx, int ty)
+{
+ bool ret = TRUE;
+
+ if (*gt == GameBoard::WHITE) {
+ km = ((o == n) && (o == GameBoard::WHITE_KING));
+ if (!km && ((o == n) && (o == GameBoard::WHITE_CASTLE)))
+ ret = checkWhiteCastle(fx, fy, tx, ty, FALSE);
+ } else if (*gt == GameBoard::BLACK) {
+ km = ((o == n) && (o == GameBoard::BLACK_KING));
+ if (!km && ((o == n) && (o == GameBoard::BLACK_CASTLE)))
+ ret = checkBlackCastle(fx, fy, tx, ty, FALSE);
+ }
+
+ return (ret);
+}
+
+
+bool
+Drawer::checkWhiteCastle(int fx, int fy, int tx, int ty, bool mirror)
+{
+ int n1, n2;
+ bool ret = TRUE;
+
+ n1 = n2 = -1;
+ if ((fx == 1) && (fy == 1)) {
+ if ((tx == 4) && (ty == 1))
+ if (mirror) {
+ n1 = Figure::map2map(*gt, 5, 1, FALSE);
+ n2 = Figure::map2map(*gt, 3, 1, FALSE);
+ } else if (!lcm) {
+ if (makeXchg()) {
+ n1 = Figure::map2map(*gt, 5, 1, FALSE);
+ n2 = Figure::map2map(*gt, 3, 1, FALSE);
+ emit moved(LONG_XCHG);
+ ret = FALSE;
+ rcm = TRUE;
+ }
+ lcm = TRUE;
+ }
+ } else if ((fx == 8) && (fy == 1)) {
+ if ((tx == 6) && (ty == 1))
+ if (mirror) {
+ n1 = Figure::map2map(*gt, 5, 1, FALSE);
+ n2 = Figure::map2map(*gt, 7, 1, FALSE);
+ } else if (!rcm) {
+ if (makeXchg()) {
+ n1 = Figure::map2map(*gt, 5, 1, FALSE);
+ n2 = Figure::map2map(*gt, 7, 1, FALSE);
+ emit moved(SHORT_XCHG);
+ ret = FALSE;
+ lcm = TRUE;
+ }
+ rcm = TRUE;
+ }
+ }
+ if (n1 != n2) {
+ map[n2] = map[n1];
+ map[n1] = GameBoard::NONE;
+ }
+
+ return (ret);
+}
+
+
+bool
+Drawer::checkBlackCastle(int fx, int fy, int tx, int ty, bool mirror)
+{
+ int n1, n2;
+ bool ret = TRUE;
+
+ n1 = n2 = -1;
+ if ((fx == 1) && (fy == 8)) {
+ if ((tx == 4) && (ty == 8)) {
+ if (mirror) {
+ n1 = Figure::map2map(*gt, 5, 8, FALSE);
+ n2 = Figure::map2map(*gt, 3, 8, FALSE);
+ } else if (!rcm) {
+ if (makeXchg()) {
+ n1 = Figure::map2map(*gt, 5, 8, FALSE);
+ n2 = Figure::map2map(*gt, 3, 8, FALSE);
+ emit moved(LONG_XCHG);
+ ret = FALSE;
+ }
+ rcm = TRUE;
+ }
+ }
+ } else if ((fx == 8) && (fy == 8)) {
+ if ((tx == 6) && (ty == 8))
+ if (mirror) {
+ n1 = Figure::map2map(*gt, 5, 8, FALSE);
+ n2 = Figure::map2map(*gt, 7, 8, FALSE);
+ } else if (!lcm) {
+ if (makeXchg()) {
+ n1 = Figure::map2map(*gt, 5, 8, FALSE);
+ n2 = Figure::map2map(*gt, 7, 8, FALSE);
+ emit moved(SHORT_XCHG);
+ ret = FALSE;
+ }
+ lcm = TRUE;
+ }
+ }
+ if (n1 != n2) {
+ map[n2] = map[n1];
+ map[n1] = GameBoard::NONE;
+ }
+
+ return (ret);
+}
+
+
+bool
+Drawer::makeXchg()
+{
+
+ return (TQMessageBox::question(this, tr("To castle"),
+ tr("Do you want to castle?"), tr("Yes"), tr("No")) == 0);
+}
+
+
+//-----------------------------------------------------------------------------
+
+FigureDialog::FigureDialog(const TQPixmap *f, const GameBoard::GameType g,
+ TQWidget *parent, const char *name):TQDialog(parent, name)
+{
+ TQFontMetrics fm(font());
+ int w, h;
+
+ gt = g; fig = f;
+ if (gt == GameBoard::WHITE)
+ fr = GameBoard::WHITE_QUEEN;
+ else if (gt == GameBoard::BLACK)
+ fr = GameBoard::BLACK_QUEEN;
+ str = tr("What figure should I set?");
+ setCaption(str);
+ fh = fm.lineSpacing() + 2;
+ h = cell_size + fh;
+ w = MAX(cell_size * 4, fm.width(str));
+ step = (w - cell_size * 4) / 2;
+ resize(w, h);
+ setMinimumSize(size());
+ setMaximumSize(size());
+}
+
+FigureDialog::~FigureDialog()
+{
+}
+
+
+void
+FigureDialog::paintEvent(TQPaintEvent *e)
+{
+ TQPainter *p;
+ int x, f = -1;
+
+ TQDialog::paintEvent(e);
+ p = new TQPainter(this);
+
+ p->setPen(TQt::black);
+ p->drawText(0, 0, width(), fh, TQt::AlignCenter, str);
+ x = step;
+ if (gt == GameBoard::BLACK)
+ f = 0;
+ else if (gt == GameBoard::WHITE)
+ f = 6;
+ p->drawPixmap(x, fh, fig[f]); x += cell_size;
+ p->drawPixmap(x, fh, fig[f + 1]); x += cell_size;
+ p->drawPixmap(x, fh, fig[f + 2]); x += cell_size;
+ p->drawPixmap(x, fh, fig[f + 5]);
+
+ delete p;
+}
+
+
+void
+FigureDialog::mousePressEvent(TQMouseEvent *e)
+{
+ int x = e->x(),
+ y = e->y(),
+ f = -1;
+
+ if (e->button() == TQt::LeftButton) {
+ if ((x >= step) && (x <= width() - step) && (y >= fh) &&
+ (y <= height()))
+ f = (x - step) / cell_size;
+ }
+
+ if (f != -1) {
+ if (gt == GameBoard::WHITE)
+ switch (f) {
+ case 0:
+ fr = GameBoard::WHITE_BISHOP;
+ break;
+ case 1:
+ fr = GameBoard::WHITE_CASTLE;
+ break;
+ case 2:
+ fr = GameBoard::WHITE_KNIGHT;
+ break;
+ case 3:
+ default:
+ fr = GameBoard::WHITE_QUEEN;
+ }
+ else if (gt == GameBoard::BLACK)
+ switch (f) {
+ case 0:
+ fr = GameBoard::BLACK_BISHOP;
+ break;
+ case 1:
+ fr = GameBoard::BLACK_CASTLE;
+ break;
+ case 2:
+ fr = GameBoard::BLACK_KNIGHT;
+ break;
+ case 3:
+ default:
+ fr = GameBoard::BLACK_QUEEN;
+ }
+ accept();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+
+void
+GameProtocol::send(TQSocket *sock, const TQString &dat)
+{
+ TQString s(dat + EOL);
+ const char *buf;
+
+ if (sock->state() == TQSocket::Connected) {
+ buf = s.ascii();
+ sock->writeBlock(buf, s.length());
+ sock->flush();
+ }
+}
+
+
+void
+GameProtocol::setGameType(TQSocket *sock, GameBoard::GameType gt)
+{
+ TQString d("GAME");
+
+ d += SEP;
+ if (gt == GameBoard::WHITE)
+ d += "WHITE";
+ else if (gt == GameBoard::BLACK)
+ d += "BLACK";
+ else
+ d += "NOGAME";
+ send(sock, d);
+}
+
+
+void
+GameProtocol::acceptGame(TQSocket *sock)
+{
+ TQString d("GAME");
+
+ d += SEP;
+ d += "ACCEPT";
+ send(sock, d);
+}
+
+
+void
+GameProtocol::sendMove(TQSocket *sock, const TQString &coo)
+{
+ TQString d("MOVE");
+
+ d += SEP;
+ d += coo;
+ send(sock, d);
+}
+
+
+void
+GameProtocol::sendQuit(TQSocket *sock)
+{
+
+ send(sock, "QUIT");
+}
+
+
+void
+GameProtocol::sendText(TQSocket *sock, const TQString &txt)
+{
+ TQString d("CHAT");
+
+ d += SEP;
+ d += txt;
+ send(sock, d);
+}
+
+
+void
+GameProtocol::sendFigure(TQSocket *sock, const TQString &coo, int id)
+{
+ TQString d("FIGURE");
+
+ d += SEP;
+ d += coo;
+ d += SEP;
+ d += TQString::number(id);
+ send(sock, d);
+}
+
+
+void
+GameProtocol::sendGameover(TQSocket *sock, const TQString &got)
+{
+ TQString d("GAME");
+
+ d += SEP;
+ d += got;
+ send(sock, d);
+}
+
+#include "gameboard.moc"