ds2.10/bin/
ds2.10/extra/
ds2.10/extra/crat/
ds2.10/extra/creremote/
ds2.10/extra/mingw/
ds2.10/extra/wolfpaw/
ds2.10/fluffos-2.16-ds05/
ds2.10/fluffos-2.16-ds05/Win32/
ds2.10/fluffos-2.16-ds05/compat/
ds2.10/fluffos-2.16-ds05/compat/simuls/
ds2.10/fluffos-2.16-ds05/include/
ds2.10/fluffos-2.16-ds05/testsuite/
ds2.10/fluffos-2.16-ds05/testsuite/clone/
ds2.10/fluffos-2.16-ds05/testsuite/command/
ds2.10/fluffos-2.16-ds05/testsuite/data/
ds2.10/fluffos-2.16-ds05/testsuite/etc/
ds2.10/fluffos-2.16-ds05/testsuite/include/
ds2.10/fluffos-2.16-ds05/testsuite/inherit/
ds2.10/fluffos-2.16-ds05/testsuite/inherit/master/
ds2.10/fluffos-2.16-ds05/testsuite/log/
ds2.10/fluffos-2.16-ds05/testsuite/single/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/compiler/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/efuns/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/operators/
ds2.10/fluffos-2.16-ds05/testsuite/u/
ds2.10/lib/cmds/admins/
ds2.10/lib/cmds/common/
ds2.10/lib/cmds/creators/include/
ds2.10/lib/daemon/services/
ds2.10/lib/daemon/tmp/
ds2.10/lib/doc/
ds2.10/lib/doc/bguide/
ds2.10/lib/doc/efun/all/
ds2.10/lib/doc/efun/arrays/
ds2.10/lib/doc/efun/buffers/
ds2.10/lib/doc/efun/compile/
ds2.10/lib/doc/efun/floats/
ds2.10/lib/doc/efun/functions/
ds2.10/lib/doc/efun/general/
ds2.10/lib/doc/efun/mixed/
ds2.10/lib/doc/efun/numbers/
ds2.10/lib/doc/efun/parsing/
ds2.10/lib/doc/help/classes/
ds2.10/lib/doc/help/races/
ds2.10/lib/doc/lfun/
ds2.10/lib/doc/lfun/all/
ds2.10/lib/doc/lfun/lib/abilities/
ds2.10/lib/doc/lfun/lib/armor/
ds2.10/lib/doc/lfun/lib/bank/
ds2.10/lib/doc/lfun/lib/bot/
ds2.10/lib/doc/lfun/lib/clay/
ds2.10/lib/doc/lfun/lib/clean/
ds2.10/lib/doc/lfun/lib/clerk/
ds2.10/lib/doc/lfun/lib/client/
ds2.10/lib/doc/lfun/lib/combat/
ds2.10/lib/doc/lfun/lib/connect/
ds2.10/lib/doc/lfun/lib/container/
ds2.10/lib/doc/lfun/lib/corpse/
ds2.10/lib/doc/lfun/lib/creator/
ds2.10/lib/doc/lfun/lib/daemon/
ds2.10/lib/doc/lfun/lib/damage/
ds2.10/lib/doc/lfun/lib/deterioration/
ds2.10/lib/doc/lfun/lib/donate/
ds2.10/lib/doc/lfun/lib/door/
ds2.10/lib/doc/lfun/lib/equip/
ds2.10/lib/doc/lfun/lib/file/
ds2.10/lib/doc/lfun/lib/fish/
ds2.10/lib/doc/lfun/lib/fishing/
ds2.10/lib/doc/lfun/lib/flashlight/
ds2.10/lib/doc/lfun/lib/follow/
ds2.10/lib/doc/lfun/lib/ftp_client/
ds2.10/lib/doc/lfun/lib/ftp_data_connection/
ds2.10/lib/doc/lfun/lib/fuel/
ds2.10/lib/doc/lfun/lib/furnace/
ds2.10/lib/doc/lfun/lib/genetics/
ds2.10/lib/doc/lfun/lib/holder/
ds2.10/lib/doc/lfun/lib/id/
ds2.10/lib/doc/lfun/lib/interactive/
ds2.10/lib/doc/lfun/lib/lamp/
ds2.10/lib/doc/lfun/lib/leader/
ds2.10/lib/doc/lfun/lib/light/
ds2.10/lib/doc/lfun/lib/limb/
ds2.10/lib/doc/lfun/lib/living/
ds2.10/lib/doc/lfun/lib/load/
ds2.10/lib/doc/lfun/lib/look/
ds2.10/lib/doc/lfun/lib/manipulate/
ds2.10/lib/doc/lfun/lib/meal/
ds2.10/lib/doc/lfun/lib/messages/
ds2.10/lib/doc/lfun/lib/player/
ds2.10/lib/doc/lfun/lib/poison/
ds2.10/lib/doc/lfun/lib/position/
ds2.10/lib/doc/lfun/lib/post_office/
ds2.10/lib/doc/lfun/lib/potion/
ds2.10/lib/doc/lfun/lib/room/
ds2.10/lib/doc/lfun/lib/server/
ds2.10/lib/doc/lfun/lib/spell/
ds2.10/lib/doc/lfun/lib/torch/
ds2.10/lib/doc/lfun/lib/vendor/
ds2.10/lib/doc/lfun/lib/virt_sky/
ds2.10/lib/doc/lfun/lib/weapon/
ds2.10/lib/doc/lfun/lib/worn_storage/
ds2.10/lib/doc/lpc/constructs/
ds2.10/lib/doc/lpc/etc/
ds2.10/lib/doc/lpc/intermediate/
ds2.10/lib/doc/lpc/types/
ds2.10/lib/doc/misc/
ds2.10/lib/doc/old/
ds2.10/lib/doc/phints/
ds2.10/lib/domains/
ds2.10/lib/domains/Praxis/adm/
ds2.10/lib/domains/Praxis/attic/
ds2.10/lib/domains/Praxis/cemetery/mon/
ds2.10/lib/domains/Praxis/data/
ds2.10/lib/domains/Praxis/death/
ds2.10/lib/domains/Praxis/mountains/
ds2.10/lib/domains/Praxis/obj/armour/
ds2.10/lib/domains/Praxis/obj/magic/
ds2.10/lib/domains/Praxis/obj/weapon/
ds2.10/lib/domains/Praxis/orc_valley/
ds2.10/lib/domains/Ylsrim/
ds2.10/lib/domains/Ylsrim/adm/
ds2.10/lib/domains/Ylsrim/armor/
ds2.10/lib/domains/Ylsrim/broken/
ds2.10/lib/domains/Ylsrim/fish/
ds2.10/lib/domains/Ylsrim/meal/
ds2.10/lib/domains/Ylsrim/npc/
ds2.10/lib/domains/Ylsrim/obj/
ds2.10/lib/domains/Ylsrim/virtual/
ds2.10/lib/domains/Ylsrim/weapon/
ds2.10/lib/domains/alpha/room/
ds2.10/lib/domains/alpha/virtual/
ds2.10/lib/domains/campus/adm/
ds2.10/lib/domains/campus/etc/
ds2.10/lib/domains/campus/meals/
ds2.10/lib/domains/campus/txt/ai/charles/
ds2.10/lib/domains/campus/txt/ai/charles/bak2/
ds2.10/lib/domains/campus/txt/ai/charles/bak2/bak1/
ds2.10/lib/domains/campus/txt/ai/charly/
ds2.10/lib/domains/campus/txt/ai/charly/bak/
ds2.10/lib/domains/campus/txt/jenny/
ds2.10/lib/domains/cave/doors/
ds2.10/lib/domains/cave/etc/
ds2.10/lib/domains/cave/meals/
ds2.10/lib/domains/cave/weap/
ds2.10/lib/domains/default/chamber/
ds2.10/lib/domains/default/creator/
ds2.10/lib/domains/default/doors/
ds2.10/lib/domains/default/etc/
ds2.10/lib/domains/default/vehicle/
ds2.10/lib/domains/default/virtual/
ds2.10/lib/domains/town/save/
ds2.10/lib/domains/town/txt/shame/
ds2.10/lib/domains/town/virtual/
ds2.10/lib/domains/town/virtual/bottom/
ds2.10/lib/domains/town/virtual/space/
ds2.10/lib/estates/
ds2.10/lib/ftp/
ds2.10/lib/lib/comp/
ds2.10/lib/lib/daemons/
ds2.10/lib/lib/daemons/include/
ds2.10/lib/lib/lvs/
ds2.10/lib/lib/user/
ds2.10/lib/lib/virtual/
ds2.10/lib/log/
ds2.10/lib/log/adm/
ds2.10/lib/log/archive/
ds2.10/lib/log/chan/
ds2.10/lib/log/errors/
ds2.10/lib/log/law/adm/
ds2.10/lib/log/law/email/
ds2.10/lib/log/law/names/
ds2.10/lib/log/law/sites-misc/
ds2.10/lib/log/law/sites-register/
ds2.10/lib/log/law/sites-tempban/
ds2.10/lib/log/law/sites-watch/
ds2.10/lib/log/open/
ds2.10/lib/log/reports/
ds2.10/lib/log/router/
ds2.10/lib/log/secure/
ds2.10/lib/log/watch/
ds2.10/lib/obj/book_source/
ds2.10/lib/obj/include/
ds2.10/lib/powers/prayers/
ds2.10/lib/powers/spells/
ds2.10/lib/realms/template/
ds2.10/lib/realms/template/adm/
ds2.10/lib/realms/template/area/
ds2.10/lib/realms/template/area/armor/
ds2.10/lib/realms/template/area/npc/
ds2.10/lib/realms/template/area/obj/
ds2.10/lib/realms/template/area/room/
ds2.10/lib/realms/template/area/weap/
ds2.10/lib/realms/template/bak/
ds2.10/lib/realms/template/cmds/
ds2.10/lib/save/kills/o/
ds2.10/lib/secure/cfg/classes/
ds2.10/lib/secure/cmds/builders/
ds2.10/lib/secure/cmds/creators/include/
ds2.10/lib/secure/cmds/players/include/
ds2.10/lib/secure/daemon/imc2server/
ds2.10/lib/secure/daemon/include/
ds2.10/lib/secure/lib/
ds2.10/lib/secure/lib/include/
ds2.10/lib/secure/lib/net/include/
ds2.10/lib/secure/lib/std/
ds2.10/lib/secure/log/adm/
ds2.10/lib/secure/log/bak/
ds2.10/lib/secure/log/intermud/
ds2.10/lib/secure/log/network/
ds2.10/lib/secure/modules/
ds2.10/lib/secure/npc/
ds2.10/lib/secure/obj/include/
ds2.10/lib/secure/room/
ds2.10/lib/secure/save/
ds2.10/lib/secure/save/backup/
ds2.10/lib/secure/save/boards/
ds2.10/lib/secure/save/players/g/
ds2.10/lib/secure/tmp/
ds2.10/lib/secure/upgrades/files/
ds2.10/lib/secure/verbs/creators/
ds2.10/lib/std/board/
ds2.10/lib/std/lib/
ds2.10/lib/verbs/admins/include/
ds2.10/lib/verbs/builders/
ds2.10/lib/verbs/common/
ds2.10/lib/verbs/common/include/
ds2.10/lib/verbs/creators/
ds2.10/lib/verbs/creators/include/
ds2.10/lib/verbs/rooms/
ds2.10/lib/verbs/rooms/include/
ds2.10/lib/www/client/
ds2.10/lib/www/errors/
ds2.10/lib/www/images/
ds2.10/win32/
/*
 * avltree.c
 *
 * This program text was created by Paul Vixie using examples from the book:
 * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
 * 0-13-022005-1.  This code and associated documentation is hereby placed
 * in the public domain.
 */

