move over rewritten lispreader from tuxkart (with additional fixes), generalized...
authorMatthias Braun <matze@braunis.de>
Sun, 28 Nov 2004 14:57:45 +0000 (14:57 +0000)
committerMatthias Braun <matze@braunis.de>
Sun, 28 Nov 2004 14:57:45 +0000 (14:57 +0000)
SVN-Revision: 2212

92 files changed:
TODO
data/images/worldmap/antarctica.stwt
data/levels/test/bonusblock.stl
data/levels/test/foresttheme.stl
data/levels/test/noloktest.stl
data/levels/test/sectors.stl
data/levels/test/simple.stl
lib/Jamfile
lib/audio/sound_manager.cpp
lib/lisp/lexer.cpp [new file with mode: 0644]
lib/lisp/lexer.h [new file with mode: 0644]
lib/lisp/lisp.cpp [new file with mode: 0644]
lib/lisp/lisp.h [new file with mode: 0644]
lib/lisp/list_iterator.cpp [new file with mode: 0644]
lib/lisp/list_iterator.h [new file with mode: 0644]
lib/lisp/parser.cpp [new file with mode: 0644]
lib/lisp/parser.h [new file with mode: 0644]
lib/lisp/writer.cpp [new file with mode: 0644]
lib/lisp/writer.h [new file with mode: 0644]
lib/special/sprite.h
lib/special/sprite_data.cpp
lib/special/sprite_data.h
lib/special/sprite_manager.cpp
lib/utils/configfile.cpp
lib/utils/configfile.h
lib/video/font.cpp
src/badguy/badguy.h
src/badguy/bomb.cpp
src/badguy/bomb.h
src/badguy/bouncing_snowball.cpp
src/badguy/bouncing_snowball.h
src/badguy/dispenser.cpp
src/badguy/dispenser.h
src/badguy/flame.cpp
src/badguy/flame.h
src/badguy/jumpy.cpp
src/badguy/jumpy.h
src/badguy/mrbomb.cpp
src/badguy/mrbomb.h
src/badguy/mriceblock.cpp
src/badguy/mriceblock.h
src/badguy/nolok_01.cpp
src/badguy/nolok_01.h
src/badguy/snowball.cpp
src/badguy/snowball.h
src/badguy/spike.cpp
src/badguy/spike.h
src/badguy/spiky.cpp
src/badguy/spiky.h
src/gameloop.cpp
src/high_scores.cpp [deleted file]
src/high_scores.h [deleted file]
src/level.cpp
src/level.h
src/level_subset.cpp
src/level_subset.h
src/leveleditor.cpp
src/misc.cpp
src/misc.h
src/object/background.cpp
src/object/background.h
src/object/camera.cpp
src/object/camera.h
src/object/gameobjs.cpp
src/object/gameobjs.h
src/object/particlesystem.cpp
src/object/particlesystem.h
src/object/platform.cpp
src/object/platform.h
src/object/tilemap.cpp
src/object/tilemap.h
src/resources.cpp
src/resources.h
src/sector.cpp
src/sector.h
src/serializable.h
src/statistics.cpp
src/statistics.h
src/supertux.cpp
src/tile.cpp
src/tile.h
src/tile_manager.cpp
src/tile_manager.h
src/title.cpp
src/trigger/door.cpp
src/trigger/door.h
src/trigger/secretarea_trigger.cpp
src/trigger/secretarea_trigger.h
src/trigger/sequence_trigger.cpp
src/trigger/sequence_trigger.h
src/worldmap.cpp
src/worldmap.h

diff --git a/TODO b/TODO
index 00e6b59..d26e624 100644 (file)
--- a/TODO
+++ b/TODO
@@ -68,7 +68,6 @@ L: low priority
 [L] rename gameloop.* files to gamesession.*
 [L] rename GameObject::action to GameObject::update()
 [L] use physfs for loading files
-[L] eventually move over new lispreader code from tuxkart
 [L] change physics class y-velocity-coordinate to be like all other
     y-coordinates again (positive y to go down)
 [M] harmonize to 1 single gameloop that switches between title, worldmap,
