; THE GAME OF DEFLECTION BY ANDREW A. RECUPERO ; FROM KILOBAUD FEB '78 #14 ; ; TO START TYPE 0,1,2,3 ; 0=1 TARGET, CLEAR FIELD ; 1=1 TARGET, SHIFT DEFLECTORS ; 2=3 TARGETS, CLEAR FIELD ; 3=3 TARGETS, SHIFT DEFLECTORS ; ; THE OBJECT OF THE GAME IS TO HIT TARGET(S) BY ; DEFLECTING THE RUNNER INTO THE TARGET. ; ; DEFLECT TARGET BY TYPING A "/" OR A "\". ; ; ALL TARGETS MUST BE HIT WITHIN A FIXED TIME. ; ;SYSTEM EQUATES: ; ORG 100H ;STATUS EQU 00 ;KEYBOARD STATUS PORT ;STROBE EQU 80H ;KEYBOARD STROBE BIT ;DATA EQU 1 ;KEYBOARD DATA PORT STATUS EQU 0FAH ;KEYBOARD STATUS PORT -- SOL STROBE EQU 01H ;KEYBOARD STROBE BIT -- SOL DATA EQU 0FCH ;KEYBOARD DATA PORT -- SOL VDMRAM EQU 0CC00H ;VDM STARTING ADDR. VDMPAGE EQU 0CCH ;VDM RAM PAGE ;VDMPORT EQU 0C8H ;VDM PORT VDMPORT EQU 0FEH ;VDM PORT TARGET EQU 05 ;TARGET SYMBOL RUNNER EQU 07 ;RUNNER SYMBOL USLSH EQU 2FH ;UP SLASH SYMBOL "/" DSLSH EQU 5CH ;DOWN SLASH SYMBOL "\" LEFT EQU 80H ;RUNNER DOWN EQU 40H ; DIRECTION UP EQU 20H ; CONTROL RIGHT EQU 10H ; EQUATES ; ; ; PROGRAM START ; GSTART LXI SP,STACK+8 ;INITIALIZE STACK CALL CLSCRN ;CLEAR SCREEN REIDLE CALL DRUNER ;DISPLAY RUNNER IDLE CALL ACTION ;MOVE RUNNER CALL DELAY ;TIME DELAY AND CHECK INPUT MOV A,C ;KEYBOARD INPUT TO ACC. ORA A ;TEST FOR NON-ZERO JZ IDLE MVI M,20H ;REMOVE RUNNER RRC ;SHIFT DEFLECTORS? PUSH PSW ;SAVE GAME OPTION IN 'A' REG JC SHIFT ;JUMP TO SHIFT IF YES CALL CLSCRN ;DO NOT SHIFT, CLEAR SCREEN JMP INIT SHIFT LXI B,VDMRAM ;SHIFT MOV D,B ; SCREEN MOV E,C ; ONE INX D ; POSITION SMOR LDAX D ; TO STAX B ; THE INX B ; LEFT INX D MOV A,D CPI VDMPAGE+4 JNZ SMOR ;GO SHIFT MORE IF NOT DONE INIT POP PSW ;RESTORE GAME OPTION TO 'A' REG MVI C,1 ;SET FOR ONE TARGET RRC ;GAME OPTION BIT 0 TO CARRY FLG MVI A,TARGET ;TARGET SYMBOL TO 'A' REG JNC GAM1 ;JUMP FOR 1 TARGET OPTION MVI C,3 ;INITIALIZE FOR 3 TARGETS STA VDMRAM+34CH ;PUT TARGET LEFT OF CENTER STA VDMRAM+2F4H ;TARGET TO THE RIGHT GAM1 STA VDMRAM+320H ;TARGET IN THE MIDDLE MOV A,C STA TARNUM ;STORE # OF TARGETS LXI H,1C0H ;INITIALIZE GAME TIMER SHLD TIMER ;SAVE TIMER VALUE CALL DRUNER ;START GAME, DISPLAY RUNNER ; ; ; THIS IS THE MAIN LOOP FOR THE GAME ; MAINLP CALL DELAY ;WAIT & CHECK KEYBOARD CALL ACTION PUSH H ;SAVE HL LHLD TIMER ;GET GAME TIMER DCX H ;DECREMENT TIMER MOV A,H ;CHECK IF GAME ORA L ; TIMER EXPIRED SHLD TIMER ;STORE UPDATED TIMER POP H ;RESTORE HL JNZ MAINLP ;JMP IF TIMER DIDN'T EXPIRE LXI B,LOSE ;DISPLAY NO CALL SHOW ; TIME MESSAGE CALL WAER ;WAIT & ERASE MESSAGE JMP GSTART ;TIMER EXPIRED, RESTART GAME ; ; ; INITIALIZE AND DISPLAY RUNNER ; 'B' HOLDS MOTION DIRECTION AS: ; REG BIT 7 6 5 4 ; | | | | ; | | | RIGHT ; | | UP ; | DOWN ; LEFT ; DRUNER LXI H,VDMRAM+40H ;RUNNER STARTING POS. LXI D,100H ;X,Y RUNNER POS. D=VERT E=HORZ MVI M,RUNNER ;DISPLAY RUNNER MVI B,RIGHT ;INITIALIZE RIGHT MOTION RET ; ; ; ALL RUNNER MOVEMENT DONE HERE ; ACTION MOV A,M ;CHECK IF CPI RUNNER ; RUNNER JNZ DF010 ; DISPLAYED MVI M,20H ;REMOVE RUNNER FROM FIELD ; ; CALCULATE NEW RUNNER POSITION ; DF010 MOV A,B CPI RIGHT ;IS MOTION TO RIGHT? JNZ DF012 ;JUMP IF NO INR E ;MOVE 1 POS TO THE RIGHT DF012 CPI UP ;IS MOTION UP? JNZ DF014 ;JUMP IF NO DCR D ;MOVE 1 POS UP DF014 CPI DOWN ;IS MOTION DOWN? JNZ DF016 ;JUMP IF NO INR D ;MOVE 1 POS DOWN DF016 CPI LEFT ;IS MOTION TO THE LEFT? JNZ DF018 ;JUMP IF NO DCR E ;MOVE 1 POS TO LEFT ; ; CALCULATE FIELD POSITION FROM HORZ AND VERT VALUES ; IN DE WITH RESULT IN HL ; DF018 MOV A,D RRC RRC MOV L,A ANI 03 ORI VDMPAGE MOV H,A ;SAVE HIGH PART OF ADDR. MOV A,L ANI 0C0H ADD E MOV L,A ;SAVE LOW PART OF ADDR. MOV A,M ;CHECK NEXT FIELD POSITION CPI TARGET ;IS IT A TARGET? JNZ DF019 ;JUMP IF DIDN'T HIT TARGET ; ; HIT A TARGET ; MVI M,20H ;REMOVE TARGET LDA TARNUM ;GET # OF TARGETS LEFT DCR A ;REDUCE BY ONE STA TARNUM ;STORE UPDATED TARGET NUMBER RNZ ;RETURN IF MORE TARGETS POP D ;ALL TARGETS GONE, FIX STACK LXI B,WIN ;DISPLAY CALL SHOW ; WIN MESSAGE CALL WAER ;WAIT & ERASE MESSAGE JMP REIDLE ;GO TO IDLE LOOP ; DF019 MOV A,C ;PUT KEYBOARD DATA IN 'A' REG CPI USLSH ;IS IT AN UPSLASH "/" ? JZ DF020 ;JUMP IF YES CPI DSLSH ;IS IT A DOWNSLASH "\" ? JZ DF020 ;JUMP TO ANALYZE DEFLECTOR ; ; CHECK FOR RUNNER HITTING A DEFLECTOR ; DELCK MOV A,M CPI 20H ;IS NEXT POSITION A SPACE? JNZ CHGMOT ;DEFLECTOR IF NO, CHNGE DIR CALL EDGCK ;REVERSE MOTION IF AT EDGE MVI M,RUNNER ;DISPLAY RUNNER AT NEW LOCATION RET DF020 MOV M,A ;INPUT WAS VALID, DISPLAY IT ; ; CHANGE DIRECTION OF RUNNER MOTION ; CHGMOT CPI DSLSH ;IS IT A DOWNSLASH? MOV A,B ;DIRECTION FLAG TO 'A' REG JNZ UPSLH ;JUMP IF NOT DOWN SLASH ANI 0C0H ;IS MOTION LEFT OR DOWN? MOV A,B ;RESTORE DIRECTION FLAG TO 'A' JZ DF030 ;JUMP IF NOT LEFT OR DOWN RRC ;CHANGE DIRECTION TO RRC ; RIGHT OR UP JMP DF050 DF030 RLC ;CHANGE DIRECTION TO RLC ; LEFT OR DOWN JMP DF050 UPSLH ANI 0A0H ;IS MOTION TO LEFT OR UP? MOV A,B ;DIRECTION FLAG TO 'A' REG JZ DF040 ;JUMP IF NOT LEFT OR UP RRC ;CHANGE DIR TO RIGHT OR DOWN JMP DF050 DF040 RLC ;CHANGE MOTION TO RIGHT OR DOWN DF050 MOV B,A ;SAVE NEW DIRECTION CALL EDGCK ;IS RUNNER AT EDGE OF FIELD? MOV A,M ;GET DEFLECTOR IN CASE AT EDGE JZ CHGMOT ;IF AT EDGE, CHANGE DIRECTION RET ; ; THIS ROUTINE CHECKS FOR EDGE OF FIELD, REVERSES MOTION, ; SETS ZERO FLAG IF AT EDGE ; EDGCK MOV A,B ;LOAD MOTION DETECTOR CPI RIGHT ;TO RIGHT? JNZ DF060 ;JUMP IF NO MVI A,3FH ;3FH=RIGHT EDGE CMP E RNZ ;RETURN IF NOT AT RIGHT EDGE MVI B,LEFT ;REVERSE DIRECTION TO LEFT RET DF060 CPI UP ;CHECK FOR UP MOTION JNZ DF070 ;JUMP IF MOTION NOT UP XRA A ORA D ;CHECK FOR TOP VERT=0 RNZ ;RETURN IF NOT AT TOP MVI B,DOWN ;REVERSE DIRECTION TO DOWN RET DF070 CPI DOWN ;CHECK FOR DOWN MOTION JNZ DF080 ;JUMP IF MOTION NOT DOWN MVI A,0FH ;CHECK FOR BOTTOM VERT=0FH CMP D RNZ ;RETURN IF NOT AT BOTTOM MVI B,UP ;REVERSE DIRECTION TO UP RET DF080 XRA A ;MUST BE MOTION TO LEFT ORA E ;CHECK FOR LEFT EDGE HORZ=0 RNZ ;RETURN IF NOT AT LEFT EDGE MVI B,RIGHT ;REVERSE DIRECTION TO RIGHT RET ; ; THIS ROUTINE PERFORMES TIME DELAY WHILE CONTINUOUSLY ; CHECKING FOR KEYBOARD INPUT. INPUT RETURN IN 'C' ; DELAY MVI C,0 ;INITIALIZE INPUT SAVE REG PUSH D ;FREE UP DE REG LXI D,700H ;LOAD DELAY VALUE DL01 DCX D ;DECREMENT DELAY COUNTER IN STATUS ;GET KEYBOARD STATUS ANI STROBE ;CHECK STROBE JNZ DL02 ;JUMP IF NO INPUT IN DATA ;GET KEYBOARD DATA ANI 7FH ;REMOVE BIT 7 MOV C,A ;SAVE INPUT IN 'C' REG DL02 MOV A,D ;CHECK FOR ORA E ; TIMER=0 JNZ DL01 POP D ;DELAY OVER, RESTORE DE REG RET ; ; THIS ROUTINE INITIALIZES THE VDM PORT & CLEARS SCREEN ; CLSCRN XRA A ;CLEAR VDM PORT OUT VDMPORT ;OUTPUT IT LXI H,VDMRAM ;POINT TO START OF VDM RAM MVI A,VDMPAGE+4 ;'A' REG=END OF VDM RAM CL01 MVI M,20H ;BLANK LOC GIVEN BY HL INX H CMP H ;DONE? JNZ CL01 ;JUMP IF NOT RET ; ; THIS ROUTINE DISPLAYS MESSAGE POINTED TO BY BC REG ; SHOW LXI D,VDMRAM+31DH ;POINT TO DISPLAY LOCATION MVI H,7 ;MESSAGE LENGTH=7 SH01 LDAX B ;GET BYTE OF MESSAGE STAX D ;DISPLAY IT INX D ;BUMP TO INX B ; NEXT BYTE DCR H ;DECREMENT COUNT JNZ SH01 ;DONE? RET ; ; THIS ROUTINE WAITS AWHILE AND THEN REMOVES MESSAGE ; WAER MVI D,32 ;LOAD UNITS OF DELAY WDLY CALL DELAY ;WAIT ONE UNIT OF DELAY DCR D ;CHECK IF JNZ WDLY ; DONE WAITING LXI B,BLNK ;POINT TO ALL BLANKS JMP SHOW ;DISPLAY BLANKS TO ERASE & RET ; ; MESSAGES ; WIN DB 'WINNER ' LOSE DB 'NO TIME' BLNK DB ' ' ; ; SAVE AREAS AND STACK ; TIMER DS 2 ;TIMER SAVE AREA TARNUM DS 1 ;NUMBER OF TARGETS STACK DS 8 ;STACK AREA (ONLY 4 DEEP)