/********************************* README *********************************

  AVL Trees V1.0
  24-July-1987
  Paul Vixie

  This library and test program are useful for creating and using balanced
  binary trees (AVL trees).  The tree is held in memory, using malloc(3) to
  allocate storage.  A better version would allow file-based trees in
  addition; once memory mapped files hit the UNIX(tm) community, this will
  be much easier to do.  In the meanwhile, these routines have been very
  useful to be for symbol tables and the like.  (Yes, I'm sure hashing is
  better in some way, but I've used this for symbol tables, just the same.)

  I cannot take credit for the algorithms.  See "Algorithms & Data Structures,"
  Niklaus Wirth, Prentice-Hall 1986, ISBN 0-13-022005-1.  This is an update of
  Wirth's previous book, titled "Algorythms + Data Structures = Programs,"
  which used Pascal as the language for examples.  This later book uses the
  newer Modula-2 for it's examples; this tree code was created using the
  Modula-2 examples as guidelines.  At the time I typed this stuff in (about
  a year ago, in July 1987), I understood how it all worked.  Today, well...

  This code is hereby placed in the public domain, unless restrictions apply
  from Prentice-Hall on the algorithms themselves.  If you use or redistribute
  this code, please leave my name (and Wirth's) in the comments.

 **************************************************************************/

