ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/arch.C
Revision: 1.68
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.67: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.37 *
4 root 1.61 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.37 *
8 root 1.68 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.37 *
13 root 1.68 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.37 *
18 root 1.68 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.61 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.37 */
23 elmex 1.1
24 root 1.12 #include <cassert>
25    
26 elmex 1.1 #include <global.h>
27     #include <funcpoint.h>
28     #include <loader.h>
29    
30 root 1.38 #include <tr1/functional>
31     #include <tr1/unordered_map>
32 elmex 1.1
33     /* The naming of these functions is really poor - they are all
34     * pretty much named '.._arch_...', but they may more may not
35     * return archetypes. Some make the arch_to_object call, and thus
36     * return an object. Perhaps those should be called 'archob' functions
37     * to denote they return an object derived from the archetype.
38     * MSW 2003-04-29
39     */
40    
41 root 1.46 bool loading_arch; // ugly flag to object laoder etc. to suppress/request special processing
42    
43 root 1.12 // the hashtable
44 root 1.18 typedef std::tr1::unordered_map
45     <
46 root 1.38 const char *,
47 root 1.26 arch_ptr,
48 root 1.38 str_hash,
49     str_equal,
50     slice_allocator< std::pair<const char *const, arch_ptr> >
51 root 1.18 > HT;
52    
53 root 1.38 static HT ht (5000);
54 root 1.62 archvec archetypes;
55 root 1.12
56 elmex 1.1 /**
57     * GROS - This function retrieves an archetype given the name that appears
58     * during the game (for example, "writing pen" instead of "stylus").
59     * It does not use the hashtable system, but browse the whole archlist each time.
60     * I suggest not to use it unless you really need it because of performance issue.
61     * It is currently used by scripting extensions (create-object).
62     * Params:
63     * - name: the name we're searching for (ex: "writing pen");
64     * Return value:
65     * - the archetype found or null if nothing was found.
66     */
67 root 1.12 archetype *
68     find_archetype_by_object_name (const char *name)
69     {
70 root 1.39 shstr_cmp name_cmp (name);
71 elmex 1.1
72 root 1.63 for_all_archetypes (at)
73 root 1.66 if (at->name == name_cmp)
74 root 1.39 return at;
75 elmex 1.1
76 root 1.39 return 0;
77 elmex 1.1 }
78    
79     /**
80     * This function retrieves an archetype by type and name that appears during
81     * the game. It is basically the same as find_archetype_by_object_name()
82     * except that it considers only items of the given type.
83     */
84 root 1.12 archetype *
85     find_archetype_by_object_type_name (int type, const char *name)
86     {
87 root 1.39 shstr_cmp name_cmp (name);
88 elmex 1.1
89 root 1.63 for_all_archetypes (at)
90 root 1.66 if (at->name == name_cmp && at->type == type)
91 root 1.39 return at;
92 elmex 1.1
93 root 1.39 return 0;
94 elmex 1.1 }
95    
96     /* This is a lot like the above function. Instead, we are trying to match
97     * the arch->skill values. type is the type of object to match
98     * against (eg, to only match against skills or only skill objects for example).
99     * If type is -1, ew don't match on type.
100     */
101 root 1.12 object *
102     get_archetype_by_skill_name (const char *skill, int type)
103     {
104 root 1.39 shstr_cmp skill_cmp (skill);
105 elmex 1.1
106 root 1.63 for_all_archetypes (at)
107     if (at->skill == skill_cmp && (type == -1 || type == at->type))
108 root 1.39 return arch_to_object (at);
109 root 1.35
110     return 0;
111 elmex 1.1 }
112    
113     /* similiar to above - this returns the first archetype
114     * that matches both the type and subtype. type and subtype
115     * can be -1 to say ignore, but in this case, the match it does
116     * may not be very useful. This function is most useful when
117     * subtypes are known to be unique for a particular type
118     * (eg, skills)
119     */
120 root 1.12 archetype *
121     get_archetype_by_type_subtype (int type, int subtype)
122     {
123 root 1.63 for_all_archetypes (at)
124     if ((type == -1 || type == at->type) && (subtype == -1 || subtype == at->subtype))
125 root 1.39 return at;
126 elmex 1.1
127 root 1.39 return 0;
128 elmex 1.1 }
129    
130     /**
131     * GROS - this returns a new object given the name that appears during the game
132     * (for example, "writing pen" instead of "stylus").
133     * Params:
134     * - name: The name we're searching for (ex: "writing pen");
135     * Return value:
136     * - a corresponding object if found; a singularity object if not found.
137     * Note by MSW - it appears that it takes the full name and keeps
138     * shortening it until it finds a match. I re-wrote this so that it
139     * doesn't malloc it each time - not that this function is used much,
140     * but it otherwise had a big memory leak.
141     */
142 root 1.12 object *
143     get_archetype_by_object_name (const char *name)
144     {
145 root 1.17 char tmpname[MAX_BUF];
146     int i;
147    
148     assign (tmpname, name);
149 root 1.12
150     for (i = strlen (tmpname); i > 0; i--)
151     {
152     tmpname[i] = 0;
153 root 1.17
154 root 1.39 if (archetype *at = find_archetype_by_object_name (tmpname))
155 root 1.20 return arch_to_object (at);
156 elmex 1.1 }
157 root 1.17
158 root 1.12 return create_singularity (name);
159 elmex 1.1 }
160    
161 root 1.65 /* This is a subset of the parse_id command. Basically, name can be
162     * a string seperated lists of things to match, with certain keywords.
163     * pl is the player (only needed to set count properly)
164     * op is the item we are trying to match. Calling function takes care
165     * of what action might need to be done and if it is valid
166     * (pickup, drop, etc.) Return NONZERO if we have a match. A higher
167     * value means a better match. 0 means no match.
168     *
169     * Brief outline of the procedure:
170     * We take apart the name variable into the individual components.
171     * cases for 'all' and unpaid are pretty obvious.
172     * Next, we check for a count (either specified in name, or in the
173     * player object.)
174     * If count is 1, make a quick check on the name.
175     * IF count is >1, we need to make plural name. Return if match.
176     * Last, make a check on the full name.
177     */
178 root 1.12 int
179 root 1.15 item_matched_string (object *pl, object *op, const char *name)
180 elmex 1.1 {
181 root 1.22 char *cp, local_name[MAX_BUF];
182     int count, retval = 0;
183 root 1.15
184 root 1.40 assign (local_name, name); /* strtok is destructive to name */
185 root 1.12
186     for (cp = strtok (local_name, ","); cp; cp = strtok (NULL, ","))
187     {
188     while (cp[0] == ' ')
189     ++cp; /* get rid of spaces */
190    
191     /* LOG(llevDebug,"Trying to match %s\n", cp); */
192     /* All is a very generic match - low match value */
193     if (!strcmp (cp, "all"))
194     return 1;
195    
196     /* unpaid is a little more specific */
197     if (!strcmp (cp, "unpaid") && QUERY_FLAG (op, FLAG_UNPAID))
198     return 2;
199     if (!strcmp (cp, "cursed") && QUERY_FLAG (op, FLAG_KNOWN_CURSED) && (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)))
200     return 2;
201    
202     if (!strcmp (cp, "unlocked") && !QUERY_FLAG (op, FLAG_INV_LOCKED))
203     return 2;
204    
205     /* Allow for things like '100 arrows' */
206     if ((count = atoi (cp)) != 0)
207     {
208     cp = strchr (cp, ' ');
209     while (cp && cp[0] == ' ')
210     ++cp; /* get rid of spaces */
211     }
212     else
213     {
214     if (pl->type == PLAYER)
215     count = pl->contr->count;
216     else
217     count = 0;
218     }
219    
220     if (!cp || cp[0] == '\0' || count < 0)
221     return 0;
222    
223    
224     /* The code here should go from highest retval to lowest. That
225     * is because of the 'else' handling - we don't want to match on
226     * something and set a low retval, even though it may match a higher retcal
227     * later. So keep it in descending order here, so we try for the best
228     * match first, and work downward.
229     */
230     if (!strcasecmp (cp, query_name (op)))
231     retval = 20;
232     else if (!strcasecmp (cp, query_short_name (op)))
233     retval = 18;
234     else if (!strcasecmp (cp, query_base_name (op, 0)))
235     retval = 16;
236     else if (!strcasecmp (cp, query_base_name (op, 1)))
237     retval = 16;
238     else if (op->custom_name && !strcasecmp (cp, op->custom_name))
239     retval = 15;
240     else if (!strncasecmp (cp, query_base_name (op, 0), strlen (cp)))
241     retval = 14;
242     else if (!strncasecmp (cp, query_base_name (op, 1), strlen (cp)))
243     retval = 14;
244     /* Do substring checks, so things like 'Str+1' will match.
245     * retval of these should perhaps be lower - they are lower
246     * then the specific strcasecmp aboves, but still higher than
247     * some other match criteria.
248     */
249     else if (strstr (query_base_name (op, 1), cp))
250     retval = 12;
251     else if (strstr (query_base_name (op, 0), cp))
252     retval = 12;
253     else if (strstr (query_short_name (op), cp))
254     retval = 12;
255     /* Check against plural/non plural based on count. */
256     else if (count > 1 && !strcasecmp (cp, op->name_pl))
257 root 1.23 retval = 6;
258 root 1.12 else if (count == 1 && !strcasecmp (op->name, cp))
259 root 1.23 retval = 6;
260 root 1.12 /* base name matched - not bad */
261     else if (strcasecmp (cp, op->name) == 0 && !count)
262     retval = 4;
263     /* Check for partial custom name, but give a real low priority */
264     else if (op->custom_name && strstr (op->custom_name, cp))
265     retval = 3;
266    
267     if (retval)
268     {
269     if (pl->type == PLAYER)
270     pl->contr->count = count;
271 root 1.23
272 root 1.12 return retval;
273 root 1.7 }
274 elmex 1.1 }
275 root 1.23
276 root 1.12 return 0;
277 elmex 1.1 }
278    
279 root 1.63 archetype::archetype (const char *name)
280 root 1.12 {
281 root 1.63 stub = true;
282     arch = this;
283     this->archname = this->name = this->name_pl = name;
284 root 1.46 }
285 root 1.12
286 root 1.46 archetype::~archetype ()
287     {
288 root 1.63 unlink ();
289 elmex 1.1 }
290    
291 root 1.63 void
292     archetype::link ()
293 elmex 1.1 {
294 root 1.63 ht.insert (std::make_pair (archname, this));
295 elmex 1.1
296 root 1.63 if (!archetypes.contains (this))
297     archetypes.insert (this);
298 elmex 1.1 }
299    
300 root 1.46 void
301 root 1.63 archetype::unlink ()
302     {
303     ht.erase (archname);
304 root 1.64 if (!strcmp (&archname, "Gaea")) fprintf (stderr, "oI\n");//D
305 root 1.63 if (archetypes.contains (this))
306     archetypes.erase (this);
307     }
308    
309     /*
310     * Finds, using the hashtable, which archetype matches the given name.
311     * returns a pointer to the found archetype, otherwise NULL.
312     */
313     archetype *
314     archetype::find (const char *name)
315     {
316     if (!name)
317     return 0;
318    
319     auto (i, ht.find (name));
320    
321     if (i == ht.end ())
322     return 0;
323     else
324     return i->second;
325     }
326    
327     archetype *
328     archetype::get (const char *name)
329 root 1.12 {
330 root 1.63 if (!name)
331     {
332     LOG (llevError, "null archetype requested\n");
333     name = "(null)";
334     }
335 root 1.55
336 root 1.63 archetype *at = find (name);
337 root 1.49
338 root 1.64 if (!at)
339 root 1.63 {
340     at = new archetype (name);
341     at->link ();
342     }
343    
344     return at;
345 elmex 1.1 }
346    
347 root 1.53 archetype *
348     archetype::read (object_thawer &f)
349 root 1.12 {
350 root 1.43 assert (f.kw == KW_object);
351    
352 root 1.53 loading_arch = true; // hack to tell parse_kv et al. to behave
353    
354 root 1.63 std::vector<archetype *> parts;
355 root 1.12
356 root 1.63 coroapi::cede_to_tick_every (10);
357 root 1.52
358 root 1.49 for (;;)
359 root 1.43 {
360 root 1.63 // the archetype might have been referenced earlier
361     // so try to find an existing stub archetype first
362     archetype *at = find (f.get_str ());
363    
364     if (!at || !at->stub)
365     at = new archetype (f.get_str ());
366    
367 root 1.54 f.next ();
368 root 1.49
369 root 1.56 #if 0
370 root 1.63 // implementing it here in the server does neither allow multiple inheritence
371     // nor does it cleanly "just override". it would allow use in map files, though,
372     // and other resource files dynamically laoded (as opposed to being preprocessed).
373     // not that any of this is relevant as of yet...
374 root 1.55 if (f.kw == KW_inherit)
375     {
376     if (archetype *at = find (f.get_str ()))
377     *op = at->clone;
378     else
379     LOG (llevError, "archetype '%s' tries to inherit from non-existent archetype '%s'.\n",
380 root 1.63 &at->archname, f.get_str ());
381 root 1.55
382     f.next ();
383     }
384 root 1.56 #endif
385 root 1.55
386 root 1.63 if (!at->parse_kv (f))
387 root 1.49 goto fail;
388    
389 root 1.63 at->post_load_check ();
390 root 1.59
391 root 1.63 parts.push_back (at);
392 root 1.12
393 root 1.49 if (f.kw != KW_more)
394     break;
395 root 1.46
396 root 1.43 f.next ();
397 root 1.54
398     if (f.kw != KW_object)
399     {
400     f.parse_error ("more object");
401     goto fail;
402     }
403 root 1.49 }
404 root 1.43
405 root 1.63 loading_arch = false;
406    
407 root 1.49 {
408 root 1.63 auto (at, parts.begin ());
409 root 1.12
410 root 1.63 archetype *new_head = parts.front ();
411     archetype *old_head = find (new_head->archname);
412    
413 root 1.64 if (old_head && !old_head->is_head ())
414     {
415     LOG (llevError, "%s: unable to overwrite non-head archetype '%s' with head archetype, skipping.\n",
416     &new_head->archname, &old_head->archname);
417     goto fail;
418     }
419 root 1.63
420     // check that all archetypes belong to the same old object or are new
421     for (auto (at, parts.begin ()); at != parts.end (); ++at)
422 root 1.49 {
423 root 1.63 archetype *new_part = *at;
424     archetype *old_part = find (new_part->archname);
425 root 1.49
426 root 1.63 if (old_part && old_part->head_ () != old_head)
427 root 1.49 {
428 root 1.63 LOG (llevError, "%s: unable to overwrite archetype '%s' with archetype of different object, skipping.\n",
429     &new_part->archname, &((archetype *)old_part->head_ ())->archname);
430 root 1.49 goto fail;
431     }
432     }
433    
434 root 1.63 // deactivate existing archetype
435     for (archetype *at = old_head; at; at = (archetype *)at->more)
436     at->unlink ();
437 root 1.49
438 root 1.64 // assemble new chain
439 root 1.63 new_head->min_x = new_head->max_x = new_head->x;
440     new_head->min_y = new_head->max_y = new_head->y;
441 root 1.49
442 root 1.63 archetype *less = new_head;
443 root 1.51 for (auto (p, parts.begin () + 1); p != parts.end (); ++p)
444 root 1.49 {
445 root 1.63 archetype *at = *p;
446 root 1.49
447 root 1.67 // some flags get inherited formt he head (probably a lot more)
448     // doing it here doesn't feel too cozy, but it allows code
449     // to ignore head checks for these flags, which saves time
450     at->flag [FLAG_ALIVE] = new_head->flag [FLAG_ALIVE];
451     at->flag [FLAG_NO_PICK] = new_head->flag [FLAG_NO_PICK];
452     at->flag [FLAG_MONSTER] = new_head->flag [FLAG_MONSTER];
453     at->flag [FLAG_IS_FLOOR] = new_head->flag [FLAG_IS_FLOOR];
454    
455 root 1.63 if (at->x < new_head->min_x) new_head->min_x = at->x;
456     if (at->y < new_head->min_y) new_head->min_y = at->y;
457     if (at->x > new_head->max_x) new_head->max_x = at->x;
458     if (at->y > new_head->max_y) new_head->max_y = at->y;
459 root 1.49
460 root 1.64 at->head = new_head;
461     less->more = at;
462     less = at;
463 root 1.63 }
464 root 1.49
465 root 1.63 // now activate it
466     for (auto (p, parts.begin ()); p != parts.end (); ++p)
467     {
468     archetype *at = *p;
469     at->stub = false;
470     at->link ();
471 root 1.49 }
472 root 1.53
473 root 1.63 return new_head;
474 root 1.49 }
475 root 1.43
476 root 1.49 fail:
477 root 1.51 for (auto (p, parts.begin ()); p != parts.end (); ++p)
478 root 1.63 (*p)->destroy (true);
479 root 1.43
480 root 1.53 loading_arch = false;
481     return 0;
482 root 1.43 }
483    
484     /*
485 root 1.53 * Initialize global archtype pointers:
486 root 1.43 */
487 root 1.53 void
488     init_archetype_pointers ()
489 root 1.43 {
490 root 1.53 ring_arch = archetype::find ("ring");
491     amulet_arch = archetype::find ("amulet");
492     staff_arch = archetype::find ("staff");
493     crown_arch = archetype::find ("crown");
494 root 1.48 empty_archetype = archetype::find ("empty_archetype");
495 elmex 1.1 }
496    
497     /*
498     * Creates and returns a new object which is a copy of the given archetype.
499     * This function returns NULL on failure.
500     */
501 root 1.12 object *
502 root 1.15 arch_to_object (archetype *at)
503 root 1.12 {
504 root 1.43 if (!at)
505 root 1.12 {
506 root 1.53 LOG (llevError, "Couldn't find archetype.\n");
507     return 0;
508 root 1.12 }
509 root 1.15
510 root 1.63 object *op = at->clone ();
511 root 1.15 op->arch = at;
512 root 1.2 op->instantiate ();
513 root 1.53
514 elmex 1.1 return op;
515     }
516    
517     /*
518     * Creates an object. This function is called by get_archetype()
519     * if it fails to find the appropriate archetype.
520     * Thus get_archetype() will be guaranteed to always return
521     * an object, and never NULL.
522     */
523 root 1.12 object *
524     create_singularity (const char *name)
525     {
526 root 1.65 LOG (llevError | logBacktrace, "FATAL: creating singularity for '%s'.\n", name);
527    
528     if (!strcmp (name, "bug"))
529     abort ();
530    
531 root 1.20 char buf[MAX_BUF];
532 root 1.66 sprintf (buf, "bug, please report (%s)", name);
533 root 1.15
534 root 1.65 object *op = get_archetype ("bug");
535 root 1.10 op->name = op->name_pl = buf;
536 root 1.65
537 elmex 1.1 return op;
538     }
539    
540     /*
541     * Finds which archetype matches the given name, and returns a new
542     * object containing a copy of the archetype.
543     */
544 root 1.12 object *
545     get_archetype (const char *name)
546     {
547 root 1.20 archetype *at = archetype::find (name);
548 root 1.15
549 root 1.20 if (!at)
550 root 1.12 return create_singularity (name);
551 root 1.15
552 root 1.12 return arch_to_object (at);
553 elmex 1.1 }
554    
555     /*
556     * Returns the first archetype using the given type.
557     * Used in treasure-generation.
558     */
559 root 1.12 archetype *
560     type_to_archetype (int type)
561     {
562 root 1.63 for_all_archetypes (at)
563     if (at->type == type && at->head_ () != at)
564 elmex 1.1 return at;
565 root 1.20
566     return 0;
567 elmex 1.1 }
568    
569     /*
570     * Returns a new object copied from the first archetype matching
571     * the given type.
572     * Used in treasure-generation.
573     */
574 root 1.12 object *
575     clone_arch (int type)
576     {
577 root 1.20 archetype *at;
578 elmex 1.1
579 root 1.12 if ((at = type_to_archetype (type)) == NULL)
580     {
581     LOG (llevError, "Can't clone archetype %d\n", type);
582 root 1.30 return 0;
583 root 1.12 }
584 root 1.20
585 root 1.63 object *op = at->clone ();
586 root 1.3 op->instantiate ();
587 elmex 1.1 return op;
588     }
589    
590     /*
591     * member: make instance from class
592     */
593 root 1.12 object *
594 root 1.15 object_create_arch (archetype *at)
595 elmex 1.1 {
596 root 1.20 object *op, *prev = 0, *head = 0;
597 elmex 1.1
598 root 1.12 while (at)
599     {
600     op = arch_to_object (at);
601 root 1.63
602     op->x = at->x;
603     op->y = at->y;
604 root 1.20
605 root 1.12 if (head)
606     op->head = head, prev->more = op;
607 root 1.20
608 root 1.12 if (!head)
609     head = op;
610 root 1.20
611 root 1.12 prev = op;
612 root 1.63 at = (archetype *)at->more;
613 elmex 1.1 }
614 root 1.20
615 root 1.63 return head;
616 elmex 1.1 }
617