Author: Russell Reagan
Date: 13:09:08 02/13/04
Go up one level in this thread
On February 13, 2004 at 15:04:31, Anthony Cozzie wrote: >However, your board structure is at the heart of everything you do - >make/unmake, eval, movegen, search, everything. You are simply not going to be >able to abstract this away without a _large_ performance hit. A point of clarification: "using classes" does not always mean "modular". Using a class to represent the chess board shouldn't need to cause any overhead at all. The main purpose of a chess board class, IMO, is to maintain the validity of the private data. Speicifically, the board should match up with the piece lists or bitboards. I am talknig about encapsulation, while I think you are talking about modularity. I confused the two for a long time, and I agree that if you try to make everything completely modular, you can take on huge performance hits. For chess, I say throw modularity out the window for the most part. Modularity is where you treat each object like a black box. The philosophy that objects shouldn't know how other objects are implemented. That's a nice idea, but it doesn't work very well in a chess program. Imagine if your chess board knew nothing about squares, pieces, colors, castling rights, moves, and so on. You could make it work, but it would be way slow with virtually no added benefit. Encapsulation on the other hand is just creating a class to act as a manager. The class makes sure things get initialized correctly, and that you as the programmer can't do nasty or stupid things easily to invalidate the private data. It's okay if you know that the board class uses bitboards internally, and even if you have member functions that return bitboards like white_pawns() or enemy_knights(int color). The point of encapsulation in that case is to make sure you can't modify the white_pawns bitboard whenever you'd like (or on accident). class board { private: public: // board gets initialized board (); // board only gets modified here void make_move(move m); void undo_move(move m); // accessor member functions const piece & operator [] (square s); // if you want bitboards... bitboard pawns (color c); bitboard knights (color c); bitboard all_pieces (); bitboard rotated90(); // ... }; All of this will get inlined so there is no overhead vs. using a struct for this, plus you can do error checking internally in a debug build if you want. This way you can still do if (board[i] == white_pawn), but you can't do if (board[i] = white_pawn). If you mistype, the compiler will complain about you modifying a const variable and your data will still be valid (piece lists will match up with the board). If you just use an array for the board, you just invalidated the board because now board[i] has a white_pawn on it, but there no white_pawn in the piece list for square i.
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.