359 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			359 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
| /*****************************************************************************/
 | |
| /* CFPython - A Python module for Crossfire RPG.                             */
 | |
| /* Version: 2.0beta8 (also known as "Alexander")                             */
 | |
| /* Contact: yann.chachkoff@myrealbox.com                                     */
 | |
| /*****************************************************************************/
 | |
| /* That code is placed under the GNU General Public Licence (GPL)            */
 | |
| /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints)     */
 | |
| /*****************************************************************************/
 | |
| /*  CrossFire, A Multiplayer game for X-windows                              */
 | |
| /*                                                                           */
 | |
| /*  Copyright (C) 2000 Mark Wedel                                            */
 | |
| /*  Copyright (C) 1992 Frank Tore Johansen                                   */
 | |
| /*                                                                           */
 | |
| /*  This program is free software; you can redistribute it and/or modify     */
 | |
| /*  it under the terms of the GNU General Public License as published by     */
 | |
| /*  the Free Software Foundation; either version 2 of the License, or        */
 | |
| /*  (at your option) any later version.                                      */
 | |
| /*                                                                           */
 | |
| /*  This program is distributed in the hope that it will be useful,          */
 | |
| /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
 | |
| /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
 | |
| /*  GNU General Public License for more details.                             */
 | |
| /*                                                                           */
 | |
| /*  You should have received a copy of the GNU General Public License        */
 | |
| /*  along with this program; if not, write to the Free Software              */
 | |
| /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
 | |
| /*                                                                           */
 | |
| /*****************************************************************************/
 | |
| 
 | |
| #include <cfpython.h>
 | |
| #include <cfpython_map_private.h>
 | |
| #include <hashtable.h>
 | |
| 
 | |
| /* Table for keeping track of which PyObject goes with with Crossfire object */
 | |
| static ptr_assoc_table map_assoc_table;
 | |
| 
 | |
| /* Helper functions for dealing with object_assoc_table */
 | |
| void init_map_assoc_table(void) {
 | |
|     init_ptr_assoc_table(map_assoc_table);
 | |
| }
 | |
| 
 | |
| static void add_map_assoc(mapstruct *key, Crossfire_Map *value) {
 | |
|     add_ptr_assoc(map_assoc_table, key, value);
 | |
| }
 | |
| 
 | |
| static PyObject *find_assoc_pymap(mapstruct *key) {
 | |
|     return (PyObject *)find_assoc_value(map_assoc_table, key);
 | |
| }
 | |
| 
 | |
