Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: transition to endgame

Author: Dann Corbit

Date: 18:02:39 04/02/04

Go up one level in this thread


On April 02, 2004 at 19:00:47, Dann Corbit wrote:

>On April 02, 2004 at 18:47:34, Eric Oldre wrote:
>
>>Hi everyone,
>>I've been working on my new chess engine for a few weeks now and am pretty happy
>>with the progress i've made so far. I'm even going to try entering it into
>>Olivier Deville's ChessWar tournament next week. I've set the lofty goal for
>>myself of not taking last place. I give myself a 50/50 shot of reaching it.
>>
>>I've been playing it against some engines here at home and noticed a trend in
>>it's play. It seems to do OK in the middle game, but about the time it get down
>>to having some pawns and 2 minors/rooks it's game starts to fall apart.
>>
>>At this point t is usually about even or sometimes up in material (not against
>>any "elite" engines of course, and i don't see any major weaknesses in it's
>>position, but the opponent either chips away at it's pawns, or gets a promotion.
>>or just mates it. The point is that i don't see any one specific thing that it
>>isn't catching.
>>
>>One thing is that i don't have any special endgame evaluation changes. I plan on
>>making it so that it starts to value the king in the center instead of behind
>>it's pawns. but i don't think that alone will make the difference.
>>
>>So my question is: what suggestions do you have for ways could i improve it's
>>play during the endgame, or would i call it the "middle-endgame" at that point?
>
>If the board is sparse, centralize your king.  He'll help a lot.  He attacks 8
>squares, just like a knight, after all.
>
>Give a bonus for the forward pawn squares.
>Give a bonus for passed pawns.
>Give a bigger bonus for unstoppable passed pawns.

Here is how Beowulf figures out the game stage:

/* Sorts out what stage of the game the board is in. */
int             GetGamestage(int tpts)
{
    if (tpts > 70)
        return Opening;
    if (tpts > 62)
        return EarlyMid;
    if (tpts > 54)
        return Middle;
    if (tpts > 46)
        return LateMid;
    if (tpts > 22)
        return Endgame;
    return LateEnd;
}

piece value is q=9, r=5, b=n=3, p=1
tpts is the total points on the board.

Here are TSCP's king square tables:

king[DARK] != i)
                assert(0);
    }
        return 1;
}
#endif

/* in_check() returns TRUE if side s is in check and FALSE
   otherwise. It just scans the board to find side s's king
   and calls attack() to see if it's being attacked. */

int            in_check(int s)
{
    verify_king_table();
    return attack(king[s], s ^ 1);
}

/* attack() returns TRUE if square sq is being attacked by side
   s and FALSE otherwise. */

BOOL            attack(int sq, int s)
{
    int             i,
                    j,
                    n;

    for (i = 0; i < 64; ++i)
        if (color[i] == s) {
            if (piece[i] == PAWN) {
                if (s == LIGHT) {
                    if (COL(i) != 0 && i - 9 == sq)
                        return TRUE;
                    if (COL(i) != 7 && i - 7 == sq)
                        return TRUE;
                } else {
                    if (COL(i) != 0 && i + 7 == sq)
                        return TRUE;
                    if (COL(i) != 7 && i + 9 == sq)
                        return TRUE;
                }
            } else
                for (j = 0; j < offsets[piece[i]]; ++j)
                    for (n = i;;) {
                        n = mailbox[mailbox64[n] + offset[piece[i]][j]];
                        if (n == -1)
                            break;
                        if (n == sq)
                            return TRUE;
                        if (color[n] != EMPTY)
                            break;
                        if (!slide[piece[i]])
                            break;
                    }
        }
    return FALSE;
}


/* gen() generates pseudo-legal moves for the current position.
   It scans the board to find friendly pieces and then determines
   what squares they attack. When it finds a piece/square
   combination, it calls gen_push to put the move on the "move
   stack." */