index 0315214..e8dfdb9 100644 (file)
@@ -2,59 +2,58 @@
 ;; (tile (id INT)
 ;;       (directions TOP RIGHT DOWN LEFT) 
 ;;
-(supertux-worldmap-tiles
-
+(supertux-tiles
  (tile (id 1)
-       (image "road_h.png")
+       (images "road_h.png")
        (north #f)
        (south #f)
        (west  #t)
        (east  #t)
        (stop #f))
  (tile (id 2)
-       (image "road_v.png")
+       (images "road_v.png")
        (north #t)
        (south #t)
        (west  #f)
        (east  #f)
        (stop #f))
  (tile (id 3)
-       (image "road_ws.png")
+       (images "road_ws.png")
        (north #f)
        (south #t)
        (west  #t)
        (east  #f)
        (stop #t))
  (tile (id 4)
-       (image "road_cross.png")
+       (images "road_cross.png")
        (north #t)
        (south #t)
        (west  #t)
        (east  #t)
        (stop #t))
  (tile (id 5)
-       (image "road_end.png")
+       (images "road_end.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #t)
        (stop #t))
  (tile (id 6)
-       (image "road_h_stop.png")
+       (images "road_h_stop.png")
        (north #f)
        (south #f)
        (west  #t)
        (east  #t)
        (stop #t))
  (tile (id 7)
-       (image "road_v_stop.png")
+       (images "road_v_stop.png")
        (north #t)
        (south #t)
        (west  #f)
        (east  #f)
        (stop #t))
  (tile (id 8)
-       (image "ground.png")
+       (images "ground.png")
        (north #f)
        (south #f)
        (east  #f)
        (stop  #f))
 
  (tile (id 9)
-       (image "water.png"))
+       (images "water.png"))
 
  (tile (id 11)
-       (image "snow1.png"))
+       (images "snow1.png"))
  (tile (id 12)
-       (image "snow2.png"))
+       (images "snow2.png"))
  (tile (id 13)
-       (image "snow3.png"))
+       (images "snow3.png"))
  (tile (id 14)
-       (image "snow4.png"))
+       (images "snow4.png"))
  (tile (id 15)
-       (image "snow5.png"))
+       (images "snow5.png"))
  (tile (id 16)
-       (image "snow6.png"))
+       (images "snow6.png"))
  (tile (id 17)
-       (image "snow7.png"))
+       (images "snow7.png"))
  (tile (id 18)
-       (image "snow8.png"))
+       (images "snow8.png"))
  (tile (id 19)
-       (image "snow9.png"))
+       (images "snow9.png"))
  (tile (id 20)
-       (image "snow10.png"))
+       (images "snow10.png"))
  (tile (id 21)
-       (image "snow11.png"))
+       (images "snow11.png"))
  (tile (id 22)
-       (image "snow12.png"))
+       (images "snow12.png"))
  (tile (id 23)
-       (image "snow13.png"))
+       (images "snow13.png"))
  (tile (id 24)
-       (image "wood1.png"))
+       (images "wood1.png"))
  (tile (id 25)
-       (image "wood2.png"))
+       (images "wood2.png"))
  (tile (id 26)
-       (image "wood3.png"))
+       (images "wood3.png"))
  (tile (id 27)
-       (image "wood4.png"))
+       (images "wood4.png"))
  (tile (id 28)
-       (image "wood5.png"))
+       (images "wood5.png"))
  (tile (id 29)
-       (image "wood6.png"))
+       (images "wood6.png"))
  (tile (id 30)
-       (image "wood7.png"))
+       (images "wood7.png"))
  (tile (id 31)
-       (image "wood8.png"))
+       (images "wood8.png"))
  (tile (id 32)
-       (image "wood9.png"))
+       (images "wood9.png"))
  (tile (id 33)
-       (image "wood10.png"))
+       (images "wood10.png"))
  (tile (id 34)
-       (image "wood11.png"))
+       (images "wood11.png"))
  (tile (id 35)
-       (image "wood12.png"))
+       (images "wood12.png"))
  (tile (id 36)
-       (image "wood13.png"))
+       (images "wood13.png"))
 
  (tile (id 37) 
-       (image "road_ne.png")
+       (images "road_ne.png")
        (stop  #f)
-       (auto-walk #t)
        (north #t)
        (south #f)
        (west  #f)
        (east  #t))
 
  (tile (id 38)
-       (image "road_nsw.png")
+       (images "road_nsw.png")
        (north #t)
        (south #t)
        (west  #t)
-       (east  #f))
+       (east  #f)
+       (stop  #t))
  (tile (id 39)
-       (image "road_sw.png")
+       (images "road_sw.png")
        (stop  #f)
-       (auto-walk #t)
        (north #f)
        (south #t)
        (west  #t)
        (east  #f))
  (tile (id 40)
-       (image "road_we.png")
+       (images "road_we.png")
        (north #f)
        (south #f)
        (west  #t)
        (east  #t)
        (stop  #f))
  (tile (id 41)
-       (image "road_nes.png")
+       (images "road_nes.png")
        (north #t)
        (south #t)
        (west  #f)
-       (east  #t))
+       (east  #t)
+       (stop  #t))
  (tile (id 42)
-       (image "road_nw.png")
+       (images "road_nw.png")
        (stop  #f)
-       (auto-walk #t)
        (north #t)
        (south #f)
        (west  #t)
        (east  #f))
  (tile (id 43)
-       (image "road_swe.png")
+       (images "road_swe.png")
        (north #f)
        (south #t)
        (west  #t)
-       (east  #t))
+       (east  #t)
+       (stop  #t))
  (tile (id 44)
-       (image "road_new.png")
+       (images "road_new.png")
        (north #t)
        (south #f)
        (west  #t)
-       (east  #t))
+       (east  #t)
+       (stop  #t))
  (tile (id 45)
-       (image "road_nesw.png")
+       (images "road_nesw.png")
        (north #t)
        (south #t)
        (west  #t)
-       (east  #t))
+       (east  #t)
+       (stop  #t))
  (tile (id 46)
-       (image "road_nws.png")
+       (images "road_nws.png")
        (north #t)
        (south #t)
        (west  #t)
-       (east  #f))
+       (east  #f)
+       (stop  #t))
  (tile (id 47)
-       (image "road_ns.png")
+       (images "road_ns.png")
        (north #t)
        (south #t)
        (west  #f)
        (east  #f)
        (stop  #f))
  (tile (id 48)
-       (image "road_se.png")
+       (images "road_se.png")
        (stop  #f)
-       (auto-walk #t)
        (north #f)
        (south #t)
        (west  #f)
 
  ;; castle
  (tile (id 49)
-       (image "castle1.png")
+       (images "castle1.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 50)
-       (image "castle2.png")
+       (images "castle2.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 51)
-       (image "castle3.png")
+       (images "castle3.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
 
  (tile (id 52)
-       (image "castle4.png")
+       (images "castle4.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 53)
-       (image "castle5.png")
+       (images "castle5.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 54)
-       (image "castle6.png")
+       (images "castle6.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
 
  (tile (id 55)
-       (image "castle7.png")
+       (images "castle7.png")
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 56)
-       (image "castle8.png")
+       (images "castle8.png")
        (stop  #t)
        (north #f)
        (south #f)
        (west  #f)
        (east  #t))
  (tile (id 57)
-       (image "castle9.png")
+       (images "castle9.png")
        (stop  #f)
        (north #f)
        (south #f)
        (east  #t))
 
  (tile (id 58)
-       (image "igloo1.png")
+       (images "igloo1.png")
        (stop #f)
        (north #f)
        (south #f)
        (west  #f)
        (east  #f))
  (tile (id 59)
-       (image "igloo2.png")
+       (images "igloo2.png")
        (stop #t)
        (north #f)
        (south #t)
        (east  #f))
 
  (tile (id 60)
-       (image "snowman.png")
+       (images "snowman.png")
        (north #f)
        (south #t)
        (west  #f)
  
  ;; Secret paths
  (tile (id 61)
-       (image "road_nws.png")
+       (images "road_nws.png")
        (north #t)
        (south #t)
        (west  #t)
        (east  #t))
   
   (tile (id 62)
-       (image "snow5.png")
+       (images "snow5.png")
        (stop  #f)
        (north #f)
        (south #f)
        (east  #t))
   
   (tile (id 63)
-       (image "water.png")
+       (images "water.png")
        (stop  #f)
        (north #f)
        (south #f)
        (east  #t))
   
   (tile (id 64)
-       (image "snow7.png")
+       (images "snow7.png")
        (stop  #f)
        (north #f)
        (south #f)
 
   ;;one-way vertical road
   (tile (id 65)
-    (image "road_ns.png")
+    (images "road_ns.png")
     (north #t)
     (south #t)
     (west  #f)
   
     ;;one-way horizontal road
   (tile (id 66)
-    (image "road_we.png")
+    (images "road_we.png")
     (north #f)
     (south #f)
     (west  #t)
   
   ;; Another invisible road
   (tile (id 67)
-     (image "snow9.png")
+     (images "snow9.png")
      (stop  #t)
      (north #f)
      (south #f)
          
   ;; End of the line
   (tile (id 68)
-     (image "road_n.png")
+     (images "road_n.png")
          (stop #t)
      (north #t)
      (south #f)
      (east  #f))
   
   (tile (id 69)
-     (image "road_e.png")
-         (stop #t)
+     (images "road_e.png")
+     (stop #t)
      (north #f)
      (south #f)
      (west  #f)
      (east  #t))
   
   (tile (id 70)
-     (image "road_s.png")
-         (stop #t)
+     (images "road_s.png")
+     (stop #t)
      (north #f)
      (south #t)
      (west  #f)
      (east  #f))
          
   (tile (id 71)
-     (image "road_w.png")
-         (stop #t)
+     (images "road_w.png")
+     (stop #t)
      (north #f)
      (south #f)
      (west  #t)
      (east  #f))
-
-
 )
-;; EOF ;;
index f8203cc..1a26873 100644 (file)
@@ -9,7 +9,7 @@
     (gravity 10.000000)
     (background (image "arctis.jpg")
                 (speed 0.5))
-    (spawn-points
+    (spawnpoint
       (name "main")
       (x 100)
       (y 170)
index e31d8c3..e3e90bf 100644 (file)
@@ -9,12 +9,12 @@
     (name "main")
     (gravity 10)
     (music "forest2.mod")
-    (spawn-points
+    (spawnpoint
       (name "main")
       (x 100)
       (y 100)
     )
-    (spawn-points
+    (spawnpoint
       (name "main")
       (x 6381)
       (y 201)
index 859c8bb..4ee451e 100644 (file)
@@ -11,7 +11,7 @@
     (background (image "forest1.jpg")
                 (speed 0.5))
     (music "Mortimers_chipdisko.mod")
-    (spawn-points (name "main") (x 100) (y 100))
+    (spawnpoint (name "main") (x 100) (y 100))
     (nolok_01 (x 650) (y 512))
     (tilemap
       (layer "background")
@@ -48,7 +48,7 @@
     (music "Mortimers_chipdisko.mod")
     (background (image "forest1.jpg")
                 (speed 0.5))
-    (spawn-points (name "main2") (x 100) (y 100))
+    (spawnpoint (name "main2") (x 100) (y 100))
     (secretarea (x 100) (y 100) (message "You found a secret area!"))
     (dispenser (x 700) (y 500) (badguy "snowball") (cycle 2))
     (tilemap
index 5ebefb1..fe437fb 100644 (file)
@@ -10,7 +10,7 @@
     (camera
       (mode "normal")
     )
-    (spawn-points
+    (spawnpoint
       (name "main")
       (x 100)
       (y 170)
@@ -90,7 +90,7 @@
       (sector "main")
       (spawnpoint "main")
     )
-    (spawn-points
+    (spawnpoint
       (name "main")    
       (x 300)
       (y 170)
index c78b5da..a42a7cb 100644 (file)
@@ -12,7 +12,7 @@
     (gravity 10.000000)
     (background (image "arctis.jpg")
                 (speed 0.5))
-    (spawn-points (name "main") (x 50) (y 200))
+    (spawnpoint (name "main") (x 50) (y 200))
     (tilemap
       (layer  "background")
       (solid #f)
index e38266a..07719c7 100644 (file)
@@ -8,6 +8,7 @@ sources =
     [ Wildcard special : *.cpp *.h ]
     [ Wildcard utils : *.cpp *.h ]
     [ Wildcard video : *.cpp *.h ]
+    [ Wildcard lisp : *.cpp *.h ]
 ;
 TRANSLATABLE_SOURCE += [ DoSourceGrist $(sources) ] ;
 
index 283fbba..0243f24 100644 (file)
@@ -33,7 +33,8 @@ using namespace SuperTux;
 SoundManager* SoundManager::instance_ = 0;
 
 SoundManager::SoundManager()
-  : current_music(0), m_music_enabled(true) , m_sound_enabled(true) , audio_device(true)
+  : current_music(0), m_music_enabled(true) , m_sound_enabled(true),
+    audio_device(true)
 {
 }
 
@@ -42,8 +43,7 @@ SoundManager::~SoundManager()
   if(audio_device)
     Mix_HaltMusic();
 
-sounds.clear();
-destroy_instance();
+  sounds.clear();
 }
 
 void
@@ -184,7 +184,8 @@ SoundManager::enable_music(bool enable)
   if(m_music_enabled == false) {
     Mix_HaltMusic();
   } else {
-    Mix_PlayMusic(current_music->music, -1);
+    if(current_music)
+      Mix_PlayMusic(current_music->music, -1);
   }
 }
 
diff --git a/lib/lisp/lexer.cpp b/lib/lisp/lexer.cpp
new file mode 100644 (file)
index 0000000..6b693f2
--- /dev/null
@@ -0,0 +1,221 @@
+//  $Id$
+//
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <sstream>
+#include <stdexcept>
+
+#include "lexer.h"
+
+namespace lisp
+{
+
+class EOFException
+{
+};
+
+Lexer::Lexer(std::istream& newstream)
+    : stream(newstream), eof(false), linenumber(0)
+{
+  try {
+    // trigger a refill of the buffer
+    c = 0;
+    bufend = c + 1;        
+    nextChar();
+  } catch(EOFException& e) {
+  }
+}
+
+Lexer::~Lexer()
+{
+}
+
+void
+Lexer::nextChar()
+{
+  ++c;
+  if(c >= bufend) {
+    if(eof)
+      throw EOFException();
+    std::streamsize n = stream.readsome(buffer, BUFFER_SIZE);
+
+    c = buffer;
+    bufend = buffer + n;
+
+    // the following is a hack that appends an additional ' ' at the end of
+    // the file to avoid problems when parsing symbols/elements and a sudden
+    // EOF. This is faster than relying on unget and IMO also nicer.
+    if(n == 0 || stream.eof()) {
+      eof = true;
+      *bufend = ' ';
+      ++bufend;
+    }
+  }
+}
+
+Lexer::TokenType
+Lexer::getNextToken()
+{
+  static const char* delims = "\"();";
+
+  try {
+    while(isspace(*c)) {
+      if(*c == '\n')
+        ++linenumber;
+      nextChar();
+    };
+    
+    token_length = 0;
+    
+    switch(*c) {
+      case ';': // comment
+        while(!stream.eof()) {
+          nextChar();
+          if(*c == '\n') {
+            ++linenumber;
+            break;
+          }
+        }
+        return getNextToken(); // and again
+      case '(':
+        nextChar();
+        return TOKEN_OPEN_PAREN;
+      case ')':
+        nextChar();
+        return TOKEN_CLOSE_PAREN;
+      case '"': {  // string
+        int startline = linenumber;
+        try {
+          while(1) {
+            if(stream.eof()) {
+              std::stringstream msg;
+              msg << "Parse Error in line " << startline << ": "
+                << "Couldn't find end of string.";
+              throw std::runtime_error(msg.str());
+            }
+            nextChar();
+            if(*c == '"')
+              break;
+            else if(*c == '\n')
+              linenumber++;
+            else if(*c == '\\') {
+              nextChar();
+              switch(*c) {
+                case 'n':
+                  *c = '\n';
+                  break;
+                case 't':
+                  *c = '\t';
+                  break;
+              }
+            }
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+          }
+          token_string[token_length] = 0;
+        } catch(EOFException& ) {
+          std::stringstream msg;
+          msg << "Parse error in line " << startline << ": "
+            << "EOF while parsing string.";
+          throw std::runtime_error(msg.str());
+        }
+        nextChar();
+        return TOKEN_STRING;
+      }
+      case '#': // constant
+        try {
+          nextChar();
+          
+          while(isalnum(*c) || *c == '_') {
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+            nextChar();
+          }
+          token_string[token_length] = 0;
+        } catch(EOFException& ) {
+          std::stringstream msg;
+          msg << "Parse Error in line " << linenumber << ": "
+            << "EOF while parsing constant.";
+          throw std::runtime_error(msg.str());
+        }
+
+        if(strcmp(token_string, "t") == 0)
+          return TOKEN_TRUE;
+        if(strcmp(token_string, "f") == 0)
+          return TOKEN_FALSE;
+
+        // we only handle #t and #f constants at the moment...
+
+        {
+          std::stringstream msg;
+          msg << "Parse Error in line " << linenumber << ": "
+            << "Unknown constant '" << token_string << "'.";
+          throw std::runtime_error(msg.str());
+        }
+
+      default:
+        if(isdigit(*c) || *c == '-') {
+          bool have_nondigits = false;
+          bool have_digits = false;
+          int have_floating_point = 0;
+          
+          do {
+            if(isdigit(*c))
+              have_digits = true;
+            else if(*c == '.')
+              ++have_floating_point;
+            else if(isalnum(*c) || *c == '_')
+              have_nondigits = true;  
+            
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+
+            nextChar();
+          } while(!isspace(*c) && !strchr(delims, *c));
+
+          token_string[token_length] = 0;
+          
+          // no nextChar
+
+          if(have_nondigits || !have_digits || have_floating_point > 1)
+            return TOKEN_SYMBOL;
+          else if(have_floating_point == 1)
+            return TOKEN_REAL;
+          else
+            return TOKEN_INTEGER;
+        } else {
+          do {
+            if(token_length < MAX_TOKEN_LENGTH)
+              token_string[token_length++] = *c;
+            nextChar();
+          } while(!isspace(*c) && !strchr(delims, *c));
+          token_string[token_length] = 0;
+          
+          // no nextChar
+
+          return TOKEN_SYMBOL;
+        }       
+    }
+  } catch(EOFException& ) {
+    return TOKEN_EOF;
+  }
+}
+
+} // end of namespace lisp
+
diff --git a/lib/lisp/lexer.h b/lib/lisp/lexer.h
new file mode 100644 (file)
index 0000000..5a2bc59
--- /dev/null
@@ -0,0 +1,70 @@
+//  $Id$
+//
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISPLEXER_H__
+#define __LISPLEXER_H__
+
+namespace lisp
+{
+
+class Lexer
+{
+public:
+  enum TokenType {
+    TOKEN_EOF,
+    TOKEN_OPEN_PAREN,
+    TOKEN_CLOSE_PAREN,
+    TOKEN_SYMBOL,
+    TOKEN_STRING,
+    TOKEN_INTEGER,
+    TOKEN_REAL,
+    TOKEN_TRUE,
+    TOKEN_FALSE
+  };
+    
+  Lexer(std::istream& stream);
+  ~Lexer();
+
+  TokenType getNextToken();
+  const char* getString() const
+  { return token_string; }
+  int getLineNumber() const
+  { return linenumber; }
+    
+private:
+  enum {
+    MAX_TOKEN_LENGTH = 16384,
+    BUFFER_SIZE = 1024
+  };
+    
+  inline void nextChar();
+    
+  std::istream& stream;
+  bool eof;
+  int linenumber;
+  char buffer[BUFFER_SIZE+1];
+  char* bufend;
+  char* c;
+  char token_string[MAX_TOKEN_LENGTH + 1];
+  int token_length;
+};
+
+} // end of namespace lisp
+
+#endif
+
diff --git a/lib/lisp/lisp.cpp b/lib/lisp/lisp.cpp
new file mode 100644 (file)
index 0000000..aa7bca9
--- /dev/null
@@ -0,0 +1,99 @@
+//  $Id$
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include "lisp.h"
+
+namespace lisp
+{
+    
+Lisp::Lisp(LispType newtype)
+  : type(newtype)
+{
+}
+
+Lisp::~Lisp()
+{
+  if(type == TYPE_SYMBOL || type == TYPE_STRING)
+    delete[] v.string;
+  if(type == TYPE_CONS) {
+    delete v.cons.cdr;
+    delete v.cons.car;
+  }
+}
+
+Lisp*
+Lisp::get_lisp(const char* name) const
+{
+  for(const Lisp* p = this; p != 0; p = p->get_cdr()) {
+    Lisp* child = p->get_car();
+    if(!child || child->get_type() != TYPE_CONS)
+      continue;
+    Lisp* childname = child->get_car();
+    if(!childname)
+      continue;
+    std::string childName;
+    if(!childname->get(childName))
+      continue;
+    if(childName == name) {
+      return child->get_cdr();
+    }
+  }
+
+  return 0;
+}
+
+void
+Lisp::print(int indent) const
+{
+  for(int i = 0; i < indent; ++i)
+    printf(" ");
+  
+  if(type == TYPE_CONS) {
+    printf("(\n");
+    const Lisp* lisp = this;
+    while(lisp) {
+      if(lisp->v.cons.car)
+        lisp->v.cons.car->print(indent + 1);
+      lisp = lisp->v.cons.cdr;
+    }
+    for(int i = 0; i < indent; ++i)
+      printf(" ");
+    printf(")");
+  }
+  if(type == TYPE_STRING) {
+    printf("'%s' ", v.string);
+  }
+  if(type == TYPE_INTEGER) {
+    printf("%d", v.integer);
+  }
+  if(type == TYPE_REAL) {
+    printf("%f", v.real);
+  }
+  if(type == TYPE_SYMBOL) {
+    printf("%s ", v.string);
+  }
+  if(type == TYPE_BOOLEAN) {
+    printf("%s ", v.boolean ? "true" : "false");
+  }
+  printf("\n");
+}
+
+} // end of namespace lisp
diff --git a/lib/lisp/lisp.h b/lib/lisp/lisp.h
new file mode 100644 (file)
index 0000000..e118298
--- /dev/null
@@ -0,0 +1,165 @@
+//  $Id$
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISPREADER_H__
+#define __LISPREADER_H__
+
+#include <string>
+#include <vector>
+
+namespace lisp
+{
+
+class Lisp
+{
+public:
+  ~Lisp();
+    
+  enum LispType {
+    TYPE_CONS,
+    TYPE_SYMBOL,
+    TYPE_INTEGER,
+    TYPE_STRING,
+    TYPE_REAL,
+    TYPE_BOOLEAN
+  };
+
+  LispType get_type() const
+  { return type; } 
+
+  Lisp* get_car() const
+  { return v.cons.car; }
+  Lisp* get_cdr() const
+  { return v.cons.cdr; }
+  bool get(std::string& val) const
+  { 
+    if(type != TYPE_STRING && type != TYPE_SYMBOL)
+      return false;
+    val = v.string;
+    return true;
+  }
+  bool get(unsigned int& val) const
+  {
+    if(type != TYPE_INTEGER)
+      return false;
+    val = v.integer;
+    return true;
+  }
+  bool get(int& val) const
+  {
+    if(type != TYPE_INTEGER)
+      return false;
+    val = v.integer;
+    return true;
+  }
+  bool get(float& val) const
+  {
+    if(type != TYPE_REAL) {
+      if(type == TYPE_INTEGER) {
+        val = v.integer;
+        return true;
+      }
+      return false;
+    }
+    val = v.real;
+    return true;
+  }
+  bool get(bool& val) const
+  {
+    if(type != TYPE_BOOLEAN)
+      return false;
+    val = v.boolean;
+    return true;
+  }
+
+  /* conveniance functions which traverse the list until a child with a
+   * specified name is found. The value part is then interpreted in a specific
+   * way. The functions return true, if a child was found and could be
+   * interpreted correctly, otherwise false is returned and the variable value
+   * is not changed.
+   * (Please note that searching the lisp structure is O(n) so these functions
+   *  are no good idea for performance critical areas)
+   */
+  template<class T>
+  bool get(const char* name, T& val) const
+  {
+    const Lisp* lisp = get_lisp(name);
+    if(!lisp)
+      return false;
+
+    if(lisp->get_type() != TYPE_CONS)
+      return false;
+    lisp = lisp->get_car();
+    if(!lisp)
+      return false;
+    return lisp->get(val);
+  }
+
+  template<class T>
+  bool get_vector(const char* name, std::vector<T>& vec) const
+  {
+    vec.clear();
+    
+    const Lisp* child = get_lisp(name);
+    if(!child)
+      return false;
+    
+    for( ; child != 0; child = child->get_cdr()) {
+      T val;
+      if(!child->get_car())
+        continue;
+      if(child->get_car()->get(val)) {
+        vec.push_back(val);
+      }
+    }
+    
+    return true;
+  }
+  
+  Lisp* get_lisp(const char* name) const;
+  Lisp* get_lisp(const std::string& name) const
+  { return get_lisp(name.c_str()); }
+
+  // for debugging
+  void print(int indent = 0) const;
+
+private:
+  friend class Parser;
+  Lisp(LispType newtype);
+
+  LispType type;
+  union
+  {
+    struct
+    {
+      Lisp* car;
+      Lisp* cdr;
+    } cons;
+
+    char* string;
+    int integer;
+    bool boolean;
+    float real;
+  } v;
+};
+
+} // end of namespace lisp
+
+#endif
+
diff --git a/lib/lisp/list_iterator.cpp b/lib/lisp/list_iterator.cpp
new file mode 100644 (file)
index 0000000..8029f2a
--- /dev/null
@@ -0,0 +1,35 @@
+#include <config.h>
+
+#include "list_iterator.h"
+#include <stdexcept>
+
+namespace lisp
+{
+
+ListIterator::ListIterator(const lisp::Lisp* newlisp)
+  : current_lisp(0), cur(newlisp)
+{
+}
+
+bool
+ListIterator::next()
+{
+  if(cur == 0)
+    return false;
+
+  const lisp::Lisp* child = cur->get_car();
+  if(!child)
+    throw new std::runtime_error("child is 0 in list entry");
+  if(child->get_type() != lisp::Lisp::TYPE_CONS)
+    throw new std::runtime_error("Expected CONS");
+  const lisp::Lisp* name = child->get_car();
+  if(!name || name->get_type() != lisp::Lisp::TYPE_SYMBOL)
+    throw new std::runtime_error("Expected symbol");
+  name->get(current_item);
+  current_lisp = child->get_cdr();
+
+  cur = cur->get_cdr();
+  return true;
+}
+
+}
diff --git a/lib/lisp/list_iterator.h b/lib/lisp/list_iterator.h
new file mode 100644 (file)
index 0000000..b7f051d
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __LISP_ITERATOR_H__
+#define __LISP_ITERATOR_H__
+
+#include "lisp/lisp.h"
+
+namespace lisp
+{
+
+/**
+ * Small and a bit hacky helper class that helps parsing lisp lists where all
+ * entries are lists again themselves
+ */
+class ListIterator
+{
+public:
+  ListIterator(const lisp::Lisp* cur);
+  
+  const std::string& item() const
+  { return current_item; }
+  lisp::Lisp* lisp() const
+  { return current_lisp; }
+  lisp::Lisp* value() const
+  { return current_lisp->get_car(); }
+  bool next();
+
+private:
+  std::string current_item;
+  lisp::Lisp* current_lisp;
+  const lisp::Lisp* cur;
+};
+
+}
+
+#endif
+
diff --git a/lib/lisp/parser.cpp b/lib/lisp/parser.cpp
new file mode 100644 (file)
index 0000000..34f5f83
--- /dev/null
@@ -0,0 +1,151 @@
+//  $Id$
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <sstream>
+#include <stdexcept>
+#include <fstream>
+
+#include "parser.h"
+#include "lisp.h"
+
+namespace lisp
+{
+
+Parser::Parser()
+  : lexer(0)
+{
+}
+
+Parser::~Parser()
+{
+  delete lexer;
+}
+
+Lisp*
+Parser::parse(const std::string& filename)
+{
+  std::ifstream in(filename.c_str());
+  if(!in.good()) {
+    std::stringstream msg;
+    msg << "Parser problem: Couldn't open file '" << filename << "'.";
+    throw std::runtime_error(msg.str());
+  }
+  return parse(in);
+}
+
+Lisp*
+Parser::parse(std::istream& stream)
+{
+  delete lexer;
+  lexer = new Lexer(stream);
+
+  token = lexer->getNextToken();
+  Lisp* result = new Lisp(Lisp::TYPE_CONS);
+  result->v.cons.car = read();
+  result->v.cons.cdr = 0;
+  
+  delete lexer;
+  lexer = 0;
+
+  return result;    
+}
+
+Lisp*
+Parser::read()
+{
+  Lisp* result;
+  switch(token) {
+    case Lexer::TOKEN_EOF: {
+      std::stringstream msg;
+      msg << "Parse Error at line " << lexer->getLineNumber() << ": "
+        << "Unexpected EOF.";
+      throw std::runtime_error(msg.str());
+    }
+    case Lexer::TOKEN_CLOSE_PAREN: {
+      std::stringstream msg;
+      msg << "Parse Error at line " << lexer->getLineNumber() << ": "
+        << "Unexpected ')'.";
+      throw std::runtime_error(msg.str());
+    }
+    case Lexer::TOKEN_OPEN_PAREN: {
+      result = new Lisp(Lisp::TYPE_CONS);
+      
+      token = lexer->getNextToken();
+      if(token == Lexer::TOKEN_CLOSE_PAREN) {
+        result->v.cons.car = 0;
+        result->v.cons.cdr = 0;
+        break;
+      }
+
+      Lisp* cur = result;
+      do {
+        cur->v.cons.car = read();
+        if(token == Lexer::TOKEN_CLOSE_PAREN) {
+          cur->v.cons.cdr = 0;
+          break;
+        }
+        cur->v.cons.cdr = new Lisp(Lisp::TYPE_CONS);
+        cur = cur->v.cons.cdr;
+      } while(1);
+
+      break;
+    }
+    case Lexer::TOKEN_SYMBOL: {
+      result = new Lisp(Lisp::TYPE_SYMBOL);
+      size_t len = strlen(lexer->getString()) + 1;
+      result->v.string = new char[len];
+      memcpy(result->v.string, lexer->getString(), len);
+      break;
+    }
+    case Lexer::TOKEN_STRING: {
+      result = new Lisp(Lisp::TYPE_STRING);
+      size_t len = strlen(lexer->getString()) + 1;
+      result->v.string = new char[len];
+      memcpy(result->v.string, lexer->getString(), len);
+      break;
+    }
+    case Lexer::TOKEN_INTEGER:
+      result = new Lisp(Lisp::TYPE_INTEGER);
+      sscanf(lexer->getString(), "%d", &result->v.integer);
+      break;
+    case Lexer::TOKEN_REAL:
+      result = new Lisp(Lisp::TYPE_REAL);
+      sscanf(lexer->getString(), "%f", &result->v.real);
+      break;
+    case Lexer::TOKEN_TRUE:
+      result = new Lisp(Lisp::TYPE_BOOLEAN);
+      result->v.boolean = true;
+      break;
+    case Lexer::TOKEN_FALSE:
+      result = new Lisp(Lisp::TYPE_BOOLEAN);
+      result->v.boolean = false;
+      break;
+
+    default:
+      // this should never happen
+      assert(false);
+  }
+
+  token = lexer->getNextToken();
+  return result;
+}
+
+} // end of namespace lisp
diff --git a/lib/lisp/parser.h b/lib/lisp/parser.h
new file mode 100644 (file)
index 0000000..726648e
--- /dev/null
@@ -0,0 +1,50 @@
+//  $Id$
+//
+//  TuxKart - a fun racing game with go-kart
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//  code in this file based on lispreader from Mark Probst
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __LISPPARSER_H__
+#define __LISPPARSER_H__
+
+#include <string>
+#include "lexer.h"
+
+namespace lisp
+{
+
+class Lisp;
+
+class Parser
+{
+public:
+  Parser();
+  ~Parser();
+
+  Lisp* parse(const std::string& filename);
+  Lisp* parse(std::istream& stream);
+
+private:
+  Lisp* read();
+    
+  Lexer* lexer;
+  Lexer::TokenType token;
+};
+
+} // end of namespace lisp
+
+#endif
+
diff --git a/lib/lisp/writer.cpp b/lib/lisp/writer.cpp
new file mode 100644 (file)
index 0000000..a8c5c24
--- /dev/null
@@ -0,0 +1,134 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <config.h>
+
+#include <iostream>
+
+#include "writer.h"
+
+namespace lisp
+{
+
+Writer::Writer(std::ostream& newout)
+  : out(newout), indent_depth(0)
+{
+}
+
+Writer::~Writer()
+{
+  if(lists.size() > 0) {
+    std::cerr << "Warning: Not all sections closed in lispwriter!\n";
+  }
+}
+
+void
+Writer::write_comment(const std::string& comment)
+{
+  out << "; " << comment << "\n";
+}
+
+void
+Writer::start_list(const std::string& listname)
+{
+  indent();
+  out << '(' << listname << '\n';
+  indent_depth += 2;
+
+  lists.push_back(listname);
+}
+
+void
+Writer::end_list(const std::string& listname)
+{
+  if(lists.size() == 0) {
+    std::cerr << "Trying to close list '" << listname 
+              << "', which is not open.\n";
+    return;
+  }
+  if(lists.back() != listname) {
+    std::cerr << "Warning: trying to close list '" << listname 
+              << "' while list '" << lists.back() << "' is open.\n";
+    return;
+  }
+  lists.pop_back();
+  
+  indent_depth -= 2;
+  indent();
+  out << ")\n";
+}
+
+void
+Writer::write_int(const std::string& name, int value)
+{
+  indent();
+  out << '(' << name << ' ' << value << ")\n";
+}
+
+void
+Writer::write_float(const std::string& name, float value)
+{
+  indent();
+  out << '(' << name << ' ' << value << ")\n";
+}
+
+void
+Writer::write_string(const std::string& name, const std::string& value)
+{
+  indent();
+  out << '(' << name << " \"" << value << "\")\n";
+}
+
+void
+Writer::write_bool(const std::string& name, bool value)
+{
+  indent();
+  out << '(' << name << ' ' << (value ? "#t" : "#f") << ")\n";
+}
+
+void
+Writer::write_int_vector(const std::string& name,
+    const std::vector<int>& value)
+{
+  indent();
+  out << '(' << name;
+  for(std::vector<int>::const_iterator i = value.begin(); i != value.end(); ++i)
+    out << " " << *i;
+  out << ")\n";
+}
+
+void
+Writer::write_int_vector(const std::string& name,
+    const std::vector<unsigned int>& value)
+{
+  indent();
+  out << '(' << name;
+  for(std::vector<unsigned int>::const_iterator i = value.begin(); i != value.end(); ++i)
+    out << " " << *i;
+  out << ")\n";
+}
+
+void
+Writer::indent()
+{
+  for(int i = 0; i<indent_depth; ++i)
+    out << ' ';
+}
+
+} // end of namespace lisp
diff --git a/lib/lisp/writer.h b/lib/lisp/writer.h
new file mode 100644 (file)
index 0000000..842efc3
--- /dev/null
@@ -0,0 +1,61 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef SUPERTUX_LISPWRITER_H
+#define SUPERTUX_LISPWRITER_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace lisp
+{
+
+  class Writer
+    {
+    public:
+      Writer(std::ostream& out);
+      ~Writer();
+
+      void write_comment(const std::string& comment);
+
+      void start_list(const std::string& listname);
+
+      void write_int(const std::string& name, int value);
+      void write_float(const std::string& name, float value);
+      void write_string(const std::string& name, const std::string& value);
+      void write_bool(const std::string& name, bool value);
+      void write_int_vector(const std::string& name, const std::vector<int>& value);
+      void write_int_vector(const std::string& name, const std::vector<unsigned int>& value);
+      // add more write-functions when needed...
+
+      void end_list(const std::string& listname);
+
+    private:
+      void indent();
+
+      std::ostream& out;
+      int indent_depth;
+      std::vector<std::string> lists;
+    };
+
+} //namespace lisp
+
+#endif //SUPERTUX_LISPWRITER_H
+
index 6d0ed7b..e8b8d85 100644 (file)
@@ -25,7 +25,6 @@
 #include <cassert>
 #include <map>
 
-#include "utils/lispreader.h"
 #include "video/surface.h"
 #include "math/vector.h"
 #include "sprite_data.h"
index 197b7c5..252fbf8 100644 (file)
@@ -27,6 +27,7 @@
 #include "app/globals.h"
 #include "app/setup.h"
 #include "video/drawing_context.h"
+#include "lisp/list_iterator.h"
 
 namespace SuperTux
 {
@@ -46,21 +47,18 @@ SpriteData::Action::~Action()
     delete *i;
 }
 
-SpriteData::SpriteData(lisp_object_t* cur)
+SpriteData::SpriteData(const lisp::Lisp* lisp)
 {
-  for(; !lisp_nil_p(cur); cur = lisp_cdr(cur)) {
-    std::string token = lisp_symbol(lisp_car(lisp_car(cur)));
-    lisp_object_t* data = lisp_car(lisp_cdr(lisp_car(cur)));
-    LispReader reader(lisp_cdr(lisp_car(cur)));
-
-    if(token == "name")
-      name = lisp_string(data);
-    else if(token == "action")
-      parse_action(reader);
-    else
-      std::cerr << "Warning: Unknown sprite field: " << token << std::endl;
+  lisp::ListIterator iter(lisp);
+  while(iter.next()) {
+    if(iter.item() == "name") {
+      iter.value()->get(name);
+    } else if(iter.item() == "action") {
+      parse_action(iter.lisp());
+    } else {
+      std::cerr << "Unknown sprite field: " << iter.item() << "\n";
+    }
   }
-
   if(name.empty())
     throw std::runtime_error("Error: Sprite wihtout name.");
   if(actions.empty())
@@ -74,21 +72,22 @@ SpriteData::~SpriteData()
 }
 
 void
-SpriteData::parse_action(LispReader& lispreader)
+SpriteData::parse_action(const lisp::Lisp* lisp)
 {
   Action* action = new Action;
 
-  if(!lispreader.read_string("name", action->name)) {
+  if(!lisp->get("name", action->name)) {
     if(!actions.empty())
       throw std::runtime_error(
           "If there are more than one action, they need names!");
   }
-  lispreader.read_int("x-offset", action->x_offset);
-  lispreader.read_int("y-offset", action->y_offset);
-  lispreader.read_int("z-order", action->z_order);
-  lispreader.read_float("fps",     action->fps);
+  lisp->get("x-offset", action->x_offset);
+  lisp->get("y-offset", action->y_offset);
+  lisp->get("z-order", action->z_order);
+  lisp->get("fps", action->fps);
 
-  /* TODO: add a top filter entry */
+  // this doesn't seem to be used and implemented
+#if 0
   std::vector <int> mask_color;
   lispreader.read_int_vector("apply-mask", mask_color);
   if(mask_color.size() == 4) {
@@ -97,9 +96,10 @@ SpriteData::parse_action(LispReader& lispreader)
       (*i)->apply_filter(MASK_FILTER, Color(mask_color));
     }
   }
+#endif
 
   std::string mirror_action;
-  lispreader.read_string("mirror-action", mirror_action);
+  lisp->get("mirror-action", mirror_action);
   if(!mirror_action.empty()) {
     Action* act_tmp = get_action(mirror_action);
     if(act_tmp == NULL) {
@@ -116,7 +116,7 @@ SpriteData::parse_action(LispReader& lispreader)
     }
   } else { // Load images
     std::vector<std::string> images;
-    if(!lispreader.read_string_vector("images", images)) {
+    if(!lisp->get_vector("images", images)) {
       std::stringstream msg;
       msg << "Sprite '" << name << "' contains no images in action '"
           << action->name << "'.";
index 55d7473..1d0e167 100644 (file)
@@ -24,7 +24,7 @@
 #include <vector>
 #include <map>
 
-#include "utils/lispreader.h"
+#include "lisp/lisp.h"
 #include "video/surface.h"
 
 namespace SuperTux
@@ -35,7 +35,7 @@ namespace SuperTux
   public:
     /** cur has to be a pointer to data in the form of ((x-offset 5)
       (y-offset 10) ...) */
-    SpriteData(lisp_object_t* cur);                                         
+    SpriteData(const lisp::Lisp* cur);                                         
     ~SpriteData();
 
     const std::string& get_name() const
@@ -72,7 +72,7 @@ namespace SuperTux
     typedef std::map <std::string, Action*> Actions;
     Actions actions;
 
-    void parse_action(LispReader& lispreader);
+    void parse_action(const lisp::Lisp* lispreader);
     /** Get an action */
     Action* get_action(std::string act);
 
index 8c9ee81..38bb659 100644 (file)
 #include <sstream>
 #include <stdexcept>
 
-#include "utils/lispreader.h"
 #include "sprite_manager.h"
 #include "sprite_data.h"
 #include "sprite.h"
+#include "lisp/lisp.h"
+#include "lisp/parser.h"
+#include "lisp/list_iterator.h"
 
 namespace SuperTux
 {
@@ -45,42 +47,39 @@ SpriteManager::~SpriteManager()
 void
 SpriteManager::load_resfile(const std::string& filename)
 {
-  lisp_object_t* root_obj = lisp_read_from_file(filename);
-  if (!root_obj)
-    {
-      std::cout << "SpriteManager: Couldn't load: " << filename << std::endl;
-      return;
-    }
-
-  lisp_object_t* cur = root_obj;
-
-  if (strcmp(lisp_symbol(lisp_car(cur)), "supertux-resources") != 0)
-    return;
-  cur = lisp_cdr(cur);
-
-  while(cur) {
-    lisp_object_t* el = lisp_car(cur);
-
-    if (strcmp(lisp_symbol(lisp_car(el)), "sprite") == 0) {
-      SpriteData* spritedata = new SpriteData(lisp_cdr(el));
-
-      Sprites::iterator i = sprites.find(spritedata->get_name());
-      if (i == sprites.end()) {
-        sprites[spritedata->get_name()] = spritedata;
+  lisp::Parser parser;
+  try {
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
+
+    const lisp::Lisp* resources = root->get_lisp("supertux-resources");
+    if(!resources)
+      throw std::runtime_error("file is not a supertux-resources files");
+
+    lisp::ListIterator iter(resources);
+    while(iter.next()) {
+      if(iter.item() == "sprite") {
+        SpriteData* spritedata = new SpriteData(iter.lisp());
+
+        printf("Spr: %s.\n", spritedata->get_name().c_str());
+        Sprites::iterator i = sprites.find(spritedata->get_name());
+        if (i == sprites.end()) {
+          sprites[spritedata->get_name()] = spritedata;
+        } else {
+          delete i->second;
+          i->second = spritedata;
+          std::cout << "Warning: dulpicate entry: '" << spritedata->get_name()
+            << "' in spritefile." << std::endl;
+        }
       } else {
-        delete i->second;
-        i->second = spritedata;
-        std::cout << "Warning: dulpicate entry: '" << spritedata->get_name()
-          << "' in spritefile." << std::endl;
+        std::cout << "SpriteManager: Unknown tag '" << iter.item() 
+          << "' in spritefile.\n";
       }
-    } else {
-      std::cout << "SpriteManager: Unknown tag in spritefile.\n";
     }
-
-    cur = lisp_cdr(cur);
+  } catch(std::exception& e) {
+    std::stringstream msg;
+    msg << "Couldn't load file '" << filename << "': " << e.what() << "\n";
+    throw std::runtime_error(msg.str());
   }
-
-  lisp_free(root_obj);
 }
 
 Sprite*
index aa8cb40..ebf9e3b 100644 (file)
 
 #include <cstdlib>
 #include <string>
+#include <stdexcept>
 
 #include "configfile.h"
 #include "app/setup.h"
 #include "app/globals.h"
 #include "audio/sound_manager.h"
+#include "lisp/parser.h"
 
 using namespace SuperTux;
 
@@ -76,64 +78,49 @@ FILE * SuperTux::opendata(const std::string& rel_filename, const char *mode)
 
 void Config::load()
 {
-  FILE * file = NULL;
-
   defaults();
 
-  /* override defaults from config file */
-
-  file = opendata(config_filename, "r");
-
-  if (file == NULL)
-    return;
-
-  /* read config file */
-
-  lisp_stream_t   stream;
-  lisp_object_t * root_obj = NULL;
-
-  lisp_stream_init_file (&stream, file);
-  root_obj = lisp_read (&stream);
-
-  if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR)
-    return;
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), (package_symbol_name+"-config").c_str()) != 0)
-    return;
-
-  LispReader reader(lisp_cdr(root_obj));
-
-  reader.read_bool("fullscreen", use_fullscreen);
-  bool temp;
-  reader.read_bool("sound",     temp);
-  SoundManager::get()->enable_sound(temp);
-  reader.read_bool("music",      temp);
-  SoundManager::get()->enable_music(temp);
-  reader.read_bool("show_fps",   show_fps);
-
-  std::string video;
-  reader.read_string ("video", video);
-  if (video == "opengl")
-    use_gl = true;
-  else
-    use_gl = false;
-
-  reader.read_int ("joystick", joystick_num);
-
-  if (joystick_num >= 0)
-    {
-    reader.read_int ("joystick-x", joystick_keymap.x_axis);
-    reader.read_int ("joystick-y", joystick_keymap.y_axis);
-    reader.read_int ("joystick-a", joystick_keymap.a_button);
-    reader.read_int ("joystick-b", joystick_keymap.b_button);
-    reader.read_int ("joystick-start", joystick_keymap.start_button);
-    reader.read_int ("joystick-deadzone", joystick_keymap.dead_zone);
+  lisp::Parser parser;
+  try {
+    std::auto_ptr<lisp::Lisp> root (parser.parse(st_dir + config_filename));
+
+    const lisp::Lisp* config_lisp = root->get_lisp(
+        package_symbol_name + "-config");
+    if(!config_lisp)
+      throw new std::runtime_error("Config file is not a supertux-config file");
+
+    config_lisp->get("fullscreen", use_fullscreen);
+    bool temp = false;
+    if(config_lisp->get("sound", temp))
+      SoundManager::get()->enable_sound(temp);
+    if(config_lisp->get("music", temp))
+      SoundManager::get()->enable_music(temp);
+    config_lisp->get("show_fps",   show_fps);
+
+    std::string video;
+    if(config_lisp->get("video", video)) {
+      if (video == "opengl")
+        use_gl = true;
+      else
+        use_gl = false;
     }
 
-  customload(reader);
+    joystick_num = 0;
+    config_lisp->get("joystick", joystick_num);
+    
+    if (joystick_num >= 0) {
+      config_lisp->get("joystick-x", joystick_keymap.x_axis);
+      config_lisp->get("joystick-y", joystick_keymap.y_axis);
+      config_lisp->get("joystick-a", joystick_keymap.a_button);
+      config_lisp->get("joystick-b", joystick_keymap.b_button);
+      config_lisp->get("joystick-start", joystick_keymap.start_button);
+      config_lisp->get("joystick-deadzone", joystick_keymap.dead_zone);
+    }
 
-  lisp_free(root_obj);
-  fclose(file);
+    customload(config_lisp);
+  } catch(std::exception& e) {
+    std::cerr << "Couldn't load configfile: " << e.what() << "\n";
+  }
 }
 
 void Config::save ()
@@ -173,4 +160,3 @@ void Config::save ()
     }
 }
 
-/* EOF */
index 6620bcb..5c2de64 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef SUPERTUX_CONFIGFILE_H
 #define SUPERTUX_CONFIGFILE_H
 
-#include "lispreader.h"
+#include "lisp/lisp.h"
 
 namespace SuperTux {
 
@@ -30,7 +30,7 @@ class Config {
   public:
   void load ();
   void save ();
-  virtual void customload(LispReader& )
+  virtual void customload(const lisp::Lisp* )
   {};
   virtual void customsave(FILE* )
   {};
index 78cfd39..303193b 100644 (file)
 
 #include <cstdlib>
 #include <cstring>
+#include <stdexcept>
 
 #include "app/globals.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
 #include "screen.h"
 #include "font.h"
 #include "drawing_context.h"
-#include "utils/lispreader.h"
 
 using namespace SuperTux;
 
@@ -202,23 +204,30 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
 #define SCROLL      60
 #define ITEMS_SPACE 4
 
-void SuperTux::display_text_file(const std::string& file, float scroll_speed, Font* heading_font, Font* normal_font, Font* small_font, Font* reference_font )
+void SuperTux::display_text_file(const std::string& file, float scroll_speed,
+    Font* heading_font, Font* normal_font, Font* small_font,
+    Font* reference_font)
 {
   std::string text;
+  std::string background_file;
   std::vector<std::string> names;
 
-  LispReader* reader = LispReader::load(datadir + "/" + file, "supertux-text");
+  std::string filename = datadir + "/" + file;
+  lisp::Parser parser;
+  try {
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
 
-  if(!reader)
-    {
-    std::cerr << "Error: Could not open text. Ignoring...\n";
+    const lisp::Lisp* text_lisp = root->get_lisp("supertux-text");
+    if(!text_lisp)
+      throw std::runtime_error("File isn't a supertux-text file");
+    
+    if(!text_lisp->get("text", text))
+      throw std::runtime_error("file doesn't contain a text field");
+  } catch(std::exception& e) {
+    std::cerr << "Couldn't load file '" << filename << "': " << e.what() <<
+      "\n";
     return;
-    }
-
-  reader->read_string("text", text, true);
-  std::string background_file;
-  reader->read_string("background", background_file, true);
-  delete reader;
+  }
 
   // Split text string lines into a vector
   names.clear();
index 68cdb57..cddb825 100644 (file)
@@ -11,8 +11,9 @@
 #include "serializable.h"
 #include "resources.h"
 #include "sector.h"
-#include "utils/lispwriter.h"
-#include "utils/lispreader.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 #include "video/drawing_context.h"
 #include "special/sprite_manager.h"
 
index 62547b9..2897e68 100644 (file)
@@ -18,7 +18,7 @@ Bomb::Bomb(const Vector& pos, Direction dir)
 }
 
 void
-Bomb::write(LispWriter& )
+Bomb::write(lisp::Writer& )
 {
   // bombs are only temporarily so don't write them out...
 }
index 9d09599..fc3beec 100644 (file)
@@ -8,7 +8,7 @@ class Bomb : public BadGuy
 public:
   Bomb(const Vector& pos, Direction dir);
 
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
   HitResponse collision_player(Player& player, const CollisionHit& hit);
   void active_action(float elapsed_time);
index 26a9534..431cac2 100644 (file)
@@ -5,10 +5,10 @@
 static const float JUMPSPEED = 450;
 static const float WALKSPEED = 80;
 
-BouncingSnowball::BouncingSnowball(LispReader& reader)
+BouncingSnowball::BouncingSnowball(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("bouncingsnowball");
   set_direction = false;
@@ -25,7 +25,7 @@ BouncingSnowball::BouncingSnowball(float pos_x, float pos_y, Direction d)
 }
 
 void
-BouncingSnowball::write(LispWriter& writer)
+BouncingSnowball::write(lisp::Writer& writer)
 {
   writer.start_list("bouncingsnowball");
 
index 4bb4d86..d53badf 100644 (file)
@@ -6,11 +6,11 @@
 class BouncingSnowball : public BadGuy
 {
 public:
-  BouncingSnowball(LispReader& reader);
+  BouncingSnowball(const lisp::Lisp& reader);
   BouncingSnowball(float pos_x, float pos_y, Direction d);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
 
 protected:
index b88ec20..5f18cc7 100644 (file)
@@ -6,20 +6,19 @@
 #include "badguy/mrbomb.h"
 #include "badguy/mriceblock.h"
 
-
-Dispenser::Dispenser(LispReader& reader)
+Dispenser::Dispenser(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
-  reader.read_float("cycle", cycle);
-  reader.read_string("badguy", badguy);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
+  reader.get("cycle", cycle);
+  reader.get("badguy", badguy);
   bbox.set_size(32, 32);
   sprite = sprite_manager->create("dispenser");
   sprite->set_action("working");
 }
 
 void
-Dispenser::write(LispWriter& writer)
+Dispenser::write(lisp::Writer& writer)
 {
   writer.start_list("dispenser");
 
index 6c83a28..3dd2489 100644 (file)
@@ -7,10 +7,10 @@
 class Dispenser : public BadGuy
 {
 public:
-  Dispenser(LispReader& reader);
+  Dispenser(const lisp::Lisp& reader);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
   void active_action(float elapsed_time);
 
index 83845a6..853ca5e 100644 (file)
@@ -2,13 +2,13 @@
 
 #include "flame.h"
 
-Flame::Flame(LispReader& reader)
+Flame::Flame(const lisp::Lisp& reader)
   : angle(0), radius(100), speed(2)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
-  reader.read_float("radius", radius);
-  reader.read_float("speed", speed);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
+  reader.get("radius", radius);
+  reader.get("speed", speed);
   bbox.set_pos(Vector(start_position.x + cos(angle) * radius,
                       start_position.y + sin(angle) * radius));
   bbox.set_size(32, 32);  
@@ -16,7 +16,7 @@ Flame::Flame(LispReader& reader)
 }
 
 void
-Flame::write(LispWriter& writer)
+Flame::write(lisp::Writer& writer)
 {
   writer.start_list("flame");
 
index b27e1f0..6a82a5a 100644 (file)
@@ -6,9 +6,9 @@
 class Flame : public BadGuy
 {
 public:
-  Flame(LispReader& reader);
+  Flame(const lisp::Lisp& reader);
 
-  void write(LispWriter& write);
+  void write(lisp::Writer& write);
   void active_action(float elapsed_time);
   void kill_fall();
 
index f7abad9..bc8dffe 100644 (file)
@@ -4,16 +4,16 @@
 
 static const float JUMPSPEED=600;
 
-Jumpy::Jumpy(LispReader& reader)
+Jumpy::Jumpy(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("jumpy");
 }
 
 void
-Jumpy::write(LispWriter& writer)
+Jumpy::write(lisp::Writer& writer)
 {
   writer.start_list("jumpy");
 
index 8abd10c..e33f6eb 100644 (file)
@@ -2,19 +2,16 @@
 #define __JUMPY_H__
 
 #include "badguy.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
-#include "serializable.h"
 
 class Jumpy : public BadGuy
 {
 public:
-  Jumpy(LispReader& reader);
+  Jumpy(const lisp::Lisp& reader);
 
   virtual HitResponse collision_solid(GameObject& other,
       const CollisionHit& hit);
 
-  virtual void write(LispWriter& writer);
+  virtual void write(lisp::Writer& writer);
 };
 
 #endif
index b7a443d..76222d2 100644 (file)
@@ -5,10 +5,10 @@
 
 static const float WALKSPEED = 80;
 
-MrBomb::MrBomb(LispReader& reader)
+MrBomb::MrBomb(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("mrbomb");
   set_direction = false;
@@ -25,7 +25,7 @@ MrBomb::MrBomb(float pos_x, float pos_y, Direction d)
 }
 
 void
-MrBomb::write(LispWriter& writer)
+MrBomb::write(lisp::Writer& writer)
 {
   writer.start_list("mrbomb");
 
index 257716f..fda40fb 100644 (file)
@@ -6,11 +6,11 @@
 class MrBomb : public BadGuy
 {
 public:
-  MrBomb(LispReader& reader);
+  MrBomb(const lisp::Lisp& reader);
   MrBomb(float pos_x, float pos_y, Direction d);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
 
 protected:
index 72a007c..e0bdbf6 100644 (file)
@@ -6,11 +6,11 @@ static const float WALKSPEED = 80;
 static const float KICKSPEED = 500;
 static const int MAXSQUISHES = 10;
 
-MrIceBlock::MrIceBlock(LispReader& reader)
+MrIceBlock::MrIceBlock(const lisp::Lisp& reader)
   : ice_state(ICESTATE_NORMAL), squishcount(0)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("mriceblock");
   set_direction = false;
@@ -28,7 +28,7 @@ MrIceBlock::MrIceBlock(float pos_x, float pos_y, Direction d)
 }
 
 void
-MrIceBlock::write(LispWriter& writer)
+MrIceBlock::write(lisp::Writer& writer)
 {
   writer.start_list("mriceblock");
 
index 7275c0e..3a6d2a6 100644 (file)
@@ -6,11 +6,11 @@
 class MrIceBlock : public BadGuy
 {
 public:
-  MrIceBlock(LispReader& reader);
+  MrIceBlock(const lisp::Lisp& reader);
   MrIceBlock(float pos_x, float pos_y, Direction d);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
 
   void active_action(float elapsed_time);
index 16214aa..ac3a8e1 100644 (file)
@@ -12,10 +12,10 @@ static const float WALKSPEED = 90;
 
 //TODO: Create sprite, give multiple hitpoints, limit max number of snowballs
 //      Stop actions when pause button is hit (probably a general problem of timers)
-Nolok_01::Nolok_01(LispReader& reader)
+Nolok_01::Nolok_01(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 63.8);
   sprite = sprite_manager->create("dummyguy");
 }
@@ -29,7 +29,7 @@ Nolok_01::Nolok_01(float pos_x, float pos_y)
 }
 
 void
-Nolok_01::write(LispWriter& writer)
+Nolok_01::write(lisp::Writer& writer)
 {
   writer.start_list("nolok01");
 
index b35ca36..cc50d5a 100644 (file)
@@ -7,11 +7,11 @@
 class Nolok_01 : public BadGuy
 {
 public:
-  Nolok_01(LispReader& reader);
+  Nolok_01(const lisp::Lisp& reader);
   Nolok_01(float pos_x, float pos_y);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   void active_action(float elapsed_time);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
   
index de77435..4442d02 100644 (file)
@@ -4,10 +4,10 @@
 
 static const float WALKSPEED = 80;
 
-SnowBall::SnowBall(LispReader& reader)
+SnowBall::SnowBall(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("snowball");
   set_direction = false;
@@ -24,7 +24,7 @@ SnowBall::SnowBall(float pos_x, float pos_y, Direction d)
 }
 
 void
-SnowBall::write(LispWriter& writer)
+SnowBall::write(lisp::Writer& writer)
 {
   writer.start_list("snowball");
 
index 55bf56c..47acaf0 100644 (file)
@@ -6,11 +6,11 @@
 class SnowBall : public BadGuy
 {
 public:
-  SnowBall(LispReader& reader);
+  SnowBall(const lisp::Lisp& reader);
   SnowBall(float pos_x, float pos_y, Direction d);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
   
 protected:
index 905e921..bc31450 100644 (file)
@@ -9,14 +9,14 @@ Spike::Spike(const Vector& pos, Direction dir)
   set_direction(dir);
 }
 
-Spike::Spike(LispReader& reader)
+Spike::Spike(const lisp::Lisp& reader)
 {
   sprite = sprite_manager->create("spike");
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(32, 32);
   int idir = 0;
-  reader.read_int("direction", idir);
+  reader.get("direction", idir);
   set_direction((Direction) idir);
 }
 
@@ -43,7 +43,7 @@ Spike::set_direction(Direction dir)
 }
 
 void
-Spike::write(LispWriter& writer)
+Spike::write(lisp::Writer& writer)
 {
   writer.start_list("spike");
   writer.write_float("x", start_position.x);
index 1122270..eae68d0 100644 (file)
@@ -10,10 +10,10 @@ public:
     NORTH=0, SOUTH, WEST, EAST
   };
   Spike(const Vector& pos, Direction dir);
-  Spike(LispReader& reader);
+  Spike(const lisp::Lisp& reader);
 
   void active_action(float elapsed_time);
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   void kill_fall();
 private:
   void set_direction(Direction dir);
index c779faa..255bb9e 100644 (file)
@@ -4,16 +4,16 @@
 
 static const float WALKSPEED = 80;
 
-Spiky::Spiky(LispReader& reader)
+Spiky::Spiky(const lisp::Lisp& reader)
 {
-  reader.read_float("x", start_position.x);
-  reader.read_float("y", start_position.y);
+  reader.get("x", start_position.x);
+  reader.get("y", start_position.y);
   bbox.set_size(31.8, 31.8);
   sprite = sprite_manager->create("spiky");
 }
 
 void
-Spiky::write(LispWriter& writer)
+Spiky::write(lisp::Writer& writer)
 {
   writer.start_list("spiky");
 
index 547ea13..2c48e29 100644 (file)
@@ -6,10 +6,10 @@
 class Spiky : public BadGuy
 {
 public:
-  Spiky(LispReader& reader);
+  Spiky(const lisp::Lisp& reader);
 
   void activate();
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
 };
 
index 3267063..84e4be2 100644 (file)
@@ -18,7 +18,6 @@
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include <iostream>
@@ -31,6 +30,7 @@
 #include <cerrno>
 #include <unistd.h>
 #include <ctime>
+#include <stdexcept>
 
 #include "SDL.h"
 
@@ -44,7 +44,6 @@
 #include "gameloop.h"
 #include "video/screen.h"
 #include "app/setup.h"
-#include "high_scores.h"
 #include "gui/menu.h"
 #include "sector.h"
 #include "level.h"
@@ -55,6 +54,8 @@
 #include "object/tilemap.h"
 #include "object/camera.h"
 #include "object/player.h"
+#include "lisp/lisp.h"
+#include "lisp/parser.h"
 #include "resources.h"
 #include "app/gettext.h"
 #include "worldmap.h"
@@ -937,25 +938,21 @@ std::string slotinfo(int slot)
   stream << slot;
   slotfile = st_save_dir + "/slot" + stream.str() + ".stsg";
 
-  lisp_object_t* savegame = lisp_read_from_file(slotfile.c_str());
-  if (savegame)
-    {
-      LispReader reader(lisp_cdr(savegame));
-      reader.read_string("title", title);
-      lisp_free(savegame);
-    }
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (parser.parse(slotfile));
 
-  if (access(slotfile.c_str(), F_OK) == 0)
-    {
-      if (!title.empty())
-        tmp = "Slot " + stream.str() + " - " + title;
-      else
-        tmp = "Slot " + stream.str() + " - Savegame";
-    }
-  else
-    tmp = std::string(_("Slot")) + " " + stream.str() + " - " + std::string(_("Free"));
+    const lisp::Lisp* savegame = root->get_lisp("supertux-savegame");
+    if(!savegame)
+      throw std::runtime_error("file is not a supertux-savegame.");
+
+    savegame->get("title", title);
+  } catch(std::exception& e) {
+    return std::string(_("Slot")) + " " + stream.str() + " - " +
+      std::string(_("Free"));
+  }
 
-  return tmp;
+  return std::string("Slot ") + stream.str() + " - " + title;
 }
 
 bool process_load_game_menu()
diff --git a/src/high_scores.cpp b/src/high_scores.cpp
deleted file mode 100644 (file)
index 86b1eb6..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Adam Czachorowski <gislan@o2.pl>
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License
-//  as published by the Free Software Foundation; either version 2
-//  of the License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-// 
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-/* Open the highscore file: */
-
-#include <config.h>
-
-#include <cstring>
-#include <cstdlib>
-
-#include "app/globals.h"
-#include "high_scores.h"
-#include "gui/menu.h"
-#include "video/drawing_context.h"
-#include "video/screen.h"
-#include "video/surface.h"
-#include "app/setup.h"
-#include "utils/lispreader.h"
-#include "resources.h"
-
-using namespace SuperTux;
-
-#ifdef WIN32
-const char * highscore_filename = "/st_highscore.dat";
-#else
-const char * highscore_filename = "/highscore";
-#endif
-
-int hs_score;
-std::string hs_name; /* highscores global variables*/
-
-/* Load data from high score file: */
-
-void load_hs(void)
-{
-  hs_score = 100;
-  hs_name  = "Grandma";
-
-  FILE * fi;
-  lisp_object_t* root_obj = 0;
-  fi = fopen(highscore_filename, "r");
-  if (fi == NULL)
-    {
-      perror(highscore_filename);
-      return;
-    }
-
-  lisp_stream_t stream;
-  lisp_stream_init_file (&stream, fi);
-  root_obj = lisp_read (&stream);
-
-  if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR)
-    {
-      printf("HighScore: Parse Error in file %s", highscore_filename);
-    }
-
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-highscore") == 0)
-    {
-      LispReader reader(lisp_cdr(root_obj));
-      reader.read_int("score",  hs_score);
-      reader.read_string("name", hs_name);
-    }
-  fclose(fi);
-  lisp_free(root_obj);
-}
-
-void save_hs(int score)
-{
-  char str[80];
-
-  Surface* bkgd;
-  SDL_Event event;
-
-  DrawingContext context;
-  bkgd = new Surface(datadir + "/images/highscore/highscore.png", false);
-
-  hs_score = score;
-
-  Menu::set_current(highscore_menu);
-
-  highscore_menu->item[0].input = hs_name;
-
-  /* ask for player's name */
-  while(Menu::current())
-    {
-      context.draw_surface(bkgd, Vector(0, 0), LAYER_BACKGROUND0);
-
-      context.draw_text(blue_text, "Congratulations", 
-          Vector(screen->w/2, 130), CENTER_ALLIGN, LAYER_FOREGROUND1);
-      context.draw_text(blue_text, "Your score:", Vector(150, 180),
-          LEFT_ALLIGN, LAYER_FOREGROUND1);
-      sprintf(str, "%d", hs_score);
-      context.draw_text(yellow_nums, str, Vector(250, 170), LEFT_ALLIGN, LAYER_FOREGROUND1);
-
-      Menu::current()->draw(context);
-      Menu::current()->action();
-
-      context.do_drawing();
-
-      while(SDL_PollEvent(&event))
-        if(event.type == SDL_KEYDOWN)
-          Menu::current()->event(event);
-
-      switch (highscore_menu->check())
-        {
-        case 0:
-          hs_name = highscore_menu->item[0].input;
-          break;
-        }
-
-      SDL_Delay(25);
-    }
-
-
-  /* Save to file: */
-
-  FILE* fi;
-  std::string filename;
-
-  /* Save data file: */
-  filename = highscore_filename;
-
-  FileSystem::fcreatedir(filename.c_str());
-  if(FileSystem::fwriteable(filename.c_str()))
-    {
-      fi = fopen(filename.c_str(), "w");
-      if (fi == NULL)
-        {
-          perror(filename.c_str());
-        }
-
-      /* Write header: */
-      fprintf(fi,";SuperTux HighScores\n");
-      fprintf(fi,"(supertux-highscore\n");
-
-      /* Save title info: */
-      fprintf(fi,"  (name \"%s\")\n", hs_name.c_str());
-
-      /* Save the description: */
-      fprintf(fi,"  (score \"%i\")\n", hs_score);
-
-      fprintf( fi,")");
-      fclose(fi);
-    }
-}
diff --git a/src/high_scores.h b/src/high_scores.h
deleted file mode 100644 (file)
index 76d6739..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Adam Czachorowski <gislan@o2.pl>
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License
-//  as published by the Free Software Foundation; either version 2
-//  of the License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-// 
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#ifndef SUPERTUX_HIGH_SCORES_H
-#define SUPERTUX_HIGH_SCORES_H
-
-#include <cstdio>
-
-extern int hs_score;
-extern std::string hs_name; /* highscores global variables*/
-
-void save_hs(int score);
-void load_hs();
-
-#endif
index 5aa0734..c159d22 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <map>
 #include <cstring>
 #include <iostream>
 #include <fstream>
+#include <sstream>
+#include <memory>
 #include <stdexcept>
 
 #include "app/globals.h"
 #include "app/setup.h"
 #include "video/screen.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "lisp/list_iterator.h"
+#include "lisp/writer.h"
 #include "level.h"
 #include "math/physic.h"
 #include "scene.h"
 #include "sector.h"
 #include "tile.h"
-#include "utils/lispreader.h"
 #include "resources.h"
-#include "utils/lispwriter.h"
 #include "object/gameobjs.h"
 #include "object/camera.h"
 #include "object/tilemap.h"
@@ -55,59 +58,66 @@ Level::Level()
 void
 Level::load(const std::string& filepath)
 {
-  LispReader* level = LispReader::load(filepath, "supertux-level");
-
-  int version = 1;
-  level->read_int("version", version);
-  if(version == 1) {
-    load_old_format(*level);
-    delete level;
-    return;
-  }
-
-  for(lisp_object_t* cur = level->get_lisp(); !lisp_nil_p(cur);
-      cur = lisp_cdr(cur)) {
-    std::string token = lisp_symbol(lisp_car(lisp_car(cur)));
-    lisp_object_t* data = lisp_car(lisp_cdr(lisp_car(cur)));
-    LispReader reader(lisp_cdr(lisp_car(cur)));
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filepath));
+
+    const lisp::Lisp* level = root->get_lisp("supertux-level");
+    if(!level)
+      throw std::runtime_error("file is not a supertux-level file.");
+
+    int version = 1;
+    level->get("version", version);
+    if(version == 1) {
+      load_old_format(*level);
+      return;
+    }
 
-    if(token == "version") {
-      if(lisp_integer(data) > 2) {
-        std::cerr << "Warning: level format newer than application.\n";
-      }
-    } else if(token == "name") {
-      name = lisp_string(data);
-    } else if(token == "author") {
-      author = lisp_string(data);
-    } else if(token == "time") {
-      timelimit = lisp_integer(data);
-    } else if(token == "sector") {
-      Sector* sector = new Sector;
-      sector->parse(reader);
-      add_sector(sector);
-    } else if(token == "end-sequence-animation") {
-      std::string endsequencename = lisp_string(data);
-      if(endsequencename == "fireworks") {
-        end_sequence_type = FIREWORKS_ENDSEQ_ANIM;
+    lisp::ListIterator iter(level);
+    while(iter.next()) {
+      const std::string& token = iter.item();
+      if(token == "version") {
+        iter.value()->get(version);
+        if(version > 2) {
+          std::cerr << "Warning: level format newer than application.\n";
+        }
+      } else if(token == "name") {
+        iter.value()->get(name);
+      } else if(token == "author") {
+        iter.value()->get(author);
+      } else if(token == "time") {
+        iter.value()->get(timelimit);
+      } else if(token == "sector") {
+        Sector* sector = new Sector;
+        sector->parse(*(iter.lisp()));
+        add_sector(sector);
+      } else if(token == "end-sequence-animation") {
+        std::string endsequencename;
+        iter.value()->get(endsequencename);
+        if(endsequencename == "fireworks") {
+          end_sequence_type = FIREWORKS_ENDSEQ_ANIM;
+        } else {
+          std::cout << "Unknown endsequence type: '" << endsequencename <<
+            "'.\n";
+        }
       } else {
-        std::cout << "Unknown endsequence type: '" << endsequencename <<
-          "'.\n";
+        std::cerr << "Unknown token '" << token << "' in level file.\n";
+        continue;
       }
-    } else {
-      std::cerr << "Unknown token '" << token << "' in level file.\n";
-      continue;
     }
+  } catch(std::exception& e) {
+    std::stringstream msg;
+    msg << "Problem when reading level '" << filepath << "': " << e.what();
+    throw std::runtime_error(msg.str());
   }
-  
-  delete level;
 }
 
 void
-Level::load_old_format(LispReader& reader)
+Level::load_old_format(const lisp::Lisp& reader)
 {
-  reader.read_string("name", name, true);
-  reader.read_string("author", author);
-  reader.read_int("time", timelimit);
+  reader.get("name", name);
+  reader.get("author", author);
+  reader.get("time", timelimit);
 
   Sector* sector = new Sector;
   sector->parse_old_format(reader);
@@ -122,7 +132,7 @@ Level::save(const std::string& filename)
   FileSystem::fcreatedir(filepath.substr(0,last_slash).c_str());
   filepath = st_dir + "/" + filepath;
   ofstream file(filepath.c_str(), ios::out);
-  LispWriter* writer = new LispWriter(file);
+  lisp::Writer* writer = new lisp::Writer(file);
 
   writer->write_comment("Level made using SuperTux's built-in Level Editor");
 
index 08d71b7..7eb0248 100644 (file)
@@ -28,8 +28,8 @@ using namespace SuperTux;
 
 class Sector;
 
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
 }
 
 class Level
@@ -77,7 +77,7 @@ public:
   int get_total_coins();
 
 private:
-  void load_old_format(LispReader& reader);
+  void load_old_format(const lisp::Lisp& reader);
 };
 
 #endif /*SUPERTUX_LEVEL_H*/
index 19edf47..5cd4fc9 100644 (file)
@@ -30,6 +30,8 @@
 #include "app/globals.h"
 #include "video/surface.h"
 #include "level_subset.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
 
 using namespace SuperTux;
 
@@ -63,27 +65,19 @@ void LevelSubset::create(const std::string& subset_name)
 
 void LevelSubset::read_info_file(const std::string& info_file)
 {
-  lisp_object_t* root_obj = lisp_read_from_file(info_file);
-  if (root_obj == NULL)
-    return;
-  lisp_object_t* cur = lisp_car(root_obj);
+  lisp::Parser parser;
+  std::auto_ptr<lisp::Lisp> root (parser.parse(info_file));
 
-  if (lisp_symbol_p(cur) && strcmp(lisp_symbol(cur), "supertux-level-subset") == 0)
-    {
-      LispReader reader(lisp_cdr(root_obj));
+  const lisp::Lisp* info = root->get_lisp("supertux-level-subset");
+  if(!info)
+    throw std::runtime_error("File is not a levelsubset file");
 
-      reader.read_string("title", title, true);
-      reader.read_string("description", description, true);
-      reader.read_string_vector("levels", levels);
-      hide_from_contribs = false;
-      reader.read_bool("hide-from-contribs", hide_from_contribs);
-    }
-  else
-    {
-      std::cout << "LevelSubset: parse error in info file: " << info_file << std::endl;
-    }
+  hide_from_contribs = false;
 
-  lisp_free(root_obj);
+  info->get("title", title);
+  info->get("description", description);
+  info->get_vector("levels", levels);
+  info->get("hide-from-contribs", hide_from_contribs);
 }
 
 void LevelSubset::load(const std::string& subset)
@@ -99,8 +93,14 @@ void LevelSubset::load(const std::string& subset)
     msg << "Couldn't find level subset '" << subset << "'.";
     throw new std::runtime_error(msg.str());
   }
-  
-  read_info_file(filename);
+  try {
+    read_info_file(filename);
+  } catch(std::exception& e) {
+    std::stringstream msg;
+    msg << "Couldn't parse info file '" << filename << "': " << e.what();
+    throw new std::runtime_error(msg.str());
+  }
 
   if (levels.empty())
     { // Level info file doesn't define any levels, so read the
index 8202271..7ae03e2 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <vector>
 #include <string>
-#include "utils/lispreader.h"
 
 using namespace SuperTux;
 
index 42f0fd8..198c0c2 100644 (file)
@@ -101,12 +101,10 @@ LevelEditor::LevelEditor()
   tiles_board = new ButtonGroup(Vector(screen->w - 140, 100),
             Vector(32,32), Vector(4,8));
 
-  TileManager* tilemanager = TileManager::instance();
-
   tiles_board->add_button(Button(img_rubber_bt, _("Eraser"), SDLKey(SDLK_DELETE)), 0);
-  for(unsigned int id = 1; id < tilemanager->get_max_tileid(); id++)
+  for(unsigned int id = 1; id < tile_manager->get_max_tileid(); id++)
     {
-    const Tile* tile = tilemanager->get(id);
+    const Tile* tile = tile_manager->get(id);
     if(!tile)
       continue;
 
@@ -642,10 +640,9 @@ if(sector)
         }
       else
         {
-        TileManager* tilemanager = TileManager::instance();
         for(unsigned int x = 0; x < selection.size(); x++)
           for(unsigned int y = 0; y < selection[x].size(); y++) {
-            const Tile* tile = tilemanager->get(selection[x][y]);
+            const Tile* tile = tile_manager->get(selection[x][y]);
             tile->draw(context,
                 Vector(event.button.x + x*32 - 8, event.button.y + y*32 - 8),
                 LAYER_GUI-2);
index b03fca1..9b32379 100644 (file)
 #include "misc.h"
 #include "app/globals.h"
 
-void MyConfig::customload(LispReader& reader)
+void MyConfig::customload(const lisp::Lisp& reader)
 {
-  reader.read_int ("keyboard-up", keymap.up);
-  reader.read_int ("keyboard-down", keymap.down);
-  reader.read_int ("keyboard-left", keymap.left);
-  reader.read_int ("keyboard-right", keymap.right);
-  reader.read_int ("keyboard-jump", keymap.jump);
-  reader.read_int ("keyboard-power", keymap.power);
+  reader.get("keyboard-up", keymap.up);
+  reader.get("keyboard-down", keymap.down);
+  reader.get("keyboard-left", keymap.left);
+  reader.get("keyboard-right", keymap.right);
+  reader.get("keyboard-jump", keymap.jump);
+  reader.get("keyboard-power", keymap.power);
 }
+
 void MyConfig::customsave(FILE * config)
 {
   fprintf(config, "\t(keyboard-up  %d)\n", keymap.up);
index bef8878..e005087 100644 (file)
@@ -31,7 +31,7 @@
 class MyConfig : public Config
 {
   public:
-    void customload(LispReader& reader);
+    void customload(const lisp::Lisp& reader);
     void customsave(FILE * config);
 };
 
index 2d6cc41..15333dd 100644 (file)
 #include "app/globals.h"
 #include "camera.h"
 #include "video/drawing_context.h"
-#include "utils/lispwriter.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 Background::Background()
   : type(INVALID), layer(LAYER_BACKGROUND0), image(0)
 {
 }
 
-Background::Background(LispReader& reader)
+Background::Background(const lisp::Lisp& reader)
   : type(INVALID), layer(LAYER_BACKGROUND0), image(0)
 {
-  reader.read_int("layer", layer);
-  if(reader.read_string("image", imagefile) 
-      && reader.read_float("speed", speed)) {
+  reader.get("layer", layer);
+  if(reader.get("image", imagefile) 
+      && reader.get("speed", speed)) {
     set_image(imagefile, speed);
   }
 
   std::vector <unsigned int> bkgd_top_color, bkgd_bottom_color;
-  if(reader.read_int_vector("top_color", bkgd_top_color) &&
-     reader.read_int_vector("bottom_color", bkgd_bottom_color))
+  if(reader.get_vector("top_color", bkgd_top_color) &&
+     reader.get_vector("bottom_color", bkgd_bottom_color))
     set_gradient(Color(bkgd_top_color), Color(bkgd_bottom_color));
 }
 
@@ -51,7 +52,7 @@ Background::~Background()
 }
 
 void
-Background::write(LispWriter& writer)
+Background::write(lisp::Writer& writer)
 {
   if(type == INVALID)
     return;
index 7ed3e83..0bc3ca1 100644 (file)
 #include "video/surface.h"
 #include "video/drawing_context.h"
 #include "special/game_object.h"
-#include "utils/lispreader.h"
 #include "serializable.h"
 
 class DisplayManager;
 
+namespace lisp {
+class Lisp;
+}
+
 class Background : public GameObject, public Serializable
 {
 public:
   Background();
-  Background(LispReader& reader);
+  Background(const lisp::Lisp& reader);
   virtual ~Background();
 
-  virtual void write(LispWriter& writer);
+  virtual void write(lisp::Writer& writer);
 
   void set_image(const std::string& name, float bkgd_speed);
 
index b2f47ed..ae9adf3 100644 (file)
 #include <sstream>
 #include <cmath>
 
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
+#include "lisp/list_iterator.h"
 #include "camera.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
 #include "player.h"
 #include "tilemap.h"
 #include "gameloop.h"
@@ -52,43 +53,41 @@ Camera::get_translation() const
 }
 
 void
-Camera::parse(LispReader& reader)
+Camera::parse(const lisp::Lisp& reader)
 {
   std::string modename;
   
-  reader.read_string("mode", modename);
+  reader.get("mode", modename);
   if(modename == "normal") {
     mode = NORMAL;
 
     do_backscrolling = true;
-    reader.read_bool("backscrolling", do_backscrolling);
+    reader.get("backscrolling", do_backscrolling);
   } else if(modename == "autoscroll") {
     mode = AUTOSCROLL;
     
-    lisp_object_t* cur = 0;
-    reader.read_lisp("path", cur);
-    if(cur == 0) {
+    const lisp::Lisp* path_lisp = reader.get_lisp("path");
+    if(!path_lisp)
       throw std::runtime_error("No path specified in autoscroll camera.");
-    }
-    float speed = 50;
-    while(!lisp_nil_p(cur)) {
-      if(strcmp(lisp_symbol(lisp_car(lisp_car(cur))), "point") != 0) {
-        std::cerr << "Warning: unknown token in camera path.\n";
+
+    lisp::ListIterator iter(path_lisp);
+    float speed = .5;
+    while(iter.next()) {
+      if(iter.item() != "point") {
+        std::cerr << "Warning: unknown token '" << iter.item() 
+          << "' in camera path.\n";
         continue;
       }
-           
-      LispReader reader(lisp_cdr(lisp_car(cur)));
+      const lisp::Lisp* point_lisp = iter.lisp();
 
       ScrollPoint point;
-      if(!reader.read_float("x", point.position.x) ||
-         !reader.read_float("y", point.position.y)) {
+      if(!point_lisp->get("x", point.position.x) ||
+         !point_lisp->get("y", point.position.y)) {
         throw std::runtime_error("x and y missing in point of camerapath");
       }
-      reader.read_float("speed", speed);
+      point_lisp->get("speed", speed);
       point.speed = speed;
       scrollpoints.push_back(point);
-
-      cur = lisp_cdr(cur);
     }
   } else if(modename == "manual") {
     mode = MANUAL;
@@ -100,7 +99,7 @@ Camera::parse(LispReader& reader)
 }
 
 void
-Camera::write(LispWriter& writer)
+Camera::write(lisp::Writer& writer)
 {
   writer.start_list("camera");
   
index 2294aa9..45351b6 100644 (file)
@@ -30,9 +30,8 @@
 #include "serializable.h"
 
 using namespace SuperTux;
-
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
 }
 
 class Sector;
@@ -44,9 +43,9 @@ public:
   virtual ~Camera();
 
   /// parse camera mode from lisp file
-  void parse(LispReader& reader);
+  void parse(const lisp::Lisp& reader);
   /// write camera mode to a lisp file
-  virtual void write(LispWriter& writer);
+  virtual void write(lisp::Writer& writer);
 
   /// reset camera postion
   virtual void reset(const Vector& tuxpos);
index 3201eb2..bce0f21 100644 (file)
@@ -146,289 +146,6 @@ FloatingText::draw(DrawingContext& context)
   context.pop_transform();
 }
 
-/* Trampoline */
-
-#if 0
-Sprite *img_trampoline;
-
-Trampoline::Trampoline(LispReader& reader)
-{
-  reader.read_float("x", base.x);
-  reader.read_float("y", base.y); 
-  base.width = 32;
-  base.height = 32;
-  power = 7.5;
-  reader.read_float("power", power);
-
-  frame = 0;
-  mode = M_NORMAL;
-  physic.reset();
-}
-
-Trampoline::Trampoline(float x, float y)
-{
-  base.x = x;
-  base.y = y;
-  base.width = 32;
-  base.height = 32;
-  power = 7.5;
-
-  frame = 0;
-  mode = M_NORMAL;
-  physic.reset();
-}
-
-void
-Trampoline::write(LispWriter& writer)
-{
-  writer.start_list("trampoline");
-
-  writer.write_float("x", base.x);
-  writer.write_float("y", base.y);
-  writer.write_float("power", power);
-
-  writer.end_list("trampoline");
-}
-
-void
-Trampoline::draw(DrawingContext& context)
-{
-  img_trampoline->set_frame(frame);
-  img_trampoline->draw(context, base, LAYER_OBJECTS);
-  frame = 0;
-}
-
-void
-Trampoline::action(float frame_ratio)
-{
-  // TODO: Remove if we're too far off the screen
-
-  // Falling
-  if (mode != M_HELD)
-  {
-    if (issolid(base.x + base.width/2, base.y + base.height))
-    {
-      base.y = int((base.y + base.height)/32) * 32 - base.height;
-
-      physic.enable_gravity(false);
-      physic.set_velocity_y(0.0f);
-
-      physic.set_velocity_x(0);
-    }
-    else
-    {
-      physic.enable_gravity(true);
-    }
-  }
-  else // Player is carrying us around
-  {
-    /* FIXME: The trampoline object shouldn't know about pplayer objects. */
-    /* If we're holding the iceblock */
-    Player& tux = *Sector::current()->player;
-    Direction dir = tux.dir;
-
-    if(dir == RIGHT)
-    {
-      base.x = tux.base.x + 16;
-      base.y = tux.base.y + tux.base.height/1.5 - base.height;
-    }
-    else /* facing left */
-    {
-      base.x = tux.base.x - 16;
-      base.y = tux.base.y + tux.base.height/1.5 - base.height;
-    }
-
-    if(collision_object_map(base))
-    {
-      base.x = tux.base.x;
-      base.y = tux.base.y + tux.base.height/1.5 - base.height;
-    }
-  }
-
-  physic.apply(frame_ratio, base.x, base.y, Sector::current()->gravity);
-  collision_swept_object_map(&old_base, &base);
-}
-
-void
-Trampoline::collision(const MovingObject&, int)
-{
-  // comes later
-}
-
-void
-Trampoline::collision(void *p_c_object, int c_object, CollisionType type)
-{
-  Player* pplayer_c = NULL;
-  switch (c_object)
-  {
-    case CO_PLAYER:
-      pplayer_c = (Player*) p_c_object;
-
-      if (type == COLLISION_NORMAL)
-      {
-        // Pick up if HELD (done in Player)
-      }
-
-      else if (type == COLLISION_SQUISH)
-      {
-        int squish_amount = (32 - (int)pplayer_c->base.y % 32);
-
-        if (squish_amount < 24)
-          frame = 3;
-        else if (squish_amount < 28)
-          frame = 2;
-        else if (squish_amount < 30)
-          frame = 1;
-        else
-          frame = 0;
-
-        if (squish_amount < 20) {
-          pplayer_c->physic.set_velocity_y(power);
-          pplayer_c->fall_mode = Player::TRAMPOLINE_JUMP;
-        }
-        else if (pplayer_c->physic.get_velocity_y() < 0)
-          pplayer_c->physic.set_velocity_y(-squish_amount/32);
-      }
-
-      break;
-
-    default:
-      break;
-    
-  }
-}
-#endif
-
-/* Flying Platform */
-
-#if 0
-Sprite *img_flying_platform;
-
-FlyingPlatform::FlyingPlatform(LispReader& reader)
-{
-  reader.read_int_vector("x", pos_x);
-  reader.read_int_vector("y", pos_y);
-
-  velocity = 2.0;
-  reader.read_float("velocity", velocity);
-
-  base.x = pos_x[0];
-  base.y = pos_y[0];
-  base.width = 96;
-  base.height = 40;
-
-  point = 0;
-  move = false;
-
-  float x = pos_x[point+1] - pos_x[point];
-  float y = pos_y[point+1] - pos_y[point];
-  vel_x = x*velocity / sqrt(x*x + y*y);
-  vel_y = -(velocity - vel_x);
-
-  frame = 0;
-}
-
-FlyingPlatform::FlyingPlatform(int x, int y)
-{
-base.x = x;
-base.y = y;
-point = 0;
-move = false;
-}
-
-void
-FlyingPlatform::write(LispWriter& writer)
-{
-  writer.start_list("flying-trampoline");
-
-  writer.write_int_vector("x", pos_x);
-  writer.write_int_vector("y", pos_y);
-  writer.write_float("velocity", velocity);
-
-  writer.end_list("flying-trampoline");
-}
-
-void
-FlyingPlatform::draw(DrawingContext& context)
-{
-  img_flying_platform->draw(context, base, LAYER_OBJECTS);
-}
-
-void
-FlyingPlatform::action(float frame_ratio)
-{
-  // TODO: Remove if we're too far off the screen
-
-if(!move)
-  return;
-
-if((unsigned)point+1 != pos_x.size())
-  {
-  if(((pos_x[point+1] > pos_x[point] && base.x >= pos_x[point+1]) ||
-      (pos_x[point+1] < pos_x[point] && base.x <= pos_x[point+1]) ||
-      pos_x[point] == pos_x[point+1]) &&
-    ((pos_y[point+1] > pos_y[point] && base.y >= pos_y[point+1]) ||
-      (pos_y[point+1] < pos_y[point] && base.y <= pos_y[point+1]) ||
-      pos_y[point] == pos_y[point+1]))
-    {
-    point++;
-
-    float x = pos_x[point+1] - pos_x[point];
-    float y = pos_y[point+1] - pos_y[point];
-    vel_x = x*velocity / sqrt(x*x + y*y);
-    vel_y = -(velocity - vel_x);
-    }
-  }
-else   // last point
-  {
-  // point = 0;
-  // reverse vector
-  return;
-  }
-/*
-if(pos_x[point+1] > base.x)
-  base.x += velocity * frame_ratio;
-else if(pos_x[point+1] < base.x)
-  base.x -= velocity * frame_ratio;
-
-if(pos_y[point+1] > base.y)
-  base.y += velocity * frame_ratio;
-else if(pos_y[point+1] < base.y)
-  base.y -= velocity * frame_ratio;
-*/
-
-base.x += vel_x * frame_ratio;
-base.y += vel_y * frame_ratio;
-}
-
-void
-FlyingPlatform::collision(const MovingObject&, int)
-{
-  // comes later
-}
-
-void
-FlyingPlatform::collision(void *p_c_object, int c_object, CollisionType type)
-{
-(void) p_c_object;
-(void) type;
-
-//  Player* pplayer_c = NULL;
-  switch (c_object)
-  {
-    case CO_PLAYER:
-//      pplayer_c = (Player*) p_c_object;
-      move = true;
-
-      break;
-
-    default:
-      break;
-    
-  }
-}
-#endif
-
 Sprite *img_smoke_cloud = 0;
 
 SmokeCloud::SmokeCloud(const Vector& pos)
index 3d928be..6b884d7 100644 (file)
@@ -18,7 +18,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef SUPERTUX_GAMEOBJS_H
 #define SUPERTUX_GAMEOBJS_H
 
@@ -29,7 +28,6 @@
 #include "special/game_object.h"
 #include "special/moving_object.h"
 #include "serializable.h"
-#include "utils/lispwriter.h"
 
 /* Bounciness of distros: */
 #define NO_BOUNCE 0
@@ -84,31 +82,6 @@ private:
   Timer2 timer;  
 };
 
-#if 0
-extern Sprite *img_trampoline;
-
-class Trampoline : public MovingObject, public Serializable
-{
-public:
-  Trampoline(LispReader& reader);
-  Trampoline(float x, float y);
-  virtual void write(LispWriter& writer);
-  virtual void action(float frame_ratio);
-  virtual void draw(DrawingContext& context);
-
-  virtual void collision(const MovingObject& other, int);
-  void collision(void *p_c_object, int c_object, CollisionType type);
-
-  Physic physic;
-  enum { M_NORMAL, M_HELD } mode;
-
- private:
-  float power;
-  unsigned int frame;
-};
-#endif
-
 extern Sprite *img_smoke_cloud;
 
 class SmokeCloud : public GameObject
index b82152a..4c24b1f 100644 (file)
 
 #include "particlesystem.h"
 #include "app/globals.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
 #include "video/drawing_context.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 ParticleSystem::ParticleSystem()
 {
@@ -97,13 +98,13 @@ SnowParticleSystem::SnowParticleSystem()
 }
 
 void
-SnowParticleSystem::parse(LispReader& reader)
+SnowParticleSystem::parse(const lisp::Lisp& reader)
 {
-  reader.read_int("layer", layer);
+  reader.get("layer", layer);
 }
 
 void
-SnowParticleSystem::write(LispWriter& writer)
+SnowParticleSystem::write(lisp::Writer& writer)
 {
   writer.start_list("particles-snow");
   writer.write_int("layer", layer);
@@ -148,13 +149,13 @@ CloudParticleSystem::CloudParticleSystem()
 }
 
 void
-CloudParticleSystem::parse(LispReader& reader)
+CloudParticleSystem::parse(const lisp::Lisp& reader)
 {
-  reader.read_int("layer", layer);
+  reader.get("layer", layer);
 }
 
 void
-CloudParticleSystem::write(LispWriter& writer)
+CloudParticleSystem::write(lisp::Writer& writer)
 {
   writer.start_list("particles-clouds");
   writer.write_int("layer", layer);
index d11c5c1..2aae295 100644 (file)
@@ -28,8 +28,8 @@
 
 using namespace SuperTux;
 
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
 }
 
 class DisplayManager;
@@ -80,8 +80,8 @@ public:
     SnowParticleSystem();
     virtual ~SnowParticleSystem();
 
-    void parse(LispReader& reader);
-    void write(LispWriter& writer);
+    void parse(const lisp::Lisp& lisp);
+    void write(lisp::Writer& writer);
 
     virtual void action(float elapsed_time);
 
@@ -104,8 +104,8 @@ public:
     CloudParticleSystem();
     virtual ~CloudParticleSystem();
 
-    void parse(LispReader& reader);
-    void write(LispWriter& writer);
+    void parse(const lisp::Lisp& lisp);
+    void write(lisp::Writer& writer);
 
     virtual void action(float elapsed_time);
 
index d72b7ac..f418596 100644 (file)
@@ -5,14 +5,15 @@
 #include "resources.h"
 #include "player.h"
 #include "special/sprite_manager.h"
-#include "utils/lispreader.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
-Platform::Platform(LispReader& reader)
+Platform::Platform(const lisp::Lisp& reader)
 {
   sprite = sprite_manager->create("flying_platform");
   movement = Vector(0, 1);
-  reader.read_float("x", bbox.p1.x);
-  reader.read_float("y", bbox.p1.y);
+  reader.get("x", bbox.p1.x);
+  reader.get("y", bbox.p1.y);
   bbox.set_size(sprite->get_width(), sprite->get_height());
 
   flags |= FLAG_SOLID;
index be4119b..1ff2860 100644 (file)
@@ -12,7 +12,7 @@ using namespace SuperTux;
 class Platform : public SuperTux::MovingObject
 {
 public:
-  Platform(LispReader& reader);
+  Platform(const lisp::Lisp& reader);
   ~Platform();
 
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
index 0878441..fd6c74d 100644 (file)
 #include "video/drawing_context.h"
 #include "level.h"
 #include "tile.h"
+#include "resources.h"
 #include "tile_manager.h"
 #include "app/globals.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 TileMap::TileMap()
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
     vertical_flip(false)
 {
-  tilemanager = TileManager::instance();
+  tilemanager = tile_manager;
 
   if(solid)
     flags |= FLAG_SOLID;
 }
 
-TileMap::TileMap(LispReader& reader)
+TileMap::TileMap(const lisp::Lisp& reader)
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
     vertical_flip(false)
 {
-  tilemanager = TileManager::instance();
+  tilemanager = tile_manager;
 
   std::string layer_str;
-  if(reader.read_string("layer", layer_str)) {
+  if(reader.get("layer", layer_str)) {
     if(layer_str == "background")
       layer = LAYER_BACKGROUNDTILES;
     else if(layer_str == "interactive")
@@ -61,8 +62,8 @@ TileMap::TileMap(LispReader& reader)
       std::cerr << "Unknown layer '" << layer_str << "' in tilemap.\n";
   }
 
-  reader.read_bool("solid", solid);
-  reader.read_float("speed", speed);
+  reader.get("solid", solid);
+  reader.get("speed", speed);
 
   if(solid && speed != 1) {
     std::cout << "Speed of solid tilemap is not 1. fixing.\n";
@@ -71,22 +72,23 @@ TileMap::TileMap(LispReader& reader)
   if(solid)
     flags |= FLAG_SOLID;
   
-  if(!reader.read_int("width", width) ||
-     !reader.read_int("height", height))
+  if(!reader.get("width", width) ||
+     !reader.get("height", height))
     throw std::runtime_error("No width or height specified in tilemap.");
 
-  if(!reader.read_int_vector("tiles", tiles))
+  if(!reader.get_vector("tiles", tiles))
     throw std::runtime_error("No tiles in tilemap.");
 
-  if(int(tiles.size()) != width*height)
+  if(int(tiles.size()) != width*height) {
     throw std::runtime_error("wrong number of tiles in tilemap.");
+  }
 }
 
 TileMap::TileMap(int layer_, bool solid_, size_t width_, size_t height_)
   : solid(solid_), speed(1), width(0), height(0), layer(layer_),
     vertical_flip(false)
 {
-  tilemanager = TileManager::instance();
+  tilemanager = tile_manager;
   
   resize(width_, height_);
 
@@ -99,7 +101,7 @@ TileMap::~TileMap()
 }
 
 void
-TileMap::write(LispWriter& writer)
+TileMap::write(lisp::Writer& writer)
 {
   writer.start_list("tilemap");
 
@@ -182,7 +184,8 @@ void
 TileMap::set(int newwidth, int newheight, const std::vector<unsigned int>&newt,
     int newlayer, bool newsolid)
 {
-  assert(int(newt.size()) == newwidth * newheight);
+  if(int(newt.size()) != newwidth * newheight)
+    throw std::runtime_error("Wrong tilecount count.");
 
   width  = newwidth;
   height = newheight;
index 8aa2b48..ecf8d10 100644 (file)
 #include "serializable.h"
 #include "math/vector.h"
 
-using namespace SuperTux;
-
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
 }
 
+using namespace SuperTux;
+
 class Level;
 class TileManager;
 class Tile;
@@ -44,11 +44,11 @@ class TileMap : public GameObject, public Serializable
 {
 public:
   TileMap();
-  TileMap(LispReader& reader);
+  TileMap(const lisp::Lisp& reader);
   TileMap(int layer_, bool solid_, size_t width_, size_t height_);
   virtual ~TileMap();
 
-  virtual void write(LispWriter& writer);
+  virtual void write(lisp::Writer& writer);
 
   virtual void action(float elapsed_time);
   virtual void draw(DrawingContext& context);
index 5267f4b..e57ee37 100644 (file)
@@ -26,6 +26,7 @@
 #include "gui/button.h"
 #include "scene.h"
 #include "resources.h"
+#include "tile_manager.h"
 #include "object/gameobjs.h"
 #include "object/player.h"
 
@@ -52,6 +53,7 @@ MusicRef herring_song;
 MusicRef level_end_song;
 
 SpriteManager* sprite_manager = 0;
+TileManager* tile_manager = 0;
 
 char * soundfilenames[NUM_SOUNDS] = {
                                        "/sounds/jump.wav",
@@ -114,7 +116,9 @@ void loadshared()
 
   int i;
 
-  sprite_manager = new SpriteManager(datadir + "/images/supertux.strf");
+  sprite_manager = new SpriteManager(
+      get_resource_filename("/images/supertux.strf"));
+  tile_manager = new TileManager("/images/tilesets/supertux.stgt");
 
   /* Tuxes: */
   smalltux_star = sprite_manager->create("smalltux-star");
@@ -302,6 +306,8 @@ void unloadshared(void)
 
   delete sprite_manager;
   sprite_manager = 0;
+  delete tile_manager;
+  tile_manager = 0;
 }
 
 std::string get_resource_filename(const std::string& resource)
index f399af8..c152f0c 100644 (file)
@@ -32,6 +32,8 @@ class Font;
 class Surface;
 }
 
+class TileManager;
+
 /* Sound files: */
 enum {
   SND_JUMP,
@@ -73,6 +75,7 @@ extern MusicRef herring_song;
 extern MusicRef level_end_song;
 
 extern SpriteManager* sprite_manager;
+extern TileManager* tile_manager;
 
 extern Menu* contrib_menu;
 extern Menu* contrib_subset_menu;
index a33ad64..abb28f9 100644 (file)
 
 #include "app/globals.h"
 #include "sector.h"
-#include "utils/lispreader.h"
 #include "object/gameobjs.h"
 #include "object/camera.h"
 #include "object/background.h"
 #include "object/particlesystem.h"
 #include "object/tilemap.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
+#include "lisp/list_iterator.h"
 #include "tile.h"
 #include "audio/sound_manager.h"
 #include "gameloop.h"
@@ -92,7 +95,7 @@ Sector::~Sector()
 }
 
 GameObject*
-Sector::parse_object(const std::string& name, LispReader& reader)
+Sector::parse_object(const std::string& name, const lisp::Lisp& reader)
 {
   if(name == "background") {
     return new Background(reader);
@@ -143,32 +146,30 @@ Sector::parse_object(const std::string& name, LispReader& reader)
 }
 
 void
-Sector::parse(LispReader& lispreader)
+Sector::parse(const lisp::Lisp& sector)
 {
   _current = this;
   
-  for(lisp_object_t* cur = lispreader.get_lisp(); !lisp_nil_p(cur);
-      cur = lisp_cdr(cur)) {
-    std::string token = lisp_symbol(lisp_car(lisp_car(cur)));
-    // FIXME: doesn't handle empty data
-    lisp_object_t* data = lisp_car(lisp_cdr(lisp_car(cur)));
-    LispReader reader(lisp_cdr(lisp_car(cur)));
-
+  lisp::ListIterator iter(&sector);
+  while(iter.next()) {
+    const std::string& token = iter.item();
     if(token == "name") {
-      name = lisp_string(data);
+      iter.value()->get(name);
     } else if(token == "gravity") {
-      gravity = lisp_real(data);
+      iter.value()->get(gravity);
     } else if(token == "music") {
-      song_title = lisp_string(data);
+      iter.value()->get(song_title);
       load_music();
-    } else if(token == "spawn-points") {
+    } else if(token == "spawnpoint") {
+      const lisp::Lisp* spawnpoint_lisp = iter.lisp();
+      
       SpawnPoint* sp = new SpawnPoint;
-      reader.read_string("name", sp->name);
-      reader.read_float("x", sp->pos.x);
-      reader.read_float("y", sp->pos.y);
+      spawnpoint_lisp->get("name", sp->name);
+      spawnpoint_lisp->get("x", sp->pos.x);
+      spawnpoint_lisp->get("y", sp->pos.y);
       spawnpoints.push_back(sp);
     } else {
-      GameObject* object = parse_object(token, reader);
+      GameObject* object = parse_object(token, *(iter.lisp()));
       if(object) {
         add_object(object);
       }
@@ -188,31 +189,31 @@ Sector::parse(LispReader& lispreader)
 }
 
 void
-Sector::parse_old_format(LispReader& reader)
+Sector::parse_old_format(const lisp::Lisp& reader)
 {
   _current = this;
   
   name = "main";
-  reader.read_float("gravity", gravity);
+  reader.get("gravity", gravity);
 
   std::string backgroundimage;
-  reader.read_string("background", backgroundimage);
+  reader.get("background", backgroundimage);
   float bgspeed = .5;
-  reader.read_float("bkgd_speed", bgspeed);
+  reader.get("bkgd_speed", bgspeed);
   bgspeed /= 100;
 
   Color bkgd_top, bkgd_bottom;
   int r = 0, g = 0, b = 128;
-  reader.read_int("bkgd_red_top", r);
-  reader.read_int("bkgd_green_top",  g);
-  reader.read_int("bkgd_blue_top",  b);
+  reader.get("bkgd_red_top", r);
+  reader.get("bkgd_green_top",  g);
+  reader.get("bkgd_blue_top",  b);
   bkgd_top.red = r;
   bkgd_top.green = g;
   bkgd_top.blue = b;
   
-  reader.read_int("bkgd_red_bottom",  r);
-  reader.read_int("bkgd_green_bottom", g);
-  reader.read_int("bkgd_blue_bottom", b);
+  reader.get("bkgd_red_bottom",  r);
+  reader.get("bkgd_green_bottom", g);
+  reader.get("bkgd_blue_bottom", b);
   bkgd_bottom.red = r;
   bkgd_bottom.green = g;
   bkgd_bottom.blue = b;
@@ -228,15 +229,15 @@ Sector::parse_old_format(LispReader& reader)
   }
 
   std::string particlesystem;
-  reader.read_string("particle_system", particlesystem);
+  reader.get("particle_system", particlesystem);
   if(particlesystem == "clouds")
     add_object(new CloudParticleSystem());
   else if(particlesystem == "snow")
     add_object(new SnowParticleSystem());
 
   Vector startpos(100, 170);
-  reader.read_float("start_pos_x", startpos.x);
-  reader.read_float("start_pos_y", startpos.y);
+  reader.get("start_pos_x", startpos.x);
+  reader.get("start_pos_y", startpos.y);
 
   SpawnPoint* spawn = new SpawnPoint;
   spawn->pos = startpos;
@@ -244,73 +245,63 @@ Sector::parse_old_format(LispReader& reader)
   spawnpoints.push_back(spawn);
 
   song_title = "Mortimers_chipdisko.mod";
-  reader.read_string("music", song_title);
+  reader.get("music", song_title);
   load_music();
 
   int width, height = 15;
-  reader.read_int("width", width);
-  reader.read_int("height", height);
+  reader.get("width", width);
+  reader.get("height", height);
   
   std::vector<unsigned int> tiles;
-  if(reader.read_int_vector("interactive-tm", tiles)
-      || reader.read_int_vector("tilemap", tiles)) {
+  if(reader.get_vector("interactive-tm", tiles)
+      || reader.get_vector("tilemap", tiles)) {
     TileMap* tilemap = new TileMap();
     tilemap->set(width, height, tiles, LAYER_TILES, true);
     add_object(tilemap);
   }
 
-  if(reader.read_int_vector("background-tm", tiles)) {
+  if(reader.get_vector("background-tm", tiles)) {
     TileMap* tilemap = new TileMap();
     tilemap->set(width, height, tiles, LAYER_BACKGROUNDTILES, false);
     add_object(tilemap);
   }
 
-  if(reader.read_int_vector("foreground-tm", tiles)) {
+  if(reader.get_vector("foreground-tm", tiles)) {
     TileMap* tilemap = new TileMap();
     tilemap->set(width, height, tiles, LAYER_FOREGROUNDTILES, false);
     add_object(tilemap);
   }
 
   // read reset-points (now spawn-points)
-  {
-    lisp_object_t* cur = 0;
-    if(reader.read_lisp("reset-points", cur)) {
-      while(!lisp_nil_p(cur)) {
-        lisp_object_t* data = lisp_car(cur);
-        LispReader reader(lisp_cdr(data));
-
+  const lisp::Lisp* resetpoints = reader.get_lisp("reset-points");
+  if(resetpoints) {
+    lisp::ListIterator iter(resetpoints);
+    while(iter.next()) {
+      if(iter.item() == "point") {
         Vector sp_pos;
-        if(reader.read_float("x", sp_pos.x) && reader.read_float("y", sp_pos.y))
+        if(reader.get("x", sp_pos.x) && reader.get("y", sp_pos.y))
           {
           SpawnPoint* sp = new SpawnPoint;
           sp->name = "main";
           sp->pos = sp_pos;
           spawnpoints.push_back(sp);
           }
-                                                             
-        cur = lisp_cdr(cur);
+      } else {
+        std::cerr << "Unknown token '" << iter.item() << "' in reset-points.\n";
       }
     }
   }
 
   // read objects
-  {
-    lisp_object_t* cur = 0;
-    if(reader.read_lisp("objects", cur)) {
-      while(!lisp_nil_p(cur)) {
-        lisp_object_t* data = lisp_car(cur);
-        std::string object_type = lisp_symbol(lisp_car(data));
-                                                                                
-        LispReader reader(lisp_cdr(data));
-
-        GameObject* object = parse_object(object_type, reader);
-        if(object) {
-          add_object(object);
-        } else {
-          std::cerr << "Unknown object '" << object_type << "' in level.\n";
-        }
-                                                                               
-        cur = lisp_cdr(cur);
+  const lisp::Lisp* objects = reader.get_lisp("objects");
+  if(objects) {
+    lisp::ListIterator iter(objects);
+    while(iter.next()) {
+      GameObject* object = parse_object(iter.item(), *(iter.lisp()));
+      if(object) {
+        add_object(object);
+      } else {
+        std::cerr << "Unknown object '" << iter.item() << "' in level.\n";
       }
     }
   }
@@ -371,7 +362,7 @@ Sector::fix_old_tiles()
 }
 
 void
-Sector::write(LispWriter& writer)
+Sector::write(lisp::Writer& writer)
 {
   writer.write_string("name", name);
   writer.write_float("gravity", gravity);
index 45a2cd5..ee08514 100644 (file)
@@ -32,11 +32,13 @@ using namespace SuperTux;
 
 namespace SuperTux {
 class GameObject;
-class LispReader;
-class LispWriter;
 class Sprite;
 class Rectangle;
 }
+namespace lisp {
+class Lisp;
+class Writer;
+}
 
 class InteractiveObject;
 class Background;
@@ -68,10 +70,10 @@ public:
   ~Sector();
 
   /// read sector from lisp file
-  void parse(LispReader& reader);
-  void parse_old_format(LispReader& reader);
+  void parse(const lisp::Lisp& lisp);
+  void parse_old_format(const lisp::Lisp& lisp);
   /// write sector to lisp file
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
 
   /// activates this sector (change music, intialize player class, ...)
   void activate(const std::string& spawnpoint = "main");
@@ -118,7 +120,7 @@ private:
   void collision_object(MovingObject* object1, MovingObject* object2);
   
   void load_music();
-  GameObject* parse_object(const std::string& name, LispReader& reader);
+  GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp);
   
   static Sector* _current;
   
index 5590207..3fc7020 100644 (file)
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_SERIALIZABLE_H
 #define SUPERTUX_SERIALIZABLE_H
 
 using namespace SuperTux;
 
-namespace SuperTux {
-class LispWriter;
+namespace lisp {
+class Writer;
 }
 
 class Serializable
 {
 public:
-  virtual void write(LispWriter& writer) = 0;
+  virtual void write(lisp::Writer& writer) = 0;
 };
 
 #endif /*SUPERTUX_SERIALIZABLE_H*/
index 0b1498d..dc3e83a 100644 (file)
 
 #include <config.h>
 
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
 #include "video/drawing_context.h"
 #include "app/gettext.h"
 #include "app/globals.h"
+#include "lisp/lisp.h"
 #include "resources.h"
 #include "statistics.h"
 
@@ -70,23 +69,21 @@ Statistics::~Statistics()
 }
 
 void
-Statistics::parse(LispReader& reader)
+Statistics::parse(const lisp::Lisp& reader)
 {
-  for(int i = 0; i < NUM_STATS; i++)
-    {
-    reader.read_int(stat_name_to_string(i).c_str(), stats[i][SPLAYER]);
-    reader.read_int((stat_name_to_string(i) + "-total").c_str(), stats[i][STOTAL]);
-    }
+  for(int i = 0; i < NUM_STATS; i++) {
+    reader.get(stat_name_to_string(i).c_str(), stats[i][SPLAYER]);
+    reader.get((stat_name_to_string(i) + "-total").c_str(), stats[i][STOTAL]);
+  }
 }
 
 void
-Statistics::write(LispWriter& writer)
+Statistics::write(lisp::Writer& writer)
 {
-  for(int i = 0; i < NUM_STATS; i++)
-    {
+  for(int i = 0; i < NUM_STATS; i++) {
     writer.write_int(stat_name_to_string(i), stats[i][SPLAYER]);
     writer.write_int(stat_name_to_string(i) + "-total", stats[i][STOTAL]);
-    }
+  }
 }
 
 #define TOTAL_DISPLAY_TIME 3400
index 9f15332..2bd8774 100644 (file)
 #define SUPERTUX_STATISTICS_H
 
 #include "timer.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 using namespace SuperTux;
 
 namespace SuperTux {
-class LispReader;
-class LispWriter;
 class DrawingContext;
 }
 
@@ -53,9 +53,9 @@ public:
   ~Statistics();
 
   /// read statistics from lisp file
-  void parse(LispReader& reader);
+  void parse(const lisp::Lisp& lisp);
   /// write statistics to lisp file
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
 
   /* Draw to the worldmap or a game message */
   // TODO: make this functions working
index 77ea138..0b67db7 100644 (file)
@@ -94,7 +94,6 @@ int main(int argc, char * argv[])
     unloadshared();
     Setup::general_free();
     st_menu_free();
-    TileManager::destroy_instance();
 #ifdef DEBUG
     Surface::debug_check();
 #endif
index 5668fa6..a57d304 100644 (file)
 #include <stdexcept>
 
 #include "app/globals.h"
+#include "lisp/lisp.h"
 #include "tile.h"
 #include "scene.h"
 #include "resources.h"
-#include "utils/lispreader.h"
 #include "math/vector.h"
 #include "video/drawing_context.h"
 
@@ -47,78 +47,91 @@ Tile::~Tile()
 }
 
 void
-Tile::parse(LispReader& reader)
+Tile::parse(const lisp::Lisp& reader)
 {
-  if(!reader.read_uint("id", id)) {
+  if(!reader.get("id", id)) {
     throw std::runtime_error("Missing tile-id.");
   }
   
   bool value;
-  if(reader.read_bool("solid", value) && value)
+  if(reader.get("solid", value) && value)
     attributes |= SOLID;
-  if(reader.read_bool("unisolid", value) && value)
+  if(reader.get("unisolid", value) && value)
     attributes |= UNISOLID | SOLID;
-  if(reader.read_bool("brick", value) && value)
+  if(reader.get("brick", value) && value)
     attributes |= BRICK;
-  if(reader.read_bool("ice", value) && value)
+  if(reader.get("ice", value) && value)
     attributes |= ICE;
-  if(reader.read_bool("water", value) && value)
+  if(reader.get("water", value) && value)
     attributes |= WATER;
-  if(reader.read_bool("spike", value) && value)
+  if(reader.get("spike", value) && value)
     attributes |= SPIKE;
-  if(reader.read_bool("fullbox", value) && value)
+  if(reader.get("fullbox", value) && value)
     attributes |= FULLBOX;
-  if(reader.read_bool("distro", value) && value)
+  if(reader.get("distro", value) && value)
     attributes |= COIN;
-  if(reader.read_bool("coin", value) && value)
+  if(reader.get("coin", value) && value)
     attributes |= COIN;
-  if(reader.read_bool("goal", value) && value)
+  if(reader.get("goal", value) && value)
     attributes |= GOAL;
 
-  reader.read_int("data", data);
-  reader.read_float("anim-fps", anim_fps);
+  if(reader.get("north", value) && value)
+    data |= WORLDMAP_NORTH;
+  if(reader.get("south", value) && value)
+    data |= WORLDMAP_SOUTH;
+  if(reader.get("west", value) && value)
+    data |= WORLDMAP_WEST;
+  if(reader.get("east", value) && value) 
+    data |= WORLDMAP_EAST;
+  if(reader.get("stop", value) && value)
+    data |= WORLDMAP_STOP;                      
 
-  if(reader.read_int("slope-type", data)) {
+  reader.get("data", data);
+  reader.get("anim-fps", anim_fps);
+
+  if(reader.get("slope-type", data)) {
     attributes |= SOLID | SLOPE;
   }
 
-  parse_images(reader.read_lisp("images"));
-  reader.read_string("editor-images", editor_imagefile);
+  const lisp::Lisp* images = reader.get_lisp("images");
+  if(images)
+    parse_images(*images);
+  reader.get("editor-images", editor_imagefile);
 }
 
 void
-Tile::parse_images(lisp_object_t* list)
+Tile::parse_images(const lisp::Lisp& images_lisp)
 {
-  while(!lisp_nil_p(list)) {
-    lisp_object_t* cur = lisp_car(list);
-    if(lisp_string_p(cur)) {
-      imagespecs.push_back(ImageSpec(lisp_string(cur), Rectangle(0, 0, 0, 0)));
-    } else if(lisp_cons_p(cur) && lisp_symbol_p(lisp_car(cur))) {
-      lisp_object_t* sym  = lisp_car(cur);
-      lisp_object_t* data = lisp_cdr(cur);
-      
-      if (strcmp(lisp_symbol(sym), "region") == 0) {
-        float x = lisp_integer(lisp_list_nth(data, 1));
-        float y = lisp_integer(lisp_list_nth(data, 2));
-        float width = lisp_integer(lisp_list_nth(data, 3));
-        float height = lisp_integer(lisp_list_nth(data, 4));
-        imagespecs.push_back(ImageSpec(lisp_string(lisp_car(data)),
-              Rectangle(x, y, x+width, y+height)));
-      } else {
-        std::cerr << "Tile: Type mismatch, should be '(region \"somestring\" x y w h)'" << std::endl;
-        continue;
-      }
+  const lisp::Lisp* list = &images_lisp;
+  while(list) {
+    const lisp::Lisp* cur = list->get_car();
+    if(cur->get_type() == lisp::Lisp::TYPE_STRING) {
+      std::string file;
+      cur->get(file);
+      imagespecs.push_back(ImageSpec(file, Rectangle(0, 0, 0, 0)));
+    } else if(cur->get_type() == lisp::Lisp::TYPE_CONS && 
+        cur->get_car()->get_type() == lisp::Lisp::TYPE_SYMBOL) {
+      const lisp::Lisp* ptr = cur->get_cdr();
+
+      std::string file;
+      float x, y, w, h;
+      ptr->get_car()->get(file); ptr = ptr->get_cdr();
+      ptr->get_car()->get(x); ptr = ptr->get_cdr();
+      ptr->get_car()->get(y); ptr = ptr->get_cdr();
+      ptr->get_car()->get(w); ptr = ptr->get_cdr();
+      ptr->get_car()->get(h);
+      imagespecs.push_back(ImageSpec(file, Rectangle(x, y, x+w, y+h)));
     } else {
       std::cerr << "Expected string or list in images tag.\n";
       continue;
     }
     
-    list = lisp_cdr(list);
+    list = list->get_cdr();
   }
 }
 
 void
-Tile::load_images()
+Tile::load_images(const std::string& tilesetpath)
 {
   assert(images.size() == 0);
   for(std::vector<ImageSpec>::iterator i = imagespecs.begin(); i !=
@@ -126,7 +139,7 @@ Tile::load_images()
     const ImageSpec& spec = *i;
     Surface* surface;
     std::string file 
-      = get_resource_filename(std::string("images/tilesets/") + spec.file);
+      = get_resource_filename(tilesetpath + spec.file);
     if(spec.rect.get_width() <= 0) {
       surface = new Surface(file, true);
     } else {
index ff76569..a5f5856 100644 (file)
@@ -22,8 +22,8 @@
 
 #include <vector>
 #include "video/surface.h"
-#include "utils/lispreader.h"
 #include "math/rectangle.h"
+#include "lisp/lisp.h"
 
 using namespace SuperTux;
 
@@ -57,7 +57,17 @@ public:
      */
     GOAL      = 0x0100,
     /** slope tile */
-    SLOPE     = 0x0200
+    SLOPE     = 0x0200,
+  };
+
+  /// worldmap flags
+  enum {
+    WORLDMAP_NORTH = 0x0001,
+    WORLDMAP_SOUTH = 0x0002,
+    WORLDMAP_EAST  = 0x0004,
+    WORLDMAP_WEST  = 0x0008,
+    
+    WORLDMAP_STOP  = 0x0010
   };
   
 private:
@@ -122,11 +132,11 @@ protected:
   friend class TileManager;
   Tile();
 
-  void load_images();
+  void load_images(const std::string& tilesetpath);
 
   /// parses the tile and returns it's id number
-  void parse(LispReader& reader);
-  void parse_images(lisp_object_t* cur);
+  void parse(const lisp::Lisp& reader);
+  void parse_images(const lisp::Lisp& cur);
 };
 
 #endif
index 64cf7c0..f2c95e0 100644 (file)
 //  02111-1307, USA.
 #include <config.h>
 
+#include <memory>
+#include <stdexcept>
 #include <assert.h>
 #include "video/drawing_context.h"
 #include "app/setup.h"
 #include "app/globals.h"
-#include "utils/lispreader.h"
+#include "lisp/lisp.h"
+#include "lisp/parser.h"
+#include "lisp/list_iterator.h"
 #include "tile.h"
 #include "tile_manager.h"
+#include "resources.h"
 #include "scene.h"
 
-TileManager* TileManager::instance_  = 0;
-
-TileManager::TileManager()
+TileManager::TileManager(const std::string& filename)
 {
-  std::string filename = datadir + "/images/tilesets/supertux.stgt";
   load_tileset(filename);
 }
 
@@ -48,64 +50,42 @@ void TileManager::load_tileset(std::string filename)
   for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
     delete *i;
   tiles.clear();
-  lisp_object_t* root_obj = lisp_read_from_file(filename);
-
-  if (!root_obj)
-    Termination::abort("Couldn't load file", filename);
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") != 0)
-    assert(false);
 
-  lisp_object_t* cur = lisp_cdr(root_obj);
-  int tileset_id = 0;
-
-  while(!lisp_nil_p(cur)) {
-    lisp_object_t* element = lisp_car(cur);
+  std::string::size_type t = filename.rfind('/');
+  if(t == std::string::npos) {
+    tiles_path = "";
+  } else {
+    tiles_path = filename.substr(0, t+1);
+  }
 
-    if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
-      {
-        LispReader reader(lisp_cdr(element));
+  lisp::Parser parser;
+  std::auto_ptr<lisp::Lisp> root (parser.parse(
+        get_resource_filename(filename)));
 
-        Tile* tile = new Tile;
-        tile->parse(reader);
+  const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles");
+  if(!tiles_lisp)
+    throw std::runtime_error("file is not a supertux tiles file.");
 
-        while(tile->id >= tiles.size()) {
-            tiles.push_back(0);
-        }
-        tiles[tile->id] = tile;
-      }
-    else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
-      {
-        LispReader reader(lisp_cdr(element));
-        std::string filename;
-        reader.read_string("file", filename);
-        filename = datadir + "/images/tilesets/" + filename;
-        load_tileset(filename);
+  lisp::ListIterator iter(tiles_lisp);
+  while(iter.next()) {
+    if(iter.item() == "tile") {
+      Tile* tile = new Tile();
+      tile->parse(*(iter.lisp()));
+      while(tile->id >= tiles.size()) {
+        tiles.push_back(0);
       }
-    else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
-      {
-        TileGroup new_;
-        LispReader reader(lisp_cdr(element));
-        reader.read_string("name", new_.name);
-        reader.read_int_vector("tiles", new_.tiles);         
-        tilegroups.insert(new_).first;
-      }
-    else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
-      {
-        LispReader reader(lisp_cdr(element));
-        reader.read_int("id", tileset_id);
-        tileset_id *= 1000;
-      }
-    else
-      {
-        std::cerr << "Unknown symbol: " << 
-          lisp_symbol(lisp_car(element)) << "\n";
-      }
-
-    cur = lisp_cdr(cur);
+      tiles[tile->id] = tile;
+    } else if(iter.item() == "tilegroup") {
+        TileGroup tilegroup;
+        const lisp::Lisp* tilegroup_lisp = iter.lisp();
+        tilegroup_lisp->get("name", tilegroup.name);
+        tilegroup_lisp->get_vector("tiles", tilegroup.tiles);
+        tilegroups.insert(tilegroup);
+    } else if(iter.item() == "properties") {
+      // deprecated
+    } else {
+      std::cerr << "Unknown symbol '" << iter.item() << "'.\n";
+    }
   }
-
-  lisp_free(root_obj);
 }
 
index 0e58613..db8a70c 100644 (file)
@@ -43,21 +43,19 @@ struct TileGroup
 class TileManager
 {
 private:
-  TileManager();
-  ~TileManager();
-  
   typedef std::vector<Tile*> Tiles;
   Tiles tiles;
 
   static TileManager* instance_ ;
   std::set<TileGroup> tilegroups;
+
+  std::string tiles_path;
+  
   void load_tileset(std::string filename);
 
 public:
-  static TileManager* instance()
-  { return instance_ ? instance_ : instance_ = new TileManager(); }
-  static void destroy_instance()
-  { delete instance_; instance_ = 0; }
+  TileManager(const std::string& filename);
+  ~TileManager();
 
   const std::set<TileGroup>& get_tilegroups() const
   {
@@ -74,7 +72,7 @@ public:
     }
 
     if(tile->images.size() == 0 && tile->imagespecs.size() != 0)
-      tile->load_images();
+      tile->load_images(tiles_path);
     
     return tile;
   }
index 714f9bd..1e5449e 100644 (file)
 #include "title.h"
 #include "video/screen.h"
 #include "video/surface.h"
-#include "high_scores.h"
 #include "gui/menu.h"
 #include "timer.h"
 #include "special/frame_rate.h"
 #include "app/setup.h"
+#include "lisp/lisp.h"
+#include "lisp/parser.h"
 #include "level.h"
 #include "level_subset.h"
 #include "gameloop.h"
@@ -127,13 +128,13 @@ void generate_contrib_menu()
   contrib_menu->additem(MN_HL,"",0,0);
   int i = 0;
 
-  for(std::set<std::string>::iterator it = worldmap_list.begin(); it != worldmap_list.end(); ++it)
-    {
+  for(std::set<std::string>::iterator it = worldmap_list.begin();
+          it != worldmap_list.end(); ++it) {
     WorldMapNS::WorldMap worldmap;
     worldmap.loadmap((*it).c_str());
     contrib_menu->additem(MN_ACTION, worldmap.get_world_title(),0,0, i);
     ++i;
-    }
+  }
 
   contrib_menu->additem(MN_HL,"",0,0);
 
@@ -158,6 +159,25 @@ void generate_contrib_menu()
   level_subsets.clear();
 }
 
+std::string get_level_name(const std::string& filename)
+{
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
+
+    const lisp::Lisp* level = root->get_lisp("supertux-level");
+    if(!level)
+      return "";
+
+    std::string name;
+    level->get("name", name);
+    return name;
+  } catch(std::exception& e) {
+    std::cerr << "Problem getting name of '" << filename << "'.\n";
+    return "";
+  }
+}
+
 void check_levels_contrib_menu()
 {
   static int current_subset = -1;
@@ -214,35 +234,12 @@ void check_levels_contrib_menu()
       contrib_subset_menu->additem(MN_HL,"",0,0);
 
       for (int i = 0; i < subset.get_num_levels(); ++i)
-        {
+      {
         /** get level's title */
-        std::string level_title = "<no title>";
-
         std::string filename = subset.get_level_filename(i);
-        std::string filepath;
-        filepath = st_dir + "/levels/" + filename;
-        if (access(filepath.c_str(), R_OK) != 0)
-        {
-          filepath = datadir + "/levels/" + filename;
-          if (access(filepath.c_str(), R_OK) != 0)
-          {
-            std::cerr << "Error: Level: couldn't find level: " << filename << std::endl;
-            continue;
-          }
-        }
-        
-        LispReader* reader = LispReader::load(filepath, "supertux-level");
-        if(!reader)
-          {
-          std::cerr << "Error: Could not open level file. Ignoring...\n";
-          continue;
-          }
-
-        reader->read_string("name", level_title, true);
-        delete reader;
-
-        contrib_subset_menu->additem(MN_ACTION, level_title, 0, 0, i);
-        }
+        std::string title = get_level_name(filename);
+        contrib_subset_menu->additem(MN_ACTION, title, 0, 0, i);
+      }
 
       contrib_subset_menu->additem(MN_HL,"",0,0);      
       contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0);
index 4c338a5..f493712 100644 (file)
 #include <config.h>
 
 #include "door.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
 #include "gameloop.h"
 #include "resources.h"
 #include "special/sprite.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
 #include "app/globals.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 using namespace SuperTux;
 
-Door::Door(LispReader& reader)
+Door::Door(const lisp::Lisp& reader)
 {
-  reader.read_float("x", bbox.p1.x);
-  reader.read_float("y", bbox.p1.y);
+  reader.get("x", bbox.p1.x);
+  reader.get("y", bbox.p1.y);
   bbox.set_size(32, 64);
 
-  reader.read_string("sector", target_sector);
-  reader.read_string("spawnpoint", target_spawnpoint);
+  reader.get("sector", target_sector);
+  reader.get("spawnpoint", target_spawnpoint);
 
   sprite = sprite_manager->create("door");
 }
@@ -58,7 +58,7 @@ Door::~Door()
 }
 
 void
-Door::write(LispWriter& writer)
+Door::write(lisp::Writer& writer)
 {
   writer.start_list("door");
 
index abcff67..bb27cfe 100644 (file)
 class Door : public TriggerBase, public Serializable
 {
 public:
-  Door(LispReader& reader);
+  Door(const lisp::Lisp& reader);
   Door(int x, int y, std::string sector, std::string spawnpoint);
   virtual ~Door();
 
-  virtual void write(LispWriter& writer);
+  virtual void write(lisp::Writer& writer);
   
   virtual void action(float elapsed_time);
   virtual void draw(DrawingContext& context);
index b57624c..53bbf8d 100644 (file)
@@ -1,19 +1,20 @@
 #include <config.h>
 
 #include "secretarea_trigger.h"
-#include "utils/lispwriter.h"
 #include "gameloop.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
 #define MESSAGE_TIME 3.5
 
 //TODO: Count numbers of triggered/total secret areas
-SecretAreaTrigger::SecretAreaTrigger(LispReader& reader)
+SecretAreaTrigger::SecretAreaTrigger(const lisp::Lisp& reader)
 {
-  reader.read_float("x", bbox.p1.x);
-  reader.read_float("y", bbox.p1.y);
+  reader.get("x", bbox.p1.x);
+  reader.get("y", bbox.p1.y);
   bbox.set_size(32, 32);
 
-  reader.read_string("message", message);
+  reader.get("message", message);
   message_displayed = false;
 }
 
@@ -30,7 +31,7 @@ SecretAreaTrigger::~SecretAreaTrigger()
 }
 
 void
-SecretAreaTrigger::write(LispWriter& writer)
+SecretAreaTrigger::write(lisp::Writer& writer)
 {
   writer.start_list("secretarea");
 
index 945c061..43b10a8 100644 (file)
 class SecretAreaTrigger : public TriggerBase, public Serializable
 {
 public:
-  SecretAreaTrigger(LispReader& reader);
+  SecretAreaTrigger(const lisp::Lisp& reader);
   SecretAreaTrigger(const Vector& pos);
   ~SecretAreaTrigger();
  
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   void event(Player& player, EventType type);
   void draw(DrawingContext& context);
   
index 98789cd..91f9c98 100644 (file)
@@ -1,13 +1,19 @@
 #include <config.h>
 
 #include "sequence_trigger.h"
-#include "utils/lispwriter.h"
 #include "gameloop.h"
+#include "lisp/lisp.h"
+#include "lisp/writer.h"
 
-SequenceTrigger::SequenceTrigger(LispReader& reader)
+SequenceTrigger::SequenceTrigger(const lisp::Lisp& reader)
 {
-  (void) reader;
-  // TODO
+  reader.get("x", bbox.p1.x);
+  reader.get("y", bbox.p1.y);
+  float w, h;
+  reader.get("width", w);
+  reader.get("height", h);
+  bbox.set_size(w, h);
+  reader.get("sequence", sequence_name);
 }
 
 SequenceTrigger::SequenceTrigger(const Vector& pos, const std::string& sequence)
@@ -23,7 +29,7 @@ SequenceTrigger::~SequenceTrigger()
 }
 
 void
-SequenceTrigger::write(LispWriter& writer)
+SequenceTrigger::write(lisp::Writer& writer)
 {
   writer.start_list("sequencetrigger");
 
index b66e760..9ef1eec 100644 (file)
@@ -7,11 +7,11 @@
 class SequenceTrigger : public TriggerBase, public Serializable
 {
 public:
-  SequenceTrigger(LispReader& reader);
+  SequenceTrigger(const lisp::Lisp& reader);
   SequenceTrigger(const Vector& pos, const std::string& sequence);
   ~SequenceTrigger();
  
-  void write(LispWriter& writer);
+  void write(lisp::Writer& writer);
   void event(Player& player, EventType type);
   
 private:
index 299fff5..1c4ab3e 100644 (file)
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include <iostream>
 #include <fstream>
 #include <vector>
 #include <cassert>
+#include <stdexcept>
+#include <sstream>
 #include <unistd.h>
 
 #include "app/globals.h"
+#include "app/gettext.h"
+#include "app/setup.h"
 #include "video/surface.h"
 #include "video/screen.h"
 #include "video/drawing_context.h"
-#include "utils/lispreader.h"
-#include "utils/lispwriter.h"
 #include "special/frame_rate.h"
+#include "audio/sound_manager.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+#include "lisp/list_iterator.h"
+#include "lisp/writer.h"
 #include "gameloop.h"
-#include "app/setup.h"
 #include "sector.h"
 #include "worldmap.h"
-#include "audio/sound_manager.h"
 #include "resources.h"
-#include "app/gettext.h"
 #include "misc.h"
 #include "scene.h"
 
@@ -99,124 +102,6 @@ string_to_direction(const std::string& directory)
     return D_NONE;
 }
 
-TileManager::TileManager()
-{
-  std::string stwt_filename = datadir +  "/images/worldmap/antarctica.stwt";
-  lisp_object_t* root_obj = lisp_read_from_file(stwt_filename);
-  if (!root_obj)
-    Termination::abort("Couldn't load file", stwt_filename);
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-worldmap-tiles") == 0)
-    {
-      lisp_object_t* cur = lisp_cdr(root_obj);
-
-      while(!lisp_nil_p(cur))
-        {
-          lisp_object_t* element = lisp_car(cur);
-
-          if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
-            {
-              int id = 0;
-
-              Tile* tile = new Tile;             
-              tile->north = tile->east = tile->south = tile->west = true;
-              tile->stop  = true;
-              tile->auto_walk = false;
-
-              LispReader reader(lisp_cdr(element));
-              reader.read_int("id", id);
-
-              std::string temp;
-              reader.read_string("possible-directions", temp);
-              if(!temp.empty())
-                {
-                tile->north = tile->east = tile->south = tile->west = false;
-                if(temp.find("north") != std::string::npos)
-                  tile->north = true;
-                if(temp.find("south") != std::string::npos)
-                  tile->south = true;
-                if(temp.find("east") != std::string::npos)
-                  tile->east = true;
-                if(temp.find("west") != std::string::npos)
-                  tile->west = true;
-                }
-
-              /* For backward compatibility */
-              reader.read_bool("north", tile->north);
-              reader.read_bool("south", tile->south);
-              reader.read_bool("west",  tile->west);
-              reader.read_bool("east",  tile->east);
-
-              reader.read_bool("stop",  tile->stop);
-              reader.read_bool("auto-walk",  tile->auto_walk);
-
-              reader.read_string("one-way", temp);
-              tile->one_way = BOTH_WAYS;
-              if(!temp.empty())
-                {
-                if(temp == "north-south")
-                  tile->one_way = NORTH_SOUTH_WAY;
-                else if(temp == "south-north")
-                  tile->one_way = SOUTH_NORTH_WAY;
-                else if(temp == "east-west")
-                  tile->one_way = EAST_WEST_WAY;
-                else if(temp == "west-east")
-                  tile->one_way = WEST_EAST_WAY;
-                }
-
-              std::vector<std::string> filenames;
-              reader.read_string_vector("image", filenames);
-
-              if(filenames.size() == 0)
-                std::cerr << "Warning: no image specified for tile " << id
-                          << ".\nIgnoring...\n" << std::endl;
-
-              for(int i = 0; static_cast<unsigned int>(i) < filenames.size(); i++)
-                {
-                Surface* image = new Surface(
-                         datadir +  "/images/worldmap/" + filenames[i], true);
-                tile->images.push_back(image);
-                }
-
-              tile->anim_fps = 1;
-              reader.read_float("anim-fps", tile->anim_fps);
-
-
-              if (id >= int(tiles.size()))
-                tiles.resize(id+1);
-
-              tiles[id] = tile;
-            }
-          else
-            {
-              puts("Unhandled symbol");
-            }
-
-          cur = lisp_cdr(cur);
-        }
-    }
-  else
-    {
-      assert(0);
-    }
-
-  lisp_free(root_obj);
-}
-
-TileManager::~TileManager()
-{
-  for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i)
-    delete *i;
-}
-
-Tile*
-TileManager::get(int i)
-{
-  assert(i >=0 && i < int(tiles.size()));
-  return tiles[i];
-}
-
 //---------------------------------------------------------------------------
 
 Tux::Tux(WorldMap* worldmap_)
@@ -356,7 +241,7 @@ Tux::action(float delta)
               }
             }
 
-          if (worldmap->at(tile_pos)->stop ||
+          if (worldmap->at(tile_pos)->getData() & Tile::WORLDMAP_STOP ||
              (special_tile && !special_tile->passive_message) ||
               worldmap->at_level())
             {
@@ -367,51 +252,60 @@ Tux::action(float delta)
             }
           else
             {
-              if (worldmap->at(tile_pos)->auto_walk || direction != input_direction)
-                { // Turn to a new direction
-                  Tile* tile = worldmap->at(tile_pos);
-
-                  if(direction != input_direction && 
-                     ((tile->north && input_direction == D_NORTH) ||
-                     (tile->south && input_direction == D_SOUTH) ||
-                     (tile->east && input_direction == D_EAST) ||
-                     (tile->west && input_direction == D_WEST)))
+              const Tile* tile = worldmap->at(tile_pos);
+              if (direction != input_direction)
+                { 
+                  // Turn to a new direction
+                  const Tile* tile = worldmap->at(tile_pos);
+
+                  if((tile->getData() & Tile::WORLDMAP_NORTH 
+                      && input_direction == D_NORTH) ||
+                     (tile->getData() & Tile::WORLDMAP_SOUTH
+                      && input_direction == D_SOUTH) ||
+                     (tile->getData() & Tile::WORLDMAP_EAST
+                      && input_direction == D_EAST) ||
+                     (tile->getData() & Tile::WORLDMAP_WEST
+                      && input_direction == D_WEST))
                     {  // player has changed direction during auto-movement
-                    direction = input_direction;
-                    back_direction = reverse_dir(direction);
-                    }
-                  else if(direction != input_direction)
-                    {  // player has changed to impossible tile
+                      direction = input_direction;
                       back_direction = reverse_dir(direction);
-                      stop();
                     }
                   else
-                    {
-                    Direction dir = D_NONE;
-                  
-                    if (tile->north && back_direction != D_NORTH)
-                      dir = D_NORTH;
-                    else if (tile->south && back_direction != D_SOUTH)
-                      dir = D_SOUTH;
-                    else if (tile->east && back_direction != D_EAST)
-                      dir = D_EAST;
-                    else if (tile->west && back_direction != D_WEST)
-                      dir = D_WEST;
-
-                    if (dir != D_NONE)
-                      {
-                      direction = dir;
-                      input_direction = direction;
+                    {  // player has changed to impossible tile
                       back_direction = reverse_dir(direction);
-                      }
-                    else
-                      {
-                      // Should never be reached if tiledata is good
                       stop();
-                      return;
-                      }
                     }
+                }
+              else
+                {
+                Direction dir = D_NONE;
+              
+                if (tile->getData() & Tile::WORLDMAP_NORTH
+                    && back_direction != D_NORTH)
+                  dir = D_NORTH;
+                else if (tile->getData() & Tile::WORLDMAP_SOUTH
+                    && back_direction != D_SOUTH)
+                  dir = D_SOUTH;
+                else if (tile->getData() & Tile::WORLDMAP_EAST
+                    && back_direction != D_EAST)
+                  dir = D_EAST;
+                else if (tile->getData() & Tile::WORLDMAP_WEST
+                    && back_direction != D_WEST)
+                  dir = D_WEST;
+
+                if (dir != D_NONE)
+                  {
+                  direction = dir;
+                  input_direction = direction;
+                  back_direction = reverse_dir(direction);
                   }
+                else
+                  {
+                  // Should never be reached if tiledata is good
+                  stop();
+                  return;
+                  }
+                }
 
               // Walk automatically to the next tile
               if(direction != D_NONE)
@@ -433,43 +327,10 @@ Tux::action(float delta)
 }
 
 //---------------------------------------------------------------------------
-Tile::Tile()
-{
-}
-
-Tile::~Tile()
-{
-  for(std::vector<Surface*>::iterator i = images.begin(); i != images.end(); i++)
-    delete *i;
-}
-
-
-void
-Tile::draw(DrawingContext& context, Vector pos)
-{
-  // same code as from tile_manager.cpp draw_tile()
-
-  if(!images.size())
-    return;
-
-  if(images.size() > 1)
-    {
-    size_t frame = size_t(global_time * anim_fps) % images.size();
-
-    context.draw_surface(images[frame], pos, LAYER_TILES);
-    }
-  else if (images.size() == 1)
-    {
-    context.draw_surface(images[0], pos, LAYER_TILES);
-    }
-}
-
-//---------------------------------------------------------------------------
 
 WorldMap::WorldMap()
 {
-  tile_manager = new TileManager();
-  //tux = new Tux(this);
+  tile_manager = new TileManager("images/worldmap/antarctica.stwt");
   
   width  = 20;
   height = 15;
@@ -507,148 +368,147 @@ WorldMap::~WorldMap()
 void
 WorldMap::load_map()
 {
-  lisp_object_t* root_obj = lisp_read_from_file(datadir + "/levels/worldmap/" + map_filename);
-  if (!root_obj)
-    Termination::abort("Couldn't load file", datadir + "/levels/worldmap/" + map_filename);
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-worldmap") == 0)
-    {
-      lisp_object_t* cur = lisp_cdr(root_obj);
-
-      while(!lisp_nil_p(cur))
-        {
-          lisp_object_t* element = lisp_car(cur);
+  try {
+    lisp::Parser parser;
+    std::string filename 
+      = get_resource_filename("/levels/worldmap/" + map_filename);
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
+
+    const lisp::Lisp* lisp = root->get_lisp("supertux-worldmap");
+    if(!lisp)
+      throw new std::runtime_error("file isn't a supertux-worldmap file.");
+
+    lisp::ListIterator iter(lisp->get_cdr());
+    while(iter.next()) {
+      if(iter.item() == "tilemap") {
+        if(tilemap.size() > 0)
+          throw new std::runtime_error("multiple tilemaps specified");
+        
+        const lisp::Lisp* tilemap_lisp = iter.lisp();
+        tilemap_lisp->get("width",  width);
+        tilemap_lisp->get("height", height);
+        tilemap_lisp->get_vector("data", tilemap);
+      } else if(iter.item() == "properties") {
+        const lisp::Lisp* props = iter.lisp();
+        props->get("name", name);
+        props->get("music", music);
+        props->get("start_pos_x", start_x);
+        props->get("start_pos_y", start_y);
+      } else if(iter.item() == "special-tiles") {
+        parse_special_tiles(iter.lisp());
+      } else {
+        std::cerr << "Unknown token '" << iter.item() << "' in worldmap.\n";
+      }
+    }
 
-          if (strcmp(lisp_symbol(lisp_car(element)), "tilemap") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              reader.read_int("width",  width);
-              reader.read_int("height", height);
-              reader.read_int_vector("data", tilemap);
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              reader.read_string("name", name, true);
-              reader.read_string("music", music);
-             reader.read_int("start_pos_x", start_x);
-             reader.read_int("start_pos_y", start_y);
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "special-tiles") == 0 ||
-                   strcmp(lisp_symbol(lisp_car(element)), "levels") == 0)
-            {
-              lisp_object_t* cur = lisp_cdr(element);
-              
-              while(!lisp_nil_p(cur))
-                {
-                  lisp_object_t* element = lisp_car(cur);
+    delete tux;
+    tux = new Tux(this);
+  } catch(std::exception& e) {
+    std::stringstream msg;
+    msg << "Problem when parsing worldmap '" << map_filename << "': " <<
+      e.what();
+    throw std::runtime_error(msg.str());
+  }
+}
 
-                  if (strcmp(lisp_symbol(lisp_car(element)), "special-tile") == 0)
-                    {
-                      SpecialTile special_tile;
-                      LispReader reader(lisp_cdr(element));
-                      
-                      reader.read_float("x", special_tile.pos.x);
-                      reader.read_float("y", special_tile.pos.y);
-
-                      special_tile.map_message.erase();
-                      reader.read_string("map-message", special_tile.map_message);
-                      special_tile.passive_message = false;
-                      reader.read_bool("passive-message", special_tile.passive_message);
-
-                      special_tile.teleport_dest = Vector(-1,-1);
-                      reader.read_float("teleport-to-x", special_tile.teleport_dest.x);
-                      reader.read_float("teleport-to-y", special_tile.teleport_dest.y);
-
-                      special_tile.invisible = false;
-                      reader.read_bool("invisible-tile", special_tile.invisible);
-
-                      special_tile.apply_action_north = special_tile.apply_action_south =
-                          special_tile.apply_action_east = special_tile.apply_action_west =
-                          true;
-
-                      std::string apply_direction;
-                      reader.read_string("apply-to-direction", apply_direction);
-                      if(!apply_direction.empty())
-                        {
-                        special_tile.apply_action_north = special_tile.apply_action_south =
-                            special_tile.apply_action_east = special_tile.apply_action_west =
-                            false;
-                        if(apply_direction.find("north") != std::string::npos)
-                          special_tile.apply_action_north = true;
-                        if(apply_direction.find("south") != std::string::npos)
-                          special_tile.apply_action_south = true;
-                        if(apply_direction.find("east") != std::string::npos)
-                          special_tile.apply_action_east = true;
-                        if(apply_direction.find("west") != std::string::npos)
-                          special_tile.apply_action_west = true;
-                        }
-
-                      special_tiles.push_back(special_tile);
-                    }
+void
+WorldMap::parse_special_tiles(const lisp::Lisp* lisp)
+{
+  lisp::ListIterator iter(lisp);
+  while(iter.next()) {
+    if(iter.item() == "special-tile") {
+      SpecialTile special_tile;
+
+      const lisp::Lisp* lisp = iter.lisp();
+      lisp->get("x", special_tile.pos.x);
+      lisp->get("y", special_tile.pos.y);
+      lisp->get("map-message", special_tile.map_message);
+      special_tile.passive_message = false;
+      lisp->get("passive-message", special_tile.passive_message);
+      special_tile.teleport_dest = Vector(-1,-1);
+      lisp->get("teleport-to-x", special_tile.teleport_dest.x);
+      lisp->get("teleport-to-y", special_tile.teleport_dest.y);
+      special_tile.invisible = false;
+      lisp->get("invisible-tile", special_tile.invisible);
+
+      special_tile.apply_action_north = true;
+      special_tile.apply_action_south = true;
+      special_tile.apply_action_east = true;
+      special_tile.apply_action_west = true;
+
+      std::string apply_direction;
+      lisp->get("apply-to-direction", apply_direction);
+      if(!apply_direction.empty()) {
+        special_tile.apply_action_north = false;
+        special_tile.apply_action_south = false;
+        special_tile.apply_action_east = false;
+        special_tile.apply_action_west = false;
+        if(apply_direction.find("north") != std::string::npos)
+          special_tile.apply_action_north = true;
+        if(apply_direction.find("south") != std::string::npos)
+          special_tile.apply_action_south = true;
+        if(apply_direction.find("east") != std::string::npos)
+          special_tile.apply_action_east = true;
+        if(apply_direction.find("west") != std::string::npos)
+          special_tile.apply_action_west = true;
+      }
+      
+      special_tiles.push_back(special_tile);
+    } else if(iter.item() == "level") {
+      Level level;
 
-                  else if (strcmp(lisp_symbol(lisp_car(element)), "level") == 0)
-                    {
-                      Level level;
-                      LispReader reader(lisp_cdr(element));
-                      level.solved = false;
+      lisp::Lisp* level_lisp = iter.lisp();
+      level.solved = false;
                       
-                      level.north = true;
-                      level.east  = true;
-                      level.south = true;
-                      level.west  = true;
+      level.north = true;
+      level.east  = true;
+      level.south = true;
+      level.west  = true;
 
-                      reader.read_string("extro-filename", level.extro_filename);
-                      reader.read_string("next-worldmap", level.next_worldmap);
+      level_lisp->get("extro-filename", level.extro_filename);
+      level_lisp->get("next-worldmap", level.next_worldmap);
 
-                      level.quit_worldmap = false;
-                      reader.read_bool("quit-worldmap", level.quit_worldmap);
+      level.quit_worldmap = false;
+      level_lisp->get("quit-worldmap", level.quit_worldmap);
 
-                      reader.read_string("name", level.name, true);
-                      reader.read_float("x", level.pos.x);
-                      reader.read_float("y", level.pos.y);
+      level_lisp->get("name", level.name);
+      level_lisp->get("x", level.pos.x);
+      level_lisp->get("y", level.pos.y);
 
-                      level.auto_path = true;
-                      reader.read_bool("auto-path", level.auto_path);
+      level.auto_path = true;
+      level_lisp->get("auto-path", level.auto_path);
 
-                      level.vertical_flip = false;
-                      reader.read_bool("vertical-flip", level.vertical_flip);
+      level.vertical_flip = false;
+      level_lisp->get("vertical-flip", level.vertical_flip);
 
-                      levels.push_back(level);
-                    }
-                  
-                  cur = lisp_cdr(cur);      
-                }
-            }
-          else
-            {
-              
-            }
-          
-          cur = lisp_cdr(cur);
-        }
+      levels.push_back(level);
+    } else {
+      std::cerr << "Unknown token '" << iter.item() <<
+        "' in worldmap special-tiles list.";
     }
-
-    lisp_free(root_obj);
-
-    delete tux;
-    tux = new Tux(this);
+  }
 }
 
-void WorldMap::get_level_title(Level& level)
+void
+WorldMap::get_level_title(Level& level)
 {
   /** get special_tile's title */
   level.title = "<no title>";
 
-  LispReader* reader = LispReader::load(datadir + "/levels/" + level.name, "supertux-level");
-  if(!reader)
-    {
-    std::cerr << "Error: Could not open level file. Ignoring...\n";
-    return;
-    }
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (
+        parser.parse(get_resource_filename("levels/" + level.name)));
 
-  reader->read_string("name", level.title, true);
-  delete reader;
+    const lisp::Lisp* level_lisp = root->get_lisp("supertux-level");
+    if(!level_lisp)
+      return;
+    
+    level_lisp->get("name", level.title);
+  } catch(std::exception& e) {
+    std::cerr << "Problem when reading leveltitle: " << e.what() << "\n";
+    return;
+  }
 }
 
 void WorldMap::calculate_total_stats()
@@ -792,31 +652,25 @@ WorldMap::path_ok(Direction direction, Vector old_pos, Vector* new_pos)
     { // New position is outsite the tilemap
       return false;
     }
-  else if(at(*new_pos)->one_way != BOTH_WAYS)
-    {
-std::cerr << "one way only\n";
-      if((at(*new_pos)->one_way == NORTH_SOUTH_WAY && direction != D_SOUTH) ||
-         (at(*new_pos)->one_way == SOUTH_NORTH_WAY && direction != D_NORTH) ||
-         (at(*new_pos)->one_way == EAST_WEST_WAY && direction != D_WEST) ||
-         (at(*new_pos)->one_way == WEST_EAST_WAY && direction != D_EAST))
-        return false;
-      return true;
-    }
   else
-    { // Check if we the tile allows us to go to new_pos
+    { // Check if the tile allows us to go to new_pos
       switch(direction)
         {
         case D_WEST:
-          return (at(old_pos)->west && at(*new_pos)->east);
+          return (at(old_pos)->getData() & Tile::WORLDMAP_WEST
+              && at(*new_pos)->getData() & Tile::WORLDMAP_EAST);
 
         case D_EAST:
-          return (at(old_pos)->east && at(*new_pos)->west);
+          return (at(old_pos)->getData() & Tile::WORLDMAP_EAST
+              && at(*new_pos)->getData() & Tile::WORLDMAP_WEST);
 
         case D_NORTH:
-          return (at(old_pos)->north && at(*new_pos)->south);
+          return (at(old_pos)->getData() & Tile::WORLDMAP_NORTH
+              && at(*new_pos)->getData() & Tile::WORLDMAP_SOUTH);
 
         case D_SOUTH:
-          return (at(old_pos)->south && at(*new_pos)->north);
+          return (at(old_pos)->getData() & Tile::WORLDMAP_SOUTH
+              && at(*new_pos)->getData() & Tile::WORLDMAP_NORTH);
 
         case D_NONE:
           assert(!"path_ok() can't work if direction is NONE");
@@ -850,121 +704,127 @@ WorldMap::update(float delta)
       if (!level)
         {
         std::cout << "No level to enter at: "
-          << tux->get_tile_pos().x << ", " << tux->get_tile_pos().y << std::endl;
+          << tux->get_tile_pos().x << ", " << tux->get_tile_pos().y
+          << std::endl;
         return;
         }
 
 
-          if (level->pos == tux->get_tile_pos())
+      if (level->pos == tux->get_tile_pos())
+        {
+          PlayerStatus old_player_status = player_status;
+
+          std::cout << "Enter the current level: " << level->name << std::endl;
+          // do a shriking fade to the level
+          shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),
+                             (level->pos.y*32 + 16 + offset.y)), 500);
+          GameSession session(
+              get_resource_filename(std::string("levels/" + level->name)),
+                              ST_GL_LOAD_LEVEL_FILE, &level->statistics);
+
+          switch (session.run())
             {
-              PlayerStatus old_player_status = player_status;
+            case GameSession::ES_LEVEL_FINISHED:
+              {
+                level_finished = true;
+                bool old_level_state = level->solved;
+                level->solved = true;
+
+                // deal with statistics
+                level->statistics.merge(global_stats);
+                calculate_total_stats();
+
+                if (session.get_current_sector()->player->got_power !=
+                      session.get_current_sector()->player->NONE_POWER)
+                  player_status.bonus = PlayerStatus::FLOWER_BONUS;
+                else if (session.get_current_sector()->player->size == BIG)
+                  player_status.bonus = PlayerStatus::GROWUP_BONUS;
+                else
+                  player_status.bonus = PlayerStatus::NO_BONUS;
 
-              std::cout << "Enter the current level: " << level->name << std::endl;
-              // do a shriking fade to the level
-              shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),(level->pos.y*32 + 16
-                      + offset.y)), 500);
-              GameSession session(
-                  get_resource_filename(std::string("levels/" + level->name)),
-                                  ST_GL_LOAD_LEVEL_FILE, &level->statistics);
+                if (old_level_state != level->solved && level->auto_path)
+                  { // Try to detect the next direction to which we should walk
+                    // FIXME: Mostly a hack
+                    Direction dir = D_NONE;
+                
+                    const Tile* tile = at(tux->get_tile_pos());
 
-              switch (session.run())
-                {
-                case GameSession::ES_LEVEL_FINISHED:
-                  {
-                    level_finished = true;
-                    bool old_level_state = level->solved;
-                    level->solved = true;
-
-                    // deal with statistics
-                    level->statistics.merge(global_stats);
-                    calculate_total_stats();
-
-                    if (session.get_current_sector()->player->got_power !=
-                          session.get_current_sector()->player->NONE_POWER)
-                      player_status.bonus = PlayerStatus::FLOWER_BONUS;
-                    else if (session.get_current_sector()->player->size == BIG)
-                      player_status.bonus = PlayerStatus::GROWUP_BONUS;
-                    else
-                      player_status.bonus = PlayerStatus::NO_BONUS;
-
-                    if (old_level_state != level->solved && level->auto_path)
-                      { // Try to detect the next direction to which we should walk
-                        // FIXME: Mostly a hack
-                        Direction dir = D_NONE;
-                    
-                        Tile* tile = at(tux->get_tile_pos());
-
-                        if (tile->north && tux->back_direction != D_NORTH)
-                          dir = D_NORTH;
-                        else if (tile->south && tux->back_direction != D_SOUTH)
-                          dir = D_SOUTH;
-                        else if (tile->east && tux->back_direction != D_EAST)
-                          dir = D_EAST;
-                        else if (tile->west && tux->back_direction != D_WEST)
-                          dir = D_WEST;
-
-                        if (dir != D_NONE)
-                          {
-                            tux->set_direction(dir);
-                            //tux->update(delta);
-                          }
-
-                        std::cout << "Walk to dir: " << dir << std::endl;
+                    if (tile->getData() & Tile::WORLDMAP_NORTH
+                        && tux->back_direction != D_NORTH)
+                      dir = D_NORTH;
+                    else if (tile->getData() & Tile::WORLDMAP_SOUTH
+                        && tux->back_direction != D_SOUTH)
+                      dir = D_SOUTH;
+                    else if (tile->getData() & Tile::WORLDMAP_EAST
+                        && tux->back_direction != D_EAST)
+                      dir = D_EAST;
+                    else if (tile->getData() & Tile::WORLDMAP_WEST
+                        && tux->back_direction != D_WEST)
+                      dir = D_WEST;
+
+                    if (dir != D_NONE)
+                      {
+                        tux->set_direction(dir);
+                        //tux->update(delta);
                       }
+
+                    std::cout << "Walk to dir: " << dir << std::endl;
                   }
+              }
 
-                  break;
-                case GameSession::ES_LEVEL_ABORT:
-                  level_finished = false;
-                  /* In case the player's abort the level, keep it using the old
-                      status. But the minimum lives and no bonus. */
-                  player_status.distros = old_player_status.distros;
-                  player_status.lives = std::min(old_player_status.lives, player_status.lives);
-                  player_status.bonus = player_status.NO_BONUS;
-
-                  break;
-                case GameSession::ES_GAME_OVER:
-                  {
-                  level_finished = false;
-                  /* draw an end screen */
-                  /* TODO: in the future, this should make a dialog a la SuperMario, asking
-                  if the player wants to restart the world map with no score and from
-                  level 1 */
-                  char str[80];
+              break;
+            case GameSession::ES_LEVEL_ABORT:
+              level_finished = false;
+              /* In case the player's abort the level, keep it using the old
+                  status. But the minimum lives and no bonus. */
+              player_status.distros = old_player_status.distros;
+              player_status.lives = std::min(old_player_status.lives, player_status.lives);
+              player_status.bonus = player_status.NO_BONUS;
 
-                  DrawingContext context;
-                  context.draw_gradient(Color (200,240,220), Color(200,200,220),
-                      LAYER_BACKGROUND0);
+              break;
+            case GameSession::ES_GAME_OVER:
+              {
+              level_finished = false;
+              /* draw an end screen */
+              /* TODO: in the future, this should make a dialog a la SuperMario, asking
+              if the player wants to restart the world map with no score and from
+              level 1 */
+              char str[80];
 
-                  context.draw_text(blue_text, _("GAMEOVER"), 
-                      Vector(screen->w/2, 200), CENTER_ALLIGN, LAYER_FOREGROUND1);
+              DrawingContext context;
+              context.draw_gradient(Color (200,240,220), Color(200,200,220),
+                  LAYER_BACKGROUND0);
 
-                  sprintf(str, _("COINS: %d"), player_status.distros);
-                  context.draw_text(gold_text, str,
-                      Vector(screen->w/2, screen->w - 32), CENTER_ALLIGN, LAYER_FOREGROUND1);
+              context.draw_text(blue_text, _("GAMEOVER"), 
+                  Vector(screen->w/2, 200), CENTER_ALLIGN, LAYER_FOREGROUND1);
 
-                  total_stats.draw_message_info(context, _("Total Statistics"));
+              sprintf(str, _("COINS: %d"), player_status.distros);
+              context.draw_text(gold_text, str,
+                  Vector(screen->w/2, screen->w - 32), CENTER_ALLIGN,
+                  LAYER_FOREGROUND1);
 
-                  context.do_drawing();
-  
-                  SDL_Event event;
-                  wait_for_event(event,2000,6000,true);
+              total_stats.draw_message_info(context, _("Total Statistics"));
 
-                  quit = true;
-                  player_status.reset();
-                  break;
-                  }
-                case GameSession::ES_NONE:
-                  assert(false);
-                  // Should never be reached 
-                  break;
-                }
+              context.do_drawing();
 
-              SoundManager::get()->play_music(song);
-              Menu::set_current(0);
-              if (!savegame_file.empty())
-                savegame(savegame_file);
+              SDL_Event event;
+              wait_for_event(event,2000,6000,true);
+
+              quit = true;
+              player_status.reset();
+              break;
+              }
+            case GameSession::ES_NONE:
+              assert(false);
+              // Should never be reached 
+              break;
             }
+
+          SoundManager::get()->play_music(song);
+          Menu::set_current(0);
+          if (!savegame_file.empty())
+            savegame(savegame_file);
+        }
       /* The porpose of the next checking is that if the player lost
          the level (in case there is one), don't show anything */
       if(level_finished)
@@ -972,7 +832,8 @@ WorldMap::update(float delta)
         if (!level->extro_filename.empty())
           {
           // Display a text file
-          display_text_file(level->extro_filename, SCROLL_SPEED_MESSAGE, white_big_text , white_text, white_small_text, blue_text );
+          display_text_file(level->extro_filename, SCROLL_SPEED_MESSAGE,
+              white_big_text , white_text, white_small_text, blue_text );
           }
 
         if (!level->next_worldmap.empty())
@@ -1013,7 +874,7 @@ WorldMap::update(float delta)
     }
 }
 
-Tile*
+const Tile*
 WorldMap::at(Vector p)
 {
   assert(p.x >= 0 
@@ -1057,8 +918,9 @@ WorldMap::draw(DrawingContext& context, const Vector& offset)
   for(int y = 0; y < height; ++y)
     for(int x = 0; x < width; ++x)
       {
-        Tile* tile = at(Vector(x, y));
-        tile->draw(context, Vector(x*32 + offset.x, y*32 + offset.y));
+        const Tile* tile = at(Vector(x, y));
+        tile->draw(context, Vector(x*32 + offset.x, y*32 + offset.y),
+            LAYER_TILES);
       }
 
   for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
@@ -1227,59 +1089,59 @@ WorldMap::savegame(const std::string& filename)
 
   std::cout << "savegame: " << filename << std::endl;
 
-   std::ofstream file(filename.c_str(), std::ios::out);
-   LispWriter* writer = new LispWriter(file);
+  std::ofstream file(filename.c_str(), std::ios::out);
+  lisp::Writer writer(file);
 
   int nb_solved_levels = 0, total_levels = 0;
-  for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
-    {
-      ++total_levels;
-      if (i->solved)
-        ++nb_solved_levels;
-    }
+  for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+    ++total_levels;
+    if (i->solved)
+      ++nb_solved_levels;
+  }
   char nb_solved_levels_str[80], total_levels_str[80];
   sprintf(nb_solved_levels_str, "%d", nb_solved_levels);
   sprintf(total_levels_str, "%d", total_levels);
 
-  writer->write_comment("Worldmap save file");
+  writer.write_comment("Worldmap save file");
 
-  writer->start_list("supertux-savegame");
+  writer.start_list("supertux-savegame");
 
-  writer->write_int("version", 1);
-  writer->write_string("title", std::string(name + " - " + nb_solved_levels_str + "/" + total_levels_str));
-  writer->write_string("map", map_filename);
-  writer->write_int("lives", player_status.lives);
-  writer->write_int("distros", player_status.lives);
-  writer->write_int("max-score-multiplier", player_status.max_score_multiplier);
+  writer.write_int("version", 1);
+  writer.write_string("title",
+      std::string(name + " - " + nb_solved_levels_str+"/"+total_levels_str));
+  writer.write_string("map", map_filename);
+  writer.write_int("lives", player_status.lives);
+  writer.write_int("distros", player_status.lives);
+  writer.write_int("max-score-multiplier", player_status.max_score_multiplier);
 
-  writer->start_list("tux");
+  writer.start_list("tux");
 
-  writer->write_float("x", tux->get_tile_pos().x);
-  writer->write_float("y", tux->get_tile_pos().y);
-  writer->write_string("back", direction_to_string(tux->back_direction));
-  writer->write_string("bonus", bonus_to_string(player_status.bonus));
+  writer.write_float("x", tux->get_tile_pos().x);
+  writer.write_float("y", tux->get_tile_pos().y);
+  writer.write_string("back", direction_to_string(tux->back_direction));
+  writer.write_string("bonus", bonus_to_string(player_status.bonus));
 
-  writer->end_list("tux");
+  writer.end_list("tux");
 
-  writer->start_list("levels");
+  writer.start_list("levels");
 
   for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
     {
       if (i->solved)
         {
-        writer->start_list("level");
+        writer.start_list("level");
 
-        writer->write_string("name", i->name);
-        writer->write_bool("solved", true);
-        i->statistics.write(*writer);
+        writer.write_string("name", i->name);
+        writer.write_bool("solved", true);
+        i->statistics.write(writer);
 
-        writer->end_list("level");
+        writer.end_list("level");
         }
     }  
 
-  writer->end_list("levels");
+  writer.end_list("levels");
 
-  writer->end_list("supertux-savegame");
+  writer.end_list("supertux-savegame");
 }
 
 void
@@ -1288,98 +1150,75 @@ WorldMap::loadgame(const std::string& filename)
   std::cout << "loadgame: " << filename << std::endl;
   savegame_file = filename;
 
-  if (access(filename.c_str(), F_OK) != 0)
-    {
-    load_map();
-
-    player_status.reset();
-
-    return;
-    }
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
   
-  lisp_object_t* savegame = lisp_read_from_file(filename);
-  if (!savegame)
-    {
-      std::cout << "WorldMap:loadgame: File not found: " << filename << std::endl;
-      load_map();
-      return;
-    }
-
-  lisp_object_t* cur = savegame;
+    const lisp::Lisp* savegame = root->get_lisp("supertux-savegame");
+    if(!savegame)
+      throw std::runtime_error("File is not a supertux-savegame file.");
 
-  if (strcmp(lisp_symbol(lisp_car(cur)), "supertux-savegame") != 0)
-    {
-    load_map();
-    return;
-    }
-
-  cur = lisp_cdr(cur);
-  LispReader reader(cur);
-
-  /* Get the Map filename and then load it before setting level settings */
-  std::string cur_map_filename = map_filename;
-  reader.read_string("map", map_filename);
-//  if(cur_map_filename != map_filename)
+    /* Get the Map filename and then load it before setting level settings */
+    std::string cur_map_filename = map_filename;
+    savegame->get("map", map_filename);
     load_map(); 
 
-  reader.read_int("lives", player_status.lives);
-  reader.read_int("distros", player_status.distros);
-  reader.read_int("max-score-multiplier", player_status.max_score_multiplier);
+    savegame->get("lives", player_status.lives);
+    savegame->get("distros", player_status.distros);
+    savegame->get("max-score-multiplier", player_status.max_score_multiplier);
+    if (player_status.lives < 0)
+      player_status.lives = START_LIVES;
 
-  if (player_status.lives < 0)
-    player_status.lives = START_LIVES;
-
-  lisp_object_t* tux_cur = 0;
-  if (reader.read_lisp("tux", tux_cur))
+    const lisp::Lisp* tux_lisp = savegame->get_lisp("tux");
+    if(tux)
     {
       Vector p;
       std::string back_str = "none";
       std::string bonus_str = "none";
 
-      LispReader tux_reader(tux_cur);
-      tux_reader.read_float("x", p.x);
-      tux_reader.read_float("y", p.y);
-      tux_reader.read_string("back", back_str);
-      tux_reader.read_string("bonus", bonus_str);
+      tux_lisp->get("x", p.x);
+      tux_lisp->get("y", p.y);
+      tux_lisp->get("back", back_str);
+      tux_lisp->get("bonus", bonus_str);
       
       player_status.bonus = string_to_bonus(bonus_str);
       tux->back_direction = string_to_direction(back_str);      
       tux->set_tile_pos(p);
     }
 
-  lisp_object_t* level_cur = 0;
-  if (reader.read_lisp("levels", level_cur))
-    {
-      while(level_cur)
-        {
-          lisp_object_t* sym  = lisp_car(lisp_car(level_cur));
-          lisp_object_t* data = lisp_cdr(lisp_car(level_cur));
-
-          if (strcmp(lisp_symbol(sym), "level") == 0)
-            {
-              std::string name;
-              bool solved = false;
+    const lisp::Lisp* levels_lisp = savegame->get_lisp("levels");
+    if(levels_lisp) {
+      lisp::ListIterator iter(levels_lisp);
+      while(iter.next()) {
+        if(iter.item() == "level") {
+          std::string name;
+          bool solved = false;
 
-              LispReader level_reader(data);
-              level_reader.read_string("name", name);
-              level_reader.read_bool("solved", solved);
+          const lisp::Lisp* level = iter.lisp();
+          level->get("name", name);
+          level->get("solved", solved);
 
-              for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
-                {
-                  if (name == i->name)
-                    {
-                    i->solved = solved;
-                    i->statistics.parse(level_reader);
-                    break;
-                    }
-                }
+          for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
+          {
+            if (name == i->name)
+            {
+              i->solved = solved;
+              i->statistics.parse(*level);
+              break;
             }
-
-          level_cur = lisp_cdr(level_cur);
+          }
+        } else {
+          std::cerr << "Unknown token '" << iter.item() 
+            << "' in levels block in worldmap.\n";
         }
+      }
     }
-  lisp_free(savegame);
+  } catch(std::exception& e) {
+    std::cerr << "Problem loading game '" << filename << "': " << e.what() 
+      << "\n";
+    load_map();
+    player_status.reset();
+  }
 
   calculate_total_stats();
 }
index 4bf2b69..80585ea 100644 (file)
 #include "math/vector.h"
 #include "audio/musicref.h"
 #include "video/screen.h"
+#include "lisp/lisp.h"
 #include "statistics.h"
 #include "timer.h"
+#include "tile_manager.h"
 
 namespace SuperTux {
   class Menu;
@@ -39,7 +41,7 @@ namespace WorldMapNS {
 enum WorldMapMenuIDs {
   MNID_RETURNWORLDMAP,
   MNID_QUITWORLDMAP
-  };
+};
 
 // For one way tiles
 enum {
@@ -48,47 +50,6 @@ enum {
   SOUTH_NORTH_WAY,
   EAST_WEST_WAY,
   WEST_EAST_WAY
-  };
-
-class Tile
-{
-public:
-  Tile();
-  ~Tile();
-
-  void draw(DrawingContext& context, Vector pos);
-
-  std::vector<Surface*> images;
-  float anim_fps;
-
-  // Directions in which Tux is allowed to walk from this tile
-  bool north;
-  bool east;
-  bool south;
-  bool west;
-
-  /** One way tile */
-  int one_way;
-
-  /** Stop on this tile or walk over it? */
-  bool stop;
-
-  /** When set automatically turn directions when walked over such a
-      tile (ie. walk smoothly a curve) */
-  bool auto_walk;
-};
-
-class TileManager
-{
-private:
-  typedef std::vector<Tile*> Tiles;
-  Tiles tiles;
-
-public:
-  TileManager();
-  ~TileManager();
-
-  Tile* get(int i);
 };
 
 enum Direction { D_NONE, D_WEST, D_EAST, D_NORTH, D_SOUTH };
@@ -265,7 +226,7 @@ public:
   void draw(DrawingContext& context, const Vector& offset);
 
   Vector get_next_tile(Vector pos, Direction direction);
-  Tile* at(Vector pos);
+  const Tile* at(Vector pos);
 
   WorldMap::Level* at_level();
   WorldMap::SpecialTile* at_special_tile();
@@ -296,6 +257,7 @@ public:
 
 private:
   void on_escape_press();
+  void parse_special_tiles(const lisp::Lisp* lisp);
 };
 
 } // namespace WorldMapNS