Chess2u
Would you like to react to this message? Create an account in a few clicks or log in to continue.

Chess2uLog in

SecondChess

descriptionSecondChess EmptySecondChess

more_horiz
SecondChess (WB)

Secondchess is a chess engine by Emilio Díaz, based on firstchess by Pham Hong Nguyen

Its main goal is to add the neccesary code to firstchess in order to make it play real chess, especially adding the rules for castle and en passant capture

to compile just "gcc secondchess.c -o secondchess -Ofast"

https://github.com/pocopito/secondchess

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi all

This is my first post in this forum. As the developer of secondchess I apreciate Steve's entry, and just wanted to add a couple of details about this humble engine.
The spirit of secondchess is quite the same than the one of firstchess: develop an easy to read and understand chess program for those who want to learn how a chess engine works. The very first steps were adding castle and eps, and so far it seems it's been done. A little modification of the eval function was also done, in order to make secondchess to play a chess game with  bit more of "understanding".
The code is GPL so anyone who's interested can develop its own engine starting from secondchess.

Needless to say, any comments and sugestions, specially in order to make the code easiert o understand are welcome.

Regards
 
  E Diaz

PS: For those who could be interested, there's a somehow stable version of the engine on this link:
https://github.com/emdio/secondchess/tags

Last edited by pocopito on Tue Dec 17, 2013 12:32 pm; edited 1 time in total (Reason for editing : Update url)

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi Emilio, when will the exe be available?

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Thomas Miller wrote:
Hi Emilio, when will the exe be available?


Hi Thomas

Actually the main point of secondchess is its source code: it just means to be a (hopefuly) useful tool for people interested on learning how a chess engine works. Its eval function is really simple (just material balance and piece square tables for bishop, kinght and king), and despite it's not completely a "woodpusher", I guess it has almost no interest to play a game against it (of course it's something I do frequently, but it has more to do with searching for bugs).
Besides, only in the last days I've worked on implementing the xboard protocol, so currently the only way to play against secondchess is from the (ugly) terminal.

On the other side, when I was thinking about the content of this response, I thought it could be a good idea to have a couple of executables (linux and windows, and probably also xboard and no xboard support) available from github, just in case someone wants to try the engine, and hopefully, report some bugs. So thanks for the suggestion: I guess in the next days I'll upload some execs and will update the info here.

Regards

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Just added executable files for linux 32 and 64 bit.
https://github.com/pocopito/secondchess/blob/master/secondchess32Linux
https://github.com/pocopito/secondchess/blob/master/secondchess64Linux

In the next days I'll try to get some windows compilations.


Regards

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
SecondChess TM (WB)
http://www3.telus.net/tmokonen/SecondChess.rar

SecondChess plays illegal moves, any idea?

descriptionSecondChess EmptyRe: SecondChess

more_horiz
jnhes wrote:
SecondChess TM (WB)
http://www3.telus.net/tmokonen/SecondChess.rar

SecondChess plays illegal moves, any idea?


Thanks for the windows executable. I'm testing it on an XP machine and seems to work fine.

Related to the illegal moves, could you provide any hint in order to reproduce it? (I'm sorry there's no fen edition utility for cases like this)

Regards

E Diaz

PS: Is it a problem if I temporally add this rar (or the link to it) in my github?

descriptionSecondChess EmptyRe: SecondChess

more_horiz
@pocopito wrote:
jnhes wrote:
SecondChess TM (WB)
http://www3.telus.net/tmokonen/SecondChess.rar

SecondChess plays illegal moves, any idea?


Thanks for the windows executable. I'm testing it on an XP machine and seems to work fine.

Related to the illegal moves, could you provide any hint in order to reproduce it? (I'm sorry there's no fen edition utility for cases like this)

Regards

E Diaz

PS: Is it a problem if I temporally add this rar (or the link to it) in my github?

From here:
http://computer-chess.org/forum/index.php?mode=thread&id=1935

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Thanks for the post and the advice. Secondches has a huge bug in the en pasant capture that I'm working right now on.

Regards

E Diaz

descriptionSecondChess EmptyCompiling SecondChess in Windows7 VisStudio cmd prompt

more_horiz
Thanks for SecondChess source.
I cannot get it to compile on Win7 with VisStudio2010 cmd line compile:
....\SecondChess>cl secondchess.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

secondchess.c
secondchess.c(806) : error C2143: syntax error : missing ';' before 'type'
secondchess.c(809) : error C2143: syntax error : missing ';' before 'type'
secondchess.c(812) : error C2065: 'i' : undeclared identifier
secondchess.c(812) : error C2065: 'i' : undeclared identifier
secondchess.c(812) : error C2065: 'i' : undeclared identifier
secondchess.c(814) : error C2065: 'i' : undeclared identifier
secondchess.c(818) : error C2065: 'score' : undeclared identifier
secondchess.c(818) : error C2065: 'i' : undeclared identifier
secondchess.c(822) : error C2065: 'i' : undeclared identifier
secondchess.c(825) : error C2065: 'score' : undeclared identifier
secondchess.c(825) : error C2065: 'i' : undeclared identifier
secondchess.c(828) : error C2065: 'score' : undeclared identifier
secondchess.c(828) : error C2065: 'i' : undeclared identifier
secondchess.c(831) : error C2065: 'score' : undeclared identifier
secondchess.c(831) : error C2065: 'i' : undeclared identifier
secondchess.c(834) : error C2065: 'score' : undeclared identifier
secondchess.c(834) : error C2065: 'i' : undeclared identifier
secondchess.c(837) : error C2065: 'score' : undeclared identifier
secondchess.c(837) : error C2065: 'i' : undeclared identifier
secondchess.c(841) : error C2065: 'i' : undeclared identifier
secondchess.c(843) : error C2065: 'score' : undeclared identifier
secondchess.c(843) : error C2065: 'i' : undeclared identifier
secondchess.c(845) : error C2065: 'i' : undeclared identifier
secondchess.c(848) : error C2065: 'score' : undeclared identifier
secondchess.c(848) : error C2065: 'i' : undeclared identifier
secondchess.c(851) : error C2065: 'score' : undeclared identifier
secondchess.c(851) : error C2065: 'i' : undeclared identifier
secondchess.c(854) : error C2065: 'score' : undeclared identifier
secondchess.c(854) : error C2065: 'i' : undeclared identifier
secondchess.c(857) : error C2065: 'score' : undeclared identifier
secondchess.c(857) : error C2065: 'i' : undeclared identifier
secondchess.c(860) : error C2065: 'score' : undeclared identifier
secondchess.c(860) : error C2065: 'i' : undeclared identifier
secondchess.c(867) : error C2065: 'score' : undeclared identifier
secondchess.c(868) : error C2065: 'score' : undeclared identifier
secondchess.c(1659) : error C2275: 'clock_t' : illegal use of this type as an ex
pression
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\time.h(82
) : see declaration of 'clock_t'
secondchess.c(1659) : error C2146: syntax error : missing ';' before identifier
'start'
secondchess.c(1659) : error C2065: 'start' : undeclared identifier
secondchess.c(1660) : error C2275: 'clock_t' : illegal use of this type as an ex
pression
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\time.h(82
) : see declaration of 'clock_t'
secondchess.c(1660) : error C2146: syntax error : missing ';' before identifier
'stop'
secondchess.c(1660) : error C2065: 'stop' : undeclared identifier
secondchess.c(1661) : error C2143: syntax error : missing ';' before 'type'
secondchess.c(1664) : error C2065: 'start' : undeclared identifier
secondchess.c(1665) : error C2065: 'start' : undeclared identifier
secondchess.c(1671) : error C2065: 'stop' : undeclared identifier
secondchess.c(1672) : error C2065: 't' : undeclared identifier
secondchess.c(1672) : error C2065: 'stop' : undeclared identifier
secondchess.c(1672) : error C2065: 'start' : undeclared identifier
secondchess.c(1673) : error C2065: 't' : undeclared identifier
secondchess.c(1675) : error C2143: syntax error : missing ';' before 'type'
secondchess.c(1678) : error C2065: 'decimal_score' : undeclared identifier
secondchess.c(1678) : error C2065: 'decimal_score' : undeclared identifier
secondchess.c(1685) : error C2065: 'decimal_score' : undeclared identifier
secondchess.c(1685) : error C2065: 't' : undeclared identifier
secondchess.c(1828) : error C2275: 'MOVE' : illegal use of this type as an expre
ssion
secondchess.c(138) : see declaration of 'MOVE'
secondchess.c(1828) : error C2146: syntax error : missing ';' before identifier
'moveBuf'
secondchess.c(1828) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1828) : error C2109: subscript requires array or pointer type
secondchess.c(1829) : error C2143: syntax error : missing ';' before 'type'
secondchess.c(1914) : error C2065: 'movecnt' : undeclared identifier
secondchess.c(1914) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1914) : warning C4047: 'function' : 'MOVE *' differs in levels of
indirection from 'int'
secondchess.c(1914) : warning C4024: 'Gen' : different types for formal and actu
al parameter 2
secondchess.c(1917) : error C2065: 'movecnt' : undeclared identifier
secondchess.c(1918) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1918) : error C2109: subscript requires array or pointer type
secondchess.c(1918) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1918) : error C2109: subscript requires array or pointer type
secondchess.c(1926) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1926) : error C2109: subscript requires array or pointer type
secondchess.c(1930) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1930) : error C2109: subscript requires array or pointer type
secondchess.c(1934) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1934) : error C2109: subscript requires array or pointer type
secondchess.c(1938) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1938) : error C2109: subscript requires array or pointer type
secondchess.c(1944) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1944) : error C2109: subscript requires array or pointer type
secondchess.c(1947) : error C2065: 'moveBuf' : undeclared identifier
secondchess.c(1947) : error C2109: subscript requires array or pointer type
secondchess.c(1947) : error C2198: 'MakeMove' : too few arguments for call