#include "std.h"
#include "avltree.h"

/*
 * Prototypes for local functions
 */
static void sprout (tree **, char *, int *, int (*) (void *, void *), int (*) (void *));
static int avldelete (tree **, int (*) (void *, void *), char *, int (*) (void *), int *, int *);
static void del (tree **, int *, tree **, int (*) (void *), int *);
static void balanceL (tree **, int *);
static void balanceR (tree **, int *);


void tree_init (tree ** ppr_tree)
{
    *ppr_tree = NULL;
    return;
}


char *tree_srch(tree *ppr_tree, int (*pfi_compare) (void *, void *), char *pc_user){
    register int i_comp;

    while (ppr_tree) {
        i_comp = (*pfi_compare) (pc_user, ppr_tree->tree_p);
        if (i_comp > 0) {
            ppr_tree = ppr_tree->tree_r;
            continue;
        }
        if (i_comp < 0) {
            ppr_tree = ppr_tree->tree_l;
            continue;
        }
        /*
         * not higher, not lower... this must be the one.
         */
        return ppr_tree->tree_p;
    }

    /*
     * grounded. NOT found.
     */
    return NULL;
}


void tree_add(tree **ppr_tree, int (*pfi_compare) (void *, void *), char *pc_user, int (*pfi_delete) (void *)){
    int i_balance = 0;

    sprout(ppr_tree, pc_user, &i_balance, pfi_compare, pfi_delete);
    return;
}


