/* create.c */ /* $Id: create.c,v 1.14 1994/01/26 05:39:15 nils Exp $ */ #include "db.h" #include "config.h" #include "interface.h" #include "externs.h" /* utility for open and link */ static dbref parse_linkable_room(player,room_name) dbref player; char *room_name; { dbref room; /* skip leading NUMBER_TOKEN if any */ if(*room_name == NUMBER_TOKEN) room_name++; /* parse room */ if(!string_compare(room_name, "here")) { room = db[player].location; } else if(!string_compare(room_name, "home")) { return HOME; /* HOME is always linkable */ } else { room = parse_dbref(room_name); } /* check room */ if(room < 0 || room >= db_top || Typeof(room)==TYPE_EXIT) { /* !!! if Wizard and unsafe do it any ways !!! */ /* if (power(player, TYPE_DIRECTOR) && unsafe) return(room);*/ if(room<0 || room>=db_top) notify(player, tprintf("#% is not a valid object.",room)); else notify(player, tprintf("%s is an exit!",unparse_object(player,room))); return NOTHING; } else if(!can_link_to(player, room, POW_MODIFY)) { /* !!! ... !!! XX */ /* if (power(player, TYPE_DIRECTOR) && unsafe) return(room);*/ notify(player, tprintf("You can't link to %s.", unparse_object(player,room))); return NOTHING; } else { return room; } } /* use this to create an exit */ void do_open(player,direction,linkto,pseudo) dbref player; char *direction; char *linkto; dbref pseudo; /* a phony location for a player if a back exit is needed */ { dbref loc=(pseudo!=NOTHING) ? pseudo : db[player].location; dbref exit; dbref loczone; dbref linkzone; if ((loc==NOTHING) || (Typeof(loc)==TYPE_PLAYER)) { notify(player,"Sorry you can't make an exit there."); return; } #ifdef RESTRICTED_BUILDING if(!Builder(player)) { notify(player, "That command is restricted to authorized builders."); return; } #endif /* RESTRICTED_BUILDING */ if(!*direction) { notify(player, "Open where?"); return; } else if(!ok_exit_name(direction)) { notify(player, tprintf("%s is a strange name for an exit!",direction)); return; } if(!controls(player, loc, POW_MODIFY)) { notify(player, "Permission denied."); } else if ( can_pay_fees(def_owner(player), EXIT_COST, QUOTA_COST) ) { /* create the exit */ exit = new_object(); /* initialize everything */ SET(db[exit].name,direction); db[exit].owner = def_owner(player); db[exit].zone = NOTHING; db[exit].flags = TYPE_EXIT|SEE_OK; db[exit].flags |= (db[db[exit].owner].flags & INHERIT_POWERS); check_spoofobj(player, exit); /* link it in */ PUSH(exit, Exits(loc)); db[exit].location = loc; db[exit].link = NOTHING; /* and we're done */ notify(player, tprintf("%s opened.",direction)); /* check second arg to see if we should do a link */ if (*linkto != '\0') { if ((loc = parse_linkable_room(player, linkto)) != NOTHING) { if (!payfor(player, LINK_COST)) { notify(player, "You don't have enough Credits to link."); } else { loczone = get_zone_first(player); linkzone = get_zone_first(loc); /* it's ok, link it */ db[exit].link = loc; notify(player, tprintf("Linked to %s.", unparse_object(player,loc))); } } } } } /* use this to link to a room that you own */ /* it seizes ownership of the exit */ /* costs 1 penny */ /* plus a penny transferred to the exit owner if they aren't you */ /* you must own the linked-to room AND specify it by room number */ void do_link(player,name,room_name) dbref player; char *name; char *room_name; { dbref thing; dbref room; init_match(player, name, TYPE_EXIT); match_everything(); if((thing = noisy_match_result()) != NOTHING) { switch(Typeof(thing)) { case TYPE_EXIT: if ( (room = parse_linkable_room(player, room_name)) == NOTHING) return; if ( (room!=HOME) && !controls(player,room,POW_MODIFY) && ! (db[room].flags & LINK_OK)) { notify(player,"Permission denied."); break; } /* we're ok, check the usual stuff */ if(db[thing].link != NOTHING) { if(controls(player, thing, POW_MODIFY)) { /* if(Typeof(db[thing].link) == TYPE_PLAYER) notify(player, "That exit is being carried."); else*/ notify(player, tprintf("%s is already linked.", unparse_object(player,thing))); } else { notify(player, "Permission denied."); } } else { /* handle costs */ if(db[thing].owner == db[player].owner) { if(!payfor(player, LINK_COST)) { notify(player, "It costs a Credit to link this exit."); return; } } else { if ( ! can_pay_fees(def_owner(player), LINK_COST+EXIT_COST, QUOTA_COST) ) return; #ifdef RESTRICTED_BUILDING else if(!Builder(player)) notify(player, "Only authorized builders may seize exits."); #endif /* RESTRICTED_BUILDING */ else { /* pay the owner for his loss */ giveto(db[thing].owner, EXIT_COST); add_quota(db[thing].owner, QUOTA_COST); } } /* link has been validated and paid for; do it */ db[thing].owner = def_owner(player); db[thing].link = room; /* notify the player */ notify(player, tprintf("%s linked to %s.", unparse_object_a(player,thing), unparse_object_a(player,room))); } break; case TYPE_PLAYER: case TYPE_THING: init_match(player, room_name, NOTYPE); match_exit(); match_neighbor(); match_possession(); match_me(); match_here(); match_absolute(); match_player(); if ((room=noisy_match_result())<0) { /* notify(player,"No match."); noisy_match_result talks bout it */ return; } if (Typeof(room)==TYPE_EXIT) { notify(player,tprintf("%s is an exit.",unparse_object(player,room))); return; } /* abode */ if (!controls(player,room,POW_MODIFY) && !(db[room].flags&LINK_OK)) { notify(player,"Permission denied."); break; } if(!controls(player, thing, POW_MODIFY) && ((db[thing].location!=player) || !(db[thing].flags & LINK_OK ))) { notify(player, "Permission denied."); } else if(room == HOME) { notify(player, "Can't set home to home."); } else { /* do the link */ db[thing].link = room; /* home */ notify(player, tprintf("Home set to %s.",unparse_object(player,room))); } break; case TYPE_ROOM: if((room = parse_linkable_room(player, room_name)) == NOTHING) return; if (Typeof(room)!=TYPE_ROOM) { notify(player,tprintf("%s is not a room!", unparse_object(player,room))); return; } if ((room!=HOME) && !controls(player,room,POW_MODIFY) && !(db[room].flags & LINK_OK)) { notify(player,"Permission denied."); break; } if(!controls(player, thing, POW_MODIFY)) { notify(player, "Permission denied."); } else { /* do the link, in location....no, in link! yay! */ db[thing].link = room; /* dropto */ notify(player, tprintf("Dropto set to %s.", unparse_object(player,room))); } break; default: notify(player, "Internal error: weird object type."); log_error(tprintf("PANIC weird object: Typeof(%d) = %d", thing, Typeof(thing))); report(); break; } } } /* Links a room to a "zone object" */ void do_zlink(player, arg1, arg2) dbref player; char *arg1; char *arg2; { dbref room; dbref object; dbref old_zone; init_match(player, arg1, TYPE_ROOM); match_here(); match_absolute(); if ((room = noisy_match_result()) != NOTHING) { init_match(player, arg2, TYPE_THING); match_neighbor(); match_possession(); match_absolute(); old_zone = get_zone_first(room); if ((object = noisy_match_result()) != NOTHING) { if ((!(controls(player,room,POW_MODIFY) && controls(player,object,POW_MODIFY))) || (Typeof(room)!=TYPE_ROOM && Typeof(room)!=TYPE_THING && !power(player,POW_SECURITY))) { notify(player, "Permission denied."); } else if (is_in_zone(object, room)) { notify(player,"I think you're feeling a bit loopy."); } else { if (db[object].zone == NOTHING && object != db[0].zone) db[object].zone = db[0].zone; /* silly person doesn't know * how to set up a zone * right.. */ db[room].zone = object; notify(player, tprintf("%s zone set to %s", db[room].name, db[object].name)); } } } } void do_unzlink(player, arg1) dbref player; char *arg1; { dbref room; init_match(player, arg1, TYPE_ROOM); match_here(); match_absolute(); if ((room = noisy_match_result()) != NOTHING) { if (!controls(player, room, POW_MODIFY)) { notify(player, "Permission denied."); } else { if (Typeof(room) == TYPE_ROOM) db[room].zone = db[0].zone; else db[room].zone = NOTHING; notify(player, "Zone unlinked."); } } return; } /* special link - sets the universal zone */ void do_ulink(player, arg1) dbref player; char *arg1; { dbref thing, p, oldu; if (player != GOD) { notify(player, "You don't have the authority. So sorry."); return; } init_match(player, arg1, TYPE_THING); match_possession(); match_neighbor(); match_absolute(); if ((thing = noisy_match_result()) != NOTHING) { oldu = db[0].zone; db[0].zone = thing; for (p = 0; p < db_top; p++) if ((Typeof(p) == TYPE_ROOM) && !(db[p].flags & GOING) && ((db[p].zone == oldu) || (db[p].zone == NOTHING))) db[p].zone = thing; } db[thing].zone = NOTHING; notify(player, tprintf("Universal zone set to %s.", db[thing].name)); } /* use this to create a room */ void do_dig(player,name,argv) dbref player; char *name; char *argv[]; { dbref room; dbref where; #ifdef RESTRICTED_BUILDING if(!Builder(player)) { notify(player, "That command is restricted to authorized builders."); return; } #endif /* RESTRICTED_BUILDING */ /* we don't need to know player's location! hooray! */ where = db[player].location; /* MMZ */ if(*name == '\0') { notify(player, "Dig what?"); } else if(!ok_room_name(name)) { notify(player, "That's a silly name for a room!"); } else if ( can_pay_fees(def_owner(player), ROOM_COST, QUOTA_COST) ) { room = new_object(); /* Initialize everything */ SET(db[room].name,name); db[room].owner = def_owner(player); db[room].flags = TYPE_ROOM|SEE_OK; db[room].location = room; db[room].zone = db[where].zone; db[room].flags |= (db[db[room].owner].flags & INHERIT_POWERS); check_spoofobj(player,room); notify(player, tprintf("%s created with room number %d.", name, room)); if (argv[1] && *argv[1]) { char nbuff[50]; sprintf(nbuff,"%d",room); do_open(player,argv[1],nbuff,NOTHING); } if (argv[2] && *argv[2]) { char nbuff[50]; sprintf(nbuff,"%d",db[player].location); do_open(player,argv[2],nbuff,room); } } } void check_spoofobj(player, thing) dbref player, thing; { dbref p; if ((p=starts_with_player(db[thing].name))!=NOTHING && !controls(player,p,POW_SPOOF) && !(db[thing].flags&HAVEN)) { notify(player,tprintf("Warning: %s can be used to spoof an existing player. It has as been set haven.",unparse_object(player,thing))); db[thing].flags |= HAVEN; } } /* use this to create an object */ void do_create(player,name,cost) dbref player; char *name; int cost; { dbref loc; dbref thing; #ifdef RESTRICTED_BUILDING if(!Builder(player)) { notify(player, "That command is restricted to authorized builders."); return; } #endif /* RESTRICTED_BUILDING */ if(*name == '\0') { notify(player, "Create what?"); return; } else if(!ok_thing_name(name)) { notify(player, "That's a silly name for a thing!"); return; } else if(cost < 0) { notify(player, "You can't create an object for less than nothing!"); return; } else if(cost < OBJECT_COST) cost = OBJECT_COST; if ( can_pay_fees(def_owner(player), cost, QUOTA_COST) ) { /* create the object */ thing = new_object(); /* initialize everything */ SET(db[thing].name,name); db[thing].location = player; db[thing].zone = NOTHING; db[thing].owner = def_owner(player); s_Pennies(thing,OBJECT_ENDOWMENT(cost)); db[thing].flags = TYPE_THING|SEE_OK; db[thing].flags |= (db[db[thing].owner].flags & INHERIT_POWERS); check_spoofobj(player, thing); /* endow the object */ if(Pennies(thing) > MAX_OBJECT_ENDOWMENT) { s_Pennies(thing,MAX_OBJECT_ENDOWMENT); } /* home is here (if we can link to it) or player's home */ if((loc = db[player].location) != NOTHING && controls(player, loc, POW_MODIFY)) { db[thing].link = loc; } else { db[thing].link = db[player].link; } db[thing].exits = NOTHING; /* link it in */ PUSH(thing, db[player].contents); /* and we're done */ notify(player, tprintf("%s created.",unparse_object(player,thing))); } } void do_clone(player,arg1,arg2) dbref player; char *arg1; char *arg2; { dbref clone,thing; if ( Guest(db[player].owner) ) { notify(player, "Guests can't clone objects\n"); return; } #ifdef RESTRICTED_BUILDING if (!Builder(player)) { notify(player,"Command is for builders only."); return; } #endif init_match(player, arg1, NOTYPE); match_everything(); thing = noisy_match_result(); if ((thing==NOTHING) || (thing==AMBIGUOUS)) return; if( !controls(player, thing, POW_SEEATR)) { notify(player, "Permission denied."); return; } if (Typeof(thing)!=TYPE_THING) { notify(player,"You can only clone things."); return; } if(!can_pay_fees(def_owner(player),OBJECT_COST,QUOTA_COST)) { notify(player,"you've not enough money."); return; } clone=new_object(); memcpy(&db[clone],&db[thing],sizeof(struct object)); db[clone].name=NULL; db[clone].owner = def_owner(player); db[clone].flags&=~(HAVEN|BEARING); /* common parent flags */ if (!(db[player].flags&INHERIT_POWERS)) db[clone].flags&=~INHERIT_POWERS; SET(db[clone].name,(*arg2)?arg2:db[thing].name); check_spoofobj(player,clone); s_Pennies(clone,1); atr_cpy_noninh(clone,thing); /* copies the noninherited attributes. */ db[clone].contents=db[clone].location=db[clone].next=NOTHING; db[clone].atrdefs = NULL; db[clone].parents = NULL; db[clone].children = NULL; PUSH_L (db[clone].parents, thing); PUSH_L (db[thing].children, clone); notify(player,tprintf("%s cloned with number %d.", unparse_object(player,thing),clone)); moveto(clone,db[player].location); did_it(player,clone,NULL,NULL,NULL,NULL,A_ACLONE); } void do_robot(player,name,pass) dbref player; char *name; char *pass; { dbref thing; #ifdef RESTRICTED_BUILDING if (!Builder(player)) { notify(player,"Only builders can make robots."); return; } #endif if (!power(player,POW_PCREATE)) { notify(player,"You can't make robots."); return; } if ( ! can_pay_fees(def_owner(player), ROBOT_COST, QUOTA_COST) ) { notify(player,"Sorry you don't have enough money to make a robot."); return; } if ((thing=create_player(name,pass,CLASS_VISITOR))==NOTHING) { giveto(player,ROBOT_COST); add_quota(player, QUOTA_COST); notify(player,tprintf("%s already exists.",name)); return; } db[thing].owner=db[player].owner; atr_clr(thing, A_RQUOTA); enter_room(thing,db[player].location); notify(player,tprintf("%s has arrived.",unparse_object(player,thing))); }