%include "parameter" || parameter.m
|| Stein und Spielfeld sind jeweils rechteckige Strukturen
|| aus Zellen. In den unteren Funktionen ist die erste Zellstruktur
|| das Spielfeld, die zweite der Stein inklusive relativer Koordinaten.
||
|| Dieser Abschnitt erscheint mir Software-technisch nicht so toll (WAM),
|| aber ich war im ersten/zweiten Semester...
koordinaten == (num,num)
|| Koordinaten z.B. eines Steins: oben links: (0,0)
tmaske == [char]
|| 0 = Leer, 1 = Voll, Rest wird ignoriert
abstype tzellen with
|| Erzeugungsfunktion: Maske ist Liste von '0'/'1', sonstige
|| Zeichen werden ignoriert, es wird mit Leerzeichen aufgefuellt
|| bzw. abgeschnitten, falls Hoehe und Breite nicht stimmen
neuezellen :: (tbreite,thoehe,tmaske) -> tzellen
|| Prueft, ob bei 2 Strukturen volle Zellen uebereinander liegen
kollisionsfrei :: tzellen -> koordinaten -> tzellen -> bool
|| Bildschirm und Stein werden uebereinandergelegt und ausgegeben
ausgabe :: tzellen -> koordinaten -> tzellen -> [char]
|| Bildschirm und Stein werden vereinigt
vereinigung :: tzellen -> koordinaten -> tzellen -> tzellen
zeilenloeschen :: tzellen -> tzellen
|| -----------------------------------------
|| Achtung! Implementation!
|| Diese Implementation implementiert eine Struktur als Tupel
|| (Breite, Hoehe, [Voll | Leer]
|| Dass jede Struktur nur 1 Liste ist, fuehrt zu ziemlich
|| fiesen Funktionen weiter unten.
|| Besser waere wohl eine Liste pro Zeile gewesen, also
|| [ [Voll|Leer] ] . Will's jemand umschreiben?
|| Typdefinition
tzellen == (tbreite,thoehe,[tzelle])
|| rechteckige Struktur, z.B Spielfeld
tbreite == num
|| breite der struktur
thoehe == num
|| hoehe der struktur
tzelle ::= Leer | Voll
|| jede Zelle der Struktur kann belegt oder nicht belegt sein
|| Aus Angaben ueber die Breite und Hoehe und mit
|| einer Maske wird eine neue Zellstruktur erzeugt:
neuezellen (breit,hoch,maske)
= (breit, hoch, neuezellen2 (breit*hoch) maske)
where
neuezellen2 0 maske
= []
neuezellen2 zaehler []
= rep zaehler Leer
neuezellen2 zaehler maske
= Voll : (neuezellen2 (zaehler-1) (tl maske)),
if hd maske = '1'
neuezellen2 zaehler maske
= Leer : (neuezellen2 (zaehler-1) (tl maske)),
if hd maske = '0'
neuezellen2 zaehler maske
= neuezellen2 zaehler (tl maske),
otherwise
|| Bildschirmausgabe der Ueberlagerung eines Spielfeldes
|| mit einem Stein:
ausgabe bild koordinaten stein
= randli ++ oben bild koordinaten stein
||= seq (force bildschirm) (randli ++ bildschirm)
where
|| Linker Rand:
|| Der Bildschirm wird (hoffentlich) geloescht (bei manchen
|| Verbindungen klappt dies nicht), und zwar mit dem
|| Kommando '\f' (Seitenvorschub, das ausgegeben wird.
|| Weiter wird der Bildschirm eingerueckt (siehe parameter.m).
randli
= '\f':(spaces randlinks)
|| nur ein alias
||bildschirm
||= oben bild koordinaten stein
|| Oben herausragende Bereiche des Steins werden abgeschnitten
oben bild (x,y) (brstein,hostein,stein)
= links bild x 0 brstein (hostein+y) (drop ((-y)*brstein) stein),
if y<0
= links bild x y brstein hostein stein,
if y>=0
|| Links herausragende Bereiche des Steins werden abgeschnitten
links bild x y brstein hostein stein
= rechts bild 0 y (brstein+x) (-x) hostein (drop (-x) stein),
if x<0
= rechts bild x y brstein 0 hostein stein,
if x>=0
|| Rechts herausragende Bereiche des Steins werden abgeschnitten
rechts (brbild,hobild,bild) x y innen aussen hostein stein
= ausdruck 0 brbild bild x y (innen-ueber) (aussen+ueber) hostein stein,
if ueber >0
= ausdruck 0 brbild bild x y innen aussen hostein stein,
if ueber <=0
where
ueber
= x+innen-brbild
|| Hintergrund und Steinrest werden ausgegeben,
|| jeweils 1 Zeichen, dann wird geguckt, ob der rechte Rand des
|| Bildes erreicht wird
ausdruck i brbild bild x y in aus hostein stein
= ['\n'],
if bild = []
= '[':']':rand (i+1) brbild (tl bild) x y in aus hostein (tl stein),
if imbereich & gefuellt
= ' ':' ':rand (i+1) brbild (tl bild) x y in aus hostein (tl stein),
if imbereich
= '[':']':rand (i+1) brbild (tl bild) x y in aus hostein stein,
if (hd bild = Voll)
= ' ':' ':rand (i+1) brbild (tl bild) x y in aus hostein stein,
if (hd bild = Leer)
where
imbereich
= (spalte>=x) & (spalte=y) & (zeile y) & ((j div brbild) < (y + hostein))
|| Ein Stein und das Spielfeld werden vereinigt.
|| Falls dadurch vollstaendig gefuellte Zeilen entstehen, werden diese
|| geloescht (ausgenommen der untersten Zeile, dem Boden).
vereinigung bild koordinaten stein
= zeilenloeschen (xbild bild, ybild bild, oben bild koordinaten stein)
|| Zur Erklaerung dieses schlechten Codes:
|| Eigentlich steht da
|| oben(links(rechts(vereinigen bild, koordinaten stein)))
|| Also werden zuerst (mal wieder) oben, links, rechts ueberstehende
|| Stuecke vom Stein abgeschnitten, und dann Bild und Stein vereinigt.
|| Auf da Ergebnis wird dann zeilenloeschen angewandt.
|| Viel Spass.
where
xbild (x,y,bild)
= x
ybild (x,y,bild)
= y
|| Oben herausragende Bereiche des Steins werden abgeschnitten
oben bild (x,y) (brstein,hostein,stein)
= links bild x 0 brstein (hostein+y) (drop ((-y)*brstein) stein),
if y<0
= links bild x y brstein hostein stein,
if y>=0
|| Links herausragende Bereiche des Steins werden abgeschnitten
links bild x y brstein hostein stein
= rechts bild 0 y (brstein+x) (-x) hostein (drop (-x) stein),
if x<0
= rechts bild x y brstein 0 hostein stein,
if x>=0
|| Rechts herausragende Bereiche des Steins werden abgeschnitten
rechts (brbild,hobild,bild) x y innen aussen hostein stein
= vereinigen 0 brbild bild x y (innen-ueber) (aussen+ueber) hostein stein,
if ueber >0
= vereinigen 0 brbild bild x y innen aussen hostein stein,
if ueber <=0
where
ueber
= x+innen-brbild
|| Bildschirm und Steinrest werden vereinigt
vereinigen i brbild bild x y in aus hostein stein
= [],
if bild = []
= Voll:rand (i+1) brbild (tl bild) x y in aus hostein (tl stein),
if imbereich & gefuellt
= Leer:rand (i+1) brbild (tl bild) x y in aus hostein (tl stein),
if imbereich
= Voll:rand (i+1) brbild (tl bild) x y in aus hostein stein,
if (hd bild = Voll)
= Leer:rand (i+1) brbild (tl bild) x y in aus hostein stein,
if (hd bild = Leer)
where
imbereich
= (spalte>=x) & (spalte=y) & (zeile y) & ((j div brbild) < (y + hostein))
|| Volle Zeilen, werden geloescht, wenn es sich nicht um die
|| letzte Zeile (den Boden) handelt
zeilenloeschen (x,y,bild)
= (x,y,loeschen x y bild [] 0)
loeschen breite hoehe bild bildneu geloescht
= leerzeilen breite (bildneu++bild) geloescht, if hoehe = 1
= loeschen breite (hoehe-1) (drop breite bild) bildneu (geloescht+1),
if (voll zeile)
= loeschen breite (hoehe-1) (drop breite bild) (bildneu++zeile) geloescht,
if ~(voll zeile)
where
zeile = take breite bild
voll [] = True
voll z = voll (tl z), if (hd z = Voll)
voll z = False, if (hd z = Leer)
leerzeilen breite bild 0
= bild
leerzeilen breite bild geloescht
= leerzeilen breite (leerzeile++bild) (geloescht-1)
where
leerzeile = Voll : (rep (breite-2) Leer) ++ [Voll]
|| Prueft, ob Stein und Bildschirm Kollisionen haben,
|| Zwei volle Zellen also uebereinanderliegen
|| Noch dabei? Den Codeaufbau muessten Sie jetzt kennen...
kollisionsfrei (brbild,hobild,bild) (x,y) (brstein,hostein,stein)
= oben brbild hobild bild x y brstein hostein stein brstein
where
||1. ragt Stein oben heraus?
oben brbild hobild bild x y brstein hostein stein brschnitt
= unten brbild hobild bild x 0 brstein (hostein+y) unterteil brschnitt,
if y<0
= unten brbild hobild bild x y brstein hostein stein brschnitt,
if y>=0
where
unterteil
= drop ((-y)*brstein) stein
||2. ragt Stein unten heraus?
unten brbild hobild bild x y brstein hostein stein brschnitt
= links brbild hobild bild x y brstein (hobild-y) stein brschnitt,
if (y+hostein)>hobild
= links brbild hobild bild x y brstein hostein stein brschnitt,
if (y+hostein)<=hobild
||3. ragt Stein links heraus?
links brbild hobild bild x y brstein hostein stein brschnitt
= rechts brbild hobild bild 0 y brstein hostein rechtsteil (brstein+x),
if x<0
= rechts brbild hobild bild x y brstein hostein stein brschnitt,
if x>=0
where
rechtsteil = drop (-x) stein
||4. ragt Stein rechts heraus?
rechts brbild hobild bild x y brstein hostein stein brschnitt
= vergleich hostein brbild bildrest brstein stein (brbild-x),
if (x+brschnitt)>brbild
= vergleich hostein brbild bildrest brstein stein brschnitt,
if (x+brschnitt)<=brbild
where
bildrest
= drop (brbild*y+x) bild
||5. Vergleich
vergleich zaehler brbild bild brstein stein brschnitt
= kofrei (take brschnitt bild) (take brschnitt stein),
if zaehler=1
= vergleich (zaehler-1) brbild restbild brstein reststein brschnitt,
if kofrei (take brschnitt bild) (take brschnitt stein)
= False,
otherwise
where
restbild
= drop brbild bild
reststein
= drop brstein stein
kofrei [] []
= True
kofrei (x:xx) (y:yy)
= False,
if ((x=Voll) & (y=Voll))
= kofrei xx yy,
otherwise