# include <config.h>
# include "/dgd/lib/privilege.h"
# undef status
# define C_CONTROL 21
# define C_IF 1
# define C_IFNOT 2
# define C_LAND 3
# define C_LOR 4
# define C_WHILE 5
# define C_DO 6
# define C_PROGN 7
# define C_ASSIGN 8
# define C_PLUSEQ 9
# define C_MINEQ 10
# define C_MULTEQ 11
# define C_DIVEQ 12
# define C_MODEQ 13
# define C_LSHIFTEQ 14
# define C_RSHIFTEQ 15
# define C_ANDEQ 16
# define C_XOREQ 17
# define C_OREQ 18
# define C_PLUSPLUS 19
# define C_MINMIN 20
# define C_SSCANF 21
# define C_INDEX 22
# define C_RANGE 23
# define C_CALL_OTHER 24
# define C_NOT 25
# define C_LNOT 26
# define C_NEGATE 27
# define C_MULT 28
# define C_DIV 29
# define C_MOD 30
# define C_PLUS 31
# define C_MIN 32
# define C_LSHIFT 33
# define C_RSHIFT 34
# define C_LESS 35
# define C_LESSEQ 36
# define C_GREATER 37
# define C_GREATEREQ 38
# define C_EQ 39
# define C_NOTEQ 40
# define C_AND 41
# define C_XOR 42
# define C_OR 43
# define C_QUOTE 44
# define C_ADD_ACTION 45
# define C_ADD_VERB 46
# define C_ADD_WORTH 47
# define C_ALL_INVENTORY 48
# define C_ALLOCATE 49
# define C_APPLY 50
# define C_CALL_OUT 51
# define C_CALL_TRACE 52
# define C_CAPITALIZE 53
# define C_CAT 54
# define C_CINDENT 55
# define C_CLEAR_BIT 56
# define C_CLONE_OBJECT 57
# define C_CLOSUREP 58
# define C_COMMAND 59
# define C_CREATE_WIZARD 60
# define C_CREATOR 61
# define C_CRYPT 62
# define C_CTIME 63
# define C_DEEP_INVENTORY 64
# define C_DESTRUCT 65
# define C_DISABLE_COMMANDS 66
# define C_ENABLE_COMMANDS 67
# define C_ENVIRONMENT 68
# define C_ERROR 69
# define C_EXEC 70
# define C_EXPLODE 71
# define C_FILE_NAME 72
# define C_FILE_SIZE 73
# define C_FILTER_ARRAY 74
# define C_FILTER_MAPPING 75
# define C_FIND_CALL_OUT 76
# define C_FIND_LIVING 77
# define C_FIND_OBJECT 78
# define C_FIND_PLAYER 79
# define C_FIRST_INVENTORY 80
# define C_FUNCTION_EXISTS 81
# define C_GET_DIR 82
# define C_GET_EXEC_COST 83
# define C_IMPLODE 84
# define C_INTERACTIVE 85
# define C_INTP 86
# define C_LAMBDA 87
# define C_LIVING 88
# define C_LOCALCMD 89
# define C_LOG_FILE 90
# define C_LOWER_CASE 91
# define C_LS 92
# define C_M_DELETE 93
# define C_M_INDICES 94
# define C_M_SIZEOF 95
# define C_M_VALUES 96
# define C_MAP_ARRAY 97
# define C_MAP_MAPPING 98
# define C_MAPPINGP 99
# define C_MEMBER_ARRAY 100
# define C_MKDIR 101
# define C_MKMAPPING 102
# define C_MOVE_OBJECT 103
# define C_NEXT_INVENTORY 104
# define C_NOTIFY_FAIL 105
# define C_OBJECTP 106
# define C_PARSE_STRING 107
# define C_POINTERP 108
# define C_PRESENT 109
# define C_PREVIOUS_OBJECT 110
# define C_QUERY_HOST_NAME 111
# define C_QUERY_IDLE 112
# define C_QUERY_IP_NAME 113
# define C_QUERY_IP_NUMBER 114
# define C_QUERY_LOAD_AVERAGE 115
# define C_QUERY_SNOOP 116
# define C_QUERY_VERB 117
# define C_RANDOM 118
# define C_READ_BYTES 119
# define C_READ_FILE 120
# define C_REMOVE_CALL_OUT 121
# define C_RENAME 122
# define C_RESTORE_OBJECT 123
# define C_RM 124
# define C_RMDIR 125
# define C_SAVE_OBJECT 126
# define C_SAY 127
# define C_SET_BIT 128
# define C_SET_HEART_BEAT 129
# define C_SET_LIVING_NAME 130
# define C_SET_THIS_PLAYER 131
# define C_SHOUT 132
# define C_SHUTDOWN 133
# define C_SIZEOF 134
# define C_SNOOP 135
# define C_SORT_ARRAY 136
# define C_STATUS 137
# define C_STRINGP 138
# define C_STRLEN 139
# define C_SWAPOUT 140
# define C_TAIL 141
# define C_TELL_OBJECT 142
# define C_TELL_ROOM 143
# define C_TEST_BIT 144
# define C_THIS_OBJECT 145
# define C_THIS_PLAYER 146
# define C_TIME 147
# define C_TRANSFER 148
# define C_UNIQUE_ARRAY 149
# define C_USERS 150
# define C_VERSION 151
# define C_WIZLIST 152
# define C_WRITE 153
# define C_WRITE_BYTES 154
# define C_WRITE_FILE 155
# define MINMAX(min, max) ((min) | ((max) << 8))
# define MIN(c) (minmax[c - 1] & 0xff)
# define MAX(c) (minmax[c - 1] >> 8)
object command_giver; /* the current player */
string notify_mesg; /* current notify_fail mesg */
string verb; /* the current verb */
mapping players; /* player mapping */
mapping monsters; /* monster mapping */
mapping objects; /* objects mapping */
mapping heart_beats; /* heart_beats mapping */
mapping call_outs; /* call_outs mapping */
mapping codes; /* function to code */
int *minmax; /* min & max # of arguments for functions */
static void reset(int arg)
{
int i;
if (players == 0) {
players = ([ ]);
monsters = ([ ]);
heart_beats = ([ ]);
call_outs = ([ ]);
codes = ([
"?" : C_IF,
"?!" : C_IFNOT,
"&&" : C_LAND,
"||" : C_LOR,
"while" : C_WHILE,
"do" : C_DO,
"," : C_PROGN,
"=" : C_ASSIGN,
"+=" : C_PLUSEQ,
"-=" : C_MINEQ,
"*=" : C_MULTEQ,
"/=" : C_DIVEQ,
"%=" : C_MODEQ,
"<<=" : C_LSHIFTEQ,
">>=" : C_RSHIFTEQ,
"&=" : C_ANDEQ,
"^=" : C_XOREQ,
"|=" : C_OREQ,
"++" : C_PLUSPLUS,
"--" : C_MINMIN,
"sscanf" : C_SSCANF,
"[" : C_INDEX,
"[.." : C_RANGE,
"->" : C_CALL_OTHER,
"~" : C_NOT,
"!" : C_LNOT,
"negate" : C_NEGATE,
"*" : C_MULT,
"/" : C_DIV,
"%" : C_MOD,
"+" : C_PLUS,
"-" : C_MIN,
"<<" : C_LSHIFT,
">>" : C_RSHIFT,
"<" : C_LESS,
"<=" : C_LESSEQ,
">" : C_GREATER,
">=" : C_GREATEREQ,
"==" : C_EQ,
"!=" : C_NOTEQ,
"&" : C_AND,
"^" : C_XOR,
"|" : C_OR,
"'" : C_QUOTE,
"add_action" : C_ADD_ACTION,
"add_verb" : C_ADD_VERB,
"add_worth" : C_ADD_WORTH,
"all_inventory" : C_ALL_INVENTORY,
"allocate" : C_ALLOCATE,
"apply" : C_APPLY,
"call_other" : C_CALL_OTHER,
"call_out" : C_CALL_OUT,
"call_trace" : C_CALL_TRACE,
"capitalize" : C_CAPITALIZE,
"cat" : C_CAT,
"cindent" : C_CINDENT,
"clear_bit" : C_CLEAR_BIT,
"clone_object" : C_CLONE_OBJECT,
"closurep" : C_CLOSUREP,
"command" : C_COMMAND,
"create_wizard" : C_CREATE_WIZARD,
"creator" : C_CREATOR,
"crypt" : C_CRYPT,
"ctime" : C_CTIME,
"deep_inventory" : C_DEEP_INVENTORY,
"destruct" : C_DESTRUCT,
"disable_commands": C_DISABLE_COMMANDS,
"enable_commands" : C_ENABLE_COMMANDS,
"environment" : C_ENVIRONMENT,
"error" : C_ERROR,
"exec" : C_EXEC,
"explode" : C_EXPLODE,
"file_name" : C_FILE_NAME,
"file_size" : C_FILE_SIZE,
"filter_array" : C_FILTER_ARRAY,
"filter_mapping" : C_FILTER_MAPPING,
"find_call_out" : C_FIND_CALL_OUT,
"find_living" : C_FIND_LIVING,
"find_object" : C_FIND_OBJECT,
"find_player" : C_FIND_PLAYER,
"first_inventory" : C_FIRST_INVENTORY,
"function_exists" : C_FUNCTION_EXISTS,
"get_dir" : C_GET_DIR,
"get_exec_cost" : C_GET_EXEC_COST,
"implode" : C_IMPLODE,
"interactive" : C_INTERACTIVE,
"intp" : C_INTP,
"lambda" : C_LAMBDA,
"living" : C_LIVING,
"localcmd" : C_LOCALCMD,
"log_file" : C_LOG_FILE,
"lower_case" : C_LOWER_CASE,
"ls" : C_LS,
"m_delete" : C_M_DELETE,
"m_indices" : C_M_INDICES,
"m_sizeof" : C_M_SIZEOF,
"m_values" : C_M_VALUES,
"map_array" : C_MAP_ARRAY,
"map_mapping" : C_MAP_MAPPING,
"mappingp" : C_MAPPINGP,
"member_array" : C_MEMBER_ARRAY,
"mkdir" : C_MKDIR,
"mkmapping" : C_MKMAPPING,
"move_object" : C_MOVE_OBJECT,
"next_inventory" : C_NEXT_INVENTORY,
"notify_fail" : C_NOTIFY_FAIL,
"objectp" : C_OBJECTP,
"parse_string" : C_PARSE_STRING,
"pointerp" : C_POINTERP,
"present" : C_PRESENT,
"previous_object" : C_PREVIOUS_OBJECT,
"query_host_name" : C_QUERY_HOST_NAME,
"query_idle" : C_QUERY_IDLE,
"query_ip_name" : C_QUERY_IP_NAME,
"query_ip_number" : C_QUERY_IP_NUMBER,
"query_load_average":C_QUERY_LOAD_AVERAGE,
"query_snoop" : C_QUERY_SNOOP,
"query_verb" : C_QUERY_VERB,
"random" : C_RANDOM,
"read_bytes" : C_READ_BYTES,
"read_file" : C_READ_FILE,
"remove_call_out" : C_REMOVE_CALL_OUT,
"rename" : C_RENAME,
"restore_object" : C_RESTORE_OBJECT,
"rm" : C_RM,
"rmdir" : C_RMDIR,
"save_object" : C_SAVE_OBJECT,
"say" : C_SAY,
"set_bit" : C_SET_BIT,
"set_heart_beat" : C_SET_HEART_BEAT,
"set_living_name" : C_SET_LIVING_NAME,
"set_this_player" : C_SET_THIS_PLAYER,
"shout" : C_SHOUT,
"shutdown" : C_SHUTDOWN,
"sizeof" : C_SIZEOF,
"snoop" : C_SNOOP,
"sort_array" : C_SORT_ARRAY,
"status" : C_STATUS,
"stringp" : C_STRINGP,
"strlen" : C_STRLEN,
"swapout" : C_SWAPOUT,
"tail" : C_TAIL,
"tell_object" : C_TELL_OBJECT,
"tell_room" : C_TELL_ROOM,
"test_bit" : C_TEST_BIT,
"this_object" : C_THIS_OBJECT,
"this_player" : C_THIS_PLAYER,
"time" : C_TIME,
"transfer" : C_TRANSFER,
"unique_array" : C_UNIQUE_ARRAY,
"users" : C_USERS,
"version" : C_VERSION,
"wizlist" : C_WIZLIST,
"write" : C_WRITE,
"write_bytes" : C_WRITE_BYTES,
"write_file" : C_WRITE_FILE,
]);
minmax = ({
MINMAX(1, 255), /* IF */
MINMAX(1, 255), /* IFNOT */
MINMAX(2, 2), /* LAND */
MINMAX(2, 2), /* LOR */
MINMAX(3, 255), /* WHILE */
MINMAX(3, 255), /* DO */
MINMAX(2, 255), /* PROGN */
MINMAX(2, 254), /* ASSIGN */
MINMAX(2, 254), /* PLUSEQ */
MINMAX(2, 254), /* MINEQ */
MINMAX(2, 254), /* MULTEQ */
MINMAX(2, 254), /* DIVEQ */
MINMAX(2, 254), /* MODEQ */
MINMAX(2, 254), /* LSHIFTEQ */
MINMAX(2, 254), /* RSHIFTEQ */
MINMAX(2, 254), /* ANDEQ */
MINMAX(2, 254), /* XOREQ */
MINMAX(2, 254), /* OREQ */
MINMAX(1, 255), /* PLUSPLUS */
MINMAX(1, 255), /* MINMIN */
MINMAX(2, 255), /* SSCANF */
MINMAX(2, 2), /* INDEX */
MINMAX(3, 3), /* RANGE */
MINMAX(2, 255), /* CALL_OTHER */
MINMAX(1, 1), /* NOT */
MINMAX(1, 1), /* LNOT */
MINMAX(1, 1), /* NEGATE */
MINMAX(2, 2), /* MULT */
MINMAX(2, 2), /* DIV */
MINMAX(2, 2), /* MOD */
MINMAX(2, 2), /* PLUS */
MINMAX(2, 2), /* MIN */
MINMAX(2, 2), /* LSHIFT */
MINMAX(2, 2), /* RSHIFT */
MINMAX(2, 2), /* LESS */
MINMAX(2, 2), /* LESSEQ */
MINMAX(2, 2), /* GREATER */
MINMAX(2, 2), /* GREATEREQ */
MINMAX(2, 2), /* EQ */
MINMAX(2, 2), /* NOTEQ */
MINMAX(2, 2), /* AND */
MINMAX(2, 2), /* XOR */
MINMAX(2, 2), /* OR */
MINMAX(1, 1), /* QUOTE */
MINMAX(1, 3), /* ADD_ACTION */
MINMAX(1, 1), /* ADD_VERB */
MINMAX(1, 2), /* ADD_WORTH */
MINMAX(0, 1), /* ALL_INVENTORY */
MINMAX(1, 1), /* ALLOCATE */
MINMAX(1, 255), /* APPLY */
MINMAX(2, 255), /* CALL_OUT */
MINMAX(0, 0), /* CALL_TRACE */
MINMAX(1, 1), /* CAPITALIZE */
MINMAX(1, 3), /* CAT */
MINMAX(1, 1), /* CINDENT */
MINMAX(2, 2), /* CLEAR_BIT */
MINMAX(1, 1), /* CLONE_OBJECT */
MINMAX(1, 1), /* CLOSUREP */
MINMAX(1, 2), /* COMMAND */
MINMAX(1, 2), /* CREATE_WIZARD */
MINMAX(1, 1), /* CREATOR */
MINMAX(1, 2), /* CRYPT */
MINMAX(1, 1), /* CTIME */
MINMAX(1, 1), /* DEEP_INVENTORY */
MINMAX(1, 1), /* DESTRUCT */
MINMAX(0, 0), /* DISABLE_COMMANDS */
MINMAX(0, 0), /* ENABLE_COMMANDS */
MINMAX(0, 1), /* ENVIRONMENT */
MINMAX(1, 1), /* ERROR */
MINMAX(2, 2), /* EXEC */
MINMAX(2, 2), /* EXPLODE */
MINMAX(1, 1), /* FILE_NAME */
MINMAX(1, 1), /* FILE_SIZE */
MINMAX(3, 4), /* FILTER_ARRAY */
MINMAX(3, 4), /* FILTER_MAPPING */
MINMAX(1, 1), /* FIND_CALL_OUT */
MINMAX(1, 1), /* FIND_LIVING */
MINMAX(1, 1), /* FIND_OBJECT */
MINMAX(1, 1), /* FIND_PLAYER */
MINMAX(0, 1), /* FIRST_INVENTORY */
MINMAX(2, 2), /* FUNCTION_EXISTS */
MINMAX(1, 1), /* GET_DIR */
MINMAX(0, 0), /* GET_EXEC_COST */
MINMAX(2, 2), /* IMPLODE */
MINMAX(0, 1), /* INTERACTIVE */
MINMAX(1, 1), /* INTP */
MINMAX(1, 2), /* LAMBDA */
MINMAX(1, 1), /* LIVING */
MINMAX(0, 0), /* LOCALCMD */
MINMAX(2, 2), /* LOG_FILE */
MINMAX(1, 1), /* LOWER_CASE */
MINMAX(1, 1), /* LS */
MINMAX(2, 2), /* M_DELETE */
MINMAX(1, 1), /* M_INDICES */
MINMAX(1, 1), /* M_SIZEOF */
MINMAX(1, 1), /* M_VALUES */
MINMAX(3, 4), /* MAP_ARRAY */
MINMAX(3, 4), /* MAP_MAPPING */
MINMAX(1, 1), /* MAPPINGP */
MINMAX(2, 2), /* MEMBER_ARRAY */
MINMAX(1, 1), /* MKDIR */
MINMAX(2, 2), /* MKMAPPING */
MINMAX(2, 2), /* MOVE_OBJECT */
MINMAX(0, 1), /* NEXT_INVENTORY */
MINMAX(1, 1), /* NOTIFY_FAIL */
MINMAX(1, 1), /* OBJECTP */
MINMAX(2, 2), /* PARSE_STRING */
MINMAX(1, 1), /* POINTERP */
MINMAX(1, 2), /* PRESENT */
MINMAX(0, 0), /* PREVIOUS_OBJECT */
MINMAX(0, 0), /* QUERY_HOST_NAME */
MINMAX(1, 1), /* QUERY_IDLE */
MINMAX(0, 1), /* QUERY_IP_NAME */
MINMAX(0, 1), /* QUERY_IP_NUMBER */
MINMAX(0, 0), /* QUERY_LOAD_AVERAGE */
MINMAX(1, 1), /* QUERY_SNOOP */
MINMAX(0, 0), /* QUERY_VERB */
MINMAX(1, 1), /* RANDOM */
MINMAX(1, 3), /* READ_BYTES */
MINMAX(1, 3), /* READ_FILE */
MINMAX(1, 1), /* REMOVE_CALL_OUT */
MINMAX(2, 2), /* RENAME */
MINMAX(1, 1), /* RESTORE_OBJECT */
MINMAX(1, 1), /* RM */
MINMAX(1, 1), /* RMDIR */
MINMAX(1, 1), /* SAVE_OBJECT */
MINMAX(1, 2), /* SAY */
MINMAX(2, 2), /* SET_BIT */
MINMAX(1, 1), /* SET_HEART_BEAT */
MINMAX(1, 1), /* SET_LIVING_NAME */
MINMAX(1, 1), /* SET_THIS_PLAYER */
MINMAX(1, 1), /* SHOUT */
MINMAX(0, 0), /* SHUTDOWN */
MINMAX(1, 1), /* SIZEOF */
MINMAX(1, 1), /* SNOOP */
MINMAX(2, 3), /* SORT_ARRAY */
MINMAX(0, 1), /* STATUS */
MINMAX(1, 1), /* STRINGP */
MINMAX(1, 1), /* STRLEN */
MINMAX(0, 1), /* SWAPOUT */
MINMAX(1, 1), /* TAIL */
MINMAX(2, 2), /* TELL_OBJECT */
MINMAX(2, 3), /* TELL_ROOM */
MINMAX(2, 2), /* TEST_BIT */
MINMAX(0, 0), /* THIS_OBJECT */
MINMAX(0, 1), /* THIS_PLAYER */
MINMAX(0, 0), /* TIME */
MINMAX(2, 2), /* TRANSFER */
MINMAX(2, 3), /* UNIQUE_ARRAY */
MINMAX(0, 0), /* USERS */
MINMAX(0, 0), /* VERSION */
MINMAX(0, 1), /* WIZLIST */
MINMAX(1, 1), /* WRITE */
MINMAX(3, 3), /* WRITE_BYTES */
MINMAX(2, 2), /* WRITE_FILE */
});
}
}
/*
* NAME: set_this_player()
* DESCRIPTION: set the current player
*/
void set_this_player(object player)
{
command_giver = player;
}
/*
* NAME: query_this_player()
* DESCRIPTION: return the current player, or interactive user
*/
object query_this_player()
{
return command_giver;
}
/*
* NAME: set_verb()
* DESCRIPTION: set the current verb
*/
void set_verb(string str)
{
if (PRIVILEGED()) {
verb = str;
}
}
/*
* NAME: query_verb()
* DESCRIPTION: return the current verb
*/
string query_verb()
{
return verb;
}
/*
* NAME: set_living_name()
* DESCRIPTION: set the living name of the current object
*/
void set_living_name(string name)
{
object obj, *list;
if (PRIVILEGED()) {
obj = previous_object();
if (living(obj)) {
if (interactive(obj) != 0) {
players[name] = obj;
} else {
list = monsters[name];
if (list == 0) {
list = ({ obj });
} else {
list = ({ obj }) + (list - ({ 0 }));
}
monsters[name] = list;
}
}
}
}
/*
* NAME: query_find_player()
* DESCRIPTION: find a player by name
*/
object query_find_player(string name)
{
object obj;
obj = players[name];
if (obj != 0 && living(obj)) {
return obj;
}
return 0;
}
/*
* NAME: query_find_living()
* DESCRIPTION: find a living object by name
*/
object query_find_living(string name)
{
object obj, *list;
int i, sz;
obj = query_find_player(name);
if (obj != 0) {
return obj;
}
list = monsters[name];
if (list != 0 && sizeof(list) != 0) {
list -= ({ 0 });
monsters[name] = list;
for (i = 0, sz = sizeof(list); i < sz; i++) {
if (living(obj=list[i])) {
return obj;
}
}
}
return 0;
}
/*
* NAME: add_object()
* DESCRIPTION: add an object
*/
void add_object()
{
if (PRIVILEGED()) {
if (objects == 0) {
objects = ([ ]);
}
objects[creator(previous_object())]++;
}
}
/*
* NAME: del_object()
* DESCRIPTION: delete an object
*/
void del_object()
{
if (PRIVILEGED()) {
objects[creator(previous_object())]--;
}
}
/*
* NAME: add_call_out()
* DESCRIPTION: add a call_out
*/
void add_call_out(int delay)
{
if (PRIVILEGED()) {
string creator;
call_outs[creator = creator(previous_object())]++;
call_out("fix_player", delay, creator, command_giver);
}
}
/*
* NAME: fix_player()
* DESCRIPTION: set this_player() in preparation of the next call_out
*/
static void fix_player(string creator, object player)
{
call_outs[creator]--;
command_giver = player;
}
/*
* NAME: add_heart_beat()
* DESCRIPTION: add a heart_beat
*/
void add_heart_beat()
{
if (PRIVILEGED()) {
heart_beats[creator(previous_object())]++;
}
}
/*
* NAME: del_heart_beat()
* DESCRIPTION: delete a heart_beat
*/
void del_heart_beat()
{
if (PRIVILEGED()) {
heart_beats[creator(previous_object())]--;
}
}
/*
* NAME: show_wiz_list()
* DESCRIPTION: show the wizlist
*/
void show_wiz_list()
{
string *wizards, name;
int i, sz;
write("name\t objects hbeats callouts\n" +
"-------------------------------------\n");
wizards = map_indices(objects);
for (i = 0, sz = sizeof(wizards); i < sz; i++) {
if (wizards[i] == 0) {
name = "Mudlib";
} else {
name = wizards[i];
}
if (strlen(name) < 8) {
name += "\t";
}
write(name + "\t" + objects[wizards[i]] + "\t" +
heart_beats[wizards[i]] + "\t" + call_outs[wizards[i]] + "\n");
}
}
/*
* NAME: ident()
* DESCRIPTION: return 1 if the argument is an identifier, 0 otherwise
*/
private int ident(mixed arg)
{
int i, len, c;
if (!stringp(arg)) {
return 0;
}
len = strlen(arg);
if (len == 0) {
return 0;
}
c = arg[0];
if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') {
return 0;
}
for (i = 1; i < len; i++) {
c = arg[i];
if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_' &&
(c < '0' || c > '9')) {
return 0;
}
}
return 1;
}
/*
* NAME: eval()
* DESCRIPTION: evaluate an expression
*/
mapping eval(mixed expr, mapping vars)
{
mixed code, *args, cond, body;
int nargs, i;
mapping old;
if (stringp(expr)) {
/* possibly a variable */
vars[1] = (strlen(expr) > 1 && expr[0] == '\'') ? vars[expr] : expr;
return vars;
} else if (!arrayp(expr) || sizeof(expr) == 0 || !closurep(expr[0])) {
/* ordinary expression */
vars[1] = expr;
return vars;
}
/* closure */
args = expr[1 ..];
expr = expr[0];
code = expr[1];
if (sizeof(expr) == 2) {
/*
* short format
*/
if ((nargs=sizeof(args)) < MIN(code)) {
error("Too few arguments for closure");
} else if (nargs > MAX(code)) {
error("Too many arguments for closure");
}
} else {
/*
* long format
*/
nargs = expr[2];
if (nargs != sizeof(args)) {
if (nargs < sizeof(args)) {
error("Too many arguments for closure");
} else {
error("Too few arguments for closure");
}
}
/* bind parameters */
body = ([ ]);
for (i = 0; i < nargs; i++) {
body[expr[i + 3]] = (vars=eval(args[i], vars))[1];
}
old = vars & expr[3 .. nargs + 2]; /* old parameter values */
vars += body; /* use new parameter values */
args = expr[nargs + 3 ..]; /* closure arguments */
expr = expr[3 .. nargs + 2]; /* parameter names */
nargs = sizeof(args);
/* deal with special codes */
switch (code) {
case C_IF:
for (i = 1; i < nargs; i += 2) {
if ((vars=eval(args[i - 1], vars))[1]) {
return (eval(args[i], vars) - expr) + old;
}
}
return (eval(args[i - 1], vars) - expr) + old;
case C_IFNOT:
for (i = 1; i < nargs; i += 2) {
if (!(vars=eval(args[i - 1], vars))[1]) {
return (eval(args[i], vars) - expr) + old;
}
}
return (eval(args[i - 1], vars) - expr) + old;
case C_LAND:
if (!(vars=eval(args[0], vars))[1]) {
vars[1] = 0;
return (vars - expr) + old;
}
vars = eval(args[1], vars);
vars[1] = !!vars[1];
return (vars - expr) + old;
case C_LOR:
if ((vars=eval(args[0], vars))[1]) {
vars[1] = 1;
return (vars - expr) + old;
}
vars = eval(args[1], vars);
vars[1] = !!vars[1];
return (vars - expr) + old;
case C_WHILE:
cond = args[0];
body = args[2];
while ((vars=eval(cond, vars))[1]) {
vars = eval(body, vars);
}
return (eval(args[1], vars) - expr) + old;
case C_DO:
body = args[0];
cond = args[1];
do {
vars = eval(body, vars);
} while ((vars=eval(cond, vars))[1]);
return (eval(args[2], vars) - expr) + old;
case C_ASSIGN:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] = vars[1];
}
return (vars - expr) + old;
case C_PLUSEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] += vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_MINEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] -= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_MULTEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] *= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_DIVEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] /= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_MODEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] %= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_LSHIFTEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] <<= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_RSHIFTEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] >>= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_ANDEQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] &= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_XOREQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] ^= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_OREQ:
for (i = 0; i < nargs; i += 2) {
vars = eval(args[i + 1], vars);
vars[args[i]] |= vars[1];
}
vars[1] = vars[args[i - 2]];
return (vars - expr) + old;
case C_PLUSPLUS:
for (i = nargs; i > 0; ) {
vars[args[--i]]++;
}
vars[1] = vars[args[nargs - 1]];
return (vars - expr) + old;
case C_MINMIN:
for (i = nargs; i > 0; ) {
--vars[args[--i]];
}
vars[1] = vars[args[nargs - 1]];
return (vars - expr) + old;
case C_SSCANF:
args[0] = (vars=eval(args[0], vars))[1];
args[1] = (vars=eval(args[1], vars))[1];
body = args[2 ..];
for (i = vars[1] = sscanf(args...); i > 0; ) {
--i;
vars[body[i]] = args[i + 2];
}
return (vars - expr) + old;
}
/*
* not a special code: evaluate all arguments
*/
for (i = 0; i < nargs; i++) {
args[i] = (vars=eval(args[i], vars))[1];
}
vars = (vars - expr) + old; /* remove parameters, add old values */
}
if (stringp(code)) {
/* local function */
vars[1] = call_other(previous_object(), code, args...);
return vars;
}
vars[1] = 0;
switch (code) {
case C_PROGN: vars[1] = args[nargs - 1];
break;
case C_INDEX: vars[1] = args[0][args[1]];
break;
case C_RANGE: vars[1] = args[0][args[1] .. args[2]];
break;
case C_CALL_OTHER: vars[1] = call_other(args...);
break;
case C_NOT: vars[1] = ~args[0];
break;
case C_LNOT: vars[1] = !args[0];
break;
case C_NEGATE: vars[1] = -args[0];
break;
case C_MULT: vars[1] = args[0] * args[1];
break;
case C_DIV: vars[1] = args[0] / args[1];
break;
case C_MOD: vars[1] = args[0] % args[1];
break;
case C_PLUS: vars[1] = args[0] + args[1];
break;
case C_MIN: vars[1] = args[0] - args[1];
break;
case C_LSHIFT: vars[1] = args[0] << args[1];
break;
case C_RSHIFT: vars[1] = args[0] >> args[1];
break;
case C_LESS: vars[1] = args[0] < args[1];
break;
case C_LESSEQ: vars[1] = args[0] <= args[1];
break;
case C_GREATER: vars[1] = args[0] > args[1];
break;
case C_GREATEREQ: vars[1] = args[0] >= args[1];
break;
case C_EQ: vars[1] = args[0] == args[1];
break;
case C_NOTEQ: vars[1] = args[0] != args[1];
break;
case C_AND: vars[1] = args[0] & args[1];
break;
case C_XOR: vars[1] = args[0] ^ args[1];
break;
case C_OR: vars[1] = args[0] | args[1];
break;
case C_QUOTE: vars[1] = args[0];
break;
case C_ADD_ACTION: add_action(args...);
break;
case C_ADD_VERB: add_verb(args[0]);
break;
case C_ADD_WORTH: if (nargs == 1) {
add_worth(args[0], previous_object(1));
} else {
add_worth(args[0], args[1]);
}
break;
case C_ALL_INVENTORY: if (nargs == 0) {
vars[1] = all_inventory(previous_object());
} else {
vars[1] = all_inventory(args[0]);
}
break;
case C_ALLOCATE: vars[1] = allocate(args[0]);
break;
case C_APPLY: vars[1] = eval(args, vars);
break;
case C_CALL_OUT: call_out(args...);
break;
case C_CALL_TRACE: vars[1] = call_trace();
break;
case C_CAPITALIZE: vars[1] = capitalize(args[0]);
break;
case C_CAT: vars[1] = cat(args...);
break;
case C_CINDENT: vars[1] = cindent(args[0]);
break;
case C_CLEAR_BIT: vars[1] = clear_bit(args[0], args[1]);
break;
case C_CLONE_OBJECT: vars[1] = clone_object(args[0]);
break;
case C_CLOSUREP: vars[1] = closurep(args[0]);
break;
case C_COMMAND: if (nargs == 1) {
vars[1] = command(args[0],
previous_object());
} else {
vars[1] = command(args[0], args[1]);
}
break;
case C_CREATE_WIZARD: vars[1] = create_wizard(args...);
break;
case C_CREATOR: vars[1] = creator(args[0]);
break;
case C_CRYPT: vars[1] = crypt(args...);
break;
case C_CTIME: vars[1] = ctime(args[0]);
break;
case C_DEEP_INVENTORY: vars[1] = deep_inventory(args[0]);
break;
case C_DESTRUCT: destruct(args[0]);
break;
case C_DISABLE_COMMANDS: disable_commands();
break;
case C_ENABLE_COMMANDS: enable_commands();
break;
case C_ENVIRONMENT: if (nargs == 0) {
vars[1] = environment(previous_object());
} else {
vars[1] = environment(args[0]);
}
break;
case C_ERROR: error(args[0]);
case C_EXEC: vars[1] = exec(args[0], args[1]);
break;
case C_EXPLODE: vars[1] = explode(args[0], args[1]);
break;
case C_FILE_NAME: vars[1] = file_name(args[0]);
break;
case C_FILE_SIZE: vars[1] = file_size(args[0]);
break;
case C_FILTER_ARRAY: vars[1] = filter_array(args...);
break;
case C_FILTER_MAPPING: vars[1] = filter_mapping(args...);
break;
case C_FIND_CALL_OUT: vars[1] = find_call_out(args[0]);
break;
case C_FIND_LIVING: vars[1] = find_living(args[0]);
break;
case C_FIND_OBJECT: vars[1] = find_object(args[0]);
break;
case C_FIND_PLAYER: vars[1] = find_player(args[0]);
break;
case C_FIRST_INVENTORY: if (nargs == 0) {
vars[1] = first_inventory(previous_object());
} else {
vars[1] = first_inventory(args[0]);
}
break;
case C_FUNCTION_EXISTS: vars[1] = function_exists(args[0], args[1]);
break;
case C_GET_DIR: vars[1] = get_dir(args[0]);
break;
case C_GET_EXEC_COST: vars[1] = get_exec_cost();
break;
case C_IMPLODE: vars[1] = implode(args[0], args[1]);
break;
case C_INTERACTIVE: if (nargs == 0) {
vars[1] = interactive(previous_object());
} else {
vars[1] = interactive(args[0]);
}
break;
case C_INTP: vars[1] = intp(args[0]);
break;
case C_LAMBDA: vars[1] = lambda(args...);
break;
case C_LIVING: vars[1] = living(args[0]);
break;
case C_LOCALCMD: localcmd();
break;
case C_LOG_FILE: log_file(args[0], args[1]);
break;
case C_LOWER_CASE: vars[1] = lower_case(args[0]);
break;
case C_LS: vars[1] = ls(args[0]);
break;
case C_M_DELETE: vars[1] = m_delete(args[0], args[1]);
break;
case C_M_INDICES: vars[1] = m_indices(args[0]);
break;
case C_M_SIZEOF: vars[1] = m_sizeof(args[0]);
break;
case C_M_VALUES: vars[1] = m_values(args[0]);
break;
case C_MAP_ARRAY: vars[1] = map_array(args...);
break;
case C_MAP_MAPPING: vars[1] = map_mapping(args...);
break;
case C_MAPPINGP: vars[1] = mappingp(args[0]);
break;
case C_MEMBER_ARRAY: vars[1] = member_array(args[0], args[1]);
break;
case C_MKDIR: vars[1] = mkdir(args[0]);
break;
case C_MKMAPPING: vars[1] = mkmapping(args[0], args[1]);
break;
case C_MOVE_OBJECT: move_object(args[0], args[1]);
break;
case C_NEXT_INVENTORY: if (nargs == 0) {
vars[1] = next_inventory(previous_object());
} else {
vars[1] = next_inventory(args[0]);
}
break;
case C_NOTIFY_FAIL: notify_fail(args[0]);
break;
case C_OBJECTP: vars[1] = objectp(args[0]);
break;
case C_PARSE_STRING: vars[1] = parse_string(args[0], args[1]);
break;
case C_POINTERP: vars[1] = pointerp(args[0]);
break;
case C_PRESENT: if (nargs == 1) {
vars[1] = present(args[0],
previous_object());
} else {
vars[1] = present(args[0], args[1]);
}
break;
case C_PREVIOUS_OBJECT: vars[1] = previous_object(1);
break;
case C_QUERY_HOST_NAME: vars[1] = query_host_name();
break;
case C_QUERY_IDLE: vars[1] = query_idle(args[0]);
break;
case C_QUERY_IP_NAME: vars[1] = query_ip_name(args...);
break;
case C_QUERY_IP_NUMBER: vars[1] = query_ip_number(args...);
break;
case C_QUERY_LOAD_AVERAGE: vars[1] = query_load_average();
break;
case C_QUERY_SNOOP: vars[1] = query_snoop(args[0]);
break;
case C_QUERY_VERB: vars[1] = query_verb();
break;
case C_RANDOM: vars[1] = random(args[0]);
break;
case C_READ_BYTES: vars[1] = read_bytes(args...);
break;
case C_READ_FILE: vars[1] = read_file(args...);
break;
case C_REMOVE_CALL_OUT: vars[1] = remove_call_out(args[0]);
break;
case C_RENAME: vars[1] = rename(args[0], args[1]);
break;
case C_RESTORE_OBJECT: vars[1] = restore_object(args[0]);
break;
case C_RM: vars[1] = rm(args[0]);
break;
case C_RMDIR: vars[1] = rmdir(args[0]);
break;
case C_SAVE_OBJECT: save_object(args[0]);
break;
case C_SAY: say(args...);
break;
case C_SET_BIT: vars[1] = set_bit(args[0], args[1]);
break;
case C_SET_HEART_BEAT: vars[1] = set_heart_beat(args[0]);
break;
case C_SET_LIVING_NAME: set_living_name(args[0]);
break;
case C_SET_THIS_PLAYER: set_this_player(args[0]);
break;
case C_SHOUT: shout(args[0]);
break;
case C_SHUTDOWN: shutdown();
break;
case C_SIZEOF: vars[1] = sizeof(args[0]);
break;
case C_SNOOP: vars[1] = snoop(args[0]);
break;
case C_SORT_ARRAY: if (nargs == 2 && stringp(args[1])) {
vars[1] = sort_array(args[0], args[1],
previous_object());
} else {
vars[1] = sort_array(args...);
}
break;
case C_STATUS: vars[1] = status(args...);
break;
case C_STRINGP: vars[1] = stringp(args[0]);
break;
case C_STRLEN: vars[1] = strlen(args[0]);
break;
case C_SWAPOUT: swapout(args...);
break;
case C_TAIL: vars[1] = tail(args[0]);
break;
case C_TELL_OBJECT: tell_object(args[0], args[1]);
break;
case C_TELL_ROOM: tell_room(args...);
break;
case C_TEST_BIT: vars[1] = test_bit(args[0], args[1]);
break;
case C_THIS_OBJECT: vars[1] = previous_object();
break;
case C_THIS_PLAYER: vars[1] = this_player(args...);
break;
case C_TIME: vars[1] = time();
break;
case C_TRANSFER: vars[1] = transfer(args[0], args[1]);
break;
case C_UNIQUE_ARRAY: vars[1] = unique_array(args...);
break;
case C_USERS: vars[1] = users();
break;
case C_VERSION: vars[1] = version();
break;
case C_WIZLIST: wizlist(args...);
break;
case C_WRITE: write(args[0]);
break;
case C_WRITE_BYTES: vars[1] = write_bytes(args[0], args[1],
args[2]);
break;
case C_WRITE_FILE: vars[1] = write_file(args[0], args[1]);
break;
default: error("Unknown closure");
}
return vars;
}
/*
* NAME: compile()
* DESCRIPTION: compile a lambda expression to a closure
*/
closure compile(mixed func, mixed *def)
{
int code, i, j, nargs;
mixed arg;
if (def == 0) {
/*
* short format
*/
code = codes[func];
if (code != 0) {
if (code <= C_CONTROL) {
error("Lambda: short format only for efuns, operators and " +
"local functions");
}
func = code;
} else if (!ident(func)) {
error("Lambda: bad function");
}
return ({ LAMBDA, code });
} else {
/*
* long format
*/
for (i = 0, nargs = sizeof(func); i < nargs; i++) {
arg = func[i];
if (!stringp(arg) || strlen(arg) <= 1 || !ident(arg[1 ..])) {
error("Lambda: invalid parameter " + (i + 1));
}
for (j = 0; j < i; j++) {
if (func[j] == func[i]) {
error("Lambda: duplicate parameter");
}
}
}
code = codes[def[0]];
if (code != 0) {
i = sizeof(def) - 1;
if (i < MIN(code)) {
error("Lambda: too few arguments");
} else if (i > MAX(code)) {
error("Lambda: too many arguments");
} else {
switch (code) {
case C_IF:
case C_IFNOT:
if ((i & 1) == 0) {
error("Lambda: odd number of arguments required");
}
break;
case C_ASSIGN:
case C_PLUSEQ:
case C_MINEQ:
case C_MULTEQ:
case C_DIVEQ:
case C_MODEQ:
case C_LSHIFTEQ:
case C_RSHIFTEQ:
case C_ANDEQ:
case C_XOREQ:
case C_OREQ:
if ((i & 1) != 0) {
error("Lambda: even number of arguments required");
}
for (j = 1; j <= i; j += 2) {
arg = def[j];
if (!stringp(arg) || strlen(arg) <= 1 ||
!ident(arg[1 ..])) {
error("Lambda: invalid argument " + j);
}
}
break;
case C_PLUSPLUS:
case C_MINMIN:
for (j = 1; j <= i; j++) {
arg = def[j];
if (!stringp(arg) || strlen(arg) <= 1 ||
!ident(arg[1 ..])) {
error("Lambda: invalid argument " + j);
}
}
break;
case C_SSCANF:
for (j = 3; j <= i; j++) {
arg = def[j];
if (!stringp(arg) || strlen(arg) <= 1 ||
!ident(arg[1 ..])) {
error("Lambda: invalid argument " + j);
}
}
break;
}
}
arg = code;
} else if (!ident(arg=def[0])) {
error("Lambda: bad function");
}
return ({ LAMBDA, code, nargs }) + func + def[1 ..];
}
}
/*
* NAME: filter_array
* DESCRIPTION: filter the elements of an array
*/
varargs mixed *lambda_filter_array(mixed *arr, closure func)
{
mixed *copy, elt;
int i, j, sz;
copy = allocate(sz = sizeof(arr));
for (i = 0, j = -1; i < sz; i++) {
if (eval(({ func, elt = arr[i] }), ([ ]))[1]) {
copy[++j] = elt;
}
}
return copy[0 .. j];
}
/*
* NAME: map_array
* DESCRIPTION: map the elements of an array
*/
varargs mixed *lambda_map_array(mixed *arr, closure func)
{
mixed *copy;
int i, sz;
copy = allocate(sz = sizeof(arr));
for (i = 0; i < sz; i++) {
copy[i] = eval(({ func, arr[i] }), ([ ])[1]);
}
return copy;
}
/*
* NAME: sort_array()
* DESCRIPTION: sort an array
*/
varargs mixed *lambda_sort_array(mixed *arr, closure func)
{
mixed elt, val;
int n, i, j, size;
arr = arr[..];
for (n = 1, size = sizeof(arr); n < size; n <<= 1) ;
for (n >>= 1; n > 0; --n) {
elt = arr[n - 1];
for (i = n, j = n << 1; j <= size; i = j, j <<= 1) {
val = arr[j - 1];
if (j < size && eval(({ func, arr[j], val }), ([ ]))[1]) {
val = arr[j++];
}
if (eval(({ func, elt, val }), ([ ]))[1]) {
break;
}
arr[i - 1] = val;
}
arr[i - 1] = elt;
}
for (n = size - 1; n > 0; --n) {
elt = arr[n];
arr[n] = arr[0];
for (i = 1, j = 2; j <= n; i = j, j <<= 1) {
val = arr[j - 1];
if (j < n && eval(({ func, arr[j], val }), ([ ]))[1]) {
val = arr[j++];
}
if (eval(({ func, elt, val }), ([ ]))[1]) {
break;
}
arr[i - 1] = val;
}
arr[i - 1] = elt;
}
return arr;
}
/*
* NAME: filter_mapping()
* DESCRIPTION: filter a mapping by its values
*/
varargs mapping lambda_filter_mapping(mapping map, closure func)
{
mixed *indices, *values, value;
mapping copy;
int i, sz;
indices = map_indices(map);
values = map_values(map);
copy = ([ ]);
for (i = 0, sz = sizeof(indices); i < sz; i++) {
if (eval(({ func, value = values[i] }), ([ ]))[1]) {
copy[indices[i]] = value;
}
}
return copy;
}
/*
* NAME: map_mapping()
* DESCRIPTION: map the values of a mapping
*/
varargs mapping lambda_map_mapping(mapping map, closure func)
{
mixed *indices, *values;
mapping copy;
int i, sz;
indices = map_indices(map);
values = map_values(map);
copy = ([ ]);
for (i = 0, sz = sizeof(indices); i < sz; i++) {
copy[indices[i]] = eval(({ func, values[i] }), ([ ])[1]);
}
return copy;
}