/* create.c */ /* Commands that create new objects */ #include <string.h> #include "config.h" #include "db.h" #include "attrib.h" #include "interface.h" #include "externs.h" /* utility for open and link */ static dbref parse_linkable_room(player, room_name) dbref player; const 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) { notify(player, "That is not a valid object."); return NOTHING; } else if (!can_link_to(player, room)) { notify(player, "You can't link to that."); return NOTHING; } else { return room; } } /* use this to create an exit */ int do_real_open(player, direction, linkto, pseudo) dbref player; const char *direction; const 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; if ((loc == NOTHING) || (Typeof(loc) != TYPE_ROOM)) { notify(player, "Sorry you can only make exits out of rooms."); return 0; } #ifdef RESTRICTED_BUILDING if (!Builder(player)) { notify(player, "That command is restricted to authorized builders."); return 0; } #endif /* RESTRICTED_BUILDING */ #ifdef GUEST_RESTRICT if (Guest(player)) { notify(player, "Guests are not allowed to build."); return 0; } #endif if(!*direction) { notify(player, "Open where?"); return 0; } else if (!ok_name(direction)) { notify(player, "That's a strange name for an exit!"); return 0; } if (!controls(player, loc)) { notify(player, "Permission denied."); } else if (can_pay_fees(player, EXIT_COST)) { /* create the exit */ exit = new_object(); /* initialize everything */ SET(db[exit].name, direction); db[exit].owner = db[player].owner; db[exit].zone = db[player].zone; db[exit].flags = TYPE_EXIT; db[exit].exits = loc; /* link it in */ PUSH(exit, db[loc].exits); /* and we're done */ notify(player, "Opened."); /* check second arg to see if we should do a link */ if (linkto && *linkto != '\0') { notify(player, "Trying to link..."); if ((loc = parse_linkable_room(player, linkto)) != NOTHING) { if (!payfor(player, LINK_COST)) { notify(player, tprintf("You don't have enough %s to link.", MONIES)); } else { /* it's ok, link it */ db[exit].location = loc; notify(player, "Linked."); } } } return exit; } return 0; } void do_open(player,direction,links) dbref player; const char *direction; const char *links[]; { do_real_open(player, direction, links[1], NOTHING); if(links[2]) { do_real_open(player, links[2], tprintf("%d",db[player].location), parse_linkable_room(player, links[1])); } } /* 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; const char *name; const char *room_name; { dbref thing; dbref room; if (Typeof(db[player].location) == TYPE_EXIT) { notify(player, "You somehow wound up in a exit. No biscuit."); return; } init_match(player, name, TYPE_EXIT); match_exit(); match_neighbor(); match_possession(); match_me(); match_here(); match_absolute(); match_player(); 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) && !(db[room].flags & LINK_OK)) { notify(player, "Permission denied."); break; } /* we're ok, check the usual stuff */ if (db[thing].location != NOTHING) { if (controls(player, thing)) { if (Typeof(db[thing].location) == TYPE_PLAYER) { notify(player, "That exit is being carried."); } else { notify(player, "That exit is already linked."); } } else { notify(player, "Permission denied."); } } else { /* handle costs */ if (db[thing].owner == db[player].owner) { if (!payfor(player, LINK_COST)) { notify(player, tprintf("It costs %d %s to link this exit.", LINK_COST, ((LINK_COST == 1) ? MONEY : MONIES))); return; } } else { if (!payfor(player, LINK_COST + EXIT_COST)) { int a; notify(player, tprintf("It costs %d %s to link this exit.", (a = LINK_COST+EXIT_COST), ((a == 1) ? MONEY : MONIES))); return; #ifdef RESTRICTED_BUILDING } else if (!Builder(player)) { notify(player, "Only authorized builders may seize exits."); #endif /* RESTRICTED_BUILDING */ #ifdef GUEST_RESTRICT } else if (Guest(player)) { notify(player, "Guests are not allowed to build."); #endif } else { /* pay the owner for his loss */ giveto(db[thing].owner, EXIT_COST); } } /* link has been validated and paid for; do it */ db[thing].owner = db[player].owner; db[thing].zone = db[player].zone; db[thing].location = room; /* notify the player */ notify(player, "Linked."); } 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."); return; } if (Typeof(room) == TYPE_EXIT) { notify(player, "That is an exit."); return; } /* abode */ if (!controls(player, room) && !IS(room, TYPE_ROOM, ROOM_ABODE)) { notify(player, "Permission denied."); break; } if (!controls(player, thing)) { notify(player, "Permission denied."); } else if (room == HOME) { notify(player, "Can't set home to home."); } else { /* do the link */ db[thing].exits = room; /* home */ notify(player, "Home set."); } break; case TYPE_ROOM: if ((room = parse_linkable_room(player, room_name)) == NOTHING) return; if (Typeof(room) != TYPE_ROOM) { notify(player, "That is not a room!"); return; } if (!controls(player, thing)) { notify(player, "Permission denied."); } else { /* do the link, in location */ db[thing].location = room; /* dropto */ notify(player, "Dropto set."); } break; default: notify(player, "Internal error: weird object type."); fprintf(stderr, "PANIC weird object: Typeof(%d) = %d\n", thing, Typeof(thing)); break; } } } /* use this to create a room */ void do_dig(player, name, argv) dbref player; const char *name; char *argv[]; { dbref room; #ifdef RESTRICTED_BUILDING if (!Builder(player)) { notify(player, "That command is restricted to authorized builders."); return; } #endif /* RESTRICTED_BUILDING */ #ifdef GUEST_RESTRICT if (Guest(player)) { notify(player, "Guests are not allowed to build."); return; } #endif /* we don't need to know player's location! hooray! */ if (*name == '\0') { notify(player, "Dig what?"); } else if (!ok_name(name)) { notify(player, "That's a silly name for a room!"); } else if (can_pay_fees(player, ROOM_COST)) { room = new_object(); /* Initialize everything */ SET(db[room].name, name); db[room].owner = db[player].owner; db[room].zone = db[player].zone; db[room].flags = TYPE_ROOM; notify(player, tprintf("%s created with room number %d.", name, room)); if (argv[1] && *argv[1]) { char nbuff[MAX_COMMAND_LEN]; sprintf(nbuff, "%d", room); do_real_open(player, argv[1], nbuff, NOTHING); } if (argv[2] && *argv[2]) { char nbuff[MAX_COMMAND_LEN]; sprintf(nbuff, "%d", db[player].location); do_real_open(player, argv[2], nbuff, room); } } } /* use this to create an object */ void do_create(player, name, cost) dbref player; char *name; int cost; { dbref loc; dbref thing; #ifndef FREE_OBJECTS #ifdef RESTRICTED_BUILDING if (!Builder(db[player].owner)) { notify(player, "That command is restricted to authorized builders."); return; } #endif /* RESTRICTED_BUILDING */ #endif /* FREE_OBJECTS */ #ifdef GUEST_RESTRICT if (Guest(player)) { notify(player, "Guests are not allowed to build."); return; } #endif if (*name == '\0') { notify(player, "Create what?"); return; } else if (!ok_name(name)) { notify(player, "That's a silly name for a thing!"); return; } else if (cost < OBJECT_COST) { cost = OBJECT_COST; } if (can_pay_fees(player, cost)) { /* create the object */ thing = new_object(); /* initialize everything */ SET(db[thing].name, name); db[thing].location = player; db[thing].owner = db[player].owner; db[thing].zone = db[player].zone; s_Pennies(thing, OBJECT_ENDOWMENT(cost)); db[thing].flags = TYPE_THING; /* endow the object */ if(Wizard(player)) { if(Pennies(thing) > MAX_WIZ_OBJECT_ENDOWMENT) s_Pennies(thing, MAX_WIZ_OBJECT_ENDOWMENT); } else 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) || IS(loc, TYPE_ROOM, ROOM_ABODE))) { db[thing].exits = loc; /* home */ } else { db[thing].exits = db[player].exits; /* home */ } /* link it in */ PUSH(thing, db[player].contents); /* and we're done */ notify(player, tprintf("Created: Object #%d.", thing)); } } void do_clone(player, name) dbref player; char *name; { dbref clone, thing; #ifdef GUEST_RESTRICT if (Guest(player)) { notify(player, "Guests are not allowed to build."); return; } #endif init_match(player, name, NOTYPE); match_everything(); thing = noisy_match_result(); if ((thing == NOTHING)) return; if (!controls(player, thing)) { notify(player, "Permission denied."); return; } /* don't allow cloning of destructed things */ if(db[thing].flags & GOING) { notify(player, "There's nothing left of it to clone!"); return; } /* make sure owner can afford it */ if (can_pay_fees(player, OBJECT_COST)) { switch (Typeof(thing)) { case TYPE_THING: #ifdef RESTRICTED_BUILDING #ifndef FREE_OBJECTS if (!Builder(player)) { notify(player, "Command is for builders only."); return; } #endif #endif clone = new_object(); memcpy(&db[clone], &db[thing], sizeof(struct object)); db[clone].name = NULL; SET(db[clone].name, db[thing].name); s_Pennies(clone, 1); atr_cpy(clone, thing); db[clone].key = dup_bool(db[thing].key); db[clone].contents = db[clone].location = db[clone].next = NOTHING; db[clone].flags &= ~WIZARD; #ifdef ROYALTY_FLAG db[clone].flags &= ~ROYALTY; #endif notify(player, tprintf("Cloned: Object #%d.", clone)); moveto(clone, db[player].location); did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING); break; case TYPE_EXIT: #ifdef RESTRICTED_BUILDING if (!Builder(player)) { notify(player, "Command is for builders only."); return; } #endif clone = do_real_open(player, db[thing].name, tprintf("%d", db[thing].location), NOTHING); atr_cpy(clone, thing); db[clone].key = dup_bool(db[thing].key); db[clone].flags &= ~WIZARD; notify(player, "Exit cloned."); break; default: notify(player, "You can only clone things and exits."); } } }