ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.205
Committed: Mon May 7 03:05:58 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.204: +40 -0 lines
Log Message:
- add two new slots for shields and combat weapons
- make slots into bitfields, they are not too speed-critical and this
  saves 16 bytes in the object structure.
- add accessors to body lcoation names etc. to perl
- use those in the body command

File Contents

# User Rev Content
1 root 1.1 /*****************************************************************************/
2     /* CrossFire, A Multiplayer game for the X Window System */
3     /*****************************************************************************/
4    
5     /*
6     * This code is placed under the GNU General Public Licence (GPL)
7     *
8     * Copyright (C) 2001-2005 by Chachkoff Yann
9 root 1.169 * Copyright (C) 2006,2007 by Marc Lehmann <cf@schmorp.de>
10 root 1.1 *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 root 1.106 */
25 root 1.1
26 root 1.198 #include "autoconf.h"
27    
28 root 1.1 #define PLUGIN_NAME "perl"
29 root 1.13 #define PLUGIN_VERSION "cfperl 0.5"
30 root 1.1
31 root 1.189 #define CEDES_PER_TICK 5
32    
33 root 1.198 #if HAVE_EXECINFO_H
34     # include <execinfo.h>
35     #endif
36    
37 root 1.1 #include <plugin_common.h>
38     #include <sounds.h>
39 root 1.6 #include <cstdarg>
40     #include <sproto.h>
41 root 1.1
42 root 1.162 #include "loader.h"
43 root 1.6 #include "cfperl.h"
44 root 1.12 #include "shstr.h"
45 root 1.1
46 root 1.125 #include <unistd.h>
47     #if _POSIX_MEMLOCK
48     # include <sys/mman.h>
49     #endif
50    
51 root 1.32 #include <EXTERN.h>
52     #include <perl.h>
53     #include <XSUB.h>
54    
55 root 1.107 #include "CoroAPI.h"
56 root 1.1 #include "perlxsi.c"
57    
58     extern sint64 *levels; // the experience table
59    
60 root 1.61 typedef object object_ornull;
61     typedef maptile maptile_ornull;
62 root 1.1
63 root 1.183 typedef char *octet_string;
64     typedef char *utf8_string;
65     typedef const char *const_octet_string;
66     typedef const char *const_utf8_string;
67    
68 root 1.194 typedef std::string std__string;
69    
70 root 1.71 #if IVSIZE >= 8
71     typedef IV val64;
72     # define newSVval64 newSViv
73     # define SvVAL64 SvIV
74     #else
75     typedef double val64;
76     # define newSVval64 newSVnv
77     # define SvVAL64 SvNV
78     #endif
79 root 1.1
80 root 1.19 static f_plug_api gethook = cfapi_get_hooks;
81     static f_plug_api object_set_property = cfapi_object_set_property;
82     static f_plug_api object_insert = cfapi_object_insert;
83 root 1.1
84     static PerlInterpreter *perl;
85    
86 root 1.116 double runtime;
87    
88 root 1.109 global gbl_ev;
89     static AV *cb_global, *cb_attachable, *cb_object, *cb_player, *cb_client, *cb_type, *cb_map;
90 root 1.189 static SV *sv_runtime, *sv_next_tick;
91 root 1.109
92     static HV
93     *stash_cf,
94     *stash_cf_object_wrap,
95     *stash_cf_object_player_wrap,
96     *stash_cf_player_wrap,
97     *stash_cf_map_wrap,
98     *stash_cf_client_wrap,
99     *stash_cf_arch_wrap,
100     *stash_cf_party_wrap,
101     *stash_cf_region_wrap,
102     *stash_cf_living_wrap;
103    
104     // helper cast function, returns super class * or 0
105     template<class super>
106     static super *
107     is_a (attachable *at)
108     {
109     //return dynamic_cast<super *>(at); // slower, safer
110     if (typeid (*at) == typeid (super))
111     return static_cast<super *>(at);
112     else
113     return 0;
114     }
115    
116     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
117    
118     unordered_vector<attachable *> attachable::mortals;
119    
120 root 1.129 attachable::~attachable ()
121 root 1.109 {
122 root 1.133 assert (!self);
123 root 1.153 assert (!cb);
124 root 1.109 }
125    
126 root 1.130 int
127     attachable::refcnt_cnt () const
128     {
129 root 1.152 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
130 root 1.130 }
131    
132     void
133 root 1.155 attachable::sever_self ()
134 root 1.109 {
135 root 1.164 if (HV *self = this->self)
136 root 1.129 {
137 root 1.155 // keep a refcount because sv_unmagic might call attachable_free,
138     // which might clear self, causing sv_unmagic to crash on a now
139     // invalid object.
140 root 1.154 SvREFCNT_inc (self);
141 root 1.155 hv_clear (self);
142     sv_unmagic ((SV *)self, PERL_MAGIC_ext);
143 root 1.154 SvREFCNT_dec (self);
144 root 1.155
145     // self *must* be null now because thats sv_unmagic's job.
146 root 1.164 assert (!this->self);
147 root 1.129 }
148 root 1.109 }
149    
150 root 1.155 void
151     attachable::optimise ()
152     {
153     if (self
154     && SvREFCNT (self) == 1
155     && !HvTOTALKEYS (self))
156     sever_self ();
157     }
158    
159 root 1.109 // check wether the object really is dead
160     void
161     attachable::do_check ()
162     {
163 root 1.152 if (refcnt_cnt () > 0)
164 root 1.109 return;
165    
166 root 1.133 destroy ();
167 root 1.109 }
168    
169     void
170     attachable::do_destroy ()
171     {
172     invoke (EVENT_ATTACHABLE_DESTROY, DT_END);
173    
174 root 1.153 if (cb)
175     {
176     SvREFCNT_dec (cb);
177     cb = 0;
178     }
179    
180 root 1.109 mortals.push_back (this);
181     }
182    
183     void
184     attachable::destroy ()
185     {
186     if (destroyed ())
187     return;
188    
189     flags |= F_DESTROYED;
190     do_destroy ();
191 root 1.198 sever_self ();
192 root 1.109 }
193    
194 root 1.130 void
195     attachable::check_mortals ()
196 root 1.109 {
197 root 1.150 static int i = 0;
198    
199     for (;;)
200 root 1.109 {
201 root 1.150 if (i >= mortals.size ())
202     {
203     i = 0;
204    
205     if (mortals.size () > 1000)
206 root 1.197 LOG (llevInfo, "mortal queue size (%d) exceeds 1000.\n", (int)mortals.size ());
207 root 1.150
208     break;
209     }
210    
211 root 1.109 attachable *obj = mortals [i];
212    
213 root 1.197 #if 0
214     if (obj->self)//D make this an assert later
215     {
216     LOG (llevError, "check_mortals: object '%s' still has self\n", typeid (obj).name ());
217     obj->sever_self ();
218     }
219     #endif
220 root 1.109
221 root 1.198 if (obj->refcnt)
222 root 1.109 {
223 root 1.150 ++i; // further delay freeing
224 root 1.109
225 root 1.150 if (!(i & 0x3ff))
226     break;
227     }
228 root 1.109 else
229     {
230 root 1.112 mortals.erase (i);
231 root 1.197 obj->sever_self ();
232 root 1.109 delete obj;
233     }
234     }
235     }
236    
237     attachable &
238     attachable::operator =(const attachable &src)
239     {
240     //if (self || cb)
241     //INVOKE_OBJECT (CLONE, this, ARG_OBJECT (dst));
242    
243     attach = src.attach;
244     return *this;
245     }
246 root 1.8
247 root 1.1 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
248    
249     static SV *
250 root 1.109 newSVptr (void *ptr, HV *stash, HV *hv = newHV ())
251 root 1.1 {
252     SV *sv;
253    
254     if (!ptr)
255     return &PL_sv_undef;
256    
257 root 1.109 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, 0, (char *)ptr, 0);
258     return sv_bless (newRV_noinc ((SV *)hv), stash);
259     }
260    
261     static int
262     attachable_free (pTHX_ SV *sv, MAGIC *mg)
263     {
264     attachable *at = (attachable *)mg->mg_ptr;
265 root 1.153
266     //TODO: check if transaction behaviour is really required here
267     if (SV *self = (SV *)at->self)
268     {
269     at->self = 0;
270     SvREFCNT_dec (self);
271     }
272    
273 root 1.111 // next line makes sense, but most objects still have refcnt 0 by default
274     //at->refcnt_chk ();
275 root 1.109 return 0;
276 root 1.1 }
277    
278 root 1.116 MGVTBL attachable::vtbl = {0, 0, 0, 0, attachable_free};
279 root 1.109
280 root 1.116 static SV *
281 root 1.109 newSVattachable (attachable *obj, HV *stash)
282 root 1.11 {
283     if (!obj)
284     return &PL_sv_undef;
285    
286     if (!obj->self)
287 root 1.109 {
288     obj->self = newHV ();
289 root 1.116 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
290 root 1.11
291 root 1.129 // now bless the object _once_
292     return sv_bless (newRV_inc ((SV *)obj->self), stash);
293 root 1.109 }
294 root 1.129 else
295 root 1.140 {
296     SV *sv = newRV_inc ((SV *)obj->self);
297    
298     if (Gv_AMG (stash)) // handle overload correctly, as the perl core does not
299     SvAMAGIC_on (sv);
300    
301     return sv;
302     }
303 root 1.11 }
304    
305 root 1.1 static void
306     clearSVptr (SV *sv)
307     {
308     if (SvROK (sv))
309     sv = SvRV (sv);
310    
311     hv_clear ((HV *)sv);
312     sv_unmagic (sv, PERL_MAGIC_ext);
313     }
314    
315     static long
316     SvPTR (SV *sv, const char *klass)
317     {
318     if (!sv_derived_from (sv, klass))
319     croak ("object of type %s expected", klass);
320    
321     MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
322    
323     if (!mg)
324     croak ("perl code used %s object, but C object is already destroyed, caught", klass);
325    
326     return (long)mg->mg_ptr;
327     }
328    
329     static long
330     SvPTR_ornull (SV *sv, const char *klass)
331     {
332     if (SvOK (sv))
333     return SvPTR (sv, klass);
334     else
335     return 0;
336     }
337    
338 root 1.45 inline SV *to_sv (const shstr & v) { return v ? newSVpvn ((const char *)v, v.length ()) : &PL_sv_undef; }
339     inline SV *to_sv (const char * v) { return newSVpv (v, 0); }
340     inline SV *to_sv (bool v) { return newSViv (v); }
341     inline SV *to_sv ( signed char v) { return newSViv (v); }
342     inline SV *to_sv (unsigned char v) { return newSViv (v); }
343     inline SV *to_sv ( signed short v) { return newSViv (v); }
344     inline SV *to_sv (unsigned short v) { return newSVuv (v); }
345     inline SV *to_sv ( signed int v) { return newSViv (v); }
346     inline SV *to_sv (unsigned int v) { return newSVuv (v); }
347     inline SV *to_sv ( signed long v) { return newSViv (v); }
348     inline SV *to_sv (unsigned long v) { return newSVuv (v); }
349 root 1.48 inline SV *to_sv ( signed long long v) { return newSVval64 (v); }
350     inline SV *to_sv (unsigned long long v) { return newSVval64 (v); }
351 root 1.45 inline SV *to_sv (float v) { return newSVnv (v); }
352     inline SV *to_sv (double v) { return newSVnv (v); }
353 root 1.109 inline SV *to_sv (client * v) { return newSVattachable (v, stash_cf_client_wrap); }
354     inline SV *to_sv (player * v) { return newSVattachable (v, stash_cf_player_wrap); }
355     inline SV *to_sv (object * v) { return newSVattachable (v, v && v->type == PLAYER ? stash_cf_object_player_wrap : stash_cf_object_wrap); }
356     inline SV *to_sv (maptile * v) { return newSVattachable (v, stash_cf_map_wrap); }
357     inline SV *to_sv (archetype * v) { return newSVattachable (v, stash_cf_arch_wrap); }
358     inline SV *to_sv (partylist * v) { return newSVptr (v, stash_cf_party_wrap); }
359     inline SV *to_sv (region * v) { return newSVptr (v, stash_cf_region_wrap); }
360     inline SV *to_sv (living * v) { return newSVptr (v, stash_cf_living_wrap); }
361 root 1.45
362     inline SV *to_sv (object & v) { return to_sv (&v); }
363     inline SV *to_sv (living & v) { return to_sv (&v); }
364    
365 root 1.194 inline SV *to_sv (const std::string & v) { return newSVpvn (v.data (), v.size ()); }
366     inline SV *to_sv (const treasurelist *v) { return to_sv (v->name); }
367 root 1.45
368 root 1.69 inline SV *to_sv (UUID v)
369     {
370 elmex 1.68 char buf[128];
371 root 1.159 snprintf (buf, 128, "<1.%" PRIx64 ">", v.seq);
372 elmex 1.68 return newSVpv (buf, 0);
373     }
374    
375 root 1.58 inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPV_nolen (sv) : 0; }
376 root 1.72 inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; }
377 root 1.45 inline void sv_to (SV *sv, bool &v) { v = SvIV (sv); }
378     inline void sv_to (SV *sv, signed char &v) { v = SvIV (sv); }
379     inline void sv_to (SV *sv, unsigned char &v) { v = SvIV (sv); }
380     inline void sv_to (SV *sv, signed short &v) { v = SvIV (sv); }
381     inline void sv_to (SV *sv, unsigned short &v) { v = SvIV (sv); }
382     inline void sv_to (SV *sv, signed int &v) { v = SvIV (sv); }
383     inline void sv_to (SV *sv, unsigned int &v) { v = SvUV (sv); }
384     inline void sv_to (SV *sv, signed long &v) { v = SvIV (sv); }
385     inline void sv_to (SV *sv, unsigned long &v) { v = SvUV (sv); }
386 root 1.53 inline void sv_to (SV *sv, signed long long &v) { v = ( signed long long)SvVAL64 (sv); }
387     inline void sv_to (SV *sv, unsigned long long &v) { v = (unsigned long long)SvVAL64 (sv); }
388 root 1.45 inline void sv_to (SV *sv, float &v) { v = SvNV (sv); }
389     inline void sv_to (SV *sv, double &v) { v = SvNV (sv); }
390 root 1.115 inline void sv_to (SV *sv, client * &v) { v = (client *)(attachable *)SvPTR_ornull (sv, "cf::client"); }
391     inline void sv_to (SV *sv, player * &v) { v = (player *)(attachable *)SvPTR_ornull (sv, "cf::player"); }
392     inline void sv_to (SV *sv, object * &v) { v = (object *)(attachable *)SvPTR_ornull (sv, "cf::object"); }
393     inline void sv_to (SV *sv, archetype * &v) { v = (archetype *)(attachable *)SvPTR_ornull (sv, "cf::arch"); }
394     inline void sv_to (SV *sv, maptile * &v) { v = (maptile *)(attachable *)SvPTR_ornull (sv, "cf::map"); }
395 root 1.128 inline void sv_to (SV *sv, attachable * &v) { v = (attachable *)SvPTR_ornull (sv, "cf::attachable"); }
396 root 1.45 inline void sv_to (SV *sv, partylist * &v) { v = (partylist *)SvPTR_ornull (sv, "cf::party"); }
397     inline void sv_to (SV *sv, region * &v) { v = (region *)SvPTR_ornull (sv, "cf::region"); }
398     inline void sv_to (SV *sv, living * &v) { v = (living *)SvPTR_ornull (sv, "cf::living"); }
399    
400 root 1.176 //inline void sv_to (SV *sv, faceinfo * &v) { v = &faces [face_find (SvPV_nolen (sv), 0)]; }
401 root 1.187 inline void sv_to (SV *sv, treasurelist * &v) { v = treasurelist::find (SvPV_nolen (sv)); }
402 root 1.45
403 root 1.52 template<class T>
404     inline void sv_to (SV *sv, refptr<T> &v) { T *tmp; sv_to (sv, tmp); v = tmp; }
405    
406 root 1.45 template<int N>
407 root 1.55 inline void sv_to (SV *sv, char (&v)[N]) { assign (v, SvPV_nolen (sv)); }
408 root 1.45
409 root 1.106 inline void sv_to (SV *sv, bowtype_t &v) { v = (bowtype_t) SvIV (sv); }
410     inline void sv_to (SV *sv, petmode_t &v) { v = (petmode_t) SvIV (sv); }
411     inline void sv_to (SV *sv, usekeytype &v) { v = (usekeytype) SvIV (sv); }
412     inline void sv_to (SV *sv, unapplymode &v) { v = (unapplymode) SvIV (sv); }
413    
414 root 1.176 inline void sv_to (SV *sv, std::string &v)
415     {
416     STRLEN len;
417     char *data = SvPVbyte (sv, len);
418     v.assign (data, len);
419     }
420    
421 root 1.69 inline void sv_to (SV *sv, UUID &v)
422     {
423     unsigned int version;
424 elmex 1.68
425 root 1.71 if (2 != sscanf (SvPV_nolen (sv), "<%d.%" SCNx64 ">", &version, &v.seq) || 1 != version)
426 root 1.69 croak ("unparsable uuid: %s", SvPV_nolen (sv));
427 elmex 1.68 }
428    
429 root 1.109 inline void sv_to (SV *sv, object::flags_t::reference v) { v = SvTRUE (sv); }
430 root 1.106
431 root 1.1 static SV *
432 root 1.6 newSVdt_va (va_list &ap, data_type type)
433 root 1.1 {
434     SV *sv;
435    
436     switch (type)
437     {
438 root 1.10 case DT_INT:
439     sv = newSViv (va_arg (ap, int));
440     break;
441    
442     case DT_INT64:
443     sv = newSVval64 ((val64)va_arg (ap, sint64));
444     break;
445    
446 root 1.6 case DT_DOUBLE:
447 root 1.10 sv = newSVnv (va_arg (ap, double));
448 root 1.1 break;
449    
450 root 1.6 case DT_STRING:
451     {
452 root 1.10 char *str = (char *)va_arg (ap, const char *);
453 root 1.6 sv = str ? newSVpv (str, 0) : &PL_sv_undef;
454     }
455 root 1.1 break;
456    
457 root 1.6 case DT_DATA:
458 root 1.1 {
459 root 1.10 char *str = (char *)va_arg (ap, const void *);
460 root 1.6 int len = va_arg (ap, int);
461     sv = str ? newSVpv (str, len) : &PL_sv_undef;
462 root 1.1 }
463     break;
464    
465 root 1.6 case DT_OBJECT:
466 root 1.45 sv = to_sv (va_arg (ap, object *));
467 root 1.1 break;
468    
469 root 1.6 case DT_MAP:
470 root 1.11 // va_arg (object *) when void * is passed is an XSI extension
471 root 1.61 sv = to_sv (va_arg (ap, maptile *));
472 root 1.1 break;
473    
474 root 1.88 case DT_CLIENT:
475 root 1.84 sv = to_sv (va_arg (ap, client *));
476 root 1.79 break;
477    
478 root 1.6 case DT_PLAYER:
479 root 1.45 sv = to_sv (va_arg (ap, player *));
480 root 1.1 break;
481    
482 root 1.6 case DT_ARCH:
483 root 1.45 sv = to_sv (va_arg (ap, archetype *));
484 root 1.1 break;
485    
486 root 1.6 case DT_PARTY:
487 root 1.45 sv = to_sv (va_arg (ap, partylist *));
488 root 1.1 break;
489    
490 root 1.6 case DT_REGION:
491 root 1.45 sv = to_sv (va_arg (ap, region *));
492 root 1.1 break;
493    
494     default:
495 root 1.6 assert (("unhandled type in newSVdt_va", 0));
496     }
497    
498     return sv;
499     }
500    
501     static SV *
502     newSVdt (data_type type, ...)
503     {
504     va_list ap;
505    
506     va_start (ap, type);
507     SV *sv = newSVdt_va (ap, type);
508     va_end (ap);
509    
510     return sv;
511     }
512    
513     static SV *
514     newSVcfapi (int type, ...)
515     {
516     SV *sv;
517    
518     va_list ap;
519     va_start (ap, type);
520    
521     switch (type)
522     {
523 root 1.12 case CFAPI_INT: sv = newSViv (*va_arg (ap, int * )); break;
524     case CFAPI_LONG: sv = newSVval64 (*va_arg (ap, sint64 *)); break;
525     case CFAPI_DOUBLE: sv = newSVnv (*va_arg (ap, double *)); break;
526 root 1.6 case CFAPI_STRING: sv = newSVdt_va (ap, DT_STRING); break;
527     case CFAPI_POBJECT: sv = newSVdt_va (ap, DT_OBJECT); break;
528     case CFAPI_PMAP: sv = newSVdt_va (ap, DT_MAP ); break;
529     case CFAPI_PPLAYER: sv = newSVdt_va (ap, DT_PLAYER); break;
530     case CFAPI_PARCH: sv = newSVdt_va (ap, DT_ARCH ); break;
531     case CFAPI_PPARTY: sv = newSVdt_va (ap, DT_PARTY ); break;
532     case CFAPI_PREGION: sv = newSVdt_va (ap, DT_REGION); break;
533    
534     default:
535 root 1.1 assert (("unhandled type in newSVcfapi", 0));
536     }
537    
538 root 1.6 va_end (ap);
539 root 1.1
540     return sv;
541     }
542    
543 root 1.11 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
544    
545 root 1.12 SV *
546 root 1.109 registry (attachable *ext)
547 root 1.12 {
548 root 1.13 if (!ext->cb)
549     ext->cb = newAV ();
550 root 1.12
551 root 1.13 return newRV_inc ((SV *)ext->cb);
552 root 1.12 }
553    
554 root 1.13 /////////////////////////////////////////////////////////////////////////////
555    
556 root 1.1 extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr)
557     {
558     return 0;
559     }
560    
561     static CommArray_s rtn_cmd;
562    
563     static int
564     runPluginCommand (object *obj, char *params)
565     {
566 root 1.73 return -1;
567 root 1.1 }
568    
569     extern "C" void *cfperl_getPluginProperty (int *type, ...)
570     {
571     va_list args;
572     char *propname;
573     int i;
574     va_start (args, type);
575     propname = va_arg (args, char *);
576     //printf ("Property name: %s\n", propname);
577    
578     if (!strcmp (propname, "command?"))
579 root 1.73 return NULL;
580 root 1.1 else if (!strcmp (propname, "Identification"))
581     {
582     va_end (args);
583 root 1.73 return (void *)PLUGIN_NAME;
584 root 1.1 }
585     else if (!strcmp (propname, "FullName"))
586     {
587     va_end (args);
588 root 1.73 return (void *)PLUGIN_VERSION;
589 root 1.1 }
590     else
591     va_end (args);
592    
593     return NULL;
594     }
595    
596     extern "C" int cfperl_postInitPlugin ()
597     {
598     int hooktype = 1;
599     int rtype = 0;
600    
601     cf_init_plugin (gethook);
602    
603     return 0;
604     }
605    
606     extern "C" int cfperl_closePlugin ()
607     {
608     return 0;
609     }
610    
611 root 1.7 void
612     cfperl_init ()
613     {
614 root 1.32 PERL_SYS_INIT3 (&settings.argc, &settings.argv, 0);
615     perl = perl_alloc ();
616     perl_construct (perl);
617    
618     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
619    
620 root 1.179 const char *argv[] = {
621 root 1.198 settings.argv [0],
622 root 1.7 "-e"
623 root 1.107 "use Event; use Coro;" // required for bootstrap
624     "cf->bootstrap;" // required for datadir :*>
625 root 1.32 "unshift @INC, cf::datadir ();"
626 root 1.41 "require cf;"
627 root 1.7 };
628    
629 root 1.179 if (perl_parse (perl, xs_init, 2, (char **)argv, (char **)NULL)
630     || perl_run (perl))
631 root 1.7 {
632     printf ("unable to initialize perl-interpreter, aborting.\n");
633     exit (EXIT_FAILURE);
634     }
635 root 1.162
636     {
637     dSP;
638    
639     PUSHMARK (SP);
640     PUTBACK;
641     call_pv ("cf::init", G_DISCARD | G_VOID);
642     }
643 root 1.7 }
644    
645 root 1.5 void cfperl_main ()
646 root 1.2 {
647     dSP;
648    
649     PUSHMARK (SP);
650     PUTBACK;
651 root 1.7 call_pv ("cf::main", G_DISCARD | G_VOID);
652     }
653    
654 root 1.109 void
655     attachable::instantiate ()
656     {
657     if (attach)
658     {
659     invoke (EVENT_ATTACHABLE_INSTANTIATE, ARG_STRING (attach), DT_END);
660     attach = 0;
661     }
662     }
663    
664     void
665     attachable::reattach ()
666     {
667     optimise ();
668     //TODO: check for _attachment's, very important for restarts
669     invoke (EVENT_ATTACHABLE_REATTACH, DT_END);
670     }
671    
672 root 1.8 static event_klass klass_of[NUM_EVENT_TYPES] = {
673     # define def(type,name) KLASS_ ## type,
674     # include "eventinc.h"
675     # undef def
676     };
677    
678 root 1.18 #define KLASS_OF(event) (((unsigned int)event) < NUM_EVENT_TYPES ? klass_of [event] : KLASS_NONE)
679    
680 root 1.8 static void
681     gather_callbacks (AV *&callbacks, AV *registry, event_type event)
682     {
683     // event must be in array
684     if (event >= 0 && event <= AvFILLp (registry))
685     {
686     SV *cbs_ = AvARRAY (registry)[event];
687    
688     // element must be list of callback entries
689     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
690     {
691     AV *cbs = (AV *)SvRV (cbs_);
692    
693     // no callback entries, no callbacks to call
694     if (AvFILLp (cbs) >= 0)
695     {
696     if (!callbacks)
697     {
698     callbacks = newAV ();
699     av_extend (callbacks, 16);
700     }
701    
702     // never use SvREFCNT_inc to copy values, but its ok here :)
703     for (int i = 0; i <= AvFILLp (cbs); ++i)
704     av_push (callbacks, SvREFCNT_inc (AvARRAY (cbs)[i]));
705     }
706     }
707     }
708     }
709    
710 root 1.109 void
711     attachable::gather_callbacks (AV *&callbacks, event_type event) const
712 root 1.6 {
713 root 1.109 ::gather_callbacks (callbacks, cb_attachable, event);
714 root 1.6
715 root 1.109 if (cb)
716     ::gather_callbacks (callbacks, cb, event);
717     }
718 root 1.8
719 root 1.109 void
720     global::gather_callbacks (AV *&callbacks, event_type event) const
721     {
722     ::gather_callbacks (callbacks, cb_object, event);
723     }
724 root 1.8
725 root 1.109 void
726     object::gather_callbacks (AV *&callbacks, event_type event) const
727     {
728     if (subtype && type + subtype * NUM_SUBTYPES <= AvFILLp (cb_type))
729     {
730     SV *registry = AvARRAY (cb_type)[type + subtype * NUM_SUBTYPES];
731 root 1.8
732 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
733     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
734     }
735 root 1.8
736 root 1.109 if (type <= AvFILLp (cb_type))
737 root 1.8 {
738 root 1.109 SV *registry = AvARRAY (cb_type)[type];
739 root 1.8
740 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
741     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
742     }
743 root 1.8
744 root 1.109 attachable::gather_callbacks (callbacks, event);
745     ::gather_callbacks (callbacks, cb_object, event);
746     }
747 root 1.8
748 root 1.109 void
749     archetype::gather_callbacks (AV *&callbacks, event_type event) const
750     {
751     attachable::gather_callbacks (callbacks, event);
752     //TODO//::gather_callbacks (callbacks, cb_archetype, event);
753     }
754 root 1.14
755 root 1.109 void
756     client::gather_callbacks (AV *&callbacks, event_type event) const
757     {
758     attachable::gather_callbacks (callbacks, event);
759     ::gather_callbacks (callbacks, cb_client, event);
760     }
761 root 1.8
762 root 1.109 void
763     player::gather_callbacks (AV *&callbacks, event_type event) const
764     {
765     attachable::gather_callbacks (callbacks, event);
766     ::gather_callbacks (callbacks, cb_player, event);
767     }
768 root 1.8
769 root 1.109 void
770     maptile::gather_callbacks (AV *&callbacks, event_type event) const
771     {
772     attachable::gather_callbacks (callbacks, event);
773     ::gather_callbacks (callbacks, cb_map, event);
774     }
775 root 1.8
776 root 1.109 bool
777     attachable::invoke (event_type event, ...)
778     {
779     data_type dt;
780     va_list ap;
781 root 1.14
782 root 1.109 va_start (ap, event);
783 root 1.8
784 root 1.109 // callback call ordering should be:
785     // 1. per-object callback
786     // 2. per-class object
787     // 3. per-type callback
788     // 4. global callbacks
789 root 1.12
790 root 1.109 AV *callbacks = 0;
791     gather_callbacks (callbacks, event);
792 root 1.8
793     // short-circuit processing if no callbacks found/defined
794     if (!callbacks)
795     return 0;
796    
797 root 1.116 CALL_BEGIN (3);
798     CALL_ARG_SV (newSViv (event)); // only used for debugging nowadays
799     CALL_ARG_SV (newRV_noinc ((SV *)callbacks));
800 root 1.8
801 root 1.109 //TODO: unhack
802 root 1.116 if (object *op = is_a<object>(this)) CALL_ARG_SV (newSVdt (DT_OBJECT, op));
803     else if (player *pl = is_a<player>(this)) CALL_ARG_SV (newSVdt (DT_PLAYER, pl));
804     else if (client *ns = is_a<client>(this)) CALL_ARG_SV (newSVdt (DT_CLIENT, ns));
805     else if (maptile *m = is_a<maptile>(this)) CALL_ARG_SV (newSVdt (DT_MAP, m));
806 root 1.109 else if (global *gl = is_a<global>(this)) /*nop*/;
807     else
808     abort (); //TODO
809 root 1.7
810 root 1.6 for (;;)
811     {
812 root 1.8 dt = (data_type) va_arg (ap, int);
813 root 1.6
814     if (dt == DT_END)
815     break;
816 root 1.109 else if (dt == DT_AV)
817 root 1.12 {
818     AV *av = va_arg (ap, AV *);
819    
820     for (int i = 0; i <= av_len (av); ++i)
821     XPUSHs (*av_fetch (av, i, 1));
822     }
823     else
824     XPUSHs (sv_2mortal (newSVdt_va (ap, dt)));
825 root 1.6 }
826    
827     va_end (ap);
828    
829 root 1.116 CALL_CALL ("cf::do_invoke", G_SCALAR);
830 root 1.6 count = count > 0 ? POPi : 0;
831    
832 root 1.116 CALL_END;
833 root 1.6
834     return count;
835 root 1.2 }
836    
837 root 1.12 SV *
838     cfperl_result (int idx)
839     {
840     AV *av = get_av ("cfperl::invoke_results", 0);
841     if (!av)
842     return &PL_sv_undef;
843    
844     SV **sv = av_fetch (av, idx, 0);
845     if (!sv)
846     return &PL_sv_undef;
847    
848     return *sv;
849     }
850    
851     int
852     cfperl_result_INT (int idx)
853     {
854     return SvIV (cfperl_result (idx));
855     }
856    
857 root 1.74 double
858 root 1.73 cfperl_result_DOUBLE (int idx)
859     {
860     return SvNV (cfperl_result (idx));
861     }
862    
863 root 1.80 /////////////////////////////////////////////////////////////////////////////
864    
865 root 1.116 void
866 root 1.134 cfperl_emergency_save ()
867 root 1.116 {
868     CALL_BEGIN (0);
869 root 1.134 CALL_CALL ("cf::emergency_save", G_VOID);
870 root 1.116 CALL_END;
871     }
872    
873 root 1.165 void
874     cfperl_cleanup (int make_core)
875     {
876     CALL_BEGIN (1);
877     CALL_ARG (make_core);
878     CALL_CALL ("cf::post_cleanup", G_VOID);
879     CALL_END;
880     }
881    
882 root 1.116 maptile *
883 root 1.126 maptile::find_sync (const char *path, maptile *origin)
884 root 1.116 {
885     CALL_BEGIN (2);
886     CALL_ARG (path);
887     CALL_ARG (origin);
888 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
889 root 1.116
890     maptile *retval;
891    
892     if (count)
893     sv_to (POPs, retval);
894     else
895     retval = 0;
896    
897     CALL_END;
898    
899     return retval;
900     }
901    
902 root 1.135 maptile *
903     maptile::find_async (const char *path, maptile *origin)
904     {
905     CALL_BEGIN (2);
906     CALL_ARG (path);
907     CALL_ARG (origin);
908     CALL_CALL ("cf::map::find_async", G_SCALAR);
909    
910     maptile *retval;
911    
912     if (count)
913     sv_to (POPs, retval);
914     else
915     retval = 0;
916    
917     CALL_END;
918    
919     return retval;
920     }
921    
922 root 1.116 void
923 root 1.126 maptile::do_load_sync ()
924     {
925     CALL_BEGIN (1);
926     CALL_ARG (this);
927     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
928     CALL_END;
929     }
930    
931     void
932 root 1.116 maptile::change_all_map_light (int change)
933     {
934     CALL_BEGIN (1);
935     CALL_ARG (change);
936     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
937     CALL_END;
938     }
939    
940     void
941     object::enter_exit (object *exit)
942     {
943     if (type != PLAYER)
944     return;
945    
946     CALL_BEGIN (2);
947     CALL_ARG (this);
948     CALL_ARG (exit);
949     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
950     CALL_END;
951     }
952    
953 root 1.198 void
954     log_backtrace (const char *msg)
955     {
956     #if HAVE_BACKTRACE
957     void *addr [20];
958     int size = backtrace (addr, 20);
959    
960     CALL_BEGIN (size);
961     CALL_ARG (msg);
962     for (int i = 0; i < size; ++i)
963     CALL_ARG ((IV)addr [i]);
964     CALL_CALL ("cf::_log_backtrace", G_VOID);
965     CALL_END;
966     #endif
967     }
968    
969 root 1.116 /////////////////////////////////////////////////////////////////////////////
970    
971 root 1.80 struct EventAPI *watcher_base::GEventAPI;
972 root 1.116 struct CoroAPI *coroapi::GCoroAPI;
973 root 1.80
974 root 1.124 int coroapi::cede_counter;
975 root 1.189 double (*coroapi::time)();
976     double coroapi::next_cede;
977    
978     void coroapi::do_cede_to_tick ()
979     {
980     cede_counter = 0;
981    
982     cede ();
983    
984     next_cede += (TICK / CEDES_PER_TICK) * 0.99;
985     if (next_cede > SvNV (sv_next_tick) - 0.02)
986     next_cede = SvNV (sv_next_tick);
987     }
988    
989     void coroapi::do_cede_every ()
990     {
991     cede_counter = 0;
992    
993     if (coroapi::nready ())
994     coroapi::cede ();
995     }
996    
997     void coroapi::do_cede_to_tick_every ()
998     {
999     cede_counter = 0;
1000    
1001     cede_to_tick ();
1002     }
1003 root 1.124
1004 root 1.188 void
1005     coroapi::wait_for_tick ()
1006     {
1007     CALL_BEGIN (0);
1008     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1009     CALL_END;
1010     }
1011    
1012     void
1013     coroapi::wait_for_tick_begin ()
1014     {
1015     CALL_BEGIN (0);
1016     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1017     CALL_END;
1018     }
1019    
1020     static void
1021     iw_dispatch (pe_event *ev)
1022 root 1.85 {
1023     iw *w = (iw *)ev->ext_data;
1024     w->call (*w);
1025     }
1026    
1027     void
1028     iw::alloc ()
1029     {
1030     pe = GEventAPI->new_idle (0, 0);
1031    
1032 root 1.150 WaREENTRANT_off (pe);
1033 root 1.85 pe->base.callback = (void *)iw_dispatch;
1034     pe->base.ext_data = (void *)this;
1035     }
1036    
1037 root 1.80 static void iow_dispatch (pe_event *ev)
1038     {
1039     iow *w = (iow *)ev->ext_data;
1040     w->call (*w, ((pe_ioevent *)ev)->got);
1041     }
1042    
1043     void
1044     iow::alloc ()
1045     {
1046     pe = GEventAPI->new_io (0, 0);
1047    
1048 root 1.150 WaREENTRANT_off (pe);
1049 root 1.80 pe->base.callback = (void *)iow_dispatch;
1050     pe->base.ext_data = (void *)this;
1051    
1052 root 1.81 pe->fd = -1;
1053     pe->poll = 0;
1054 root 1.80 }
1055    
1056 root 1.85 void
1057 root 1.80 iow::fd (int fd)
1058     {
1059     pe->fd = fd;
1060     }
1061    
1062     int
1063     iow::poll ()
1064     {
1065     return pe->poll;
1066     }
1067    
1068 root 1.85 void
1069 root 1.80 iow::poll (int events)
1070     {
1071 root 1.81 if (pe->poll != events)
1072     {
1073     if (pe->poll) stop ();
1074     pe->poll = events;
1075     if (pe->poll) start ();
1076     }
1077 root 1.80 }
1078    
1079 root 1.109 void
1080     _connect_to_perl ()
1081     {
1082     stash_cf = gv_stashpv ("cf" , 1);
1083    
1084     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1085     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1086     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1087     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1088     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1089     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1090     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1091     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1092     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1093    
1094 root 1.189 sv_runtime = get_sv ("cf::RUNTIME" , 1); sv_upgrade (sv_runtime , SVt_NV);
1095     sv_next_tick = get_sv ("cf::NEXT_TICK", 1); sv_upgrade (sv_next_tick, SVt_NV);
1096 root 1.116
1097 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1098     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1099     cb_object = get_av ("cf::CB_OBJECT", 1);
1100     cb_player = get_av ("cf::CB_PLAYER", 1);
1101     cb_client = get_av ("cf::CB_CLIENT", 1);
1102     cb_type = get_av ("cf::CB_TYPE" , 1);
1103     cb_map = get_av ("cf::CB_MAP" , 1);
1104     }
1105    
1106 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1107    
1108     BOOT:
1109     {
1110 root 1.116 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1111     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1112 root 1.80
1113 root 1.189 _connect_to_perl ();
1114    
1115 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1116 root 1.63
1117 root 1.189 {
1118     require_pv ("Time::HiRes");
1119    
1120     SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1121     if (!svp) croak ("Time::HiRes is required");
1122     if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1123     coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1124     }
1125    
1126 root 1.1 static const struct {
1127     const char *name;
1128     IV iv;
1129     } *civ, const_iv[] = {
1130     # define const_iv(name) { # name, (IV)name },
1131 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1132 root 1.198 const_iv (logBacktrace)
1133 root 1.180
1134 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1135    
1136     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1137 root 1.180
1138 root 1.5 const_iv (MAX_TIME)
1139 root 1.189
1140 root 1.205 const_iv (NUM_BODY_LOCATIONS) const_iv (BODY_ARMS)
1141    
1142 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1143     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1144     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1145     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1146     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1147     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1148     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1149     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1150     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1151     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1152     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1153     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1154     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1155     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1156     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1157     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1158     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1159     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1160     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1161     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1162     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1163     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1164     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1165     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1166     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1167     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1168     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1169     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1170 root 1.1
1171 root 1.14 const_iv (NUM_SUBTYPES)
1172    
1173 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1174     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1175 root 1.1
1176 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1177     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1178     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1179     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1180     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1181     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1182     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1183    
1184     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1185     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1186 root 1.1 const_iv (WEAP_BLUD)
1187    
1188 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1189     const_iv (FLAG_WAS_WIZ) const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1190     const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1191     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1192     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1193     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1194     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1195     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1196     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1197     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1198     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1199     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1200     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1201     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1202     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1203     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1204     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1205     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1206     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1207     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1208     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1209     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1210     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1211     const_iv (FLAG_OBJ_SAVE_ON_OVL) const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1212     const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1213     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1214    
1215     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1216     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1217     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1218     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1219 root 1.1 const_iv (NDI_ALL)
1220    
1221 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1222     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1223    
1224     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1225    
1226     const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1227     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1228 root 1.1 const_iv (F_LOCKED)
1229    
1230 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1231    
1232     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1233     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1234    
1235     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1236    
1237     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1238     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1239    
1240     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1241     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1242    
1243     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1244    
1245     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1246     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1247     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1248     const_iv (M_ICE) const_iv (M_SPECIAL)
1249    
1250     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1251     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1252    
1253     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1254     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1255     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1256     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1257     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1258     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1259     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1260     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1261     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1262     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1263 root 1.1 const_iv (SK_POISON_NAIL)
1264    
1265 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1266     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1267     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1268     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1269     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1270     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1271    
1272     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1273    
1274     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1275     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1276     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1277     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1278     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1279     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1280     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1281    
1282     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1283    
1284     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1285     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1286    
1287     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1288    
1289     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1290 root 1.99
1291 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1292 root 1.117
1293     // random map generator
1294 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1295     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1296    
1297     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1298     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1299     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1300    
1301     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1302     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1303 root 1.195
1304     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1305     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1306     const_iv (GT_MINIMAL)
1307 root 1.1 };
1308    
1309     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1310 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1311 root 1.1
1312     static const struct {
1313     const char *name;
1314 root 1.14 int skip;
1315 root 1.7 IV klass;
1316 root 1.1 IV iv;
1317 root 1.6 } *eiv, event_iv[] = {
1318 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1319 root 1.6 # include "eventinc.h"
1320     # undef def
1321     };
1322    
1323     AV *av = get_av ("cf::EVENT", 1);
1324    
1325     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1326 root 1.7 {
1327     AV *event = newAV ();
1328 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1329 root 1.7 av_push (event, newSViv (eiv->klass));
1330     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1331 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1332 root 1.7 }
1333 root 1.14 }
1334    
1335 root 1.109 void _connect_to_perl ()
1336 root 1.14
1337 root 1.47 void _global_reattach ()
1338 root 1.14 CODE:
1339     {
1340     // reattach to all attachable objects in the game.
1341 root 1.128 for_all_clients (ns)
1342     ns->reattach ();
1343 root 1.96
1344 root 1.128 for_all_objects (op)
1345 root 1.109 op->reattach ();
1346 root 1.1 }
1347    
1348 root 1.189 void _post_tick ()
1349     CODE:
1350     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1351    
1352 root 1.192 # support function for map-world.ext
1353     void _quantise (SV *data_sv, SV *plt_sv)
1354     CODE:
1355     {
1356     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1357     croak ("_quantise called with invalid agruments");
1358    
1359     plt_sv = SvRV (plt_sv);
1360     SV **plt = AvARRAY (plt_sv);
1361     int plt_count = AvFILL (plt_sv) + 1;
1362    
1363     STRLEN len;
1364     char *data = SvPVbyte (data_sv, len);
1365     char *dst = data;
1366    
1367     while (len >= 3)
1368     {
1369     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1370     {
1371     char *val = SvPVX (*val_sv);
1372    
1373     if (val [0] == data [0]
1374     && val [1] == data [1]
1375     && val [2] == data [2])
1376     {
1377     *dst++ = val [3];
1378     goto next;
1379     }
1380     }
1381    
1382     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1383     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1384     dst - SvPVX (data_sv), len);
1385    
1386     next:
1387     data += 3;
1388     len -= 3;
1389     }
1390    
1391     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1392     }
1393    
1394 root 1.1 NV floor (NV x)
1395    
1396     NV ceil (NV x)
1397    
1398 root 1.143 NV rndm (...)
1399     CODE:
1400     switch (items)
1401     {
1402     case 0: RETVAL = rndm (); break;
1403     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1404     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1405     default: croak ("cf::rndm requires none, one or two parameters."); break;
1406     }
1407     OUTPUT:
1408     RETVAL
1409    
1410 root 1.5 void server_tick ()
1411 root 1.116 CODE:
1412     runtime = SvNVx (sv_runtime);
1413     server_tick ();
1414 root 1.5
1415 root 1.1 void
1416 root 1.198 log_backtrace (utf8_string msg)
1417    
1418     void
1419     LOG (int flags, utf8_string msg)
1420 root 1.1 PROTOTYPE: $$
1421 root 1.198 C_ARGS: flags, "%s", msg
1422 root 1.1
1423 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1424 root 1.1 PROTOTYPE: $$
1425    
1426 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1427 root 1.1 PROTOTYPE: $$
1428    
1429 root 1.183 const_octet_string
1430     get_maps_directory (octet_string path)
1431 root 1.1 PROTOTYPE: $
1432     ALIAS: maps_directory = 0
1433 root 1.19 CODE:
1434     RETVAL = create_pathname (path);
1435     OUTPUT: RETVAL
1436 root 1.1
1437     void
1438     sub_generation_inc ()
1439     CODE:
1440     PL_sub_generation++;
1441    
1442 root 1.183 const_octet_string
1443 root 1.1 mapdir ()
1444     PROTOTYPE:
1445     ALIAS:
1446     mapdir = 0
1447     uniquedir = 1
1448     tmpdir = 2
1449     confdir = 3
1450     localdir = 4
1451     playerdir = 5
1452     datadir = 6
1453     CODE:
1454 root 1.19 switch (ix)
1455     {
1456     case 0: RETVAL = settings.mapdir ; break;
1457     case 1: RETVAL = settings.uniquedir; break;
1458     case 2: RETVAL = settings.tmpdir ; break;
1459     case 3: RETVAL = settings.confdir ; break;
1460     case 4: RETVAL = settings.localdir ; break;
1461     case 5: RETVAL = settings.playerdir; break;
1462     case 6: RETVAL = settings.datadir ; break;
1463     }
1464 root 1.1 OUTPUT: RETVAL
1465    
1466 root 1.120 void abort ()
1467    
1468 root 1.199 void reset_signals ()
1469    
1470 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1471 root 1.144
1472 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1473 root 1.134
1474 root 1.116 void emergency_save ()
1475    
1476 root 1.156 void _exit (int status = EXIT_SUCCESS)
1477    
1478 root 1.149 UV sv_2watcher (SV *w)
1479     CODE:
1480     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1481     OUTPUT:
1482     RETVAL
1483    
1484 root 1.125 #if _POSIX_MEMLOCK
1485    
1486     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1487    
1488     int munlockall ()
1489    
1490     #endif
1491    
1492 root 1.183 int find_animation (utf8_string text)
1493 root 1.1 PROTOTYPE: $
1494    
1495 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1496 root 1.1
1497 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1498 root 1.1
1499     int
1500     exp_to_level (val64 exp)
1501     CODE:
1502     {
1503     int i = 0;
1504    
1505     RETVAL = settings.max_level;
1506    
1507     for (i = 1; i <= settings.max_level; i++)
1508     {
1509     if (levels[i] > exp)
1510     {
1511     RETVAL = i - 1;
1512     break;
1513     }
1514     }
1515     }
1516     OUTPUT: RETVAL
1517    
1518     val64
1519     level_to_min_exp (int level)
1520     CODE:
1521     if (level > settings.max_level)
1522     RETVAL = levels[settings.max_level];
1523     else if (level < 1)
1524     RETVAL = 0;
1525     else
1526     RETVAL = levels[level];
1527     OUTPUT: RETVAL
1528    
1529     SV *
1530     resistance_to_string (int atnr)
1531     CODE:
1532     if (atnr >= 0 && atnr < NROFATTACKS)
1533     RETVAL = newSVpv (resist_plus[atnr], 0);
1534     else
1535     XSRETURN_UNDEF;
1536     OUTPUT: RETVAL
1537    
1538 root 1.162 bool
1539 root 1.183 load_resource_file (octet_string filename)
1540 root 1.162
1541 root 1.97 MODULE = cf PACKAGE = cf::attachable
1542    
1543 root 1.27 int
1544 root 1.97 valid (SV *obj)
1545 root 1.27 CODE:
1546     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1547     OUTPUT:
1548     RETVAL
1549    
1550 root 1.164 void
1551     debug_trace (attachable *obj, bool on = true)
1552     CODE:
1553     obj->flags &= ~attachable::F_DEBUG_TRACE;
1554     if (on)
1555     obj->flags |= attachable::F_DEBUG_TRACE;
1556    
1557 root 1.153 int mortals_size ()
1558     CODE:
1559     RETVAL = attachable::mortals.size ();
1560     OUTPUT: RETVAL
1561    
1562     #object *mortals (U32 index)
1563     # CODE:
1564     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1565     # OUTPUT: RETVAL
1566    
1567 root 1.173 INCLUDE: $PERL $srcdir/genacc attachable ../include/cfperl.h |
1568 root 1.115
1569 root 1.101 MODULE = cf PACKAGE = cf::global
1570    
1571     int invoke (SV *klass, int event, ...)
1572     CODE:
1573     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1574     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1575     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1576 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1577 root 1.101 OUTPUT: RETVAL
1578    
1579 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1580    
1581 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1582 root 1.62
1583 root 1.18 int invoke (object *op, int event, ...)
1584     CODE:
1585     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1586 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1587     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1588 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1589 root 1.18 OUTPUT: RETVAL
1590    
1591     SV *registry (object *op)
1592    
1593 root 1.134 int objects_size ()
1594     CODE:
1595     RETVAL = objects.size ();
1596     OUTPUT: RETVAL
1597    
1598     object *objects (U32 index)
1599     CODE:
1600     RETVAL = index < objects.size () ? objects [index] : 0;
1601     OUTPUT: RETVAL
1602    
1603     int actives_size ()
1604     CODE:
1605     RETVAL = actives.size ();
1606     OUTPUT: RETVAL
1607    
1608     object *actives (U32 index)
1609 root 1.57 CODE:
1610 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1611 root 1.57 OUTPUT: RETVAL
1612    
1613 root 1.205 const char *slot_save_name (U32 slot)
1614     ALIAS:
1615     slot_use_name = 1
1616     slot_nonuse_name = 2
1617     CODE:
1618     {
1619     if (slot >= NUM_BODY_LOCATIONS)
1620     croak ("body slot index out of range");
1621    
1622     switch (ix)
1623     {
1624     case 0: RETVAL = body_locations[slot].save_name; break;
1625     case 1: RETVAL = body_locations[slot].use_name; break;
1626     case 2: RETVAL = body_locations[slot].nonuse_name; break;
1627     }
1628     }
1629     OUTPUT:
1630     RETVAL
1631    
1632 root 1.1 # missing properties
1633    
1634 root 1.54 object *head (object *op)
1635     PROTOTYPE: $
1636     CODE:
1637 root 1.134 RETVAL = op->head_ ();
1638 root 1.54 OUTPUT: RETVAL
1639    
1640     int is_head (object *op)
1641     PROTOTYPE: $
1642     CODE:
1643 root 1.134 RETVAL = op->head_ () == op;
1644 root 1.54 OUTPUT: RETVAL
1645    
1646 root 1.1 void
1647     inv (object *obj)
1648     PROTOTYPE: $
1649     PPCODE:
1650     {
1651     object *o;
1652     for (o = obj->inv; o; o = o->below)
1653 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1654 root 1.1 }
1655    
1656 root 1.102 void
1657     set_animation (object *op, int idx)
1658     CODE:
1659     SET_ANIMATION (op, idx);
1660    
1661 elmex 1.160 int
1662     num_animations (object *op)
1663     CODE:
1664     RETVAL = NUM_ANIMATIONS (op);
1665     OUTPUT: RETVAL
1666    
1667 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1668     ALIAS:
1669     slot_used = 1
1670     CODE:
1671     {
1672     if (slot >= NUM_BODY_LOCATIONS)
1673     croak ("body slot index out of range");
1674    
1675     RETVAL = ix ? op->slot[slot].info : op->slot[slot].used;
1676    
1677     if (items > 2)
1678     if (ix)
1679     op->slot[slot].info = value;
1680     else
1681     op->slot[slot].used = value;
1682     }
1683     OUTPUT:
1684     RETVAL
1685    
1686 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1687 root 1.58
1688     object *find_marked_object (object *op)
1689    
1690 root 1.109 int need_identify (object *obj);
1691 root 1.1
1692     int apply_shop_mat (object *shop_mat, object *op);
1693    
1694 pippijn 1.172 int move_player (object *op, int dir)
1695     CODE:
1696     RETVAL = move_player (op, dir);
1697     OUTPUT:
1698     RETVAL
1699    
1700 root 1.27 int move (object *op, int dir, object *originator = op)
1701     CODE:
1702     RETVAL = move_ob (op, dir, originator);
1703     OUTPUT:
1704     RETVAL
1705 root 1.1
1706 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1707     CODE:
1708     manual_apply (applied, applier, flags);
1709 root 1.1
1710 root 1.74 void apply_below (object *op)
1711     CODE:
1712     player_apply_below (op);
1713 root 1.1
1714 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1715    
1716 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1717 root 1.1
1718     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1719    
1720 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1721 root 1.1
1722 root 1.116 #//TODO
1723     object *clone_ (object *op, int recursive = 0)
1724 root 1.74 CODE:
1725     if (recursive)
1726     RETVAL = object_create_clone (op);
1727     else
1728     {
1729     RETVAL = object::create ();
1730 root 1.75 op->copy_to (RETVAL);
1731 root 1.74 }
1732     OUTPUT: RETVAL
1733 root 1.1
1734 root 1.74 int pay_item (object *op, object *buyer)
1735     CODE:
1736     RETVAL = pay_for_item (op, buyer);
1737     OUTPUT: RETVAL
1738 root 1.1
1739 root 1.74 int pay_amount (object *op, uint64 amount)
1740     CODE:
1741     RETVAL = pay_for_amount (amount, op);
1742     OUTPUT: RETVAL
1743 root 1.1
1744     void pay_player (object *op, uint64 amount)
1745    
1746 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1747 root 1.1
1748 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1749 root 1.1
1750 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1751     CODE:
1752     do_learn_spell (op, sp, special_prayer);
1753 root 1.1
1754 root 1.74 void forget_spell (object *op, object *sp)
1755     CODE:
1756     do_forget_spell (op, query_name (sp));
1757 root 1.1
1758 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1759 root 1.74 CODE:
1760     RETVAL = check_spell_known (op, spellname);
1761     OUTPUT: RETVAL
1762 root 1.1
1763 root 1.74 int query_money (object *op)
1764 root 1.1 ALIAS: money = 0
1765    
1766 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1767 root 1.1 ALIAS: cost = 0
1768    
1769 root 1.74 void spring_trap (object *op, object *victim)
1770 root 1.1
1771 root 1.74 int check_trigger (object *op, object *cause)
1772 root 1.1
1773 root 1.74 void drop (object *who, object *op)
1774 root 1.1
1775 root 1.74 void pick_up (object *who, object *op)
1776 root 1.1
1777 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
1778 root 1.1
1779 root 1.102 void update_object (object *op, int action)
1780 root 1.1
1781 root 1.183 object *cf_create_object_by_name (utf8_string name)
1782 root 1.1
1783 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
1784 root 1.1
1785     void player_lvl_adj (object *who, object *skill = 0)
1786    
1787     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1788    
1789     int calc_skill_exp (object *who, object *op, object *skill);
1790    
1791     void push_button (object *op);
1792    
1793     void use_trigger (object *op);
1794    
1795 root 1.61 void add_button_link (object *button, maptile *map, int connected);
1796 root 1.1
1797     void remove_button_link (object *op);
1798    
1799    
1800     MODULE = cf PACKAGE = cf::object PREFIX = cf_
1801    
1802     object *cf_insert_ob_in_ob (object *ob, object *where)
1803    
1804     # no clean way to get an object from an archetype - stupid idiotic
1805     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1806    
1807 root 1.183 object *new (utf8_string archetype = 0)
1808 root 1.1 PROTOTYPE: ;$
1809     CODE:
1810     RETVAL = archetype ? get_archetype (archetype) : cf_create_object ();
1811     OUTPUT:
1812     RETVAL
1813    
1814 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1815 root 1.1 PROTOTYPE: $$$$$$
1816     CODE:
1817     {
1818     int unused_type;
1819     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1820     }
1821    
1822     player *contr (object *op)
1823     CODE:
1824     RETVAL = op->contr;
1825     OUTPUT: RETVAL
1826    
1827 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
1828 root 1.1
1829 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
1830 root 1.1
1831     object *get_nearest_player (object *ob)
1832     ALIAS: nearest_player = 0
1833     PREINIT:
1834     extern object *get_nearest_player (object *);
1835    
1836     void rangevector (object *ob, object *other, int flags = 0)
1837     PROTOTYPE: $$;$
1838     PPCODE:
1839     {
1840     rv_vector rv;
1841     get_rangevector (ob, other, &rv, flags);
1842     EXTEND (SP, 5);
1843     PUSHs (newSVuv (rv.distance));
1844     PUSHs (newSViv (rv.distance_x));
1845     PUSHs (newSViv (rv.distance_y));
1846     PUSHs (newSViv (rv.direction));
1847     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
1848     }
1849    
1850     bool on_same_map_as (object *ob, object *other)
1851     CODE:
1852     RETVAL = on_same_map (ob, other);
1853     OUTPUT: RETVAL
1854    
1855 root 1.183 const_utf8_string
1856 root 1.58 base_name (object *op, int plural = op->nrof > 1)
1857 root 1.1 CODE:
1858 root 1.58 RETVAL = query_base_name (op, plural);
1859 root 1.1 OUTPUT: RETVAL
1860    
1861 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
1862    
1863 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
1864    
1865     player *player (object *op)
1866     CODE:
1867     RETVAL = op->contr;
1868     OUTPUT: RETVAL
1869    
1870 root 1.105 void check_score (object *op)
1871    
1872 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
1873 root 1.120 CODE:
1874     new_draw_info (flags, 0, op, txt);
1875 root 1.1
1876     object *cf_player_send_inventory (object *op)
1877    
1878 root 1.183 octet_string cf_player_get_ip (object *op)
1879 root 1.1 ALIAS: ip = 0
1880    
1881     object *cf_player_get_marked_item (object *op)
1882     ALIAS: marked_item = 0
1883    
1884     void cf_player_set_marked_item (object *op, object *ob)
1885    
1886     partylist *cf_player_get_party (object *op)
1887     ALIAS: party = 0
1888    
1889     void cf_player_set_party (object *op, partylist *party)
1890    
1891     void kill_player (object *op)
1892    
1893 root 1.58 void esrv_update_item (object *op, int what, object *item)
1894     C_ARGS: what, op, item
1895    
1896 root 1.66 void clear_los (object *op)
1897    
1898 root 1.183 int command_summon (object *op, utf8_string params)
1899 root 1.67
1900 root 1.183 int command_arrest (object *op, utf8_string params)
1901 root 1.67
1902 root 1.66
1903 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
1904 root 1.1
1905 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
1906 root 1.62
1907 root 1.18 int invoke (player *pl, int event, ...)
1908     CODE:
1909     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
1910 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1911     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1912 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
1913 root 1.18 OUTPUT: RETVAL
1914    
1915 root 1.12 SV *registry (player *pl)
1916 root 1.1
1917 root 1.102 void
1918     save_stats (player *pl)
1919     CODE:
1920     pl->ob->stats.hp = pl->ob->stats.maxhp;
1921     pl->ob->stats.sp = pl->ob->stats.maxsp;
1922     pl->ob->stats.grace = pl->ob->stats.maxgrace;
1923     pl->orig_stats = pl->ob->stats;
1924    
1925 root 1.1 void cf_player_move (player *pl, int dir)
1926    
1927     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
1928    
1929     bool
1930     cell_visible (player *pl, int dx, int dy)
1931     CODE:
1932 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
1933     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
1934 root 1.1 OUTPUT:
1935     RETVAL
1936    
1937 root 1.4 void
1938 root 1.1 send (player *pl, SV *packet)
1939     CODE:
1940     {
1941     STRLEN len;
1942     char *buf = SvPVbyte (packet, len);
1943    
1944 root 1.100 if (pl->ns)
1945     pl->ns->send_packet (buf, len);
1946 root 1.1 }
1947    
1948     int
1949     listening (player *pl, int new_value = -1)
1950     CODE:
1951     RETVAL = pl->listening;
1952     if (new_value >= 0)
1953     pl->listening = new_value;
1954     OUTPUT:
1955     RETVAL
1956    
1957 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
1958 root 1.45 PROTOTYPE: $;$$$
1959 root 1.1 PPCODE:
1960 root 1.45 if (GIMME_V != G_VOID)
1961     {
1962     EXTEND (SP, 3);
1963     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
1964     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
1965     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
1966     }
1967 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
1968     if (x) sv_to (x, pl->bed_x);
1969     if (y) sv_to (y, pl->bed_y);
1970 root 1.1
1971     void
1972     list ()
1973     PPCODE:
1974 root 1.128 for_all_players (pl)
1975 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
1976 root 1.1
1977    
1978     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
1979    
1980 root 1.61 int invoke (maptile *map, int event, ...)
1981 root 1.18 CODE:
1982     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
1983 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1984     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1985 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
1986 root 1.25 OUTPUT: RETVAL
1987 root 1.18
1988 root 1.61 SV *registry (maptile *map)
1989 root 1.12
1990 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
1991 root 1.1
1992 root 1.116 void
1993     maptile::instantiate ()
1994    
1995     maptile *new ()
1996 root 1.1 PROTOTYPE:
1997     CODE:
1998 root 1.116 RETVAL = new maptile;
1999 root 1.1 OUTPUT:
2000     RETVAL
2001    
2002 root 1.116 void
2003 root 1.117 maptile::players ()
2004     PPCODE:
2005     if (GIMME_V == G_SCALAR)
2006 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2007 root 1.117 else if (GIMME_V == G_ARRAY)
2008     {
2009     EXTEND (SP, THIS->players);
2010     for_all_players (pl)
2011     if (pl->ob && pl->ob->map == THIS)
2012 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2013 root 1.117 }
2014    
2015 root 1.156 void
2016 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2017 root 1.156 CODE:
2018     {
2019 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2020     croak ("maptile::add_underlay: palette must be arrayref");
2021 root 1.156
2022 root 1.168 palette = SvRV (palette);
2023 root 1.156
2024 root 1.168 STRLEN idxlen;
2025     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2026 root 1.156
2027 root 1.168 for (int x = 0; x < THIS->width; ++x)
2028     for (int y = 0; y < THIS->height; ++y)
2029     {
2030     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2031     if (op->flag [FLAG_IS_FLOOR])
2032     goto skip_space;
2033    
2034     {
2035     int offs = offset + y * stride + x;
2036     if (IN_RANGE_EXC (offs, 0, idxlen))
2037     {
2038     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2039     {
2040     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2041     ob->flag [FLAG_NO_MAP_SAVE] = true;
2042     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2043 root 1.200
2044     if (ob->randomitems)
2045     {
2046 root 1.203 if (!ob->above)
2047     {
2048     ob->create_treasure (ob->randomitems);
2049    
2050     for (object *op = ob->above; op; op = op->above)
2051     op->flag [FLAG_NO_MAP_SAVE] = true;
2052     }
2053    
2054 root 1.200 ob->randomitems = 0;
2055     }
2056 root 1.168 }
2057     }
2058     }
2059 root 1.156
2060 root 1.168 skip_space: ;
2061     }
2062     }
2063    
2064     void
2065     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2066     CODE:
2067     {
2068     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2069     croak ("maptile::set_regiondata: palette must be arrayref");
2070    
2071     palette = SvRV (palette);
2072    
2073     STRLEN idxlen;
2074     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2075    
2076     region **regionmap = (region **)malloc (
2077     (av_len ((AV *)palette) + 1) * sizeof (region *));
2078     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2079    
2080     for (int i = av_len ((AV *)palette) + 1; i--; )
2081     regionmap [i] = region::find (
2082     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2083    
2084     for (int y = 0; y < THIS->height; ++y)
2085     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2086    
2087     sfree (THIS->regions, THIS->size ());
2088     free (THIS->regionmap);
2089    
2090     THIS->regions = regions;
2091 root 1.156 THIS->regionmap = regionmap;
2092     }
2093    
2094 root 1.193 void
2095     maptile::create_region_treasure ()
2096     CODE:
2097     {
2098     object *op = object::create ();
2099     op->type = FLOOR;
2100     op->map = THIS;
2101    
2102     for (int x = 0; x < THIS->width; ++x)
2103     for (int y = 0; y < THIS->height; ++y)
2104     {
2105     region *rgn = THIS->region (x, y);
2106    
2107     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2108     if (rgn->treasure && rndm () < rgn->treasure_density)
2109     {
2110     op->x = x;
2111     op->y = y;
2112     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2113     }
2114     }
2115    
2116     op->destroy ();
2117     }
2118    
2119 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2120 root 1.1
2121 root 1.74 int out_of_map (maptile *map, int x, int y)
2122    
2123 root 1.29 void
2124 root 1.61 trigger (maptile *map, long connection, bool state = true)
2125 root 1.29 CODE:
2126     activate_connection (map, connection, state);
2127    
2128     void
2129 root 1.61 get_connection (maptile *map, long connection)
2130 root 1.29 PPCODE:
2131     oblinkpt *obp = get_connection_links (map, connection);
2132     if (obp)
2133     for (objectlink *ol = obp->link; ol; ol = ol->next)
2134 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2135 root 1.29
2136 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2137 root 1.1
2138 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2139 root 1.1
2140 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2141 root 1.1 C_ARGS: str, map, nx, ny
2142    
2143     void
2144 root 1.140 get_map_flags (maptile *map, int x, int y)
2145 root 1.1 PPCODE:
2146     {
2147 root 1.61 maptile *nmap = 0;
2148 root 1.1 I16 nx = 0, ny = 0;
2149 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2150 root 1.1
2151     EXTEND (SP, 4);
2152     PUSHs (sv_2mortal (newSViv (flags)));
2153    
2154     if (GIMME_V == G_ARRAY)
2155     {
2156     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2157     PUSHs (sv_2mortal (newSViv (nx)));
2158     PUSHs (sv_2mortal (newSViv (ny)));
2159     }
2160     }
2161    
2162     void
2163 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2164 root 1.1 PROTOTYPE: $$$
2165     PPCODE:
2166     {
2167     object *o;
2168 root 1.61 maptile *nmap = 0;
2169 root 1.1 I16 nx, ny;
2170    
2171 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2172 root 1.1
2173     if (nmap)
2174     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2175     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2176     }
2177    
2178     SV *
2179 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2180 root 1.1 PROTOTYPE: $$$
2181     ALIAS:
2182     top_at = 1
2183     flags_at = 2
2184     light_at = 3
2185     move_block_at = 4
2186     move_slow_at = 5
2187     move_on_at = 6
2188     move_off_at = 7
2189     INIT:
2190 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2191 root 1.1 CODE:
2192     switch (ix)
2193     {
2194     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2195     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2196     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2197     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2198     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2199     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2200     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2201     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2202     }
2203 root 1.122 OUTPUT: RETVAL
2204 root 1.1
2205 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2206    
2207     void fix_walls_around (maptile *map, int x, int y)
2208 root 1.1
2209 root 1.117 # worst xs function of my life
2210 root 1.140 bool
2211 root 1.117 _create_random_map (\
2212 root 1.140 maptile *self,\
2213 root 1.183 utf8_string wallstyle,\
2214     utf8_string wall_name,\
2215     utf8_string floorstyle,\
2216     utf8_string monsterstyle,\
2217     utf8_string treasurestyle,\
2218     utf8_string layoutstyle,\
2219     utf8_string doorstyle,\
2220     utf8_string decorstyle,\
2221     utf8_string origin_map,\
2222     utf8_string final_map,\
2223     utf8_string exitstyle,\
2224     utf8_string this_map,\
2225     utf8_string exit_on_final_map,\
2226 root 1.146 int xsize,\
2227     int ysize,\
2228 root 1.117 int expand2x,\
2229     int layoutoptions1,\
2230     int layoutoptions2,\
2231     int layoutoptions3,\
2232     int symmetry,\
2233     int difficulty,\
2234     int difficulty_given,\
2235     float difficulty_increase,\
2236     int dungeon_level,\
2237     int dungeon_depth,\
2238     int decoroptions,\
2239     int orientation,\
2240     int origin_y,\
2241     int origin_x,\
2242 root 1.146 U32 random_seed,\
2243 root 1.117 val64 total_map_hp,\
2244     int map_layout_style,\
2245     int treasureoptions,\
2246     int symmetry_used,\
2247 root 1.137 region *region,\
2248 root 1.183 utf8_string custom\
2249 root 1.117 )
2250     CODE:
2251     {
2252     random_map_params rmp;
2253    
2254     assign (rmp.wallstyle , wallstyle);
2255     assign (rmp.wall_name , wall_name);
2256     assign (rmp.floorstyle , floorstyle);
2257     assign (rmp.monsterstyle , monsterstyle);
2258     assign (rmp.treasurestyle , treasurestyle);
2259     assign (rmp.layoutstyle , layoutstyle);
2260     assign (rmp.doorstyle , doorstyle);
2261     assign (rmp.decorstyle , decorstyle);
2262     assign (rmp.exitstyle , exitstyle);
2263     assign (rmp.exit_on_final_map, exit_on_final_map);
2264    
2265 root 1.122 rmp.origin_map = origin_map;
2266     rmp.final_map = final_map;
2267     rmp.this_map = this_map;
2268 root 1.146 rmp.xsize = xsize;
2269     rmp.ysize = ysize;
2270 root 1.117 rmp.expand2x = expand2x;
2271     rmp.layoutoptions1 = layoutoptions1;
2272     rmp.layoutoptions2 = layoutoptions2;
2273     rmp.layoutoptions3 = layoutoptions3;
2274     rmp.symmetry = symmetry;
2275     rmp.difficulty = difficulty;
2276     rmp.difficulty_given = difficulty_given;
2277     rmp.difficulty_increase = difficulty_increase;
2278     rmp.dungeon_level = dungeon_level;
2279     rmp.dungeon_depth = dungeon_depth;
2280     rmp.decoroptions = decoroptions;
2281     rmp.orientation = orientation;
2282     rmp.origin_y = origin_y;
2283     rmp.origin_x = origin_x;
2284     rmp.random_seed = random_seed;
2285     rmp.total_map_hp = total_map_hp;
2286     rmp.map_layout_style = map_layout_style;
2287     rmp.treasureoptions = treasureoptions;
2288     rmp.symmetry_used = symmetry_used;
2289     rmp.region = region;
2290 root 1.137 rmp.custom = custom;
2291 root 1.117
2292 root 1.140 RETVAL = self->generate_random_map (&rmp);
2293 root 1.117 }
2294     OUTPUT:
2295     RETVAL
2296    
2297 root 1.19 MODULE = cf PACKAGE = cf::arch
2298 root 1.1
2299 root 1.183 archetype *find (utf8_string name)
2300 elmex 1.36 CODE:
2301 root 1.60 RETVAL = archetype::find (name);
2302 elmex 1.36 OUTPUT:
2303     RETVAL
2304    
2305 root 1.19 archetype *first()
2306 root 1.1 PROTOTYPE:
2307 root 1.19 CODE:
2308     RETVAL = first_archetype;
2309     OUTPUT: RETVAL
2310 root 1.1
2311 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2312 root 1.1
2313 root 1.19 MODULE = cf PACKAGE = cf::party
2314 root 1.1
2315 root 1.19 partylist *first ()
2316 root 1.1 PROTOTYPE:
2317 root 1.19 CODE:
2318     RETVAL = get_firstparty ();
2319     OUTPUT: RETVAL
2320 root 1.1
2321 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2322 root 1.1
2323 root 1.19 MODULE = cf PACKAGE = cf::region
2324 root 1.1
2325 root 1.161 void
2326     list ()
2327     PPCODE:
2328     for_all_regions (rgn)
2329     XPUSHs (sv_2mortal (to_sv (rgn)));
2330    
2331 root 1.183 region *find (utf8_string name)
2332 root 1.161 PROTOTYPE: $
2333 root 1.19 CODE:
2334 root 1.161 RETVAL = region::find (name);
2335 root 1.19 OUTPUT: RETVAL
2336 root 1.1
2337 root 1.183 region *find_fuzzy (utf8_string name)
2338 root 1.122 PROTOTYPE: $
2339     CODE:
2340 root 1.161 RETVAL = region::find_fuzzy (name);
2341 root 1.122 OUTPUT: RETVAL
2342    
2343 root 1.186 int specificity (region *rgn)
2344     CODE:
2345     RETVAL = 0;
2346     while (rgn = rgn->parent)
2347     RETVAL++;
2348     OUTPUT: RETVAL
2349    
2350 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2351 root 1.1
2352 root 1.19 MODULE = cf PACKAGE = cf::living
2353 root 1.1
2354 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2355 root 1.1
2356 root 1.76 MODULE = cf PACKAGE = cf::settings
2357    
2358 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2359 root 1.76
2360 root 1.84 MODULE = cf PACKAGE = cf::client
2361 root 1.79
2362 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2363 root 1.79
2364 root 1.84 int invoke (client *ns, int event, ...)
2365 root 1.79 CODE:
2366 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2367 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2368     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2369 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2370 root 1.79 OUTPUT: RETVAL
2371    
2372 root 1.84 SV *registry (client *ns)
2373 root 1.79
2374 root 1.100 void
2375     list ()
2376     PPCODE:
2377     EXTEND (SP, clients.size ());
2378     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2379     PUSHs (sv_2mortal (to_sv (*i)));
2380    
2381 root 1.88 void
2382 root 1.100 client::send_packet (SV *packet)
2383     CODE:
2384     {
2385     STRLEN len;
2386     char *buf = SvPVbyte (packet, len);
2387    
2388     THIS->send_packet (buf, len);
2389     }
2390    
2391 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2392    
2393 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2394 root 1.176
2395 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2396 root 1.176
2397 root 1.183 faceidx alloc (utf8_string name)
2398 root 1.176 CODE:
2399     {
2400     do
2401     {
2402     RETVAL = faces.size ();
2403 root 1.177 faces.resize (RETVAL + 1);
2404 root 1.176 }
2405     while (!RETVAL); // crude way to leave index 0
2406    
2407     faces [RETVAL].name = name;
2408     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2409    
2410     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2411     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2412     }
2413     OUTPUT: RETVAL
2414    
2415 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2416 root 1.176 CODE:
2417 root 1.177 faceinfo *f = face_info (idx);
2418     assert (f);
2419     f->visibility = visibility;
2420     f->magicmap = magicmap;
2421 root 1.176
2422 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2423 root 1.177 CODE:
2424 root 1.184 faceinfo *f = face_info (idx); assert (f);
2425     f->smooth = smooth;
2426     f->smoothlevel = smoothlevel;
2427 root 1.177
2428     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2429 root 1.176 CODE:
2430 root 1.182 {
2431 root 1.176 facedata *d = face_data (idx, faceset);
2432 root 1.177 assert (d);
2433 root 1.181 sv_to (data, d->data);
2434     STRLEN clen;
2435     char *cdata = SvPVbyte (chksum, clen);
2436 root 1.182 clen = min (CHKSUM_SIZE, clen);
2437    
2438     if (memcmp (d->chksum, cdata, clen))
2439     {
2440     memcpy (d->chksum, cdata, clen);
2441    
2442     // invalidate existing client face info
2443     for_all_clients (ns)
2444     if (ns->faceset == faceset)
2445     {
2446     ns->faces_sent [idx] = false;
2447     ns->force_newmap = true;
2448     }
2449     }
2450     }
2451 root 1.176
2452 root 1.177 void invalidate (faceidx idx)
2453     CODE:
2454     for_all_clients (ns)
2455 root 1.182 {
2456     ns->faces_sent [idx] = false;
2457     ns->force_newmap = true;
2458     }
2459 root 1.177
2460     void invalidate_all ()
2461     CODE:
2462     for_all_clients (ns)
2463 root 1.182 {
2464     ns->faces_sent.reset ();
2465     ns->force_newmap = true;
2466     }
2467 root 1.177
2468 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2469    
2470     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2471    
2472     animidx anim_find (utf8_string name)
2473     CODE:
2474     RETVAL = animation::find (name).number;
2475     OUTPUT: RETVAL
2476    
2477     animidx set (utf8_string name, SV *frames, int facings = 1)
2478     CODE:
2479     {
2480     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2481     croak ("frames must be an arrayref");
2482    
2483     AV *av = (AV *)SvRV (frames);
2484    
2485     animation *anim = &animation::find (name);
2486     if (anim->number)
2487     {
2488     anim->resize (av_len (av) + 1);
2489     anim->facings = facings;
2490     }
2491     else
2492     anim = &animation::create (name, av_len (av) + 1, facings);
2493    
2494     for (int i = 0; i < anim->num_animations; ++i)
2495     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2496     }
2497     OUTPUT: RETVAL
2498    
2499     void invalidate_all ()
2500     CODE:
2501     for_all_clients (ns)
2502     ns->anims_sent.reset ();
2503