/* ************************************************************************
* file: mobact.c , Mobile action module. Part of DIKUMUD *
* Usage: Procedures generating 'intelligent' behavior in the mobiles. *
* Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */
#include <stdio.h>
#include <stdlib.h>
#include "structs.h"
#include "utils.h"
#include "db.h"
#include "comm.h"
#include "interpreter.h"
extern struct char_data *character_list;
extern struct index_data *mob_index;
extern struct room_data *world;
extern struct str_app_type str_app[];
void hit(struct char_data *ch, struct char_data *victim, int type);
void mobile_activity(void)
{
register struct char_data *ch;
struct char_data *tmp_ch, *vict;
struct obj_data *obj, *best_obj;
int door, found, max;
memory_rec * names;
extern int no_specials;
ACMD(do_move);
ACMD(do_get);
for (ch = character_list; ch; ch = ch->next)
if (IS_MOB(ch)) {
/* Examine call for special procedure */
if (IS_SET(ch->specials2.act, MOB_SPEC) && !no_specials) {
if (!mob_index[ch->nr].func) {
sprintf(buf, "%s (#%d): Attempting to call non-existing mob func",
GET_NAME(ch), (int)mob_index[ch->nr].virtual);
log(buf);
REMOVE_BIT(ch->specials2.act, MOB_SPEC);
} else {
if ((*mob_index[ch->nr].func) (ch, 0, ""))
continue; /* go to next char */
}
}
if (AWAKE(ch) && !(ch->specials.fighting)) {
if (IS_SET(ch->specials2.act, MOB_SCAVENGER)) { /* if scavenger */
if (world[ch->in_room].contents && !number(0, 10)) {
for (max = 1, best_obj = 0, obj = world[ch->in_room].contents;
obj; obj = obj->next_content) {
if (CAN_GET_OBJ(ch, obj)) {
if (obj->obj_flags.cost > max) {
best_obj = obj;
max = obj->obj_flags.cost;
}
}
} /* for */
if (best_obj) {
obj_from_room(best_obj);
obj_to_char(best_obj, ch);
act("$n gets $p.", FALSE, ch, best_obj, 0, TO_ROOM);
}
}
}/* Scavenger */
if (!IS_SET(ch->specials2.act, MOB_SENTINEL) &&
(GET_POS(ch) == POSITION_STANDING) &&
((door = number(0, 45)) <= 5) && CAN_GO(ch, door) &&
!IS_SET(world[EXIT(ch, door)->to_room].room_flags, NO_MOB) &&
!IS_SET(world[EXIT(ch, door)->to_room].room_flags, DEATH)) {
if (ch->specials.last_direction == door) {
ch->specials.last_direction = -1;
} else {
if (!IS_SET(ch->specials2.act, MOB_STAY_ZONE)) {
ch->specials.last_direction = door;
do_move(ch, "", ++door, 0);
} else {
if (world[EXIT(ch, door)->to_room].zone == world[ch->in_room].zone) {
ch->specials.last_direction = door;
do_move(ch, "", ++door, 0);
}
}
}
} /* if can go */
if (IS_SET(ch->specials2.act, MOB_AGGRESSIVE)) {
found = FALSE;
for (tmp_ch = world[ch->in_room].people; tmp_ch && !found;
tmp_ch = tmp_ch->next_in_room) {
if (!IS_NPC(tmp_ch) && CAN_SEE(ch, tmp_ch) && !PRF_FLAGGED(tmp_ch, PRF_NOHASSLE)) {
if (!IS_SET(ch->specials2.act, MOB_WIMPY) || !AWAKE(tmp_ch)) {
if ((IS_SET(ch->specials2.act, MOB_AGGRESSIVE_EVIL) &&
IS_EVIL(tmp_ch)) ||
(IS_SET(ch->specials2.act, MOB_AGGRESSIVE_GOOD) &&
IS_GOOD(tmp_ch)) ||
(IS_SET(ch->specials2.act, MOB_AGGRESSIVE_NEUTRAL) &&
IS_NEUTRAL(tmp_ch)) ||
(!IS_SET(ch->specials2.act, MOB_AGGRESSIVE_EVIL) &&
!IS_SET(ch->specials2.act, MOB_AGGRESSIVE_NEUTRAL) &&
!IS_SET(ch->specials2.act, MOB_AGGRESSIVE_GOOD) ) ) {
hit(ch, tmp_ch, 0);
found = TRUE;
}
}
}
}
} /* if aggressive */
if (IS_SET(ch->specials2.act, MOB_MEMORY) && ch->specials.memory) {
for (vict = 0, tmp_ch = world[ch->in_room].people;
tmp_ch && !vict; tmp_ch = tmp_ch->next_in_room)
if (!IS_NPC(tmp_ch))
for (names = ch->specials.memory; names && !vict; names = names->next)
if (names->id == GET_IDNUM(tmp_ch))
vict = tmp_ch;
if (vict) {
act("'Hey! You're the fiend that attacked me!!!', exclaims $n.",
FALSE, ch, 0, 0, TO_ROOM);
hit(ch, vict, 0);
}
} /* mob memory */
}
} /* If IS_MOB(ch) */
}
/* Mob Memory Routines */
/* make ch remember victim */
void remember (struct char_data *ch, struct char_data *victim)
{
memory_rec * tmp;
bool present = FALSE;
if (!IS_NPC(ch) || IS_NPC(victim))
return;
for (tmp = ch->specials.memory; tmp && !present; tmp = tmp->next)
if (tmp->id == GET_IDNUM(victim))
present = TRUE;
if (!present) {
CREATE(tmp, memory_rec, 1);
tmp->next = ch->specials.memory;
tmp->id = GET_IDNUM(victim);
ch->specials.memory = tmp;
}
}
/* make ch forget victim */
void forget (struct char_data *ch, struct char_data *victim)
{
memory_rec * curr, *prev;
if (!(curr = ch->specials.memory))
return;
while (curr && curr->id != GET_IDNUM(victim)) {
prev = curr;
curr = curr->next;
}
if (!curr)
return; /* person wasn't there at all. */
if (curr == ch->specials.memory)
ch->specials.memory = curr->next;
else
prev->next = curr->next;
free(curr);
}
/* erase ch's memory */
void clearMemory(struct char_data *ch)
{
memory_rec * curr, *next;
curr = ch->specials.memory;
while (curr) {
next = curr->next;
free(curr);
curr = next;
}
ch->specials.memory = NULL;
}