From 4a308ce51f1300ad7c9c041272521f6df71036de Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Sun, 15 Apr 2007 22:06:08 +0000 Subject: [PATCH] Statistics are now saved to disk SVN-Revision: 4983 --- src/scripting/squirrel_util.cpp | 164 ++++++++++++++++++++++++++++++++++++++++ src/scripting/squirrel_util.hpp | 22 ++++++ src/statistics.cpp | 47 ++++++++++++ src/statistics.hpp | 16 +++- src/worldmap/worldmap.cpp | 109 +++----------------------- 5 files changed, 258 insertions(+), 100 deletions(-) diff --git a/src/scripting/squirrel_util.cpp b/src/scripting/squirrel_util.cpp index f16bb63bb..d3fde6db3 100644 --- a/src/scripting/squirrel_util.cpp +++ b/src/scripting/squirrel_util.cpp @@ -389,4 +389,168 @@ HSQUIRRELVM object_to_vm(HSQOBJECT object) return object._unVal.pThread; } +// begin: serialization functions + +void store_float(HSQUIRRELVM vm, const char* name, float val) +{ + sq_pushstring(vm, name, -1); + sq_pushfloat(vm, val); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +void store_int(HSQUIRRELVM vm, const char* name, int val) +{ + sq_pushstring(vm, name, -1); + sq_pushinteger(vm, val); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add int value to table"); +} + +void store_string(HSQUIRRELVM vm, const char* name, const std::string& val) +{ + sq_pushstring(vm, name, -1); + sq_pushstring(vm, val.c_str(), val.length()); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +void store_bool(HSQUIRRELVM vm, const char* name, bool val) +{ + sq_pushstring(vm, name, -1); + sq_pushbool(vm, val ? SQTrue : SQFalse); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +bool has_float(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if (SQ_FAILED(sq_get(vm, -2))) return false; + sq_pop(vm, 1); + return true; +} + +bool has_int(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +bool has_string(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +bool has_bool(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +float read_float(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get float value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + float result; + if(SQ_FAILED(sq_getfloat(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get float value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result; +} + +int read_int(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get int value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + int result; + if(SQ_FAILED(sq_getinteger(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get int value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result; +} + + +std::string read_string(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get string value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + const char* result; + if(SQ_FAILED(sq_getstring(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get string value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return std::string(result); +} + +bool read_bool(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get bool value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + SQBool result; + if(SQ_FAILED(sq_getbool(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get bool value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result == SQTrue; +} + +bool get_float(HSQUIRRELVM vm, const char* name, float& val) { + if (!has_float(vm, name)) return false; + val = read_float(vm, name); + return true; +} + +bool get_int(HSQUIRRELVM vm, const char* name, int& val) { + if (!has_int(vm, name)) return false; + val = read_int(vm, name); + return true; +} + +bool get_string(HSQUIRRELVM vm, const char* name, std::string& val) { + if (!has_string(vm, name)) return false; + val = read_string(vm, name); + return true; +} + +bool get_bool(HSQUIRRELVM vm, const char* name, bool& val) { + if (!has_bool(vm, name)) return false; + val = read_bool(vm, name); + return true; +} + +// end: serialization functions + } diff --git a/src/scripting/squirrel_util.hpp b/src/scripting/squirrel_util.hpp index 5ebb44aad..da61b2674 100644 --- a/src/scripting/squirrel_util.hpp +++ b/src/scripting/squirrel_util.hpp @@ -80,6 +80,28 @@ namespace Scripting } } + // begin serialization functions + void store_float(HSQUIRRELVM vm, const char* name, float val); + void store_int(HSQUIRRELVM vm, const char* name, int val); + void store_string(HSQUIRRELVM vm, const char* name, const std::string& val); + void store_bool(HSQUIRRELVM vm, const char* name, bool val); + + bool has_float(HSQUIRRELVM vm, const char* name); + bool has_int(HSQUIRRELVM vm, const char* name); + bool has_string(HSQUIRRELVM vm, const char* name); + bool has_bool(HSQUIRRELVM vm, const char* name); + + bool get_float(HSQUIRRELVM vm, const char* name, float& val); + bool get_int(HSQUIRRELVM vm, const char* name, int& val); + bool get_string(HSQUIRRELVM vm, const char* name, std::string& val); + bool get_bool(HSQUIRRELVM vm, const char* name, bool& val); + + float read_float(HSQUIRRELVM vm, const char* name); + int read_int(HSQUIRRELVM vm, const char* name); + std::string read_string(HSQUIRRELVM vm, const char* name); + bool read_bool(HSQUIRRELVM vm, const char* name); + // end serialization functions + } #endif diff --git a/src/statistics.cpp b/src/statistics.cpp index 0b9aa0369..5eb0cefd0 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -32,6 +32,7 @@ #include "main.hpp" #include "statistics.hpp" #include "log.hpp" +#include "scripting/squirrel_util.hpp" namespace { const int nv_coins = std::numeric_limits::min(); @@ -57,6 +58,7 @@ Statistics::~Statistics() { } +/* void Statistics::parse(const lisp::Lisp& reader) { @@ -80,6 +82,42 @@ Statistics::write(lisp::Writer& writer) writer.write_int("secrets-found", secrets); writer.write_int("secrets-found-total", total_secrets); } +*/ + +void +Statistics::serialize_to_squirrel(HSQUIRRELVM vm) +{ + // TODO: there's some bug in the unserialization routines that breaks stuff when an empty statistics table is written, so -- as a workaround -- let's make sure we will actually write something first + if (!((coins != nv_coins) || (total_coins != nv_coins) || (badguys != nv_badguys) || (total_badguys != nv_badguys) || (time != nv_time) || (secrets != nv_secrets) || (total_secrets != nv_secrets))) return; + + sq_pushstring(vm, "statistics", -1); + sq_newtable(vm); + if (coins != nv_coins) Scripting::store_int(vm, "coins-collected", coins); + if (total_coins != nv_coins) Scripting::store_int(vm, "coins-collected-total", total_coins); + if (badguys != nv_badguys) Scripting::store_int(vm, "badguys-killed", badguys); + if (total_badguys != nv_badguys) Scripting::store_int(vm, "badguys-killed-total", total_badguys); + if (time != nv_time) Scripting::store_float(vm, "time-needed", time); + if (secrets != nv_secrets) Scripting::store_int(vm, "secrets-found", secrets); + if (total_secrets != nv_secrets) Scripting::store_int(vm, "secrets-found-total", total_secrets); + sq_createslot(vm, -3); +} + +void +Statistics::unserialize_from_squirrel(HSQUIRRELVM vm) +{ + sq_pushstring(vm, "statistics", -1); + if(SQ_FAILED(sq_get(vm, -2))) { + return; + } + Scripting::get_int(vm, "coins-collected", coins); + Scripting::get_int(vm, "coins-collected-total", total_coins); + Scripting::get_int(vm, "badguys-killed", badguys); + Scripting::get_int(vm, "badguys-killed-total", total_badguys); + Scripting::get_float(vm, "time-needed", time); + Scripting::get_int(vm, "secrets-found", secrets); + Scripting::get_int(vm, "secrets-found-total", total_secrets); + sq_pop(vm, 1); +} //define TOTAL_DISPLAY_TIME 3400 //define FADING_TIME 600 @@ -267,6 +305,15 @@ Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, S } void +Statistics::zero() +{ + reset(); + total_coins = 0; + total_badguys = 0; + total_secrets = 0; +} + +void Statistics::reset() { coins = 0; diff --git a/src/statistics.hpp b/src/statistics.hpp index d282e0e23..4aca2ad96 100644 --- a/src/statistics.hpp +++ b/src/statistics.hpp @@ -22,6 +22,7 @@ #ifndef SUPERTUX_STATISTICS_H #define SUPERTUX_STATISTICS_H +#include #include "timer.hpp" namespace lisp { class Writer; } @@ -48,14 +49,25 @@ public: ~Statistics(); /// read statistics from lisp file - void parse(const lisp::Lisp& lisp); + //void parse(const lisp::Lisp& lisp); /// write statistics to lisp file - void write(lisp::Writer& writer); + //void write(lisp::Writer& writer); + + /** + * serialize statistics object as squirrel table "statistics" + */ + void serialize_to_squirrel(HSQUIRRELVM vm); + + /** + * unserialize statistics object from squirrel table "statistics" + */ + void unserialize_from_squirrel(HSQUIRRELVM vm); void draw_worldmap_info(DrawingContext& context); /**< draw worldmap stat HUD */ void draw_message_info(DrawingContext& context, std::string title); /**< draw stats at level start */ void draw_endseq_panel(DrawingContext& context, Statistics* best_stats, Surface* backdrop); /**< draw panel shown during level's end sequence */ + void zero(); /**< Set stats to zero */ void reset(); /**< Set stats (but not totals) to zero */ void merge(Statistics& stats); /**< Given another Statistics object finds the best of each one */ void operator+=(const Statistics& o); /**< Add two Statistics objects */ diff --git a/src/worldmap/worldmap.cpp b/src/worldmap/worldmap.cpp index 0477ed8a6..8cc033ffa 100644 --- a/src/worldmap/worldmap.cpp +++ b/src/worldmap/worldmap.cpp @@ -371,7 +371,7 @@ WorldMap::get_level_title(LevelTile& level) void WorldMap::calculate_total_stats() { - total_stats.reset(); + total_stats.zero(); for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) { LevelTile* level = *i; if (level->solved) { @@ -885,100 +885,6 @@ WorldMap::leave() sq_pop(global_vm, 1); } -static void store_float(HSQUIRRELVM vm, const char* name, float val) -{ - sq_pushstring(vm, name, -1); - sq_pushfloat(vm, val); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); -} - -/* -static void store_int(HSQUIRRELVM vm, const char* name, int val) -{ - sq_pushstring(vm, name, -1); - sq_pushinteger(vm, val); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); -} -*/ - -static void store_string(HSQUIRRELVM vm, const char* name, const std::string& val) -{ - sq_pushstring(vm, name, -1); - sq_pushstring(vm, val.c_str(), val.length()); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); -} - -static void store_bool(HSQUIRRELVM vm, const char* name, bool val) -{ - sq_pushstring(vm, name, -1); - sq_pushbool(vm, val ? SQTrue : SQFalse); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); -} - -static float read_float(HSQUIRRELVM vm, const char* name) -{ - sq_pushstring(vm, name, -1); - if(SQ_FAILED(sq_get(vm, -2))) { - std::ostringstream msg; - msg << "Couldn't get float value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - - float result; - if(SQ_FAILED(sq_getfloat(vm, -1, &result))) { - std::ostringstream msg; - msg << "Couldn't get float value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - sq_pop(vm, 1); - - return result; -} - -static std::string read_string(HSQUIRRELVM vm, const char* name) -{ - sq_pushstring(vm, name, -1); - if(SQ_FAILED(sq_get(vm, -2))) { - std::ostringstream msg; - msg << "Couldn't get string value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - - const char* result; - if(SQ_FAILED(sq_getstring(vm, -1, &result))) { - std::ostringstream msg; - msg << "Couldn't get string value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - sq_pop(vm, 1); - - return std::string(result); -} - -static bool read_bool(HSQUIRRELVM vm, const char* name) -{ - sq_pushstring(vm, name, -1); - if(SQ_FAILED(sq_get(vm, -2))) { - std::ostringstream msg; - msg << "Couldn't get bool value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - - SQBool result; - if(SQ_FAILED(sq_getbool(vm, -1, &result))) { - std::ostringstream msg; - msg << "Couldn't get bool value for '" << name << "' from table"; - throw Scripting::SquirrelError(vm, msg.str()); - } - sq_pop(vm, 1); - - return result == SQTrue; -} - void WorldMap::save_state() { @@ -1036,14 +942,16 @@ WorldMap::save_state() sq_newtable(vm); store_bool(vm, "solved", level->solved); - // TODO write statistics - // i->statistics.write(writer); + level->statistics.serialize_to_squirrel(vm); sq_createslot(vm, -3); } sq_createslot(vm, -3); + // overall statistics... + total_stats.serialize_to_squirrel(vm); + // push world into worlds table sq_createslot(vm, -3); } catch(std::exception& ) { @@ -1106,12 +1014,17 @@ WorldMap::load_state() if(SQ_SUCCEEDED(sq_get(vm, -2))) { level->solved = read_bool(vm, "solved"); level->sprite->set_action(level->solved ? "solved" : "default"); - // i->statistics.parse(*level); + level->statistics.unserialize_from_squirrel(vm); sq_pop(vm, 1); } } + + // leave state table sq_pop(vm, 1); + // load overall statistics + total_stats.unserialize_from_squirrel(vm); + } catch(std::exception& e) { log_debug << "Not loading worldmap state: " << e.what() << std::endl; } -- 2.11.0