title GOBBLE fuer SOL name ('GOBBLE') include solvdm.lib ; Das Spiel GOBBLE fuer den SOL-Computer ; Race the clock to pick up as many pieces as you can ; Disassemblierte Version fuer CP/M ; ; Wegen der Disassemblierung sind die Kommentare vielleicht ; nicht immer richtig! ; ; ######################################################### ; # Angepasst an den JOYCE, Werner Cirsovius, Januar 2003 # ; ######################################################### extrn SOLon,SOLOS,VDMclr extrn CONsta,CONdat,CONin _NL equ 0feh _EOT equ 0ffh _man equ _bel ; Symbol fuer Spieler _bush equ _dwn+MSB _dand equ '*' ; Symbol fuer Loewenzahn _dandv equ _dand+MSB _blnk equ ' '+MSB _inc equ 25 MaxDand equ 0580h dandc equ 500 $DANDC macro db '500' endm DELVAL equ 0ffffh ; Maximaler Wert fuer Verzoegerung xy.bc macro x,y ld bc,SOLvid+y*maxcol+x endm xy.hl macro x,y ld hl,SOLvid+y*maxcol+x endm Score: dw 0 ; Punktzahl HiScore: dw 0 ; Bestwert ; ; Zufallszahl in Akku und Register C holen ; Random: ld hl,(RndPtr) ; Listenadresse holen ld a,l push bc ld bc,RndPtr-1 sub c ; Test ob Liste durchgesucht ist pop bc jr z,NewRnd ; Ja ld a,(hl) ; Byte laden inc hl add a,(hl) ; Kombinieren dec hl ld (hl),a ; Abspeichern ld c,a ; Wert holen inc hl RndStor: ld (RndPtr),hl ; Adresse speichern ret NewRnd: ld a,(RndList) ; Ersten Eintrag holen add a,(hl) ; Addieren ld (hl),a ; Und speichern ld c,a ; Wert holen ld hl,RndList ; Zeiger auf Anfang jr RndStor ; Und eintragen ; RndList: db 0feh,013h,095h,062h,087h,0a7h,0b2h db 0a3h,00ch,0f4h,0e6h,0ddh,04ch,001h db 058h RndPtr: dw RndList ; ; Videospeicher loeschen ; ClrVDM: ld_hl_8 ' ' ; Speicher loeschen inc hl ld a,h cp HIGH VidTop jr nz,ClrVDM ret ; ; Textausgabe ^DE in Speicher ^BC ; strgVID: ld h,b ; Speicheradresse kopieren ld l,c ld a,(de) ; Zeichen holen sub _EOT ; Test ob Ende ret z ; Ja ld a,(de) ; Spalte laden add a,l ; Speicheradresse berechnen jr nc,strgRow1 inc h ; Zeilenuebertrag beachten strgRow1: ld l,a strgNxt: inc de ld a,(de) ; Zeichen holen sub _NL ; Test neue Zeile jr nz,strgChar ; Nein inc de ld a,c add a,maxcol ; Spalte erhoehen jr nc,strgRow2 inc b ; Naechste Zeile strgRow2: ld c,a jr strgVID ; Naechste Ausgabe strgChar: ld a,(de) ; Zeichen holen ld_hl_a ; Ausgabe auf Bildschirm inc hl jr strgNxt ; ; ASCII Zahl ^HL um Wert in reg DE erhoehen ; incASCII: ld a,e ; Wert holen or d ; Test ob Null ret z ; Ja, fertig dec de ; Runterzaehlen ld c,l ; Spalte kopieren DoInc: ld_a_hl ; Ziffer laden inc a ; Ziffer hochzaehlen ld_hl_a and NOMSB ; Videoattribut aus cp '9'+1 ; Test ob Ueberlauf jr z,IncFix ; Ja ld l,c ; Spalte zurueckladen jr incASCII ; Weiter erhoehen IncFix: ld_a_hl ; Ziffer holen sub 10 ; Korrektur ld_hl_a ; Und speichern dec l ; Auf vorige Spalte stellen jr DoInc ; Diese dann erhoehen ; ; Zeichen von Tastatur holen ; Kein Zeichen vorhanden falls Z gesetzt ist ; GetChr: call CONsta ; Tastaturstatus holen ret z ; Kein Zeichen vorhanden call CONdat ; Zeichen holen cp esc ; Test ob Abbruch jp z,SOLOS ; Ja ret ; ; #################### ; ### Start GOBBLE ### ; #################### ; GOBBLE: ld sp,LocStk ; Lokalen Stack laden call SOLon ; SOL einschalten xy.bc 0,0 ; Videoadresse laden ld de,$RULES call strgVID ; Spielregeln ausgeben WtAccept: call Random ; Zufallszahl ermittlen call GetChr ; Zeichen holen jr z,WtAccept ; Noch nicht cp ' ' ; Test ob echte Annahme jr nz,WtAccept ld hl,0 ld (HiScore),hl ; Bestwert einstellen ; ; Naechste Feldstufe ; MoreFields: ld hl,0 ld (Score),hl ; Punktzahl loeschen call VDMclr ; Videospeicher loeschen call PresetBoard ; Spielfeld einstellen xy.bc 0,0 ; Videoadresse laden ld de,$PUNKTE call strgVID ; Zeile mit Punktzahl ausgeben xy.bc 0,15 ; Adresse des Videospeichers laden ld de,$WTKEY call strgVID ; Weiter mit Taste ausgeben xy.hl 0,0 ; Linke Seite laden call BlnkVert ; Linke Spalte loeschen xy.hl maxcol-1,0 call BlnkVert ; Rechte Spalte loeschen xy.hl 0,0 call HiliteLine ; Erste Zeile hell xy.hl 0,15 ; Adresse des Videospeichers laden call HiliteLine ; Letzte Zeile hell ld hl,(HiScore) ; Bestwert laden ex de,hl xy.hl 55,0 ; Adresse des Videospeichers laden call incASCII ; ASCII-Zahl um Punktzahl erhoehen ld a,_man ; Spieler eintragen ld (SOLvid+7*maxcol+32),a call CONin ; Zeichen holen sub a ld (BushCnt),a ; Buschzaehler loeschen ; ; Echter Spielbeginn ; ExeGobble: call FillDand ; Bildschirm mit Loewenzahn fuellen ld hl,0 ld (CurrDand),hl ; Anzahl Loewenzahn loeschen ld hl,MaxDand ld (DandCount),hl ; Loewenzahnzaehler setzen xy.hl 32,7 ld (PlayPos),hl ; Spielerposition speichern ld_hl_8 _man ; Spieler eintragen xy.hl 0,0 call BlnkVert ; Linke Spalte loeschen xy.hl maxcol-1,0 call BlnkVert ; Rechte Spalte loeschen call LastHilite ; Letzte Zeile loeschen ld a,(BushCnt) ; Zahl der Buesche laden add a,_inc ; Zahle erhoehen ld (BushCnt),a ld b,a ; Und laden NoBush: call Random ; Zufallszahl ermitteln xy.hl 0,0 ; Adresse des Videospeichers laden NxtRow: sub maxcol ; Zufallszahl testen jr c,GotRow inc h ; Auf naechste Zeile jr NxtRow GotRow: ex de,hl call Random ; Zufallszahl holen ex de,hl ld l,a ; Als Spalte eintragen ld_a_hl ; Spielstein holen cp _dandv ; Test ob Loewenzahn jr nz,NoBush ; Ignorieren wenn nicht ld_hl_8 _bush ; Mit Busch ueberschreiben djnz NoBush ; Bis alle Buesche verteilt sind sub a ld (CurrDir),a ; Richtung loeschen IniPlay: ld b,5 ; Zeitwert setzen InpMove: ld c,255 ; Zeitwert erweitern InpDir: call GetChr ; Zeichen holen jr z,IllDir ; Keins da cp '1' ; 1..9 verifizieren jr c,IllDir cp '9'+1 jr nc,IllDir sub '0' ; Daraus Ziffer 1..9 ld hl,DirTab-1 ; Zeiger laden push bc ld a,c ld b,0 add hl,bc ; Position auf Richtung pop bc ld a,(hl) ; Richtung holen ld (CurrDir),a ; Speichern IllDir: dec c jr nz,InpDir ; Es ist noch Zeit djnz InpMove ld a,(CurrDir) ; Richtung holen or a ; Test ob Aenderung jr z,NoMove ; Nein ld hl,(PlayPos) ; Richtung des Spielers holen ld c,a and MSB ; Test Richtung nach oben jp nz,MoveUp ; Ja ld a,l add a,c ; Richtung berechnen ld l,a jr nc,MoveChk inc h jr MoveChk MoveUp: ld a,c and NOMSB ; Bit abschalten ld c,a ld a,l sub c ; Richtung berechnen ld l,a jr nc,MoveChk dec h MoveChk: ld_a_hl ; Spielstein laden cp _dandv ; Test ob Loewenzahn jr z,HitDandy ; Ja cp ' ' ; Test ob leer jr nz,NoMove ; Nein ; ; Spieler bewegen ; MovPlay: ex de,hl ld hl,(PlayPos) ; Position des Spielers holen ld_hl_8 ' ' ; Als leer kennzeichnen ex de,hl ; Aktuelle Position laden ld_hl_8 _man ; Spieler eintragen ld (PlayPos),hl ; Neue Position des Spielers setzen ; ; Keine Richtung gewaehlt ; NoMove: ld hl,(DandCount) ; Anzahl Loewenzahn holen dec hl ; Runterzaehlen ld (DandCount),hl ld a,h or l ; Test ob noch welche uebrig sind jr nz,IniPlay ; Ja, Zeitwert auf Null ld de,(CurrDand) ; Anzahl Loewenzahn holen ld hl,(Score) ; Punktzahl holen add hl,de ; Neue Punktzahl ermitteln ld (Score),hl ; Neue Punktzahl speichern ld a,d cp HIGH dandc ; Test naechstes Feld jr c,NxtField ; Ja jr nz,FldDone ld a,e cp LOW dandc jr c,NxtField ; ; Ende eines Feldes ; FldDone: call RemDandy ; Restlichen Loewenzahn markieren jp ExeGobble ; Naechstes Spiel ; ; Loewenzahn gefunden ; HitDandy: push hl ; Aktuelle Position vom Loewenzahn speichern ld hl,(CurrDand) ; Aktuelle Anzahl Loewenzahn laden inc hl ; Das neue dazu zaehlen ld (CurrDand),hl xy.hl 18,0 ld de,1 call incASCII ; ASCII um eins hochzaehlen pop hl jr MovPlay ; Und weiter ; ; Spielfeld voreinstellen ; PresetBoard: call FillDand ; Bildschirm mit Loewenzahn fuellen xy.hl 0,15 ; Adresse der letzten Zeile call ClrVDM ; Letzte Zeile loeschen ret ; ; Restlichen Loewenzahn markieren ; RemDandy: xy.hl 0,0 ; Adresse des Videospeichers laden NxtDandy: ld_a_hl cp _dandv ; Test ob Loewenzahn jr nz,SkpDandy ; Nein ld_hl_8 _dand ; Als normal markieren SkpDandy: inc hl ld a,h cp HIGH VidTop ; Test ob alles durchgesehen wurde jr nz,NxtDandy ; Noch nicht ld hl,DELVAL jr EraseBrd ; Dann Spielfeld loeschen ; ; Neues Feld beginnen ; NxtField: call RemDandy ; Restlichen Loewenzahn markieren call VDMclr ; Videospeicher loeschen xy.bc 0,1 ; Adresse des Videospeichers laden ld de,$DANDEAT call strgVID ; Loewenzahnzeile voreinstellen ld de,(Score) ; Get Punktzahl holen xy.hl 11,1 call incASCII ; ASCII Zahl um Punktzahl erhoehen ld de,(Score) ; Punktzahl holen ld hl,(HiScore) ; Bestwert laden or a sbc hl,de ; Maximum pruefen jr nc,NotMax ; Kein Maximum xy.bc 0,4 ld (HiScore),de ; Bestwert einstellen ld de,$NEWHI call strgVID ; Bestwert ausgeben NotMax: xy.bc 0,7 ld de,$RATING call strgVID ; Einstufung ausgeben, Frage nach mehr WtMore: call CONin ; Zeichen holen cp 'N' ; Test ob nicht mehr jp z,SOLOS ; Ende falls ja cp 'J' ; Test ob mehr jr nz,WtMore jp MoreFields ; Neuer Start ; ; Spielfeld loeschen ; EraseBrd: call EraseDel ; Verzoegerung xy.hl 0,0 ; Adresse des Videospeichers laden WithinLine: ld_a_hl ; Spielstein holen cp _dand ; Test Loewenzahn jr nz,NotDandy ; Nein ld_hl_8 ' ' ; Loeschen NotDandy: inc hl ld a,h cp HIGH VidTop ; Test ob alles untersucht ist jr z,EraseRdy ; Ja ld a,l ; Position laden EraseFix: or a ; Test ob Begrenzung jr z,Boundary ; Ja sub maxcol jr c,WithinLine ; Test ob innerhalb einer Zeile jr EraseFix Boundary: ld a,DELVAL ShortDel: dec a ; Kurze Verzoegerung jr nz,ShortDel jr WithinLine EraseRdy: ld hl,DELVAL EraseDel: dec hl ; Letzte Verzoegerung ld a,h or l jr nz,EraseDel ret ; BushCnt: db 0 ; Buschzaehler ; ; Blank vertical line ; BlnkVert: ld_hl_8 _blnk ld a,l add a,maxcol ; Zeile erhoehen ld l,a jr nc,BlnkVert inc h ld a,h cp HIGH VidTop ; Test ob Ende jr nz,BlnkVert ret ; ; Eine Zeile hell zeichnen ; HiliteLine: ld b,maxcol ; Zaehler laden HiliteLoop: ld_a_hl ; Zeichen holen or MSB ; Hell markieren ld_hl_a inc hl djnz HiliteLoop ret ; ; Letzte Zeile hell zeichnen ; LastHilite: xy.hl 0,15 ; Adresse des Videospeichers laden AnyHilite: ld_hl_8 _blnk inc hl ld a,h cp HIGH VidTop ; Test Ende jr nz,AnyHilite ; Nein ret ; DandCount: dw 0 ; Zaehler fuer Loewenzahn CurrDand: dw 0 ; Aktuelle Anzahl Loewenzahn PlayPos: dw SOLvid+7*maxcol+32 ; ; Richtungstabelle ; CurrDir: db 0 ; Aktuelle Richtung DirTab: db maxcol-1 ; 1: Nach unten links db maxcol ; 2: Nach unten db maxcol+1 ; 3: Nach unten rechts db 2*maxcol+1 ; 4: Nach links db 0 ; 5: Keine Aenderung db 1 ; 6: Nach rechts db -(maxcol-1) ; 7: Nach oben links db -(maxcol) ; 8: Nach oben db -(maxcol+1) ; 9: Nach oben rechts ; ; Bildschirm mit Loewenzahn fuellen ; FillDand: xy.hl 0,1 ; Adresse der ersten Zeile FillDandLp: ld_hl_8 _dandv ; Auffuellen inc hl ld a,h cp HIGH VidTop ; Test ob Ende jr nz,FillDandLp ret ; $RULES: db 27 db 'GOBBLE ''EM' db _NL db 25 db 'VON RAY G WHITE' db _NL db 0 db _NL db 2 db 'Der Inhalt dieses Spieles ist, den eigenen Spieler (',_man,') auf dem' db _NL db 0 db 'Bildschirm zu bewegen, um den Loewenzahn (',_dandv,') zu verspeisen,' db _NL db 15 db 'wobei Buesche (',_bush,') zu vermeiden sind. Der Spieler' db _NL db 0 db '7 8 9 kann durch Betaetigung einer Taste fuer eine' db _NL db 2 db '\ ! / Richtung entsprechend dem Raster, wie links' db _NL db 0 db '4 - 5 - 6 abgebildet, bewegt werden. Er hat nur begrenzt' db _NL db 2 db '/ ! \ Zeit, um den Loewenzahn zu verspeisen, bevor der' db _NL db 0 db '1 2 3 austrocknet und verschwindet. Wenn jedoch ' $DANDC db _NL db 15 db 'oder mehr Loewenzahn von einem Feld verspeist' db _NL db 0 db 'wird, bekommt der Spieler genug Energie fuer ein weiteres Feld.' db _NL db 0 db 'Andernfalls verhungert der Spieler.' db _NL db 0 db _NL db 19 db '*WEITER MIT LEERZEICHEN*' db _NL db _EOT $RATING: db 0 db 'BEWERTUNG: ' ; 1111 ; 01234567890123 db '0000-0999: GRASSCHNEIDER' db _NL db 14 db '1000-2499: SENSE' db _NL db 14 db '2500-4999: RASENMAEHER' db _NL db 14 db '5000-9999: ERNTEMASCHINE' db _NL db 14 db '10000+ : MAEHDRESCHER' db _NL db 0 db _NL db 0 db 'NOCH EIN SPIEL? (Y OR N)' db _NL db _EOT $PUNKTE: db 7 db 'STAND: 00000 BESTWERT: 00000' ; 1111111111222222222233333333334444444444455555 ; 7890123456789012345678901234567890123456789012345 ; ^ ^ db _NL db _EOT $DANDEAT: db 0 db 'DU HAST 00000 LOEWENZAHN VERSPEIST.' ; 11 ; 012345678901 ; ^ db _NL db _EOT $WTKEY: db 20 db '*WEITER MIT BELIEBIGER TASTE*' db _NL db _EOT ; ; Hilite Version von ' NEUER BESTWERT! ' ; $NEWHI: db 8 db 0a0h,0ceh,0c5h,0d5h,0c5h,0d2h,0a0h,0c2h,0c5h db 0d3h,0d4h,0d7h,0c5h,0d2h,0d4h,0a1h,0a0h db _NL db _EOT ; ds 2*32 LocStk equ $ end GOBBLE