Author: Michael J Sherwin
Date: 11:02:36 02/16/06
Go up one level in this thread
On February 15, 2006 at 16:13:31, David B Weller wrote: >I am fascinated by the incredible speed you attained > >And carnivor seemed to work ok in arena ... [your readme mentioned crashing] > >But there are so many fascinating avenues out here in cyberspace!! > >I was looking at your movegen in carnivor and I couldnt figure out how you were >stepping along lines and diagonals ?? I didnt even see the loop/while/fornext?? > >Of course, 10 minutes is hardly enough time to digest such things ... Hi David, Here is a brief explanation as to how carnivor's move generator works. First of all let me say that carnivor is a very crude program and represents my very first attempt to write a chess program. I barely even knew how to program when I started it. It is similar to the way that GNU Chess 4.0 does it. Only faster. My data structures are a bit compressed, because, at the time of writing, my computer only had 4mb memory and I wanted to save a little space. I will decribe the method as it would be with out compression, just for simplicity. Every piece has for every square that it can be on two board arrays. One of the arrays is called 'next square' the other 'next direction'. A simple lookup of 'next square'[fs] returns the first ts. Using the ts in the next lookup gives you the next ts. This proceedes untill a 64 is returned as there is no 64th square (0 to 63). If in the meantime a blocking piece is encountered, then the ts is used to access the first square of the next direction as in 'next direction'[ts]. If the enemy king is encountered the mg returns FALSE. There is no inCheck function in Carnivor. for(id=piece[0].nxt;id<39;id=piece[id].nxt) // piece[id].nxt gives the next piece pseudo or real. { // castle king side is a pseduo piece. fs=piece[id].ps; // I use piece indexs on the board, not piece types. switch(piece[id].pt) // piece[index].pt gives the type of piece. { case BISHOP: sbns=bns+bol[fs]; // sbns is set to the first square of 'next square' sbnd=bnd+bol[fs]; // sbnd is set to the first square of 'next direction' ts=*(sbns+fs); // get first ts while(ts<64) // today I would use a do loop instead { switch(wtrgt[brd[ts]]) // get the target { case VACANT: link(MOVE); ts=*(sbns+ts); // get the next ts from 'next square' continue; case FRIEND: ts=*(sbnd+ts); // get the next ts from 'next direction' continue; case ENEMY: link(CAPTURE); ts=*(sbnd+ts); // get the next ts from 'next direction' continue; default: return FALSE; // last move was illegal, left king in check } } continue; case ROOK: I hope this helps. The method is old, but, occasionally something old can be made new again. Bruce Morland has some ideas about how to enhance this method on his web site. Have you looked at Conundrum yet. If you want to understand this one you will have to empty your mind of all preconcieved ideas first. Amy is the closest thing to it, although, Amy is bitboard and Conundrum is something else. There is a hidden gem in Conundrum and later sources including Romi and that is another move generation system that will absolutly fly (I believe) and is worth concidering to use as a stand alone method. It is based on vector and magnitude lookup tables. Best wishes, Mike
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.