? COMPILE 0WITA3/DISK WITH XALGOL LIBRARY ? XALGOL STACK=1200 ? XALGOL FILE LINE=LISTING/WITA3 BACK UP DISK ? DATA CARD $ CARD LIST SINGLE % BURROUGHS B-5500 XALGOL COMPILER LEVEL 27 TUESDAY, 8/11/70, 2:07 PM BEGIN COMMENT THIS PROGRAM NO LONGER REQUIRES PERMANENT DISC STORAGE FOR THE GAME-RECORD AND THE TREE. THE TREE IS HELD IN MEMORY ARRAYS STATES AND MOVES. THE GAME-RECORD IS ON A "SCRATCH" FILE; % 1 AUG COMMENT TO B-5500 OPERATOR FOR YOUNG AND RUBICAM. PLEASE MAIL THIS LISTING TO DR. T.A. MARSLAND, TELEPHONE 201-949-7310 ROOM 4E-618, BELL TELEPHONE LABS., HOLMDEL, N.J., 07733. MANY THANKS, TONY M. ; % PROGRAM WRITTEN FOR THE B-5500 IN B-6500 COMPATIBLE ALGOL. % LAST REVISION 1 JULY 1970 COMMENT WITA, A CHESS PLAYING PROGRAM BY T.A. MARSLAND. ***** MOST OF THE I/O ROUTINES WERE TAKEN FROM A PROGRAM COMPLETED BY R.W. STUBBLEFIELD IN 1967. WORK ON THE CURRENT VERSION BEGAN AT THE UNIVERSITY OF WASHINGTON IN MAR 1968 AND IS BEING CONTINUED AS A HOBBY WHILE AT BELL LABS. HOLMDEL. ******************PREAMBLE**************** ("DO YOU WANT TO PLAY BOTH SIDES:"--COMPUTER) IF ("YES"--USER) THEN ("COMPUTER TO PLAY ITSELF"--COMPUTER) IF ("YES"--USER) THEN COMPUTER TO PLAY BOTH SIDES ELSE BEGIN USER MUST INPUT MOVES FOR BOTH WHITE AND BLACK. END ("DO YOU WANT A NEW GAME:"--COMPUTER) IF ("YES"--USER) THEN BEGIN COMPUTER SETS BOARD TO A NEW GAME, PLAY: IF USER PLAYS BOTH SIDES THEN BEGIN ("1 "--COMPUTER), READ WHITES MOVE, ETC., END ELSE BEGIN ("DO YOU WANT WHITE OR BLACK"--COMPUTER) IF ("WHITE"--USER) THEN USER SUPPLIES FIRST MOVE ELSE THE COMPUTER MOVES. END ELSE BEGIN ("YOU SET THE BOARD THEN:"--COMPUTER), USER TYPES DESIRED BOARD POSITION, FOR EXAMPLE,("K/KN1,Q/Q4,K/KN1,P/KN2." --USER) MEANS THAT WHITE HAS HIS KING ON HIS KN1 AND A QUEEN ON Q4 AND BLACK HAS HIS KING ON HIS KN1 AND A PAWN ON HIS KN2. NOTE WHITE-S MEN ARE LISTED FIRST SEPARATED BY COMMAS. A PERIOD INDICATES THAT THE FOLLOWING MEN ARE BLACK. THERE SHOULD ALWAYS BE ONE KING OF EACH COLOUR. ALTERNATIVELY, USE THE SHORTHAND NOTATION. FOR EXAMPLE, $6K18830.8888886P16K. THE DOLLAR SIGN IS USED TO SPECIFY THAT THE SHORTHAND NOTATION FOLLOWS. ("WHOSE MOVE WHITE OR BLACK"--COMP) COMP MOVES PIECE OF RIGHT COLOUR END. DURING PLAY MOVES ARE MADE IN STANDARD CHESS NOTATION. AN INPUT OF "ST" AT ANY TIME WILL CAUSE THE PRO- GRAM TO TERMINATE. A TRACING PROCEDURE IS ENTERED IF THE FIRST SYMBOL TYPED IS "*". DIFFERENT ACTIONS ARE TAKEN DEPENDING ON THE CHARACTERS WHICH FOLLOW. 0-- SPECIAL OPTION WHICH REVERSES THE CHECK FOR LEGAL MOVES. ALLOWS ONE TO RETRACT MOST MOVES. EXPLICITLY MENTION SQUARES, E.G.,PIECE/SQUAREFROM * PIECE/SQUARETO. 1--NEGATES TERMINAL DEBUG OPTION. 2--NEGATES THE OPPONENTS MOBILITY SCORE OPTION. 3--WRITE THE PRESENT BOARD POSITION. 4--THE COMPUTER WILL PLAY ALTERNATE MOVES HEREAFTER 5--THE USER WILL CONTINUE BY PLAYING BOTH SIDES. 6--START AGAIN AT THE BEGINNING. 7--IF LOOKAHEAD ON THEN NEGATES PRINTING OF MOVE TREE ELSE NEGATES RANDOM MOVE SELECTION. 8--WRITE AN EXPLANATION OF THE DYNAMIC CONTROL PARAMETERS. 9--WRITE THE NUMBER AND TYPE OF ALL CHESS MEN ON THE BOARD. W-- PRINTS WHITE-S MOVES. B-- PRINTS BLACK-S MOVES. Z--PRINTS BOARD IN SHORTHAND NOTATION. P--SHORTHAND BOARD OUTPUT. D--PRINTS MOVES CONSIDERED BY SELECTRTMV. R#--RETRACTS LAST # + 1 HALF MOVES. L--ALLOWS THE PROGRAM TO LOOKAHEAD. C###--SETS THE COMPUTER-S CLOCK TO ### MINS. O--PRINTS ALL THE CURRENT OPTION SETTINGS. Q--ALLOWS QUICK (2 PLY) LOOKAHEAD STOP--TERMINATES THE PROGRAM; % END OF OPENING COMMENT %*****************DECLARATIONS************* DEFINE MAXCHAR = 80 #, MAXTREE = 50 #, LIM = 28#, MAXLEV = 7 #, BAD = 0#; DEFINE FROMSQ = QQ[N].[21:7] #, % MOVEFROM[N] TOSQUARE = QQ[N].[14:7] #, % MOVETO[N] CONSEQ = QQ[N].[7:8] #, % RESULT[N] MERIT = QQ[N].[34:13] #, % SCORE[N] REWARD = QQ[N].[46:12]#; % NOT PREVIOUSLY IMPLEMENTED DEFINE DUPSCR = GETNODE[NODE].[34:13]#, PARENT = GETNODE[NODE].[15:8]#, GETNODEL = GETNODE[L:=L+1].[7:8]#, GETNODEZ = GETNODE[0].[7:8]#, GETNODEX = GETNODE[MAXL].[7:8]#; DEFINE % ALL THE FOLLOWING PARTIAL WORDS ARE USED ONLY ONCE. QQBEST = QQ[TRY[I]].[34:13]#, % SCORE(TRY[I]) LASTSQUARE = QQ[BESTMOVES[IP+1]].[14:7]#, % MOVETO[BESTMOVES[IP+1]] NEXTSQUARE = QQ[BESTMOVES[IP-1]].[21:7]#, % MOVEFROM[BESTMOVES[IP-1]] FIND1 = I.[2:3] #, % I MOD 8 FIND2 = (I-1).[2:3] #, % (I-1) MOD 8 FIND3 = (I+6).[2:3] #, % (I+6) MOD 8 FIND4 = (I+1).[2:3] #, % (I+1) MOD 8 KINGSM = (J2|L -1).[2:3] #, % (J2xL -1) MOD 8 CHECKP = (SQU -SQ).[2:3] #, % (SQU -SQ) MOD 8 MAKEM = M2.[2:3] #; % M2 MOD 8 FILE TTY 14 (2,10,30), REMOTE 14(2,10); %file TTY(KIND=REMOTE); FILE BOARD DISK SERIAL [20: 5] "BOARD" (1,90,90); %file BOARD(kind=disk,title="BOARD."); FILE GAME DISK SERIAL [9:12] "GAME" (2,10,30); %file GAME(kind=disk,title="GAME."); % SAVE FILE STATES DISK RANDOM [20:3] "STATES" (2,90,90,SAVE 5); %FILE STATES DISK RANDOM "STATES" (1,90,90); % SAVE FILE MOVES DISK RANDOM [20:3] "MOVES" (2,90,90,SAVE 5); %FILE MOVES DISK RANDOM "MOVES" (1,90,90); % NOTE THAT 20|3 = 60 MUST BE GREATER THAN MAXTREE. % [ # OF AREAS : # LOGICAL RECORDS/AREA ] % ( # OF BUFFERS, # WORDS/LOGICAL RECORD, # WORDS/PHYSICAL RECORD ) % EACH READ OR WRITE STATEMENT CONSTITUTES 1 LOGICAL RECORD. % ONLY WHEN 1 PHYSICAL RECORD OF INFORMATION IS AVAILABLE, % IS IT WRITTEN ON (OR READ FROM) DISK. % IN ORDER TO REDUCE CORE REQUIREMENTS THE ARRAYS SCOPE, MOVEFROM, % MOVETO AND RESULT CAN BE PACKED INTO ONE ARRAY, QQ, THROUGH % THE USE OF PARTIAL WORDS AND A GLOBAL DEFINITION. FOR EXAMPLE % MERIT = SCORE[N] = QQ[N].[38:17], FROMSQ = MOVEFROM[N] = QQ[N].[21:7] % TOSQUARE = MOVETO[N] = QQ[N].[14:7], CONSEQ = RESULT[N] = QQ[N].[7:8] % IN THE INTERESTS OF SPEED, PARTIAL WDS. ARE USED FOR MOD 8 ARITHMETIC % INTEGER A, B, C; % PARAMETERS GENERATED BY FINDARC; INTEGER KTEST, MVS, RTMV, I,II, MOVE, CLIST, K, NUM, ONUM, CNUM, SLIST, WCON,BCON, NUMB, PROMCAPT, MOVECOUNT, F, CHARCOUNT, KINGVAL,QSQ, ZEROTIME, N, LAST, BLANK, M1, M2, M3, M5, M6, M7, M8, M9, M10, M11, M12, M14, KSQ, MAXPIECE, DATUM, CHECKSQ, MINPIECE, LOSSES, GAINS, SENDTIME, COMPUTERTIME, USERTIME, USERPROCESS, STARTIME, CPU, IO, REALTIME, CPUTIME,OLDCPU,IOTIME,OLDIO,ELAPSEDTIME, COUNT, DIFFVAL, REALVAL, ONEVAL, TWOVAL, MOVETIME; BOOLEAN NEWGAME,EXAMINE,REMEMBER, LEGAL, NOQUEEN, WH, BOTH, NEEDKING, DEBUG,WTERMINAL, KINGCHECK, TEST, REVERSE, NULLMOVE, DUMPP, CBOTH, WS, LOOKAHEAD, PRUNE, TOURNAMENT, MAKEMV,SCORES,INCHECK, QUICK; INTEGER LEVEL, MAXLEVEL, MAXNODES, WDIRECT, REPLY, ORIGIN, MAXL, SAVEL, PATH, OLDSCR, PREVSCR, ASCORE,DSCORE; % IN ORDER TO EMPHASIZE THE THREE LEVELS OF THIS CHESS PROGRAM, % THE ARRAYS THAT ARE ASSOCIATED WITH EACH LEVEL HAVE BEEN % SEPARATED. THE THREE LEVELS ARE :- CONVERSATIONAL, OCCURING % WHENEVER THE USER CAN INPUT DATA; POSITION GENERATION, WHENEVER % A NEW MODE OF THE SEARCH TREE IS CREATED; AND MOVE SCORING. IN % WHICH MANY MOVES FROM A FIXED POSITION (NODE) ARE STUDIED. %****************:CONVERSATIONAL*************: INTEGER ARRAY U[0:MAXCHAR], COLOR[-1:1], LL[0:1], L[0:1], IR[0:2], M[0:2], MM[0:2], MAN[-8:8], DIGIT[0:9], CHESSPIECE[0:8], CHESSMAN[0:11], MC[0:10], NUMBER[-1:1], SPAN[-1:1], %*****************POSITIONAL******************** STATES[0:MAXTREE, 0:89], MOVES[0:MAXTREE, 0:89], BESTMOVES[0:65], TRY[0:8], NODETO[0:MAXTREE, 0:7], GETNODE[0:MAXTREE], ROOTNODE[0:MAXLEV], BACK[0:MAXLEV, 0:29], %******************SCORING***************** TLIST[0:12], RLIST[0:12], POWER[0:10], SQR[-5:10], ATTASQRS[0:10], S[0:8], KSQRS[-9:9], VALUES[0:12], PIECES[-8:8], KINGSQ[-1:1], CHECKLIST[0:LIM], OLDLIST[0:LIM], NEWLIST[0:LIM], %MOVEFROM[-65:65], MOVETO[-65:65], RESULT[-65:65], SCORE[-65:65] % QQ[-65:65], % CONVERTED TO REAL ARRAY, MORE WIDTH POSITION[0:64, 0:LIM], POS[0:64], CONTROL[0:64, -6:6], CON[-1:1, 0:64], NSQ[0:64], SQUARE[0:16], OLDSQUARE[0:9], OLDLOSS[0:9], LOSS[0:16]; BOOLEAN ARRAY CASTLE[-2:2]; ALPHA ARRAY QQ[-65:65]; INTEGER ARRAY STORE[-508:508]; % DEBUGGING AIDS. LIST TIMELIST(TIME(2)/3600,TIME(3)/3600,(TIME(1)-ZEROTIME)/3600, TIME(0),TIME(1)/216000), BOARDLIST(K, NUM, MOVECOUNT,ONEVAL,TWOVAL,DIFFVAL, KTEST, FOR I := -2,-1,1,2 DO CASTLE[I], FOR I := -1,1 DO [SPAN[I], NUMBER[I]], FOR I:=1 STEP 1 UNTIL 64 DO NSQ[I]), NODELIST(K,KTEST,NUM,COUNT,MOVECOUNT,DIFFVAL, SPAN[0], OLDSCR, OLDSQUARE[0], SQUARE[0], PREVSCR, REALVAL,ONEVAL,TWOVAL, FOR I := 0 STEP 1 UNTIL 8 DO TRY[I], FOR I := 1 STEP 1 UNTIL 64 DO NSQ[I]), MOVELIST(CASTLE[K],SPAN[K],NUMBER[K],CASTLE[K+K], KINGSQ[K], FOR I := -8 STEP 1 UNTIL 8 DO PIECES[I], FOR I:=OLDSQUARE[0] STEP -1 UNTIL 1 DO [OLDSQUARE[I],OLDLOSS[I]], FOR I := SQUARE[0] STEP -1 UNTIL 1 DO [SQUARE[I],LOSS[I]], FOR I:= TRY[8] STEP -1 UNTIL 1 DO % [SCORE[TRY[I]],MOVEFROM[TRY[I]],MOVETO[TRY[I]],RESULT[TRY[I]] QQ[TRY[I]]), BACKLIST(M2,M3,M7,M8,M9,M14,FOR II:=NUMB STEP -1 UNTIL 0 DO [RLIST[II], TLIST[II] ]); LABEL STOP, STARTS; FORMAT AMBIG("AMBIGUOUS--"), ILLEGAL("ILLEGAL MOVE, TRY AGAIN."), NOTLISTED("NOT LISTED--"), TRYORTRACE("TRY AGAIN."); FORMAT AUTHOR("PLEASE SUBMIT ALL INTERESTING GAMES,"/ "CRITICAL COMMENTS AND HELPFUL SUGGESTIONS TO"/ "DR. T.A. MARSLAND, ROOM 4E-618."/ "BELL TELEPHONE LABS.,"/ "HOLMDEL, N.J. 07733"), COLORS("DO YOU WANT WHITE OR BLACK", A1), INSTRUCTIONS ("DESCRIPTIVE (ENGLISH) NOTATION IS USED TO DESCRIBE"/ "A MOVE. A + OPTION MAY BE EXERCISED IN REPLY TO ANY REQUEST FOR"/ "INPUT. THE BOOLEAN CONTROL OPTIONS SHOULD BE USED WITH CARE."/ "+O (LETTER) GIVES THEIR VALUES."), NEWGM("NEW GAME(YES OR NO)"), PLAYBOTH("PLAY BOTH SIDES(YES OR NO)"), PLAYER("WHOSE MOVE, BLACK OR WHITE"), TIMEFORM("PROCESSOR TIME=",R6.2," MINUTES. IO TIME=",R6.2, " MINUTES."/"ELAPSED TIME=",R6.2," MIN. DATE=",A6,". TIME = "R6.2), TITLE(///"WITA III, A CHESS PROGRAM"/ " MARCH 1970"///), TRACER("TYPE *8 FOR CONTROL OPTIONS AND INSTRUCTIONS"), USETBRD("YOU SET THE BOARD;"/ "LIST WHITE PIECES FIRST"), WANTCOMPUTER("COMPUTER TO PLAY ITSELF (YES OR NO)"), MOREKINGS("THERE MUST BE TWO KINGS"); FORMAT TRACETITLE("*0=NEGATES LEGAL (BEWARE)"/ "*1=TERMINAL DEBUG"/ "*2=NEGATES SCORES"/ "*3=PRINT BOARD"/ "*4=COMPUTER TAKESOVER"/ "*5=USER TAKESOVER"/ "*6=START AGAIN"/ "*7=NEGATES RANDOM"/ "*8 = PRINTS ALL THIS STUFF"/ "*9=PRINT PIECES"/ "*Z=SAVE SHORTHAND BOARD"/ "*B=PRINT BLACK-S MOVES"/ "*W=PRINT WHITE-S MOVES"/ "*P=PRINT SIMPLE BOARD"/ "*R#=RETRACTS LAST # +1 HALF MOVES"/ "*D=PRINT MOVE SELECTION"/ "*L = NEGATES LOOK-AHEAD"/ "*C### = SETS THE COMPUTER-S CLOCK TO ###MINS."/ "*O = PRINT OPTION SETTINGS."/ "*Q = NEGATES QUICK LOOKAHEAD"/ "*A = AUTHOR-S REQUEST"/ "*I = INSTRUCTIONS"/ "*T = NEGATES TOURNAMENT"/ "*G = PRINT CURRENT GAME RECORD"/ "*V = NEGATES SCORING FUNCTION VARIETY"/ "STOP=STOP EXECUTION"); FORMAT FT1(14I5), LINES(80A1), CONTINUED("CONTINUE:"), COMMAND("SHALL I CONTINUE. MAY ALSO ALTER CONTROL OPTIONS."), LPMR(I5,3A1,A3,3A1,A3,X1,2A1,X1,2A5,A1,2I7,I4), TPMR(I4," MOVES CONSIDERED OUT OF"I4); SWITCH FORMAT FT9 := (I4, X1, 2A1, A3, 3A1, A3, X1, 2A1, X1, 2A5, I3), (X6,I3,X1, 2A1, A3, 3A1, A3, X1, 2A1, X1, 2A5); % SWITCH FORMAT TERM :=("HISTORY FILE FULL. STOP EXECUTION"), ("RESIGN"), ("STALEMATE"), ("DRAW"), ("MATE"), ("KING CAPTURED"); SWITCH FORMAT BRAN := (5I5),(5I5),(X3,5I5),(X6,5I5),(X9,5I5), (X12,5I5),(X15,5I5),(X18,5I5); FORMAT YOURMOVE(A5"-S MOVE"I3), %" (I HAD "I3" LEGAL MOVES)"); TIMING(" ("I2"/"I2" IN ("I3" + "I2")/"I3")"); FORMAT BRANCH( X5,2A1,A3,3A1,A2,X1,2A1,X1,2A5); FORMAT MAIL(/"PLEASE MAIL INTERESTING GAME RECORDS TO"/ "T.A. MARSLAND, BTL, HOLMDEL, 07733"/); % COMMENT THIS FIRST ATTEMPT AT A CHESS PLAYING PROGRAM IS VERY UNSOPHISTICATED. ITS LEVEL OF PLAY IS THAT OF ADVANCED BEGINNER. IT WAS THE AIM OF THIS PROGRAM TO PLAY REASONABLE MIDDLE GAME CHESS. AT ANY STAGE IN THE GAME THE SEVEN BEST MOVES ARE SELECTED ON A BASIS MOBILITY, MODIFIED BY MATERIAL GAIN AND CHECKING THREATS. FOR EACH OF THESE MOVES THE ATTACKING AND OFFENSIVE POTENTIAL IS COMPUTED AND THE OVERALL SCORE MODIFIED AGAIN. MOVE WITH HIGHEST SCORE SELECTED. NOTE THAT NO SPECIAL OPENING STRATEGY OR FIXED LINES OF PLAY HAVE BEEN PREPROGRAMMED NOR IS THERE A SPECIAL SECTION ON ENDGAMES. SUCH ADDITIONS WOULD CERTAINLY BE ADVANTAGEOUS. TAM. ;%END OF COMMENT % PROCEDURE SKIP(N); % CAUSE THE TELETYPE TO SKIP N LINES VALUE N; INTEGER N; FOR I := 1 STEP 1 UNTIL N DO WRITE(TTY,LINES," "); %***********************PRINT BOARD**************** PROCEDURE PRINTBOARD ; %PUTS PIECES ON BOARD AS PER NSQ[*] AND PRINTS THE BOARD. BEGIN INTEGER I,J,L,JK,PC,SQ; INTEGER ARRAY BRD[0:32]; FORMAT A4(8A4,A1); FOR J := 0 STEP 4 UNTIL 32 DO BRD[J] := "I"; SQ := 72; JK := 2; FOR I := 8 STEP -1 UNTIL 1 DO BEGIN FOR J := 4 STEP 8 UNTIL 28 DO BEGIN L := J -JK; BRD[L-1] := BRD[L] := BRD[L+1] := " "; L := J +JK; BRD[L-1] := BRD[L] := BRD[L+1] := "/"; END; SQ := SQ -16; JK := - JK; FOR J := 2 STEP 4 UNTIL 30 DO BEGIN PC := NSQ[SQ:=SQ+1]; IF PC NEQ 0 THEN BEGIN IF PC LSS 0 THEN BRD[J-1] := "*"; BRD[J] := CHESSMAN[ABS(PC)]; END; END; WRITE(TTY,A4,FOR J:=1 STEP 1 UNTIL 8 DO "+---", "+"); WRITE(TTY,LINES,FOR J:=0 STEP 1 UNTIL 32 DO BRD[J]); END; WRITE(TTY,A4,FOR J:=1 STEP 1 UNTIL 8 DO "+---", "+"); WRITE(TTY, YOURMOVE, COLOR [K] ); END OF PRINT BOARD; %*************PRINT SHORT BOARD************; PROCEDURE PRINTSHORTBRD; BEGIN INTEGER PC,I,J; FORMAT FT(8A3); WRITE(TTY,FT,FOR I:=1 STEP 1 UNTIL 8 DO FOR J := 0 STEP 1 UNTIL 7 DO IF PC:=NSQ[8|I-J] = 0 THEN IF (I+J) MOD 2 = 0 THEN " **" ELSE " --" ELSE IF ABS(PC) GTR 8 THEN " EP" ELSE MAN[PC]); WRITE(TTY,YOURMOVE,COLOR[K]); END OF PRINT SHORT BOARD; % PROCEDURE PUNCHBRD; BEGIN INTEGER I,J,K,L,M,T; INTEGER ARRAY U[0:80]; DEFINE FORI = FOR I := 0 STEP 1 #; U[0] := "$"; M := 0; FOR K := 1, -1 DO BEGIN L := 0; FOR I := 1 STEP 1 UNTIL 8 DO BEGIN T := 0; FOR J := 1 STEP 1 UNTIL 8 DO IF NSQ[L := L+1] = 0 OR SIGN(NSQ[L]) NEQ K THEN T := T + 1 ELSE BEGIN IF T NEQ 0 THEN U[M := M+1] := T; T := 0; U[M := M+1] := CHESSMAN[ABS(NSQ[L])]; END; IF T NEQ 0 THEN U[M := M+1] := T; END; U[M := M+1] := "."; END; WRITE(TTY, LINES, FORI UNTIL 15 DO " ", % RUB OUT CHARS FORI UNTIL M DO U[I], FORI UNTIL 10 DO " ", 30); END OF PUNCHBRD; % PROCEDURE DESCRIBEMOVE (N,CM); %INTERNAL MOVE DESCRIPTION IS CONVERTED TO CHESS NOTATION VALUE N; INTEGER N; INTEGER ARRAY CM[0]; BEGIN LABEL AA; INTEGER M,M2,M4,M5,M6,M3,K; % INTEGER PROCEDURE CHESSBOARD(SQ); VALUE SQ; INTEGER SQ; BEGIN INTEGER ROW, COL, DUMMY; ROW := (SQ+7) DIV 8; COL := SQ - 8|(ROW -1); DUMMY.[17:6] := IF COL LSS 4 THEN "Q" ELSE IF COL GTR 5 THEN "K" ELSE " "; DUMMY.[11:6] := CHESSPIECE[COL]; DUMMY.[5:6] := IF K GTR 0 THEN ROW ELSE 9 - ROW; CHESSBOARD := DUMMY; END OF CHESSBOARD; % K := SIGN(N); BEGIN M2 := ABS (CONSEQ); M := IF M2 LSS 20 THEN 0 ELSE M2 DIV 20; M2 := IF M2 LSS 20 THEN M2 ELSE M2 MOD 20; IF M = 0 THEN CM [9] :=CM [10] :=BLANK ELSE IF M = 1 THEN BEGIN CM [9] :="CHECK"; CM [10] :=BLANK END ELSE IF M = 2 THEN BEGIN CM [9] :="DBL. "; CM [10] :="CH. " END ELSE IF M = 3 THEN BEGIN CM[9] := "DIS. "; CM[10] := "CH. "; END ELSE IF M = 4 THEN BEGIN CM [9] :="STALE"; CM [10] :="MATE " END ELSE BEGIN CM [9] :="MATE "; CM [10] :=BLANK END; IF M2 = 10 THEN BEGIN CM [2] :="U "; AA: CM [0] :="0"; CM [1] :="-"; CM [3] :=CM [4] :=CM [5] := CM [6] :=CM [7] :=CM [8] := BLANK; END ELSE IF M2 = 9 THEN BEGIN CM [2] :="0-0"; GO TO AA END ELSE BEGIN M3:=FROMSQ; M4 :=NSQ [M3]; M5 :=TOSQUARE; M6 := NSQ[M5]; IF ABS(M6) = 11 THEN M6 := 0; CM [0] :=CHESSMAN [ABS (M4)]; IF PIECES [M4] > 1 THEN BEGIN CM [2] :=CHESSBOARD (M3); CM [1] :="/" END ELSE CM [1] :=CM [2] :=BLANK; IF M2 = 11 AND ABS (M4) = 1 THEN BEGIN CM [3] := "*"; CM [4] :="P"; CM [5] :=BLANK; CM [6] :="E.P"; END ELSE BEGIN IF M6 = 0 OR M2 = 11 OR M2 = 12 THEN BEGIN CM [3] :="-"; CM [4] :=CM [5] :=BLANK; CM [6] :=CHESSBOARD (M5) END ELSE BEGIN CM [3] := "*"; CM [4] :=CHESSMAN [ABS (M6)]; IF PIECES [M6] > 1 THEN BEGIN CM [5] :="/"; CM [6] :=CHESSBOARD (M5) END ELSE CM [5] :=CM [6] :=BLANK; END; END; IF M2 LSS 13 THEN CM[7] := CM[8] := BLANK ELSE BEGIN CM[7] := "="; % PAWN PROMOTION. CM[8] := CHESSMAN[M2-10]; END; END NOT CASTLE; END; END DESCRIBEMOVE; % PROCEDURE PRINTGAMERECORD; BEGIN INTEGER I,L; INTEGER ARRAY U[0:35]; REWIND(GAME); READ(GAME,LINES,I); IF L = "8" THEN %% WRITE(TTY[STOP],LINES,FOR I:=1 STEP 1 UNTIL 29 DO "."); WRITE(TTY,LINES,FOR I:=1 STEP 1 UNTIL 29 DO "."); FOR L :=1 STEP 1 UNTIL COUNT DO BEGIN READ(GAME,LINES,FOR I:=1 STEP 1 UNTIL 35 DO U[I]); %% IF U[4] NEQ" " THEN WRITE(TTY[STOP],LINES,FOR I:=1 STEP 1 UNTIL 29 DO IF U[4] NEQ" " THEN WRITE(TTY,LINES,FOR I:=1 STEP 1 UNTIL 29 DO U[I],31) ELSE WRITE(TTY,LINES,FOR I:= 7 STEP 1 UNTIL 35 DO U[I]); END; WRITE(TTY,LINES," "); END OF PRINT GAME RECORD; % PROCEDURE PRINTSELECTION; % PRINTS MOVES CONSIDERED IN SELECTRTMV. BEGIN INTEGER I, J, JN, TN, N, M; FORMAT FT1("P",2I3,2I5,I5,2I3,5I3,2I3,I5,X1,2A1,A3,3A1,A3,X1, 2A1,A5); M := SQUARE[0]; WRITE(TTY, FT1, M,FOR J:=1 STEP 1 UNTIL M DO [SQUARE[J],LOSS[J]], DIFFVAL,NUMBER[0],ONEVAL,TWOVAL,NUMBER[K],SPAN[0]); FOR J := TRY[8] STEP -1 UNTIL 1 DO BEGIN N := TRY[J]; JN := N|8; TN := (J-1)|5; DESCRIBEMOVE(N,MC); IF DUMPP THEN %% WRITE(TTY[STOP], FT1,N, FOR I:=0 STEP 1 UNTIL 7 DO STORE[JN+I]); WRITE(TTY, FT1,N, FOR I:=0 STEP 1 UNTIL 7 DO STORE[JN+I]); WRITE(TTY,LPMR, MERIT, " ", FOR I:=0 STEP 1UNTIL 0 DO MC[I]); END; END OF PRINTSELECTION; %*****************SCORER******************* PROCEDURE SCORER(II); VALUE II; INTEGER II; BEGIN FORMAT FT(10I5,X1,2A1,A3,3A1,A3,X1,2A1,X1,2A5); INTEGER I,N,J,L,S,F,T; T:=U[II]; S:=U[I-2]; F := U[II-1]; J := IF S = "-" THEN -1 ELSE 1; F := J|(F|6)+J; T := J|(T+1)|6; IF NOT LOOKAHEAD THEN FOR N := F STEP J UNTIL T DO BEGIN DESCRIBEMOVE(N,MC); L := N|8; IF DUMPP THEN %% WRITE(TTY[STOP],FT,N,FOR I:=0 STEP 1 UNTIL 7 DO STORE[L+I]); WRITE(TTY,FT,N,FOR I:=0 STEP 1 UNTIL 7 DO STORE[L+I]); WRITE(TTY, LPMR, MERIT, " ", FOR I := 0 STEP 1 UNTIL 9 DO MC[I]); END; END OF SCORER; % PROCEDURE CLOCK(I); VALUE I; INTEGER I; BEGIN INTEGER T; T:= COMPUTERTIME + USERTIME; COMPUTERTIME := 60|(U[I] + 10|(U[I-1] + 10|U[I-2])); USERTIME := T - COMPUTERTIME; END OF CLOCK UPDATE; PROCEDURE PRINTMOVES( KK); %POSSIBLE MOVES ARE PRINTED VALUE KK; INTEGER KK; BEGIN LABEL AGAIN; INTEGER LINECOUNT,N,BCD,I,LAST,NK;; AGAIN: LINECOUNT :=NK + 1; LAST := ABS(NUMBER[KK]); WRITE(TTY, TPMR, SPAN[KK], LAST ); FOR NK :=LINECOUNT STEP 1 UNTIL LAST DO BEGIN N := NK|KK; IF NK = 62 THEN GO TO AGAIN; BCD :=IF N = RTMV THEN "#" ELSE " "; DESCRIBEMOVE (N, MC); WRITE(TTY, LPMR, NK, BCD,FOR I:=0 STEP 1 UNTIL 10 DO MC[I], BCD, CONSEQ, MERIT, NK); END FOR NK; END PRINTMOVES; % %****************DUMPER**************** PROCEDURE DUMPER(I); VALUE I; INTEGER I; BEGIN INTEGER T,J,L,ONE,TWO; FORMAT FT(I3,X2,20I3); TWO := U[I]; ONE := U[I-1]; T := (TWO+1)|8; FOR L:=ONE|8 +1 STEP 1 UNTIL T DO WRITE(TTY,FT,L,FOR J:=POS[L] STEP -1 UNTIL 1 DO POSITION[L,J],9999,FOR J:=POSITION[L,LIM] STEP 1 UNTIL LIM-1 DO POSITION[L,J],9999,FOR J:=CON[-1,L] STEP 1 UNTIL CON[1,L] DO CONTROL[L,J],9999,CON[1,L],CON[0,L]); END OF DUMPER; % BOOLEAN PROCEDURE MODOK (M,TM); %CHECKS MODIFIER OF CHESS NOTATION E.G. DISTINGUISHES KP FROM KRP VALUE TM; INTEGER TM; INTEGER ARRAY M [0]; BEGIN INTEGER J; BOOLEAN B, Q; LABEL AA, BB, CC, QUIT; % BOOLEAN PROCEDURE SEEABOUT(J); VALUE J; INTEGER J; SEEABOUT := IF (J) MOD 8 = 0 THEN TRUE ELSE FALSE; % END OF SEEABOUT % B := FALSE; Q := FALSE; IF M [1] = 0 THEN B :=TRUE ELSE BEGIN IF M [0] = 7 THEN BEGIN Q :=TRUE; AA: J := IF M [1] = 5 THEN 7 ELSE IF M [1] = 4 THEN 5 ELSE 6; BB: IF B := SEEABOUT(TM+J) OR Q THEN GO TO QUIT ELSE GO TO CC END ELSE IF M [0] = 8 THEN BEGIN CC: J :=IF M [1] = 5 THEN 0 ELSE IF M [1] = 4 THEN 2 ELSE 1; Q :=TRUE; GO TO BB END ELSE IF M [1] = 8 THEN IF M [2] = 1 THEN B := SEEABOUT(3+TM) ELSE FOR J := 0, 1, 2, 3 DO IF B := SEEABOUT(TM+J) THEN GO TO QUIT ELSE ELSE IF M [1] = 7 THEN IF M [2] = 1 THEN B := SEEABOUT(4+TM) ELSE FOR J := 4, 5, 6, 7 DO IF B := SEEABOUT(TM+J) THEN GO TO QUIT ELSE ELSE GO TO AA; END; QUIT: MODOK :=B END MODOK; % PROCEDURE FINDRTMV; %FINDS WHICH MOVE ON THE LIST CORRESPONDS TO THE INPUT MOVE BEGIN LABEL QUIT, NEXTN; INTEGER N; RTMV := 0; NULLMOVE := TRUE; FOR N := NUMBER[K] STEP -K UNTIL K DO BEGIN IF FROMSQ NEQ 0 THEN BEGIN IF M [2] = 0 THEN IF CONSEQ = IR [0] AND IR [ 0] NEQ 0 THEN BEGIN RTMV := N; GO TO QUIT; END ELSE GO TO NEXTN; IF M [2] NEQ ABS (NSQ [FROMSQ]) THEN GO TO NEXTN; IF MM [2] NEQ ABS (NSQ [TOSQUARE]) % MUST WRITE PXP E.P., FOR ENPASSANT CAPTURE. AND ABS(NSQ[TOSQUARE]) NEQ 11 THEN GO TO NEXTN; IF ABS (NSQ [TOSQUARE]) = 11 THEN BEGIN RTMV := N; GO TO NEXTN; END ; IF LL [0] NEQ 0 THEN IF FROMSQ NEQ LL [0] AND FROMSQ NEQ LL [1] THEN GO TO NEXTN; IF L [0] NEQ 0 THEN IF TOSQUARE NEQ L [0] AND TOSQUARE NEQ L [1] THEN GO TO NEXTN; IF IR [2] NEQ 0 THEN IF IR [2] + 10 NEQ ABS (CONSEQ) MOD 20 THEN GO TO NEXTN; IF MODOK (MM,TOSQUARE) THEN IF MODOK (M,FROMSQ) THEN IF RTMV = 0 THEN RTMV := N ELSE BEGIN RTMV :=0; WRITE(TTY, AMBIG); NULLMOVE := TRUE; GO TO QUIT; END; END; NEXTN: NULLMOVE := FALSE; END; IF RTMV = 0 THEN BEGIN WRITE(TTY, NOTLISTED); NULLMOVE := TRUE; END; QUIT: END FINDRTMV; % PROCEDURE RETRACT(RTMV); INTEGER RTMV; BEGIN INTEGER N; N:= RTMV := 0; CONSEQ := IF IR[2] NEQ 0 THEN IR[2] + 10 ELSE MM[2]; FROMSQ := LL[0]; TOSQUARE := L[0]; NULLMOVE := IF L[0] = 0 OR LL[0] = 0 THEN TRUE ELSE FALSE; END OF RETRACT; % PROCEDURE GETMAN(D, M, L); %DETERMINES INTERNAL CODE FOR CHESS MAN MENTIONED VALUE L; INTEGER L; INTEGER ARRAY D [0], M [0]; BEGIN LABEL NEXTI; INTEGER I, J; FOR I :=0, 1, 2 DO BEGIN M[I] :=0; FOR J :=0 STEP 1 UNTIL 8 DO IF D [L] = CHESSMAN [J] THEN BEGIN D [I] :=J; % D is uncertain GO TO NEXTI END; NEXTI: L := L + 1; END FOR I; IF M [1] = 0 THEN BEGIN M [2] :=M [0]; M [0] := 0; END ELSE IF M [2] = 0 THEN BEGIN M [2] :=M [1]; M [1] :=M [0]; M [0] :=0; END; END GETMAN; % PROCEDURE GETSQ (C, L, D); %DETERMINES INTERNAL NUMBER FOR CHESS SQUARE VALUE D; INTEGER D; INTEGER ARRAY C [0], L [0]; BEGIN LABEL AA, BB, CC, DD, EE, QUIT; INTEGER A, B, F, I, LI,J; A :=D + 2; B :=D + 1; F :=C [0]; EE: FOR I :=1 STEP 1 UNTIL 8 DO IF C [A] = DIGIT [I] THEN BEGIN LI := I; GO TO AA END; IF F = 0 THEN BEGIN L [0] := 65; % [0] is not certain GO TO QUIT END; A :=B; B :=D; F :=0; GO TO EE; AA: IF K < 0 THEN LI :=9 - LI; L[ 1] :=0; IF F = "K" THEN BEGIN BB: J :=IF C [B] = "R" THEN 7 ELSE IF C [B] = "B" THEN 5 ELSE IF C [B] = "N" THEN 6 ELSE IF C [B] = "K" THEN 4 ELSE 3; CC: L [0] :=8 | LI + J - 7; IF L [1] NEQ 65 THEN GO TO QUIT ELSE BEGIN L [1] :=L [0]; GO TO DD END END ELSE IF F = "Q" THEN BEGIN DD: J :=IF C [B] = "N" THEN 1 ELSE IF C [B] = "B" THEN 2 ELSE IF C [B] = "R" THEN 0 ELSE 3; GO TO CC END ELSE IF C [B] NEQ "Q" AND C [B] NEQ "K" THEN L [1] :=65; GO TO BB; QUIT: END GETSQ; % PROCEDURE GETMOVE (G); %CONVERTS CHESS MOVE FROM CHESS TO INTERNAL NOTATION INTEGER ARRAY G [0]; BEGIN INTEGER T, F, POINT, I; LABEL SLFALSE, UNSET, BUMP, ENDLEFT, ENDRIGHT, QUIT; BOOLEAN LEFT, SL, CAPT, POINTSET; LEFT :=TRUE; NULLMOVE := CAPT :=FALSE; I := -1; FOR F := 0, 1 DO IR [F] :=M [F] :=MM [F] :=L [F] :=LL [F] :=0; IR [2] :=M [2] :=MM [2] :=0; SLFALSE: POINTSET :=FALSE; UNSET: POINTSET :=FALSE; BUMP: I :=I + 1; IF I > CHARCOUNT THEN GO TO ENDRIGHT; T :=G [I]; IF T = " " THEN GO TO UNSET; IF T = "K" THEN KTEST :=4 ELSE IF T = "D" AND G [I + 1] = "R" THEN KTEST :=3 ELSE IF T = "S" THEN KTEST :=2 ELSE IF T = "R" AND G [I + 1] = "E" THEN KTEST :=1; IF KTEST NEQ 0 THEN BEGIN IF LEFT THEN BEGIN NULLMOVE := TRUE; GO TO QUIT; END ELSE GO TO ENDRIGHT; END; IF T = "/" THEN BEGIN SL :=TRUE; IF LEFT THEN GETMAN (G, M, POINT) % LE?? is left maybe ELSE GETMAN (G, MM, POINT); GO TO UNSET; END; IF T = "-" THEN ENDLEFT: BEGIN LEFT :=FALSE; IF SL THEN GETSQ (G, LL, POINT) ELSE GETMAN (G, M, POINT); GO TO SLFALSE; END; IF T = "X" OR T = "x" OR T = "*" THEN BEGIN CAPT :=TRUE; GO TO ENDLEFT; END; IF T = "." OR T = "," THEN ENDRIGHT: BEGIN IF CAPT AND NOT SL THEN GETMAN (G, MM, POINT) ELSE GETSQ (G, L, POINT); GO TO QUIT; END; IF T = "=" OR T = "#" THEN BEGIN GETMAN (G, IR, I + 1); I :=I + 2; GO TO ENDRIGHT; END; IF T = "E" THEN BEGIN MM [2] :=IR [2] :=11; I :=I + 3; GO TO QUIT; END; IF T = "C" OR T = "D" THEN BEGIN I :=I + 2; IR [0] :=1; GO TO ENDRIGHT; END; IF T = "O" OR T = "0" THEN BEGIN IF G [I + 4] = "O" OR G[I +4] = "0" THEN BEGIN IR [0] :=9; I :=I + 5; END ELSE BEGIN IR [0] :=10; I :=I +3; END; GO TO QUIT; END; IF NOT POINTSET THEN BEGIN POINT :=I; POINTSET :=TRUE; END; GO TO BUMP; QUIT: END GETMOVE; % INTEGER PROCEDURE FINDJ1 (I); %J1<0 MEANS SQUARE I IS ON WHITES EIGHTH RANK %J1>0 MEANS SQUARE I IS ON WHITES FIRST RANK VALUE I; INTEGER I; BEGIN FINDJ1 := IF I LSS 9 THEN 1 ELSE IF I GTR 56 THEN -1 ELSE 0; END FINDJ1; % INTEGER PROCEDURE FINDJ2 (I); %J2>0 MEANS SQUARE I IS ON THE KR FILE %J2<0 MEANS SQUARE I IS ON THE QR FILE VALUE I; INTEGER I; BEGIN FINDJ2 :=IF FIND1 = 0 THEN 1 % IF I MOD 8 = 0 THEN 1 ELSE IF FIND2 = 0 THEN -1 % (I -1) MOD 8 = 0 THEN -1 ELSE 0 END FINDJ2; % INTEGER PROCEDURE FINDJ3 (I); %J3>0 MEANS SQUARE I IS ON WHITE-S FIRST OR SECOND RANK %J3<0 MEANS SQUARE I IS ON WHITE-S SEVENTH OR EIGHTH RANK VALUE I; INTEGER I; BEGIN FINDJ3 :=IF I LEQ 16 THEN 1 ELSE IF I GEQ 49 THEN -1 ELSE 0 END FINDJ3; % INTEGER PROCEDURE FINDJ4 (I); %J4>0 MEANS SQUARE I IS ON KN FILE %J4<0 MEANS SQUARE I IS ON QN FILE VALUE I; INTEGER I; BEGIN FINDJ4 :=IF FIND3 = 0 THEN -1 % IF (I + 6) MOD 8 = 0 THEN ELSE IF FIND4 = 0 THEN 1 % (I + 1) MOD 8 = 0 THEN 1 ELSE 0 END FINDJ4; % PROCEDURE LISTPAWNMOVES(I);VALUE I; INTEGER I; BEGIN INTEGER J2, PC,K, L; % PROCEDURE STOREMOVE; BEGIN % PROCEDURE PROMOTEPAWN; FOR L := 0 STEP 1 UNTIL 3 DO CHECKLIST[CLIST:=CLIST+1] := MOVE; % END OF PROMOTE PAWN. IF K GTR 0 AND I GTR 48 OR K LSS 0 AND I LSS 17 THEN PROMOTEPAWN ELSE CHECKLIST[CLIST:=CLIST+1] := MOVE; END OF STORE MOVE; K:=SIGN(NSQ[I]); J2 := FINDJ2(I); % ENPASSANT HANDLED BY MOVE R. & MOVE IF NSQ[MOVE:= I + 6|K] = 0 THEN BEGIN STOREMOVE; IF K GTR 0 AND I LSS 17 OR K LSS 0 AND I GTR 48 THEN BEGIN IF NSQ[MOVE:=I+16|K] = 0 THEN CHECKLIST[CLIST:=CLIST+1] := MOVE; CHECKLIST[SLIST:=SLIST-1]:=MOVE;END; END OF PAWN FORWARD; CHECKLIST[SLIST:=SLIST-1] := I +8|K; IF K|J2 LEQ 0 THEN BEGIN MOVE := I + 9|K; IF PC := K|NSQ[MOVE] LSS 0 THEN STOREMOVE; CHECKLIST[SLIST:=SLIST-1] := MOVE; END CAPTURE RIGHT; IF K|J2 GEQ 0 THEN BEGIN MOVE := I + 7|K; IF PC := K|NSQ[MOVE] LSS 0 THEN STOREMOVE; % CAPTURE CHECKLIST[SLIST:=SLIST-1] := MOVE; END CAPTURE LEFT; END LISTPAWNMOVES; % PROCEDURE TRYKNIGHTMOVE (M); VALUE M; INTEGER M; BEGIN INTEGER M6,M7,K; K := SIGN(NSQ[F]); %% MOVE := ????M; MOVE := F + M; % perhaps F + M M7 :=NSQ [MOVE]; M6 :=K | M7; IF ABS(M7) = 11 THEN M6 := M7 := 0; IF M6 LEQ 0 THEN CHECKLIST[CLIST:=CLIST+1] := MOVE ELSE CHECKLIST[SLIST := SLIST -1] := MOVE; END TRYKNIGHTMOVE; % PROCEDURE LISTKNIGHTMOVES (I); VALUE I; INTEGER I; BEGIN INTEGER M, J1, J2, J3, J4; F := I; J1 := FINDJ1(F); J2 := FINDJ2(F); IF J1 = 0 THEN BEGIN J3 := FINDJ3 (F); IF J2 = 0 THEN BEGIN J4 := FINDJ4 (F); IF J3 = 0 THEN BEGIN IF J4 = 0 THEN FOR M :=1 STEP 1 UNTIL 8 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 < 0 THEN FOR M :=8, 1 STEP 1 UNTIL 5 DO TRYKNIGHTMOVE (S[M]) ELSE FOR M :=1, 4, 5, 6, 7, 8 DO TRYKNIGHTMOVE (S[M]) END ELSE IF J3 > 0 THEN IF J4 = 0 THEN FOR M :=1, 2, 3, 6, 7, 8 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 < 0 THEN FOR M := 1, 2, 3, 8 DO TRYKNIGHTMOVE (S[M]) ELSE FOR M :=1, 6, 7, 8 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 = 0 THEN FOR M :=2, 3, 4, 5, 6, 7 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 < 0 THEN FOR M :=2, 3, 4, 5 DO TRYKNIGHTMOVE (S[M]) ELSE FOR M :=4, 5, 6, 7 DO TRYKNIGHTMOVE (S[M]) END ELSE IF J2 > 0 THEN BEGIN IF J3 = 0 THEN FOR M :=5, 6, 7, 8 DO TRYKNIGHTMOVE (S[M]) ELSE IF J3 < 0 THEN FOR M :=6, 7, 5 DO TRYKNIGHTMOVE ( S[M]) ELSE FOR M :=6, 7, 8 DO TRYKNIGHTMOVE (S[M]) END ELSE BEGIN IF J3 = 0 THEN FOR M :=1, 2, 3, 4 DO TRYKNIGHTMOVE (S[M]) ELSE IF J3 < 0 THEN FOR M :=4, 2, 3 DO TRYKNIGHTMOVE ( S[M]) ELSE FOR M :=1, 2, 3 DO TRYKNIGHTMOVE (S[M]) END END ELSE IF J1 > 0 THEN BEGIN IF J2 < 0 THEN FOR M :=1, 2 DO TRYKNIGHTMOVE (S[M]) ELSE IF J2 > 0 THEN FOR M :=7, 8 DO TRYKNIGHTMOVE (S[M]) ELSE BEGIN J4 := FINDJ4 (F); IF J4 = 0 THEN FOR M :=1, 2, 7, 8 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 < 0 THEN FOR M :=1, 2, 8 DO TRYKNIGHTMOVE ( S[M]) ELSE FOR M :=1, 7, 8 DO TRYKNIGHTMOVE (S[M]) END END ELSE BEGIN IF J2 < 0 THEN FOR M :=3, 4 DO TRYKNIGHTMOVE (S[M]) ELSE IF J2 > 0 THEN FOR M :=5, 6 DO TRYKNIGHTMOVE (S[M]) ELSE BEGIN J4 := FINDJ4 (F); IF J4 < 0 THEN FOR M :=3, 4, 5 DO TRYKNIGHTMOVE (S[M]) ELSE IF J4 > 0 THEN FOR M :=4, 5, 6 DO TRYKNIGHTMOVE ( S[M]) ELSE FOR M :=3, 4, 5, 6 DO TRYKNIGHTMOVE (S[M]) END END END LISTKNIGHTMOVES; % PROCEDURE TRYBISHOPMOVE (M); VALUE M; INTEGER M; BEGIN INTEGER M5, M6, M7, J1, J2,K; LABEL AA, QUIT; J1 := FINDJ1(F); J2 := FINDJ2( F); M5 :=F; K := SIGN(NSQ[M5]); AA: IF M = 9 THEN BEGIN MOVE :=M5 + 9; IF J1 < 0 OR J2 > 0 THEN GO TO QUIT END ELSE IF M = -7 THEN BEGIN MOVE :=M5 - 7; IF J1 > 0 OR J2 > 0 THEN GO TO QUIT END ELSE IF M = -9 THEN BEGIN MOVE :=M5 - 9; IF J1 > 0 OR J2 < 0 THEN GO TO QUIT END ELSE BEGIN MOVE :=M5 + 7; IF J1 < 0 OR J2 < 0 THEN GO TO QUIT END; M7 :=NSQ [MOVE]; M6 :=K | M7; IF ABS(M7) = 11 THEN M7 := M6 := 0; IF M6 LEQ 0 THEN CHECKLIST[CLIST:=CLIST+1] := MOVE ELSE CHECKLIST[SLIST := SLIST -1] := MOVE; IF (M6 = 0 ) THEN BEGIN M5 :=MOVE; J1 := FINDJ1 (M5); J2 := FINDJ2 (M5); GO TO AA END; QUIT: END TRYBISHOPMOVE; % PROCEDURE TRYROOKMOVE (M); VALUE M; INTEGER M; BEGIN LABEL AA, QUIT; FORMAT FT1 ("TRMV", 24I5); INTEGER M5, M6, M7, J1, J2,K; J1 := FINDJ1 (F); J2 := FINDJ2 (F); M5 :=F; K := SIGN(NSQ[M5]); AA: IF M = 8 THEN BEGIN MOVE :=M5 + 8; % M5 is just a guess IF J1 < 0 THEN GO TO QUIT ELSE J1 := FINDJ1 (MOVE) END ELSE IF M =1 THEN BEGIN MOVE :=M5 + 1; IF J2 > 0 THEN GO TO QUIT ELSE J2 := FINDJ2 (MOVE) END ELSE IF M = -1 THEN BEGIN MOVE :=M5 - 1; IF J2 < 0 THEN GO TO QUIT ELSE J2 := FINDJ2 (MOVE) END ELSE BEGIN MOVE :=M5 - 8; IF J1 > 0 THEN GO TO QUIT ELSE J1 := FINDJ1 (MOVE) END; M7 :=NSQ [MOVE]; M6 :=K | M7; IF ABS(M7) = 11 THEN M6 := M7 := 0; IF M6 LEQ 0 THEN CHECKLIST[CLIST:=CLIST+1] := MOVE ELSE CHECKLIST[SLIST := SLIST -1] := MOVE; M5 := MOVE; IF (M6 = 0 ) THEN GO TO AA; QUIT: END TRYROOKMOVE; % PROCEDURE LISTQUEENMOVES(I); VALUE I; INTEGER I; BEGIN INTEGER M; FOR M := 9,-7,-9,7 DO TRYBISHOPMOVE(M); FOR M := 8,1,-1,-8 DO TRYROOKMOVE(M); END LISTQUEENMOVES; % PROCEDURE FINDABC(SQ1,SQ2); VALUE SQ1,SQ2; INTEGER SQ1, SQ2; % DETERMINES WHETHER SQ1 AND SQ2 ARE IN LINE. % A IS THE FIRST HIDDEN SQ, B, IS THE INCREMENT AND C IS THE BOARD EDGE. BEGIN LABEL QUIT; INTEGER ROW1, SGN, ROW2, COL1, COL2, I; A := B := C := 0; IF SQ1 = SQ2 THEN GO TO QUIT; ROW1 := (SQ1 +7) DIV 8; ROW2 := (SQ2 + 7) DIV 8; COL1 := SQ1 -8|(ROW1-1); COL2 := SQ2 -8|(ROW2-1); SGN := SIGN(SQ2 - SQ1); IF ROW1 = ROW2 THEN IF COL1 LSS COL2 THEN BEGIN A := SQ2 +1; B := 1; C := ROW2|8; END ELSE BEGIN A := SQ2 -1; B := -1; C := ROW2|8 -7; END ELSE IF COL1 = COL2 THEN IF ROW1 LSS ROW2 THEN BEGIN A := SQ2 +8; B := 8; C := COL2 +56; END ELSE BEGIN A := SQ2 -8; B := -8; C := COL2; END ELSE IF (SQ2 - SQ1) MOD 7 = 0 THEN BEGIN A := SQ2 + 7|SGN; B := 7|SGN; C := IF SGN LSS 0 THEN IF ROW2 -1 LSS 8 -COL2 THEN SQ2 -(ROW2 -1)|7 ELSE SQ2 -(8 - COL2)|7 ELSE IF COL2 -1 LSS 8 -ROW2 THEN SQ2 +(COL2 -1)|7 ELSE SQ2 +(8- ROW2)|7; END ELSE IF (SQ2 - SQ1) MOD 9 = 0 THEN BEGIN A := SQ2 +9|SGN; B := 9|SGN; C := IF SGN LSS 0 THEN IF ROW2 -1 LSS COL2 -1 THEN SQ2 -(ROW2 -1)|9 ELSE SQ2 -(COL2 -1)|9 % col2 -1 ELSE IF 8 -COL2 LSS 8 -ROW2 THEN SQ2 +(8 -COL2)|9 ELSE SQ2 + (8 - ROW2)|9; END; QUIT: END OF FINDABC; % BOOLEAN PROCEDURE HIDDEN(SQ1, SQ2, SQ3, KK); VALUE SQ1,SQ2,KK; INTEGER SQ1, SQ2, SQ3, KK; % HIDDEN TRUE IF SQ3 CONTAINS Q, R OR B OF COLOUR -KK. BEGIN LABEL PIECE, QUIT; INTEGER I, PC; SQ3 := 0; HIDDEN := FALSE; FINDABC(SQ1,SQ2); IF B = 0 THEN GO TO QUIT; FOR I := A STEP B UNTIL C DO IF NSQ[I] NEQ 0 THEN GO TO PIECE; GO TO QUIT; PIECE: SQ3 := I; IF PC := NSQ[I] = -7|KK OR PC = -5|KK AND (ABS(B) = 1 OR ABS(B) = 8) OR PC = -4|KK AND (ABS(B) = 7 OR ABS(B) = 9) THEN HIDDEN := TRUE; QUIT: END OF SEARCH FOR HIDDEN ATTACK; % %*********************CHECK************************* BOOLEAN PROCEDURE CHECK(SQ,KK,MT); % HOW MANY TIMES (MT) IS SQUARE SQ "ATTACKED" % BY PIECES OF COLOUR -KK. VALUE KK,SQ; INTEGER KK,MT,SQ; BEGIN INTEGER NN,HN,ATTACKER,MATTACKER,COST,SQU,VAL,PC,L,SQ3,II,PC1,PC3; INTEGER ARRAY COUNT[0:8]; INTEGER I; BOOLEAN KINGUSED, NOTKING; LABEL OMIT; NN := HN := 0; ATTACKER := 999999; MATTACKER := COST := 0; KINGUSED := FALSE; NOTKING := IF PC1:=ABS(NSQ[SQ]) = 8 THEN FALSE ELSE TRUE; FOR L := CON[-KK,SQ] STEP KK UNTIL -KK DO IF PC:=ABS(NSQ[SQU:=CONTROL[SQ,L]]) GTR 1 OR CHECKP NEQ 0 THEN % MOD 8 NEQ 0 THEN BEGIN VAL := VALUES[PC]; IF PC = 8 THEN KINGUSED := TRUE ELSE IF PC NEQ 3 THEN IF NOTKING % CHECK IF HIDDEN ATTACK THEN IF HIDDEN(SQ,SQU,SQ3,KK) THEN SQR[HN:=HN-1] := SQ3 ELSE IF SQ3 NEQ 0 THEN IF PC3 := ABS(NSQ[SQ3]) = 7 OR PC3 = 5 AND (ABS(B)=1 OR ABS(B)=8) OR PC3= 4 AND (ABS(B)=7 OR ABS(B)=9) THEN IF VALUES[PC1] LEQ VAL THEN GO TO OMIT ELSE ELSE; % HIDDEN DEFENCE. SQR[NN:=NN+1] := SQU; COST := COST + VAL; COUNT[PC] := COUNT[PC] +1; IF ATTACKER GTR VAL THEN ATTACKER := VAL; IF MATTACKER LSS VAL THEN MATTACKER := VAL; OMIT: END; IF NN GTR 0 THEN CHECK :=FALSE ELSE CHECK:=TRUE; MINPIECE := ATTACKER; MAXPIECE := MATTACKER; VALUES[0] := IF KINGUSED THEN -COST ELSE COST; L := POWER[0] := 0; FOR I := 1 STEP 1 UNTIL 7 DO IF COUNT[I] NEQ 0 THEN FOR II:=1 STEP 1 UNTIL COUNT[I] DO POWER[L:=L+1] := POWER[L-1] +VALUES[I]; POWER[0] := NN; SQR[0] := NN + ABS(HN); FOR I := -1 STEP -1 UNTIL HN DO BEGIN % INCLUDE HIDDEN PIECES. L:=L-1; POWER[L]:=POWER[L-1] + VALUES[ABS(NSQ[SQR[L]:=SQR[I]])]; END; % PLACE KING AT END IF USED. IF KINGUSED THEN BEGIN SQR[NN] := KINGSQ[-KK]; POWER[NN] := POWER[NN-1] + VALUES[8]; END; NN := SQR[0]; END CHECK; % %******************DELETE****************** PROCEDURE DELETE(SQF,SQT,T,PC); VALUE SQF,SQT,T,PC; INTEGER SQF,SQT,T,PC; BEGIN INTEGER L,KK; LABEL NEXT; KK := SIGN(PC); FOR L := T STEP -KK UNTIL KK DO IF SQF = CONTROL[SQT,L] THEN BEGIN CONTROL[SQT,L] := CONTROL[SQT,T]; CON[KK,SQT] := T - KK; IF ABS(PC) GTR 1 OR (SQT-SQF) MOD 8 NEQ 0 THEN CON[0,SQT] := CON[0,SQT] -KK; GO TO NEXT; END; NEXT: END OF DELETE; % %****************FIXIT***************** PROCEDURE FIXIT(SQF,SQT,PC); VALUE SQF,SQT,PC; INTEGER SQF,SQT,PC; %BEGIN INTEGER M,KK,P; FORMAT FT1("FIX"3(13I5)); BEGIN INTEGER M,KK,P; FORMAT FT1("FIX",13I5,13I5,13I5); KK := SIGN(PC); M := CON[KK,SQT] + KK; IF ABS(M) GTR 6 THEN BEGIN WRITE(TTY,FT1,M,SQF,SQT,KK, % ?/6 ?/M FOR P := NUMB STEP -1 UNTIL 1 DO RLIST[P]); GO TO STARTS; END; CON[KK,SQT] := M; CONTROL[SQT,M] := SQF; IF ABS(PC) GTR 1 OR (SQT-SQF) MOD 8 NEQ 0 THEN CON[0,SQT] := CON[0,SQT] + KK; END OF FIXIT; % PROCEDURE KINGSMOVE(I); VALUE I; INTEGER I; BEGIN INTEGER L, J2, M, DUM, M6, M7, SQ, SQU,K,ONE,TWO; LABEL NEXTL; J2 := FINDJ2(I); ONE := TWO := 0; K :=SIGN(NSQ[I]); FOR N := CON[-K,I] STEP K UNTIL -K DO IF ABS(NSQ[SQU:=CONTROL[I,M]]) GTR 3 THEN BEGIN FINDABC(SQU,I); IF ONE = 0 THEN ONE := 8 ELSE TWO := 8; END; FOR L := 7 ,8, 9, -1, 1, -9, -8, -7 DO IF SQ := I + L GTR 0 AND SQ LSS 65 THEN IF KINGSM NEQ 0 THEN BEGIN % MOD 8 NEQ 0 THEN BEGIN M7 := NSQ[SQ]; M6 := IF M7 = -11|K THEN M7 := 0 ELSE K|M7; IF L = ONE OR L = TWO THEN GO TO NEXTL; % MOVE INLINE OF CHECK. IF M6 LEQ 0 THEN IF CHECK(SQ, K, DUM) THEN CHECKLIST[CLIST:=CLIST+1] :=SQ ELSE CHECKLIST[SLIST := SLIST -1] := SQ ELSE CHECKLIST[SLIST := SLIST -1] := SQ; NEXTL: END; END OF KINGSMOVE; % %******************LIST OF KING MOVES************ PROCEDURE LISTKINGMOVES(SQ); VALUE SQ; INTEGER SQ; BEGIN LABEL QUIT; INTEGER K; DEFINE TRYCASTLING = K := SIGN(NSQ[SQ]); IF K GTR 0 THEN BEGIN IF CASTLE[1] AND NSQ[8] = 5 AND NSQ[7] = 0 AND NSQ[6] = 0 THEN IF CON[-K,5] NEQ 0 THEN GO TO QUIT ELSE IF CON[-K,6] = 0 THEN IF CON[-K,7] = 0 THEN CHECKLIST[CLIST:=CLIST+1] := 7; IF CASTLE[2] AND NSQ[1]=5 AND NSQ[2]=0 AND NSQ[3]=0 AND NSQ[4]=0 THEN IF CON[-K,5] NEQ 0 THEN GO TO QUIT ELSE IF CON[-K,4] = 0 THEN IF CON[-K,3] = 0 THEN CHECKLIST[CLIST:=CLIST+1] := 3; END CASTLING FOR WHITE ELSE BEGIN IF CASTLE[-1] AND NSQ[64]=-5 AND NSQ[63]=0 AND NSQ[62]=0 THEN IF CON[-K,61] NEQ 0 THEN GO TO QUIT ELSE IF CON[-K,62] = 0 THEN IF CON[-K,63] = 0 THEN CHECKLIST[CLIST:=CLIST+1] := 63; IF CASTLE[-2] AND NSQ[57]=-5 AND NSQ[58]=0 AND NSQ[59]=0 AND NSQ[60]=0 THEN IF CON[-K,61] NEQ 0 THEN GO TO QUIT ELSE IF CON[-K,60] = 0 THEN IF CON[-K,59] = 0 THEN CHECKLIST[CLIST:=CLIST+1] := 59; END OF CASTLING FOR BLACK; COMMENT THIS CASTLING ALGORITHM WAS DEVELOPED TO MINIMIZE THE USAGE OF CONTROL. THE PROBABILITY OF SIMULTANEOUS K-SIDE AND Q-SIDE CASTLING IS VERY SMALL; % TAM QUIT: #; % END OF TRYCASTLING DEFINITION. TRYCASTLING; KINGSMOVE(59); % ORDER IMPORTANT END KINGMOVES; % %*******************UNMAKE*************** PROCEDURE UNMAKE(SQ); VALUE SQ; INTEGER SQ; BEGIN INTEGER I,KK,T,J,PC; KK := SIGN(PC:=NSQ[SQ]); IF KK = 0 THEN BEGIN T := IF POS[SQ] GTR 0 THEN POSITION[SQ,1] ELSE IF POSITION[SQ,LIM] LSS LIM THEN POSITION[SQ,LIM-1] ELSE 0; IF T GTR 0 THEN FOR J:=CON[-1,T] STEP 1 UNTIL CON[1,T] DO IF CONTROL[T,J] = SQ THEN KK := SIGN(J); END; IF KK NEQ 0 THEN BEGIN IF PC = 0 THEN PC := 2|KK; IF PC NEQ KK THEN FOR J := POS[SQ] STEP -1 UNTIL 1 DO BEGIN I:=POSITION[SQ,J]; T := CON[KK,I]; DELETE(SQ,I,T,PC); END; SLIST := POSITION[SQ,LIM]; FOR J:=LIM-1 STEP -1 UNTIL SLIST DO BEGIN I := POSITION[SQ,J]; T := CON[KK,I]; DELETE(SQ,I,T,PC); END; POS[SQ] := POSITION[SQ,0] := 0; POSITION[SQ,LIM] := LIM; END; END OF UNMAKE; % PROCEDURE MOVESQUARE(I,WDIRECT);VALUE I,WDIRECT; INTEGER I, WDIRECT; % LISTS THE MOVES FOR THE PIECE ON SQUARE I BEGIN INTEGER M1, M; % MOVESQUARE IS CALLED BY MANY PROCEDURES M1 := ABS(NSQ[I]); SLIST := LIM; CLIST := 0; F := I; % GLOBAL F IS SQUARE # IF M1 = 1 THEN LISTPAWNMOVES(I) ELSE IF M1 = 3 THEN IF WDIRECT = 0 THEN LISTKNIGHTMOVES(I) ELSE TRYKNIGHTMOVE(WDIRECT) ELSE IF M1 = 4 THEN IF WDIRECT = 0 THEN FOR M := 9,-7,-9,7 DO TRYBISHOPMOVE(M) ELSE TRYBISHOPMOVE(WDIRECT) ELSE IF M1 = 5 THEN IF WDIRECT = 0 THEN FOR M := 8,1,-1,-8 DO TRYROOKMOVE(M) ELSE TRYROOKMOVE(WDIRECT) ELSE IF M1 = 7 THEN IF WDIRECT = 0 THEN LISTQUEENMOVES(I) ELSE IF ABS(WDIRECT) = 6 OR ABS(WDIRECT) = 1 THEN TRYROOKMOVE(WDIRECT) ELSE TRYBISHOPMOVE(WDIRECT) ELSE IF M1 = 8 THEN LISTKINGMOVES(I); CHECKLIST[0]:=CLIST; CHECKLIST[LIM] := SLIST; END OF MOVESQUARE; % %********************MAKE*************** PROCEDURE MAKE(I); VALUE I; INTEGER I; BEGIN INTEGER L,PC,KK; IF PC := NSQ[I] NEQ 0 THEN BEGIN KK := SIGN(PC); MOVESQUARE(I,0); POS[I] := CLIST; FOR L := CLIST STEP -1 UNTIL 0 DO POSITION[I,L] := CHECKLIST[L]; FOR L := SLIST STEP 1 UNTIL LIM DO POSITION[I,L] := CHECKLIST[L]; IF ABS(PC) GTR 1 THEN FOR L := CLIST STEP -1 UNTIL 1 DO FIXIT(I,CHECKLIST[L],PC); FOR L:=LIM-1 STEP -1 UNTIL SLIST DO FIXIT(I,CHECKLIST[L],PC); END; END OF MAKE; % %**************REMAKE**************** PROCEDURE REMAKE(SQF,SQT); VALUE SQF,SQT; INTEGER SQF,SQT; BEGIN INTEGER I,J,L,PC,SGN,D,WDIRECT,DIST,SQ1,SQ2,SQ3,LL,L1,L2,I1,I2; LABEL QUIT, NEW,NEXTL; FORMAT FT1("REM", 3(12I5/)); BOOLEAN FLAG; INTEGER PROCEDURE DIR; BEGIN FINDABC(SQF,SQT); DIR := ABS(8); END OF DIR; PC := NSQ[SQF]; IF MAKEMV AND REMEMBER THEN BEGIN IF SQF = KINGSQ[1] OR SQF = KINGSQ[-1] THEN GO TO QUIT; IF ABS(PC) = 1 THEN % WILL DUPLICATE INLINE MOVES ONLY. FOR L := NUMB STEP -1 UNTIL 1 DO IF SQF = RLIST[L] THEN GO TO QUIT; RLIST[NUMB := NUMB+1] := SQF; TLIST[NUMB] := SQT; END; IF PC = 0 THEN BEGIN WRITE(TTY,FT1,SQF,SQT,FOR I:=NUMB STEP -1 UNTIL 0 DO [RLIST[I],TLIST[I]]); GO TO STARTS; END; IF SQT = SQF OR ABS(PC) LSS 2 OR ABS(PC) GTR 7 % OP NOT TEST THEN BEGIN MOVESQUARE(SQF,0); % FILLS CHECKLIST FOR L:=LIM STEP -1 UNTIL 0 DO OLDLIST[L]:=POSITION[SQF,L]; FOR L:=LIM STEP -1 UNTIL 0 DO POSITION[SQF,L]:=CHECKLIST[L]; L1:=OLDLIST[0]; L2:=I2:=1; I1:=POS[SQF]:=CLIST; FLAG:=TRUE; IF SLIST - CLIST NEQ OLDLIST[LIM] - L1 THEN DO BEGIN FLAG := NOT FLAG; IF FLAG OR ABS(PC) GTR 1 THEN BEGIN FOR L := L2 STEP 1 UNTIL L1 DO BEGIN SQ1:=OLDLIST[L]; FOR I:=I2 STEP 1 UNTIL I1 DO IF SQ2:=CHECKLIST[I] NEQ 0 THEN IF SQ2 = SQ1 THEN BEGIN CHECKLIST[I] := 0; GO TO NEXTL;END; DELETE(SQF,SQ1,CON[SIGN(PC),SQ1],PC); NEXTL: END; FOR I:=I2 STEP 1 UNTIL I1 DO IF SQ2:=CHECKLIST[I] NEQ 0 THEN FIXIT(SQF,SQ2,PC); END; L2 := OLDLIST[LIM]; L1 := I1 := LIM-1; I2 := SLIST; END UNTIL FLAG END ELSE BEGIN SGN := SIGN(D:=(SQT-SQF)); WDIRECT := IF ABS(PC) = 5 THEN IF ABS(D) LSS 8 THEN 1 ELSE 8 ELSE IF ABS(PC) = 4 THEN IF D MOD 7 = 0 THEN 7 ELSE 9 ELSE IF ABS(PC) = 7 THEN IF ABS(D) LSS 7 THEN 1 ELSE IF D MOD 8 = 0 THEN 8 ELSE IF D MOD 7 = 0 THEN DIR ELSE 9 ELSE ABS(D); WDIRECT := SGN|WDIRECT; MOVESQUARE(SQF,WDIRECT); % FILLS CHECKLIST SQ1 := SQF + WDIRECT; DIST := D DIV WDIRECT; FOR L := LIM STEP -1 UNTIL 0 DO OLDLIST[L] := POSITION[SQF,L]; LL := OLDLIST[0]; J := 0; FLAG := TRUE; FOR L := 1 STEP 1 UNTIL LL DO BEGIN SQ2 := NEWLIST[J:=L] := OLDLIST[L]; IF SQ2 = SQ1 THEN BEGIN % PIECES NOT ADJACENT J := L-1; DO L:=L+1 UNTIL L GTR LL OR OLDLIST[L] NEQ SQ1:=SQ1+WDIRECT; DIST := L -J -1; FOR I:=L STEP 1 UNTIL LL DO NEWLIST[J:=J+1] :=OLDLIST[I]; GO TO NEW; END; END; L:=LL; DIST:=DIST-1; % OWN PIECE ON ADJACENT SQUARE. NEW: FOR I:=1 STEP 1 UNTIL CLIST DO NEWLIST[J:=J+1] := CHECKLIST[I]; POS[SQF] := NEWLIST[0] := J; IF CLIST LSS DIST THEN FOR J:=L+CLIST-DIST STEP 1 UNTIL L-1 DO BEGIN IF J LSS 1 THEN WRITE(TTY,FT1,SQF,SQT,PC,D,WDIRECT,DIST,CLIST,L,LL, FOR I:=NUMB STEP -1 UNTIL 0 DO [RLIST[I],TLIST[I]]); SQ3:=OLDLIST[J]; DELETE(SQF,SQ3,CON[SIGN(PC),SQ3],PC); END; LL := OLDLIST[LIM]; J:=LIM; FOR L := LIM-1 STEP -1 UNTIL LL DO BEGIN SQ2 := NEWLIST[J:=J-1] := OLDLIST[L]; IF FLAG THEN IF SIGN(SQ2-SQF) = SIGN(D) THEN BEGIN FINDABC(SQF,SQ2); IF D = WDIRECT OR SQ2 = SQT THEN BEGIN J:=J+1; DELETE(SQF,SQ2,CON[SIGN(PC),SQ2],PC); FLAG := FALSE; END; END; END; IF SLIST NEQ LIM THEN BEGIN SQ3:=NEWLIST[J:=J-1] :=CHECKLIST[SLIST]; FIXIT(SQF,SQ3,PC); END; NEWLIST[LIM] := J; IF DIST LSS CLIST THEN FOR J:=DIST +1 STEP 1 UNTIL CLIST DO FIXIT(SQF,CHECKLIST[J],PC); FOR L:=LIM STEP -1 UNTIL 0 DO POSITION[SQF,L] := NEWLIST[L]; END; QUIT: END OF REMAKE; % PROCEDURE LISTMOVES; %ALL MOVES ARE LISTED INCLUDING SOME WHICH PUT OWN KING IN CHECK BEGIN INTEGER M,I,L,PC,N,SQ,R; DEFINE LISTMOVE = BEGIN MERIT := ABS(N := N+K); FROMSQ := I; TOSQUARE := SQ := POSITION[I,L]; CONSEQ := IF R := ABS(NSQ[SQ]) = 11 THEN IF ABS(PC) = 1 THEN R ELSE 0 ELSE R; % PIECE CAN MOVE TO E IF ABS(PC) = 8 THEN IF ABS(SQ-I) = 2 THEN % CASTLING CONSEQ := IF I GTR SQ THEN 9 ELSE 10; % PF 2 IF ABS(PC) = 1 THEN IF ABS(I-SQ) = 16 THEN CONSEQ:=12; END #; M := 0; FOR I := 1 STEP 1 UNTIL 64 DO IF M:=POS[I] GTR 0 THEN IF SIGN(PC:=NSQ[I]) = K THEN IF ABS(PC) NEQ 11 THEN IF ABS(PC) GTR 1 OR M LSS 4 THEN BEGIN FOR L := M STEP -1 UNTIL 1 DO LISTMOVE; END ELSE BEGIN % PAWN MOVE WITH POTENTIAL PROMOTION IF POSITION[I,1] NEQ POSITION[I,2] THEN % FLUKE FOR L := N STEP -1 UNTIL 1 DO LISTMOVE ELSE BEGIN N := M DIV 4; % that N is a guess FOR L := 1 STEP 1 UNTIL N DO FOR R := 13,14,15,17 DO BEGIN MERIT := ABS(N:=N+K); FROMSQ := I; TOSQUARE := POSITION[I,4|L]; CONSEQ := R; END; END; END; NUM := ABS(NUMBER[K] := N); END LISTMOVES; % %*******************SACRIFICE********************* BOOLEAN PROCEDURE SACRIFICE(SQ, PRINT); % DETERMINES WHETHER THE PIECE ON SQUARE SQ IS BEING ATTACKED VALUE SQ; BOOLEAN PRINT; INTEGER SQ; BEGIN INTEGER MAXATTACK, MINATTACK, TOTALATTACK, IA, ID, LOST; INTEGER ARRAY ATTACKERS[0:9]; FORMAT FT1 ("SACR",24I5); INTEGER COST, PC, ROW; LABEL SWAP, NOSWAP, NOPIN, NONPIN; INTEGER I, L, LL, SQ3, BB; SACRIFICE := FALSE; MINATTACK := 999999; LOSSES := ATTASQRS[0] := 0; IF NOT CHECK(SQ,K,IA) THEN BEGIN MAXATTACK := MAXPIECE; TOTALATTACK := VALUES[0]; MINATTACK := MINPIECE; LOST := IF PC := ABS(NSQ[SQ]) NEQ 1 OR ROW := K|(2|((SQ-1) DIV 8) -7) LSS 0 THEN VALUES[PC] ELSE (VALUES[1]|(7+ROW)) DIV 6; FOR I := IA STEP 1 UNTIL 1 DO BEGIN ATTACKERS[I] := POWER[I] -LOST; ATTASQRS[I] := SQR[I]; % SEE IF ATTACKED PIECES ARE PINNED AGAINST THE KING. % A MORE GENERAL ROUTINE IS REQUIRED, PIN AGAINST ANY MAJOR PIECE. IF HIDDEN(KINGSQ[-K], SQR[I], SQ3, -K) THEN BEGIN % SEE IF SQR[I] REALLY PINNED. FOR LL := KINGSQ[-K] +8 STEP 8 UNTIL SQR[I] -8 DO IF NSQ[LL] NEQ 0 THEN GO TO NOPIN; % DOES SQR[I] ATTACK SQ. BB := B; FINDABC(SQR[I], SQ); IF (PC := ABS(NSQ[SQR[I]]) = 7 OR PC = 5 OR PC = 4 OR PC = 1 AND (SQ -SQR[I]) = BB) AND BB = B THEN GO TO NOPIN; IA := IA -1; NOPIN: END; END; ATTASQRS[0] := SQR[0]; IF IA GTR 0 THEN IF CHECK(SQ, -K, ID) THEN BEGIN SACRIFICE := TRUE; LOSSES := LOST; END ELSE BEGIN FOR I := ID STEP -1 UNTIL 1 DO IF HIDDEN(KINGSQ[K], SQR[I], SQ3, K) THEN BEGIN FOR LL := KINGSQ[K] +8 STEP 8 UNTIL SQR[I] -8 DO IF NSQ[LL] NEQ 0 THEN GO TO NONPIN; FOR L := IA STEP -1 UNTIL 1 DO IF SQ3 = ATTASQRS[L] THEN GO TO NONPIN; ID := ID -1; NONPIN: END; IF COST := LOST - MINATTACK GTR 0 THEN GO TO SWAP; IF IA =1 THEN IF ID GTR 0 THEN GO TO NOSWAP; IF IA GTR ID THEN % E.G., BN/P/QK, N/P/R, RR/P/NQ, PP/P/NNB, RR/B/P, QBN/B/NR BEGIN FOR I := ID STEP -1 UNTIL 1 DO % QP/N/RQ, QN/Q/NBK IF COST := POWER[I] -ATTACKERS[I] LEQ 0 THEN GO TO NOSWAP ELSE IF COST LSS LOST THEN GO TO SWAP; COST := LOST; SWAP: LOSSES := COST; SACRIFICE := TRUE; END ELSE % 2 LEQ IA LEQ ID. FOR I := 2 STEP 1 UNTIL IA DO IF COST := POWER[I-1] - ATTACKERS[I] GTR 0 THEN BEGIN IF COST GTR LOST THEN COST := LOST; GO TO SWAP; END; END; END; NOSWAP: IF DUMPP AND NOT LOOKAHEAD AND PRINT AND ( LOSSES NEQ 0 AND ID LSS IA) THEN WRITE(TTY, FT1, IA, MINATTACK, MAXATTACK, TOTALATTACK, SQ, NSQ[SQ], VALUES[0], MAXPIECE, MINPIECE, ID, LOSSES ); END OF SACRIFICE; %**************KINGCONTROL*************** PROCEDURE KINGCONTROL(K); VALUE K; INTEGER K; BEGIN INTEGER I, SQ, J,KSQ; KSQ := KINGSQ[K]; J := 0; FOR I := 7,8,9,1,-7,-8,-9,-1 DO IF SQ := KSQ +I GTR 0 THEN IF SQ LSS 65 THEN KSQRS[J:=J+K] := SQ; KSQRS[9|K] := J; END OF KINGCONTROL; %*****************MAKE MOVE************ PROCEDURE MAKEMOVE(N, FINAL); % MOVES PIECES AND KEEP TRACK OF PIECE COUNT. VALUE N; INTEGER N; BOOLEAN FINAL; BEGIN INTEGER I,TT, M, M1, M4, T,L,K; BOOLEAN CASTLING; FORMAT FT1("MAKEMOVE. NO PIECE ON SQUARE",12I5); K := SIGN(NSQ[M2:=FROMSQ]); IF K = 0 THEN BEGIN WRITE(TTY,FT1,M2,TOSQUARE,CONSEQ, N); PRINTBOARD; GO TO STARTS; END; % ERROR TERMINATION PROMCAPT := M8 := M9 := M14 := 0; MAKEMV := TRUE; IF REMEMBER THEN BEGIN KSQ := KINGSQ[K]; M11 := 0; M4 := (29+12|K); T := M4 + 8; M12:= -11|K; FOR I := M4 STEP 1 UNTIL T DO IF NSQ[I] = M12 THEN BEGIN NSQ[I] := 0; M11 := I; END; END; M1 := ABS(CONSEQ) ; IF M1 LSS 20 THEN TT := 0 ELSE BEGIN TT:=M1 DIV 20; M1 := M1 MOD 20; END; M3 := TOSQUARE; M4 := ABS(M5 := NSQ[M2]); M6 := M7 := NSQ[M3]; UNMAKE(M2); % MOVING PIECE IF M7 NEQ 0 THEN UNMAKE(M3); % CAPTURED PIECE NSQ[M2] := 0; IF REMEMBER THEN BEGIN NUMB := -1; IF M4 NEQ 8 THEN RLIST[NUMB:=0] := TLIST[0] := KSQ; NUMB := NUMB +1; RLIST[NUMB] := TLIST[NUMB] := KINGSQ[-K]; END; IF M1 GTR 12 THEN BEGIN PROMCAPT := ABS(M7); NSQ[M3] := M14 := (M1 -10)|K; % PROMOTED PIECE PIECES[M14] := PIECES[M14] +1; END ELSE BEGIN IF M1 = 11 THEN BEGIN UNMAKE(M9:=M3-8|K); % M9 IS THE SQUARE OF NSQ[M9] := 0; % THE ENPASSANT PAWN. M6 := M10 := -K; END ELSE IF M1 = 9 % CASTLE Q-SIDE THEN BEGIN M10 := NSQ[M8 := M3+1] := NSQ[M9:=M3-2]; CASTLING := TRUE; UNMAKE(M9); % KING ROOK NSQ[M9] := 0; END % M8 IS THE NEW SQUARE OF THE ROOK ELSE IF M1 = 10 % CASTLE K-SIDE. THEN BEGIN M10 := NSQ[M8:=M3-1] := NSQ[M9:=M3+1]; CASTLING := TRUE; UNMAKE(M9); % QUEEN ROOK NSQ[M9] := 0; END % M9 IS THE OLD SQUARE OF THE ROOK ELSE IF M1 = 12 THEN IF ((T := MAKEM) NEQ 0 AND NSQ[M3+K] = -K) OR (T NEQ 1 AND NSQ[M3-K] = -K) THEN BEGIN NSQ[M8:=M3+8|K] := -M12; % M8 IS A POTENTIAL; E.P SQ.%M3 guess IF NSQ[M3+K] = -K THEN REMAKE(M3+K,M3+K); IF NSQ[M3-K] = -K THEN REMAKE(M3-K,M3-K); END; NSQ[M3] := M5; % MOVING PIECE END; FOR L:=CON[K,M2] STEP -K UNTIL K DO REMAKE(CONTROL[M2,L],M2); FOR L:=CON[-K,M2] STEP K UNTIL -K DO REMAKE(CONTROL[M2,L],M2); REMEMBER := WTERMINAL; % ONLY INCREMENNT NUMB IF TERMINAL MOVE FOR L:=CON[K,M3] STEP -K UNTIL K DO REMAKE(CONTROL[M3,L],M3); FOR L:=CON[-K,M3] STEP K UNTIL -K DO REMAKE(CONTROL[M3,L],M3); IF M10 = -K OR CASTLING THEN % ENPASSANT PAWN BEGIN FOR L:=CON[K,M9] STEP -K UNTIL K DO REMAKE(CONTROL[M9,L],M9); FOR L:=CON[-K,M9] STEP K UNTIL-K DO REMAKE(CONTROL[M9,L],M9); IF CASTLING THEN BEGIN % EX DEFENCE OF ROOKS SQUARE FOR L:=CON[-K,M8] STEP -K UNTIL K DO REMAKE(CONTROL[M8,L],M8); MAKE(M8); END; END; MAKE(M3); MAKEMV := FALSE; % MOVING PIECE IF M4 = 8 THEN BEGIN KINGSQ[K] := M3; KINGCONTROL(K); END ELSE REMAKE(KSQ,KSQ); REMAKE(KINGSQ[-K],KINGSQ[-K]); IF FINAL THEN BEGIN VALUES[0] := 0; IF M6 NEQ 0 THEN PIECES[M6] := PIECES[M6] -1; % CAPTURE IF M1 GTR 12 THEN PIECES[K] := PIECES[K] -1 % PROMOTION INCREASE SEPARATE. ELSE IF M4 = 8 THEN CASTLE[K] := CASTLE[2|K] := FALSE ELSE IF M4 = 5 THEN IF M2 = 36 -28|K THEN CASTLE[K] := FALSE % K-ROOK MOVING. ELSE IF M2 = 29 -28|K THEN CASTLE[2|K] := FALSE; % Q-ROOK MOVING. KTEST := IF TT GTR 4 THEN 4 ELSE IF TT LSS 4 THEN IF ABS(M7) = 8 THEN 5 ELSE 0 ELSE 2; DIFFVAL := DIFFVAL + (VALUES[ABS(M6)] + (IF M1 GTR 12 THEN VALUES[ABS(M14)] - VALUES[1] ELSE 0))|K; COUNT := COUNT +1; IF K = -1 THEN MOVECOUNT := MOVECOUNT +1; IF I := SQUARE[0] GTR 0 THEN BEGIN K := -K; M := 0; FOR I := I STEP -1 UNTIL 1 DO IF SIGN(NSQ[SQUARE[I]]) = K THEN IF SACRIFICE(SQUARE[I],FALSE) THEN BEGIN OLDSQUARE[M:=M+1] := SQUARE[I]; OLDLOSS[M] := LOSS[I]; LOSS[I] := 0; END; K := +K; OLDSQUARE[0] := M; END ELSE OLDSQUARE[0] := 0; TWOVAL := 0; IF CON[-K,M3] NEQ 0 THEN IF SACRIFICE(M3,FALSE) THEN BEGIN OLDSQUARE[M:=M+1] := M3; % EXCHANGE PIECE IS EP. OLDLOSS[M] := TWOVAL := VALUES[M4]; OLDSQUARE[0] := M; END ; END; END OF MAKEMOVE; %**************UPDATE************ PROCEDURE UPDATE; % BOARD POSITION GOOD. UPDATE MOVE LIST BEGIN INTEGER II,PC; FORMAT FT1("UPDA",3(13I5/)); PC := NSQ[M3] := IF M14 = 0 THEN NSQ[M2] ELSE M14; UNMAKE(M3); NSQ[M3] := M7; IF M8 GTR 0 THEN BEGIN NSQ[M8] := NSQ[M9]; UNMAKE(M8); NSQ[M8] := 0; END; IF M9 GTR 0 THEN MAKE(M9); IF M7 NEQ 0 THEN MAKE(M3); MAKE(M2); FOR II:=NUMB STEP -1 UNTIL 0 DO REMAKE(RLIST[II],TLIST[II]); IF DUMPP THEN WRITE(TTY,FT1,BACKLIST); IF DUMPP AND M14 NEQ 0 THEN PRINTBOARD; IF ABS(PC) = 8 THEN KINGCONTROL(SIGN(PC)); END OF UPDATE; %*************TAKE BACK MOVE************* PROCEDURE TAKEBACKMOVE; % RETRACTS LAST MOVE MADE BY MAKEMOVE DURING MOBILITYSCORE. BEGIN INTEGER II,L,K; K := SIGN(NSQ[M3]); KINGSQ[K] := KSQ; UNMAKE(M3); NSQ[M2] := M5; NSQ[M3] := M7; IF M6 GTR 0 THEN BEGIN UNMAKE(M6); NSQ[M8] := 0; END; IF M9 GTR 0 THEN BEGIN NSQ[M9] := M10; MAKE(M9); END; IF M7 NEQ 0 THEN MAKE(M3); % RESTORE CAPTURED PIECE. IF M11 GTR 0 THEN NSQ[M11] := M12; MAKE(M2); FOR II := NUMB STEP -1 UNTIL 0 DO REMAKE(RLIST[II],TLIST[II]); IF ABS(M5) = 8 THEN KINGCONTROL(SIGN(M5)); IF M14 NEQ 0 THEN PIECES[M14] := PIECES[M14] -1; % RETRACT PROMOTION. END OF TAKEBACKMOVE; %*******************FORKLOSS********************* INTEGER PROCEDURE FORKLOSS(SQ); VALUE SQ; INTEGER SQ; BEGIN INTEGER L, LOSS, HI, HIGH, PC; BOOLEAN NOTCHECK; HIGH := LOSS := 0; NOTCHECK := TRUE; FOR L := 1 STEP 1 UNTIL CLIST DO IF PC:=ABS(NSQ[CHECKLIST[L]]) GTR 0 THEN BEGIN IF PC = 8 THEN NOTCHECK := FALSE; IF HI := VALUES[PC] GTR HIGH THEN HIGH := HI; LOSS := LOSS + HI; END; IF NOTCHECK THEN IF 2|VALUES[ABS(NSQ[SQ])] GTR LOSS THEN LOSS:=HIGH; % MUST RE-ORG. IN ORDER TO CALL SACRIFICE FORKLOSS := LOSS - HIGH; END OF FORKLOSS; %*******************ENPRISE********************** PROCEDURE ENPRISE; % DETERMINES WHICH MOVING PIECES ARE ENPRISE. BEGIN INTEGER I, APC, L, PC, SQ, M; M := 0; FOR SQ := 1 STEP 1 UNTIL 64 DO IF K|(NSQ[SQ]) GTR 0 THEN BEGIN IF SQ NEQ KINGSQ[K] THEN IF CON[-K,SQ] NEQ 0 THEN % ATTACKED IF SACRIFICE(SQ, TRUE) THEN BEGIN SQUARE[M := M + 1] := SQ; PC := NSQ[SQ]; K := -K; FOR I := SQR[0] +1 STEP 1 UNTIL ATTASQRS[0] DO BEGIN APC := NSQ[SQ] := NSQ[ATTASQRS[I]]; NSQ[ATTASQRS[I]] := 0; IF APC = K AND (K = 1 AND SQ GTR 56 OR K = -1 AND SQ LSS 0) THEN BEGIN FOR APC := 3,4,5,7 DO BEGIN NSQ[SQ] := APC|K; MOVESQUARE(SQ,0); LOSSES := LOSSES + (IF CLIST GTR 1 THEN FORKLOSS(SQ) ELSE 0); END; NSQ[ATTASQRS[I]] := K; END ELSE BEGIN MOVESQUARE(SQ,0); % FILLS CHECKLIST LOSSES := LOSSES + (IF CLIST GTR 1 THEN FORKLOSS(SQ) ELSE 0); NSQ[ATTASQRS[I]] := NSQ[SQ]; END; END; K := -K; NSQ[SQ] := PC; LOSS[M] := LOSSES; END; END OF FOR SQ LOOP; SQUARE[0] := M; END OF ENPRISE; % PROCEDURE HIDDENLOSS(N); VALUE N; INTEGER N; BEGIN INTEGER SQF,SQT,SQA,SQD,SQ3,SQ33,I,J,K,L,PC,PCA,PCD,SAVEB; BOOLEAN T; L := SQUARE[0]; SQF := FROMSQ; SQT := TOSQUARE; K := SIGN(PC:=NSQ[SQF]); IF K = 0 THEN GO TO STARTS; % DIRECT PIN FOR J := CON[-K,SQF] STEP K UNTIL -K DO IF PCA := ABS(NSQ[SQA:=CONTROL[SQF,J]]) = 7 OR PCA = 5 OR PCA = 4 THEN BEGIN T := HIDDEN(SQA,SQF,SQ3,K); IF SQ3 NEQ 0 THEN IF SIGN(NSQ[SQ3]) = K THEN BEGIN SAVEB := B; FINDABC(SQF,SQT); IF ABS(B) NEQ ABS(SAVEB) THEN SQUARE[L:=L+1] := SQ3; END; END; % INDIRECT PIN FOR J := POSITION[SQF,LIM] STEP 1 UNTIL LIM-1 DO IF SIGN(NSQ[SQD:=POSITION[SQF,J]]) = K THEN SQUARE[L:=L+1] := SQD; IF ABS(PC) = 8 THEN BEGIN % CHECK FOR CASTLING I := CONSEQ; SQ3 := IF I = 9 THEN 29-28|K ELSE IF I = 10 THEN 36-28|K ELSE 0; IF SQ3 NEQ 0 THEN FOR SQD := POSITION[SQ3,LIM] STEP 1 UNTIL LIM-1 DO IF SQD NEQ KINGSQ[K] AND SIGN(NSQ[SQD]) = K % examine = or NEQ THEN SQUARE[L:=L+1] := SQD; END; % BLOCKING A DEFENCE FOR I := CON[K,SQT] STEP -K UNTIL K DO IF PCD := ABS(NSQ[SQD:=CONTROL[SQT,I]]) = 7 OR PCD = 5 OR PCD = 4 THEN BEGIN T := HIDDEN(SQD,SQT,SQ3,-K); IF SIGN(NSQ[SQ3]) = K THEN SQUARE[L:=L+1] := SQ3; END; % UNPINNING ATTACK FOR I := POS[SQF] STEP -1 UNTIL 1 DO IF SIGN(NSQ[SQA := POSITION[SQF,I]]) = -K THEN BEGIN T := HIDDEN(SQF,SQA,SQ3,K); IF SIGN(PCA := NSQ[SQ3]) = -K THEN IF PC LSS -K|PCA THEN % POSSIBLE UNPIN BEGIN T := HIDDEN(SQT,SQA,SQ33,K); IF SQ3 NEQ SQ33 THEN % DEFINITE UNPIN FOR J := POS[SQA] STEP -1 UNTIL 1 DO IF SIGN(NSQ[SQD := POSITION[SQA,J]]) = K THEN SQUARE[L:=L+1] := SQD; END; END; LOSS[0] := L; END OF HIDDEN LOSS; % %************MOBILITYSCORE************ PROCEDURE MOBILITYSCORE(BEST); % SCORES ON MOBILITY AND DEFENCE % THIS WHOLE CHESS PROGRAM IS POORLY ORGANIZED AND INEFFICIENT. % A COMPLETE RE-WRITING IS PROBABLY BETTER THAN CONTINUED EVOLUTION % TOO MUCH RELIANCE HAS BEEN PLACED ON GLOBAL VARIABLES, % IN THE INTERESTS OF EFFECTIVE CORE UTILIZATION. % ONE IMMEDIATE PROSPECT FOR INCLUDEING "LEARNING" CAPACITY % IS TO TRY TO FIND THE BEST SCORING PARAMETERS VALUES[12],5,2 % ( AS USED IN MOBILITYSCORE AND SELECTRTMV) % SINCE THESE WERE ARBITARILY CHOSEN. INTEGER BEST; BEGIN INTEGER MV, SAMV,SC,NK, JJ, SQ, SVMV, RESULTN,PC,ROW, JN, I,II; LABEL SKIP, NEXTJJ, TEST; INTEGER GAINS, EPGAIN, EP,EPSQ, SQA, SAVEB,GOODCASTLE,KINGATTACKER,SQJJ, L,J, ATTACKSCORE,DEFENCESCORE,N,KSQ,ENPR,MF,BASE,NN,IP; BOOLEAN SACRIFICING, DBLCHECK,KINGCHECK, MATE, LEGALMV; %*****************SCOREMOVE*************** PROCEDURE SCOREMOVE; % GENERATES WCON, BCON, ONUM, CNUM ETC AS OUTPUT BEGIN INTEGER I,PC,KK,VAL; ASCORE:=DSCORE:=VALUES[8]:=WCON := BCON :=ONUM := CNUM := 0; FOR I := 1 STEP 1 UNTIL 64 DO BEGIN IF PC:=CON[0,I] GTR 0 THEN WCON := WCON+1 ELSE IF PC LSS 0 THEN BCON := BCON +1; IF PC := NSQ[I] NEQ 0 THEN BEGIN VAL := VALUES[ABS(PC)]; KK := SIGN(PC); ASCORE := ASCORE + CON[-KK,I]|VAL; DSCORE := DSCORE + CON[KK,I]|VAL; IF PC GTR 0 THEN ONUM := ONUM + POS[I] ELSE CNUM := CNUM + POS[I]; END; END; VALUES[8] := KINGVAL; FOR I := KSQRS[-9] STEP 1 UNTIL -1 DO WCON := WCON + ABS(CON[1,KSQRS[I]]); FOR I := KSQRS[9] STEP -1 UNTIL 1 DO BCON := BCON + ABS(CON[-1,KSQRS[I]]); IF K = 1 THEN BEGIN PC := ONUM; ONUM := CNUM; CNUM := PC; PC := BCON; BCON := WCON; WCON := PC; END; END OF SCOREMOVE; % %***********EPSCORE****************** INTEGER PROCEDURE EPSCORE(SQT,SACRIFICING); % FIND THE SECOND LARGEST P VALUE SQT; INTEGER SQT; BOOLEAN SACRIFICING; BEGIN INTEGER I,J,SQA,OLD,SCR; LABEL NEXT; SCR := EPSCORE := 0; I := OLDSQUARE[0]; K := -K; IF SACRIFICING OR I GTR 1 THEN FOR I := I STEP -1 UNTIL 1 DO IF SQA := OLDSQUARE[I] NEQ SQT THEN % NOT JUST CAPTURED IF SACRIFICE (SQA,FALSE) THEN BEGIN % STIL ENPRISE IF OLD := OLDLOSS[I] GTR SCR THEN BEGIN % LARGEST PIECE IF SACRIFICING THEN % DOES SQA ATTACK SQT FOR J := CON[K,SQT] STEP -K UNTIL K DO IF SQA = CONTROL[SQT,J] THEN GO TO NEXT % YES IT DOES ELSE SCR := OLD; EPSCORE := SCR; SCR := OLD; END; NEXT: END; K := -K; END OF EPSCORE; % IF INCHECK THEN BEGIN KSQ := KINGSQ[K]; FINDABC(KSQ,CHECKSQ); IF SAVEB:=B = 0 THEN SAVEB := CHECKSQ -KSQ; END; % KNIGHT ATTACK FROMSQ := N := 0; NN := SPAN[0]; WTERMINAL := REMEMBER := TRUE; BASE := MVS := 0; SC := VALUES[12]; FOR IP:=NN STEP -1 UNTIL 1 DO BEGIN N := BESTMOVES[IP]; SQ := EPSQ := TOSQUARE; IF INCHECK THEN FOR JJ := KSQ+SAVEB STEP SAVEB UNTIL CHECKSQ DO IF JJ = SQ THEN LEGALMV := FALSE ELSE LEGALMV := TRUE ELSE LEGALMV := TRUE; MF := FROMSQ; IF LEGALMV OR ABS(NSQ[MF]) = 8 THEN BEGIN % KINGMOVE OR LEGAL MOVE IF WTERMINAL THEN BASE := MF ELSE FROMSQ:=LASTSQUARE; WTERMINAL:=IF BASE NEQ NEXTSQUARE OR CONSEQ NEQ 0 THEN TRUE ELSE FALSE; HIDDENLOSS(N); % ADD "HIDDEN" PIECES TO ENPRISE LIST MAKEMOVE(N,FALSE); KSQ := KINGSQ[K]; % MAKE MOVE N IF CON[-K,KSQ] = 0 OR CHECK(KSQ,K,I) THEN BEGIN RESULTN := CONSEQ; MV := ENPR := 0; KINGCHECK := MATE := FALSE; IF CON[-K,SQ] NEQ 0 THEN SQUARE[LOSS[0]:=LOSS[0]+1] := SQ; IF RESULTN = 12 THEN IF NSQ[SQ-8|K] = 11|K % ADD ENPASSANT SQ THEN SQUARE[LOSS[0]:= LOSS[0]+1] := SQ-8|K; % TO ENPRISE LIST SCOREMOVE; % REMOVE MOBILITY OF LARGEST PIECE LATER. KSQ := KINGSQ[-K]; IF CON[K,KSQ] NEQ 0 THEN IF NOT CHECK(KSQ,-K,I) THEN BEGIN II := IF I = 1 AND SQ NEQ SQR[I] THEN 3 ELSE I; % DIS. CH. CONSEQ := CONSEQ + II|20; KINGCHECK := TRUE; KINGATTACKER := SQR[1]; DBLCHECK := IF II = 2 THEN TRUE ELSE FALSE; IF POS[KSQ] = 0 THEN BEGIN MATE := TRUE; SQA := 0; IF NOT DBLCHECK THEN IF SACRIFICE(KINGATTACKER,FALSE) THEN MATE := FALSE ELSE SQA := KINGATTACKER; % TEST FOR IF SQA GTR 0 THEN BEGIN FINDABC(SQA,KSQ); IF B NEQ 0 THEN FOR SQA := SQA+B STEP B UNTIL KSQ-B DO IF CON[-K,SQA] NEQ 0 THEN MATE := FALSE; % CAN INTERPOSE END; IF MATE THEN CONSEQ := CONSEQ + 80; END; END ELSE ELSE I := 0; % FOR JJ := LOSS[0] STEP -1 UNTIL 1 DO BEGIN IF NSQ[SQJJ:=SQUARE[JJ]] = 0 THEN IF EP := LOSS[JJ] - VALUES[ABS(NSQ[SQ])] GTR 0 THEN GO TO TEST % DON-T TRY TO MOVE FORKED PIECE, DEFEND IT. ELSE GO TO NEXTJJ ELSE IF SACRIFICE(SQJJ, FALSE) THEN BEGIN IF KINGCHECK THEN IF SQR[0] NEQ 0 OR NSQ[ATTASQRS[ATTASQRS[0]]] NEQ -8|K THEN IF SQJJ NEQ KINGATTACKER THEN GO TO NEXTJJ ELSE IF DBLCHECK THEN GO TO NEXTJJ; IF EP := LOSS[JJ] LSS LOSSES THEN EP := LOSSES; TEST: IF ENPR LSS EP THEN BEGIN ENPR := EP ; EPSQ := SQJJ; END; END ELSE GO TO NEXTJJ; NEXTJJ: END; SACRIFICING := IF ENPR GTR 0 THEN TRUE ELSE FALSE; IF SACRIFICING THEN CNUM := CNUM - POS[EPSQ]; % -MOBILITY SAMV := IF DEBUG THEN DATUM - 5|(ONUM - CNUM + WCON - BCON) ELSE ((DATUM|CNUM|BCON) DIV (ONUM|WCON)); IF I NEQ 0 THEN MV := MV +60|I; % DIS. & DBL. CH IF NOQUEEN THEN IF ABS(NSQ[SQ]) = 7 THEN MV:=MV-SC | 15; EPGAIN := EPSCORE(EPSQ,SACRIFICING); PC := RESULTN ; IF PC GTR 9 THEN PC:=PC-10; GAINS := 0; IF PROMCAPT NEQ 0 THEN GAINS := GAINS + VALUES[PROMCAPT]; IF PC GTR 0 AND PC LSS 9 THEN GAINS := GAINS + (IF PC GTR 1 OR ROW:=K|(2|((SQ-1) DIV 8) -7) GTR 0 THEN VALUES[PC] ELSE (VALUES[1]|(7+ROW)) DIV 6); IF NOT LOOKAHEAD THEN IF RESULTN = 9 OR RESULTN = 10 THEN % CASTLING SCORE. BEGIN GOODCASTLE := 1; L := SQ + (IF RESULTN = 9 THEN 8 ELSE 9)|K; FOR J := L-2 STEP 1 UNTIL L DO IF NSQ[J] NEQ K THEN IF NSQ[J+8|K] NEQ K THEN GOODCASTLE := -1; END ELSE IF ABS(NSQ[SQ]) = 8 THEN % KEEP CASTLING PROSPECTS GOODCASTLE := IF CASTLE[K] OR CASTLE[2|K] THEN -1 ELSE 0 ELSE GOODCASTLE := 0; IF GOODCASTLE NEQ 0 THEN MV := MV + GOODCASTLE|SC|10; GAINS := GAINS + EPGAIN - ENPR; EP := IF ENPR GTR 0 THEN IF GAINS GTR 0 THEN 0 ELSE % PENALIZE IF IF REALVAL LSS 0 THEN -REALVAL ELSE ? ELSE 0; % TRADING WHEN LOST SVMV:=MV:=MV +SC|(ONEVAL + GAINS - EP); % INCLUDE LOSSES LATER % ABOVE PRODUCES AN EXCHANGE PENALTY WHEN DOWN. ATTACKSCORE := ASCORE|K; DEFENCESCORE := DSCORE|K; MV := MV + 5|ATTACKSCORE + 2|DEFENCESCORE; IF DUMPP THEN BEGIN JN := 8|N; STORE[JN] := EPGAIN; STORE[JN+1] := SAMV; STORE[JN+2] := SVMV; STORE[JN+3] := MV; STORE[JN+4] := GAINS; STORE[JN+5] := ENPR; STORE[JN+6] := ATTACKSCORE; STORE[JN+7] := DEFENCESCORE; END; REWARD := IF SVMV := DATUM + MV LSS 0 THEN 0 ELSE IF SVMV GTR 4095 THEN 4095 ELSE SVMV; MERIT := IF MV := SAMV + MV LSS 0 THEN BAD+1 ELSE IF MATE THEN 8191 ELSE IF MV GTR 8190 THEN 8190 ELSE MV; END ELSE BEGIN MERIT := BAD; MVS := MVS +1; END; % IF THE MOVING PIECE DOES NOT CAPTURE THEN THE CONCEPT OF AN INCREMENT % MOVE CAN BE USED TO REDUCE THE NEEDLESS REFERENCING OF TAKEBACKMOVE. FROMSQ := MF; IF WTERMINAL THEN BEGIN M2 := MF; TAKEBACKMOVE; END; IF MERIT GTR BEST THEN BEST := MERIT; % NOTE HIGHEST SCORE END ELSE BEGIN MERIT := BAD; MVS := MVS +1; END; END FOR M; END OF MOBILITYSCORE; % PROCEDURE STARTTHISPROBLEM; %SETS PARAMETERS TO START A CHESS PROBLEM BEGIN INTEGER I, J, L,LL,SQ,SQ1; NEEDKING := EXAMINE := FALSE; KINGSQ [1] :=KINGSQ [- 1] := DIFFVAL := 0; FOR I :=- 8 STEP 1 UNTIL 8 DO PIECES [I] :=0; FOR I :=1 STEP 1 UNTIL 64 DO IF J := SIGN(L := NSQ[I]) NEQ 0 THEN IF ABS(L) LSS 9 THEN BEGIN DIFFVAL := DIFFVAL + J|VALUES[ABS(L)]; PIECES[L] := PIECES[L] + 1; IF ABS(L) = 8 THEN KINGSQ [J] :=I; END FOR I; IF KINGSQ[1] NEQ 0 AND KINGSQ[-1] NEQ 0 THEN BEGIN FOR I := 1 STEP 1 UNTIL 64 DO CON[-1,I] := CON[0,I] := CON[1,I] := CONTROL[I,0]:=0; FOR SQ := 1 STEP 1 UNTIL 64 DO % ASSUME NO ENPASSANT SQRS. IF LL := SIGN(NSQ[SQ]) NEQ 0 THEN BEGIN MAKE(SQ); END ELSE BEGIN POSITION[SQ,LIM]:=LIM;POSITION[SQ,0]:=POS[SQ] := 0; END; REMAKE(KINGSQ[1],KINGSQ[1]); REMAKE(KINGSQ[-1],KINGSQ[-1]); NULLMOVE := FALSE; KINGCONTROL(1); KINGCONTROL(-1); IF NOT NEWGAME THEN BEGIN ENPRISE; IF I := SQUARE[0] GTR 0 THEN FOR I := I STEP -1 UNTIL 0 DO BEGIN OLDSQUARE[I] := SQUARE[I]; OLDLOSS[I] := LOSS[I]; END ELSE OLDSQUARE[0] := 0; END; END ELSE NEEDKING := TRUE; END STARTTHISPROBLEM; %****************REINITIALIZE***************** PROCEDURE REINITIALIZE(M); VALUE M; INTEGER M; BEGIN INTEGER I, NUMS; COUNT := COUNT -M -1; READ(BOARD[COUNT], *, BOARDLIST); READ(GAME[COUNT+1]); % RESET THE POINTER WRITE(TTY, YOURMOVE, COLOR[K], MOVECOUNT); NUMS := NUM; STARTTHISPROBLEM; LISTMOVES; NUM := NUMS; END OF REINITIALIZE; % %*******************TRACE**************** PROCEDURE TRACE; %INITIATES TRACE ACCORDING TO TRACE PARAMETERS BEGIN INTEGER I, J, CHAR; FORMAT FT1("TRAC",22I3); FORMAT FMT (" *0 = "L1" *1 = "L1" *2 = "L1" *4 = "L1" *5 = "L1 " *7 = "L1" *L = "L1" *t = "L1); FOR I := 1 STEP 1 UNTIL CHARCOUNT DO BEGIN CHAR := U[I]; IF CHAR = 0 THEN REVERSE := NOT REVERSE ELSE IF CHAR = "1" THEN DUMPP := NOT DUMPP ELSE IF CHAR = "2" THEN WS := NOT WS ELSE IF CHAR = "3" THEN PRINTBOARD ELSE IF CHAR = 4 THEN IF BOTH THEN BOTH:=CBOTH:=WH:=FALSE ELSE BOTH := CBOTH := TRUE ELSE IF CHAR = 5 THEN IF CBOTH % "4" or 4, "5" or 5 THEN CBOTH := BOTH := FALSE ELSE BOTH := WH:=TRUE ELSE IF CHAR = "6" THEN GO TO STARTS ELSE IF CHAR = 7 THEN TEST := NOT TEST ELSE IF CHAR = "8" THEN BEGIN WRITE(TTY, TRACETITLE ); END ELSE IF CHAR = "9" THEN WRITE (TTY, FT1, FOR J :=- 1, 1 DO KINGSQ [J], FOR J := -8 STEP 1 UNTIL 8 DO PIECES[J],DIFFVAL,TWOVAL) ELSE IF CHAR ="W" THEN PRINTMOVES( 1) ELSE IF CHAR = "B" THEN PRINTMOVES( -1) ELSE IF CHAR = "Z" THEN PUNCHBRD ELSE IF CHAR = "P" THEN PRINTSHORTBRD ELSE IF CHAR = "R" THEN REINITIALIZE(U[I:=I+1]) ELSE IF CHAR = "D" THEN PRINTSELECTION ELSE IF CHAR = "C" THEN CLOCK(I:=I+3) ELSE IF CHAR = "O" THEN WRITE(TTY,FMT,REVERSE,DUMPP,WS,BOTH,CBOTH,TEST,LOOKAHEAD, TOURNAMENT) ELSE IF CHAR = "A" THEN WRITE(TTY,AUTHOR) ELSE IF CHAR = "I" THEN WRITE(TTY,INSTRUCTIONS) ELSE IF CHAR = "T" THEN TOURNAMENT :=NOT TOURNAMENT ELSE IF CHAR = "X" THEN DUMPER(I:=I+2) ELSE IF CHAR = "S" THEN SCORER(I:=I+3) ELSE IF CHAR = "G" THEN PRINTGAMERECORD ELSE IF CHAR = "L" THEN LOOKAHEAD :=IF LOOKAHEAD THEN TEST:=EXAMINE:=FALSE ELSE TRUE ELSE IF CHAR = "Q" THEN QUICK := LOOKAHEAD := IF QUICK THEN TEST := FALSE ELSE TRUE ELSE IF CHAR = "V" THEN DEBUG := NOT DEBUG END; END TRACE; % PROCEDURE READU; %READS TELETYPE BEGIN INTEGER N, I, LT; BOOLEAN LOOK; PROCEDURE READSU(S,F,LAST,FLAG); VALUE S,F; INTEGER S,F,LAST; BOOLEAN FLAG; BEGIN COMMENT U[S:F] IS READ FROM REMOTE TTY ONE CHAR PER WORD LAST POINTS TO LAST NON-BLANK CHAR FLAG IS FALSE IF TOO MUCH INPUT IS ENCOUNTERED; INTEGER IS,L,I; FORMAT F1("TOO MUCH INPUT"), F2(80A1); LABEL LOOP,NONBLANK; IS:=S; FLAG:=TRUE; LOOP: IF IS GEQ F THEN BEGIN WRITE(TTY,F1); FLAG:=FALSE; END ELSE BEGIN L:=IS+71; IF L GTR F THEN BEGIN L:=F; WRITE(TTY,F2,FOR I:=IS STEP 1 UNTIL L DO "-"); END; READ(REMOTE,F2,FOR I:=IS STEP 1 UNTIL L DO U[I]); FOR LAST:=L STEP -1 UNTIL 0 DO IF U[LAST] NEQ " " THEN GO TO NONBLANK; LAST := 0; NONBLANK: IF U[LAST] = "@" THEN BEGIN IS:=LAST; GO TO LOOP; END; END; END OF READSU; COMMENT BEGINNING OF READU; LABEL START; START:READSU(0,MAXCHAR,CHARCOUNT,LOOK); IF U [0] = "*" THEN BEGIN TRACE; WRITE(TTY, CONTINUED ); GO TO START; END ELSE IF U[0] = "S" THEN GO TO STOP; END READU; % PROCEDURE STARTNEWGAME; %SETS NSQ[*] TO CORRESPOND TO A NEW GAME BEGIN INTEGER I; NOQUEEN := NEWGAME := TRUE; FILL NSQ [*] WITH 0, 5, 3, 4, 7, 8, 4, 3, 5; FOR I := 17 STEP 1 UNTIL 48 DO NSQ[I] :=0; FOR I :=49 STEP 1 UNTIL 56 DO BEGIN NSQ [I] :=- 1; % I is a guess NSQ [I + 8] :=- NSQ [I - 48]; NSQ [I - 40] :=1; END; FOR I:=-2 STEP 1 UNTIL 2 DO CASTLE[I]:=TRUE; K := -1; NOQUEEN := TRUE; % DISCOURAGES EARLY QUEEN MOVES. IF NOT BOTH THEN BEGIN WRITE(TTY, COLORS, 12 ); READU; IF U[0] = "B" THEN WH := TRUE; END; END STARTNEWGAME; % PROCEDURE STARTOLDGAME; %SETS NSQ[*] TO CORRESPOND TO POSITION READ FROM TELETYPE BEGIN PROCEDURE RDBOARD; %FILLS NSQ[*] TO DESCRIBE BOARD POSITION READ IN BEGIN INTEGER ARRAY M [0 : 2], L [0 : 1]; LABEL QUIT, ALTERNATIVE, PIECE; INTEGER I, J, T, KK; FOR I :=1 STEP 1 UNTIL 64 DO NSQ [I] :=0; K := 1; I := 0; READU; J := -1; DO J := J+1 UNTIL U[J] NEQ " "; IF U[J] = "$" THEN GO TO ALTERNATIVE; DO BEGIN T := U[J]; IF T = "0" THEN GO TO QUIT; IF T = "/" OR T = "-" THEN GETMAN(U, M, J-1) ELSE IF T="," OR T="." THEN BEGIN GETSQ (U, L, J - 3); NSQ [ M[0]] :=K | M [2]; % M[0] is a guess IF T NEQ "," THEN IF K < 0 THEN GO TO QUIT ELSE K := - 1; END; J :=J + 1; END UNTIL J GTR CHARCOUNT; GO TO QUIT; ALTERNATIVE: T := U[J := J+1]; IF T GTR 0 AND T LSS 9 THEN I := I + T ELSE BEGIN FOR KK := 1,3,4,5,7,8,11 DO IF T = CHESSMAN [KK] THEN GO TO PIECE; K := -K; I := 0; IF K = -1 THEN GO TO ALTERNATIVE ELSE GO TO QUIT; PIECE: NSQ[I:= I+1] := K|KK; END; GO TO ALTERNATIVE; QUIT: IF NSQ[61] =-8 THEN BEGIN CASTLE[-1]:=IF NSQ[64] =-5 THEN TRUE ELSE FALSE; CASTLE[-2] := IF NSQ[57] = -5 THEN TRUE ELSE FALSE; END ELSE CASTLE[-1] := CASTLE[-2] := FALSE; CASTLE[2] := IF NSQ[1] = 5 AND NSQ[5] = 8 THEN TRUE ELSE FALSE; CASTLE[1] := IF NSQ[8] = 5 AND NSQ[5] = 8 THEN TRUE ELSE FALSE; END RDBOARD; % NEWGAME := FALSE; WH := TRUE; % COMPUTER PLAYS FIRST MOVE. WRITE(TTY, USETBRD ); RDBOARD; NOQUEEN := FALSE; WRITE(TTY, PLAYER ); READU; IF U[0] = "W" THEN K := -1 ELSE K := 1; END STARTOLDGAME; % %**************PRIMARYSCOPE****************** PROCEDURE PRIMARYSCOPE(BEST); INTEGER BEST; BEGIN INTEGER MV,SQF,SQT,PC,PCA,PCT,I,N; BOOLEAN PROCEDURE ENPRISQ(SQ); VALUE SQ; INTEGER SQ; BEGIN INTEGER I; ENPRISQ := FALSE; FOR I := SQUARE[0] STEP -1 UNTIL 1 DO IF SQ = SQUARE[I] THEN ENPRISQ := TRUE; END OF ENPRISE SQUARE; % FROMSQ := N := BEST := 0; N := NUMBER[K]; DO BEGIN PC := NSQ[SQF:=FROMSQ]; NSQ[SQF] := 0; DO BEGIN PCT := NSQ[SQT:=TOSQUARE]; NSQ[SQT] := IF CONSEQ LSS 13 THEN PC ELSE (CONSEQ - 10)|K; MOVESQUARE(SQT,0); % FILLS CHECKLIST DSCORE := ASCORE := 0; FOR I := CLIST STEP -1 UNTIL 1 DO IF PCA := NSQ[CHECKLIST[I]] NEQ 0 THEN ASCORE := ASCORE + VALUES[ABS(PCA)]; FOR I := LIM -1 STEP -1 UNTIL SLIST DO IF ABS(PC) GTR 1 OR (CHECKLIST[I] - SQT) MOD 8 NEQ 0 THEN DSCORE := DSCORE + VALUES[ABS(NSQ[CHECKLIST[I]])]; MERIT := IF MV :=(DATUM + 5|( (CLIST - POS[SQF])))|2 +(5|ASCORE + 2|DSCORE) LSS 1 THEN 1 ELSE MV; IF BEST LSS MV THEN BEST := MV; NSQ[SQT] := PCT; IF DUMPP THEN BEGIN SQT := 8|N; STORE[SQT+3] := MV; STORE[SQT+6] := ASCORE; STORE[SQT+7] := DSCORE; END; N := N-K; END UNTIL SQF NEQ FROMSQ; NSQ[SQF] := PC; END UNTIL N = 0; N := NUMBER[K]; DO BEGIN SQF := FROMSQ; IF CON[0,SQF]|K GTR 1 OR ENPRISQ(SQF) THEN % PROSPECT DO BEGIN MERIT := BEST; N := N-K; END UNTIL SQF NEQ FROMSQ ELSE IF CONSEQ NEQ 0 AND CONSEQ NEQ 12 THEN BEGIN MERIT := BEST; N := N-K; END ELSE N := N-K; END UNTIL N = 0; END OF PRIMARY SCOPE; %******************SELECT RIGHT MOVE************* PROCEDURE SELECTRTMV; % CHOOSE THE MOVE WITH THE HIGHEST SCOPE BEGIN INTEGER NN,J,N, I, JJ, SQ, BESTSCORE,BEST,LIMIT,SCR,NM; LABEL FOUND; FORMAT FT1("SELE",12I5); % NN := NUMBER[0] := 0; LIMIT := 180; JJ := ABS(NUMBER[K]); INCHECK := IF CHECK(KINGSQ[K],K,SCR) THEN FALSE ELSE TRUE; CHECKSQ := SQR[1]; % ONLY VALID AND ONLY USED IF INCHECK IS TR IF INCHECK OR NUM LSS 16 THEN % SCORE ALL THE MOVES FOR N:=NUMBER[K] STEP -K UNTIL K DO BESTMOVES[NN:=NN+1] := N ELSE BEGIN PRIMARYSCOPE(BEST); NUMBER[0] := BEST; DO BEGIN N :=K; NN := 0; NN := 4; LIMIT := LIMIT + 60; DO BEGIN IF SCR:=BEST - MERIT LSS LIMIT THEN BESTMOVES[NN:=NN+1] := N; IF SCR = 0 THEN NN:=NN+1; N := N +K; END UNTIL ABS(N) GTR JJ ; END UNTIL NN GTR NM OR NN GTR 20 OR LIMIT GTR 780 AND NN GTR 7; END; SPAN[0] := NN; % SCR:=2+BAD; FOR N:=NUMBER[K] STEP -K UNTIL K DO MERIT := SCR; MOBILITYSCORE(BESTSCORE); SPAN[0] := SPAN[0] - (IF INCHECK THEN MVS ELSE 0); NUM := NUM - MVS; IF DEBUG THEN WRITE(TTY,FT1,NN,LIMIT,NUM,MVS,JJ,NN,BEST,BESTSCORE); SPAN[K] := NN - MVS; IF BESTSCORE LSS BAD + 2 THEN KTEST := 1; % PUT THE 7 BEST MOVES INTO ARRAY TRY. J := NN; NN := 0; FOR J := J STEP -1 UNTIL 1 DO BEGIN N := BESTMOVES[J]; IF SCR := MERIT NEQ BAD THEN BEGIN FOR I := 1 STEP 1 UNTIL NN DO IF SCR GTR QQBEST THEN BEGIN FOR JJ := NN STEP -1 UNTIL I DO TRY[JJ+1] := TRY[JJ]; GO TO FOUND; END; I := NN+1; FOUND: IF NN LSS 7 THEN NN := NN+1; TRY[I] := N; END; END; % THE BEST MOVES ARE NOW ORDERED. J := 0; FOR I := 1 STEP 1 UNTIL NN DO IF BESTSCORE - QQBEST LSS 60 THEN J := J+1; TRY[0] := J; TRY[8] := NN; % USED BY SEARCH AND TREE IF NEWGAME AND MOVECOUNT LSS 3 THEN J := NN; % SEMI-RANDOM OPENING I := IF J GTR 1 THEN (TIME(1) MOD J) + 1 ELSE 1; RTMV := TRY[I]; % THE "RIGHT" MOVE HAS NOT BEEN FOUND. (NON-LOOKAHEAD CASE) END OF SELECTRTMV; %**************LIST LEGAL MOVES************** PROCEDURE LISTLEGALMOVES; % ONLY LEGAL MOVES ARE LISTED BEGIN INTEGER I,J,M,N; % M is a guess FORMAT FT1("LLMV",24I5); K := -K; % SWITCHSIDES. ENPRISE; M := SQUARE[0]; % ENPRISE MAKES A LIST OF PIECES THAT % ARE ATTACKED AND PROVIDES SOME INCENTIVE TO MOVE THEM. IF NOQUEEN THEN IF NSQ[QSQ:=32-28|K] = 7|K % IS IT ENPRISE. THEN FOR J := 1 STEP 1 UNTIL M DO IF SQUARE[J] = QSQ THEN NOQUEEN := FALSE; % DO NOT PENALIZE Q MOVE LISTMOVES; % GENERATES ALL POTENTIAL MOVES. REALVAL :=(ONEVAL:=DIFFVAL|K) + TWOVAL; % INC. ENPRISE PIECE IF NOT LOOKAHEAD AND TEST AND DUMPP THEN WRITE(TTY, FT1, M, FOR J:=1 STEP 1 UNTIL M DO [SQUARE[J],LOSS[J]], DIFFVAL,ONEVAL,TWOVAL); IF SCORES THEN SELECTRTMV; IF NUM = 0 THEN KTEST := IF CHECK(KINGSQ[K],K,I) THEN 2 ELSE 4; END LISTLEGALMOVES; % %*********************SEARCH*********************** PROCEDURE SEARCH; % DETERMINES RTMV THROUGH LOOKAHEAD BEGIN INTEGER L,BEST,II, LL, N, KK, I, SCR,TNUMB,NEWLEVEL,NEWNODES; INTEGER BRANCHES, NODE,NEW,NUMBE,LIMBS,FINAL; BOOLEAN SHAH; INTEGER ARRAY OLDSC[0:MAXLEV], MAXSC[0:8]; FORMAT FT1("SEAR"3(13I5/)); FORMAT FORM(I3" MOVES SCORED OUT OF "I3"." I3" NEW POSITIONS OUT OF "I2", DEPTH OF "I1); % BOOLEAN PROCEDURE DUPLICATE(NODE); VALUE NODE; INTEGER NODE; BEGIN INTEGER ARRAY NNSQ[-21:64]; INTEGER I; LABEL QUIT; DUPLICATE := FALSE; READ(STATES[NODE,*], 86, NNSQ[*]); FOR I := 1 STEP 1 UNTIL 64 DO IF NSQ[I] NEQ NNSQ[I] THEN GO TO QUIT; DUPLICATE := TRUE; % IF FALSE THEN QUIT: % IF TEST THEN WRITE(TTY,FT1,NODE,I,NSQ[I],NNSQ[I]); END OF DUPLICATE POSITION CHECKER; % PROCEDURE TREE; % GENERATES THE SEARCH TREE. BEGIN INTEGER I,MAX,ROOT,IDONE,LIMIT, PASTSCR, LASTSCR,TNUMB; LABEL QUIT, EXIT, FOUNDUPLICATE; BOOLEAN INCREASE; % ORIGINALLY MINIMIZED SCQRE, NOW MAXIMIZE. ROOT := ROOTNODE[LEVEL:=LEVEL+1] := NODE; KK := -KK; IDONE := NODETO[ROOT,0]; OLDSC[LEVEL] := 9999|KK; LASTSCR := OLDSCR; PASTSCR := PREVSCR; MAX := 8888|KK; IF IDONE = -1 THEN BEGIN LL := LL+1; LISTLEGALMOVES; NEW:=NEW+1; BRANCHES:=BRANCHES + NUM; LIMBS := LIMBS - SPAN[0]; IF NUM = 0 THEN BEGIN % RATE MATE OR STALEMATE CONDITION IF KTEST = 2 THEN MAX := VALUES[10]|2 ELSE PRUNE := TRUE; IF TEST THEN WRITE(TTY,TERM[KTEST]); GO TO QUIT; END; NODETO[ROOT,0] := IDONE := 0; IF TRY[0] = 1 THEN IF TRY[8] GTR 1 THEN TRY[0] := 2; WRITE(STATES[ROOT,*],*, NODELIST); WRITE(MOVES[ROOT,*],*,MOVELIST); END ELSE BEGIN READ(STATES[ROOT,*],*,NODELIST); READ(MOVES[ROOT,*],* , MOVELIST); END; LIMIT := IF LEVEL GTR 3 THEN 1 ELSE IF LEVEL GTR 2 THEN IF TRY[0] GTR 1 AND NUM GTR 10 THEN 2 ELSE TRY[0] ELSE IF LEVEL GTR 1 THEN IF TRY[0] GTR 2 AND NUM GTR 20 THEN 3 ELSE TRY[0] ELSE TRY[0]; IF LEVEL = 1 THEN BEGIN NUMBE := ABS(NUMBER[K]); N := RTMV; IF NUMBE LSS 16 AND ABS(CONSEQ) LSS 20 AND TOURNAMENT THEN BEGIN NEWLEVEL := 7; NEWNODES := 13; END ELSE IF NUMBE LSS 31 OR TOURNAMENT THEN BEGIN NEWLEVEL := 5; NEWNODES := 9; END ELSE BEGIN NEWLEVEL := 3; NEWNODES := 5; END; IF QUICK THEN NEWLEVEL := 2; % 2 PLY TREE FOR QUICK LOOKAHEA IF TOURNAMENT THEN BEGIN I := COMPUTERTIME DIV (MOVECOUNT|MOVETIME); NEWLEVEL := NEWLEVEL -I; NEWNODES := NEWNODES -2|I; EXAMINE := IF I = 0 THEN TRUE ELSE FALSE; END; IF MAXLEVEL LSS NEWLEVEL THEN MAXLEVEL:=NEWLEVEL; IF MAXNODES LSS NEWNODES THEN MAXNODES := NEWNODES; END; FOR I := 1 STEP 1 UNTIL LIMIT DO BEGIN N := TRY[I]; FINAL := 0; SCR := MERIT; SHAH := IF ABS(CONSEQ) LSS 20 THEN FALSE ELSE TRUE; IF TEST THEN DESCRIBEMOVE(N,MC); IF LEVEL = MAXLEVEL THEN IF SHAH THEN IF MAXLEVEL LSS MAXLEV-1 THEN BEGIN INCREASE := TRUE; MAXLEVEL := MAXLEVEL+2; END; IF LEVEL = 1 THEN BEGIN MAXSC[PATH:=I] := SCR; LL:=0; END ELSE IF KK = -1 AND I GTR IDONE THEN IF ABS(SCR-PASTSCR) GTR (IF TOURNAMENT THEN 360 ELSE 240) THEN IF SCR GTR PASTSCR THEN IF NOT SHAH THEN BEGIN FINAL := -2; GO TO EXIT; END % GREAT REPLY, FORWARD PRUNE. ELSE ELSE BEGIN IF I = 1 THEN PRUNE := TRUE; FINAL := -1; GO TO EXIT; END % SEVER REVERSAL IN SCORE. ELSE IF PATH GTR 1 THEN IF SCR - BEST LSS-240 AND IDONE LSS I THEN GO TO EXIT; % PRUNE, POOR PROSPECT FOR IMPROVEM IF LEVEL LSS MAXLEVEL AND L LSS MAXL AND LL LSS MAXNODES AND NUM NEQ -KK OR IDONE GEQ I THEN BEGIN PREVSCR := OLDSCR; OLDSCR := SCR; MAKEMOVE(N,TRUE); % NORMALLY KTEST = 0 IF I GTR IDONE THEN BEGIN IF LEVEL GTR 2 THEN % CHECK FOR DUPLICATE POSITION FOR NODE := 1 STEP 1 UNTIL MAXTREE DO IF SCR = DUPSCR THEN IF ROOT NEQ PARENT THEN IF DUPLICATE(NODE) THEN GO TO FOUNDUPLICATE; NODETO[ROOT,0] := I; NODE := NODETO[ROOT,I] := GETNODEL; DUPSCR := SCR; PARENT := ROOT; FOUNDUPLICATE: END ELSE NODE := NODETO[ROOT,I]; IF TEST THEN BEGIN %% WRITE(TTY[STOP],BRAN[LEVEL],SCR,PASTSCR,NUM|K,SPAN[0],NODE); WRITE(TTY,BRAN[LEVEL],SCR,PASTSCR,NUM|K,SPAN[0],NODE); WRITE(TTY,BRANCH,FOR II:=0 STEP 1 UNTIL 10 DO MC[II]); END; WRITE(BACK[LEVEL,*],*,BACKLIST); TNUMB := NUMB; TREE; NUMB := TNUMB; READ(BACK[LEVEL,*],*,BACKLIST); UPDATE; IF INCREASE THEN BEGIN INCREASE:=FALSE; MAXLEVEL :=MAXLEVEL-2; END; IF KK|(MAX -OLDSC[LEVEL]) GTR 0 THEN MAX := OLDSC[LEVEL]; IF PRUNE THEN BEGIN PRUNE :=FALSE; GO TO QUIT; END; % ANTICIPATING REVERSE PRUNING IF ABS(OLDSC[LEVEL-1]) NEQ 9999 THEN IF (OLDSC[LEVEL-1] - MAX)|KK GTR 0 THEN GO TO QUIT; % REVERSE PRINE, ALREADY FOUND BETTER LINE IF MAX LEQ BEST THEN IF KK = 1 THEN GO TO QUIT; END ELSE BEGIN FINAL := MAXTREE+1; EXIT: MAX := IF LEVEL = MAXLEVEL OR I = 1 THEN % level is guess IF KK = -1 THEN SCR ELSE % LASTSCR-(SCR-PASTSCR) DIV 2 ((DATUM|2) DIV (SCR-REWARD+DATUM)) -REWARD+DATUM ELSE OLDSC[LEVEL]; IF TEST THEN BEGIN %% WRITE(TTY[STOP],BRAN[LEVEL],MAX,PASTSCR,NUM|K,SPAN[0],FINAL); WRITE(TTY,BRAN[LEVEL],MAX,PASTSCR,NUM|K,SPAN[0],FINAL); WRITE(TTY,BRANCH,FOR II:=0 STEP 1 UNTIL 10 DO MC[II]); END; GO TO QUIT; END; N := TRY[I+1]; IF LEVEL = 1 THEN IF PATH = LIMIT THEN IF MAXL - L GTR MAXNODES DIV 2 THEN % SUFFICIENT NODES REMAIN IF BEST LSS MERIT + (IF TOURNAMENT THEN 360 ELSE 240) THEN IF TRY[8] GTR LIMIT THEN LIMIT := LIMIT +1; END; QUIT: KK := -KK; ROOT := ROOTNODE[LEVEL:=LEVEL-1]; IF LEVEL GTR 0 THEN BEGIN READ(STATES[ROOT,*], *, NODELIST); READ(MOVES[ROOT,*],*,MOVELIST); IF (OLDSC[LEVEL] -MAX)|KK GTR 0 THEN OLDSC[LEVEL] := MAX; IF LEVEL = 1 THEN IF MAXSC[PATH] := MAX GTR BEST THEN BEST := MAX; END ELSE BEST := MAX; END OF TREE; % PROCEDURE COLLECT(NODE,ROOT); INTEGER NODE,ROOT; % COLLECTS NODES FROM DISCARDED TREE. BEGIN INTEGER I; IF NODE LSS MAXTREE AND ROOT = PARENT THEN BEGIN GETNODEL := NODE; DUPSCR := 0; FOR I := NODETO[NODE,0] STEP -1 UNTIL 1 DO COLLECT(NODETO[NODE,I],NODE); END; END OF COLLECT; % PROCEDURE MARKTREE(NODE,ROOT); INTEGER NODE,ROOT; BEGIN INTEGER I; PARENT := ROOT; FOR I := NODETO[NODE,0] STEP -1 UNTIL 1 DO MARKTREE(NODETO[NODE,I],NODE); END OF ISOLATION OF NEXT TREE; % PROCEDURE DEADTREE; BEGIN L := -1; IF SAVEL GTR -1 THEN BEGIN FOR I := SAVEL STEP 1 UNTIL MAXL-1 DO GETNODEL := GETNODE[I]; GETNODEL := NODE := ORIGIN; DUPSCR := 0; IF REPLY NEQ 0 THEN MARKTREE(NODETO[ORIGIN,REPLY],ORIGIN); FOR I := NODETO[ORIGIN,0] STEP -1 UNTIL 1 DO IF I NEQ REPLY THEN COLLECT(NODETO[ORIGIN,I],ORIGIN); IF REPLY GTR 0 THEN ORIGIN := NODETO[ORIGIN,REPLY] ELSE BEGIN ORIGIN := GETNODEZ; % UNEXPECTED MOVE MAXLEVEL := MAXNODES := 2; END; MAXL := L+1; END ELSE ORIGIN := GETNODEZ; GETNODEX := MAXTREE; L := -1; DO BEGIN NODE := GETNODEL; NODETO[NODE,0] := -1; END UNTIL L = MAXL; END OF DEAD TREE COLLECTION; % IF NOT CBOTH AND WH THEN DEADTREE; % COLLECT OPPONENT TREE KK := 1; BRANCHES := NEW := LIMBS:=0; SCORES := TRUE; LEVEL := LL := 0; OLDSC[0] := +KK|9999; PRUNE := FALSE; NODE := ORIGIN; L := IF ORIGIN = GETNODEZ THEN 0 ELSE -1; BEST := BAD; IF WH OR EXAMINE THEN TREE ELSE K := -K; SAVEL := L+1; REPLY := 0; FOR I := NODETO[ORIGIN,0] STEP -1 UNTIL 1 DO IF BEST = MAXSC[I] THEN REPLY := I; COMMENT IF TEST THEN WRITE(TTY,FT1,LEVEL,MAXLEVEL,SAVEL,MAXL,LL,MAXNODES, BRANCHES,BEST, SCR, OLDSCR, PREVSCR,FOR I:=NODETO[ORIGIN,0] STEP 01 UNTIL 1 DO MAXSC[I]); IF WH OR EXAMINE THEN WRITE(TTY,FORM,LIMBS,BRANCHES,NEW,MAXTREE-MAXL+SAVEL-1,MAXLEVEL); N := RTMV := TRY[REPLY]; IF WH THEN DEADTREE; PREVSCR := OLDSCR; OLDSCR := MERIT; END OF SEARCH; % PROCEDURE ANALYSE; % ANALYSES THE EFFECT OF LIKELY MOVES BY THE USER BEGIN IF REVERSE THEN K := -K ELSE LISTLEGALMOVES; COMMENT IT IS INTENDED THAT PROCEDURE ANALYSE SHOULD BE USED TO PREDICT THE USER-S MOVE. IF A WRONG PREDICTION I MADE THEN THE USER-S MOVE SHOULD BE EXAMINED FURTHER TO SEE IF IT IS "GOOD" OR "BAD". IF IT IS "BETTER" THAN THE MOVE SELECTED BY THE COMPUTER, THEN THE COMPUTER-S MOVE SELECTION PARAMETERS SHOULD BE ADJUSTED. WHEN IMPLEMENTED, THE PROCEDURE WILL BE AN EXAMPLE OF "DEDUCTIVE INFERENCE" OR "LEARNING WITHOUT A TEACHER". ; %END OF COMMENT END OF ANALYSE; % %**************OPPONENT***************** PROCEDURE OPPONENT; %MAKES MOVES READ FROM TELETYPE BEGIN LABEL AA; INTEGER I,NUMS,N; FORMAT FT1 ("MVBL",24I5); SWITCH FORMAT FT8 := (I4,X1,60A1),(X6,I3,X1,60A1); % X1 is guess IF LEGAL THEN BEGIN SCORES := WS; %% WRITE(TTY[STOP], YOURMOVE, COLOR[-K], MOVECOUNT); WRITE(TTY, YOURMOVE, COLOR[-K], MOVECOUNT); IF NOT REVERSE AND (SCORES OR NOT BOTH) THEN WRITE(TTY,TIMING,SPAN[0],NUM,CPUTIME,IOTIME,ELAPSEDTIME); IF NOT REVERSE AND EXAMINE AND NOT BOTH THEN BEGIN SEARCH; NUMS := NUM; LISTMOVES; NUM := NUMS; END ELSE ANALYSE; END ELSE LEGAL := TRUE; IF NUM NEQ 0 OR REVERSE THEN BEGIN AA: READU; GETMOVE(U); IF REVERSE OR NUM = 0 THEN RETRACT(RTMV) % NUM = 0 TRANSIT ELSE IF NOT NULLMOVE THEN FINDRTMV; N := RTMV; REPLY := 0; IF LOOKAHEAD THEN FOR I:=TRY[0] STEP -1 UNTIL 1 DO IF RTMV = TRY[I] THEN REPLY := I; IF NULLMOVE OR SCORES AND MERIT = BAD THEN BEGIN WRITE(TTY, TRYORTRACE); KTEST := 0; GO TO AA; END RTMV EQUAL ZERO; WRITE(GAME,FT8[(1-K) DIV 2],MOVECOUNT, FOR I:=0 STEP 1 UNTIL CHARCOUNT DO U[I]); END ELSE KTEST := 2; % NEVER HAPPENS. END MOVEBLACK; % PROCEDURE COMPUTER; %MAKES MOVE FOR WHITE WHICH HAS LARGEST SCORE BEGIN INTEGER I; DEFINE FORI = FOR I:=0 STEP 1 UNTIL 10 #; FORMAT FT7(X1,2A1,A3,3A1,A3,X1,2A1,X1,2A5); LIST MOVE (MOVECOUNT, FOR I:=0 STEP 1 UNTIL 10 DO MC[I]); SCORES := TRUE; IF NOT LOOKAHEAD OR NEWGAME AND MOVECOUNT LSS 3 THEN LISTLEGALMOVES ELSE SEARCH; IF NUM NEQ 0 AND KTEST = 0 THEN BEGIN DESCRIBEMOVE(RTMV, MC); IF BOTH AND NOT DUMPP AND NOT TEST THEN IF K = 1 THEN %% WRITE(TTY[STOP],FT9[0],MOVECOUNT,FORI DO MC[I],MOVECOUNT) WRITE(TTY,FT9[0],MOVECOUNT,FORI DO MC[I],MOVECOUNT) ELSE WRITE(TTY,FT7,FORI DO MC[I]) % ELIMINATES PARTIAL WDS. ELSE WRITE(TTY, FT9[(1-K) DIV 2], MOVE); WRITE(GAME,FT9[(1-K) DIV 2],MOVE); END; END MOVEWHITE; % PROCEDURE SETUP; BEGIN INTEGER L; LABEL AGAIN; WRITE(TTY,PLAYBOTH); READU; % ALSO ERROR RESTART WH := FALSE; KTEST := ONEVAL := TWOVAL := NUM:=0; USERPROCESS := TIME(2); NUMB := -1; CBOTH := FALSE; USERTIME := COMPUTERTIME := 0; MOVECOUNT := 1; REMEMBER := WTERMINAL := TRUE; DATUM := VALUES[10]; MOVETIME := 180; % SETS THE MOVERATE TO 20 MOVES/HOUR IF U [0] = "Y" THEN BEGIN WRITE(TTY, WANTCOMPUTER ); READU; IF U [0] = "Y" THEN CBOTH := WH := TRUE; BOTH := TRUE; END ELSE BOTH := FALSE; WRITE(TTY, NEWGM ); MAXL := MAXTREE-1; ORIGIN := MAXNODES := MAXLEVEL := 1; FOR L:=0STEP 1 UNTIL MAXTREE DO BEGIN GETNODE[L]:=L+1; NODETO[L,0] := -1; END; PREVSCR := OLDSCR := 9999; SAVEL := -1; % OVERWRITTEN BY GETPOSITION READU; IF U [0] = "N" THEN AGAIN: STARTOLDGAME ELSE STARTNEWGAME; STARTTHISPROBLEM; IF NEEDKING THEN BEGIN WRITE(TTY, MOREKINGS ); GO TO AGAIN; END; REWIND(BOARD); REWIND(GAME); COUNT := 0; WRITE(GAME,LINES,IF K = 1 THEN "B" ELSE "W"); % SEE PRINTGAMERECORD SENDTIME := TIME(1); END OF SETUP; % PROCEDURE FINALIZE; BEGIN MAKEMOVE(RTMV,TRUE); IF NOT CHECK(KINGSQ[K],K,I) THEN BEGIN WRITE(TTY,ILLEGAL); LEGAL := FALSE; REINITIALIZE(0); END ELSE BEGIN IF NOQUEEN THEN IF MOVECOUNT GTR 5 THEN NOQUEEN := FALSE; ELAPSEDTIME := (TIME(1) - SENDTIME)/60; IF NOT WH THEN USERTIME := USERTIME + ELAPSEDTIME ELSE COMPUTERTIME := COMPUTERTIME + ELAPSEDTIME; WH := IF CBOTH THEN TRUE ELSE IF BOTH THEN FALSE ELSE NOT WH; CPUTIME := (TIME(2) - OLDCPU)/60; IOTIME := (TIME(3) - OLDIO)/60; END; END OF FINALIZE; % PROCEDURE HUB; % CENTRAL HUB OF CHESS PROGRAM. BEGIN LABEL QUIT,AGAIN,REPEAT; FORMAT TIMES("WITA ="R6.2" USER="R6.2" CPU ="I4 " IO ="I3" REAL ="R6.2); AGAIN: SETUP; WH := IF NOT BOTH AND WH OR CBOTH THEN TRUE ELSE FALSE; REPEAT: IF LOOKAHEAD OR K = -1 AND (MOVECOUNT-1) MOD 5 = 0 THEN BEGIN WRITE(TTY, TIMES,COMPUTERTIME/60,USERTIME/60, (TIME(2)-CPU)/60, (TIME(3)-10)/60, (TIME(1)-REALTIME)/3600); CPU := TIME(2); IO := TIME(3); REALTIME := TIME(1); IF CBOTH AND K = -1 AND MOVECOUNT GTR 1 THEN BEGIN PUNCHBRD; WRITE(TTY, COMMAND); K := -K; READU; K:= -K; IF U[0] NEQ "Y" THEN BOTH := WH := CBOTH := FALSE; END; END; OLDCPU := TIME(2); OLDIO := TIME(3); SENDTIME := TIME(1); IF WH THEN COMPUTER ELSE OPPONENT; IF KTEST NEQ 9 THEN GO TO QUIT; WRITE(BOARD, *, BOARDLIST)[QUIT]; FINALIZE; GO TO REPEAT; QUIT: WRITE(TTY, TERM[KTEST] ); PRINTBOARD; GO TO AGAIN; END USEREMOTE; % PROCEDURE INITIALIZE; BEGIN ZEROTIME := TIME (1); COLOR[-1] := "BLACK"; COLOR[1] := "WHITE"; BLANK :=" "; COMMENT THE VALUES OF THE PIECES ARE GIVEN BELOW; FILL VALUES[*] WITH 0, 6, 0, 18, 20, 30, 57, 57, 90, 5, 2000, 10,20; FILL DIGIT [*] WITH "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"; I:=-8; FOR MAN[I] := " K."," 0.",0," R."," B."," N.",0," P.",0, " P#",0," N#"," R#"," R#",0," Q#"," K#" DO I := I+1; FILL S[*] WITH 0,17,10,-6,-15,-17,-10,6,15; FILL CHESSMAN [*] WITH " ", "P", "+", "N", "B", "R", "+", "Q", "K", 0,0,"*"; FILL CHESSPIECE[*] WITH 0,"R","N","B","Q","K","B","N","R"; KINGVAL := VALUES[8]; DEBUG:=TEST := TOURNAMENT := WS := LOOKAHEAD := FALSE; LEGAL := TRUE; WRITE(TTY,TITLE); END OF INITIALIZE; %***************WRAP UP************** PROCEDURE WRAPUP; BEGIN WRITE(TTY, TIMEFORM, TIMELIST ); SKIP (6); WRITE(TTY,MAIL); PRINTGAMERECORD; END OF WRAPUP; INITIALIZE; IF FALSE THEN STARTS: PRINTGAMERECORD; WRITE(TTY,TRACER); SKIP(2); COUNT := 0; REALTIME := STARTIME := TIME(1); HUB; STOP: SKIP(2); WRAPUP; END. % % NUMBER OF ERRORS DETECTED = 0. COMPILATION TIME = 2403 SECONDS. % PRT SIZE = 355; TOTAL SEGMENT SIZE = 6601 WORDS; DISK SIZE = 360 SEGS %; NO. PGM. SEGS = 117 % ESTIMATED CORE STORAGE REQUIREMENT = 9515 WORDS. % handwritten comment for line 0039000 ! should be 97 secs cpu ! % must be elapsed time ?END