Author: Gerd Isenberg
Date: 12:05:26 02/18/04
Go up one level in this thread
On February 18, 2004 at 05:15:15, Steven Edwards wrote:
>On February 17, 2004 at 17:01:49, Gerd Isenberg wrote:
>>On February 17, 2004 at 15:13:02, Steven Edwards wrote:
>
>>Even i'm not familar with Lisp, i like your high abstraction level
>>approach with performant chess intrinsics.
>
>Thank you.
>
>I first learned about Lisp back around 1970 from a book by Jean Sammet on
>programming languages; I was not quite a teenager at the time. I have written
>lotsa Lisp over the years plus an interpreter. And still I am sometimes
>mystitfied by others' Lisp code. Particularly if said code has tricky nested
>defmacro forms.
>
>>The bitboard intrinsics (BBAtkFrSq BBAtkToSq) imply a rotated bitboard
>>implementation, i guess. Or do you hide the bitboard implementation at all?
>>Do you consider setwise attack generation with Kogge Stone Fill algorithm?
>
>Some of the BB intrinsics are in ChessLisp solely for testing purposes; all of
>the usual low level BB code found in a BB program is hidden away in the
>underlying toolkit. ChessLisp BB intrincs like BBAtkToSq take a Position symbol
>as their first argument and pull the selected BB value by appropriately
>dereferencing the BB database structure associated with the pointer stored in
>the atom that is the value of the position symbol. The bitboard database
>associated with a position symbol that is attached to a node (via the Position
>property) is produced at the time of node creation and its values do not change.
>
>A single BB value is contained in a Lisp atom as a 64 bit integer. A ChessLisp
>BB atom is a typed value (and is not a Lisp number), so it is used with
>intrinsics like BBNot, BBAnd, BBXor, etc. The intrinsics lognot, logand,
>logxor, etc., are also present and do the same operations on 64 bit integer
>value atoms; however, they are not used for BB work. This retains the type
>safety features of ChessLisp and encourages better Lisp programming style.
>
>Example:
>
>Lisp: InitialFEN
>"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
>
>Lisp: (PosFromFEN InitialFEN)
>Pos0
>
>Lisp: (symbol-plist 'Pos0)
>(ActiveColor #<Color White> ActiveMaterial #<Score +40.160> Cstl #<Cstl KQkq>
>EnPassantSq nil EnvValStack nil Evaluation #<Score NegInf> HalfMoveClock 0
>IsCheckmate nil IsStalemate nil MainHash #<Hash 893b42c4bcfb0cbc> Material
>#<Score Even> MoveNumber 1 MoveValStack nil Ord 0 PassiveColor #<Color Black>
>PassiveMaterial #<Score +40.160> PawnHash #<Hash a782b164eeb612b3>)
Ok, a list of properties.
>
>Lisp: (BBAtkToSq 'Pos0 SqD2)
>#<BB 0111100000000000000000000000000000000000000000000000000000000000>
>
>Lisp: (SqListFromBB (BBAtkToSq 'Pos0 SqD2))
>(#<Sq b1> #<Sq c1> #<Sq d1> #<Sq e1>)
>
>Lisp: (BBAtkByColor 'Pos0 Black)
>#<BB 0000000000000000000000000000000000000000111111111111111101111110>
>
>Lisp: (SqListFromBB (BBAtkByColor 'Pos0 Black))
>(#<Sq a6> #<Sq b6> #<Sq c6> #<Sq d6> #<Sq e6> #<Sq f6> #<Sq g6> #<Sq h6> #<Sq
>a7> #<Sq b7> #<Sq c7> #<Sq d7> #<Sq e7> #<Sq f7> #<Sq g7> #<Sq h7> #<Sq b8> #<Sq
>c8> #<Sq d8> #<Sq e8> #<Sq f8> #<Sq g8>)
>
What about intrinsics that work setwise?
Eg. like
Lisp: (BBAtkByBishop 'Pos0 BBBlackBishops)
>Lisp: (SqListFromBB (BBAnd (BBAtkByColor 'Pos0 White) (BBLocByColor 'Pos0
>White)))
>(#<Sq b1> #<Sq c1> #<Sq d1> #<Sq e1> #<Sq f1> #<Sq g1> #<Sq a2> #<Sq b2> #<Sq
>c2> #<Sq d2> #<Sq e2> #<Sq f2> #<Sq g2> #<Sq h2>)
>
Lisp: BBAtkByBishop ('Pos0 BBAnd (BBAtkByBishop 'Pos0 BBBlackBishops)
( BBPor (BBAtkByPawns 'Pos0 White) (BBPieces 'Pos0 Black) ) )
A bit unusual and difficult to read for me.
How would following kogge stone fill look like in lisp?
// down attacks
// gp a set of pieces, able to move rookwise down the board
// pd set of empty squares
gd |= pd & (gd>>8);
pd &= pd>>8;
gd |= pd & (gd>>16);
pd &= pd>>16;
gd |= pd & (gd>>32);
gd>>= 8;
Ok, one may better implement a C++ intrinsic for that too...
>Lisp: (SqListFromBB (BBAnd (BBNot (BBAtkByColor 'Pos0 White)) (BBLocByColor
>'Pos0 White)))
>(#<Sq a1> #<Sq h1>)
>
>Lisp: (BBMerge 'Pos0)
>#<BB 1111111111111111000000000000000000000000000000001111111111111111>
>
>Lisp: (SqListFromBB (BBMerge 'Pos0))
>(#<Sq a1> #<Sq b1> #<Sq c1> #<Sq d1> #<Sq e1> #<Sq f1> #<Sq g1> #<Sq h1> #<Sq
>a2> #<Sq b2> #<Sq c2> #<Sq d2> #<Sq e2> #<Sq f2> #<Sq g2> #<Sq h2> #<Sq a7> #<Sq
>b7> #<Sq c7> #<Sq d7> #<Sq e7> #<Sq f7> #<Sq g7> #<Sq h7> #<Sq a8> #<Sq b8> #<Sq
>c8> #<Sq d8> #<Sq e8> #<Sq f8> #<Sq g8> #<Sq h8>)
>
>Lisp: (length (SqListFromBB (BBMerge 'Pos0)))
>32
>
>Lisp: (CardOfBB (BBMerge 'Pos0))
>32
>
>Lisp: (format nil "%c" (CardOfBB (BBMerge 'Pos0)))
>"thirty-two"
>
>>For performance reasons i use node related memory for eval and (pre-)movegen
>>purposes with limited validity until expansion, shared by all nodes. They got
>>initialized shortly after a node is entered but not restored in unmake.
>>How does your Lisp approach handles such node state related validity (if any)
>>during search?
>
>In ChessLisp, there are the Tree and Node chesstypes. A tree, and there may be
>more than one, can be made by the TreeFromFEN intrinsic function. Each tree
>symbol has a RootNode property which is the node symbol produced by genertating
>the tree. All other node symbols are manufactured by the intrinsic function
>ExpandNode which produces all the subnodes from the supplied node. No illegal
>nodes are ever gererated. The tree symbol and all the node symbols hang around
>for the entire search, at least for now. So there is currenly no need for using
>the Generate/Execute/Retract trio for either building or moving around in the
>tree.
So you have dynamic objects and garbage collecton for now.
Thanks for the lesson - quite interesting stuff.
Cheers,
Gerd
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.