btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * create.c -- Commands that create new objects 
 */

/*
 * $Id: create.c,v 1.2 2005/08/08 09:43:06 murrayma Exp $ 
 */

#include "copyright.h"
#include "config.h"

#include "mudconf.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
#include "match.h"
#include "command.h"
#include "alloc.h"
#include "attrs.h"
#include "powers.h"

/*
 * ---------------------------------------------------------------------------
 * * parse_linkable_room: Get a location to link to.
 */

static dbref parse_linkable_room(player, room_name)
    dbref player;
    char *room_name;
{
    dbref room;

    init_match(player, room_name, NOTYPE);
    match_everything(MAT_NO_EXITS | MAT_NUMERIC | MAT_HOME);
    room = match_result();

    /*
     * HOME is always linkable 
     */

    if (room == HOME)
        return HOME;

    /*
     * Make sure we can link to it 
     */

    if (!Good_obj(room)) {
        notify_quiet(player, "That's not a valid object.");
        return NOTHING;
    } else if (!Has_contents(room) || !Linkable(player, room)) {
        notify_quiet(player, "You can't link to that.");
        return NOTHING;
    } else {
        return room;
    }
}

/*
 * ---------------------------------------------------------------------------
 * * open_exit, do_open: Open a new exit and optionally link it somewhere.
 */

static void open_exit(player, loc, direction, linkto)
    dbref player, loc;
    char *direction, *linkto;
{
    dbref exit;

    if (!Good_obj(loc))
        return;

    if (!direction || !*direction) {
        notify_quiet(player, "Open where?");
        return;
    } else if (!controls(player, loc)) {
        notify_quiet(player, "Permission denied.");
        return;
    }
    exit = create_obj(player, TYPE_EXIT, direction, 0);
    if (exit == NOTHING)
        return;

    /*
     * Initialize everything and link it in. 
     */

    s_Exits(exit, loc);
    s_Next(exit, Exits(loc));
    s_Exits(loc, exit);

    /*
     * and we're done 
     */

    notify_quiet(player, "Opened.");

    /*
     * See if we should do a link 
     */

    if (!linkto || !*linkto)
        return;

    loc = parse_linkable_room(player, linkto);
    if (loc != NOTHING) {

        /*
         * Make sure the player passes the link lock 
         */

        if (!could_doit(player, loc, A_LLINK)) {
            notify_quiet(player, "You can't link to there.");
            return;
        }
        /*
         * Link it if the player can pay for it 
         */

        if (!payfor(player, mudconf.linkcost)) {
            notify_quiet(player,
                    tprintf("You don't have enough %s to link.",
                        mudconf.many_coins));
        } else {
            s_Location(exit, loc);
            notify_quiet(player, "Linked.");
        }
    }
}

void do_open(player, cause, key, direction, links, nlinks)
    dbref player, cause;
    int key, nlinks;
    char *direction, *links[];
{
    dbref loc, destnum;
    char *dest;

    /*
     * Create the exit and link to the destination, if there is one 
     */

    if (nlinks >= 1)
        dest = links[0];
    else
        dest = NULL;

    if (key == OPEN_INVENTORY)
        loc = player;
    else
        loc = Location(player);

    open_exit(player, loc, direction, dest);

    /*
     * Open the back link if we can 
     */

    if (nlinks >= 2) {
        destnum = parse_linkable_room(player, dest);
        if (destnum != NOTHING) {
            open_exit(player, destnum, links[1], tprintf("%d", loc));
        }
    }
}

/*
 * ---------------------------------------------------------------------------
 * * link_exit, do_link: Set destination(exits), dropto(rooms) or
 * * home(player,thing)
 */