I could not get my copy of FirstChess to compile either....

Anyway I have dl'd the Windows binary/exe from this page for SecondChess.
However I would be grateful if some expert C programmer could sort out the code to compile with MS VisStudio2010 compiler. I'm sure it isn't too hard but my programming/coding skills are very limited right now. I am trying to learn C & chess programming & hope to improve my coding skill rapidly!

Many thanks

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi richardpd

Could you paste the very source code that gave this errors messages? I'm not a windows programmer myself, but due to the number and the type of errors it seems to be something related to code standards.

Regards

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Sure...
Spoiler :

Code:

*
 secondchess - gpl, by Emilio Díaz, based on firstchess by Pham Hong Nguyen
 Version: beta ta
 */
/*

 This program 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 3 of the License, or
 (at your option) any later version.

 This program 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 this program. If not, see <http://www.gnu.org/licenses/>

 * BASIC PARTS: *
 * Some definitions *
 * Board representation and main varians *
 * Move generator *
 * Evaluation for current position *
 * Make and Take back a move, IsInCheck *
 * Search function - a typical alphabeta *
 * Utility *
 * Main program *
 */
#include <stdio.h>
#include <string.h>
#include <time.h>

//#define NDEBUG
#include <assert.h>

/*
 ****************************************************************************
 * Some definitions *
 ****************************************************************************
 */
#define PAWN 0
#define KNIGHT 1
#define BISHOP 2
#define ROOK 3
#define QUEEN 4
#define KING 5
#define EPS_SQUARE 6
#define EMPTY 7
#define WHITE 0
#define BLACK 1
#define false 0

#define VALUE_PAWN 100
#define VALUE_KNIGHT 310
#define VALUE_BISHOP 320
#define VALUE_ROOK 500
#define VALUE_QUEEN 900
#define VALUE_KING 10000

#define MATE 10000 /* equal value of King, losing King==mate */

#define COL(pos) ((pos)&7)
#define ROW(pos) (((unsigned)pos)>>3)

/* Some  useful squares */
#define A1            56
#define B1            57
#define C1            58
#define D1            59
#define E1            60
#define F1            61
#define G1            62
#define H1            63
#define A8            0
#define B8            1
#define C8            2
#define D8            3
#define E8            4
#define F8            5
#define G8            6
#define H8            7

/*
 ****************************************************************************
 * Board representation and main variants *
 ****************************************************************************
 */
/* Board representation */
/* Piece in each square */
int piece[64] = {
      ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK,
      PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      PAWN, PAWN, PAWN, PAWN, PAWN,PAWN, PAWN, PAWN,
      ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT,ROOK };

/* Color of each square */
int color[64] = {
      BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
      BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
      WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE,
      WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, WHITE };

int side; /* Side to move, value = BLACK or WHITE */

/* For move generation */
#define MOVE_TYPE_NONE 0
#define MOVE_TYPE_NORMAL 1
#define MOVE_TYPE_CASTLE 2
#define MOVE_TYPE_ENPASANT 3
#define MOVE_TYPE_PAWN_TWO 4
#define MOVE_TYPE_PROMOTION_TO_QUEEN 5
#define MOVE_TYPE_PROMOTION_TO_ROOK 6
#define MOVE_TYPE_PROMOTION_TO_BISHOP 7
#define MOVE_TYPE_PROMOTION_TO_KNIGHT 8

/* A move is defined by its origin and final squares, and by the kind of
 * move it's: normal,  enpasant... */
typedef struct tag_MOVE
{
   int from;
   int dest;
   int castle;
   int type;
} MOVE;

/* For storing all moves of game */
typedef struct tag_HIST
{
   MOVE m;
   int cap;
} HIST;

HIST hist[6000]; /* Game length < 6000 */

/* For catle rights we use a bitfield, like in TSCP
 * 15 = 1111  = 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
 *
 * 0001 White can short castle
 * 0010 White can long castle
 * 0100 Black can short castle
 * 1000 Black can long castle
 *
 */
int castle = 15;

/* This mask is applied like this
 *
 * castle &= castle_mask[from] & castle_mask[dest]
 *
 * When from and dest are whatever pieces, then nothing happens, otherwise
 * the values are chosen in such a way that if vg the white king moves
 * to F1 then
 *
 * castle = castle & (12 & 15)
 * 1111 & (1100 & 1111) == 1111 & 1100 == 1100
 *
 * and white's lost its castle rights
 *
 *  */
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 };

int hdp; /* Current move order */
int allmoves = 0;

/* For searching */
int nodes; /* Count all visited nodes when searching */
int ply; /* ply of search */
int count_evaluations;
int count_checks;
int count_MakeMove;

/* The values of the pieces in centipawns */
int value_piece[6] =
{ VALUE_PAWN, VALUE_KNIGHT, VALUE_BISHOP, VALUE_ROOK, VALUE_QUEEN, VALUE_KING };

/* * * * * * * * * * * * *
 * Piece Square Tables
 * * * * * * * * * * * * */
int pst_pawn[64] ={
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0, 12, 12,  0,  0,  0,
      0,  0,  0, 10, 10,  0,  0,  0,
      0,  0,  0,  5,  5,  0,  0,  0,
      0,  0,  0, -5, -5,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0  };

int pst_knight[64] = {
      -40,-25,-25,-25,-25,-25,-25,-40,
      -25,  0,  0,  0,  0,  0,  0,-25,
      -25,  0,  0,  0,  0,  0,  0,-25,
      -25,  0,  0, 15, 15,  0,  0,-25,
      -25,  0,  0, 15, 15,  0,  0,-25,
      -25,  0,  0,  0,  0,  0,  0,-25,
      -25,  0,  0,  0,  0,  0,  0,-25,
      -40,-35,-25,-25,-25,-25,-35,-40 };

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

int pst_rook[64] = {
      0,  0,  0,  0,  0,  0,  0,  0,
     10, 10, 10, 10, 10, 10, 10, 10,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  5,  5,  0,  0,  0 };

int pst_king[64] = {
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
      -25,-25,-25,-25,-25,-25,-25,-25,
       10, 15,-15,-15,-15,-15, 15, 10};

/* The flip array is used to calculate the piece/square
  values for DARK pieces.
  The piece/square value of a white pawn is pawn_pcsq[sq]
  and the value of a black pawn is pawn_pcsq[flip[sq]] */
int flip[64] = {
    56,  57,  58,  59,  60,  61,  62,  63,
    48,  49,  50,  51,  52,  53,  54,  55,
    40,  41,  42,  43,  44,  45,  46,  47,
    32,  33,  34,  35,  36,  37,  38,  39,
    24,  25,  26,  27,  28,  29,  30,  31,
    16,  17,  18,  19,  20,  21,  22,  23,
     8,  9,  10,  11,  12,  13,  14,  15,
     0,  1,  2,  3,  4,  5,  6,  7
};
/*
 ****************************************************************************
 * Move generator *
 * Lack: no enpassant *
 ****************************************************************************
 */
void Gen_Push(int from, int dest, int type, MOVE * pBuf, int *pMCount)
{
   MOVE move;
   move.from = from;
   move.dest = dest;
   move.type = type;
   move.castle = castle;
   pBuf[*pMCount] = move;
   *pMCount = *pMCount + 1;
}

void Gen_PushNormal(int from, int dest, MOVE * pBuf, int *pMCount)
{
   Gen_Push(from, dest, MOVE_TYPE_NORMAL, pBuf, pMCount);
}

/* Pawn can promote */
void Gen_PushPawn(int from, int dest, MOVE * pBuf, int *pMCount)
{
   /* The 7 and 56 are to limit pawns to the 2nd through 7th ranks, which
    * means this isn't a promotion, i.e., a normal pawn move */
   if (dest > 7 && dest < 56) /* this is just a normal move */
   {
      Gen_Push(from, dest, MOVE_TYPE_NORMAL, pBuf, pMCount);
   }
   else /* otherwise it's a promotion */
   {
      Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_QUEEN, pBuf, pMCount);
      Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_ROOK, pBuf, pMCount);
      Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_BISHOP, pBuf, pMCount);
      Gen_Push(from, dest, MOVE_TYPE_PROMOTION_TO_KNIGHT, pBuf, pMCount);
   }
}

/* When a pawn moves two squares then appears the possibility of the en passanta capture*/
void Gen_PushPawnTwo(int from, int dest, MOVE * pBuf, int *pMCount)
{
   Gen_Push(from, dest, MOVE_TYPE_PAWN_TWO, pBuf, pMCount);
}

/* For en passant capture */
//void Gen_PushPawnEPS(int from, int dest, MOVE * pBuf, int *pMCount)
//{
//   Gen_Push(from, dest, MOVE_TYPE_ENPASANT, pBuf, pMCount);
//}

/* King*/
void Gen_PushKing(int from, int dest, MOVE * pBuf, int *pMCount)
{
   /* Is it a castle?*/
   if (from == E1 && (dest == G1 || dest == C1)) /* this is a white short castle */
   {
      Gen_Push(from, dest, MOVE_TYPE_CASTLE, pBuf, pMCount);
   }
   else if (from == E8 && (dest == G8 || dest == C8)) /* this is a white long castle */
   {
      Gen_Push(from, dest, MOVE_TYPE_CASTLE, pBuf, pMCount);
   }
   else /* otherwise it's a normal king's move */
   {
      Gen_Push(from, dest, MOVE_TYPE_NORMAL, pBuf, pMCount);
   }
}

