#include "config.h"
#include "object.h"
#include "instr.h"
#include "construct.h"
#include "compile.h"
#include "interp.h"
#include "operproto.h"
#include "interface.h"
#include "dbhandle.h"
#include "globals.h"
#include "cache.h"
int s_add_verb(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp,tmp2;
struct verb *new_verb;
struct fns *tmp_fns;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=2) {
return 1;
}
if (pop(&tmp,rts,obj)) {
return 1;
}
if (tmp.type!=STRING) {
clear_var(&tmp);
return 1;
}
if (pop(&tmp2,rts,obj)) {
clear_var(&tmp);
return 1;
}
if (tmp2.type==INTEGER && tmp2.value.integer==0) {
tmp2.type=STRING;
tmp2.value.string=copy_string("");
}
if (tmp2.type!=STRING) {
clear_var(&tmp);
clear_var(&tmp2);
return 1;
}
if ((strlen(tmp2.value.string)+1)>MAX_STR_LEN) {
clear_var(&tmp);
clear_var(&tmp2);
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
tmp_fns=find_fns(tmp.value.string,obj);
if (!tmp_fns) {
clear_var(&tmp);
clear_var(&tmp2);
tmp.type=INTEGER;
tmp.value.num=1;
push(&tmp,rts);
return 0;
}
remove_verb(obj,tmp2.value.string);
new_verb=(struct verb *) MALLOC(sizeof(struct verb));
new_verb->verb_name=tmp2.value.string;
new_verb->is_xverb=0;
new_verb->function=tmp.value.string;
new_verb->next=obj->verb_list;
obj->verb_list=new_verb;
tmp.type=INTEGER;
tmp.value.num=0;
push(&tmp,rts);
return 0;
}
int s_add_xverb(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp,tmp2;
struct verb *new_verb;
struct fns *tmp_fns;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=2) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=STRING) {
clear_var(&tmp);
return 1;
}
if (pop(&tmp2,rts,obj)) {
clear_var(&tmp);
return 1;
}
if (tmp2.type==INTEGER && tmp2.value.integer==0) {
tmp2.type=STRING;
tmp2.value.string=copy_string("");
}
if (tmp2.type!=STRING) {
clear_var(&tmp);
clear_var(&tmp2);
return 1;
}
if ((strlen(tmp2.value.string)+1)>MAX_STR_LEN) {
clear_var(&tmp);
clear_var(&tmp2);
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
tmp_fns=find_fns(tmp.value.string,obj);
if (!tmp_fns) {
clear_var(&tmp);
clear_var(&tmp2);
tmp.type=INTEGER;
tmp.value.num=1;
push(&tmp,rts);
return 0;
}
remove_verb(obj,tmp2.value.string);
new_verb=(struct verb *) MALLOC(sizeof(struct verb));
new_verb->verb_name=tmp2.value.string;
new_verb->is_xverb=1;
new_verb->function=tmp.value.string;
new_verb->next=obj->verb_list;
obj->verb_list=new_verb;
tmp.type=INTEGER;
tmp.value.num=0;
push(&tmp,rts);
return 0;
}
int s_call_other(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp1,tmp2,tmp3;
struct var_stack *arg_stack;
struct fns *tmp_fns;
struct var *old_locals;
unsigned int old_num_locals;
if (pop(&tmp1,rts,obj)) return 1;
if (tmp1.type!=NUM_ARGS) {
clear_var(&tmp1);
return 1;
}
if (tmp1.value.num<2) return 1;
tmp1.value.num-=2;
push(&tmp1,rts);
if (!(arg_stack=gen_stack(rts,obj))) return 1;
if (pop(&tmp2,rts,obj)) {
free_stack(&arg_stack);
return 1;
}
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
free_stack(&arg_stack);
return 1;
}
if (tmp1.type!=OBJECT || tmp2.type!=STRING) {
clear_var(&tmp1);
clear_var(&tmp2);
free_stack(&arg_stack);
return 1;
}
tmp_fns=find_fns(tmp2.value.string,tmp1.value.objptr);
clear_var(&tmp2);
if (!tmp_fns) {
free_stack(&arg_stack);
tmp1.type=INTEGER;
tmp1.value.integer=0;
push(&tmp1,rts);
return 0;
}
if (tmp_fns->is_static) {
free_stack(&arg_stack);
tmp1.type=INTEGER;
tmp1.value.integer=0;
push(&tmp1,rts);
return 0;
}
old_locals=locals;
old_num_locals=num_locals;
if (interp(obj,tmp1.value.objptr,player,&arg_stack,tmp_fns)) {
locals=old_locals;
num_locals=old_num_locals;
free_stack(&arg_stack);
tmp1.type=INTEGER;
tmp1.value.integer=0;
push(&tmp1,rts);
return 0;
}
locals=old_locals;
num_locals=old_num_locals;
if (pop(&tmp1,&arg_stack,obj)) {
tmp1.type=INTEGER;
tmp1.value.integer=0;
}
free_stack(&arg_stack);
push(&tmp1,rts);
return 0;
}
int s_alarm(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp1,tmp2;
if (pop(&tmp1,rts,obj)) return 1;
if (tmp1.type!=NUM_ARGS) {
clear_var(&tmp1);
return 1;
}
if (tmp1.value.num!=2) return 1;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (tmp1.type!=INTEGER || tmp2.type!=STRING) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (!find_fns(tmp2.value.string,obj) || tmp1.value.integer<0) {
clear_var(&tmp2);
tmp1.value.integer=1;
push(&tmp1,rts);
return 0;
}
queue_for_alarm(obj,tmp1.value.integer,tmp2.value.string);
clear_var(&tmp2);
tmp1.value.integer=0;
push(&tmp1,rts);
return 0;
}
int s_remove_alarm(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
signed long tmpint;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num==0) {
tmp.type=INTEGER;
tmp.value.integer=remove_alarm(obj,NULL);
push(&tmp,rts);
return 0;
} else
if (tmp.value.num==1) {
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=STRING) {
clear_var(&tmp);
return 1;
}
tmpint=remove_alarm(obj,tmp.value.string);
clear_var(&tmp);
tmp.type=INTEGER;
tmp.value.integer=tmpint;
push(&tmp,rts);
return 0;
}
return 1;
}
int s_caller_object(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=0) return 1;
tmp.type=OBJECT;
tmp.value.objptr=caller;
if (!caller) {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_clone_object(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp,tmp2,tmp3;
struct object *tmpobj;
struct code *newcode;
unsigned int line;
struct var_stack *arg_stack;
struct fns *tmpfns;
struct var *old_locals;
struct proto *tmp_proto;
unsigned int old_num_locals;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=STRING && tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.type==STRING) {
if (!(tmpobj=find_proto(tmp.value.string))) {
line=parse_code(tmp.value.string,obj,&newcode);
if (line==((unsigned int) -1)) {
clear_var(&tmp);
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}
if (line) {
compile_error(player,tmp.value.string,line);
clear_var(&tmp);
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}
tmpobj=newobj();
tmp_proto=(struct proto *) MALLOC(sizeof(struct proto));
tmpobj->flags|=PROTOTYPE;
tmpobj->parent=tmp_proto;
tmpobj->parent->funcs=newcode;
tmpobj->parent->next_proto=ref_to_obj(0)->parent->next_proto;
ref_to_obj(0)->parent->next_proto=tmpobj->parent;
tmpobj->parent->pathname=tmp.value.string;
tmpobj->parent->proto_obj=tmpobj;
if (newcode->num_globals) {
tmpobj->globals=(struct var *) MALLOC(sizeof(struct var)*newcode->
num_globals);
line=0;
while (line<newcode->num_globals) {
tmpobj->globals[line].type=INTEGER;
tmpobj->globals[line].value.integer=0;
line++;
}
}
add_loaded(tmpobj);
tmpobj->obj_state=DIRTY;
tmpfns=find_fns("init",tmpobj);
if (tmpfns) {
tmp2.type=NUM_ARGS;
tmp2.value.num=0;
arg_stack=NULL;
push(&tmp2,&arg_stack);
old_locals=locals;
old_num_locals=num_locals;
interp(obj,tmpobj,player,&arg_stack,tmpfns);
locals=old_locals;
num_locals=old_num_locals;
free_stack(&arg_stack);
}
} else
clear_var(&tmp);
tmp.type=OBJECT;
tmp.value.objptr=tmpobj;
}
tmpobj=newobj();
tmpobj->parent=tmp.value.objptr->parent;
tmpobj->next_child=tmpobj->parent->proto_obj->next_child;
tmpobj->parent->proto_obj->next_child=tmpobj;
if (tmpobj->parent->funcs->num_globals) {
tmpobj->globals=(struct var *) MALLOC(sizeof(struct var)*tmpobj->parent->
funcs->num_globals);
line=0;
while (line<tmpobj->parent->funcs->num_globals) {
tmpobj->globals[line].type=INTEGER;
tmpobj->globals[line].value.integer=0;
line++;
}
}
add_loaded(tmpobj);
tmpobj->obj_state=DIRTY;
tmpfns=find_fns("init",tmpobj);
if (tmpfns) {
arg_stack=NULL;
old_locals=locals;
old_num_locals=num_locals;
tmp3.type=NUM_ARGS;
tmp3.value.num=0;
push(&tmp3,&arg_stack);
interp(obj,tmpobj,player,&arg_stack,tmpfns);
locals=old_locals;
num_locals=old_num_locals;
free_stack(&arg_stack);
}
tmp.value.objptr=tmpobj;
push(&tmp,rts);
return 0;
}
int s_destruct(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
struct object *curr,*prev;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr!=obj && (!(obj->flags & PRIV))) {
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
if (tmp.value.objptr==ref_to_obj(0)) {
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
queue_for_destruct(tmp.value.objptr);
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}
int s_contents(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->contents) {
tmp.value.objptr=tmp.value.objptr->contents;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_next_object(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->next_object) {
tmp.value.objptr=tmp.value.objptr->next_object;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_location(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->location) {
tmp.value.objptr=tmp.value.objptr->location;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_next_child(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->next_child) {
tmp.value.objptr=tmp.value.objptr->next_child;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_parent(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->parent) {
tmp.value.objptr=tmp.value.objptr->parent->proto_obj;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_next_proto(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
if (tmp.value.objptr->parent->next_proto) {
tmp.value.objptr=tmp.value.objptr->parent->next_proto->proto_obj;
} else {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_move_object(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
struct object *item,*dest,*prev,*curr;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=2) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT && (tmp.type!=INTEGER || tmp.value.integer!=0)) {
clear_var(&tmp);
return 1;
}
if (tmp.type==OBJECT)
dest=tmp.value.objptr;
else
dest=NULL;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=OBJECT && (tmp.type!=INTEGER || tmp.value.integer!=0)) {
clear_var(&tmp);
return 1;
}
if (tmp.type==OBJECT)
item=tmp.value.objptr;
else {
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
if (dest) {
curr=dest;
while (curr) {
if (curr==item) {
tmp.type=INTEGER;
tmp.value.integer=1;
push(&tmp,rts);
return 0;
}
curr=curr->location;
}
}
if (item->location) {
curr=item->location->contents;
if (curr==item)
item->location->contents=item->next_object;
else
while (curr) {
prev=curr;
curr=curr->next_object;
if (curr==item) {
prev->next_object=curr->next_object;
break;
}
}
}
item->next_object=NULL;
item->location=dest;
if (dest) {
item->next_object=dest->contents;
dest->contents=item;
}
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}
int s_this_object(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=0) return 1;
tmp.type=OBJECT;
tmp.value.objptr=obj;
if (!obj) {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_this_player(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=0) return 1;
tmp.type=OBJECT;
tmp.value.objptr=player;
if (!player) {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}
int s_remove_verb(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num!=1) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type==INTEGER && tmp.value.integer==0) {
tmp.type=STRING;
*(tmp.value.string=MALLOC(1))='\0';
}
if (tmp.type!=STRING) {
clear_var(&tmp);
return 1;
}
remove_verb(obj,tmp.value.string);
clear_var(&tmp);
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}