Crossfire Server, Branches 1.12  R18729
special.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_special_c =
3  * "$Id: special.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
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 
34 #include <global.h>
35 #include <random_map.h>
36 #include <rproto.h>
37 
42 #define NUM_OF_SPECIAL_TYPES 4
43 #define NO_SPECIAL 0
44 #define SPECIAL_SUBMAP 1
45 #define SPECIAL_FOUNTAIN 2
46 #define SPECIAL_EXIT 3
47 
53 #define GLORY_HOLE 1
54 #define ORC_ZONE 2
55 #define MINING_ZONE 3
56 #define NR_OF_HOLE_TYPES 3
57 
70 void nuke_map_region(mapstruct *map, int xstart, int ystart, int xsize, int ysize) {
71  int i, j;
72  object *tmp;
73 
74  for (i = xstart; i < xstart+xsize; i++)
75  for (j = ystart; j < ystart+ysize; j++) {
76  for (tmp = GET_MAP_OB(map, i, j); tmp != NULL; tmp = tmp->above) {
77  if (!QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
78  if (tmp->head)
79  tmp = tmp->head;
80  remove_ob(tmp);
81  free_object(tmp);
82  tmp = GET_MAP_OB(map, i, j);
83  }
84  if (tmp == NULL)
85  break;
86  }
87  }
88 }
89 
100 void include_map_in_map(mapstruct *dest_map, mapstruct *in_map, int x, int y) {
101  int i, j;
102  object *tmp;
103  object *new_ob;
104 
105  /* First, splatter everything in the dest map at the location */
106  nuke_map_region(dest_map, x, y, MAP_WIDTH(in_map), MAP_HEIGHT(in_map));
107 
108  for (i = 0; i < MAP_WIDTH(in_map); i++)
109  for (j = 0; j < MAP_HEIGHT(in_map); j++) {
110  for (tmp = GET_MAP_OB(in_map, i, j); tmp != NULL; tmp = tmp->above) {
111  /* don't copy things with multiple squares: must be dealt with
112  specially. */
113  if (tmp->head != NULL)
114  continue;
115  new_ob = arch_to_object(tmp->arch);
116  copy_object_with_inv(tmp, new_ob);
117  if (QUERY_FLAG(tmp, FLAG_IS_LINKED))
118  add_button_link(new_ob, dest_map, tmp->path_attuned);
119  new_ob->x = i+x;
120  new_ob->y = j+y;
121  insert_multisquare_ob_in_map(new_ob, dest_map);
122  }
123  }
124 }
125 
141 int find_spot_for_submap(mapstruct *map, char **layout, int *ix, int *iy, int xsize, int ysize) {
142  int tries;
143  int i = 0, j = 0; /* initialization may not be needed but prevents compiler warnings */
144  int is_occupied = 0;
145  int l, m;
146 
147  /* don't even try to place a submap into a map if the big map isn't
148  sufficiently large. */
149  if (2*xsize > MAP_WIDTH(map) || 2*ysize > MAP_HEIGHT(map))
150  return 0;
151 
152  /* search a bit for a completely free spot. */
153  for (tries = 0; tries < 20; tries++) {
154  /* pick a random location in the layout */
155  i = RANDOM()%(MAP_WIDTH(map)-xsize-2)+1;
156  j = RANDOM()%(MAP_HEIGHT(map)-ysize-2)+1;
157  is_occupied = 0;
158  for (l = i; l < i+xsize; l++)
159  for (m = j; m < j+ysize; m++)
160  is_occupied |= layout[l][m];
161  if (!is_occupied)
162  break;
163  }
164 
165  /* if we failed, relax the restrictions */
166  if (is_occupied) { /* failure, try a relaxed placer. */
167  /* pick a random location in the layout */
168  for (tries = 0; tries < 10; tries++) {
169  i = RANDOM()%(MAP_WIDTH(map)-xsize-2)+1;
170  j = RANDOM()%(MAP_HEIGHT(map)-ysize-2)+1;
171  is_occupied = 0;
172  for (l = i; l < i+xsize; l++)
173  for (m = j; m < j+ysize; m++)
174  if (layout[l][m] == 'C' || layout[l][m] == '>' || layout[l][m] == '<')
175  is_occupied |= 1;
176  }
177  }
178  if (is_occupied)
179  return 0;
180  *ix = i;
181  *iy = j;
182  return 1;
183 }
184 
193  int ix, iy, i = -1, tries = 0;
194  mapstruct *fountain_style = find_style("/styles/misc", "fountains", -1);
195  object *fountain = create_archetype("fountain");
196  object *potion = get_object();
197 
198  copy_object(pick_random_object(fountain_style), potion);
199  while (i < 0 && tries < 10) {
200  ix = RANDOM()%(MAP_WIDTH(map)-2)+1;
201  iy = RANDOM()%(MAP_HEIGHT(map)-2)+1;
202  i = find_first_free_spot(fountain, map, ix, iy);
203  tries++;
204  };
205  if (i == -1) { /* can't place fountain */
206  free_object(fountain);
207  free_object(potion);
208  return;
209  }
210  ix += freearr_x[i];
211  iy += freearr_y[i];
212  potion->face = fountain->face;
213  SET_FLAG(potion, FLAG_NO_PICK);
214  SET_FLAG(potion, FLAG_IDENTIFIED);
215  potion->name = add_string("fountain");
216  potion->name_pl = add_string("fountain");
217  potion->x = ix;
218  potion->y = iy;
219  potion->material = M_ADAMANT;
220  fountain->x = ix;
221  fountain->y = iy;
222  insert_ob_in_map(fountain, map, NULL, 0);
223  insert_ob_in_map(potion, map, NULL, 0);
224 }
225 
235 void place_special_exit(mapstruct *map, int hole_type, RMParms *RP) {
236  int ix, iy, i = -1;
237  char buf[HUGE_BUF];
238  const char *style, *decor, *mon;
239  mapstruct *exit_style = find_style("/styles/misc", "obscure_exits", -1);
240  int g_xsize, g_ysize;
241  object *the_exit = get_object();
242 
243  if (!exit_style)
244  return;
245 
246  copy_object(pick_random_object(exit_style), the_exit);
247 
248  while (i < 0) {
249  ix = RANDOM()%(MAP_WIDTH(map)-2)+1;
250  iy = RANDOM()%(MAP_HEIGHT(map)-2)+1;
251  i = find_first_free_spot(the_exit, map, ix, iy);
252  }
253 
254  ix += freearr_x[i];
255  iy += freearr_y[i];
256  the_exit->x = ix;
257  the_exit->y = iy;
258 
259  if (!hole_type)
260  hole_type = RANDOM()%NR_OF_HOLE_TYPES+1;
261 
262  switch (hole_type) {
263  case GLORY_HOLE: { /* treasures */
264  g_xsize = RANDOM()%3+4+RP->difficulty/4;
265  g_ysize = RANDOM()%3+4+RP->difficulty/4;
266  style = "onion";
267  decor = "wealth2";
268  mon = "none";
269  break;
270  }
271 
272  case ORC_ZONE: { /* hole with orcs in it. */
273  g_xsize = RANDOM()%3+4+RP->difficulty/4;
274  g_ysize = RANDOM()%3+4+RP->difficulty/4;
275  style = "onion";
276  decor = "wealth2";
277  mon = "orc";
278  break;
279  }
280 
281  case MINING_ZONE: { /* hole with orcs in it. */
282  g_xsize = RANDOM()%9+4+RP->difficulty/4;
283  g_ysize = RANDOM()%9+4+RP->difficulty/4;
284  style = "maze";
285  decor = "minerals2";
286  mon = "none";
287  break;
288  }
289 
290  default: /* undefined */
291  LOG(llevError, "place_special_exit: undefined hole type %d\n", hole_type);
292  return;
293  break;
294  }
295 
296  /* Need to be at least this size, otherwise the load
297  * code will generate new size values which are too large.
298  */
299  if (g_xsize < MIN_RANDOM_MAP_SIZE)
300  g_xsize = MIN_RANDOM_MAP_SIZE;
301  if (g_ysize < MIN_RANDOM_MAP_SIZE)
302  g_ysize = MIN_RANDOM_MAP_SIZE;
303 
304  write_parameters_to_string(buf, g_xsize, g_ysize, RP->wallstyle, RP->floorstyle, mon,
305  "none", style, decor, "none", RP->exitstyle, NULL, NULL, NULL,
306  OPT_WALLS_ONLY, 0, 0, 1, RP->dungeon_level, RP->dungeon_level,
307  RP->difficulty, RP->difficulty, -1, 1, 0, 0, 0, 0, RP->difficulty_increase);
308  the_exit->slaying = add_string("/!");
309  the_exit->msg = add_string(buf);
310 
311  insert_ob_in_map(the_exit, map, NULL, 0);
312 }
313 
323 void place_specials_in_map(mapstruct *map, char **layout, RMParms *RP) {
324  mapstruct *special_map;
325  int ix, iy; /* map insertion locatons */
326  int special_type; /* type of special to make */
327 
328  special_type = RANDOM()%NUM_OF_SPECIAL_TYPES;
329  switch (special_type) {
330  /* includes a special map into the random map being made. */
331  case SPECIAL_SUBMAP: {
332  special_map = find_style("/styles/specialmaps", NULL, RP->difficulty);
333  if (special_map == NULL)
334  return;
335 
336  if (find_spot_for_submap(map, layout, &ix, &iy, MAP_WIDTH(special_map), MAP_HEIGHT(special_map)))
337  include_map_in_map(map, special_map, ix, iy);
338  break;
339  }
340 
341  /* Make a special fountain: an unpickable potion disguised as
342  * a fountain, or rather, colocated with a fountain.
343  */
344  case SPECIAL_FOUNTAIN: {
346  break;
347  }
348 
349  /* Make an exit to another random map, e.g. a gloryhole. */
350  case SPECIAL_EXIT: {
351  place_special_exit(map, 0, RP);
352  break;
353  }
354  }
355 }
#define FLAG_IS_FLOOR
Definition: define.h:599
#define ORC_ZONE
Definition: special.c:54
#define FLAG_IS_LINKED
Definition: define.h:612
#define SET_FLAG(xyz, p)
Definition: define.h:510
uint16 material
Definition: object.h:198
char floorstyle[RM_SIZE]
Definition: random_map.h:45
object * mon
Definition: comet_perf.c:74
#define HUGE_BUF
Definition: define.h:83
#define MAP_HEIGHT(m)
Definition: map.h:99
short freearr_x[SIZEOFFREE]
Definition: object.c:75
const char * slaying
Definition: object.h:172
#define M_ADAMANT
Definition: material.h:52
struct obj * above
Definition: object.h:146
int find_spot_for_submap(mapstruct *map, char **layout, int *ix, int *iy, int xsize, int ysize)
Definition: special.c:141
sint16 x
Definition: object.h:179
uint32 path_attuned
Definition: object.h:194
#define SPECIAL_EXIT
Definition: special.c:46
object * pick_random_object(mapstruct *style)
Definition: style.c:275
void nuke_map_region(mapstruct *map, int xstart, int ystart, int xsize, int ysize)
Definition: special.c:70
#define NR_OF_HOLE_TYPES
Definition: special.c:56
short freearr_y[SIZEOFFREE]
Definition: object.c:81
void place_fountain_with_specials(mapstruct *map)
Definition: special.c:192
void remove_ob(object *op)
Definition: object.c:1515
#define SPECIAL_SUBMAP
Definition: special.c:44
const char * name_pl
Definition: object.h:168
object * create_archetype(const char *name)
Definition: arch.c:625
#define FLAG_IDENTIFIED
Definition: define.h:557
int find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3240
const char * name
Definition: object.h:167
int dungeon_level
Definition: random_map.h:69
#define MIN_RANDOM_MAP_SIZE
Definition: random_map.h:131
#define SPECIAL_FOUNTAIN
Definition: special.c:45
char exitstyle[RM_SIZE]
Definition: random_map.h:54
void add_button_link(object *button, mapstruct *map, int connected)
Definition: button.c:663
sint16 y
Definition: object.h:179
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
object * get_object(void)
Definition: object.c:921
void include_map_in_map(mapstruct *dest_map, mapstruct *in_map, int x, int y)
Definition: special.c:100
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
float difficulty_increase
Definition: random_map.h:68
void place_specials_in_map(mapstruct *map, char **layout, RMParms *RP)
Definition: special.c:323
void write_parameters_to_string(char *buf, int xsize_n, int ysize_n, const char *wallstyle_n, const char *floorstyle_n, const char *monsterstyle_n, const char *treasurestyle_n, const char *layoutstyle_n, const char *decorstyle_n, const char *doorstyle_n, const char *exitstyle_n, const char *final_map_n, const char *exit_on_final_map_n, const char *this_map_n, int layoutoptions1_n, int layoutoptions2_n, int layoutoptions3_n, int symmetry_n, int dungeon_depth_n, int dungeon_level_n, int difficulty_n, int difficulty_given_n, int decoroptions_n, int orientation_n, int origin_x_n, int origin_y_n, int random_seed_n, int treasureoptions_n, float difficulty_increase)
Definition: random_map.c:877
struct archt * arch
Definition: object.h:263
void insert_multisquare_ob_in_map(object *new_obj, mapstruct *map)
Definition: monster.c:49
#define MAP_WIDTH(m)
Definition: map.h:97
#define MINING_ZONE
Definition: special.c:55
const char * msg
Definition: object.h:175
sstring add_string(const char *str)
Definition: shstr.c:116
void place_special_exit(mapstruct *map, int hole_type, RMParms *RP)
Definition: special.c:235
void copy_object_with_inv(object *src_ob, object *dest_ob)
Definition: object.c:862
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
#define OPT_WALLS_ONLY
Definition: random_map.h:113
struct obj * head
Definition: object.h:154
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
int difficulty
Definition: random_map.h:66
mapstruct * find_style(const char *dirname, const char *stylename, int difficulty)
Definition: style.c:177
void copy_object(object *op2, object *op)
Definition: object.c:758
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
New_Face * face
Definition: object.h:183
#define FLAG_NO_PICK
Definition: define.h:535
#define NUM_OF_SPECIAL_TYPES
Definition: special.c:42
#define GLORY_HOLE
Definition: special.c:53
object * arch_to_object(archetype *at)
Definition: arch.c:576
char wallstyle[RM_SIZE]
Definition: random_map.h:43