/* Gen all moves of current_side to move and push them to pBuf, return number of moves */
int Gen(int current_side, MOVE * pBuf)
{
   int i; /* Counter for the board squares */
   int k; /* Counter for cols */
   int y;
   int row;
   int col;
   int movecount;
   movecount = 0;

   assert (movecount < 201);

   for (i = 0; i < 64; i++) /* Scan all board */
      if (color[i] == current_side)
      {
         switch (piece[i])
         {

         case PAWN:
            col = COL(i);
            row = ROW(i);
            if (current_side == BLACK)
            {
               if (color[i + 8] == EMPTY)
                  /* Pawn advances one square.
                   * We use Gen_PushPawn because it can be a promotion */
                  Gen_PushPawn(i, i + 8, pBuf, &movecount);
               if (row == 1 && color[i + 8] == EMPTY && color[i + 16] == EMPTY)
                  /* Pawn advances two squares */
                  Gen_PushPawnTwo(i, i + 16, pBuf, &movecount);
               if (col && color[i + 7] == WHITE)
                  /* Pawn captures and it can be a promotion*/
                  Gen_PushPawn(i, i + 7, pBuf, &movecount);
               if (col < 7 && color[i + 9] == WHITE)
                  /* Pawn captures and can be a promotion*/
                  Gen_PushPawn(i, i + 9, pBuf, &movecount);
               /* For en passant capture */
               if (col && piece[i + 7] == EPS_SQUARE)
                  /* Pawn captures and it can be a promotion*/
                  Gen_PushPawn(i, i + 7, pBuf, &movecount);
               if (col < 7 && piece[i + 9] == EPS_SQUARE)
                  /* Pawn captures and can be a promotion*/
                  Gen_PushPawn(i, i + 9, pBuf, &movecount);
            }
            else
            {
               if (color[i - 8] == EMPTY)
                  Gen_PushPawn(i, i - 8, pBuf, &movecount);
               /* Pawn moves 2 squares */
               if (row == 6 && color[i - 8] == EMPTY && color[i - 16] == EMPTY)
                  Gen_PushPawnTwo(i, i - 16, pBuf, &movecount);
               /* For captures */
               if (col && color[i - 9] == BLACK)
                  Gen_PushPawn(i, i - 9, pBuf, &movecount);
               if (col < 7 && color[i - 7] == BLACK)
                  Gen_PushPawn(i, i - 7, pBuf, &movecount);
               /* For en passant capture */
               if (col && piece[i - 9] == EPS_SQUARE)
                  Gen_PushPawn(i, i - 9, pBuf, &movecount);
               if (col < 7 && piece[i - 7] == EPS_SQUARE)
                  Gen_PushPawn(i, i - 7, pBuf, &movecount);
            }
            break;

         case QUEEN: /* == BISHOP+ROOK */

         case BISHOP:
            for (y = i - 9; y >= 0 && COL(y) != 7; y -= 9)
            { /* go left up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i - 7; y >= 0 && COL(y) != 0; y -= 7)
            { /* go right up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 9; y < 64 && COL(y) != 0; y += 9)
            { /* go right down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 7; y < 64 && COL(y) != 7; y += 7)
            { /* go left down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            if (piece[i] == BISHOP) /* In the case of the bishop we're done */
               break;

            /* FALL THROUGH FOR QUEEN {I meant to do that!} ;-) */
         case ROOK:
            col = COL(i);
            for (k = i - col, y = i - 1; y >= k; y--)
            { /* go left */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (k = i - col + 7, y = i + 1; y <= k; y++)
            { /* go right */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i - 8; y >= 0; y -= 8)
            { /* go up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 8; y < 64; y += 8)
            { /* go down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            break;

         case KNIGHT:
            col = COL(i);
            y = i - 6;
            if (y >= 0 && col < 6 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 10;
            if (y >= 0 && col > 1 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 15;
            if (y >= 0 && col < 7 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 17;
            if (y >= 0 && col > 0 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 6;
            if (y < 64 && col > 1 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 10;
            if (y < 64 && col < 6 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 15;
            if (y < 64 && col > 0 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 17;
            if (y < 64 && col < 7 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            break;

         case KING:
            /* the column and rank checks are to make sure it is on the board*/
            col = COL(i);
            if (col && color[i - 1] != current_side)
               Gen_PushKing(i, i - 1, pBuf, &movecount); /* left */
            if (col < 7 && color[i + 1] != current_side)
               Gen_PushKing(i, i + 1, pBuf, &movecount); /* right */
            if (i > 7 && color[i - 8] != current_side)
               Gen_PushKing(i, i - 8, pBuf, &movecount); /* up */
            if (i < 56 && color[i + 8] != current_side)
               Gen_PushKing(i, i + 8, pBuf, &movecount); /* down */
            if (col && i > 7 && color[i - 9] != current_side)
               Gen_PushKing(i, i - 9, pBuf, &movecount); /* left up */
            if (col < 7 && i > 7 && color[i - 7] != current_side)
               Gen_PushKing(i, i - 7, pBuf, &movecount); /* right up */
            if (col && i < 56 && color[i + 7] != current_side)
               Gen_PushKing(i, i + 7, pBuf, &movecount); /* left down */
            if (col < 7 && i < 56 && color[i + 9] != current_side)
               Gen_PushKing(i, i + 9, pBuf, &movecount); /* right down */


               if (current_side == WHITE)
               {
                  /* Can white short castle? */
                  if (castle & 1)
                  {
                     /* If white can castle the white king has to be in square 60 */
                     if (col &&
                        color[i + 1] == EMPTY &&
                        color[i + 2] == EMPTY &&
                        !IsInCheck(current_side) &&
                        !IsAttacked(current_side, i + 1))
                     {
                        /* The king goes 2 sq to the left */
                        Gen_PushKing(i, i + 2, pBuf, &movecount);
                     }
                  }

                  /* Can white long castle? */
                  if (castle & 2)
                  {
                     if (col &&
                        color[i - 1] == EMPTY &&
                        color[i - 2] == EMPTY &&
                        color[i - 3] == EMPTY &&
                        !IsInCheck(current_side) &&
                        !IsAttacked(current_side, i - 1))
                     {
                        /* The king goes 2 sq to the left */
                        Gen_PushKing(i, i - 2, pBuf, &movecount);
                     }
                  }
               }
               else if (current_side == BLACK)
               {
                  /* Can black short castle? */
                  if (castle & 4)
                  {
                     /* If white can castle the white king has to be in square 60 */
                     if (col &&
                        color[i + 1] == EMPTY &&
                        color[i + 2] == EMPTY &&
                        piece[i + 3] == ROOK &&
                        !IsInCheck(current_side) &&
                        !IsAttacked(current_side, i + 1))
                     {
                        /* The king goes 2 sq to the left */
                        Gen_PushKing(i, i + 2, pBuf, &movecount);
                     }
                  }
                  /* Can black long castle? */
                  if (castle & 8)
                  {
                     if (col &&
                        color[i - 1] == EMPTY &&
                        color[i - 2] == EMPTY &&
                        color[i - 3] == EMPTY &&
                        piece[i - 4] == ROOK &&
                        !IsInCheck(current_side) &&
                        !IsAttacked(current_side, i - 1))
                     {
                        /* The king goes 2 sq to the left */
                        Gen_PushKing(i, i - 2, pBuf, &movecount);
                     }
                  }
               }

            break;
//         default:
//            printf("Piece type unknown");
//            assert(false);
         }
      }
   return movecount;
}

/* Gen all captures of current_side to move and push them to pBuf, return number of moves */
int GenCaps(int current_side, MOVE * pBuf)
{
   int i; /* Counter for the board squares */
   int k; /* Counter for cols */
   int y;
   int row;
   int col;
   int movecount;
   movecount = 0;

   assert (movecount < 201);

   for (i = 0; i < 64; i++) /* Scan all board */
      if (color[i] == current_side)
      {
         switch (piece[i])
         {

         case PAWN:
            col = COL(i);
            row = ROW(i);
            if (current_side == BLACK)
            {
               if (col && color[i + 7] == WHITE)
                  /* Pawn captures and it can be a promotion*/
                  Gen_PushPawn(i, i + 7, pBuf, &movecount);
               if (col < 7 && color[i + 9] == WHITE)
                  /* Pawn captures and can be a promotion*/
                  Gen_PushPawn(i, i + 9, pBuf, &movecount);
               /* For en passant capture */
               if (col && piece[i + 7] == EPS_SQUARE)
                  /* Pawn captures and it can be a promotion*/
                  Gen_PushPawn(i, i + 7, pBuf, &movecount);
               if (col < 7 && piece[i + 9] == EPS_SQUARE)
                  /* Pawn captures and can be a promotion*/
                  Gen_PushPawn(i, i + 9, pBuf, &movecount);
            }
            else
            {
               /* For captures */
               if (col && color[i - 9] == BLACK)
                  Gen_PushPawn(i, i - 9, pBuf, &movecount);
               if (col < 7 && color[i - 7] == BLACK)
                  Gen_PushPawn(i, i - 7, pBuf, &movecount);
               /* For en passant capture */
               if (col && piece[i - 9] == EPS_SQUARE)
                  Gen_PushPawn(i, i - 9, pBuf, &movecount);
               if (col < 7 && piece[i - 7] == EPS_SQUARE)
                  Gen_PushPawn(i, i - 7, pBuf, &movecount);
            }
            break;

         case QUEEN: /* == BISHOP+ROOK */

         case BISHOP:
            for (y = i - 9; y >= 0 && COL(y) != 7; y -= 9)
            { /* go left up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i - 7; y >= 0 && COL(y) != 0; y -= 7)
            { /* go right up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 9; y < 64 && COL(y) != 0; y += 9)
            { /* go right down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 7; y < 64 && COL(y) != 7; y += 7)
            { /* go left down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            if (piece[i] == BISHOP) /* In the case of the bishop we're done */
               break;

            /* FALL THROUGH FOR QUEEN {I meant to do that!} ;-) */
         case ROOK:
            col = COL(i);
            for (k = i - col, y = i - 1; y >= k; y--)
            { /* go left */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (k = i - col + 7, y = i + 1; y <= k; y++)
            { /* go right */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i - 8; y >= 0; y -= 8)
            { /* go up */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            for (y = i + 8; y < 64; y += 8)
            { /* go down */
               if (color[y] != current_side)
                  Gen_PushNormal(i, y, pBuf, &movecount);
               if (color[y] != EMPTY)
                  break;
            }
            break;

         case KNIGHT:
            col = COL(i);
            y = i - 6;
            if (y >= 0 && col < 6 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 10;
            if (y >= 0 && col > 1 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 15;
            if (y >= 0 && col < 7 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i - 17;
            if (y >= 0 && col > 0 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 6;
            if (y < 64 && col > 1 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 10;
            if (y < 64 && col < 6 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 15;
            if (y < 64 && col > 0 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            y = i + 17;
            if (y < 64 && col < 7 && color[y] != current_side)
               Gen_PushNormal(i, y, pBuf, &movecount);
            break;

         case KING:
            /* the column and rank checks are to make sure it is on the board*/
            col = COL(i);
            if (col && color[i - 1] != current_side)
               Gen_PushKing(i, i - 1, pBuf, &movecount); /* left */
            if (col < 7 && color[i + 1] != current_side)
               Gen_PushKing(i, i + 1, pBuf, &movecount); /* right */
            if (i > 7 && color[i - 8] != current_side)
               Gen_PushKing(i, i - 8, pBuf, &movecount); /* up */
            if (i < 56 && color[i + 8] != current_side)
               Gen_PushKing(i, i + 8, pBuf, &movecount); /* down */
            if (col && i > 7 && color[i - 9] != current_side)
               Gen_PushKing(i, i - 9, pBuf, &movecount); /* left up */
            if (col < 7 && i > 7 && color[i - 7] != current_side)
               Gen_PushKing(i, i - 7, pBuf, &movecount); /* right up */
            if (col && i < 56 && color[i + 7] != current_side)
               Gen_PushKing(i, i + 7, pBuf, &movecount); /* left down */
            if (col < 7 && i < 56 && color[i + 9] != current_side)
               Gen_PushKing(i, i + 9, pBuf, &movecount); /* right down */



               /* We don't need any of the castle stuf */

            break;
//         default:
//            printf("Piece type unknown");
//            assert(false);
         }
      }
   return movecount;
}

/*
 ****************************************************************************
 * Evaluation for current position - main "brain" function *
 * Lack: almost no knowlegde *
 ****************************************************************************
 */
int Eval()
{

   count_evaluations++;

   /* A counter for the board squares */
   int i;

   /* The score of the position */
   int score = 0;

   /* Check all the squares searching for the pieces */
   for (i = 0; i < 64; i++)
   {
      if (color[i] == WHITE)
      {
         /* In the current square, add the material
          * value of the piece */
         score += value_piece[piece[i]];

         /* Now we add to the evaluation the value of the
          * piece square tables */
         switch (piece[i])
         {
         case PAWN:
            score += pst_pawn[i];
            break;
         case KNIGHT:
            score += pst_knight[i];
            break;
         case BISHOP:
            score += pst_bishop[i];
            break;
         case ROOK:
            score += pst_rook[i];
            break;
         case KING:
            score += pst_king[i];
            break;
         }
      }
      else if (color[i] == BLACK)
      {
         score -= value_piece[piece[i]];

         switch (piece[i])
         {
         case PAWN:
            score -= pst_pawn[flip[i]];
            break;
         case KNIGHT:
            score -= pst_knight[flip[i]];
            break;
         case BISHOP:
            score -= pst_bishop[flip[i]];
            break;
         case ROOK:
            score -= pst_rook[flip[i]];
            break;
         case KING:
            score -= pst_king[flip[i]];
            break;
         }
      }
   }

   if (side == WHITE)
      return score;
   return -score;
}

/*
 ****************************************************************************
 * Make and Take back a move, IsInCheck *
 ****************************************************************************
 */
/* Check and return 1 if side is in check, 0 otherwise */
int IsInCheck(int current_side)
{
   int k; /* The square where the king is placed */
   int h;
   int y;
   int row; /* Row where the king is placed */
   int col; /* Col where the king is placed */
   int xside;
   xside = (WHITE + BLACK) - current_side; /* opposite current_side, who may be checking */

   /* Find King */
   for (k = 0; k < 64; k++)
      if ((piece[k] == KING) && color[k] == current_side)
         break;
   /* Situation of the king */
   row = ROW(k);
   col = COL(k);

   /* Check Knight attack */
   if (col > 0 && row > 1 && color[k - 17] == xside && piece[k - 17] == KNIGHT)
      return 1;
   if (col < 7 && row > 1 && color[k - 15] == xside && piece[k - 15] == KNIGHT)
      return 1;
   if (col > 1 && row > 0 && color[k - 10] == xside && piece[k - 10] == KNIGHT)
      return 1;
   if (col < 6 && row > 0 && color[k - 6] == xside && piece[k - 6] == KNIGHT)
      return 1;
   if (col > 1 && row < 7 && color[k + 6] == xside && piece[k + 6] == KNIGHT)
      return 1;
   if (col < 6 && row < 7 && color[k + 10] == xside && piece[k + 10] == KNIGHT)
      return 1;
   if (col > 0 && row < 6 && color[k + 15] == xside && piece[k + 15] == KNIGHT)
      return 1;
   if (col < 7 && row < 6 && color[k + 17] == xside && piece[k + 17] == KNIGHT)
      return 1;

   /* Check horizontal and vertical lines for attacking of Queen, Rook, King */
   /* go down */
   y = k + 8;
   if (y < 64)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y += 8; y < 64; y += 8)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go left */
   y = k - 1;
   h = k - col;
   if (y >= h)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y--; y >= h; y--)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go right */
   y = k + 1;
   h = k - col + 7;
   if (y <= h)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y++; y <= h; y++)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go up */
   y = k - 8;
   if (y >= 0)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y -= 8; y >= 0; y -= 8)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* Check diagonal lines for attacking of Queen, Bishop, King, Pawn */
   /* go right down */
   y = k + 9;
   if (y < 64 && COL(y) != 0)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == BLACK && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y += 9; y < 64 && COL(y) != 0; y += 9)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go left down */
   y = k + 7;
   if (y < 64 && COL(y) != 7)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == BLACK && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y += 7; y < 64 && COL(y) != 7; y += 7)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;

         }
   }
   /* go left up */
   y = k - 9;
   if (y >= 0 && COL(y) != 7)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == WHITE && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y -= 9; y >= 0 && COL(y) != 7; y -= 9)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;

         }
   }
   /* go right up */
   y = k - 7;
   if (y >= 0 && COL(y) != 0)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == WHITE && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y -= 7; y >= 0 && COL(y) != 0; y -= 7)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   return 0;
}

/* Check and return 1 if square k is attacked, 0 otherwise. Necesary, vg, to check
 * castle rules (if king goes from e1 to g1, f1 can't be attacked by an enemy piece) */
int IsAttacked(int current_side, int k)
{
   int h;
   int y;
   int row; /* Row where the sqaure is placed */
   int col; /* Col where the square is placed */
   int xside;
   xside = (WHITE + BLACK) - current_side; /* opposite current_side, who may be attacking */

   /* Situation of the square*/
   row = ROW(k);
   col = COL(k);

   /* Check Knight attack */
   if (col > 0 && row > 1 && color[k - 17] == xside && piece[k - 17] == KNIGHT)
      return 1;
   if (col < 7 && row > 1 && color[k - 15] == xside && piece[k - 15] == KNIGHT)
      return 1;
   if (col > 1 && row > 0 && color[k - 10] == xside && piece[k - 10] == KNIGHT)
      return 1;
   if (col < 6 && row > 0 && color[k - 6] == xside && piece[k - 6] == KNIGHT)
      return 1;
   if (col > 1 && row < 7 && color[k + 6] == xside && piece[k + 6] == KNIGHT)
      return 1;
   if (col < 6 && row < 7 && color[k + 10] == xside && piece[k + 10] == KNIGHT)
      return 1;
   if (col > 0 && row < 6 && color[k + 15] == xside && piece[k + 15] == KNIGHT)
      return 1;
   if (col < 7 && row < 6 && color[k + 17] == xside && piece[k + 17] == KNIGHT)
      return 1;

   /* Check horizontal and vertical lines for attacking of Queen, Rook, King */
   /* go down */
   y = k + 8;
   if (y < 64)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y += 8; y < 64; y += 8)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go left */
   y = k - 1;
   h = k - col;
   if (y >= h)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y--; y >= h; y--)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go right */
   y = k + 1;
   h = k - col + 7;
   if (y <= h)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y++; y <= h; y++)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go up */
   y = k - 8;
   if (y >= 0)
   {
      if (color[y] == xside && (piece[y] == KING || piece[y] == QUEEN
            || piece[y] == ROOK))
         return 1;
      if (piece[y] == EMPTY)
         for (y -= 8; y >= 0; y -= 8)
         {
            if (color[y] == xside
                  && (piece[y] == QUEEN || piece[y] == ROOK))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* Check diagonal lines for attacking of Queen, Bishop, King, Pawn */
   /* go right down */
   y = k + 9;
   if (y < 64 && COL(y) != 0)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == BLACK && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y += 9; y < 64 && COL(y) != 0; y += 9)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   /* go left down */
   y = k + 7;
   if (y < 64 && COL(y) != 7)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == BLACK && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y += 7; y < 64 && COL(y) != 7; y += 7)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;

         }
   }
   /* go left up */
   y = k - 9;
   if (y >= 0 && COL(y) != 7)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == WHITE && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y -= 9; y >= 0 && COL(y) != 7; y -= 9)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;

         }
   }
   /* go right up */
   y = k - 7;
   if (y >= 0 && COL(y) != 0)
   {
      if (color[y] == xside)
      {
         if (piece[y] == KING || piece[y] == QUEEN || piece[y] == BISHOP)
            return 1;
         if (current_side == WHITE && piece[y] == PAWN)
            return 1;
      }
      if (piece[y] == EMPTY)
         for (y -= 7; y >= 0 && COL(y) != 0; y -= 7)
         {
            if (color[y] == xside && (piece[y] == QUEEN || piece[y]
                  == BISHOP))
               return 1;
            if (piece[y] != EMPTY)
               break;
         }
   }
   return 0;
}