void            gen()
{
    int             i,
                    j,
                    n;

    /* so far, we have no moves for the current ply */
    first_move[ply + 1] = first_move[ply];

    for (i = 0; i < 64; ++i)
        if (color[i] == side) {
            if (piece[i] == PAWN) {
                if (side == LIGHT) {
                    if (COL(i) != 0 && color[i - 9] == DARK)
                        gen_push(i, i - 9, 17);
                    if (COL(i) != 7 && color[i - 7] == DARK)
                        gen_push(i, i - 7, 17);
                    if (color[i - 8] == EMPTY) {
                        gen_push(i, i - 8, 16);
                        if (i >= 48 && color[i - 16] == EMPTY)
                            gen_push(i, i - 16, 24);
                    }
                } else {
                    if (COL(i) != 0 && color[i + 7] == LIGHT)
                        gen_push(i, i + 7, 17);
                    if (COL(i) != 7 && color[i + 9] == LIGHT)
                        gen_push(i, i + 9, 17);
                    if (color[i + 8] == EMPTY) {
                        gen_push(i, i + 8, 16);
                        if (i <= 15 && color[i + 16] == EMPTY)
                            gen_push(i, i + 16, 24);
                    }
                }
            } else
                for (j = 0; j < offsets[piece[i]]; ++j)
                    for (n = i;;) {
                        n = mailbox[mailbox64[n] + offset[piece[i]][j]];
                        if (n == -1)
                            break;
                        if (color[n] != EMPTY) {
                            if (color[n] == xside)
                                gen_push(i, n, 1);
                            break;
                        }
                        gen_push(i, n, 0);
                        if (!slide[piece[i]])
                            break;
                    }
        }
    /* generate castle moves */
    if (side == LIGHT) {
        if (castle & 1)
            gen_push(E1, G1, 2);
        if (castle & 2)
            gen_push(E1, C1, 2);
    } else {
        if (castle & 4)
            gen_push(E8, G8, 2);
        if (castle & 8)
            gen_push(E8, C8, 2);
    }

    /* generate en passant moves */
    if (ep != -1) {
        if (side == LIGHT) {
            if (COL(ep) != 0 && color[ep + 7] == LIGHT && piece[ep + 7] == PAWN)
                gen_push(ep + 7, ep, 21);
            if (COL(ep) != 7 && color[ep + 9] == LIGHT && piece[ep + 9] == PAWN)
                gen_push(ep + 9, ep, 21);
        } else {
            if (COL(ep) != 0 && color[ep - 9] == DARK && piece[ep - 9] == PAWN)
                gen_push(ep - 9, ep, 21);
            if (COL(ep) != 7 && color[ep - 7] == DARK && piece[ep - 7] == PAWN)
                gen_push(ep - 7, ep, 21);
        }
    }
}


/* gen_caps() is basically a copy of gen() that's modified to
   only generate capture and promote moves. It's used by the
   quiescence search. */

void            gen_caps()
{
    int             i,
                    j,
                    n;

    first_move[ply + 1] = first_move[ply];
    for (i = 0; i < 64; ++i)
        if (color[i] == side) {
            if (piece[i] == PAWN) {
                if (side == LIGHT) {
                    if (COL(i) != 0 && color[i - 9] == DARK)
                        gen_push(i, i - 9, 17);
                    if (COL(i) != 7 && color[i - 7] == DARK)
                        gen_push(i, i - 7, 17);
                    if (i <= 15 && color[i - 8] == EMPTY)
                        gen_push(i, i - 8, 16);
                }
                if (side == DARK) {
                    if (COL(i) != 0 && color[i + 7] == LIGHT)
                        gen_push(i, i + 7, 17);
                    if (COL(i) != 7 && color[i + 9] == LIGHT)
                        gen_push(i, i + 9, 17);
                    if (i >= 48 && color[i + 8] == EMPTY)
                        gen_push(i, i + 8, 16);
                }
            } else
                for (j = 0; j < offsets[piece[i]]; ++j)
                    for (n = i;;) {
                        n = mailbox[mailbox64[n] + offset[piece[i]][j]];
                        if (n == -1)
                            break;
                        if (color[n] != EMPTY) {
                            if (color[n] == xside)
                                gen_push(i, n, 1);
                            break;
                        }
                        if (!slide[piece[i]])
                            break;
                    }
        }
    if (ep != -1) {
        if (side == LIGHT) {
            if (COL(ep) != 0 && color[ep + 7] == LIGHT && piece[ep + 7] == PAWN)
                gen_push(ep + 7, ep, 21);
            if (COL(ep) != 7 && color[ep + 9] == LIGHT && piece[ep + 9] == PAWN)
                gen_push(ep + 9, ep, 21);
        } else {
            if (COL(ep) != 0 && color[ep - 9] == DARK && piece[ep - 9] == PAWN)
                gen_push(ep - 9, ep, 21);
            if (COL(ep) != 7 && color[ep - 7] == DARK && piece[ep - 7] == PAWN)
                gen_push(ep - 7, ep, 21);
        }
    }
}


