static int grid_jitter_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); if(top<2 || !lua_isnumber(L, 2)) return typerror(L, 2, "number"); grid *g = lua_touserdata(L, 1); double amount = lua_tonumber(L, 2); grid_jitter(g, amount); return 0; }
static int grid_set_offset_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) typerror(L, 1, "grid"); if(top<3) typerror(L, top+1, "number"); grid *g = lua_touserdata(L, 1); g->x0 = lua_tonumber(L, 2); g->y0 = lua_tonumber(L, 3); return 2; }
void *check_udata(lua_State *L, int idx, const char *mt) { void *p = lua_touserdata(L, idx); if (!p) typerror(L, idx, mt); if (!lua_getmetatable(L, idx)) typerror(L, idx, mt); lua_getfield(L, LUA_REGISTRYINDEX, mt); if (!lua_rawequal(L, -1, -2)) typerror(L, idx, mt); lua_pop(L, 2); return p; }
static int grid_contains_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); if(top<2 || !lua_isnumber(L, 2)) return typerror(L, 2, "number"); if(top<3 || !lua_isnumber(L, 3)) return typerror(L, 3, "number"); grid *g = lua_touserdata(L, 1); int x = lua_tointeger(L, 2); int y = lua_tointeger(L, 3); lua_pushboolean(L, grid_contains(g, x, y)); return 1; }
static int grid_create_lua(lua_State *L) { int top = lua_gettop(L); if(top<1 || !lua_isnumber(L, 1)) return typerror(L, 1, "number"); if(top<2 || !lua_isnumber(L, 2)) return typerror(L, 2, "number"); if(top<3 || !lua_isnumber(L, 3)) return typerror(L, 3, "number"); if(top<4 || !lua_isnumber(L, 4)) return typerror(L, 4, "number"); grid *g = lua_newuserdata(L, sizeof(grid)); *g = grid_create(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4)); grid_create_metatable_lua(L); return 1; }
static int grid_set_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); if(top<2 || !lua_isnumber(L, 2)) return typerror(L, 2, "number"); if(top<3 || !lua_isnumber(L, 3)) return typerror(L, 3, "number"); if(top<4 || !lua_isnumber(L, 4)) return typerror(L, 4, "number"); grid *g = lua_touserdata(L, 1); int x = lua_tointeger(L, 2); int y = lua_tointeger(L, 3); double value = lua_tonumber(L, 4); grid_set(g, x, y, value); return 0; }
static int grid_mul_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); if(top<2) return typerror(L, 2, "number or grid"); grid *g1 = lua_touserdata(L, 1); if(lua_isnumber(L, 2)) { grid_mul_number(g1, lua_tonumber(L, 2)); } else { check_userdata_type(L, 2, "grid"); grid *g2 = lua_touserdata(L, 2); grid_mul_grid(g1, g2); } return 0; }
static int grid_dilate_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); grid *g1 = lua_touserdata(L, 1); grid_dilate(g1); return 0; }
static int grid_offset_lua(lua_State *L) { if(lua_gettop(L)<1) typerror(L, 1, "grid"); grid *g = lua_touserdata(L, 1); lua_pushinteger(L, g->x0); lua_pushinteger(L, g->y0); return 2; }
static int grid_size_lua(lua_State *L) { if(lua_gettop(L)<1) typerror(L, 1, "grid"); grid *g = lua_touserdata(L, 1); lua_pushinteger(L, g->width); lua_pushinteger(L, g->height); return 2; }
static int grid_step_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); grid *g1 = lua_touserdata(L, 1); grid_step(g1, lua_tonumber(L, 2)); return 0; }
static int gradient_lua(lua_State *L) { int top = lua_gettop(L); check_userdata_type(L, 1, "grid"); if(top<3) return typerror(L, 3, "number"); grid *distances = lua_touserdata(L, 1); int x0 = lua_tonumber(L, 2); int y0 = lua_tonumber(L, 3); int movement = 8; if(top>=4) movement = lua_tointeger(L, 4); int minindex = -1; double minval = grid_get(distances, x0, y0); for(int i = 0;i<movement;++i) { int x = x0+offsets[i].x; int y = y0+offsets[i].y; if(!grid_contains(distances, x, y)) continue; double ival = grid_get(distances, x, y); if(ival<minval) { minval = ival; minindex = i; } } if(minindex == -1) { return 0; } else { lua_pushinteger(L, offsets[minindex].x); lua_pushinteger(L, offsets[minindex].y); return 2; } }
size_t check_uint(lua_State *L, int idx) { auto v = lua_tointeger(L, idx); if (v == 0 && !lua_isnumber(L, idx)) typerror(L, idx, "number"); if (v < 0) argerror(L, idx, "must be >= 0"); return static_cast<size_t>(v); }
static int grid_assign_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); check_userdata_type(L, 2, "grid"); grid *g1 = lua_touserdata(L, 1); grid *g2 = lua_touserdata(L, 2); grid_assign_grid(g1, g2); return 0; }
static struct apk_database *checkdb(lua_State *L, int index) { struct apk_database *db; luaL_checktype(L, index, LUA_TUSERDATA); db = (struct apk_database *) luaL_checkudata(L, index, APK_DB_META); if (db == NULL) typerror(L, index, APK_DB_META); return db; }
static int grid_from_table_lua(lua_State *L) { if(!lua_istable(L, 1)) return typerror(L, 1, "table"); lua_pushstring(L, "x0"); lua_gettable(L, 1); int x0 = lua_tonumber(L, -1); lua_pop(L, 1); lua_pushstring(L, "y0"); lua_gettable(L, 1); int y0 = lua_tonumber(L, -1); lua_pop(L, 1); lua_pushstring(L, "width"); lua_gettable(L, 1); int width = lua_tonumber(L, -1); lua_pop(L, 1); lua_pushstring(L, "height"); lua_gettable(L, 1); int height = lua_tonumber(L, -1); lua_pop(L, 1); grid *g = lua_newuserdata(L, sizeof(grid)); *g = grid_create(x0, y0, width, height); grid_create_metatable_lua(L); lua_pushstring(L, "data"); lua_gettable(L, 1); int size = g->width*g->height; for(int i = 0;i<size;++i) { lua_rawgeti(L, -1, i+1); g->data[i] = lua_tonumber(L, -1); lua_pop(L, 1); } lua_pop(L, 1); return 1; }
static int dijkstra_lua(lua_State *L) { int top = lua_gettop(L); int tableindex = lua_istable(L, 3)?3:4; check_userdata_type(L, 1, "grid"); check_userdata_type(L, 2, "grid"); if(tableindex == 4) check_userdata_type(L, 3, "grid"); if(!lua_istable(L, tableindex)) return typerror(L, tableindex, "table"); grid *walkable = lua_touserdata(L, 1); grid *distances = lua_touserdata(L, 2); grid *target = tableindex==4 ? lua_touserdata(L, 3) : NULL; int count = lua_objlen(L, tableindex); pos *targets = malloc(count*sizeof(pos)); for(int i = 1;i<=count;++i) { lua_pushinteger(L, i); lua_gettable(L, tableindex); lua_pushinteger(L, 1); lua_gettable(L, -2); targets[i-1].x = lua_tointeger(L, -1); lua_pop(L, 1); lua_pushinteger(L, 2); lua_gettable(L, -2); targets[i-1].y = lua_tointeger(L, -1); lua_pop(L, 1); } int movement = 8; if(top > tableindex) movement = lua_tointeger(L, tableindex+1); dijkstra_distance_target(distances, target, targets, count, movement, binary_grid_cost_function, walkable); free(targets); return 0; }
static int grid_fill_lua(lua_State *L) { int top = lua_gettop(L); if(top<1) return typerror(L, 1, "grid"); if(top<2 || !lua_isnumber(L, 2)) return typerror(L, 2, "number"); if(top>2) { if(top<3 || !lua_isnumber(L, 3)) return typerror(L, 3, "number"); if(top<4 || !lua_isnumber(L, 4)) return typerror(L, 4, "number"); if(top<5 || !lua_isnumber(L, 5)) return typerror(L, 5, "number"); if(top<6 || !lua_isnumber(L, 6)) return typerror(L, 6, "number"); } grid *g = lua_touserdata(L, 1); int x = top==2?g->x0:lua_tointeger(L, 2); int y = top==2?g->y0:lua_tointeger(L, 3); int width = top==2?g->width:lua_tointeger(L, 4); int height = top==2?g->height:lua_tointeger(L, 5); double value = top==2?lua_tonumber(L, 2):lua_tonumber(L, 6); grid_fill(g, x, y, width, height, value); return 0; }
std::string check_string(lua_State *L, int idx) { size_t len = 0; const char *str = lua_tolstring(L, idx, &len); if (!str) typerror(L, idx, "string"); return std::string(str, len); }
int check_int(lua_State *L, int idx) { auto v = lua_tointeger(L, idx); if (v == 0 && !lua_isnumber(L, idx)) typerror(L, idx, "number"); return v; }