static void link_exit(player, exit, dest)
    dbref player, exit, dest;
{
    int cost, quot;

    /*
     * Make sure we can link there 
     */

    if ((dest != HOME) && ((!controls(player, dest) && !Link_ok(dest)) ||
                !could_doit(player, dest, A_LLINK))) {
        notify_quiet(player, "Permission denied.");
        return;
    }
    /*
     * Exit must be unlinked or controlled by you 
     */

    if ((Location(exit) != NOTHING) && !controls(player, exit)) {
        notify_quiet(player, "Permission denied.");
        return;
    }
    /*
     * handle costs 
     */

    cost = mudconf.linkcost;
    quot = 0;
    if (Owner(exit) != Owner(player)) {
        cost += mudconf.opencost;
        quot += mudconf.exit_quota;
    }
    if (!canpayfees(player, player, cost, quot))
        return;

    /*
     * Pay the owner for his loss 
     */

    if (Owner(exit) != Owner(player)) {
        giveto(Owner(exit), mudconf.opencost);
        add_quota(Owner(exit), quot);
        s_Owner(exit, Owner(player));
        s_Flags(exit, (Flags(exit) & ~(INHERIT | WIZARD)) | HALT);
    }
    /*
     * link has been validated and paid for, do it and tell the player 
     */

    s_Location(exit, dest);
    if (!Quiet(player))
        notify_quiet(player, "Linked.");
}

void do_link(player, cause, key, what, where)
    dbref player, cause;
    int key;
    char *what, *where;
{
    dbref thing, room;
    char *buff;

    /*
     * Find the thing to link 
     */

    init_match(player, what, TYPE_EXIT);
    match_everything(0);
    thing = noisy_match_result();
    if (thing == NOTHING)
        return;

    /*
     * Allow unlink if where is not specified 
     */

    if (!where || !*where) {
        do_unlink(player, cause, key, what);
        return;
    }
    switch (Typeof(thing)) {
        case TYPE_EXIT:

            /*
             * Set destination 
             */

            room = parse_linkable_room(player, where);
            if (room != NOTHING)
                link_exit(player, thing, room);
            break;
        case TYPE_PLAYER:
        case TYPE_THING:

            /*
             * Set home 
             */

            if (!Controls(player, thing)) {
                notify_quiet(player, "Permission denied.");
                break;
            }
            init_match(player, where, NOTYPE);
            match_everything(MAT_NO_EXITS);
            room = noisy_match_result();
            if (!Good_obj(room))
                break;
            if (!Has_contents(room)) {
                notify_quiet(player, "Can't link to an exit.");
                break;
            }
            if (!can_set_home(player, thing, room) ||
                    !could_doit(player, room, A_LLINK)) {
                notify_quiet(player, "Permission denied.");
            } else if (room == HOME) {
                notify_quiet(player, "Can't set home to home.");
            } else {
                s_Home(thing, room);
                if (!Quiet(player))
                    notify_quiet(player, "Home set.");
            }
            break;
        case TYPE_ROOM:

            /*
             * Set dropto 
             */

            if (!Controls(player, thing)) {
                notify_quiet(player, "Permission denied.");
                break;
            }
            room = parse_linkable_room(player, where);
            if (!(Good_obj(room) || (room == HOME)))
                break;

            if ((room != HOME) && !isRoom(room)) {
                notify_quiet(player, "That is not a room!");
            } else if ((room != HOME) && ((!controls(player, room) &&
                            !Link_ok(room)) ||
                        !could_doit(player, room, A_LLINK))) {
                notify_quiet(player, "Permission denied.");
            } else {
                s_Dropto(thing, room);
                if (!Quiet(player))
                    notify_quiet(player, "Dropto set.");
            }
            break;
        case TYPE_GARBAGE:
            notify_quiet(player, "Permission denied.");
            break;
        default:
            STARTLOG(LOG_BUGS, "BUG", "OTYPE") {
                buff = alloc_mbuf("do_link.LOG.badtype");
                sprintf(buff, "Strange object type: object #%d = %d", thing,
                        Typeof(thing));
                log_text(buff);
                free_mbuf(buff);
                ENDLOG;
            }
    }
}

/*
 * ---------------------------------------------------------------------------
 * * do_parent: Set an object's parent field.
 */

