Wegfindung selber programmieren (als .dll / .so)
Verfasst: 23.08.2011 22:10
Wenn auch Ihr euch fragt wie findet eine Spielfigur alleine den Weg zum Ziel und sogar maist den kürzesten...
Ich hoffe ich kann Euch das anschaulich erklären, damit jeder in der Lage ist die Wegfindungsroutinen selber zu schreiben.
Als erstes was benötigt man:
a)Geduld {Hab ich am Anfang noch, schlägt aber schnell um}
b)Zettel und Stifte {es geht auch ein TabletPC, aber ich bin altmodisch}
c)ein Plan {den hab ich nicht }
Ich persönlich arbeite mit 2Listen, um mit einen mal möglichst viele Wege abzuarbeiten.
Der A-Algorytmus geht anders vor aber die Lib ist ja schon fertig...
Wenn man die Routine schreibt sollte man sich vorher überlegen:
Welche Befehle brauche ich? -> Befehl Finde_den_Weg() und NächsterSchritt()
Was soll der Befehl zurückgeben? ->Entweder den Nächsten Schritt oder den ganzen Weg
In Welcher Form soll der Befehl es zurückgeben? ->String oder Zahl
Welche Informationen benötigt der Befehl um zu funktionieren? -> {Berechne den WEG!!!} oder Startpunkt, Zielpunkt
und die KartenInformationen meist als Array.
Dann kommen noch die Überlegungen welche Variabeln benötige ich?? -> das kommt ganz drauf an, hier hilft meist nur ein Probeanlauf mit Bauchplanscher ( man kann es als gelungenen Fehlversuch sehen oder nur als Test).
Hier mein 3. Anlauf für die Lib: Erstma der StichZETTEL:
Variabeln:
StartX.i , StartY.i, ZielX.i, ZielY.i ->Achtung Dimensionslage (wird bei For Next wichtig)
Wasistbetreten.i, Wasistnichtbetreten.i ->Damit der Computer weiss, wo er hintreten darf.
Array Karte.i(2) ->Karte mit 2Dimensionen X_Achse und Y_Achse
Gesicherte Variabeln nur in der Procedure Gültig:
KarteSizeX.i, KartesizeY.i ->Speichert Kartengrösse auch hier Dimensionslage
PointerImage-> hier hatte ich vorher Probleme da ein Array komplett übergeben wird, dafür also diese Lösung
ZaehlerX.i, ZaehlerY.i-> für die For Next Schleifen
List Wegfinder1() und Wegfinder2()->hier sind die lang erwarteten Listen
achja Weg_gefunden.b darf man nicht vergessen er speichert nur True und False ab->damit der PC weiss wann er aufhören darf
Tada hier ein grober Ablaufplan der Wegfindung:
1.Vorprüfen ob Ziel auf Start, oder Start nicht betretbar, oder Ziel nicht betretbar, oder ob der Startpunkt und/oder Zielpunkt innerhalb der Karte liegen.
Haben wir diese Fehler ausgeschlossen geht es weiter ...
2.Alles Initialisieren jetzt wo die grössten Fehler ausgemerzt sind werden alle protected Variabeln, Listen und Was weiss ich initialisiert.
3.Bild (Image) erstellen die Daten des Arrays werden ins Bild übertragen (als Farbcode daher die Limitierung der Untergrundeigenschaften auf 16777215 Möglichkeiten, da wir ganze 2Möglichkeiten nutzen kommen wir noch nicht in Schwirigkeiten)
4.Grosse SchleifeSie enthält die Schleife Wegfinder und die KopierenSchleife
a)Schleife Wegfinderunterscheidet 2 Varianten
I: Ist das Ziel in der Nähe?
II: Welche anderen Möglichkeiten habe ich wohin kann ich gehen.-> füge für jede Möglichkeit ein Element der 2.Liste hinzu.
b)Schleife Kopiere die 2.Liste in Liste Eins
I: Liste 1 löschen
II: Liste 2 in Liste 1 kopieren , man kann auch sagen ich erstelle die Liste1 neu mit den Daten der Liste 2
c)Liste 2 löschen
Ende der Grossen Schleife
So was habe ich vergessen ...... Ach Ja man malt bei jeden errechneten Schritt ein nicht_Betreten_Punkt auf das Image
und beim Prüfen nach verfügbaren Punkten wird das Bild zu Rate gezogen -> somit vermeidet man das Zurücklaufen.
Die Weg.dll oder Weg.so
die "HeaderDllWegfindung.pbi"
Und zum Testen:
Ich hoffe ich kann Euch das anschaulich erklären, damit jeder in der Lage ist die Wegfindungsroutinen selber zu schreiben.
Als erstes was benötigt man:
a)Geduld {Hab ich am Anfang noch, schlägt aber schnell um}
b)Zettel und Stifte {es geht auch ein TabletPC, aber ich bin altmodisch}
c)ein Plan {den hab ich nicht }
Ich persönlich arbeite mit 2Listen, um mit einen mal möglichst viele Wege abzuarbeiten.
Der A-Algorytmus geht anders vor aber die Lib ist ja schon fertig...
Wenn man die Routine schreibt sollte man sich vorher überlegen:
Welche Befehle brauche ich? -> Befehl Finde_den_Weg() und NächsterSchritt()
Was soll der Befehl zurückgeben? ->Entweder den Nächsten Schritt oder den ganzen Weg
In Welcher Form soll der Befehl es zurückgeben? ->String oder Zahl
Welche Informationen benötigt der Befehl um zu funktionieren? -> {Berechne den WEG!!!} oder Startpunkt, Zielpunkt
und die KartenInformationen meist als Array.
Dann kommen noch die Überlegungen welche Variabeln benötige ich?? -> das kommt ganz drauf an, hier hilft meist nur ein Probeanlauf mit Bauchplanscher ( man kann es als gelungenen Fehlversuch sehen oder nur als Test).
Hier mein 3. Anlauf für die Lib: Erstma der StichZETTEL:
Variabeln:
StartX.i , StartY.i, ZielX.i, ZielY.i ->Achtung Dimensionslage (wird bei For Next wichtig)
Wasistbetreten.i, Wasistnichtbetreten.i ->Damit der Computer weiss, wo er hintreten darf.
Array Karte.i(2) ->Karte mit 2Dimensionen X_Achse und Y_Achse
Gesicherte Variabeln nur in der Procedure Gültig:
KarteSizeX.i, KartesizeY.i ->Speichert Kartengrösse auch hier Dimensionslage
PointerImage-> hier hatte ich vorher Probleme da ein Array komplett übergeben wird, dafür also diese Lösung
ZaehlerX.i, ZaehlerY.i-> für die For Next Schleifen
List Wegfinder1() und Wegfinder2()->hier sind die lang erwarteten Listen
achja Weg_gefunden.b darf man nicht vergessen er speichert nur True und False ab->damit der PC weiss wann er aufhören darf
Tada hier ein grober Ablaufplan der Wegfindung:
1.Vorprüfen ob Ziel auf Start, oder Start nicht betretbar, oder Ziel nicht betretbar, oder ob der Startpunkt und/oder Zielpunkt innerhalb der Karte liegen.
Haben wir diese Fehler ausgeschlossen geht es weiter ...
2.Alles Initialisieren jetzt wo die grössten Fehler ausgemerzt sind werden alle protected Variabeln, Listen und Was weiss ich initialisiert.
3.Bild (Image) erstellen die Daten des Arrays werden ins Bild übertragen (als Farbcode daher die Limitierung der Untergrundeigenschaften auf 16777215 Möglichkeiten, da wir ganze 2Möglichkeiten nutzen kommen wir noch nicht in Schwirigkeiten)
4.Grosse SchleifeSie enthält die Schleife Wegfinder und die KopierenSchleife
a)Schleife Wegfinderunterscheidet 2 Varianten
I: Ist das Ziel in der Nähe?
II: Welche anderen Möglichkeiten habe ich wohin kann ich gehen.-> füge für jede Möglichkeit ein Element der 2.Liste hinzu.
b)Schleife Kopiere die 2.Liste in Liste Eins
I: Liste 1 löschen
II: Liste 2 in Liste 1 kopieren , man kann auch sagen ich erstelle die Liste1 neu mit den Daten der Liste 2
c)Liste 2 löschen
Ende der Grossen Schleife
So was habe ich vergessen ...... Ach Ja man malt bei jeden errechneten Schritt ein nicht_Betreten_Punkt auf das Image
und beim Prüfen nach verfügbaren Punkten wird das Bild zu Rate gezogen -> somit vermeidet man das Zurücklaufen.
Die Weg.dll oder Weg.so
Code: Alles auswählen
;WegFindungsroutinen
;17.08.2011-
;OhmStudios Markus
#Version=20110828
Enumeration
#X_ist_Vorne=1
#Y_ist_Vorne
#Start
#Stop
EndEnumeration
Enumeration
#NoWay=0
#Vorwaerts
#Rueckwaerts
#LinkeRichtung
#RechteRichtung
#EtageHoch
#EtageRunter
EndEnumeration
;1. Position obenlinks ist 0/0
;Limitierung auf 8192x8192 Bildpunkte sofern möglich
Structure PunktdllWegfindung
X.i
Y.i
EndStructure
Structure Weg; Weg zum Speichern nur String und Zur Koordinierung Die letzte Position
SpeichereWeg.s
LastPosition.PunktdllWegfindung
EndStructure
ProcedureDLL.i WelchesSystem()
Protected Groesse.i
ProcedureReturn SizeOf(Groesse)*8; gibt 64 oder 32 zurück für Systemprüfung
EndProcedure
ProcedureDLL.i Version()
ProcedureReturn #Version
EndProcedure
ProcedureDLL.i NaechsterSchritt(*WegstreckenString.s)
Protected tempstr.s
If Left(*WegstreckenString,3)="-+-" ;Prüfe ob Weg ferfügbar
ProcedureReturn #NoWay
ElseIf Left(*WegstreckenString,3)="+++"; hier ist ein Weg ferfügbar
If Len(*WegstreckenString)>4
tempstr=Mid(*WegstreckenString,4,1)
*WegstreckenString="+++"+Right(*WegstreckenString, (Len(*WegstreckenString)-4 ))
ProcedureReturn Val(tempstr)
Else; Wenn nur noch ein Schritt fehlt
tempstr=Mid(*WegstreckenString,4,1)
*WegstreckenString="-+-"
ProcedureReturn Val(tempstr)
EndIf
Else; Falscher String nicht von der dll
;Print("Ungueltiger String")
ProcedureReturn #NoWay
EndIf
EndProcedure
ProcedureDLL.s FindedenWegdurchBetretenFelder( StartX.i, StartY.i, ZielX.i, ZielY.i, WasIstBetreten.i, WasIstNichtBetreten.i, Array Karte.i(2));Dll für 4 Richtungen vorwärts Rückwärts Links Rechts
;Deklariere Gesicherte Variabeln und Listen
; OpenConsole()
; Print("Eröffnet"+Chr(10))
Protected.b WegGefunden=#False ;True wenn Weg gefunden wurde
Protected.PunktdllWegfindung KarteDim, StartPunkt, ZielPunkt ;Speichert die Breite und Länge der Karte
Protected.i PointerImage, ZaehlerX, ZaehlerY, Dimensionslage
Protected NewList Wegfinder1.Weg();Liste 1 zum Abarbeiten nachster Schritt
Protected NewList Wegfinder2.Weg();Liste 2 zum Speichern der Ergebnisse aus Liste 1
Protected.s TempString; Temporärer String
Protected.i WegVorwaerts=#Vorwaerts, WegRueckwaerts=#Rueckwaerts, WegLinks=#LinkeRichtung, WegRechts=#RechteRichtung
; Print("Vorpruefen"+Chr(10))
;Vorprüfen
If StartX<0 Or StartX>ArraySize(Karte(),1) Or ZielX<0 Or ZielX>ArraySize(Karte(),1) Or StartY<0 Or StartY>ArraySize(Karte(),2) Or ZielY<0 Or ZielY>ArraySize(Karte(),2)
ProcedureReturn "-+- Start/Ziel ausserhalb der Karte"
ElseIf Karte( StartX, StartY )=WasIstNichtBetreten
ProcedureReturn "-+- Start nicht möglich"
ElseIf Karte( ZielX, ZielY )=WasIstNichtBetreten
ProcedureReturn "-+- Ziel nicht möglich"
ElseIf StartX=ZielX And ZielY=StartY
ProcedureReturn "-+- Ziel erreicht"
EndIf
; Print("Alles initialisieren"+Chr(10))
;Alles Initialisieren
StartPunkt\X=StartX
StartPunkt\Y=StartY
ZielPunkt\X=ZielX
ZielPunkt\Y=ZielY
If ArraySize(Karte(),1)>=ArraySize(Karte(),2);Dimensionen festlegen : Wo ist die Breite Wo die Länge
Dimensionslage=#X_ist_Vorne
KarteDim\X=ArraySize(Karte(),1)
KarteDim\Y=ArraySize(Karte(),2)
Else
Dimensionslage=#Y_ist_Vorne
KarteDim\X=ArraySize(Karte(),2)
KarteDim\Y=ArraySize(Karte(),1)
Swap StartPunkt\X, StartPunkt\Y ;Tausche X- mit Y-Achse
Swap ZielPunkt\X, ZielPunkt\Y ;Auch hier tauschen
Swap WegVorwaerts, WegLinks;Passe Richtung an
Swap WegRueckwaerts, WegRechts;Passe Richtung an
EndIf
AddElement(Wegfinder1())
Wegfinder1()\LastPosition\X=StartPunkt\X
Wegfinder1()\LastPosition\Y=StartPunkt\Y
Wegfinder1()\SpeichereWeg="+++"
; Print("Bild erstellen"+Chr(10))
;Bild erstellen: Image da dies auch ohne Sprites geht
PointerImage=CreateImage(#PB_Any,KarteDim\X+5,KarteDim\Y+5)
; Print(Str(PointerImage)+Chr(10))
If PointerImage=#False
ProcedureReturn "-+- Prüfinstanz nicht einrichtbar"
ElseIf #False=StartDrawing(ImageOutput(PointerImage))
ProcedureReturn "-+- Prüfdraw nicht verfügbar"
EndIf
For ZaehlerX=0 To KarteDim\X
For ZaehlerY=0 To KarteDim\Y
Select Dimensionslage
Case #X_ist_Vorne
Plot(ZaehlerX, ZaehlerY, Karte(ZaehlerX, ZaehlerY))
Case #Y_ist_Vorne
Plot(ZaehlerX, ZaehlerY, Karte(ZaehlerY, ZaehlerX))
Default
ProcedureReturn "-+- Dimensionen sind falsch eingerichtet"
EndSelect
Next ZaehlerY
Next ZaehlerX
; Print("Grosse Schleife"+Chr(10))
;Grosse Schleife für 4 Richtungen
While WegGefunden=#False
; Print("Schleife Wegfinden"+Chr(10))
;Schleife Wegfinden
ResetList(Wegfinder1())
ForEach Wegfinder1()
If Wegfinder1()\LastPosition\Y>0;vorwärts
If Point( Wegfinder1()\LastPosition\X, Wegfinder1()\LastPosition\Y-1)=WasIstBetreten;Prüfen ob Betretbar
If Wegfinder1()\LastPosition\X=ZielPunkt\X And Wegfinder1()\LastPosition\Y-1=ZielPunkt\Y;Zielabfrage
TempString=Wegfinder1()\SpeichereWeg+Str(WegVorwaerts)
WegGefunden=#True
Else
AddElement(Wegfinder2())
Wegfinder2()\SpeichereWeg=Wegfinder1()\SpeichereWeg+Str(WegVorwaerts)
Wegfinder2()\LastPosition\X=Wegfinder1()\LastPosition\X
Wegfinder2()\LastPosition\Y=Wegfinder1()\LastPosition\Y-1
Plot(Wegfinder2()\LastPosition\X,Wegfinder2()\LastPosition\Y,WasIstNichtBetreten)
EndIf
EndIf
EndIf
If Wegfinder1()\LastPosition\Y<KarteDim\Y;rückwärts
If Point( Wegfinder1()\LastPosition\X, Wegfinder1()\LastPosition\Y+1)=WasIstBetreten;Prüfen ob Betretbar
If Wegfinder1()\LastPosition\X=ZielPunkt\X And Wegfinder1()\LastPosition\Y+1=ZielPunkt\Y;Zielabfrage
TempString=Wegfinder1()\SpeichereWeg+Str(WegRueckwaerts)
WegGefunden=#True
Else
AddElement(Wegfinder2())
Wegfinder2()\SpeichereWeg=Wegfinder1()\SpeichereWeg+Str(WegRueckwaerts)
Wegfinder2()\LastPosition\X=Wegfinder1()\LastPosition\X
Wegfinder2()\LastPosition\Y=Wegfinder1()\LastPosition\Y+1
Plot(Wegfinder2()\LastPosition\X,Wegfinder2()\LastPosition\Y,WasIstNichtBetreten)
EndIf
EndIf
EndIf
If Wegfinder1()\LastPosition\X>0;links
If Point( Wegfinder1()\LastPosition\X-1, Wegfinder1()\LastPosition\Y)=WasIstBetreten;Prüfen ob Betretbar
If Wegfinder1()\LastPosition\X-1=ZielPunkt\X And Wegfinder1()\LastPosition\Y=ZielPunkt\Y;Zielabfrage
TempString=Wegfinder1()\SpeichereWeg+Str(WegLinks)
WegGefunden=#True
Else
AddElement(Wegfinder2())
Wegfinder2()\SpeichereWeg=Wegfinder1()\SpeichereWeg+Str(WegLinks)
Wegfinder2()\LastPosition\X=Wegfinder1()\LastPosition\X-1
Wegfinder2()\LastPosition\Y=Wegfinder1()\LastPosition\Y
Plot(Wegfinder2()\LastPosition\X,Wegfinder2()\LastPosition\Y,WasIstNichtBetreten)
EndIf
EndIf
EndIf
If Wegfinder1()\LastPosition\X<KarteDim\X;rechts
If Point( Wegfinder1()\LastPosition\X+1, Wegfinder1()\LastPosition\Y)=WasIstBetreten;Prüfen ob Betretbar
If Wegfinder1()\LastPosition\X+1=ZielPunkt\X And Wegfinder1()\LastPosition\Y=ZielPunkt\Y;Zielabfrage
TempString=Wegfinder1()\SpeichereWeg+Str(WegRechts)
WegGefunden=#True
Else
AddElement(Wegfinder2())
Wegfinder2()\SpeichereWeg=Wegfinder1()\SpeichereWeg+Str(WegRechts)
Wegfinder2()\LastPosition\X=Wegfinder1()\LastPosition\X+1
Wegfinder2()\LastPosition\Y=Wegfinder1()\LastPosition\Y
Plot(Wegfinder2()\LastPosition\X,Wegfinder2()\LastPosition\Y,WasIstNichtBetreten)
EndIf
EndIf
EndIf
Next ; ForEach Schleife Wegfinder1()
; Print("Schleife kopieren"+Chr(10))
;Schleife Liste kopieren
If WegGefunden=#False
ClearList(Wegfinder1())
ResetList(Wegfinder2())
; Print(Str(ListSize(Wegfinder2()))+Chr(10))
If 1=<ListSize(Wegfinder2())
ForEach Wegfinder2()
AddElement(Wegfinder1())
Wegfinder1()\SpeichereWeg=Wegfinder2()\SpeichereWeg
Wegfinder1()\LastPosition\X=Wegfinder2()\LastPosition\X
Wegfinder1()\LastPosition\Y=Wegfinder2()\LastPosition\Y
Next;Kleine Schleife
ClearList(Wegfinder2())
; Print("Liste 2 gelöscht."+Str(ListSize(Wegfinder2()))+Chr(10))
ResetList(Wegfinder1())
Else
WegGefunden=#True ; Um Keine Unendliche Schleife zu erzeugen
TempString="-+- KeinWeg möglich"
EndIf
EndIf
; Print("Grosse Schleife durch"+Chr(10))
Wend
;Beende Sauber
StopDrawing()
; Print("Befreihe Image"+Chr(10))
FreeImage(PointerImage);-Hier wurde der Fehler verursacht
; Print("lösche Listen"+Chr(10))
ClearList(Wegfinder2())
ClearList(Wegfinder1())
ProcedureReturn TempString
EndProcedure
Code: Alles auswählen
;==========================================================================
; Generated with PureDLLHelper, Copyright ©2011 by Thomas <ts-soft> Schulz
;==========================================================================
Prototype FindedenWegdurchBetretenFelder( StartX.i, StartY.i, ZielX.i, ZielY.i, WasIstBetreten.i, WasIstNichtBetreten.i, Array Karte.i(2))
Prototype Version()
Prototype WelchesSystem()
Prototype NaechsterSchritt(WegstreckenString.s)
Global FindedenWegdurchBetretenFelder.FindedenWegdurchBetretenFelder
Global Version.Version
Global WelchesSystem.WelchesSystem
Global NaechsterSchritt.NaechsterSchritt
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
#Lib="Weg32.so"
CompilerCase #PB_OS_Windows
#Lib="Weg32.dll"
CompilerEndSelect
Procedure.i Weg_LoadDLL()
Protected hDLL.i
hDLL = OpenLibrary(#PB_Any, #Lib)
If hDLL <> 0
FindedenWegdurchBetretenFelder = GetFunction(hDLL, "FindedenWegdurchBetretenFelder")
Version = GetFunction(hDLL, "Version")
WelchesSystem = GetFunction(hDLL, "WelchesSystem")
NaechsterSchritt= GetFunction(hDLL,"NaechsterSchritt")
ProcedureReturn hDLL
EndIf
ProcedureReturn #False
EndProcedure
Enumeration
#NoWay=0
#Vorwaerts
#Rueckwaerts
#LinkeRichtung
#RechteRichtung
#EtageHoch
#EtageRunter
EndEnumeration
WegDllID=Weg_LoadDLL()
If WegDllID=0
End
EndIf
Code: Alles auswählen
;Hier teste ich die Weffindungs Dll
IncludeFile "headerdllWegfindung.pbi"
;-Erst ab hier sind die Befehle nutzbar
If Version()<20110823
End
EndIf
OpenConsole()
Dim KartenMaterial.i(16,15)
Restore Karte2
#KarteBreite=7
#KarteTiefe=8
For Y=0 To #KarteTiefe
For X=0 To #KarteBreite
Read.i KartenMaterial(X, Y)
Next X
Next Y
StartpunktX=1
StartpunktY=1
ZielpunktX=1
ZielpunktY=6
Global Wegstrecke.s
Wegstrecke=PeekS(FindedenWegdurchBetretenFelder(StartpunktX, StartpunktY, ZielpunktX, ZielpunktY, 0, 2, KartenMaterial()))
;Repeat
For Y=0 To #KarteTiefe
For X=0 To #KarteBreite
If StartpunktX=X And StartpunktY=Y
Print("C")
ElseIf ZielpunktX=X And ZielpunktY=Y
Print("Z")
Else
Select KartenMaterial(X,Y)
Case 0
Print(" ")
Case 2
Print("H")
EndSelect
EndIf
Next X
Print(Chr(10))
Next Y
Print(Chr(10))
Input()
Repeat
EnableGraphicalConsole(#True)
ClearConsole()
EnableGraphicalConsole(#False)
Richtung.i=NaechsterSchritt(Wegstrecke)
Select Richtung
Case #LinkeRichtung
StartpunktX=StartpunktX-1
Case #RechteRichtung
StartpunktX=StartpunktX+1
Case #Vorwaerts
StartpunktY=StartpunktY-1
Case #Rueckwaerts
StartpunktY=StartpunktY+1
Case #NoWay
Ende=3
EndSelect
For Y=0 To #KarteTiefe
For X=0 To #KarteBreite
If StartpunktX=X And StartpunktY=Y
Print("C")
ElseIf ZielpunktX=X And ZielpunktY=Y
Print("Z")
Else
Select KartenMaterial(X,Y)
Case 0
Print(" ")
Case 2
Print("H")
EndSelect
EndIf
Next X
Print(Chr(10))
Next Y
Print(Chr(10))
Delay(200)
Print(Wegstrecke+Chr(10))
Until Ende=3
Print("Sie haben Ihr Ziel erreicht")
Input()
End
DataSection
Karte1:
Data.i 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
Data.i 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data.i 2,2,2,2,0,2,2,2,2,2,2,2,2,0,0,0,2
Data.i 2,2,2,0,0,0,0,0,0,0,0,0,2,0,0,0,2
Data.i 2,2,0,0,0,2,2,2,2,2,0,0,0,0,0,0,2
Data.i 2,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2
Data.i 2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0,2
Data.i 2,2,2,2,0,0,0,2,2,2,2,2,2,0,0,0,2
Data.i 2,2,2,0,0,0,2,2,2,2,0,0,0,0,0,0,2
Data.i 2,2,2,0,2,2,2,2,2,2,2,0,0,0,2,2,2
Data.i 2,2,2,0,2,0,0,0,2,0,0,0,2,2,2,2,2
Data.i 2,2,2,0,0,0,2,0,0,0,2,0,0,0,2,2,2
Data.i 2,2,2,2,2,0,0,0,2,0,0,0,2,0,0,0,2
Data.i 2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2
Data.i 2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2
Data.i 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
Karte2:
Data.i 2,2,2,2,2,2,2,2
Data.i 2,0,2,2,2,2,2,2
Data.i 2,0,2,0,0,0,2,2
Data.i 2,0,0,0,2,0,2,2
Data.i 2,2,0,2,2,0,0,2
Data.i 2,2,0,0,0,2,0,2
Data.i 2,0,2,2,2,2,0,2
Data.i 2,0,0,0,0,0,0,2
Data.i 2,2,2,2,2,2,2,2
EndDataSection