/* ************************************************************************
* File: interpreter.c Part of CircleMUD *
* Usage: parse user commands, search for specials, call ACMD functions *
* *
* All rights reserved. See license.doc for complete information. *
* *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
************************************************************************ */
#define __INTERPRETER_CC__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "structs.h"
#include "awake.h"
#include "comm.h"
#include "interpreter.h"
#include "db.h"
#include "utils.h"
#include "spells.h"
#include "handler.h"
#include "mail.h"
#include "screen.h"
#include "memory.h"
#include "newmagic.h"
#include "shop.h"
#include "quest.h"
#if defined(__CYGWIN__)
#include <crypt.h>
#endif
extern class memoryClass *Mem;
extern char *motd;
extern char *imotd;
extern char *background;
extern char *MENU;
extern char *QMENU;
extern char *WELC_MESSG;
extern char *START_MESSG;
extern struct char_data *character_list;
extern struct player_index_element *player_table;
extern int top_of_p_table;
extern int restrict;
extern struct index_data *mob_index;
extern struct index_data *obj_index;
extern struct room_data *world;
extern int free_rent;
extern struct descriptor_data *descriptor_list;
/* external functions */
void echo_on(struct descriptor_data * d);
void echo_off(struct descriptor_data * d);
void do_start(struct char_data * ch);
void init_char(struct char_data * ch);
int create_entry(char *name);
int special(struct char_data * ch, int cmd, char *arg);
int isbanned(char *hostname);
int Valid_Name(char *newname);
void create_parse(struct descriptor_data *d, char *arg);
void init_create_vars(struct descriptor_data *d);
// for olc
void iedit_parse(struct descriptor_data *d, char *arg);
void redit_parse(struct descriptor_data *d, char *arg);
void medit_parse(struct descriptor_data *d, char *arg);
void qedit_parse(struct descriptor_data *d, char *arg);
void shedit_parse(struct descriptor_data *d, char *arg);
void zedit_parse(struct descriptor_data *d, char *arg);
void free_shop(struct shop_data *shop);
void free_quest(struct quest_data *quest);
// for spell creation
void sedit_parse(struct descriptor_data *d, char *arg);
void cedit_parse(struct descriptor_data *d, char *arg);
extern void display_rent_status(struct descriptor_data *d);
extern void Crash_rentsave(struct char_data *ch, int cost);
extern void affect_total(struct char_data * ch);
extern void mag_menu_system(struct descriptor_data * d, char *arg);
/* prototypes for all do_x functions. */
ACMD(do_olcon);
ACMD(do_action);
ACMD(do_activate);
ACMD(do_advance);
ACMD(do_alias);
ACMD(do_antilar);
ACMD(do_assist);
ACMD(do_ask);
ACMD(do_astral);
ACMD(do_at);
ACMD(do_attach);
ACMD(do_backstab);
ACMD(do_ban);
ACMD(do_bash);
ACMD(do_bioware);
ACMD(do_bond);
ACMD(do_broadcast);
ACMD(do_cast);
ACMD(do_color);
ACMD(do_commands);
ACMD(do_conjure);
ACMD(do_connect);
ACMD(do_consider);
ACMD(do_crack);
ACMD(do_create);
ACMD(do_credits);
ACMD(do_customize);
ACMD(do_cyberware);
ACMD(do_date);
ACMD(do_dc);
ACMD(do_defense);
ACMD(do_dig);
ACMD(do_disconnect);
ACMD(do_diagnose);
ACMD(do_display);
ACMD(do_drag);
ACMD(do_drink);
ACMD(do_drop);
ACMD(do_eat);
ACMD(do_echo);
ACMD(do_enter);
ACMD(do_equipment);
ACMD(do_examine);
ACMD(do_exit);
ACMD(do_exits);
ACMD(do_flee);
ACMD(do_follow);
ACMD(do_force);
ACMD(do_gecho);
ACMD(do_gen_comm);
ACMD(do_gen_door);
ACMD(do_gen_ps);
ACMD(do_gen_write);
ACMD(do_get);
ACMD(do_give);
ACMD(do_gold);
ACMD(do_goto);
ACMD(do_grab);
ACMD(do_group);
ACMD(do_glist);
ACMD(do_gname);
ACMD(do_hail);
ACMD(do_hcontrol);
ACMD(do_help);
ACMD(do_hide);
ACMD(do_hit);
ACMD(do_house);
ACMD(do_ident);
ACMD(do_ilist);
ACMD(do_iload);
ACMD(do_info);
ACMD(do_insult);
ACMD(do_inventory);
ACMD(do_invis);
ACMD(do_kick);
ACMD(do_kil);
ACMD(do_kill);
ACMD(do_last);
ACMD(do_leave);
ACMD(do_load);
ACMD(do_look);
ACMD(do_logwatch);
ACMD(do_move);
ACMD(do_mlist);
ACMD(do_not_here);
//ACMD(do_olc);
ACMD(do_operate);
ACMD(do_order);
ACMD(do_page);
ACMD(do_patch);
ACMD(do_poofset);
ACMD(do_pour);
ACMD(do_pool);
ACMD(do_practice);
ACMD(do_prequel);
ACMD(do_purge);
ACMD(do_put);
ACMD(do_qcomm);
ACMD(do_qedit);
ACMD(do_qlist);
ACMD(do_quit);
ACMD(do_radio);
ACMD(do_reboot);
ACMD(do_release);
ACMD(do_reload);
ACMD(do_remove);
ACMD(do_rent);
ACMD(do_reply);
ACMD(do_report);
ACMD(do_rescue);
ACMD(do_rest);
ACMD(do_restore);
ACMD(do_return);
ACMD(do_rlist);
ACMD(do_run);
ACMD(do_save);
ACMD(do_say);
ACMD(do_scan);
ACMD(do_score);
ACMD(do_send);
ACMD(do_set);
ACMD(do_settime);
ACMD(do_sdelete);
ACMD(do_shedit);
ACMD(do_shoot);
ACMD(do_show);
ACMD(do_shutdown);
ACMD(do_sit);
ACMD(do_skills);
ACMD(do_skillset);
ACMD(do_sleep);
ACMD(do_slist);
ACMD(do_slowns);
ACMD(do_sneak);
ACMD(do_snoop);
ACMD(do_software);
ACMD(do_spec_comm);
ACMD(do_spells);
ACMD(do_split);
ACMD(do_stand);
ACMD(do_stat);
ACMD(do_status);
ACMD(do_steal);
//ACMD(do_study);
ACMD(do_switch);
ACMD(do_tail);
ACMD(do_teleport);
ACMD(do_tell);
ACMD(do_throw);
ACMD(do_time);
ACMD(do_title);
ACMD(do_toggle);
ACMD(do_track);
ACMD(do_train);
ACMD(do_trans);
ACMD(do_treat);
ACMD(do_type);
ACMD(do_unattach);
ACMD(do_unban);
ACMD(do_ungroup);
ACMD(do_unoperate);
ACMD(do_use);
ACMD(do_users);
ACMD(do_visible);
ACMD(do_vnum);
ACMD(do_vstat);
ACMD(do_wake);
ACMD(do_wear);
ACMD(do_weather);
ACMD(do_where);
ACMD(do_who);
ACMD(do_wield);
ACMD(do_wimpy);
ACMD(do_wizhelp);
ACMD(do_wizlock);
ACMD(do_wiztell);
ACMD(do_wizfeel);
ACMD(do_wiztitle);
ACMD(do_wizwho);
ACMD(do_wizutil);
ACMD(do_zreset);
ACMD(do_iedit);
ACMD(do_iclone);
ACMD(do_idelete);
ACMD(do_redit);
ACMD(do_rclone);
ACMD(do_rdelete);
ACMD(do_medit);
ACMD(do_mclone);
ACMD(do_mdelete);
ACMD(do_exclaim);
ACMD(do_unload);
ACMD(do_zedit);
ACMD(do_zdelete);
ACMD(do_zlist);
ACMD(do_vars);
ACMD(do_learn);
ACMD(do_index);
ACMD(do_zswitch);
struct command_info cmd_info[] = {
{ "RESERVED", 0, 0, 0, 0 }, /* this must be first -- for specprocs */
/* directions must come before other commands but after RESERVED */
{ "north" , POS_STANDING, do_move , 0, SCMD_NORTH },
{ "east" , POS_STANDING, do_move , 0, SCMD_EAST },
{ "south" , POS_STANDING, do_move , 0, SCMD_SOUTH },
{ "west" , POS_STANDING, do_move , 0, SCMD_WEST },
{ "up" , POS_STANDING, do_move , 0, SCMD_UP },
{ "down" , POS_STANDING, do_move , 0, SCMD_DOWN },
{ "ne" , POS_STANDING, do_move , 0, SCMD_NORTHEAST},
{ "se" , POS_STANDING, do_move , 0, SCMD_SOUTHEAST},
{ "sw" , POS_STANDING, do_move , 0, SCMD_SOUTHWEST},
{ "nw" , POS_STANDING, do_move , 0, SCMD_NORTHWEST},
{ "northeast", POS_STANDING, do_move , 0, SCMD_NORTHEAST},
{ "southeast", POS_STANDING, do_move , 0, SCMD_SOUTHEAST},
{ "southwest", POS_STANDING, do_move , 0, SCMD_SOUTHWEST},
{ "northwest", POS_STANDING, do_move , 0, SCMD_NORTHWEST},
/* now, the main list */
{ "abilities", POS_SLEEPING, do_skills , 0, SCMD_ABILITIES },
{ "activate" , POS_RESTING , do_activate , 0, 0 },
{ "agree" , POS_RESTING , do_action , 0, 0 },
{ "at" , POS_DEAD , do_at , LVL_LEGEND, 0 },
{ "attach" , POS_RESTING , do_attach , 0, 0 },
{ "advance" , POS_DEAD , do_advance , LVL_OWNER, 0 },
{ "alias" , POS_DEAD , do_alias , 0, 0 },
{ "antilar" , POS_DEAD , do_antilar , LVL_OWNER, 0 },
{ "accuse" , POS_SITTING , do_action , 0, 0 },
{ "apologize", POS_RESTING , do_action , 0, 0 },
{ "applaud" , POS_RESTING , do_action , 0, 0 },
{ "assist" , POS_FIGHTING, do_assist , 1, 0 },
{ "ask" , POS_RESTING , do_spec_comm, 0, 0 },
{ "bounce" , POS_STANDING, do_action , 0, 0 },
{ "bond" , POS_RESTING , do_bond , 0, 0 },
{ "ban" , POS_DEAD , do_ban , LVL_PRESIDENT, 0 },
{ "balance" , POS_RESTING , do_gold , 0, 0 },
{ "bat" , POS_RESTING , do_action , 0, 0 },
{ "bdance" , POS_STANDING, do_action , 0, 0 },
{ "beam" , POS_RESTING , do_action , 0, 0 },
{ "bearhug" , POS_STANDING, do_action , 0, 0 },
{ "beg" , POS_RESTING , do_action , 0, 0 },
{ "bioware" , POS_DEAD , do_bioware , 0, 0 },
{ "blink" , POS_RESTING , do_action , 0, 0 },
{ "bleed" , POS_RESTING , do_action , 0, 0 },
{ "blush" , POS_RESTING , do_action , 0, 0 },
{ "boggle" , POS_RESTING , do_action , 0, 0 },
{ "bonk" , POS_STANDING, do_action , 0, 0 },
{ "bow" , POS_STANDING, do_action , 0, 0 },
{ "brb" , POS_RESTING , do_action , 0, 0 },
{ "broadcast", POS_RESTING , do_broadcast, 0, 0 },
{ "brick" , POS_STANDING, do_action , 0, 0 },
{ "burp" , POS_RESTING , do_action , 0, 0 },
{ "buy" , POS_STANDING, do_not_here , 0, 0 },
{ "bug" , POS_DEAD , do_gen_write, 0, SCMD_BUG },
{ "bypass" , POS_STANDING, do_gen_door , 0, SCMD_PICK},
{ "cast" , POS_SITTING , do_cast , 1, 0 },
{ "cancel" , POS_RESTING , do_not_here , 0, 0 },
{ "cackle" , POS_RESTING , do_action , 0, 0 },
{ "cbonk" , POS_STANDING, do_action , 0, 0 },
{ "chuckle" , POS_RESTING , do_action , 0, 0 },
{ "chillout" , POS_RESTING , do_action , 0, 0 },
{ "check" , POS_RESTING , do_not_here , 0, 0 },
{ "cheer" , POS_RESTING , do_action , 0, 0 },
{ "clap" , POS_RESTING , do_action , 0, 0 },
{ "clear" , POS_DEAD , do_gen_ps , 0, SCMD_CLEAR },
{ "climb" , POS_STANDING, do_not_here , 0, 0 },
{ "close" , POS_SITTING , do_gen_door , 0, SCMD_CLOSE },
{ "cls" , POS_DEAD , do_gen_ps , 0, SCMD_CLEAR },
{ "collapse" , POS_STANDING, do_action , 0, 0 },
{ "consider" , POS_RESTING , do_consider , 0, 0 },
{ "conjure" , POS_RESTING , do_conjure , 0, 0 },
{ "confused" , POS_RESTING, do_action , 0, 0 },
{ "congrat" , POS_RESTING , do_action , 0, 0 },
{ "connect" , POS_RESTING , do_connect , 0, 0 },
{ "convince" , POS_RESTING , do_action , 0, 0 },
{ "color" , POS_DEAD , do_color , 0, 0 },
{ "comfort" , POS_RESTING , do_action , 0, 0 },
{ "comb" , POS_RESTING , do_action , 0, 0 },
{ "commands" , POS_DEAD , do_commands , 0, SCMD_COMMANDS },
{ "cough" , POS_RESTING , do_action , 0, 0 },
{ "crack" , POS_RESTING , do_crack , 0, 0 },
{ "create" , POS_RESTING , do_create , 0, 0 },
{ "credits" , POS_DEAD , do_gen_ps , 0, SCMD_CREDITS },
{ "cringe" , POS_RESTING , do_action , 0, 0 },
{ "cry" , POS_RESTING , do_action , 0, 0 },
{ "cuddle" , POS_RESTING , do_action , 0, 0 },
{ "curse" , POS_RESTING , do_action , 0, 0 },
{ "curtsey" , POS_STANDING, do_action , 0, 0 },
// { "customize", POS_SLEEPING, do_customize, 0, 0 },
{ "cyberware", POS_DEAD , do_cyberware, 0, 0 },
{ "dance" , POS_STANDING, do_action , 0, 0 },
{ "date" , POS_DEAD , do_date , 0, SCMD_DATE },
{ "daydream" , POS_SLEEPING, do_action , 0, 0 },
{ "dc" , POS_DEAD , do_dc , LVL_MANAGER, 0 },
{ "deposit" , POS_STANDING, do_not_here , 1, 0 },
{ "defense" , POS_SLEEPING, do_defense , 0, 0 },
{ "diagnose" , POS_RESTING , do_diagnose , 0, 0 },
{ "dig" , POS_RESTING , do_dig , LVL_LEGEND, 0 },
{ "dis" , POS_RESTING , do_action , 0, 0 },
{ "disagree" , POS_RESTING , do_action , 0, 0 },
{ "disco" , POS_RESTING , do_action , 0, 0 },
{ "disconnect",POS_DEAD , do_disconnect, 0, 0 },
{ "display" , POS_DEAD , do_display , 0, 0 },
{ "disregard", POS_RESTING , do_action , 0, 0 },
{ "doh" , POS_RESTING , do_action , 0, 0 },
{ "donate" , POS_RESTING , do_drop , 0, SCMD_DONATE },
{ "download" , POS_RESTING , do_get , 0, SCMD_DOWNLOAD },
{ "drag" , POS_STANDING, do_drag , 0, 0 },
{ "dribble" , POS_RESTING , do_action , 0, 0 },
{ "drink" , POS_RESTING , do_drink , 0, SCMD_DRINK },
{ "drop" , POS_RESTING , do_drop , 0, SCMD_DROP },
{ "drool" , POS_RESTING , do_action , 0, 0 },
{ "dunce" , POS_RESTING , do_action , 0, 0 },
{ "eat" , POS_RESTING , do_eat , 0, SCMD_EAT },
{ "echo" , POS_SLEEPING, do_echo , LVL_BUILDER, SCMD_ECHO },
{ "emote" , POS_RESTING , do_echo , 0, SCMD_EMOTE },
{ ":" , POS_RESTING , do_echo , 0, SCMD_EMOTE },
{ "embrace" , POS_RESTING , do_action , 0, 0 },
{ "enter" , POS_STANDING, do_enter , 0, 0 },
{ "envy" , POS_RESTING , do_action , 0, 0 },
{ "equipment", POS_SLEEPING, do_equipment, 0, 0 },
{ "exits" , POS_RESTING , do_exits , 0, 0 },
{ "examine" , POS_SITTING , do_examine , 0, 0 },
{ "exclaim" , POS_RESTING , do_exclaim , 0, 0 },
{ "eyebrow" , POS_RESTING , do_action , 0, 0 },
{ "force" , POS_SLEEPING, do_force , LVL_ADVISOR, 0 },
{ "forgive" , POS_RESTING , do_action , 0, 0 },
{ "fart" , POS_RESTING , do_action , 0, 0 },
{ "fill" , POS_STANDING, do_pour , 0, SCMD_FILL },
{ "finger" , POS_RESTING , do_last , 0, SCMD_FINGER },
{ "flee" , POS_FIGHTING, do_flee , 0, 0 },
{ "flex" , POS_STANDING, do_action , 0, 0 },
{ "flip" , POS_STANDING, do_action , 0, 0 },
{ "flirt" , POS_RESTING , do_action , 0, 0 },
{ "follow" , POS_RESTING , do_follow , 0, 0 },
{ "fondle" , POS_RESTING , do_action , 0, 0 },
{ "freeze" , POS_DEAD , do_wizutil , LVL_FREEZE, SCMD_FREEZE },
{ "french" , POS_RESTING , do_action , 0, 0 },
{ "frown" , POS_RESTING , do_action , 0, 0 },
{ "fume" , POS_RESTING , do_action , 0, 0 },
{ "get" , POS_RESTING , do_get , 0, 0 },
{ "gasp" , POS_RESTING , do_action , 0, 0 },
{ "gecho" , POS_DEAD , do_gecho , LVL_DIRECTOR, 0 },
{ "giggle" , POS_RESTING , do_action , 0, 0 },
{ "give" , POS_RESTING , do_give , 0, 0 },
{ "glist" , POS_RESTING , do_glist , 0, 0 },
{ "glare" , POS_RESTING , do_action , 0, 0 },
{ "goto" , POS_SLEEPING, do_goto , LVL_LEGEND, 0 },
{ "group" , POS_RESTING , do_group , 1, 0 },
{ "gname" , POS_RESTING , do_gname , 0, 0 },
{ "grab" , POS_RESTING , do_grab , 0, 0 },
{ "greet" , POS_RESTING , do_action , 0, 0 },
{ "grin" , POS_RESTING , do_action , 0, 0 },
{ "grimace" , POS_RESTING , do_action , 0, 0 },
{ "groan" , POS_RESTING , do_action , 0, 0 },
{ "grope" , POS_RESTING , do_action , 0, 0 },
{ "grovel" , POS_RESTING , do_action , 0, 0 },
{ "growl" , POS_RESTING , do_action , 0, 0 },
{ "grumble" , POS_RESTING , do_action , 0, 0 },
{ "grunt" , POS_RESTING , do_action , 0, 0 },
{ "help" , POS_DEAD , do_help , 0, 0 },
{ "hair" , POS_RESTING , do_action , 0, 0 },
{ "hail" , POS_STANDING, do_hail , 0, 0 },
{ "happy" , POS_RESTING , do_action , 0, 0 },
{ "hand" , POS_RESTING , do_action , 0, 0 },
{ "hate" , POS_RESTING , do_action , 0, 0 },
{ "handbook" , POS_DEAD , do_gen_ps , LVL_LEGEND, SCMD_HANDBOOK },
{ "hcontrol" , POS_DEAD , do_hcontrol , LVL_PRESIDENT, 0 },
{ "hhold" , POS_RESTING , do_action , 0, 0 },
{ "hiccup" , POS_RESTING , do_action , 0, 0 },
{ "hit" , POS_FIGHTING, do_hit , 0, SCMD_HIT },
{ "hifive" , POS_STANDING, do_action , 0, 0 },
{ "hop" , POS_RESTING , do_action , 0, 0 },
{ "hoi" , POS_RESTING , do_action , 0, 0 },
{ "hold" , POS_RESTING , do_grab , 1, 0 },
{ "howl" , POS_RESTING , do_action , 0, 0 },
{ "hop" , POS_RESTING , do_action , 0, 0 },
{ "house" , POS_RESTING , do_house , 0, 0 },
{ "hkiss" , POS_STANDING, do_action , 0, 0 },
{ "hug" , POS_RESTING , do_action , 0, 0 },
{ "inventory", POS_DEAD , do_inventory, 0, 0 },
{ "install" , POS_RESTING , do_put , 0, SCMD_INSTALL },
{ "iclone" , POS_DEAD , do_iclone , LVL_PRESIDENT, 0 },
{ "idea" , POS_DEAD , do_gen_write, 0, SCMD_IDEA },
{ "idelete" , POS_DEAD , do_idelete , LVL_PRESIDENT, 0 },
{ "ident" , POS_DEAD , do_ident , LVL_PRESIDENT, 0 },
{ "iedit" , POS_DEAD , do_iedit , LVL_LEGEND, 0 },
{ "ilist" , POS_DEAD , do_ilist , LVL_LEGEND, 0 },
{ "iload" , POS_DEAD , do_iload , LVL_LEGEND, 0 },
{ "imotd" , POS_DEAD , do_gen_ps , LVL_LEGEND, SCMD_IMOTD },
{ "immlist" , POS_DEAD , do_gen_ps , 0, SCMD_IMMLIST },
{ "index" , POS_SLEEPING, do_index , 0, 0},
{ "info" , POS_SLEEPING, do_gen_ps , 0, SCMD_INFO },
{ "innocent" , POS_RESTING , do_action , 0, 0 },
{ "insult" , POS_RESTING , do_insult , 0, 0 },
{ "invis" , POS_DEAD , do_invis , LVL_LEGEND, 0 },
{ "jig" , POS_STANDING, do_action , 0, 0},
{ "jeer" , POS_RESTING , do_action , 0, 0 },
{ "jump" , POS_RESTING , do_action , 0, 0},
{ "junk" , POS_RESTING , do_drop , 0, SCMD_JUNK },
{ "kil" , POS_FIGHTING, do_kil , 0, 0 },
{ "kill" , POS_FIGHTING, do_kill , 0, SCMD_KILL },
{ "kiss" , POS_RESTING , do_action , 0, 0 },
{ "kick" , POS_STANDING, do_kick , 0, 0 },
{ "kenny" , POS_STANDING, do_action , 0, 0 },
{ "look" , POS_RESTING , do_look , 0, SCMD_LOOK },
{ "lap" , POS_STANDING, do_action , 0, 0 },
{ "laugh" , POS_RESTING , do_action , 0, 0 },
{ "last" , POS_DEAD , do_last , LVL_BUILDER, 0 },
{ "learn" , POS_RESTING , do_learn , 0, 0 },
{ "leave" , POS_STANDING, do_leave , 0, 0 },
{ "list" , POS_STANDING, do_not_here , 0, 0 },
{ "listen" , POS_RESTING , do_action , 0, 0 },
{ "lick" , POS_RESTING , do_action , 0, 0 },
{ "lock" , POS_SITTING , do_gen_door , 0, SCMD_LOCK },
{ "load" , POS_RESTING , do_load , 0, 0 },
{ "lol" , POS_RESTING , do_action , 0, 0 },
{ "love" , POS_RESTING , do_action , 0, 0 },
{ "logwatch" , POS_DEAD , do_logwatch , LVL_LEGEND, 0 },
{ "mellow" , POS_RESTING , do_action , 0, 0 },
{ "mclone" , POS_DEAD , do_mclone , LVL_PRESIDENT, 0},
{ "mdelete" , POS_DEAD , do_mdelete , LVL_PRESIDENT, 0},
{ "medit" , POS_DEAD , do_medit , LVL_LEGEND, 0},
{ "mlist" , POS_DEAD , do_mlist , LVL_LEGEND, 0},
{ "moan" , POS_RESTING , do_action , 0, 0 },
{ "moon" , POS_STANDING, do_action , 0, 0 },
{ "motd" , POS_DEAD , do_gen_ps , 0, SCMD_MOTD },
{ "mail" , POS_STANDING, do_not_here , 1, 0 },
{ "massage" , POS_RESTING , do_action , 0, 0 },
{ "muthafucka",POS_RESTING , do_action , LVL_PRESIDENT, 0 },
{ "mute" , POS_DEAD , do_wizutil , LVL_MANAGER, SCMD_SQUELCH },
{ "murder" , POS_FIGHTING, do_hit , 0, SCMD_MURDER },
{ "news" , POS_SLEEPING, do_gen_ps , 0, SCMD_NEWS },
{ "newbie" , POS_RESTING , do_gen_comm , 0, SCMD_NEWBIE },
{ "nibble" , POS_RESTING , do_action , 0, 0 },
{ "nod" , POS_RESTING , do_action , 0, 0 },
{ "noogie" , POS_STANDING, do_action , 0, 0 },
{ "notitle" , POS_DEAD , do_wizutil , LVL_ADVISOR, SCMD_NOTITLE },
{ "nudge" , POS_RESTING , do_action , 0, 0 },
{ "nuzzle" , POS_RESTING , do_action , 0, 0 },
{ "order" , POS_RESTING , do_order , 1, 0 },
{ "offer" , POS_RESTING , do_not_here , 0, 0 },
{ "olc" , POS_DEAD , do_olcon , LVL_PRESIDENT, 0 },
{ "ooc" , POS_SLEEPING, do_gen_comm , 0, SCMD_OOC},
{ "open" , POS_SITTING , do_gen_door , 0, SCMD_OPEN },
{ "operate" , POS_STANDING, do_operate , 0, 0 },
{ "osay" , POS_RESTING , do_say , 0, SCMD_OSAY },
{ "put" , POS_RESTING , do_put , 0, 0 },
{ "pant" , POS_RESTING , do_action , 0, 0 },
{ "pat" , POS_RESTING , do_action , 0, 0 },
{ "patch" , POS_RESTING , do_patch , 0, 0 },
{ "page" , POS_DEAD , do_page , LVL_ARCHITECT, 0 },
{ "pardon" , POS_DEAD , do_wizutil , LVL_DIRECTOR, SCMD_PARDON },
{ "peck" , POS_RESTING , do_action , 0, 0 },
{ "peer" , POS_RESTING , do_action , 0, 0 },
{ "perceive" , POS_RESTING , do_astral , 0, SCMD_PERCEIVE },
{ "point" , POS_RESTING , do_action , 0, 0 },
{ "poke" , POS_RESTING , do_action , 0, 0 },
{ "policy" , POS_DEAD , do_gen_ps , 0, SCMD_POLICIES },
{ "ponder" , POS_RESTING , do_action , 0, 0 },
{ "poofin" , POS_DEAD , do_poofset , LVL_LEGEND, SCMD_POOFIN },
{ "poofout" , POS_DEAD , do_poofset , LVL_LEGEND, SCMD_POOFOUT },
{ "pools" , POS_DEAD , do_pool , 0, 0 },
{ "pour" , POS_STANDING, do_pour , 0, SCMD_POUR },
{ "pout" , POS_RESTING , do_action , 0, 0 },
{ "prompt" , POS_DEAD , do_display , 0, 0 },
{ "project" , POS_RESTING , do_astral , 0, SCMD_PROJECT },
{ "prequel" , POS_DEAD , do_prequel , 0, 0 },
{ "pretitle" , POS_DEAD , do_wiztitle , LVL_LEGEND, SCMD_PRETITLE },
{ "practice" , POS_RESTING , do_practice , 1, 0 },
{ "prance" , POS_STANDING, do_action , 0, 0 },
{ "pray" , POS_SITTING , do_action , 0, 0 },
{ "propose" , POS_STANDING, do_action , 0, 0 },
{ "psychoanalyze", POS_RESTING, do_action, 0, 0 },
{ "push" , POS_STANDING, do_not_here , 0, 0 },
{ "pucker" , POS_RESTING , do_action , 0, 0 },
{ "puke" , POS_RESTING , do_action , 0, 0 },
{ "pull" , POS_STANDING, do_not_here , 0, 0 },
{ "punch" , POS_RESTING , do_action , 0, 0 },
{ "puppy" , POS_RESTING , do_action , 0, 0 },
{ "purr" , POS_RESTING , do_action , 0, 0 },
{ "purge" , POS_DEAD , do_purge , LVL_ARCHITECT, 0 },
{ "quaff" , POS_RESTING , do_use , 0, SCMD_QUAFF },
{ "qecho" , POS_DEAD , do_qcomm , LVL_BUILDER, SCMD_QECHO },
{ "qui" , POS_DEAD , do_quit , 0, 0 },
{ "quit" , POS_SLEEPING, do_quit , 0, SCMD_QUIT },
{ "qlist" , POS_DEAD , do_qlist , LVL_LEGEND, 0 },
{ "qedit" , POS_DEAD , do_qedit , LVL_PRESIDENT, 0 },
{ "reply" , POS_RESTING , do_reply , 0, 0 },
{ "radio" , POS_RESTING , do_radio , 0, 0 },
{ "rtfm" , POS_STANDING, do_action , 0, 0 },
{ "rclone" , POS_DEAD , do_rclone , LVL_LEGEND, 0},
{ "rdelete" , POS_DEAD , do_rdelete , LVL_PRESIDENT, 0},
{ "rest" , POS_RESTING , do_rest , 0, 0 },
{ "read" , POS_RESTING , do_look , 0, SCMD_READ },
{ "reboot" , POS_DEAD , do_reboot , LVL_PRESIDENT, 0 },
{ "reload" , POS_RESTING , do_reload , 0, 0 },
{ "release" , POS_RESTING , do_release , 0, 0 },
{ "recite" , POS_RESTING , do_use , 0, SCMD_RECITE },
{ "receive" , POS_STANDING, do_not_here , 1, 0 },
{ "remove" , POS_RESTING , do_remove , 0, 0 },
{ "rent" , POS_STANDING, do_not_here , 1, 0 },
{ "report" , POS_RESTING , do_report , 0, 0 },
{ "repair" , POS_STANDING, do_not_here , 0, 0 },
{ "restore" , POS_DEAD , do_restore , LVL_DIRECTOR, 0 },
{ "return" , POS_DEAD , do_return , 0, 0 },
{ "rlist" , POS_DEAD , do_rlist , LVL_LEGEND, 0 },
{ "roar" , POS_RESTING , do_action , 0, 0 },
{ "rofl" , POS_RESTING , do_action , 0, 0 },
{ "roll" , POS_RESTING , do_action , 0, 0 },
{ "rose" , POS_STANDING, do_action , 0, 0 },
{ "run" , POS_RESTING , do_run , 0, 0 },
{ "rub" , POS_RESTING , do_action , 0, 0 },
{ "ruffle" , POS_STANDING, do_action , 0, 0 },
{ "redit" , POS_DEAD , do_redit , LVL_LEGEND, 0 },
{ "sage" , POS_RESTING , do_action , 0, 0 },
{ "say" , POS_RESTING , do_say , 0, SCMD_SAY },
{ "'" , POS_RESTING , do_say , 0, SCMD_SAY },
{ "save" , POS_SLEEPING, do_save , 0, 0 },
{ "score" , POS_DEAD , do_score , 0, 0 },
{ "scan" , POS_RESTING , do_scan , 0, 0 },
{ "scratch" , POS_RESTING , do_action , 0, 0 },
{ "scream" , POS_RESTING , do_action , 0, 0 },
{ "sdelete" , POS_DEAD , do_sdelete , LVL_PRESIDENT, 0 },
{ "sell" , POS_STANDING, do_not_here , 0, 0 },
{ "send" , POS_SLEEPING, do_send , LVL_MANAGER, 0 },
{ "sedit" , POS_DEAD , do_shedit , LVL_LEGEND, 0 },
{ "set" , POS_DEAD , do_set , LVL_DIRECTOR, 0 },
{ "settime" , POS_DEAD , do_settime , LVL_OWNER, 0 },
{ "shout" , POS_RESTING , do_gen_comm , 0, SCMD_SHOUT },
{ "shoot" , POS_FIGHTING, do_shoot , 0, 0 },
{ "shake" , POS_RESTING , do_action , 0, 0 },
{ "shiver" , POS_RESTING , do_action , 0, 0 },
{ "show" , POS_DEAD , do_show , LVL_LEGEND, 0 },
{ "shrug" , POS_RESTING , do_action , 0, 0 },
{ "shutdown" , POS_RESTING , do_shutdown , 0, SCMD_SHUTDOWN },
{ "sigh" , POS_RESTING , do_action , 0, 0 },
{ "sing" , POS_RESTING , do_action , 0, 0 },
{ "sip" , POS_RESTING , do_drink , 0, SCMD_SIP },
{ "sit" , POS_RESTING , do_sit , 0, 0 },
{ "skills" , POS_SLEEPING, do_skills , 0, 0 },
{ "skillset" , POS_SLEEPING, do_skillset , LVL_PRESIDENT, 0 },
{ "slist" , POS_DEAD , do_slist , LVL_LEGEND, 0 },
{ "sleep" , POS_SLEEPING, do_sleep , 0, 0 },
{ "slap" , POS_RESTING , do_action , 0, 0 },
{ "slobber" , POS_RESTING , do_action , 0, 0 },
{ "slowns" , POS_DEAD , do_slowns , LVL_OWNER, 0 },
{ "slurp" , POS_STANDING, do_action , 0, 0 },
{ "smile" , POS_RESTING , do_action , 0, 0 },
{ "smirk" , POS_RESTING , do_action , 0, 0 },
{ "snicker" , POS_RESTING , do_action , 0, 0 },
{ "snap" , POS_RESTING , do_action , 0, 0 },
{ "snarl" , POS_RESTING , do_action , 0, 0 },
{ "sneeze" , POS_RESTING , do_action , 0, 0 },
{ "sneak" , POS_STANDING, do_sneak , 1, 0 },
{ "sniff" , POS_RESTING , do_action , 0, 0 },
{ "snore" , POS_SLEEPING, do_action , 0, 0 },
{ "snowball" , POS_STANDING, do_action , LVL_LEGEND, 0 },
{ "snoop" , POS_DEAD , do_snoop , LVL_DIRECTOR, 0 },
{ "snuggle" , POS_RESTING , do_action , 0, 0 },
{ "socials" , POS_DEAD , do_commands , 0, SCMD_SOCIALS },
{ "sob" , POS_RESTING , do_action , 0, 0 },
{ "software" , POS_RESTING , do_software , 0, 0 },
{ "spells" , POS_SLEEPING, do_spells , 0, 0 },
{ "split" , POS_SITTING , do_split , 1, 0 },
{ "spank" , POS_RESTING , do_action , 0, 0 },
{ "spit" , POS_STANDING, do_action , 0, 0 },
{ "squeeze" , POS_RESTING , do_action , 0, 0 },
{ "stand" , POS_RESTING , do_stand , 0, 0 },
{ "stare" , POS_RESTING , do_action , 0, 0 },
{ "stamp" , POS_RESTING , do_action , 0, 0 },
{ "stat" , POS_DEAD , do_stat , LVL_LEGEND, 0 },
{ "status" , POS_RESTING , do_status , 0, 0 },
{ "steal" , POS_STANDING, do_steal , LVL_OWNER, 0 },
{ "steam" , POS_RESTING , do_action , 0, 0 },
{ "striptease", POS_STANDING , do_action , 0, 0 },
{ "stroke" , POS_RESTING , do_action , 0, 0 },
{ "strut" , POS_STANDING, do_action , 0, 0 },
//{ "study" , POS_DEAD , do_study , LVL_OWNER, 0 },
{ "sulk" , POS_RESTING , do_action , 0, 0 },
{ "swat" , POS_RESTING , do_action , 0, 0 },
{ "swear" , POS_RESTING , do_action , 0, 0 },
{ "switch" , POS_DEAD , do_switch , LVL_BUILDER, 0 },
{ "tell" , POS_RESTING, do_tell , 0, 0 },
{ "tackle" , POS_RESTING , do_action , 0, 0 },
{ "take" , POS_RESTING , do_get , 0, 0 },
{ "tango" , POS_STANDING, do_action , 0, 0 },
{ "tap" , POS_RESTING , do_action , 0, 0 },
{ "taunt" , POS_RESTING , do_action , 0, 0 },
{ "taste" , POS_RESTING , do_eat , 0, SCMD_TASTE },
{ "tail" , POS_DEAD , do_tail , LVL_ADVISOR, 0 },
{ "teleport" , POS_DEAD , do_teleport , LVL_ARCHITECT, 0 },
{ "thank" , POS_RESTING , do_action , 0, 0 },
{ "think" , POS_RESTING , do_action , 0, 0 },
{ "throw" , POS_FIGHTING, do_throw , 0, 0 },
{ "thwap" , POS_SITTING , do_action , 0, 0 },
{ "thaw" , POS_DEAD , do_wizutil , LVL_FREEZE, SCMD_THAW },
{ "title" , POS_DEAD , do_title , 0, 0 },
{ "tickle" , POS_RESTING , do_action , 0, 0 },
{ "time" , POS_DEAD , do_time , 0, SCMD_NORMAL },
{ "tiptoe" , POS_RESTING , do_action , 0, 0 },
{ "toggle" , POS_DEAD , do_toggle , 0, 0 },
{ "tongue" , POS_RESTING , do_action , 0, 0 },
{ "torture" , POS_RESTING , do_action , 0, 0 },
{ "touch" , POS_STANDING, do_action , 0, 0 },
{ "toss" , POS_STANDING, do_action , 0, 0 },
{ "treat" , POS_SITTING , do_treat , 0, 0 },
{ "track" , POS_STANDING, do_track , 0, 0 },
{ "train" , POS_STANDING, do_train , 0, 0 },
{ "transfer" , POS_SLEEPING, do_trans , 0, 0 },
{ "twitch" , POS_RESTING , do_action , 0, 0 },
{ "twiddle" , POS_RESTING , do_action , 0, 0 },
{ "twirl" , POS_STANDING, do_action , 0, 0 },
{ "type" , POS_STANDING, do_type , 0, 0 },
{ "typo" , POS_DEAD , do_gen_write, 0, SCMD_TYPO },
{ "uninstall", POS_RESTING , do_get , 0, SCMD_UNINSTALL },
{ "unlock" , POS_SITTING , do_gen_door , 0, SCMD_UNLOCK },
{ "ungroup" , POS_DEAD , do_ungroup , 0, 0 },
{ "unload" , POS_RESTING , do_unload , 0, 0 },
{ "unban" , POS_DEAD , do_unban , LVL_PRESIDENT, 0 },
{ "unaffect" , POS_DEAD , do_wizutil , LVL_PRESIDENT, SCMD_UNAFFECT },
{ "unattach" , POS_RESTING , do_unattach , 0, 0 },
{ "unoperate", POS_RESTING , do_unoperate, LVL_PRESIDENT, 0 },
{ "upload" , POS_RESTING , do_not_here , 0, 0 },
{ "uptime" , POS_DEAD , do_date , LVL_LEGEND, SCMD_UPTIME },
{ "use" , POS_SITTING , do_use , 1, SCMD_USE },
{ "users" , POS_DEAD , do_users , LVL_LEGEND, 0 },
{ "value" , POS_STANDING, do_not_here , 0, 0 },
{ "vars" , POS_DEAD , do_vars , LVL_OWNER, 0},
{ "version" , POS_DEAD , do_gen_ps , 0, SCMD_VERSION },
{ "visible" , POS_RESTING , do_visible , 1, 0 },
{ "vnum" , POS_DEAD , do_vnum , LVL_LEGEND, 0 },
{ "volunteer", POS_RESTING , do_action , 0, 0 },
{ "vstat" , POS_DEAD , do_vstat , LVL_LEGEND, 0 },
{ "wake" , POS_SLEEPING, do_wake , 0, 0 },
{ "wave" , POS_RESTING , do_action , 0, 0 },
{ "wear" , POS_RESTING , do_wear , 0, 0 },
{ "weather" , POS_RESTING , do_weather , 0, 0 },
{ "who" , POS_DEAD , do_who , 0, 0 },
{ "whoami" , POS_DEAD , do_gen_ps , 0, SCMD_WHOAMI },
{ "whotitle" , POS_DEAD , do_wiztitle , LVL_LEGEND, SCMD_WHOTITLE },
{ "where" , POS_RESTING , do_where , 1, 0 },
{ "whimper" , POS_RESTING , do_action , 0, 0 },
{ "whisper" , POS_RESTING , do_spec_comm, 0, SCMD_WHISPER },
{ "whine" , POS_RESTING , do_action , 0, 0 },
{ "whistle" , POS_RESTING , do_action , 0, 0 },
{ "whiz" , POS_SITTING , do_action , 0, 0 },
{ "wibble" , POS_STANDING, do_action , 0, 0 },
{ "wield" , POS_RESTING , do_wield , 0, 0 },
{ "wiggle" , POS_STANDING, do_action , 0, 0 },
{ "wimpy" , POS_DEAD , do_wimpy , 0, 0 },
{ "wince" , POS_RESTING , do_action , 0, 0 },
{ "wink" , POS_RESTING , do_action , 0, 0 },
{ "withdraw" , POS_STANDING, do_not_here , 1, 0 },
{ "wtell" , POS_DEAD , do_wiztell , LVL_LEGEND, 0 },
{ "wf" , POS_DEAD , do_wizfeel , LVL_LEGEND, 0 },
{ "wizhelp" , POS_SLEEPING, do_wizhelp , LVL_LEGEND, 0 },
{ "wizlist" , POS_DEAD , do_gen_ps , 0, SCMD_WIZLIST },
{ "wizlock" , POS_DEAD , do_wizlock , LVL_PRESIDENT, 0 },
{ "worship" , POS_RESTING , do_action , 0, 0 },
{ "write" , POS_RESTING , do_not_here , 0, 0 },
{ "wrestle" , POS_STANDING, do_action , 0, 0 },
{ "wwho" , POS_DEAD , do_wizwho , LVL_LEGEND, 0 },
{ "xyz" , POS_STANDING, do_action , 0, 0 },
{ "yawn" , POS_RESTING , do_action , 0, 0 },
{ "yell" , POS_RESTING , do_gen_comm , 0, SCMD_SHOUT},
{ "yodel" , POS_RESTING , do_action , 0, 0 },
{ "zdelete" , POS_DEAD , do_zdelete , LVL_PRESIDENT, 0 },
{ "zedit" , POS_DEAD , do_zedit , LVL_LEGEND, 0 },
{ "zlist" , POS_DEAD , do_zlist , LVL_LEGEND, 0 },
{ "zreset" , POS_DEAD , do_zreset , LVL_LEGEND, 0 },
{ "zswitch" , POS_DEAD , do_zswitch , LVL_LEGEND, 0},
{ "\n", 0, 0, 0, 0 } }; /* this must be last */
const char *fill[] =
{
"in",
"from",
"with",
"the",
"on",
"at",
"to",
"\n"
};
const char *reserved[] =
{
"self",
"me",
"all",
"room",
"someone",
"something",
"\n"
};
void nonsensical_reply(struct char_data *ch)
{
switch (number(1, 8)) {
case 1:
send_to_char(ch, "Huh?!?\r\n");
break;
case 2:
send_to_char(ch, "Your command dissolves into oblivion.\r\n");
break;
case 3:
send_to_char(ch, "Faint laughter can be heard...\r\n");
break;
case 4:
send_to_char(ch, "Just what're you trying to do?!\r\n");
break;
case 5:
send_to_char(ch, "That makes no sense.\r\n", ch);
break;
case 6:
send_to_char(ch, "What?\r\n");
break;
case 7:
send_to_char(ch, "Lemmings run mindlessly around you.\r\n");
break;
case 8:
send_to_char(ch, "Nonsensical gibberish, it is.\r\n");
break;
}
}
/*
* This is the actual command interpreter called from game_loop() in comm.c
* It makes sure you are the proper level and position to execute the command,
* then calls the appropriate function.
*/
void command_interpreter(struct char_data * ch, char *argument)
{
int cmd, length;
extern int no_specials;
char *line;
REMOVE_BIT(AFF_FLAGS(ch), AFF_HIDE);
REMOVE_BIT(PRF_FLAGS(ch), PRF_AFK);
/* just drop to next line for hitting CR */
skip_spaces(&argument);
if (!*argument)
return;
/*
* special case to handle one-character, non-alphanumeric commands;
* requested by many people so "'hi" or ";godnet test" is possible.
* Patch sent by Eric Green and Stefan Wasilewski.
*/
if (!isalpha(*argument)) {
arg[0] = argument[0];
arg[1] = '\0';
line = argument+1;
} else line = any_one_arg(argument, arg);
/* otherwise, find the command */
for (length = strlen(arg), cmd = 0; *cmd_info[cmd].command != '\n'; cmd++)
if (!strncmp(cmd_info[cmd].command, arg, length))
if ((cmd_info[cmd].minimum_level < LVL_LEGEND) ||
access_level(ch, cmd_info[cmd].minimum_level) ||
((CMD_IS("echo") || CMD_IS("qecho") || CMD_IS("send") ||
CMD_IS("switch") || CMD_IS("transfer")) && PLR_FLAGGED(ch, PLR_QUESTER)))
break;
// this was added so we can make the special respond to any text they type
if (*cmd_info[cmd].command == '\n')
nonsensical_reply(ch);
else if (PLR_FLAGGED(ch, PLR_FROZEN) && !access_level(ch, LVL_OWNER))
send_to_char("You try, but the mind-numbing cold prevents you...\r\n", ch);
else if (AFF_FLAGGED(ch, AFF_PETRIFY) && cmd_info[cmd].minimum_position > POS_DEAD)
send_to_char("Your muscles don't respond to your impulse.\r\n", ch);
else if (cmd_info[cmd].command_pointer == NULL)
send_to_char("Sorry, that command hasn't been implemented yet.\r\n", ch);
else if (cmd_info[cmd].minimum_level >= LVL_LEGEND && IS_PERSONA(ch))
send_to_char("You cannot use immortal commands while connected to the Matrix.\r\n", ch);
else if (GET_POS(ch) < cmd_info[cmd].minimum_position)
switch (GET_POS(ch)) {
case POS_DEAD:
send_to_char("Lie still; you are DEAD!!! :-(\r\n", ch);
break;
case POS_INCAP:
case POS_MORTALLYW:
send_to_char("You are in a pretty bad shape, unable to do anything!\r\n", ch);
break;
case POS_STUNNED:
send_to_char("All you can do right now is think about the stars!\r\n", ch);
break;
case POS_SLEEPING:
send_to_char("In your dreams, or what?\r\n", ch);
break;
case POS_RESTING:
send_to_char("Nah... You feel too relaxed to do that..\r\n", ch);
break;
case POS_SITTING:
send_to_char("Maybe you should get on your feet first?\r\n", ch);
break;
case POS_FIGHTING:
send_to_char("No way! You're fighting for your life!\r\n", ch);
break;
}
else if (no_specials || !special(ch, cmd, line))
((*cmd_info[cmd].command_pointer) (ch, line, cmd, cmd_info[cmd].subcmd));
}
/**************************************************************************
* Routines to handle aliasing *
**************************************************************************/
struct alias *find_alias(struct alias *alias_list, char *str)
{
while (alias_list != NULL) {
if (*str == *alias_list->command) /* hey, every little bit counts :-) */
if (!strcmp(str, alias_list->command))
return alias_list;
alias_list = alias_list->next;
}
return NULL;
}
void free_alias(struct alias *a)
{
if (a->command)
delete [] a->command;
if (a->replacement)
delete [] a->replacement;
delete a;
}
/* The interface to the outside world: do_alias */
ACMD(do_alias)
{
char *repl;
struct alias *a, *temp;
if (IS_NPC(ch))
return;
repl = any_one_arg(argument, arg);
if (!*arg) { /* no argument specified -- list currently defined aliases */
send_to_char("Currently defined aliases:\r\n", ch);
if ((a = GET_ALIASES(ch)) == NULL)
send_to_char(" None.\r\n", ch);
else {
while (a != NULL) {
sprintf(buf, "%-15s %s\r\n", a->command, a->replacement);
send_to_char(buf, ch);
a = a->next;
}
}
} else { /* otherwise, add or remove aliases */
/* is this an alias we've already defined? */
if ((a = find_alias(GET_ALIASES(ch), arg)) != NULL) {
REMOVE_FROM_LIST(a, GET_ALIASES(ch), next);
free_alias(a);
}
/* if no replacement string is specified, assume we want to delete */
if (!*repl) {
if (a == NULL)
send_to_char("No such alias.\r\n", ch);
else send_to_char("Alias deleted.\r\n", ch);
} else { /* otherwise, either add or redefine an alias */
if (!str_cmp(arg, "alias")) {
send_to_char("You can't alias 'alias'.\r\n", ch);
return;
}
else if ( strstr(repl,"kill") && strlen(arg) < 4 )
{
send_to_char(
"If you alias contains the 'kill' command, it must be accompanied by at least a 4 letter alias.\n\r",ch);
return;
}
a = new alias;
a->command = str_dup(arg);
skip_spaces(&repl);
delete_doubledollar(repl);
a->replacement = str_dup(repl);
if (strchr((const char *)repl, ALIAS_SEP_CHAR) ||
strchr((const char *)repl, ALIAS_VAR_CHAR))
a->type = ALIAS_COMPLEX;
else a->type = ALIAS_SIMPLE;
a->next = GET_ALIASES(ch);
GET_ALIASES(ch) = a;
send_to_char("Alias added.\r\n", ch);
}
}
}
/*
* Valid numeric replacements are only &1 .. &9 (makes parsing a little
* easier, and it's not that much of a limitation anyway.) Also valid
* is "&*", which stands for the entire original line after the alias.
* ";" is used to delimit commands.
*/
#define NUM_TOKENS 9
void perform_complex_alias(struct txt_q *input_q, char *orig, struct alias *a)
{
struct txt_q temp_queue;
char *tokens[NUM_TOKENS], *temp, *write_point;
int num_of_tokens = 0, num;
skip_spaces(&orig);
/* First, parse the original string */
temp = strtok(strcpy(buf2, orig), " ");
while (temp != NULL && num_of_tokens < NUM_TOKENS) {
tokens[num_of_tokens++] = temp;
temp = strtok(NULL, " ");
}
/* initialize */
write_point = buf;
temp_queue.head = temp_queue.tail = NULL;
/* now parse the alias */
for (temp = a->replacement; *temp; temp++) {
if (*temp == ALIAS_SEP_CHAR) {
*write_point = '\0';
buf[MAX_INPUT_LENGTH-1] = '\0';
write_to_q(buf, &temp_queue, 1);
write_point = buf;
} else if (*temp == ALIAS_VAR_CHAR) {
temp++;
if ((num = *temp - '1') < num_of_tokens && num >= 0) {
strcpy(write_point, tokens[num]);
write_point += strlen(tokens[num]);
} else if (*temp == ALIAS_GLOB_CHAR) {
strcpy(write_point, orig);
write_point += strlen(orig);
} else if ((*(write_point++) = *temp) == '$') /* redouble $ for act safety */
*(write_point++) = '$';
} else *(write_point++) = *temp;
}
*write_point = '\0';
buf[MAX_INPUT_LENGTH-1] = '\0';
write_to_q(buf, &temp_queue, 1);
/* push our temp_queue on to the _front_ of the input queue */
if (input_q->head == NULL)
*input_q = temp_queue;
else {
temp_queue.tail->next = input_q->head;
input_q->head = temp_queue.head;
}
}
/*
* Given a character and a string, perform alias replacement on it.
*
* Return values:
* 0: String was modified in place; call command_interpreter immediately.
* 1: String was _not_ modified in place; rather, the expanded aliases
* have been placed at the front of the character's input queue.
*/
int perform_alias(struct descriptor_data * d, char *orig)
{
char first_arg[MAX_INPUT_LENGTH], *ptr;
struct alias *a, *tmp;
/* bail out immediately if the guy doesn't have any aliases */
if ((tmp = GET_ALIASES(d->character)) == NULL)
return 0;
/* find the alias we're supposed to match */
ptr = any_one_arg(orig, first_arg);
/* bail out if it's null */
if (!*first_arg)
return 0;
/* if the first arg is not an alias, return without doing anything */
if ((a = find_alias(tmp, first_arg)) == NULL)
return 0;
if (a->type == ALIAS_SIMPLE) {
strcpy(orig, a->replacement);
return 0;
} else {
perform_complex_alias(&d->input, ptr, a);
return 1;
}
}
/***************************************************************************
* Various other parsing utilities *
**************************************************************************/
/*
* searches an array of strings for a target string. "exact" can be
* 0 or non-0, depending on whether or not the match must be exact for
* it to be returned. Returns -1 if not found; 0..n otherwise. Array
* must be terminated with a '\n' so it knows to stop searching.
*/
int search_block(char *arg, const char **list, bool exact)
{
register int i, l;
/* Make into lower case, and get length of string */
for (l = 0; *(arg + l); l++)
*(arg + l) = LOWER(*(arg + l));
if (exact) {
for (i = 0; **(list + i) != '\n'; i++)
if (!strcmp(arg, *(list + i)))
return (i);
} else {
if (!l)
l = 1; /* Avoid "" to match the first available
* string */
for (i = 0; **(list + i) != '\n'; i++)
if (!strncmp(arg, *(list + i), l))
return (i);
}
return -1;
}
int is_number(char *str)
{
while (*str)
if (!isdigit(*(str++)))
return 0;
return 1;
}
void skip_spaces(char **string)
{
for (; **string && isspace(**string); (*string)++);
}
char *delete_doubledollar(char *string)
{
char *read, *write;
if ((write = strchr((const char *)string, '$')) == NULL)
return string;
read = write;
while (*read)
if ((*(write++) = *(read++)) == '$')
if (*read == '$')
read++;
*write = '\0';
return string;
}
int fill_word(char *argument)
{
return (search_block(argument, fill, TRUE) >= 0);
}
int reserved_word(char *argument)
{
return (search_block(argument, reserved, TRUE) >= 0);
}
/*
* copy the first non-fill-word, space-delimited argument of 'argument'
* to 'first_arg'; return a pointer to the remainder of the string.
*/
char *one_argument(char *argument, char *first_arg)
{
char *begin = first_arg;
do {
skip_spaces(&argument);
first_arg = begin;
while (*argument && !isspace(*argument)) {
*(first_arg++) = LOWER(*argument);
argument++;
}
*first_arg = '\0';
} while (fill_word(begin));
skip_spaces(&argument);
return argument;
}
/* same as one_argument except that it doesn't ignore fill words */
char *any_one_arg(char *argument, char *first_arg)
{
if (!argument)
return NULL;
skip_spaces(&argument);
while (*argument && !isspace(*argument)) {
*(first_arg++) = LOWER(*argument);
argument++;
}
*first_arg = '\0';
return argument;
}
/*
* Same as one_argument except that it takes two args and returns the rest;
* ignores fill words
*/
char *two_arguments(char *argument, char *first_arg, char *second_arg)
{
return one_argument(one_argument(argument, first_arg), second_arg); /* :-) */
}
/*
* determine if a given string is an abbreviation of another
* (now works symmetrically -- JE 7/25/94)
*
* that was dumb. it shouldn't be symmetrical. JE 5/1/95
*
* returns 1 if arg1 is an abbreviation of arg2
*/
int is_abbrev(char *arg1, const char *arg2)
{
if (!*arg1)
return 0;
for (; *arg1 && *arg2; arg1++, arg2++)
if (LOWER(*arg1) != LOWER(*arg2))
return 0;
if (!*arg1)
return 1;
else return 0;
}
/* return first space-delimited token in arg1; remainder of string in arg2 */
void half_chop(char *string, char *arg1, char *arg2)
{
char *temp;
temp = any_one_arg(string, arg1);
skip_spaces(&temp);
strcpy(arg2, temp);
}
/* Used in specprocs, mostly. (Exactly) matches "command" to cmd number */
int find_command(char *command)
{
int cmd;
for (cmd = 0; *cmd_info[cmd].command != '\n'; cmd++)
if (!strcmp(cmd_info[cmd].command, command))
return cmd;
return -1;
}
int special(struct char_data * ch, int cmd, char *arg)
{
/* special in room? */
if (GET_ROOM_SPEC(ch->in_room) != NULL)
if (GET_ROOM_SPEC(ch->in_room) (ch, world + ch->in_room, cmd, arg))
return 1;
/* special in equipment list? */
int j = 0;
for (; j < NUM_WEARS; j++)
if (GET_EQ(ch, j) && GET_OBJ_SPEC(ch->equipment[j]) != NULL)
if (GET_OBJ_SPEC(ch->equipment[j]) (ch, ch->equipment[j], cmd, arg))
return 1;
/* special in inventory? */
register struct obj_data *i;
for (i = ch->carrying; i; i = i->next_content)
if (GET_OBJ_SPEC(i) != NULL)
if (GET_OBJ_SPEC(i) (ch, i, cmd, arg))
return 1;
/* special in mobile present? */
register struct char_data *k;
for (k = world[ch->in_room].people; k; k = k->next_in_room) {
if (GET_MOB_SPEC(k) != NULL)
if (GET_MOB_SPEC(k) (ch, k, cmd, arg))
return 1;
if (mob_index[GET_MOB_RNUM(k)].sfunc != NULL)
if ((mob_index[GET_MOB_RNUM(k)].sfunc) (ch, k, cmd, arg))
return 1;
}
/* special in object present? */
for (i = world[ch->in_room].contents; i; i = i->next_content)
if (GET_OBJ_SPEC(i) != NULL)
if (GET_OBJ_SPEC(i) (ch, i, cmd, arg))
return 1;
return 0;
}
/* *************************************************************************
* Stuff for controlling the non-playing sockets (get name, pwd etc) *
************************************************************************* */
/* locate entry in p_table with entry->name == name. -1 mrks failed search */
int find_name(char *name)
{
int i;
for (i = 0; i <= top_of_p_table; i++) {
if (!str_cmp((player_table + i)->name, name))
return i;
}
return -1;
}
int _parse_name(char *arg, char *name)
{
int i;
/* skip whitespaces */
for (; isspace(*arg); arg++);
for (i = 0; (*name = *arg); arg++, i++, name++)
if (!isalpha(*arg))
return 1;
if (!i)
return 1;
return 0;
}
#define RECON 1
#define USURP 2
#define UNSWITCH 3
int perform_dupe_check(struct descriptor_data *d)
{
struct descriptor_data *k, *next_k;
struct char_data *target = NULL, *ch, *next_ch;
int mode = 0, i;
struct obj_data *obj;
int id = GET_IDNUM(d->character);
/*
* Now that this descriptor has successfully logged in, disconnect all
* other descriptors controlling a character with the same ID number.
*/
for (k = descriptor_list; k; k = next_k) {
next_k = k->next;
if (k == d)
continue;
if (k->original && (GET_IDNUM(k->original) == id)) { /* switched char */
SEND_TO_Q("\r\nMultiple login detected -- disconnecting.\r\n", k);
STATE(k) = CON_CLOSE;
if (!target) {
target = k->original;
mode = UNSWITCH;
}
if (k->character)
k->character->desc = NULL;
k->character = NULL;
k->original = NULL;
} else if (k->character && (GET_IDNUM(k->character) == id)) {
if (!target && STATE(k) == CON_PLAYING) {
SEND_TO_Q("\r\nThis body has been usurped!\r\n", k);
target = k->character;
mode = USURP;
}
k->character->desc = NULL;
k->character = NULL;
k->original = NULL;
SEND_TO_Q("\r\nMultiple login detected -- disconnecting.\r\n", k);
STATE(k) = CON_CLOSE;
}
}
/*
* now, go through the character list, deleting all characters that
* are not already marked for deletion from the above step (i.e., in the
* CON_HANGUP state), and have not already been selected as a target for
* switching into. In addition, if we haven't already found a target,
* choose one if one is available (while still deleting the other
* duplicates, though theoretically none should be able to exist).
*/
for (ch = character_list; ch; ch = next_ch) {
next_ch = ch->next;
if (IS_NPC(ch))
continue;
if (GET_IDNUM(ch) != id)
continue;
/* ignore chars with descriptors (already handled by above step) */
if (ch->desc)
continue;
/* don't extract the target char we've found one already */
if (ch == target)
continue;
/* we don't already have a target and found a candidate for switching */
if (!target) {
target = ch;
mode = RECON;
continue;
}
/* we've found a duplicate - blow him away, dumping his eq in limbo. */
if (ch->in_room != NOWHERE)
char_from_room(ch);
char_to_room(ch, 1);
extract_char(ch);
}
/* no target for swicthing into was found - allow login to continue */
if (!target)
return 0;
/* Okay, we've found a target. Connect d to target. */
Mem->DeleteCh(d->character); /* get rid of the old char */
d->character = target;
d->character->desc = d;
d->original = NULL;
d->character->char_specials.timer = 0;
REMOVE_BIT(PLR_FLAGS(d->character), PLR_MAILING | PLR_WRITING |
PLR_EDITING | PLR_SPELL_CREATE | PLR_CUSTOMIZE |
PLR_PROJECT | PLR_MATRIX);
STATE(d) = CON_PLAYING;
switch (mode) {
case RECON:
SEND_TO_Q("Reconnecting.\r\n", d);
act("$n has reconnected.", TRUE, d->character, 0, 0, TO_ROOM);
sprintf(buf, "%s [%s] has reconnected.", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, FALSE);
break;
case USURP:
SEND_TO_Q("You take over your own body, already in use!\r\n", d);
act("$n suddenly keels over in pain, surrounded by a white aura...\r\n"
"$n's body has been taken over by a new spirit!",
TRUE, d->character, 0, 0, TO_ROOM);
sprintf(buf, "%s has re-logged in ... disconnecting old socket.",
GET_NAME(d->character));
mudlog(buf, d->character, LOG_CONNLOG, FALSE);
// now delete all the editing struct
if (d->edit_obj)
Mem->DeleteObject(d->edit_obj);
d->edit_obj = NULL;
if (d->edit_room)
Mem->DeleteRoom(d->edit_room);
d->edit_room = NULL;
if (d->edit_mob)
Mem->DeleteCh(d->edit_mob);
d->edit_mob = NULL;
if (d->edit_shop) {
free_shop(d->edit_shop);
delete d->edit_shop;
d->edit_shop = NULL;
}
if (d->edit_quest) {
free_quest(d->edit_quest);
delete d->edit_quest;
d->edit_quest = NULL;
}
if (d->edit_zon)
delete d->edit_zon;
d->edit_zon = NULL;
if (d->edit_cmd)
delete d->edit_cmd;
d->edit_cmd = NULL;
if (d->edit_spell)
delete d->edit_spell;
d->edit_spell = NULL;
break;
case UNSWITCH:
SEND_TO_Q("Reconnecting to unswitched char.", d);
sprintf(buf, "%s [%s] has reconnected.", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, FALSE);
break;
}
return 1;
}
/* deal with newcomers and other non-playing sockets */
void nanny(struct descriptor_data * d, char *arg)
{
char buf[128];
int player_i, load_result;
char tmp_name[MAX_INPUT_LENGTH];
struct char_file_u tmp_store;
struct char_data *tmp_ch;
struct descriptor_data *k, *next;
extern struct descriptor_data *descriptor_list;
extern sh_int mortal_start_room;
extern sh_int immort_start_room;
extern sh_int frozen_start_room;
extern sh_int newbie_start_room;
extern const char *class_menu;
extern const char *totem_menu;
extern int max_bad_pws;
extern const char *race_menu;
sh_int load_room;
int load_char(char *name, struct char_file_u * char_element);
int parse_class(struct descriptor_data *d, char *arg);
int parse_race(struct descriptor_data *d, char *arg);
int parse_totem(struct descriptor_data *d, char *arg);
skip_spaces(&arg);
switch (STATE(d)) {
// this sends control to the various on-line creation systems
case CON_REDIT:
redit_parse(d, arg);
break;
case CON_IEDIT:
iedit_parse(d, arg);
break;
case CON_MEDIT:
medit_parse(d, arg);
break;
case CON_QEDIT:
qedit_parse(d, arg);
break;
case CON_SHEDIT:
shedit_parse(d, arg);
break;
case CON_ZEDIT:
zedit_parse(d, arg);
break;
// this sends control to the spell creation system
case CON_SPELL_CREATE:
sedit_parse(d, arg);
break;
case CON_PCUSTOMIZE:
case CON_ACUSTOMIZE:
cedit_parse(d, arg);
break;
case CON_CCREATE:
create_parse(d, arg);
break;
case CON_GET_NAME: /* wait for input of name */
d->idle_tics = 0;
if (d->character == NULL) {
d->character = Mem->GetCh();
d->character->player_specials = new player_special_data;
// make sure to clear it up here
memset((char *)d->character->player_specials, 0, sizeof(player_special_data));
d->character->desc = d;
}
if (!*arg) {
d->invalid_name++;
if (d->invalid_name > 3)
close_socket(d);
else {
SEND_TO_Q("\r\nWhat name do you wish to be called by? ", d);
return;
}
} else {
if ((_parse_name(arg, tmp_name)) || strlen(tmp_name) < 2 ||
strlen(tmp_name) > MAX_NAME_LENGTH ||
fill_word(strcpy(buf, tmp_name)) || reserved_word(buf)) {
d->invalid_name++;
if (d->invalid_name > 3)
close_socket(d);
else SEND_TO_Q("Invalid name, please try another.\r\nName: ", d);
return;
}
if ((player_i = load_char(tmp_name, &tmp_store)) > -1) {
store_to_char(&tmp_store, d->character);
GET_PFILEPOS(d->character) = player_i;
if (PLR_FLAGGED(d->character, PLR_DELETED)) {
Mem->DeleteCh(d->character);
d->character = Mem->GetCh();
d->character->player_specials = new player_special_data;
memset((char *)d->character->player_specials, 0, sizeof(player_special_data));
d->character->desc = d;
d->character->player.name = new char[strlen(tmp_name) + 1];
strcpy(d->character->player.name, CAP(tmp_name));
GET_PFILEPOS(d->character) = player_i;
sprintf(buf, "Did I get that right, %s (Y/N)? ", tmp_name);
SEND_TO_Q(buf, d);
STATE(d) = CON_NAME_CNFRM;
} else {
if (isname("neuromancer", GET_NAME(d->character)))
strncpy(d->host, "255@unknown.net", HOST_LENGTH);
SEND_TO_Q("Password: ", d);
echo_off(d);
read_etext(d->character);
read_spells(d->character);
STATE(d) = CON_PASSWORD;
}
} else {
/* player unknown -- make new character */
if (!Valid_Name(tmp_name)) {
SEND_TO_Q("Invalid name, please try another.\r\n", d);
SEND_TO_Q("Name: ", d);
return;
}
d->character->player.name = new char[strlen(tmp_name) + 1];
strcpy(d->character->player.name, CAP(tmp_name));
sprintf(buf, "Did I get that right, %s (Y/N)? ", tmp_name);
SEND_TO_Q(buf, d);
STATE(d) = CON_NAME_CNFRM;
}
}
break;
case CON_NAME_CNFRM: /* wait for conf. of new name */
if (UPPER(*arg) == 'Y') {
if (isbanned(d->host) >= BAN_NEW) {
sprintf(buf, "Request for new char %s denied from [%s] (siteban)",
GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, TRUE);
SEND_TO_Q("Sorry, new characters are not allowed from your site.\r\n", d);
STATE(d) = CON_CLOSE;
return;
}
if (restrict) {
if (restrict == LVL_OWNER)
SEND_TO_Q("The mud is being reconfigured. Try again a bit later.\r\n", d);
else
SEND_TO_Q("Sorry, new players can't be created at the moment.\r\n", d);
sprintf(buf, "Request for new char %s denied from %s (wizlock)", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, TRUE);
STATE(d) = CON_CLOSE;
return;
}
SEND_TO_Q("New character.\r\n", d);
sprintf(buf, "Give me a password for %s: ", GET_NAME(d->character));
SEND_TO_Q(buf, d);
echo_off(d);
STATE(d) = CON_NEWPASSWD;
} else if (*arg == 'n' || *arg == 'N') {
SEND_TO_Q("Okay, what IS it, then? ", d);
delete [] d->character->player.name;
d->character->player.name = NULL;
STATE(d) = CON_GET_NAME;
} else {
SEND_TO_Q("Please type Yes or No: ", d);
}
break;
case CON_PASSWORD: /* get pwd for known player */
/*
* To really prevent duping correctly, the player's record should
* be reloaded from disk at this point (after the password has been
* typed). However I'm afraid that trying to load a character over
* an already loaded character is going to cause some problem down the
* road that I can't see at the moment. So to compensate, I'm going to
* (1) add a 15 or 20-second time limit for entering a password, and (2)
* re-add the code to cut off duplicates when a player quits. JE 6 Feb 96
*/
/* turn echo back on */
echo_on(d);
if (!*arg)
close_socket(d);
else {
if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) {
sprintf(buf, "Bad PW: %s [%s]", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, FALSE);
GET_BAD_PWS(d->character)++;
save_char(d->character, NOWHERE);
if (++(d->bad_pws) >= max_bad_pws) { /* 3 strikes and you're out. */
SEND_TO_Q("Wrong password... disconnecting.\r\n", d);
STATE(d) = CON_CLOSE;
} else {
SEND_TO_Q("Wrong password.\r\nPassword: ", d);
echo_off(d);
}
return;
}
load_result = GET_BAD_PWS(d->character);
GET_BAD_PWS(d->character) = 0;
save_char(d->character, NOWHERE);
if (isbanned(d->host) == BAN_SELECT &&
!PLR_FLAGGED(d->character, PLR_SITEOK)) {
SEND_TO_Q("Sorry, this char has not been cleared for login >from your site!\r\n", d);
STATE(d) = CON_CLOSE;
sprintf(buf, "Connection attempt for %s denied from %s", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, TRUE);
return;
}
if (GET_LEVEL(d->character) < restrict) {
if (restrict == LVL_OWNER)
SEND_TO_Q("The mud is about to reboot. Please try again in a few minutes.\r\n", d);
else SEND_TO_Q("The game is temporarily restricted.. try again later.\r\n", d);
STATE(d) = CON_CLOSE;
sprintf(buf, "Request for login denied for %s [%s] (wizlock)", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, TRUE);
return;
}
/* check and make sure no other copies of this player are logged in */
if (perform_dupe_check(d))
return;
/* undo it just in case they are set */
REMOVE_BIT(PLR_FLAGS(d->character), PLR_WRITING | PLR_MAILING | PLR_CRYO | PLR_EDITING |
PLR_SPELL_CREATE | PLR_CUSTOMIZE | PLR_PROJECT | PLR_MATRIX);
if (GET_LEVEL(d->character) >= LVL_LEGEND)
SEND_TO_Q(imotd, d);
else SEND_TO_Q(motd, d);
sprintf(buf, "%s [%s] has connected.", GET_NAME(d->character), d->host);
mudlog(buf, d->character, LOG_CONNLOG, FALSE);
if (load_result) {
sprintf(buf, "\r\n\r\n\007\007\007"
"%s%d LOGIN FAILURE%s SINCE LAST SUCCESSFUL LOGIN.%s\r\n",
CCRED(d->character, C_SPR), load_result,
(load_result > 1) ? "S" : "", CCNRM(d->character, C_SPR));
SEND_TO_Q(buf, d);
GET_BAD_PWS(d->character) = 0;
}
SEND_TO_Q("\r\n\n*** PRESS RETURN: ", d);
STATE(d) = CON_RMOTD;
}
break;
case CON_NEWPASSWD:
case CON_CHPWD_GETNEW:
case CON_QGETNEWPW:
if (!*arg || strlen(arg) > MAX_PWD_LENGTH || strlen(arg) < 3 ||
!str_cmp(arg, GET_NAME(d->character))) {
SEND_TO_Q("\r\nIllegal password.\r\n", d);
SEND_TO_Q("Password: ", d);
return;
}
strncpy(GET_PASSWD(d->character), CRYPT(arg, GET_NAME(d->character)), MAX_PWD_LENGTH);
*(GET_PASSWD(d->character) + MAX_PWD_LENGTH) = '\0';
SEND_TO_Q("\r\nPlease retype password: ", d);
if (STATE(d) == CON_NEWPASSWD)
STATE(d) = CON_CNFPASSWD;
else if (STATE(d) == CON_CHPWD_GETNEW)
STATE(d) = CON_CHPWD_VRFY;
else STATE(d) = CON_QVERIFYPW;
break;
case CON_CNFPASSWD:
case CON_CHPWD_VRFY:
case CON_QVERIFYPW:
if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character),
MAX_PWD_LENGTH)) {
SEND_TO_Q("\r\nPasswords don't match... start over.\r\n", d);
SEND_TO_Q("Password: ", d);
if (STATE(d) == CON_CNFPASSWD)
STATE(d) = CON_NEWPASSWD;
else if (STATE(d) == CON_CHPWD_VRFY)
STATE(d) = CON_CHPWD_GETNEW;
else STATE(d) = CON_QGETNEWPW;
return;
}
echo_on(d);
if (STATE(d) == CON_CNFPASSWD) {
SEND_TO_Q("What is your sex (M/F)? ", d);
STATE(d) = CON_CCREATE;
init_create_vars(d);
} else {
save_char(d->character, NOWHERE);
echo_on(d);
SEND_TO_Q("\r\nDone.\r\n", d);
if (STATE(d) == CON_CHPWD_VRFY) {
SEND_TO_Q(MENU, d);
STATE(d) = CON_MENU;
} else {
SEND_TO_Q(QMENU, d);
STATE(d) = CON_QMENU;
}
}
break;
case CON_RMOTD: /* read CR after printing motd */
SEND_TO_Q(MENU, d);
STATE(d) = CON_MENU;
break;
case CON_MENU: /* get selection from main menu */
switch (*arg) {
case '0':
/* save them so they won't lose their cyberware */
if ((IS_SET(PLR_FLAGS(d->character), PLR_JUST_DIED)))
REMOVE_BIT(PLR_FLAGS(d->character), PLR_JUST_DIED);
close_socket(d);
break;
case '1':
if ((IS_SET(PLR_FLAGS(d->character), PLR_JUST_DIED)))
REMOVE_BIT(PLR_FLAGS(d->character), PLR_JUST_DIED);
reset_char(d->character);
if (PLR_FLAGGED(d->character, PLR_INVSTART))
GET_INVIS_LEV(d->character) = GET_LEVEL(d->character);
if ((load_result = Crash_load(d->character)))
d->character->in_room = NOWHERE;
save_char(d->character, GET_LOADROOM(d->character));
send_to_char(WELC_MESSG, d->character);
d->character->next = character_list;
character_list = d->character;
if ((load_room = GET_LOADROOM(d->character)) != NOWHERE)
load_room = real_room(load_room);
if (GET_LEVEL(d->character) >= LVL_LEGEND && !PLR_FLAGGED(d->character, PLR_LOADROOM))
load_room = real_room(immort_start_room);
/* If char was saved with NOWHERE, or real_room above failed... */
if (load_room == NOWHERE) {
if (PLR_FLAGGED(d->character, PLR_NEWBIE))
load_room = real_room(newbie_start_room);
else load_room = real_room(mortal_start_room);
}
if (PLR_FLAGGED(d->character, PLR_FROZEN))
load_room = real_room(frozen_start_room);
if (!GET_LEVEL(d->character)) {
load_room = real_room(newbie_start_room);
do_start(d->character);
send_to_char(START_MESSG, d->character);
}
char_to_room(d->character, load_room);
act("$n has entered the game.", TRUE, d->character, 0, 0, TO_ROOM);
STATE(d) = CON_PLAYING;
/* set infra and low light eyes for races */
if ((GET_RACE(d->character) == RACE_DWARF) || (GET_RACE(d->character) == RACE_TROLL))
SET_BIT(d->character->char_specials.saved.affected_by, AFF_INFRAVISION);
else if (GET_RACE(d->character) != RACE_HUMAN)
SET_BIT(d->character->char_specials.saved.affected_by, AFF_LOW_LIGHT);
look_at_room(d->character, 0);
if (PRF_FLAGGED(d->character, PRF_MSP) && world[d->character->in_room].msp_trigger)
send_to_char(d->character, "!!%s\r\n", world[d->character->in_room].msp_trigger);
if (has_mail(GET_IDNUM(d->character)))
send_to_char("You have mail waiting.\r\n", d->character);
if (load_result == 2) { /* rented items lost */
send_to_char("\r\n\007You could not afford your rent!\r\n"
"Your possessions have been donated to the Salvation Army!\r\n", d->character);
}
d->prompt_mode = 1;
/* affect total to make cyberware update stats */
affect_total(d->character);
break;
case '2':
SEND_TO_Q("Enter the text you'd like others to see when they look at you.\r\n", d);
SEND_TO_Q("Terminate with a '@' on a new line.\r\n", d);
if (d->character->player.description) {
SEND_TO_Q("Old description:\r\n", d);
SEND_TO_Q(d->character->player.description, d);
delete [] d->character->player.description;
d->character->player.description = NULL;
}
d->str = &d->character->player.description;
d->max_str = EXDSCR_LENGTH;
STATE(d) = CON_EXDESC;
break;
case '3':
page_string(d, background, 0);
STATE(d) = CON_RMOTD;
break;
case '4':
display_rent_status(d);
SEND_TO_Q(MENU, d);
break;
case '5':
SEND_TO_Q("\r\nEnter your old password: ", d);
echo_off(d);
STATE(d) = CON_CHPWD_GETOLD;
break;
case '6':
SEND_TO_Q("\r\nEnter your password for verification: ", d);
echo_off(d);
STATE(d) = CON_DELCNF1;
break;
default:
SEND_TO_Q("\r\nThat's not a menu choice!\r\n", d);
SEND_TO_Q(MENU, d);
break;
}
break;
case CON_CHPWD_GETOLD:
case CON_QGETOLDPW:
if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) {
echo_on(d);
SEND_TO_Q("\r\nIncorrect password.\r\n", d);
if (STATE(d) == CON_CHPWD_GETOLD) {
SEND_TO_Q(MENU, d);
STATE(d) = CON_MENU;
} else {
SEND_TO_Q(QMENU, d);
STATE(d) = CON_QMENU;
}
return;
} else {
SEND_TO_Q("\r\nEnter a new password: ", d);
if (STATE(d) == CON_CHPWD_GETOLD)
STATE(d) = CON_CHPWD_GETNEW;
else STATE(d) = CON_QGETNEWPW;
return;
}
break;
case CON_DELCNF1:
case CON_QDELCONF1:
echo_on(d);
if (strncmp(CRYPT(arg, GET_PASSWD(d->character)), GET_PASSWD(d->character), MAX_PWD_LENGTH)) {
SEND_TO_Q("\r\nIncorrect password.\r\n", d);
if (STATE(d) == CON_DELCNF1) {
SEND_TO_Q(MENU, d);
STATE(d) = CON_MENU;
} else {
SEND_TO_Q(QMENU, d);
STATE(d) = CON_QMENU;
}
} else {
SEND_TO_Q("\r\nYOU ARE ABOUT TO DELETE THIS CHARACTER PERMANENTLY.\r\n"
"ARE YOU ABSOLUTELY SURE?\r\n\r\n"
"Please type \"yes\" to confirm: ", d);
if (STATE(d) == CON_DELCNF1)
STATE(d) = CON_DELCNF2;
else STATE(d) = CON_QDELCONF2;
}
break;
case CON_DELCNF2:
case CON_QDELCONF2:
if (!strcmp(arg, "yes") || !strcmp(arg, "YES")) {
if (PLR_FLAGGED(d->character, PLR_FROZEN)) {
SEND_TO_Q("You try to kill yourself, but the ice stops you.\r\n", d);
SEND_TO_Q("Character not deleted.\r\n\r\n", d);
STATE(d) = CON_CLOSE;
return;
}
if (!access_level(d->character, LVL_ADVISOR))
SET_BIT(PLR_FLAGS(d->character), PLR_DELETED);
save_char(d->character, NOWHERE);
Crash_delete_file(GET_NAME(d->character));
sprintf(buf, "Character '%s' deleted!\r\nGoodbye.\r\n", GET_NAME(d->character));
SEND_TO_Q(buf, d);
sprintf(buf, "%s (lev %d) has self-deleted.", GET_NAME(d->character), GET_LEVEL(d->character));
mudlog(buf, d->character, LOG_MISCLOG, TRUE);
STATE(d) = CON_CLOSE;
return;
} else {
SEND_TO_Q("\r\nCharacter not deleted.\r\n", d);
if (STATE(d) == CON_DELCNF2) {
SEND_TO_Q(MENU, d);
STATE(d) = CON_MENU;
} else {
SEND_TO_Q(QMENU, d);
STATE(d) = CON_QMENU;
}
}
break;
case CON_QMENU: /* get selection from main quit menu */
switch (*arg) {
case '0':
/* save them so they won't lose their cyberware */
if ((IS_SET(PLR_FLAGS(d->character), PLR_JUST_DIED)))
REMOVE_BIT(PLR_FLAGS(d->character), PLR_JUST_DIED);
close_socket(d);
break;
case '1':
display_rent_status(d);
SEND_TO_Q(QMENU, d);
break;
case '2':
SEND_TO_Q("\r\nEnter your old password: ", d);
echo_off(d);
STATE(d) = CON_QGETOLDPW;
break;
case '3':
SEND_TO_Q("\r\nEnter your password for verification: ", d);
echo_off(d);
STATE(d) = CON_QDELCONF1;
break;
default:
SEND_TO_Q("\r\nThat's not a menu choice!\r\n", d);
SEND_TO_Q(QMENU, d);
break;
}
break;
case CON_CLOSE:
close_socket(d);
break;
// case CON_SPELL_CREATE:
// /* sent to mag_create.c for the menu system to make spells */
// mag_menu_system(d, arg);
// break;
case CON_IDCONING:
case CON_IDCONED:
case CON_IDREADING:
case CON_IDREAD:
case CON_ASKNAME:
break;
default:
log("SYSERR: Nanny: illegal state of con'ness; closing connection");
close_socket(d);
break;
}
}