Beginning to Program...

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Suji

Beginning to Program...

Post by Suji »

I'm relatively new to the computer chess programming, but I've researched it quite a bit. I've liked chess for years, but never into the programming side of it until recently.

I'm trying to program an engine (named Pebble), but I've found that programming chess is a lot harder than it looks. I don't think it helps much that I'm still a beginner at programming, either.

I want to at least make an engine that can beat me. That's my whole goal with computer chess. I think once I understand most of the intricacies, I won't feel so overwhelmed then.

I'm having trouble with the board representation. I am planning to implement the 0x88 method since I think that bitboards are stupid (I don't understand them at all.). Obviously, though, the top programs use bitboards and I can see why. It's a slick implementation that makes the program run smoother. I think I might implement these later once I understand them.

Here is the code I have so far. I am using C++, since I'm learning it right now, and even though it's a speed drain I am going to be using Object Oriented Programming.

Code: Select all

class Board
{
	private:
		int board[128];  //Will keep track of the state of the board
		int fifty_move_rule;  //Keeps track of the fifty move rule
		int total_moves;	 //Keeps track of the total number of moves
		int sidetomove;  //Keeps track of the side to move

		struct pieces
		{
			static const int whitepawn = 1;
			static const int whiteknight = 2;
			static const int whitebishop = 3;
			static const int whiterook = 4;
			static const int whitequeen = 5;
			static const int whiteking = 6;
			static const int blackpawn = -1;
			static const int blackknight = -2;
			static const int blackbishop = -3;
			static const int blackrook = -4;
			static const int blackqueen = -5;
			static const int blackking = -6;
		};

	public:
		Board();
		int switchside(int sidetomove);

		//makemove();  Don't know the return types
		//unmakemove();
};
Am I going about this in the right way?

Any comments or suggestions would be greatly appreciated. Thanks in advance.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: Beginning to Program...

Post by sje »

Before you go any further, you should learn about enumeration types.

Example:

Code: Select all

// Chess colors

typedef enum
{
  CTColorNil = -1,
  CTColorWhite,
  CTColorBlack,
  CTColorVacant,
  CTColorExtra
} CTColor;

#define CTColorLen   (CTColorExtra + 1)
#define CTColorRCLen (CTColorBlack + 1)
Also:

Code: Select all

// Chess pieces

typedef enum
{
  CTPieceNil = -1,
  CTPiecePawn,
  CTPieceKnight,
  CTPieceBishop,
  CTPieceRook,
  CTPieceQueen,
  CTPieceKing,
  CTPieceVacant,
  CTPieceExtra
} CTPiece;

#define CTPieceLen   (CTPieceExtra + 1)
#define CTPieceRCLen (CTPieceKing + 1)
And:

Code: Select all

// Chess man

typedef enum
{
  CTManNil = -1,
  CTManWhitePawn,
  CTManWhiteKnight,
  CTManWhiteBishop,
  CTManWhiteRook,
  CTManWhiteQueen,
  CTManWhiteKing,
  CTManBlackPawn,
  CTManBlackKnight,
  CTManBlackBishop,
  CTManBlackRook,
  CTManBlackQueen,
  CTManBlackKing,
  CTManVacant,
  CTManExtra
} CTMan;

#define CTManLen   (CTManExtra + 1)
#define CTManRCLen (CTManBlackKing + 1)
User avatar
hgm
Posts: 27836
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Beginning to Program...

Post by hgm »

I always found it very awkward to encode black pieces as the negative of their white counterpart. It means yourcode has to tak absolute values quite often, and there is no elementary instruction for that. So it likely involves code wth lots of (mispredicted) branches.

So I always use representations where the color can be read from the piece by looking at a single bit. Like BackPiece = WhitePiece+8. Then you can still easily test if a piece is hite or black through "if(piece&8)" in stead of "if(piece<0)" in your current system. But you can also easily extract the piece type through an AND operation stripping off the color bit, for which there exists a single instruction, and no branches are needed: "pieceType = piece&7;". This makes it much easier to write color-independent code.
User avatar
cms271828
Posts: 316
Joined: Wed Apr 12, 2006 10:47 pm

Re: Beginning to Program...

Post by cms271828 »

Bitboards aren't as hard as they look, they can't be if I use them.
I'm also a beginner, and I had the same goal, to build a program that could beat me,
and now I've never actually beaten it since I put in transposition table, QS, and a little move ordering, and a more complex eval.

I still have a long way to go before I get a much stronger program.

Bitboards are fun, you just need to know binary, and & | ^ operations, and how this translates to moves.

Theres 2 basic move generation techniques with them, rotated bitboards, and magic move generation, and some other ones I don't know.

These take a bit more to time to figure out.
Colin
mathmoi
Posts: 289
Joined: Mon Mar 13, 2006 5:23 pm
Location: Québec

Re: Beginning to Program...

Post by mathmoi »

Suji wrote:Here is the code I have so far. I am using C++, since I'm learning it right now, and even though it's a speed drain I am going to be using Object Oriented Programming.
Hi,

If you code carefully C++ code is no less efficient than C code. There is only a couple of OOP concept that you should avoid (inheritance with virtual function is the only that came to mind now, maybe there is other). Short of that C++ code can be at least as fast as the equivalent C code.
Harald
Posts: 318
Joined: Thu Mar 09, 2006 1:07 am

Re: Beginning to Program...

Post by Harald »

Suji wrote:I'm relatively new to the computer chess programming, but I've researched it quite a bit. I've liked chess for years, but never into the programming side of it until recently.

I'm trying to program an engine (named Pebble), but I've found that programming chess is a lot harder than it looks. I don't think it helps much that I'm still a beginner at programming, either.

