/*
* robot.c -- the robot mode (Hi there! Why do you look like that?)
*
* PMF -- Padrone's MudFrontend, a frontend for (maybe mostly LP-)mud
* Thomas Padron-McCarthy (Email: padrone@lysator.liu.se), 1990, 1991
* Share and enjoy, but be nice: don't steal my program! Hugo is watching!
* This file latest updated: Sept 22, 1991
*
*/
#include <stdio.h>
#include <strings.h>
#include "safe_malloc.h"
#include "str_galore.h"
#include "config.h"
#include "pmf.h"
#include "globals.h"
#define ELEMENT_POINTER_TYPE struct robot_action_struct *
#include "generic_set.h"
/* The generic set "robot_actions" contains the robot_action definitions. */
struct robot_action_struct {
char *pattern, *action;
};
static generic_set robot_actions = NULL;
extern char *apply_definition();
extern long int time();
/*---------------------------------------------------------------------------*/
static int compare_robot_actions(struct1, struct2)
struct robot_action_struct *struct1, *struct2;
{
return strcmp(struct1->pattern, struct2->pattern);
} /* compare_robot_actions */
void init_set_of_robot_actions() {
robot_actions = create_generic_set(compare_robot_actions);
set_generic_set_increment(robot_actions, ROBOT_ACTIONS_INCREMENT);
} /* init_set_of_robot_actions */
static struct robot_action_struct *find_robot_action_pointer(this_pattern)
char *this_pattern;
{
struct robot_action_struct dummy;
dummy.pattern = this_pattern;
return (struct robot_action_struct *)find_in_generic_set(robot_actions, &dummy);
} /* find_robot_action_pointer */
char *find_robot_action_string(this_pattern)
char *this_pattern;
{
struct robot_action_struct *it;
it = find_robot_action_pointer(this_pattern);
return it ? it->action : NULL;
} /* find_robot_action_string */
/* Add a robot_action definition.
* The strings, "this_pattern" and "this_action" are copied.
*/
void add_robot_action(this_pattern, this_action)
char *this_pattern, *this_action;
{
struct robot_action_struct *new_structp, *old_structp;
new_structp = (struct robot_action_struct*)
safe_malloc(sizeof(struct robot_action_struct));
new_structp->pattern = copy_string(this_pattern);
new_structp->action = copy_string(this_action);
old_structp = (struct robot_action_struct *)
add_to_generic_set(robot_actions, new_structp);
if (old_structp) {
safe_free(old_structp->pattern);
safe_free(old_structp->action);
safe_free(old_structp);
}
} /* add_robot_action */
remove_robot_action(this_pattern)
char *this_pattern;
{
struct robot_action_struct dummy, *old_structp;
dummy.pattern = this_pattern;
old_structp = (struct robot_action_struct *)
remove_from_generic_set(robot_actions, &dummy);
if (old_structp) {
safe_free(old_structp->pattern);
safe_free(old_structp->action);
safe_free(old_structp);
}
else
message("No such robot action defined: %s", this_pattern);
} /* remove_robot_action */
struct robot_action_struct *kill_one_robot_action(this_robot_action_p)
struct robot_action_struct *this_robot_action_p;
{
safe_free(this_robot_action_p->pattern);
safe_free(this_robot_action_p->action);
safe_free(this_robot_action_p);
return NULL;
} /* kill_one_robot_action */
remove_all_robot_actions() {
empty_generic_set(robot_actions, kill_one_robot_action);
ASSERT(query_generic_set_size(robot_actions) == 0);
} /* remove_all_robot_actions */
static struct robot_action_struct *list_one_robot_action(this_robot_action_p, outfile)
struct robot_action_struct *this_robot_action_p;
FILE *outfile;
{
if (slash_commands)
fprintf(outfile, "/");
fprintf(outfile, "action ");
quote_and_print_string(outfile, this_robot_action_p->pattern);
fprintf(outfile, " ");
quote_and_print_string(outfile, this_robot_action_p->action);
fprintf(outfile, "\n");
return NULL;
} /* list_one_robot_action */
void list_robot_actions(outfile)
FILE *outfile;
{
traverse_generic_set(robot_actions, list_one_robot_action, outfile);
} /* list_robot_actions */
void dump_robot_actions(outfile)
FILE *outfile;
{
list_robot_actions(outfile);
} /* dump_robot_actions */
int query_nr_robot_actions() {
return query_generic_set_size(robot_actions);
}
char *try_one_robot_action(this_action, the_line)
struct robot_action_struct *this_action;
char *the_line;
{
static char *mudline_words[MAX_WORDS_PER_LINE];
static char mudline_words_buffer[2 * MAX_LINE_LENGTH];
int nr_words;
char *response;
INTERNAL_DEBUG(("try_one_robot_action: %s", this_action->pattern));
nr_words = dollar_match(this_action->pattern,
the_line, mudline_words + 1, mudline_words_buffer);
if (nr_words != -1) {
/* Ok, this was a match. Do this robot action. */
USER_DEBUG(("Robot action triggered: %s", this_action->action));
if (this_action->action[0] == '\0') /* Empty string: no action! */
return this_action->action;
mudline_words[0] = this_action->action;
response = apply_definition(this_action->action,
nr_words + 1, mudline_words, 0);
ASSERT(response != NULL);
return response;
}
else
return NULL;
} /* try_one_robot_action */
void robot_handle_line(the_line)
char *the_line;
{
char *response;
static int time_counter = 0;
static long int latest_time = 0L;
USER_DEBUG(("robot_handle_line: %s", the_line));
response = (char *)
traverse_generic_set(robot_actions, try_one_robot_action, the_line);
if (response != NULL && response[0] != '\0') {
if (verbose) {
ldisplay("\007");
ldisplay("*** PMF robot action: ");
ldisplay("%s\n", response); /* The response can contain %'s! */
ldisplay("\n");
}
if (time_counter == 0 && latest_time == 0L) {
/* Initialize the robot action timer */
latest_time = time(NULL);
}
else if (++time_counter >= 10) {
/* Ten actions since last check! Do a check! */
time_counter = 0;
if (time(NULL) - latest_time < 30) {
latest_time = 0L;
unset_variable("robot");
error("Possible robot action loop detected. Robot mode turned off.");
}
else
latest_time = time(NULL);
}
handle_command(response, 1); /* Handle with express! */
flush_express_list(); /* Now the express commands are actually queued. */
/* add_history(response); -- NO! */
safe_free(response);
}
} /* robot_handle_line */
syntax highlighted by Code2HTML, v. 0.9.1