I like the console output of your program, it is very clean. Reading your site, i've seen that you switched from classes to native dta structure. I've verified that this is not an optimization (for my engine) because there are no overhead at assembly level. Even some kind of indirection is not bad thing. I don't know C# but i hope that you avoid managed allocation and use pre-allocated structures/classes only.
My Satana engine is about as your program, from an ELO point of view but i use a different approach to move generation.
MadChess 2.0 Development
Moderators: hgm, Rebel, chrisw
-
- Posts: 859
- Joined: Mon Aug 10, 2009 10:05 pm
- Location: Italy
- Full name: Stefano Gemma
-
- Posts: 434
- Joined: Thu Apr 26, 2012 1:51 am
- Location: Oak Park, IL, USA
- Full name: Erik Madsen
Re: MadChess 2.0 Development
Thanks. I intend to embed a lot of Debug.Asserts in my code, and add a lot of test commands to ensure everything is working as expected.I like the console output of your program, it is very clean.
Madchess 1.x did allocate and garbage collect objects during search. I wrote it in the spirit of a business application, with object oriented constructs and little concern for memory management.I don't know C# but i hope that you avoid managed allocation and use pre-allocated structures/classes only.
I'll download your engine and check it out.My Satana engine is about as your program, from an ELO point of view but i use a different approach to move generation.
My C# chess engine: https://www.madchess.net
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: MadChess 2.0 Development
I dont think performance hit has anything to do with OOP. The same C code can be written with classes in C++ with no performance penalty (except a few edge cases), and vice versa. I dont see any reason why it would be differnt in C#.
The slowness is inherent to managed languages that are not compiled into machine code, and repy on garbage collectror. The performance cost of C# can be reduced to a factor 2 compared to C++, as shown by portfish, but at the cost of a lot of work and not doing things the C# way but the C way (preallocated arrays or manually allocated and deallocated etc.)
However the religious belief that every piece of code should belong to an object (whatever that means), which is typical of Java programmers, leads to bad design decision, which may result inmessy, unmaintainable, and slow code.
Sometimes OOP is nice and natural. Sometimes not. Bjarn Stroustrup keeps repeating in his talk that he's fed up of people trying to fit class hierarchies where they dont belong (eg. Java programmers who use classes instead of namespaces).
For example:
- it makes sense to make the board a class. It can have several instances (it has to for SMP). It can be constructed from a fen, or another board. It may have to allocate some memory, depending on how you manage the game stack, that should be freed in the destructor.
- It makes no sense at all to define a piece or a square as a class. This inevitably leads to complicated and inefficient code. This is where the OOP brainwashed people go wrong.
The slowness is inherent to managed languages that are not compiled into machine code, and repy on garbage collectror. The performance cost of C# can be reduced to a factor 2 compared to C++, as shown by portfish, but at the cost of a lot of work and not doing things the C# way but the C way (preallocated arrays or manually allocated and deallocated etc.)
However the religious belief that every piece of code should belong to an object (whatever that means), which is typical of Java programmers, leads to bad design decision, which may result inmessy, unmaintainable, and slow code.
Sometimes OOP is nice and natural. Sometimes not. Bjarn Stroustrup keeps repeating in his talk that he's fed up of people trying to fit class hierarchies where they dont belong (eg. Java programmers who use classes instead of namespaces).
For example:
- it makes sense to make the board a class. It can have several instances (it has to for SMP). It can be constructed from a fen, or another board. It may have to allocate some memory, depending on how you manage the game stack, that should be freed in the destructor.
- It makes no sense at all to define a piece or a square as a class. This inevitably leads to complicated and inefficient code. This is where the OOP brainwashed people go wrong.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
- Posts: 859
- Joined: Mon Aug 10, 2009 10:05 pm
- Location: Italy
- Full name: Stefano Gemma
Re: MadChess 2.0 Development
Ops... in Satana i have a piece class. The first version of the program have engine, board, piece, move classes. In the last release, i've simplified the move class (now it is less more than a structure and doesn't have a function Execute on it) and merged board class into engine class but still i have the piece class. In my test i've seen that having a switch on the piece type, to choose the right MakeMoves, have the same speed as using virtual MakeMove funtions on the piece class.lucasart wrote:[...]
- It makes no sense at all to define a piece or a square as a class. This inevitably leads to complicated and inefficient code. This is where the OOP brainwashed people go wrong.
For the rest, you're right when you say that OOP and performance are not related but wich class structure to choose is one of the programmer's choices and anything could have sense, if it helps the programmer itself.
-
- Posts: 892
- Joined: Sun Nov 19, 2006 9:16 pm
- Location: Russia
Re: MadChess 2.0 Development
Declaring Square as a class allows you to write things like this with no overhead.
Code: Select all
attack[Knight][sq] =
sq(-2, -1) + sq(-2, +1) + sq(-1, -2) + sq(-1, +2)
+ sq(+2, +1) + sq(+2, -1) + sq(+1, +2) + sq(+1, -2);
-
- Posts: 7220
- Joined: Mon May 27, 2013 10:31 am
Re: MadChess 2.0 Development
I also don't understand how one can maintain lists for black pawns, white bishops, etcetera if you don't have a class or structure to represent a piece.
If you don't have these lists you have to iterate over their bitmap. I think that is slower than iterating over a list.
If you don't have these lists you have to iterate over their bitmap. I think that is slower than iterating over a list.
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: MadChess 2.0 Development
You dont need a square class to write that. What you're writing in artificially complicated way,, is that sq(x,y) is a function taking a rank and a file and returning a bitboard.Aleks Peshkov wrote:Declaring Square as a class allows you to write things like this with no overhead.Code: Select all
attack[Knight][sq] = sq(-2, -1) + sq(-2, +1) + sq(-1, -2) + sq(-1, +2) + sq(+2, +1) + sq(+2, -1) + sq(+1, +2) + sq(+1, -2);
A move class can make sense though.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: MadChess 2.0 Development
ok, you save a bit of typing here (using a square offset ctor), but this code is written only once for bitboard initialization. How much extra typing to define all the OOP bureaucracy that allows your fancy code (ctor, offset ctor, bitboard cast, operators etc.) ?lucasart wrote:You dont need a square class to write that. What you're writing in artificially complicated way,, is that sq(x,y) is a function taking a rank and a file and returning a bitboard.Aleks Peshkov wrote:Declaring Square as a class allows you to write things like this with no overhead.Code: Select all
attack[Knight][sq] = sq(-2, -1) + sq(-2, +1) + sq(-1, -2) + sq(-1, +2) + sq(+2, +1) + sq(+2, -1) + sq(+1, +2) + sq(+1, -2);
A move class can make sense though.
So you have a square class. What do you do with it. Is the board going to contain an array of squares now? And how do you represent the fact that a given piece of a given color is on a square? How much OOP bureaucracy do you add to play/undo moves, when you square/piece classes? That was my point.. It's about the bigger picture, syntactic details are unimportant. piec3/square classes = wrong design. wrong design typically results in complicated and possibly inefficient code.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
- Posts: 7220
- Joined: Mon May 27, 2013 10:31 am
Re: MadChess 2.0 Development
My question is if you don't have a piece class where do you store the location of your pieces ?lucasart wrote:ok, you save a bit of typing here (using a square offset ctor), but this code is written only once for bitboard initialization. How much extra typing to define all the OOP bureaucracy that allows your fancy code (ctor, offset ctor, bitboard cast, operators etc.) ?lucasart wrote:You dont need a square class to write that. What you're writing in artificially complicated way,, is that sq(x,y) is a function taking a rank and a file and returning a bitboard.Aleks Peshkov wrote:Declaring Square as a class allows you to write things like this with no overhead.Code: Select all
attack[Knight][sq] = sq(-2, -1) + sq(-2, +1) + sq(-1, -2) + sq(-1, +2) + sq(+2, +1) + sq(+2, -1) + sq(+1, +2) + sq(+1, -2);
A move class can make sense though.
So you have a square class. What do you do with it. Is the board going to contain an array of squares now? And how do you represent the fact that a given piece of a given color is on a square? How much OOP bureaucracy do you add to play/undo moves, when you square/piece classes? That was my point.. It's about the bigger picture, syntactic details are unimportant. piec3/square classes = wrong design. wrong design typically results in complicated and possibly inefficient code.
Perhaps it might be beneficial to take a slightly slower evaluation for granted just to speed up do/undo move.
[By the way is it important to rewrite your program to improve speed with a factor of two. What is 70 ELO if you are at least 1000 ELO behind ]
-
- Posts: 2929
- Joined: Sat Jan 22, 2011 12:42 am
- Location: NL
Re: MadChess 2.0 Development
Huh?Henk wrote: My question is if you don't have a piece class where do you store the location of your pieces ?
In the data-structure that represents the board state, where else?
Piece-id's and square-id's are effectively just indices referencing data tables.
Depends on the individual case (you call make/unmake at least as often as eval, possibly more often), but typically the cost of make/unmake is insignificant compared to the cost of evaluation.Perhaps it might be beneficial to take a slightly slower evaluation for granted just to speed up do/undo move.
You just answered your own question.[By the way is it important to rewrite your program to improve speed with a factor of two. What is 70 ELO if you are at least 1000 ELO behind ]
However, both are irrelevant if you have search bugs that need fixing first.