title Irrgarten name ('IRR') ; Quelle: http://www.iee.et.tu-dresden.de/~kc-club/09/RUBRIK17.HTM ; Das Original war mit TURBO Pascal kompiliert ; Dies ist die disassemblierte und optimierte Fassung .true equ 1 ; Version mit geaenderter Ausgabe einer Meldung an einer Cursorposition, ; veraenderte Cursor Positionierung ; Nun ohne RTL und mit Datensegment ; Anschauliche Namen und Optimierung ; Optimierung der Spielfeldgroesse ; Ausgaben nicht mehr dynamisch erzeugen ; Neuer Befehl "Umkehren" ; Joyce spezifische Zeichen OS equ 0000h BDOS equ 0005h TPATOP equ BDOS+1 .condir equ 6 .tod equ 105 _CIN equ 0fdh _CST equ 0feh null equ 00h bs equ 08h lf equ 0ah cr equ 0dh esc equ 1bh _NORD equ 1 _OST equ 2 _SUED equ 3 _WEST equ 4 ; ; Darstellung der Himmelsrichtung im Grundriss ; $NORD equ '^' ; Pfeil nach oben $SUED equ 09h ; Pfeil nach unten $WEST equ 0bh ; Pfeil nach links $OST equ 0ch ; Pfeil nach rechts $frei equ ' ' $aus equ 04h ; Kreis mit Kreuz $ort equ $OST $verz equ '0' $vor equ '8' $links equ '4' $rechts equ '6' $drehen equ '2' $map equ 'M' @lrand equ 0a0h @rrand equ 0a1h @senkr equ 0a2h @obrand equ 0a3h $lrand equ @lrand ;;'\' ; Linker schraeger Rand $rrand equ @rrand ;;'/' ; Rechter schraeger Rand $obrand equ @obrand ;;'~' ; Oberer Rand $unrand equ '_' ; Unterer Rand $senkr equ @senkr ;;'|' ; Senkrechter Rand $endrnd equ '*' ; Rand fuer Ende SENKLEN equ 26 ; Hoehe des senkrechten Randes MAXMAP equ 4 ; Maximale Anzahl fuer Grundrissausgabe FeldDim equ 20 ; Feldgroesse 20x20 MAPX equ 15 ; Startspalte fuer Grundriss spermsk equ 11110000b ; Maske fuer Sperrzeichen $sperre equ spermsk+0 ; Sperre l0002 equ 02h l0003 equ 03h l0005 equ 05h l0006 equ 06h l0007 equ 07h l0008 equ 08h l000a equ 0ah l000c equ 0ch l0011 equ 11h l0012 equ 12h l0013 equ 13h l0014 equ 14h l0017 equ 17h l0018 equ 18h l001a equ 1ah l001e equ 1eh l0024 equ 24h l0025 equ 25h l0033 equ 33h l003c equ 3ch ; ; Feld mit Himmelsrichtungen ; Himmelsrichtungen: db 'N' db 'O' db 'S' db 'W' db 'N' db 'O' db 'S' ; ; Feld mit Werten fuer Begrenzungen ; Koordinaten: db 32,15, 3, 7, 3, 7 ; Laengen der Begrenzungszeichen db 20, 9, 2, 5, 2, 5 db 12, 5, 1, 3, 1, 3 db 8, 3, 0, 1, 0, 1 ; db 5, 5, 1, 5, 1, 5 ; 1. Vertikale Startositionen db 8, 8, 5, 8, 5, 8 db 10,10, 8,10, 8,10 db 11,11,10,11,10,11 ; db 19,56,23,19,23,19 ; 2. Vertikale Startositionen db 16,50,19,16,19,16 db 14,46,16,14,16,14 db 13,44,14,13,14,13 ; db 24,23,16,16,63,57 ; Horizontale Startositionen db 30,29,24,24,55,51 db 34,33,30,30,49,47 db 36,35,34,34,45,45 ; ; Untere Begrenzung ausgeben ; BegrenzungUnten: ld hl,0 ld (IrrGartenPos),hl; Aktuelle Begrenzung waehlen NaechsteBegrenzung: ld hl,(IrrGartenPos) inc hl ld (IrrGartenPos),hl ex de,hl ld hl,IrrGartenPosTab-3 add hl,de add hl,de add hl,de push hl pop ix ld b,(ix+0) ; Laenge der Begrenzung ld h,(ix+2) ld l,(ix+1) ; Cursorposition laden call Cursor ; Cursor positionieren ld c,$unrand call MOTpr ; Ausgabe ld de,(IrrGartenPos) ld hl,(NordSued) ; Aenderung Nord-Sued holen or a sbc hl,de jr nz,NaechsteBegrenzung ret ; IrrGartenPosTab: db l001e db 19,25 ; db l0012 db 16,31 ; db l000a db 14,35 ; db l0008 db 13,36 ; ; Obere und untere Begrenzung anzeigen, Test ob Ziel erreicht ; ZielBegrenzung: ld hl,(WestOst) ; Bewegungswerte holen ld de,(NordSued) or a sbc hl,de ; Test ob Wert groesser oder gleich ld hl,$obrand+256*$unrand jr c,NormalBegrenzung; Wert ist kleiner, dann normale Begrenzung ; ; Ziel in Sicht - FERTIG anzeigen ; ld hl,256*l0025+l000c call Cursor ; Cursor positionieren ld hl,$FERTIG call PrStrg ; Anzeige, dass Ende erreicht ist ld hl,$endrnd+256*$endrnd ; ; Normale Begrenzung anzeigen ; NormalBegrenzung: ld (RandTyp),hl ; Randzeichen eintragen ld hl,1 call NS.Zeiger ; Laenge laden ld (RandLen),a ; Und eintragen ld hl,4 call NS.Zeiger ; Koordinaten laden push af ld hl,2 call NS.Zeiger ; Adresse berechnen pop hl ld l,a call Cursor ; Cursor positionieren ld a,(RandTyp) ; Oberen Teil ~~~~~~/****** laden call MOT ld hl,4 call NS.Zeiger ; Koordinaten laden push af ld hl,3 call NS.Zeiger ; Adresse berechnen pop hl ld l,a call Cursor ; Cursor positionieren ld a,(RandTyp+1) ; Unteren Teil ______/****** laden call MOT ret ; ; Obere und untere Begrenzung ausgeben ; ObenUnten: ld (OU.Auswahl),a ld hl,1 ld c,a call AR.Zeiger ; Laenge laden ld (RandLen),a ; Und eintragen ld hl,4 ld bc,(OU.Auswahl) call AR.Zeiger ; Koordinaten laden push af ld hl,2 ld bc,(OU.Auswahl) call AR.Zeiger ; Zeile laden pop hl ld l,a call Cursor ; Cursor positionieren ld a,$obrand call MOT ; ~~~~~~ an Cursorposition ausgeben ld hl,4 ld bc,(OU.Auswahl) call AR.Zeiger ; Koordinaten laden push af ld hl,3 ld bc,(OU.Auswahl) call AR.Zeiger ; Zeile laden pop hl ld l,a call Cursor ; Cursor positionieren ld a,$unrand call MOT ; ______ an Cursorposition ausgeben ret ; ; Rand ausgeben ; MOT: ld c,a ; Randzeichen retten ld a,(RandLen) ; Randlaenge laden ld b,a MOTpr: ld a,c call COT ; Zeichen ausgeben djnz MOTpr ret ; OU.Auswahl: ds 1 RandLen: ds 1 RandTyp: ds 1+1 ; ; Zwei senkrechte Begrenzungen ausgeben ; LR.Begrenzung: ld l,4 ; Erste Senkrechte call Senkrechte ld l,3 ; Zweite Senkrechte Senkrechte: ld h,0 ld c,2 call AR.Zeiger ; Koordinaten laden push af ld hl,2 ld c,2 call AR.Zeiger ld l,a pop af ld h,a call Cursor ; Cursor positionieren ld hl,1 ld c,2 call AR.Zeiger ; Laenge holen ld b,a SenkLoop: ld hl,$SENKRECHT ; Senkrechten Rand | laden call PrStrg djnz SenkLoop ; Entsprechend oft ausgeben ret ; ; Rand ausgeben ; RandAusgabe1: ld hl,1 ld c,3 call AR.Zeiger ; Laenge holen ld l,a ld h,0 ld e,l ld d,h inc de ; Schleifenlaenge RandSchleife1: ld a,d or e ret z push de ld (RandIndex),hl add hl,hl ld (Rand2Index),hl ; ; Linken Rand an Cursorposition ausgeben ; ld hl,4 ld c,3 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(Rand2Index) add hl,de ld a,l ; Koordinaten laden push af ld hl,2 ld c,3 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(RandIndex) add hl,de pop af ld h,a call Cursor ; Cursor positionieren ld a,$lrand ; Linken Rand laden call COT ; Und ausgeben ; ; Rechten Rand an Cursorposition ausgeben ; ld hl,4 ld c,3 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(Rand2Index) add hl,de ld a,l push af ld hl,3 ld c,3 call AR.Zeiger ; Adresse berechnen ld l,a ld h,0 ld de,(RandIndex) or a sbc hl,de pop af ld h,a call Cursor ; Cursor positionieren ld a,$rrand ; Rechten Rand laden call COT ; Und ausgeben ; ld hl,(RandIndex) dec hl pop de dec de jr RandSchleife1 ; ; Rand ausgeben ; RandAusgabe2: ld hl,1 ld c,5 call AR.Zeiger ; Laenge laden ld l,a ld h,0 ld e,l ld d,h inc de ; Schleife setzen RandSchleife2: ld a,d or e ret z push de ld (RandIndex),hl add hl,hl ld (Rand2Index),hl ; ; Rechten Rand an Cursorposition ausgeben ; ld hl,4 ld c,5 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(Rand2Index) ex de,hl or a sbc hl,de ld a,l push af ld hl,2 ld c,5 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(RandIndex) add hl,de pop af ld h,a call Cursor ; Cursor positionieren ld a,$rrand ; Rechten Rand laden call COT ; Und ausgeben ; ; Linken Rand an Cursorposition ausgeben ; ld hl,4 ld c,5 call AR.Zeiger ; Adresse berechnen ld e,a ld d,0 ld hl,(Rand2Index) ex de,hl or a sbc hl,de ld a,l push af ld hl,3 ld c,5 call AR.Zeiger ; Adresse berechnen ld l,a ld h,0 ld de,(RandIndex) or a sbc hl,de pop af ld h,a call Cursor ; Cursor positionieren ld a,$lrand ; Linken Rand laden call COT ; Und ausgeben ; ld hl,(RandIndex) dec hl pop de dec de jr RandSchleife2 ; ; Irrgarten darstellen ; ZugIrrgarten: ld hl,(Zug) inc hl ; Zug hochzaehlen ld (Zug),hl AusgabeIrrgarten: call SchirmLoeschen ; Bildschirm loeschen ld hl,256*l0024+l0018 call Cursor ; Cursor positionieren ld hl,$ZUG call PrStrg ; Zug ausgeben ld hl,(Zug) call PrDezimal ld hl,256*l000a+l001a call Cursor ; Cursor positionieren ld hl,$BEFEHLE1 call PrStrg ; Kommandos ausgeben ld hl,256*(l000a+19)+(l001a+1) call Cursor ; Cursor positionieren ld hl,$BEFEHLE2 call PrStrg ; Kommandos ausgeben ld hl,0 ld (WestOst),hl ; Bewegungswert einstellen ld hl,1 ; Startwert ld b,4 ; Anzahl Durchlaeufe IrrGartenBilder: push bc ld (IrrGartenPos),hl ld (NordSued),hl ; Aenderung Nord-Sued setzen ld de,(Horizontal) ; Horizontale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielSpalte); Aktuelle Spalte add hl,de ; Addieren ld (sp.idx),hl ; SpielSpalte+Horizontal*IrrGartenPos ld c,l ld b,h ld de,(Vertikal) ; Vertikale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielZeile) ; Aktuelle Zeile add hl,de ; Addieren ld (ze.idx),hl call FeldAdresse ; Adresse berechnen pop bc call Sperre ; Test ob Sperre jr nc,FeldBelegt ; Ja ld hl,(ze.idx) ; Aktueller Zeileindex ld de,(AusgangZeile) or a sbc hl,de jr nz,Ungleich ; Test ob Zeilen gleich ld hl,(sp.idx) ; Aktuelle Spaltenindex ld de,(AusgangSpalte); Ausgangsspalte or a sbc hl,de jr nz,Ungleich ; Test ob gleich ld hl,(NordSued) ; N-S Begrenzung holen inc hl ld (WestOst),hl ; W-O Bewegungswert einstellen jr FeldBelegt Ungleich: ld hl,(IrrGartenPos) ld (WestOst),hl ; Bewegungswert einstellen inc hl djnz IrrGartenBilder ; ; Kompass ausgeben ; FeldBelegt: ld ix,KompassXY ld b,4 ; Anzahl Himmelsrichtungen ld de,Himmelsrichtungen-1 ld hl,(Richtung) add hl,de ; Auf ersten Eintrag positionieren KompassRose: push bc push hl ld l,(ix+0) ld h,(ix+1) push ix call Cursor ; Cursor positionieren pop hl inc hl inc hl ex (sp),hl ; Zeiger zurueck holne ld a,(hl) call COT ; Himmelsrichtung ausgeben ; inc hl pop ix pop bc djnz KompassRose ; ; Gaenge des Irrgartens aufbauen ; call BegrenzungUnten ; Untere Begrenzung ausgeben ld de,(WestOst) ; Bewegungswert holen ld hl,(NordSued) push hl or a sbc hl,de ; Test gleicher Wert call nz,ZielBegrenzung; Obere und untere Begrenzung anzeigen, Test ob Ziel erreicht pop hl ; Aenderung Nord-Sued zurueck holen ld d,h ld e,l dec hl GaengeZeigen: ld a,d or e ret z push de ld (IrrGartenPos),hl inc hl ld (AktRichtung),hl call LR.Begrenzung ; Zwei senkrechte Begrenzungen ausgeben ld de,(Horizontal) ; Horizontale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielSpalte); Aktuelle Spalte add hl,de ld de,(Vertikal) ; Vertikale Aenderung laden (+1/0/-1) add hl,de ld c,l ld b,h ld de,(Vertikal) ; Horizontale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielZeile) ; Aktuelle Zeile add hl,de ld de,(Horizontal) ; Vertikale Aenderung laden (+1/0/-1) or a sbc hl,de call FeldAdresse ; Adresse im Grundriss berechnen call Sperre ; Test Begrenzung push af call nc,RandAusgabe1 ; Linken und rechten Rand ausgeben pop af ld a,4 call c,ObenUnten ; Obere und untere Begrenzung ausgeben ld de,(Horizontal) ; Horizontale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielSpalte); Aktuelle Spalte add hl,de ld de,(Vertikal) ; Vertikale Aenderung laden (+1/0/-1) or a sbc hl,de ld c,l ld b,h ld de,(Vertikal) ; Horizontale Aenderung laden (+1/0/-1) ld hl,(IrrGartenPos) call mult.x1 ld de,(SpielZeile) ; Aktuelle Zeile add hl,de ld de,(Horizontal) ; Vertikale Aenderung laden (+1/0/-1) add hl,de call FeldAdresse ; Adresse im Grundriss berechnen call Sperre ; Test Begrenzung push af call nc,RandAusgabe2 ; Linken und rechten Rand ausgeben pop af ld a,6 call c,ObenUnten ; Obere und untere Begrenzung ausgeben ld hl,(IrrGartenPos) dec hl pop de dec de jp GaengeZeigen ; ; Grundriss ausgeben ; ; Pro realem Feld wird ein Leerzeichen zugefuegt ; GrundrissZeigen: call SchirmLoeschen ; Bildschirm loeschen ld de,256*(MAPX+2)+1 ld hl,Spielfeld ; Zeiger auf das Feld ld b,FeldDim ; Anzahl Zeilen GrundrissZeilen: push bc ex de,hl call Cursor ; Cursor positionieren ex de,hl ld b,FeldDim ; Anzahl Spalten GrundrissSpalten: ld a,(hl) call spCOT ; Moegliches Sperrzeichen ausgeben ld a,' ' call COT inc hl djnz GrundrissSpalten inc e pop bc djnz GrundrissZeilen ; ; Richtung des Spielers anzeigen ; ld hl,(SpielSpalte); Aktuelle Spalte add hl,hl ; Verdoppeln fuer Bildschirm ld de,MAPX ; Startspalte fuer Grundriss add hl,de ld a,l ld hl,(SpielZeile) ; Aktuelle Zeile ld h,a call Cursor ; Cursor positionieren ld de,SpielerTabelle-1 ld hl,(Richtung) ; Himmelsrichtung laden add hl,de ld a,(hl) ; Zeichen holen call COT ; Richtung anzeigen ; ; Ausgang anzeigen ; ld hl,(AusgangSpalte); Ausgangsspalte add hl,hl ; Verdoppeln fuer Bildschirm ld de,MAPX ; Startspalte fuer Grundriss add hl,de ld a,l ld hl,(AusgangZeile); Ausgangszeile ld h,a call Cursor ; Cursor positionieren ld a,$aus call COT ; Ausgang anzeigen ; ; Status fuer Grundriss ; ld hl,256*l0012+l0018 call Cursor ld hl,(Einblendungen); Anzahl Grundrisseinblendungen holen add hl,hl ld de,$M.LISTE add hl,de ld e,(hl) ; Zugehoerige Meldung laden inc hl ld d,(hl) ex de,hl call PrStrg ; Ausgabe ld hl,$TASTE$ET call ET.Meldung ; Weiter mit ENTER ld a,(Eingabe) cp esc ; Test, ob runterzaehlen ret z ; Nein ld hl,(Einblendungen) ld a,l ; Test ob noch mehr moeglich ist or h ret z ; Nein dec hl ; Anzahl runterzaehlen ld (Einblendungen),hl ret ; SpielerTabelle: db $NORD,$OST,$SUED,$WEST ; ; Himmelsrichtung in vertikale oder horizontal Aenderung wandeln ; Bewegung: ld ix,Horizontal ld de,BewegungsTabelle-1 jr HoleRichtung ; ; Himmelsrichtung in vertikale oder horizontal Aenderung wandeln ; RichtungHolen: ld de,(Richtung) ; Himmelsrichtung laden ld hl,_NORD-1 or a sbc hl,de ; Test Unterlauf ld hl,_WEST jr z,NeueRichtung ; Ja, dann neuer Wert inc hl or a sbc hl,de ; Test Ueberlauf jr nz,Richtung.istOk ld hl,_NORD NeueRichtung: ld (Richtung),hl ; Neuen Wert setzen Richtung.istOk: xor a ld (Fertig),a ; Status setzen ld ix,WestOst ld de,RichtungsTabelle-1 HoleRichtung: xor a ld (ix+0),a ; Bewegungswerte einstellen ld (ix+1),a ld (ix+2),a ld (ix+3),a ld hl,(Richtung) ; Himmelsrichtung laden bit 0,l ; Test NORD oder SUED jr z,TabelleOk ; Nein inc ix ; Zeiger einstellen inc ix TabelleOk: add hl,de ld a,(hl) ; Wert holen (+1/-1) ld (ix+0),a add a,a sbc a,a ; Expandiren auf 16 Bit ld (ix+1),a ret ; RichtungsTabelle: db +1 ; Nord db -1 ; Ost BewegungsTabelle: db -1 ; Sued Nord db +1 ; West Ost db +1 ; Sued db -1 ; West ; ; Das Spiel initialisieren ; Initialisierung: ld hl,_NORD ld (Richtung),hl ; Himmelsrichtung vorbesetzen ld hl,0 ld (WestOst),hl ; Bewegungswerte einstellen inc hl ld (NordSued),hl ; Stellen auf Norden inc hl ld (SpielZeile),hl ; Werte einstellen ld (IrrGartenPos),hl ld (AusgangSpalte),hl ld hl,19 ld (SpielSpalte),hl ld (RandIndex),hl ld (AusgangZeile),hl WeiterSetzen: ld hl,(RandIndex) ld de,(WestOst) ; Bewegungswert holen add hl,de ld c,l ld b,h ld hl,(IrrGartenPos) ld de,(NordSued) ; Aenderung Nord-Sued holen add hl,de call FeldAdresse ; Adresse im Grundriss berechnen call Sperre ; Test Sperre jr c,VielleichtFertig ld hl,(Richtung) ; Himmelsrichtung laden dec hl ; Und aendern ld (Richtung),hl call RichtungHolen ; Himmelsrichtung in vertikale oder horizontal Aenderung wandeln ld a,(Fertig) or a ; Status testen jr z,WeiterSetzen ; Weiter versuchen falls noch nichts frei jr Fertig.testen VielleichtFertig: ld a,.true ld (Fertig),a ; Status setzen Fertig.testen: ld hl,(IrrGartenPos) ld de,(NordSued) ; Aenderung Nord-Sued holen add hl,de ld (IrrGartenPos),hl ld hl,(RandIndex) ld de,(WestOst) ; Bewegungswert holen add hl,de ld (RandIndex),hl ld hl,(Richtung) ; Himmelsrichtung laden inc hl ; Und aendern ld (Richtung),hl call RichtungHolen ; Himmelsrichtung in vertikale oder horizontal Aenderung wandeln ld a,.true ld (Fertig),a ; Status setzen ld hl,(IrrGartenPos) ld de,(SpielZeile) ; Aktuelle Zeile or a sbc hl,de ; Test Uebereinstimmung jr nz,FertigEnde ld hl,(RandIndex) ld de,(SpielSpalte); Aktuelle Spalte or a sbc hl,de jr nz,FertigEnde ld hl,(AusgangZeile); Ausgangszeile ld (IrrGartenPos),hl ld hl,(AusgangSpalte); Ausgangsspalte ld (RandIndex),hl xor a ld (Fertig),a ; Status ruecksetzen FertigEnde: ld hl,(IrrGartenPos) ld de,(AusgangZeile); Ausgangszeile or a sbc hl,de ; Test Uebereinstimmung jp nz,WeiterSetzen ld hl,(RandIndex) ld de,(AusgangSpalte); Ausgangsspalte or a sbc hl,de ; Test Uebereinstimmung jp nz,WeiterSetzen ret ; ; Ausgang gefunden ; SpielFertig: call SchirmLoeschen ; Bildschirm loeschen ld hl,256*l001e+l000c call Cursor ld hl,$GEWONNEN call PrStrg ; Ein Lob ausprechen WartenAufEnde: ld hl,256*l0033+l0017 call Cursor ld hl,$NOCHMAL call PrStrg call CIN cp 'J' ; Test ob nochmal jr z,SpielfeldBelegen cp cr jr z,SpielfeldBelegen cp 'N' jr nz,WartenAufEnde SpielEnde: call SchirmLoeschen ; Bildschirm loeschen call CurEin ; Cursor einschalten ;; call ZeichenAlt ; Alte Zeichen wieder herstellen jp OS ; Ende des Spieles ; ; Das Spiel beginnt ; Irrgarten: ld sp,(TPATOP) ; Stapelspeicher laden call Randinit ; Zufallszahl initiieren call CurAus ; Cursor ausschalten call ZeichenNeu ; Neue Zeichen definieren ; ; *** Hauptspielschleife ** ; ; Belegung des Spielfeldes ; SpielfeldBelegen: ld hl,1 ld b,FeldDim/2 - 1 Belegung1: push bc ld (IrrGartenPos),hl ld hl,1 ld b,FeldDim/2 - 1 Belegung2: push bc ld (RandIndex),hl add hl,hl ld c,l ld b,h ld hl,(IrrGartenPos) add hl,hl push bc ; -> RandIndex*2 push hl ; -> IrrGartenPos*2 call FeldAdresse ld (hl),$frei ; Spielfeld als frei markieren inc hl ld (hl),$frei pop hl inc hl pop bc call FeldAdresse ld (hl),$frei inc hl ld (hl),$sperre ; Spielfeld als belegt markieren ld c,FeldDim/2 call Random ; Zufallszahl im Bereich 0..9 cp l0003 jr c,BelegeKeinFeld; Bereich ab 3 ist gueltig cp l0006 jr z,BelegeEinFeld ; Bereich 3..6 testen jr nc,BelegeNochEinFeld BelegeEinFeld: push af ld hl,(RandIndex) add hl,hl ld c,l ld b,h inc bc ld hl,(IrrGartenPos) add hl,hl call FeldAdresse ld (hl),$sperre ; Spielfeld als belegt markieren pop af jr nz,BelegeKeinFeld; Nicht Mittelwert 6 BelegeNochEinFeld: ld hl,(RandIndex) add hl,hl ld c,l ld b,h ld hl,(IrrGartenPos) add hl,hl inc hl call FeldAdresse ld (hl),$sperre ; Bei Mittelwert 6 auch dieses Spielfeld belegen BelegeKeinFeld: ld hl,(RandIndex) inc hl pop bc djnz Belegung2 ld hl,(IrrGartenPos) inc hl pop bc djnz Belegung1 ; ; Spielfeld ist nun belegt, einen Durchgang schaffen und Ecken frei machen ; ld a,$frei ld (Spielfeld+(l0012-1)*FeldDim+(l0007-1)),a ; ld ix,Spielfeld+(l0002-1)*FeldDim+(l0011-1) ld (ix+0),a ld (ix+1),a ld (ix+2),a ld ix,Spielfeld+(l0012-1)*FeldDim+(l0002-1) ld (ix+0),a ld (ix+1),a ld (ix+2),a ld ix,Spielfeld+(l0003-1)*FeldDim+(l0012-1) ld (ix+0),a ld (ix+1*(FeldDim+1)),a ld ix,Spielfeld+(l0011-1)*FeldDim+(l0002-1) ld (ix+0),a ld (ix+2*(FeldDim+1)),a call Initialisierung ; Spiel initialisieren ld a,(Fertig) or a ; Status testen jp z,SpielfeldBelegen ; ; Das Spiel beginnt ; call SchirmLoeschen ; Bildschirm loeschen ld hl,256*l0014+l0003 call Cursor ld hl,$TITEL call PrStrg ; Ueberschrift ausgeben ld hl,256*l0005+l0006 call Cursor ld hl,$HILFE call PrStrg ; Hilfe ausgeben ld hl,256*l003c+l0018 call Cursor ld hl,$TASTE.ET call ET.Meldung ; Weiter mit ENTER ld hl,l0002 ld (AusgangZeile),hl; AusgangZeile=2 ld (SpielSpalte),hl; Aktuelle Spalte=2 ld hl,l0013 ld (AusgangSpalte),hl; Ausgangsspalte=19 ld (SpielZeile),hl ; Aktuelle Zeile=19 ld hl,MAXMAP ; Maximale Anzahl Grundrisseinblendungen einstellen ld (Einblendungen),hl ld hl,-1 ld (Vertikal),hl ; Vertikale Aenderung nach Norden ld hl,0 ld (Horizontal),hl ; Keine horizontale Aenderung ld (Zug),hl ; Noch kein Zug gemacht ld hl,_NORD ld (Richtung),hl ; Himmelsrichtung vorbesetzen call GrundrissZeigen ; Grundriss ausgeben ld hl,l0014 ld (SpielZeile),hl ; Aktuelle Zeile=20 ld a,$vor ld (Eingabe),a ; Vorwaerts einstellen ; ; Spielablauf ; SpielLauf: ld hl,BefehlTesten push hl ; Ruecksprungadresse setzen ld a,(Eingabe) ld hl,$cmdtab+cmdlen-1 ld bc,cmdlen cpdr ; Zeichen finden ret nz ; Nicht gefunden ld hl,cmdexe add hl,bc add hl,bc ld e,(hl) ; Adresse holen inc hl ld d,(hl) ex de,hl jp (hl) ; Ausfuehren ; ; Ende eines Kommandos ; BefehlTesten: ld a,$verz ld (Eingabe),a ; Verzoegrung setzen falls keine Eingabe call CST ; Test ob Zeichen vorhanden jr z,SpielLauf ; Nein, dann naechster Versuch Abwarten: call CIN cp 'C'-'@' ; Test Abbruch jp z,SpielEnde ld hl,$cmdtab+1 ld bc,cmdlen-1 cpir ; Test, ob Zeichen gueltig jr z,SpielLauf ; Ja jr Abwarten ; Sonst auf gueltiges Zeichen warten ; ; Befehlstabelle ; $cmdtab: db $verz,$map,esc,$links,$rechts,$vor,$drehen cmdlen equ $-$cmdtab ; cmdexe: dw Warten,GrundrissAusgabe,ImmerGrundrissAusgabe dw NachLinks,NachRechts,Geradeaus,Umkehr ; ; Dummy Eingabe, Verzoegerung ; Warten: ld hl,110 ; Einfache Verzoegerung Verzoegerung: ld a,4*8 ; CPU-Takt beim Joyce ist 4MHz WarteSchleife: ex (sp),hl ; 5 Zyklen ex (sp),hl ; 10 Zyklen ex (sp),hl ; 15 Zyklen ex (sp),hl ; 20 Zyklen push bc ; 23 Zyklen ld bc,1234 ; 26 Zyklen pop bc ; 29 Zyklen dec a ; 30 Zyklen jr nz,WarteSchleife dec hl ld a,l or h jr nz,Verzoegerung ret ; ; Grundriss einblenden ; GrundrissAusgabe: ld hl,(Einblendungen); Anzahl Grundrisseinblendungen holen ld a,l or h ; Test ob Ausgabe noch erlaubt jr nz,ImmerGrundrissAusgabe ld hl,256*l0012+l0018 call Cursor ; Cursor fuer Meldung setzen ld hl,$M.KEINEHILFE call PrStrg ; Keine Hilfestellung mehr ld hl,5000 call Verzoegerung ; Warten call AusgabeIrrgarten; Irrgarten darstellen ret ; ; Grundriss IMMER einblenden ; ImmerGrundrissAusgabe: call GrundrissZeigen ; Grundriss ausgeben call AusgabeIrrgarten; Danach den Irrgarten ret ; ; Umkehr ; Umkehr: call NachLinks ; Zweimal links ; ; Linkswendung ; NachLinks: ld hl,(Richtung) ; Himmelsrichtung laden dec hl ; Nach links bewegen ld de,_NORD-1 ld bc,_WEST jr RichtungAendern ; ; Rechtswendung ; NachRechts: ld hl,(Richtung) ; Himmelsrichtung laden inc hl ; Nach rechts bewegen ld de,_WEST+1 ld bc,_NORD RichtungAendern: ld (Richtung),hl ; Bewegung eintragen or a sbc hl,de ; Test ob im richtigen Bereich jr nz,RichtungOk ; Noch ja ld (Richtung),bc ; Startwert setzen RichtungOk: call Bewegung ; Himmelsrichtung in Aenderung wandeln NeuerIrrgarten: call ZugIrrgarten ; Irrgarten darstellen ret ; ; Vorwaerts ; Geradeaus: ld de,(SpielSpalte); Aktuelle Spalte ld hl,(Horizontal) ; Horizontale Aenderung laden (+1/0/-1) add hl,de ; Naechsten Ort bestimmen ld c,l ld b,h ld de,(SpielZeile) ; Aktuelle Zeile ld hl,(Vertikal) ; Vertikale Aenderung laden (+1/0/-1) add hl,de call FeldAdresse ; Ort berechnen call Sperre ; Test ob frei ret nc ; Nein ld de,(SpielZeile) ; Aktuelle Zeile ld hl,(Vertikal) ; Vertikale Aenderung laden (+1/0/-1) add hl,de ld (SpielZeile),hl ; Neuen Ort bestimmen ld de,(SpielSpalte); Aktuelle Spalte ld hl,(Horizontal) ; Horizontale Aenderung laden (+1/0/-1) add hl,de ld (SpielSpalte),hl ; ; Test ob am Ausgang angekommen ; ld de,(SpielZeile) ; Aktuelle Zeile ld hl,(AusgangZeile); Ausgangszeile or a sbc hl,de jr nz,NeuerIrrgarten ld de,(SpielSpalte); Aktuelle Spalte ld hl,(AusgangSpalte); Ausgangsspalte or a sbc hl,de jr nz,NeuerIrrgarten ld hl,SpielFertig ; Ende erreicht, wenn Koordinaten gleich sind ex (sp),hl ret ; ; Text ausgeben ; PrStrg: ld a,(hl) ; Zeichen holen or a ; Test ob Ende ret z call COT ; Zeichen ausgeben inc hl jr PrStrg ; ; Sperrzeichen ausgeben ; spCOT:: cp spermsk ; Test ob Sperrzeichen jr c,COT ; Nein and NOT spermsk push bc push hl ld hl,SP$TAB ld c,a ld b,0 add hl,bc ld a,(hl) ; Zeichen wandeln pop hl pop bc jr COT ; ; Dezimalzahl in HL ausgeben ; PrDezimal: ld c,0 ; Keine fuehrenden Nullen und Leerzeichen ld de,-10000 call PR.DIG ; Ziffern der Potenz nach ausgeben ld de,-1000 call PR.DIG ld de,-100 call PR.DIG ld de,-10 call PR.DIG ld a,'0' add a,l jr COT ; Letzte Ziffer ausgeben ; ; Ziffer einer Potenz ausgeben ; PR.DIG: ld b,'0' ; Resultat vorbelegen DIV.LOP: push hl add hl,de ; Durch Zehnerpotenz dividieren jr nc,DIV.OK pop af inc b jr DIV.LOP DIV.OK: pop hl ld a,b cp '0' ; Test Resultat Null jr nz,PR.IT ; Nein, dann Ausgabe bit 0,c ; Test ob Null ausgegeben werden darf ret z ; Nein PR.IT: set 0,c ; Ausgabe anzeigen ; ; Zeichen in Akku auf Konsole ausgeben - Spezielle Zeuchen filtern ; COT: cp ' ' ; Test Kontrollzeichen jr nc,Konsole ; Nein, normal cp bs jr z,Konsole ; Zeichen filtern cp lf jr z,Konsole cp cr jr z,Konsole cp esc jr z,Konsole push af ld a,esc call Konsole pop af Konsole: push bc push de push hl ld e,a ld c,.condir call BDOS ; Zeichen ausgeben pop hl pop de pop bc ret ; ; Test ob Taste betaetigt - NZ bedeutet Taste betaetigt ; CST: ld a,_CST call Konsole ; Status holen or a ; Z bedeutet keine Taste ret ; ; Zeichen von Konsole lesen und in Grossbuchstaben wandeln ; CIN: ld a,_CIN call Konsole ; Zeichen lesen ld (Eingabe),a ; Und eintragen cp 'a' ; Test Kleinbuchstabe ret c ; Nein cp 'z'+1 ret nc add a,'A'-'a' ; Wandeln falls ja ld (Eingabe),a ret ; ; Meldung ausgeben und auf ENTER warten ; ET.Meldung: call PrStrg ; Weiter mit ENTER Quittung: ld a,_CIN call Konsole ; Zeichen lesen cp cr jr nz,Quittung ret ; ; Feldadresse (HL,BC) berechnen ; FeldAdresse: dec hl add hl,hl ; * 2 add hl,hl ; * 4 push hl ; -> * 4 add hl,hl ; * 8 add hl,hl ; *16 pop de ; <- * 4 add hl,de ; *20 add hl,bc ; Index ist nun fertig ld de,Spielfeld-1 add hl,de ; Adresse berechnen ld a,(hl) ; Eintrag laden ret ; ; Koordinaten fuer Spielfeld berechnen ; NS.Zeiger: ld a,(NordSued) ; Aenderung Nord-Sued holen ld c,1 jr FeldZeiger ; Adresse berechnen ; AR.Zeiger: ld a,(AktRichtung) ; ; HL:=Koordinaten[HL,AKKU,C] ; FeldZeiger: ld b,h ; Oberes Byte ist immer Null dec hl add hl,hl ; Index berechnen add hl,hl add hl,hl push hl add hl,hl pop de add hl,de push hl ld l,a ld h,b dec hl add hl,hl ld e,l ld d,h add hl,hl add hl,de pop de add hl,de add hl,bc ld de,Koordinaten-1 add hl,de ; Adresse im Datenfeld ld a,(hl) ret ; $TITEL: db esc,'p','* I R R G A R T E N * ',esc,'q',null $HILFE: db 'Durchlaufe die Gaenge des Irrgartens bis zum Ausgang! Zu Deiner' db cr,lf db 'Orientierung kannst Du viermal den Grundriss einblenden.' db cr,lf db 'Der Ausgang ist mit ',$aus,' markiert,' db cr,lf db 'Dein Standort mit einem ',$ort,' in Bewegungsrichtung!' db cr,lf db 'Du kannst Dich auch nach dem Kompass am oberen Bildrand orientieren,' db cr,lf db 'der Grundriss ist eingenordet.' db cr,lf,lf db 'Steuertasten: ' db cr,lf db ' ',$vor,' - Vorwaerts' db cr,lf db ' ',$links,' - Linkswendung' db cr,lf db ' ',$rechts,' - Rechtswendung' db cr,lf db ' ',$drehen,' - Umkehr' db cr,lf,lf db 'Grundriss einblenden - "',$map,'" Abbruch - CTRL C.',null $GEWONNEN: db ' Hervorragend !!!',null $NOCHMAL: db ' Nochmal ? J/N ',null $M.KEINEHILFE: db 'Es gibt keine Hilfestellung mehr !!!',null $M.LISTE: dw $M.BETRUG,$M.LETZTER,$M.NOCHEINER,$M.MELDUNG,$M.START $M.BETRUG: db 'BETRUG !!! Das ist kein Fairplay !!',null $M.LETZTER: db ' Allerletzte Orientierungshilfe !!!',null $M.NOCHEINER: db ' Jetzt hast Du noch eine Chance !',null $M.MELDUNG: db ' Gib Dir bitte etwas mehr Muehe !!',null $M.START: db ' Gute Reise durch''s Labyrinth !!',null $TASTE$ET: db ' ' $TASTE.ET: db 'Taste ET',null $FERTIG: db 'FERTIG',null $ZUG: db 'Zug ',null $BEFEHLE1: db esc,'p' db ' ' db $vor,' - Vorwaerts, ' db $links,' - Linkswendung, ' db $rechts,' - Rechtswendung, ' db $drehen,' - Zurueck ',null $BEFEHLE2: db ' ' db $map,' - Grundriss, ' db '^C - Abbruch ' db esc,'q',null sp.idx: ds 2 ze.idx: ds 2 ; ; Koordinaten des Kompass ; KompassXY: db 1,40 db 2,42 db 3,40 db 2,38 Zug: ds 2 ; ; Multiplikation HL mit 0, +1 oder -1 ; mult.x1: bit 7,d ; Test -1 jr nz,mult.neg inc e dec e ; Test +1 ret nz ; Ja ex de,hl ; 0 als Ergebnis ret mult.neg: inc de ; 0 ex de,hl or a sbc hl,de ; Negieren bei -1 ret ; ; Cursor einschalten ; CurEin: ld a,'e' jr esc.out ; PCW Sequenzen ausgeben ; ; Cursor ausschalten ; CurAus: ld a,'f' jr esc.out ; ; Bildschirm loeschen ; SchirmLoeschen: ld a,'H' call esc.out ld a,'E' esc.out: push af ld a,esc call COT ; Vorspann ausgeben pop af call COT ret ; ; Cursor positionieren X=H, Y=L ; Cursor: ld a,'Y' call esc.out ; Vorspann ausgeben ld a,l ; Erst Reihe call pos.XY ld a,h ; Dann Spalte pos.XY: add a,' '-1 ; Offset addieren call COT ret ; ; Zufallszahl initiieren - hier ueber die Zeitfunktion von CP/M 3 ; Randinit: ld de,Zufallszahl-2; Zeitblock laden ld c,.tod call BDOS ; Zeitstempel holen ld (Zufallszahl+1),a; Wert ablegen ld c,255 call Random ; Erste Zufallszahl ld (Zufallszahl),a ; Ergebnis speichern ret ; ; Block fuer Zufallszahl ; ds 2 ; Jahr Zufallszahl: ds 1 ; Std ds 1 ; Min ; ; Zufallswert 0..9 erzeugen ; Random: ld hl,Zufallszahl ld a,(hl) ; Zahl erzeugen rlca xor (hl) rrca inc hl inc (hl) add a,(hl) jp pe,Zufall1 inc (hl) Zufall1: dec hl ld (hl),a and 00001111b ; Maximal 15 in diesem Spiel cp c ; Test, ob im Bereich jr nc,Random ret ; SP$TAB:: db '*' ; Sperrzeichen db 086h db 08ch db 083h db 089h db 08ah db 085h db '*' db '*' db '*' db '*' db '*' db '*' db '*' db '*' db '*' ; ; Test ob Zeichen eine Sperre - C gesetzt wenn nicht ; Sperrzeichen liegen im Bereich 1111xxxx ; (16 Sperrzeichen sind moeglich) ; Sperre: cp spermsk ret ; $sperre equ spermsk+0 ; Sperre $ol equ spermsk+1 ; Obere linke Ecke $or equ spermsk+2 ; Obere rechte Ecke $ul equ spermsk+3 ; Untere linke Ecke $ur equ spermsk+4 ; Untere rechte Ecke $hl equ spermsk+5 ; Horizontale Linie $vl equ spermsk+6 ; Vertikale Linie $SENKRECHT: db $senkr,lf,bs,null ; Spielfeld: db $ol ds FeldDim-2,$hl db $or ;; ds FeldDim,$sperre rept FeldDim-2 db $vl ds FeldDim-2,' ' db $vl endm db $ul ds FeldDim-2,$hl db $ur ;; ds FeldDim,$sperre Richtung: ds 2 ; Himmelsrichtung N-O-S-W AktRichtung: ds 2 ; Aktuelle Richtung Horizontal: ; \ ds 2 ; | Horizontale Aenderung Vertikal: ; | ds 2 ; / Vertikale Aenderung WestOst: ; \ ds 2 ; | Aenderung W-O NordSued: ; | ds 2 ; / Aenderung N-S Einblendungen: ds 2 ; Anzahl Grundrisseinblendungen AusgangSpalte: ds 2 ; Ausgangsspalte AusgangZeile: ds 2 ; Ausgangszeile SpielSpalte: ds 2 ; Aktuelle Spalte SpielZeile: ds 2 ; Aktuelle Zeile RandIndex: ds 2 ; Index fuer Randberechnung Rand2Index: ds 2 IrrGartenPos: ds 2 ; Irrgartenposition Fertig: ds 1 ; Status der Belegung Eingabe: ds 1 ; Befehlseingabe ; ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ; %%%%% Joyce spezifisch Routinen %%%%% ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ; _USERF equ 30 ; BIOS Funktion ; _SCRRUN equ 000e9h ; XBIOS Funktion ; CHRMTX equ 0b800h ; Zeichenmatrix COMRAM equ 0c000h ; Common Memory ; MTRX equ 8 ; Laenge einer Matrix ; ; Die neuen Zeichen ; NZ$TAB: db @lrand db 10000000b db 01000000b db 00100000b db 00010000b db 00001000b db 00000100b db 00000010b db 00000001b chmtx equ $-NZ$TAB db @rrand db 00000001b db 00000010b db 00000100b db 00001000b db 00010000b db 00100000b db 01000000b db 10000000b ; db @senkr db 00010000b db 00010000b db 00010000b db 00010000b db 00010000b db 00010000b db 00010000b db 00010000b ; db @obrand db 00011000b db 01100110b db 10000001b db 00000000b db 00000000b db 00000000b db 00000000b db 00000000b chlen equ $-NZ$TAB chitm equ chlen / chmtx AZ$TAB: ds chlen ; Speicher fuer alte Matrizen ; ; Neue Zeichen definieren ; ZeichenNeu: ld hl,Cod1 ld de,XBIOS ld bc,codl1 ldir ; Maschinencode abspeichern ld hl,(OS+1) ld de,3*(_USERF-1) add hl,de ld (XBIOS+1),hl ; XBIOS Vektor setzen call Rout1 ; Vorhandene Zeichen abspeichern ld hl,Cod2 ld de,Rout2 ld bc,codl2 ldir ; Weiteren Maschinencode abspeichern ld hl,NZ$TAB jr SetzeZeichen ; ; Alte Zeichen zurueckschreiben ; ZeichenAlt: ld hl,AZ$TAB SetzeZeichen: ld (Rout2+1),hl ; Tabellenadresse eintragen call Rout2 ; Zeichen laden ret ; ; Maschinencode 1: Zu definierende Zeichen abspeichern ; Cod1: .phase COMRAM XBIOS: jp $-$ ; XBIOS Vektor ZBuff: ds chmtx ; Aktuelle Zeichenmatrix ; rout1: ld de,AZ$TAB ; Adresse der alten Tabelle ld hl,NZ$TAB ; .. und der neuen Tabelle ld b,chitm ; Laenge setzen cod1l: push bc push hl push de ld de,ZBuff push de ld a,(hl) ld (de),a ld bc,cc1 call XBIOS ; Alte Matrix laden dw _SCRRUN pop hl pop de ld bc,chmtx push bc ldir ; Matrix retten pop bc pop hl add hl,bc pop bc djnz cod1l ret ; cc1: ld a,(de) ; Zeichen laden inc de ld l,a ld h,0 add hl,hl ; *2 add hl,hl ; *4 add hl,hl ; *8 ld bc,CHRMTX add hl,bc ; Matrix adressieren ld bc,MTRX ldir ; Matrix retten ret .dephase codl1 equ $-Cod1 ; ; Maschinencode 2: Zeichen definieren ; Cod2: .phase COMRAM+3+chmtx rout2: ld hl,$-$ ; Adresse der Tabelle ld b,chitm ; Laenge setzen cod2l: push bc ld de,ZBuff push de ld bc,chmtx ldir ; Matrix umkopieren ex (sp),hl ld bc,cc2 call XBIOS dw _SCRRUN pop hl pop bc djnz cod2l ret ; cc2: ld a,(hl) ; Zeichen laden inc hl push hl ld l,a ld h,0 add hl,hl ; *2 add hl,hl ; *4 add hl,hl ; *8 ld de,CHRMTX add hl,de ; Matrix adressieren push hl pop de pop hl ld bc,MTRX ldir ; Zeichen laden ret .dephase codl2 equ $-Cod2 TOP:: end Irrgarten