Computer Chess Club Archives


Search

Terms

Messages

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

Author: Sune Fischer

Date: 03:24:16 08/15/04

Go up one level in this thread


On August 15, 2004 at 01:52:31, Russell Reagan wrote:

>On August 14, 2004 at 15:10:45, Sune Fischer wrote:
>
>>Because of:
>>"3. Write abstract code that hides the implementation details when possible."
>>
>>Depends to what extent you mean that of course, but in the extreme (virtual
>>functions etc..) I'm afraid it will be dreadfully slow.
>>
>>-S.
>
>Abstraction is possible without slower features of OOP. It's possible without
>OOP at all. Let's say I'm using C, and the goal is flexibility. I would put
>everything behind a function (or macro at least), use typedefs, limit the places
>where data is modified to a few functions, and things like that.
>
>Later on if I want to change a signed type to an unsigned type to avoid a sign
>extension, I just change one typedef. If attack detection is a hot spot, I only
>need to rewrite one function, and everything else continues to work just the
>same.
>
>Here is an example of how I might abstract the board modification in C. I would
>create a few functions to modify the state of the board.
>
>void add_piece(Piece piece);
>void clear_square(Square square);
>void move_piece(Square from, Square to);

Yes that might be a bit of abstraction, but when I hear that word I'm thinking
something like

class Piece {
 virtual bitboard Attacks();
 virtual void MakeMove();
}
class Rook : public Piece {
 bitboard Attacks () { return ....}
 void MakeMove () { ....}
}

so you have type of piece indifference with
myPiecearray[sq].Attacks()

>Everything else is done in terms of those functions. Even a major change like
>switching from 0x88 to bitboards would be less intrusive because of this
>approach. My make/undo functions still work without modification.
>
>In my evaluation function I would have functions describing what I want to know.
>If I want to know if there is a possible trojan horse attack, I write a
>function: bool trojan_horse_attack_exists(); Then I just write: if
>(trojan_horse_attack_exists()) { ... }. So my evaluation function would still
>work after a major change like switching from 0x88 to bitboards.
>
>Even basic abstractions like these will go a very long way toward making
>transition much easier in the future.

I'm unsure how much development time would actually be saved if you e.g. want to
change fundamental datastructures.

The layer on top might in the best case remain unthouched, at least that would
be idea, but everything below that layer would have to be rewritten anyway.

So you might have 500 small functions need for abstraction instead of just 10
big ones without abstraction, it's still a lot of coding inside all of that.

>Obviously this approach is very class friendly. I would, for instance, make a
>board class and make add_piece(), clear_square(), and move_piece() member
>functions, and the board data would be private of course. The difference is that
>with classes the compiler will enforce that only those three functions modify
>the board.

In chess almost everything is about what's happening on the board, so private
members or not you'll need heavy access.

I'm not too fond of all that Get()/Set() myself.
Does it really make the code easier to read?

>If my bitboards are out of sync, or my piece list doesn't match my
>0x88 board, then I only have three small functions to examine. In C, I have to
>rely on my own discipline to make sure I always use the modifier functions, and
>being human, that usually doesn't work well in the long run.

The only place my boards are changed is in MakeMove and UnMakeMove, so I only
have two functions :)

>Using this approach also gives you a cascading effect when you start optimizing.
>If you speed up one function, then every function that calls that function is
>faster.

Well you should never have to write the same (large) piece of code twice anyway,
then something is wrong if it's not in a function.

>When you profile, you get a more fine grained picture of where your program is
>spending its time. Rather than thinking, "my evaluation takes up 90% of the
>execution time," you know which parts of the evaluation take up the most time.

Perhaps, or perhaps you just get a profile with 500 functions at 0.2% and a lot
of overhead.

>Programming flexibly doesn't only benefit optimization opportunites. It makes
>your code better in a number of other ways as well. It's more readable and
>easier to track down bugs and prevent bugs in the first place. It makes the
>program less mentally complex.

I agree to an extent, but only as long as it doesn't cost performance.

To know how to code good computer chess one should not just read the standard
textbooks on programming and blindly follow all their advices.
Most of what you find in them makes the implict assumption that speed of the
application is not critical.

I suggest you also read some texts on how to write high perfornamnce numerical
codes for e.g. super computers.

Now try and keep both "extremes" in mind when you write the chess engine.

-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.