read Blackboard data correctly from the SFC file, and construct a BlackboardPart...
[openc2e.git] / caosVM_variables.cpp
blob63825801aee888b8b48e45e2123341133cf025e4
1 /*
2 * caosVM_variables.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Mon May 31 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "caosVM.h"
21 #include "Agent.h"
22 #include <stdlib.h> // rand()
23 #include <iostream>
24 #include <math.h> // abs()/fabs()
25 #include "openc2e.h"
26 #include "World.h"
27 #include "Engine.h"
28 #include "Catalogue.h"
30 #include <cctype> // toupper/tolower
31 #include <algorithm> // transform
32 #include <boost/format.hpp>
34 #include "Vehicle.h"
35 #include "PointerAgent.h"
36 #include "CreatureAgent.h"
38 /**
39 VAxx (variable)
40 %status maybe
41 %pragma stackdelta 0
42 %pragma variants c2 cv c3 sm
44 Script-local variables (exist only in the current script) with xx being from 00 to 99. Examples: VA01, VA45.
46 CAOS_LVALUE(VAxx,
47 VM_PARAM_INTEGER(index); caos_assert(index >= 0 && index < 100),
48 var[index],
49 var[index] = newvalue)
52 /**
53 VARx (variable)
54 %status maybe
55 %pragma variants c1 c2
56 %pragma stackdelta 0
57 %pragma implementation caosVM::v_VAxx
58 %pragma saveimpl caosVM::s_VAxx
60 Like VAxx, but restricted to 0-9. Legacy from Creatures 1.
63 /**
64 MVxx (variable)
65 %pragma stackdelta 0
66 %status maybe
68 Like OVxx, only for OWNR, not TARG.
70 CAOS_LVALUE_WITH(MVxx, owner,
71 VM_PARAM_INTEGER(index); caos_assert(index >= 0 && index < 100),
72 owner->var[index],
73 owner->var[index] = newvalue)
75 /**
76 ADDS (command) var (variable) value (string)
77 %status maybe
79 Append the given string to the given variable.
81 void caosVM::c_ADDS() {
82 VM_VERIFY_SIZE(2)
83 VM_PARAM_STRING(value)
84 VM_PARAM_VARIABLE(variable)
86 caos_assert(variable->hasString());
87 variable->setString(variable->getString() + value);
90 /**
91 SETS (command) var (variable) value (string)
92 %status maybe
94 Sets the given variable to the given string.
96 void caosVM::c_SETS() {
97 VM_VERIFY_SIZE(2)
98 VM_PARAM_STRING(value)
99 VM_PARAM_VARIABLE(var)
100 var->reset();
101 var->setString(value);
105 SETV (command) var (variable) value (decimal)
106 %status maybe
107 %pragma variants c1 c2 cv c3 sm
108 %cost c1,c2 0
109 %% Don't enable c1 or c2 here; we activate them with horrible hacks later
111 Sets the given variable to the given decimal value.
113 void caosVM::c_SETV() {
114 VM_VERIFY_SIZE(2)
115 // TODO: hackery for c2
116 //VM_PARAM_DECIMAL(value)
117 VM_PARAM_VALUE(value)
118 VM_PARAM_VARIABLE(var)
119 var->reset();
121 // TODO: hackery for c2
122 if (value.hasAgent()) {
123 var->setAgent(value.getAgent());
124 return;
125 } else caos_assert(value.hasDecimal());
127 if (value.hasFloat()) {
128 var->setFloat(value.getFloat());
129 } else { // VM_PARAM_DECIMAL guarantees us float || int
130 var->setInt(value.getInt());
135 SETA (command) var (variable) value (agent)
136 %status maybe
138 Sets the given variable to the given agent.
140 void caosVM::c_SETA() {
141 VM_VERIFY_SIZE(2)
142 VM_PARAM_AGENT(value)
143 VM_PARAM_VARIABLE(var)
144 var->reset();
145 var->setAgent(value);
149 OVxx (variable)
150 %status maybe
151 %pragma stackdelta 0
152 %pragma variants c2 cv c3 sm
154 Agent-local variables (exist only in the current agent's VM) from TARG, with xx being from 00 to 99. Examples: OV01, OV45.
156 CAOS_LVALUE_TARG(OVxx,
157 VM_PARAM_INTEGER(index); caos_assert(index >= 0 && index < 100),
158 targ->var[index],
159 targ->var[index] = newvalue)
162 OBVx (variable)
163 %status maybe
164 %pragma stackdelta 0
165 %pragma variants c1 c2
166 %pragma implementation caosVM::v_OVxx
167 %pragma saveimpl caosVM::s_OVxx
169 Like OVxx, but restricted to 0-2 in C1, or 0-9 in C2. Legacy from Creatures 1.
171 // TODO: restrict to 0-2 in C1?
174 TYPE (integer) value (anything)
175 %status maybe
177 Returns a integer value representing the type of data in 'value'. 0 is integer, 1 is float, 2 is string, 3 is agent.
179 void caosVM::v_TYPE() {
180 VM_PARAM_VALUE(value)
182 caos_assert(!value.isEmpty());
184 if (value.hasInt())
185 result.setInt(0);
186 else if (value.hasFloat())
187 result.setInt(1);
188 else if (value.hasString())
189 result.setInt(2);
190 else if (value.hasAgent()) {
191 boost::shared_ptr<Agent> a = value.getAgent();
192 if (a == 0)
193 result.setInt(-1);
194 else if (typeid(*a) == typeid(SimpleAgent))
195 result.setInt(3);
196 else if (typeid(*a) == typeid(PointerAgent))
197 result.setInt(4);
198 else if (typeid(*a) == typeid(CompoundAgent))
199 result.setInt(5);
200 else if (typeid(*a) == typeid(Vehicle))
201 result.setInt(6);
202 else {
203 CreatureAgent *c = dynamic_cast<CreatureAgent *>(a.get());
204 if (c)
205 result.setInt(7);
206 else
207 result.setInt(-2); // unknown agent
209 } else
210 throw creaturesException("caosVar confused us terribly in TYPE");
214 MODV (command) var (variable) mod (integer)
215 %status maybe
216 %pragma variants c1 c2 cv c3 sm
217 %cost c1,c2 0
219 Divides the given variable by the given integer, and returns the remainder (var % mod).
221 void caosVM::c_MODV() {
222 VM_VERIFY_SIZE(2)
223 VM_PARAM_INTEGER(mod)
224 VM_PARAM_VARIABLE(v) // integer
225 if (!v->hasInt()) throw badParamException();
226 v->setInt(v->getInt() % mod);
230 ANDV (command) var (variable) and (integer)
231 %status maybe
232 %pragma variants c1 c2 cv c3 sm
233 %cost c1,c2 0
235 Returns the result of a bitwise AND comparison of the given variable and the given integer (var & and).
237 void caosVM::c_ANDV() {
238 VM_VERIFY_SIZE(2)
239 VM_PARAM_INTEGER(andv)
240 VM_PARAM_VARIABLE(v)
241 if (!v->hasInt()) throw badParamException();
242 v->setInt(v->getInt() & andv);
246 ORRV (command) var (variable) or (integer)
247 %status maybe
248 %pragma variants c1 c2 cv c3 sm
249 %cost c1,c2 0
251 Returns the result of a bitwise OR comparison of the given variable and the given integer (var | or)
253 void caosVM::c_ORRV() {
254 VM_VERIFY_SIZE(2)
255 VM_PARAM_INTEGER(orv)
256 VM_PARAM_VARIABLE(v)
257 if (!v->hasInt()) throw badParamException();
258 v->setInt(v->getInt() | orv);
262 ADDV (command) var (variable) add (integer)
263 %status maybe
264 %pragma variants c1 c2 cv c3 sm
265 %cost c1,c2 0
267 Adds the given integer to the given variable and returns the result.
269 void caosVM::c_ADDV() {
270 VM_VERIFY_SIZE(2)
271 VM_PARAM_DECIMAL(add)
272 VM_PARAM_VARIABLE(v)
273 if (v->hasFloat())
274 v->setFloat(v->getFloat() + (add.hasFloat() ? add.getFloat() : add.getInt()));
275 else if (v->hasInt())
276 v->setInt((int)(v->getInt() + (add.hasFloat() ? add.getFloat() : add.getInt())));
277 else
278 throw badParamException();
282 SUBV (command) var (variable) sub (integer)
283 %status maybe
284 %pragma variants c1 c2 cv c3 sm
285 %cost c1,c2 0
287 Subtracts the given integer from the given variable and returns the result.
289 void caosVM::c_SUBV() {
290 VM_VERIFY_SIZE(2)
291 VM_PARAM_DECIMAL(sub)
292 VM_PARAM_VARIABLE(v)
293 if (v->hasFloat())
294 v->setFloat(v->getFloat() - (sub.hasFloat() ? sub.getFloat() : sub.getInt()));
295 else if (v->hasInt())
296 v->setInt((int)(v->getInt() - (sub.hasFloat() ? sub.getFloat() : sub.getInt())));
297 else
298 throw badParamException();
302 NEGV (command) var (variable)
303 %status maybe
304 %pragma variants c1 c2 cv c3 sm
305 %cost c1,c2 0
307 Returns the inverse of (negates) the given variable. For example, 1 to -1, or -4 to 4.
309 void caosVM::c_NEGV() {
310 VM_VERIFY_SIZE(1)
311 VM_PARAM_VARIABLE(v)
312 if (v->hasFloat())
313 v->setFloat(-v->getFloat());
314 else if (v->hasInt())
315 v->setInt(-v->getInt());
316 else
317 throw badParamException();
321 DIVV (command) var (variable) div (decimal)
322 %status maybe
323 %pragma variants c1 c2 cv c3 sm
324 %cost c1,c2 0
326 Divides the given variable by the given integer and returns the result.
328 void caosVM::c_DIVV() {
329 VM_VERIFY_SIZE(2)
330 VM_PARAM_DECIMAL(div)
331 VM_PARAM_VARIABLE(v)
333 caos_assert(div.hasDecimal());
334 if (div.getFloat() == 0.0f) throw caosException("attempt to divide by zero");
336 if ((engine.version < 3 && v->hasDecimal() && div.hasDecimal()) || (v->hasInt() && div.hasInt())) {
337 // integer division
338 v->setInt(v->getInt() / div.getInt());
339 } else if (v->hasInt() || v->hasFloat()) {
340 // floating point division
341 v->setFloat((v->hasFloat() ? v->getFloat() : v->getInt()) /
342 (div.hasFloat() ? div.getFloat() : div.getInt()));
343 } else
344 throw badParamException();
348 MULV (command) var (variable) mul (decimal)
349 %status maybe
350 %pragma variants c1 c2 cv c3 sm
351 %cost c1,c2 0
353 Multiplies the given variable by the given integer and returns the result.
355 void caosVM::c_MULV() {
356 VM_VERIFY_SIZE(2)
357 VM_PARAM_DECIMAL(mul)
358 VM_PARAM_VARIABLE(v)
359 if (v->hasFloat() || mul.hasFloat())
360 v->setFloat(v->getFloat() * mul.getFloat());
361 else if (v->hasInt() && mul.hasInt())
362 v->setInt(v->getInt() * mul.getInt());
363 else
364 throw badParamException();
367 int calculateRand(int value1, int value2) {
368 // TODO: i'm sure there's a better way to do this. tired. - fuzzie
369 int diff;
370 if (abs(value2) < abs(value1))
371 diff = abs(value1 - value2) + 1;
372 else
373 diff = abs(value2 - value1) + 1;
374 int val;
375 if (value2 < value1)
376 val = value2;
377 else
378 val = value1;
379 double r = rand() / ((unsigned int)RAND_MAX + 1.0);
381 return (int)(r * diff) + val;
386 RAND (integer) value1 (integer) value2 (integer)
387 %status maybe
389 Returns a random integer between 'value1' and 'value2', inclusive.
391 void caosVM::v_RAND() {
392 VM_VERIFY_SIZE(2)
393 VM_PARAM_INTEGER(value2)
394 VM_PARAM_INTEGER(value1)
396 result.setInt(calculateRand(value1, value2));
400 REAF (command)
401 %status maybe
403 Re-reads all catalogue files.
405 void caosVM::c_REAF() {
406 VM_VERIFY_SIZE(0)
408 catalogue.reset();
409 world.initCatalogue();
413 UFOS (string)
414 %status stub
416 Returns 'uname -a' on platforms which support it, or OS details in another format otherwise.
418 void caosVM::v_UFOS() {
419 VM_VERIFY_SIZE(0)
420 result.setString("some random platform"); // TODO
424 MODU (string)
425 %status stub
426 %pragma variants all
428 Returns information about which modules are being used by the engine (for now, backend and audio backend names).
430 void caosVM::v_MODU() {
431 VM_VERIFY_SIZE(0)
432 result.setString(engine.getBackendName() + ", " + engine.getAudioBackendName());
433 //result.setString("OriginalDisplay SDL (netbabel 148)"); // TODO
437 GNAM (string)
438 %status maybe
439 %pragma variants all
441 Returns the currently-running game (like "Creatures 1" or "Docking Station").
443 void caosVM::v_GNAM() {
444 VM_VERIFY_SIZE(0)
445 result.setString(engine.getGameName());
449 ABSV (command) var (variable)
450 %status maybe
452 Modifies the given variable, if negative, so that its value is positive (absolute value).
454 void caosVM::c_ABSV() {
455 VM_VERIFY_SIZE(1)
456 VM_PARAM_VARIABLE(var)
458 if (var->hasFloat()) var->setFloat(fabs(var->getFloat()));
459 else if (var->hasInt()) var->setInt(abs(var->getInt()));
460 else throw badParamException();
464 ACOS (float) x (float)
465 %status maybe
467 Returns the arccosine of x in degrees.
469 void caosVM::v_ACOS() {
470 VM_VERIFY_SIZE(1)
471 VM_PARAM_FLOAT(x)
473 double f = acos(x);
474 f = f * 360;
475 f = f / (M_PI * 2);
476 result.setFloat(f);
480 ASIN (float) x (float)
481 %status maybe
483 Returns the arcsine of x in degrees.
485 void caosVM::v_ASIN() {
486 VM_VERIFY_SIZE(1)
487 VM_PARAM_FLOAT(x)
489 double f = asin(x);
490 f = f * 360;
491 f = f / (M_PI * 2);
492 result.setFloat(f);
496 ATAN (float) x (float)
497 %status maybe
499 Returns the arctangent of x in degrees.
501 void caosVM::v_ATAN() {
502 VM_VERIFY_SIZE(1)
503 VM_PARAM_FLOAT(x)
505 double f = atan(x);
506 f = f * 360;
507 f = f / (M_PI * 2);
508 result.setFloat(f);
512 COS_ (float) x (float)
513 %status maybe
515 Returns the cosine of x in degrees.
517 void caosVM::v_COS_() {
518 VM_VERIFY_SIZE(1)
519 VM_PARAM_FLOAT(x)
521 double f = x * (M_PI * 2);
522 f = f / 360;
523 result.setFloat(cos(f));
527 SIN_ (float) x (float)
528 %status maybe
530 Returns the sine of x in degrees.
532 void caosVM::v_SIN_() {
533 VM_VERIFY_SIZE(1)
534 VM_PARAM_FLOAT(x)
536 double f = x * (M_PI * 2);
537 f = f / 360;
539 result.setFloat(sin(f));
543 TAN_ (float) x (float)
544 %status maybe
546 Returns the tangent of x in degrees.
548 void caosVM::v_TAN_() {
549 VM_VERIFY_SIZE(1)
550 VM_PARAM_FLOAT(x)
552 double f = x * (M_PI * 2);
553 f = f / 360;
555 result.setFloat(tan(f));
559 SQRT (float) v (float)
560 %status maybe
562 Returns the square root of v.
564 void caosVM::v_SQRT() {
565 VM_VERIFY_SIZE(1)
566 VM_PARAM_FLOAT(x)
568 caos_assert(x >= 0); // no imaginary numbers for you!
570 result.setFloat(sqrt(x));
574 _P1_ (variable)
575 %pragma implementation caosVM::v_P1
576 %pragma saveimpl caosVM::s_P1
577 %status maybe
578 %pragma variants c2 cv c3 sm
580 The first argument given to the current script.
584 _P2_ (variable)
585 %pragma implementation caosVM::v_P2
586 %pragma saveimpl caosVM::s_P2
587 %status maybe
588 %pragma variants c2 cv c3 sm
590 The second argument given to the current script.
592 CAOS_LVALUE_SIMPLE(P1, _p_[0])
593 CAOS_LVALUE_SIMPLE(P2, _p_[1])
596 AVAR (variable) agent (agent) index (integer)
597 %status maybe
599 Returns the value of OVxx for the given agent, where xx is equal to 'index'.
601 CAOS_LVALUE(AVAR,
602 VM_VERIFY_SIZE(2)
603 VM_PARAM_INTEGER(index)
604 VM_PARAM_AGENT(agent)
605 caos_assert(index >= 0 && index < 100);
606 valid_agent(agent)
608 agent->var[index]
610 agent->var[index] = newvalue
614 VTOS (string) value (decimal)
615 %status maybe
617 Returns a string representation of the given value.
619 void caosVM::v_VTOS() {
620 VM_VERIFY_SIZE(1)
621 VM_PARAM_DECIMAL(value)
623 if (value.hasInt()) {
624 result.setString(boost::str(boost::format("%i") % value.getInt()));
625 } else {
626 // TODO: this format isn't right (see OUTS also)
627 result.setString(boost::str(boost::format("%f") % value.getFloat()));
632 CHAR (integer) str (string) index (integer)
633 %status maybe
635 Returns the character at position 'index' of the given string.
636 Indexes start at 1.
638 void caosVM::v_CHAR() {
639 VM_VERIFY_SIZE(2)
640 VM_PARAM_INTEGER(index)
641 VM_PARAM_STRING(str)
643 caos_assert(index >= 1);
644 caos_assert(str.size() >= (unsigned int)index);
646 result.setInt(str[index - 1]);
650 CHAR (command) string (variable) index (integer) character (integer)
651 %status maybe
653 Sets the character at position 'index' of the given string.
654 Indexes start at 1.
656 void caosVM::c_CHAR() {
657 VM_PARAM_INTEGER(character)
658 VM_PARAM_INTEGER(index)
659 VM_PARAM_VARIABLE(str)
661 caos_assert(0 <= character && character <= 255);
663 caos_assert(str->hasString());
664 std::string mystr = str->getString();
665 caos_assert(index >= 1);
666 caos_assert(mystr.size() >= (unsigned int)index);
668 mystr[index - 1] = (unsigned char)character;
669 str->setString(mystr);
673 ITOF (float) number (integer)
674 %status maybe
676 Converts the given integer to a float.
678 void caosVM::v_ITOF() {
679 VM_PARAM_FLOAT(number) // watson tells me this function is COMPLETELY pointless - fuzzie
681 result.setFloat(number);
685 FTOI (integer) number (float)
686 %status maybe
688 Converts the given float to an integer, by rounding.
690 void caosVM::v_FTOI() {
691 VM_PARAM_INTEGER(number)
693 result.setInt(number);
697 STRL (integer) string (string)
698 %status maybe
700 Returns the length in characters of the given string.
702 void caosVM::v_STRL() {
703 VM_PARAM_STRING(string)
705 result.setInt(string.size());
709 READ (string) tag (string) offset (integer)
710 %status maybe
712 Returns the value of the string at 'offset' inside the given catalogue tag.
713 Offsets start at zero. Throws an error if tag doesn't exist.
715 void caosVM::v_READ() {
716 VM_PARAM_INTEGER(offset)
717 VM_PARAM_STRING(tag)
719 // TODO: i'm not sure if we're meant to throw errors here. - fuzzie
720 caos_assert(catalogue.hasTag(tag));
721 const std::vector<std::string> &t = catalogue.getTag(tag);
722 caos_assert(offset >= 0);
723 caos_assert((unsigned int)offset < t.size());
724 result.setString(t[offset]);
728 REAQ (integer) tag (string)
729 %status maybe
731 Returns 1 if the specified catalogue tag exists, or 0 otherwise.
733 void caosVM::v_REAQ() {
734 VM_PARAM_STRING(tag)
736 if (catalogue.hasTag(tag))
737 result.setInt(1);
738 else
739 result.setInt(0);
743 CATA (integer)
744 %status maybe
746 Returns the agent category of the TARG agent.
748 void caosVM::v_CATA() {
749 valid_agent(targ);
751 result.setInt(targ->category);
755 CATI (integer) family (integer) genus (integer) species (integer)
756 %status maybe
758 Returns the agent category for the given family/genus/species.
760 void caosVM::v_CATI() {
761 VM_PARAM_INTEGER(species)
762 VM_PARAM_INTEGER(genus)
763 VM_PARAM_INTEGER(family) // TODO: check values are in range
765 result.setInt(world.findCategory(family, genus, species));
769 CATX (string) category_id (integer)
770 %status maybe
772 Returns a string containing the name of the given category.
774 void caosVM::v_CATX() {
775 VM_PARAM_INTEGER(category_id)
777 caos_assert(catalogue.hasTag("Agent Categories"));
778 const std::vector<std::string> &t = catalogue.getTag("Agent Categories");
779 if (category_id >= 0 && (unsigned int)category_id < t.size())
780 result.setString(t[category_id]);
781 else
782 result.setString("");
787 CATO (command) category_id (integer)
788 %status maybe
790 void caosVM::c_CATO() {
791 VM_PARAM_INTEGER(category_id)
793 valid_agent(targ);
794 targ->category = category_id;
798 WILD (string) family (integer) genus (integer) species (integer) tag (string) offset (integer)
799 %status maybe
801 Searches for a catalogue tag starting with 'tag' and matching the given
802 family/genus/species. For instance, 'Agent Help 2 3 4' where family is 2,
803 genus is 3 and species is 4. If it doesn't find it, it sets the minor value
804 to 0 repeatedly until it either finds one, or discovers 'tag 0 0 0' doesn't
805 exist, at which point an error is thrown. If it does find a suitable one, it
806 returns the string at offset inside the tag. See READ.
808 void caosVM::v_WILD() {
809 VM_PARAM_INTEGER(offset)
810 VM_PARAM_STRING(tag)
811 VM_PARAM_INTEGER(species)
812 VM_PARAM_INTEGER(genus)
813 VM_PARAM_INTEGER(family)
815 std::string searchstring = catalogue.calculateWildcardTag(tag, family, genus, species); // calculate tag name
816 caos_assert(searchstring.size()); // check we found a tag
818 const std::vector<std::string> &t = catalogue.getTag(searchstring); // retrieve tag
819 caos_assert(offset >= 0);
820 caos_assert((unsigned int)offset < t.size()); // check the offset is useful for the tag we found
822 result.setString(t[offset]);
826 NAME (variable) name (anything)
827 %status maybe
829 Named, agent-local variables (like OVxx) in the TARG agent.
831 CAOS_LVALUE_TARG(NAME, VM_PARAM_VALUE(name),
832 targ->name_variables[name],
833 targ->name_variables[name] = newvalue
837 MAME (variable) name (anything)
838 %status maybe
840 Like NAME variables, except for OWNR rather than TARG.
842 CAOS_LVALUE_WITH(MAME, owner,
843 VM_PARAM_VALUE(name),
844 owner->name_variables[name],
845 owner->name_variables[name] = newvalue
849 SUBS (string) value (string) start (integer) count (integer)
850 %status maybe
852 Returns the text in a string starting at 'start' into the string (starting at 1), and with 'count' characters.
854 void caosVM::v_SUBS() {
855 VM_PARAM_INTEGER(count)
856 VM_PARAM_INTEGER(start)
857 VM_PARAM_STRING(value)
859 result.setString(value.substr(start - 1, count)); // TODO: check start/count are valid?
863 STOI (integer) string (string)
864 %status maybe
866 Returns the provided string as an integer, or 0 if it can't be converted.
868 void caosVM::v_STOI() {
869 VM_PARAM_STRING(string)
871 result.setInt(atoi(string.c_str()));
875 STOF (float) string (string)
876 %status maybe
878 Returns the provided string as a float, or 0 if it can't be converted.
880 void caosVM::v_STOF() {
881 VM_PARAM_STRING(string)
883 result.setFloat(atof(string.c_str()));
887 LOWA (string) string (string)
888 %status maybe
890 Return a lower-cased version of a string.
892 void caosVM::v_LOWA() {
893 VM_PARAM_STRING(string)
895 std::transform(string.begin(), string.end(), string.begin(), (int(*)(int))tolower);
896 result.setString(string);
900 UPPA (string) string (string)
901 %status maybe
903 Return an upper-cased version of a string.
905 void caosVM::v_UPPA() {
906 VM_PARAM_STRING(string)
908 std::transform(string.begin(), string.end(), string.begin(), (int(*)(int))toupper);
909 result.setString(string);
913 SINS (integer) string (string) index (integer) searchstring (string)
914 %status maybe
916 Searches for an occurance of 'searchstring' inside 'string', starting at the given index inside 'string' (first character is 1).
917 The index of the 'searchstring' inside the string is returned, or -1 if the searchstring wasn't found.
919 void caosVM::v_SINS() {
920 VM_PARAM_STRING(searchstring)
921 VM_PARAM_INTEGER(index) caos_assert(index > 0);
922 VM_PARAM_STRING(string)
924 // TODO: check for string having a size, perhaps?
925 std::string::size_type i = string.find(searchstring, index - 1);
927 if (i == string.npos)
928 result.setInt(-1);
929 else
930 result.setInt(i + 1);
934 REAN (integer) tag (string)
935 %status maybe
937 Return number of strings associated with the catalogue tag specified.
939 void caosVM::v_REAN() {
940 VM_PARAM_STRING(tag)
942 if (!catalogue.hasTag(tag))
943 result.setInt(0);
944 else {
945 const std::vector<std::string> &t = catalogue.getTag(tag);
946 result.setInt(t.size());
951 DELN (command) name (anything)
952 %status maybe
954 Delete the specified NAME variable on the target agent.
956 void caosVM::c_DELN() {
957 VM_PARAM_VALUE(name)
959 valid_agent(targ);
960 std::map<caosVar, caosVar, caosVarCompare>::iterator i = targ->name_variables.find(name);
961 if (i == targ->name_variables.end()) return;
962 targ->name_variables.erase(i);
966 GAMN (string) previous (string)
967 %status maybe
969 void caosVM::v_GAMN() {
970 VM_PARAM_STRING(previous)
972 // TODO: we assume that GAME variables don't have an empty string
973 if (previous.empty()) {
974 if (world.variables.size() == 0)
975 result.setString("");
976 else
977 result.setString(world.variables.begin()->first);
978 } else {
979 std::map<std::string, caosVar>::iterator i = world.variables.find(previous);
980 caos_assert(i != world.variables.end()); // TODO: this probably isn't correct behaviour
981 i++;
982 if (i == world.variables.end())
983 result.setString("");
984 else
985 result.setString(i->first);
990 NAMN (command) previous (variable)
991 %status maybe
993 void caosVM::c_NAMN() {
994 VM_PARAM_VARIABLE(previous)
996 valid_agent(targ);
997 // TODO: we assume that NAME variables don't have an empty string
998 if (previous->hasString() && previous->getString().empty()) {
999 if (targ->name_variables.size() == 0)
1000 previous->setString("");
1001 else
1002 *previous = targ->name_variables.begin()->first;
1003 } else {
1004 std::map<caosVar, caosVar, caosVarCompare>::iterator i = targ->name_variables.find(*previous);
1005 caos_assert(i != targ->name_variables.end()); // TODO: this probably isn't correct behaviour
1006 i++;
1007 if (i == targ->name_variables.end())
1008 previous->setString("");
1009 else
1010 *previous = i->first;
1015 * POWV (command) value (variable) exponent (decimal)
1016 * %status maybe
1018 * Raises value to the exponent power, and saves the result back in value.
1019 * Results are undefined if value is negative.
1021 * Openc2e-only command
1024 void caosVM::c_POWV() {
1025 VM_PARAM_FLOAT(exponent)
1026 VM_PARAM_VARIABLE(value)
1028 value->setFloat(powf(value->getFloat(), exponent));
1032 RNDV (command) var (variable) value1 (integer) value (integer)
1033 %status maybe
1034 %pragma variants c1 c2
1035 %cost c1,c2 0
1037 void caosVM::c_RNDV() {
1038 VM_PARAM_INTEGER(value2)
1039 VM_PARAM_INTEGER(value1)
1040 VM_PARAM_VARIABLE(var)
1042 var->setInt(calculateRand(value1, value2));
1046 EGGL (integer)
1047 %status stub
1048 %pragma variants c2
1050 Returns the egg limit - when there are more than this many norns in the world, eggs should not hatch.
1052 void caosVM::v_EGGL() {
1053 result.setInt(16); // TODO
1057 HATL (integer)
1058 %status stub
1059 %pragma variants c2
1061 Returns the hatchery limit - when there are more than this many norns in the world, the hatchery should shut down.
1063 void caosVM::v_HATL() {
1064 result.setInt(12); // TODO
1067 /* vim: set noet: */