ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/exit.C
Revision: 1.2
Committed: Tue Aug 29 08:01:36 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +28 -28 lines
Log Message:
expand initial tabs to spaces

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_exit_c =
3 root 1.2 * "$Id: exit.C,v 1.1 2006-08-13 17:16:03 elmex Exp $";
4 elmex 1.1 */
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 root 1.2 if(strstr(RP->exit_on_final_map,"no")) final_map_exit=0;
123 elmex 1.1 }
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 root 1.2
214     sprintf(buf,"This is a random map.\nLevel: %d\n", (RP->dungeon_level)-1);
215 elmex 1.1
216 root 1.2 random_sign->msg = add_string(buf);
217 elmex 1.1 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 root 1.2 /* 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 elmex 1.1
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 root 1.2 return;
282 elmex 1.1
283     the_exit_down->slaying = add_string(RP->final_map);
284     strcpy(new_map->path,RP->final_map);
285    
286 root 1.2 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 elmex 1.1
298 root 1.2 if (final_map_exit == 1)
299     {
300 elmex 1.1 /* 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 root 1.2 }
309    
310     set_map_timeout(new_map); /* So it gets swapped out */
311 elmex 1.1 }
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 root 1.2 walk->move_block = MOVE_BLOCK_DEFAULT;
338 elmex 1.1 update_object(walk,UP_OBJ_CHANGE);
339     }
340     }
341     }
342     }