' Chess Note Taker ' This program accepts chess moves by mouse input from a graphical ' display. Any position can be stored by a mouse click, and moves ' can then still be entered in from the current position. Another ' mouse click will restore the saved position. ' ' version 2 - took out some of user error checking because it was ' causing errors. User can now keep entering same color moves. ' Fixed problems in castling. I miscalculated the x and y ' coordinates in the previous version. ' Fixed game load and save exit feature - wasn't saving line ' and node numbers correctly before. This was the biggest ' headache in writing this program; keeping line and node numbers ' correct after event changes and/or interrupts. ' ' version 3 - Bug fix in menu routine that effected subsequent execution ' once it was hit. LatestBoard(81) wasn't being set right when ' lines were being changed down. ' ' version 4 - Shrink width of files from 80 pixels to 60 pixels ' yielding 160 pixels on the right side for the menu ' so the user can make menu selections without flipping ' between the menu and the board ' ' version 5 - text notes can now be brought up with a click of the right ' mouse button. CTRL-U scrolls up, CTRL-D down. ' Up and down arrow keys are for moving text cursor. ' To backup text cursor use the BS key. ' To print a space use the space bar (nothing fancy). ' Can accept up to 1600 characters per note session but since ' notes are kept in random access files they know no bound in ' size (except because of the way I defined them, a 576K limit). ' ^Q quits. New routine called textnotes (descriptive name). ' ' version 5.2 - bug fix. promotion screen wasn't working right due to change ' in size of chess board (version 4). Also got rid of already ' array (castling problems). ' ' version 6 - Legal Move Generator. Legal move list is generated after ' each legal move is made. The next move made is searched ' for in the MoveList% - if it's found then the program continues ' as normal, otherwise the move is retracted by a call to ' gameflow (direction$ = "T") and then all legal moves(to squares) ' for the current piece are lit up for 3 seconds. ' ' version 6.1 - Bug fix for setting color to move when changing line numbers. ' 6.2 - EP bug fix. Pawns captured EP when they shouldn't be. ' 6.3 - EP capture no longer working because of last bug fix. ' This is a bug fix for the bug in the last bug fix. ' 6.4 - ditto ' 6.6 - After changing lines to an empty line and then forwarding ' up the line - an error occured; fixed. ' Added two routines: clean2tailptr - after deleteing a move ' this routine releases all the memory aftr this node to the ' end of the current line (linked list). ' cleanchildren - after deleteing a move this routine releases ' all child lines to the current mode (as the root node). ' Had the castling moves in an IF ELSEIF structure; changed to ' two consecutive if statements (it was really puzzling me for ' awhile that my program wouldn't accept castling in a book ' variation I was going through - Scotch). '$DYNAMIC '$INCLUDE: 'C:\QB45\QB.BI' ' ' Declarations ' user defined type - node, move information (uses 18 bytes) TYPE nodetype nodenumber AS INTEGER linenumber AS INTEGER fromsqr AS INTEGER tosqr AS INTEGER material AS STRING * 2 ' material captured Special AS STRING * 2 ' signifies double moves ptr AS INTEGER ' pointer to next move prev AS INTEGER ' pointer to previous move END TYPE DIM SHARED node AS nodetype ' TYPE firstmove ' first move information stored here moved AS INTEGER nodenumber AS INTEGER linenumber AS INTEGER END TYPE ' ' Sub Routine and Function Declarations DECLARE FUNCTION isitillegal% (from%, tosqr%) ' determines if move is illegal DECLARE FUNCTION traverse% (nodenumber%, linenumber%) ' traverse list DECLARE FUNCTION malloc% () ' memory allocation routine DECLARE FUNCTION Bin2BinStr$ (b%) ' convert decimal integer to binary string DECLARE FUNCTION BinStr2Bin% (b$) ' convert binary string to decimal integer DECLARE FUNCTION gethigh% (b$) ' get high level bits from binary string DECLARE FUNCTION cgamonitor% () ' finds out what kind of monitor we have DECLARE SUB clean2tailptr (pres%) ' release memory to end of list DECLARE SUB cleanchildren (pres%) ' release all child lines to a root node DECLARE SUB BMoves (i%) ' get legal bishop moves in node DECLARE SUB NMoves (i%) ' get legal knight moves in node DECLARE SUB RMoves (i%) ' get legal rook moves in node DECLARE SUB BPMoves (i%) ' get legal black pawn moves in node DECLARE SUB WKMoves (i%) ' get legal white king moves in node DECLARE SUB BKMoves (i%) ' get legal black king moves in node DECLARE SUB QMoves (i%) ' get legal queen moves in node DECLARE SUB KMoves (i%) ' get legal king moves in node DECLARE SUB WPMoves (i%) ' get legal white pawn moves ' ah% = 6 for scroll up, ah% = 7 for scroll down DECLARE SUB scrolltxt (ah%, lines%, colors%, ULR%, ULC%, LRR%, LRC%) DECLARE SUB crsrpos (putback%) ' 0 saves crsr position, -1 restores DECLARE SUB textnotes () ' added with v.5, takes text notes DECLARE SUB printmenu () ' print menu on right side of board DECLARE SUB help () ' help - just like it says DECLARE SUB TextMsg (msg$) ' routine to display text message ' while in graphics mode DECLARE SUB RefreshBoard () ' has funny effect on sqr 81 DECLARE SUB linenumbers () ' display linenumber information DECLARE SUB Promotion (piece$) ' promote pawn to piece DECLARE SUB Special () 'for declaring special moves; e.g., EP DECLARE SUB Loadheadarray () ' for holding head positions DECLARE SUB pause (n&) ' pause program for n seconds DECLARE SUB gameflow (direction$) ' Forwards, Backwards, Delete to end DECLARE SUB GOTOEOL () ' Go To End Of Line, keeps calling ' gameflow("F") until ptr = MAXMOVES DECLARE SUB SaveGame () ' a menu choice DECLARE SUB LoadGame (New%) ' ditto DECLARE SUB DisplayTree () ' ditto DECLARE SUB listinitialize () ' initialize linked list DECLARE SUB delete () ' delete a node DECLARE SUB insertafter () ' insert a node DECLARE SUB updatemovetree (fromsqr%, tosqr%) ' load data into node record DECLARE SUB RORax (n%) ' shift and rotate ax register n bits DECLARE SUB Move (oldx%, oldy%, newx%, newy%, piece$, capture%) DECLARE SUB menu () DECLARE SUB GetBQueen (x%, y%) ' get black queen graphics DECLARE SUB GetWQueen (x%, y%) ' get white queen graphics DECLARE SUB GetBRook (x%, y%) ' get black rook graphics DECLARE SUB GetWRook (x%, y%) ' get white rook graphics DECLARE SUB GetBBishop (x%, y%) ' get black bishop graphics DECLARE SUB GetWBishop (x%, y%) ' get white bishop graphics DECLARE SUB GetBKing (x%, y%) ' get black king graphics DECLARE SUB GetWKing (x%, y%) ' get white king graphics DECLARE SUB GetBKnight (x%, y%) ' get black knight graphics DECLARE SUB GetWKnight (x%, y%) ' get white knight graphics DECLARE SUB GetBPawn (x%, y%) ' get black pawn graphics DECLARE SUB GetWPawn (x%, y%) ' get white pawn graphics DECLARE SUB GetKings () ' put kings on board DECLARE SUB GetQueens () ' put queens on board DECLARE SUB GetBishops () ' put bishops on board DECLARE SUB GetKnights () ' put knights on board DECLARE SUB GetRooks () ' put rooks on board DECLARE SUB GetPawns () ' put pawns on board DECLARE SUB GetBoard () ' put board on screen DECLARE SUB putx (tosqr%) ' hilight to square DECLARE SUB Initboard () ' sub routine to set up initial position DECLARE SUB Mouseinput () ' the main subroutine - gets user input and ' decides what to do with it DECLARE SUB legalmoves (force$) ' get list of legal moves in a particular node ' and place results in the array moveslist DECLARE SUB lightupsqrs (sqrs%) ' light up to squares from ,from sqrs ' ' Global Variables COMMON SHARED testing% ' any non zero CL - argument displays the debug menu COMMON SHARED whitemove% COMMON SHARED gamename$ COMMON SHARED illegalfunctioncall% COMMON SHARED finished% ' boolean variable, Finished% = TRUE% ends game COMMON SHARED another% ' flag to see if user wants another game COMMON SHARED Initing% ' flag to let routines know if this is a set ' up call or a regular game call COMMON SHARED linenumber% ' present linenumber COMMON SHARED linechange% ' boolean variable COMMON SHARED curindex% ' current position in buffer COMMON SHARED highestline% ' highest line analysed so far COMMON SHARED error53% ' error flag COMMON SHARED error64% ' error flag COMMON SHARED error75% ' error flag COMMON SHARED error76% ' error flag COMMON SHARED error68% ' error flag CONST FALSE% = 0 ' boolean false CONST TRUE% = NOT FALSE% ' boolean true CONST MAXMOVES = 1000 ' number of nodes allowed DIM SHARED mallocbuf(0 TO MAXMOVES) AS nodetype ' memory allocation buffer for building ' linked lists - using C like functions ' written in BASIC - my idea DIM SHARED MoveList%(11 TO 89, 1 TO 28) ' legal moves in current node DIM SHARED InRegs AS RegType ' define register types for use with DIM SHARED OutRegs AS RegType ' interrupts DIM SHARED board(1 TO 4045) AS LONG DIM SHARED CurrBoard(0 TO 99) AS STRING * 2 ' Current Board in move tree DIM SHARED LatestBoard(0 TO 99) AS STRING * 2 ' board showing on screen DIM SHARED headboard(0 TO 99, 11 TO 91) AS STRING * 2 'holds position before new head DIM SHARED material AS STRING * 2 DIM SHARED linenumberarray(0 TO 99) AS firstmove ' to display linenumber info DIM SHARED bbishop(1 TO 164) AS LONG 'array to hold black bishop graphics DIM SHARED bking(1 TO 284) AS LONG 'array to hold black king graphics DIM SHARED bknight(1 TO 284) AS LONG 'array to hold black knight graphics DIM SHARED bpawn(1 TO 164) AS LONG 'array to hold black pawn graphics DIM SHARED bqueen(1 TO 284) AS LONG 'array to hold black queen graphics DIM SHARED brook(1 TO 164) AS LONG 'array to hold black rook graphics DIM SHARED wbishop(1 TO 164) AS LONG 'array to hold white bishop graphics DIM SHARED wking(1 TO 284) AS LONG 'array to hold white king graphics DIM SHARED wknight(1 TO 284) AS LONG 'array to hold white knight graphics DIM SHARED wpawn(1 TO 164) AS LONG 'array to hold white pawn graphics DIM SHARED wqueen(1 TO 284) AS LONG 'array to hold white queen graphics DIM SHARED wrook(1 TO 164) AS LONG 'array to hold white rook graphics DIM SHARED xfig(1 TO 164) AS LONG 'array to hold x figure to highlight squares ' ' get command line argument (to display debug menu or not) testing$ = COMMAND$ IF VAL(testing$) <> 0 THEN testing% = TRUE% ELSE testing% = FALSE% END IF ' ' Main Routine ' ON ERROR GOTO errorhandler Top: ' of main routine gamename$ = "" ' this is a new game, no name yet CLS LOCATE 12, 20 PRINT "I N I T I A L I Z I N G V A R I A B L E S" LOCATE 14, 34 PRINT "please wait..." pause (2&) ' make user think a lot of work is going on Loadheadarray ' with "NU"s to indicate Not Used yet SCREEN 2 ' all graphics files were created in screen mode 2 VIEW SCREEN (0, 0)-(480, 199) ' graphics port Initboard ' setup initial board position and global variables ' routine direction$ = "" ' game flow direction for keyboard control ' default input device is mouse so variable is null DO legalmoves ("n")' get move list Mouseinput ' Get user inputs - like moves, menus, etc. LOOP UNTIL finished% ' until he sets the Finished flag to TRUE% ' SCREEN 0, 0 ' restore text screen IF another% THEN ' the user just had opportunity to set CLS GOTO Top ' another% flag to TRUE% ELSE ' if he did, go ahead to top of program logic i% = 0 LOCATE 1, 1 PRINT "nodenumber"; TAB(12); "linenumber"; TAB(23); "fromsqr"; TAB(31); "tosqr"; TAB(37); "material"; TAB(46); "Special"; TAB(54); "ptr"; TAB(58); "prev" dispmalloc: more$ = "" WHILE more$ = "" more$ = INKEY$ WEND IF (more$ = "Q" OR more$ = "q") THEN GOTO endisp PRINT mallocbuf(i%).nodenumber; TAB(12); mallocbuf(i%).linenumber; TAB(23); mallocbuf(i%).fromsqr; TAB(31); mallocbuf(i%).tosqr; TAB(37); mallocbuf(i%).material; TAB(46); mallocbuf(i%).Special; TAB(54); mallocbuf(i%).ptr; TAB(60); mallocbuf( _ i%).prev i% = i% + 1 GOTO dispmalloc endisp: END END IF ' errorhandler: SELECT CASE ERR CASE 5 ' an illegal function call means we hit a null string and ' were trying to modify it, so illegalfunctioncall% = TRUE% RESUME NEXT CASE 7 CLS SCREEN 0 LOCATE 12, 20 PRINT "You are out of memory - exiting program." pause (5&) END CASE 14 CLS SCREEN 0 LOCATE 12, 20 PRINT "You are out of string space - exiting program." pause (5&) END CASE 19 RESUME CASE 24 CALL TextMsg("Device Timeout - power up device, put it on line, etc. Press 'X' to exit program") DO WHILE interog$ = "": interog$ = INKEY$: LOOP IF UCASE$(interog$) = "X" THEN END ELSE RESUME END IF CASE 25 CALL TextMsg("Device Fault...") DO: LOOP WHILE INKEY$ = "" RESUME CASE 27 CALL TextMsg("Printer Out Of Paper.") DO: LOOP WHILE INKEY$ = "" RESUME CASE 52 CALL TextMsg("Bad File Name") error52% = TRUE% RESUME NEXT CASE 53 CALL TextMsg("File not found") error53% = TRUE% RESUME NEXT CASE 57 CALL TextMsg("Device I/O error") pause (5&) RESUME CASE 61 CLS SCREEN 0 LOCATE 12, 20 PRINT "DISK FULL - Exiting Program." pause (5&) END CASE 64 CALL TextMsg("Bad File Name") pause (5&) error64% = TRUE% RESUME NEXT CASE 68 CALL TextMsg("Device Unavailable...Press 'X' to exit program") interog$ = INKEY$ DO WHILE interog$ = "": interog$ = INKEY$: LOOP IF UCASE$(interog$) = "X" THEN END ELSE error68% = TRUE% RESUME NEXT END IF CASE 71 CALL TextMsg("Disk not ready...") DO: LOOP WHILE INKEY$ = "" RESUME CASE 72 CALL TextMsg("DISK MEDIA ERROR - Exiting Program.") END CASE 75 error75% = TRUE% RESUME NEXT CASE 76 CALL TextMsg("Path Not Found...") DO: LOOP WHILE INKEY$ = "" error76% = TRUE% RESUME NEXT END SELECT REM $STATIC FUNCTION Bin2BinStr$ (b%) STATIC t$ = STRING$(16, "0") IF b% THEN IF b% < 0 THEN MID$(t$, 1, 1) = "1" END IF mask% = &H4000 FOR i% = 2 TO 16 IF b% AND mask% THEN MID$(t$, i%, 1) = "1" END IF mask% = mask% \ 2 NEXT i% END IF Bin2BinStr$ = t$ END FUNCTION FUNCTION BinStr2Bin% (b$) STATIC bin% = 0 t$ = RIGHT$(STRING$(16, "0") + b$, 16) IF LEFT$(t$, 1) = "1" THEN bin% = &H8000 END IF mask% = &H4000 FOR i% = 2 TO 16 IF MID$(t$, i%, 1) = "1" THEN bin% = bin% OR mask% END IF mask% = mask% \ 2 NEXT i% BinStr2Bin% = bin% END FUNCTION SUB BKMoves (i%) ' castle moves are different then white king CALL KMoves(i%) b% = 0 FOR j% = 1 TO 8 IF MoveList%(i%, j%) = 0 THEN EXIT FOR ELSE b% = b% + 1 END IF NEXT j% IF i% = 85 AND CurrBoard(81) = "BR" AND CurrBoard(82) = "MT" AND CurrBoard(83) = "MT" AND CurrBoard(84) = "MT" THEN b% = b% + 1 MoveList%(i%, b%) = 83 END IF IF i% = 85 AND CurrBoard(88) = "BR" AND CurrBoard(86) = "MT" AND CurrBoard(87) = "MT" THEN b% = b% + 1 MoveList%(i%, b%) = 87 END IF END SUB SUB BMoves (i%) ' bishop moves j% = 0 FOR k% = 11 TO 77 STEP 11 IF CurrBoard(i% + k%) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + k% IF CurrBoard(i% + k%) <> "MT" THEN EXIT FOR END IF ELSE EXIT FOR END IF NEXT k% FOR l% = 9 TO 63 STEP 9 IF CurrBoard(i% + l%) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + l% IF CurrBoard(i% + l%) <> "MT" THEN EXIT FOR END IF ELSE EXIT FOR END IF NEXT l% FOR m% = -9 TO -63 STEP -9 IF CurrBoard(i% + m%) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + m% IF CurrBoard(i% + m%) <> "MT" THEN EXIT FOR END IF ELSE EXIT FOR END IF NEXT m% FOR n% = -11 TO -77 STEP -11 IF CurrBoard(i% + n%) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + n% IF CurrBoard(i% + n%) <> "MT" THEN EXIT FOR END IF ELSE EXIT FOR END IF NEXT n% END SUB SUB BPMoves (i%) j% = 0 IF CurrBoard(i% - 10) = "MT" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 10 IF CurrBoard(i% - 20) = "MT" AND (i% \ 10 = 7) THEN j% = j% + 1 MoveList%(i%, j%) = i% - 20 END IF END IF IF CurrBoard(i% - 9) <> "MT" AND CurrBoard(i% - 9) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 9 END IF IF CurrBoard(i% - 11) <> "MT" AND CurrBoard(i% - 11) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 11 END IF IF CurrBoard(i% - 1) = "WP" THEN IF mallocbuf(curindex%).fromsqr \ 10 = 2 THEN IF mallocbuf(curindex%).tosqr \ 10 = 4 THEN IF i% \ 10 = 4 THEN IF (i% MOD 10) = ((mallocbuf(curindex%).fromsqr) MOD 10) + 1 THEN j% = j% + 1 MoveList%(i%, j%) = i% - 11 END IF END IF END IF END IF END IF IF CurrBoard(i% + 1) = "WP" THEN IF mallocbuf(curindex%).fromsqr \ 10 = 2 THEN IF mallocbuf(curindex%).tosqr \ 10 = 4 THEN IF i% \ 10 = 4 THEN IF (i% MOD 10) = ((mallocbuf(curindex%).fromsqr) MOD 10) - 1 THEN j% = j% + 1 MoveList%(i%, j%) = i% - 9 END IF END IF END IF END IF END IF END SUB SUB clean2tailptr (nextndx%) ' free up memory from nextndx% to the last IF nextndx% >= MAXMOVES THEN 'node in the current list EXIT SUB END IF DO pres% = nextndx% mallocbuf(pres%).nodenumber = 0 mallocbuf(pres%).linenumber = -1 mallocbuf(pres%).prev = -1 nextndx% = mallocbuf(pres%).ptr mallocbuf(pres%).ptr = MAXMOVES LOOP WHILE nextndx% <> MAXMOVES pres% = nextndx% mallocbuf(pres%).nodenumber = 0 mallocbuf(pres%).linenumber = -1 mallocbuf(pres%).prev = -1 END SUB SUB cleanchildren (pres%) ' called by gameflow("T") to release all ' memory used by child lines '$DYNAMIC DIM child(0 TO 99) AS INTEGER ' array to hold child lines presline% = mallocbuf(pres%).linenumber ' root line number IF presline% = highestline% THEN lowestline% = presline% ELSE lowestline% = presline% + 1 END IF childcntr% = -1 FOR lcntr% = highestline% TO lowestline% STEP -1 ' get all child lines IF linenumberarray(lcntr%).moved THEN i% = lcntr% DO IF linenumberarray(i%).linenumber = presline% THEN childcntr% = childcntr% + 1 child(childcntr%) = lcntr% i% = presline% ELSE i% = linenumberarray(i%).linenumber END IF LOOP WHILE i% > presline% END IF NEXT lcntr% lncntr% = 0 DO WHILE child(lncntr%) <> 0 ' release memory used by child ' lines ' first node in present line nodenum% = linenumberarray(child(lncntr%)).nodenumber + 1 ' get index of beggining of list begindx% = traverse%(nodenum%, child(lncntr%)) ' clean to the tail of the list clean2tailptr (begindx%) linenumberarray(lncntr%).moved = FALSE% lncntr% = lnctr% + 1 ' keep going LOOP ERASE child END SUB REM $STATIC SUB crsrpos (putback%) STATIC row% STATIC col% IF putback% THEN LOCATE row%, col% ELSE row% = CSRLIN col% = POS(0) END IF END SUB SUB DisplayTree LOCATE 1, 62 PRINT SPACE$(18); LOCATE 1, 62 INPUT "Line number: "; line$ lyne% = VAL(line$) i = traverse%(-1, lyne%) disp$ = "" DO WHILE UCASE$(disp$) <> "S" AND UCASE$(disp$) <> "P" LOCATE 2, 62 PRINT SPACE$(18) LOCATE 2, 62 PRINT "Screen or Printer"; LOCATE 3, 62 PRINT SPACE$(18); LOCATE 3, 62 INPUT "(S/P): "; disp$ LOOP FOR i% = 1 TO 24 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% IF UCASE$(disp$) <> "P" THEN LOCATE 1, 62 PRINT "line number "; line$ LOCATE 2, 62 PRINT "Press 'Q' to quit"; LOCATE 3, 62 PRINT "other keys scroll" ELSE LPRINT "Printing line number "; line$ END IF WHILE i <> MAXMOVES fromfile% = mallocbuf(i).fromsqr MOD 10 fromrank% = mallocbuf(i).fromsqr \ 10 fromfile% = fromfile% + 64 fromrank$ = STR$(fromrank%) fromfile$ = CHR$(fromfile%) from$ = RTRIM$(fromfile$) + LTRIM$(fromrank$) tofile% = mallocbuf(i).tosqr MOD 10 torank% = mallocbuf(i).tosqr \ 10 tofile% = tofile% + 64 torank$ = STR$(torank%) tofile$ = CHR$(tofile%) to$ = RTRIM$(tofile$) + LTRIM$(torank$) IF (mallocbuf(i).nodenumber \ 2 <> (mallocbuf(i).nodenumber / 2) OR (mallocbuf(i).nodenumber = 1)) THEN IF UCASE$(disp$) = "S" THEN LOCATE CSRLIN, 62 PRINT LTRIM$(STR$((mallocbuf(i).nodenumber + 1) \ 2)); "."; LOCATE CSRLIN, 66 PRINT from$; "-"; to$; ELSE LPRINT from$; "-"; to$; END IF ELSE IF UCASE$(disp$) = "S" THEN LOCATE CSRLIN, 74 PRINT from$; "-"; to$ ELSE LPRINT TAB(20); from$; " - "; to$ END IF interog$ = "" WHILE interog$ = "": interog$ = INKEY$: WEND IF UCASE$(interog$) = "Q" THEN EXIT SUB END IF END IF i = mallocbuf(i).ptr WEND PRINT LOCATE CSRLIN, 62 PRINT "Any key continues" interog$ = "" WHILE interog$ = "": interog$ = INKEY$: WEND FOR i% = 1 TO 24 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% END SUB SUB gameflow (direction$) pres% = 0 ' present index before a move back up or take back ' if pres% <> 0 at end of case statement then we ' know the moves have been backed up SELECT CASE LTRIM$(RTRIM$(direction$)) CASE "F" oldindex% = curindex% IF ((mallocbuf(curindex%).linenumber <> linenumber%) OR curindex% = MAXMOVES) THEN curindex% = traverse%(-1, linenumber%) ELSE curindex% = mallocbuf(curindex%).ptr END IF IF curindex% >= MAXMOVES THEN curindex% = oldindex% EXIT SUB ELSE node.linenumber% = mallocbuf(curindex%).linenumber node.nodenumber = mallocbuf(curindex%).nodenumber node.fromsqr = mallocbuf(curindex%).fromsqr node.tosqr = mallocbuf(curindex%).tosqr node.ptr = mallocbuf(curindex%).ptr node.prev = mallocbuf(curindex%).prev i = mallocbuf(curindex%).tosqr toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) i = mallocbuf(curindex%).fromsqr fromy% = i \ 10: fromx% = i MOD 10 fromx% = (fromx% - 1) * 60 fromy% = 25 * (8 - fromy%) piece$ = CurrBoard(i) CALL Move(fromx%, fromy%, tox%, toy%, piece$, FALSE%) CALL Move(tox%, toy%, tox%, toy%, piece$, TRUE%) CurrBoard(mallocbuf(curindex%).fromsqr) = LatestBoard(mallocbuf(curindex%).fromsqr) CurrBoard(mallocbuf(curindex%).tosqr) = LatestBoard(mallocbuf(curindex%).tosqr) whitemove% = NOT whitemove% END IF CASE "B" IF curindex% = 0 THEN EXIT SUB END IF i = mallocbuf(curindex%).fromsqr toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) i = mallocbuf(curindex%).tosqr piece$ = CurrBoard(i) fromy% = i \ 10: fromx% = i MOD 10 fromx% = (fromx% - 1) * 60 fromy% = 25 * (8 - fromy%) piece$ = CurrBoard(i) CALL Move(fromx%, fromy%, tox%, toy%, piece$, FALSE%) CALL Move(tox%, toy%, tox%, toy%, piece$, TRUE%) capture$ = mallocbuf(curindex%).material IF capture$ <> "MT" THEN IF mallocbuf(curindex%).Special = "EP" THEN culur$ = LEFT$(capture$, 1) IF culur$ = "B" THEN dif% = 25 ELSE dif% = -25 END IF ELSE dif% = 0 END IF CALL Move(0, 0, fromx%, fromy% + dif%, capture$, FALSE%) END IF CurrBoard(mallocbuf(curindex%).fromsqr) = CurrBoard(mallocbuf(curindex%).tosqr) pres% = curindex% IF mallocbuf(curindex%).Special <> "EP" THEN CurrBoard(mallocbuf(curindex%).tosqr) = capture$ curindex% = mallocbuf(curindex%).prev ELSE CurrBoard(mallocbuf(curindex%).tosqr) = "MT" curindex% = mallocbuf(curindex%).prev CurrBoard(mallocbuf(curindex%).tosqr) = capture$ END IF node.linenumber = mallocbuf(curindex%).linenumber IF node.linenumber <> linenumber% THEN linenumber% = node.linenumber END IF node.nodenumber = mallocbuf(curindex%).nodenumber node.fromsqr = mallocbuf(curindex%).fromsqr node.tosqr = mallocbuf(curindex%).tosqr node.ptr = mallocbuf(curindex%).ptr node.prev = mallocbuf(curindex%).prev whitemove% = NOT whitemove% CASE "T" IF curindex% = 0 THEN EXIT SUB ELSE nxtptr$ = mallocbuf(curindex%).Special IF LEFT$(LTRIM$(nxtptr$), 1) = "P" THEN fromsqr% = mallocbuf(curindex%).fromsqr tosqr% = mallocbuf(curindex%).tosqr fromx% = ((fromsqr% MOD 10) - 1) * 60 fromy% = (8 - (fromsqr% \ 10)) * 25 mypiece$ = CurrBoard(tosqr%) mycolor$ = LEFT$(LTRIM$(mypiece$), 1) END IF rank% = mallocbuf(curindex%).tosqr \ 10 IF curindex% = 0 THEN EXIT SUB END IF i = mallocbuf(curindex%).fromsqr toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) i = mallocbuf(curindex%).tosqr piece$ = CurrBoard(i) fromy% = i \ 10: fromx% = i MOD 10 fromx% = (fromx% - 1) * 60 fromy% = 25 * (8 - fromy%) piece$ = CurrBoard(i) CALL Move(fromx%, fromy%, tox%, toy%, piece$, FALSE%) CALL Move(tox%, toy%, tox%, toy%, piece$, TRUE%) capture$ = mallocbuf(curindex%).material IF capture$ <> "MT" THEN IF mallocbuf(curindex%).Special = "EP" THEN culur$ = LEFT$(capture$, 1) IF culur$ = "B" THEN dif% = 25 ELSE dif% = -25 END IF ELSE dif% = 0 END IF CALL Move(0, 0, fromx%, fromy% + dif%, capture$, FALSE%) END IF CurrBoard(mallocbuf(curindex%).fromsqr) = CurrBoard(mallocbuf(curindex%).tosqr) pres% = curindex% IF mallocbuf(curindex%).Special <> "EP" THEN CurrBoard(mallocbuf(curindex%).tosqr) = capture$ curindex% = mallocbuf(curindex%).prev ELSE CurrBoard(mallocbuf(curindex%).tosqr) = "MT" curindex% = mallocbuf(curindex%).prev CurrBoard(mallocbuf(curindex%).tosqr) = capture$ END IF node.linenumber = mallocbuf(curindex%).linenumber IF node.linenumber <> linenumber% THEN linenumber% = node.linenumber END IF node.nodenumber = mallocbuf(curindex%).nodenumber node.fromsqr = mallocbuf(curindex%).fromsqr node.tosqr = mallocbuf(curindex%).tosqr node.ptr = MAXMOVES node.prev = mallocbuf(curindex%).prev present% = mallocbuf(curindex%).ptr clean2tailptr (present%) cleanchildren (curindex%) mallocbuf(curindex%).ptr = MAXMOVES highestline% = mallocbuf(curindex%).linenumber whitemove% = NOT whitemove% END IF END SELECT curflag$ = mallocbuf(curindex%).Special IF pres% <> 0 THEN nxtflag$ = mallocbuf(pres%).Special ELSE nxtflag$ = mallocbuf(mallocbuf(curindex%).ptr).Special END IF IF mallocbuf(pres%).Special = "CK" AND direction$ <> "F" THEN IF mallocbuf(pres%).fromsqr = 15 THEN CurrBoard(18) = "WR" CurrBoard(16) = "MT" CALL Move(0, 0, 420, 175, "WR", FALSE%) CALL Move(0, 0, 300, 175, "WR", FALSE%) ELSEIF mallocbuf(pres%).fromsqr = 85 THEN CurrBoard(88) = "BR" CurrBoard(86) = "MT" CALL Move(0, 0, 420, 0, "BR", FALSE%) CALL Move(0, 0, 300, 0, "BR", FALSE%) END IF ELSEIF mallocbuf(pres%).Special = "CQ" AND direction$ <> "F" THEN IF mallocbuf(pres%).fromsqr = 15 THEN CurrBoard(11) = "WR" CurrBoard(14) = "MT" CALL Move(0, 0, 180, 175, "WR", FALSE%) CALL Move(0, 0, 0, 175, "WR", FALSE%) ELSEIF mallocbuf(pres%).fromsqr = 85 THEN CurrBoard(81) = "WR" CurrBoard(84) = "MT" CALL Move(0, 0, 180, 0, "BR", FALSE%) CALL Move(0, 0, 0, 0, "BR", FALSE%) END IF END IF IF mallocbuf(curindex%).Special = "CK" AND direction$ = "F" THEN IF mallocbuf(curindex%).fromsqr = 15 THEN CurrBoard(18) = "MT" CurrBoard(16) = "WR" CALL Move(0, 0, 420, 175, "WR", FALSE%) CALL Move(0, 0, 300, 175, "WR", FALSE%) ELSEIF mallocbuf(curindex%).fromsqr = 85 THEN CurrBoard(88) = "MT" CurrBoard(86) = "BR" CALL Move(0, 0, 420, 0, "BR", FALSE%) CALL Move(0, 0, 300, 0, "BR", FALSE%) END IF ELSEIF mallocbuf(curindex%).Special = "CQ" AND direction$ = "F" THEN IF mallocbuf(curindex%).fromsqr = 15 THEN CurrBoard(11) = "MT" CurrBoard(14) = "WR" CALL Move(0, 0, 180, 175, "WR", FALSE%) CALL Move(0, 0, 0, 175, "WR", FALSE%) ELSEIF mallocbuf(curindex%).fromsqr = 85 THEN CurrBoard(16) = "BR" CurrBoard(18) = "MT" CALL Move(0, 0, 180, 0, "WR", FALSE%) CALL Move(0, 0, 0, 0, "WR", FALSE%) END IF END IF IF LEFT$(curflag$, 1) = "P" AND direction$ = "F" THEN prom$ = RTRIM$(LEFT$(CurrBoard(mallocbuf(curindex%).tosqr), 1)) + LTRIM$(RIGHT$(RTRIM$(curflag$), 1)) CALL Move(0, 0, ((mallocbuf(curindex%).tosqr MOD 10) - 1) * 60, (8 - (mallocbuf(curindex%).tosqr \ 10)) * 25, CurrBoard(mallocbuf(curindex%).tosqr), FALSE%) CALL Move(0, 0, ((mallocbuf(curindex%).tosqr MOD 10) - 1) * 60, (8 - (mallocbuf(curindex%).tosqr \ 10)) * 25, prom$, FALSE%) RSET CurrBoard(mallocbuf(curindex%).tosqr) = RTRIM$(LTRIM$(prom$)) ELSEIF (LEFT$(nxtflag$, 1) = "P" AND direction$ = "B") OR (LEFT$(nxtflag$, 1) = "P" AND direction$ = "T") THEN ' get rid of promoted material prom$ = CurrBoard(mallocbuf(pres%).fromsqr) CALL Move(0, 0, ((mallocbuf(pres%).fromsqr MOD 10) - 1) * 60, (8 - (mallocbuf(pres%).fromsqr \ 10)) * 25, prom$, FALSE%) IF mallocbuf(pres%).tosqr \ 10 = 8 THEN pawn$ = "WP" ELSE pawn$ = "BP" END IF ' put pawn on square CALL Move(0, 0, ((mallocbuf(pres%).fromsqr MOD 10) - 1) * 60, (8 - (mallocbuf(pres%).fromsqr \ 10)) * 25, pawn$, FALSE%) CurrBoard(mallocbuf(pres%).tosqr) = mallocbuf(pres%).material LatestBoard(mallocbuf(pres%).tosqr) = CurrBoard(mallocbuf(pres%).tosqr) RSET CurrBoard(mallocbuf(pres%).fromsqr) = RTRIM$(LTRIM$(pawn$)) LatestBoard(mallocbuf(pres%).fromsqr) = CurrBoard(mallocbuf(pres%).fromsqr) END IF END SUB SUB GetBBishop (x%, y%) ' Get Black Bishop From File ' DEF SEG = VARSEG(bbishop(1)) IF Initing% THEN BLOAD "bbishop.grh", VARPTR(bbishop(1)) END IF DEF SEG PUT (x% + 20, y% + 1), bbishop END SUB SUB GetBishops CALL GetBBishop(120, 0) CurrBoard(83) = "BB" CALL GetBBishop(300, 0) CurrBoard(86) = "BB" CALL GetWBishop(120, 175) CurrBoard(13) = "WB" CALL GetWBishop(300, 175) CurrBoard(16) = "WB" END SUB SUB GetBKing (x%, y%) DEF SEG = VARSEG(bking(1)) IF Initing% THEN BLOAD "bking.grh", VARPTR(bking(1)) DEF SEG ' return to DGROUP PUT (x%, y%), bking END SUB SUB GetBKnight (x%, y%) ' DEF SEG = VARSEG(bknight(1)) IF Initing% THEN BLOAD "bknight.grh", VARPTR(bknight(1)) DEF SEG PUT (x% + 10, y%), bknight END SUB SUB GetBoard ' get chess board from file ' DEF SEG = VARSEG(board(1)) BLOAD "board.grh", VARPTR(board(1)) DEF SEG PUT (0, 0), board FOR i = 31 TO 68 CurrBoard(i) = "MT" ' for eMpTy NEXT i FOR i = 0 TO 9 CurrBoard(i) = "KO" ' for Keep Off NEXT i ' can not move to these squares FOR i = 90 TO 99 CurrBoard(i) = "KO" NEXT i FOR i = 10 TO 80 STEP 10 CurrBoard(i) = "KO" NEXT i FOR i = 19 TO 89 STEP 10 CurrBoard(i) = "KO" NEXT i END SUB SUB GetBPawn (x%, y%) ' DEF SEG = VARSEG(bpawn(1)) IF Initing% THEN BLOAD "bpawn.grh", VARPTR(bpawn(1)) DEF SEG PUT (x% + 19, y%), bpawn END SUB SUB GetBQueen (x%, y%) ' DEF SEG = VARSEG(bqueen(1)) IF Initing% THEN BLOAD "bqueen.grh", VARPTR(bqueen(1)) DEF SEG ' return to DGROUP PUT (x%, y%), bqueen END SUB SUB GetBRook (x%, y%) DEF SEG = VARSEG(brook(1)) IF Initing% THEN BLOAD "brook.grh", VARPTR(brook(1)) DEF SEG PUT (x% + 20, y%), brook END SUB FUNCTION gethigh% (b$) ' convert low order binary string to high order ' value (decimal result) temp% = 0 FOR i% = 9 TO 16 IF MID$(b$, i%, 1) = "1" THEN temp% = temp% + 2 ^ (24 - i%) END IF NEXT i% gethigh% = temp% END FUNCTION SUB GetKings ' get kings from file CALL GetBKing(240, 0) CurrBoard(85) = "BK" CALL GetWKing(240, 175) CurrBoard(15) = "WK" END SUB SUB GetKnights ' get knights from file CALL GetBKnight(60, 0) CurrBoard(82) = "BN" CALL GetBKnight(360, 0) CurrBoard(87) = "BN" CALL GetWKnight(60, 175) CurrBoard(12) = "WN" CALL GetWKnight(360, 175) CurrBoard(17) = "WN" END SUB SUB GetPawns ' get pawns from file FOR x% = 0 TO 420 STEP 60 CALL GetBPawn(x%, 25) ' put black pawn on board CurrBoard(x% \ 60 + 71) = "BP" ' record what is on current square NEXT x% FOR x% = 0 TO 420 STEP 60 CALL GetWPawn(x%, 150) ' put white pawn on board CurrBoard(x% \ 60 + 21) = "WP" ' this will be used for graphics NEXT x% ' and tree building END SUB SUB GetQueens CALL GetBQueen(180, 0) CurrBoard(84) = "BQ" CALL GetWQueen(180, 175) CurrBoard(14) = "WQ" END SUB SUB GetRooks CALL GetBRook(0, 0) CurrBoard(81) = "BR" CALL GetBRook(420, 0) CurrBoard(88) = "BR" CALL GetWRook(0, 175) CurrBoard(11) = "WR" CALL GetWRook(420, 175) CurrBoard(18) = "WR" END SUB SUB GetWBishop (x%, y%) ' DEF SEG = VARSEG(wbishop(1)) IF Initing% THEN BLOAD "wbishop.grh", VARPTR(wbishop(1)) DEF SEG PUT (x% + 20, y% + 1), wbishop END SUB SUB GetWKing (x%, y%) DEF SEG = VARSEG(wking(1)) IF Initing% THEN BLOAD "wking.grh", VARPTR(wking(1)) DEF SEG ' return to DGROUP PUT (x%, y%), wking END SUB SUB GetWKnight (x%, y%) DEF SEG = VARSEG(wknight(1)) IF Initing% THEN BLOAD "wknight.grh", VARPTR(wknight(1)) DEF SEG PUT (x% + 10, y%), wknight END SUB SUB GetWPawn (x%, y%) DEF SEG = VARSEG(wpawn(1)) IF Initing% THEN BLOAD "wpawn.grh", VARPTR(wpawn(1)) DEF SEG PUT (x% + 19, y%), wpawn END SUB SUB GetWQueen (x%, y%) ' DEF SEG = VARSEG(wqueen(1)) IF Initing% THEN BLOAD "wqueen.grh", VARPTR(wqueen(1)) DEF SEG ' return to DGROUP PUT (x%, y%), wqueen END SUB SUB GetWRook (x%, y%) ' DEF SEG = VARSEG(wrook(1)) IF Initing% THEN BLOAD "wrook.grh", VARPTR(wrook(1)) DEF SEG PUT (x% + 20, y%), wrook END SUB SUB GOTOEOL ' forward to End Of the Line WHILE mallocbuf(curindex%).ptr <> MAXMOVES gameflow ("F") WEND legalmoves ("f") END SUB SUB help DIM recarray$(1 TO 1000) '$DYNAMIC DIM scrnsave(1 TO 4045) ' save current screen GET (0, 0)-(639, 199), scrnsave CLS SCREEN 0 filnumber = FREEFILE filename$ = "NOTE.HLP" length% = LEN(filename$) OPEN filename$ FOR INPUT AS filnumber FOR i% = 1 TO 23 INPUT #filnumber, rec$ recarray$(i%) = rec$ LOCATE i%, 1 PRINT recarray$(i%) NEXT i% i% = 23 highi = i% looptop: interog$ = "" DO WHILE UCASE$(interog$) = "" interog$ = INKEY$ IF UCASE$(interog$) = CHR$(0) + CHR$(80) THEN 'scroll up CALL scrolltxt(6, 1, 7, 0, 0, 23, 79) i% = i% + 1 IF ((i% > highi) AND (NOT EOF(filnumber))) THEN INPUT #filnumber, rec$ recarray$(i%) = rec$ highi = i% END IF LOCATE 23, 1 PRINT recarray$(i%); ELSEIF UCASE$(interog$) = CHR$(0) + CHR$(72) THEN ' scroll down IF i% - 23 > 1 THEN CALL scrolltxt(7, 1, 7, 0, 0, 23, 79) i% = i% - 1 LOCATE 1, 1 PRINT recarray$(i% - 23); END IF ELSEIF UCASE$(interog$) = "Q" THEN CLOSE filnumber CLS SCREEN 2 PUT (0, 0), scrnsave VIEW SCREEN (0, 0)-(480, 199) ' graphics port ERASE scrnsave 'deallocate array memory EXIT SUB END IF LOOP GOTO looptop END SUB REM $STATIC SUB Initboard ' set variables Initing% = TRUE% ' let the called routines now this is ' the first call to them finished% = FALSE% ' the game isnt over yet CALL GetBoard ' put chess board on screen CALL GetPawns ' put pawns on chess board CALL GetRooks ' put rooks on chess board CALL GetKnights ' put knights on chess board CALL GetBishops ' put bishops on chess board CALL GetQueens ' put queens on chess board CALL GetKings ' put kings on chess board CALL putx(0) ' load up hilight array InRegs.ax = 1 ' make mouse cursor visible CALL INTERRUPT(51, InRegs, OutRegs) FOR i = 0 TO 99 LatestBoard(i) = CurrBoard(i) ' node zero is the inital NEXT i Initing% = FALSE% linenumber% = 0 ' start at main line highestline% = 0 ' can be changed with menu selection FOR i = 1 TO MAXMOVES ' initialize move buffer mallocbuf(i).linenumber = -1 'implies free memory mallocbuf(i).nodenumber = -9 'unused NEXT i FOR i = 0 TO 99 ' init head positions headboard(i, 11) = "NU" ' to not used NEXT i linenumberarray(0).moved = TRUE% ' the main line is always in use linenumberarray(0).nodenumber = -1 ' the node leading into main linenumberarray(0).linenumber = -1 ' is the phantom -1, -1 FOR i = 1 TO 99 linenumberarray(i).moved = FALSE% NEXT i CALL listinitialize ' init linked list error53% = FALSE% error64% = FALSE% error75% = FALSE% error76% = FALSE% CALL printmenu whitemove% = TRUE% linechange% = TRUE% END SUB SUB insertafter IF node.nodenumber <> 1 THEN oldindex% = curindex% curindex% = malloc% mallocbuf(curindex%).prev = oldindex% IF mallocbuf(oldindex%).linenumber = linenumber% THEN mallocbuf(oldindex%).ptr = curindex% END IF END IF mallocbuf(curindex%).nodenumber = node.nodenumber mallocbuf(curindex%).linenumber = node.linenumber mallocbuf(curindex%).fromsqr = node.fromsqr mallocbuf(curindex%).tosqr = node.tosqr RSET mallocbuf(curindex%).material = node.material node.Special = "RM" ' assume Regular Move mallocbuf(curindex%).Special = "RM" ' find out if true CALL Special ' set field for special moves mallocbuf(curindex%).ptr = MAXMOVES END SUB FUNCTION isitillegal% (from%, tosqr%) good% = FALSE% FOR j% = 1 TO 28 IF MoveList%(from%, j%) = tosqr% THEN good% = TRUE% EXIT FOR END IF NEXT j% IF good% THEN isitillegal% = FALSE% ELSE isitillegal% = TRUE% END IF END FUNCTION SUB KMoves (i%) ' king moves j% = 0 IF CurrBoard(i% - 1) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 1 END IF IF CurrBoard(i% + 9) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 9 END IF IF CurrBoard(i% + 10) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 10 END IF IF CurrBoard(i% + 11) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 11 END IF IF CurrBoard(i% + 1) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 1 END IF IF CurrBoard(i% - 9) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 9 END IF IF CurrBoard(i% - 10) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 10 END IF IF CurrBoard(i% - 11) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% - 11 END IF END SUB SUB legalmoves (force$) ' find all legal moves in position STATIC oldcolor% IF linechange% THEN GOTO skiptest ' test for color to move IF force$ = "f" THEN GOTO skiptest IF oldcolor% = whitemove% THEN EXIT SUB END IF skiptest: InRegs.ax = 3 ' get pointer position CALL INTERRUPT(51, InRegs, OutRegs) xsave% = OutRegs.cx ' save x position of pointer ysave% = OutRegs.dx ' ditto for y - both in pixels InRegs.ax = 2 ' hide mouse pointer while CALL INTERRUPT(51, InRegs, OutRegs) ' generating legal moves InRegs.ax = 0 ' disable mouse support InRegs.bx = -1 ' to be safe CALL INTERRUPT(51, InRegs, OutRegs) FOR i% = 11 TO 89 ' i% is the from square and FOR j% = 1 TO 28 MoveList%(i%, j%) = 0 ' the array element is the to square NEXT j% NEXT i% FOR i% = 11 TO 88 SELECT CASE CurrBoard(i%) CASE "BP" IF NOT whitemove% THEN CALL BPMoves(i%) CASE "BR" IF NOT whitemove% THEN CALL RMoves(i%) CASE "BN" IF NOT whitemove% THEN CALL NMoves(i%) CASE "BB" IF NOT whitemove% THEN CALL BMoves(i%) CASE "BQ" IF NOT whitemove% THEN CALL QMoves(i%) CASE "BK" IF NOT whitemove% THEN CALL BKMoves(i%) CASE "WP" IF whitemove% THEN CALL WPMoves(i%) CASE "WR" IF whitemove% THEN CALL RMoves(i%) CASE "WN" IF whitemove% THEN CALL NMoves(i%) CASE "WB" IF whitemove% THEN CALL BMoves(i%) CASE "WQ" IF whitemove% THEN CALL QMoves(i%) CASE "WK" IF whitemove% THEN CALL WKMoves(i%) CASE ELSE ' nothing to do END SELECT NEXT i% oldcolor% = whitemove% linechange% = FALSE% BEEP InRegs.ax = 0 ' enable mouse support InRegs.bx = 2 ' for two buttons CALL INTERRUPT(51, InRegs, OutRegs) InRegs.ax = 4 ' set pointer position InRegs.cx = xsave% ' restore pointer InRegs.dx = ysave% ' coordinates CALL INTERRUPT(51, InRegs, OutRegs) InRegs.ax = 1 ' make pointer visible CALL INTERRUPT(51, InRegs, OutRegs) END SUB SUB lightupsqrs (from%) ' light up to squares the piece on the from square ' can move to FOR j% = 1 TO 28 IF MoveList%(from%, j%) <> 0 THEN IF LEFT$(CurrBoard(from%), 1) <> LEFT$(CurrBoard(MoveList%(from%, j%)), 1) THEN CALL putx(MoveList%(from%, j%)) END IF ELSE EXIT FOR END IF NEXT j% pause (&O3) FOR j% = 1 TO 28 IF MoveList%(from%, j%) <> 0 THEN IF LEFT$(CurrBoard(from%), 1) <> LEFT$(CurrBoard(MoveList%(from%, j%)), 1) THEN CALL putx(MoveList%(from%, j%)) END IF ELSE EXIT FOR END IF NEXT j% END SUB SUB linenumbers ' display lines of play already used and the FOR i% = 1 TO 24 ' head positions leading into them LOCATE i%, 62 PRINT SPACE$(18); NEXT i% LOCATE 1, 62 PRINT "Any key scrolls"; LOCATE 2, 62 PRINT "Except 'Q' quits"; LOCATE 3, 62 PRINT " line "; "node"; LOCATE 4, 62 FOR i = 0 TO 99 IF linenumberarray(i).moved = TRUE% THEN LOCATE CSRLIN, 62 PRINT i; " "; linenumberarray(i).linenumber; " "; linenumberarray(i).nodenumber interog$ = "" WHILE interog$ = "" interog$ = INKEY$ IF UCASE$(interog$) = "Q" THEN EXIT FOR END IF WEND ELSE EXIT FOR END IF NEXT i LOCATE 23, 62 PRINT "Press Any Key To"; LOCATE 24, 62 PRINT "Exit This Screen"; DO: LOOP WHILE INKEY$ = "" FOR i% = 1 TO 24 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% CALL printmenu END SUB SUB listinitialize node.prev = -1 ' no previous moves node.ptr = MAXMOVES ' at initializtion the head points to the ' tail, implying no moves yet node.nodenumber = 0 ' the head is node zero node.linenumber = 0 ' it is part of the main line, zero node.fromsqr = 0 ' this is illegal for a move - ok here node.tosqr = 0 ' ditto mallocbuf(0).prev = node.prev mallocbuf(0).ptr = node.ptr mallocbuf(0).nodenumber = node.nodenumber mallocbuf(0).linenumber = node.linenumber mallocbuf(0).fromsqr = node.fromsqr mallocbuf(0).tosqr = node.tosqr ' initialize headboard FOR i = 11 TO 88 headboard(0, i) = CurrBoard(i) NEXT i RSET headboard(0, 89) = "00" RSET headboard(0, 90) = "00" END SUB SUB LoadGame (New%) loadtop: New% = TRUE% ' a new game LOCATE 16, 62: PRINT SPACE$(17); LOCATE 16, 62 PRINT "?"; LOCATE 16, 65, 1 filename$ = "" char$ = "" DO char$ = "" WHILE char$ = "" char$ = INKEY$ WEND IF ASC(char$) = 8 AND POS(0) <> 65 THEN ' backspace LOCATE 16, POS(0) - 1, 1 ELSEIF char$ <> CHR$(13) THEN filename$ = RTRIM$(filename$) + LTRIM$(char$) PRINT char$; END IF LOOP UNTIL char$ = CHR$(13) IF char$ = CHR$(13) AND filename$ = "" THEN New% = FALSE% LOCATE 16, 62 PRINT SPACE$(17); gamename$ = "" EXIT SUB END IF dot% = INSTR(RTRIM$(LTRIM$(filename$)), ".") IF dot% > 9 OR (dot% = 0 AND LEN(RTRIM$(LTRIM$(filename$))) > 8) THEN LOCATE 16, 62: PRINT SPACE$(17); GOTO loadtop ELSEIF LEN(RTRIM$(LTRIM$(filename$))) - dot% > 3 THEN LOCATE 16, 62: PRINT SPACE$(17); GOTO loadtop ELSEIF LEN(LTRIM$(RTRIM$(filename$))) = 0 THEN LOCATE 16, 62: PRINT SPACE$(17); gamename$ = "" EXIT SUB END IF filenum = FREEFILE IF dot% = 0 THEN filename$ = RTRIM$(filename$) + LTRIM$(".") dot% = LEN(LTRIM$(RTRIM$(filename$))) END IF filename$ = RTRIM$(LEFT$(filename$, dot%)) + LTRIM$("GAM") OPEN filename$ FOR RANDOM AS filenum LEN = 16 IF error52% THEN error52% = FALSE% GOTO loadtop ELSEIF error53% THEN error53% = FALSE% GOTO loadtop ELSEIF error64% THEN error64% = FALSE% GOTO loadtop ELSEIF error68% THEN error68% = FALSE% GOTO loadtop ELSEIF error75% THEN error75% = FALSE% GOTO loadtop ELSEIF error76% THEN error76% = FALSE% GOTO loadtop END IF FOR i = 0 TO MAXMOVES GET #filenum, i + 1, mallocbuf(i) IF mallocbuf(i).linenumber > highestline% THEN highestline% = mallocbuf(i).linenumber END IF NEXT i CLOSE filenum filenum = FREEFILE filename$ = RTRIM$(LEFT$(filename$, dot%)) + LTRIM$("HBD") OPEN filename$ FOR RANDOM AS filenum LEN = 2 counter% = 0 FOR l = 0 TO 99 FOR m = 11 TO 88 counter% = counter% + 1 GET #filenum, counter%, headboard(l, m) NEXT m NEXT l CLOSE #filenum InRegs.ax = 2 ' hide mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) CLS SCREEN 2 VIEW SCREEN (0, 0)-(480, 199) ' graphics port ' set up new board Initing% = TRUE% ' let the called routines now this is ' the first call to them finished% = FALSE% ' the game isnt over yet CALL GetBoard ' put chess board on screen CALL GetPawns ' put pawns on chess board CALL GetRooks ' put rooks on chess board CALL GetKnights ' put knights on chess board CALL GetBishops ' put bishops on chess board CALL GetQueens ' put queens on chess board CALL GetKings ' put kings on chess board FOR i = 0 TO 99 LatestBoard(i) = CurrBoard(i) ' node zero is the inital NEXT i Initing% = FALSE% linenumber% = 0 ' start at main line linenumberarray(0).moved = TRUE% curindex% = 0 error53% = FALSE% error64% = FALSE% error75% = FALSE% error76% = FALSE% i = mallocbuf(curindex%).tosqr toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) i = mallocbuf(curindex%).fromsqr fromy% = i \ 10: fromx% = i MOD 10 fromx% = (fromx% - 1) * 60 fromy% = 25 * (8 - fromy%) piece$ = CurrBoard(i) CALL Move(fromx%, fromy%, tox%, toy%, piece$, FALSE%) CALL Move(tox%, toy%, tox%, toy%, piece$, TRUE%) CurrBoard(mallocbuf(curindex%).fromsqr) = LatestBoard(mallocbuf(curindex%).fromsqr) CurrBoard(mallocbuf(curindex%).tosqr) = LatestBoard(mallocbuf(curindex%).tosqr) gamename$ = filename$ FOR i% = 1 TO 24 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% CALL printmenu InRegs.ax = 1 ' show mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) END SUB SUB Loadheadarray FOR i = 11 TO 88 headboard(0, i) = CurrBoard(i) NEXT i RSET headboard(0, 89) = "00" ' line 0 starts at index% 0 RSET headboard(0, 90) = "00" RSET headboard(0, 91) = "WM" ' White to Move FOR i = 1 TO 99 headboard(i, 11) = "NU" ' Not Used yet NEXT i END SUB FUNCTION malloc% FOR index% = 0 TO MAXMOVES IF mallocbuf(index%).linenumber = -1 THEN malloc% = index% EXIT FUNCTION END IF NEXT index% END FUNCTION SUB menu DIM btleft AS INTEGER ' boolean value of left button InRegs.ax = 3 ' Get Coordinate Info InRegs.bx = 3 ' view left and right buttons CALL INTERRUPT(51, InRegs, OutRegs) ' make mouse call OutRegs.ax = OutRegs.bx ' decode mouse button information btleft = OutRegs.ax AND 1 ' mask for left button bit btleft = -btleft OutRegs.ax = OutRegs.bx ' decode mouse button information OutRegs.ax = OutRegs.ax AND 2 ' mask for right button bit CALL RORax(1) ' move this to lsb btright = -OutRegs.ax ' save right button info IF (btright = -1) THEN ' text entry CALL textnotes EXIT SUB END IF newx% = OutRegs.cx newy% = OutRegs.dx CALL printmenu interog$ = "" IF NOT btleft THEN interog$ = INKEY$ END IF IF (NOT btleft) THEN IF interog$ = "" THEN EXIT SUB ELSE GOTO endofmouse END IF END IF IF newx% > 610 THEN IF newy% > 25 AND newy% < 43 THEN interog$ = "N" ELSEIF newy% > 43 AND newy% < 59 THEN interog$ = "?" ELSEIF newy% > 60 AND newy% < 74 THEN interog$ = CHR$(0) + CHR$(72) ELSEIF newy% > 74 AND newy% < 90 THEN interog$ = CHR$(0) + CHR$(80) ELSEIF newy% > 92 AND newy% < 105 THEN interog$ = "S" ELSEIF newy% > 107 AND newy% < 124 THEN interog$ = "G" ELSEIF newy% > 124 AND newy% < 139 THEN interog$ = "D" ELSEIF newy% > 139 AND newy% < 150 THEN interog$ = "I" ELSEIF newy% > 150 AND newy% < 169 THEN interog$ = "X" END IF END IF endofmouse: InRegs.ax = 2 'hide cursor CALL INTERRUPT(51, InRegs, OutRegs) SELECT CASE UCASE$(interog$) CASE CHR$(0) + CHR$(72) ' up arrow linenumber% = linenumber% + 1 IF (linenumber% > highestline%) THEN linenumberarray(linenumber%).moved = TRUE% linenumberarray(linenumber%).nodenumber = mallocbuf(curindex%).nodenumber linenumberarray(linenumber%).linenumber = mallocbuf(curindex%).linenumber highestline% = linenumber% FOR i = 11 TO 88 headboard(linenumber%, i) = CurrBoard(i) NEXT i temp$ = STR$(node.nodenumber) IF LEN(RTRIM$(temp$)) > 2 THEN lnode$ = LEFT$(temp$, 2) rnode$ = RIGHT$(temp$, 2 - LEN(RTRIM$(lnode$))) ELSE lnode$ = temp$ rnode$ = " " END IF RSET headboard(linenumber%, 89) = RTRIM$(lnode$) RSET headboard(linenumber%, 90) = rnode$ IF whitemove% = TRUE% THEN headboard(linenumber%, 91) = "WM" ELSE headboard(linenumber%, 91) = "BM" END IF ELSE CLS SCREEN 2 VIEW SCREEN (0, 0)-(480, 199) ' graphics port PUT (0, 0), board FOR i = 11 TO 88 piece$ = headboard(linenumber%, i) toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) CALL Move(0, 0, tox%, toy%, piece$, FALSE%) LatestBoard(i) = piece$ CurrBoard(i) = piece$ ' update board array NEXT i LatestBoard(81) = headboard(linenumber%, 81) CurrBoard(81) = headboard(linenumber%, 81) lnode$ = headboard(linenumber%, 89) rnode$ = headboard(linenumber%, 90) temp$ = RTRIM$(lnode$) + rnode$ ' the head of our list is defined by node.nodenumber = VAL(temp$) node.linenumber = linenumber% - 1 curindex% = traverse%(node.nodenumber, node.linenumber) END IF IF (headboard(linenumber%, 91) = "BM") THEN whitemove% = FALSE% ELSE whitemove% = TRUE% END IF linechange% = TRUE% curindex% = MAXMOVES CASE CHR$(0) + CHR$(80) ' down arrow IF linenumber% > 0 THEN linenumber% = linenumber% - 1 CLS SCREEN 2 VIEW SCREEN (0, 0)-(480, 199) ' graphics port PUT (0, 0), board FOR i = 11 TO 88 piece$ = headboard(linenumber%, i) toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) CALL Move(0, 0, tox%, toy%, piece$, FALSE%) CurrBoard(i) = piece$ ' update board array LatestBoard(i) = CurrBoard(i) NEXT i LatestBoard(81) = CurrBoard(81) ulnode$ = headboard(linenumber%, 89) rnode$ = headboard(linenumber%, 90) temp$ = RTRIM$(lnode$) + rnode$ node.nodenumber = VAL(temp$) IF linenumber% = 0 THEN node.linenumber = 0 ELSE node.linenumber = linenumber% - 1 END IF END IF IF (headboard(linenumber%, 91) = "BM") THEN whitemove% = FALSE% ELSE whitemove% = TRUE% END IF linechange% = TRUE% curindex% = MAXMOVES CASE "S" CALL SaveGame CASE "G" CALL LoadGame(New%) CASE "D" CALL DisplayTree CASE "X" another$ = "" another% = 3 finished% = TRUE% LOCATE 22, 62 PRINT SPACE$(17); LOCATE 22, 62 PRINT "another (Y/N) "; LOCATE 22, 75, 1 DO WHILE another$ = "" another$ = INKEY$ LOOP IF UCASE$(another$) = "Y" THEN another% = TRUE% ELSEIF UCASE$(another$) = "N" THEN another% = FALSE% ELSE finished% = FALSE% LOCATE 22, 62 PRINT SPACE$(17); END IF CASE "N" LOCATE 6, 62 PRINT "Line Number:"; newlinenumber$ = "" LOCATE 6, 74, 1 DO WHILE newlinenumber$ = "" newlinenumber$ = INKEY$ LOOP IF ASC(newlinenumber$) < 48 OR ASC(newlinenumber$) > 57 THEN LOCATE 6, 62 PRINT SPACE$(17); GOTO menuend END IF newlinenumber% = VAL(newlinenumber$) IF ((newlinenumber% > highestline%) OR (newlinenumber% < 0)) THEN LOCATE 6, 62 PRINT SPACE$(18); LOCATE 6, 62 PRINT "High line is "; highestline% pause (5&) ELSE CLS PUT (0, 0), board linenumber% = newlinenumber% FOR i = 11 TO 88 piece$ = headboard(linenumber%, i) toy% = i \ 10: tox% = i MOD 10 tox% = (tox% - 1) * 60 toy% = 25 * (8 - toy%) CALL Move(0, 0, tox%, toy%, piece$, FALSE%) CurrBoard(i) = LatestBoard(i) ' update board array NEXT i lnode$ = headboard(linenumber%, 89) rnode$ = headboard(linenumber%, 90) temp$ = RTRIM$(lnode$) + rnode$ node.nodenumber = VAL(temp$) IF linenumber% = 0 THEN node.linenumber = 0 ELSE node.linenumber = linenumber% - 1 END IF END IF LOCATE 6, 62 PRINT SPACE$(17); IF (mallocbuf(curindex%).nodenumber MOD 2) THEN whitemove% = FALSE% ELSE whitemove% = TRUE% END IF linechange% = TRUE% curindex% = MAXMOVES CASE "?" help CASE "I" CALL linenumbers CASE "R" CALL RefreshBoard CASE "B" gameflow ("B") CASE "F" gameflow ("F") CASE "T" gameflow ("T") CASE "M" menu CASE "L" GOTOEOL END SELECT menuend: CALL printmenu InRegs.ax = 1 ' show mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) END SUB SUB Mouseinput STATIC lastx% ' x position at end of last call STATIC lasty% ' y position at end of last call DIM btright AS INTEGER ' boolean value of right button DIM btleft AS INTEGER ' boolean value of left button InRegs.ax = 3 ' Get Coordinate Info InRegs.bx = 3 ' view left and right buttons OutRegs.bx = 0 CALL INTERRUPT(51, InRegs, OutRegs) ' make mouse call IF OutRegs.bx = 2 THEN btright = TRUE 'find out if a button was IF OutRegs.bx = 1 THEN btleft = TRUE 'depressed or not IF btright THEN ' text entry CALL textnotes EXIT SUB END IF newx% = OutRegs.cx IF newx% > 480 THEN CALL menu ' call menu if right button EXIT SUB END IF newy% = OutRegs.dx xsqr% = lastx% \ 60 + 1 'the contents of each square are saved in ysqr% = 8 - lasty% \ 25 ' an array where the domain is of the form lastsqr$ = RTRIM$(STR$(ysqr%)) + LTRIM$(RTRIM$(STR$(xsqr%))) piece$ = LatestBoard(VAL(lastsqr$)) xsqr% = newx% \ 60 + 1 'the contents of each square are saved in ysqr% = 8 - newy% \ 25 ' an array where the domain is of the form newsqr$ = RTRIM$(STR$(ysqr%)) + LTRIM$(RTRIM$(STR$(xsqr%))) mycolor$ = LEFT$(piece$, 1) oldpiece$ = CurrBoard(VAL(newsqr$)) yourcolor$ = LEFT$(oldpiece$, 1) InRegs.ax = 5 ' get button press information InRegs.bx = 0 ' left button CALL INTERRUPT(51, InRegs, OutRegs) pressx% = OutRegs.cx pressy% = OutRegs.dx xsqr% = pressx% \ 60 + 1 'the contents of each square are saved in ysqr% = 8 - pressy% \ 25 ' an array where the domain is of the form presssqr$ = RTRIM$(STR$(ysqr%)) + LTRIM$(RTRIM$(STR$(xsqr%))) IF lastsqr$ = newsqr$ THEN 'no motion, maybe a capture IF ((NOT btleft) AND (NOT btright)) THEN ' buttons will be up IF CurrBoard(VAL(newsqr$)) <> LatestBoard(VAL(newsqr$)) THEN capture% = TRUE% CALL Move(lastx%, lasty%, newx%, newy%, piece$, capture%) CurrBoard(VAL(presssqr$)) = LatestBoard(VAL(presssqr$)) CurrBoard(VAL(newsqr$)) = LatestBoard(VAL(newsqr$)) CALL updatemovetree(VAL(presssqr$), VAL(newsqr$)) IF NOT linechange% THEN whitemove% = NOT whitemove% END IF notok% = isitillegal%(VAL(presssqr$), VAL(newsqr$)) IF notok% THEN CALL gameflow("T") ' do not allow user to ' capture his own men ' and do not count moving off ' and back on square as a move CALL lightupsqrs(VAL(presssqr$)) END IF END IF END IF ELSEIF btleft THEN ' move piece if left button capture% = FALSE% CALL Move(lastx%, lasty%, newx%, newy%, piece$, capture%) ' if we are covering up a piece with an exact image of it ' then it is invisible because of the XOR graphics we are ' using, so make it visible IF ((piece$ = CurrBoard(VAL(newsqr$))) AND (newsqr$ <> presssqr$)) THEN CALL Move(0, 0, newx%, newy%, piece$, capture%) END IF 'and refill it after moving off IF ((CurrBoard(VAL(lastsqr$)) = piece$) AND (presssqr$ <> lastsqr$)) THEN CALL Move(0, 0, lastx%, lasty%, piece$, capture%) END IF IF newsqr$ = presssqr$ THEN CALL lightupsqrs(VAL(presssqr$)) END IF END IF lastx% = newx% lasty% = newy% InRegs.ax = 1 ' show mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) LOCATE 1, 62 PRINT "Curr Linenum:"; TAB(77); linenumber% LOCATE 3, 62 PRINT "Curr NodeNum:"; TAB(77); node.nodenumber END SUB SUB Move (oldx%, oldy%, newx%, newy%, piece$, capture%) InRegs.ax = 2 ' hide mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) fromx% = oldx% \ 60 + 1 'the contents of each square are saved in fromy% = 8 - oldy% \ 25 ' an array where the domain is of the form fromsqr$ = RTRIM$(STR$(fromy%)) + LTRIM$(RTRIM$(STR$(fromx%))) ' rank-file IF CurrBoard(VAL(fromsqr$)) = piece$ THEN ' we are on the original LatestBoard(VAL(fromsqr$)) = "MT" ' from square ELSE ' so empty it LatestBoard(VAL(fromsqr$)) = CurrBoard(VAL(fromsqr$)) END IF 'otherwise reinstate the last piece that was on it tox% = newx% \ 60 + 1 'get the to square coordinates toy% = 8 - newy% \ 25 tosqr$ = RTRIM$(STR$(toy%)) + LTRIM$(RTRIM$(STR$(tox%))) ' rank-file LatestBoard(VAL(tosqr$)) = piece$ oldpiece$ = CurrBoard(VAL(tosqr$)) IF capture% THEN RSET material = LTRIM$(RTRIM$(oldpiece$)) END IF IF oldx% = 0 AND oldy% = 0 THEN 'this is a reset up GOTO resetup ' from the menu END IF IF capture% THEN resetup: SELECT CASE RTRIM$(LTRIM$(piece$)) CASE "KO" ' off of board - Keep Off CASE "MT" ' empty square CASE "BR" CALL GetBRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BN" CALL GetBKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BB" CALL GetBBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BQ" CALL GetBQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BK" CALL GetBKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BP" CALL GetBPawn(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WR" CALL GetWRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WN" CALL GetWKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WB" CALL GetWBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WQ" CALL GetWQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WK" CALL GetWKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WP" CALL GetWPawn(60 * (tox% - 1), 25 * (8 - toy%)) END SELECT IF oldx% = 0 AND oldy% = 0 THEN 'this is a reset up InRegs.ax = 1 CALL INTERRUPT(51, InRegs, OutRegs) EXIT SUB END IF SELECT CASE LTRIM$(RTRIM$(oldpiece$)) CASE "KO" ' off of board - Keep Off CASE "MT" ' empty square CASE "BR" CALL GetBRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BN" CALL GetBKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BB" CALL GetBBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BQ" CALL GetBQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BK" CALL GetBKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BP" CALL GetBPawn(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WR" CALL GetWRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WN" CALL GetWKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WB" CALL GetWBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WQ" CALL GetWQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WK" CALL GetWKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WP" CALL GetWPawn(60 * (tox% - 1), 25 * (8 - toy%)) END SELECT SELECT CASE LTRIM$(RTRIM$(piece$)) CASE "KO" ' off of board - Keep Off CASE "MT" ' empty square CASE "BR" CALL GetBRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BN" CALL GetBKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BB" CALL GetBBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BQ" CALL GetBQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BK" CALL GetBKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BP" CALL GetBPawn(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WR" CALL GetWRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WN" CALL GetWKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WB" CALL GetWBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WQ" CALL GetWQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WK" CALL GetWKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WP" CALL GetWPawn(60 * (tox% - 1), 25 * (8 - toy%)) END SELECT InRegs.ax = 1 ' make mouse cursor visible CALL INTERRUPT(51, InRegs, OutRegs) EXIT SUB END IF SELECT CASE RTRIM$(LTRIM$(piece$)) CASE "KO" ' off of board - Keep Off CASE "MT" ' empty square CASE "BR" CALL GetBRook(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BN" CALL GetBKnight(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BB" CALL GetBBishop(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BQ" CALL GetBQueen(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BK" CALL GetBKing(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "BP" CALL GetBPawn(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetBPawn(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WR" CALL GetWRook(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWRook(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WN" CALL GetWKnight(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWKnight(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WB" CALL GetWBishop(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWBishop(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WQ" CALL GetWQueen(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWQueen(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WK" CALL GetWKing(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWKing(60 * (tox% - 1), 25 * (8 - toy%)) CASE "WP" CALL GetWPawn(60 * (fromx% - 1), 25 * (8 - fromy%)) CALL GetWPawn(60 * (tox% - 1), 25 * (8 - toy%)) END SELECT InRegs.ax = 1 ' show mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) END SUB SUB NMoves (i%) ' knight moves j% = 0 IF (CurrBoard(i% + 8) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% + 8 END IF IF (i% + 19) < 100 THEN IF (CurrBoard(i% + 19) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% + 19 END IF END IF IF (i% + 21) < 100 THEN IF (CurrBoard(i% + 21) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% + 21 END IF END IF IF (i% + 12) < 100 THEN IF (CurrBoard(i% + 12) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% + 12 END IF END IF IF (i% - 8) > 10 THEN IF (CurrBoard(i% - 8) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% - 8 END IF END IF IF (i% - 19) > 10 THEN IF (CurrBoard(i% - 19) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% - 19 END IF END IF IF (i% - 21) > 10 THEN IF (CurrBoard(i% - 21) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% - 21 END IF END IF IF (i% - 12) > 10 THEN IF (CurrBoard(i% - 12) <> "KO") THEN j% = j% + 1 MoveList%(i%, j%) = i% - 12 END IF END IF END SUB SUB pause (n&) ' pause for n seconds a& = TIMER b& = TIMER WHILE b& - a& < n& b& = TIMER WEND END SUB SUB printmenu IF testing% THEN GOTO printlistnode LOCATE 1, 62 PRINT "Curr Linenum:"; TAB(77); linenumber% LOCATE 3, 62 PRINT "Curr NodeNum:"; TAB(77); node.nodenumber LOCATE 5, 62 PRINT "New Line num: "; TAB(78); "N" LOCATE 7, 62 PRINT "Help:"; TAB(78); "?" LOCATE 9, 62 PRINT "Incrmnt Linenum:"; TAB(78); CHR$(24) LOCATE 11, 62 PRINT "Dcrmnt Linenum:"; TAB(78); CHR$(25) LOCATE 13, 62 PRINT "Save Game:"; TAB(78); "S" LOCATE 15, 62 PRINT "Load game file:"; TAB(78); "G" LOCATE 17, 62 PRINT "Move Tree:"; TAB(78); "D" LOCATE 19, 62 PRINT "Line Info:"; TAB(78); "I"; "" LOCATE 21, 62 PRINT "Exit Program:"; TAB(78); "X" LOCATE 22, 62 PRINT "KEYBRD FLOW CTRL"; LOCATE 23, 65 PRINT "F"; TAB(70); "B"; TAB(75); "T"; LOCATE 24, 67 PRINT "L"; TAB(72); "R"; EXIT SUB printlistnode: LOCATE 1, 62 PRINT "Curr Linenum:"; TAB(77); mallocbuf(curindex%).linenumber LOCATE 3, 62 PRINT "Curr NodeNum:"; TAB(77); mallocbuf(curindex%).nodenumber LOCATE 5, 62 PRINT "From Square: "; mallocbuf(curindex%).fromsqr LOCATE 7, 62 PRINT "Help:"; TAB(78); "?" LOCATE 9, 62 PRINT "To Square:"; mallocbuf(curindex%).tosqr LOCATE 11, 62 PRINT "material:"; TAB(78); mallocbuf(curindex%).material LOCATE 13, 62 PRINT "Special:"; TAB(78); mallocbuf(curindex%).Special LOCATE 15, 62 PRINT "Next Index: "; mallocbuf(curindex%).ptr LOCATE 17, 62 PRINT "Prev Index:"; TAB(78); mallocbuf(curindex%).prev LOCATE 19, 62 PRINT "Line Info:"; TAB(78); "I"; "" LOCATE 21, 62 PRINT "Exit Program:"; TAB(78); "X" LOCATE 22, 62 PRINT "KEYBRD FLOW CTRL"; LOCATE 23, 65 PRINT "F"; TAB(70); "B"; TAB(75); "T"; LOCATE 24, 67 PRINT "L"; TAB(72); "R"; END SUB SUB Promotion (piece$) oldpiece$ = piece$ FOR i% = 1 TO 25 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% LOCATE 1, 62 PRINT "Promotion Pieces:"; LOCATE 6, 62 PRINT "Rook: (Enter R)"; LOCATE 11, 62 PRINT "Knight: (Enter N)"; LOCATE 16, 62 PRINT "Bishop: (Enter B)"; LOCATE 21, 62 PRINT "Queen: (Enter Q)"; MakeChoice: LOCATE 24, 62 PRINT "Make A Choice: "; LOCATE 24, 77, 1 interog$ = "" WHILE interog$ = "" interog$ = INKEY$ WEND SELECT CASE UCASE$(interog$) CASE "R" piece$ = "R" CASE "N" piece$ = "N" CASE "B" piece$ = "B" CASE "Q" piece$ = "Q" CASE ELSE GOTO MakeChoice END SELECT piece$ = RTRIM$(LEFT$(CurrBoard(mallocbuf(curindex%).tosqr), 1)) + LTRIM$(piece$) CALL Move(0, 0, ((mallocbuf(curindex%).tosqr MOD 10) - 1) * 60, (8 - (mallocbuf(curindex%).tosqr \ 10)) * 25, oldpiece$, FALSE%) CALL Move(0, 0, ((mallocbuf(curindex%).tosqr MOD 10) - 1) * 60, (8 - (mallocbuf(curindex%).tosqr \ 10)) * 25, piece$, FALSE%) FOR i% = 1 TO 25 LOCATE i%, 62 PRINT SPACE$(18); NEXT i% CALL printmenu END SUB SUB putx (tosqr%) IF Initing% THEN DEF SEG = VARSEG(xfig(1)) BLOAD "xfig.grh", VARPTR(xfig(1)) DEF SEG EXIT SUB END IF x% = ((tosqr% MOD 10) - 1) * 60 y% = (8 - tosqr% \ 10) * 25 PUT (x% + 10, y% - 5), xfig END SUB SUB QMoves (i%) ' queen moves CALL RMoves(i%) ' queens move like a b% = 0: c% = 0 ' combination of a rook FOR j% = 1 TO 14 ' and a bishop IF MoveList%(i%, j%) = 0 THEN ' square 89 is a dummy EXIT FOR ' square for storing ELSE ' "to" moves for moving b% = b% + 1 ' to the correct i%, j% END IF ' element when the NEXT j% ' "slots" are ready for FOR j% = 1 TO b% MoveList%(89, j%) = MoveList%(i%, j%) ' them MoveList%(i%, j%) = 0 NEXT j% CALL BMoves(i%) FOR j% = 1 TO 14 IF MoveList%(i%, j%) = 0 THEN EXIT FOR ELSE c% = c% + 1 END IF NEXT j% IF b% > 0 THEN FOR j% = 1 TO b% MoveList%(i%, c% + j%) = MoveList%(89, j%) NEXT j% END IF END SUB SUB RefreshBoard CLS SCREEN 2 VIEW SCREEN (0, 0)-(480, 199) ' graphics port PUT (0, 0), board FOR i = 11 TO 88 CALL Move(0, 0, ((i MOD 10) - 1) * 60, (8 - i \ 10) * 25, CurrBoard(i), FALSE%) LatestBoard(i) = CurrBoard(i) NEXT i END SUB SUB RMoves (i%) ' rook moves j% = 0 FOR k% = 10 TO 70 STEP 10 IF (CurrBoard(i% + k%) = "KO") THEN ' off of the board EXIT FOR ELSE j% = j% + 1 MoveList%(i%, j%) = i% + k% IF CurrBoard(i% + k%) <> "MT" THEN ' got to stop EXIT FOR ' after a capture END IF END IF NEXT k% FOR l% = -10 TO -70 STEP -10 IF (CurrBoard(i% + l%) = "KO") THEN ' off of the board EXIT FOR ELSE j% = j% + 1 MoveList%(i%, j%) = i% + l% IF CurrBoard(i% + l%) <> "MT" THEN ' got to stop EXIT FOR ' after a capture END IF END IF NEXT l% FOR m% = 1 TO 7 IF (CurrBoard(i% + m%) = "KO") THEN ' off of the board EXIT FOR ELSE j% = j% + 1 MoveList%(i%, j%) = i% + m% IF CurrBoard(i% + m%) <> "MT" THEN ' got to stop EXIT FOR ' after a capture END IF END IF NEXT m% FOR n% = -1 TO -7 STEP -1 IF (CurrBoard(i% + n%) = "KO") THEN ' off of the board EXIT FOR ELSE j% = j% + 1 MoveList%(i%, j%) = i% + n% IF CurrBoard(i% + n%) <> "MT" THEN ' got to stop EXIT FOR ' after a capture END IF END IF NEXT n% END SUB SUB RORax (n%) 'rotate OutRegs.ax by n% bits to the right RORstr$ = STR$(OutRegs.ax) i% = n% 'loop counter DO lsb$ = RIGHT$(RORstr$, 1) hbts$ = LEFT$(RORstr$, 15) RORstr$ = RTRIM$(lsb$) + LTRIM$(hbts$) i% = i% - 1 LOOP WHILE i% > 0 OutRegs.ax = VAL(RORstr$) 'return value (OutRegs is global) END SUB SUB SaveGame savtop: IF gamename$ <> "" THEN LOCATE 15, 62, 1 PRINT "Current File is: "; LOCATE 16, 62, 1 PRINT RTRIM$(gamename$); LOCATE 17, 62, 1 PRINT "hit to keep"; LOCATE 18, 62, 1 PRINT "name or enter a "; LOCATE 19, 62, 1 PRINT "new file name"; END IF LOCATE 14, 62: PRINT "?"; LOCATE 14, 64 filename$ = "" char$ = "" DO char$ = "" WHILE char$ = "" char$ = INKEY$ WEND IF ASC(char$) = 8 AND POS(0) <> 65 THEN LOCATE 14, POS(0) - 1, 1 ELSEIF char$ <> CHR$(13) THEN filename$ = RTRIM$(filename$) + LTRIM$(char$) PRINT char$; END IF LOOP UNTIL char$ = CHR$(13) IF char$ = CHR$(13) AND filename$ = "" THEN IF gamename$ = "" THEN LOCATE 14, 62 PRINT SPACE$(17); EXIT SUB ELSE filename$ = gamename$ END IF END IF BEEP dot% = INSTR(RTRIM$(LTRIM$(filename$)), ".") IF dot% > 9 OR (dot% = 0 AND LEN(RTRIM$(LTRIM$(filename$))) > 8) THEN LOCATE 14, 62 PRINT SPACE$(17); GOTO savtop ELSEIF LEN(RTRIM$(LTRIM$(filename$))) - dot% > 3 THEN LOCATE 14, 62: PRINT SPACE$(17); GOTO savtop ELSEIF LEN(LTRIM$(RTRIM$(filename$))) = 0 THEN LOCATE 14, 62 PRINT SPACE$(17); EXIT SUB END IF IF dot% = 0 THEN filename$ = RTRIM$(filename$) + LTRIM$(".") dot% = LEN(LTRIM$(RTRIM$(filename$))) END IF filenum = FREEFILE filename$ = RTRIM$(LEFT$(filename$, dot%)) + LTRIM$("GAM") OPEN filename$ FOR RANDOM AS filenum LEN = 16 IF error52% THEN error52% = FALSE% GOTO savtop ELSEIF error53% THEN error53% = FALSE% GOTO savtop ELSEIF error64% THEN error64% = FALSE% GOTO savtop ELSEIF error68% THEN error68% = FALSE% GOTO savtop ELSEIF error75% THEN error75% = FALSE% ELSEIF error76% THEN error76% = FALSE% GOTO savtop END IF FOR i = 0 TO MAXMOVES PUT #filenum, i + 1, mallocbuf(i) NEXT i CLOSE filenum filenum = FREEFILE filename$ = RTRIM$(LEFT$(filename$, dot%)) + LTRIM$("HBD") OPEN filename$ FOR RANDOM AS filenum LEN = 2 counter% = 0 FOR l = 0 TO highestline% FOR m = 11 TO 88 counter% = counter% + 1 PUT #filenum, counter%, headboard(l, m) NEXT m NEXT l CLOSE #filenum FOR i% = 1 TO 24 LOCATE i%, 62, 1 PRINT SPACE$(18); NEXT i% CALL printmenu gamename$ = filename$ END SUB SUB scroll (interog$) IF UCASE$(interog$) = CHR$(0) + CHR$(80) THEN 'scroll up InRegs.ax = 1536 InRegs.ax = InRegs.ax + 1 InRegs.bx = 1792 InRegs.cx = 0 InRegs.dx = 6223 CALL INTERRUPT(16, InRegs, OutRegs) ELSEIF UCASE$(interog$) = CHR$(0) + CHR$(72) THEN ' scroll down InRegs.ax = 1792 InRegs.ax = InRegs.ax + 1 InRegs.bx = 1792 InRegs.cx = 0 InRegs.dx = 6223 CALL INTERRUPT(16, InRegs, OutRegs) END IF END SUB SUB scrolltxt (ah%, al%, bh%, ch%, cl%, dh%, dl%) ' first get binary strings for high bit values ah$ = Bin2BinStr(ah%) bh$ = Bin2BinStr(bh%) ch$ = Bin2BinStr(ch%) dh$ = Bin2BinStr(dh%) ' get decimal values for registers ah% = gethigh%(ah$) bh% = gethigh%(bh$) ch% = gethigh%(ch$) dh% = gethigh%(dh$) ' set registers for interrupt InRegs.ax = al% + ah% InRegs.bx = bh% InRegs.cx = cl% + ch% InRegs.dx = dl% + dh% ' make video interrupt CALL INTERRUPT(16, InRegs, OutRegs) END SUB SUB Special ' handling of special moves like Castling IF RIGHT$(RTRIM$(CurrBoard(node.tosqr)), 1) <> "K" AND RIGHT$(RTRIM$(CurrBoard(node.tosqr)), 1) <> "P" THEN EXIT SUB ' Check for En Passant Capture IF RIGHT$(RTRIM$(CurrBoard(node.tosqr)), 1) = "K" THEN GOTO Castle WhiteEP: IF node.fromsqr \ 10 <> 5 THEN GOTO BlackEP IF node.tosqr \ 10 <> 6 THEN GOTO BlackEP oldfrom% = mallocbuf(mallocbuf(curindex%).prev).fromsqr oldto% = mallocbuf(mallocbuf(curindex%).prev).tosqr IF (oldto% MOD 10) <> (node.tosqr MOD 10) THEN GOTO BlackEP IF LTRIM$(RTRIM$(CurrBoard(oldto%))) <> "BP" THEN GOTO Promotion IF oldfrom% \ 10 - oldto% \ 10 <> 2 THEN GOTO BlackEP CurrBoard(oldto%) = "MT" CALL Move(0, 0, 60 * ((oldto% MOD 10) - 1), 75, "BP", FALSE%) node.Special = "EP" mallocbuf(curindex%).Special = "EP" node.material = "BP" mallocbuf(curindex%).material = "BP" GOTO SpecialExit BlackEP: IF node.fromsqr \ 10 <> 4 THEN GOTO Castle: IF node.tosqr \ 10 <> 3 THEN GOTO Castle: oldfrom% = mallocbuf(mallocbuf(curindex%).prev).fromsqr oldto% = mallocbuf(mallocbuf(curindex%).prev).tosqr IF (oldto% MOD 10) <> (node.tosqr MOD 10) THEN GOTO Promotion IF LTRIM$(RTRIM$(CurrBoard(oldto%))) <> "WP" THEN GOTO Promotion IF oldfrom% \ 10 - oldto% \ 10 <> -2 THEN EXIT SUB CurrBoard(oldto%) = "MT" CALL Move(0, 0, 60 * ((oldto% MOD 10) - 1), 100, "WP", FALSE%) node.Special = "EP" mallocbuf(curindex%).Special = "EP" node.material = "WP" mallocbuf(curindex%).material = "WP" GOTO SpecialExit Castle: IF RIGHT$(RTRIM$(CurrBoard(node.tosqr)), 1) <> "K" THEN GOTO Promotion IF LEFT$(CurrBoard(node.tosqr), 1) = "W" AND node.fromsqr <> 15 THEN GOTO Promotion IF LEFT$(CurrBoard(node.tosqr), 1) = "B" AND node.fromsqr <> 85 THEN GOTO Promotion IF LEFT$(CurrBoard(node.tosqr), 1) = "W" THEN IF ((node.tosqr = 17) OR (node.tosqr = 13)) THEN IF node.tosqr = 17 THEN node.Special = "CK" mallocbuf(curindex%).Special = "CK" ELSE node.Special = "CQ" mallocbuf(curindex%).Special = "CQ" END IF IF node.Special = "CK" THEN CALL Move(0, 0, 420, 175, "WR", FALSE%) CALL Move(0, 0, 300, 175, "WR", FALSE%) CurrBoard(18) = "MT" CurrBoard(16) = "WR" ELSEIF node.Special = "CQ" THEN CALL Move(0, 0, 0, 175, "WR", FALSE%) CALL Move(0, 0, 180, 175, "WR", FALSE%) CurrBoard(11) = "MT" CurrBoard(14) = "WR" END IF END IF ELSE IF ((node.tosqr = 87) OR (node.tosqr = 83)) THEN IF node.tosqr = 87 THEN node.Special = "CK" mallocbuf(curindex%).Special = "CK" ELSE node.Special = "CQ" mallocbuf(curindex%).Special = "CQ" END IF IF node.Special = "CK" THEN CALL Move(0, 0, 420, 0, "BR", FALSE%) CALL Move(0, 0, 300, 0, "BR", FALSE%) CurrBoard(88) = "MT" CurrBoard(86) = "BR" ELSEIF node.Special = "CQ" THEN CALL Move(0, 0, 0, 0, "BR", FALSE%) CALL Move(0, 0, 180, 0, "BR", FALSE%) CurrBoard(81) = "MT" CurrBoard(84) = "BR" END IF END IF END IF GOTO SpecialExit Promotion: piece$ = CurrBoard(mallocbuf(curindex%).tosqr) IF ((LTRIM$(RTRIM$(piece$)) = "BP") AND (mallocbuf(curindex%).tosqr \ 10 = 1)) THEN CALL Promotion(piece$) node.Special = RTRIM$("P") + LTRIM$(RIGHT$(piece$, 1)) END IF IF ((LTRIM$(RTRIM$(piece$)) = "WP") AND (mallocbuf(curindex%).tosqr \ 10 = 8)) THEN CALL Promotion(piece$) node.Special = RTRIM$("P") + LTRIM$(RIGHT$(piece$, 1)) END IF IF node.Special <> "RM" THEN mallocbuf(curindex%).Special = node.Special CurrBoard(mallocbuf(curindex%).tosqr) = LTRIM$(RTRIM$(piece$)) END IF SpecialExit: IF node.Special <> "RM" THEN FOR i% = 11 TO 88 LatestBoard(i%) = CurrBoard(i%) NEXT i% END IF END SUB SUB TextMsg (msg$) InRegs.ax = 2 ' hide mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) '$DYNAMIC DIM scrnsave(1 TO 4045) ' save current screen GET (0, 0)-(639, 199), scrnsave CLS 'erase screen and display menu in text mode SCREEN 0 ' text mode in color COLOR 1, 7, 4 ' white background, blue foreground, red border LOCATE 12, 20 PRINT msg$ pause (5) CLS SCREEN 2 'restore graphical display PUT (0, 0), scrnsave VIEW SCREEN (0, 0)-(480, 199) ' graphics port ERASE scrnsave 'deallocate array memory InRegs.ax = 1 ' display cursor CALL INTERRUPT(51, InRegs, OutRegs) END SUB REM $STATIC SUB textnotes ' read and write text notes InRegs.ax = 2 ' hide mouse cursor CALL INTERRUPT(51, InRegs, OutRegs) ' next create file name for notes gethename: IF gamename$ = "" THEN LOCATE 1, 62, 1 PRINT "There is no "; LOCATE 2, 62, 1 PRINT "current game name"; LOCATE 3, 62, 1 PRINT "Please set one "; LOCATE 4, 62, 1 PRINT "now. "; LOCATE 5, 62, 1 PRINT " "; LOCATE 4, 67, 1 INPUT filename$ dot% = INSTR(RTRIM$(LTRIM$(filename$)), ".") IF dot% > 9 OR (dot% = 0 AND LEN(RTRIM$(LTRIM$(filename$))) > 8) THEN LOCATE 5, 62, 1 PRINT "bad name"; pause (3&) LOCATE 5, 62, 1 PRINT SPACE$(18); GOTO gethename ELSEIF LEN(RTRIM$(LTRIM$(filename$))) - dot% > 3 THEN LOCATE 5, 62, 1 PRINT "bad name"; pause (3&) LOCATE 5, 62, 1 PRINT SPACE$(18); GOTO gethename ELSEIF LEN(LTRIM$(RTRIM$(filename$))) = 0 THEN LOCATE 5, 62, 1 PRINT "bad name"; pause (3&) LOCATE 5, 62, 1 PRINT SPACE$(18); GOTO gethename END IF gamename$ = filename$ END IF dot% = INSTR(RTRIM$(LTRIM$(gamename$)), ".") IF dot% > 0 THEN dirname$ = LEFT$(gamename$, dot% - 1) ELSE dirname$ = gamename$ END IF MKDIR dirname$ textnode$ = STR$(mallocbuf(curindex%).nodenumber) textline$ = STR$(linenumber%) nodelen% = LEN(LTRIM$(RTRIM$(textnode$))) linelen% = LEN(LTRIM$(RTRIM$(textline$))) WHILE nodelen% < 3 textnode$ = RTRIM$("0") + LTRIM$(textnode$) nodelen% = LEN(LTRIM$(RTRIM$(textnode$))) WEND WHILE linelen% < 2 textline$ = RTRIM$("0") + LTRIM$(textline$) linelen% = LEN(LTRIM$(RTRIM$(textline$))) WEND filname$ = RTRIM$(dirname$) + LTRIM$(RTRIM$("\TXT")) + LTRIM$(RTRIM$(textline$)) + LTRIM$(RTRIM$(textnode$)) + LTRIM$(".DAT") filnum% = FREEFILE ' get new filenumber OPEN filname$ FOR RANDOM AS filnum% LEN = 16 'open file and get size to filsize% = LOF(filnum%) \ 16 IF filsize% < 24 THEN filsize% = 24 END IF REDIM textarray(1 TO filsize%) AS STRING * 16 ' dimension arrays REDIM addendum(filsize% + 1 TO filsize% + 100) AS STRING * 16 ' for new notes 'Now load file into textarray recnum% = 0 WHILE recnum% < filsize% recnum% = recnum% + 1 GET #filnum%, recnum%, textarray(recnum%) IF EOF(filnum%) THEN LSET textarray(recnum%) = STRING$(16, "*") END IF WEND ' clear off text already on screen CALL scrolltxt(6, 24, 7, 0, 61, 23, 79) ' Now put whatever text we have on the screen FOR i% = 1 TO 24 LOCATE i%, 62, 1 PRINT textarray(i%); NEXT i% i% = 24 highi% = i% ' highest array element + 1 of text on screen LOCATE 1, 62, 1 ' locate text cursor to bottom of text textlooptop: char$ = "" WHILE char$ = "" char$ = INKEY$ WEND SELECT CASE char$ CASE CHR$(4) ' CTR-D scrolls up CALL crsrpos(0) 'save cursor position CALL scrolltxt(6, 1, 7, 0, 61, 23, 79) i% = i% + 1 LOCATE 24, 62, 1 IF i% < filsize% + 1 THEN PRINT textarray(i%); ELSEIF i% < filsize% + 101 THEN PRINT addendum(i%); END IF CALL crsrpos(-1) 'restore cursor position CASE CHR$(21) ' CTRL-U scrolls down IF i% > 24 THEN i% = i% - 1 CALL crsrpos(0) 'save cursor position CALL scrolltxt(7, 1, 7, 0, 61, 23, 79) LOCATE 1, 62, 1 IF ((i% - 23) <= filsize%) THEN PRINT textarray(i% - 23); ELSEIF (i% <= (filesize% + 101)) THEN PRINT addendum(i%); END IF CALL crsrpos(-1) 'restore cursor position END IF CASE CHR$(0) + CHR$(72) 'up-arrow moves cursor up IF CSRLIN > 1 THEN LOCATE CSRLIN - 1, 62, 1 CALL crsrpos(0) ' record new position END IF CASE CHR$(0) + CHR$(80) ' down-arrow moves cursor down IF CSRLIN < 24 THEN LOCATE CSRLIN + 1, 62, 1 CALL crsrpos(0) ' record new position END IF CASE CHR$(17) ' CTRL-Q to end GOTO textloopbot END SELECT IF ASC(char$) > 31 AND ASC(char$) < 127 THEN 'got a printable char IF POS(0) < 78 THEN PRINT char$; ' save array element temp$ = "" FOR k% = 62 TO 77 n% = SCREEN(CSRLIN, k%) n$ = CHR$(n%) temp$ = temp$ + n$ NEXT k% k% = i% - 24 + CSRLIN IF k% < filsize% + 1 THEN LSET textarray(k%) = temp$ PUT filnum%, k%, textarray(k%) ELSEIF k% < filsize% + 102 THEN LSET addendum(k%) = temp$ PUT filnum%, k%, addendum(k%) END IF ELSE IF CSRLIN > 23 THEN i% = i% + 1 CALL scrolltxt(6, 1, 7, 0, 61, 23, 79) LOCATE CSRLIN, 62, 1 ELSE LOCATE CSRLIN + 1, 62, 1 END IF PRINT char$; CALL crsrpos(0) END IF END IF IF ASC(char$) = 8 THEN ' backspace IF POS(0) > 62 THEN LOCATE CSRLIN, POS(0) - 1, 1 PRINT SPACE$(1); LOCATE CSRLIN, POS(0) - 1, 1 CALL crsrpos(0) END IF END IF IF i% > highi% THEN highi% = i% END IF GOTO textlooptop textloopbot: CLOSE filnum% LOCATE 1, 62, 1 ' clear text from screen FOR i% = 1 TO 24: LOCATE i%, 62: PRINT SPACE$(18); : NEXT i% CALL printmenu 'display menu END SUB FUNCTION traverse% (nodenumber%, linenumber%) ' traverse linked list FOR i = 0 TO MAXMOVES IF nodenumber% = -1 THEN IF i = 0 THEN lastline% = -1 ELSE IF mallocbuf(i).prev <> -1 THEN lastline% = mallocbuf(mallocbuf(i).prev).linenumber END IF END IF IF mallocbuf(i).linenumber = linenumber% AND lastline% <> linenumber% THEN EXIT FOR END IF ELSE IF ((mallocbuf(i).linenumber = linenumber%) AND (mallocbuf(i).nodenumber = nodenumber%)) THEN EXIT FOR END IF END IF NEXT i traverse% = i END FUNCTION SUB updatemovetree (fromsqr%, tosqr%) IF fromsqr% = 0 THEN EXIT SUB END IF node.nodenumber = node.nodenumber + 1 node.linenumber = linenumber% node.fromsqr = fromsqr% node.tosqr = tosqr% RSET node.material = material CALL insertafter END SUB SUB WKMoves (i%) CALL KMoves(i%) b% = 0 FOR j% = 1 TO 8 IF MoveList%(i%, j%) = 0 THEN EXIT FOR ELSE b% = b% + 1 END IF NEXT j% IF i% = 15 AND CurrBoard(11) = "WR" AND CurrBoard(12) = "MT" AND CurrBoard(13) = "MT" AND CurrBoard(14) = "MT" THEN b% = b% + 1 MoveList%(i%, b%) = 13 END IF IF i% = 15 AND CurrBoard(18) = "WR" AND CurrBoard(16) = "MT" AND CurrBoard(17) = "MT" THEN b% = b% + 1 MoveList%(i%, b%) = 17 END IF END SUB SUB WPMoves (i%) ' legal white pawn moves in given node j% = 0 IF CurrBoard(i% + 10) = "MT" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 10 IF CurrBoard(i% + 20) = "MT" AND (i% \ 10 = 2) THEN j% = j% + 1 MoveList%(i%, j%) = i% + 20 END IF END IF IF CurrBoard(i% + 9) <> "MT" AND CurrBoard(i% + 9) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 9 END IF IF CurrBoard(i% + 11) <> "MT" AND CurrBoard(i% + 11) <> "KO" THEN j% = j% + 1 MoveList%(i%, j%) = i% + 11 END IF IF CurrBoard(i% - 1) = "BP" THEN IF mallocbuf(curindex%).fromsqr \ 10 = 7 THEN IF mallocbuf(curindex%).tosqr \ 10 = 5 THEN IF i% \ 10 = 5 THEN IF (i% MOD 10) = (mallocbuf(curindex%).tosqr MOD 10) + 1 THEN j% = j% + 1 MoveList%(i%, j%) = i% + 9 END IF END IF END IF END IF END IF IF CurrBoard(i% + 1) = "BP" THEN IF mallocbuf(curindex%).fromsqr \ 10 = 7 THEN IF mallocbuf(curindex%).tosqr \ 10 = 5 THEN IF i% \ 10 = 5 THEN IF (i% MOD 10) = (mallocbuf(curindex%).tosqr MOD 10) - 1 THEN j% = j% + 1 MoveList%(i%, j%) = i% + 11 END IF END IF END IF END IF END IF END SUB *********************************************************************************** ' chess board ' $DYNAMIC DIM board(1 TO 4045) 'array to hold board SCREEN 2 ' my Tandy 1100FD uses CGA graphics ' ' use coordinate system where 0,0 is the corner of Black's QR square, ' and 639,199 is the corner of White's KR square WINDOW SCREEN (0, 0)-(639, 199) ' just set coordinate system ' FOR f% = 0 TO 639 STEP 80 ' draw files LINE (f%, 0)-(f%, 199) NEXT f% LINE (639, 0)-(639, 199) ' FOR r% = 0 TO 199 STEP 25 ' draw ranks LINE (0, r%)-(639, r%) NEXT r% LINE (0, 199)-(639, 199) ' clr% = 0 ' color of squares - 0 is black, 15 is white xstart% = 0: ystart% = 0'we are starting at the upper left corner of the screen DO WHILE ystart% < 199 DO WHILE xstart% < 639 IF clr% = 0 THEN clr% = 15 ELSE clr% = 0 END IF FOR x% = xstart% + 1 TO xstart% + 79 FOR y% = ystart% + 1 TO ystart% + 24 IF clr% = 15 THEN PSET (x%, y%), clr% END IF NEXT y% NEXT x% xstart% = xstart% + 80 LOOP IF clr% = 0 THEN clr% = 15 ELSE clr% = 0 END IF xstart% = 0 ystart% = ystart% + 25 LOOP GET (0, 0)-(639, 199), board 'put board in array for saving DEF SEG = VARSEG(board(1)) 'set segment to beggining of board array BSAVE "board.grh", VARPTR(board(1)), 16180 DEF SEG 'set segment back to DGROUP interog$ = "" WHILE interog$ = "": interog$ = INKEY$: WEND END ************************************************************************************ 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((30*1/1+7)/8)) = 164 DIM bishop(1 TO 164) ' array to hold graphical picture of bishop SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 10" 'draw left 10 units DRAW "R 20" 'draw right 20 units CIRCLE (320, 100), 10, 15, 0, .785397 'draw right side of bishop base CIRCLE (320, 100), 10, 15, 2.356196, 3.141593 'draw left side of bishop base DRAW "B M 314,96" 'put graphics cursor there DRAW "M +0,-7" 'draw left side upright DRAW "B M 326,96" 'put graphics cursor on right DRAW "M +0,-7" 'draw right side upright DRAW "R 6" 'draw right side of tops bot DRAW "L 24" 'draw left side of tops bot DRAW "B R 12" 'move to center of tops bot DRAW "B D 10" 'move to interior of bishop PAINT STEP(0, 0), BTile$ 'paint interior "white" DRAW "B U 10" 'get back to center of circle DRAW "B R 12" 'goto right side of top CIRCLE STEP(-12, 0), 12, 15, 0, 3.141593, 1 'draw bishops hat DRAW "B U 8" 'get inside hat PAINT STEP(0, 0), BTile$ 'paint it white 'DRAW "D 6 C15" ' paint cross 'DRAW "B U3 C15" ' goto midpoint of cross 'DRAW "L 3 C15" 'DRAW "R 6 C15" ' draw crossmember of cross GET (305, 77)-(335, 100), bishop 'store image in bishop array DEF SEG = VARSEG(bishop(1)) 'set segment to beginning of bishop array BSAVE "bbishop.grh", VARPTR(bishop(1)), 656 'this is a white piece DEF SEG 'set segment back to DGROUP END ************************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((49*1/1+7)/8)) = 164 DIM king(1 TO 284) ' array to hold graphical picture of king WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 15" 'draw left 10 units DRAW "R 30" 'draw right 20 units) CIRCLE STEP(-15, 0), 15, 15, 0, .75, 1 'right side of king CIRCLE STEP(0, 0), 15, 15, 3.141593 - .75, 3.141593, 1 'left side of king DRAW "B M+11,-10" DRAW "M-11,+4" DRAW "M-11,-4" PAINT STEP(5, 5), WTile$ ' white piece DRAW "C15" DRAW "B U 5" DRAW "B R 5" DRAW "U 2" DRAW "D 4" DRAW "U 2" DRAW "R 2" DRAW "L 4" GET (285, 80)-(335, 100), king 'store image in king array DEF SEG = VARSEG(king(1)) 'set segment to beggining of king array BSAVE "wking.grh", VARPTR(king(1)), 1136 'this is a white king DEF SEG 'set segment back to DGROUP END **************************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((49*1/1+7)/8)) = 164 DIM knight(1 TO 284) ' array to hold graphical picture of knight WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 10" 'draw left 10 units DRAW "R 20" 'draw right 20 units) FOR i = 330 TO 310 STEP -1 ' knight faces left PSET (i, 100 + 10 * COS(3.141593 + 3.141593 * (i - 300) / 60)), 15 NEXT i DRAW "M -2,-4" ' draw an ear DRAW "M -2,+4" FOR i = 306 TO 300 STEP -1 ' forhead PSET (i, 100 + 10 * COS(3.141593 + 3.141593 * (i - 300) / 60)), 15 NEXT i DRAW "M -2,-4" ' draw second ear DRAW "M -2,+4" FOR i = 296 TO 292 STEP -1 ' getting to the snout PSET (i, 100 + 10 * COS(3.141593 + 3.141593 * (i - 300) / 60)), 15 NEXT i DRAW "M -3,+5" 'top of the snout CIRCLE STEP(3, 1), 4, 15, 3.141593 'tip of the snout DRAW "B M +3,+2" 'move cursor DRAW "M +3,-5" 'underside of snout DRAW "TA 45 D 8" 'down at an angle - finish the figure DRAW "B R 3" DRAW "B U 3" PAINT STEP(0, 0), WTile$ ' white piece GET (285, 80)-(334, 100), knight 'store image in knight array DEF SEG = VARSEG(knight(1)) 'set segment to beggining of knight array BSAVE "wknight.grh", VARPTR(knight(1)), 1136 'this is a white knight DEF SEG 'set segment back to DGROUP END **************************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((30*1/1+7)/8)) = 164 DIM pawn(1 TO 164) ' array to hold graphical picture of pawn WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 10" 'draw left 10 units DRAW "R 20" 'draw right 20 units CIRCLE (320, 100), 10, 15, 0, .785397 'draw right side of pawn base CIRCLE (320, 100), 10, 15, 2.356196, 3.141593 'draw left side of pawn base DRAW "B M 314,96" 'put graphics cursor there DRAW "M +0,-10" 'draw left side upright DRAW "B M 326,96" 'put graphics cursor on right DRAW "M +0,-10" 'draw right side upright DRAW "R 6" 'draw right side of tops bot DRAW "L 24" 'draw left side of tops bot DRAW "B R 12" 'move to center of tops bot DRAW "B D 10" 'move to interior of pawn PAINT STEP(0, 0), BTile$ 'paint interior "white" DRAW "B U 10" 'get back to center of circle CIRCLE STEP(0, 0), 10, 15, 0, 3.141593 'draw the top of the top DRAW "B U 2" 'get into top PAINT STEP(0, 0), BTile$ 'paint it white GET (305, 80)-(335, 100), pawn 'store image in pawn array DEF SEG = VARSEG(pawn(1)) 'set segment to beggining of pawn array BSAVE "bpawn.grh", VARPTR(pawn(1)), 656 'this is a white pawn DEF SEG 'set segment back to DGROUP END *************************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((49*1/1+7)/8)) = 164 DIM queen(1 TO 284) ' array to hold graphical picture of queen WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 15" 'draw left 10 units DRAW "R 30" 'draw right 20 units) CIRCLE STEP(-15, 0), 15, 15, 0, .75, 1 'right side of queen CIRCLE STEP(0, 0), 15, 15, 3.141593 - .75, 3.141593, 1 'left side of queen DRAW "B M+11,-10" DRAW "M-2,+4" DRAW "M-3,-4" DRAW "M-3,+4" DRAW "M-3,-4" DRAW "M-3,+4" DRAW "M-3,-4" DRAW "M-3,+4" DRAW "M-2,-4" PAINT STEP(5, 5), WTile$ ' white piece GET (285, 80)-(335, 100), queen 'store image in queen array DEF SEG = VARSEG(queen(1)) 'set segment to beginning of queen array BSAVE "wqueen.grh", VARPTR(queen(1)), 1136 'this is a white queen DEF SEG 'set segment back to DGROUP END ****************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((30*1/1+7)/8)) = 164 DIM rook(1 TO 164) ' array to hold graphical picture of rook WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics DRAW "C15" 'Set color to bright white (shows up as black!) DRAW "B M 320,100" 'put cursor in center of screen DRAW "L 10" 'draw left 10 units DRAW "R 20" 'draw right 20 units CIRCLE (320, 100), 10, 15, 0, .785397 'draw right side of rook base CIRCLE (320, 100), 10, 15, 2.356196, 3.141593 'draw left side of rook base DRAW "B M 314,96" 'put graphics cursor there DRAW "M +0,-10" 'draw left side upright DRAW "B M 326,96" 'put graphics cursor on right DRAW "M +0,-10" 'draw right side upright DRAW "R 6" 'draw right side of tops bot DRAW "L 24" 'draw left side of tops bot DRAW "B R 12" 'move to center of tops bot DRAW "B D 10" 'move to interior of rook PAINT STEP(0, 0), WTile$ 'paint interior "white" DRAW "C 15" DRAW "B U 10" 'get back to center of circle DRAW "B R 12" 'goto right side of top DRAW "U 5" 'draw top right upright FOR i = 1 TO 2 DRAW "L 5" ' draw top of top DRAW "D 2" DRAW "L 5" DRAW "U 2" NEXT i DRAW "L 4" DRAW "D 5" ' draw left side of top DRAW "B R 2" DRAW "B U 2" 'get into top PAINT STEP(0, 0), WTile$ 'paint it white GET (305, 77)-(335, 100), rook 'store image in rook array DEF SEG = VARSEG(rook(1)) 'set segment to beggining of pawn array BSAVE "wrook.grh", VARPTR(rook(1)), 656 'this is a white pawn DEF SEG 'set segment back to DGROUP END ************************************************************************************** ' Code to create tiles WTile$ = CHR$(&H41) + CHR$(&H49) + CHR$(&H45) + CHR$(&H55) + CHR$(&H22) BTile$ = CHR$(&H38) + CHR$(&H24) + CHR$(&H24) + CHR$(&H28) + CHR$(&H30) + CHR$(&H30) + CHR$(&H28) + CHR$(&H24) + CHR$(&H24) + CHR$(&H38) **************************************************************************************** 'calculate the size of an array to hold the following graphics screen ' size in bytes = 4 + 40*1*INT((30*1/1+7)/8)) = 164 ' to be displayed when we need to light up a swuare DIM xfig(1 TO 164) ' array to hold graphics SCREEN 2 'My Tandy 1100FD is monochrome with CGA graphics CIRCLE (320, 100), 20, 15 PAINT STEP(0, 0), 15, 15 'paint it white GET (305, 77)-(335, 100), xfig 'store image in array DEF SEG = VARSEG(xfig(1)) 'set segment to beginning of figure array BSAVE "xfig.grh", VARPTR(xfig(1)), 656 'this is a white figure DEF SEG 'set segment back to DGROUP END **************************************************************************************** READ.ME file I wrote TakeNote about 11 years ago (near the start of 1993) after having a discussion with a chess master about how to study the game. This master told me that he studied games on ChessMaster 2000 (it was up to 5000 the last time I looked). The probem with using a chess program is that you can only enter one line of play at a time. When you go through a game in a chess book, the annotator branches off into multiple lines of play from interesting points in the game; e.g., interesting would be... . So you want a a program that is capable of brancing off from the main line of play into different lines, where it can branch off from branches, branch off from those branches, etc. You also want to be able to jump around to different lines of play from any other line, enter notes at each node of play, traverse each line of play in a forwards or backwards fashion. I.e., you want to be able to create a full game tree, complete with annotations (just like what you read in a chess book). You can accomplish all of this with TakeNote. You start the program from the command line; C:\>Taken661 Once the board comes up you can move pieces with you mouse (I didn't bother adding cursor control of the pieces; common back in the MS/DOS days) but if you want to take advantage of TakeNote's features you must move your mouse cursor into the menu field on the right side of the screen. E.g., you can change lines with the up and down cursor keys, but only if you move your mouse cursor into the menu field. Most of the menu controls can be brought up by clicking on them but there are also keys you can press for the same effect but only if you mouse cursor is in the menu field. The controls at the bottom of the menu are key only; e.g., 'B' moves you Backwards along a line of play, 'T' takes back a move (and all the moves after it along that line of play), etc. The reason why I'm uplloading this version of TakeNote after writting it back in 1995 (around then, anyway) is that I recently saw TakeNote 6.1 still on the Internet. 6.1 was very buggy but it contained a lot of "new" features I wanted uploaded. By the time I came up with TakeNote 6.61 I was too busy in a new job as an AS/400 software engineer out in Orange County, California. By the time I could finally consider working on TakeNote again, my "new" wife had trashed a boxload of floppies I'd been saving; yes, TakeNote was on one of those floppies. Fortunately I found TakeNote 6.61 on a "scratch" floppy just a few days ago (as of this writting on 12/31/2003). However, I don't have my original copy of QuickBASIC 4.5, the language I wrote this in, so I am supplying source code. You can download QuickBASIC 4.5 from http://www.mofunzone.com/downloadsoftware/14000000036569.shtml The main program to compile is TAKEN661.BAS, and everything else is already built; the graphics for BOARD.GRH, and all the pieces. The graphics files were developed on a Tandy 1100 laptop, so you might want to "enhance" them. TakeNote isn't 100% bug free either, but I've gone through games on it like the Scotch and branched off to the Scotch Gambit without any problem. One problem with TakeNote is that I wanted to prove that the data types supported by GWBASIC were capable of supporting a chess program; e.g., the lines are stored on array representations of linked lists and are all stored in the same array, etc. I thought of abandoning my original idea and using real linked lists created with real pointers, etc. However, the program is very full featured; e.g., illegal moves are retracted automatically by TakeNote and the legal moves for that piece are lit up for three seconds. There are enough bug fixes and enhancements in 6.61 to be worthwhile to a 6.1 user. Sincerely, David Katelansky david_katelansky@yahoo.com 12-DEC-2003. NOTE (25-AUG-2012): I was going through some CDs and DVDs I've put back ups on and I found TakeNote 6.61 on one of them. I wrote TakeNote 19 years ago and this is the last version I created, two years later. The code might look old fashioned (it was written for MS/DOS) but it's clean and could be easily applied to a newer language then MS QuickBASIC (one of my all time favorite languages).