adonthell-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Adonthell-commits] adonthell/src/rpg schedule.cc schedule.h


From: Kai Sterker
Subject: [Adonthell-commits] adonthell/src/rpg schedule.cc schedule.h
Date: Sun, 18 Jun 2006 19:26:48 +0000

CVSROOT:        /cvsroot/adonthell
Module name:    adonthell
Changes by:     Kai Sterker <ksterker>  06/06/18 19:26:48

Added files:
        src/rpg        : schedule.cc schedule.h 

Log message:
        ADDED schedule stuff (untested)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/adonthell/src/rpg/schedule.cc?cvsroot=adonthell&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/adonthell/src/rpg/schedule.h?cvsroot=adonthell&rev=1.1

Patches:
Index: schedule.cc
===================================================================
RCS file: schedule.cc
diff -N schedule.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ schedule.cc 18 Jun 2006 19:26:48 -0000      1.1
@@ -0,0 +1,229 @@
+/*
+ $Id: schedule.cc,v 1.1 2006/06/18 19:26:48 ksterker Exp $
+ 
+ Copyright (C) 2004/2005/2006 Kai Sterker <address@hidden>
+ Part of the Adonthell Project http://adonthell.linuxgames.com
+ 
+ Adonthell 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.
+ 
+ Adonthell 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 Adonthell; if not, write to the Free Software 
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/**
+ * @file rpg/schedule.cc
+ *
+ * @author Kai Sterker
+ * @brief Implements the character schedule class.
+ */
+ 
+#include "rpg/schedule.h"
+#include "event/date.h"
+#include "event/time_event.h"
+
+using rpg::schedule;
+
+// standart constructor
+schedule::schedule ()
+{
+    Active = false;
+    Running = false;
+    QueuedSchedule = NULL;
+}
+
+// destructor
+schedule::~schedule ()
+{
+    delete QueuedSchedule;
+}
+
+// execute the schedule
+void schedule::update ()
+{
+    // no schedule active
+    if (!Active) return;
+    
+    // no schedule running --> assign a new one
+    if (!Running) 
+    {
+        // if schedule queued, try to activate it 
+        if (QueuedSchedule)
+        {
+            QueuedSchedule->activate (this);
+            delete QueuedSchedule;
+            QueuedSchedule = NULL;            
+        }
+
+        // no queued schedule or initialization failed
+        if (!Running)
+        {
+            // clearing the schedule before the manager runs
+            // allows the manager to access the most recent data
+            Schedule.clear ();
+            Manager.call_method ("run");
+        }
+    }
+        
+    // finally run schedule
+    Schedule.call_method ("run");
+}
+
+// assign a (new) schedule
+bool schedule::set_schedule (const string & file, PyObject *args)
+{
+    if (Running)
+    {
+        fprintf (stderr, "*** schedule::set_schedule: stop current schedule 
first!\n");
+        return false;
+    }
+    
+    // no need to clear anything, as py_object takes care of that
+    if (Schedule.create_instance (SCHEDULE_DIR + file, file, args))
+    {    
+        // 'run' schedule
+        Running = true;
+    
+        // cancel alarm
+        Factory.clear ();
+    
+        return true;
+    }
+    
+    return false;
+}
+
+// queue a schedule
+void schedule::queue_schedule (const string & file, PyObject *args)
+{
+    if (QueuedSchedule) delete QueuedSchedule;
+
+    QueuedSchedule = new schedule_data (file, args);
+}
+
+// assign a (new) manager script
+bool schedule::set_manager (const string & file, PyObject *args)
+{
+    return Manager.create_instance (SCHEDULE_DIR + file, file, args);
+}
+
+// set the alarm
+void schedule::set_alarm (const string & time, const bool & absolute)
+{
+    string tm (time);
+    
+    // get rid of the current alarm
+    Factory.clear ();
+    
+    // absolute hour of the day
+    if (absolute)
+    {
+        char day[16];
+
+        // if that hour has already passed today, assume the
+        // same hour tomorrow
+        if (events::date::parse_time (time) > (u_int32) events::date::hour () 
* 60)
+            sprintf (day, "%id", events::date::day ());
+        else
+            sprintf (day, "%id", events::date::day () + 1);
+
+        tm += day;
+    }
+
+    // create and register the new alarm
+    events::time_event *ev = new events::time_event (tm, absolute);
+    events::listener *li = Factory.add (ev, events::LISTENER_CXX);
+    li->connect_callback (base::make_functor (*this, &schedule::on_alarm));
+    li->set_id ("alarm");
+}
+
+// set alarm for a queued schedule
+void schedule::queue_alarm (const string & time, const bool & absolute)
+{
+    if (!QueuedSchedule)
+    {
+        fprintf (stderr, "*** schedule::queue_alarm: queue a schedule 
first!\n");
+        return;
+    }
+    
+    QueuedSchedule->set_alarm (time, absolute);
+}
+
+// save state to disk
+void schedule::put_state (base::flat & out) const
+{
+    out.put_bool ("sca", Active);
+    out.put_bool ("scr", Running);
+    
+    // current manager script
+    Manager.put_state (out);
+    
+    // current schedule script
+    Schedule.put_state (out);
+    
+    // save alarm, if any
+    Factory.put_state (out);
+    
+    // save queue, if any
+    if (!QueuedSchedule)
+    {
+        out.put_bool ("scq", false);
+    }
+    else
+    {
+        out.put_bool ("scq", true);
+        QueuedSchedule->put_state (out);
+    }
+}
+
+// load state from disk
+bool schedule::get_state (base::flat & in)
+{
+    Active = in.get_bool ("sca");
+    Running = in.get_bool ("scr");
+    
+    // restore manager script
+    if (!Manager.get_state (in))
+    {
+        fprintf (stderr, "*** schedule::get_state: failed loading manager 
script\n");
+        return false;
+    }
+    
+    // restore schedule script
+    if (!Schedule.get_state (in))
+    {
+        fprintf (stderr, "*** schedule::get_state: failed loading schedule 
script\n");
+        return false;
+    }
+    
+    // restore alarm
+    if (!Factory.get_state (in))
+    {
+        fprintf (stderr, "*** schedule::get_state: failed loading alarm\n");
+        return false;
+    }
+    
+    // restore listener callback (which cannot be saved)
+    events::listener *li = Factory.get_listener ("alarm");
+    if (li != NULL)
+    {
+        li->connect_callback (base::make_functor (*this, &schedule::on_alarm));
+    }
+    
+    // restore queue
+    if (in.get_bool ("scq"))
+    {
+        QueuedSchedule = new schedule_data;
+        QueuedSchedule->get_state (in);
+    }
+    
+    return in.success ();
+}

Index: schedule.h
===================================================================
RCS file: schedule.h
diff -N schedule.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ schedule.h  18 Jun 2006 19:26:48 -0000      1.1
@@ -0,0 +1,251 @@
+/*
+ $Id: schedule.h,v 1.1 2006/06/18 19:26:48 ksterker Exp $
+ 
+ Copyright (C) 2004/2005/2006 Kai Sterker <address@hidden>
+ Part of the Adonthell Project http://adonthell.linuxgames.com
+ 
+ Adonthell 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.
+ 
+ Adonthell 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 Adonthell; if not, write to the Free Software 
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/**
+ * @file rpg/schedule.h
+ *
+ * @author Kai Sterker
+ * @brief Declares the character schedule class.
+ */
+
+#ifndef RPG_SCHEDULE_H
+#define RPG_SCHEDULE_H
+
+#include "python/script.h"
+#include "event/factory.h"
+#include "rpg/schedule_data.h"
+
+/**
+ * Path to the schedule scripts.
+ */
+#define SCHEDULE_DIR "schedules."
+
+namespace rpg
+{
+    /**
+     * This class manages %character schedules. Each %character has a
+     * manager script that defines what it does all day long. The 
+     * character's actual activity is controlled by different schedule 
+     * scripts that are selected by the manager script, depending on 
+     * various factors.
+     */
+    class schedule
+    {
+    public:
+
+        /**
+         * Standart constructor. Initialize everything to NULL/false.
+         */        
+        schedule ();
+
+        /**
+         * Destructor.
+         */        
+        ~schedule ();
+        
+        /**
+         * Executes the mapcharacter's %schedule script in case it is active
+         * and running. If it stopped running, the manager script will be
+         * launched to determine a new %schedule. If the %schedule isn't 
active,
+         * nothing will happen.
+         */
+        void update ();
+
+        /**
+         * @name Manager Schedule / Schedule Control
+         */
+        //@{
+        /** 
+         * Returns whether the %schedule is active or not. As long as the
+         * %schedule is active, it is executed every %game cycle. If it's
+         * inactive, it will cause the %character to freeze.
+         * 
+         * @return \c true if the %schedule is active, \c false otherwise.
+         */
+        bool is_active () const     { return Active; }
+        
+        /** 
+         * Sets whether the %schedule is active or not. As long as the
+         * %schedule is active, it is executed every %game cycle. If it's
+         * inactive, it will cause the %character to freeze.
+         * 
+         * @param a \c true if the %schedule should be activated, \c false
+         * otherwise.
+         */
+        void set_active (bool a)    { Active = a; }
+        
+        /** 
+         * Returns whether the current %schedule is running or not. Once
+         * it stops running, the manager script will be executed to
+         * determine a new schedule.
+         * 
+         * @return \c true if the schedule is running, \c false otherwise.
+         */
+        bool is_running () const     { return Running; }
+        
+        /** 
+         * Sets whether the %schedule is running or not. Once
+         * it stops running, the manager script will be executed to
+         * determine a new %schedule.
+         *
+         * @param a \c false if the %schedule should be stopped, \c true 
otherwise.
+         */
+        void set_running (bool r)    { Running = r; }
+                
+        /**
+         * Assign a (new) manager script. This script is responsible for
+         * the overall %character behaviour.
+         *
+         * @param file Filename of the script to load.
+         * @param args Addional arguments to pass to the script constructor.
+         * @retrun \e true on success, \e false otherwise
+         */
+        bool set_manager (const std::string & file, PyObject * args = NULL);
+        //@}
+
+        /**
+         * Activity Schedule, Future Activity
+         */
+        //@{
+        /**
+         * Assign a (new) %schedule script, which is responsible for the
+         * character's current activity. This method should only be used
+         * from the manager %schedule. From within a %schedule script, use
+         * queue_schedule () instead.
+         *
+         * @param file Filename of the script to load.
+         * @param args Addional arguments to pass to the script constructor.
+         *
+         * @retrun \e true on success, \e false otherwise
+         * @sa queue_schedule ()
+         */
+        bool set_schedule (const std::string & file, PyObject * args = NULL);
+        
+        /**
+         * Call this to explicitly clear the attached %schedule. This will
+         * also run the destructor (__del__ method) of the script, if it
+         * exists.
+         */
+        void clear_schedule ()
+        {
+            Schedule.clear ();
+        }
+                
+        /**
+         * Set %schedule to use once the current one stops. Overrides
+         * the %schedule otherwise chosen by the manager script. This
+         * method allows a %schedule to decide upon the character's
+         * next activity.
+         *
+         * @param file Filename of the script to load.
+         * @param args Addional arguments to pass to the script constructor.
+         * 
+         * @sa set_schedule ()
+         */
+        void queue_schedule (const std::string & file, PyObject * args = NULL);
+        
+        /**
+         * Specify a period after which the manager script is run,
+         * whether the active %schedule is finished or not. This function
+         * makes use of the %event system and is much more efficient than
+         * querying the current time within the %schedule itself. It
+         * therefore is the preferred method of letting schedules run a 
+         * fixed amount of gametime.
+         *
+         * Note that setting a new %schedule script will cancel the alarm.
+         * Setting a new alarm will also override the existing one. That
+         * means, only one alarm can be active at any given time.
+         *
+         * @param time The amount of time the %schedule should be active,
+         *      in the format used by time_event::time_event ().
+         * @param absolute If <b>true</b>, the current day will be added
+         *      to the time. For example, set_alarm ("14h", true) means
+         *      "today at 14:00", whereas set_alarm ("14h", false) means
+         *      "14 hours from now on".
+         */
+        void set_alarm (const std::string & time, const bool & absolute = 
false);
+        
+        /**
+         * Set an alarm for a script set with queue_schedule (). This 
+         * needs to happen after the call to %queue_schedule, but before
+         * calling set_running (false). If a %schedule is already running,
+         * use set_alarm () instead.
+         * 
+         * @param time The amount of time the %schedule should be active.
+         * @param absolute whether the given time is relative to the current
+         *      time or an absolute hour of the current (or next) day.
+         *
+         * @sa set_alarm ()
+         */
+        void queue_alarm (const std::string & time, const bool & absolute = 
false);
+        //@}
+        
+        /**
+         * @name Loading / Saving
+         */
+        //@{
+        /** 
+         * Save the %schedule to a stream.
+         * @param out stream where to save the %schedule.
+         */ 
+        void put_state (base::flat& out) const;
+        
+        /** 
+         * Loads the %schedule from a stream.
+         * @param in stream to load the %schedule from.
+         * @return \e true if the %schedule was loaded successfully, \e false 
otherwise.
+         */
+        bool get_state (base::flat& in);
+        //@}
+    
+    #ifndef SWIG
+        /// allow schedule to be passed through SWIG
+        GET_TYPE_NAME(rpg::schedule);
+    #endif // SWIG
+        
+    private:
+    #ifndef SWIG
+        /// callback for alarm event
+        void on_alarm () { set_running (false); }
+
+        /// whether the schedule should be executed 
+        bool Active;
+
+        /// whether the manager should be executed
+        bool Running;
+        
+        /// the script describing a character's general behaviour.
+        python::script Manager;
+        
+        /// the script describing a specific activity in detail.
+        python::script Schedule;
+        
+        /// store the alarm event to execute the manager script at a certain 
time
+        events::factory Factory;
+        
+        /// schedule to set instead of running manager script
+        rpg::schedule_data *QueuedSchedule;
+    #endif // SWIG
+    };
+
+} // namespace rpg
+
+#endif // RPG_SCHEDULE_H




reply via email to

[Prev in Thread] Current Thread [Next in Thread]