File: Object.hh

package info (click to toggle)
enigma 1.20-dfsg.1-2.2
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye
  • size: 64,696 kB
  • sloc: xml: 153,614; cpp: 63,581; ansic: 31,088; sh: 4,825; makefile: 1,858; yacc: 288; perl: 84; sed: 16
file content (300 lines) | stat: -rw-r--r-- 12,471 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
 * Copyright (C) 2002,2003,2004 Daniel Heck
 * Copyright (C) 2007,2008,2009 Ronald Lamprecht
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#ifndef OBJECT_HH
#define OBJECT_HH

#include "display.hh"
#include "ecl_alist.hh"
#include "ecl_math.hh"
#include "Value.hh"
#include <map>
#include <stdint.h>

namespace enigma { 

    using std::string;
    
    struct Message;
    
    enum ObjectFlagsBits {
        OBJBIT_LIGHTNEWDIRS  =  15,    ///< GridObject 4 direction bits with current/new light
        OBJBIT_LIGHTOLDDIRS  =  240,   ///< GridObject 4 direction bits with previous light
        OBJBIT_LIGHTALLDIRS  =  255,   ///< GridObject all 8 direction bits with old an new light
        OBJBIT_PHOTOACTIV    =  1<<8,  ///< GridObject registered as photo activ
        OBJBIT_INVERSE       =  1<<9,  ///< Object invert action value
        OBJBIT_NOP           =  1<<10, ///< Object use nop instead toggle as default action
        OBJBIT_INIT          =  1<<11  ///< Object needs init message for @ finalization
    };
    
    enum ValidationResult {
        VALID_OK,
        VALID_ACCESS_DENIED,
        VALID_UNKNOWN_KEY,
        VALID_TYPE_MISMATCH,
        VALID_ILLEAGAL_VALUE
    };    
        
    class Value;

    /**
     * Object is the base class for all "objects" in the world.
     * The most important facilities this class provides are:
     *
     * - A way to clone() and dispose() objects.  This is mainly used
     *     in function MakeObject() to create new objects of a given
     *     type.
     * 
     * - A way to pass messages between unrelated objects via message().
     *     This allows us to send messages to objects from Lua and to
     *     decouple objects types as much as possible.
     * 
     * - A way to get and set attributes.  These attributes are quite
     *     similar to instance variables, but they can be easily modified
     *     from Lua.  This makes it possible to modify certain object
     *     parameters (such as the text on a piece of paper or the color
     *     of an oxyd stone) in level descriptions.
     * 
     * The various Object subclasses instances need to register a template
     * instance for each object name. To avoid the inclusion of every
     * subclass declaration file into the registry for registry driven forward
     * initialization we make use of the static file based initialization
     * that occurs prior to the main application startup. To be independent of
     * the undefined sequence in which the files are initialized we store the
     * template instances, object names and id's in function local static caches.
     * These caches are copied to the final runtime data structures on the main
     * application startup. We call this feature "boot"-initialization. The macros
     * BOOT_REGISTER_START and BOOT_REGISTER_END will be used once at the end of
     * every subclass file. They embrace the BootRegister() function calls that
     * register the templates.
     */
    class Object {

    public:
        enum ObjectType { 
            OBJECT,
            OTHER,
            STONE,
            FLOOR,
            ITEM,
            ACTOR
        };
            
        typedef ecl::AssocList<std::string, Value> AttribMap;

        Object();
        Object(const char *kind);
        Object(const Object &src_obj); 
        virtual ~Object();

        static Object * getObject(int id);
        int getId() const;
        
        /* ---------- depreceated methods ---------- */

        const AttribMap &get_attribs() const { return attribs; }  // just used by ObjectRepos::dump_info()        

        /* ---------- Helper routines ---------- */

        void send_impulse(const GridPos& dest, Direction dir);

        /* ---------- Object interface ---------- */
        
        /**
         * The main object category name of the object that describes its gaming class.
         * All objects of a gaming class support the same attributes and messages. But
         * they may still be members of different kind subcategories. E.g. "st_panel"
         * is a class with "st_panel_n", "st_panel_s",... as kinds. A gaming object
         * class is often implemented as a separate C++ class. But sometimes several 
         * gaming classes share a single C++ class. E.g. "st_panel", "st_bluesand" are
         * both implemented by the class "ClusterStone". In this case we talk about a 
         * common "family". 
         */
        virtual std::string getClass() const =0;
        
        /**
         * The most specific object category name. Many objects change their kind during
         * their lifecycle. All attributes are evaluated to determine the current kind
         * of a gaming object. 
         */
        std::string getKind() const;
        
        /**
         * Check the current kind of the object versus the given name.
         */
        bool isKind(const std::string &kind) const;
        
        
        bool validateMessage(std::string msg, Value arg);

        /**
         * 
         */
        virtual Value message(const Message &m);
                
        /**
         * Store the value information for the given key with prior checking of
         * write allowance. All level code attribute settings should pass this
         * central call. If a set is granted the virtual unchecked setAttr is 
         * executed.
         */
        void setAttrChecked(const std::string &key, const Value &val);
        
