help this guy

Discussion of chess software programming and technical issues.

Moderator: Ras

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

Re: help this guy

Post by Gerd Isenberg »

OliverUwira wrote: However, out of interest, I'd have a question about switches in general. I suck at ASM and compilers but I sort of remember from a MIPS architecture class (long ago... ) that compilers can avoid comparisons in switches by using the case values as indices to a jump table.

This surely can't be done with case values such as the above, but would that happen with GCC or MSVC if the values went from, say, 0 to 8?
Yes, indirect jump likely with leading range check. That was very fast with early x86 (386, 486, PI, PII ?) but branch prediction always takes last target afaik. Depending on the randomness of the pattern, with log2 (cardinality(range)) < 3 or 4 conditional jump chains might be better...

See also Dann Corbit's switch proposal mentioned in cpw:
https://chessprogramming.wikispaces.com ... h+Approach
User avatar
towforce
Posts: 12695
Joined: Thu Mar 09, 2006 12:57 am
Location: Birmingham UK
Full name: Graham Laight

Re: help this guy

Post by towforce »

If there is no issue with speed, then they should go for readability - in which case, it's just:

log(x) / log(2)

(if you need to rationalise this, you'd probably add 0.5 and convert to an integer)
Human chess is partly about tactics and strategy, but mostly about memory
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help with chess engine

Post by Sven »

Hi,

I took a brief look into the source code that was published here. I think that the programmer has done a good job so far - creating a program that plays correct chess is already a huge work and needs a lot of patience and precision. Congratulations to the author, and welcome to a hobby that will never release you!

In my opinion the program needs a major rework on the design level regarding these points at least:

1) separation of move generation from creation of tree nodes (as pointed out by Daniel, I see this as one of the main problems);

2) memory management: at each node some arrays of bitboards and nodes are allocated using "new" but that memory is never released, and furthermore extensive use of "new" in a chess engine is a huge performance killer.

There might be even more issues, and clearly there is also quite a lot of work to be done from the usual "check list" to turn a program that can "only" play chess according to the rules into a decent chess engine matching our current standards. But before I post that check list (I had actually prepared one but then discovered the major issues above), some redesign appears to be inevitable.

The standard way of move generation is to store all (legal or pseudo-legal) moves of the current position in a move list, where each move is represented by almost minimal information that would be needed to actually make the move on the board when required, usually "from" and "to" square, promotion piece type and possibly also other information like castling type or information to en passant captures or pawn double steps. Moves are then ordered (or assigned a value that can be used to select the next best move) before entering the move loop during search. When a move is selected next, it will be made on the board, and only then you have a new node of the search tree. Creating all successor nodes of the current node during move generation creates really a huge overhead in an alphaBeta search since alphaBeta will visit only a fraction of all nodes, so almost the whole work of creating nodes in advance (and, as in the given implementation, immediately testing it for legality) will be wasted.

It is important that this node will disappear again as soon as the move leading to it will be undone, either directly (if the move was illegal) or after returning from searching its subtree. Dynamic memory allocation is far from optimal for chess engines, but if it is used then at least the memory management must be correct. There are a couple of changes to fix this but it can be done so that the program stops eating up all memory of the PC. The key point is to call "delete[]" at an appropriate time for the two arrays that have been allocated at the end of the growConnections() function. I can help here if required, as well as with some advice for a redesign of the "move generator / search" collaboration. Just PM me.

Sven
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help with chess engine

Post by Sven »

The two comments in codeguru.com regarding thread usage are not correct in my opinion, they ignore the fact that the main thread is sleeping while waiting for console input (which is almost all the time), and the AI thread is sleeping if "aiThinking" is false, i.e. it is the opponent's turn. So for me the threads concept looks o.k. (pondering can be added at a later stage).

Sven
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: help this guy

Post by lucasart »

bob wrote:
Daniel Shawul wrote:http://www.codeguru.com/forum/showthread.php?t=520797
It could be a new addition to the list of swedish (I think) engines when finished. He probably hasn't found CCC yet from what I saw in his code. His bitToIndex function is
map<unsigned __int64, unsigned __int64> _bitToIndex, _indexToBit;
//_bitToIndex[1] = 0;

int bitToIndex(unsigned __int64* bit) {
switch (*bit) {
case 1: return 0;
case 2: return 1;
case 4: return 2;
case 8: return 3;
case 16: return 4;
case 32: return 5;
case 64: return 6;
case 128: return 7;
case 256: return 8;
case 512: return 9;
case 1024: return 10;
case 2048: return 11;
case 4096: return 12;
case 8192: return 13;
case 16384: return 14;
case 32768: return 15;
case 65536: return 16;
case 131072: return 17;
case 262144: return 18;
case 524288: return 19;
case 1048576: return 20;
case 2097152: return 21;
case 4194304: return 22;
case 8388608: return 23;
case 16777216: return 24;
case 33554432: return 25;
case 67108864: return 26;
case 134217728: return 27;
case 268435456: return 28;
case 536870912: return 29;
case 1073741824: return 30;
case 2147483648: return 31;
case 4294967296: return 32;
case 8589934592: return 33;
case 17179869184: return 34;
case 34359738368: return 35;
case 68719476736: return 36;
case 137438953472: return 37;
case 274877906944: return 38;
case 549755813888: return 39;
case 1099511627776: return 40;
case 2199023255552: return 41;
case 4398046511104: return 42;
case 8796093022208: return 43;
case 17592186044416: return 44;
case 35184372088832: return 45;
case 70368744177664: return 46;
case 140737488355328: return 47;
case 281474976710656: return 48;
case 562949953421312: return 49;
case 1125899906842624: return 50;
case 2251799813685248: return 51;
case 4503599627370496: return 52;
case 9007199254740992: return 53;
case 18014398509481984: return 54;
case 36028797018963968: return 55;
case 72057594037927936: return 56;
case 144115188075855872: return 57;
case 288230376151711744: return 58;
case 576460752303423488: return 59;
case 1152921504606846976: return 60;
case 2305843009213693952: return 61;
case 4611686018427387904: return 62;
case 9223372036854775808: return 63;
}
return -1;
}
Looks like a non-functioning BSF? unless not more than one bit is set. And about as slow a BSF as one can write to boot... 64 comparisons???

The compiler will likely do a sort of "binary search" by checking to see if the initial value is > 32 bits or not, then in each of those, test to see if it is >16 bits or > 48 bits, etc...

Ugly beyond belief when it can be replaced by a single BSF...
yes, very, VERY ugly indeed...
another abomination

Code: Select all

unsigned __int64
this is not portable and the ISO C++ standard defines uint64_t for that.
Daniel Shawul
Posts: 4186
Joined: Tue Mar 14, 2006 11:34 am
Location: Ethiopia

Re: help this guy

Post by Daniel Shawul »

yes, very, VERY ugly indeed...
another abomination

Code: Select all

unsigned __int64
this is not portable and the ISO C++ standard defines uint64_t for that.
Says the man who himself uses the same thing in his own engine :?
DoubleCheck:

Code: Select all

typedef unsigned __int64 U64;
And would you please tone it down? We are trying to attract a programmer ,not drive him away.