void do_parent(player, cause, key, tname, pname)
    dbref player, cause;
    int key;
    char *tname, *pname;
{
    dbref thing, parent, curr;
    int lev;

    /*
     * get victim 
     */

    init_match(player, tname, NOTYPE);
    match_everything(0);
    thing = noisy_match_result();
    if (thing == NOTHING)
        return;

    /*
     * Make sure we can do it 
     */

    if (!Controls(player, thing)) {
        notify_quiet(player, "Permission denied.");
        return;
    }
    /*
     * Find out what the new parent is 
     */

    if (*pname) {
        init_match(player, pname, Typeof(thing));
        match_everything(0);
        parent = noisy_match_result();
        if (parent == NOTHING)
            return;

        /*
         * Make sure we have rights to set parent 
         */

        if (!Parentable(player, parent)) {
            notify_quiet(player, "Permission denied.");
            return;
        }
        /*
         * Verify no recursive reference 
         */

        ITER_PARENTS(parent, curr, lev) {
            if (curr == thing) {
                notify_quiet(player,
                        "You can't have yourself as a parent!");
                return;
            }
        }
    } else {
        parent = NOTHING;
    }

    s_Parent(thing, parent);
    if (!Quiet(thing) && !Quiet(player)) {
        if (parent == NOTHING)
            notify_quiet(player, "Parent cleared.");
        else
            notify_quiet(player, "Parent set.");
    }
}

/*
 * ---------------------------------------------------------------------------
 * * do_dig: Create a new room.
 */

void do_dig(player, cause, key, name, args, nargs)
    dbref player, cause;
    int key, nargs;
    char *name, *args[];
{
    dbref room;
    char *buff;

    /*
     * we don't need to know player's location!  hooray! 
     */

    if (!name || !*name) {
        notify_quiet(player, "Dig what?");
        return;
    }
    room = create_obj(player, TYPE_ROOM, name, 0);
    if (room == NOTHING)
        return;

    notify(player, tprintf("%s created with room number %d.", name, room));

    buff = alloc_sbuf("do_dig");
    if ((nargs >= 1) && args[0] && *args[0]) {
        sprintf(buff, "%d", room);
        open_exit(player, Location(player), args[0], buff);
    }
    if ((nargs >= 2) && args[1] && *args[1]) {
        sprintf(buff, "%d", Location(player));
        open_exit(player, room, args[1], buff);
    }
    free_sbuf(buff);
    if (key == DIG_TELEPORT)
        (void) move_via_teleport(player, room, cause, 0);
}

/*
 * ---------------------------------------------------------------------------
 * * do_create: Make a new object.
 */

void do_create(dbref player, dbref cause, int key, char *name, char *coststr) {
    dbref thing;
    int cost;
    char clearbuffer[MBUF_SIZE];

    cost = atoi(coststr);
    strip_ansi_r(clearbuffer, name, MBUF_SIZE);
    if (!name || !*name || (strlen(clearbuffer) == 0)) {
        notify_quiet(player, "Create what?");
        return;
    } else if (cost < 0) {
        notify_quiet(player,
                "You can't create an object for less than nothing!");
        return;
    }
    thing = create_obj(player, TYPE_THING, name, cost);
    if (thing == NOTHING)
        return;

    move_via_generic(thing, player, NOTHING, 0);
    s_Home(thing, new_home(player));
    if (!Quiet(player)) {
        notify(player, tprintf("%s created as object #%d", Name(thing),
                    thing));
    }
}


/*
 * ---------------------------------------------------------------------------
 * * do_clone: Create a copy of an object.
 */

