ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/region.C
Revision: 1.33
Committed: Sun Jul 1 05:00:18 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.32: +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.33 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.16 *
4 root 1.32 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2001-2003,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.16 *
8 root 1.33 * 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.16 *
13 root 1.33 * 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 root 1.32 *
18 root 1.33 * 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.32 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.16 */
23 elmex 1.1
24     #include <global.h>
25 pippijn 1.8 #include <unistd.h>
26 root 1.4
27 root 1.21 regionvec regions;
28    
29 root 1.18 region *
30     region::default_region ()
31     {
32 root 1.21 for_all_regions (rgn)
33     if (rgn->fallback)
34     return rgn;
35 root 1.18
36 root 1.21 return regions [0];
37 root 1.18 }
38    
39 elmex 1.1 /*
40     * Pass a char array, returns a pointer to the region of the same name.
41     * if it can't find a region of the same name it returns the first region
42     * with the 'fallback' property set.
43     * if it can't find a matching name /or/ a fallback region it logs an info message
44     * message and returns NULL
45     * used by the map parsing code.
46     */
47 root 1.4 region *
48 root 1.18 region::find (const char *name)
49 root 1.4 {
50 root 1.21 for_all_regions (rgn)
51     if (!strcmp (rgn->name, name))
52     return rgn;
53 root 1.4
54 root 1.18 LOG (llevError, "region called %s requested, but not found, using fallback.\n", name);
55 root 1.4
56 root 1.18 return default_region ();
57 elmex 1.1 }
58    
59     /*
60     * Tries to find a region that 'name' corresponds to.
61     * It looks, in order, for:
62     * an exact match to region name (case insensitive)
63     * an exact match to longname (case insensitive)
64     * a substring that matches to the longname (eg Kingdom)
65     * a substring that matches to the region name (eg nav)
66     * if it can find none of these it returns the first parentless region
67     * (there should be only one of these - the top level one)
68     * If we got a NULL, then just return the top level region
69     *
70     */
71 root 1.4 region *
72 root 1.19 region::find_fuzzy (const char *name)
73 root 1.4 {
74 root 1.21 if (!name)
75     return default_region ();
76 root 1.19
77 root 1.21 char *p = strchr (name, '\n');
78 root 1.4 if (p)
79     *p = '\0';
80 root 1.19
81 root 1.21 for_all_regions (rgn)
82     if (!strcasecmp (rgn->name, name))
83     return rgn;
84    
85     for_all_regions (rgn)
86     if (rgn->longname)
87     if (!strcasecmp (rgn->longname, name))
88     return rgn;
89    
90     for_all_regions (rgn)
91     if (rgn->longname)
92 root 1.4 {
93 root 1.21 if (strstr (rgn->longname, name))
94     return rgn;
95 root 1.4 }
96 root 1.19
97 root 1.21 for_all_regions (rgn)
98     if (rgn->longname)
99 root 1.4 {
100 root 1.2 /*
101 root 1.19 * This is not a bug, we want the region that is most identifiably a discrete
102 root 1.2 * area in the game, eg if we have 'scor', we want to return 'scorn' and not
103     * 'scornarena', regardless of their order on the list so we only look at those
104     * regions with a longname set.
105     */
106 root 1.21 if (strstr (rgn->name, name))
107     return rgn;
108 root 1.4 }
109 root 1.19
110 root 1.21 for_all_regions (rgn)
111 root 1.4 {
112 root 1.21 if (strstr (rgn->name, name))
113     return rgn;
114 root 1.4 }
115 root 1.19
116 root 1.21 return default_region ();
117 elmex 1.1 }
118    
119     /*
120     * returns 1 if the player is in the region reg, or a child region thereof
121     * otherwise returns 0
122     * if passed a NULL region returns -1
123     */
124    
125 root 1.19 static int
126 root 1.4 region_is_child_of_region (const region * child, const region * r)
127     {
128    
129     if (r == NULL)
130     return -1;
131 root 1.19
132 root 1.4 if (child == NULL)
133     return 0;
134 root 1.19
135 root 1.4 if (!strcmp (child->name, r->name))
136     return 1;
137 root 1.19
138 root 1.4 else if (child->parent != NULL)
139     return region_is_child_of_region (child->parent, r);
140     else
141     return 0;
142 elmex 1.1 }
143    
144     /** Returns an object which is an exit through which the player represented by op should be
145     * sent in order to be imprisoned. If there is no suitable place to which an exit can be
146     * constructed, then NULL will be returned. The caller is responsible for freeing the object
147     * created by this function.
148     */
149 root 1.4 object *
150     get_jail_exit (object *op)
151     {
152     region *reg;
153     object *exit;
154    
155     if (op->type != PLAYER)
156     {
157     LOG (llevError, "region.c: get_jail_exit called against non-player object.\n");
158     return NULL;
159     }
160 root 1.19
161     reg = op->region ();
162     while (reg)
163 root 1.4 {
164     if (reg->jailmap)
165     {
166 root 1.9 exit = object::create ();
167 root 1.4 EXIT_PATH (exit) = reg->jailmap;
168     /* damned exits reset savebed and remove teleports, so the prisoner can't escape */
169     SET_FLAG (exit, FLAG_DAMNED);
170     EXIT_X (exit) = reg->jailx;
171     EXIT_Y (exit) = reg->jaily;
172     return exit;
173 root 1.2 }
174 root 1.4 else
175     reg = reg->parent;
176 elmex 1.1 }
177 root 1.19
178 root 1.21 LOG (llevError, "No suitable jailmap for region %s was found.\n", &reg->name);
179    
180     return 0;
181 elmex 1.1 }
182    
183 root 1.25 region *
184 root 1.26 region::read (object_thawer &f)
185 root 1.19 {
186 root 1.26 assert (f.kw == KW_region);
187    
188 root 1.21 region *rgn = new region;
189 root 1.25 f.get (rgn->name);
190 root 1.26 f.next ();
191 root 1.19
192 root 1.20 for (;;)
193     {
194 root 1.25 switch (f.kw)
195 root 1.20 {
196     case KW_parent:
197 root 1.25 rgn->parent = region::find (f.get_str ());
198 root 1.20 break;
199    
200 root 1.31 case KW_msg: f.get_ml (KW_endmsg, rgn->msg); break;
201     case KW_longname: f.get (rgn->longname); break;
202     case KW_match: f.get (rgn->match); break;
203     case KW_jail_map: f.get (rgn->jailmap); break;
204     case KW_jail_x: f.get (rgn->jailx); break;
205     case KW_jail_y: f.get (rgn->jaily); break;
206     case KW_portal_map: f.get (rgn->portalmap);break;
207     case KW_portal_x: f.get (rgn->portalx); break;
208     case KW_portal_y: f.get (rgn->portaly); break;
209     case KW_fallback: f.get (rgn->fallback); break;
210     case KW_chance: f.get (rgn->treasure_density); break;
211 root 1.30
212     case KW_randomitems:
213     rgn->treasure = treasurelist::get (f.get_str ());
214     break;
215 root 1.20
216 root 1.21 case KW_end:
217 root 1.29 f.next ();
218    
219 root 1.25 for_all_regions (old)
220     if (old->name == rgn->name)
221     {
222     // replace, copy new values (ugly)
223     rgn->index = old->index;
224     *old = *rgn;
225     delete rgn;
226    
227     return old;
228     }
229    
230     // just append
231     regions.push_back (rgn);
232     return rgn;
233 root 1.21
234     default:
235 root 1.25 if (!f.parse_error ("region", rgn->name))
236     {
237     delete rgn;
238     return 0;
239     }
240 root 1.21 break;
241 root 1.20 }
242 root 1.25
243 root 1.26 f.next ();
244 root 1.20 }
245     }
246    
247     /*
248 elmex 1.1 * First initialises the archtype hash-table (init_archetable()).
249     * Reads and parses the archetype file (with the first and second-pass
250     * functions).
251     */
252 root 1.4 void
253     init_regions (void)
254     {
255 root 1.21 if (!regions.size ())
256     {
257     // make sure one region is always available
258     region *rgn = new region;
259     rgn->name = "<builtin>";
260     rgn->longname = "Built-in Region";
261     regions.push_back (rgn);
262     }
263 elmex 1.1 }
264 root 1.24