static void sprout(tree **ppr, char *pc_data, int *pi_balance, int (*pfi_compare) (void *, void *), int (*pfi_delete) (void *)){
    tree *p1, *p2;
    int cmp;

    /*
     * are we grounded?  if so, add the node "here" and set the rebalance
     * flag, then exit.
     */
    if (!*ppr) {
        *ppr = ALLOCATE(tree, TAG_UID, "sprout");
        (*ppr)->tree_l = NULL;
        (*ppr)->tree_r = NULL;
        (*ppr)->tree_b = 0;
        (*ppr)->tree_p = pc_data;
        *pi_balance = 1;
        return;
    }
    /*
     * compare the data using routine passed by caller.
     */
    cmp = (*pfi_compare) (pc_data, (*ppr)->tree_p);

    /*
     * if LESS, prepare to move to the left.
     */
    if (cmp < 0) {
        sprout(&(*ppr)->tree_l, pc_data, pi_balance,
                pfi_compare, pfi_delete);
        if (*pi_balance) {	/* left branch has grown longer */
            switch ((*ppr)->tree_b) {
                case 1:		/* right branch WAS longer; balance is ok now */
                    (*ppr)->tree_b = 0;
                    *pi_balance = 0;
                    break;
                case 0:		/* balance WAS okay; now left branch longer */
                    (*ppr)->tree_b = -1;
                    break;
                case -1:
                    /* left branch was already too long. rebalnce */
                    p1 = (*ppr)->tree_l;
                    if (p1->tree_b == -1) {	/* LL */
                        (*ppr)->tree_l = p1->tree_r;
                        p1->tree_r = *ppr;
                        (*ppr)->tree_b = 0;
                        *ppr = p1;
                    } else {	/* double LR */
                        p2 = p1->tree_r;
                        p1->tree_r = p2->tree_l;
                        p2->tree_l = p1;

                        (*ppr)->tree_l = p2->tree_r;
                        p2->tree_r = *ppr;

                        if (p2->tree_b == -1)
                            (*ppr)->tree_b = 1;
                        else
                            (*ppr)->tree_b = 0;

                        if (p2->tree_b == 1)
                            p1->tree_b = -1;
                        else
                            p1->tree_b = 0;
                        *ppr = p2;
                    }		/* else */
                    (*ppr)->tree_b = 0;
                    *pi_balance = 0;
            }			/* switch */
        }			/* if */
        return;
    }				/* if */
    /*
     * if MORE, prepare to move to the right.
     */
    if (cmp > 0) {
        sprout(&(*ppr)->tree_r, pc_data, pi_balance,
                pfi_compare, pfi_delete);
        if (*pi_balance) {	/* right branch has grown longer */
            switch ((*ppr)->tree_b) {
                case -1:
                    (*ppr)->tree_b = 0;
                    *pi_balance = 0;
                    break;
                case 0:
                    (*ppr)->tree_b = 1;
                    break;
                case 1:
                    p1 = (*ppr)->tree_r;
                    if (p1->tree_b == 1) {	/* RR */
                        (*ppr)->tree_r = p1->tree_l;
                        p1->tree_l = *ppr;
                        (*ppr)->tree_b = 0;
                        *ppr = p1;
                    } else {	/* double RL */
                        p2 = p1->tree_l;
                        p1->tree_l = p2->tree_r;
                        p2->tree_r = p1;

                        (*ppr)->tree_r = p2->tree_l;
                        p2->tree_l = *ppr;

                        if (p2->tree_b == 1)
                            (*ppr)->tree_b = -1;
                        else
                            (*ppr)->tree_b = 0;

                        if (p2->tree_b == -1)
                            p1->tree_b = 1;
                        else
                            p1->tree_b = 0;

                        *ppr = p2;
                    }		/* else */
                    (*ppr)->tree_b = 0;
                    *pi_balance = 0;
            }			/* switch */
        }			/* if */
        return;
    }				/* if */
    /*
     * not less, not more: this is the same key!  replace...
     */
    *pi_balance = 0;
    if (pfi_delete)
        (*pfi_delete) ((*ppr)->tree_p);
    (*ppr)->tree_p = pc_data;
    return;
}


