;*********************************************************** ; ; SARGON ; ; Sargon is a computer chess playing program designed ; and coded by Dan and Kathe Spracklen. Copyright 1978. All ; rights reserved. No part of this publication may be ; reproduced without the prior written permission. ; ;*********************************************************** ; SYSTEM EQUATES ;*********************************************************** INCHAR: EQU 1 PRINTBUF:EQU 9 INBUF: EQU 10 SYSTEM: EQU 5 ;*********************************************************** ; EQUATES ;*********************************************************** ; PAWN: EQU 1 KNIGHT: EQU 2 BISHOP: EQU 3 ROOK: EQU 4 QUEEN: EQU 5 KING: EQU 6 WHITE: EQU 0 BLACK: EQU 80H BPAWN: EQU BLACK+PAWN ORG 100H PUT 100H ;*********************************************************** ; MAIN PROGRAM DRIVER ;*********************************************************** ; FUNCTION: -- To coordinate the game moves. ; ; CALLED BY: -- None ; ; CALLS: -- INITBD ; CPTRMV ; PLYRMV ; ; ARGUMENTS: None ;********************************************************** DRIVER: MOV SP,STACK ; Set stack pointer MOV DX,CLRMSG ; Request color choice MOV CL,PRINTBUF CALL SYSTEM MOV CL,INCHAR ; Accept response CALL SYSTEM CMP AL,57H ; Did player request white ? JZ DR05 ; Yes - branch CMP AL,42H ; Did player request black ? JNZ DRIVER ; No - error XOR AL,AL JP DR10 ; Jump DR05: MOV AL,BLACK ; Set computers color to black DR10: MOV [KOLOR],AL DR15: MOV DX,PLYDEP ; Request depth of search MOV CL,PRINTBUF CALL SYSTEM MOV CL,INCHAR CALL SYSTEM SUB AL,31H ; Subtract Ascii constant JB DR15 ; Under minimum - prompt again CMP AL,6 ; Over maximum of 6 ? JNB DR15 ; Yes - prompt again INC AL ; Increment by one MOV [PLYMAX],AL ; Set desired depth MOV DX,CRLF ; Output CRLF MOV CL,PRINTBUF CALL SYSTEM XOR AL,AL MOV [COLOR],AL ; Set color to white INC AL MOV [MOVENO],AL ; Set move number to 1 CALL INITBD ; Init board MOV AL,[KOLOR] ; Get color OR AL,AL ; Computer move ? JZ DR25 ; Yes - jump DR20: CALL PLYRMV ; Do player move DR25: CALL CPTRMV ; Do computer move MOV BX,MOVENO INC B,[BX] ; Increment move number JP DR20 ; Back to player move ;*********************************************************** ; TABLES SECTION ;*********************************************************** ORG 200H ; Start at 200H START: ORG START+80H PUT START+80H TBASE: EQU START+100H ;*********************************************************** ; DIRECT -- Direction Table. Used to determine the dir- ; ection of movement of each piece. ;*********************************************************** DIRECT: EQU $-TBASE DB +09,+11,-11,-09 DB +10,-10,+01,-01 DB -21,-12,+08,+19 DB +21,+12,-08,-19 DB +10,+10,+11,+09 DB -10,-10,-11,-09 ;*********************************************************** ; DPOINT -- Direction Table Pointer. Used to determine ; where to begin in the direction table for any ; given piece. ;*********************************************************** DPOINT: EQU $-TBASE DB 20,16,8,0,4,0,0 ;*********************************************************** ; DCOUNT -- Direction Table Counter. Used to determine ; the number of directions of movement for any ; given piece. ;*********************************************************** DCOUNT: EQU $-TBASE DB 4,4,8,4,4,8,8 ;*********************************************************** ; PVALUE -- Point Value. Gives the point value of each ; piece, or the worth of each piece. ;*********************************************************** PVALUE: EQU $-TBASE-1 DB 1,3,3,5,9,10 ;*********************************************************** ; PIECES -- The initial arrangement of the first rank of ; pieces on the board. Use to set up the board ; for the start of the game. ;*********************************************************** PIECES: EQU $-TBASE DB 4,2,3,5,6,3,2,4 ;*********************************************************** ; BOARD -- Board Array. Used to hold the current position ; of the board during play. The board itself ; looks like: ; FFFFFFFFFFFFFFFFFFFF ; FFFFFFFFFFFFFFFFFFFF ; FF0402030506030204FF ; FF0101010101010101FF ; FF0000000000000000FF ; FF0000000000000000FF ; FF0000000000000060FF ; FF0000000000000000FF ; FF8181818181818181FF ; FF8482838586838284FF ; FFFFFFFFFFFFFFFFFFFF ; FFFFFFFFFFFFFFFFFFFF ; The values of FF form the border of the ; board, and are used to indicate when a piece ; moves off the board. The individual bits of ; the other bytes in the board array are as ; follows: ; Bit 7 -- Color of the piece ; 1 -- Black ; 0 -- White ; Bit 6 -- Not used ; Bit 5 -- Pawn attack flag for ATTACK ; Bit 4 -- Castle flag for Kings only ; Bit 3 -- Piece has moved flag ; Bits 2-0 Piece type ; 1 -- Pawn ; 2 -- Knight ; 3 -- Bishop ; 4 -- Rook ; 5 -- Queen ; 6 -- King ; 7 -- Not used ; 0 -- Empty Square ;************************************************************ BOARD: EQU $-TBASE BOARDA: DS 120 ;************************************************************ ; ATKLIST -- Attack List. A two part array, the first ; half for white and the second half for black. ; It is used to hold the attackers of any given ; square in the order of their value. ; ; WACT -- White Attack Count. This is the first ; byte of the array and tells how many pieces are ; in the white portion of the attack list. ; ; BACT -- Black Attack Count. This is the eighth byte of ; the array and does the same for black. ;*********************************************************** ATKLST: DW 0,0,0,0,0,0,0 WACT: EQU ATKLST BACT: EQU ATKLST+7 ;*********************************************************** ; PLIST -- Pinned Piece Array. This is a two part array. ; PLISTA contains the pinned piece position. ; PLISTD contains the direction from the pinned ; piece to the attacker. ;*********************************************************** PLIST: EQU $-TBASE-1 PLISTD: EQU PLIST+10 PLISTA: DW 0,0,0,0,0,0,0,0,0,0 ;*********************************************************** ; POSK -- Position of Kings. A two byte area, the first ; byte of which hold the position of the white ; king and the second holding the position of ; the black king. ; ; POSQ -- Position of Queens. Like POSK,but for queens. ;************************************************************ POSK: DB 24,95 POSQ: DB 14,94 DB -1 ;************************************************************ ; SCORE -- Score Array. Used during Alpha-Beta pruning to ; hold the scores at each ply. It includes two ; "dummy" entries for ply -1 and ply 0. ;************************************************************ SCORE: DW 0,0,0,0,0,0 ;************************************************************ ; PLYIX -- Ply Table. Contains pairs of pointers, a pair ; for each ply. The first pointer points to the ; top of the list of possible moves at that ply. ; The second pointer points to which move in the ; list is the one currently being considered. ;************************************************************ PLYIX: DW 0,0,0,0,0,0,0,0,0,0 DW 0,0,0,0,0,0,0,0,0,0 ;************************************************************ ; STACK -- Contains the stack for the program. ;************************************************************ ORG START+2FFH STACK: ;************************************************************ ; TABLE INDICES SECTION ; ; M1-M4 -- Working indices used to index into ; the board array. ; ; T1-T3 -- Working indices used to index into Direction ; Count, Direction Value, and Piece Value tables. ; ; INDX1 -- General working indices. Used for various ; INDX2 purposes. ; ; NPINS -- Number of Pins. Count and pointer into the ; pinned piece list. ; ; MLPTRI -- Pointer into the ply table which tells ; which pair of pointers are in current use. ; ; MLPTRJ -- Pointer into the move list to the move that is ; currently being processed. ; ; SCRIX -- Score Index. Pointer to the score table for ; the ply being examined. ; ; BESTM -- Pointer into the move list for the move that ; is currently considered the best by the ; Alpha-Beta pruning process. ; ; MLLST -- Pointer to the previous move placed in the move ; list. Used during generation of the move list. ; ; MLNXT -- Pointer to the next available space in the move ; list. ; ;************************************************************ ORG START+0 PUT START+0 M1: DW TBASE M2: DW TBASE M3: DW TBASE M4: DW TBASE T1: DW TBASE T2: DW TBASE T3: DW TBASE INDX1: DW TBASE INDX2: DW TBASE NPINS: DW TBASE MLPTRI: DW PLYIX MLPTRJ: DW 0 SCRIX: DW 0 BESTM: DW 0 MLLST: DW 0 MLNXT: DW MLIST ;************************************************************ ; VARIABLES SECTION ; ; KOLOR -- Indicates computer's color. White is 0, and ; Black is 80H. ; ; COLOR -- Indicates color of the side with the move. ; ; P1-P3 -- Working area to hold the contents of the board ; array for a given square. ; ; PMATE -- The move number at which a checkmate is ; discovered during look ahead. ; ; MOVENO -- Current move number. ; ; PLYMAX -- Maximum depth of search using Alpha-Beta ; pruning. ; ; NPLY -- Current ply number during Alpha-Beta ; pruning. ; ; CKFLG -- A non-zero value indicates the king is in check. ; ; MATEF -- A zero value indicates no legal moves. ; ; VALM -- The score of the current move being examined. ; ; BRDC -- A measure of mobility equal to the total number ; of squares white can move to minus the number ; black can move to. ; ; PTSL -- The maximum number of points which could be lost ; through an exchange by the player not on the ; move. ; ; PTSW1 -- The maximum number of points which could be won ; through an exchange by the player not on the ; move. ; ; PTSW2 -- The second highest number of points which could ; be won through a different exchange by the player ; not on the move. ; ; MTRL -- A measure of the difference in material ; currently on the board. It is the total value of ; the white pieces minus the total value of the ; black pieces. ; ; BC0 -- The value of board control(BRDC) at ply 0. ; ; MV0 -- The value of material(MTRL) at ply 0. ; ; PTSCK -- A non-zero value indicates that the piece has ; just moved itself into a losing exchange of ; material. ; ; BMOVES -- Our very tiny book of openings. Determines ; the first move for the computer. ; ;************************************************************ KOLOR: DB 0 COLOR: DB 0 P1: DB 0 P2: DB 0 P3: DB 0 PMATE: DB 0 MOVENO: DB 0 PLYMAX: DB 2 NPLY: DB 0 CKFLG: DB 0 MATEF: DB 0 VALM: DB 0 BRDC: DB 0 PTSL: DB 0 PTSW1: DB 0 PTSW2: DB 0 MTRL: DB 0 BC0: DB 0 MV0: DB 0 PTSCK: DB 0 BMOVES: DB 35,55,10H DB 34,54,10H DB 85,65,10H DB 84,64,10H ;************************************************************ ; MOVE LIST SECTION ; ; MLIST -- A 2048 byte storage area for generated moves. ; This area must be large enough to hold all ; the moves for a single leg of the move tree. ; ; MLEND -- The address of the last available location ; in the move list. ; ; MLPTR -- The Move List is a linked list of individual ; moves each of which is 6 bytes in length. The ; move list pointer(MLPTR) is the link field ; within a move. ; ; MLFRP -- The field in the move entry which gives the ; board position from which the piece is moving. ; ; MLTOP -- The field in the move entry which gives the ; board position to which the piece is moving. ; ; MLFLG -- A field in the move entry which contains flag ; information. The meaning of each bit is as ; follows: ; Bit 7 -- The color of any captured piece ; 0 -- White ; 1 -- Black ; Bit 6 -- Double move flag (set for castling and ; en passant pawn captures) ; Bit 5 -- Pawn Promotion flag; set when pawn ; promotes. ; Bit 4 -- When set, this flag indicates that ; this is the first move for the ; piece on the move. ; Bit 3 -- This flag is set is there is a piece ; captured, and that piece has moved at ; least once. ; Bits 2-0 Describe the captured piece. A ; zero value indicates no capture. ; ; MLVAL -- The field in the move entry which contains the ; score assigned to the move. ; ;************************************************************ ORG START+300H PUT START+300H MLIST: DS 2048 MLEND: EQU MLIST+2040 MLPTR: EQU 0 MLFRP: EQU 2 MLTOP: EQU 3 MLFLG: EQU 4 MLVAL: EQU 5 ;************************************************************ ; PROGRAM CODE SECTION ;************************************************************ ; BOARD SETUP ROUTINE ;************************************************************ ; FUNCTION: To initialize the board array, setting the ; pieces in their initial positions for the ; start of the game. ; ; CALLED BY: DRIVER ; ; CALLS: None ; ; ARGUMENTS: None ; ;************************************************************* INITBD: MOV CX,60 ; Pre-fill board with -1's MOV DI,BOARDA MOV AX,-1 REP STOW MOV CH,8 MOV SI,BOARDA IB2: MOV AL,[SI-8] ; Fill non-border squares MOV [SI+21],AL ; White pieces LAHF OR AL,080H SAHF ; Change to black MOV [SI+91],AL ; Black pieces MOV B,[SI+31],PAWN ; White Pawns MOV B,[SI+81],BPAWN ; Black Pawns MOV B,[SI+41],0 ; Empty squares MOV B,[SI+51],0 MOV B,[SI+61],0 MOV B,[SI+71],0 INC SI DEC CH JNZ IB2 MOV SI,POSK ; Init King/Queen position list MOV B,[SI+0],25 MOV B,[SI+1],95 MOV B,[SI+2],24 MOV B,[SI+3],94 RET ;************************************************************ ; PATH ROUTINE ;************************************************************ ; FUNCTION: To generate a single possible move for a given ; piece along its current path of motion including: ; ; Fetching the contents of the board at the new ; position, and setting a flag describing the ; contents: ; 0 -- New postion is empty ; 1 -- Encountered a piece of the ; opposite color ; 2 -- Encountered a piece of the ; same color ; 3 -- New position is off the ; board ; ; CALLED BY: MPIECE ; ATTACK ; PINFND ; ; CALLS: None ; ; ARGUMENTS: Direction from the direction array giving the ; constant to be added for the new position. ;************************************************************ PATH: ADD [M2],CL ; Add direction constant to prev pos MOV SI,[M2] ; Load board index MOV AL,[SI+BOARD] ; Get contents of board CMP AL,-1 ; In boarder area ? JZ PA2 ; Yes - jump MOV [P2],AL ; Save piece MOV AH,AL ; Save piece in register AND AL,7 ; Clear flags MOV [T2],AL ; Save piece type JZ RET ; Return if empty XOR AH,[P1] ; Compare with moving piece SHL AH ; Set flag MOV AL,2 SBB AL,0 RET ; Return PA2: MOV AL,3 ; Set off board flag RET ; Return ;************************************************************ ; PIECE MOVER ROUTINE ;************************************************************ ; FUNCTION: To generate all the possible legal moves for a ; given piece. ; ; CALLED BY: GENMOV ; ; CALLS: PATH ; ADMOVE ; CASTLE ; ENPSNT ; ; ARGUMENTS: The piece to be moved. ;************************************************************* MPIECE: XOR AL,[BX] ; Piece to move AND AL,87H ; Clear flag bit CMP AL,BPAWN ; Is it a black Pawn ? JNZ MP1 ; No-Skip DEC AL ; Decrement for black Pawns MP1: AND AL,7 ; Get piece type MOV [T1],AL ; Save piece type MOV DI,[T1] ; Load index to DCOUNT/DPOINT MOV CH,[DI+DCOUNT] ; Get direction count MOV AL,[DI+DPOINT] ; Get direction pointer MOV [INDX2],AL ; Save as index to direct MOV DI,[INDX2] ; Load index MP5: MOV CL,[DI+DIRECT] ; Get move direction MOV AL,[M1] ; From position MOV [M2],AL ; Initialize to position MP10: CALL PATH ; Calculate next position CMP AL,2 ; Ready for new direction ? JNC MP15 ; Yes - Jump AND AL,AL ; Test for empty square PUSHF MOV AL,[T1] ; Get piece moved CMP AL,PAWN+1 ; Is it a Pawn ? JC MP20 ; Yes - Jump CALL ADMOVE ; Add move to list POPF JNZ MP15 ; No - Jump MOV AL,[T1] ; Piece type CMP AL,KING ; King ? JZ MP15 ; Yes - Jump CMP AL,BISHOP ; Bishop, Rook, or Queen ? JNC MP10 ; Yes - Jump MP15: INC DI ; Increment direction index DEC CH JNZ MP5 ; Decr. count-jump if non-zerc MOV AL,[T1] ; Piece type CMP AL,KING ; King ? JNZ RET JMP CASTLE ; Yes - Try Castling ; ***** PAWN LOGIC ***** MP20: MOV AL,CH ; Counter for direction CMP AL,3 ; On diagonal moves ? JC MP35 ; Yes - Jump JZ MP30 ; -or-jump if on 2 square move POPF JNZ MP15 ; No - jump MOV AL,[M2] ; Get "to" position CMP AL,91 ; Promote white Pawn ? JNC MP25 ; Yes - Jump CMP AL,29 ; Promote black Pawn ? JNC MP26 ; No - Jump MP25: OR B,[P2],020H ; Set promote flag MP26: CALL ADMOVE ; Add to move list INC DI ; Adjust to two square move DEC CH TEST B,[P1],008H ; Check Pawn moved flag, has it moved before ? JZ MP10 ; No - Jump JMP MP15 ; Jump MP30: POPF JNZ MP15 ; No - Jump MP31: CALL ADMOVE ; Add to move list JMP MP15 ; Jump MP35: POPF JZ MP36 ; Yes - Jump MOV AL,[M2] ; Get "to" position CMP AL,91 ; Promote white Pawn ? JNC MP37 ; Yes - Jump CMP AL,29 ; Black Pawn promotion ? JNC MP31 ; No- Jump MP37: OR B,[P2],020H ; Set promote flag JP MP31 ; Jump MP36: CALL ENPSNT ; Try en passant capture JMP MP15 ; Jump ;*********************************************************** ; EN PASSANT ROUTINE ;*********************************************************** ; FUNCTION: -- To test for en passant Pawn capture and ; to add it to the move list if it is ; legal. ; ; CALLED BY: -- MPIECE ; ; CALLS: -- ADMOVE ; ADJPTR ; ; ARGUMENTS: -- None ;************************************************************ ENPSNT: MOV AL,[M1] ; Set position of Pawn TEST B,[P1],080H ; Check color, is it white ? JZ EP5 ; Yes - skip ADD AL,10 ; Add 10 for black EP5: CMP AL,61 ; On en passant capture rank ? JC RET ; No - return CMP AL,69 ; On en passant capture rank ? JNC RET ; No - return MOV SI,[MLPTRJ] ; Get pointer to previous move TEST B,[SI+MLFLG],010H ; First move for that piece ? JZ RET ; No - return MOV AL,[SI+MLTOP] ; Get "to" postion MOV [M4],AL ; Store as index to board MOV SI,[M4] ; Load board index MOV AL,[SI+BOARD] ; Get piece moved MOV [P3],AL ; Save it AND AL,7 ; Get piece type CMP AL,PAWN ; Is it a Pawn ? JNZ RET ; No - return MOV AL,[M4] ; Get "to" position MOV BX,M2 ; Get present "to" position SUB AL,[BX] ; Find difference JNS EP10 ; Positive ? Yes - Jump NEG AL ; Else take absolute value EP10: CMP AL,10 ; Is difference 10 ? JNZ RET ; No - return OR B,[P2],040H ; Set double move flag CALL ADMOVE ; Add Pawn move to move list MOV AL,[M1] ; Save initial Pawn position MOV [M3],AL MOV AL,[M4] ; Set "from" and "to" positions ; for dummy move MOV [M1],AL MOV [M2],AL MOV AL,[P3] ; Save captured Pawn MOV [P2],AL CALL ADMOVE ; Add Pawn capture to move list MOV AL,[M3] ; Restore "from" position MOV [M1],AL ;************************************************************ ; ADJUST MOVE LIST POINTER FOR DOUBLE MOVE ;************************************************************ ; FUNCTION: -- To adjust move list pointer to link around ; second move in double move. ; ; CALLED BY: -- ENPSNT ; CASTLE ; (This mini-routine is not really called, ; but is jumped to to save time.) ; ; CALLS: -- None ; ; ARGUMENTS: -- None ;************************************************************* ADJPTR: MOV BX,[MLLST] ; Get list pointer SUB BX,6 ; Back up list pointer MOV [MLLST],BX ; Save list pointer MOV [BX],0 ; Zero out link RET ; Return ;************************************************************ ;CASTLE ROUTINE ;************************************************************ ; FUNCTION: -- To determine whether castling is legal ; (Queen side, King side, or both) and add it ; to the move list if it is. ; ; CALLED BY: -- MPIECE ; ; CALLS: -- ATTACK ; ADMOVE ; ADJPTR ; ; ARGUMENTS: -- None ;************************************************************ CASTLE: TEST B,[P1],008H ; Has king moved ? JNZ RET ; Yes - return MOV AL,[CKFLG] ; Fetch Check Flag AND AL,AL ; Is the King in check ? JNZ RET ; Yes - Return MOV CX,0FF03H ; Initialize King-side values CA5: ADD CL,[M1] ; Rook position MOV AL,CL MOV [M3],AL ; Store as board index MOV SI,[M3] ; Load board index MOV AL,[SI+BOARD] ; Get contents of board AND AL,7FH ; Clear color bit CMP AL,ROOK ; Has Rook ever moved ? JNZ CA20 ; Yes - Jump MOV AL,CL ; Restore Rook position JP CA15 ; Jump CA10: MOV SI,[M3] ; Load board index MOV AL,[SI+BOARD] ; Get contents of board AND AL,AL ; Empty ? JNZ CA20 ; No - Jump MOV AL,[M3] ; Current position CMP AL,22 ; White Queen Knight square ? JZ CA15 ; Yes - Jump CMP AL,92 ; Black Queen Knight square ? JZ CA15 ; Yes - Jump CALL ATTACK ; Look for attack on square AND AL,AL ; Any attackers ? JNZ CA20 ; Yes - Jump MOV AL,[M3] ; Current position CA15: ADD AL,CH ; Next position MOV [M3],AL ; Save as board index MOV BX,M1 ; King position CMP AL,[BX] ; Reached King ? JNZ CA10 ; No - jump SUB AL,CH ; Determine King's position SUB AL,CH MOV [M2],AL ; Save it MOV BX,P2 ; Address of flags MOV B,[BX],40H ; Set double move flag CALL ADMOVE ; Put king move in list MOV BX,M1 ; Addr of King "from" position MOV AL,[BX] ; Get King's "from" position MOV [BX],CL ; Store Rook "from" position SUB AL,CH ; Get Rook "to" position MOV [M2],AL ; Store Rook "to" position XOR AL,AL ; Zero MOV [P2],AL ; Zero move flags CALL ADMOVE ; Put Rook move in list CALL ADJPTR ; Re-adjust move list pointer MOV AL,[M3] ; Restore King position MOV [M1],AL ; Store CA20: MOV AL,CH ; Scan Index CMP AL,1 ; Done ? JZ RET ; Yes - return MOV CX,01FCH ; Set Queen-side initial values JMP CA5 ; Jump ;************************************************************ ; ADMOVE ROUTINE ;************************************************************ ; FUNCTION: -- To add a move to the move list ; ; CALLED BY: -- MPIECE ; ENPSNT ; CASTLE ; ; CALLS: -- None ; ; ARGUMENT: -- None ;************************************************************* ADMOVE: MOV DX,[MLNXT] ; Addr of next loc in move list MOV BX,MLEND ; Address of list end SUB BX,DX ; Calculate difference JC AM10 ; Jump if out of space MOV BX,[MLLST] ; Addr of prev. list area MOV [MLLST],DX ; Save next as previous MOV [BX],DX ; Store link address TEST B,[P1],008H ; Has moved piece moved before ? JNZ AM5 ; Yes - jump OR B,[P2],010H ; Set first move flag AM5: XCHG DX,DI ; Address of move area XOR AX,AX ; Store zero in link address CLD STOW MOV AL,[M1] ; Store "from" move position STOB MOV AL,[M2] ; Store "to" move position STOB MOV AL,[P2] ; Store move flags/capt. piece STOB XOR AL,AL ; Store initial move value STOB MOV [MLNXT],DI ; Save address for next move MOV DI,DX RET ; Return AM10: MOV [BX],0 ; Abort entry on table ovflow RET ;************************************************************ ; GENERATE MOVE ROUTINE ;************************************************************ ; FUNCTION: -- To generate the move set for all of the ; pieces of a given color. ; ; CALLED BY: -- FNDMOV ; ; CALLS: -- MIECE ; INCHK ; ; ARGUMENTS: -- None ;************************************************************ GENMOV: CALL INCHK ; Test for King in check MOV [CKFLG],AL ; Save attack count as flag MOV DX,[MLNXT] ; Addr of next avail list space MOV BX,[MLPTRI] ; Ply list pointer index INC BX ; Increment to next ply INC BX MOV [BX],DX ; Save move list pointer INC BX INC BX MOV [MLPTRI],BX ; Save new index MOV [MLLST],BX ; Last pointer for chain init. MOV AL,21 ; First position on board GM5: MOV [M1],AL ; Save as index MOV SI,[M1] ; Load board index MOV AL,[SI+BOARD] ; Fetch board contents AND AL,AL ; Is it empty ? JZ GM10 ; Yes - Jump CMP AL,-1 ; Is it a boarder square ? JZ GM10 ; Yes - Jump MOV [P1],AL ; Save piece MOV BX,COLOR ; Address of color of piece XOR AL,[BX] ; Test color of piece TEST AL,080H ; Match ? JNZ GM10 CALL MPIECE ; Yes - call Move Piece GM10: MOV AL,[M1] ; Fetch current board position INC AL ; Incr to next board position CMP AL,99 ; End of board array ? JNZ GM5 ; No - Jump RET ; Return ;************************************************************ ; CHECK ROUTINE ;************************************************************ ; FUNCTION: -- To determine whether or not the ; King is in check. ; ; CALLED BY: -- GENMOV ; FNDMOV ; EVAL ; ; CALLS: -- ATTACK ; ; ARGUMENTS: -- Color of King ;************************************************************ INCHK: MOV AL,[COLOR] ; Get color INCHK1: MOV BX,POSK ; Addr of white King position AND AL,AL ; White ? JZ IC5 ; Yes - Skip INC BX ; Addr of black King position IC5: MOV AL,[BX] ; Fetch King position MOV [M3],AL ; Save MOV SI,[M3] ; Load board index MOV AL,[SI+BOARD] ; Fetch board contents MOV [P1],AL ; Save AND AL,7 ; Get piece type MOV [T1],AL ; Save ;************************************************************ ; ATTACK ROUTINE ;************************************************************ ; FUNCTION: -- To find all attackers on a given square ; by scanning outward from the square ; until a piece is found that attacks ; that square, or a piece is found that ; doesn't attack that square, or the edge ; of the board is reached. ; ; In determining which pieces attack ; a square, this routine also takes into ; account the ability of certain pieces to ; attack through another attacking piece. (For ; example a queen lined up behind a bishop ; of her same color along a diagonal.) The ; bishop is then said to be transparent to the ; queen, since both participate in the ; attack. ; ; In the case where this routine is called ; by CASTLE or INCHK, the routine is ; terminated as soon as an attacker of the ; opposite color is encountered. ; ; CALLED BY: -- POINTS ; PINFND ; CASTLE ; INCHK ; ; CALLS: -- ATKADJ ; ATKOUT ; ; ARGUMENTS: -- None ;************************************************************ ATTACK: PUSH CX ; Save Register CX MOV BP,[M3] ; Get piece index ADD BP,BOARD ; Add board pointer to it MOV DH,0 ; Init. scan count/flags MOV SI,DIRECT+TBASE ; Load direction table MOV AH,KING ; Check for a King CALL ATKADJ ; Scan adjacent squares MOV AH,KNIGHT ; Check for a Knight CALL ATKADJ ; Scan adjacent squares MOV AH,20H ; Pawn attack flag MOV AL,[BP+11] ; Get piece at +11 AND AL,87H ; Clear flag bit CMP AL,BPAWN ; Black Pawn ? JNZ AT5 ; No - jump OR [BP+11],AH ; Set Pawn attack flag AT5: MOV AL,[BP+9] ; Get piece at +9 AND AL,87H ; Clear flag bit CMP AL,BPAWN ; Black Pawn ? JNZ AT10 ; No - jump OR [BP+9],AH ; Set Pawn attack flag AT10: MOV AL,[BP-11] ; Get piece at -11 AND AL,87H ; Clear flag bit CMP AL,PAWN ; White Pawn ? JNZ AT15 ; No - jump OR [BP-11],AH ; Set Pawn attack flag AT15: MOV AL,[BP-9] ; Get piece at -9 AND AL,87H ; Clear flag bit CMP AL,PAWN ; White Pawn ? JNZ AT20 ; No - jump OR [BP-9],AH ; Set Pawn attack flag AT20: MOV SI,DIRECT+TBASE ; Load direction table MOV AH,BISHOP ; Check for a Bishop CALL ATKOUT ; Scan outwards MOV AH,ROOK ; Check for a Rook CALL ATKOUT ; Scan outwards XOR AL,AL ; No attackers POP CX ; Restore CX reg RET ; Return ;************************************************************ ; ATTACK ADJACENT SCAN ROUTINE ;************************************************************ ; FUNCTION: -- To scan for a specified attacker on adjacent ; squares. ; ; CALLED BY: -- ATTACK ; ; CALLS: -- ATKCHK ; ; ARGUMENTS: -- The piece under attack. The attacker. ;************************************************************ ATKADJ: MOV CX,8 ; 8 directions to scan AA5: XCHG AX,BX ; Save AX LODB ; Get direction byte CBW ; Convert to word XCHG AX,BX ; Save direction and restore AX MOV DI,BP ; Load pointer to piece ADD DI,BX ; Add direction constant MOV AL,[DI] ; Get attacking piece AND AL,7 ; Get piece type CMP AL,AH ; Same as what we want ? JNZ AA10 ; No - jump CALL ATKCHK ; Check and save attacker AA10: LOOP AA5 ; Go check for next direction RET ; Return ;************************************************************ ; ATTACK OUTWARD SCAN ROUTINE ;************************************************************ ; FUNCTION: -- To scan for a specified attacker outwards ; from the piece under attack, until found ; or edge of the board is reached. ; ; CALLED BY: -- ATTACK ; ; CALLS: -- ATKCHK ; ; ARGUMENTS: -- The piece under attack. The attacker. ;************************************************************ ATKOUT: MOV CL,4 ; 4 directions to scan AO5: MOV DX,0C0H ; Bitmask for color flags XCHG AX,BX ; Save AX LODB ; Get direction byte CBW ; Convert to word XCHG AX,BX ; Save direction and restore AX MOV DI,BP ; Load pointer to piece AO10: ADD DI,BX ; Add direction constant MOV AL,[DI] ; Get attacking piece AND AL,27H ; Get piece type and Pawn attack flag JZ AO10 ; No piece, keep going CMP AL,AH ; Same as what we want ? JZ AO22 ; Yes - jump CMP AL,QUEEN ; Queen ? JZ AO20 ; Yes - jump CMP AL,PAWN+20H ; Pawn with Pawn attack flag ? JZ AO21 ; Yes - jump AO15: LOOP AO5 ; Go check for next direction RET ; Return AO20: INC DH ; Set Queen found flag AO21: AND B,[DI],0DFH ; Remove Pawn attack flag AO22: MOV AL,[DI] ; Get piece ADD AL,80H ; CY if black, NC if white RCR AL ; Bit 7 set if black, bit 6 if white AND DL,AL ; Keep only bits 6 and 7 JZ AO15 ; Nothing, next direction CALL ATKCHK ; Check and save attack JP AO10 ; Keeping going that direction ;************************************************************ ; ATTACK CHECK AND SAVE ROUTINE ;************************************************************ ; FUNCTION: -- To check if a piece can attack the target ; square and save the attacking piece value ; in the attack list. ; ; The pin piece list is checked for the ; attacking piece, and if found there, the ; piece is not included in the attack list. ; ; In the case where ATTACK is called by ; CASTLE or INCHK, control is returned to ; the aforementioned routines as soon as an ; attacker of the opposite color is encountered. ; ; CALLED BY: -- ATKADJ ; ATKOUT ; ; CALLS: -- None ; ; ARGUMENTS: -- The attacking piece. The piece under attack. ;************************************************************ ATKCHK: MOV AL,[DI] ; Get piece CMP B,[T1],7 ; Call from POINTS ? JZ ACK10 ; Yes - jump XOR AL,[BP] ; Attacker and target same color ? JNS RET ; Yes - return POP AX POP AX ; Set SP level to ATTACK MOV AX,0DFFFH ; FF (border) in AL and DF in AH CMP [BP+9],AL ; Is +9 border ? JZ ACK5 ; Yes, jump AND [BP+9],AH ; Remove Pawn attack flag ACK5: CMP [BP+11],AL ; Is +11 border ? JZ ACK6 ; Yes - jump AND [BP+11],AH ; Remove Pawn attack flag ACK6: CMP [BP-9],AL ; Is -9 border ? JZ ACK7 ; Yes - jump AND [BP-9],AH ; Remove Pawn attack flag ACK7: CMP [BP-11],AL ; Is -11 border ? JZ ACK8 ; Yes - jump AND [BP-11],AH ; Remove Pawn attack flag ACK8: MOV AL,1 ; Set attacker found flag POP CX ; Restore CX reg RET ; Return from ATTACK ACK10: PUSH CX ; Save regs PUSH DI MOV CL,[NPINS] ; Number of pinned pieces JCXZ ACK26 ; No pins - jump PUSH AX ; Save AX MOV AX,DI ; Load piece pointer in AX SUB AX,BOARDA ; Minus BOARDA for position MOV DI,PLISTA ; Pin list address ACK15: OR AL,AL ; Set flags for REP REPZ SCAB ; Search list for position JNZ ACK25 ; Continue if not found OR AH,AH ; Is this the first find ? JNZ ACK20 ; No - jump MOV AH,[DI+9] ; Get direction CMP AH,BL ; Same as attacking direction ? JZ ACK15 ; Yes - jump NEG AH ; Opposite direction ? CMP AH,BL ; Same as attacking direction ? JZ ACK15 ; Yes - jump ACK20: POP AX ; Restore regs. POP DI POP CX RET ; Return to ATTACK ACK25: POP AX ; Restore AX ACK26: MOV CL,AL ; Put piece in CL AND CL,7 ; Get piece type MOV DI,PVALUE+TBASE ; PVALUE list address ADD DI,CX ; Point to piece value MOV CL,[DI] ; Get point value of piece MOV DI,ATKLST ; Init address of attack list TEST AL,80H ; Is it white ? JZ ACK30 ; Yes - jump ADD DI,7 ; Attack list address ACK30: OR DH,DH ; Queen found this scan ? JZ ACK31 ; No - jump MOV AL,QUEEN ; Use Queen slot in attack list ACK31: AND AL,7 ; Attacking piece type INC B,[DI] ; Increment list count XCHG AL,CL ; Save point value in AL ADD DI,CX ; Attack list slot address MOV CH,[DI] ; Get data already there TEST CH,0FH ; Is first slot empty ? JZ ACK40 ; Yes - jump TEST CH,0F0H ; Is second slot empty ? JZ ACK35 ; Yes - jump INC DI ; Increment to King slot MOV CH,[DI] ; Get byte XCHG AL,CH ; Byte to AL, point value to CH ACK35: SHL AL ; Lower bits to upper SHL AL SHL AL SHL AL OR AL,CH ; Combine with point value ACK40: MOV [DI],AL ; Put back into attack list POP DI ; Restore regs POP CX RET ; Return ;************************************************************ ; PIN FIND ROUTINE ;************************************************************ ; FUNCTION: -- To produce a list of all pieces pinned ; against the King or Queen, for both white ; and black. ; ; CALLED BY: -- FNDMOV ; EVAL ; ; CALLS: -- PATH ; ATTACK ; ; ARGUMENTS: -- None ;************************************************************ PINFND: XOR AL,AL ; Zero pin count MOV [NPINS],AL MOV DX,POSK ; Addr of King/Queen pos list PF1: MOV BP,DX MOV AL,[BP] ; Get position of royal piece AND AL,AL ; Is it on board ? JNZ PF1A ; Yes - continue JMP PF26 PF1A: CMP AL,-1 ; At end of list ? JZ RET ; Yes return MOV [M3],AL ; Save position as board index MOV SI,[M3] ; Load index to board MOV AL,[SI+BOARD] ; Get contents of board MOV [P1],AL ; Save MOV CH,8 ; Init scan direction count XOR AL,AL MOV [INDX2],AL ; Init direction index MOV DI,[INDX2] PF2: MOV AL,[M3] ; Get King/Queen position MOV [M2],AL ; Save XOR AL,AL MOV [M4],AL ; Clear pinned piece saved pos MOV CL,[DI+DIRECT] ; Get direction of scan PF5: CALL PATH ; Compute next position AND AL,AL ; Is it empty ? JZ PF5 ; Yes - jump CMP AL,3 ; Off board ? JZ JPF25 ; Yes - jump CMP AL,2 ; Piece of same color found ? MOV AL,[M4] ; Load pinned piece position JZ PF15 ; Yes - jump AND AL,AL ; Possible pin ? JZ JPF25 ; No - jump MOV AL,[T2] ; Piece type encountered CMP AL,QUEEN ; Queen ? JZ PF19 ; Yes - jump MOV BL,AL ; Save piece type MOV AL,CH ; Direction counter CMP AL,5 ; Non-diagonal direction ? JC PF10 ; Yes - jump MOV AL,BL ; Piece type CMP AL,BISHOP ; Bishop ? JNZ PF25 ; No - jump JMP PF20 ; Jump JPF25: JMP PF25 PF10: MOV AL,BL ; Piece type CMP AL,ROOK ; Rook ? JNZ PF25 ; No - jump JMP PF20 ; Jump PF15: AND AL,AL ; Possible pin ? JNZ PF25 ; No - jump MOV AL,[M2] ; Save possible pin position MOV [M4],AL JMP PF5 ; Jump PF19: MOV AL,[P1] ; Load King or Queen AND AL,7 ; Clear flags CMP AL,QUEEN ; Queen ? JNZ PF20 ; No - jump PUSH CX ; Save regs. PUSH DX PUSH DI XOR AX,AX ; Zero out attack list MOV CX,7 MOV BX,ATKLST XCHG DI,BX CLD REP STOW XCHG DI,BX MOV AL,7 ; Set attack flag MOV [T1],AL CALL ATTACK ; Find attackers/defenders MOV BX,WACT ; White queen attackers MOV DX,BACT ; Black queen attackers TEST B,[P1],080H ; Is queen white ? JZ PF19A ; Yes - skip XCHG DX,BX ; Reverse for black PF19A: MOV AL,[BX] ; Number of defenders XCHG DX,BX ; Reverse for attackers SUB AL,[BX] ; Defenders minus attackers DEC AL ; Less 1 POP DI ; Restore regs. POP DX POP CX JNS PF25 ; Jump if pin not valid PF20: MOV BX,NPINS ; Address of pinned piece count INC B,[BX] ; Increment MOV SI,[NPINS] ; Load pin list index MOV [SI+PLISTD],CL ; Save direction of pin MOV AL,[M4] ; Position of pinned piece MOV [SI+PLIST],AL ; Save in list PF25: INC DI ; Increment direction index DEC CH JZ PF26 ; Done ? Yes - Continue JMP PF2 PF26: INC DX ; Incr King/Queen pos index JMP PF1 ; Jump ;************************************************************ ; EXCHANGE ROUTINE ;************************************************************ ; FUNCTION: -- To determine the exchange value of a ; piece on a given square by examining all ; attackers and defenders of that piece. ; ; CALLED BY: -- POINTS ; ; CALLS: -- NEXTAD ; ; ARGUMENTS: -- None. ;*********************************************************** XCHNG: XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] ; Swap regs. MOV AL,[P1] ; Piece attacked MOV BX,WACT ; Addr of white attkrs/dfndrs MOV DX,BACT ; Addr of black attkrs/dfndrs TEST AL,080H ; Is piece white ? JZ XC5 ; Yes - jump XCHG DX,BX ; Swap list pointers XC5: MOV CH,[BX] ; Init list counts XCHG DX,BX MOV CL,[BX] XCHG DX,BX XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] ; Restore regs. MOV CL,0 ; Init attacker/defender flag MOV DL,0 ; Init points lost count MOV SI,[T3] ; Load piece value index MOV DH,[SI+PVALUE] ; Get attacked piece value SAL DH ; Double it MOV CH,DH ; Save CALL NEXTAD ; Retrieve first attacker JNZ XC10 JMP RET ; Return if none XC10: MOV BL,AL ; Save attacker value CALL NEXTAD ; Get next defender JZ XC18 ; Jump if none LAHF CMP CH,BL ; Attacked less than attacker ? JNC XC19 ; No - jump XC15: CMP AL,BL ; Defender less than attacker ? JC RET ; Yes - return CALL NEXTAD ; Retrieve next attacker value JZ RET ; Return if none MOV BL,AL ; Save attacker value CALL NEXTAD ; Retrieve next defender value JNZ XC15 ; Jump if none XC18: LAHF XC19: TEST CL,001H ; Attacker or defender ? JZ XC20 ; Jump if defender NEG CH ; Negate value for attacker XC20: ADD DL,CH ; Total points lost SAHF JZ RET ; Return if none MOV CH,BL ; Prev attckr becomes defender JMP XC10 ; Jump ;************************************************************ ; NEXT ATTACKER/DEFENDER ROUTINE ;************************************************************ ; FUNCTION: -- To retrieve the next attacker or defender ; piece value from the attack list, and delete ; that piece from the list. ; ; CALLED BY: -- XCHNG ; ; CALLS: -- None ; ; ARGUMENTS: -- Attack list addresses. ; Side flag ; Attack list counts ;********************************************************* NEXTAD: INC CL ; Increment side flag XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] ; Swap registers XCHG CH,CL ; Swap list counts XCHG DX,BX ; Swap list pointers XOR AL,AL CMP AL,CH ; At end of list ? JZ NX6 ; Yes - jump DEC CH ; Decrement list count NX5: INC BX ; Increment list pointer CMP AL,[BX] ; Check next item in list JZ NX5 ; Jump if empty MOV AL,[BX] ; Get value from list MOV AH,AL SHR AH SHR AH SHR AH SHR AH MOV [BX],AH AND AL,0FH DEC BX ; Decrement list pointer ADD AL,AL ; Double it NX6: XCHG BX,[HL] XCHG DX,[DE] XCHG CX,[BC] ; Restore regs. RET ; Return ;************************************************************ ; POINT EVALUATION ROUTINE ;************************************************************ ;FUNCTION: -- To perform a static board evaluation and ; derive a score for a given board position ; ; CALLED BY: -- FNDMOV ; EVAL ; ; CALLS: -- ATTACK ; XCHNG ; LIMIT ; ; ARGUMENTS: -- None ;************************************************************** POINTS: XOR AL,AL ; Zero out variables MOV [MTRL],AL MOV [BRDC],AL MOV [PTSL],AL MOV [PTSW1],AL MOV [PTSW2],AL MOV [PTSCK],AL MOV BX,T1 ; Set attacker flag MOV B,[BX],7 MOV AL,21 ; Init to first square on board PT5: MOV [M3],AL ; Save as board index MOV SI,[M3] ; Load board index MOV AL,[SI+BOARD] ; Get piece from board CMP AL,-1 ; Off board edge ? JNZ PT5A JMP PT25 ; Yes - jump PT5A: MOV BX,P1 ; Save piece, if any MOV [BX],AL AND AL,7 ; Save piece type, if any MOV [T3],AL CMP AL,KNIGHT ; Less than a Knight (Pawn) ? JC PT6X ; Yes - Jump CMP AL,ROOK ; Rook, Queen or King ? JC PT6B ; No - jump CMP AL,KING ; Is it a King ? JZ PT6AA ; Yes - jump MOV AL,[MOVENO] ; Get move number CMP AL,7 ; Less than 7 ? JC PT6A ; Yes - Jump JMP PT6X ; Jump PT6AA: TEST B,[BX],010H ; Castled yet ? JZ PT6A ; No - jump MOV AL,+6 ; Bonus for castling TEST B,[BX],080H ; Check piece color JZ PT6D ; Jump if white MOV AL,-6 ; Bonus for black castling JP PT6D ; Jump PT6A: TEST B,[BX],008H ; Has piece moved yet ? JZ PT6X ; No - jump JP PT6C ; Jump PT6B: TEST B,[BX],008H ; Has piece moved yet ? JNZ PT6X ; Yes - jump PT6C: MOV AL,-2 ; Two point penalty for white TEST B,[BX],080H ; Check piece color JZ PT6D ; Jump if white MOV AL,+2 ; Two point penalty for black PT6D: MOV BX,BRDC ; Get address of board control ADD [BX],AL ; Add on penalty/bonus points PT6X: XOR AX,AX ; Zero out attack list MOV CX,7 MOV BX,ATKLST XCHG DI,BX CLD REP STOW XCHG DI,BX CALL ATTACK ; Build attack list for square MOV BX,BACT ; Get black attacker count addr MOV AL,[WACT] ; Get white attacker count SUB AL,[BX] ; Compute count difference MOV BX,BRDC ; Address of board control ADD AL,[BX] ; Accum board control score MOV [BX],AL ; Save MOV AL,[P1] ; Get piece on current square AND AL,AL ; Is it empty ? JZ PT25 ; Yes - jump CALL XCHNG ; Evaluate exchange, if any XOR AL,AL ; Check for a loss CMP AL,DL ; Points lost ? JZ PT23 ; No - Jump DEC DH ; Deduct half a Pawn value MOV AL,[P1] ; Get piece under attack XOR AL,[COLOR] ; Compare color of side just moved with piece TEST AL,080H ; Do colors match ? MOV AL,DL ; Points lost JNZ PT20 ; Jump if no match MOV BX,PTSL ; Previous max points lost CMP AL,[BX] ; Compare to current value JC PT23 ; Jump if greater than MOV [BX],DL ; Store new value as max lost MOV SI,[MLPTRJ] ; Load pointer to this move MOV AL,[M3] ; Get position of lost piece CMP AL,[SI+MLTOP] ; Is it the one moving ? JNZ PT23 ; No - jump MOV [PTSCK],AL ; Save position as a flag JP PT23 ; Jump PT20: MOV BX,PTSW1 ; Previous maximum points won CMP AL,[BX] ; Compare to current value JC PT21 ; Jump if greater than MOV AL,[BX] ; Load previous max value MOV [BX],DL ; Store new value as max won PT21: MOV BX,PTSW2 ; Previous 2nd max points won CMP AL,[BX] ; Compare to current value JC PT23 ; Jump if greater than MOV [BX],AL ; Store as new 2nd max lost PT23: TEST B,[P1],080H ; Test piece color MOV AL,DH ; Value of piece JZ PT24 ; Jump if white NEG AL ; Negate for black PT24: MOV BX,MTRL ; Get addrs of material total ADD AL,[BX] ; Add new value MOV [BX],AL ; Store PT25: MOV AL,[M3] ; Get current board position INC AL ; Increment CMP AL,99 ; At end of board ? JZ PT25AA JMP PT5 ; No - jump PT25AA: MOV AL,[PTSCK] ; Moving piece lost flag AND AL,AL ; Was it lost ? JZ PT25A ; No - jump MOV AL,[PTSW2] ; 2nd max points won MOV [PTSW1],AL ; Store as max points won XOR AL,AL ; Zero out 2nd max points won MOV [PTSW2],AL PT25A: MOV AL,[PTSL] ; Get max points lost AND AL,AL ; Is it zero ? JZ PT26 ; Yes - jump DEC AL ; Decrement it PT26: MOV CH,AL ; Save it MOV AL,[PTSW1] ; Max points won AND AL,AL ; Is it zero ? JZ PT27 ; Yes - jump MOV AL,[PTSW2] ; 2nd max points won AND AL,AL ; Is it zero ? JZ PT27 ; Yes - jump DEC AL ; Decrement it SHR AL ; Divide it by 2 PT27: SUB AL,CH ; Subtract points lost TEST B,[COLOR],080H ; Is color of side just moved white ? JZ PT28 ; Yes - jump NEG AL ; Negate for black PT28: MOV BX,MTRL ; Net material on board ADD AL,[BX] ; Add exchange adjustments MOV BX,MV0 ; Material at ply 0 SUB AL,[BX] ; Subtract from current MOV CH,AL ; Save MOV AL,30 ; Load material limit CALL LIMIT ; Limit to plus or minus value MOV DL,AL ; Save limited value MOV AL,[BRDC] ; Get board control points MOV BX,BC0 ; Board control at ply zero SUB AL,[BX] ; Get difference MOV CH,AL ; Save MOV AL,[PTSCK] ; Moving piece lost flag AND AL,AL ; Is it zero ? JZ PT29 ; Yes - jump MOV CH,0 ; Zero board control points PT29: MOV AL,6 ; Load board control limit CALL LIMIT ; Limit to plus or minus value MOV DH,AL ; Save limited value MOV AL,DL ; Get material points ADD AL,AL ; Multiply by 4 ADD AL,AL ADD AL,DH ; Add board control TEST B,[COLOR],080H ; Is color of side just moved white ? JNZ PT30 ; No - jump NEG AL ; Negate for white PT30: ADD AL,80H ; Rescale score (neutral = 80H) MOV [VALM],AL ; Save score MOV SI,[MLPTRJ] ; Load move list pointer MOV [SI+MLVAL],AL ; Save score in move list RET ; Return ;*********************************************************** ; LIMIT ROUTINE ;********************************************************** ; FUNCTION: -- To limit the magnitude of a given value ; to another given value. ; ; CALLED BY: -- POINTS ; ; CALLS: -- None ; ; ARGUMENTS: -- Input - Value to be limited in the CH ; register. ; - Value to limit to in the AL register. ; Output - Limited value in the AL register. ;************************************************************ LIMIT: TEST CH,080H ; Is value negative ? JZ LIM10 ; No - jump NEG AL ; Make positive CMP AL,CH ; Compare to limit JNC RET ; Return if outside limit MOV AL,CH ; Output value as is RET ; Return LIM10: CMP AL,CH ; Compare to limit JC RET ; Return if outside limit MOV AL,CH ; Output value as is RET ; Return ;*********************************************************** ; MOVE ROUTINE ;*********************************************************** ; FUNCTION: -- To execute a move from the move list on the ; board array. ; ; CALLED BY: -- CPTRMV ; PLYRMV ; EVAL ; FNDMOV ; VALMOV ; ; CALLS: -- None ; ; ARGUMENTS: -- None ;************************************************************ MOVE: MOV BX,[MLPTRJ] ; Load move list pointer INC BX ; Increment past link bytes INC BX MV1: MOV AL,[BX] ; "From" position MOV [M1],AL ; Save INC BX ; Increment pointer MOV AL,[BX] ; "To" position MOV [M2],AL ; Save INC BX ; Increment pointer MOV DH,[BX] ; Get captured piece/flags MOV SI,[M1] ; Load "from" pos board index MOV DL,[SI+BOARD] ; Get piece moved TEST DH,020H ; Test Pawn promotion flag JNZ MV15 ; Jump if set MOV AL,DL ; Piece moved AND AL,7 ; Clear flag bits CMP AL,QUEEN ; Is it a queen ? JZ MV20 ; Yes - jump CMP AL,KING ; Is it a king ? JZ MV30 ; Yes - jump MV5: MOV DI,[M2] ; Load "to" pos board index OR DL,008H ; Set piece moved flag MOV [DI+BOARD],DL ; Insert piece at new position MOV B,[SI+BOARD],0 ; Empty previous position TEST DH,040H ; Double move ? JNZ MV40 ; Yes - jump MOV AL,DH ; Get captured piece, if any AND AL,7 CMP AL,QUEEN ; Was it a queen ? JNZ RET ; No - return MOV BX,POSQ ; Addr of saved Queen position TEST DH,080H ; Is Queen white ? JZ MV10 ; Yes - jump INC BX ; Increment to black Queen pos MV10: XOR AL,AL ; Set saved position to zero MOV [BX],AL RET ; Return MV15: OR DL,004H ; Change Pawn to a Queen JMP MV5 ; Jump MV20: MOV BX,POSQ ; Addr of saved Queen position MV21: TEST DL,080H ; Is Queen white ? JZ MV22 ; Yes - jump INC BX ; Increment to black Queen pos MV22: MOV AL,[M2] ; Get new Queen position MOV [BX],AL ; Save JMP MV5 ; Jump MV30: MOV BX,POSK ; Get saved King position TEST DH,020H ; Castling ? JZ MV21 ; No - jump OR DL,010H ; Set King castled flag JMP MV21 ; Jump MV40: MOV BX,[MLPTRJ] ; Get move list pointer ADD BX,8 ; Increment to next move JMP MV1 ; Jump (2nd part of dbl move) ;********************************************************** ; UN-MOVE ROUTINE ;********************************************************** ; FUNCTION: -- To reverse the process of the move routine, ; thereby restoring the board array to its ; previous position. ; ; CALLED BY: -- VALMOV ; EVAL ; FNDMOV ; ASCEND ; ; CALLS: -- None ; ; ARGUMENTS: -- None ;************************************************************* UNMOVE: MOV BX,[MLPTRJ] ; Load move list pointer INC BX ; Increment past link bytes INC BX UM1: MOV AL,[BX] ; Get "from" position MOV [M1],AL ; Save INC BX ; Increment pointer MOV AL,[BX] ; Get "to" position MOV [M2],AL ; Save INC BX ; Increment pointer MOV DH,[BX] ; Get captured piece/flags MOV SI,[M2] ; Load "to" pos board index MOV DL,[SI+BOARD] ; Get piece moved TEST DH,020H ; Was it a Pawn promotion ? JNZ UM15 ; Yes - jump MOV AL,DL ; Get piece moved AND AL,7 ; Clear flag bits CMP AL,QUEEN ; Was it a Queen ? JZ UM20 ; Yes - jump CMP AL,KING ; Was it a King ? JZ UM30 ; Yes - jump UM5: TEST DH,010H ; Is this 1st move for piece ? JNZ UM16 ; Yes - jump UM6: MOV DI,[M1] ; Load "from" pos board index MOV [DI+BOARD],DL ; Return to previous board pos MOV AL,DH ; Get captured piece, if any AND AL,8FH ; Clear flags MOV [SI+BOARD],AL ; Return to board TEST DH,040H ; Was it a double move ? JNZ UM40 ; Yes - jump MOV AL,DH ; Get captured piece, if any AND AL,7 ; Clear flag bits CMP AL,QUEEN ; Was it a Queen ? JNZ RET ; No - return MOV BX,POSQ ; Address of saved Queen pos TEST DH,080H ; Is Queen white ? JZ UM10 ; Yes - jump INC BX ; Increment to black Queen pos UM10: MOV AL,[M2] ; Queen's previous position MOV [BX],AL ; Save RET ; Return UM15: AND DL,0FBH ; Restore Queen to Pawn JMP UM5 ; Jump UM16: AND DL,0F7H ; Clear piece moved flag JMP UM6 ; Jump UM20: MOV BX,POSQ ; Addr of saved Queen position UM21: TEST DL,080H ; Is Queen white ? JZ UM22 ; Yes - jump INC BX ; Increment to black Queen pos UM22: MOV AL,[M1] ; Get previous position MOV [BX],AL ; Save JMP UM5 ; Jump UM30: MOV BX,POSK ; Address of saved King pos TEST DH,040H ; Was it a castle ? JZ UM21 ; No - jump AND DL,0EFH ; Clear castled flag JMP UM21 ; Jump UM40: MOV BX,[MLPTRJ] ; Load move list pointer ADD BX,8 ; Increment to next move JMP UM1 ; Jump (2nd part of dbl move) ;********************************************************** ; SORT ROUTINE ;********************************************************** ; FUNCTION: -- To sort the move list in order of ; increasing move value scores. ; ; CALLED BY: -- FNDMOV ; ; CALLS: -- EVAL ; ; ARGUMENTS: -- None ;************************************************************* SORTM: MOV CX,[MLPTRI] ; Move list begin pointer MOV DX,0 ; Initialize working pointers SR5: MOV BH,CH MOV BL,CL MOV CL,[BX] ; Link to next move INC BX MOV CH,[BX] MOV [BX],DH ; Store to link in list DEC BX MOV [BX],DL XOR AL,AL ; End of list ? CMP AL,CH JZ RET ; Yes - return SR10: MOV [MLPTRJ],CX ; Save list pointer CALL EVAL ; Evaluate move MOV BX,[MLPTRI] ; Begining of move list MOV CX,[MLPTRJ] ; Restore list pointer SR15: MOV DL,[BX] ; Next move for compare INC BX MOV DH,[BX] XOR AL,AL ; At end of list ? CMP AL,DH JZ SR25 ; Yes - jump MOV SI,DX ; Transfer move pointer MOV AL,[VALM] ; Get new move value CMP AL,[SI+MLVAL] ; Less than list value ? JNC SR30 ; No - jump SR25: MOV [BX],CH ; Link new move into list DEC BX MOV [BX],CL JMP SR5 ; Jump SR30: XCHG DX,BX ; Swap pointers JMP SR15 ; Jump ;********************************************************** ; EVALUATION ROUTINE ;********************************************************** ; FUNCTION: -- To evaluate a given move in the move list. ; It first makes the move on the board, then if ; the move is legal, it evaluates it, and then ; restores the boaard position. ; ; CALLED BY: -- SORT ; ; CALLS: -- MOVE ; INCHK ; PINFND ; POINTS ; UNMOV ; ; ARGUMENTS: -- None ;************************************************************* EVAL: CALL MOVE ; Make move on the board array CALL INCHK ; Determine if move is legal AND AL,AL ; Legal move ? JZ EV5 ; Yes - jump XOR AL,AL ; Score of zero MOV [VALM],AL ; For illegal move JMP UNMOVE ; Jump EV5: CALL PINFND ; Compile pinned list CALL POINTS ; Assign points to move JMP UNMOVE ; Restore board array ;********************************************************* ; FIND MOVE ROUTINE ;********************************************************* ; FUNCTION: -- To determine the computer's best move by ; performing a depth first tree search using ; the techniques of alpha-beta pruning. ; ; CALLED BY: -- CPTRMV ; ; CALLS: -- PINFND ; POINTS ; GENMOV ; SORTM ; ASCEND ; UNMOV ; ; ARGUMENTS: -- None ;************************************************************ FNDMOV: MOV AL,[MOVENO] ; Currnet move number CMP AL,1 ; First move ? JNZ L0003 CALL BOOK ; Yes - execute book opening L0003: XOR AL,AL ; Initialize ply number to zero MOV [NPLY],AL MOV BX,0 ; Initialize best move to zero MOV [BESTM],BX MOV BX,MLIST ; Initialize ply list pointers MOV [MLNXT],BX MOV BX,PLYIX-2 MOV [MLPTRI],BX MOV AL,[KOLOR] ; Initialize color MOV [COLOR],AL MOV BX,SCORE ; Initialize score index MOV [SCRIX],BX MOV AL,[PLYMAX] ; Get max ply number ADD AL,2 ; Add 2 MOV CH,AL ; Save as counter XOR AL,AL ; Zero out score table FM1: MOV [BX],AL INC BX DEC CH JNZ FM1 MOV [BC0],AL ; Zero ply 0 board control MOV [MV0],AL ; Zero ply 0 material CALL PINFND ; Complie pin list CALL POINTS ; Evaluate board at ply 0 MOV AL,[BRDC] ; Get board control points MOV [BC0],AL ; Save MOV AL,[MTRL] ; Get material count MOV [MV0],AL ; Save FM5: MOV BX,NPLY ; Address of ply counter INC B,[BX] ; Increment ply count XOR AL,AL ; Initialize mate flag MOV [MATEF],AL CALL GENMOV ; Generate list of moves MOV AL,[NPLY] ; Current ply counter MOV BX,PLYMAX ; Address of maximum ply number CMP AL,[BX] ; At max ply ? JNC L0004 CALL SORTM ; No - call sort L0004: MOV BX,[MLPTRI] ; Load ply index pointer MOV [MLPTRJ],BX ; Save as last move pointer FM15: MOV BX,[MLPTRJ] ; Load last move pointer MOV DL,[BX] ; Get next move pointer INC BX MOV DH,[BX] MOV AL,DH AND AL,AL ; End of move list ? JNZ FM15A JMP FM25 ; Yes - jump FM15A: MOV [MLPTRJ],DX ; Save current move pointer MOV BX,[MLPTRI] ; Save in ply pointer list MOV [BX],DL INC BX MOV [BX],DH MOV AL,[NPLY] ; Current ply counter MOV BX,PLYMAX ; Maximum ply number ? CMP AL,[BX] ; Compare JC FM18 ; Jump if not max CALL MOVE ; Execute move on board array CALL INCHK ; Check for legal move AND AL,AL ; Is move legal ? JZ FM16 ; Yes - jump CALL UNMOVE ; Restore board position JMP FM15 ; Jump FM16: MOV AL,[NPLY] ; Get ply counter MOV BX,PLYMAX ; Max ply number CMP AL,[BX] ; Beyond max ply ? JZ FM17 JMP FM35 ; Yes - jump FM17: MOV AL,[COLOR] ; Get current color XOR AL,80H ; Get opposite color CALL INCHK1 ; Determine if King is in check AND AL,AL ; In check ? JZ FM35 ; No - jump JMP FM19 ; Jump (One more ply for check) FM18: MOV SI,[MLPTRJ] ; Load move pointer MOV AL,[SI+MLVAL] ; Get move score AND AL,AL ; Is it zero (illegal move) ? JZ FM15 ; Yes - jump CALL MOVE ; Execute move on board array FM19: XOR B,[COLOR],80H ; Toggle color, is new color white ? JS FM20 ; No - jump INC B,[MOVENO] ; Increment move number FM20: MOV BX,[SCRIX] ; Load score table pointer MOV AL,[BX] ; Get score two plys above INC BX ; Increment to current ply MOV [SCRIX],BX ; Save it INC BX MOV [BX],AL ; Save score as initial value JMP FM5 ; Jump FM25: MOV AL,[MATEF] ; Get mate flag AND AL,AL ; Checkmate or stalemate ? JNZ FM30 ; No - jump MOV AL,[CKFLG] ; Get check flag AND AL,AL ; Was King in check ? MOV AL,80H ; Pre-set stalemate score JZ FM36 ; No - jump (stalemate) MOV AL,[MOVENO] ; Get move number MOV [PMATE],AL ; Save MOV AL,0FFH ; Pre-set checkmate score JMP FM36 ; Jump FM30: MOV AL,[NPLY] ; Get ply counter CMP AL,1 ; At top of tree ? JZ RET ; Yes - return CALL ASCEND ; Ascend one ply in tree MOV BX,[SCRIX] ; Load score table pointer INC BX ; Increment to current ply INC BX MOV AL,[BX] ; Get score DEC BX ; Restore pointer DEC BX JMP FM37 ; Jump JFM15: JMP FM15 FM35: CALL PINFND ; Compile pin list CALL POINTS ; Evaluate move CALL UNMOVE ; Restore board position MOV AL,[VALM] ; Get value of move FM36: OR B,[MATEF],001H ; Set mate flag MOV BX,[SCRIX] ; Load score table pointer FM37: CMP AL,[BX] ; Compare to score 2 ply above JC FM40 ; Jump if less JZ FM40 ; Jump if equal NEG AL ; Negate score INC BX ; Incr score table pointer CMP AL,[BX] ; Compare to score 1 ply above JC JFM15 ; Jump if less than JZ JFM15 ; Jump if equal MOV [BX],AL ; Save as new score 1 ply above MOV AL,[NPLY] ; Get current ply counter CMP AL,1 ; At top of tree ? JNZ JFM15 ; No - jump MOV BX,[MLPTRJ] ; Load current move pointer MOV [BESTM],BX ; Save as best move pointer MOV AL,[SCORE+1] ; Get best move score CMP AL,0FFH ; Was it a checkmate ? JNZ JFM15 ; No - jump MOV BX,PLYMAX ; Get maximum ply number SUB B,[BX],2 ; Subtract 2 MOV AL,[KOLOR] ; Get computer's color TEST AL,080H ; Is it white ? JZ RET ; Yes - return MOV BX,PMATE ; Checkmate move number DEC B,[BX] ; Decrement RET ; Return FM40: CALL ASCEND ; Ascend one ply in tree JMP FM15 ; Jump ;********************************************************** ; ASCEND TREE ROUTINE ;********************************************************* ; FUNCTION: -- To adjust all necessary parameters to ; ascend one ply in the tree. ; ; CALLED BY: -- FNDMOV ; ; CALLS: -- UNMOV ; ; ARGUMENTS: -- None ;************************************************************ ASCEND: XOR B,[COLOR],80H ; Toggle color, is new color white ? JNS AC5 ; Yes - jump DEC B,[MOVENO] ; Decrement move number AC5: DEC [SCRIX] ; Decrement score table index DEC B,[NPLY] ; Decrement ply counter MOV BX,[MLPTRI] ; Load ply list pointer DEC BX ; Load pointer to move list top DEC BX MOV DX,[BX] MOV [MLNXT],DX ; Update move list avail ptr DEC BX ; Get ptr to next move to undo DEC BX MOV DX,[BX] MOV [MLPTRI],BX ; Save new ply list pointer MOV [MLPTRJ],DX ; Save next move pointer JMP UNMOVE ; Restore board to previous ply ;********************************************************** ; ONE MOVE BOOK OPENING ;********************************************************* ; FUNCTION: -- To provide an opening book of a single ; move. ; ; CALLED BY: -- FNDMOV ; ; CALLS: -- None ; ; ARGUMENTS: -- None ;*********************************************************** BOOK: POP AX MOV B,[SCORE+1],0 ; Zero out score table MOV [BESTM],BMOVES-2 ; Init best move ptr to book MOV BX,BESTM ; Initialize address of pointer MOV AL,[KOLOR] ; Get computer's color AND AL,AL ; Is it white ? JNZ BM5 ; No - jump MOV AL,0 ; Load random number (0) TEST AL,001H ; Test random bit JZ RET ; Return if zero (P-K4) ADD B,[BX],3 ; P-Q4 RET ; Return BM5: ADD B,[BX],6 ; Increment to black moves MOV SI,[MLPTRJ] ; Pointer to opponents 1st move MOV AL,[SI+MLFRP] ; Get "from" position CMP AL,22 ; Is it a Queen Knight move ? JZ BM9 ; Yes - Jump CMP AL,27 ; Is it a King Knight move ? JZ BM9 ; Yes - jump CMP AL,34 ; Is it a Queen Pawn ? JZ BM9 ; Yes - jump JC RET ; If Queen side Pawn opening - ; return (P-K4) CMP AL,35 ; Is it a King Pawn ? JZ RET ; Yes - return (P-K4) BM9: ADD B,[BX],3 ; (P-Q4) RET ; Return to CPTRMV ;*********************************************************** ; COMPUTER MOVE ROUTINE ;*********************************************************** ; FUNCTION: -- To control the search for the computers move ; and the display of that move on the board ; and in the move list. ; ; CALLED BY: -- DRIVER ; ; CALLS: -- FNDMOV ; FCDMAT ; MOVE ; BITASN ; INCHK ; ; ARGUMENTS: -- None ;*********************************************************** CPTRMV: CALL FNDMOV ; Select best move MOV BX,[BESTM] ; Move list pointer variable MOV [MLPTRJ],BX ; Pointer to move data MOV AL,[SCORE+1] ; To check for mates CMP AL,1 ; Mate against computer ? JNZ CP0C ; No - jump MOV CL,1 ; Computer mate flag CALL FCDMAT ; Full checkmate ? CP0C: CALL MOVE ; Produce move on board array MOV SI,[MLPTRJ] ; Get pointer to move MOV DH,[SI+MLTOP] ; "To" position of the move CALL BITASN ; Convert to Ascii MOV [MVEMSG+3],BX ; Put in move message MOV DH,[SI+MLFRP] ; "From" position of the move CALL BITASN ; Convert to Ascii MOV [MVEMSG],BX ; Put in move message MOV DX,MVEMSG ; Output move MOV CL,PRINTBUF CALL SYSTEM CP1C: MOV AL,[COLOR] ; Should computer call check ? MOV CH,AL XOR AL,80H ; Toggle color MOV [COLOR],AL CALL INCHK ; Check for check AND AL,AL ; Is enemy in check ? MOV AL,CH ; Restore color MOV [COLOR],AL JZ CP24 ; No - return MOV DX,CKMSG ; Output "check" MOV CL,PRINTBUF CALL SYSTEM CP24: MOV AL,[SCORE+1] ; Check again for mates CMP AL,0FFH ; Player mated ? JNZ RET ; No - return MOV CL,0 ; Set player mate flag CALL FCDMAT ; Full checkmate ? RET ; Return ;*********************************************************** ; FORCED MATE HANDLING ;*********************************************************** ; FUNCTION: -- To examine situations where there exits ; a forced mate and determine whether or ; not the current move is checkmate. If it is, ; a losing player is offered another game, ; while a loss for the computer signals the ; King to tip over in resignation. ; ; CALLED BY: -- CPTRMV ; ; CALLS: -- None ; ; ARGUMENTS: -- The only value passed in a register is the ; flag which tells FCDMAT whether the computer ; or the player is mated. ;*********************************************************** FCDMAT: MOV AL,[MOVENO] ; Current move number MOV CH,AL ; Save MOV AL,[PMATE] ; Move number where mate occurs SUB AL,CH ; Number of moves till mate AND AL,AL ; Checkmate ? JNZ RET ; No - return RCR AH TEST CL,001H ; Check flag for who is mated RCL AH JZ FM04 ; Jump if player MOV DX,CKMSG ; Print "CHECK" MOV CL,PRINTBUF CALL SYSTEM MOV DX,UWIN ; Output "YOU WIN" MOV CL,PRINTBUF CALL SYSTEM JP FM08 ; Jump FM04: MOV DX,CKMSG ; Print "CHECK" MOV CL,PRINTBUF CALL SYSTEM MOV DX,IWIN ; Output "I WIN" MOV CL,PRINTBUF CALL SYSTEM FM08: POP BX ; Remove return addresses POP BX MOV CL,INCHAR ; Input any char to play again CALL SYSTEM JMP DRIVER ; Jump (Rest of game init) ;*********************************************************** ; BOARD INDEX TO ASCII SQUARE NAME ;************************************************************ ; FUNCTION: -- To translate a hexadecimal index in the ; board array into an ascii description ; of the square in algebraic chess notation. ; ; CALLED BY: -- CPTRMV ; ; CALLS: -- DIVIDE ; ; ARGUMENTS: -- Board index input in register DH and the ; Ascii square name is output in register BX. ;************************************************************ BITASN: SUB AL,AL ; Get ready for division MOV DL,10 CALL DIVIDE ; Divide DEC DH ; Get rank on 1-8 basis ADD AL,60H ; Convert file to Ascii (a-h) MOV BL,AL ; Save MOV AL,DH ; Rank ADD AL,30H ; Convert rank to Ascii (1-8) MOV BH,AL ; Save RET ; Return ;*********************************************************** ; PLAYERS MOVE ANALYSIS ;*********************************************************** ; FUNCTION: -- To accept and validate the players move ; Also allows player to resign the game by ; entering R. ; ; CALLED BY: -- DRIVER ; ; CALLS: -- ASNTBI ; VALMOV ; ; ARGUMENTS: -- None ;************************************************************ PLYRMV: MOV DX,BUFFER ; Ask for input MOV CL,INBUF CALL SYSTEM MOV DX,CRLF ; Output CRLF MOV CL,PRINTBUF CALL SYSTEM MOV BX,BUFFER+1 ; Point to input length MOV AL,[BX] ; Get input length OR AL,AL ; Empty ? JZ PLYRMV ; Jump if empty MOV CH,AL ; Save length LAHF INC BX ; Point to actual buffer SAHF MOV AL,[BX] ; Get first char CMP AL,"R" ; Restart game ? JNZ PL05 ; Jump if not restart JMP DRIVER PL05: MOV AL,CH ; Get input length CMP AL,5 ; Long enough ? JC PL08 ; Jump if less than 5 chars CALL ASNTBI ; Convert "from" to a board index JC PL08 ; Jump if invalid MOV [MVEMSG],AL ; Move list "from" position CALL ATBINX ; Convert "to" to a board index JC PL08 ; Jump if invalid MOV [MVEMSG+1],AL ; Move list "to" position CALL VALMOV ; Determines if a legal move OR AL,AL ; Legal ? JZ RET ; Yes - return PL08: MOV DX,INVAL ; Output "INVALID MOVE--TRY AGAIN" MOV CL,PRINTBUF CALL SYSTEM JP PLYRMV ; Jump ;************************************************************ ; ASCII SQUARE NAME TO BOARD INDEX ;************************************************************ ; FUNCTION: -- To convert an algebraic square name in ; Ascii to a hexadecimal board index. ; This routine also checks the input for ; validity. ; ; CALLED BY: -- PLYRMV ; ; CALLS: -- None ; ; ARGUMENTS: -- Accepts the square name in pointer BX ; and outputs the board index in register AL. ; CF = 0 if ok. CF = 1 if invalid. ;************************************************************ ATBINX: INC BX ; Increment pointer to skip a char ASNTBI: MOV AL,[BX] ; Ascii file letter (a - h) INC BX SUB AL,41H ; File 1 - 8 JC RET ; Not file letter CMP AL,8 ; Check upper bound CMC JC RET ; Invalid MOV CH,AL MOV AL,[BX] SUB AL,31H ; Rank 1 - 8 JC RET CMP AL,8 ; Check upper bound CMC JC RET ADD AL,AL ; Multiply rank by 10 MOV CL,AL ADD AL,AL ADD AL,AL ADD AL,CL ADD AL,CH ; 10 * rank + file INC BX ; Increment pointer ADD AL,21 RET ; Return ;*********************************************************** ; VALIDATE MOVE SUBROUTINE ;*********************************************************** ; FUNCTION: -- To check a players move for validity. ; ; CALLED BY: -- PLYRMV ; ; CALLS: -- GENMOV ; MOVE ; INCHK ; UNMOVE ; ; ARGUMENTS: -- Returns flag in register AL, 0 for valid ; and 1 for invalid move. ;************************************************************ VALMOV: MOV BX,[MLPTRJ] ; Save last move pointer PUSH BX ; Save register MOV AL,[KOLOR] ; Computers color XOR AL,80H ; Toggle color MOV [COLOR],AL ; Store MOV BX,PLYIX-2 ; Load move list index MOV [MLPTRI],BX MOV BX,MLIST+1024 ; Next available list pointer MOV [MLNXT],BX CALL GENMOV ; Generate opponents moves MOV SI,MLIST+1024 ; Index to start of moves VA5: MOV AL,[MVEMSG] ; "From" position CMP AL,[SI+MLFRP] ; Is it in list ? JNZ VA6 ; No - jump MOV AL,[MVEMSG+1] ; "To" position CMP AL,[SI+MLTOP] ; Is it in list ? JZ VA7 ; Yes - jump VA6: MOV DL,[SI+MLPTR] ; Pointer to next list move MOV DH,[SI+MLPTR+1] XOR AL,AL ; At end of list ? CMP AL,DH JZ VA10 ; Yes - jump PUSH DX ; Move to SI register POP SI JP VA5 ; Jump VA7: MOV [MLPTRJ],SI ; Save opponents move pointer CALL MOVE ; Make move on board array CALL INCHK ; Was it a legal move ? AND AL,AL JNZ VA9 ; No - jump VA8: POP BX ; Restore saved register RET ; Return VA9: CALL UNMOVE ; Un-do move on board array VA10: MOV AL,1 ; Set flag for invalid move POP BX ; Restore saved register MOV [MLPTRJ],BX ; Save move pointer RET ; Return ;************************************************************ ; POSITIVE INTEGER DIVISION ;************************************************************ DIVIDE: PUSH CX MOV CH,8 DD04: SAL DH RCL AL SUB AL,DL JS DD05 INC DH JP DD06 DD05: ADD AL,DL DD06: DEC CH JNZ DD04 POP CX RET ;******************************************************* ; STANDARD MESSAGES ;******************************************************* CLRMSG: DB 13,10,"Choose your color (W/B): $" PLYDEP: DB 13,10,"Ply depth (1-6): $" MVEMSG: DB " ",13,10,"$" CKMSG: DB "CHECK",13,10,"$" UWIN: DB "You win",13,10,"$" IWIN: DB "I win" CRLF: DB 13,10,"$" INVAL: DB "INVALID MOVE--TRY AGAIN",13,10,"$" BUFFER: DB 7 DS 6 IX: DS 2 IY: DS 2 BC: DS 2 DE: DS 2 HL: DS 2