sokoban parser done
authorMart Lubbers <mart@martlubbers.net>
Mon, 7 Mar 2016 14:05:18 +0000 (15:05 +0100)
committerMart Lubbers <mart@martlubbers.net>
Mon, 7 Mar 2016 14:05:18 +0000 (15:05 +0100)
code/.gitignore [new file with mode: 0644]
code/Sokoban.dcl
code/Sokoban.icl [new file with mode: 0644]

diff --git a/code/.gitignore b/code/.gitignore
new file mode 100644 (file)
index 0000000..bf86cd0
--- /dev/null
@@ -0,0 +1,2 @@
+Clean System Files
+a.out
index 32b5e11..631cf7d 100644 (file)
@@ -1,9 +1,11 @@
 definition module Sokoban
 
-:: SokobanPuzzle = {
-       width :: Int,
-       height :: Int,
-       data :: [[SokobanTile]]}
+from StdString import class toString
+
+:: SokobanPuzzle = Sokoban [[SokobanTile]]
 :: SokobanTile = Wall | Free | Box | Target | Agent
 
+instance toString SokobanTile
+instance toString SokobanPuzzle
+
 parse :: String *World -> (SokobanPuzzle, *World)
diff --git a/code/Sokoban.icl b/code/Sokoban.icl
new file mode 100644 (file)
index 0000000..9102bc1
--- /dev/null
@@ -0,0 +1,60 @@
+implementation module Sokoban
+
+import StdFile
+import StdList
+import StdString
+import StdMisc
+
+Start :: *World -> (String, *World)
+Start w
+# (s, w) = parse "../sokobanzip/screens/screen.1" w
+= ("\n" +++ toString s, w)
+
+instance toString SokobanPuzzle where
+       toString (Sokoban []) = ""
+       toString (Sokoban [[]:rows]) = "\n" +++ toString (Sokoban rows)
+       toString (Sokoban [[x:xs]:rows]) = 
+               toString x +++ toString (Sokoban [xs:rows])
+
+instance toString SokobanTile where
+       toString Free = " "
+       toString Wall = "#"
+       toString Box = "$"
+       toString Agent = "@"
+       toString Target = "."
+
+parse :: String *World -> (SokobanPuzzle, *World)
+parse fp w
+# (ok, f, w) = fopen fp FReadText w
+| not ok = abort ("Couldn't open file: '" +++ fp +++ "'")
+# (contents, f) = readEntireFile f
+| isEmpty contents = abort "File is empty or unreadable"
+# (ok, w) = fclose f w
+| not ok = abort "Couldn't close file"
+= (Sokoban (parseRows contents), w)
+
+parseRows :: [Char] -> [[SokobanTile]]
+parseRows cs = case parseRow cs of
+       ([], _) = []
+       (x, rest) = [x:parseRows rest]
+
+parseRow :: [Char] -> ([SokobanTile], [Char])
+parseRow [] = ([], [])
+parseRow ['\n':xs] = ([], xs)
+parseRow [x:xs]
+# (rest, xs) = parseRow xs
+# current = case x of
+       '#' = Wall
+       '$' = Box
+       '@' = Agent
+       '.' = Target
+       ' ' = Free
+       _ = abort ("Unknown char: '" +++ toString x +++ "'")
+= ([current:rest], xs)
+
+readEntireFile :: *File -> *([Char], *File)
+readEntireFile f
+# (b, c, f) = freadc f
+| not b = ([], f)
+# (cs, f) = readEntireFile f
+= ([c:cs], f)