int MakeMove(MOVE m)
{
   int r;
   int i;

   count_MakeMove ++;

   hist[hdp].m = m;
   /* store in history the piece of the dest square */
   hist[hdp].cap = piece[m.dest];
   /* dest piece is the original piece */
   piece[m.dest] = piece[m.from];
   /* The original square becomes empty */
   piece[m.from] = EMPTY;
   /* The dest square color is the one of the origin piece */
   color[m.dest] = color[m.from];
   /* The original color becomes empty */
   color[m.from] = EMPTY;


   /* Once the move is done we check either this is a promotion */
   if (m.type >= MOVE_TYPE_PROMOTION_TO_QUEEN)
   {
      /* In this case we put in the destiny sq the chosen piece */
      switch (m.type)
      {
      case MOVE_TYPE_PROMOTION_TO_QUEEN:
         piece[m.dest] = QUEEN;
         break;

      case MOVE_TYPE_PROMOTION_TO_ROOK:
         piece[m.dest] = ROOK;
         break;

      case MOVE_TYPE_PROMOTION_TO_BISHOP:
         piece[m.dest] = BISHOP;
         break;

      case MOVE_TYPE_PROMOTION_TO_KNIGHT:
         piece[m.dest] = KNIGHT;
         break;

      default:
         puts("Impossible to get here...");
         assert(false);
      }
   }

   /* Remove possible eps piece, remaining from former move */
   if (hist[hdp-1].m.type == MOVE_TYPE_PAWN_TWO)
   {
      for (i = 16; i <= 23; i++)
      {
         if (piece[i] == EPS_SQUARE)
         {
            piece[i] = EMPTY;
            /* this seems unnecesary, but otherwise a bug occurs:
            * after: a3 Nc6 d4 e6, white isn't allowed to play e4 */
            color[i] = EMPTY;
            break;
         }
      }
      for (i = 40; i <= 47; i++)
      {
         if (piece[i] == EPS_SQUARE)
         {
            piece[i] = EMPTY;
            color[i] = EMPTY;
            break;
         }
      }
   }
//   for (i = 0; i <= 63; i++)
//         {
//            if (piece[i] == EPS_SQUARE)
//            {
//               piece[i] = EMPTY;
//               color[i] = EMPTY;
//               break;
//            }
//         }

   /* Add the eps square when a pawn moves two sqaures */
   if (m.type == MOVE_TYPE_PAWN_TWO)
   {
      if (side == BLACK)
      {
         piece[m.from + 8] = EPS_SQUARE;
      }
      else if (side == WHITE)
      {
         piece[m.from - 8] = EPS_SQUARE;
      }
   }

   if (m.type == MOVE_TYPE_CASTLE)
   {
      if (m.dest == G1)
      {
         /* h1-h8 becomes empty */
         piece[m.from + 3] = EMPTY;
         color[m.from + 3] = EMPTY;
         /* rook to f1-f8 */
         piece[m.from + 1] = ROOK;
         color[m.from + 1] = WHITE;
      }
      else if (m.dest == C1)
      {
         /* h1-h8 becomes empty */
         piece[m.from - 4] = EMPTY;
         color[m.from - 4] = EMPTY;
         /* rook to f1-f8 */
         piece[m.from - 1] = ROOK;
         color[m.from - 1] = WHITE;
      }
      else if (m.dest == G8)
      {
         /* h1-h8 becomes empty */
         piece[m.from + 3] = EMPTY;
         color[m.from + 3] = EMPTY;
         /* rook to f1-f8 */
         piece[m.from + 1] = ROOK;
         color[m.from + 1] = BLACK;
      }
      else if (m.dest == C8)
      {
         /* h1-h8 becomes empty */
         piece[m.from - 4] = EMPTY;
         color[m.from - 4] = EMPTY;
         /* rook to f1-f8 */
         piece[m.from - 1] = ROOK;
         color[m.from - 1] = BLACK;
      }
   }

   /* Update ply and hdp */
   ply++;
   hdp++;

   /* Update the castle */
   castle &= castle_mask[m.from] & castle_mask[m.dest];

   r = !IsInCheck(side);

   /* After making move, give turn to opponent */
   side = (WHITE + BLACK) - side;

   return r;
}

