home *** CD-ROM | disk | FTP | other *** search
- /*
- C source for Winsock Chess
-
- Revision 1994-03-15
- Modified by Donald Munro for use as a 2 player chess game over a
- WINSOCK layer on a TCP (or other WinSock supporting) network.
- Source code and make files for MS Visual C/C++ V1.00/1.50.
- February/March 1994
- All GNU copyright and distribution conditions as described below and in the
- file COPYING also apply to WinSock Chess.
- This module is adapted from GNU Chess.
-
- C source for GNU CHESS
-
- Revision: 1990-09-30
-
- Modified by Daryl Baker for use in MS WINDOWS environment
-
- Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
- Copyright (c) 1988, 1989, 1990 John Stanback
-
- This file is part of CHESS.
-
- CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone for
- the consequences of using it or for whether it serves any particular
- purpose or works at all, unless he says so in writing. Refer to the CHESS
- General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute CHESS, but
- only under the conditions described in the CHESS General Public License.
- A copy of this license is supposed to have been given to you along with
- CHESS so you can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice and this
- notice must be preserved on all copies.
- */
-
- #define NOATOM
- #define NOCLIPBOARD
- #define NOCREATESTRUCT
- #define NOFONT
- #define NOREGION
- #define NOSOUND
- #define NOWH
- #define NOWINOFFSETS
- #define NOCOMM
- #define NOKANJI
-
- #include <windows.h>
- #include <string.h>
- #include <time.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <stdio.h>
-
- #include "gnuchess.h"
- #include "defs.h"
-
- /*
- hashbd contains a 32 bit "signature" of the board position. hashkey
- contains a 16 bit code used to address the hash table. When a move is
- made, XOR'ing the hashcode of moved piece on the from and to squares with
- the hashbd and hashkey values keeps things current.
- */
- #define UpdateHashbd(side, piece, f, t) \
- {\
- if ((f) >= 0)\
- {\
- hashbd ^= (hashcode+(side)*7*64+(piece)*64+f)->bd;\
- hashkey ^= (hashcode+(side)*7*64+(piece)*64+f)->key;\
- }\
- if ((t) >= 0)\
- {\
- hashbd ^= (hashcode+(side)*7*64+(piece)*64+t)->bd;\
- hashkey ^= (hashcode+(side)*7*64+(piece)*64+t)->key;\
- }\
- }
-
-
- #if ttblsz
- extern unsigned long hashkey, hashbd;
- /*extern struct hashval hashcode[2][7][64];*/
- /*extern struct hashentry huge ttable[2][ttblsz];*/
- extern struct hashval far *hashcode;
- extern struct hashentry far *ttable;
- #endif /* ttblsz */
-
- /*extern unsigned char history[8192];*/
- extern unsigned char far * history;
-
- extern short rpthash[2][256];
- /*extern unsigned char nextpos[8][64][64];*/
- /*extern unsigned char nextdir[8][64][64];*/
- extern unsigned char far *nextpos;
- extern unsigned char far *nextdir;
-
- extern short FROMsquare, TOsquare, Zscore, zwndw;
- extern unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
- extern unsigned short killr0[maxdepth], killr1[maxdepth];
- extern unsigned short killr2[maxdepth], killr3[maxdepth];
- extern short Pscore[maxdepth], Tscore[maxdepth];
- extern unsigned long hashkey, hashbd;
- extern short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
- extern short mtl[2], pmtl[2], emtl[2], hung[2];
- extern short player, xwndw, rehash;
- extern short PieceCnt[2];
- extern long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
- extern short HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
- extern short Pindex[64];
-
- static short _based(_segname("_CODE")) rank7[3] = {6, 1, 0};
- static short _based(_segname("_CODE")) kingP[3] = {4, 60, 0};
- static short _based(_segname("_CODE")) value[7] =
- {0, valueP, valueN, valueB, valueR, valueQ, valueK};
-
- static short _based(_segname("_CODE")) sweep[8] =
- {false, false, false, true, true, true, false, false};
-
- static short _based(_segname("_CODE")) ptype[2][8] = {
- no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
- no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
-
- static short _based(_segname("_CODE")) control[7] =
- {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
-
-
- void ZeroRPT (void)
- {
- register int side, i;
-
- for (side = white; side <= black; side++)
- for (i = 0; i < 256; i++)
- rpthash[side][i] = 0;
- }
-
- int castle (short int side, short int kf, short int kt, short int iop)
-
- /* Make or Unmake a castling move. */
-
- {
- short rf, rt, t0, xside;
-
- xside = otherside[side];
- if (kt > kf)
- {
- rf = kf + 3;
- rt = kt - 1;
- }
- else
- {
- rf = kf - 4;
- rt = kt + 1;
- }
- if (iop == 0)
- {
- if (kf != kingP[side] ||
- board[kf] != king ||
- board[rf] != rook ||
- Mvboard[kf] != 0 ||
- Mvboard[rf] != 0 ||
- color[kt] != neutral ||
- color[rt] != neutral ||
- color[kt - 1] != neutral ||
- SqAtakd (kf, xside) ||
- SqAtakd (kt, xside) ||
- SqAtakd (rt, xside))
- return (false);
- }
- else
- {
- if (iop == 1)
- {
- castld[side] = true;
- Mvboard[kf]++;
- Mvboard[rf]++;
- }
- else
- {
- castld[side] = false;
- Mvboard[kf]--;
- Mvboard[rf]--;
- t0 = kt;
- kt = kf;
- kf = t0;
- t0 = rt;
- rt = rf;
- rf = t0;
- }
- board[kt] = king;
- color[kt] = side;
- Pindex[kt] = 0;
- board[kf] = no_piece;
- color[kf] = neutral;
- board[rt] = rook;
- color[rt] = side;
- Pindex[rt] = Pindex[rf];
- board[rf] = no_piece;
- color[rf] = neutral;
- PieceList[side][Pindex[kt]] = kt;
- PieceList[side][Pindex[rt]] = rt;
- #if ttblsz
- UpdateHashbd (side, king, kf, kt);
- UpdateHashbd (side, rook, rf, rt);
- #endif /* ttblsz */
- }
- return (true);
- }
-
-
- static inline void
- EnPassant (short int xside, short int f, short int t, short int iop)
-
- /*
- Make or unmake an en passant move.
- */
-
- {
- register short l;
-
- if (t > f)
- l = t - 8;
- else
- l = t + 8;
- if (iop == 1)
- {
- board[l] = no_piece;
- color[l] = neutral;
- }
- else
- {
- board[l] = pawn;
- color[l] = xside;
- }
- InitializeStats ();
- }
-
-
- static inline void
- UpdatePieceList (short int side, short int sq, short int iop)
-
- /*
- Update the PieceList and Pindex arrays when a piece is captured or when a
- capture is unmade.
- */
-
- {
- register short i;
- if (iop == 1)
- {
- PieceCnt[side]--;
- for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
- {
- PieceList[side][i] = PieceList[side][i + 1];
- Pindex[PieceList[side][i]] = i;
- }
- }
- else
- {
- PieceCnt[side]++;
- PieceList[side][PieceCnt[side]] = sq;
- Pindex[sq] = PieceCnt[side];
- }
- }
-
- void
- ZeroTTable (void)
- {
- register int side, i;
-
- if (flag.hash)
- for (side = white; side <= black; side++)
- for (i = 0; i < ttblsz; i++)
- /* ttable[side][i].depth = 0; */
- (ttable+side*2+i)->depth = 0;
- }
-
- #define Link(from,to,flag,s) \
- {\
- node->f = from; node->t = to;\
- node->reply = 0;\
- node->flags = flag;\
- node->score = s;\
- ++node;\
- ++TrPnt[ply+1];\
- }
-
- static inline void
- LinkMove (short int ply,
- short int f,
- short int t,
- short int flag,
- short int xside)
-
- /*
- Add a move to the tree. Assign a bonus to order the moves
- as follows:
- 1. Principle variation
- 2. Capture of last moved piece
- 3. Other captures (major pieces first)
- 4. Killer moves
- 5. "history" killers
- */
-
- {
- register short s, z;
- unsigned short mv;
- struct leaf far *node;
-
- node = &Tree[TrPnt[ply + 1]];
- mv = (f << 8) | t;
- s = 0;
- if (mv == Swag0)
- s = 2000;
- else if (mv == Swag1)
- s = 60;
- else if (mv == Swag2)
- s = 50;
- else if (mv == Swag3)
- s = 40;
- else if (mv == Swag4)
- s = 30;
- z = (f << 6) | t;
- if (xside == white)
- z |= 0x1000;
- /* s += history[z]; */
- s += *(history+z);
- if (color[t] != neutral)
- {
- if (t == TOsquare)
- s += 500;
- s += value[board[t]] - board[f];
- }
- if (board[f] == pawn)
- if (row (t) == 0 || row (t) == 7)
- {
- flag |= promote;
- s += 800;
- Link (f, t, flag | queen, s - 20000);
- s -= 200;
- Link (f, t, flag | knight, s - 20000);
- s -= 50;
- Link (f, t, flag | rook, s - 20000);
- flag |= bishop;
- s -= 50;
- }
- else if (row (t) == 1 || row (t) == 6)
- {
- flag |= pwnthrt;
- s += 600;
- }
- Link (f, t, flag, s - 20000);
- }
-
-
- static inline void
- GenMoves (short int ply, short int sq, short int side, short int xside)
-
- /*
- Generate moves for a piece. The moves are taken from the precalulated
- array nextpos/nextdir. If the board is free, next move is choosen from
- nextpos else from nextdir.
- */
-
- {
- register short u, piece;
- unsigned char far *ppos, far *pdir;
-
- piece = board[sq];
- ppos = nextpos+ptype[side][piece]*64*64+sq*64;
- pdir = nextdir+ptype[side][piece]*64*64+sq*64;
- if (piece == pawn)
- {
- u = ppos[sq]; /* follow no captures thread */
- if (color[u] == neutral)
- {
- LinkMove (ply, sq, u, 0, xside);
- u = ppos[u];
- if (color[u] == neutral)
- LinkMove (ply, sq, u, 0, xside);
- }
- u = pdir[sq]; /* follow captures thread */
- if (color[u] == xside)
- LinkMove (ply, sq, u, capture, xside);
- else
- if (u == epsquare)
- LinkMove (ply, sq, u, capture | epmask, xside);
- u = pdir[u];
- if (color[u] == xside)
- LinkMove (ply, sq, u, capture, xside);
- else
- if (u == epsquare)
- LinkMove (ply, sq, u, capture | epmask, xside);
- }
- else
- {
- u = ppos[sq];
- do
- {
- if (color[u] == neutral)
- {
- LinkMove (ply, sq, u, 0, xside);
- u = ppos[u];
- }
- else
- {
- if (color[u] == xside)
- LinkMove (ply, sq, u, capture, xside);
- u = pdir[u];
- }
- } while (u != sq);
- }
- }
-
-
- void
- MoveList (short int side, short ply)
-
- /*
- Fill the array Tree[] with all available moves for side to play. Array
- TrPnt[ply] contains the index into Tree[] of the first move at a ply.
- */
-
- {
- short i, xside, f;
-
- //ply = 2;
- xside = otherside[side];
- TrPnt[ply + 1] = TrPnt[ply];
- if (PV == 0)
- Swag0 = killr0[ply];
- else
- Swag0 = PV;
- Swag1 = killr1[ply];
- Swag2 = killr2[ply];
- Swag3 = killr3[ply];
- if (ply > 2)
- Swag4 = killr1[ply - 2];
- else
- Swag4 = 0;
- for (i = PieceCnt[side]; i >= 0; i--)
- GenMoves (ply, PieceList[side][i], side, xside);
- if (!castld[side])
- {
- f = PieceList[side][0];
- if (castle (side, f, f + 2, 0))
- {
- LinkMove (ply, f, f + 2, cstlmask, xside);
- }
- if (castle (side, f, f - 2, 0))
- {
- LinkMove (ply, f, f - 2, cstlmask, xside);
- }
- }
- }
-
-
- void
- MakeMove (short int side,
- struct leaf far * node,
- short int *tempb,
- short int *tempc,
- short int *tempsf,
- short int *tempst,
- short int *INCscore)
-
- /*
- Update Arrays board[], color[], and Pindex[] to reflect the new board
- position obtained after making the move pointed to by node. Also update
- miscellaneous stuff that changes when a move is made.
- */
-
- {
- short f, t, xside, ct, cf;
-
- xside = otherside[side];
- GameCnt++;
- f = node->f;
- t = node->t;
- epsquare = -1;
- FROMsquare = f;
- TOsquare = t;
- *INCscore = 0;
- GameList[GameCnt].gmove = (f << 8) | t;
- if (node->flags & cstlmask)
- {
- GameList[GameCnt].piece = no_piece;
- GameList[GameCnt].color = side;
- (void) castle (side, f, t, 1);
- }
- else
- {
- if (!(node->flags & capture) && (board[f] != pawn))
- rpthash[side][hashkey & 0xFF]++;
- *tempc = color[t];
- *tempb = board[t];
- *tempsf = svalue[f];
- *tempst = svalue[t];
- GameList[GameCnt].piece = *tempb;
- GameList[GameCnt].color = *tempc;
- if (*tempc != neutral)
- {
- UpdatePieceList (*tempc, t, 1);
- if (*tempb == pawn)
- --PawnCnt[*tempc][column (t)];
- if (board[f] == pawn)
- {
- --PawnCnt[side][column (f)];
- ++PawnCnt[side][column (t)];
- cf = column (f);
- ct = column (t);
- if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
- *INCscore -= 15;
- else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
- *INCscore += 15;
- else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
- *INCscore -= 15;
- }
- mtl[xside] -= value[*tempb];
- if (*tempb == pawn)
- pmtl[xside] -= valueP;
- #if ttblsz
- UpdateHashbd (xside, *tempb, -1, t);
- #endif /* ttblsz */
- *INCscore += *tempst;
- Mvboard[t]++;
- }
- color[t] = color[f];
- board[t] = board[f];
- svalue[t] = svalue[f];
- Pindex[t] = Pindex[f];
- PieceList[side][Pindex[t]] = t;
- color[f] = neutral;
- board[f] = no_piece;
- if (board[t] == pawn)
- if (t - f == 16)
- epsquare = f + 8;
- else if (f - t == 16)
- epsquare = f - 8;
- if (node->flags & promote)
- {
- board[t] = node->flags & pmask;
- if (board[t] == queen)
- HasQueen[side]++;
- else if (board[t] == rook)
- HasRook[side]++;
- else if (board[t] == bishop)
- HasBishop[side]++;
- else if (board[t] == knight)
- HasKnight[side]++;
- --PawnCnt[side][column (t)];
- mtl[side] += value[board[t]] - valueP;
- pmtl[side] -= valueP;
- #if ttblsz
- UpdateHashbd (side, pawn, f, -1);
- UpdateHashbd (side, board[t], f, -1);
- #endif /* ttblsz */
- *INCscore -= *tempsf;
- }
- if (node->flags & epmask)
- EnPassant (xside, f, t, 1);
- else
- #if ttblsz
- UpdateHashbd (side, board[t], f, t);
- #else
- /* NOOP */;
- #endif /* ttblsz */
- Mvboard[f]++;
- }
- }
-
- void
- UnmakeMove (short int side,
- struct leaf far * node,
- short int *tempb,
- short int *tempc,
- short int *tempsf,
- short int *tempst)
-
- /*
- Take back a move.
- */
-
- {
- short f, t, xside;
-
- xside = otherside[side];
- f = node->f;
- t = node->t;
- epsquare = -1;
- GameCnt--;
- if (node->flags & cstlmask)
- (void) castle (side, f, t, 2);
- else
- {
- color[f] = color[t];
- board[f] = board[t];
- svalue[f] = *tempsf;
- Pindex[f] = Pindex[t];
- PieceList[side][Pindex[f]] = f;
- color[t] = *tempc;
- board[t] = *tempb;
- svalue[t] = *tempst;
- if (node->flags & promote)
- {
- board[f] = pawn;
- ++PawnCnt[side][column (t)];
- mtl[side] += valueP - value[node->flags & pmask];
- pmtl[side] += valueP;
- #if ttblsz
- UpdateHashbd (side, (short) node->flags & pmask, -1, t);
- UpdateHashbd (side, pawn, -1, t);
- #endif /* ttblsz */
- }
- if (*tempc != neutral)
- {
- UpdatePieceList (*tempc, t, 2);
- if (*tempb == pawn)
- ++PawnCnt[*tempc][column (t)];
- if (board[f] == pawn)
- {
- --PawnCnt[side][column (t)];
- ++PawnCnt[side][column (f)];
- }
- mtl[xside] += value[*tempb];
- if (*tempb == pawn)
- pmtl[xside] += valueP;
- #if ttblsz
- UpdateHashbd (xside, *tempb, -1, t);
- #endif /* ttblsz */
- Mvboard[t]--;
- }
- if (node->flags & epmask)
- EnPassant (xside, f, t, 2);
- else
- #if ttblsz
- UpdateHashbd (side, board[f], f, t);
- #else
- /* NOOP */;
- #endif /* ttblsz */
- Mvboard[f]--;
- if (!(node->flags & capture) && (board[f] != pawn))
- rpthash[side][hashkey & 0xFF]--;
- }
- }
-
-
- void
- InitializeStats (void)
-
- /*
- Scan thru the board seeing what's on each square. If a piece is found,
- update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
- determine the material for each side and set the hashkey and hashbd
- variables to represent the current board position. Array
- PieceList[side][indx] contains the location of all the pieces of either
- side. Array Pindex[sq] contains the indx into PieceList for a given
- square.
- */
-
- {
- short i, sq;
-
- epsquare = -1;
- for (i = 0; i < 8; i++)
- PawnCnt[white][i] = PawnCnt[black][i] = 0;
- mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
- PieceCnt[white] = PieceCnt[black] = 0;
- #if ttblsz
- hashbd = hashkey = 0;
- #endif /* ttblsz */
- for (sq = 0; sq < 64; sq++)
- if (color[sq] != neutral)
- {
- mtl[color[sq]] += value[board[sq]];
- if (board[sq] == pawn)
- {
- pmtl[color[sq]] += valueP;
- ++PawnCnt[color[sq]][column (sq)];
- }
- if (board[sq] == king)
- Pindex[sq] = 0;
- else
- Pindex[sq] = ++PieceCnt[color[sq]];
- PieceList[color[sq]][Pindex[sq]] = sq;
- #if ttblsz
- hashbd ^= (hashcode+color[sq]*7*64+board[sq]*64+sq)->bd;
- hashkey ^= (hashcode+color[sq]*7*64+board[sq]*64+sq)->key;
- #endif /* ttblsz */
- }
- }
-
-
- int
- SqAtakd (short int sq, short int side)
-
- /*
- See if any piece with color 'side' ataks sq. First check pawns then Queen,
- Bishop, Rook and King and last Knight.
- */
-
- {
- register short u;
- unsigned char far *ppos, far *pdir;
- short xside;
-
- xside = otherside[side];
- pdir = nextdir+ptype[xside][pawn]*64*64+sq*64;
- u = pdir[sq]; /* follow captures thread */
- if (u != sq)
- {
- if (board[u] == pawn && color[u] == side)
- return (true);
- u = pdir[u];
- if (u != sq && board[u] == pawn && color[u] == side)
- return (true);
- }
- /* king capture */
- if (distance (sq, PieceList[side][0]) == 1)
- return (true);
- /* try a queen bishop capture */
- ppos = nextpos+bishop*64*64+sq*64;
- pdir = nextdir+bishop*64*64+sq*64;
- u = ppos[sq];
- do
- {
- if (color[u] == neutral)
- u = ppos[u];
- else
- {
- if (color[u] == side &&
- (board[u] == queen || board[u] == bishop))
- return (true);
- u = pdir[u];
- }
- } while (u != sq);
- /* try a queen rook capture */
- ppos = nextpos+rook*64*64+sq*64;
- pdir = nextdir+rook*64*64+sq*64;
- u = ppos[sq];
- do
- {
- if (color[u] == neutral)
- u = ppos[u];
- else
- {
- if (color[u] == side &&
- (board[u] == queen || board[u] == rook))
- return (true);
- u = pdir[u];
- }
- } while (u != sq);
- /* try a knight capture */
- pdir = nextdir+knight*64*64+sq*64;
- u = pdir[sq];
- do
- {
- if (color[u] == side && board[u] == knight)
- return (true);
- u = pdir[u];
- } while (u != sq);
- return (false);
- }
-
-