I want to at least make an engine that can beat me. That's my whole goal with computer chess. I think once I understand most of the intricacies, I won't feel so overwhelmed then.

I'm having trouble with the board representation. I am planning to implement the 0x88 method since I think that bitboards are stupid (I don't understand them at all.). Obviously, though, the top programs use bitboards and I can see why. It's a slick implementation that makes the program run smoother. I think I might implement these later once I understand them.

Here is the code I have so far. I am using C++, since I'm learning it right now, and even though it's a speed drain I am going to be using Object Oriented Programming.

Code: Select all

class Board
&#123;
	private&#58;
		int board&#91;128&#93;;  //Will keep track of the state of the board
		int fifty_move_rule;  //Keeps track of the fifty move rule
		int total_moves;	 //Keeps track of the total number of moves
		int sidetomove;  //Keeps track of the side to move

		struct pieces
		&#123;
			static const int whitepawn = 1;
			static const int whiteknight = 2;
			static const int whitebishop = 3;
			static const int whiterook = 4;
			static const int whitequeen = 5;
			static const int whiteking = 6;
			static const int blackpawn = -1;
			static const int blackknight = -2;
			static const int blackbishop = -3;
			static const int blackrook = -4;
			static const int blackqueen = -5;
			static const int blackking = -6;
		&#125;;

	public&#58;
		Board&#40;);
		int switchside&#40;int sidetomove&#41;;

		//makemove&#40;);  Don't know the return types
		//unmakemove&#40;);
&#125;;
Am I going about this in the right way?

Any comments or suggestions would be greatly appreciated. Thanks in advance.
I think an en_passant square is missing and the castling flags.
With this you have basically all the information that is needed to describe
a board or chess position. But that is not enough. You have many choices
before you and you have to make many decisions. Let me write down a few:

- Is the fast int the best type or the small (unsigned) char?
- Others mentioned the piece numbers.
- How do you save the castling rights? Bits in an int or a struct of variables?
- It is very conveniant to have the positions of the two kings in additional variables.
This means a little bit more effort at make/undo move but helps
everywhere else. There are many more decisions like this.
- Perhaps you can gain from additional piece lists. (piece -> some lists -> squares)
- Even if you want to avoid bitboards for each piece type it may be a good
idea to have a bitboard for all occupied squares.
- Is the in_check flag part of the board or a local variable in the search?
- Don't use too many classes and member functions. Find a good class structure. (I think I did this wrong.)
- ...

And then the design of moves and move lists has as many possibilities.

Good luck!

Harald
Gerd Isenberg
Posts: 2250
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Beginning to Program...

Post by Gerd Isenberg »

Additionally to what others said about the negative piece codes, you'll earlier or later index tables by pieces and piece types, e.g. piece square tables. Thus, keeping positive codes for black and white pieces in the 0..15 range for all pieces (bit 3 == black) and 0..7 (bit 0..2) for piece types (or white pieces) is quite convenient, without considering an offset. You'll get the color of a piece by >> 3 and piece type by & 7 rather than abs.

Also, that was a proposal of HG, it makes sense to keep white and black pawns as distinct piece types, not only distinct pieces. Of course white will never have "black moving pawns", and black will not have "white moving pawns", but the small redundancy will pay off, since the piece type (without color) specifies all movements.

See Pieces inside the cpw as well.
mathmoi
Posts: 289
Joined: Mon Mar 13, 2006 5:23 pm
Location: Québec

Re: Beginning to Program...

Post by mathmoi »

Gerd Isenberg wrote:Additionally to what others said about the negative piece codes, you'll earlier or later index tables by pieces and piece types, e.g. piece square tables. Thus, keeping positive codes for black and white pieces in the 0..15 range for all pieces (bit 3 == black) and 0..7 (bit 0..2) for piece types (or white pieces) is quite convenient, without considering an offset. You'll get the color of a piece by >> 3 and piece type by & 7 rather than abs.

Also, that was a proposal of HG, it makes sense to keep white and black pawns as distinct piece types, not only distinct pieces. Of course white will never have "black moving pawns", and black will not have "white moving pawns", but the small redundancy will pay off, since the piece type (without color) specifies all movements.

See Pieces inside the cpw as well.
Hi,

On the CPW the values for the pieces types ranges from 1 to 7. I do use differents values in the range 0..14 (white are even, black are odds) that while they have unused values have some other benefits.

Code: Select all

   static const int AUCUNE_PIECE = 0;
   static const int PION = 2;
   static const int CAVALIER = 4;
   static const int FOU = 10;
   static const int TOUR = 12;
   static const int REINE =14;
   static const int ROI = 6;
With theses values, if you want to know if a piece can move like a rook you can simply do this :

Code: Select all

if &#40;piece & 4&#41;
   // do something
This work because only rook and queens have their second bit setted.

There is some other operations that are interesting :

Code: Select all

// Switch color
piece ^= 1;

// get color
color = piece & 1;

// get piece type
type = piece & ~1;

// Can the piece slide?
slider = piece & 8;

// move like a bishop?
move = piece & 2;

// move like a rook?
move = piece & 4;
Gerd Isenberg
Posts: 2250
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Beginning to Program...

Post by Gerd Isenberg »

This is nice as well beside I prefer enums as Steven. I would also hide the bit semantics with inlines.
mathmoi
Posts: 289
Joined: Mon Mar 13, 2006 5:23 pm
Location: Québec

Re: Beginning to Program...

Post by mathmoi »

Gerd Isenberg wrote:This is nice as well beside I prefer enums as Steven. I would also hide the bit semantics with inlines.
Hi Gerd,

In my program the sementics is hidden in a class indeed. I prefer enums too, however I had problem casting between an enum type and my CPiece class type.