title The Game of Deflection name ('DEFLECT') include solvdm.lib ; THE GAME OF DEFLECTION BY ANDREW A. RECUPERO ; FROM KILOBAUD FEB '78 #14 ; ; ######################################################## ; # Angepasst an den JOYCE, Werner Cirsovius, Maerz 2002 # ; ######################################################## ; ; 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. extrn SOLon,CONsta,CONdat,CONin,CONout,VDMclr ; ; Systemzuweisungen: ; _timval equ 01c0h ; Timer-Wert _delvl1 equ 0700h _delvl2 equ 0020h target equ _bcr ; Ziel Symbol runner equ _bel ; Spielstein-Symbol uslsh equ '/' ; Symbol fuer Deflektor hoch "/" dslsh equ '\' ; Symbol fuer Deflektor runter "\" ; left equ 10000000b ; Spielstein- down equ 01000000b ; Richtungs- up equ 00100000b ; Kontroll- right equ 00010000b ; Zuweisungen ; ; Programmstart ; ld sp,stack ; Stack initialisieren call SOLon ; SOL einschalten ld hl,$HELP call string ; Kurze Hilfe ausgeben call CONin ; Auf Start warten call VDMclr gstart: ld sp,stack ; Stack initialisieren reidle: call druner ; Runner anzeigen idle: call action ; Runner bewegen call delay ; Verzoegern und Eingabe testen ld a,c ; Moegliches Zeichen in Akku or a ; Test ob Zeichen gelesen jr z,idle ld_hl_8 ' ' ; Runner loeschen rrca ; Deflektoren bewegen? push af ; Spieleoptionen retten jr c,shift ; Verschieben! call VDMclr ; Nicht schieben, Bildschirm loeschen jr init shift: ld hl,SOLvid ; Bildschirm ld d,h ; eine ld e,l ; Position inc de ; nach smor: ld_a_de ; links ld_hl_a ; verschieben inc hl inc de ld a,d cp high VidTop jr nz,smor ; Schiebeschleife init: pop af ; Spieleoptionen zurueckladen ld c,1 ; Ein Ziel setzen rrca ; Spieleoptionen nach Carry ld a,target ; Zielsymbol in Akku jr nc,gam1 ; Sprung bei nur mittlerem Ziel ld c,3 ; Drei Ziele initialisieren ld_@_a SOLvid+13*maxcol+12 ld_@_a SOLvid+11*maxcol+52 gam1: ld_@_a SOLvid+12*maxcol+32 ld a,c ld (tarnum),a ; Anzahl Ziele speichern ld hl,_timval ; Timer setzen ld (timer),hl ; .. speichern call druner ; Runner anzeigen und Spiel starten ; ; Dies ist die Hauptschleife fuer das Spiel ; mainlp: call delay ; Verzoegern und Eingabe testen call action push hl ; HL retten ld hl,(timer) ; Spieletimer holen dec hl ; Runterzaehlen ld a,h ; Test ob Timer or l ; ... durchgelaufen ld (timer),hl ; Neuen Timer speichern pop hl ; HL holen jr nz,mainlp ; Schleife falls Timer noch nicht fertig ld hl,lose ; Meldung ausgeben, call show ; dass Zeit abgelaufen ist call waer ; Warten und Meldung loeschen jp gstart ; Timer abgelaufen, neues Spiel ; ; Runner initiieren und anzeigen ; Register 'B' haelt Bewegungsrichtung wie folgt: ; Reg Bit 7 6 5 4 ; | | | | ; | | | Rechts ; | | Hoch ; | Runter ; Links ; druner: ld hl,SOLvid+maxcol; Runner Startposition ld de,1*256+0 ; X,Y Runnerposition D=vert E=horz ld_hl_8 runner ; Runner anzeigen ld b,right ; Bewegungsrichtung initiieren ret ; ; Runnerbewegung wird hier abgewickelt ; action: ld_a_hl ; Test ob cp runner ; Runner jr nz,df010 ; angezeigt ld_hl_8 ' ' ; Runner vom Feld entfernen ; ; Neue Runnerposition berechnen ; df010: ld a,b cp right ; Bewegung rechts? jr nz,df012 ; ... nein inc e ; Eine Position nach rechts df012: cp up ; Bewegung hoch? jr nz,df014 ; ... nein dec d ; Eine Position hoch df014: cp down ; Bewegung runter? jr nz,df016 ; ... nein inc d ; Eine Position nach unten df016: cp left ; Bewegung links? jr nz,df018 ; ... nein dec e ; Eine Position nach links ; ; Feldposition aus horizontalen und verikalen Werten ; in DE berechnen mit Resultat in HL ; df018: ld a,d ; Vertikalwert rrca ; .. *64 ist *256/4 rrca ld l,a and high vidspc-1 or high SOLvid ld h,a ; Hoeherer Teil der Adresse ld a,l and not maxcol-1 add a,e ld l,a ; Niedriger Teil der Adresse ld_a_hl ; Test Spilefeld cp target ; Ist es ein Ziel? jr nz,df019 ; Nein, ignorieren ; ; Ziel getroffen ; ld_hl_8 ' ' ; Ziel entfernen ld a,(tarnum) ; Zielzaehler laden dec a ; Herunterzaehlen ld (tarnum),a ; Neuen Wert speichern ret nz ; Zurueck falls noch mehr Ziele pop de ; Alle Ziele vernichtet ld hl,win ; Gewinnmeldung call show ; ausgeben call waer ; Warten und Meldung loeschen jp reidle ; Neustart ; df019: ld a,c ; Zeichen in Akku holen cp uslsh ; Test Slash "/" jr z,df020 ; ... ja cp dslsh ; Test Back-Slash "\" ? jr z,df020 ; ... ok, Deflektor analysieren ; ; Test ob Speilstein einen Deflektor getroffen hat ; delck: ld_a_hl ; Ist das ein Leerzeichen? cp ' ' ; Deflektor wenn nicht jr nz,chgmot ; ... Richtung aendern call edgck ; Bewegung aendern wenn Kante ld_hl_8 runner ; Runner anzeigen ret ; ; Richtung der Runnerbewegung aendern ; df020: ld_hl_a ; Anzeige der gueltigen Eingabe chgmot: cp dslsh ; Test Back-Slash "\"? ld a,b ; Richtungsmarke laden jr nz,upslh ; Sprung wenn nicht Back-Slash and left+down ; Bewegung links oder runter? ld a,b ; Richtungsmarke neu laden jr z,df030 ; Sprung wenn nicht links oder runter rrca ; Richtung aendern in rrca ; rechts oder hoch jr df050 df030: rlca ; Richtung aendern in rlca ; links oder runter jr df050 upslh: and left+up ; Bewegung links oder hoch? ld a,b ; Richtungsmarke neu laden jr z,df040 ; Sprung wenn nicht links oder hoch rrca ; Richtung aendern in rechts oder runter jr df050 df040: rlca ; Richtung aendern in rechts oder runter df050: ld b,a ; Neue Bewegung retten call edgck ; Ist Runner an einer Kante? ld_a_hl ; Deflektor laden falls ja jr z,chgmot ; Bei Ecke Bewegung aendern ret ; ; Diese Routine testet Kante des Spielfelds, ; aendert die Bewegung und setzt die Zero Flag bei Kante ; edgck: ld a,b ; Richtungsmarke laden cp right ; Nach rechts? jr nz,df060 ; Sprung wenn nicht ld a,maxcol-1 ; Test rechte Kante cp e ret nz ; Nein, dann Ende ld b,left ; Richtung aendern nach links ret df060: cp up ; Nach oben? jr nz,df070 ; Sprung wenn nicht xor a or d ; Test linke Kante ret nz ; Nein, dann Ende ld b,down ; Richtung aendern nach unten ret df070: cp down ; Nach unten? jr nz,df080 ; Sprung wenn nicht ld a,maxrow-1 ; Test untere Kante cp d ret nz ; Nein, dann Ende ld b,up ; Richtung aendern nach oben ret df080: xor a ; Muss Bewegung nach links sein or e ; Test obere Kante ret nz ; Nein, dann Ende ld b,right ; Richtung aendern nach rechts ret ; ; Diese Routine durchlaeuft eine Verzoegerung, wobei ; die Tastatur getestet wird. Eingabe in Register 'C' ; delay: ld c,null ; Eingabe loeschen push de ; Register DE retten ld de,_delvl1 ; Wert fuer Verzoegerung dl01: dec de ; Verzoegerung runterzaehlen call CONsta ; Taste gedrueckt? jr z,dl02 ; Sprung wenn nicht call CONdat ; Zeichen von Tastatur lesen ld c,a ; In Register 'C' packen dl02: ld a,d ; Test ob or e ; Verzoegerung=0 jr nz,dl01 pop de ; Ende, Register DE holen ret ; ; Diese Routine wartet etwas und loescht eine Meldung ; waer: ld d,_delvl2 ; Verzoegerung laden wdly: call delay ; Einen Durchlauf warten dec d ; Test ob jr nz,wdly ; Durchlauf fertig ld hl,blnk ; Zeiger auf Leerzeile ; Leerzeichen ausgeben und Ende ; ; Diese Routine gibt eine Meldung in Register HL aus ; show: ld de,SOLvid+12*maxcol+29 ld b,msgl ; Laenge der Meldung sh01: ld a,(hl) ; Zeichen laden ld_de_a ; ... ausgeben inc de ; Zeiger auf inc hl ; naechstes Zeichen djnz sh01 ; Fertig? ret ; ; Meldung fuer Hilfe ausgeben ; ; EIN Reg HL zeigt auf Meldung ; string: ld a,(hl) cp eot ret z call CONout ; .. Zeichen ausgeben inc hl jr string ; ; Meldungen ; $HELP: db 'F',_ue,'r Start ','0'+MSB,',','1'+MSB,',' db '2'+MSB,' oder ','3'+MSB,' eingeben' db nl,nl db '0'+MSB,': 1 Ziel, Feld l',_oe,'schen' db nl db '1'+MSB,': 1 Ziel, Deflektoren schieben' db nl db '2'+MSB,': 3 Ziele, Feld l',_oe,'schen' db nl db '3'+MSB,': 3 Ziele, Deflektoren schieben' db nl,nl db 'Deflektoren mit ','/'+MSB,' oder ' db '\'+MSB,' eingeben.' db ' Viel Gl',_ue,'ck!',eot win: db 'Gewinner ' msgl equ $-win ; lose: db 'Zeit ist um' blnk: db ' ' ; ; Datenspeicher und Stack ; timer: ds 2 ; Speicher fuer Timer tarnum: ds 1 ; Anzahl Ziele ; ds 2*32 stack equ $ end