Crossfire Server, Branch 1.12  R12190
cfpython_map.c
Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /* CFPython - A Python module for Crossfire RPG.                             */
00003 /* Version: 2.0beta8 (also known as "Alexander")                             */
00004 /* Contact: yann.chachkoff@myrealbox.com                                     */
00005 /*****************************************************************************/
00006 /* That code is placed under the GNU General Public Licence (GPL)            */
00007 /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints)     */
00008 /*****************************************************************************/
00009 /*  CrossFire, A Multiplayer game for X-windows                              */
00010 /*                                                                           */
00011 /*  Copyright (C) 2000 Mark Wedel                                            */
00012 /*  Copyright (C) 1992 Frank Tore Johansen                                   */
00013 /*                                                                           */
00014 /*  This program is free software; you can redistribute it and/or modify     */
00015 /*  it under the terms of the GNU General Public License as published by     */
00016 /*  the Free Software Foundation; either version 2 of the License, or        */
00017 /*  (at your option) any later version.                                      */
00018 /*                                                                           */
00019 /*  This program is distributed in the hope that it will be useful,          */
00020 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
00021 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
00022 /*  GNU General Public License for more details.                             */
00023 /*                                                                           */
00024 /*  You should have received a copy of the GNU General Public License        */
00025 /*  along with this program; if not, write to the Free Software              */
00026 /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
00027 /*                                                                           */
00028 /*****************************************************************************/
00029 
00030 #include <cfpython.h>
00031 #include <cfpython_map_private.h>
00032 #include <hashtable.h>
00033 
00034 /* Table for keeping track of which PyObject goes with with Crossfire object */
00035 static ptr_assoc_table map_assoc_table;
00036 
00037 /* Helper functions for dealing with object_assoc_table */
00038 void init_map_assoc_table(void) {
00039     init_ptr_assoc_table(map_assoc_table);
00040 }
00041 
00042 static void add_map_assoc(mapstruct *key, Crossfire_Map *value) {
00043     add_ptr_assoc(map_assoc_table, key, value);
00044 }
00045 
00046 static PyObject *find_assoc_pymap(mapstruct *key) {
00047     return (PyObject *)find_assoc_value(map_assoc_table, key);
00048 }
00049 
00050 static void free_map_assoc(mapstruct *key) {
00051     free_ptr_assoc(map_assoc_table, key);
00052 }
00053 
00054 static PyObject *Map_GetDifficulty(Crossfire_Map *whoptr, void *closure) {
00055     MAPEXISTCHECK(whoptr);
00056     return Py_BuildValue("i", cf_map_get_difficulty(whoptr->map));
00057 }
00058 
00059 static PyObject *Map_GetPath(Crossfire_Map *whoptr, void *closure) {
00060     MAPEXISTCHECK(whoptr);
00061     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_PATH));
00062 }
00063 
00064 static PyObject *Map_GetTempName(Crossfire_Map *whoptr, void *closure) {
00065     MAPEXISTCHECK(whoptr);
00066     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_TMPNAME));
00067 }
00068 
00069 static PyObject *Map_GetName(Crossfire_Map *whoptr, void *closure) {
00070     MAPEXISTCHECK(whoptr);
00071     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_NAME));
00072 }
00073 
00074 static PyObject *Map_GetResetTime(Crossfire_Map *whoptr, void *closure) {
00075     MAPEXISTCHECK(whoptr);
00076     return Py_BuildValue("i", cf_map_get_reset_time(whoptr->map));
00077 }
00078 
00079 static PyObject *Map_GetResetTimeout(Crossfire_Map *whoptr, void *closure) {
00080     MAPEXISTCHECK(whoptr);
00081     return Py_BuildValue("i", cf_map_get_reset_timeout(whoptr->map));
00082 }
00083 
00084 static PyObject *Map_GetPlayers(Crossfire_Map *whoptr, void *closure) {
00085     MAPEXISTCHECK(whoptr);
00086     return Py_BuildValue("i", cf_map_get_players(whoptr->map));
00087 }
00088 
00089 static PyObject *Map_GetDarkness(Crossfire_Map *whoptr, void *closure) {
00090     MAPEXISTCHECK(whoptr);
00091     return Py_BuildValue("i", cf_map_get_darkness(whoptr->map));
00092 }
00093 
00094 static PyObject *Map_GetWidth(Crossfire_Map *whoptr, void *closure) {
00095     MAPEXISTCHECK(whoptr);
00096     return Py_BuildValue("i", cf_map_get_width(whoptr->map));
00097 }
00098 
00099 static PyObject *Map_GetHeight(Crossfire_Map *whoptr, void *closure) {
00100     MAPEXISTCHECK(whoptr);
00101     return Py_BuildValue("i", cf_map_get_height(whoptr->map));
00102 }
00103 
00104 static PyObject *Map_GetEnterX(Crossfire_Map *whoptr, void *closure) {
00105     MAPEXISTCHECK(whoptr);
00106     return Py_BuildValue("i", cf_map_get_int_property(whoptr->map, CFAPI_MAP_PROP_ENTER_X));
00107 }
00108 
00109 static PyObject *Map_GetEnterY(Crossfire_Map *whoptr, void *closure) {
00110     MAPEXISTCHECK(whoptr);
00111     return Py_BuildValue("i", cf_map_get_enter_x(whoptr->map));
00112 }
00113 
00114 static PyObject *Map_GetMessage(Crossfire_Map *whoptr, void *closure) {
00115     MAPEXISTCHECK(whoptr);
00116     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_MESSAGE));
00117 }
00118 
00119 static PyObject *Map_GetRegion(Crossfire_Map *whoptr, void *closure) {
00120     MAPEXISTCHECK(whoptr);
00121     return Crossfire_Region_wrap(cf_map_get_region_property(whoptr->map, CFAPI_MAP_PROP_REGION));
00122 }
00123 
00124 static int Map_SetPath(Crossfire_Map *whoptr, PyObject *value, void *closure) {
00125     const char *val;
00126 
00127     MAPEXISTCHECK_INT(whoptr);
00128     if (!PyArg_Parse(value, "s", &val))
00129         return -1;
00130 
00131     cf_map_set_string_property(whoptr->map, CFAPI_MAP_PROP_PATH, val);
00132     return 0;
00133 
00134 }
00135 
00136 static PyObject *Map_GetUnique(Crossfire_Map *whoptr, void *closure) {
00137     MAPEXISTCHECK(whoptr);
00138     return Py_BuildValue("i", cf_map_get_int_property(whoptr->map, CFAPI_MAP_PROP_UNIQUE));
00139 }
00140 
00141 static PyObject *Map_Message(Crossfire_Map *map, PyObject *args) {
00142     int color = NDI_BLUE|NDI_UNIQUE;
00143     char *message;
00144 
00145     if (!PyArg_ParseTuple(args, "s|i", &message, &color))
00146         return NULL;
00147 
00148     MAPEXISTCHECK(map);
00149 
00150     cf_map_message(map->map, message, color);
00151 
00152     Py_INCREF(Py_None);
00153     return Py_None;
00154 }
00155 
00156 static PyObject *Map_GetFirstObjectAt(Crossfire_Map *map, PyObject *args) {
00157     int x, y;
00158     object *val;
00159 
00160     if (!PyArg_ParseTuple(args, "ii", &x, &y))
00161         return NULL;
00162 
00163     MAPEXISTCHECK(map);
00164 
00165     val = cf_map_get_object_at(map->map, x, y);
00166     return Crossfire_Object_wrap(val);
00167 }
00168 
00169 static PyObject *Map_CreateObject(Crossfire_Map *map, PyObject *args) {
00170     char *txt;
00171     int x, y;
00172     object *op;
00173 
00174     if (!PyArg_ParseTuple(args, "sii", &txt, &x, &y))
00175         return NULL;
00176 
00177     MAPEXISTCHECK(map);
00178 
00179     op = cf_create_object_by_name(txt);
00180 
00181     if (op)
00182         op = cf_map_insert_object(map->map, op, x, y);
00183     return Crossfire_Object_wrap(op);
00184 }
00185 
00186 static PyObject *Map_Check(Crossfire_Map *map, PyObject *args) {
00187     char *what;
00188     int x, y;
00189     object *foundob;
00190     sint16 nx, ny;
00191     int mflags;
00192 
00193     if (!PyArg_ParseTuple(args, "s(ii)", &what, &x, &y))
00194         return NULL;
00195 
00196     MAPEXISTCHECK(map);
00197 
00198     /* make sure the map is swapped in */
00199     if (map->map->in_memory != MAP_IN_MEMORY) {
00200         cf_log(llevError, "MAP AIN'T READY !\n");
00201     }
00202 
00203     mflags = cf_map_get_flags(map->map, &(map->map), (sint16)x, (sint16)y, &nx, &ny);
00204     if (mflags&P_OUT_OF_MAP) {
00205         Py_INCREF(Py_None);
00206         return Py_None;
00207     }
00208     foundob = cf_map_present_arch_by_name(what, map->map, nx, ny);
00209     return Crossfire_Object_wrap(foundob);
00210 }
00211 
00212 static PyObject *Map_Next(Crossfire_Map *map, PyObject *args) {
00213     MAPEXISTCHECK(map);
00214     return Crossfire_Map_wrap(cf_map_get_map_property(map->map, CFAPI_MAP_PROP_NEXT));
00215 }
00216 
00217 static PyObject *Map_Insert(Crossfire_Map *map, PyObject *args) {
00218     int x, y;
00219     Crossfire_Object *what;
00220 
00221     if (!PyArg_ParseTuple(args, "O!ii", &Crossfire_ObjectType, &what, &x, &y))
00222         return NULL;
00223 
00224     MAPEXISTCHECK(map);
00225 
00226     return Crossfire_Object_wrap(cf_map_insert_object(map->map, what->obj, x, y));
00227 }
00228 
00229 static PyObject *Map_ChangeLight(Crossfire_Map *map, PyObject *args) {
00230     int change;
00231 
00232     if (!PyArg_ParseTuple(args, "i", &change))
00233         return NULL;
00234 
00235     MAPEXISTCHECK(map);
00236 
00237     return Py_BuildValue("i", cf_map_change_light(map->map, change));
00238 }
00254 static PyObject *Map_TriggerConnected(Crossfire_Map *map, PyObject *args) {
00255     objectlink *ol = NULL;
00256     int connected;
00257     int state;
00258     Crossfire_Object *cause = NULL;
00259     oblinkpt *olp;
00260 
00261     if (!PyArg_ParseTuple(args, "ii|O!", &connected, &state, &Crossfire_ObjectType, &cause))
00262         return NULL;
00263 
00264     MAPEXISTCHECK(map);
00265     /* locate objectlink for this connected value */
00266     if (!map->map->buttons) {
00267         cf_log(llevError, "Map %s called for trigger on connected %d but there ain't any button list for that map!\n", cf_map_get_sstring_property(map->map, CFAPI_MAP_PROP_PATH), connected);
00268         return NULL;
00269     }
00270     for (olp = map->map->buttons; olp; olp = olp->next) {
00271         if (olp->value == connected) {
00272             ol = olp->link;
00273             break;
00274         }
00275     }
00276     if (ol == NULL) {
00277         cf_log(llevInfo, "Map %s called for trigger on connected %d but there ain't any button list for that map!\n", cf_map_get_sstring_property(map->map, CFAPI_MAP_PROP_PATH), connected);
00278         return NULL;
00279     }
00280     /* run the object link */
00281     cf_map_trigger_connected(ol, cause ? cause->obj : NULL, state);
00282 
00283     Py_INCREF(Py_None);
00284     return Py_None;
00285 }
00286 
00287 static int Map_InternalCompare(Crossfire_Map *left, Crossfire_Map *right) {
00288     MAPEXISTCHECK_INT(left);
00289     MAPEXISTCHECK_INT(right);
00290     return left->map < right->map ? -1 : (left->map == right->map ? 0 : 1);
00291 }
00292 
00293 /* Legacy code: convert to long so that non-object functions work correctly */
00294 static PyObject *Crossfire_Map_Long(PyObject *obj) {
00295     MAPEXISTCHECK((Crossfire_Map *)obj);
00296     return Py_BuildValue("l", ((Crossfire_Map *)obj)->map);
00297 }
00298 
00299 #ifndef IS_PY3K
00300 static PyObject *Crossfire_Map_Int(PyObject *obj) {
00301     MAPEXISTCHECK((Crossfire_Map *)obj);
00302     return Py_BuildValue("i", ((Crossfire_Map *)obj)->map);
00303 }
00304 #endif
00305 
00309 static PyObject *Crossfire_Map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
00310     Crossfire_Map *self;
00311 
00312     self = (Crossfire_Map *)type->tp_alloc(type, 0);
00313     if (self)
00314         self->map = NULL;
00315 
00316     return (PyObject *)self;
00317 }
00318 
00319 static void Crossfire_Map_dealloc(PyObject *obj) {
00320     Crossfire_Map *self;
00321 
00322     self = (Crossfire_Map *)obj;
00323     if (self) {
00324         if (self->map && self->valid) {
00325             free_map_assoc(self->map);
00326         }
00327         Py_TYPE(self)->tp_free(obj);
00328     }
00329 }
00330 
00331 void Handle_Map_Unload_Hook(Crossfire_Map *map) {
00332     map->valid = 0;
00333     free_map_assoc(map->map);
00334 }
00335 
00336 PyObject *Crossfire_Map_wrap(mapstruct *what) {
00337     Crossfire_Map *wrapper;
00338 
00339     /* return None if no object was to be wrapped */
00340     if (what == NULL) {
00341         Py_INCREF(Py_None);
00342         return Py_None;
00343     }
00344 
00345     wrapper = (Crossfire_Map *)find_assoc_pymap(what);
00346     if (!wrapper) {
00347         wrapper = PyObject_NEW(Crossfire_Map, &Crossfire_MapType);
00348         if (wrapper != NULL) {
00349             wrapper->map = what;
00350             wrapper->valid = 1;
00351             add_map_assoc(what, wrapper);
00352         }
00353     } else {
00354         Py_INCREF(wrapper);
00355     }
00356 
00357     return (PyObject *)wrapper;
00358 }