void do_clone(player, cause, key, name, arg2)
    dbref player, cause;
    int key;
    char *name, *arg2;
{
    dbref clone, thing, new_owner, loc;
    FLAG rmv_flags;
    int cost;

    if ((key & CLONE_INVENTORY) || !Has_location(player))
        loc = player;
    else
        loc = Location(player);

    if (!Good_obj(loc))
        return;

    init_match(player, name, NOTYPE);
    match_everything(0);
    thing = noisy_match_result();
    if ((thing == NOTHING) || (thing == AMBIGUOUS))
        return;

    /*
     * Let players clone things set VISUAL.  It's easier than retyping in
     * all that data 
     */

    if (!Examinable(player, thing)) {
        notify_quiet(player, "Permission denied.");
        return;
    }
    if (isPlayer(thing)) {
        notify_quiet(player, "You cannot clone players!");
        return;
    }
    /*
     * You can only make a parent link to what you control 
     */

    if (!Controls(player, thing) && !Parent_ok(thing) &&
            (key & CLONE_PARENT)) {
        notify_quiet(player,
                tprintf("You don't control %s, ignoring /parent.",
                    Name(thing)));
        key &= ~CLONE_PARENT;
    }
    /*
     * Determine the cost of cloning 
     */

    new_owner = (key & CLONE_PRESERVE) ? Owner(thing) : Owner(player);
    if (key & CLONE_SET_COST) {
        cost = atoi(arg2);
        if (cost < mudconf.createmin)
            cost = mudconf.createmin;
        if (cost > mudconf.createmax)
            cost = mudconf.createmax;
        arg2 = NULL;
    } else {
        cost = 1;
        switch (Typeof(thing)) {
            case TYPE_THING:
                cost =
                    OBJECT_DEPOSIT((mudconf.
                                clone_copy_cost) ? Pennies(thing) : 1);
                break;
            case TYPE_ROOM:
                cost = mudconf.digcost;
                break;
            case TYPE_EXIT:
                if (!Controls(player, loc)) {
                    notify_quiet(player, "Permission denied.");
                    return;
                }
                cost = mudconf.digcost;
                break;
        }
    }

    /*
     * Go make the clone object 
     */

    if ((arg2 && *arg2) && ok_name(arg2))
        clone = create_obj(new_owner, Typeof(thing), arg2, cost);
    else
        clone = create_obj(new_owner, Typeof(thing), Name(thing), cost);
    if (clone == NOTHING)
        return;

    /*
     * Wipe out any old attributes and copy in the new data 
     */

    atr_free(clone);
    if (key & CLONE_PARENT)
        s_Parent(clone, thing);
    else
        atr_cpy(player, clone, thing);

    /*
     * Reset the name, since we cleared the attributes 
     */

    if ((arg2 && *arg2) && ok_name(arg2))
        s_Name(clone, arg2);
    else
        s_Name(clone, Name(thing));

    /*
     * Clear out problem flags from the original 
     */

    rmv_flags = WIZARD;
    if (!(key & CLONE_INHERIT) || (!Inherits(player)))
        rmv_flags |= INHERIT | IMMORTAL;
    s_Flags(clone, Flags(thing) & ~rmv_flags);

    /*
     * Tell creator about it 
     */

    if (!Quiet(player)) {
        if (arg2 && *arg2)
            notify(player,
                    tprintf("%s cloned as %s, new copy is object #%d.",
                        Name(thing), arg2, clone));
        else
            notify(player, tprintf("%s cloned, new copy is object #%d.",
                        Name(thing), clone));
    }
    /*
     * Put the new thing in its new home.  Break any dropto or link, then
     * * * * * * * try to re-establish it. 
     */

    switch (Typeof(thing)) {
        case TYPE_THING:
            s_Home(clone, clone_home(player, thing));
            move_via_generic(clone, loc, player, 0);
            break;
        case TYPE_ROOM:
            s_Dropto(clone, NOTHING);
            if (Dropto(thing) != NOTHING)
                link_exit(player, clone, Dropto(thing));
            break;
        case TYPE_EXIT:
            s_Exits(loc, insert_first(Exits(loc), clone));
            s_Exits(clone, loc);
            s_Location(clone, NOTHING);
            if (Location(thing) != NOTHING)
                link_exit(player, clone, Location(thing));
            break;
    }

    /*
     * If same owner run ACLONE, else halt it.  Also copy parent * if we
     * * * * * * can 
     */

    if (new_owner == Owner(thing)) {
        if (!(key & CLONE_PARENT))
            s_Parent(clone, Parent(thing));
        did_it(player, clone, 0, NULL, 0, NULL, A_ACLONE, (char **) NULL,
                0);
    } else {
        if (!(key & CLONE_PARENT) && (Controls(player, thing) ||
                    Parent_ok(thing)))
            s_Parent(clone, Parent(thing));
        s_Halted(clone);
    }
}

