[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,
;; (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 ;;
(gravity 10.000000)
(background (image "arctis.jpg")
(speed 0.5))
- (spawn-points
+ (spawnpoint
(name "main")
(x 100)
(y 170)
(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)
(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")
(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
(camera
(mode "normal")
)
- (spawn-points
+ (spawnpoint
(name "main")
(x 100)
(y 170)
(sector "main")
(spawnpoint "main")
)
- (spawn-points
+ (spawnpoint
(name "main")
(x 300)
(y 170)
(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)
[ Wildcard special : *.cpp *.h ]
[ Wildcard utils : *.cpp *.h ]
[ Wildcard video : *.cpp *.h ]
+ [ Wildcard lisp : *.cpp *.h ]
;
TRANSLATABLE_SOURCE += [ DoSourceGrist $(sources) ] ;
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)
{
}
if(audio_device)
Mix_HaltMusic();
-sounds.clear();
-destroy_instance();
+ sounds.clear();
}
void
if(m_music_enabled == false) {
Mix_HaltMusic();
} else {
- Mix_PlayMusic(current_music->music, -1);
+ if(current_music)
+ Mix_PlayMusic(current_music->music, -1);
}
}
--- /dev/null
+// $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
+
--- /dev/null
+// $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
+
--- /dev/null
+// $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
--- /dev/null
+// $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
+
--- /dev/null
+#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;
+}
+
+}
--- /dev/null
+#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
+
--- /dev/null
+// $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
--- /dev/null
+// $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
+
--- /dev/null
+// $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
--- /dev/null
+// $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
+
#include <cassert>
#include <map>
-#include "utils/lispreader.h"
#include "video/surface.h"
#include "math/vector.h"
#include "sprite_data.h"
#include "app/globals.h"
#include "app/setup.h"
#include "video/drawing_context.h"
+#include "lisp/list_iterator.h"
namespace SuperTux
{
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())
}
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) {
(*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) {
}
} 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 << "'.";
#include <vector>
#include <map>
-#include "utils/lispreader.h"
+#include "lisp/lisp.h"
#include "video/surface.h"
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
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);
#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
{
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*
#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;
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 ()
}
}
-/* EOF */
#ifndef SUPERTUX_CONFIGFILE_H
#define SUPERTUX_CONFIGFILE_H
-#include "lispreader.h"
+#include "lisp/lisp.h"
namespace SuperTux {
public:
void load ();
void save ();
- virtual void customload(LispReader& )
+ virtual void customload(const lisp::Lisp* )
{};
virtual void customsave(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;
#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();
#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"
}
void
-Bomb::write(LispWriter& )
+Bomb::write(lisp::Writer& )
{
// bombs are only temporarily so don't write them out...
}
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);
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;
}
void
-BouncingSnowball::write(LispWriter& writer)
+BouncingSnowball::write(lisp::Writer& writer)
{
writer.start_list("bouncingsnowball");
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:
#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");
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);
#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);
}
void
-Flame::write(LispWriter& writer)
+Flame::write(lisp::Writer& writer)
{
writer.start_list("flame");
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();
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");
#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
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;
}
void
-MrBomb::write(LispWriter& writer)
+MrBomb::write(lisp::Writer& writer)
{
writer.start_list("mrbomb");
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:
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;
}
void
-MrIceBlock::write(LispWriter& writer)
+MrIceBlock::write(lisp::Writer& writer)
{
writer.start_list("mriceblock");
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);
//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");
}
}
void
-Nolok_01::write(LispWriter& writer)
+Nolok_01::write(lisp::Writer& writer)
{
writer.start_list("nolok01");
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);
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;
}
void
-SnowBall::write(LispWriter& writer)
+SnowBall::write(lisp::Writer& writer)
{
writer.start_list("snowball");
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:
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);
}
}
void
-Spike::write(LispWriter& writer)
+Spike::write(lisp::Writer& writer)
{
writer.start_list("spike");
writer.write_float("x", start_position.x);
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);
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");
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);
};
// 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 <cerrno>
#include <unistd.h>
#include <ctime>
+#include <stdexcept>
#include "SDL.h"
#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"
#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"
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()
+++ /dev/null
-// $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);
- }
-}
+++ /dev/null
-// $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
// 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"
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);
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");
class Sector;
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
}
class Level
int get_total_coins();
private:
- void load_old_format(LispReader& reader);
+ void load_old_format(const lisp::Lisp& reader);
};
#endif /*SUPERTUX_LEVEL_H*/
#include "app/globals.h"
#include "video/surface.h"
#include "level_subset.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
using namespace SuperTux;
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)
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
#include <vector>
#include <string>
-#include "utils/lispreader.h"
using namespace SuperTux;
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;
}
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);
#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);
class MyConfig : public Config
{
public:
- void customload(LispReader& reader);
+ void customload(const lisp::Lisp& reader);
void customsave(FILE * config);
};
#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));
}
}
void
-Background::write(LispWriter& writer)
+Background::write(lisp::Writer& writer)
{
if(type == INVALID)
return;
#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);
#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"
}
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;
}
void
-Camera::write(LispWriter& writer)
+Camera::write(lisp::Writer& writer)
{
writer.start_list("camera");
#include "serializable.h"
using namespace SuperTux;
-
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
}
class Sector;
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);
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)
// 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
#include "special/game_object.h"
#include "special/moving_object.h"
#include "serializable.h"
-#include "utils/lispwriter.h"
/* Bounciness of distros: */
#define NO_BOUNCE 0
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
#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()
{
}
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);
}
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);
using namespace SuperTux;
-namespace SuperTux {
-class LispReader;
+namespace lisp {
+class Lisp;
}
class DisplayManager;
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);
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);
#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;
class Platform : public SuperTux::MovingObject
{
public:
- Platform(LispReader& reader);
+ Platform(const lisp::Lisp& reader);
~Platform();
virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
#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")
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";
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_);
}
void
-TileMap::write(LispWriter& writer)
+TileMap::write(lisp::Writer& writer)
{
writer.start_list("tilemap");
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;
#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;
{
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);
#include "gui/button.h"
#include "scene.h"
#include "resources.h"
+#include "tile_manager.h"
#include "object/gameobjs.h"
#include "object/player.h"
MusicRef level_end_song;
SpriteManager* sprite_manager = 0;
+TileManager* tile_manager = 0;
char * soundfilenames[NUM_SOUNDS] = {
"/sounds/jump.wav",
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");
delete sprite_manager;
sprite_manager = 0;
+ delete tile_manager;
+ tile_manager = 0;
}
std::string get_resource_filename(const std::string& resource)
class Surface;
}
+class TileManager;
+
/* Sound files: */
enum {
SND_JUMP,
extern MusicRef level_end_song;
extern SpriteManager* sprite_manager;
+extern TileManager* tile_manager;
extern Menu* contrib_menu;
extern Menu* contrib_subset_menu;
#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"
}
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);
}
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(§or);
+ 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);
}
}
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;
}
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;
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";
}
}
}
}
void
-Sector::write(LispWriter& writer)
+Sector::write(lisp::Writer& writer)
{
writer.write_string("name", name);
writer.write_float("gravity", gravity);
namespace SuperTux {
class GameObject;
-class LispReader;
-class LispWriter;
class Sprite;
class Rectangle;
}
+namespace lisp {
+class Lisp;
+class Writer;
+}
class InteractiveObject;
class Background;
~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");
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;
// 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*/
#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"
}
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
#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;
}
~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
unloadshared();
Setup::general_free();
st_menu_free();
- TileManager::destroy_instance();
#ifdef DEBUG
Surface::debug_check();
#endif
#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"
}
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 !=
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 {
#include <vector>
#include "video/surface.h"
-#include "utils/lispreader.h"
#include "math/rectangle.h"
+#include "lisp/lisp.h"
using namespace SuperTux;
*/
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:
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
// 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);
}
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);
}
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
{
}
if(tile->images.size() == 0 && tile->imagespecs.size() != 0)
- tile->load_images();
+ tile->load_images(tiles_path);
return tile;
}
#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"
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);
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;
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);
#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");
}
}
void
-Door::write(LispWriter& writer)
+Door::write(lisp::Writer& writer)
{
writer.start_list("door");
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);
#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;
}
}
void
-SecretAreaTrigger::write(LispWriter& writer)
+SecretAreaTrigger::write(lisp::Writer& writer)
{
writer.start_list("secretarea");
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);
#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)
}
void
-SequenceTrigger::write(LispWriter& writer)
+SequenceTrigger::write(lisp::Writer& writer)
{
writer.start_list("sequencetrigger");
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:
// 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"
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_)
}
}
- if (worldmap->at(tile_pos)->stop ||
+ if (worldmap->at(tile_pos)->getData() & Tile::WORLDMAP_STOP ||
(special_tile && !special_tile->passive_message) ||
worldmap->at_level())
{
}
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)
}
//---------------------------------------------------------------------------
-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;
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()
{ // 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");
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)
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())
}
}
-Tile*
+const Tile*
WorldMap::at(Vector p)
{
assert(p.x >= 0
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)
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
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();
}
#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;
enum WorldMapMenuIDs {
MNID_RETURNWORLDMAP,
MNID_QUITWORLDMAP
- };
+};
// For one way tiles
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 };
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();
private:
void on_escape_press();
+ void parse_special_tiles(const lisp::Lisp* lisp);
};
} // namespace WorldMapNS