/* gen_push() puts a move on the move stack, unless it's a
   pawn promotion that needs to be handled by gen_promote().
   It also assigns a score to the move for alpha-beta move
   ordering. If the move is a capture, it uses MVV/LVA
   (Most Valuable Victim/Least Valuable Attacker). Otherwise,
   it uses the move's history heuristic value. Note that
   1,000,000 is added to a capture move's score, so it
   always gets ordered above a "normal" move. */

void            gen_push(int from, int to, int bits)
{
    gen_t          *g;

    if (bits & 16) {
        if (side == LIGHT) {
            if (to <= H8) {
                gen_promote(from, to, bits);
                return;
            }
        } else {
            if (to >= A1) {
                gen_promote(from, to, bits);
                return;
            }
        }
    }
    g = &gen_dat[first_move[ply + 1]++];
    g->m.b.from = (char) from;
    g->m.b.to = (char) to;
    g->m.b.promote = 0;
    g->m.b.bits = (char) bits;
    if (color[to] != EMPTY)
        g->score = 1000000 + (piece[to] * 10) - piece[from];
    else
        g->score = history[from][to];
}


/* gen_promote() is just like gen_push(), only it puts 4 moves
   on the move stack, one for each possible promotion piece */

void            gen_promote(int from, int to, int bits)
{
    int             i;
    gen_t          *g;

    for (i = KNIGHT; i <= QUEEN; ++i) {
        g = &gen_dat[first_move[ply + 1]++];
        g->m.b.from = (char) from;
        g->m.b.to = (char) to;
        g->m.b.promote = (char) i;
        g->m.b.bits = (char) (bits | 32);
        g->score = 1000000 + (i * 10);
    }
}


/* makemove() makes a move. If the move is illegal, it
   undoes whatever it did and returns FALSE. Otherwise, it
   returns TRUE. */

