void do_kill (dbref player, dbref cause, int key, char *what, char *costchar) { dbref victim; char *buf1, *buf2; int cost; init_match(player, what, TYPE_PLAYER); match_neighbor(); match_me(); match_here(); if (Wizard(player)) { match_player(); match_absolute(); } victim = match_result(); switch (victim) { case NOTHING: notify(player, "I don't see that player here."); break; case AMBIGUOUS: notify(player, "I don't know who you mean!"); break; default: if ((Typeof(victim) != TYPE_PLAYER) && (Typeof(victim) != TYPE_THING)) { notify(player, "Sorry, you can only kill players and things."); break; } if ((Haven(Location(victim)) && !Wizard(player)) || (controls(victim, Location(victim)) && !controls(player, Location(victim))) || Immortal(victim)) { notify(player, "Sorry."); break; } if (key == KILL_SLAY) { if (Builder(player) && Builder(victim)) { notify(player, "Sorry."); break; } } /* go for it */ cost = atoi(costchar); if (key == KILL_KILL) { if (HasPriv(victim,player,POWER_NOKILL,POWER4,NOTHING)) { notify(player, "Sorry."); break; } if (cost < mudconf.killmin) cost = mudconf.killmin; if (cost > mudconf.killmax) cost = mudconf.killmax; /* see if it works */ if (!payfor(player, cost)) { notify(player, unsafe_tprintf("You don't have enough %s.", mudconf.many_coins)); return; } } else { cost = 0; } if (!(((random() % mudconf.killguarantee) < cost) || (key == KILL_SLAY)) || Wizard(victim)) { /* Failure: notify player and victim only */ notify(player, "Your murder attempt failed."); buf1 = alloc_lbuf("do_kill.failed"); sprintf(buf1, "%s tried to kill you!", Name(player)); notify_with_cause(victim, player, buf1); if (Suspect(player)) { strcpy(buf1, Name(player)); if (player == Owner(player)) { raw_broadcast(0, WIZARD, "[Suspect] %s tried to kill %s(#%d).", buf1, Name(victim), victim); } else { buf2 = alloc_lbuf("do_kill.SUSP.failed"); strcpy(buf2, Name(Owner(player))); raw_broadcast(0, WIZARD, "[Suspect] %s <via %s(#%d)> tried to kill %s(#%d).", buf2, buf1, player, Name(victim), victim); free_lbuf(buf2); } } free_lbuf(buf1); break; } /* Success! You killed him */ buf1 = alloc_lbuf("do_kill.succ.1"); buf2 = alloc_lbuf("do_kill.succ.2"); if (Suspect(player)) { strcpy(buf1, Name(player)); if (player == Owner(player)) { raw_broadcast(0, WIZARD, "[Suspect] %s killed %s(#%d).", buf1, Name(victim), victim); } else { strcpy(buf2, Name(Owner(player))); raw_broadcast(0, WIZARD, "[Suspect] %s <via %s(#%d)> killed %s(#%d).", buf2, buf1, player, Name(victim), victim); } } sprintf(buf1, "You killed %s!", Name(victim)); sprintf(buf2, "killed %s!", Name(victim)); if (Typeof(victim) != TYPE_PLAYER) if (halt_que(NOTHING, victim) > 0) if (!Quiet(victim)) notify(Owner(victim), "Halted."); did_it(player, victim, A_KILL, buf1, A_OKILL, buf2, A_AKILL, (char **)NULL, 0); /* notify victim */ sprintf(buf1, "%s killed you!", Name(player)); notify_with_cause(victim, player, buf1); /* Pay off the bonus */ if (key == KILL_KILL) { cost /= 2; /* victim gets half */ if (Pennies(Owner(victim)) < mudconf.paylimit) { sprintf(buf1, "Your insurance policy pays %d %s.", cost, mudconf.many_coins); notify(victim, buf1); giveto(Owner(victim), cost, NOTHING); } else { notify(victim, "Your insurance policy has been revoked."); } } free_lbuf(buf1); free_lbuf(buf2); /* send him home */ move_via_generic(victim, HOME, NOTHING, 0); divest_object(victim); break; } }
// --------------------------------------------------------------------------- // setup_que: Set up a queue entry. // static BQUE *setup_que ( dbref executor, dbref caller, dbref enactor, int eval, char *command, int nargs, char *args[], reg_ref *sargs[] ) { // Can we run commands at all? // if (Halted(executor)) { return NULL; } // Make sure executor can afford to do it. // int a = mudconf.waitcost; if (mudconf.machinecost && RandomINT32(0, mudconf.machinecost-1) == 0) { a++; } if (!payfor(executor, a)) { notify(Owner(executor), "Not enough money to queue command."); return NULL; } // Wizards and their objs may queue up to db_top+1 cmds. Players are // limited to QUEUE_QUOTA. -mnp // a = QueueMax(Owner(executor)); if (a_Queue(Owner(executor), 1) > a) { a_Queue(Owner(executor), -1); notify(Owner(executor), "Run away objects: too many commands queued. Halted."); halt_que(Owner(executor), NOTHING); // Halt also means no command execution allowed. // s_Halted(executor); return NULL; } // We passed all the tests. // // Calculate the length of the save string. // size_t tlen = 0; static size_t nCommand; static size_t nLenEnv[NUM_ENV_VARS]; if (command) { nCommand = strlen(command) + 1; tlen = nCommand; } if (nargs > NUM_ENV_VARS) { nargs = NUM_ENV_VARS; } for (a = 0; a < nargs; a++) { if (args[a]) { nLenEnv[a] = strlen(args[a]) + 1; tlen += nLenEnv[a]; } } // Create the qeue entry and load the save string. // BQUE *tmp = alloc_qentry("setup_que.qblock"); tmp->comm = NULL; char *tptr = tmp->text = (char *)MEMALLOC(tlen); ISOUTOFMEMORY(tptr); if (command) { memcpy(tptr, command, nCommand); tmp->comm = tptr; tptr += nCommand; } for (a = 0; a < nargs; a++) { if (args[a]) { memcpy(tptr, args[a], nLenEnv[a]); tmp->env[a] = tptr; tptr += nLenEnv[a]; } else { tmp->env[a] = NULL; } } for ( ; a < NUM_ENV_VARS; a++) { tmp->env[a] = NULL; } if (sargs) { for (a = 0; a < MAX_GLOBAL_REGS; a++) { tmp->scr[a] = sargs[a]; if (sargs[a]) { RegAddRef(sargs[a]); } } } else { for (a = 0; a < MAX_GLOBAL_REGS; a++) { tmp->scr[a] = NULL; } } // Load the rest of the queue block. // tmp->executor = executor; tmp->IsTimed = false; tmp->sem = NOTHING; tmp->attr = 0; tmp->enactor = enactor; tmp->caller = caller; tmp->eval = eval; tmp->nargs = nargs; return tmp; }
// This Task assumes that pEntry is already unlinked from any lists it may // have been related to. // static void Task_RunQueueEntry(void *pEntry, int iUnused) { UNUSED_PARAMETER(iUnused); BQUE *point = (BQUE *)pEntry; dbref executor = point->executor; if ( Good_obj(executor) && !Going(executor)) { giveto(executor, mudconf.waitcost); mudstate.curr_enactor = point->enactor; mudstate.curr_executor = executor; a_Queue(Owner(executor), -1); point->executor = NOTHING; if (!Halted(executor)) { // Load scratch args. // for (int i = 0; i < MAX_GLOBAL_REGS; i++) { if (mudstate.global_regs[i]) { RegRelease(mudstate.global_regs[i]); mudstate.global_regs[i] = NULL; } mudstate.global_regs[i] = point->scr[i]; point->scr[i] = NULL; } char *command = point->comm; mux_assert(!mudstate.inpipe); mux_assert(mudstate.pipe_nest_lev == 0); mux_assert(mudstate.poutobj == NOTHING); mux_assert(!mudstate.pout); break_called = false; while ( command && !break_called) { mux_assert(!mudstate.poutnew); mux_assert(!mudstate.poutbufc); char *cp = parse_to(&command, ';', 0); if ( cp && *cp) { // Will command be piped? // if ( command && *command == '|' && mudstate.pipe_nest_lev < mudconf.ntfy_nest_lim) { command++; mudstate.pipe_nest_lev++; mudstate.inpipe = true; mudstate.poutnew = alloc_lbuf("process_command.pipe"); mudstate.poutbufc = mudstate.poutnew; mudstate.poutobj = executor; } else { mudstate.inpipe = false; mudstate.poutobj = NOTHING; } CLinearTimeAbsolute ltaBegin; ltaBegin.GetUTC(); MuxAlarm.Set(mudconf.max_cmdsecs); CLinearTimeDelta ltdUsageBegin = GetProcessorUsage(); char *log_cmdbuf = process_command(executor, point->caller, point->enactor, point->eval, false, cp, point->env, point->nargs); CLinearTimeAbsolute ltaEnd; ltaEnd.GetUTC(); if (MuxAlarm.bAlarmed) { notify(executor, "GAME: Expensive activity abbreviated."); s_Flags(point->enactor, FLAG_WORD1, Flags(point->enactor) | HALT); s_Flags(point->executor, FLAG_WORD1, Flags(point->executor) | HALT); halt_que(point->enactor, NOTHING); halt_que(executor, NOTHING); } MuxAlarm.Clear(); CLinearTimeDelta ltdUsageEnd = GetProcessorUsage(); CLinearTimeDelta ltd = ltdUsageEnd - ltdUsageBegin; db[executor].cpu_time_used += ltd; ltd = ltaEnd - ltaBegin; if (ltd > mudconf.rpt_cmdsecs) { STARTLOG(LOG_PROBLEMS, "CMD", "CPU"); log_name_and_loc(executor); char *logbuf = alloc_lbuf("do_top.LOG.cpu"); mux_sprintf(logbuf, LBUF_SIZE, " queued command taking %s secs (enactor #%d): ", ltd.ReturnSecondsString(4), point->enactor); log_text(logbuf); free_lbuf(logbuf); log_text(log_cmdbuf); ENDLOG; } } // Transition %| value. // if (mudstate.pout) { free_lbuf(mudstate.pout); mudstate.pout = NULL; } if (mudstate.poutnew) { *mudstate.poutbufc = '\0'; mudstate.pout = mudstate.poutnew; mudstate.poutnew = NULL; mudstate.poutbufc = NULL; } } // Clean up %| value. // if (mudstate.pout) { free_lbuf(mudstate.pout); mudstate.pout = NULL; } mudstate.pipe_nest_lev = 0; mudstate.inpipe = false; mudstate.poutobj = NOTHING; } } for (int i = 0; i < MAX_GLOBAL_REGS; i++) { if (point->scr[i]) { RegRelease(point->scr[i]); point->scr[i] = NULL; } if (mudstate.global_regs[i]) { RegRelease(mudstate.global_regs[i]); mudstate.global_regs[i] = NULL; } } MEMFREE(point->text); point->text = NULL; free_qentry(point); }
// --------------------------------------------------------------------------- // do_halt: Command interface to halt_que. // void do_halt(dbref executor, dbref caller, dbref enactor, int eval, int key, char *target) { UNUSED_PARAMETER(caller); UNUSED_PARAMETER(enactor); UNUSED_PARAMETER(eval); dbref executor_targ, obj_targ; if ((key & HALT_ALL) && !Can_Halt(executor)) { notify(executor, NOPERM_MESSAGE); return; } // Figure out what to halt. // if (!target || !*target) { obj_targ = NOTHING; if (key & HALT_ALL) { executor_targ = NOTHING; } else { executor_targ = Owner(executor); if (!isPlayer(executor)) { obj_targ = executor; } } } else { if (Can_Halt(executor)) { obj_targ = match_thing(executor, target); } else { obj_targ = match_controlled(executor, target); } if (!Good_obj(obj_targ)) { return; } if (key & HALT_ALL) { notify(executor, "Can't specify a target and /all"); return; } if (isPlayer(obj_targ)) { executor_targ = obj_targ; obj_targ = NOTHING; } else { executor_targ = NOTHING; } } int numhalted = halt_que(executor_targ, obj_targ); if (Quiet(executor)) { return; } notify(Owner(executor), tprintf("%d queue entr%s removed.", numhalted, numhalted == 1 ? "y" : "ies")); }