John Penner wrote: > i've got a question for the chess listers out there -- because i try > to put everything > possible into local for passing between FN's -- i thought of storing > the entire game state > in some sort of STRUCT or RECORD -- but passing records seemed > complicated > to me, and i wanted to keep it simple -- so i stored the game state > in a bunch of global variables: A well chosen record definition is better than a bunch of global variables and arrays. A record, being a single object, is easy to copy and pass as a parameter to a function. The board representation is going to be copied millions of times during a search, so it should contain only what's needed to generate moves and evaluate a position; it shouldn't contain the complete game history. Below is a minimal definition. Some fields that your program will need (for fully correct play), or may want (e.g. to avoid slow searching, or slow recomputation of material balance) are commented out. If you uncomment them, those fields immediately become available to every function that takes a Board parameter. That extensibility is a big advantage of a record over multiple globals; it allows a program to grow simply, from small beginnings. '--------- begin record Board dim as byte squareContent dim as byte sideToPlay // 1 white; -1 black //dim as Boolean whiteCanCastleKSide, whiteCanCastleQSide //dim as Boolean blackCanCastleKSide, blackCanCastleQSide //dim as byte enPassantSquare //dim as byte whiteKingSquare, blackKingSquare //dim as short whiteRawMaterialScore, blackRawMaterialScore end record // feeble demo of Board variables dim as Board currentBoard, copyBoard dim as long k copyBoard = currentBoard for k = 0 to 63 // how to scan the entire board long if ( copyBoard.squareContent[k] == 0 ) // the square is empty xelse //...do something end if next '--------- Then, with another record definition to represent a move, we start to see what real chess code with these records might look like. To me it looks compact, comprehensible and fast. '--------- begin record MoveRec dim as byte fromSquare, toSquare end record local fn MakeMove( theBoard as ^Board, theMove as ^MoveRec ) '~'1 dim as byte movingPiece theBoard.sideToPlay = -theBoard.sideToPlay movingPiece = theBoard.squareContent[theMove.fromSquare] // special handling for K R and P omitted theBoard.squareContent[theMove.toSquare] = movingPiece theBoard.squareContent[theMove.fromSquare] = 0 end fn '--------- > a function called mTree() which provides to the eval function a > list of every possible move the current colour can make -- since i > dont think i can pass that whole list of possible moves as a single > variable (i.e. END FN = x%) -- i thot i was forced to return the > results of the mTree FN through yet another global variable An array parameter would allow the entire move list to be returned without recourse to a global. > so -- my problem is -- if i nest the eval() FN recursively, just how > will it deal with the states of these global variables?? It won't and can't. You will have pass the relevant state (i.e the current board) as a parameter to the recursive call. Your Evaluate function would keep its list of generated moves in a local array, and make each move on a copy of the board that was passed to it. ... dim as Board tempBoard dim as long nMoves, j dim as MoveRec moves(200) nMoves = fn GenerateAllMoves( theBoard, moves(0) ) for j = 0 to nMoves - 1 tempBoard = theBoard // copy fn MakeMove( tempBoard, moves(j) ) // Evaluate recursively... next ... You have made great progress in writing a (nearly) fully functional chess program with little reference to existing art. This may be a good time to consider Fred Brooks' famous advice on big software projects: "...plan to throw one away; you will, anyhow." I also recommend a switch to FB5, especially if you decide to rewrite your program. FB4 is obsolete. One of FB5's advantages is not being confused by non-breaking spaces in the code snippets above. FB5 does, however, enforce the discipline of declaring all local variables. Robert P.