ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/exit.c
Revision: 1.3
Committed: Sun Aug 13 17:16:03 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +1 -1 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

# Content
1 /*
2 * static char *rcsid_exit_c =
3 * "$Id$";
4 */
5
6 /*
7 CrossFire, A Multiplayer game for X-windows
8
9 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28
29 #include <global.h>
30 #include <random_map.h>
31 #include <sproto.h>
32 #include <rproto.h>
33
34
35 /* find a character in the layout. fx and fy are pointers to
36 where to find the char. fx,fy = -1 if not found. */
37 void find_in_layout(int mode, char target,int *fx,int *fy,char **layout,RMParms *RP) {
38 int M;
39 int i,j;
40 *fx=-1;
41 *fy=-1;
42
43 /* if a starting point isn't given, pick one */
44 if(mode < 1 || mode > 4) M=RANDOM() % 4 + 1 ;
45 else M = mode;
46
47 /* four different search starting points and methods so that
48 we can do something different for symmetrical maps instead of
49 the same damned thing every time. */
50 switch(M) {
51 case 1: { /* search from top left down/right */
52 for(i=1;i<RP->Xsize;i++)
53 for(j=1;j<RP->Ysize;j++) {
54 if(layout[i][j]==target) {
55 *fx = i; *fy = j;
56 return;
57 }
58 }
59 break;
60 }
61 case 2: { /* Search from top right down/left */
62 for(i=RP->Xsize-2;i>0;i--)
63 for(j=1;j<RP->Ysize-1;j++) {
64 if(layout[i][j]==target) {
65 *fx = i; *fy = j;
66 return;
67 }
68 }
69 break;
70 }
71 case 3: { /* search from bottom-left up-right */
72 for(i=1;i<RP->Xsize-1;i++)
73 for(j=RP->Ysize-2;j>0;j--) {
74 if(layout[i][j]==target) {
75 *fx = i; *fy = j;
76 return;
77 }
78 }
79 break;
80 }
81 case 4: { /* search from bottom-right up-left */
82 for(i=RP->Xsize-2;i>0;i--)
83 for(j=RP->Ysize-2;j>0;j--) {
84 if(layout[i][j]==target) {
85 *fx = i; *fy = j;
86 return;
87 }
88 }
89 break;
90 }
91 }
92 }
93
94
95
96
97
98
99 /* orientation: 0 means random,
100 1 means descending dungeon
101 2 means ascending dungeon
102 3 means rightward
103 4 means leftward
104 5 means northward
105 6 means southward
106 */
107
108 void place_exits(mapstruct *map, char **maze,char *exitstyle,int orientation,RMParms *RP) {
109 char styledirname[256];
110 mapstruct *style_map_down=0; /* harder maze */
111 mapstruct *style_map_up=0; /* easier maze */
112 object *the_exit_down; /* harder maze */
113 object *the_exit_up; /* easier maze */
114 object *random_sign; /* magic mouth saying this is a random map. */
115 char buf[512];
116 int cx=-1,cy=-1; /* location of a map center */
117 int upx=-1,upy=-1; /* location of up exit */
118 int downx=-1,downy=-1;
119 int final_map_exit=1;
120
121 if(RP->exit_on_final_map){
122 if(strstr(RP->exit_on_final_map,"no")) final_map_exit=0;
123 }
124
125 if(orientation == 0) orientation = RANDOM() % 6 + 1;
126
127 switch(orientation) {
128 case 1:
129 {
130 sprintf(styledirname,"/styles/exitstyles/up");
131 style_map_up = find_style(styledirname,exitstyle,-1);
132 sprintf(styledirname,"/styles/exitstyles/down");
133 style_map_down = find_style(styledirname,exitstyle,-1);
134 break;
135 }
136 case 2:
137 {
138 sprintf(styledirname,"/styles/exitstyles/down");
139 style_map_up = find_style(styledirname,exitstyle,-1);
140 sprintf(styledirname,"/styles/exitstyles/up");
141 style_map_down = find_style(styledirname,exitstyle,-1);
142 break;
143 }
144 default:
145 {
146 sprintf(styledirname,"/styles/exitstyles/generic");
147 style_map_up = find_style(styledirname,exitstyle,-1);
148 style_map_down = style_map_up;
149 break;
150 }
151 }
152 if(style_map_up == 0) the_exit_up =arch_to_object(find_archetype("exit"));
153 else {
154 object *tmp;
155 tmp = pick_random_object(style_map_up);
156 the_exit_up = arch_to_object(tmp->arch);
157 }
158
159 /* we need a down exit only if we're recursing. */
160 if(RP->dungeon_level < RP->dungeon_depth || RP->final_map[0]!=0)
161 if(style_map_down == 0) the_exit_down = arch_to_object(find_archetype("exit"));
162 else {
163 object *tmp;
164 tmp = pick_random_object(style_map_down);
165 the_exit_down = arch_to_object(tmp->arch);
166 }
167 else the_exit_down = 0;
168
169 /* set up the up exit */
170 the_exit_up->stats.hp = RP->origin_x;
171 the_exit_up->stats.sp = RP->origin_y;
172 the_exit_up->slaying = add_string(RP->origin_map);
173
174 /* figure out where to put the entrance */
175 /* begin a logical block */
176 {
177 int i,j;
178 /* First, look for a '<' char */
179 find_in_layout(0,'<',&upx,&upy,maze,RP);
180
181 /* next, look for a C, the map center. */
182 find_in_layout(0,'C',&cx,&cy,maze,RP);
183
184
185 /* if we didn't find an up, find an empty place far from the center */
186 if(upx==-1 && cx!=-1) {
187 if(cx > RP->Xsize/2) upx = 1;
188 else upx = RP->Xsize -2;
189 if(cy > RP->Ysize/2) upy = 1;
190 else upy = RP->Ysize -2;
191 /* find an empty place far from the center */
192 if(upx==1 && upy==1) find_in_layout(1,0,&upx,&upy,maze,RP);
193 else
194 if(upx==1 && upy>1) find_in_layout(3,0,&upx,&upy,maze,RP);
195 else
196 if(upx>1 && upy==1) find_in_layout(2,0,&upx,&upy,maze,RP);
197 else
198 if(upx>1 && upy>1) find_in_layout(4,0,&upx,&upy,maze,RP);
199 }
200
201 /* no indication of where to place the exit, so just place it. */
202 if(upx==-1) find_in_layout(0,0,&upx,&upy,maze,RP);
203
204 the_exit_up->x = upx;
205 the_exit_up->y = upy;
206
207 /* surround the exits with notices that this is a random map. */
208 for(j=1;j<9;j++) {
209 if(!wall_blocked(map,the_exit_up->x+freearr_x[j],the_exit_up->y+freearr_y[j])) {
210 random_sign = get_archetype("sign");
211 random_sign->x = the_exit_up->x+freearr_x[j];
212 random_sign->y = the_exit_up->y+freearr_y[j];
213
214 sprintf(buf,"This is a random map.\nLevel: %d\n", (RP->dungeon_level)-1);
215
216 random_sign->msg = add_string(buf);
217 insert_ob_in_map(random_sign,map,NULL,0);
218 }
219 }
220 /* Block the exit so things don't get dumped on top of it. */
221 the_exit_up->move_block = MOVE_ALL;
222
223 insert_ob_in_map(the_exit_up,map,NULL,0);
224 maze[the_exit_up->x][the_exit_up->y]='<';
225
226 /* set the starting x,y for this map */
227 MAP_ENTER_X(map) = the_exit_up->x;
228 MAP_ENTER_Y(map) = the_exit_up->y;
229
230 /* first, look for a '>' character */
231 find_in_layout(0,'>',&downx,&downy,maze,RP);
232 /* if no > is found use C */
233 if(downx==-1) { downx = cx; downy=cy;};
234
235 /* make the other exit far away from this one if
236 there's no center. */
237 if(downx==-1) {
238 if(upx > RP->Xsize/2) downx = 1;
239 else downx = RP->Xsize -2;
240 if(upy > RP->Ysize/2) downy = 1;
241 else downy = RP->Ysize -2;
242 /* find an empty place far from the entrance */
243 if(downx==1 && downy==1) find_in_layout(1,0,&downx,&downy,maze,RP);
244 else
245 if(downx==1 && downy>1) find_in_layout(3,0,&downx,&downy,maze,RP);
246 else
247 if(downx>1 && downy==1) find_in_layout(2,0,&downx,&downy,maze,RP);
248 else
249 if(downx>1 && downy>1) find_in_layout(4,0,&downx,&downy,maze,RP);
250
251 }
252 /* no indication of where to place the down exit, so just place it */
253 if(downx==-1) find_in_layout(0,0,&downx,&downy,maze,RP);
254 if(the_exit_down) {
255 char buf[2048];
256 i = find_first_free_spot(the_exit_down, map, downx, downy);
257 the_exit_down->x = downx + freearr_x[i];
258 the_exit_down->y = downy + freearr_y[i];
259 RP->origin_x = the_exit_down->x;
260 RP->origin_y = the_exit_down->y;
261 write_map_parameters_to_string(buf,RP);
262 the_exit_down->msg = add_string(buf);
263 /* the identifier for making a random map. */
264 if(RP->dungeon_level >= RP->dungeon_depth && RP->final_map[0]!=0) {
265 mapstruct *new_map;
266 object *the_exit_back = arch_to_object(the_exit_up->arch), *tmp;
267 #if 0
268 /* I'm not sure if there was any reason to change the path to the
269 * map other than to maybe make it more descriptive in the 'maps'
270 * command. But changing the map name makes life more complicated,
271 * (has_been_loaded needs to use the new name)
272 */
273
274 char new_map_name[MAX_BUF];
275 /* give the final map a name */
276 sprintf(new_map_name,"%sfinal_map",RP->final_map);
277 /* set the exit down. */
278 #endif
279 /* load it */
280 if((new_map=ready_map_name(RP->final_map,0)) == NULL)
281 return;
282
283 the_exit_down->slaying = add_string(RP->final_map);
284 strcpy(new_map->path,RP->final_map);
285
286 for (tmp=GET_MAP_OB(new_map, MAP_ENTER_X(new_map), MAP_ENTER_Y(new_map)); tmp; tmp=tmp->above)
287 /* Remove exit back to previous random map. There should only be one
288 * which is why we break out. To try to process more than one
289 * would require keeping a 'next' pointer, ad free_object kills tmp, which
290 * breaks the for loop.
291 */
292 if (tmp->type == EXIT && EXIT_PATH(tmp) && !strncmp(EXIT_PATH(tmp),"/random/", 8)) {
293 remove_ob(tmp);
294 free_object(tmp);
295 break;
296 }
297
298 if (final_map_exit == 1)
299 {
300 /* setup the exit back */
301 the_exit_back->slaying = add_string(map->path);
302 the_exit_back->stats.hp = the_exit_down->x;
303 the_exit_back->stats.sp = the_exit_down->y;
304 the_exit_back->x = MAP_ENTER_X(new_map);
305 the_exit_back->y = MAP_ENTER_Y(new_map);
306
307 insert_ob_in_map(the_exit_back,new_map,NULL,0);
308 }
309
310 set_map_timeout(new_map); /* So it gets swapped out */
311 }
312 else
313 the_exit_down->slaying = add_string("/!");
314 /* Block the exit so things don't get dumped on top of it. */
315 the_exit_down->move_block = MOVE_ALL;
316 insert_ob_in_map(the_exit_down,map,NULL,0);
317 maze[the_exit_down->x][the_exit_down->y]='>';
318 }
319 }
320
321 }
322
323
324
325 /* this function unblocks the exits. We blocked them to
326 keep things from being dumped on them during the other
327 phases of random map generation. */
328 void unblock_exits(mapstruct *map, char **maze, RMParms *RP) {
329 int i=0,j=0;
330 object *walk;
331
332 for(i=0;i<RP->Xsize;i++)
333 for(j=0;j<RP->Ysize;j++)
334 if(maze[i][j]=='>' || maze[i][j]=='<') {
335 for(walk=get_map_ob(map,i,j);walk!=NULL;walk=walk->above) {
336 if(walk->move_block == MOVE_ALL && walk->type != LOCKED_DOOR) {
337 walk->move_block = MOVE_BLOCK_DEFAULT;
338 update_object(walk,UP_OBJ_CHANGE);
339 }
340 }
341 }
342 }