BOOL            makemove(move_bytes m)
{

    /* test to see if a castle move is legal and move the rook (the king is
     * moved with the usual move code later) */
    verify_king_table();

    if (m.bits & 2) {
        int             from,
                        to;

        if (in_check(side))
            return FALSE;
        switch (m.to) {
        case 62:
            if (color[F1] != EMPTY || color[G1] != EMPTY ||
                attack(F1, xside) || attack(G1, xside))
                return FALSE;
            from = H1;
            to = F1;
            break;
        case 58:
            if (color[B1] != EMPTY || color[C1] != EMPTY || color[D1] != EMPTY
||
                attack(C1, xside) || attack(D1, xside))
                return FALSE;
            from = A1;
            to = D1;
            break;
        case 6:
            if (color[F8] != EMPTY || color[G8] != EMPTY ||
                attack(F8, xside) || attack(G8, xside))
                return FALSE;
            from = H8;
            to = F8;
            break;
        case 2:
            if (color[B8] != EMPTY || color[C8] != EMPTY || color[D8] != EMPTY
||
                attack(C8, xside) || attack(D8, xside))
                return FALSE;
            from = A8;
            to = D8;
            break;
        default:                /* shouldn't get here */
            from = -1;
            to = -1;
            break;
        }
        color[to] = color[from];
        piece[to] = piece[from];
		if (piece[to] == KING)
			king[color[to]] = to;
        color[from] = EMPTY;
        piece[from] = EMPTY;
    }
    verify_king_table();
    /* back up information so we can take the move back later. */
    hist_dat[hply].m.b = m;
    hist_dat[hply].capture = piece[(int) m.to];
    hist_dat[hply].castle = castle;
    hist_dat[hply].ep = ep;
    hist_dat[hply].fifty = fifty;
    hist_dat[hply].hash = hash;
    ++ply;
    ++hply;

    /* update the castle, en passant, and fifty-move-draw variables */
    castle &= castle_mask[(int) m.from] & castle_mask[(int) m.to];
    if (m.bits & 8) {
        if (side == LIGHT)
            ep = m.to + 8;
        else
            ep = m.to - 8;
    } else
        ep = -1;
    if (m.bits & 17)
        fifty = 0;
    else
        ++fifty;

    /* move the piece */
    color[(int) m.to] = side;
    if (m.bits & 32)
        piece[(int) m.to] = m.promote;
    else
	{
        piece[(int) m.to] = piece[(int) m.from];
	if (piece[(int) m.to] == KING)
            king[color[(int) m.to]] = m.to;
	}
    color[(int) m.from] = EMPTY;
    piece[(int) m.from] = EMPTY;
    verify_king_table();

    /* erase the pawn if this is an en passant move */
    if (m.bits & 4) {
        if (side == LIGHT) {
            color[m.to + 8] = EMPTY;
            piece[m.to + 8] = EMPTY;
        } else {
            color[m.to - 8] = EMPTY;
            piece[m.to - 8] = EMPTY;
        }
    }
    /* switch sides and test for legality (if we can capture the other guy's
     * king, it's an illegal position and we need to take the move back) */
    side ^= 1;
    xside ^= 1;
    if (in_check(xside)) {
        takeback();
        return FALSE;
    }
    set_hash();
    verify_king_table();
    return TRUE;
}


/* takeback() is very similar to makemove(), only backwards :)  */

void            takeback()
{
    move_bytes      m;
    verify_king_table();

    side ^= 1;
    xside ^= 1;
    --ply;
    --hply;
    m = hist_dat[hply].m.b;
    castle = hist_dat[hply].castle;
    ep = hist_dat[hply].ep;
    fifty = hist_dat[hply].fifty;
    hash = hist_dat[hply].hash;
    color[(int) m.from] = side;
    if (m.bits & 32)
        piece[(int) m.from] = PAWN;
    else
	{
        piece[(int) m.from] = piece[(int) m.to];
        if (piece[(int)m.from] == KING)
            king[color[(int)m.from]] = m.from;
	}
    if (hist_dat[hply].capture == EMPTY) {
        color[(int) m.to] = EMPTY;
        piece[(int) m.to] = EMPTY;
    } else {
        color[(int) m.to] = xside;
        piece[(int) m.to] = hist_dat[hply].capture;
    }
    if (m.bits & 2) {
        int             from,
                        to;

        switch (m.to) {
        case 62:
            from = F1;
            to = H1;
            break;
        case 58:
            from = D1;
            to = A1;
            break;
        case 6:
            from = F8;
            to = H8;
            break;
        case 2:
            from = D8;
            to = A8;
            break;
        default:                /* shouldn't get here */
            from = -1;
            to = -1;
            break;
        }
        color[to] = side;
        piece[to] = ROOK;
        color[from] = EMPTY;
        piece[from] = EMPTY;
    }
    if (m.bits & 4) {
        if (side == LIGHT) {
            color[m.to + 8] = xside;
            piece[m.to + 8] = PAWN;
        } else {
            color[m.to - 8] = xside;
            piece[m.to - 8] = PAWN;
        }
    }
    verify_king_table();

}
/*
 *	BOOK.C
 *	Tom Kerrigan's Simple Chess Program (TSCP)
 *
 *	Copyright 1997 Tom Kerrigan
 */


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "defs.h"
#include "data.h"
#include "protos.h"


