diff --git a/source/tools/rmgen/api.cpp b/source/tools/rmgen/api.cpp
new file mode 100644
index 0000000000..9daeba8127
--- /dev/null
+++ b/source/tools/rmgen/api.cpp
@@ -0,0 +1,197 @@
+#include "stdafx.h"
+#include "api.h"
+#include "rmgen.h"
+#include "map.h"
+#include "random.h"
+
+using namespace std;
+
+// Function specs
+
+JSFunctionSpec globalFunctions[] = {
+// {name, native, args}
+ {"init", init, 3},
+ {"print", print, 1},
+ {"error", error, 1},
+ {"getTerrain", getTerrain, 2},
+ {"setTerrain", setTerrain, 3},
+ {"getHeight", getHeight, 2},
+ {"setHeight", setHeight, 3},
+ {"randInt", randInt, 1},
+ {"randFloat", randFloat, 0},
+ {0}
+};
+
+// JS API implementation
+
+JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 1) {
+ JS_ReportError(cx, "print: expected 1 argument but got %d", argc);
+ }
+
+ cout << JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+ return JS_TRUE;
+}
+
+JSBool error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 1) {
+ // wow, you made an error calling the error() function!
+ JS_ReportError(cx, "error: expected 1 argument but got %d", argc);
+ }
+
+ JS_ReportError(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
+ return JS_TRUE;
+}
+
+JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 3) {
+ JS_ReportError(cx, "init: expected 3 arguments but got %d", argc);
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "init: first argument must be an integer");
+ }
+ if(!JSVAL_IS_STRING(argv[1])) {
+ JS_ReportError(cx, "init: second argument must be a string");
+ }
+ if(!JSVAL_IS_NUMBER(argv[2])) {
+ JS_ReportError(cx, "init: third argument must be a number");
+ }
+ if(theMap != 0) {
+ JS_ReportError(cx, "init: cannot be called twice");
+ }
+
+ int size = JSVAL_TO_INT(argv[0]);
+ char* baseTerrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]));
+ jsdouble baseHeight;
+ JS_ValueToNumber(cx, argv[2], &baseHeight);
+
+ theMap = new Map(size, baseTerrain, (float) baseHeight);
+ return JS_TRUE;
+}
+
+JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 2) {
+ JS_ReportError(cx, "getTerrain: expected 2 arguments but got %d", argc);
+ }
+ if(theMap == 0) {
+ JS_ReportError(cx, "getTerrain: cannot be called before init()");
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "getTerrain: first argument must be an integer");
+ }
+ if(!JSVAL_IS_INT(argv[1])) {
+ JS_ReportError(cx, "getTerrain: second argument must be an integer");
+ }
+
+ int x = JSVAL_TO_INT(argv[0]);
+ int y = JSVAL_TO_INT(argv[1]);
+ string terrain = theMap->getTerrain(x, y);
+ *rval = NewJSString(terrain);
+ return JS_TRUE;
+}
+
+JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 3) {
+ JS_ReportError(cx, "setTerrain: expected 3 arguments but got %d", argc);
+ }
+ if(theMap == 0) {
+ JS_ReportError(cx, "setTerrain: cannot be called before init()");
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "setTerrain: first argument must be an integer");
+ }
+ if(!JSVAL_IS_INT(argv[1])) {
+ JS_ReportError(cx, "setTerrain: second argument must be an integer");
+ }
+ if(!JSVAL_IS_STRING(argv[2])) {
+ JS_ReportError(cx, "setTerrain: third argument must be a string");
+ }
+
+ int x = JSVAL_TO_INT(argv[0]);
+ int y = JSVAL_TO_INT(argv[1]);
+ char* terrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[2]));
+ theMap->setTerrain(x, y, terrain);
+ return JS_TRUE;
+}
+
+JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 2) {
+ JS_ReportError(cx, "getHeight: expected 2 arguments but got %d", argc);
+ }
+ if(theMap == 0) {
+ JS_ReportError(cx, "getHeight: cannot be called before init()");
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "getHeight: first argument must be an integer");
+ }
+ if(!JSVAL_IS_INT(argv[1])) {
+ JS_ReportError(cx, "getHeight: second argument must be an integer");
+ }
+
+ int x = JSVAL_TO_INT(argv[0]);
+ int y = JSVAL_TO_INT(argv[1]);
+ jsdouble height = theMap->getHeight(x, y);
+ JS_NewDoubleValue(cx, height, rval);
+ return JS_TRUE;
+}
+
+JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 3) {
+ JS_ReportError(cx, "setHeight: expected 3 arguments but got %d", argc);
+ }
+ if(theMap == 0) {
+ JS_ReportError(cx, "setHeight: cannot be called before init()");
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "setHeight: first argument must be an integer");
+ }
+ if(!JSVAL_IS_INT(argv[1])) {
+ JS_ReportError(cx, "setHeight: second argument must be an integer");
+ }
+ if(!JSVAL_IS_NUMBER(argv[2])) {
+ JS_ReportError(cx, "setHeight: third argument must be a number");
+ }
+
+ int x = JSVAL_TO_INT(argv[0]);
+ int y = JSVAL_TO_INT(argv[1]);
+ jsdouble height;
+ JS_ValueToNumber(cx, argv[2], &height);
+ theMap->setHeight(x, y, (float) height);
+ return JS_TRUE;
+}
+
+JSBool randInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 1) {
+ JS_ReportError(cx, "randInt: expected 1 argument but got %d", argc);
+ }
+ if(!JSVAL_IS_INT(argv[0])) {
+ JS_ReportError(cx, "randInt: first argument must be an integer");
+ }
+
+ int x = JSVAL_TO_INT(argv[0]);
+ if(x<=0) {
+ JS_ReportError(cx, "randInt: argument must be positive");
+ }
+ int r = RandInt(x);
+ *rval = INT_TO_JSVAL(r);
+ return JS_TRUE;
+}
+
+JSBool randFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if(argc != 0) {
+ JS_ReportError(cx, "randFloat: expected 0 arguments but got %d", argc);
+ }
+
+ jsdouble r = RandFloat();
+ JS_NewDoubleValue(cx, r, rval);
+ return JS_TRUE;
+}
\ No newline at end of file
diff --git a/source/tools/rmgen/api.h b/source/tools/rmgen/api.h
new file mode 100644
index 0000000000..372c9fe36f
--- /dev/null
+++ b/source/tools/rmgen/api.h
@@ -0,0 +1,23 @@
+#ifndef __API_H__
+#define __API_H__
+
+// Function specs
+extern JSFunctionSpec globalFunctions[];
+
+// JS API implementation
+
+JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool randInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+JSBool randFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+#endif
\ No newline at end of file
diff --git a/source/tools/rmgen/library.js b/source/tools/rmgen/library.js
new file mode 100644
index 0000000000..456eba6a7d
--- /dev/null
+++ b/source/tools/rmgen/library.js
@@ -0,0 +1,12 @@
+function println(x) {
+ print(x);
+ print("\n");
+}
+
+function chooseRand() {
+ if(arguments.length==0) {
+ error("chooseRand: requires at least 1 argument");
+ }
+ var ar = (arguments.length==1 ? arguments[0] : arguments);
+ return ar[randInt(ar.length)];
+}
\ No newline at end of file
diff --git a/source/tools/rmgen/map.cpp b/source/tools/rmgen/map.cpp
index 0a17436c86..0dea925730 100644
--- a/source/tools/rmgen/map.cpp
+++ b/source/tools/rmgen/map.cpp
@@ -67,20 +67,20 @@ bool Map::validH(int x, int y) {
string Map::getTerrain(int x, int y) {
if(!validT(x,y)) JS_ReportError(cx, "getTerrain: invalid tile position");
- else return idToName[terrain[x][y]];
+ return idToName[terrain[x][y]];
}
void Map::setTerrain(int x, int y, const string& t) {
if(!validT(x,y)) JS_ReportError(cx, "setTerrain: invalid tile position");
- else terrain[x][y] = getId(t);
+ terrain[x][y] = getId(t);
}
float Map::getHeight(int x, int y) {
if(!validH(x,y)) JS_ReportError(cx, "getHeight: invalid point position");
- else return height[x][y];
+ return height[x][y];
}
void Map::setHeight(int x, int y, float h) {
if(!validH(x,y)) JS_ReportError(cx, "setHeight: invalid point position");
- else height[x][y] = h;
+ height[x][y] = h;
}
\ No newline at end of file
diff --git a/source/tools/rmgen/output.cpp b/source/tools/rmgen/output.cpp
index ba5886bfc0..3006fb321b 100644
--- a/source/tools/rmgen/output.cpp
+++ b/source/tools/rmgen/output.cpp
@@ -8,7 +8,6 @@ using namespace std;
typedef unsigned short u16;
typedef unsigned int u32;
-
void OutputXml(Map* m, FILE* f) {
const char* xml = "\
\n\
@@ -24,6 +23,16 @@ void OutputXml(Map* m, FILE* f) {
\n\
\n\
\n";
+
+ /*
+
+ hele_hc
+ 0
+
+
+
+ */
+
fprintf(f, "%s", xml);
}
diff --git a/source/tools/rmgen/random.cpp b/source/tools/rmgen/random.cpp
new file mode 100644
index 0000000000..681380ce5f
--- /dev/null
+++ b/source/tools/rmgen/random.cpp
@@ -0,0 +1,20 @@
+#include "stdafx.h"
+#include "random.h"
+
+using namespace boost;
+
+mt19937 rng;
+
+void SeedRand(unsigned long s) {
+ rng.seed(s);
+}
+
+int RandInt(int maxVal) {
+ return rng()%maxVal;
+}
+
+float RandFloat() {
+ return float(rng()) * (1.0f/4294967296.0f);
+}
+
+
diff --git a/source/tools/rmgen/random.h b/source/tools/rmgen/random.h
new file mode 100644
index 0000000000..17cbb20bbd
--- /dev/null
+++ b/source/tools/rmgen/random.h
@@ -0,0 +1,3 @@
+void SeedRand(unsigned long seed);
+int RandInt(int maxVal);
+float RandFloat(); // in range [0,1)
diff --git a/source/tools/rmgen/rmgen.cpp b/source/tools/rmgen/rmgen.cpp
index 601cf0ff54..7e574b1c45 100644
--- a/source/tools/rmgen/rmgen.cpp
+++ b/source/tools/rmgen/rmgen.cpp
@@ -2,9 +2,13 @@
#include "rmgen.h"
#include "map.h"
#include "output.h"
+#include "api.h"
+#include "random.h"
using namespace std;
+const char* LIBRARY_FILE = "library.js";
+
JSRuntime *rt = 0;
JSContext *cx = 0;
JSObject *global = 0;
@@ -19,17 +23,6 @@ void ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) {
Shutdown(1);
}
-JSFunctionSpec globalFunctions[] = {
-// {name, native, args}
- {"init", init, 3},
- {"print", print, 1},
- {"getTerrain", getTerrain, 2},
- {"setTerrain", setTerrain, 3},
- {"getHeight", getHeight, 2},
- {"setHeight", setHeight, 3},
- {0}
-};
-
void InitJS() {
rt = JS_NewRuntime(8L * 1024L * 1024L);
cx = JS_NewContext(rt, 8192);
@@ -65,165 +58,59 @@ jsval NewJSString(const string& str) {
return STRING_TO_JSVAL(JS_NewString(cx, buf, str.length()));
}
-// JS API implementation
-
-JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 1) {
- JS_ReportError(cx, "print: expected 1 argument but got %d", argc);
+void ExecuteFile(const char* fileName) {
+ FILE* f = fopen(fileName, "r");
+ if(!f) {
+ cerr << "Cannot open " << fileName << endl;
+ Shutdown(1);
}
- cout << JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
- return JS_TRUE;
+ string code;
+ char buf[1025];
+ while(fgets(buf, 1024, f)) {
+ code += buf;
+ }
+
+ jsval rval;
+ JSBool ok = JS_EvaluateScript(cx, global, code.c_str(), code.length(), fileName, 1, &rval);
+ if(!ok) Shutdown(1);
}
-JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 3) {
- JS_ReportError(cx, "init: expected 3 arguments but got %d", argc);
- }
- if(!JSVAL_IS_INT(argv[0])) {
- JS_ReportError(cx, "init: first argument must be an integer");
- }
- if(!JSVAL_IS_STRING(argv[1])) {
- JS_ReportError(cx, "init: second argument must be a string");
- }
- if(!JSVAL_IS_NUMBER(argv[2])) {
- JS_ReportError(cx, "init: third argument must be a number");
- }
- if(theMap != 0) {
- JS_ReportError(cx, "init: cannot be called twice");
- }
-
- int size = JSVAL_TO_INT(argv[0]);
- char* baseTerrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]));
- jsdouble baseHeight;
- JS_ValueToNumber(cx, argv[2], &baseHeight);
-
- theMap = new Map(size, baseTerrain, (float) baseHeight);
- return JS_TRUE;
-}
-
-JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 2) {
- JS_ReportError(cx, "getTerrain: expected 2 arguments but got %d", argc);
- }
- if(theMap == 0) {
- JS_ReportError(cx, "getTerrain: cannot be called before init()");
- }
- if(!JSVAL_IS_INT(argv[0])) {
- JS_ReportError(cx, "getTerrain: first argument must be an integer");
- }
- if(!JSVAL_IS_INT(argv[1])) {
- JS_ReportError(cx, "getTerrain: second argument must be an integer");
- }
-
- int x = JSVAL_TO_INT(argv[0]);
- int y = JSVAL_TO_INT(argv[1]);
- string terrain = theMap->getTerrain(x, y);
- *rval = NewJSString(terrain);
- return JS_TRUE;
-}
-
-JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 3) {
- JS_ReportError(cx, "setTerrain: expected 3 arguments but got %d", argc);
- }
- if(theMap == 0) {
- JS_ReportError(cx, "setTerrain: cannot be called before init()");
- }
- if(!JSVAL_IS_INT(argv[0])) {
- JS_ReportError(cx, "setTerrain: first argument must be an integer");
- }
- if(!JSVAL_IS_INT(argv[1])) {
- JS_ReportError(cx, "setTerrain: second argument must be an integer");
- }
- if(!JSVAL_IS_STRING(argv[2])) {
- JS_ReportError(cx, "setTerrain: third argument must be a string");
- }
-
- int x = JSVAL_TO_INT(argv[0]);
- int y = JSVAL_TO_INT(argv[1]);
- char* terrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[2]));
- theMap->setTerrain(x, y, terrain);
- return JS_TRUE;
-}
-
-JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 2) {
- JS_ReportError(cx, "getHeight: expected 2 arguments but got %d", argc);
- }
- if(theMap == 0) {
- JS_ReportError(cx, "getHeight: cannot be called before init()");
- }
- if(!JSVAL_IS_INT(argv[0])) {
- JS_ReportError(cx, "getHeight: first argument must be an integer");
- }
- if(!JSVAL_IS_INT(argv[1])) {
- JS_ReportError(cx, "getHeight: second argument must be an integer");
- }
-
- int x = JSVAL_TO_INT(argv[0]);
- int y = JSVAL_TO_INT(argv[1]);
- jsdouble height = theMap->getHeight(x, y);
- JS_NewDoubleValue(cx, height, rval);
- return JS_TRUE;
-}
-
-JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
- if(argc != 3) {
- JS_ReportError(cx, "setHeight: expected 3 arguments but got %d", argc);
- }
- if(theMap == 0) {
- JS_ReportError(cx, "setHeight: cannot be called before init()");
- }
- if(!JSVAL_IS_INT(argv[0])) {
- JS_ReportError(cx, "setHeight: first argument must be an integer");
- }
- if(!JSVAL_IS_INT(argv[1])) {
- JS_ReportError(cx, "setHeight: second argument must be an integer");
- }
- if(!JSVAL_IS_NUMBER(argv[2])) {
- JS_ReportError(cx, "setHeight: third argument must be a number");
- }
-
- int x = JSVAL_TO_INT(argv[0]);
- int y = JSVAL_TO_INT(argv[1]);
- jsdouble height;
- JS_ValueToNumber(cx, argv[2], &height);
- theMap->setHeight(x, y, (float) height);
- return JS_TRUE;
-}
// Program entry point
int main(int argc, char* argv[])
{
InitJS();
- if(argc!=3) {
- cerr << "Usage: rmgen