void TakeBack() /* undo what MakeMove did */
{

   int i;

   side = (WHITE + BLACK) - side;
   hdp--;
   ply--;
   piece[hist[hdp].m.from] = piece[hist[hdp].m.dest];
   piece[hist[hdp].m.dest] = hist[hdp].cap;
   color[hist[hdp].m.from] = side;

   /* Update castle rights */
   castle = hist[hdp].m.castle;

   if (hist[hdp].cap != EMPTY)
   {
      color[hist[hdp].m.dest] = (WHITE + BLACK) - side;
   }
   else
   {
      color[hist[hdp].m.dest] = EMPTY;
   }

   /* Promotion */
   if (hist[hdp].m.type >= MOVE_TYPE_PROMOTION_TO_QUEEN)
   {
      piece[hist[hdp].m.from] = PAWN;
   }

   /* Pawn moves two in the former move, so we hace to replace
       * the eps square */
   if (hist[hdp-1].m.type == MOVE_TYPE_PAWN_TWO)
   {
      if (side == BLACK)
         {
         piece[hist[hdp-1].m.dest + 8] = EPS_SQUARE;
         }
      else if (side == WHITE)
      {
         piece[hist[hdp-1].m.dest - 8] = EPS_SQUARE;
      }
   }

   /* To remove the eps square after unmaking a pawn
    * movein two sqaures*/
   if (hist[hdp].m.type == MOVE_TYPE_PAWN_TWO)
   {
      if (side == WHITE)
      {
         piece[hist[hdp].m.from - 8] = EMPTY;
      }
      else if (side == BLACK)
      {
         piece[hist[hdp].m.from + 8] = EMPTY;
      }
   }

   /* Castle: return rook to its original square */
   if (hist[hdp].m.type == MOVE_TYPE_CASTLE)
   {
      /* Take the tower to its poriginal place */
      if (hist[hdp].m.dest == G1)
      {
         piece[H1] = ROOK;
         color[H1] = WHITE;
         piece[F1] = EMPTY;
         color[F1] = EMPTY;
      }
      else if (hist[hdp].m.dest == C1)
      {
         piece[A1] = ROOK;
         color[A1] = WHITE;
         piece[D1] = EMPTY;
         color[D1] = EMPTY;
      }
      else if (hist[hdp].m.dest == G8)
      {
         piece[H8] = ROOK;
         color[H8] = BLACK;
         piece[F8] = EMPTY;
         color[F8] = EMPTY;
      }
      else if (hist[hdp].m.dest == C8)
      {
         piece[A8] = ROOK;
         color[A8] = BLACK;
         piece[D8] = EMPTY;
         color[D8] = EMPTY;
      }
   }
}

/*
 ****************************************************************************
 * Search function - a typical alphabeta, main search function *
 * Lack: no any technique for move ordering *
 ****************************************************************************
 */