int tree_delete(tree **ppr_p, int (*pfi_compare) (void *, void *), char *pc_user, int (*pfi_uar) (void *)){
    int i_balance = 0, i_uar_called = 0;

    return avldelete(ppr_p, pfi_compare, pc_user, pfi_uar,
            &i_balance, &i_uar_called);
}


static int avldelete(tree **ppr_p, int (*pfi_compare) (void *, void *), char *pc_user, int (*pfi_uar) (void *), int *pi_balance, int *pi_uar_called){
    tree *pr_q;
    int i_comp, i_ret;

    if (*ppr_p == NULL) {
        return 0;
    }
    i_comp = (*pfi_compare) ((*ppr_p)->tree_p, pc_user);
    if (i_comp > 0) {
        i_ret = avldelete(&(*ppr_p)->tree_l, pfi_compare, pc_user, pfi_uar,
                pi_balance, pi_uar_called);
        if (*pi_balance)
            balanceL(ppr_p, pi_balance);
    } else if (i_comp < 0) {
        i_ret = avldelete(&(*ppr_p)->tree_r, pfi_compare, pc_user, pfi_uar,
                pi_balance, pi_uar_called);
        if (*pi_balance)
            balanceR(ppr_p, pi_balance);
    } else {
        pr_q = *ppr_p;
        if (pr_q->tree_r == NULL) {
            *ppr_p = pr_q->tree_l;
            *pi_balance = 1;
        } else if (pr_q->tree_l == NULL) {
            *ppr_p = pr_q->tree_r;
            *pi_balance = 1;
        } else {
            del(&pr_q->tree_l, pi_balance, &pr_q, pfi_uar,
                    pi_uar_called);
            if (*pi_balance)
                balanceL(ppr_p, pi_balance);
        }
        FREE(pr_q);
        if (!*pi_uar_called && pfi_uar)
            (*pfi_uar) (pr_q->tree_p);
        i_ret = 1;
    }
    return i_ret;
}


