Crossfire Server, Trunk
move.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 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 
19 #include "global.h"
20 
21 #include <stdlib.h>
22 
23 #include "sproto.h"
24 
25 static int roll_ob(object *op, int dir, object *pusher);
26 
39 int move_object(object *op, int dir) {
40  return move_ob(op, dir, op);
41 }
42 
58 int move_ob(object *op, int dir, object *originator) {
59  object *part;
60  mapstruct *m;
61 
62  op->direction = dir;
63 
64  if (op->will_apply&(WILL_APPLY_EARTHWALL|WILL_APPLY_DOOR)) {
65  tag_t op_tag;
66 
67  op_tag = op->count;
68  for (part = op; part != NULL; part = part->more) {
69  int16_t x, y;
70 
71  if (get_map_flags(part->map, &m, part->x+freearr_x[dir], part->y+freearr_y[dir], &x, &y)&P_OUT_OF_MAP)
72  continue;
73 
74  if (op->will_apply&WILL_APPLY_EARTHWALL) {
76  if (object_was_destroyed(op, op_tag))
77  return 1;
78  }
79 
80  if (op->will_apply&WILL_APPLY_DOOR) {
82  if (object_was_destroyed(op, op_tag))
83  return 1;
84  }
85  }
86  }
87 
88  for (part = op; part != NULL; part = part->more) {
89  int16_t x, y;
90 
91  if (get_map_flags(part->map, &m, part->x+freearr_x[dir], part->y+freearr_y[dir], &x, &y)&P_OUT_OF_MAP)
92  return 0;
93 
94  if (!QUERY_FLAG(op, FLAG_WIZPASS) && blocked_link(op->type == TRANSPORT ? part : op, m, x, y))
95  return 0;
96  }
97 
98  if (QUERY_FLAG(op, FLAG_ALIVE) && op->move_type == MOVE_WALK && op->weight >= 100) {
99  if (!op->hide) {
100  play_sound_map(SOUND_TYPE_GROUND, op, 0, "step");
101  }
102  }
103 
104  // It is possible for op to be inanimate and not have a move type, e.g.
105  // when this function is called by check_spell_knockback(). In this case
106  // we need to give it a temporary move type so that object_remove() and
107  // object_insert_in_map_at() correctly trigger move_on events for this
108  // object.
109  MoveType old_move_type = op->move_type;
110  if (old_move_type == 0) {
111  op->move_type = MOVE_WALK; // triggers buttons and such
112  }
113 
114  object_remove(op);
115  object_insert_in_map_at(op, op->map, originator, 0, op->x+freearr_x[dir], op->y+freearr_y[dir]);
116 
117  // Restore original move type.
118  op->move_type = old_move_type;
119 
120  /* Hmmm. Should be possible for multispace players now */
121  if (op->type == PLAYER) {
122  esrv_map_scroll(&op->contr->socket, freearr_x[dir], freearr_y[dir]);
123  op->contr->socket.update_look = 1;
124  op->contr->socket.look_position = 0;
125  } else if (op->type == TRANSPORT) {
127  if (pl->type == PLAYER) {
128  pl->contr->do_los = 1;
129  pl->map = op->map;
130  pl->x = op->x;
131  pl->y = op->y;
132  esrv_map_scroll(&pl->contr->socket, freearr_x[dir], freearr_y[dir]);
133  pl->contr->socket.update_look = 1;
134  pl->contr->socket.look_position = 0;
135  }
136  FOR_INV_FINISH();
137  }
138 
139  return 1; /* this shouldn't be reached */
140 }
141 
163 int transfer_ob(object *op, int x, int y, int randomly, object *originator) {
164  int i;
165 
166  if (randomly)
167  i = object_find_free_spot(op, op->map, x, y, 0, SIZEOFFREE);
168  else
169  i = object_find_first_free_spot(op, op->map, x, y);
170 
171  if (i == -1)
172  return 0; /* No free spot */
173 
174  op = HEAD(op);
175  object_remove(op);
176  op = object_insert_in_map_at(op, op->map, originator, 0, x+freearr_x[i], y+freearr_y[i]);
177  if (op && op->type == PLAYER) {
178  map_newmap_cmd(&op->contr->socket);
181  }
182  return op ? 0 : 1;
183 }
184 
204 int teleport(object *teleporter, uint8_t tele_type, object *user) {
205  object *altern[120]; /* Better use c/malloc here in the future */
206  int i, j, k, nrofalt = 0;
207  object *other_teleporter;
208  mapstruct *m;
209  int16_t sx, sy;
210 
211  if (user == NULL)
212  return 0;
213  user = HEAD(user);
214 
215  /* Find all other teleporters within range. This range
216  * should really be setable by some object attribute instead of
217  * using hard coded values.
218  */
219  for (i = -5; i < 6; i++)
220  for (j = -5; j < 6; j++) {
221  if (i == 0 && j == 0)
222  continue;
223  /* Perhaps this should be extended to support tiled maps */
224  if (OUT_OF_REAL_MAP(teleporter->map, teleporter->x+i, teleporter->y+j))
225  continue;
226  FOR_MAP_PREPARE(teleporter->map, teleporter->x+i, teleporter->y+j, tmp) {
227  if (tmp->type == tele_type) {
228  altern[nrofalt++] = tmp;
229  break;
230  }
231  } FOR_MAP_FINISH();
232  }
233 
234  if (!nrofalt) {
235  LOG(llevError, "No alternative teleporters around!\n");
236  return 0;
237  }
238 
239  other_teleporter = altern[RANDOM()%nrofalt];
240  k = object_find_free_spot(user, other_teleporter->map, other_teleporter->x, other_teleporter->y, 1, 9);
241 
242  /* if k==-1, unable to find a free spot. If this is shop
243  * mat that the player is using, find someplace to move
244  * the player - otherwise, player can get trapped in the shops
245  * that appear in random dungeons. We basically just make
246  * sure the space isn't no pass (eg wall), and don't care
247  * about is alive.
248  */
249  if (k == -1) {
250  if (tele_type == SHOP_MAT && user->type == PLAYER) {
251  for (k = 1; k < 9; k++) {
252  if (get_map_flags(other_teleporter->map, &m,
253  other_teleporter->x+freearr_x[k],
254  other_teleporter->y+freearr_y[k], &sx, &sy)&P_OUT_OF_MAP)
255  continue;
256 
257  if (!OB_TYPE_MOVE_BLOCK(user, GET_MAP_MOVE_BLOCK(m, sx, sy)))
258  break;
259  }
260  if (k == 9) {
261  LOG(llevError, "Shop mat %s (%d, %d) is in solid rock?\n", other_teleporter->name, other_teleporter->x, other_teleporter->y);
262  /* Teleport player on top of blocked destination: this prevents
263  * players from being trapped inside shops if the destination
264  * is blocked with earth walls.
265  */
266  k = 0;
267  }
268  } else
269  return 0;
270  }
271 
272  object_remove(user);
273 
274  user = object_insert_in_map_at(user, other_teleporter->map, NULL, 0, other_teleporter->x+freearr_x[k], other_teleporter->y+freearr_y[k]);
275  if (user && user->type == PLAYER) {
276  map_newmap_cmd(&user->contr->socket);
278  pets_attempt_follow(user, 1);
279  }
280  return (user == NULL);
281 }
282 
293 void recursive_roll(object *op, int dir, object *pusher) {
294  char name[MAX_BUF];
295 
297  if (!roll_ob(op, dir, pusher)) {
299  "You fail to push the %s.",
300  name);
301  return;
302  }
303  (void)move_ob(pusher, dir, pusher);
305  "You move the %s.",
306  name);
307  return;
308 }
309 
331 static int try_fit(object *op, mapstruct *m, int x, int y) {
332  object *more;
333  int16_t tx, ty;
334  int mflags;
335  mapstruct *m2;
336 
337  op = HEAD(op);
338  for (more = op; more; more = more->more) {
339  tx = x+more->x-op->x;
340  ty = y+more->y-op->y;
341 
342  mflags = get_map_flags(m, &m2, tx, ty, &tx, &ty);
343 
344  if (mflags&P_OUT_OF_MAP)
345  return 1;
346 
347  FOR_MAP_PREPARE(m2, tx, ty, tmp) {
348  if (tmp->head == op || tmp == op)
349  continue;
350 
351  if ((QUERY_FLAG(tmp, FLAG_ALIVE) && tmp->type != DOOR))
352  return 1;
353 
354  if (OB_MOVE_BLOCK(op, tmp))
355  return 1;
356  } FOR_MAP_FINISH();
357  }
358  return 0;
359 }
360 
380 static int roll_ob(object *op, int dir, object *pusher) {
381  int16_t x, y;
382  int flags;
383  mapstruct *m;
384  MoveType move_block;
385 
386  op = HEAD(op);
387  x = op->x+freearr_x[dir];
388  y = op->y+freearr_y[dir];
389 
391  || (op->weight && random_roll(0, op->weight/50000-1, pusher, PREFER_LOW) > pusher->stats.Str))
392  return 0;
393 
394  m = op->map;
395  flags = get_map_flags(m, &m, x, y, &x, &y);
396 
398  return 0;
399 
400  move_block = GET_MAP_MOVE_BLOCK(m, x, y);
401 
402  /* If the target space is not blocked, no need to look at the objects on it */
403  if ((op->move_type&move_block) == op->move_type) {
404  FOR_MAP_PREPARE(m, x, y, tmp) {
405  if (tmp->head == op)
406  continue;
407  if (OB_MOVE_BLOCK(op, tmp) && !roll_ob(tmp, dir, pusher))
408  return 0;
409  } FOR_MAP_FINISH();
410  }
411  if (try_fit(op, m, x, y))
412  return 0;
413 
414  object_remove(op);
415  object_insert_in_map_at(op, op->map, pusher, 0, op->x+freearr_x[dir], op->y+freearr_y[dir]);
416  return 1;
417 }
418 
434 int push_ob(object *who, int dir, object *pusher) {
435  int str1, str2;
436  object *owner;
437 
438  who = HEAD(who);
439  owner = object_get_owner(who);
440 
441  /* Wake up sleeping monsters that may be pushed */
443 
444  /* player change place with his pets or summoned creature */
445  /* TODO: allow multi arch pushing. Can't be very difficult */
446  if (who->more == NULL
447  && (owner == pusher || (owner != NULL && owner->type == PLAYER && owner->contr->party != NULL && owner->contr->party == pusher->contr->party))) {
448  int temp;
449  mapstruct *m;
450 
452  object_remove(pusher);
453  temp = pusher->x;
454  pusher->x = who->x;
455  who->x = temp;
456 
457  temp = pusher->y;
458  pusher->y = who->y;
459  who->y = temp;
460 
461  m = pusher->map;
462  pusher->map = who->map;
463  who->map = m;
464 
465  object_insert_in_map_at(who, who->map, pusher, 0, who->x, who->y);
466  object_insert_in_map_at(pusher, pusher->map, pusher, 0, pusher->x, pusher->y);
467 
468  /* we presume that if the player is pushing his put, he moved in
469  * direction 'dir'. I can' think of any case where this would not be
470  * the case. Putting the map_scroll should also improve performance some.
471  */
472  if (pusher->type == PLAYER) {
473  esrv_map_scroll(&pusher->contr->socket, freearr_x[dir], freearr_y[dir]);
474  pusher->contr->socket.update_look = 1;
475  pusher->contr->socket.look_position = 0;
476  }
477  return 0;
478  }
479 
480  /* We want ONLY become enemy of evil, unaggressive monster. We must RUN in them */
481  /* In original we have here a unaggressive check only - that was the reason why */
482  /* we so often become an enemy of friendly monsters... */
483  /* funny: was they set to unaggressive 0 (= not so nice) they don't attack */
484  if (owner != pusher
485  && pusher->type == PLAYER
486  && who->type != PLAYER
488  && !QUERY_FLAG(who, FLAG_NEUTRAL)) {
489  if (pusher->contr->run_on) { /* only when we run */
490  draw_ext_info_format(NDI_UNIQUE, 0, pusher,
492  "You start to attack %s!",
493  who->name);
494  CLEAR_FLAG(who, FLAG_UNAGGRESSIVE); /* the sucker don't like you anymore */
495  object_set_enemy(who, pusher);
497  return 1;
498  } else {
499  draw_ext_info_format(NDI_UNIQUE, 0, pusher,
501  "You avoid attacking %s.",
502  who->name);
503  }
504  }
505 
506  /* now, lets test stand still. we NEVER can push stand_still monsters. */
508  draw_ext_info_format(NDI_UNIQUE, 0, pusher,
510  "You can't push %s.",
511  who->name);
512  return 0;
513  }
514 
515  /* This block is basically if you are pushing friendly but
516  * non pet creaturs.
517  * It basically does a random strength comparision to
518  * determine if you can push someone around. Note that
519  * this pushes the other person away - its not a swap.
520  */
521 
522  str1 = (who->stats.Str > 0 ? who->stats.Str : who->level);
523  str2 = (pusher->stats.Str > 0 ? pusher->stats.Str : pusher->level);
524  if (QUERY_FLAG(who, FLAG_WIZ)
525  || random_roll(str1, str1/2+str1*2, who, PREFER_HIGH) >= random_roll(str2, str2/2+str2*2, pusher, PREFER_HIGH)
526  || !move_object(who, dir)) {
527  if (who->type == PLAYER) {
529  "%s tried to push you.",
530  pusher->name);
531  }
532  return 0;
533  }
534 
535  /* If we get here, the push succeeded.
536  * Let everyone know the status.
537  */
538  if (who->type == PLAYER) {
540  "%s pushed you.",
541  pusher->name);
542  }
543  if (pusher->type == PLAYER) {
545  "You pushed %s back.",
546  who->name);
547  }
548 
549  return 1;
550 }
551 
563 int move_to(object *op, int x, int y) {
564  int direction;
565 
566  if (op->x == x && op->y == y)
567  return 0;
568 
569  if (get_map_flags(op->map, NULL, x, y, NULL, NULL)&P_OUT_OF_MAP)
570  return 2;
571 
572  direction = monster_compute_path(op, GET_MAP_OB(op->map, x, y), -1);
573  if (direction == -1)
574  return 2;
575 
576  op->direction = direction;
577  op->facing = direction;
578  if (op->animation)
579  animate_object(op, op->direction);
580 
581  /* can fail, as the direction computing takes into account the blocked state,
582  * except for the final spot... */
583  if (move_ob(op, direction, op) == 0)
584  return 2;
585 
586  return 1;
587 }
588 
597 int object_teleport(object *op, mapstruct *map, int x, int y) {
598  if (!out_of_map(map, x, y)) {
599  int k;
601  if (k == -1) {
602  return 0;
603  }
604 
605  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
606  object_remove(op);
607  }
608 
609  object_insert_in_map_at(op, map, NULL, 0, x, y);
610  if (op->type == PLAYER) {
611  map_newmap_cmd(&op->contr->socket);
613  }
614  return 1;
615  }
616  return 0;
617 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3570
PLAYER
@ PLAYER
Definition: object.h:107
global.h
FLAG_NEUTRAL
#define FLAG_NEUTRAL
Definition: define.h:354
object_remove
void object_remove(object *op)
Definition: object.c:1819
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.c:919
FLAG_STAND_STILL
#define FLAG_STAND_STILL
Definition: define.h:308
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:530
llevError
@ llevError
Definition: logger.h:11
push_ob
int push_ob(object *who, int dir, object *pusher)
Definition: move.c:434
esrv_map_scroll
void esrv_map_scroll(socket_struct *ns, int dx, int dy)
Definition: request.c:1613
socket_struct::look_position
uint16_t look_position
Definition: newserver.h:114
diamondslots.x
x
Definition: diamondslots.py:15
obj::map
struct mapdef * map
Definition: object.h:300
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
move_to
int move_to(object *op, int x, int y)
Definition: move.c:563
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2312
liv::Str
int8_t Str
Definition: living.h:36
monster_check_doors
void monster_check_doors(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2270
pl::socket
socket_struct socket
Definition: player.h:107
pl
Definition: player.h:105
PREFER_LOW
#define PREFER_LOW
Definition: define.h:564
MoveType
unsigned char MoveType
Definition: define.h:417
monster_check_earthwalls
void monster_check_earthwalls(object *op, mapstruct *m, int x, int y)
Definition: monster.c:2254
blocked_link
int blocked_link(object *ob, mapstruct *m, int16_t sx, int16_t sy)
Definition: map.c:345
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:113
Ice.tmp
int tmp
Definition: Ice.py:207
TRANSPORT
@ TRANSPORT
Definition: object.h:108
flags
static const flag_definition flags[]
Definition: gridarta-types-convert.c:101
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
teleport
int teleport(object *teleporter, uint8_t tele_type, object *user)
Definition: move.c:204
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:415
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:299
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:305
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
animate_object
void animate_object(object *op, int dir)
Definition: anim.c:43
socket_struct::update_look
uint32_t update_look
Definition: newserver.h:104
m
static event_registration m
Definition: citylife.cpp:427
autojail.who
who
Definition: autojail.py:3
PREFER_HIGH
#define PREFER_HIGH
Definition: define.h:563
disinfect.map
map
Definition: disinfect.py:4
obj::name
sstring name
Definition: object.h:314
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:585
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
HEAD
#define HEAD(op)
Definition: object.h:594
obj::x
int16_t x
Definition: object.h:330
move_ob
int move_ob(object *op, int dir, object *originator)
Definition: move.c:58
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
FLAG_CAN_ROLL
#define FLAG_CAN_ROLL
Definition: define.h:254
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
pl::run_on
uint32_t run_on
Definition: player.h:143
tag_t
uint32_t tag_t
Definition: object.h:12
sproto.h
give.direction
direction
Definition: give.py:37
mapdef
Definition: map.h:324
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
recursive_roll
void recursive_roll(object *op, int dir, object *pusher)
Definition: move.c:293
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
MAX_BUF
#define MAX_BUF
Definition: define.h:35
SHOP_MAT
@ SHOP_MAT
Definition: object.h:184
OB_MOVE_BLOCK
#define OB_MOVE_BLOCK(ob1, ob2)
Definition: define.h:423
RANDOM
#define RANDOM()
Definition: define.h:644
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:42
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:531
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
obj::y
int16_t y
Definition: object.h:330
OUT_OF_REAL_MAP
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:218
pets_attempt_follow
void pets_attempt_follow(object *for_owner, int force)
Definition: pets.c:248
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
obj::type
uint8_t type
Definition: object.h:343
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
obj::stats
living stats
Definition: object.h:373
obj::contr
struct pl * contr
Definition: object.h:279
MSG_TYPE_VICTIM_WAS_PUSHED
#define MSG_TYPE_VICTIM_WAS_PUSHED
Definition: newclient.h:657
SOUND_TYPE_GROUND
#define SOUND_TYPE_GROUND
Definition: newclient.h:336
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3530
monster_npc_call_help
void monster_npc_call_help(object *op)
Definition: monster.c:2004
pl::do_los
uint32_t do_los
Definition: player.h:141
roll_ob
static int roll_ob(object *op, int dir, object *pusher)
Definition: move.c:380
diamondslots.y
y
Definition: diamondslots.py:16
WILL_APPLY_DOOR
#define WILL_APPLY_DOOR
Definition: object.h:55
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
obj::more
struct obj * more
Definition: object.h:298
map_newmap_cmd
void map_newmap_cmd(socket_struct *ns)
Definition: request.c:620
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
DOOR
@ DOOR
Definition: object.h:126
OB_TYPE_MOVE_BLOCK
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:432
transfer_ob
int transfer_ob(object *op, int x, int y, int randomly, object *originator)
Definition: move.c:163
object_teleport
int object_teleport(object *op, mapstruct *map, int x, int y)
Definition: move.c:597
WILL_APPLY_EARTHWALL
#define WILL_APPLY_EARTHWALL
Definition: object.h:54
pl::party
partylist * party
Definition: player.h:202
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:301
guildbuy.temp
def temp
Definition: guildbuy.py:26
try_fit
static int try_fit(object *op, mapstruct *m, int x, int y)
Definition: move.c:331
FLAG_SLEEP
#define FLAG_SLEEP
Definition: define.h:307
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
obj::level
int16_t level
Definition: object.h:356
monster_compute_path
int monster_compute_path(object *source, object *target, int default_dir)
Definition: monster.c:465
give.name
name
Definition: give.py:27
player_update_bg_music
void player_update_bg_music(object *player)
object_get_owner
object * object_get_owner(object *op)
Definition: object.c:808
move_object
int move_object(object *op, int dir)
Definition: move.c:39