int Search(int alpha, int beta, int depth, MOVE * pBestMove)
{
   int i;
   int value;  /* To store the evaluation */
   int havemove;  /* Either we have or not a legal move available */
   int movecnt;  /* The number of available moves */

   MOVE moveBuf[200]; /* List of movements */
   MOVE tmpMove;

   nodes++; /* visiting a node, count it */
   havemove = 0; /* is there a move available? */
   pBestMove->type = MOVE_TYPE_NONE;

   /* Generate and count all moves for current position */
   movecnt = Gen(side, moveBuf);
   assert (movecnt < 201);

   /* Once we have all the moves available, we loop through the posible
    * moves and apply an alpha-beta search */
   for (i = 0; i < movecnt; ++i)
   {

//      {
//      printf("move #%d = %c%d%c%d; \n",
//            i,
//            'a' + COL(moveBuf[i].from), 8 - ROW(moveBuf[i].from),
//            'a' + COL(moveBuf[i].dest), 8 - ROW(moveBuf[i].dest));
//      }

      if (!MakeMove(moveBuf[i]))
      {
         /* If the current move isn't legal, we take it back
          * and take the next move in the list */
         TakeBack();
         continue;
      }

      /* If we're here, that means we have a move available */
      havemove = 1;

      /* This 'if' takes us to the deep of the position, the leaf nodes */
      if (depth - 1 > 0)
      {
         value = -Search(-beta, -alpha, depth - 1, &tmpMove);
      }
      else /* If no depth left (leaf node), we evalute the position
       and apply the alpha-beta search.
       In the case of existing a quiescent function, it should be
       called here instead of Eval() */
      {
         value = -Eval();
      }

      /* We've evaluated the position, so we return to the previous position
       * in such a way that when we take the next move in moveBuf everything is in order */
      TakeBack();

      /* Once we have an evaluation, we use it in in an alpha-beta search */
      if (value > alpha)
      {
         /* This move is so good and caused a cutoff */
         if (value >= beta)
         {
            return beta;
         }
         alpha = value;
         /* So far, current move is the best reaction for current position */
         *pBestMove = moveBuf[i];
      }
   }

   /* Once we've checked all the moves and we have no legal moves,
    * then that's checkmate or stalemate */
   if (!havemove)
   {
      if (IsInCheck(side))
         return -MATE + ply; /* add ply to find the longest path to lose or shortest path to win */
      else
         return 0;
   }

   /* Finally .we return alpha, the score value */
   return alpha;
}

MOVE ComputerThink(int max_depth)
{
   /* It returns the move the computer makes */
   MOVE m;
   int score;
   double nps;

   /* Reset some values before searching */
   ply = 0;
   nodes = 0;
   count_evaluations = 0;
   count_MakeMove = 0;


   clock_t start;
   clock_t stop;
   double t = 0.0;

   /* Start timer */
   start = clock();
   assert(start != -1);

   /* Search now */
   score = Search(-MATE, MATE, max_depth, &m);

   /* Stop timer */
   stop = clock();
   t = (double) (stop - start) / CLOCKS_PER_SEC;
   nps = nodes / t;

   /* After searching, print results */
   float decimal_score = ((float)score)/100.;
   printf(
         "Search result: move = %c%d%c%d; nodes = %d, evaluations = %d, moves made = %d, depth = %d, score = %.2f, time = %.2fs, nps = %.0f\n",
         'a' + COL(m.from), 8 - ROW(m.from), 'a' + COL(m.dest), 8
               - ROW(m.dest), nodes, count_evaluations, count_MakeMove, max_depth, decimal_score, t, nps);
   return m;
}

/*
 ****************************************************************************
 * Utilities *
 ****************************************************************************
 */
void PrintBoard()
{
   char pieceName[] = "PNBRQKpnbrqk";
   int i;
   for (i = 0; i < 64; i++)
   {
      if ((i & 7) == 0)
      {
         printf("  +---+---+---+---+---+---+---+---+\n");
         if (i <= 56)
         {
            printf(" %d |", 8 - (((unsigned) i) >> 3));
         }
      }
      if (piece[i] == EMPTY)
         printf("  |");
      else if (piece[i] == EPS_SQUARE)
         printf(" * |");
      else
      {
         printf(" %c |", pieceName[piece[i] + (color[i] == WHITE ? 0 : 6)]);
      }
      if ((i & 7) == 7)
         printf("\n");
   }
   printf(
         "  +---+---+---+---+---+---+---+---+\n    a  b  c  d  e  f  g  h\n");
}

void perft(depth)
{
   int i;
   int value;  /* To store the evaluation */
   int havemove;  /* Either we have or not a legal move available */
   int movecnt;  /* The number of available moves */

   MOVE moveBuf[200]; /* List of movements */
   MOVE tmpMove;

   nodes++; /* visiting a node, count it */
   havemove = 0; /* is there a move available? */

   /* Generate and count all moves for current position */
   movecnt = Gen(side, moveBuf);
   assert (movecnt < 201);

   /* Once we have all the moves available, we loop through the posible
    * moves and apply an alpha-beta search */
   for (i = 0; i < movecnt; ++i)
   {
      if (!MakeMove(moveBuf[i]))
      {
         /* If the current move isn't legal, we take it back
          * and take the next move in the list */
         TakeBack();
         continue;
      }

      /* Checks? */
      if (IsInCheck(side) || IsInCheck(!side))
      {
         count_checks++;
//         count_evaluations--;
      }


      /* If we're here, that means we have a move available */
      havemove = 1;

      if (depth - 1 > 0)
      {
      if (IsInCheck(side))
         {
            count_evaluations--;
         }
      }

      /* This 'if' takes us to the deep of the position, the leaf nodes */
      if (depth - 1 > 0)
      {
         perft(depth - 1);
      }
      else
      {
         count_evaluations++;
      }

      TakeBack();

   }

   /* Once we've checked all the moves and we have no legal moves,
    * then that's checkmate or stalemate */
   if (!havemove)
   {
//      if (IsInCheck(side))
//         return -MATE + ply; /* add ply to find the longest path to lose or shortest path to win */
//      else
//         return 0;
      puts("Check");
   }

//   printf("nodes = %d, counted evals = %d, depth = %d\n", nodes, count_evaluations, depth);
}
/*
 ****************************************************************************
 * Main program *
 ****************************************************************************
 */
void main()
{

   /* It mainly calls ComputerThink(maxdepth) to the desired ply */

   char s[256];
   int from;
   int dest;
   int i;
   int computer_side;
   int max_depth; /* max depth to search */
   MOVE moveBuf[200];
   int movecnt;

   puts("Second Chess, by Emilio Diaz");
   puts(" Help");
   puts(" d: display board");
   puts(" MOVE: make a move (e.g. b1c3, a7a8q, e1g1)");
   puts(" on: force computer to move");
   puts(" quit: exit");
   puts(" sd n: set engine depth to n plies");
   puts(" undo: take back last move");

   side = WHITE;
   computer_side = BLACK; /* Human is white side */
   max_depth = 6;
   hdp = 0; /* Current move order */
   for (;;)
   {
      if (side == computer_side)
      { /* Computer's turn */
         /* Find out the best move to react the current position */
         MOVE bestMove = ComputerThink(max_depth);
         MakeMove(bestMove);
         PrintBoard();
         printf("CASTLE: %d\n", castle);
         continue;
      }

      /* Get user input */
      printf("sc> ");
      if (scanf("%s", s) == EOF) /* close program */
         return;
      if (!strcmp(s, "d"))
      {
         PrintBoard();
         continue;
      }
      if (!strcmp(s, "undo"))
      {
         TakeBack();
         PrintBoard();
         computer_side = (WHITE + BLACK) - computer_side;
         continue;
      }
      if (!strcmp(s, "on"))
      {
         computer_side = side;
         continue;
      }
      if (!strcmp(s, "sd"))
      {
         scanf("%d", &max_depth);
         continue;
      }
      if (!strcmp(s, "perft"))
      {
         count_evaluations = 0;
         count_checks = 0;
         scanf("%d", &max_depth);
         perft(max_depth);
         printf("nodes = %d,"
               "counted evals = %d,"
               "checks = %d, depth = %d\n",
               nodes,
               count_evaluations,
               count_checks,
               max_depth);
         continue;
      }
      if (!strcmp(s, "quit"))
      {
         printf("Good bye!\n");
         return;
      }

      /* Maybe the user entered a move? */
      from = s[0] - 'a';
      from += 8 * (8 - (s[1] - '0'));
      dest = s[2] - 'a';
      dest += 8 * (8 - (s[3] - '0'));
      ply = 0;
      movecnt = Gen(side, moveBuf);

      /* Loop through the moves to see if it's legal */
      for (i = 0; i < movecnt; i++)
         if (moveBuf[i].from == from && moveBuf[i].dest == dest)
         {
            /* Promotion move? */
            if (piece[from] == PAWN && (dest < 8 || dest > 55))
            {
               switch (s[4])
               {
               case 'q':
                  moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_QUEEN;
                  break;

               case 'r':
                  moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_ROOK;
                  break;

               case 'b':
                  moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_BISHOP;
                  break;

               case 'n':
                  moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_KNIGHT;
                  break;

               default:
                  puts(
                        "promoting to a McGuffin..., I'll give you a queen");
                  moveBuf[i].type = MOVE_TYPE_PROMOTION_TO_QUEEN;
               }
            }
            if (!MakeMove(moveBuf[i]))
            {
               TakeBack();
               printf("Illegal move.\n");
            }
            break;
         }
      PrintBoard();
   }
}


BTW I played SecondChess in Arena 5 min time control & I won on time. Can move speed be improved?See:
[Event "Computer chess game"]
[Site "RICHARD-PC"]
[Date "2012.04.22"]
[Round "?"]
[White "Richard"]
[Black "SecondChess"]
[Result "1-0"]
[BlackElo "2000"]
[ECO "C44"]
[Opening "Open Game"]
[Time "01"]
[Variation "Inverted Hanham"]
[WhiteElo "2400"]
[TimeControl "300"]
[Termination "time forfeit"]
[PlyCount "37"]
[WhiteType "human"]
[BlackType "program"]

1. e4 d5 2. Nc3 d4 3. Nce2 e5 4. Nf3 Nc6 5. d3 Bg4 6. Ng3 Nf6 7. Be2 Bb4+
8. Bd2 Bxf3 9. Bxf3 O-O 10. O-O Bxd2 11. Qxd2 Rb8 12. a3 Ra8 13. Nf5 Ne8
14. Bg4 Nd6 15. f4 Re8 16. Nxd6 cxd6 17. f5 Qh4 18. h3 Rad8 19. Rf2 ...
{Black forfeits on time} 1-0


