ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.213
Committed: Thu May 24 03:33:29 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.212: +10 -0 lines
Log Message:
add books from books.pod via some most dire hacks

File Contents

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