#include "prims.h"
#include "db.h"
#include "money.h"
/* private globals */
extern inst *p_oper1, *p_oper2, *p_oper3, *p_oper4;
extern int p_result;
extern int p_nargs;
extern dbref p_ref;
char buffer[500];
#ifdef COPYOBJ
/****************************************
* copyobj ( d -- d ) - copy an object
****************************************/
void prims_copyobj (__P_PROTO)
{
dbref newobj;
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(1);
p_oper1 = POP();
if (!valid_object(p_oper1)) abort_interp("Invalid object.");
p_ref = p_oper1->data.objref;
if (Typeof(p_ref) != TYPE_THING) abort_interp("Invalid object type.");
if (!fr->wizard)
{
if (!payfor(fr->euid, OBJECT_DEPOSIT(DBFETCH(p_ref)->pennies)))
sprintf(buffer, "You don't have enough %s.", PL_MONEY);
abort_interp(buffer); /* defined in money.h */
}
newobj = new_object();
*DBFETCH(newobj)= *DBFETCH(p_ref);
DBSTORE(newobj, desc, dup_string(GET_DESC(p_ref)));
DBSTORE(newobj, name, dup_string(NAME(p_ref)));
DBSTORE(newobj, succ, dup_string(GET_SUCC(p_ref)));
DBSTORE(newobj, fail, dup_string(GET_FAIL(p_ref)));
DBSTORE(newobj, drop, dup_string(GET_DROP(p_ref)));
DBSTORE(newobj, osucc, dup_string(GET_OSUCC(p_ref)));
DBSTORE(newobj, ofail, dup_string(GET_OFAIL(p_ref)));
DBSTORE(newobj, odrop, dup_string(GET_ODROP(p_ref)));
copy_prop(p_ref, newobj, access_rights(player, p_ref, program));
DBSTORE(newobj, key, copy_bool(DBFETCH(p_ref)->key));
add_backlocks_parse(newobj, DBFETCH(newobj)->key);
DBSTORE(newobj, exits, NOTHING);
add_ownerlist(newobj);
add_backlinks(newobj);
moveto(newobj, fr->euid);
DBDIRTY(newobj);
CLEAR(p_oper1);
push(arg, top, PROG_OBJECT, MIPSCAST &newobj);
}
#endif /* COPYOBJ */
int prims_recycle_checkcallers (dbref_list *drl, dbref object)
{
for (;drl;drl = drl->next)
{
if (drl->object == object) return 1;
}
return 0;
}
/****************************************
* recycle ( d -- ) recycles an object
****************************************/
void prims_recycle (__P_PROTO)
{
CHECKOP(1);
p_oper1 = POP();
if (!valid_object(p_oper1)) abort_interp("Invalid arguement.");
if (OWNER(p_oper1->data.objref) != fr->euid)
abort_interp("Permission denied.");
p_ref = p_oper1->data.objref;
if (Typeof(p_ref) == program) abort_interp("Can't recycle this program.");
if (prims_recycle_checkcallers (fr->caller, p_ref))
abort_interp("Can't recycle a caller.");
switch (Typeof(p_ref))
{
case TYPE_ROOM:
if (p_ref == PLAYER_START || p_ref == GLOBAL_ENVIRONMENT)
abort_interp("Can't recycle that room.");
break;
case TYPE_PLAYER: abort_interp("Can't recycle players.");
case TYPE_GARBAGE: abort_interp("Can't recycle garbage.");
}
recycle (player, p_ref);
CLEAR(p_oper1);
}
/*NEEDS REWRITING!*/
void prims_kill (__P_PROTO)
{
CHECKOP(1);
p_oper1 = POP();
if (!p_oper1->type != PROG_INTEGER) abort_interp("Invalid arguement.");
CLEAR(p_oper1);
}
/****************************************
* create ( s i -- d ) - create a new THING
****************************************/
void prims_create (__P_PROTO)
{
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(2);
p_oper2 = POP();
p_oper1 = POP();
if (p_oper1->type != PROG_STRING) abort_interp("Non-string arguement. (1)");
if (p_oper2->type != PROG_INTEGER) abort_interp("Non-integer arguement. (2)");
if ((*(p_oper1->data.string) == '\0') ||
!ok_name(p_oper1->data.string))
abort_interp ("That's a silly name for an object!");
p_result = (p_oper2->data.number < OBJECT_COST) ?
OBJECT_COST :
p_oper2->data.number;
if (!fr->wizard && !payfor(fr->euid, p_result)) {
sprintf(buffer, "Not enough %s", PL_MONEY);
abort_interp(buffer); /* defined in money.h */
}
p_ref = new_object ();
DBSTORE(p_ref, flags, TYPE_THING);
DBSTORE(p_ref, name, dup_string(p_oper1->data.string));
DBSTORE(p_ref, location, fr->euid);
DBSTORE(p_ref, owner, OWNER(fr->euid));
add_ownerlist(p_ref);
DBSTORE(p_ref, link, fr->euid);
add_backlinks(p_ref);
DBSTORE(p_ref, pennies,
(OBJECT_ENDOWMENT(p_result) > MAX_OBJECT_ENDOWMENT) ?
MAX_OBJECT_ENDOWMENT :
OBJECT_ENDOWMENT(p_result));
DBSTORE(p_ref, exits, NOTHING);
PUSH(p_ref, DBFETCH(fr->euid)->contents);
DBDIRTY(p_ref);
DBDIRTY(fr->euid);
CLEAR(p_oper1);
CLEAR(p_oper2);
push(arg, top, PROG_OBJECT, MIPSCAST &p_ref);
}
/****************************************
* dig ( s d -- d d ) - creates a new ROOM
****************************************/
void prims_dig (__P_PROTO)
{
dbref parent;
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(2);
p_oper2 = POP();
p_oper1 = POP();
if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument. (1)");
if (p_oper2->type != PROG_OBJECT) abort_interp("Non-object arguement. (2)");
if (p_oper2->data.objref == NOTHING)
p_oper2->data.objref = DBFETCH(DBFETCH(fr->euid)->location)->location;
if (p_oper2->data.objref == NOTHING)
p_oper2->data.objref = DBFETCH(fr->euid)->location;
if (!valid_object(p_oper2)) abort_interp("Invalid object. (2)");
parent = p_oper2->data.objref;
if (Typeof(parent) != TYPE_ROOM) abort_interp ("Parent not a room.");
if (!can_link_to(fr->euid, TYPE_ROOM, parent)) parent = GLOBAL_ENVIRONMENT;
if ((*(p_oper1->data.string) == '\0') ||
!ok_name(p_oper1->data.string))
abort_interp ("That's a silly name for a room!");
if (!fr->wizard && !payfor(fr->euid, ROOM_COST)) {
sprintf(buffer, "Not enough %s", PL_MONEY);
abort_interp(buffer); /* defined in money.h */
}
p_ref = new_object();
FLAGS(p_ref) = TYPE_ROOM | (FLAGS(fr->euid) & JUMP_OK);
DBSTORE(p_ref, name, dup_string(p_oper1->data.string));
DBSTORE(p_ref, location, parent);
DBSTORE(p_ref, owner, OWNER(fr->euid));
add_ownerlist(p_ref);
DBSTORE(p_ref, exits, NOTHING);
DBSTORE(p_ref, link, NOTHING);
PUSH(p_ref, DBFETCH(parent)->contents);
DBDIRTY(p_ref);
DBDIRTY(parent);
CLEAR(p_oper1);
CLEAR(p_oper2);
push(arg, top, PROG_OBJECT, MIPSCAST &p_ref);
push(arg, top, PROG_OBJECT, MIPSCAST &parent);
}
/****************************************
* open ( s d -- d d ) - creates a new EXIT
****************************************/
void prims_open (__P_PROTO)
{
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(2);
p_oper2 = POP();
p_oper1 = POP();
if (!valid_object(p_oper2)) abort_interp("Invalid object. (2)");
if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument. (1)");
if (!ok_name(p_oper1->data.string)) abort_interp ("Illegal exit name.");
if (!fr->wizard && (fr->euid != OWNER(p_oper2->data.objref)))
abort_interp ("Permission denied.");
if (!fr->wizard && !payfor(fr->euid, EXIT_COST)) {
sprintf(buffer, "Not enough %s", PL_MONEY);
abort_interp(buffer); /* defined in money.h */
}
p_ref = new_object ();
DBSTORE(p_ref, name, dup_string(p_oper1->data.string));
DBSTORE(p_ref, location, NOTHING);
DBSTORE(p_ref, sp.exit.ndest, 0);
DBSTORE(p_ref, sp.exit.dest, NULL);
DBSTORE(p_ref, owner, OWNER(fr->euid));
add_ownerlist(p_ref);
FLAGS(p_ref) = TYPE_EXIT;
moveto(p_ref, p_oper2->data.objref);
DBDIRTY(p_ref);
CLEAR(p_oper1);
CLEAR(p_oper2);
push(arg, top, PROG_OBJECT, MIPSCAST &p_ref);
}
/****************************************
* unlink ( d -- ) unlinks an EXIT
****************************************/
void prims_unlink (__P_PROTO)
{
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(1);
p_oper1 = POP();
if (!valid_object(p_oper1)) abort_interp("Invalid object.");
p_ref = p_oper1->data.objref;
if (!fr->wizard && (fr->euid != OWNER(p_ref)))
abort_interp("Permission denied.");
switch (Typeof(p_ref))
{
case TYPE_EXIT:
remove_backlinks(p_ref);
if(DBFETCH(p_ref)->sp.exit.ndest != 0)
{
if (!fr->wizard)
DBFETCH(OWNER(p_ref))->pennies += LINK_COST;
DBDIRTY(OWNER(p_ref));
}
DBSTORE(p_ref, sp.exit.ndest, 0);
if (DBFETCH(p_ref)->sp.exit.dest)
{
free ((void *)DBFETCH(p_ref)->sp.exit.dest);
DBSTORE(p_ref, sp.exit.dest, NULL);
}
break;
case TYPE_ROOM:
remove_backlinks(p_ref);
DBSTORE(p_ref, link, NOTHING);
break;
default:
abort_interp("Invalid object type");
}
CLEAR(p_oper1);
}
/** addlink_check -> checks to make sure there isn't already a link to
something other than an exit **/
int prims_addlink_check (dbref exit)
{
int i;
for (i = 0; i < DBFETCH(exit)->sp.exit.ndest; i++)
{
switch (Typeof(DBFETCH(exit)->sp.exit.dest[i]))
{
case TYPE_PLAYER:
case TYPE_ROOM:
case TYPE_PROGRAM:
return 1;
}
}
return 0;
}
/** addlink_sub -> checks to see if a link is valid, and links it **/
int prims_addlink_sub (frame *fr, dbref exit, dbref destination)
{
#ifndef TELEPORT_TO_PLAYER
if (Typeof(destination) == TYPE_PLAYER)
return 0;
#endif /* TELEPORT_TO_PLAYER */
if (DBFETCH(exit)->sp.exit.ndest == MAX_LINKS) return 0;
if (!can_link(fr->euid, exit)) return 0;
if (!can_link_to(fr->euid, TYPE_EXIT, destination)) return 0;
switch (Typeof(destination))
{
case TYPE_PLAYER:
case TYPE_ROOM:
case TYPE_PROGRAM:
if (prims_addlink_check(exit)) return 0;
break;
case TYPE_EXIT:
if (exit_loop_check(exit, destination)) return 0;
}
/* chown it if it isna' linked to anything */
if (!DBFETCH(exit)->sp.exit.ndest) db_chown(exit, fr->player);
/* increment the # of destinations */
DBSTORE(exit, sp.exit.ndest, DBFETCH(exit)->sp.exit.ndest + 1);
/* realloc if there's more than one dest, malloc new memory if there is
* no previos destinations.
*/
if (DBFETCH(exit)->sp.exit.ndest > 1)
{ DBSTORE(exit, sp.exit.dest, (dbref *)realloc(DBFETCH(exit)->sp.exit.dest,
sizeof(dbref) * DBFETCH(exit)->sp.exit.ndest));
} else
DBSTORE(exit, sp.exit.dest, (dbref *)malloc(sizeof(dbref)));
/* shove the dest in the array. */
DBSTORE(exit, sp.exit.dest[DBFETCH(exit)->sp.exit.ndest - 1], destination);
return 1;
}
/****************************************
* addlink ( d d -- ) - adds a link to an OBJECT
****************************************/
void prims_addlink (__P_PROTO)
{
if (!Builder(fr->euid) && !fr->wizard && !(FLAGS(program) & BUILDER))
abort_interp ("You're not a builder.");
CHECKOP(2);
p_oper2 = POP();
p_oper1 = POP();
if (!valid_object(p_oper1)) abort_interp("Invalid object. (1)");
if (!valid_object(p_oper2)) abort_interp("Invalid object. (2)");
switch (Typeof(p_oper1->data.objref))
{
case TYPE_EXIT:
if (fr->euid != OWNER(p_oper1->data.objref))
abort_interp("Permission denied.");
remove_backlinks(p_oper1->data.objref);
if (!prims_addlink_sub (fr, p_oper1->data.objref, p_oper2->data.objref))
abort_interp ("Can't link.");
add_backlinks(p_oper1->data.objref);
break;
case TYPE_PLAYER:
case TYPE_THING:
case TYPE_PROGRAM:
case TYPE_ROOM:
if (!controls(fr->euid, p_oper1->data.objref) ||
!can_link_to(fr->euid, Typeof(p_oper1->data.objref),
p_oper2->data.objref))
abort_interp("Permission denied.");
remove_backlinks(p_oper1->data.objref);
DBSTORE(p_oper1->data.objref, link, p_oper2->data.objref);
add_backlinks(p_oper1->data.objref);
}
CLEAR(p_oper1);
CLEAR(p_oper2);
}