/* the opening book file, declared here so we don't have to include stdio.h in
   a header file */
FILE *book_file;


/* open_book() opens the opening book file and initializes the random number
   generator so we play random book moves. */

void open_book()
{
	srand(time(NULL));
	book_file = fopen("book.txt", "r");
	if (!book_file)
		printf("Opening book missing.\n");
}


/* close_book() closes the book file. This is called when the program exits. */

void close_book()
{
	if (book_file)
		fclose(book_file);
	book_file = NULL;
}


/* book_move() returns a book move (in integer format) or -1 if there is no
   book move. */

int book_move()
{
	char line[256];
	char book_line[256];
	int i, j, m;
	int move[50];  /* the possible book moves */
	int count[50];  /* the number of occurrences of each move */
	int moves = 0;
	int total_count = 0;

	if (!book_file || hply > 25)
		return -1;

	/* line is a string with the current line, e.g., "e2e4 e7e5 g1f3 " */
	line[0] = '\0';
	j = 0;
	for (i = 0; i < hply; ++i)
		j += sprintf(line + j, "%s ", move_str(hist_dat[i].m.b));

	/* compare line to each line in the opening book */
	fseek(book_file, 0, SEEK_SET);
	while (fgets(book_line, 256, book_file)) {
		if (book_match(line, book_line)) {

			/* parse the book move that continues the line */
			m = parse_move(&book_line[strlen(line)]);
			if (m == -1)
				continue;
			m = gen_dat[m].m.u;

			/* add the book move to the move list, or update the move's
			   count */
			for (j = 0; j < moves; ++j)
				if (move[j] == m) {
					++count[j];
					break;
				}
			if (j == moves) {
				move[moves] = m;
				count[moves] = 1;
				++moves;
			}
			++total_count;
		}
	}

	/* no book moves? */
	if (moves == 0)
		return -1;

	/* Think of total_count as the set of matching book lines.
	   Randomly pick one of those lines (j) and figure out which
	   move j "corresponds" to. */
	j = rand() % total_count;
	for (i = 0; i < moves; ++i) {
		j -= count[i];
		if (j < 0)
			return move[i];
	}
	return -1;  /* shouldn't get here */
}


/* book_match() returns TRUE if the first part of s2 matches s1. */

BOOL book_match(char *s1, char *s2)
{
	int i;

	for (i = 0; i < (signed int)strlen(s1); ++i)
		if (s2[i] == '\0' || s2[i] != s1[i])
			return FALSE;
	return TRUE;
}
/*
 *	DATA.C
 *	Tom Kerrigan's Simple Chess Program (TSCP)
 *
 *	Copyright 1997 Tom Kerrigan
 */


#include "defs.h"


/* the board representation */
int             color[64];      /* LIGHT, DARK, or EMPTY */
int             piece[64];      /* PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
                                 * or EMPTY */
int             side;           /* the side to move */
int             xside;          /* the side not to move */
int             castle;         /* a bitfield with the castle permissions. if
                                 * 1 is set, white can still castle kingside.
                                 * 2 is white queenside. 4 is black kingside.
                                 * 8 is black queenside. */
int             ep;             /* the en passant square. if white moves
                                 * e2e4, the en passant square is set to e3,
                                 * because that's where a pawn would move in
                                 * an en passant capture */
int             fifty;          /* the number of moves since a capture or
                                 * pawn move, used to handle the
                                 * fifty-move-draw rule */
int             hash;           /* a (more or less) unique number that
                                 * corresponds to the position */
int             ply;            /* the number of half-moves (ply) since the
                                 * root of the search tree */
int             hply;           /* h for history; the number of ply since the
                                 * beginning of the game */