        /**
         * Store the value information for the given key. If it is a XML declared
         * system attribute or a user attribute it will be stored in the attribute
         * map. Otherwise an ivar may be set. Nothing happens if the attribute is
         * declared as read only. If the value is "nil" the attribute will be reset
         * to its declared default. If the default is "nil", too, or if it is a user
         * attribute, it will be deleted in the attribute map. In these cases a read
         * will return "nil" either way.
         */
        virtual void setAttr(const std::string &key, const Value &val);
        
        /**
         * Get an attribute or value for the given key with prior checking of
         * read allowance. All level code attribute reads should pass this central
         * call. If a read is granted the virtual unchecked getAttr is executed.
         */
        Value getAttrChecked(const std::string &key) const;
        
        /**
         * Get an attribute that has been set or that stands as a proxy for a
         * trait or ivar. Object itself will just return attribute values
         * that are stored in its attribute map. For not existing attributes
         * a XML declared standard default value will be returned. If the default
         * is "nil" type DEFAULT will be returned. 
         * 
         * Subclasses may override this method to supply values of traits or
         * ivars. This way levels can gain read access to attributes that can
         * not to be stored in the attribute map due to performance reasons.
         */
        virtual Value getAttr(const std::string &key) const;
        

        /**
         * Get an attribute or a special given default value. This method
         * gets attributes like the simple argumented getAttr method but
         * returns the given default value instead of a DEFAULT value if
         * no explicit attribute exists.
         */
        Value getDefaultedAttr(const string &key, Value defaultValue) const;
        
        
        virtual Object *clone() =0;
        virtual void dispose() =0;

        virtual void warning(const char *format, ...) const;
        virtual ObjectType getObjectType() const;
        void transferName(Object *target);
        virtual void transferIdentity(Object *target);
        virtual double squareDistance(const Object *other) const;
        virtual bool isSouthOrEastOf(const Object *other) const;

    protected:
        /** This function is used by all triggers, switches etc. that
         * perform some particular action when activated (like opening
         * doors or switching lasers on and off). It interprets the
         * "action" and "target" attributes of `o'. 
         */
        void performAction(const Value &val);
        
        virtual Value invertActionValue(const Value &val) const;
        
        /**
         * Evaluate multiple destinations described by tokenized destination
         * attribute where every token may be a group by itself. All valid
         * destinations are indexed in the sequence of tokens and group positions.
         * The position at the given index is returned as the destination position.
         * If the caller did index beyond the last valid position this convenience
         * method returns false, otherwise true to mark a valid position. 
         * Objects with destinations like Vortex and Horse make use of this method.
         * @arg idx      requested index of destination starting with 0
         * @arg destpos  return value for position that is centered to a grid
         * @return       validity of position at given index
         */
        bool getDestinationByIndex(int idx, ecl::V2 &dstpos);
        
        /**
         * A central managed container for 32 single bit flags to be used by 
         * subclasses. Object is reponsible for efficiently cloning, saving and
         * restoring these flags on demand. Subclasses use the bits as follows:
         * 
         * - Bit 0-15 are reserved for classes Object to GridObject
         * 
         * - Bit 16-23 are reserved for classes Item, Stone, Floor, Actor
         * 
         * - Bit 24-31 are reserved for the final subclass
         * 
         * See enumeration ObjectFlagsBits for Bitmasks of Bit 0-15. Note that
         * Bitmasks would not have been an alternative as the subclasses may
         * and will use the upper bits in a quite different manner.
         */
        uint32_t  objFlags;
        
    private:
        friend void InitWorld();   // for bootFinished() access
        
        static int next_id;
        static std::map<int, Object *> objects;
        
        int       id;
        AttribMap attribs;
        
        void finalizeNearestObjectReferences(std::string attr);
        void finalizeNearestObjectReferences();
        
        static int getNextId(Object *obj, bool bootFinished);
        static void bootFinished();
        static void freeId(int id);
        
    };


} // namespace enigma


#define BOOT_REGISTER_START        \
        namespace {                \
            bool do_boot_register() {

#define BOOT_REGISTER_END          \
                return true;       \
            }                      \
            static bool boot_registered = do_boot_register(); \
        } 

#define CLONEOBJ(TYPE)                                  \
        TYPE* clone() { return new TYPE(*this); }       \
        void dispose() { delete this; }

#define CLONEACTOR(TYPE)                                                \
        TYPE* clone() { TYPE *o=new TYPE(*this); o->init(); return o; } \
        void dispose() { delete this; }

#define INSTANCELISTOBJ(TYPE)                                                   \
        typedef std::vector<TYPE*> InstanceList;                                \
        static InstanceList instances;                                          \
        TYPE *clone() { TYPE *o = new TYPE(*this); instances.push_back(o); return o;}  \
        void dispose() {                                                        \
            instances.erase(find(instances.begin(), instances.end(), this));    \
            delete this;                                                        \
        }

#endif