Crossfire Server, Trunk
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  mapstruct *style_map = NULL;
187  object *the_wall;
188 
189  /* get the style map */
190  if (!strcmp(w_style, "none")) {
191  return;
192  }
193  const char *styledirname = "/styles/wallstyles";
194  style_map = find_style(styledirname, w_style, -1);
195  if (style_map == NULL) {
196  return;
197  }
198 
199  /* fill up the map with the given floor style */
200  if ((the_wall = pick_random_object(style_map)) != NULL) {
201  int i, j;
202  char *cp;
203  int joinedwalls = 0;
204  object *thiswall;
205 
206  strlcpy(RP->wall_name, the_wall->arch->name, sizeof(RP->wall_name));
207  if ((cp = strchr(RP->wall_name, '_')) != NULL) {
208  *cp = 0;
209  joinedwalls = 1;
210  }
211 
212  for (i = 0; i < RP->Xsize; i++)
213  for (j = 0; j < RP->Ysize; j++) {
214  if (layout[i][j] == '#') {
215  if (joinedwalls) {
216  thiswall = pick_joined_wall(the_wall, layout, i, j, RP);
217  } else {
218  thiswall = arch_to_object(the_wall->arch);
219  }
220  thiswall->move_block = MOVE_ALL;
221  thiswall->move_allow = 0;
222  object_insert_in_map_at(thiswall, map, thiswall, INS_NO_MERGE|INS_NO_WALK_ON, i, j);
223  }
224  }
225  }
226 }
227 
232 static const char* wall_join[16] = {
233  "_0", "_1_3", "_1_4", "_2_1_2",
234  "_1_2", "_2_2_4", "_2_2_1", "_3_1",
235  "_1_1", "_2_2_3", "_2_2_2", "_3_3",
236  "_2_1_1", "_3_4", "_3_2", "_4"
237 };
238 
255 object *pick_joined_wall(object *the_wall, char **layout, int i, int j, RMParms *RP)
256 {
257  /* 1 = wall to left,
258  2 = wall to right,
259  4 = wall above
260  8 = wall below */
261  int surround_index = 0;
262  int l;
263  char wall_name[64];
264  archetype *wall_arch = NULL;
265 
266  strncpy(wall_name, the_wall->arch->name, sizeof(wall_name));
267 
268  /* conventionally, walls are named like this:
269  wallname_wallcode, where wallcode indicates
270  a joinedness, and wallname is the wall.
271  this code depends on the convention for
272  finding the right wall. */
273 
274  /* extract the wall name, which is the text up to the leading _ */
275  for (l = 0; l < 64; l++) {
276  if (wall_name[l] == '_') {
277  wall_name[l] = 0;
278  break;
279  }
280  }
281 
282  surround_index = surround_flag2(layout, i, j, RP);
283  assert(surround_index >= 0 && surround_index < 16);
284  strcat(wall_name, wall_join[surround_index]);
285 
286  wall_arch = try_find_archetype(wall_name);
287  if (wall_arch) {
288  return arch_to_object(wall_arch);
289  } else {
290  return arch_to_object(the_wall->arch);
291  }
292 }
293 
314 object *retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP)
315 {
316  /* 1 = wall to left,
317  * 2 = wall to right,
318  * 4 = wall above
319  * 8 = wall below
320  */
321  int surround_index = 0;
322  int l;
323  object *the_wall = NULL;
324  object *new_wall = NULL;
325  archetype *wall_arch = NULL;
326 
327  /* first find the wall */
328  FOR_MAP_PREPARE(the_map, i, j, tmp)
329  if ((tmp->move_type&MOVE_WALK) && tmp->type != EXIT && tmp->type != TELEPORTER) {
330  the_wall = tmp;
331  break;
332  }
333  FOR_MAP_FINISH();
334 
335  /* if what we found is a door, don't remove it, set the_wall to NULL to
336  * signal that later.
337  */
338  if (the_wall && (the_wall->type == DOOR || the_wall->type == LOCKED_DOOR)) {
339  the_wall = NULL;
340  /* if we're not supposed to insert a new wall where there wasn't one,
341  * we've gotta leave.
342  */
343  if (insert_flag == 0) {
344  return NULL;
345  }
346  } else if (the_wall == NULL) {
347  return NULL;
348  }
349 
350  /* canonicalize the wall name */
351  for (l = 0; l < 64; l++) {
352  if (RP->wall_name[l] == '_') {
353  RP->wall_name[l] = 0;
354  break;
355  }
356  }
357 
358  surround_index = surround_flag4(the_map, i, j, RP);
359  assert(surround_index >= 0 && surround_index < 16);
360  strcat(RP->wall_name, wall_join[surround_index]);
361  wall_arch = try_find_archetype(RP->wall_name);
362  if (wall_arch != NULL) {
363  new_wall = arch_to_object(wall_arch);
364  if (the_wall && the_wall->map) {
365  object_remove(the_wall);
366  object_free_drop_inventory(the_wall);
367  }
368  the_wall->move_block = MOVE_ALL;
369  object_insert_in_map_at(new_wall, the_map, new_wall, INS_NO_MERGE|INS_NO_WALK_ON, i, j);
370  }
371  return new_wall;
372 }
surround_flag
int surround_flag(char **layout, int i, int j, RMParms *RP)
Definition: wall.c:40
global.h
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:568
banquet.l
l
Definition: banquet.py:164
random_map.h
object_remove
void object_remove(object *op)
Definition: object.c:1819
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
MOVE_BLOCK_DEFAULT
#define MOVE_BLOCK_DEFAULT
Definition: define.h:409
obj::move_block
MoveType move_block
Definition: object.h:430
layout
Definition: main.c:85
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
obj::map
struct mapdef * map
Definition: object.h:300
surround_flag4
int surround_flag4(mapstruct *map, int i, int j, RMParms *RP)
Definition: wall.c:152
RMParms::Ysize
int Ysize
Definition: random_map.h:75
Ice.tmp
int tmp
Definition: Ice.py:207
find_style
mapstruct * find_style(const char *dirname, const char *stylename, int difficulty)
Definition: style.c:180
RMParms
Definition: random_map.h:14
archt
Definition: object.h:469
RMParms::wall_name
char wall_name[RM_SIZE]
Definition: random_map.h:24
surround_flag2
int surround_flag2(char **layout, int i, int j, RMParms *RP)
Definition: wall.c:77
disinfect.map
map
Definition: disinfect.py:4
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:123
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:566
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
rproto.h
mapdef
Definition: map.h:317
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:220
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:181
obj::arch
struct archt * arch
Definition: object.h:417
obj::type
uint8_t type
Definition: object.h:343
pick_joined_wall
object * pick_joined_wall(object *the_wall, char **layout, int i, int j, RMParms *RP)
Definition: wall.c:255
surround_flag3
int surround_flag3(mapstruct *map, int i, int j, RMParms *RP)
Definition: wall.c:114
wall_join
static const char * wall_join[16]
Definition: wall.c:232
pick_random_object
object * pick_random_object(mapstruct *style)
Definition: style.c:289
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
retrofit_joined_wall
object * retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP)
Definition: wall.c:314
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2080
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1546
wall_blocked
int wall_blocked(mapstruct *m, int x, int y)
Definition: treasure.c:62
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:288
DOOR
@ DOOR
Definition: object.h:126
archt::name
sstring name
Definition: object.h:470
make_map_walls
void make_map_walls(mapstruct *map, char **layout, char *w_style, RMParms *RP)
Definition: wall.c:184
TELEPORTER
@ TELEPORTER
Definition: object.h:141
obj::move_allow
MoveType move_allow
Definition: object.h:431
RMParms::Xsize
int Xsize
Definition: random_map.h:74