/* ************************************************************************ * 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; } }