| static void free_map_assoc(mapstruct *key) {
 | |
|     free_ptr_assoc(map_assoc_table, key);
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetDifficulty(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_difficulty(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetPath(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_PATH));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetTempName(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_TMPNAME));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetName(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_NAME));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetResetTime(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_reset_time(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetResetTimeout(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_reset_timeout(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetPlayers(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_players(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetDarkness(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_darkness(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetWidth(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_width(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetHeight(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_height(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetEnterX(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_int_property(whoptr->map, CFAPI_MAP_PROP_ENTER_X));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetEnterY(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_enter_x(whoptr->map));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetMessage(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("s", cf_map_get_sstring_property(whoptr->map, CFAPI_MAP_PROP_MESSAGE));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetRegion(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Crossfire_Region_wrap(cf_map_get_region_property(whoptr->map, CFAPI_MAP_PROP_REGION));
 | |
| }
 | |
| 
 | |
| static int Map_SetPath(Crossfire_Map *whoptr, PyObject *value, void *closure) {
 | |
|     const char *val;
 | |
| 
 | |
|     MAPEXISTCHECK_INT(whoptr);
 | |
|     if (!PyArg_Parse(value, "s", &val))
 | |
|         return -1;
 | |
| 
 | |
|     cf_map_set_string_property(whoptr->map, CFAPI_MAP_PROP_PATH, val);
 | |
|     return 0;
 | |
| 
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetUnique(Crossfire_Map *whoptr, void *closure) {
 | |
|     MAPEXISTCHECK(whoptr);
 | |
|     return Py_BuildValue("i", cf_map_get_int_property(whoptr->map, CFAPI_MAP_PROP_UNIQUE));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_Message(Crossfire_Map *map, PyObject *args) {
 | |
|     int color = NDI_BLUE|NDI_UNIQUE;
 | |
|     char *message;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "s|i", &message, &color))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     cf_map_message(map->map, message, color);
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| static PyObject *Map_GetFirstObjectAt(Crossfire_Map *map, PyObject *args) {
 | |
|     int x, y;
 | |
|     object *val;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "ii", &x, &y))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     val = cf_map_get_object_at(map->map, x, y);
 | |
|     return Crossfire_Object_wrap(val);
 | |
| }
 | |
| 
 | |
| static PyObject *Map_CreateObject(Crossfire_Map *map, PyObject *args) {
 | |
|     char *txt;
 | |
|     int x, y;
 | |
|     object *op;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "sii", &txt, &x, &y))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     op = cf_create_object_by_name(txt);
 | |
| 
 | |
|     if (op)
 | |
|         op = cf_map_insert_object(map->map, op, x, y);
 | |
|     return Crossfire_Object_wrap(op);
 | |
| }
 | |
| 
 | |
| static PyObject *Map_Check(Crossfire_Map *map, PyObject *args) {
 | |
|     char *what;
 | |
|     int x, y;
 | |
|     object *foundob;
 | |
|     sint16 nx, ny;
 | |
|     int mflags;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "s(ii)", &what, &x, &y))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     /* make sure the map is swapped in */
 | |
|     if (map->map->in_memory != MAP_IN_MEMORY) {
 | |
|         cf_log(llevError, "MAP AIN'T READY !\n");
 | |
|     }
 | |
| 
 | |
|     mflags = cf_map_get_flags(map->map, &(map->map), (sint16)x, (sint16)y, &nx, &ny);
 | |
|     if (mflags&P_OUT_OF_MAP) {
 | |
|         Py_INCREF(Py_None);
 | |
|         return Py_None;
 | |
|     }
 | |
|     foundob = cf_map_present_arch_by_name(what, map->map, nx, ny);
 | |
|     return Crossfire_Object_wrap(foundob);
 | |
| }
 | |
| 
 | |
| static PyObject *Map_Next(Crossfire_Map *map, PyObject *args) {
 | |
|     MAPEXISTCHECK(map);
 | |
|     return Crossfire_Map_wrap(cf_map_get_map_property(map->map, CFAPI_MAP_PROP_NEXT));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_Insert(Crossfire_Map *map, PyObject *args) {
 | |
|     int x, y;
 | |
|     Crossfire_Object *what;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "O!ii", &Crossfire_ObjectType, &what, &x, &y))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     return Crossfire_Object_wrap(cf_map_insert_object(map->map, what->obj, x, y));
 | |
| }
 | |
| 
 | |
| static PyObject *Map_ChangeLight(Crossfire_Map *map, PyObject *args) {
 | |
|     int change;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "i", &change))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
| 
 | |
|     return Py_BuildValue("i", cf_map_change_light(map->map, change));
 | |
| }
 | |
| /**
 | |
|  * Python backend method for Map.TriggerConnected(int connected, CfObject cause, int state)
 | |
|  *
 | |
|  * Expected arguments:
 | |
|  * - connected will be used to locate Objectlink with given id on map
 | |
|  * - state: 0=trigger the "release", other is trigger the "push", default is push
 | |
|  * - cause, eventual CfObject causing this trigger
 | |
|  *
 | |
|  * @param map
 | |
|  * map we're on.
 | |
|  * @param args
 | |
|  * arguments as explained above.
 | |
|  * @return
 | |
|  * NULL if error, Py_None else.
 | |
|  */
 | |
| static PyObject *Map_TriggerConnected(Crossfire_Map *map, PyObject *args) {
 | |
|     objectlink *ol = NULL;
 | |
|     int connected;
 | |
|     int state;
 | |
|     Crossfire_Object *cause = NULL;
 | |
|     oblinkpt *olp;
 | |
| 
 | |
|     if (!PyArg_ParseTuple(args, "ii|O!", &connected, &state, &Crossfire_ObjectType, &cause))
 | |
|         return NULL;
 | |
| 
 | |
|     MAPEXISTCHECK(map);
 | |
|     /* locate objectlink for this connected value */
 | |
|     if (!map->map->buttons) {
 | |
|         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);
 | |
|         return NULL;
 | |
|     }
 | |
|     for (olp = map->map->buttons; olp; olp = olp->next) {
 | |
|         if (olp->value == connected) {
 | |
|             ol = olp->link;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     if (ol == NULL) {
 | |
|         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);
 | |
|         return NULL;
 | |
|     }
 | |
|     /* run the object link */
 | |
|     cf_map_trigger_connected(ol, cause ? cause->obj : NULL, state);
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| static int Map_InternalCompare(Crossfire_Map *left, Crossfire_Map *right) {
 | |
|     MAPEXISTCHECK_INT(left);
 | |
|     MAPEXISTCHECK_INT(right);
 | |
|     return left->map < right->map ? -1 : (left->map == right->map ? 0 : 1);
 | |
| }
 | |
| 
 | |
| /* Legacy code: convert to long so that non-object functions work correctly */
 | |
| static PyObject *Crossfire_Map_Long(PyObject *obj) {
 | |
|     MAPEXISTCHECK((Crossfire_Map *)obj);
 | |
|     return Py_BuildValue("l", ((Crossfire_Map *)obj)->map);
 | |
| }
 | |
| 
 | |
| #ifndef IS_PY3K
 | |
| static PyObject *Crossfire_Map_Int(PyObject *obj) {
 | |
|     MAPEXISTCHECK((Crossfire_Map *)obj);
 | |
|     return Py_BuildValue("i", ((Crossfire_Map *)obj)->map);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * Python initialized.
 | |
|  **/
 | |
| static PyObject *Crossfire_Map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
 | |
|     Crossfire_Map *self;
 | |
| 
 | |
|     self = (Crossfire_Map *)type->tp_alloc(type, 0);
 | |
|     if (self)
 | |
|         self->map = NULL;
 | |
| 
 | |
|     return (PyObject *)self;
 | |
| }
 | |
| 
 | |
| static void Crossfire_Map_dealloc(PyObject *obj) {
 | |
|     Crossfire_Map *self;
 | |
| 
 | |
|     self = (Crossfire_Map *)obj;
 | |
|     if (self) {
 | |
|         if (self->map && self->valid) {
 | |
|             free_map_assoc(self->map);
 | |
|         }
 | |
|         Py_TYPE(self)->tp_free(obj);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Handle_Map_Unload_Hook(Crossfire_Map *map) {
 | |
|     map->valid = 0;
 | |
|     free_map_assoc(map->map);
 | |
| }
 | |
| 
 | |
| PyObject *Crossfire_Map_wrap(mapstruct *what) {
 | |
|     Crossfire_Map *wrapper;
 | |
| 
 | |
|     /* return None if no object was to be wrapped */
 | |
|     if (what == NULL) {
 | |
|         Py_INCREF(Py_None);
 | |
|         return Py_None;
 | |
|     }
 | |
| 
 | |
|     wrapper = (Crossfire_Map *)find_assoc_pymap(what);
 | |
|     if (!wrapper) {
 | |
|         wrapper = PyObject_NEW(Crossfire_Map, &Crossfire_MapType);
 | |
|         if (wrapper != NULL) {
 | |
|             wrapper->map = what;
 | |
|             wrapper->valid = 1;
 | |
|             add_map_assoc(what, wrapper);
 | |
|         }
 | |
|     } else {
 | |
|         Py_INCREF(wrapper);
 | |
|     }
 | |
| 
 | |
|     return (PyObject *)wrapper;
 | |
| }
 |