ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/special.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: +43 -43 lines
Log Message:
expand initial tabs to spaces

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_special_c =
3 root 1.2 * "$Id: special.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) 2002 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     /* Specials in this file:
30 root 1.2 included maps */
31 elmex 1.1
32     #include <global.h>
33     #include <random_map.h>
34     #include <rproto.h>
35    
36     #define NUM_OF_SPECIAL_TYPES 4
37     #define NO_SPECIAL 0
38     #define SPECIAL_SUBMAP 1
39     #define SPECIAL_FOUNTAIN 2
40     #define SPECIAL_EXIT 3
41    
42     #define GLORY_HOLE 1
43     #define ORC_ZONE 2
44     #define MINING_ZONE 3
45     #define NR_OF_HOLE_TYPES 3
46    
47     /* clear map completely of all objects: a rectangular area of xsize, ysize
48     is cleared with the top left corner at xstart, ystart */
49    
50     void nuke_map_region(mapstruct *map,int xstart,int ystart, int xsize, int ysize) {
51     int i,j;
52     object *tmp;
53     for(i=xstart;i<xstart + xsize;i++)
54     for(j=ystart;j<ystart +ysize;j++) {
55     for(tmp=get_map_ob(map,i,j);tmp!=NULL;tmp=tmp->above) {
56     if(!QUERY_FLAG(tmp,FLAG_IS_FLOOR)) {
57     if(tmp->head) tmp=tmp->head;
58     remove_ob(tmp);
59     free_object(tmp);
60     tmp=get_map_ob(map,i,j);
61     }
62     if(tmp==NULL) break;
63     }
64     }
65     }
66    
67    
68    
69     /* copy in_map into dest_map at point x,y */
70    
71    
72     void include_map_in_map(mapstruct *dest_map, mapstruct *in_map,int x, int y) {
73     int i,j;
74     object *tmp;
75     object *new_ob;
76    
77     /* First, splatter everything in the dest map at the location */
78     nuke_map_region(dest_map,x,y,MAP_WIDTH(in_map),MAP_HEIGHT(in_map));
79 root 1.2
80 elmex 1.1 for(i=0;i<MAP_WIDTH(in_map);i++)
81     for(j=0;j<MAP_HEIGHT(in_map);j++) {
82     for(tmp=get_map_ob(in_map,i,j);tmp!=NULL;tmp=tmp->above) {
83     /* don't copy things with multiple squares: must be dealt with
84     specially. */
85     if(tmp->head!=NULL) continue;
86     new_ob = arch_to_object(tmp->arch);
87     copy_object_with_inv(tmp,new_ob);
88     if(QUERY_FLAG(tmp,FLAG_IS_LINKED))
89     add_button_link(new_ob,dest_map,tmp->path_attuned);
90     new_ob->x = i + x;
91     new_ob->y = j + y;
92     insert_multisquare_ob_in_map(new_ob,dest_map);
93     }
94     }
95     }
96    
97     int find_spot_for_submap(mapstruct *map,char **layout,int *ix, int *iy,int xsize, int ysize) {
98     int tries;
99     int i=0,j=0; /* initialization may not be needed but prevents compiler warnings */
100     int is_occupied=0;
101     int l,m;
102     /* don't even try to place a submap into a map if the big map isn't
103     sufficiently large. */
104     if(2*xsize > MAP_WIDTH(map) || 2*ysize > MAP_HEIGHT(map)) return 0;
105    
106     /* search a bit for a completely free spot. */
107     for(tries=0;tries<20;tries++) {
108     /* pick a random location in the layout */
109     i = RANDOM() % (MAP_WIDTH(map) - xsize-2)+1;
110     j = RANDOM() % (MAP_HEIGHT(map) - ysize-2)+1;
111     is_occupied=0;
112     for(l=i;l<i + xsize;l++)
113     for(m=j;m<j + ysize;m++)
114     is_occupied|=layout[l][m];
115     if(!is_occupied) break;
116     }
117    
118 root 1.2
119 elmex 1.1 /* if we failed, relax the restrictions */
120    
121     if(is_occupied) { /* failure, try a relaxed placer. */
122     /* pick a random location in the layout */
123     for(tries=0;tries<10;tries++) {
124     i = RANDOM() % (MAP_WIDTH(map) - xsize-2)+1;
125     j = RANDOM() % (MAP_HEIGHT(map) - ysize-2)+1;
126     is_occupied=0;
127     for(l=i;l<i + xsize;l++)
128     for(m=j;m<j + ysize;m++)
129     if(layout[l][m]=='C' || layout[l][m]=='>' || layout[l][m]=='<')
130     is_occupied|=1;
131     }
132     }
133     if(is_occupied) return 0;
134     *ix=i;
135     *iy=j;
136     return 1;
137     }
138    
139    
140     void place_fountain_with_specials(mapstruct *map) {
141     int ix,iy,i=-1,tries=0;
142     mapstruct *fountain_style=find_style("/styles/misc","fountains",-1);
143     object *fountain=get_archetype("fountain");
144     object *potion=get_object();
145     copy_object(pick_random_object(fountain_style),potion);
146     while(i<0 && tries<10) {
147     ix = RANDOM() % (MAP_WIDTH(map) -2) +1;
148     iy = RANDOM() % (MAP_HEIGHT(map) -2) +1;
149     i = find_first_free_spot(fountain,map,ix,iy);
150     tries++;
151     };
152     if(i==-1) { /* can't place fountain */
153     free_object(fountain);
154     free_object(potion);
155     return;
156     }
157     ix += freearr_x[i];
158     iy += freearr_y[i];
159     potion->face=fountain->face;
160     SET_FLAG(potion,FLAG_NO_PICK);
161     SET_FLAG(potion,FLAG_IDENTIFIED);
162     potion->name=add_string("fountain");
163     potion->name_pl=add_string("fountain");
164     potion->x = ix;
165     potion->y = iy;
166     potion->material=M_ADAMANT;
167     fountain->x = ix;
168     fountain->y = iy;
169     insert_ob_in_map(fountain,map,NULL,0);
170     insert_ob_in_map(potion,map,NULL,0);
171    
172     }
173    
174     void place_special_exit(mapstruct * map, int hole_type,RMParms *RP) {
175     int ix,iy,i=-1;
176     char buf[HUGE_BUF], *style, *decor, *mon;
177     mapstruct *exit_style=find_style("/styles/misc","obscure_exits",-1);
178     int g_xsize,g_ysize;
179    
180     object *the_exit=get_object();
181     if(!exit_style) return;
182    
183     copy_object(pick_random_object(exit_style),the_exit);
184    
185     while(i<0) {
186 root 1.2 ix = RANDOM() % (MAP_WIDTH(map) -2) +1;
187     iy = RANDOM() % (MAP_HEIGHT(map) -2) +1;
188     i = find_first_free_spot(the_exit,map,ix,iy);
189 elmex 1.1 }
190    
191     ix += freearr_x[i];
192     iy += freearr_y[i];
193     the_exit->x = ix;
194     the_exit->y = iy;
195    
196     if(!hole_type) hole_type = RANDOM() % NR_OF_HOLE_TYPES + 1 ;
197    
198     switch(hole_type) {
199 root 1.2 case GLORY_HOLE: /* treasures */
200     {
201     g_xsize = RANDOM() %3 + 4 + RP->difficulty/4;
202     g_ysize = RANDOM() %3 + 4 + RP->difficulty/4;
203     style = "onion";
204     decor = "wealth2";
205     mon = "none";
206     break;
207     }
208    
209     case ORC_ZONE: /* hole with orcs in it. */
210     {
211     g_xsize = RANDOM() %3 + 4 + RP->difficulty/4;
212     g_ysize = RANDOM() %3 + 4 + RP->difficulty/4;
213     style = "onion";
214     decor = "wealth2";
215     mon = "orc";
216     break;
217     }
218    
219     case MINING_ZONE: /* hole with orcs in it. */
220     {
221     g_xsize = RANDOM() %9 + 4 + RP->difficulty/4;
222     g_ysize = RANDOM() %9 + 4 + RP->difficulty/4;
223     style = "maze";
224     decor = "minerals2";
225     mon = "none";
226     break;
227     }
228    
229     default: /* undefined */
230     LOG(llevError, "place_special_exit: undefined hole type %d\n", hole_type);
231     return;
232     break;
233 elmex 1.1 }
234    
235     /* Need to be at least this size, otherwise the load
236     * code will generate new size values which are too large.
237     */
238     if (g_xsize < MIN_RANDOM_MAP_SIZE) g_xsize = MIN_RANDOM_MAP_SIZE;
239     if (g_ysize < MIN_RANDOM_MAP_SIZE) g_ysize = MIN_RANDOM_MAP_SIZE;
240    
241     write_parameters_to_string(buf, g_xsize, g_ysize,RP->wallstyle,RP->floorstyle,mon,
242     "none",style,decor,"none",RP->exitstyle,0,0,0,
243     OPT_WALLS_ONLY,0,0,1,RP->dungeon_level,RP->dungeon_level,
244     RP->difficulty,RP->difficulty,-1,1,0,0,0,0, RP->difficulty_increase);
245     the_exit->slaying = add_string("/!");
246     the_exit->msg = add_string(buf);
247    
248     insert_ob_in_map(the_exit,map,NULL,0);
249     }
250    
251 root 1.2
252 elmex 1.1 void place_specials_in_map(mapstruct *map, char **layout,RMParms *RP) {
253     mapstruct *special_map;
254     int ix,iy; /* map insertion locatons */
255     int special_type; /* type of special to make */
256    
257    
258     special_type = RANDOM() % NUM_OF_SPECIAL_TYPES;
259     switch(special_type) {
260    
261     /* includes a special map into the random map being made. */
262     case SPECIAL_SUBMAP: {
263     special_map = find_style("/styles/specialmaps",0,RP->difficulty);
264     if(special_map==NULL) return;
265 root 1.2
266 elmex 1.1 if(find_spot_for_submap(map,layout,&ix,&iy,MAP_WIDTH(special_map),MAP_HEIGHT(special_map)))
267     include_map_in_map(map,special_map,ix,iy);
268     break;
269     }
270    
271     /* Make a special fountain: an unpickable potion disguised as
272     a fountain, or rather, colocated with a fountain. */
273     case SPECIAL_FOUNTAIN: {
274     place_fountain_with_specials(map);
275     break;
276     }
277    
278     /* Make an exit to another random map, e.g. a gloryhole. */
279     case SPECIAL_EXIT: {
280     place_special_exit(map,0,RP);
281     break;
282     }
283     }
284    
285     }