Xonotic
rpn.qc
Go to the documentation of this file.
1 #include "rpn.qh"
2 
4 
5 
6 // ========================================
7 // RPN command code, written by divVerent
8 // Last updated: December 28th, 2011
9 // ========================================
10 
11 string rpn_pop()
12 {
13  if(rpn_sp > 0) {
14  --rpn_sp;
15  return rpn_stack[rpn_sp];
16  } else {
17  LOG_INFO("rpn: stack underflow");
18  rpn_error = true;
19  return "";
20  }
21 }
22 void rpn_push(string s)
23 {
24  if(rpn_sp < MAX_RPN_STACK) {
25  rpn_stack[rpn_sp] = s;
26  ++rpn_sp;
27  } else {
28  LOG_INFO("rpn: stack overflow");
29  rpn_error = true;
30  }
31 }
32 string rpn_get()
33 {
34  if(rpn_sp > 0) {
35  return rpn_stack[rpn_sp - 1];
36  } else {
37  LOG_INFO("rpn: empty stack");
38  rpn_error = true;
39  return "";
40  }
41 }
42 void rpn_set(string s)
43 {
44  if(rpn_sp > 0) {
45  rpn_stack[rpn_sp - 1] = s;
46  } else {
47  LOG_INFO("rpn: empty stack");
48  rpn_error = true;
49  }
50 }
51 
52 float rpn_getf() { return stof(rpn_get()); }
53 float rpn_popf() { return stof(rpn_pop()); }
54 void rpn_pushf(float f) { return rpn_push(sprintf("%.9g", f)); }
55 void rpn_setf(float f) { return rpn_set(sprintf("%.9g", f)); }
56 
57 SHUTDOWN(_rpndb)
58 {
59  if(rpn_db)
61 }
62 
63 void GenericCommand_rpn(int request, int argc, string command)
64 {
65  switch(request)
66  {
68  {
69  float i, j, f, f2, f3, rpnpos;
70  //vector rgb;
71  string s, s2, rpncmd;
72 
73  if(!rpn_db)
74  {
75  rpn_db = db_create();
76  db_put(rpn_db, "stack.pointer", "0");
77  db_put(rpn_db, "stack.pos", "-1");
78  }
79 
80  if(argc >= 2)
81  {
82  rpn_sp = 0;
83  rpn_error = false;
84  for(rpnpos = 1; rpnpos < argc; ++rpnpos)
85  {
86  rpncmd = argv(rpnpos);
87  f = strlen(rpncmd);
88  if(rpncmd == "") {
89  } else if(stof(substring(rpncmd, 0, 1)) > 0) {
90  rpn_push(rpncmd);
91  } else if(substring(rpncmd, 0, 1) == "0") {
92  rpn_push(rpncmd);
93  } else if(f >= 2 && substring(rpncmd, 0, 1) == "+") {
94  rpn_push(rpncmd);
95  } else if(f >= 2 && substring(rpncmd, 0, 1) == "-") {
96  rpn_push(rpncmd);
97  } else if(f >= 2 && substring(rpncmd, 0, 1) == "/") {
98  rpn_push(substring(rpncmd, 1, strlen(rpncmd) - 1));
99  } else if(rpncmd == "clear") {
100  rpn_sp = 0;
101  } else if(rpncmd == "def" || rpncmd == "=") {
102  s = rpn_pop();
103  s2 = rpn_pop();
104 
105  if(s2 != "")
106  {
107  #ifdef MENUQC
108  registercvar(s2, "", 0);
109  #else
110  registercvar(s2, "");
111  #endif
112  if(!rpn_error) // don't change cvars if a stack error had happened!
113  cvar_set(s2, s);
114  }
115  else
116  {
117  LOG_INFO("rpn: empty cvar name for 'def'");
118  rpn_error = true;
119  }
120  } else if(rpncmd == "defs" || rpncmd == "@") {
121  s = "";
122  i = rpn_popf();
123  j = (i == 0);
124  while(rpn_sp > 1 && (j || i > 0))
125  {
126  s = strcat("/", rpn_pop(), " ", s);
127  --i;
128  }
129  s2 = rpn_pop();
130  if(s2 != "")
131  {
132  #ifdef MENUQC
133  registercvar(s2, "", 0);
134  #else
135  registercvar(s2, "");
136  #endif
137  if(!rpn_error) // don't change cvars if a stack error had happened!
138  cvar_set(s2, s);
139  }
140  else
141  {
142  LOG_INFO("rpn: empty cvar name for 'defs'");
143  rpn_error = true;
144  }
145  } else if(rpncmd == "load") {
147  } else if(rpncmd == "exch") {
148  s = rpn_pop();
149  s2 = rpn_get();
150  rpn_set(s);
151  rpn_push(s2);
152  } else if(rpncmd == "dup") {
153  rpn_push(rpn_get());
154  } else if(rpncmd == "pop") {
155  rpn_pop();
156  } else if(rpncmd == "add" || rpncmd == "+") {
157  f = rpn_popf();
158  rpn_setf(rpn_getf() + f);
159  } else if(rpncmd == "sub" || rpncmd == "-") {
160  f = rpn_popf();
161  rpn_setf(rpn_getf() - f);
162  } else if(rpncmd == "mul" || rpncmd == "*") {
163  f = rpn_popf();
164  rpn_setf(rpn_getf() * f);
165  } else if(rpncmd == "div" || rpncmd == "/") {
166  f = rpn_popf();
167  rpn_setf(rpn_getf() / f);
168  } else if(rpncmd == "mod" || rpncmd == "%") {
169  f = rpn_popf();
170  f2 = rpn_getf();
171  rpn_setf(f2 - f * floor(f2 / f));
172  } else if(rpncmd == "pow" || rpncmd == "**") {
173  f = rpn_popf();
174  rpn_setf(rpn_getf() ** f);
175  } else if(rpncmd == "bitand" || rpncmd == "&") {
176  f = rpn_popf();
177  rpn_setf(rpn_getf() & f);
178  } else if(rpncmd == "bitor" || rpncmd == "|") {
179  f = rpn_popf();
180  rpn_setf(rpn_getf() | f);
181  } else if(rpncmd == "bitxor" || rpncmd == "^") {
182  f = rpn_popf();
183  rpn_setf(rpn_getf() ^ f);
184  } else if(rpncmd == "and" || rpncmd == "&&") {
185  f = rpn_popf();
186  rpn_setf(rpn_getf() && f);
187  } else if(rpncmd == "or" || rpncmd == "||") {
188  f = rpn_popf();
189  rpn_setf(rpn_getf() || f);
190  } else if(rpncmd == "xor" || rpncmd == "^^") {
191  f = rpn_popf();
192  rpn_setf(!rpn_getf() != !f);
193  } else if(rpncmd == "bitnot") {
194  rpn_setf(~rpn_popf());
195  } else if(rpncmd == "not") {
196  rpn_setf(!rpn_popf());
197  } else if(rpncmd == "abs") {
198  rpn_setf(fabs(rpn_getf()));
199  } else if(rpncmd == "sgn") {
200  f = rpn_getf();
201  if(f < 0)
202  rpn_set("-1");
203  else if(f > 0)
204  rpn_set("1");
205  else
206  rpn_set("0");
207  } else if(rpncmd == "neg" || rpncmd == "~") {
208  rpn_setf(-rpn_getf());
209  } else if(rpncmd == "floor" || rpncmd == "f") {
210  rpn_setf(floor(rpn_getf()));
211  } else if(rpncmd == "ceil" || rpncmd == "c") {
212  rpn_setf(ceil(rpn_getf()));
213  } else if(rpncmd == "exp") {
214  rpn_setf(exp(rpn_getf()));
215  } else if(rpncmd == "log") {
216  rpn_setf(exp(rpn_getf()));
217  } else if(rpncmd == "sin") {
218  rpn_setf(sin(rpn_getf()));
219  } else if(rpncmd == "cos") {
220  rpn_setf(cos(rpn_getf()));
221  } else if(rpncmd == "max") {
222  f = rpn_popf();
223  f2 = rpn_getf();
224  rpn_setf(max(f2, f));
225  } else if(rpncmd == "min") {
226  f = rpn_popf();
227  f2 = rpn_getf();
228  rpn_setf(min(f2, f));
229  } else if(rpncmd == "bound") {
230  f = rpn_popf();
231  f2 = rpn_popf();
232  f3 = rpn_getf();
233  rpn_setf(bound(f3, f2, f));
234  } else if(rpncmd == "when") {
235  f = rpn_popf();
236  s = rpn_pop();
237  s2 = rpn_get();
238  if(f)
239  rpn_set(s2);
240  else
241  rpn_set(s);
242  } else if(rpncmd == ">" || rpncmd == "gt") {
243  f = rpn_popf();
244  rpn_setf(rpn_getf() > f);
245  } else if(rpncmd == "<" || rpncmd == "lt") {
246  f = rpn_popf();
247  rpn_setf(rpn_getf() < f);
248  } else if(rpncmd == "==" || rpncmd == "eq") {
249  f = rpn_popf();
250  rpn_setf(rpn_getf() == f);
251  } else if(rpncmd == ">=" || rpncmd == "ge") {
252  f = rpn_popf();
253  rpn_setf(rpn_getf() >= f);
254  } else if(rpncmd == "<=" || rpncmd == "le") {
255  f = rpn_popf();
256  rpn_setf(rpn_getf() <= f);
257  } else if(rpncmd == "!=" || rpncmd == "ne") {
258  f = rpn_popf();
259  rpn_setf(rpn_getf() != f);
260  } else if(rpncmd == "rand") {
261  rpn_setf(ceil(random() * rpn_getf()) - 1);
262  } else if(rpncmd == "crc16") {
263  rpn_setf(crc16(false, rpn_get()));
264  } else if(rpncmd == "put") {
265  s2 = rpn_pop();
266  if (!rpn_error)
267  {
268  s = rpn_pop();
269  if (!rpn_error)
270  db_put(rpn_db, s, s2);
271  }
272  } else if(rpncmd == "get") {
273  s = rpn_pop();
274  if (!rpn_error)
275  rpn_push(db_get(rpn_db, s));
276  } else if(rpncmd == "dbpush") {
277  s = rpn_pop();
278  if(!rpn_error)
279  {
280  i = stof(db_get(rpn_db, "stack.pointer"));
281  db_put(rpn_db, "stack.pointer", ftos(i+1));
282  db_put(rpn_db, strcat("stack.", ftos(i)), s);
283  if(!i)
284  db_put(rpn_db, "stack.pos", "0");
285  }
286  } else if(rpncmd == "dbpop") {
287  i = stof(db_get(rpn_db, "stack.pointer"));
288  if(i)
289  {
290  s = ftos(i-1);
291  db_put(rpn_db, "stack.pointer", s);
292  rpn_push(db_get(rpn_db, strcat("stack.", s)));
293  j = stof(db_get(rpn_db, "stack.pos"));
294  if(j >= i)
295  db_put(rpn_db, "stack.pos", ftos(i-2));
296  } else {
297  rpn_error = 1;
298  LOG_INFO("rpn: database underflow");
299  }
300  } else if(rpncmd == "dbget") {
301 
302  i = stof(db_get(rpn_db, "stack.pointer"));
303  if(i)
304  {
305  rpn_push(db_get(rpn_db, strcat("stack.", ftos(i-1))));
306  } else {
307  rpn_error = 1;
308  LOG_INFO("rpn: database empty");
309  }
310  } else if(rpncmd == "dblen") {
311  rpn_push(db_get(rpn_db, "stack.pointer"));
312  } else if(rpncmd == "dbclr") {
313  db_close(rpn_db);
314  rpn_db = db_create();
315  db_put(rpn_db, "stack.pointer", "0");
316  db_put(rpn_db, "stack.pos", "-1");
317  } else if(rpncmd == "dbsave") {
318  s = rpn_pop();
319  if(!rpn_error)
320  db_save(rpn_db, s);
321  } else if(rpncmd == "dbload") {
322  s = rpn_pop();
323  if(!rpn_error)
324  {
325  db_close(rpn_db);
326  rpn_db = db_load(s);
327  }
328  } else if(rpncmd == "dbins") {
329  s = rpn_pop();
330  if(!rpn_error)
331  //if(rpn_sp > 0)
332  {
333  j = stof(db_get(rpn_db, "stack.pointer"));
334  i = stof(db_get(rpn_db, "stack.pos"));
335 
336  if(i < 0)
337  {
338  i = 0;
339  db_put(rpn_db, "stack.pos", "0");
340  }
341 
342  db_put(rpn_db, "stack.pointer", ftos(j+1));
343  for(--j; j >= i; --j)
344  {
345  db_put(rpn_db, strcat("stack.", ftos(j+1)),
346  db_get(rpn_db, (strcat("stack.", ftos(j))))
347  );
348  }
349  db_put(rpn_db, strcat("stack.", ftos(i)), s);
350  }
351  } else if(rpncmd == "dbext") {
352  j = stof(db_get(rpn_db, "stack.pointer"));
353  i = stof(db_get(rpn_db, "stack.pos"));
354  if(!j)
355  {
356  rpn_error = true;
357  LOG_INFO("rpn: empty database");
358  } else {
359  --j;
360  rpn_push(db_get(rpn_db, strcat("stack.", ftos(i))));
361  db_put(rpn_db, "stack.pointer", ftos(j));
362  if(i == j)
363  {
364  db_put(rpn_db, "stack.pos", ftos(j-1));
365  } else {
366  while(i < j)
367  {
368  db_put(rpn_db, strcat("stack.", ftos(i)),
369  db_get(rpn_db, (strcat("stack.", ftos(i+1))))
370  );
371  ++i;
372  }
373  }
374  }
375  } else if(rpncmd == "dbread") {
376  s = db_get(rpn_db, "stack.pos");
377  if(stof(s) >= 0)
378  {
379  rpn_push(db_get(rpn_db, strcat("stack.", s)));
380  } else {
381  rpn_error = 1;
382  LOG_INFO("rpn: empty database");
383  }
384  } else if(rpncmd == "dbat") {
385  rpn_push(db_get(rpn_db, "stack.pos"));
386  } else if(rpncmd == "dbmov") {
387  j = stof(db_get(rpn_db, "stack.pointer"));
388  i = stof(db_get(rpn_db, "stack.pos"));
389  i += rpn_popf();
390  if(!rpn_error)
391  {
392  if(i < 0 || i >= j)
393  {
394  LOG_INFO("rpn: database cursor out of bounds");
395  rpn_error = true;
396  }
397  if(!rpn_error)
398  {
399  db_put(rpn_db, "stack.pos", ftos(i));
400  }
401  }
402  } else if(rpncmd == "dbgoto") {
403  s = rpn_pop();
404  j = stof(db_get(rpn_db, "stack.pointer"));
405  if(!j)
406  {
407  rpn_error = true;
408  LOG_INFO("rpn: empty database, cannot move cursor");
409  }
410  if(!rpn_error)
411  {
412  if(s == "end")
413  i = stof(db_get(rpn_db, "stack.pointer"))-1;
414  else if(s == "beg")
415  i = 0;
416  else
417  i = stof(s);
418 
419  j = stof(db_get(rpn_db, "stack.pointer"));
420  if(i < 0 || i >= j)
421  {
422  LOG_INFO("rpn: database cursor destination out of bounds");
423  rpn_error = true;
424  }
425  if(!rpn_error)
426  {
427  db_put(rpn_db, "stack.pos", ftos(i));
428  }
429  }
430  } else if(rpncmd == "union") {
431  // s s2 union
432  s2 = rpn_pop();
433  s = rpn_get();
434  f = tokenize_console(s);
435  f2 = tokenize_console(strcat(s, " ", s2));
436  // tokens 0..(f-1) represent s
437  // tokens f..f2 represent s2
438  // UNION: add all tokens to s that are in s2 but not in s
439  s = "";
440  for(i = 0; i < f; ++i)
441  s = strcat(s, " ", argv(i));
442  for(i = f; i < f2; ++i) {
443  for(j = 0; j < f; ++j)
444  if(argv(i) == argv(j))
445  goto skip_union;
446  s = strcat(s, " ", argv(i));
447 LABEL(skip_union)
448  }
449  if(substring(s, 0, 1) == " ")
450  s = substring(s, 1, 99999);
451  rpn_set(s);
452  tokenize_console(command);
453  } else if(rpncmd == "intersection") {
454  // s s2 intersection
455  s2 = rpn_pop();
456  s = rpn_get();
457  f = tokenize_console(s);
458  f2 = tokenize_console(strcat(s, " ", s2));
459  // tokens 0..(f-1) represent s
460  // tokens f..f2 represent s2
461  // INTERSECTION: keep only the tokens from s that are also in s2
462  s = "";
463  for(i = 0; i < f; ++i) {
464  for(j = f; j < f2; ++j)
465  if(argv(i) == argv(j))
466  {
467  s = strcat(s, " ", argv(i));
468  break;
469  }
470  }
471  if(substring(s, 0, 1) == " ")
472  s = substring(s, 1, 99999);
473  rpn_set(s);
474  tokenize_console(command);
475  } else if(rpncmd == "difference") {
476  // s s2 difference
477  s2 = rpn_pop();
478  s = rpn_get();
479  f = tokenize_console(s);
480  f2 = tokenize_console(strcat(s, " ", s2));
481  // tokens 0..(f-1) represent s
482  // tokens f..f2 represent s2
483  // DIFFERENCE: keep only the tokens from s that are not in s2
484  s = "";
485  for(i = 0; i < f; ++i) {
486  for(j = f; j < f2; ++j)
487  if(argv(i) == argv(j))
488  goto skip_difference;
489  s = strcat(s, " ", argv(i));
490 LABEL(skip_difference)
491  }
492  if(substring(s, 0, 1) == " ")
493  s = substring(s, 1, 99999);
494  rpn_set(s);
495  tokenize_console(command);
496  } else if(rpncmd == "shuffle") {
497  // s shuffle
498  s = rpn_get();
499  f = tokenize_console(s);
500 
501  for(i = 0; i < f - 1; ++i) {
502  // move a random item from i..f-1 to position i
503  s = "";
504  f2 = floor(random() * (f - i) + i);
505  for(j = 0; j < i; ++j)
506  s = strcat(s, " ", argv(j));
507  s = strcat(s, " ", argv(f2));
508  for(j = i; j < f; ++j)
509  if(j != f2)
510  s = strcat(s, " ", argv(j));
511  f = tokenize_console(s);
512  }
513 
514  if(substring(s, 0, 1) == " ")
515  s = substring(s, 1, 99999);
516  rpn_set(s);
517  tokenize_console(command);
518  } else if(rpncmd == "fexists_assert") {
519  s = rpn_pop();
520  if(!rpn_error)
521  {
522  if (!fexists(s))
523  {
524  LOG_INFO("rpn: ERROR: ", s, " does not exist!");
525  rpn_error = true;
526  }
527  }
528  } else if(rpncmd == "fexists") {
529  s = rpn_get();
530  if(!rpn_error)
531  {
532  if (fexists(s))
533  rpn_setf(1);
534  else
535  rpn_setf(0);
536  }
537  } else if(rpncmd == "localtime") {
538  rpn_set(strftime(true, rpn_get()));
539  } else if(rpncmd == "gmtime") {
540  rpn_set(strftime(false, rpn_get()));
541  } else if(rpncmd == "time") {
542  rpn_pushf(time);
543  } else if(rpncmd == "digest") {
544  s = rpn_pop();
545  rpn_set(digest_hex(s, rpn_get()));
546  } else if(rpncmd == "sprintf1s") {
547  s = rpn_pop();
548  rpn_set(sprintf(s, rpn_get()));
549  } else if(rpncmd == "eval") {
550  s = rpn_pop();
551  command = strcat(s, substring(command, argv_end_index(rpnpos), -1));
552  argc = tokenize_console(command);
553  rpnpos = -1;
554  } else {
555  rpn_push(cvar_string(rpncmd));
556  }
557  if(rpn_error)
558  break;
559  }
560  while(rpn_sp > 0)
561  {
562  s = rpn_pop();
563  LOG_INFO("rpn: still on stack: ", s);
564  }
565  }
566 
567  return;
568  }
569 
570  default:
571  case CMD_REQUEST_USAGE:
572  {
573  LOG_HELP("Usage:^3 ", GetProgramCommandPrefix(), " rpn <expression>");
574  LOG_HELP(" Operator description (x: string, s: set, f: float):");
575  LOG_HELP(" x pop -----------------------------> : removes the top");
576  LOG_HELP(" x dup -----------------------------> x x : duplicates the top");
577  LOG_HELP(" x x exch --------------------------> x x : swap the top two");
578  LOG_HELP(" /cvarname load --------------------> x : loads a cvar");
579  LOG_HELP(" /cvarname x def -------------------> : writes to a cvar");
580  LOG_HELP(" f f add|sub|mul|div|mod|pow -------> f : adds/... two numbers");
581  LOG_HELP(" f f and|or|xor|bitand|bitor|bitxor > f : logical and bitwise operations");
582  LOG_HELP(" f f eq|ne|gt|ge|lt|le|max|min -----> f : compares two numbers");
583  LOG_HELP(" f neg|abs|sgn|rand|floor|ceil------> f : negates/... a number");
584  LOG_HELP(" f not|bitnot ----------------------> f : logical and bitwise negation");
585  LOG_HELP(" f exp|log|sin|cos -----------------> f : exponential function & Co.");
586  LOG_HELP(" f f f bound -----------------------> f : bounds the middle number");
587  LOG_HELP(" f1 f2 b when ----------------------> f : f1 if b, f2 otherwise");
588  LOG_HELP(" s s union|intersection|difference -> s : set operations");
589  LOG_HELP(" s shuffle -------------------------> s : randomly arrange elements");
590  LOG_HELP(" /key /value put -------------------> : set a database key");
591  LOG_HELP(" /key get --------------------------> s : get a database value");
592  LOG_HELP(" x dbpush --------------------------> : pushes the top onto the database");
593  LOG_HELP(" dbpop|dbget -----------------------> x : removes/reads DB's top");
594  LOG_HELP(" dblen|dbat ------------------------> f : gets the DB's size/cursor pos");
595  LOG_HELP(" dbclr -----------------------------> : clear the DB");
596  LOG_HELP(" s dbsave|dbload--------------------> : save/load the DB to/from a file");
597  LOG_HELP(" x dbins ---------------------------> : moves the top into the DB");
598  LOG_HELP(" dbext|dbread ----------------------> x : extract/get from the DB's cursor");
599  LOG_HELP(" f dbmov|dbgoto --------------------> : move or set the DB's cursor");
600  LOG_HELP(" s localtime -----------------------> s : formats the current local time");
601  LOG_HELP(" s gmtime --------------------------> s : formats the current UTC time");
602  LOG_HELP(" time ------------------------------> f : seconds since VM start");
603  LOG_HELP(" s /MD4 digest ---------------------> s : MD4 digest");
604  LOG_HELP(" s /SHA256 digest ------------------> s : SHA256 digest");
605  LOG_HELP(" s /formatstring sprintf1s ---------> s : sprintf with 1 string (pad, cut)");
606  LOG_HELP(" s eval ----------------------------> : does something eval");
607  LOG_HELP(" Set operations operate on 'such''strings'.");
608  LOG_HELP(" Unknown tokens insert their cvar value.");
609  return;
610  }
611  }
612 }
void GenericCommand_rpn(int request, int argc, string command)
Definition: rpn.qc:63
ERASEABLE int db_create()
Definition: map.qh:25
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
void rpn_pushf(float f)
Definition: rpn.qc:54
float rpn_getf()
Definition: rpn.qc:52
int rpn_db
Definition: rpn.qh:9
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1 f1points s1 s2
Definition: all.inc:438
ERASEABLE int db_load(string filename)
Definition: map.qh:35
const int CMD_REQUEST_USAGE
Definition: command.qh:4
SHUTDOWN(_rpndb)
Definition: rpn.qc:57
ERASEABLE void db_close(int db)
Definition: map.qh:84
int rpn_error
Definition: rpn.qh:10
#define LOG_HELP(...)
Definition: log.qh:95
void rpn_set(string s)
Definition: rpn.qc:42
float exp(float e)
Definition: mathlib.qc:73
#define argv_end_index
Definition: dpextensions.qh:30
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1 f1points f2
Definition: all.inc:348
string rpn_stack[MAX_RPN_STACK]
Definition: rpn.qh:12
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
ERASEABLE void db_save(int db, string filename)
Definition: map.qh:8
const int CMD_REQUEST_COMMAND
Definition: command.qh:3
#define LOG_INFO(...)
Definition: log.qh:70
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
float rpn_popf()
Definition: rpn.qc:53
#define tokenize_console
Definition: dpextensions.qh:24
void rpn_setf(float f)
Definition: rpn.qc:55
int rpn_sp
Definition: rpn.qh:11
string rpn_pop()
Definition: rpn.qc:11
string rpn_get()
Definition: rpn.qc:32
#define LABEL(id)
Definition: compiler.qh:36
void rpn_push(string s)
Definition: rpn.qc:22
float time
Definition: csprogsdefs.qc:16
ERASEABLE bool fexists(string f)
Definition: file.qh:4
const int MAX_RPN_STACK
Definition: rpn.qh:8