;***********************************************************************
;
; MicroChess (c) 1976 Peter Jennings, peterj@benlo.com
;
;***********************************************************************
;
; Sources:
; http://www.benlo.com - personal page of P.Jennings
; http://www.6502.org/source/games/uchess/uchess.htm - source by Daryl Rictor
; http://www.benlo.com/microchess/Kim-1Microchess.html - detailed ASM documentation
;
*=$0800 ; Loading address of all block
JMP BEGIN ; Good to start right from the beginning
banner = * ; current address
.byte "MicroChess (c) 1976 by Peter Jennings, "
.byte "RS-232 for PC by Daryl Rictor, 2002 ", $00
;
; page zero variables
; These are actual addresses, it's important
BOARD = $0850
BK = $0860
PIECE = $08B0
SQUARE = $08B1
SP2 = $08B2
SP1 = $08B3
INCHEK = $08B4
STATE = $08B5
MOVEN = $08B6
REV = $08B7
OMOVE = $08DC
WCAP0 = $08DD
COUNT = $08DE
BCAP2 = $08DE
WCAP2 = $08DF
BCAP1 = $08E0
WCAP1 = $08E1
BCAP0 = $08E2
MOB = $08E3
MAXC = $08E4
CC = $08E5
PCAP = $08E6
BMOB = $08E3
BMAXC = $08E4
BMCC = $08E5 ; was BCC (TASS doesn't like it as a label)
BMAXP = $08E6
XMAXC = $08E8
WMOB = $08EB
WMAXC = $08EC
WCC = $08ED
WMAXP = $08EE
PMOB = $08EF
PMAXC = $08F0
PCC = $08F1
PCP = $08F2
OLDKY = $08F3
BESTP = $08FB
BESTV = $08FA
BESTM = $08F9
DIS1 = $08FB
DIS2 = $08FA
DIS3 = $08F9
INPKEY = $08FC ; Input at address... Javascript modifies this byte...
*=$0850 ; To let insert empty bytes...(javascript does)
*=$0900
; BLOCK DATA
SETW = *
.byte $03, $04, $00, $07, $02, $05, $01, $06
.byte $10, $17, $11, $16, $12, $15, $14, $13
.byte $73, $74, $70, $77, $72, $75, $71, $76
.byte $60, $67, $61, $66, $62, $65, $64, $63
MOVEX = *
.byte $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1
.byte $DF, $E1, $EE, $F2, $12, $0E, $1F, $21
POINTS = *
.byte $0B, $0A, $06, $06, $04, $04, $04, $04
.byte $02, $02, $02, $02, $02, $02, $02, $02
OPNING = *
.byte $99, $25, $0B, $25, $01, $00, $33, $25
.byte $07, $36, $34, $0D, $34, $34, $0E, $52
.byte $25, $0D, $45, $35, $04, $55, $22, $06
.byte $43, $33, $0F, $CC
; THE PROGRAM STARTS HERE...
;
BEGIN LDA #$00 ;
CLD ; INITIALIZE
LDX #$FF ; TWO STACKS
TXS
LDX #$C8
STX SP2
;
; ROUTINES TO LIGHT LED
; DISPLAY AND GET KEY
; FROM KEYBOARD
;
INOUT LDA INPKEY
PHA
LDA #$00 ; CLEAR INPUT
STA INPKEY
PLA
;
CMP #$43 ; [C]
BNE NOSET ; SET UP
LDX #$1F ; BOARD
WHSET LDA SETW,X ; FROM
STA BOARD,X ; SETW
DEX
BPL WHSET
LDX #$1B ; *ADDED
STX OMOVE ; INITS TO $FF
LDA #$CC ; Display CCC
BNE CLDSP
;
NOSET CMP #$45 ; [E]
BNE NOREV ; REVERSE
JSR REVERSE ; BOARD IS
SEC
LDA #$01
SBC REV
STA REV ; TOGGLE REV FLAG
LDA #$EE ; IS
BNE CLDSP
;
NOREV CMP #$40 ; [P]
BNE NOGO ; PLAY CHESS
JSR GO
CLDSP STA DIS1 ; DISPLAY
STA DIS2 ; ACROSS
STA DIS3 ; DISPLAY
JMP exitprog
;
NOGO CMP #$0D ; [Enter]
BNE NOMV ; MOVE MAN
JSR MOVE ; AS ENTERED
JMP DISP
NOMV CMP #$41 ; [Q] ***Added to allow game exit***
BEQ DONE ; quit the game, exit back to system.
JMP INPUT ; process move
DONE JMP exitprog ; exit
;
; THE ROUTINE JANUS DIRECTS THE
; ANALYSIS BY DETERMINING WHAT
; SHOULD OCCUR AFTER EACH MOVE
; GENERATED BY GNM
;
;
;
JANUS LDX STATE
BMI NOCOUNT
;
; THIS ROUTINE COUNTS OCCURRENCES
; IT DEPENDS UPON STATE TO INDEX
; THE CORRECT COUNTERS
;
COUNTS LDA PIECE
BEQ OVER ; IF STATE=8
CPX #$08 ; DO NOT COUNT
BNE OVER ; BLK MAX CAP
CMP BMAXP ; MOVES FOR
BEQ XRT ; WHITE
;
OVER INC MOB,X ; MOBILITY
CMP #$01 ; + QUEEN
BNE NOQ ; FOR TWO
INC MOB,X
;
NOQ BVC NOCAP
LDY #$0F ; CALCULATE
LDA SQUARE ; POINTS
ELOOP CMP BK,Y ; CAPTURED
BEQ FOUN ; BY THIS
DEY ; MOVE
BPL ELOOP
FOUN LDA POINTS,Y
CMP MAXC,X
BCC LESS ; SAVE IF
PHP
PHA ;
TYA ; STY alternative
STA PCAP,X ; Emulator specific
PLA ;
PLP ;
STA MAXC,X ; STATE
;
LESS CLC
PHP ; ADD TO
ADC CC,X ; CAPTURE
STA CC,X ; COUNTS
PLP
;
NOCAP CPX #$04
BEQ ON4
BMI TREE ;(=00 ONLY)
XRT RTS
;
; GENERATE FURTHER MOVES FOR COUNT
; AND ANALYSIS
;
ON4 LDA XMAXC ; SAVE ACTUAL
STA WCAP0 ; CAPTURE
LDA #$00 ; STATE=0
STA STATE
JSR MOVE ; GENERATE
JSR REVERSE ; IMMEDIATE
JSR GNMZ ; REPLY MOVES
JSR REVERSE
;
LDA #$08 ; STATE=8
STA STATE ; GENERATE
; JSR OHM ; CONTINUATION
JSR UMOVE ; MOVES
;
JMP STRATGY ; FINAL EVALUATION
NOCOUNT CPX #$F9
BNE TREE
;
; DETERMINE IF THE KING CAN BE
; TAKEN, USED BY CHKCHK
;
LDA BK ; IS KING
CMP SQUARE ; IN CHECK?
BNE RETJ ; SET INCHEK=0
LDA #$00 ; IF IT IS
STA INCHEK
RETJ RTS
;
; IF A PIECE HAS BEEN CAPTURED BY
; A TRIAL MOVE, GENERATE REPLIES &
; EVALUATE THE EXCHANGE GAIN/LOSS
;
TREE BVC RETJ ; NO CAP
LDY #$07 ; (PIECES)
LDA SQUARE
LOOPX CMP BK,Y
BEQ FOUNX
DEY
BEQ RETJ ; (KING)
BPL LOOPX ; SAVE
FOUNX LDA POINTS,Y ; BEST CAP
CMP BCAP0,X ; AT THIS
BCC NOMAX ; LEVEL
STA BCAP0,X
NOMAX DEC STATE
LDA #$FB ; IF STATE=FB
CMP STATE ; TIME TO TURN
BEQ UPTREE ; AROUND
JSR GENRM ; GENERATE FURTHER
UPTREE INC STATE ; CAPTURES
RTS
;
; THE PLAYER'S MOVE IS INPUT
;
INPUT CMP #$08 ; NOT A LEGAL
BCS ERROR ; SQUARE #
JSR DISMV
DISP LDX #$1F
SEARCH LDA BOARD,X
CMP DIS2
BEQ HERE ; DISPLAY
DEX ; PIECE AT
BPL SEARCH ; FROM
HERE STX DIS1 ; SQUARE
STX PIECE
ERROR JMP exitprog
;
; GENERATE ALL MOVES FOR ONE
; SIDE, CALL JANUS AFTER EACH
; ONE FOR NEXT STE?
;
;
GNMZ LDX #$10 ; CLEAR
GNMX LDA #$00 ; COUNTERS
CLEAR STA COUNT,X
DEX
BPL CLEAR
;
GNM LDA #$10 ; SET UP
STA PIECE ; PIECE
NEWP DEC PIECE ; NEW PIECE
BPL NEX ; ALL DONE?
RTS ; #NAME?
;
NEX JSR RESET ; READY
LDY PIECE ; GET PIECE
LDX #$08
STX MOVEN ; COMMON START
CPY #$08 ; WHAT IS IT?
BPL PAWN ; PAWN
CPY #$06
BPL KNIGHT ; KNIGHT
CPY #$04
BPL BISHOP ; BISHOP
CPY #$01
BEQ QUEEN ; QUEEN
BPL ROOK ; ROOK
;
KING JSR SNGMV ; MUST BE KING!
BNE KING ; MOVES
BEQ NEWP ; 8 TO 1
QUEEN JSR LINE
BNE QUEEN ; MOVES
BEQ NEWP ; 8 TO 1
;
ROOK LDX #$04
STX MOVEN ; MOVES
AGNR JSR LINE ; 4 TO 1
BNE AGNR
BEQ NEWP
;
BISHOP JSR LINE
LDA MOVEN ; MOVES
CMP #$04 ; 8 TO 5
BNE BISHOP
BEQ NEWP
;
KNIGHT LDX #$10
STX MOVEN ; MOVES
AGNN JSR SNGMV ; 16 TO 9
LDA MOVEN
CMP #$08
BNE AGNN
BEQ NEWP
;
PAWN LDX #$06
STX MOVEN
P1 JSR CMOVE ; RIGHT CAP?
BVC P2
BMI P2
JSR JANUS ; YES
P2 JSR RESET
DEC MOVEN ; LEFT CAP?
LDA MOVEN
CMP #$05
BEQ P1
P3 JSR CMOVE ; AHEAD
BVS NEWP ; ILLEGAL
BMI NEWP
JSR JANUS
LDA SQUARE ; GETS TO
AND #$F0 ; 3RD RANK?
CMP #$20
BEQ P3 ; DO DOUBLE
JMP NEWP
;
; CALCULATE SINGLE STEP MOVES
; FOR K,N
;
SNGMV JSR CMOVE ; CALC MOVE
BMI ILL1 ; -IF LEGAL
JSR JANUS ; -EVALUATE
ILL1 JSR RESET
DEC MOVEN
RTS
;
; CALCULATE ALL MOVES DOWN A
; STRAIGHT LINE FOR Q,B,R
;
LINE JSR CMOVE ; CALC MOVE
BCC OVL ; NO CHK
BVC LINE ; NOCAP
OVL BMI ILL ; RETURN
PHP
JSR JANUS ; EVALUATE POSN
PLP
BVC LINE ; NOT A CAP
ILL JSR RESET ; LINE STOPPED
DEC MOVEN ; NEXT DIR
RTS
;
; EXCHANGE SIDES FOR REPLY
; ANALYSIS
;
REVERSE LDX #$0F
ETC SEC
LDY BK,X ; SUBTRACT
LDA #$77 ; POSITION
SBC BOARD,X ; FROM 77
STA BK,X
PHP
PHA ; STY BOARD,X
TYA ; alternative
STA BOARD,X ; Emulator specific
PLA ;
PLP
SEC
LDA #$77 ; EXCHANGE
SBC BOARD,X ; PIECES
STA BOARD,X
DEX
BPL ETC
RTS
;
; CMOVE CALCULATES THE TO SQUARE
; USING SQUARE AND THE MOVE
; TABLE FLAGS SET AS FOLLOWS:
; N#NAME? MOVE
; V#NAME? (LEGAL UNLESS IN CR)
; C#NAME? BECAUSE OF CHECK
; [MY &THANKS TO JIM BUTTERFIELD
; WHO WROTE THIS MORE EFFICIENT
; VERSION OF CMOVE)
;
CMOVE LDA SQUARE ; GET SQUARE
LDX MOVEN ; MOVE POINTER
CLC
ADC MOVEX,X ; MOVE LIST
STA SQUARE ; NEW POS'N
AND #$88
BNE ILLEGAL ; OFF BOARD
LDA SQUARE
;
LDX #$20
LOOP DEX ; IS TO
BMI NO ; SQUARE
CMP BOARD,X ; OCCUPIED?
BNE LOOP
;
CPX #$10 ; BY SELF?
BMI ILLEGAL
;
LDA #$FF ; MUST BE CAP! ORIGINALLY $7F, emulator doesnt set overflow flag
ADC #$01 ; SET V FLAG
BVS SPX ; (JMP)
;
NO CLV ; NO CAPTURE
;
SPX LDA STATE ; SHOULD WE
BMI RETL ; DO THE
CMP #$08 ; CHECK CHECK?
BPL RETL
;
; CHKCHK REVERSES SIDES
; AND LOOKS FOR A KING
; CAPTURE TO INDICATE
; ILLEGAL MOVE BECAUSE OF
; CHECK SINCE THIS IS
; TIME CONSUMING, IT IS NOT
; ALWAYS DONE
;
CHKCHK PHA ; STATE #392
PHP
LDA #$F9
STA STATE ; GENERATE
STA INCHEK ; ALL REPLY
JSR MOVE ; MOVES TO
JSR REVERSE ; SEE IF KING
JSR GNM ; IS IN
JSR RUM ; CHECK
PLP
PLA
STA STATE
LDA INCHEK
BMI RETL ; NO - SAFE
SEC ; YES - IN CHK
LDA #$FF
RTS
;
RETL CLC ; LEGAL
LDA #$00 ; RETURN
RTS
;
ILLEGAL LDA #$FF
CLC ; ILLEGAL
CLV ; RETURN
RTS
;
; REPLACE PIECE ON CORRECT SQUARE
;
RESET LDX PIECE ; GET LOGAT
LDA BOARD,X ; FOR PIECE
STA SQUARE ; FROM BOARD
RTS
;
;
;
GENRM JSR MOVE ; MAKE MOVE
GENR2 JSR REVERSE ; REVERSE BOARD
JSR GNM ; GENERATE MOVES
RUM JSR REVERSE ; REVERSE BACK
;
; ROUTINE TO UNMAKE A MOVE MADE BY
; MOVE
;
UMOVE TSX ; UNMAKE MOVE
STX SP1
LDX SP2 ; EXCHANGE
TXS ; STACKS
PLA ; MOVEN
STA MOVEN
PLA ; CAPTURED
STA PIECE ; PIECE
TAX
PLA ; FROM SQUARE
STA BOARD,X
PLA ; PIECE
TAX
PLA ; TO SOUARE
STA SQUARE
STA BOARD,X
JMP STRV
;
; THIS ROUTINE MOVES PIECE
; TO SQUARE, PARAMETERS
; ARE SAVED IN A STACK TO UNMAKE
; THE MOVE LATER
;
MOVE TSX
STX SP1 ; SWITCH
LDX SP2 ; STACKS
TXS
LDA SQUARE
PHA ; TO SQUARE
TAY
LDX #$1F
CHECK CMP BOARD,X ; CHECK FOR
BEQ TAKE ; CAPTURE
DEX
BPL CHECK
TAKE LDA #$CC
STA BOARD,X
TXA ; CAPTURED
PHA ; PIECE
LDX PIECE
LDA BOARD,X
PHP ; FROM
PHA ; STY BOARD,X
TYA ; alternative
STA BOARD,X ; Emulator specific
PLA ;
PLP
PHA ; SQUARE
TXA
PHA ; PIECE
LDA MOVEN
PHA ; MOVEN
STRV TSX
STX SP2 ; SWITCH
LDX SP1 ; STACKS
TXS ; BACK
RTS
;
; CONTINUATION OF SUB STRATGY
; -CHECKS FOR CHECK OR CHECKMATE
; AND ASSIGNS VALUE TO MOVE
;
CKMATE LDY BMAXC ; CAN BLK CAP
CPX POINTS ; MY KING?
BNE NOCHEK
LDA #$00 ; GULP!
BEQ RETV ; DUMB MOVE!
;
NOCHEK LDX BMOB ; IS BLACK
BNE RETV ; UNABLE TO
LDX WMAXP ; MOVE AND
BNE RETV ; KING IN CH?
LDA #$FF ; YES! MATE
;
RETV LDX #$04 ; RESTORE
STX STATE ; STATE=4
;
; THE VALUE OF THE MOVE (IN ACCU)
; IS COMPARED TO THE BEST MOVE AND
; REPLACES IT IF IT IS BETTER
;
PUSH CMP BESTV ; IS THIS BEST
BCC RETP ; MOVE SO FAR?
BEQ RETP
STA BESTV ; YES!
LDA PIECE ; SAVE IT
STA BESTP
LDA SQUARE
STA BESTM ; FLASH DISPLAY
RETP RTS ; print; actually do nothing & return
;
; MAIN PROGRAM TO PLAY CHESS
; PLAY FROM OPENING OR THINK
;
GO LDX OMOVE ; OPENING?
BMI NOOPEN ; -NO *ADD CHANGE FROM BPL
LDA DIS3 ; -YES WAS
CMP OPNING,X ; OPPONENT'S
BNE END ; MOVE OK?
DEX
LDA OPNING,X ; GET NEXT
STA DIS1 ; CANNED
DEX ; OPENING MOVE
LDA OPNING,X
STA DIS3 ; DISPLAY IT
DEX
STX OMOVE ; MOVE IT
BNE MV2 ; (JMP)
;
END LDA #$FF ; *ADD - STOP CANNED MOVES
STA OMOVE ; FLAG OPENING
NOOPEN LDX #$0C ; FINISHED
STX STATE ; STATE=C
STX BESTV ; CLEAR BESTV
LDX #$14 ; GENERATE P
JSR GNMX ; MOVES
;
LDX #$04 ; STATE=4
STX STATE ; GENERATE AND
JSR GNMZ ; TEST AVAILABLE
;
; MOVES
;
LDX BESTV ; GET BEST MOVE
CPX #$0F ; IF NONE
BCC MATE ; OH OH!
;
MV2 LDX BESTP ; MOVE
LDA BOARD,X ; THE
STA BESTV ; BEST
STX PIECE ; MOVE
LDA BESTM
STA SQUARE ; AND DISPLAY
JSR MOVE ; IT
JMP exitprog
;
MATE LDA #$FF ; RESIGN
RTS ; OR STALEMATE
;
; SUBROUTINE TO ENTER THE
; PLAYER'S MOVE
;
DISMV LDX #$04 ; ROTATE
DROL ASL DIS3 ; KEY
ROL DIS2 ; INTO
DEX ; DISPLAY
BNE DROL ;
ORA DIS3
STA DIS3
STA SQUARE
RTS
;
; THE FOLLOWING SUBROUTINE ASSIGNS
; A VALUE TO THE MOVE UNDER
; CONSIDERATION AND RETURNS IT IN
; THE ACCUMULATOR
;
STRATGY CLC
LDA #$80
ADC WMOB ; PARAMETERS
ADC WMAXC ; WITH WHEIGHT
ADC WCC ; OF O25
ADC WCAP1
ADC WCAP2
SEC
SBC PMAXC
SBC PCC
SBC BCAP0
SBC BCAP1
SBC BCAP2
SBC PMOB
SBC BMOB
BCS POS ; UNDERFLOW
LDA #$00 ; PREVENTION
POS LSR A
CLC ; **************
ADC #$40
ADC WMAXC ; PARAMETERS
ADC WCC ; WITH WEIGHT
SEC ; OF 05
SBC BMAXC
LSR A ; **************
CLC
ADC #$90
ADC WCAP0 ; PARAMETERS
ADC WCAP0 ; WITH WEIGHT
ADC WCAP0 ; OF 10
ADC WCAP0
ADC WCAP1
SEC ; [UNDER OR OVER-
SBC BMAXC ; FLOW MAY OCCUR
SBC BMAXC ; FROM THIS
SBC BMCC ; SECTION]
SBC BMCC
SBC BCAP1
LDX SQUARE ; ***************
CPX #$33
BEQ POSN ; POSITION
CPX #$34 ; BONUS FOR
BEQ POSN ; MOVE TO
CPX #$22 ; CENTRE
BEQ POSN ; OR
CPX #$25 ; OUT OF
BEQ POSN ; BACK RANK
LDX PIECE
BEQ NOPOSN
LDY BOARD,X
CPY #$10
BPL NOPOSN
POSN CLC
ADC #$02
NOPOSN JMP CKMATE ; CONTINUE
exitprog LDA #$50 ; indicate to javascript
STA STATE ; that process is over
JMP $FFFF ; break and stop the emulator
;
;
; end of file
;
; This version is for http://e-tradition.net/bytes/6502/assembler.html
; javascript based 6502 emulator.