Best wishes

UPDATE-I just removed 'spoiler' tags from this post-I did not add them-did they add in automatically or did someone add them?
NEXT UPDATE-I have replaced 'spoiler' tags on this code now (see Victors post about this).I still do not know how/who put this tag here to start with! (not sure 'spoiler' is the best name for these either- why not 'show/hide'? Nevermind...:-)

Last edited by richardpd on Sun Apr 22, 2012 3:05 pm; edited 2 times in total (Reason for editing : adding spoiler tags)

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Maybe this could help:
http://msdn.microsoft.com/en-us/library/ewcf0002%28v=vs.80%29.aspx

The xboard implementation in secondchess is very simplistic, and it won't recognize anything related to time controls. Sorry for that, but right now I'm focused on other parts of the code.
When you can compile your own executables, you can modify the max_depth parameter. It'll make the engine to play faster (and worse), but of course won't fix the "this time control stuff isn't for me" issue.
In the scidVSpc I've got secondchess to play full games against other engines setting a time control of fixed time per move.

Regards

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
The link hasn't helped me & I have spent too much time this morning googling for help & trying to fix the code. For some reason cl compiler thinks syntax errors and undeclared variables around line 785-790....& too many other errors. I am not a proficient C/C++ programmer-surely someone here on this forum is & knows how to & can fix this easily?
(also why does the code I posted earlier not now show-just 'spoiler'?).


Update: I remembered I once looked at TinyCC compiler & sure enough I had a copy on my drive-so I used tcc compiler to compile secondchess.c & it worked (after I had added tcc to my windows path).
It still bugs me that MSVisStudio 2010 cl compiler baulks at this code-so the code is probably not strictly standards compliant? Still using tcc compiler is a backup/temporary option which will suffice for now and maybe useful again.

Last edited by richardpd on Sun Apr 22, 2012 1:25 pm; edited 1 time in total (Reason for editing : update)

descriptionSecondChess EmptyRe: SecondChess

more_horiz


In Otros(in spahish) in rigth opciones the messenger.

I could not compile a few days ago when asked.
Too many errors with VisualC + +.

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Well, I guess I've solved the hideous en passant bug. After some quick tests it seems to work now fine. Right now I'm testing it playing many games in fast controls, but in any case the improve is good enough to update the code in the github repository. So please replace the old code ASAP with the new one:
https://github.com/pocopito/secondchess


Best regards and thanks everybody who is testing the code.

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Emilio
My compile problems persist as now trying to compile the latest 1.24v secondchess. c with tcc I get xboard type error eg:

Code:

SecondChess>tcc secondchess.c
secondchess.c:2000: incompatible types for redefinition of 'xboard'

Any idea why & how to fix?
Best wishes

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi Richard

Thanks for testing and for the feedback.
I'm not quite sure how the xboard part works, but check this: Right under the "main" section:
/*
****************************************************************************
* Main program *
****************************************************************************
*/

//void xboard();


Check either the "void xboard()" part is either commented or not, and just change to the opposite :) (I've seen that with different compilers I need one or the other option.)

Regards

Emilio

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Emilio
Thanks for your quick reply-your fix worked (I uncommented xboard).
Then I compiled fine (tcc) & played my second game & I lost on time!!!
(I'm having a bad day.....) Game pgn below:

[Event "Computer chess game"]
[Site "RICHARD-PC"]
[Date "2012.04.25"]
[Round "?"]
[White "Richard"]
[Black "SecondChess"]
[Result "0-1"]
[BlackElo "2000"]
[ECO "A18"]
[Opening "English"]
[Time "17:22:55"]
[Variation "Mikenas, Flohr, 4...d4"]
[WhiteElo "2400"]
[TimeControl "300"]
[Termination "time forfeit"]
[PlyCount "114"]
[WhiteType "human"]
[BlackType "program"]

1. e4 d5 2. Nc3 d4 3. Nce2 e6 4. Nf3 Nc6 5. e5 a6 6. Ng3 Qd5 7. d3 Nxe5 8.
Nxe5 Qxe5+ 9. Qe2 Bb4+ 10. Bd2 Bxd2+ 11. Kxd2 Qf4+ 12. Ke1 Nf6 13. Qd2
Qxd2+ 14. Kxd2 O-O 15. Be2 Bd7 16. Bf3 Rad8 17. Bxb7 a5 18. Ba6 Bc6 19. f3
Ra8 20. Bc4 Rab8 21. b3 Bd5 22. Bxd5 exd5 23. Rae1 a4 24. Re7 Rbc8 25. Nf5
axb3 26. axb3 c5 27. Ra1 Ra8 28. Rxa8 Rxa8 29. Rc7 g6 30. Ne7+ Kf8 31. Nc6
Kg8 32. Ra7 Rxa7 33. Nxa7 c4 34. b4 Kh8 35. b5 Kg8 36. b6 Nd7 37. b7 Nb8
38. Nc8 Kf8 39. dxc4 dxc4 40. Nd6 c3+ 41. Kd3 Nc6 42. Nb5 Ne5+ 43. Kxd4
Nc6+ 44. Kxc3 Kg8 45. Kc4 Na5+ 46. Kc5 Nxb7+ 47. Kb6 Nd8 48. c4 Ne6 49. c5
Nf4 50. c6 Nd5+ 51. Kb7 f6 52. c7 Nxc7 53. Kxc7 Kf8 54. Nd4 Kg8 55. Kd7 Kf7
56. g4 h5 57. h3 Kg7 58. ... {White forfeits on time} 0-1

I was surprised SecondChess played quicker-I was expecting it to time out like my first game! So it's one all (game score) and now I'll have to play a deciding game....
Thanks

descriptionSecondChess EmptyRe: SecondChess

more_horiz
@richardpd wrote:
Emilio
Thanks for your quick reply-your fix worked (I uncommented xboard).
Then I compiled fine (tcc) & played my second game & I lost on time!!!
(I'm having a bad day.....) Game pgn below:

[Event "Computer chess game"]
[Site "RICHARD-PC"]
[Date "2012.04.25"]
[Round "?"]
[White "Richard"]
[Black "SecondChess"]
[Result "0-1"]
[BlackElo "2000"]
[ECO "A18"]
[Opening "English"]
[Time "17"]
[Variation "Mikenas, Flohr, 4...d4"]
[WhiteElo "2400"]
[TimeControl "300"]
[Termination "time forfeit"]
[PlyCount "114"]
[WhiteType "human"]
[BlackType "program"]

1. e4 d5 2. Nc3 d4 3. Nce2 e6 4. Nf3 Nc6 5. e5 a6 6. Ng3 Qd5 7. d3 Nxe5 8.
Nxe5 Qxe5+ 9. Qe2 Bb4+ 10. Bd2 Bxd2+ 11. Kxd2 Qf4+ 12. Ke1 Nf6 13. Qd2
Qxd2+ 14. Kxd2 O-O 15. Be2 Bd7 16. Bf3 Rad8 17. Bxb7 a5 18. Ba6 Bc6 19. f3
Ra8 20. Bc4 Rab8 21. b3 Bd5 22. Bxd5 exd5 23. Rae1 a4 24. Re7 Rbc8 25. Nf5
axb3 26. axb3 c5 27. Ra1 Ra8 28. Rxa8 Rxa8 29. Rc7 g6 30. Ne7+ Kf8 31. Nc6
Kg8 32. Ra7 Rxa7 33. Nxa7 c4 34. b4 Kh8 35. b5 Kg8 36. b6 Nd7 37. b7 Nb8
38. Nc8 Kf8 39. dxc4 dxc4 40. Nd6 c3+ 41. Kd3 Nc6 42. Nb5 Ne5+ 43. Kxd4
Nc6+ 44. Kxc3 Kg8 45. Kc4 Na5+ 46. Kc5 Nxb7+ 47. Kb6 Nd8 48. c4 Ne6 49. c5
Nf4 50. c6 Nd5+ 51. Kb7 f6 52. c7 Nxc7 53. Kxc7 Kf8 54. Nd4 Kg8 55. Kd7 Kf7
56. g4 h5 57. h3 Kg7 58. ... {White forfeits on time} 0-1

I was surprised SecondChess played quicker-I was expecting it to time out like my first game! So it's one all (game score) and now I'll have to play a deciding game....
Thanks

Could you please send me link to the latest build?

descriptionSecondChess EmptyRe: SecondChess

more_horiz
@richardpd wrote:
Emilio
Thanks for your quick reply-your fix worked (I uncommented xboard).
Then I compiled fine (tcc) & played my second game & I lost on time!!!
(I'm having a bad day.....) Game pgn below:
...

I was surprised SecondChess played quicker-I was expecting it to time out like my first game! So it's one all (game score) and now I'll have to play a deciding game....
Thanks


I'm glad the trick worked!

If the engine is playing faster, it can be due to several reasons:
-You modified the max_depth parameter to a lower value (which'd make the engine play faster but, of course, worse)
-Maybe you applied an optimization option in the compilation, but it seems tcc has nothing like this
-If in the search function you switch from

Code:

else
{
//value = Quiescent(alpha, beta);
value = -Eval();
}


to

Code:

else
{
value = Quiescent(alpha, beta);
//value = -Eval();
}


The engine will play slower.

In any case I'm glad you're enjoying it. If while reading the code you find some parts hard to understand, please let me know, as the main goal of secondchess is being a useful tool for anyone interested on how a chess engine works.

Regards

Emilio

PS: secondchess has no opening book or random on its code, so if you want to get some variations in the game, the "novelties" must be made by you
PS': take into account that despite you're playing games with time control seondchess has no idea of this issue. I mean, it won't play faster when you set a shorter time control.

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi Emilio
Since my last post I have played quite a few games versus SecondChess-some I win & some I lose.
Like the game I posted earlier all the games I have played as White with 1.e4 & SecondChess always replies 1.d5 (Scandinavian opening).
I do not mind this as it gives me practice in this opening!!(one day I will let SecondChess play white!!).

Meanwhile I have been trying to learn C programming from internet resources and playing around trying to make my own C console chess engine.
This will take a while as my C programming expertise/skill is basic!
I do hope to look at SecondChess C sourcecode and understand it more now I know more of C language!
If I look at it & get queries I will ask for your help & many thanks for trying to make this engine understandable to a fledgling/beginner chess programmer-this is very helpful! smile

I am posting this from my login on my wife's desktop computer Win7, where I have just compiled SecondChess so I can play it on this computer(my computer is updating Ubuntu as I type-although it dual boots with Win7 -via KVM switch...).I did this in Geany editor for windows (this uses gcc compiler that is from DevC++ which is in the Win7 path).
It compiled with some error messages which I post below but it runs fine in Arena.

I thought you might be interested in the compile errors/warnings:

gcc -Wall -c "secondchess.c" (in directory: C:\pocopito-secondchess-v0.1-30-gc8db4a0\pocopito-secondchess-c8db4a0)
secondchess.c: In function `Gen':
secondchess.c:530: warning: implicit declaration of function `IsInCheck'
secondchess.c:531: warning: implicit declaration of function `IsAttacked'
secondchess.c: In function `GenCaps':
secondchess.c:603: warning: unused variable `row'
secondchess.c: In function `TakeBack':
secondchess.c:1432: warning: unused variable `i'
secondchess.c: In function `perft':
secondchess.c:1767: warning: unused variable `value'
secondchess.c:1772: warning: unused variable `tmpMove'
Compilation finished successfully.

Doesn't seem to be any major issue here but you may want to consider fixing the code for the GCC compiler?
I have not tried it with VisStudioExpress cl.exe as I did initially on my machine! (As per my orginal post here. Also I have now more experience with various C compilers on Win7 eg cl.exe, tcc, gcc, lcc etc & various IDE eg MSVisStudioExpress/DevC++/Geany!).

Best wishes smile

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Hi Richard

I'm glad to read the good news, specially the one related to the use of geany+gcc in order to compile secondchess without problems under windows. Probably I'll add this info to the README file, and I guess I myself will use it in order to provide windows executables. Thanks for the info!

One little tip: if you want to play something different to the scandinavian, you can undo the d5 move played by black, make the move you desire. After that the engine will play white automatically, but all you have to do is just undo its move and play as white again.

I myself am not a good C programmer, and actually one of the reasons I started this little project was to refresh and improve my C skills.

Thanks for the compiler warnings. I guess most of them are due to the fact that currently secondchess is in an unstable stage, and some of the tests I do leave bad code such as unused vars.
By the way, as you're working under linux, give a try to the clang compiler. It works quite like gcc, but very often the kind of info it provides is more human friendly:
http://clang.llvm.org/diagnostics.html

I'm not sure if I provided this info on a previous post, but just in case:

This is a nice forum about chess programming:
http://talkchess.com/forum/index.php

And this is a nice wikispace about the same topic:
http://chessprogramming.wikispaces.com/

Cheers

E Diaz

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Emilio
Many thanks for your prompt & helpful reply and all your help with SecondChess.
I'm sure our Chess & C programming will progress well!
Best wishes smile

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Emilio
I have been running SecondChess in Arena GUI but I've just tried it in console mode-but the board display there is not so good. Have you noticed that?
With a minor adjustment to PrintBoard function this is fixed eg:
Presently I have this console output:-

Code:

Second Chess, by Emilio Diaz
 Help
 d: display board
 MOVE: make a move (e.g. b1c3, a7a8q, e1g1)
 on: force computer to move
 quit: exit
 sd n: set engine depth to n plies
 undo: take back last move
sc> e2e4
 +---+---+---+---+---+---+---+---+
 8 | r | n | b | q | k | b | n | r |
 +---+---+---+---+---+---+---+---+
 7 | p | p | p | p | p | p | p | p |
 +---+---+---+---+---+---+---+---+
 6 |  |  |  |  |  |  |  |  |
 +---+---+---+---+---+---+---+---+
 5 |  |  |  |  |  |  |  |  |
 +---+---+---+---+---+---+---+---+
 4 |  |  |  |  | P |  |  |  |
 +---+---+---+---+---+---+---+---+
 3 |  |  |  |  | * |  |  |  |
 +---+---+---+---+---+---+---+---+
 2 | P | P | P | P |  | P | P | P |
 +---+---+---+---+---+---+---+---+
 1 | R | N | B | Q | K | B | N | R |
 +---+---+---+---+---+---+---+---+
    a  b  c  d  e  f  g  h
Search result: move = d7d5; nodes = 0, evaluations = 4074706, moves made = 45130
41, depth = 6, score = 0.85, time = 3.26s, knps = 0.00
 +---+---+---+---+---+---+---+---+
 8 | r | n | b | q | k | b | n | r |
 +---+---+---+---+---+---+---+---+
 7 | p | p | p |  | p | p | p | p |
 +---+---+---+---+---+---+---+---+
 6 |  |  |  | * |  |  |  |  |
 +---+---+---+---+---+---+---+---+
 5 |  |  |  | p |  |  |  |  |
 +---+---+---+---+---+---+---+---+
 4 |  |  |  |  | P |  |  |  |
 +---+---+---+---+---+---+---+---+
 3 |  |  |  |  |  |  |  |  |
 +---+---+---+---+---+---+---+---+
 2 | P | P | P | P |  | P | P | P |
 +---+---+---+---+---+---+---+---+
 1 | R | N | B | Q | K | B | N | R |
 +---+---+---+---+---+---+---+---+
    a  b  c  d  e  f  g  h
CASTLE: 15
sc>





SO...on changing PrintBoard function to:-

Code:


void PrintBoard()
{
   char pieceName[] = "PNBRQKpnbrqk";
   int i;
   for (i = 0; i < 64; i++)
   {
      if ((i & 7) == 0)
      {
         printf("    +---+---+---+---+---+---+---+---+\n");
         if (i <= 56)
         {
            printf(" %2d |", 8 - (((unsigned) i) >> 3));
         }
      }
      if (piece[i] == EMPTY)
         printf("  |");
      else if (piece[i] == EPS_SQUARE)
         printf(" * |");
      else
      {
         printf(" %c |", pieceName[piece[i] + (color[i] == WHITE ? 0 : 6)]);
      }
      if ((i & 7) == 7)
         printf("\n");
   }
   printf("    +---+---+---+---+---+---+---+---+\n      a  b  c  d  e  f  g  h\n");
}




this outputs a better board at the console eg:


Code:


Second Chess, by Emilio Diaz
 Help
 d: display board
 MOVE: make a move (e.g. b1c3, a7a8q, e1g1)
 on: force computer to move
 quit: exit
 sd n: set engine depth to n plies
 undo: take back last move
sc> e2e4
    +---+---+---+---+---+---+---+---+
  8 | r | n | b | q | k | b | n | r |
    +---+---+---+---+---+---+---+---+
  7 | p | p | p | p | p | p | p | p |
    +---+---+---+---+---+---+---+---+
  6 |  |  |  |  |  |  |  |  |
    +---+---+---+---+---+---+---+---+
  5 |  |  |  |  |  |  |  |  |
    +---+---+---+---+---+---+---+---+
  4 |  |  |  |  | P |  |  |  |
    +---+---+---+---+---+---+---+---+
  3 |  |  |  |  | * |  |  |  |
    +---+---+---+---+---+---+---+---+
  2 | P | P | P | P |  | P | P | P |
    +---+---+---+---+---+---+---+---+
  1 | R | N | B | Q | K | B | N | R |
    +---+---+---+---+---+---+---+---+
      a  b  c  d  e  f  g  h
Search result: move = d7d5; nodes = 0, evaluations = 4074706, moves made = 45130
41, depth = 6, score = 0.85, time = 3.23s, knps = 0.00
    +---+---+---+---+---+---+---+---+
  8 | r | n | b | q | k | b | n | r |
    +---+---+---+---+---+---+---+---+
  7 | p | p | p |  | p | p | p | p |
    +---+---+---+---+---+---+---+---+
  6 |  |  |  | * |  |  |  |  |
    +---+---+---+---+---+---+---+---+
  5 |  |  |  | p |  |  |  |  |
    +---+---+---+---+---+---+---+---+
  4 |  |  |  |  | P |  |  |  |
    +---+---+---+---+---+---+---+---+
  3 |  |  |  |  |  |  |  |  |
    +---+---+---+---+---+---+---+---+
  2 | P | P | P | P |  | P | P | P |
    +---+---+---+---+---+---+---+---+
  1 | R | N | B | Q | K | B | N | R |
    +---+---+---+---+---+---+---+---+
      a  b  c  d  e  f  g  h
CASTLE: 15
sc>


I hope you can see the difference and do not mind me asking and showing this!?
Thanks
smile

descriptionSecondChess EmptyRe: SecondChess

more_horiz
Permissions in this forum:
You cannot reply to topics in this forum