Planeshift
mathscript.h
Go to the documentation of this file.
1 /*
2  * mathscript.h by Keith Fulton <keith@planeshift.it>
3  *
4  * Copyright (C) 2010 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)
5  *
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation (version 2 of the License)
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  */
19 #ifndef __MATHSCRIPT_H__
20 #define __MATHSCRIPT_H__
21 
22 #include <../tools/fparser/fparser.h>
23 #include <csutil/csstring.h>
24 #include <csutil/hash.h>
25 #include <csutil/randomgen.h>
26 #include <csutil/set.h>
27 #include <csutil/strset.h>
28 #include <util/scriptvar.h>
29 #include <csutil/weakreferenced.h>
30 #include <csutil/weakref.h>
31 
32 #ifdef _MSC_VER
33 double round(double value);
34 #endif
35 
36 class MathScript;
37 class MathVar;
38 struct iDataConnection;
39 
52 {
53 protected:
54  csHash<MathScript*, csString> scripts;
55  static csRandomGen rng;
56 
57  static csStringSet stringLiterals;
58  static csStringSet customCompoundFunctions;
59 
60 
61  csString mathScriptTable;
62 
63 public:
65  {
66  double value; // masked float value
67  struct
68  {
69 #ifdef CS_LITTLE_ENDIAN
70  CS_ALIGNED_MEMBER(uint32 value,1); // value of the ID
71  CS_ALIGNED_MEMBER(uint16 ignored,1); // ignored part
72  CS_ALIGNED_MEMBER(uint16 mask,1); // mask used to identify strings/objects
73 #else
74  CS_ALIGNED_MEMBER(uint16 mask,1); // mask used to identify strings/objects
75  CS_ALIGNED_MEMBER(uint16 ignored,1); // ignored part
76  CS_ALIGNED_MEMBER(uint32 value,1); // value of the ID
77 #endif
78  } ID;
79  uintptr_t p; // packed pointer
80  };
81 
82  MathScriptEngine(iDataConnection* db, const csString& mathScriptTable);
84 
86  MathScript* FindScript(const csString& name);
87 
91  void ReloadScripts(iDataConnection* db);
92 
97  bool LoadScripts(iDataConnection* db, bool reload = false);
98 
102  void UnloadScripts();
103 
108  static CS::StringIDValue GetCompoundFunction(const csString& name)
109  {
110  return customCompoundFunctions.Request(name);
111  }
112 
114  static const char* Request(uint32 ID)
115  {
116  return stringLiterals.Request(ID);
117  }
118 
120  static const char* Request(double f)
121  {
122  // initialize ID conversion
123  IDConverter ID;
124  ID.value = f;
125  ID.ID.mask &= 0xFFF0;
126 
127  // check the mask matches our string mask
128  if(ID.ID.mask != 0xFFF0)
129  {
130  // not a string
131  return "";
132  }
133 
134  // we seem to have an ID here, retrieve the associated
135  // string and return it
136  return Request(ID.ID.value);
137  }
138 
140  static uint32 RequestID(const char* str)
141  {
142  return stringLiterals.Request(str);
143  }
144 
146  static double Request(const char* str)
147  {
148  // intialize the ID conversion
149  IDConverter ID;
150 
151  // set our string mask so the value will be recognizable
152  ID.ID.mask = 0xFFF0;
153 
154  // initialize the part we won't use
155  ID.ID.ignored = 0;
156 
157  // retrieve the ID
158  ID.ID.value = RequestID(str);
159 
160  // return the masked value
161  return ID.value;
162  }
163 
165  static bool HasString(const char* str)
166  {
167  return stringLiterals.Contains(str);
168  }
169 
174  static double CustomCompoundFunc(const double * parms);
175 
177  static double RandomGen(const double *dummy);
178 
180  static csString FormatMessage(const csString& formatString, size_t arg_count, const double* parms);
181 };
182 
189 {
190 private:
191  MathVar* GetVar(const char* name);
192 
194  uint32* UID;
196  csHash<iScriptableVar*,uint32> scriptableVariables;
198  csHash<uint32,iScriptableVar*> scriptableRegistry;
199 
201  csStringSet stringLiterals;
202 
203  const MathEnvironment *parent;
204  csHash<MathVar*, csString> variables;
205 
206  void Init();
207 
208  // environments mustn't be copy-constructed
210 
211 public:
212  MathEnvironment() : UID(new uint32),parent(NULL)
213  {
214  *UID = 0;
215  Init();
216  }
217  MathEnvironment(const MathEnvironment *parent) : UID(parent->UID),parent(parent)
218  {
219  Init();
220  }
221  ~MathEnvironment();
222 
224  void Define(const char *name, double value);
225 
227  void Define(const char *name, iScriptableVar* obj);
228 
230  void Define(const char *name, const char* str);
231 
233  bool HasString(const char* p) const;
234 
236  bool HasObject(iScriptableVar* p) const;
237 
239  csString GetString(double id) const;
240 
242  double GetValue(iScriptableVar* p);
243 
245  iScriptableVar* GetPointer(double id) const;
246 
248  double GetValue(const char* p);
249 
250  MathVar* Lookup(const char *name) const;
251  void DumpAllVars() const;
252 
254  void InterpolateString(csString & str) const;
255 };
256 
259 {
263 };
264 
270 class MathVar
271 {
272 protected:
273  double value;
275 
276  typedef void (*MathScriptVarCallback)(void* arg);
277  MathScriptVarCallback changedVarCallback;
279 
280 public:
281  MathVar(MathEnvironment* parent) : value(0.f),parent(parent),
282  changedVarCallback(NULL),
283  changedVarCallbackArg(NULL)
284  {
285  }
286 
287  void SetChangedCallback(MathScriptVarCallback callback, void* arg)
288  {
289  changedVarCallback = callback;
290  changedVarCallbackArg = arg;
291  }
292 
293  void SetValue(double v);
294  void SetObject(iScriptableVar* p);
295  void SetString(const char* p);
296 
297  MathType Type() const;
298 
299  inline int GetRoundValue() const
300  {
301  return (int)round(GetValue());
302  }
303 
304  inline double GetValue() const
305  {
306  return value;
307  }
308 
309  inline iScriptableVar* GetObject() const
310  {
311  return parent->GetPointer(value);
312  }
313 
314  inline csString GetString() const
315  {
316  return parent->GetString(value);
317  }
318 
319  csString ToString() const;
320  csString Dump() const;
321 };
322 
331 {
332 protected:
333  enum
334  {
335  MATH_NONE = 0, // NOP
336  MATH_COND = 1, // is a conditional
337  MATH_EXP = 2, // has expression
338  MATH_LOOP = 4, // is a loop
339  MATH_ASSIGN = 8, // is an assignment
340  MATH_BREAK = 16, // flow control break
341 
342  // aliases
343  MATH_WHILE = MATH_COND | MATH_EXP | MATH_LOOP,
344  MATH_IF = MATH_COND | MATH_EXP,
345  MATH_ELSE = MATH_COND,
346  MATH_DO = MATH_EXP | MATH_LOOP
347  };
348  size_t opcode; // opcode of this expression
349 
350  MathExpression(); // may only be constructed via MathExpression::Create
351 
352  bool Parse(const char *expression);
353 
354  struct PropertyRef
355  {
356  csString object; // name of the object this property refers to
357  csString property; // property to be retrieved
358 
359  // required to be used in csHash as used by csSet
360  uint GetHash() const
361  {
362  return (object+":"+property).GetHash();
363  }
364 
365  // required by csComparator used in csHash used by csSet
366  bool operator<(const PropertyRef& rhs) const
367  {
368  return (object+":"+property) < (rhs.object+":"+rhs.property);
369  }
370  };
371 
372  csSet<csString> requiredVars;
373  csSet<csString> requiredObjs;
374  csSet<PropertyRef> propertyRefs;
376 
377  const char *name; // used for debugging
378 
379 public:
380  virtual ~MathExpression() {}
381  static MathExpression* Create(const char *expression, const char *name = "");
382 
383  virtual double Evaluate(MathEnvironment *env) const;
384 
385  size_t GetOpcode() const
386  {
387  return opcode;
388  }
389 
390  void SetOpcode(size_t newOpcode)
391  {
392  opcode = newOpcode;
393  }
394 };
395 
405 {
406 protected:
407  MathStatement() { } // may only be constructed via MathStatement::Create
408 
409  csString assignee;
410 
411 public:
412  static MathStatement* Create(const csString & expression, const char *name);
413  double Evaluate(MathEnvironment *env) const;
414 };
415 
421 {
422 public:
424  {
425  opcode = MATH_NONE;
426  }
427 
428  double Evaluate(MathEnvironment* /*env*/) const
429  {
430  return 0;
431  }
432 };
433 
434 
442 class MathScript : private MathExpression
443 {
444 protected:
445  MathScript(const char *name) : name(name) { } // may only be constructed using MathScript::Create
446  csString name;
447  csArray<MathExpression*> scriptLines;
448 
449 public:
450  static MathScript* Create(const char *name, const csString & script);
451  static void Destroy(MathScript* &mathScript);
452 
453  ~MathScript();
454 
455  const csString & Name() const
456  {
457  return name;
458  }
459 
460  void CopyAndDestroy(MathScript* other);
461 
462  double Evaluate(MathEnvironment *env) const;
463 };
464 
467 #endif
468 
MathEnvironment(const MathEnvironment *parent)
Definition: mathscript.h:217
csSet< csString > requiredObjs
a subset of requiredVars which are known to be objects; for type checking
Definition: mathscript.h:373
csHash< MathScript *, csString > scripts
Definition: mathscript.h:54
static uint32 RequestID(const char *str)
request an ID for a string
Definition: mathscript.h:140
csString mathScriptTable
Definition: mathscript.h:61
MathScriptEngine(iDataConnection *db, const csString &mathScriptTable)
csString assignee
variable the result will be assinged to
Definition: mathscript.h:409
static double RandomGen(const double *dummy)
rnd(limit) generates a random number between 0 and limit.
const csString & Name() const
Definition: mathscript.h:455
csSet< csString > requiredVars
variables required to execute this expression
Definition: mathscript.h:372
csString GetString(double id) const
retrieve a string literal based on it&#39;s id.
This holds an empty statement that shall not be executed but is used for control flow statements...
Definition: mathscript.h:420
A specific MathEnvironment to be used in a MathScript.
Definition: mathscript.h:188
A MathScript is a mini-program to run.
Definition: mathscript.h:442
static csString FormatMessage(const csString &formatString, size_t arg_count, const double *parms)
format a message using csString&#39;s Format given a string ID and a number of floating points...
double Evaluate(MathEnvironment *) const
Definition: mathscript.h:428
iScriptableVar * GetPointer(double id) const
retrieve a pointer to a scriptable object based on it&#39;s id.
void UnloadScripts()
Cleans up all the script and data loaded.
void * changedVarCallbackArg
Definition: mathscript.h:278
size_t GetOpcode() const
Definition: mathscript.h:385
MathScript * FindScript(const csString &name)
retrieve a MathScript given it&#39;s name.
int GetRoundValue() const
Definition: mathscript.h:299
static csStringSet customCompoundFunctions
Definition: mathscript.h:58
static csStringSet stringLiterals
Definition: mathscript.h:57
The base expression class.
Definition: mathscript.h:330
static const char * Request(double f)
obtain a string literal based on it&#39;s masked value
Definition: mathscript.h:120
static double Request(const char *str)
request a masked value for a string
Definition: mathscript.h:146
csString GetString() const
Definition: mathscript.h:314
csArray< MathExpression * > scriptLines
Definition: mathscript.h:447
MathVar(MathEnvironment *parent)
Definition: mathscript.h:281
void SetChangedCallback(MathScriptVarCallback callback, void *arg)
Definition: mathscript.h:287
iDataConnection * db
Global connection to the Database. Set from the psDatabase class.
bool LoadScripts(iDataConnection *db, bool reload=false)
Loads all the scripts from the database.
const char * name
Definition: mathscript.h:377
This holds information about a specific variable in a specific MathEnvironment to be used for MathScr...
Definition: mathscript.h:270
MathScriptVarCallback changedVarCallback
Definition: mathscript.h:277
MathEnvironment * parent
Definition: mathscript.h:274
bool operator<(const PropertyRef &rhs) const
Definition: mathscript.h:366
void ReloadScripts(iDataConnection *db)
Triggers a cleanup and reload of all the scripts.
MathType
possible types of variables.
Definition: mathscript.h:258
double GetValue() const
Definition: mathscript.h:304
void SetOpcode(size_t newOpcode)
Definition: mathscript.h:390
FunctionParser fp
Definition: mathscript.h:375
iScriptableVar * GetObject() const
Definition: mathscript.h:309
csString name
Definition: mathscript.h:446
csSet< PropertyRef > propertyRefs
properties that have to be resolved prior to evaluation
Definition: mathscript.h:374
MathScript(const char *name)
Definition: mathscript.h:445
bool GetValue(const char *name)
This holds one line of a (potentially) multi-line script.
Definition: mathscript.h:404
static double CustomCompoundFunc(const double *parms)
internal function used for callbacks to scriptable objects from fparser.
double value
Definition: mathscript.h:273
struct MathScriptEngine::IDConverter::@35 ID
virtual ~MathExpression()
Definition: mathscript.h:380
static csRandomGen rng
Definition: mathscript.h:55
static bool HasString(const char *str)
check whether a string is present in the global lookup table.
Definition: mathscript.h:165
static const char * Request(uint32 ID)
obtain a string literal based on it&#39;s actual ID
Definition: mathscript.h:114
This holds all the formulas loaded from the MathScript table and provides a container for them...
Definition: mathscript.h:51
static CS::StringIDValue GetCompoundFunction(const csString &name)
retrieve the index of a custom compound function given it&#39;s name.
Definition: mathscript.h:108