Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- x86 equ 1 ; x86=1 PC/emu vs. win32b/(DOS)Box
- saf equ 0 ; saf=0 +queening -exotic failsafe
- _b equ byte ; DEFAULTS=PC FLOPPY BOOT+QUEENING
- _w equ word ; x86=1 saf=0 512b inc. queening
- _d equ dword ; x86=1 saf=1 500b+ excl. queening*
- _s equ short ; x86=0 saf=1 506b inc. queening
- _n equ near ; x86=0 saf=0 487b excl. queening
- _f equ far ; *only working version in Bochs
- if x86 ; beg of boot vs .com preprocessing
- org 7c00h ; std start of bootsector after post
- if saf ; beg clear any start ambiguous segment
- jmp _f 0:fix ; 7c0:0000 vs. 0:7c000 cs para fix-up
- end if ; end clear any start ambiguous segment
- fix:push cs ; if post int 19h isr bootsrap loader
- pop ds ; left any bda or shadow segment values
- push cs ; then enforce ds=cs=0
- pop es ; then enforce es=ds=cs=0
- mov aX,13h ; function set vga mode 320x200x256
- else ; else if 16-bit binary assume ah=0
- org 100h ; start of com binary program ip
- mov aL,13h ; function set vga mode 320x200x256
- end if ; end of boot vs .com preprocessing
- int 10h ; standard bios video api
- brd equ bf1+16 ; chess board at end of sector
- mov di,brd ; set physical board index
- mov bp,12 ; set 6x8+8 empty sqr mid board lines
- call in2 ; pass#1 black "rnbqkbnr" low-caps
- push word opn ; pass#2 hi-caps whites & fall-through
- rle:lodsb ; al='.'/al=null (fixed length rle)
- mov cl,8 ; empty sqr mid board line length
- rep stosb ; set one empty sqr mid board line
- dec bp ; all empty sqr mid brd lines inited ?
- jnz rle ; if not repeat init else bp=0 assumed
- mov ah,'A'-'a' ; fall-through pass#2 white hi-caps
- in2:mov si,br0 ; si points to endrank "rnbqkbnr" str
- if x86=0 ; if .com binary environment ch=0
- mov cL,8 ; "rnbqkbnr" endrank str length
- else ; assume nothing although tempting
- mov cX,8 ; "rnbqkbnr" endrank str length
- end if ; end of register ch startup value
- in3:lodsb ; read physical board str car
- add al,ah ; hi-caps rank 1 / low-caps rank 8
- stosb ; write physical board str car
- loop in3 ; all "rnbqkbnr" str car written ?
- mov cl,8 ; si-;equiv piece vals di-;0x88 brd
- rep movsb ; write logical 0x88 board str vals
- retn ; return to callers
- ge0:mov bx,di ; physical board idx (bx=brd)
- mov dh,'1' ; beg white move src rank
- ge1:mov dl,'h' ; beg white move src file
- ge2:mov [si],dx ; beg white move src str
- mov ch,'1' ; beg white move dst rank
- ge3:mov cl,'h' ; beg white move dst file
- ge4:mov [si+2],cx ; beg white move dst str
- pusha ; save all values
- call idx ; passive chess coords to linear indexes
- jbe mis ; white move src color not conforming
- push bx ; save white move dst idx
- call ver ; white move legal chess ?
- pop bx ; restore white move dst idx
- jc mis ; white move not legal chess
- mov di,num+3 ; compare move destination rank in 7dfeh
- inc si ; with move source rank in 7dfch
- cmpsb ; is taxi distance to topmost bettered ?
- jnc wor ; else not getting closer to black king
- cmp _b [di],'?' ; does any fallback move exist yet ?
- jz lkj ; no, then last valid move good enough
- wor:mov aL,_b[si+bx+brd-num-'a'+6]; yes, previous valid legal exist so
- dec aL ; only override if it's a capture
- js mis ; no, don't want worse taxi distance
- mov bx,fs ; it's a capture with piece value=al
- cmp bL,aL ; but hightest capture value yet ?
- jnc mis ; no, less important opponent piece
- max:mov fs,bx ; fs=best move yet in taxi half-ply
- lkj:dec si ; realign source index
- dec si ; to copy dword bst=dword idx
- movsd ; after 4096 tries : move=dword bst
- mis:popa ; restore all values
- cmp cl,'a' ; end white move dst file ?
- loopnz ge4 ; dec white move else next dst file
- inc ch ; inc white move dst rank
- cmp ch,'9' ; end white move dst rank ?
- jnz ge3 ; else next move dst rank
- cpx:inc bx ; inc physical board index
- dec dx ; dec white move src file
- cmp dl,'`' ; end white move src file ?
- jnz ge2 ; else next move src file
- inc dh ; inc white move src rank
- cmp dh,ch ; end white move src rank ? ch=9
- jnz ge1 ; else next move src rank
- push _d [si+4] ; get best white move found
- pop _d [si] ; set it as final white move
- val:mov cl,'.' ; valid : empty sqr replaces src piece
- call act ; active chess coords to linear indexes
- xor bp,3 ; player turn and pawn unidir. delta
- jz ge0 ; white turn to play (case best=0)
- bla:mov al,'?' ; input str clear pattern
- mov di,si ; input str clear pattern (di=num)
- mov cx,8 ; input str clear pattern
- rep stosb ; input str clear pattern (di=brd)
- call key ; get user keyboard input
- jbe bla ; black move src color not conforming
- opn:call ver ; di=brd, black move legal chess ?
- jc bla ; white move not legal chess
- jmp _s val ; validate black move
- ver:call idx ; get lin indexes /w implicit passive
- xchg bx,dx ; switch bx=dst idx dx=src idx
- mov ah,[si+bx+brd-num-'a'+8] ; get piece logical 0x88 brd val...
- mov dh,bl ; dh=src idx dl=dst idx
- sub dx,"aa" ; get move file zero-based indexes
- bsr bx,ax ; scan for 1st bit set (si=idx+10)
- movsx bx,[si+bx-10-num+tab] ; bl=moved piece type idx (bh=0)
- mov cx,_w [si+bx-num+tab] ; piece type deltas cl=repeats ch=num
- sahf ; set piece logical 0x88 brd val
- jnp sp1 ; branch if piece not pawn (bit#4!=1)
- jc sp2 ; branch if pawn prev moved (bit#0=1)
- sp1:jns sp3 ; branch if piece not king (bit#7!=1)
- sp2:mov cl,1 ; override repeat if piece pawn or king
- sp3:jnp sp4 ; branch if piece not pawn (bit#4!=1)
- add bx,bp ; pawn player turn unidirection mutex
- sp4:inc bx ; advance piece type struct field ptr
- and ah,11111100b ; isolate piece bitmask only
- vl1:push cx ; save piece type deltas
- mov al,dh ; load start dst idx val
- inc bx ; advance piece type struct field ptr
- vl2:add al,[si+bx-num+tab] ; add this piece delta to dst idx val
- xchg aL,bL ; base reg=dst idx val and preserved
- mov ch,[si+bx+brd-num+8] ; read projected dst square val
- xchg aL,bL ; base reg=piece type struct field ptr
- cmp al,dl ; wanted move found (src+delta(s)=dst) ?
- jnz dif ; different than requested move
- sam:sahf ; get piece logical 0x88 brd val in flgs
- jnp yes ; branch if piece is not pawn (bit#2=0)
- test [si+bx-num+tab],1 ; pawn piece delta parity=diag vs. vert
- jz ord ; branch if pawn piece moving vert
- test ch,ch ; pawn piece vert move=;eating ?
- jnz yes ; capturing verify dst sqr not empty
- jmp _s bad ; else illegal chess move is a miss
- ord:test ch,ch ; pawn piece vert move=;no eating ?
- jz yes ; no eating=;empty dst sqr else illegal
- dif:sahf ; store piece nature in flags register
- jnp skp ; not pawn piece so skip direction test
- test [si+bx-num+tab],1 ; pawn piece delta parity=diag vs. vert
- jnz bad ; diagonal pawn move is illegal
- skp:test ch,ch ; else skipping over dst square val ?
- jnz bad ; projected dst sqr val is not empty
- sahf ; get piece logical 0x88 brd val in flgs
- jz x88 ; branch if piece is queen (bit#6=1)
- jna bad ; branch if piece is not knight(bit#4=0)
- x88:test al,88h ; ch=0 dst out of physical board limits?
- loopz vl2 ; else cont if delta repeats remain
- bad:pop cx ; restore piece type deltas
- dec ch ; all possible delta nums verified ?
- jnz vl1 ; if not then cont next delta type
- nok:stc ; else return /w no match flg set
- retn ; return to caller
- yes:pop cx ; correct entry sp and disregard count
- retn ; return to caller(s)
- key:call prt ; refresh screen to account input echo
- xor bx,bx ; bx=str idx=odd/even/alpha/num mutex
- kbd:cbw ; fun blocking wait for keystroke (ah=0)
- int 16h ; std bios keybd api (ah=scan al=ascii)
- esc:dec ah ; was esc key pressed to quit ?
- jnz car ; else default process key input
- xit:if x86 ; if x86 boot context environment
- int 19h ; exit through bootstrap to reboot cpu
- else ; else if .com 16-bit binary
- int 20h ; dos 1+ - terminate program
- end if ; end of exit methods (os load or shell)
- car:mov [bx+si],al ; sav ascii val to move string (si=num)
- prt:pusha ; save game state snapshot
- cwd ; curs location dx=(0,0)=(row,column)
- mov ax,1301h ; function ega write str write mode 1
- mov bl,7 ; page 0 grey car attrib matching tty
- mov cl,8 ; src str lngth (curs updated horiz)
- mov bp,bf1 ; es:bp is "abcdefgh" ptr
- lns:int 10h ; standard bios video api
- add bp,16 ; bp=para step siz separating strings
- push ax ; save old bios video api func params
- mov ax,0e39h ; function teletype outp car=rank '9'
- sub al,dh ; decrement right handside rank value
- int 10h ; standard bios video api
- pop ax ; restore old bios video api fx params
- cmp dh,cl ; src str total (curs updated vert)
- inc dh ; preemptive off-by-one allows 9 verts
- jc lns ; all 9 brd gui row strings printed ?
- mov bp,si ; 10th row tail bp=move coords, cl=8
- int 10h ; standard bios video api
- popa ; restore game state snapshot
- inc bx ; test if any more keys ?
- cmp bl,4 ; frFR format input string
- jc kbd ; else continue input
- idx:loop idx ; ch=0 passive call load src/dst lin idx
- act:mov si,num ; reinit si to point to coord input str.
- mov bx,[si] ; bx=src coord (pass#1)
- cbw ; empty sqr val in logical 0x88 board
- call put ; place param passed as fun pass#1
- mov dx,[si+2] ; bx=dst idx dx=src idx
- xchg bx,dx ; fall-through for second pass
- push word mat ; test for checkmate and conforming
- put:xchg ax,bx ; bx|dx=[num+di]+16*((8-'0')-[num+di+1])
- aad -10h ; shl ah,4/sub al,ah/xor ah,ah
- add al,80h ; bx|dx=al-640%256-16*ah
- xchg ax,bx ; bx|dx=al+128-16*ah
- jcxz sim ; active call request or simulation ?
- if saf=0 ; standard non-failsafe queening
- cmp _b [si+3],'8' ; validated dst rank is top-most ?
- jz qq ; if so then promote pawn to queen
- cmp _b [si+3],'1' ; validated dst rank is bottom-most ?
- jnz prm ; if not no pawn queening promotion
- qq: sahf ; store piece nature in flag register
- jnp prm ; no pawn queening promotion
- xor ah,01000110b ; transform p to promoted queen
- inc cx ; queen promotion p2q or P2Q
- end if ; end of conditional queening
- prm:xchg ah,[si+bx+brd-num-'a'+8] ; update piece logical 0x88 board val
- xchg cl,[si+bx+brd-num-'a'] ; update piece physical board ascii val
- or ah,1 ; update piece moved once (bit#0)
- sim:retn ; return to caller(s)
- mat:sahf ; catured piece king and mate ?
- js xit ; if piece is king then game is over
- call chk ; move src color conforming ?
- jnz nok ; move src color not conforming
- chk:xchg bx,dx ; src idx <- dst idx
- mov al,[si+bx+brd-num-'a'] ; pass#1:src idx pass#2:dst idx di=brd
- xor _b [si+len-num],8 ; self-modif 8/26 val=[1;8]/[a(A);z(Z)]
- mov cl,-'a' ; assert black piece car interval
- test bp,bp ; test whose turn it is to play
- jnz lim ; assert white piece car interval
- mov cl,-'A' ; al=ascii value cl=-(lower boundery)
- lim:xadd al,cl ; tmp=al+cl cl=al al=tmp +fall-trough
- db 0d4h ; aam <self-modified value>
- len:db 12h ; ah=al/8 al%=8
- mov al,cl ; al=restored ascii value
- test ah,ah ; set/clear zf=0 success zf=1 failure
- retn ; return to caller(s) nb: destroys ah
- tab db p-tab,r-tab,n-tab,b-tab ; piece type mov offset array
- db q-tab,q-tab ; note original 1K ZX Chess q=k trick
- br0 db "rnbqkbnr",8,16,32,64,128 ; end rank pattern + beg piece values
- db 32,16,8,'p',4,'.',0,'.',0 ; end piece values + beg mid board reps
- db '.',0,'.',0,'P',4 ; ... end mid board reps
- p db 2,3,-10h,-15,-17,10h,15 ; bit#2 pf=04 p[6]=r[0] overlay
- r db 17,4,10h,-1h,-10h ; bit#3 ??=08 r[5]=n[0] overlay
- n db 1,8,1fh,21h,12h,-0eh,-1fh ; bit#4 af=16 n[9]=b[0] overlay
- db -21h,-12h ; ... end of knight moves list
- b db 0eh,4,-0fh,11h,-11h ; bit#5 ??=32 b[5]=q[0] overlay
- q db 0fh,8,10h,11h,0fh,1h,-10h ; bit#6 zf=64 k=q except k[0]=1
- db -11h,-0fh,-1h ; ... end of queen/king moves list
- bf1 db "abcdefgh" ; gui file index string
- num db "e2e4" ; hardcoded Ruy Lopez opening
- if saf and x86 ; x86 failsafe exotic boot environment
- times 510-($-$$) db 0 ; nul padding if necessary
- org 7df0h ; boot signature vbr/mbr standard offset
- sig db 55h,0aah ; magic number no-endian boot signature
- end if ; end of conditional failsafe signature
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement