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, 11 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

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * 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 *
8 * 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 *
13 * 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 *
18 * 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 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 #include <global.h>
25 #include <unistd.h>
26
27 regionvec regions;
28
29 region *
30 region::default_region ()
31 {
32 for_all_regions (rgn)
33 if (rgn->fallback)
34 return rgn;
35
36 return regions [0];
37 }
38
39 /*
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 region *
48 region::find (const char *name)
49 {
50 for_all_regions (rgn)
51 if (!strcmp (rgn->name, name))
52 return rgn;
53
54 LOG (llevError, "region called %s requested, but not found, using fallback.\n", name);
55
56 return default_region ();
57 }
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 region *
72 region::find_fuzzy (const char *name)
73 {
74 if (!name)
75 return default_region ();
76
77 char *p = strchr (name, '\n');
78 if (p)
79 *p = '\0';
80
81 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 {
93 if (strstr (rgn->longname, name))
94 return rgn;
95 }
96
97 for_all_regions (rgn)
98 if (rgn->longname)
99 {
100 /*
101 * This is not a bug, we want the region that is most identifiably a discrete
102 * 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 if (strstr (rgn->name, name))
107 return rgn;
108 }
109
110 for_all_regions (rgn)
111 {
112 if (strstr (rgn->name, name))
113 return rgn;
114 }
115
116 return default_region ();
117 }
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 static int
126 region_is_child_of_region (const region * child, const region * r)
127 {
128
129 if (r == NULL)
130 return -1;
131
132 if (child == NULL)
133 return 0;
134
135 if (!strcmp (child->name, r->name))
136 return 1;
137
138 else if (child->parent != NULL)
139 return region_is_child_of_region (child->parent, r);
140 else
141 return 0;
142 }
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 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
161 reg = op->region ();
162 while (reg)
163 {
164 if (reg->jailmap)
165 {
166 exit = object::create ();
167 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 }
174 else
175 reg = reg->parent;
176 }
177
178 LOG (llevError, "No suitable jailmap for region %s was found.\n", &reg->name);
179
180 return 0;
181 }
182
183 region *
184 region::read (object_thawer &f)
185 {
186 assert (f.kw == KW_region);
187
188 region *rgn = new region;
189 f.get (rgn->name);
190 f.next ();
191
192 for (;;)
193 {
194 switch (f.kw)
195 {
196 case KW_parent:
197 rgn->parent = region::find (f.get_str ());
198 break;
199
200 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
212 case KW_randomitems:
213 rgn->treasure = treasurelist::get (f.get_str ());
214 break;
215
216 case KW_end:
217 f.next ();
218
219 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
234 default:
235 if (!f.parse_error ("region", rgn->name))
236 {
237 delete rgn;
238 return 0;
239 }
240 break;
241 }
242
243 f.next ();
244 }
245 }
246
247 /*
248 * 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 void
253 init_regions (void)
254 {
255 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 }
264