static void del(tree **ppr_r, int *pi_balance, tree **ppr_q, int (*pfi_uar) (void *), int *pi_uar_called){
    if ((*ppr_r)->tree_r != NULL) {
        del(&(*ppr_r)->tree_r, pi_balance, ppr_q, pfi_uar,
                pi_uar_called);
        if (*pi_balance)
            balanceR(ppr_r, pi_balance);
    } else {
        if (pfi_uar)
            (*pfi_uar) ((*ppr_q)->tree_p);
        *pi_uar_called = 1;
        (*ppr_q)->tree_p = (*ppr_r)->tree_p;
        *ppr_q = *ppr_r;
        *ppr_r = (*ppr_r)->tree_l;
        *pi_balance = 1;
    }

    return;
}


static void balanceL (tree ** ppr_p, int * pi_balance){
    tree *p1, *p2;
    int b1, b2;

    switch ((*ppr_p)->tree_b) {
        case -1:
            (*ppr_p)->tree_b = 0;
            break;
        case 0:
            (*ppr_p)->tree_b = 1;
            *pi_balance = 0;
            break;
        case 1:
            p1 = (*ppr_p)->tree_r;
            b1 = p1->tree_b;
            if (b1 >= 0) {
                (*ppr_p)->tree_r = p1->tree_l;
                p1->tree_l = *ppr_p;
                if (b1 == 0) {
                    (*ppr_p)->tree_b = 1;
                    p1->tree_b = -1;
                    *pi_balance = 0;
                } else {
                    (*ppr_p)->tree_b = 0;
                    p1->tree_b = 0;
                }
                *ppr_p = p1;
            } else {
                p2 = p1->tree_l;
                b2 = p2->tree_b;
                p1->tree_l = p2->tree_r;
                p2->tree_r = p1;
                (*ppr_p)->tree_r = p2->tree_l;
                p2->tree_l = *ppr_p;
                if (b2 == 1)
                    (*ppr_p)->tree_b = -1;
                else
                    (*ppr_p)->tree_b = 0;
                if (b2 == -1)
                    p1->tree_b = 1;
                else
                    p1->tree_b = 0;
                *ppr_p = p2;
                p2->tree_b = 0;
            }
    }
    return;
}


static void balanceR (tree ** ppr_p, int * pi_balance){
    tree *p1, *p2;
    int b1, b2;

    switch ((*ppr_p)->tree_b) {
        case 1:
            (*ppr_p)->tree_b = 0;
            break;
        case 0:
            (*ppr_p)->tree_b = -1;
            *pi_balance = 0;
            break;
        case -1:
            p1 = (*ppr_p)->tree_l;
            b1 = p1->tree_b;
            if (b1 <= 0) {
                (*ppr_p)->tree_l = p1->tree_r;
                p1->tree_r = *ppr_p;
                if (b1 == 0) {
                    (*ppr_p)->tree_b = -1;
                    p1->tree_b = 1;
                    *pi_balance = 0;
                } else {
                    (*ppr_p)->tree_b = 0;
                    p1->tree_b = 0;
                }
                *ppr_p = p1;
            } else {
                p2 = p1->tree_r;
                b2 = p2->tree_b;
                p1->tree_r = p2->tree_l;
                p2->tree_l = p1;
                (*ppr_p)->tree_l = p2->tree_r;
                p2->tree_r = *ppr_p;
                if (b2 == -1)
                    (*ppr_p)->tree_b = 1;
                else
                    (*ppr_p)->tree_b = 0;
                if (b2 == 1)
                    p1->tree_b = -1;
                else
                    p1->tree_b = 0;
                *ppr_p = p2;
                p2->tree_b = 0;
            }
    }
    return;
}


    int tree_trav(tree **ppr_tree, int (*pfi_uar) (void *)){
        if (!*ppr_tree)
            return 1;

        if (!tree_trav(&(**ppr_tree).tree_l, pfi_uar))
            return 0;
        if (!(*pfi_uar) ((**ppr_tree).tree_p))
            return 0;
        if (!tree_trav(&(**ppr_tree).tree_r, pfi_uar))
            return 0;
        return 1;
    }


void tree_mung(tree **ppr_tree, int (*pfi_uar) (void *)){
    if (*ppr_tree) {
        tree_mung(&(**ppr_tree).tree_l, pfi_uar);
        tree_mung(&(**ppr_tree).tree_r, pfi_uar);
        if (pfi_uar)
            (*pfi_uar) ((**ppr_tree).tree_p);
        FREE(*ppr_tree);
        *ppr_tree = NULL;
    }
    return;
}