ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.221
Committed: Sat Jun 16 00:12:20 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.220: +50 -2 lines
Log Message:
add some debugging code, fix players not getting freed on logout

File Contents

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