/* gen_dat is some memory for move lists that are created by the move
   generators. The move list for ply n starts at first_move[n] and ends
   at first_move[n + 1]. */
gen_t           gen_dat[GEN_STACK];
int             first_move[MAX_PLY];

/* the history heuristic array (used for move ordering) */
int             history[64][64];

/* we need an array of hist_t's so we can take back the
   moves we make */
hist_t          hist_dat[HIST_STACK];

/* the engine will search for max_time milliseconds or until it finishes
   searching max_depth ply. */
int             max_time=5000;
int             max_depth=MAX_PLY-1;

/* the time when the engine starts searching, and when it should stop */
int             start_time;
int             stop_time;

int             nodes;          /* the number of nodes we've searched */

/* a "triangular" PV array; for a good explanation of why a triangular
   array is needed, see "How Computers Play Chess" by Levy and Newborn. */
move            pv[MAX_PLY][MAX_PLY];
int             pv_length[MAX_PLY];
BOOL            follow_pv;

/* random numbers used to compute hash; see set_hash() in board.c */
int             hash_piece[2][6][64];   /* indexed by piece
                                         * [color][type][square] */
int             hash_side;
int             hash_ep[64];

/* Now we have the mailbox array, so called because it looks like a
   mailbox, at least according to Bob Hyatt. This is useful when we
   need to figure out what pieces can go where. Let's say we have a
   rook on square a4 (32) and we want to know if it can move one
   square to the left. We subtract 1, and we get 31 (h5). The rook
   obviously can't move to h5, but we don't know that without doing
   a lot of annoying work. Sooooo, what we do is figure out a4's
   mailbox number, which is 61. Then we subtract 1 from 61 (60) and
   see what mailbox[60] is. In this case, it's -1, so it's out of
   bounds and we can forget it. You can see how mailbox[] is used
   in attack() in board.c. */

int             mailbox[120] = {
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
    -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
    -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
    -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
    -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
    -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
    -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
    -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

int             mailbox64[64] = {
    21, 22, 23, 24, 25, 26, 27, 28,
    31, 32, 33, 34, 35, 36, 37, 38,
    41, 42, 43, 44, 45, 46, 47, 48,
    51, 52, 53, 54, 55, 56, 57, 58,
    61, 62, 63, 64, 65, 66, 67, 68,
    71, 72, 73, 74, 75, 76, 77, 78,
    81, 82, 83, 84, 85, 86, 87, 88,
    91, 92, 93, 94, 95, 96, 97, 98
};


/* slide, offsets, and offset are basically the vectors that
   pieces can move in. If slide for the piece is FALSE, it can
   only move one square in any one direction. offsets is the
   number of directions it can move in, and offset is an array
   of the actual directions. */

BOOL            slide[6] = {
    FALSE, FALSE, TRUE, TRUE, TRUE, FALSE
};

int             offsets[6] = {
    0, 8, 4, 4, 8, 8
};

int             offset[6][8] = {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {-21, -19, -12, -8, 8, 12, 19, 21},
    {-11, -9, 9, 11, 0, 0, 0, 0},
    {-10, -1, 1, 10, 0, 0, 0, 0},
    {-11, -10, -9, -1, 1, 9, 10, 11},
    {-11, -10, -9, -1, 1, 9, 10, 11}
};


/* This is the castle_mask array. We can use it to determine
   the castling permissions after a move. What we do is
   logical-AND the castle bits with the castle_mask bits for
   both of the move's squares. Let's say castle is 1, meaning
   that white can still castle kingside. Now we play a move
   where the rook on h1 gets captured. We AND castle with
   castle_mask[63], so we have 1&14, and castle becomes 0 and
   white can't castle kingside anymore. */

int             castle_mask[64] = {
    7, 15, 15, 15, 3, 15, 15, 11,
    15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15,
    13, 15, 15, 15, 12, 15, 15, 14
};


/* the piece letters, for print_board() */
char            piece_char[6] = {
    'P', 'N', 'B', 'R', 'Q', 'K'
};


/* the initial board state */

int             init_color[64] = {
    1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};

int             init_piece[64] = {
    3, 1, 2, 4, 5, 2, 1, 3,
    0, 0, 0, 0, 0, 0, 0, 0,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    0, 0, 0, 0, 0, 0, 0, 0,
    3, 1, 2, 4, 5, 2, 1, 3
};
/*
 *	EVAL.C
 *	Tom Kerrigan's Simple Chess Program (TSCP)
 *
 *	Copyright 1997 Tom Kerrigan
 */


#include <string.h>
#include "defs.h"
#include "data.h"
#include "protos.h"


#define DOUBLED_PAWN_PENALTY		10
#define ISOLATED_PAWN_PENALTY		20
#define BACKWARDS_PAWN_PENALTY		8
#define PASSED_PAWN_BONUS			20
#define ROOK_SEMI_OPEN_FILE_BONUS	10
#define ROOK_OPEN_FILE_BONUS		15
#define ROOK_ON_SEVENTH_BONUS		20


/* the values of the pieces */
int             piece_value[6] = {
    100, 300, 300, 500, 900, 0
};

/* The "pcsq" arrays are piece/square tables. They're values
   added to the material value of the piece based on the
   location of the piece. */

int             pawn_pcsq[64] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    5, 10, 15, 20, 20, 15, 10, 5,
    4, 8, 12, 16, 16, 12, 8, 4,
    3, 6, 9, 12, 12, 9, 6, 3,
    2, 4, 6, 8, 8, 6, 4, 2,
    1, 2, 3, -10, -10, 3, 2, 1,
    0, 0, 0, -40, -40, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};

