/* Cque.c */ #include "os.h" #include "config.h" #include "db.h" #include "interface.h" #include "match.h" #include "externs.h" #ifdef MEM_CHECK #include "mem_check.h" #endif static void big_que (dbref player, char *command, dbref cause); typedef struct bque BQUE; struct bque { BQUE *next; dbref player; /* player who will do command */ dbref cause; /* player causing command (for %N) */ int left; /* seconds left until execution */ char *env[10]; /* environment, from wild match */ char *comm; /* command to be executed */ }; static BQUE *qfirst = NULL, *qlast = NULL, *qwait = NULL; static BQUE *qlfirst = NULL, *qllast = NULL; void parse_que (dbref player, char *command, dbref cause /* cause is needed to determine priority */ ) { char buff[BUFFER_LEN], *s, *r; s = buff; strcpy (buff, command); while (r = parse_up (&s, ';')) { big_que (player, r, cause); } } static int add_to (dbref player, int am) { int num = 0; ATTR *a; char buff[MAX_COMMAND_LEN]; player = db[player].owner; a = atr_get (player, "QUEUE"); if (a) num = atoi (a->value); num += am; if (num > 0) sprintf (buff, "%d", num); else *buff = 0; (void) atr_add (player, "QUEUE", buff, GOD, NOTHING); return (num); } static void big_que (dbref player, char *command, dbref cause) { int a; BQUE *tmp; if ((Typeof (player) != TYPE_PLAYER) && (db[player].flags & HALT)) return; /* make sure player can afford to do it */ if (!payfor (player, QUEUE_COST + (((OS_RAND () & QUEUE_LOSS) == 0) ? 1 : 0))) { notify (db[player].owner, "Not enough money to queue command."); return; } if (add_to (player, 1) > QUEUE_QUOTA) { notify (db[player].owner, "Run away objects, commands halted"); do_halt (db[player].owner, ""); /* halt means no command execution allowed */ db[player].flags |= HALT; return; } tmp = (BQUE *) malloc (sizeof (BQUE)); strcpy ((tmp->comm = (char *) malloc (strlen (command) + 1)), command); #ifdef MEM_CHECK add_check ("bqueue"); add_check ("bqueue_comm"); #endif tmp->player = player; tmp->next = NULL; tmp->left = 0; tmp->cause = cause; for (a = 0; a < 10; a++) if (!wptr[a]) tmp->env[a] = NULL; else { strcpy ((tmp->env[a] = (char *) malloc (strlen (wptr[a]) + 1)), wptr[a]); #ifdef MEM_CHECK add_check ("bqueue_env"); #endif } if (Typeof (cause) == TYPE_PLAYER) { if (qlast) { qlast->next = tmp; qlast = tmp; } else qlast = qfirst = tmp; } else { if (qllast) { qllast->next = tmp; qllast = tmp; } else qllast = qlfirst = tmp; } } void wait_que (dbref player, int wait, char *command, dbref cause) { BQUE *tmp; int a; /* make sure player can afford to do it */ if (!payfor (player, QUEUE_COST + (((OS_RAND () & QUEUE_LOSS) == 0) ? 1 : 0))) { notify (player, "Not enough money to queue command."); return; } tmp = (BQUE *) malloc (sizeof (BQUE)); strcpy ((tmp->comm = (char *) malloc (strlen (command) + 1)), command); #ifdef MEM_CHECK add_check ("bqueue"); add_check ("bqueue_comm"); #endif tmp->player = player; tmp->next = qwait; tmp->left = wait; tmp->cause = cause; for (a = 0; a < 10; a++) if (!wptr[a]) tmp->env[a] = NULL; else { strcpy ((tmp->env[a] = (char *) malloc (strlen (wptr[a]) + 1)), wptr[a]); #ifdef MEM_CHECK add_check ("bqueue_env"); #endif } qwait = tmp; } /* call every second to check for wait queue commands */ void do_second (void) { BQUE *trail = NULL, *point, *next; /* move contents of low priority queue onto end of normal one */ /* this helps to keep objects from getting out of control since */ /* its affects on other objects happen only after one seconds */ /* this should allow @halt to be type before getting blown away */ /* by scrolling text */ if (qlfirst) { if (qlast) qlast->next = qlfirst; else qfirst = qlfirst; qlast = qllast; qllast = qlfirst = NULL; } for (point = qwait; point; point = next) /* * Note: this would be 0 except the command is being put in the low * priority queue to be done in one second anyways */ if (point->left-- <= 1) { int a; giveto (point->player, QUEUE_COST); for (a = 0; a < 10; a++) { wptr[a] = point->env[a]; } parse_que (point->player, point->comm, point->cause); if (trail) trail->next = next = point->next; else qwait = next = point->next; for (a = 0; a < 10; a++) if (point->env[a]) { free ((char *) point->env[a]); #ifdef MEM_CHECK del_check ("bqueue_env"); #endif } if (point->comm) free ((char *) point->comm); free ((char *) point); #ifdef MEM_CHECK del_check ("bqueue_comm"); del_check ("bqueue"); #endif } else next = (trail = point)->next; } int test_top (void) { return (qfirst ? 1 : 0); } /* execute one command off the top of the queue */ int do_top (void) { int a; int i = 0; BQUE *tmp; dbref player; char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN]; char tbuf3[BUFFER_LEN], *s; if (!qfirst) return (0); if (qfirst->player && !(db[qfirst->player].flags & GOING)) { giveto (qfirst->player, QUEUE_COST); cplr = qfirst->player; strcpy (ccom, qfirst->comm); add_to (player = qfirst->player, -1); qfirst->player = 0; if ((Typeof (player) == TYPE_PLAYER) || !(db[player].flags & HALT)) { for (a = 0; a < 10; a++) { wptr[a] = qfirst->env[a]; } strcpy (tbuf2, uncompress (qfirst->comm)); tbuf3[0] = '\0'; for (s = tbuf2; *s; tbuf3[i++] = toupper ((int)*s++)); tbuf3[i++] = '\0'; if ((strstr (tbuf3, "@DOL")) == NULL) strcpy (tbuf1, pronoun_substitute (qfirst->cause, tbuf2, player)); else strcpy (tbuf1, tbuf2); if (IS (player, TYPE_THING, THING_VERBOSE)) notify (db[player].owner, tprintf ("#%d] %s", player, tbuf1)); process_command (player, tbuf1, qfirst->cause); } } tmp = qfirst->next; for (a = 0; a < 10; a++) if (qfirst->env[a]) { free ((char *) qfirst->env[a]); #ifdef MEM_CHECK del_check ("bqueue_env"); #endif } if (qfirst->comm) free ((char *) qfirst->comm); free ((char *) qfirst); #ifdef MEM_CHECK del_check ("bqueue_comm"); del_check ("bqueue"); #endif if (!(qfirst = tmp)) qlast = NULL; return (1); } /* tell player what commands they have pending in the queue */ void do_queue (dbref player, const char *what) { BQUE *tmp; dbref victim = NOTHING; int everything = 0; int quick = 0; int pq = 0, oq = 0, wq = 0; int tpq = 0, toq = 0, twq = 0; if (!string_compare (what, "count")) { victim = player; everything = 1; quick = 1; } else if (Wizard (player)) { if (!what || !*what) victim = player; else if (!string_compare (what, "all")) { /* do the whole thing */ victim = player; everything = 1; } else { init_match (player, what, TYPE_PLAYER); match_player (); match_absolute (); match_me (); victim = match_result (); } } else { victim = player; } switch (victim) { case NOTHING: notify (player, "I couldn't find that player."); break; case AMBIGUOUS: notify (player, "I don't know who you mean!"); break; default: if (everything == 1) notify (player, "Queue for : all"); else notify (player, tprintf ("Queue for : %s", db[victim].name)); if (!quick) notify (player, "Player Queue:"); for (tmp = qfirst; tmp; tmp = tmp->next) { tpq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { pq++; if (!quick) notify (player, tprintf ("%s:%s", unparse_object (player, tmp->player), tmp->comm)); } } if (!quick) notify (player, "Object Queue:"); for (tmp = qlfirst; tmp; tmp = tmp->next) { toq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { oq++; if (!quick) notify (player, tprintf ("%s:%s", unparse_object (player, tmp->player), tmp->comm)); } } if (!quick) notify (player, "Wait Queue:"); for (tmp = qwait; tmp; tmp = tmp->next) { twq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { wq++; if (!quick) notify (player, tprintf ("[%d]%s:%s", tmp->left, unparse_object (player, tmp->player), tmp->comm)); } } notify (player, "------------ Queue Done ------------"); notify (player, tprintf ("Totals: Player...%d/%d Object...%d/%d Wait...%d/%d", pq, tpq, oq, toq, wq, twq)); } } /* remove all queued commands from a certain player */ /* it cannot be called on specific objects */ void do_halt (dbref player, char *ncom) { BQUE *tmp, *trail = NULL, *point, *next; int num = 0; notify (db[player].owner, "Halted."); for (tmp = qfirst; tmp; tmp = tmp->next) if ((tmp->player == player) || (db[tmp->player].owner == player)) { num--; giveto (player, QUEUE_COST); tmp->player = 0; } for (tmp = qlfirst; tmp; tmp = tmp->next) if ((tmp->player == player) || (db[tmp->player].owner == player)) { num--; giveto (player, QUEUE_COST); tmp->player = 0; } /* remove wait q stuff */ for (point = qwait; point; point = next) if ((point->player == player) || (db[point->player].owner == player)) { int a; giveto (player, QUEUE_COST); if (trail) trail->next = next = point->next; else qwait = next = point->next; for (a = 0; a < 10; a++) if (point->env[a]) { free ((char *) point->env[a]); #ifdef MEM_CHECK del_check ("bqueue_env"); #endif } if (point->comm) free ((char *) point->comm); free ((char *) point); #ifdef MEM_CHECK del_check ("bqueue_comm"); del_check ("bqueue"); #endif } else next = (trail = point)->next; if (db[player].owner == player) (void) atr_add (player, "QUEUE", "", GOD, NOTHING); else add_to (player, num); if (*ncom) parse_que (player, ncom, player); } void do_halt1 (dbref player, const char *arg1, const char *arg2) { dbref victim; char temp[BUFFER_LEN]; if (*arg1 == '\0') do_halt (player, ""); else { init_match (player, arg1, NOTYPE); match_neighbor (); match_possession (); match_me (); match_absolute (); match_player (); if ((victim = noisy_match_result ()) == NOTHING) return; if ((db[victim].owner != player) && (!Wizard (player))) { notify (player, "Permission denied."); return; } if (Typeof (victim) != TYPE_PLAYER) { sprintf (temp, "#%d", victim); do_set (player, temp, "HALT"); } else { if (victim != player) notify (player, "Halted."); do_halt (victim, (char*)arg2); } } } void do_allhalt (dbref player) { dbref victim; if (!Wizard (player)) { notify (player, "Sorry, you can only halt your own items."); return; } for (victim = 0; victim < db_top; victim++) { if (Typeof (victim) == TYPE_PLAYER) { notify (victim, tprintf ("Your objects have been globally halted by %s", db[player].name)); do_halt (victim, ""); } } }