/*
 * ---------------------------------------------------------------------------
 * * do_pcreate: Create new players and robots.
 */

void do_pcreate(player, cause, key, name, pass)
    dbref player, cause;
    int key;
    char *name, *pass;
{
    int isrobot;
    dbref newplayer;

    isrobot = (key == PCRE_ROBOT) ? 1 : 0;
    newplayer = create_player(name, pass, player, isrobot, 0);
    if (newplayer == NOTHING) {
        notify_quiet(player, tprintf("Failure creating '%s'", name));
        return;
    }
    if (isrobot) {
        move_object(newplayer, Location(player));
        notify_quiet(player,
                tprintf("New robot '%s' created with password '%s'", name,
                    pass));
        notify_quiet(player, "Your robot has arrived.");
        STARTLOG(LOG_PCREATES, "CRE", "ROBOT") {
            log_name(newplayer);
            log_text((char *) " created by ");
            log_name(player);
            ENDLOG;
        }} else {
            move_object(newplayer, mudconf.start_room);
            notify_quiet(player,
                    tprintf("New player '%s' created with password '%s'", name,
                        pass));
            STARTLOG(LOG_PCREATES | LOG_WIZARD, "WIZ", "PCREA") {
                log_name(newplayer);
                log_text((char *) " created by ");
                log_name(player);
                ENDLOG;
            }}
}

/*
 * ---------------------------------------------------------------------------
 * * can_destroy_exit, can_destroy_player, do_destroy:
 * * Destroy things.
 */

static int can_destroy_exit(player, exit)
    dbref player, exit;
{
    dbref loc;

    loc = Exits(exit);
    if ((loc != Location(player)) && (loc != player) && !Wizard(player)) {
        notify_quiet(player, "You can not destroy exits in another room.");
        return 0;
    }
    return 1;
}

/*
 * ---------------------------------------------------------------------------
 * * destroyable: Indicates if target of a @destroy is a 'special' object in
 * * the database.
 */

static int destroyable(victim)
    dbref victim;
{
    if ((victim == mudconf.default_home) || (victim == mudconf.start_home)
            || (victim == mudconf.start_room) ||
            (victim == mudconf.master_room) || (victim == (dbref) 0) ||
            (God(victim)))
        return 0;
    return 1;
}


static int can_destroy_player(player, victim)
    dbref player, victim;
{
    if (!Wizard(player)) {
        notify_quiet(player, "Sorry, no suicide allowed.");
        return 0;
    }
    if (Wizard(victim)) {
        notify_quiet(player, "Even you can't do that!");
        return 0;
    }
    return 1;
}

