/ circle3.1 / src / utils.h
utils.h
  1  /* ************************************************************************
  2  *   File: utils.h                                       Part of CircleMUD *
  3  *  Usage: header file: utility macros and prototypes of utility funcs     *
  4  *                                                                         *
  5  *  All rights reserved.  See license.doc for complete information.        *
  6  *                                                                         *
  7  *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
  8  *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
  9  ************************************************************************ */
 10  
 11  
 12  /* external declarations and prototypes **********************************/
 13  
 14  extern struct weather_data weather_info;
 15  extern FILE *logfile;
 16  
 17  #define log			basic_mud_log
 18  
 19  #define READ_SIZE	256
 20  
 21  /* public functions in utils.c */
 22  void	basic_mud_log(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
 23  void	basic_mud_vlog(const char *format, va_list args);
 24  int	touch(const char *path);
 25  void	mudlog(int type, int level, int file, const char *str, ...) __attribute__ ((format (printf, 4, 5)));
 26  void	log_death_trap(struct char_data *ch);
 27  int	rand_number(int from, int to);
 28  int	dice(int number, int size);
 29  size_t	sprintbit(bitvector_t vektor, const char *names[], char *result, size_t reslen);
 30  size_t	sprinttype(int type, const char *names[], char *result, size_t reslen);
 31  int	get_line(FILE *fl, char *buf);
 32  int	get_filename(char *filename, size_t fbufsize, int mode, const char *orig_name);
 33  time_t	mud_time_to_secs(struct time_info_data *now);
 34  struct time_info_data *age(struct char_data *ch);
 35  int	num_pc_in_room(struct room_data *room);
 36  void	core_dump_real(const char *, int);
 37  int	room_is_dark(room_rnum room);
 38  
 39  #define core_dump()		core_dump_real(__FILE__, __LINE__)
 40  
 41  /*
 42   * Only provide our versions if one isn't in the C library. These macro names
 43   * will be defined by sysdep.h if a strcasecmp or stricmp exists.
 44   */
 45  #ifndef str_cmp
 46  int	str_cmp(const char *arg1, const char *arg2);
 47  #endif
 48  #ifndef strn_cmp
 49  int	strn_cmp(const char *arg1, const char *arg2, int n);
 50  #endif
 51  
 52  /* random functions in random.c */
 53  void circle_srandom(unsigned long initial_seed);
 54  unsigned long circle_random(void);
 55  
 56  /* undefine MAX and MIN so that our functions are used instead */
 57  #ifdef MAX
 58  #undef MAX
 59  #endif
 60  
 61  #ifdef MIN
 62  #undef MIN
 63  #endif
 64  
 65  int MAX(int a, int b);
 66  int MIN(int a, int b);
 67  char *CAP(char *txt);
 68  
 69  /* Followers */
 70  int	num_followers_charmed(struct char_data *ch);
 71  void	die_follower(struct char_data *ch);
 72  void	add_follower(struct char_data *ch, struct char_data *leader);
 73  void	stop_follower(struct char_data *ch);
 74  bool	circle_follow(struct char_data *ch, struct char_data *victim);
 75  
 76  /* in act.informative.c */
 77  void	look_at_room(struct char_data *ch, int mode);
 78  
 79  /* in act.movmement.c */
 80  int	do_simple_move(struct char_data *ch, int dir, int following);
 81  int	perform_move(struct char_data *ch, int dir, int following);
 82  
 83  /* in limits.c */
 84  int	mana_gain(struct char_data *ch);
 85  int	hit_gain(struct char_data *ch);
 86  int	move_gain(struct char_data *ch);
 87  void	advance_level(struct char_data *ch);
 88  void	set_title(struct char_data *ch, char *title);
 89  void	gain_exp(struct char_data *ch, int gain);
 90  void	gain_exp_regardless(struct char_data *ch, int gain);
 91  void	gain_condition(struct char_data *ch, int condition, int value);
 92  void	check_idling(struct char_data *ch);
 93  void	point_update(void);
 94  void	update_pos(struct char_data *victim);
 95  
 96  
 97  /* various constants *****************************************************/
 98  
 99  /* defines for mudlog() */
100  #define OFF	0
101  #define BRF	1
102  #define NRM	2
103  #define CMP	3
104  
105  /* get_filename() */
106  #define CRASH_FILE	0
107  #define ETEXT_FILE	1
108  #define ALIAS_FILE	2
109  
110  /* breadth-first searching */
111  #define BFS_ERROR		(-1)
112  #define BFS_ALREADY_THERE	(-2)
113  #define BFS_NO_PATH		(-3)
114  
115  /*
116   * XXX: These constants should be configurable. See act.informative.c
117   *	and utils.c for other places to change.
118   */
119  /* mud-life time */
120  #define SECS_PER_MUD_HOUR	75
121  #define SECS_PER_MUD_DAY	(24*SECS_PER_MUD_HOUR)
122  #define SECS_PER_MUD_MONTH	(35*SECS_PER_MUD_DAY)
123  #define SECS_PER_MUD_YEAR	(17*SECS_PER_MUD_MONTH)
124  
125  /* real-life time (remember Real Life?) */
126  #define SECS_PER_REAL_MIN	60
127  #define SECS_PER_REAL_HOUR	(60*SECS_PER_REAL_MIN)
128  #define SECS_PER_REAL_DAY	(24*SECS_PER_REAL_HOUR)
129  #define SECS_PER_REAL_YEAR	(365*SECS_PER_REAL_DAY)
130  
131  
132  /* string utils **********************************************************/
133  
134  
135  #define YESNO(a) ((a) ? "YES" : "NO")
136  #define ONOFF(a) ((a) ? "ON" : "OFF")
137  
138  #define LOWER(c)   (((c)>='A'  && (c) <= 'Z') ? ((c)+('a'-'A')) : (c))
139  #define UPPER(c)   (((c)>='a'  && (c) <= 'z') ? ((c)+('A'-'a')) : (c) )
140  
141  #define ISNEWL(ch) ((ch) == '\n' || (ch) == '\r') 
142  
143  /* See also: ANA, SANA */
144  #define AN(string) (strchr("aeiouAEIOU", *string) ? "an" : "a")
145  
146  
147  /* memory utils **********************************************************/
148  
149  
150  #define CREATE(result, type, number)  do {\
151  	if ((number) * sizeof(type) <= 0)	\
152  		log("SYSERR: Zero bytes or less requested at %s:%d.", __FILE__, __LINE__);	\
153  	if (!((result) = (type *) calloc ((number), sizeof(type))))	\
154  		{ perror("SYSERR: malloc failure"); abort(); } } while(0)
155  
156  #define RECREATE(result,type,number) do {\
157    if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\
158  		{ perror("SYSERR: realloc failure"); abort(); } } while(0)
159  
160  /*
161   * the source previously used the same code in many places to remove an item
162   * from a list: if it's the list head, change the head, else traverse the
163   * list looking for the item before the one to be removed.  Now, we have a
164   * macro to do this.  To use, just make sure that there is a variable 'temp'
165   * declared as the same type as the list to be manipulated.  BTW, this is
166   * a great application for C++ templates but, alas, this is not C++.  Maybe
167   * CircleMUD 4.0 will be...
168   */
169  #define REMOVE_FROM_LIST(item, head, next)	\
170     if ((item) == (head))		\
171        head = (item)->next;		\
172     else {				\
173        temp = head;			\
174        while (temp && (temp->next != (item))) \
175  	 temp = temp->next;		\
176        if (temp)				\
177           temp->next = (item)->next;	\
178     }					\
179  
180  
181  /* basic bitvector utils *************************************************/
182  
183  
184  #define IS_SET(flag,bit)  ((flag) & (bit))
185  #define SET_BIT(var,bit)  ((var) |= (bit))
186  #define REMOVE_BIT(var,bit)  ((var) &= ~(bit))
187  #define TOGGLE_BIT(var,bit) ((var) ^= (bit))
188  
189  /*
190   * Accessing player specific data structures on a mobile is a very bad thing
191   * to do.  Consider that changing these variables for a single mob will change
192   * it for every other single mob in the game.  If we didn't specifically check
193   * for it, 'wimpy' would be an extremely bad thing for a mob to do, as an
194   * example.  If you really couldn't care less, change this to a '#if 0'.
195   */
196  #if 1
197  /* Subtle bug in the '#var', but works well for now. */
198  #define CHECK_PLAYER_SPECIAL(ch, var) \
199  	(*(((ch)->player_specials == &dummy_mob) ? (log("SYSERR: Mob using '"#var"' at %s:%d.", __FILE__, __LINE__), &(var)) : &(var)))
200  #else
201  #define CHECK_PLAYER_SPECIAL(ch, var)	(var)
202  #endif
203  
204  #define MOB_FLAGS(ch)	((ch)->char_specials.saved.act)
205  #define PLR_FLAGS(ch)	((ch)->char_specials.saved.act)
206  #define PRF_FLAGS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.pref))
207  #define AFF_FLAGS(ch)	((ch)->char_specials.saved.affected_by)
208  #define ROOM_FLAGS(loc)	(world[(loc)].room_flags)
209  #define SPELL_ROUTINES(spl)	(spell_info[spl].routines)
210  
211  /*
212   * See http://www.circlemud.org/~greerga/todo/todo.009 to eliminate MOB_ISNPC.
213   * IS_MOB() acts as a VALID_MOB_RNUM()-like function.
214   */
215  #define IS_NPC(ch)	(IS_SET(MOB_FLAGS(ch), MOB_ISNPC))
216  #define IS_MOB(ch)	(IS_NPC(ch) && GET_MOB_RNUM(ch) <= top_of_mobt && \
217  				GET_MOB_RNUM(ch) != NOBODY)
218  
219  #define MOB_FLAGGED(ch, flag) (IS_NPC(ch) && IS_SET(MOB_FLAGS(ch), (flag)))
220  #define PLR_FLAGGED(ch, flag) (!IS_NPC(ch) && IS_SET(PLR_FLAGS(ch), (flag)))
221  #define AFF_FLAGGED(ch, flag) (IS_SET(AFF_FLAGS(ch), (flag)))
222  #define PRF_FLAGGED(ch, flag) (IS_SET(PRF_FLAGS(ch), (flag)))
223  #define ROOM_FLAGGED(loc, flag) (IS_SET(ROOM_FLAGS(loc), (flag)))
224  #define EXIT_FLAGGED(exit, flag) (IS_SET((exit)->exit_info, (flag)))
225  #define OBJAFF_FLAGGED(obj, flag) (IS_SET(GET_OBJ_AFFECT(obj), (flag)))
226  #define OBJVAL_FLAGGED(obj, flag) (IS_SET(GET_OBJ_VAL((obj), 1), (flag)))
227  #define OBJWEAR_FLAGGED(obj, flag) (IS_SET(GET_OBJ_WEAR(obj), (flag)))
228  #define OBJ_FLAGGED(obj, flag) (IS_SET(GET_OBJ_EXTRA(obj), (flag)))
229  #define HAS_SPELL_ROUTINE(spl, flag) (IS_SET(SPELL_ROUTINES(spl), (flag)))
230  
231  /* IS_AFFECTED for backwards compatibility */
232  #define IS_AFFECTED(ch, skill) (AFF_FLAGGED((ch), (skill)))
233  
234  #define PLR_TOG_CHK(ch,flag) ((TOGGLE_BIT(PLR_FLAGS(ch), (flag))) & (flag))
235  #define PRF_TOG_CHK(ch,flag) ((TOGGLE_BIT(PRF_FLAGS(ch), (flag))) & (flag))
236  
237  
238  /* room utils ************************************************************/
239  
240  
241  #define SECT(room)	(VALID_ROOM_RNUM(room) ? \
242  				world[(room)].sector_type : SECT_INSIDE)
243  
244  #define IS_DARK(room)	room_is_dark((room))
245  #define IS_LIGHT(room)  (!IS_DARK(room))
246  
247  #define VALID_ROOM_RNUM(rnum)	((rnum) != NOWHERE && (rnum) <= top_of_world)
248  #define GET_ROOM_VNUM(rnum) \
249  	((room_vnum)(VALID_ROOM_RNUM(rnum) ? world[(rnum)].number : NOWHERE))
250  #define GET_ROOM_SPEC(room) \
251  	(VALID_ROOM_RNUM(room) ? world[(room)].func : NULL)
252  
253  
254  /* char utils ************************************************************/
255  
256  
257  #define IN_ROOM(ch)	((ch)->in_room)
258  #define GET_WAS_IN(ch)	((ch)->was_in_room)
259  #define GET_AGE(ch)     (age(ch)->year)
260  
261  #define GET_PC_NAME(ch)	((ch)->player.name)
262  #define GET_NAME(ch)    (IS_NPC(ch) ? \
263  			 (ch)->player.short_descr : GET_PC_NAME(ch))
264  #define GET_TITLE(ch)   ((ch)->player.title)
265  #define GET_LEVEL(ch)   ((ch)->player.level)
266  #define GET_PASSWD(ch)	((ch)->player.passwd)
267  #define GET_PFILEPOS(ch)((ch)->pfilepos)
268  
269  /*
270   * I wonder if this definition of GET_REAL_LEVEL should be the definition
271   * of GET_LEVEL?  JE
272   */
273  #define GET_REAL_LEVEL(ch) \
274     (ch->desc && ch->desc->original ? GET_LEVEL(ch->desc->original) : \
275      GET_LEVEL(ch))
276  
277  #define GET_CLASS(ch)   ((ch)->player.chclass)
278  #define GET_HOME(ch)	((ch)->player.hometown)
279  #define GET_HEIGHT(ch)	((ch)->player.height)
280  #define GET_WEIGHT(ch)	((ch)->player.weight)
281  #define GET_SEX(ch)	((ch)->player.sex)
282  
283  #define GET_STR(ch)     ((ch)->aff_abils.str)
284  #define GET_ADD(ch)     ((ch)->aff_abils.str_add)
285  #define GET_DEX(ch)     ((ch)->aff_abils.dex)
286  #define GET_INT(ch)     ((ch)->aff_abils.intel)
287  #define GET_WIS(ch)     ((ch)->aff_abils.wis)
288  #define GET_CON(ch)     ((ch)->aff_abils.con)
289  #define GET_CHA(ch)     ((ch)->aff_abils.cha)
290  
291  #define GET_EXP(ch)	  ((ch)->points.exp)
292  #define GET_AC(ch)        ((ch)->points.armor)
293  #define GET_HIT(ch)	  ((ch)->points.hit)
294  #define GET_MAX_HIT(ch)	  ((ch)->points.max_hit)
295  #define GET_MOVE(ch)	  ((ch)->points.move)
296  #define GET_MAX_MOVE(ch)  ((ch)->points.max_move)
297  #define GET_MANA(ch)	  ((ch)->points.mana)
298  #define GET_MAX_MANA(ch)  ((ch)->points.max_mana)
299  #define GET_GOLD(ch)	  ((ch)->points.gold)
300  #define GET_BANK_GOLD(ch) ((ch)->points.bank_gold)
301  #define GET_HITROLL(ch)	  ((ch)->points.hitroll)
302  #define GET_DAMROLL(ch)   ((ch)->points.damroll)
303  
304  #define GET_POS(ch)	  ((ch)->char_specials.position)
305  #define GET_IDNUM(ch)	  ((ch)->char_specials.saved.idnum)
306  #define IS_CARRYING_W(ch) ((ch)->char_specials.carry_weight)
307  #define IS_CARRYING_N(ch) ((ch)->char_specials.carry_items)
308  #define FIGHTING(ch)	  ((ch)->char_specials.fighting)
309  #define HUNTING(ch)	  ((ch)->char_specials.hunting)
310  #define GET_SAVE(ch, i)	  ((ch)->char_specials.saved.apply_saving_throw[i])
311  #define GET_ALIGNMENT(ch) ((ch)->char_specials.saved.alignment)
312  
313  #define GET_COND(ch, i)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.conditions[(i)]))
314  #define GET_LOADROOM(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.load_room))
315  #define GET_PRACTICES(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.spells_to_learn))
316  #define GET_INVIS_LEV(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.invis_level))
317  #define GET_WIMP_LEV(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.wimp_level))
318  #define GET_FREEZE_LEV(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.freeze_level))
319  #define GET_BAD_PWS(ch)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.bad_pws))
320  #define GET_TALK(ch, i)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.talks[i]))
321  #define POOFIN(ch)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->poofin))
322  #define POOFOUT(ch)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->poofout))
323  #define GET_LAST_OLC_TARG(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->last_olc_targ))
324  #define GET_LAST_OLC_MODE(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->last_olc_mode))
325  #define GET_ALIASES(ch)		CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->aliases))
326  #define GET_LAST_TELL(ch)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->last_tell))
327  
328  #define GET_SKILL(ch, i)	CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.skills[i]))
329  #define SET_SKILL(ch, i, pct)	do { CHECK_PLAYER_SPECIAL((ch), (ch)->player_specials->saved.skills[i]) = pct; } while(0)
330  
331  #define GET_EQ(ch, i)		((ch)->equipment[i])
332  
333  #define GET_MOB_SPEC(ch)	(IS_MOB(ch) ? mob_index[(ch)->nr].func : NULL)
334  #define GET_MOB_RNUM(mob)	((mob)->nr)
335  #define GET_MOB_VNUM(mob)	(IS_MOB(mob) ? \
336  				 mob_index[GET_MOB_RNUM(mob)].vnum : NOBODY)
337  
338  #define GET_DEFAULT_POS(ch)	((ch)->mob_specials.default_pos)
339  #define MEMORY(ch)		((ch)->mob_specials.memory)
340  
341  #define STRENGTH_APPLY_INDEX(ch) \
342          ( ((GET_ADD(ch)==0) || (GET_STR(ch) != 18)) ? GET_STR(ch) :\
343            (GET_ADD(ch) <= 50) ? 26 :( \
344            (GET_ADD(ch) <= 75) ? 27 :( \
345            (GET_ADD(ch) <= 90) ? 28 :( \
346            (GET_ADD(ch) <= 99) ? 29 :  30 ) ) )                   \
347          )
348  
349  #define CAN_CARRY_W(ch) (str_app[STRENGTH_APPLY_INDEX(ch)].carry_w)
350  #define CAN_CARRY_N(ch) (5 + (GET_DEX(ch) >> 1) + (GET_LEVEL(ch) >> 1))
351  #define AWAKE(ch) (GET_POS(ch) > POS_SLEEPING)
352  #define CAN_SEE_IN_DARK(ch) \
353     (AFF_FLAGGED(ch, AFF_INFRAVISION) || (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_HOLYLIGHT)))
354  
355  #define IS_GOOD(ch)    (GET_ALIGNMENT(ch) >= 350)
356  #define IS_EVIL(ch)    (GET_ALIGNMENT(ch) <= -350)
357  #define IS_NEUTRAL(ch) (!IS_GOOD(ch) && !IS_EVIL(ch))
358  
359  
360  /* These three deprecated. */
361  #define WAIT_STATE(ch, cycle) do { GET_WAIT_STATE(ch) = (cycle); } while(0)
362  #define CHECK_WAIT(ch)                ((ch)->wait > 0)
363  #define GET_MOB_WAIT(ch)      GET_WAIT_STATE(ch)
364  /* New, preferred macro. */
365  #define GET_WAIT_STATE(ch)    ((ch)->wait)
366  
367  
368  /* descriptor-based utils ************************************************/
369  
370  /* Hrm, not many.  We should make more. -gg 3/4/99 */
371  #define STATE(d)	((d)->connected)
372  
373  
374  /* object utils **********************************************************/
375  
376  /*
377   * Check for NOWHERE or the top array index?
378   * If using unsigned types, the top array index will catch everything.
379   * If using signed types, NOTHING will catch the majority of bad accesses.
380   */
381  #define VALID_OBJ_RNUM(obj)	(GET_OBJ_RNUM(obj) <= top_of_objt && \
382  				 GET_OBJ_RNUM(obj) != NOTHING)
383  
384  #define GET_OBJ_TYPE(obj)	((obj)->obj_flags.type_flag)
385  #define GET_OBJ_COST(obj)	((obj)->obj_flags.cost)
386  #define GET_OBJ_RENT(obj)	((obj)->obj_flags.cost_per_day)
387  #define GET_OBJ_AFFECT(obj)	((obj)->obj_flags.bitvector)
388  #define GET_OBJ_EXTRA(obj)	((obj)->obj_flags.extra_flags)
389  #define GET_OBJ_WEAR(obj)	((obj)->obj_flags.wear_flags)
390  #define GET_OBJ_VAL(obj, val)	((obj)->obj_flags.value[(val)])
391  #define GET_OBJ_WEIGHT(obj)	((obj)->obj_flags.weight)
392  #define GET_OBJ_TIMER(obj)	((obj)->obj_flags.timer)
393  #define GET_OBJ_RNUM(obj)	((obj)->item_number)
394  #define GET_OBJ_VNUM(obj)	(VALID_OBJ_RNUM(obj) ? \
395  				obj_index[GET_OBJ_RNUM(obj)].vnum : NOTHING)
396  #define GET_OBJ_SPEC(obj)	(VALID_OBJ_RNUM(obj) ? \
397  				obj_index[GET_OBJ_RNUM(obj)].func : NULL)
398  
399  #define IS_CORPSE(obj)		(GET_OBJ_TYPE(obj) == ITEM_CONTAINER && \
400  					GET_OBJ_VAL((obj), 3) == 1)
401  
402  #define CAN_WEAR(obj, part)	OBJWEAR_FLAGGED((obj), (part))
403  
404  
405  /* compound utilities and other macros **********************************/
406  
407  /*
408   * Used to compute CircleMUD version. To see if the code running is newer
409   * than 3.0pl13, you would use: #if _CIRCLEMUD > CIRCLEMUD_VERSION(3,0,13)
410   */
411  #define CIRCLEMUD_VERSION(major, minor, patchlevel) \
412  	(((major) << 16) + ((minor) << 8) + (patchlevel))
413  
414  #define HSHR(ch) (GET_SEX(ch) ? (GET_SEX(ch)==SEX_MALE ? "his":"her") :"its")
415  #define HSSH(ch) (GET_SEX(ch) ? (GET_SEX(ch)==SEX_MALE ? "he" :"she") : "it")
416  #define HMHR(ch) (GET_SEX(ch) ? (GET_SEX(ch)==SEX_MALE ? "him":"her") : "it")
417  
418  #define ANA(obj) (strchr("aeiouAEIOU", *(obj)->name) ? "An" : "A")
419  #define SANA(obj) (strchr("aeiouAEIOU", *(obj)->name) ? "an" : "a")
420  
421  
422  /* Various macros building up to CAN_SEE */
423  
424  #define LIGHT_OK(sub)	(!AFF_FLAGGED(sub, AFF_BLIND) && \
425     (IS_LIGHT(IN_ROOM(sub)) || AFF_FLAGGED((sub), AFF_INFRAVISION)))
426  
427  #define INVIS_OK(sub, obj) \
428   ((!AFF_FLAGGED((obj),AFF_INVISIBLE) || AFF_FLAGGED(sub,AFF_DETECT_INVIS)) && \
429   (!AFF_FLAGGED((obj), AFF_HIDE) || AFF_FLAGGED(sub, AFF_SENSE_LIFE)))
430  
431  #define MORT_CAN_SEE(sub, obj) (LIGHT_OK(sub) && INVIS_OK(sub, obj))
432  
433  #define IMM_CAN_SEE(sub, obj) \
434     (MORT_CAN_SEE(sub, obj) || (!IS_NPC(sub) && PRF_FLAGGED(sub, PRF_HOLYLIGHT)))
435  
436  #define SELF(sub, obj)  ((sub) == (obj))
437  
438  /* Can subject see character "obj"? */
439  #define CAN_SEE(sub, obj) (SELF(sub, obj) || \
440     ((GET_REAL_LEVEL(sub) >= (IS_NPC(obj) ? 0 : GET_INVIS_LEV(obj))) && \
441     IMM_CAN_SEE(sub, obj)))
442  
443  /* End of CAN_SEE */
444  
445  
446  #define INVIS_OK_OBJ(sub, obj) \
447    (!OBJ_FLAGGED((obj), ITEM_INVISIBLE) || AFF_FLAGGED((sub), AFF_DETECT_INVIS))
448  
449  /* Is anyone carrying this object and if so, are they visible? */
450  #define CAN_SEE_OBJ_CARRIER(sub, obj) \
451    ((!obj->carried_by || CAN_SEE(sub, obj->carried_by)) &&	\
452     (!obj->worn_by || CAN_SEE(sub, obj->worn_by)))
453  
454  #define MORT_CAN_SEE_OBJ(sub, obj) \
455    (LIGHT_OK(sub) && INVIS_OK_OBJ(sub, obj) && CAN_SEE_OBJ_CARRIER(sub, obj))
456  
457  #define CAN_SEE_OBJ(sub, obj) \
458     (MORT_CAN_SEE_OBJ(sub, obj) || (!IS_NPC(sub) && PRF_FLAGGED((sub), PRF_HOLYLIGHT)))
459  
460  #define CAN_CARRY_OBJ(ch,obj)  \
461     (((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) <= CAN_CARRY_W(ch)) &&   \
462      ((IS_CARRYING_N(ch) + 1) <= CAN_CARRY_N(ch)))
463  
464  #define CAN_GET_OBJ(ch, obj)   \
465     (CAN_WEAR((obj), ITEM_WEAR_TAKE) && CAN_CARRY_OBJ((ch),(obj)) && \
466      CAN_SEE_OBJ((ch),(obj)))
467  
468  #define PERS(ch, vict)   (CAN_SEE(vict, ch) ? GET_NAME(ch) : "someone")
469  
470  #define OBJS(obj, vict) (CAN_SEE_OBJ((vict), (obj)) ? \
471  	(obj)->short_description  : "something")
472  
473  #define OBJN(obj, vict) (CAN_SEE_OBJ((vict), (obj)) ? \
474  	fname((obj)->name) : "something")
475  
476  
477  #define EXIT(ch, door)  (world[IN_ROOM(ch)].dir_option[door])
478  
479  #define CAN_GO(ch, door) (EXIT(ch,door) && \
480  			 (EXIT(ch,door)->to_room != NOWHERE) && \
481  			 !IS_SET(EXIT(ch, door)->exit_info, EX_CLOSED))
482  
483  
484  #define CLASS_ABBR(ch) (IS_NPC(ch) ? "--" : class_abbrevs[(int)GET_CLASS(ch)])
485  
486  #define IS_MAGIC_USER(ch)	(!IS_NPC(ch) && \
487  				(GET_CLASS(ch) == CLASS_MAGIC_USER))
488  #define IS_CLERIC(ch)		(!IS_NPC(ch) && \
489  				(GET_CLASS(ch) == CLASS_CLERIC))
490  #define IS_THIEF(ch)		(!IS_NPC(ch) && \
491  				(GET_CLASS(ch) == CLASS_THIEF))
492  #define IS_WARRIOR(ch)		(!IS_NPC(ch) && \
493  				(GET_CLASS(ch) == CLASS_WARRIOR))
494  
495  #define OUTSIDE(ch) (!ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS))
496  
497  
498  /* OS compatibility ******************************************************/
499  
500  
501  /* there could be some strange OS which doesn't have NULL... */
502  #ifndef NULL
503  #define NULL (void *)0
504  #endif
505  
506  #if !defined(FALSE)
507  #define FALSE 0
508  #endif
509  
510  #if !defined(TRUE)
511  #define TRUE  (!FALSE)
512  #endif
513  
514  /* defines for fseek */
515  #ifndef SEEK_SET
516  #define SEEK_SET	0
517  #define SEEK_CUR	1
518  #define SEEK_END	2
519  #endif
520  
521  /*
522   * NOCRYPT can be defined by an implementor manually in sysdep.h.
523   * CIRCLE_CRYPT is a variable that the 'configure' script
524   * automatically sets when it determines whether or not the system is
525   * capable of encrypting.
526   */
527  #if defined(NOCRYPT) || !defined(CIRCLE_CRYPT)
528  #define CRYPT(a,b) (a)
529  #else
530  #define CRYPT(a,b) ((char *) crypt((a),(b)))
531  #endif
532