int             knight_pcsq[64] = {
    -10, -10, -10, -10, -10, -10, -10, -10,
    -10, 0, 0, 0, 0, 0, 0, -10,
    -10, 0, 5, 5, 5, 5, 0, -10,
    -10, 0, 5, 10, 10, 5, 0, -10,
    -10, 0, 5, 10, 10, 5, 0, -10,
    -10, 0, 5, 5, 5, 5, 0, -10,
    -10, 0, 0, 0, 0, 0, 0, -10,
    -10, -30, -10, -10, -10, -10, -30, -10
};

int             bishop_pcsq[64] = {
    -10, -10, -10, -10, -10, -10, -10, -10,
    -10, 0, 0, 0, 0, 0, 0, -10,
    -10, 0, 5, 5, 5, 5, 0, -10,
    -10, 0, 5, 10, 10, 5, 0, -10,
    -10, 0, 5, 10, 10, 5, 0, -10,
    -10, 0, 5, 5, 5, 5, 0, -10,
    -10, 0, 0, 0, 0, 0, 0, -10,
    -10, -10, -20, -10, -10, -20, -10, -10
};

int             king_pcsq[64] = {
    -40, -40, -40, -40, -40, -40, -40, -40,
    -40, -40, -40, -40, -40, -40, -40, -40,
    -40, -40, -40, -40, -40, -40, -40, -40,
    -40, -40, -40, -40, -40, -40, -40, -40,
    -40, -40, -40, -40, -40, -40, -40, -40,
    -40, -40, -40, -40, -40, -40, -40, -40,
    -20, -20, -20, -20, -20, -20, -20, -20,
    0, 20, 40, -20, 0, -20, 40, 20
};

int             king_endgame_pcsq[64] = {
    0, 10, 20, 30, 30, 20, 10, 0,
    10, 20, 30, 40, 40, 30, 20, 10,
    20, 30, 40, 50, 50, 40, 30, 20,
    30, 40, 50, 60, 60, 50, 40, 30,
    30, 40, 50, 60, 60, 50, 40, 30,
    20, 30, 40, 50, 50, 40, 30, 20,
    10, 20, 30, 40, 40, 30, 20, 10,
    0, 10, 20, 30, 30, 20, 10, 0
};



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.