lash_game_map_wrapper.c (8267B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include "Python.h" 5 6 #include "liblashgame/lash_game_map.h" 7 #include "liblashgame/lash_game_path_simple.h" 8 9 void mapDestroy(PyObject *capsule) { 10 11 lash_map_simple_t *map; 12 13 //fprintf(stderr, "Entered destructor\n"); 14 15 map = (lash_map_simple_t*)PyCapsule_GetPointer(capsule, "MAP_C_API"); 16 if (map == NULL) 17 return; 18 19 //fprintf(stderr, "Destroying map %p\n", map); 20 21 lash_mapSimpleFree(map); 22 free(map); 23 24 } 25 26 static PyObject * mapSimpleInit_func(PyObject *self, PyObject *args) { 27 unsigned int w; 28 unsigned int h; 29 PyObject *pymap; 30 31 lash_map_simple_t *map = (lash_map_simple_t*)malloc(sizeof(lash_map_simple_t)); 32 33 if (!PyArg_ParseTuple(args, "II", &w, &h)) { 34 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 35 return NULL; 36 } 37 38 if (!lash_mapSimpleInit(map, &w, &h)) { 39 PyErr_SetString(PyExc_RuntimeError, "Cannot initialize map! "); 40 return NULL; 41 } 42 43 44 pymap = PyCapsule_New((void *)map, "MAP_C_API", mapDestroy); 45 46 // free(map); 47 48 return Py_BuildValue("O", pymap); 49 50 } 51 52 static PyObject * mapSimplePeek_func(PyObject *self, PyObject *args) { 53 lash_game_map_index_t idx; 54 lash_map_simple_t *map; 55 PyObject *pymap; 56 57 if (!PyArg_ParseTuple(args, "Ok", &pymap, &idx)) { 58 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 59 return NULL; 60 } 61 62 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 63 64 if (idx >= *(map->w) * *(map->h)) 65 return NULL; 66 67 return Py_BuildValue("h", (unsigned short)lash_mapSimpleLayerPeek(map->layer_path, idx)); 68 } 69 70 static PyObject * mapSimplePoke_func(PyObject *self, PyObject *args) { 71 lash_game_map_index_t idx; 72 unsigned short val; 73 lash_map_simple_t *map; 74 PyObject *pymap; 75 76 if (!PyArg_ParseTuple(args, "Okh", &pymap, &idx, &val)) { 77 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 78 return NULL; 79 } 80 81 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 82 83 if (idx < *(map->w) * *(map->h)) 84 lash_mapSimpleLayerPoke(map->layer_path, idx, (lash_map_simple_layer_item_t)val); 85 86 return Py_BuildValue("s", NULL); 87 } 88 89 static PyObject * getMapSizeUnits_func(PyObject *self, PyObject *args) { 90 91 lash_map_simple_t *map; 92 PyObject *pymap; 93 94 if (!PyArg_ParseTuple(args, "O", &pymap)) 95 return NULL; 96 97 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 98 if (map == NULL) { 99 PyErr_SetString(PyExc_RuntimeError, "Invalid map object"); 100 return NULL; 101 } 102 103 return Py_BuildValue("II", *(map->w), *(map->h)); 104 105 } 106 107 static PyObject * getPathFreeSpaces_func(PyObject *self, PyObject *args) { 108 int i; 109 110 lash_map_simple_t *map; 111 112 // args 113 PyObject *pymap; 114 115 // process 116 unsigned int mapsize; 117 118 // result 119 unsigned int *freeindices; 120 int freeindices_count; 121 PyObject *freeindices_final; 122 123 if (!PyArg_ParseTuple(args, "O", &pymap)) { 124 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 125 return NULL; 126 } 127 128 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 129 if (map == NULL) { 130 PyErr_SetString(PyExc_RuntimeError, "Invalid map object"); 131 return NULL; 132 } 133 134 mapsize = lash_mapSimpleGetSize(map); 135 136 freeindices = (unsigned int*)calloc(sizeof(unsigned int), mapsize); 137 if (freeindices == NULL) { 138 PyErr_SetString(PyExc_RuntimeError, "Could not allocate array to hold free spaces index list"); 139 return NULL; 140 } 141 142 freeindices_count = lash_pathSimpleCompileFreeSpaces(&freeindices, mapsize, map->layer_path, mapsize, NULL, 0); 143 144 if (freeindices_count == -1) { 145 PyErr_SetString(PyExc_RuntimeError, "List compilation of free spaces failed"); 146 return NULL; 147 } 148 149 freeindices_final = PyList_New(freeindices_count); 150 151 for (i = 0; i < freeindices_count; i++) { 152 PyObject *newindex = Py_BuildValue("I", (unsigned int)*(freeindices + i)); 153 //if (PyList_SetItem(freeindices_final, i, PyBytes_FromFormat("%u", (unsigned int)*(freeindices + i))) == -1) { 154 if (PyList_SetItem(freeindices_final, i, newindex) == -1) { 155 PyErr_SetString(PyExc_RuntimeError, "Could not complete populating final free spaces index array"); 156 return NULL; 157 } 158 } 159 160 free(freeindices); 161 return freeindices_final; 162 } 163 164 static PyObject * makeSimplePath_func(PyObject *self, PyObject *args) { 165 166 int i; 167 168 lash_map_simple_t *map; 169 lash_path_simple_t path; 170 lash_path_simple_space_t *space; 171 lash_path_simple_space_t *nextspace; 172 unsigned int *pathindices; 173 174 // args 175 PyObject *pymap; 176 unsigned int index_start; 177 unsigned int index_end; 178 179 // processing 180 unsigned int steps; 181 182 // output 183 PyObject *path_final; 184 185 186 if (!PyArg_ParseTuple(args, "OII", &pymap, &index_start, &index_end)) { 187 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 188 return NULL; 189 } 190 191 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 192 if (map == NULL) { 193 PyErr_SetString(PyExc_RuntimeError, "Invalid map object"); 194 return NULL; 195 } 196 197 if (lash_pathSimpleNew(&path, map, index_start, index_end) == NULL) { 198 PyErr_SetString(PyExc_RuntimeError, "Could not initialize path object"); 199 return NULL; 200 } 201 202 lash_pathSimpleNext(&path, &space); 203 204 steps = 0; 205 206 while (space->index != path.target) { 207 lash_pathSimpleStepProcess(&path, map, space, NULL, 0); 208 steps++; 209 lash_pathSimpleNext(&path, &space); 210 211 if (space == NULL) { 212 return Py_None; 213 } 214 } 215 216 pathindices = (unsigned int*)calloc(sizeof(unsigned int), steps * 2); 217 if (pathindices == NULL){ 218 PyErr_SetString(PyExc_RuntimeError, "Could not initialize array for final path storage"); 219 return NULL; 220 } 221 222 *(pathindices + 0) = space->index; 223 224 nextspace = space; 225 226 steps = 0; 227 228 while (nextspace->parent != NULL) { 229 steps++; 230 space = nextspace; 231 nextspace = space->parent; 232 *(pathindices + steps) = nextspace->index; 233 } 234 235 i = 0; 236 237 path_final = PyList_New(steps); 238 239 for (i = 0; i < steps; i++) { 240 //if (PyList_SetItem(path_final, i, PyBytes_FromFormat("%u", *(pathindices + i))) == -1) { 241 if (PyList_SetItem(path_final, i, Py_BuildValue("I", *(pathindices + i))) == -1) { 242 PyErr_SetString(PyExc_RuntimeError, "Could not complete populating final path index array"); 243 if (pathindices != NULL) 244 free(pathindices); 245 return NULL; 246 } 247 } 248 249 if (pathindices != NULL) 250 free(pathindices); 251 252 lash_pathSimpleFree(&path); 253 254 return path_final; 255 } 256 257 static PyObject * pathInit_func(PyObject *self, PyObject *args) { 258 259 return Py_BuildValue("i", lash_pathSimpleInit()); 260 261 } 262 263 static PyObject * pathFinish_func(PyObject *self, PyObject *args) { 264 lash_pathSimpleFinish(); 265 return Py_None; 266 } 267 268 static PyObject * mapSimpleFree_func(PyObject *self, PyObject *args) { 269 lash_map_simple_t *map; 270 PyObject *pymap; 271 272 if (!PyArg_ParseTuple(args, "O", &pymap)) { 273 PyErr_SetString(PyExc_RuntimeError, "Invalid input"); 274 return NULL; 275 } 276 277 map = (lash_map_simple_t*)PyCapsule_GetPointer(pymap, "MAP_C_API"); 278 279 lash_mapSimpleFree(map); 280 free(map); 281 282 return Py_None; 283 } 284 285 static PyMethodDef PylashgamemapMethods[] = { 286 {"mapSimpleInit", (PyCFunction)mapSimpleInit_func, METH_VARARGS, "Initialize a new map object"}, 287 {"mapSimplePeek", (PyCFunction)mapSimplePeek_func, METH_VARARGS, "Get an obstacle value at a certain index"}, 288 {"mapSimplePoke", (PyCFunction)mapSimplePoke_func, METH_VARARGS, "Set an obstacle value at a certain index"}, 289 {"mapSimpleFree", (PyCFunction)mapSimpleFree_func, METH_VARARGS, "Frees resources used by map object"}, 290 {"getMapSizeUnits", (PyCFunction)getMapSizeUnits_func, METH_VARARGS, "Return with and height in units"}, 291 {"makeSimplePath", (PyCFunction)makeSimplePath_func, METH_VARARGS, "Returns shortest path between two points using the specified layerpath"}, 292 {"getPathFreeSpaces", (PyCFunction)getPathFreeSpaces_func, METH_VARARGS, "Get map indices of free spaces from map layer path"}, 293 {"pathInit", (PyCFunction)pathInit_func, METH_VARARGS, "Initialize the pathfinder library"}, 294 {"pathFinish", (PyCFunction)pathFinish_func, METH_VARARGS, "Clean the pathfinder library"}, 295 {NULL, NULL, 0, NULL} 296 }; 297 298 static struct PyModuleDef lashgamemapmodule = { 299 PyModuleDef_HEAD_INIT, 300 "lashgamemap", /* name of module */ 301 NULL, /* module documentation, may be NULL */ 302 -1, /* size of per-interpreter state of the module, 303 or -1 if the module keeps state in global variables. */ 304 PylashgamemapMethods 305 }; 306 307 PyMODINIT_FUNC PyInit_lashgamemap(void) 308 { 309 return PyModule_Create(&lashgamemapmodule); 310 }