//#define USE_SIDEBIT 1 // 4PL70 uses SIDEBIT here!! /* * genmoves.c - C source for GNU CHESS * * Copyright (c) 1988,1989,1990 John Stanback * Copyright (c) 1992 Free Software Foundation * * This file is part of GNU CHESS. * * GNU Chess is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GNU Chess is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Chess; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gnuchess.h" short __aligned *TrP; #define Link(from,to,flag,s) \ {\ node->f = from; node->t = to;\ node->reply = 0;\ node->flags = flag;\ node->score = s;\ ++node;\ (*TrP)++;\ } #ifndef KILLTO inline void LinkMove (ARGSZ int ply, ARGSZ int f, ARGSZ int t, ARGSZ int flag, ARGSZ int xside) #else inline void LinkMove (ARGSZ int ply, ARGSZ int f, ARGSZ int t, ARGSZ int flag) #endif /* * 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. */ { register short s = 0; #if defined HISTORY register short z; #endif register unsigned short mv; register struct leaf *node; node = &Tree[*TrP]; mv = (f << 8) | t; #ifdef KILLT #ifdef USE_SIDEBIT s += killt[mv | sidebit]; #else s += killt[mv]; #endif #endif #ifdef HISTORY z = mv; if (xside == white) z |= 0x4000; s += history[z]; #endif if (color[t] != neutral) { /* TOsquare is the square the last piece moved moved to */ s += value[board[t]] - board[f] + ((t == TOsquare) ? 500 : 0); } if (board[f] == pawn) if (row (t) == 0 || row (t) == 7) { flag |= promote; s += 800; #if !defined OLDXBOARD && !defined GNU3 && !defined CHESSTOOL 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 flag |= queen; #endif } else if (row (t) == 1 || row (t) == 6) { flag |= pwnthrt; s += 600; } else if ((row(t) == ((color[f] == white)?5:2)) && (ply > MINDEPTH) && (ply < Sdepth+3)) { if ((mtl[white] - pmtl[white] + mtl[black] - pmtl[black]) < PTVALUE) { flag |= pwnthrt; s += 400; } } Link (f, t, flag, s - 20000); } inline void GenMoves (ARGSZ int ply, ARGSZ int sq, ARGSZ int side, ARGSZ 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; register unsigned char *ppos, *pdir; TrP = &TrPnt[ply + 1]; piece = board[sq]; ppos = nextpos[ptype[side][piece]][sq]; pdir = nextdir[ptype[side][piece]][sq]; if (piece == pawn) { u = ppos[sq]; /* follow no captures thread */ if (color[u] == neutral) { #ifndef KILLTO LinkMove (ply, sq, u, 0, xside); #else LinkMove (ply, sq, u, 0); #endif u = ppos[u]; if (color[u] == neutral) #ifndef KILLTO LinkMove (ply, sq, u, 0, xside); #else LinkMove (ply, sq, u, 0); #endif } u = pdir[sq]; /* follow captures thread */ if (color[u] == xside && board[u] != king) #ifndef KILLTO LinkMove (ply, sq, u, capture, xside); #else LinkMove (ply, sq, u, capture); #endif u = pdir[u]; if (color[u] == xside && board[u] != king) #ifndef KILLTO LinkMove (ply, sq, u, capture, xside); #else LinkMove (ply, sq, u, capture); #endif } else { u = ppos[sq]; do { if (color[u] == neutral) { #ifndef KILLTO LinkMove (ply, sq, u, 0, xside); #else LinkMove (ply, sq, u, 0); #endif u = ppos[u]; } else { if (color[u] == xside && board[u] != king) #ifndef KILLTO LinkMove (ply, sq, u, capture, xside); #else LinkMove (ply, sq, u, capture); #endif u = pdir[u]; } } while (u != sq); } } void MoveList (INTSIZE int side, INTSIZE int 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. */ { register short i, xside, f; xside = side ^ 1; TrP = &TrPnt[ply + 1]; *TrP = TrPnt[ply]; if (!PV) 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; #ifdef KILLT #ifdef USE_SIDEBIT sidebit = ((side == white) ? 0 : 0x80); killt[SwagHt | sidebit] += 5000; killt[Swag0 | sidebit] += 2000; killt[Swag1 | sidebit] += 60; killt[Swag2 | sidebit] += 50; killt[Swag3 | sidebit] += 40; killt[Swag4 | sidebit] += 30; #else killt[SwagHt] += 5000; killt[Swag0] += 2000; killt[Swag1] += 60; killt[Swag2] += 50; killt[Swag3] += 40; killt[Swag4] += 30; #endif #endif #ifdef HISTORKILLT #ifdef HISTORY i = (side == black)?0x4000:0; history[SwagHt | i] += 5000; history[Swag0 | i] += 2000; history[Swag1 | i] += 60; history[Swag2 | i] += 50; history[Swag3 | i] += 40; history[Swag4 | i] += 30; #endif #endif 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)) { #ifndef KILLTO LinkMove (ply, f, f + 2, cstlmask, xside); #else LinkMove (ply, f, f + 2, cstlmask); #endif } if (castle (side, f, f - 2, 0)) { #ifndef KILLTO LinkMove (ply, f, f - 2, cstlmask, xside); #else LinkMove (ply, f, f - 2, cstlmask); #endif } } if (epsquare > 0) { register SHORT l; f = epmove1[epsquare]; if (color[f] == side && board[f] == pawn) { l = epsquare + ((epsquare > f) ? -8 : 8); board[l] = no_piece; color[l] = neutral; LinkMove (ply, f, epsquare, capture | epmask, xside); board[l] = pawn; color[l] = xside; } f = epmove2[epsquare]; if (color[f] == side && board[f] == pawn) { l = epsquare + ((epsquare > f) ? -8 : 8); board[l] = no_piece; color[l] = neutral; LinkMove (ply, f, epsquare, capture | epmask, xside); board[l] = pawn; color[l] = xside; } } #ifdef KILLT #ifdef USE_SIDEBIT killt[SwagHt | sidebit] -= 5000; killt[Swag0 | sidebit] -= 2000; killt[Swag1 | sidebit] -= 60; killt[Swag2 | sidebit] -= 50; killt[Swag3 | sidebit] -= 40; killt[Swag4 | sidebit] -= 30; #else killt[SwagHt] -= 5000; killt[Swag0] -= 2000; killt[Swag1] -= 60; killt[Swag2] -= 50; killt[Swag3] -= 40; killt[Swag4] -= 30; #endif #endif #ifdef HISTORKILLT #ifdef HISTORY i = (side == black)?0x4000:0; history[SwagHt | i] -= 5000; history[Swag0 | i] -= 2000; history[Swag1 | i] -= 60; history[Swag2 | i] -= 50; history[Swag3 | i] -= 40; history[Swag4 | i] -= 30; #endif #endif SwagHt = 0; /* SwagHt is only used once */ GenCnt += (TrPnt[ply+1] - TrPnt[ply]); } void CaptureList (INTSIZE int side, INTSIZE int ply) /* * Fill the array Tree[] with all available cature and promote moves for side * to play. Array TrPnt[ply] contains the index into Tree[] of the first move * at a ply. */ { register short u, sq, xside; register struct leaf *node; register unsigned char *ppos, *pdir; short i, piece, *PL, r7; xside = side ^ 1; TrP = &TrPnt[ply + 1]; *TrP = TrPnt[ply]; node = &Tree[*TrP]; r7 = rank7[side]; PL = PieceList[side]; #ifdef KILLT // 4PL70 USES sidebit here!! #ifdef USE_SIDEBIT sidebit = ((side == white) ? 0 : 0x80); killt[SwagHt | sidebit] += 5000; killt[Swag0 | sidebit] += 2000; killt[Swag1 | sidebit] += 60; killt[Swag2 | sidebit] += 50; killt[Swag3 | sidebit] += 40; killt[Swag4 | sidebit] += 30; #else killt[SwagHt] += 5000; killt[Swag0] += 2000; killt[Swag1] += 60; killt[Swag2] += 50; killt[Swag3] += 40; killt[Swag4] += 30; #endif #endif for (i = 0; i <= PieceCnt[side]; i++) { SHORT r = row(PieceList[xside][0]); SHORT c = column(PieceList[xside][0]); sq = PL[i]; piece = board[sq]; if (sweep[piece]) { ppos = nextpos[piece][sq]; pdir = nextdir[piece][sq]; u = ppos[sq]; do { if (color[u] == neutral) { if (piece == rook | piece == queen) { if(r == row(sq) || c == column(sq)) Link (sq, u, 0, -999);} else if(abs(r - row(sq)) == abs(c - column(sq)))Link (sq, u, 0, -999); u = ppos[u];} else { if (color[u] == xside) Link (sq, u, capture, value[board[u]] + svalue[u] - piece); u = pdir[u]; } } while (u != sq); } else { pdir = nextdir[ptype[side][piece]][sq]; if (piece == pawn && row (sq) == r7) { u = pdir[sq]; if (color[u] == xside){ Link (sq, u, capture | promote | queen, valueQ); #if !defined OLDXBOARD && !defined GNU3 && !defined CHESSTOOL Link (sq, u, capture | promote | knight, valueN); Link (sq, u, capture | promote | rook, valueR); Link (sq, u, capture | promote | bishop, valueB); #endif } u = pdir[u]; if (color[u] == xside) { Link (sq, u, capture | promote | queen, valueQ); #if !defined OLDXBOARD && !defined GNU3 && !defined CHESSTOOL Link (sq, u, capture | promote | knight, valueN); Link (sq, u, capture | promote | rook, valueR); Link (sq, u, capture | promote | bishop, valueB); #endif } ppos = nextpos[ptype[side][piece]][sq]; u = ppos[sq]; /* also generate non capture promote */ if (color[u] == neutral) { Link (sq, u, promote | queen, valueQ); #if !defined OLDXBOARD && !defined GNU3 && !defined CHESSTOOL Link (sq, u, promote | knight, valueN); Link (sq, u, promote | rook, valueR); Link (sq, u, promote | bishop, valueB); #endif } } else { u = pdir[sq]; do { if (color[u] == xside) Link (sq, u, capture, value[board[u]] + svalue[u] - piece); u = pdir[u]; } while (u != sq); } } } #ifdef KILLT #ifdef USE_SIDEBIT // 4PL70 uses SIDEBIT here!! sidebit = ((side == white) ? 0 : 0x80); killt[SwagHt | sidebit] -= 5000; killt[Swag0 | sidebit] -= 2000; killt[Swag1 | sidebit] -= 60; killt[Swag2 | sidebit] -= 50; killt[Swag3 | sidebit] -= 40; killt[Swag4 | sidebit] -= 30; #else killt[SwagHt] -= 5000; killt[Swag0] -= 2000; killt[Swag1] -= 60; killt[Swag2] -= 50; killt[Swag3] -= 40; killt[Swag4] -= 30; #endif #endif SwagHt = 0; /* SwagHt is only used once */ }