Files
86-DOS-0.11/Source/CHESS.A86
T

2401 lines
72 KiB
Plaintext

;***********************************************************
;
; 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