Crossfire Server, Trunk  R20513
wall.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
14 #include "global.h"
15 
16 #include <string.h>
17 
18 #include "random_map.h"
19 #include "rproto.h"
20 #include <assert.h>
21 
40 int surround_flag(char **layout, int i, int j, RMParms *RP)
41 {
42  int surround_index = 0;
43 
44  if ((i > 0) && layout[i-1][j] != 0) {
45  surround_index |= 1;
46  }
47  if ((i < RP->Xsize-1) && layout[i+1][j] != 0) {
48  surround_index |= 2;
49  }
50  if ((j > 0) && layout[i][j-1] != 0) {
51  surround_index |= 4;
52  }
53  if ((j < RP->Ysize-1) && layout[i][j+1] != 0) {
54  surround_index |= 8;
55  }
56  return surround_index;
57 }
58 
77 int surround_flag2(char **layout, int i, int j, RMParms *RP)
78 {
79  int surround_index = 0;
80 
81  if ((i > 0) && layout[i-1][j] == '#') {
82  surround_index |= 1;
83  }
84  if ((i < RP->Xsize-1) && layout[i+1][j] == '#') {
85  surround_index |= 2;
86  }
87  if ((j > 0) && layout[i][j-1] == '#') {
88  surround_index |= 4;
89  }
90  if ((j < RP->Ysize-1) && layout[i][j+1] == '#') {
91  surround_index |= 8;
92  }
93  return surround_index;
94 }
95 
114 int surround_flag3(mapstruct *map, int i, int j, RMParms *RP)
115 {
116  int surround_index = 0;
117 
118  if ((i > 0) && (GET_MAP_MOVE_BLOCK(map, i-1, j)&~MOVE_BLOCK_DEFAULT)) {
119  surround_index |= 1;
120  }
121  if ((i < RP->Xsize-1) && (GET_MAP_MOVE_BLOCK(map, i+1, j)&~MOVE_BLOCK_DEFAULT)) {
122  surround_index |= 2;
123  }
124  if ((j > 0) && (GET_MAP_MOVE_BLOCK(map, i, j-1)&~MOVE_BLOCK_DEFAULT)) {
125  surround_index |= 4;
126  }
127  if ((j < RP->Ysize-1) && (GET_MAP_MOVE_BLOCK(map, i, j+1)&~MOVE_BLOCK_DEFAULT)) {
128  surround_index |= 8;
129  }
130 
131  return surround_index;
132 }
133 
152 int surround_flag4(mapstruct *map, int i, int j, RMParms *RP)
153 {
154  int surround_index = 0;
155 
156  if ((i > 0) && wall_blocked(map, i-1, j)) {
157  surround_index |= 1;
158  }
159  if ((i < RP->Xsize-1) && wall_blocked(map, i+1, j)) {
160  surround_index |= 2;
161  }
162  if ((j > 0) && wall_blocked(map, i, j-1)) {
163  surround_index |= 4;
164  }
165  if ((j < RP->Ysize-1) && wall_blocked(map, i, j+1)) {
166  surround_index |= 8;
167  }
168 
169  return surround_index;
170 }
171 
184 void make_map_walls(mapstruct *map, char **layout, char *w_style, RMParms *RP)
185 {
186  char styledirname[256];
187  mapstruct *style_map = NULL;
188  object *the_wall;
189 
190  /* get the style map */
191  if (!strcmp(w_style, "none")) {
192  return;
193  }
194  snprintf(styledirname, sizeof(styledirname), "%s", "/styles/wallstyles");
195  style_map = find_style(styledirname, w_style, -1);
196  if (style_map == NULL) {
197  return;
198  }
199 
200  /* fill up the map with the given floor style */
201  if ((the_wall = pick_random_object(style_map)) != NULL) {
202  int i, j;
203  char *cp;
204  int joinedwalls = 0;
205  object *thiswall;
206 
207  snprintf(RP->wall_name, sizeof(RP->wall_name), "%s", the_wall->arch->name);
208  if ((cp = strchr(RP->wall_name, '_')) != NULL) {
209  *cp = 0;
210  joinedwalls = 1;
211  }
212 
213  for (i = 0; i < RP->Xsize; i++)
214  for (j = 0; j < RP->Ysize; j++) {
215  if (layout[i][j] == '#') {
216  if (joinedwalls) {
217  thiswall = pick_joined_wall(the_wall, layout, i, j, RP);
218  } else {
219  thiswall = arch_to_object(the_wall->arch);
220  }
221  thiswall->move_block = MOVE_ALL;
222  thiswall->move_allow = 0;
223  object_insert_in_map_at(thiswall, map, thiswall, INS_NO_MERGE|INS_NO_WALK_ON, i, j);
224  }
225  }
226  }
227 }
228 
233 static const char* wall_join[16] = {
234  "_0", "_1_3", "_1_4", "_2_1_2",
235  "_1_2", "_2_2_4", "_2_2_1", "_3_1",
236  "_1_1", "_2_2_3", "_2_2_2", "_3_3",
237  "_2_1_1", "_3_4", "_3_2", "_4"
238 };
239 
256 object *pick_joined_wall(object *the_wall, char **layout, int i, int j, RMParms *RP)
257 {
258  /* 1 = wall to left,
259  2 = wall to right,
260  4 = wall above
261  8 = wall below */
262  int surround_index = 0;
263  int l;
264  char wall_name[64];
265  archetype *wall_arch = NULL;
266 
267  strncpy(wall_name, the_wall->arch->name, sizeof(wall_name));
268 
269  /* conventionally, walls are named like this:
270  wallname_wallcode, where wallcode indicates
271  a joinedness, and wallname is the wall.
272  this code depends on the convention for
273  finding the right wall. */
274 
275  /* extract the wall name, which is the text up to the leading _ */
276  for (l = 0; l < 64; l++) {
277  if (wall_name[l] == '_') {
278  wall_name[l] = 0;
279  break;
280  }
281  }
282 
283  surround_index = surround_flag2(layout, i, j, RP);
284  assert(surround_index >= 0 && surround_index < 16);
285  strcat(wall_name, wall_join[surround_index]);
286 
287  wall_arch = try_find_archetype(wall_name);
288  if (wall_arch) {
289  return arch_to_object(wall_arch);
290  } else {
291  return arch_to_object(the_wall->arch);
292  }
293 }
294 
315 object *retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP)
316 {
317  /* 1 = wall to left,
318  * 2 = wall to right,
319  * 4 = wall above
320  * 8 = wall below
321  */
322  int surround_index = 0;
323  int l;
324  object *the_wall = NULL;
325  object *new_wall = NULL;
326  archetype *wall_arch = NULL;
327 
328  /* first find the wall */
329  FOR_MAP_PREPARE(the_map, i, j, tmp)
330  if ((tmp->move_type&MOVE_WALK) && tmp->type != EXIT && tmp->type != TELEPORTER) {
331  the_wall = tmp;
332  break;
333  }
334  FOR_MAP_FINISH();
335 
336  /* if what we found is a door, don't remove it, set the_wall to NULL to
337  * signal that later.
338  */
339  if (the_wall && (the_wall->type == DOOR || the_wall->type == LOCKED_DOOR)) {
340  the_wall = NULL;
341  /* if we're not supposed to insert a new wall where there wasn't one,
342  * we've gotta leave.
343  */
344  if (insert_flag == 0) {
345  return NULL;
346  }
347  } else if (the_wall == NULL) {
348  return NULL;
349  }
350 
351  /* canonicalize the wall name */
352  for (l = 0; l < 64; l++) {
353  if (RP->wall_name[l] == '_') {
354  RP->wall_name[l] = 0;
355  break;
356  }
357  }
358 
359  surround_index = surround_flag4(the_map, i, j, RP);
360  assert(surround_index >= 0 && surround_index < 16);
361  strcat(RP->wall_name, wall_join[surround_index]);
362  wall_arch = try_find_archetype(RP->wall_name);
363  if (wall_arch != NULL) {
364  new_wall = arch_to_object(wall_arch);
365  if (the_wall && the_wall->map) {
366  object_remove(the_wall);
367  object_free_drop_inventory(the_wall);
368  }
369  the_wall->move_block = MOVE_ALL;
370  object_insert_in_map_at(new_wall, the_map, new_wall, INS_NO_MERGE|INS_NO_WALK_ON, i, j);
371  }
372  return new_wall;
373 }
static const char * wall_join[16]
Suffix to add to a base wall archetype name to get the joined wall based on the value returned by sur...
Definition: wall.c:233
Random map parameters.
Definition: random_map.h:14
#define MOVE_WALK
Object walks.
Definition: define.h:407
int surround_flag2(char **layout, int i, int j, RMParms *RP)
Given a layout and a coordinate, tell me which squares up/down/right/left are occupied by walls...
Definition: wall.c:77
MoveType move_allow
What movement types explicitly allowed.
Definition: object.h:426
Random map related variables.
int surround_flag(char **layout, int i, int j, RMParms *RP)
Given a layout and a coordinate, tell me which squares up/down/right/left are occupied.
Definition: wall.c:40
Global type definitions and header inclusions.
object * pick_random_object(mapstruct *style)
Picks a random object from a style map.
Definition: style.c:286
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
#define MOVE_ALL
Mask of all movement types.
Definition: define.h:413
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
See Exit.
Definition: object.h:181
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
#define snprintf
Definition: win32.h:46
#define INS_NO_WALK_ON
Don&#39;t call check_walk_on against the originator.
Definition: object.h:570
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
int surround_flag3(mapstruct *map, int i, int j, RMParms *RP)
Check a map for blocked spots.
Definition: wall.c:114
archetype * try_find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:666
See Locked Door.
Definition: object.h:123
See Door.
Definition: object.h:126
int Ysize
Definition: random_map.h:70
#define MOVE_BLOCK_DEFAULT
The normal assumption is that objects are walking/flying.
Definition: define.h:424
object * retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP)
this takes a map, and changes an existing wall to match what&#39;s blocked around it, counting only doors...
Definition: wall.c:315
int wall_blocked(mapstruct *m, int x, int y)
Returns true if square x,y has P_NO_PASS set, which is true for walls and doors but not monsters...
Definition: treasure.c:62
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
int Xsize
Definition: random_map.h:69
char wall_name[RM_SIZE]
Will contain the actual wall archetype, can be an empty string in which case a random one is chosen...
Definition: random_map.h:24
#define INS_NO_MERGE
Don&#39;t try to merge with other items.
Definition: object.h:568
struct archt * arch
Pointer to archetype.
Definition: object.h:412
void make_map_walls(mapstruct *map, char **layout, char *w_style, RMParms *RP)
takes a map and a layout, and puts walls in the map (picked from w_style) at &#39;#&#39; marks.
Definition: wall.c:184
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
object * pick_joined_wall(object *the_wall, char **layout, int i, int j, RMParms *RP)
Picks the right wall type for this square, to make it look nice, and have everything nicely joined...
Definition: wall.c:256
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
MoveType move_block
What movement types this blocks.
Definition: object.h:425
mapstruct * find_style(const char *dirname, const char *stylename, int difficulty)
Loads and returns the map requested.
Definition: style.c:180
This is a game-map.
Definition: map.h:325
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
See Teleporter.
Definition: object.h:141
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
int surround_flag4(mapstruct *map, int i, int j, RMParms *RP)
Check a map for spots with walls.
Definition: wall.c:152
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
Definition: main.c:88