void do_destroy(player, cause, key, what)
    dbref player, cause;
    int key;
    char *what;
{
    dbref thing;

    /*
     * You can destroy anything you control 
     */

    thing = match_controlled_quiet(player, what);

    /*
     * If you own a location, you can destroy its exits 
     */

    if ((thing == NOTHING) && controls(player, Location(player))) {
        init_match(player, what, TYPE_EXIT);
        match_exit();
        thing = last_match_result();
    }
    /*
     * You may destroy DESTROY_OK things in your inventory 
     */

    if (thing == NOTHING) {
        init_match(player, what, TYPE_THING);
        match_possession();
        thing = last_match_result();
        if ((thing != NOTHING) && !(isThing(thing) && Destroy_ok(thing))) {
            thing = NOPERM;
        }
    }
    /*
     * Return an error if we didn't find anything to destroy 
     */

    if (match_status(player, thing) == NOTHING) {
        return;
    }
    /*
     * Check SAFE and DESTROY_OK flags 
     */

    if (Safe(thing, player) && !(key & DEST_OVERRIDE) && !(isThing(thing)
                && Destroy_ok(thing))) {
        notify_quiet(player,
                "Sorry, that object is protected.  Use @destroy/override to destroy it.");
        return;
    }
    /*
     * Make sure we're not trying to destroy a special object 
     */

    if (!destroyable(thing)) {
        notify_quiet(player, "You can't destroy that!");
        return;
    }
    /*
     * Go do it 
     */

    switch (Typeof(thing)) {
        case TYPE_EXIT:
            if (can_destroy_exit(player, thing)) {
                if (Going(thing)) {
                    notify_quiet(player, "No sense beating a dead exit.");
                } else {
                    if (Hardcode(thing)) {
                        DisposeSpecialObject(player, thing);
                        c_Hardcode(thing);
                    }
                    if (Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
                        destroy_exit(thing);
                    } else {
                        notify(player,
                                "The exit shakes and begins to crumble.");
                        if (!Quiet(thing) && !Quiet(Owner(thing)))
                            notify_quiet(Owner(thing),
                                    tprintf
                                    ("You will be rewarded shortly for %s(#%d).",
                                     Name(thing), thing));
                        if ((Owner(thing) != player) && !Quiet(player)) {
                            notify_quiet(player,
                                    tprintf("Destroyed. #%d's %s(#%d)",
                                        Owner(thing), Name(thing), thing));
                            s_Going(thing);
                        }
                    }
                }
            }
            break;
        case TYPE_THING:
            if (Going(thing)) {
                notify_quiet(player, "No sense beating a dead object.");
            } else {
                if (Hardcode(thing)) {
                    DisposeSpecialObject(player, thing);
                    c_Hardcode(thing);
                }
                if (Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
                    destroy_thing(thing);
                } else {
                    notify(player, "The object shakes and begins to crumble.");
                    if (!Quiet(thing) && !Quiet(Owner(thing)))
                        notify_quiet(Owner(thing),
                                tprintf
                                ("You will be rewarded shortly for %s(#%d).",
                                 Name(thing), thing));
                    if ((Owner(thing) != player) && !Quiet(player))
                        notify_quiet(player, tprintf("Destroyed. %s's %s(#%d)",
                                    Name(Owner(thing)), Name(thing), thing));
                    s_Going(thing);
                }
            }
            break;
        case TYPE_PLAYER:
            if (can_destroy_player(player, thing)) {
                if (Going(thing)) {
                    notify_quiet(player, "No sense beating a dead player.");
                } else {
                    if (Hardcode(thing)) {
                        DisposeSpecialObject(player, thing);
                        c_Hardcode(thing);
                    }
                    if (Destroy_ok(thing)) {
                        atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
                        destroy_player(thing);
                    } else {
                        notify(player,
                                "The player shakes and begins to crumble.");
                        s_Going(thing);
                        atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
                    }
                }
            }
            break;
        case TYPE_ROOM:
            if (Going(thing)) {
                notify_quiet(player, "No sense beating a dead room.");
            } else {
                if (Destroy_ok(thing) || Destroy_ok(Owner(thing))) {
                    empty_obj(thing);
                    destroy_obj(NOTHING, thing);
                } else {
                    notify_all(thing, player,
                            "The room shakes and begins to crumble.");
                    if (!Quiet(thing) && !Quiet(Owner(thing)))
                        notify_quiet(Owner(thing),
                                tprintf
                                ("You will be rewarded shortly for %s(#%d).",
                                 Name(thing), thing));
                    if ((Owner(thing) != player) && !Quiet(player))
                        notify_quiet(player, tprintf("Destroyed. %s's %s(#%d)",
                                    Name(Owner(thing)), Name(thing), thing));
                    s_Going(thing);
                }
            }
    }
}