Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: c,c++5,c#.

Author: Sune Fischer

Date: 00:16:19 08/16/04

Go up one level in this thread


On August 16, 2004 at 00:04:08, Russell Reagan wrote:

>>I think that your access functions can still be called from anywhere to do
>>something which would corrupt, so it's not really a guarantee.
>
>That isn't the main reason I use a class for this. There are two main goals. One
>is to establish and maintain an invariant. The other is to make that class as
>minimal as possible to protect encapsulation. I'll give you links to the
>articles that led me to adopt this approach.
>
>http://www.artima.com/intv/goldilocks.html
>This one is an interview with Bjarne Stroustrup. He talks about using a class as
>a means to establish and maintain an invariant, and minimizing member functions
>to increase the level of encapsulation.

I'd like to see Bjarne write an open source chess program :)

>Example 1: I may accidentally call add_piece() somewhere in the program, but the
>board remains valid. I'd rather the board remain valid and play an inferior move
>(or even an illegal move) than just crash.

I would not, actually. If there is a bug it's about finding it as soon as
possible. A crash will tell you instantly if something is wrong :)
Unfortunately not all bugs cause crashes.

>I'm also much less likely to
>accidentally call a function like add_piece() than I am to make a typo like: if
>(board[sq] = empty) { ... }

Agreed, so you use something like sq.IsEmpty()?
I wonder how much of such abuse a compiler can handle :)

>Example 2: If I need to find out if my king is in check, I'd make that a
>non-member function. I provide efficient access to my board's data and write a
>non-member function. My data is never at risk.

I think this would be very inefficient, I do checks incrementally.
I figured since you need to know at every node anyway for move generation, there
 is a good reason to do it incrementally.

>You mentioned making board a const when passing it to a non-member function.
>That is true, and it minimizes my advantage quite a bit, but I can also do that
>in addition to my approach, and I have some extra safety nets while you have to
>always remember to make it const. I will always prefer to rely on the compiler
>and put it out of my mind than to always remind myself, "Don't forget to make it
>const..."

What I meant was making the member function const, like this

int Board::Eval(...) const;

The advantage is that you still have full access to all variables, as opposed to
a non-member that will have to uses accessers.

I find that it's too much trouble to write e.g.

int OtherClass::Eval(Board * B) {
  if (B->GetWhiteRooks() & ....)
}

it really does not improve readability, IMO, it only clutters the code.
Of course you could replace that call with macros, but I think we both would
dislike that solution.

Now compare the above with

int Board::Eval(...) const {
  if (white_rooks & ...)
}

Not even a member selection operator needed! :)

It's my personal preference that the latter is more readable and that
readability in this case outweighs the tiny risk it may involve.

>>Wow, over 50? You have more experience than me then :)
>
>Let's just say that I probably have more experience at writing perft calculators
>that don't work correctly all of the time :) This new approach I've taken is
>working much better than my many previous failed attempts. Pretty much every one
>of these failed attempts was due to premature optimization. It really is as
>deadly as they say...

I'd suggest that you should rather focus on getting good move ordering than a
speedy generation, generation won't be a bottleneck anyway.

-S.



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.