]> jfr.im git - irc/gameservirc.git/blobdiff - gameserv/gameserv.cpp
Fixed bug # 998029 causing a crash on gentoo systems due to a mistake in code:
[irc/gameservirc.git] / gameserv / gameserv.cpp
index 5d9b56b1b5f7e8c61e91ca57d04cfd3de6695da2..d1b50f7ab84013cf67b543fb66c3947aac7502ad 100644 (file)
@@ -3,6 +3,7 @@
 #include "extern.h"
 #include "flags.h"
 #include "list.h"
+#include "level.h"
 #include "sockhelp.h"
 
 #include <cctype>
@@ -22,16 +23,9 @@ using std::ios;
 
 #endif
 
-// this will be hash.cpp start
-// thank you wcampbel
-unsigned long sHASH(const unsigned char *name);
-unsigned long iHASH(const unsigned char *name);
-List<aClient> players[U_TABLE_SIZE];
-// this will be hash.cpp end
 
-
-Monster *monsters[LEVELS][MONSTERS];   // Monsters per level. Total = MONSTERS * LEVELS
 Monster boss;                          // The boss monster
+Level levels[LEVELS];                  // The newest way to store monsters
 
 Monster *masters[LEVELS];              // A master for each level
 
@@ -61,7 +55,7 @@ bool check_password(char *name, char *plaintext); // Finds a password for the gi
 
 bool shuttingdown;
 bool timedOut(Player *p);
-void  updateTS(Player *p);
+void updateTS(Player *p);
 void timeOutEvent(Player *p);
 
 bool is_playing(char *u); // True if the given nickname in the clients list is playing.
@@ -93,14 +87,15 @@ void refreshall();
 void updateTS(Player *p);
 void reset(Player *p);
 void init_masters();
-void init_monsters();
 bool load_monsters();
+bool load_levels();
 void delete_monsters();
 void delete_masters();
 
 void do_admin(char *u);
 void do_attack(char *u);
 void do_bank(char *u);
+void do_check(char *u);
 void do_fight(char *u);
 void do_heal(char *u);
 void do_help(char *u);
@@ -165,20 +160,6 @@ void gameserv(char *source, char *buf)
        log("Source: %s  Command: %s", source, cmd);
     #endif
 
-    struct tm *tm;
-    time_t ti;
-    time(&ti);
-    tm = localtime(&ti);
-
-    int curday = tm->tm_mday;
-
-    if (curday != day)
-    {
-        refreshall();
-        day = curday;
-       save_day(); // here i come to save the day!
-    }
-
     if (strnicmp(cmd, "\1PING", 6) == 0)
     {
        char *ts;
@@ -198,6 +179,8 @@ void gameserv(char *source, char *buf)
        do_fight(source);
     } else if (stricmp(cmd, "ATTACK") == 0) {
        do_attack(source);
+    } else if (stricmp(cmd, "CHECK") == 0) {
+       do_check(source);
     } else if (stricmp(cmd, "RUN") == 0) {
        do_run(source);
     } else if (stricmp(cmd, "USE") == 0) {
@@ -226,6 +209,8 @@ void gameserv(char *source, char *buf)
        do_list(source);
     } else if (stricmp(cmd, "LOGOUT") == 0) {
        do_logout(source);
+    } else if (stricmp(cmd, "NEWS") == 0) {
+       do_news(source);
     } else if (stricmp(cmd, "REGISTER") == 0) {
        do_register(source);
     } else if (stricmp(cmd, "IDENTIFY") == 0) {
@@ -318,6 +303,14 @@ void gameserv(char *source, char *buf)
            char *rest = strtok(NULL, "");
            raw("%s", rest);
        }
+    } else if (stricmp(cmd, "PRINT") == 0) {
+       for (int x = 0; x < LEVELS; x++)
+           levels[x].monsters.print();
+    } else if (stricmp(cmd, "RANDOM") == 0) {
+       char *rstr = strtok(NULL, "");
+       range trange;
+       trange.setRange(rstr);
+       notice(s_GameServ, source, "Random number in that range: %d", trange.random());
     #endif
     } else {
        aClient *user;
@@ -404,6 +397,20 @@ void showstats(const char *u, const char *nick)
         space = spaces(strlen(buf), " ");
         notice(s_GameServ, sender->getNick(), "%s%sPlayer Fights: %d", buf, space, ni->stats->player_fights);
         delete [] space;
+       Pouch *inv = &ni->stats->inventory;
+
+       notice(s_GameServ, u, "Potions");
+       sprintf(buf, "Healing: %d", inv->Healing());
+       space = spaces(strlen(buf), " ");
+       notice(s_GameServ, sender->getNick(), "%s%sHP: %d", buf, 
+               space, inv->HP());
+       delete [] space;
+
+       sprintf(buf, "Strength: %d", inv->Strength());
+       space = spaces(strlen(buf), " ");
+       notice(s_GameServ, sender->getNick(), "%s%sDefense: %d", buf, 
+               space, inv->Defense());
+       delete [] space;
     }
     else
     {
@@ -576,9 +583,25 @@ char *strtok(char *str, const char *delim)
 }
 #endif
 
+void do_check(char *u)
+{
+    int days, hours, minutes, seconds;
+    long complete;
+    complete = (lastrefresh + refreshperiod) - time(NULL);
+    days = complete / 86400;
+    hours = (complete % 86400) / 3600;
+    minutes = (complete % 86400) % 3600 / 60;
+    seconds = (complete % 86400) % 3600 % 60;
+
+    notice(s_GameServ, u, "Time left to next refresh: %dd %dh %dm %ds", 
+          days, hours, minutes, seconds);
+}
+
 void do_list(char *u)
 {
     aClient *user;
+    char *cmd = strtok(NULL, " ");
+
     if (!(user = find(u)))
     {
        log("Fatal Error: Couldn't find %s in the client list", u);
@@ -594,25 +617,29 @@ void do_list(char *u)
 
     ListNode<aClient> *temp;
     bool header = false;
+
   for (unsigned long x = 0; x < U_TABLE_SIZE; x++)
   {
     temp = players[x].First();
     if (!players[x].isEmpty())
     {
-       if (!header)
-       {
-           notice(s_GameServ, u, "People Playing:");
-           header = true;
-       }
        while(temp)
        {
-           #ifdef P10
-           notice(s_GameServ, u, "IRC: %s     Game: %s", temp->getData()->getRealNick(), 
-                  temp->getData()->stats->name);
-           #else
-           notice(s_GameServ, u, "IRC: %s     Game: %s", temp->getData()->getNick(), 
-                  temp->getData()->stats->name);
-           #endif
+           if (cmd || is_playing(temp->getData()))
+           {
+               if (!header)
+               {
+                   notice(s_GameServ, u, "Players:");
+                   header = true;
+               }
+               #ifdef P10
+               notice(s_GameServ, u, "IRC: %s     Game: %s", temp->getData()->getRealNick(), 
+                       temp->getData()->stats->name);
+               #else
+               notice(s_GameServ, u, "IRC: %s     Game: %s", temp->getData()->getNick(), 
+                       temp->getData()->stats->name);
+               #endif
+           }
 
            temp = temp->Next();
        }
@@ -786,6 +813,9 @@ void do_register(char *u)
            temp = players[hv].insertAtBack_RLN(user);
            temp->setPtr(user); // This is an extra step, but necessary for now
 
+           // Update the last login time
+           user->stats->lastlogin = time(NULL);
+
            notice(s_GameServ, u, "Player %s registered with password %s.", user->stats->name, password);
            notice(s_GameServ, u, "Write this password down. If you lose it, there is no way to retrieve it!");
            log("Nickname %s registered player %s.", u, user->stats->name);
@@ -861,7 +891,12 @@ void do_identify(char *u)
        setPlaying(user); // set the playing flag
 
        temp->setPtr(user);
-       notice(s_GameServ, u, "Password Accepted. Identified.");            
+
+       // Update the last login time
+       user->stats->lastlogin = time(NULL);
+
+       notice(s_GameServ, u, "Password Accepted. Identified.");
+       showNews(u, todaysnews);
     }
 }
 
@@ -918,7 +953,7 @@ void init_masters()
 
     strcpy(masters[0]->name, "Old Bones");
     strcpy(masters[0]->weapon, "Dull Sword Cane");
-    masters[0]->strength = 30;
+    masters[0]->strength = 32;
     masters[0]->gold = 0;
     masters[0]->exp = 0;
     masters[0]->maxhp = 35;
@@ -927,7 +962,7 @@ void init_masters()
 
     strcpy(masters[1]->name, "Master Chang");
     strcpy(masters[1]->weapon, "Nanchaku");
-    masters[1]->strength = 45;
+    masters[1]->strength = 48;
     masters[1]->gold = 0;
     masters[1]->exp = 0;
     masters[1]->maxhp = 51;
@@ -936,7 +971,7 @@ void init_masters()
 
     strcpy(masters[2]->name, "Chuck Norris");
     strcpy(masters[2]->weapon, "Ranger Kick");
-    masters[2]->strength = 83;
+    masters[2]->strength = 88;
     masters[2]->gold = 0;
     masters[2]->exp = 0;
     masters[2]->maxhp = 100;
@@ -946,7 +981,7 @@ void init_masters()
 
     strcpy(masters[3]->name, "Mr. Miagi");
     strcpy(masters[3]->weapon, "Petrified Bonsai");
-    masters[3]->strength = 159;
+    masters[3]->strength = 169;
     masters[3]->gold = 0;
     masters[3]->exp = 0;
     masters[3]->maxhp = 165;
@@ -955,7 +990,7 @@ void init_masters()
 
     strcpy(masters[4]->name, "Jackie Chan");
     strcpy(masters[4]->weapon, "Kung Fu Kick");
-    masters[4]->strength = 260;
+    masters[4]->strength = 275;
     masters[4]->gold = 0;
     masters[4]->exp = 0;
     masters[4]->maxhp = 232;
@@ -964,7 +999,7 @@ void init_masters()
 
     strcpy(masters[5]->name, "Jet Li");
     strcpy(masters[5]->weapon, "Motorcycle");
-    masters[5]->strength = 325;
+    masters[5]->strength = 347;
     masters[5]->gold = 0;
     masters[5]->exp = 0;
     masters[5]->maxhp = 504;
@@ -974,7 +1009,7 @@ void init_masters()
 
     strcpy(masters[6]->name, "Muhammad Ali");
     strcpy(masters[6]->weapon, "Quick Jab");
-    masters[6]->strength = 380;
+    masters[6]->strength = 515;
     masters[6]->gold = 0;
     masters[6]->exp = 0;
     masters[6]->maxhp = 1078;
@@ -983,7 +1018,7 @@ void init_masters()
 
     strcpy(masters[7]->name, "Li Mu Bai");
     strcpy(masters[7]->weapon, "Green Destiny");
-    masters[7]->strength = 462;
+    masters[7]->strength = 655;
     masters[7]->gold = 0;
     masters[7]->exp = 0;
     masters[7]->maxhp = 2207;
@@ -993,7 +1028,7 @@ void init_masters()
 
     strcpy(masters[8]->name, "Jimmy Wang Yu");
     strcpy(masters[8]->weapon, "Flying Guillotine");
-    masters[8]->strength = 511;
+    masters[8]->strength = 819;
     masters[8]->gold = 0;
     masters[8]->exp = 0;
     masters[8]->maxhp = 2780;
@@ -1002,7 +1037,7 @@ void init_masters()
 
     strcpy(masters[9]->name, "Wong Fei Hung");
     strcpy(masters[9]->weapon, "Drunken Boxing");
-    masters[9]->strength = 618;
+    masters[9]->strength = 1014;
     masters[9]->gold = 0;
     masters[9]->exp = 0;
     masters[9]->maxhp = 3046;
@@ -1011,7 +1046,7 @@ void init_masters()
 
     strcpy(masters[10]->name, "Bruce Lee");
     strcpy(masters[10]->weapon, "Fists of fury");
-    masters[10]->strength = 725;
+    masters[10]->strength = 1286;
     masters[10]->gold = 0;
     masters[10]->exp = 0;
     masters[10]->maxhp = 3988;
@@ -1019,25 +1054,10 @@ void init_masters()
     strcpy(masters[10]->death, "You must learn to concentrate. It is like a finger pointing away to the moon... DONT concentrate on the finger, or you will miss all the heavenly glory.");
 }
 
-void init_monsters()
-{
-    #ifdef DEBUGMODE
-       log("Calling delete_monsters");
-    #endif
-
-    delete_monsters();
-
-    for (int x = 0; x < LEVELS; x++)
-       for (int y = 0; y < MONSTERS; y++)
-           monsters[x][y] = new Monster();
-}
-
 void delete_monsters()
 {
     for (int x = 0; x < LEVELS; x++)
-       for (int y = 0; y < MONSTERS; y++)
-           if (monsters[x][y])
-               delete monsters[x][y];
+       levels[x].monsters.deleteNodes();
 }
 
 void delete_masters()
@@ -1331,19 +1351,35 @@ void do_use(char *u)
 
     p = &user->stats->inventory;
 
-    if (stricmp(item, "HEALTH") == 0)
+    if (stricmp(item, "HEALING") == 0)
     {
        if (p->Healing() <= 0)
        {
-           notice(s_GameServ, u, "You are out of Health Potions!");
+           notice(s_GameServ, u, "You are out of Healing Potions!");
            return;
        }
-       int oldhealth = user->stats->hp;
+       int oldhealing = user->stats->hp;
+       user->stats->hp += (10 * user->stats->level) + (rand() % 10) * user->stats->level;
+       if (user->stats->hp - user->stats->maxhp >= 100)
+       {
+           user->stats->hp = user->stats->maxhp + 100;
+
+           if (oldhealing >= (user->stats->maxhp + 100))
+           {
+               notice(s_GameServ, u, "You cannot hold anymore HP!");
+               return;
+           }
+       }
+
        notice(s_GameServ, u, "You hastiliy gulp down the flask of cool life-giving waters.");
        notice(s_GameServ, u, "Rejuvination spreads throughout your body.");
-       user->stats->hp += (10 * user->stats->level) + (rand() % 10) * user->stats->level;
-       notice(s_GameServ, u, "You gain %d HP!", user->stats->hp - oldhealth);
+       notice(s_GameServ, u, "You gain %d HP!", user->stats->hp - oldhealing);
        p->decHealing();
+       if (player_fight(user))
+       {
+           notice(s_GameServ, user->stats->battle->getNick(),
+               "%s has used a healing potion!");
+       }
     }
     else if (stricmp(item, "STRENGTH") == 0)
     {
@@ -1358,6 +1394,11 @@ void do_use(char *u)
        user->stats->strength += 1 + (rand() % 10 >= 8 ? 1 : 0); // 1-2
        notice(s_GameServ, u, "You gain %d Strength points!", user->stats->strength - oldstrength);
        p->decStrength();
+       if (player_fight(user))
+       {
+           notice(s_GameServ, user->stats->battle->getNick(),
+               "%s has used a strength potion!");
+       }
     }
     else if (stricmp(item, "DEFENSE") == 0)
     {
@@ -1372,6 +1413,11 @@ void do_use(char *u)
        user->stats->defense += 1 + (rand() % 10 >= 8 ? 1 : 0); // 1-2
        notice(s_GameServ, u, "You gain %d Defense points!", user->stats->defense - olddefense);
        p->decDefense();
+       if (player_fight(user))
+       {
+           notice(s_GameServ, user->stats->battle->getNick(),
+               "%s has used a defense potion!");
+       }
     }
     else if (stricmp(item, "HP") == 0)
     {
@@ -1387,10 +1433,15 @@ void do_use(char *u)
 
        notice(s_GameServ, u, "You gain %d Maximum hit points!", user->stats->maxhp - oldHP);
        p->decHP();
+       if (player_fight(user))
+       {
+           notice(s_GameServ, user->stats->battle->getNick(),
+               "%s has used a HP potion!");
+       }
     }
     else
     {
-       notice(s_GameServ, u, "SYNTAX: /msg %S USE {HEALTH | STRENGTH | DEFENSE}");
+       notice(s_GameServ, u, "SYNTAX: /msg %S USE {HEALING | STRENGTH | DEFENSE | HP}");
        return;
     }
 
@@ -1610,7 +1661,12 @@ void do_attack(char *u)
     if (hit >= fight->hp)
     {
         if (master_fight(ni))
+       {
             notice(s_GameServ, u, "You have bested %s!", fight->name);
+           addNews(todaysnews, "%s has bested %s and moved "\
+                   "to level %d", ni->stats->name, fight->name,
+                   (ni->stats->level + 1));
+       }
         else
             notice(s_GameServ, u, "You have killed \ 2%s\ 2!", fight->name);
 
@@ -1622,12 +1678,13 @@ void do_attack(char *u)
        // then set your exp to 2bil. (2 billion max)... otherwise add them.
        // This could be a problem with overflowing out of the sign bit.
        // Unsigned long int maybe? Leave it for now.
-        ni->stats->exp = ( (ni->stats->exp + fight->exp) > 2000000000 ? 2000000000 : 
-                               ni->stats->exp + fight->exp);
-
-        ni->stats->gold = (ni->stats->gold + fight->gold > 2000000000 ? 2000000000 : 
-                               ni->stats->gold + fight->gold);
+       ni->stats->exp += fight->exp;
+       if (ni->stats->exp < 0 || ni->stats->exp > 2000000000)
+           ni->stats->exp = 2000000000;
 
+       ni->stats->gold += fight->gold;
+       if (ni->stats->gold < 0 || ni->stats->gold > 2000000000)
+           ni->stats->gold = 2000000000;
 
         if (master_fight(ni))
         {
@@ -1636,7 +1693,6 @@ void do_attack(char *u)
                      strbonus[ni->stats->level - 1], defbonus[ni->stats->level - 1]);
 
            // Increase your level
-            ni->stats->level++;
 
            // Increase your maximum hit points
             ni->stats->maxhp += hpbonus[ni->stats->level - 1];
@@ -1650,6 +1706,8 @@ void do_attack(char *u)
            // Add to your defensive power
             ni->stats->defense += defbonus[ni->stats->level - 1];
 
+            ni->stats->level++;
+
            // Clear the pointer for your master
             ni->stats->master = NULL;
         }
@@ -1680,6 +1738,8 @@ void do_attack(char *u)
                 notice(s_GameServ, u, "You have been \ 2\1fkilled\1f\ 2 by %s!", fight->name);
                 notice(s_GameServ, u, "You lose all gold on hand and lose 10 percent "\
                         "of your experience!");
+               addNews(todaysnews, "%s has been killed by %s!",
+                       ni->stats->name, fight->name);
                 ni->stats->gold = 0;
                 ni->stats->exp -= (long int)(ni->stats->exp * .10);
                ni->stats->hp = 0;
@@ -1691,6 +1751,8 @@ void do_attack(char *u)
             {
                 notice(s_GameServ, u, "%s has bested you! You will have to wait "\
                         "until tomorrow to try again", ni->stats->master->name);
+               addNews(todaysnews, "%s tried to best %s and failed!",
+                       ni->stats->name, fight->name);
                 ni->stats->fight = NULL;
                 ni->stats->master = NULL;
                return;
@@ -1806,18 +1868,13 @@ void do_attack(char *u)
         notice(s_GameServ, battle->getNick(), "%s has hit you with their %s for "\
                                              "\ 2%d\ 2 damage!", ni->stats->name, 
                                              weapons[ni->stats->weapon], hit);
-       clearYourTurn(ni->stats);
-       setYourTurn(battle->stats);
-        display_players(battle);
     }
     else
     {
         notice(s_GameServ, u, "You miss \1f%s\1f completely!", battle->stats->name);
         notice(s_GameServ, battle->getNick(), "%s misses you completely!", ni->stats->name);
-       clearYourTurn(ni->stats);
-       setYourTurn(battle->stats);
-        display_players(battle);
     }
+
     if (hit >= battle->stats->hp)
     {
         notice(s_GameServ, u, "You have killed \ 2%s\ 2!", battle->stats->name);
@@ -1828,16 +1885,11 @@ void do_attack(char *u)
         battle->stats->hp = 0;
         clearAlive(battle->stats);
 
-        if (2000000000 - ni->stats->exp > (long int)(battle->stats->exp * .10))
-        {
-            ni->stats->exp += (long int)(battle->stats->exp * .10);
-            battle->stats->exp -= (long int)(battle->stats->exp * .10);
-        }
-        else
-        {
-            battle->stats->exp -= (long int)(battle->stats->exp * .10);
+        ni->stats->exp += (long int)(battle->stats->exp * .10);
+        battle->stats->exp -= (long int)(battle->stats->exp * .10);
+
+        if (ni->stats->exp < 0 || ni->stats->exp > 2000000000)
             ni->stats->exp = 2000000000;
-        }
 
         if (2000000000 - ni->stats->gold > battle->stats->gold)
         {
@@ -1859,6 +1911,9 @@ void do_attack(char *u)
 
             ni->stats->gold = 2000000000;
         }
+
+       clearYourTurn(ni->stats);
+       clearYourTurn(battle->stats);
        battle->stats->battle = NULL;
         ni->stats->battle = NULL;
         return;
@@ -1869,9 +1924,9 @@ void do_attack(char *u)
             battle->stats->hp -= hit;
        clearYourTurn(ni->stats);
        setYourTurn(battle->stats);
+        display_players(battle);
         notice(s_GameServ, u, "Please wait while %s decides what to do!", 
                battle->stats->name);
-
         return;
     }
    }
@@ -2048,7 +2103,8 @@ int save_gs_dbase()
                << it->armor << ' ' << it->weapon << ' '
                << it->forest_fights << ' ' << it->player_fights <<  ' ' 
                << it->getFlags() << ' ' << it->password << ' ' << it->inventory.Healing()
-               << ' ' << it->inventory.Strength() << ' ' << it->inventory.Defense() << ' ' << it->inventory.HP() << endl;
+               << ' ' << it->inventory.Strength() << ' ' << it->inventory.Defense() << ' ' << it->inventory.HP()
+               << ' ' << it->lastlogin << endl;
        ptr = ptr->Next();
     }
    }
@@ -2072,6 +2128,19 @@ int load_gs_dbase()
        return 0;
     }
 
+    for (int x = 0; x < U_TABLE_SIZE; x++)
+    {
+       ListNode<aClient> *tempNode;
+       tempNode = players[x].First();
+       while (tempNode)
+       {
+           if (tempNode->getData()->stats->client)
+               logout(tempNode->getData()->stats->client);
+           tempNode = tempNode->Next();
+       }
+       players[x].deleteNodes();
+    }
+
     while (infile.getline(buf, 1024, '\n'))
     {
        temp = new aClient;
@@ -2119,6 +2188,13 @@ int load_gs_dbase()
        tempname = strtok(NULL, " ");
        if (tempname)
            p->inventory.setHP(stringtoint(tempname));
+
+        tempname = strtok(NULL, " ");
+       if (tempname)
+           p->lastlogin = stringtoint(tempname);
+       else
+           p->lastlogin = time(NULL);
+
        unsigned long hv = iHASH((unsigned char *) temp->stats->name);
 
        temp->stats->client = NULL;
@@ -2414,6 +2490,7 @@ void do_tavern(char *u)
 
     aClient *user;
     Player *p;
+
     if (!(user = find(u)))
     {
        notice(s_GameServ, u, "Fatal Error. See a %S admin for help");
@@ -2449,19 +2526,21 @@ void do_tavern(char *u)
     }
     else if (stricmp(cmd, "LIST") == 0)
     {
-       notice(s_GameServ, u, "Here is a list of what we have to offer:");
-       notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 100 * p->level + (p->exp / 10));
-       notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 205 * p->level + (p->exp / 10));
-       notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 200 * p->level + (p->exp / 10));
-       notice(s_GameServ, u, "4. HP Potions for %ld Gold", 230 * p->level + (p->exp / 10));
-       notice(s_GameServ, u, "To buy a potion, type /msg %S TAVERN BUY #");
-       notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1 buys a healing potion!");
-       notice(s_GameServ, u, "By something will ya!");
+           notice(s_GameServ, u, "Here is a list of what we have to offer:");
+           notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 
+                                       1000 * p->level * 4);
+           notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 
+                                       2500 * p->level * 4);
+           notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 
+                                       3000 * p->level * 4);
+           notice(s_GameServ, u, "4. HP Potions for %ld Gold", 
+                                       2000 * p->level * 4);
+           notice(s_GameServ, u, "To buy a potion, type /msg %S TAVERN BUY #");
+           notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1 buys a healing potion!");
     }
     else if (stricmp(cmd, "BUY") == 0)
     {
        char *chnum = strtok(NULL, " ");
-       int num = stringtoint(chnum);
 
        if (!chnum)
        {
@@ -2469,14 +2548,20 @@ void do_tavern(char *u)
            notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1");
            return;
        }
+       int num = stringtoint(chnum);
+
        if (num < 1 || num > 4)
        {
            notice(s_GameServ, u, "Invalid Choice!");
            notice(s_GameServ, u, "Here is a list of what we have to offer:");
-           notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 100 * p->level + (p->exp / 10));
-           notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 205 * p->level + (p->exp / 10));
-           notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 200 * p->level + (p->exp / 10));
-           notice(s_GameServ, u, "4. HP Potions for %ld Gold", 230 * p->level + (p->exp / 10));
+           notice(s_GameServ, u, "1. Healing Potions for %ld Gold", 
+                                       1000 * p->level * 4);
+           notice(s_GameServ, u, "2. Strength Potions for %ld Gold", 
+                                       2500 * p->level * 4);
+           notice(s_GameServ, u, "3. Defense Potions for %ld Gold", 
+                                       3000 * p->level * 4);
+           notice(s_GameServ, u, "4. HP Potions for %ld Gold", 
+                                       2000 * p->level * 4);
            notice(s_GameServ, u, "To buy a potion, type /msg %S TAVERN BUY #");
            notice(s_GameServ, u, "Example: /msg %S TAVERN BUY 1 buys a healing potion!");
            return;
@@ -2484,7 +2569,7 @@ void do_tavern(char *u)
        switch(num)
        {
            case 1:
-               price = (100 * p->level) + (p->exp / 10);
+               price = (1000 * p->level * 4);
                if (p->gold >= price)
                {
                    notice(s_GameServ, u, "One healing potion coming right up!");
@@ -2495,7 +2580,7 @@ void do_tavern(char *u)
                    notice(s_GameServ, u, "You don't have enough gold!");
                break;
            case 2:
-               price = (205 * p->level) + (p->exp / 10);
+               price = 2500 * p->level * 4;
                if (p->gold >= price)
                {
                    notice(s_GameServ, u, "One strength boost coming right up!");
@@ -2506,7 +2591,7 @@ void do_tavern(char *u)
                    notice(s_GameServ, u, "You don't have enough gold!");
                break;
            case 3:
-               price = (200 * p->level) + (p->exp / 10);
+               price = 3000 * p->level * 4;
                if (p->gold >= price)
                {
                    notice(s_GameServ, u, "One defense boost coming right up!");
@@ -2517,7 +2602,7 @@ void do_tavern(char *u)
                    notice(s_GameServ, u, "You don't have enough gold!");
                break;
            case 4:
-               price = (230 * p->level) + (p->exp / 10);
+               price = 2000 * p->level * 4;
                if (p->gold >= price)
                {
                    notice(s_GameServ, u, "One HP Potion coming right up!");
@@ -2594,7 +2679,12 @@ void do_bank(char *u)
         notice(s_GameServ, u, "I don't know how to convert alphabet letters into currency, sire!");
         return;
     }
-
+    if (stringtoint(amount) < 0)
+    {
+        notice(s_GameServ, u, "Sorry. This bank is not licensed "\
+       "to handle such sums of cash, noble Lord.");
+        return;
+    }
     p = user->stats;
 
     if (stricmp(cmd, "DEPOSIT") == 0)
@@ -2733,28 +2823,28 @@ void do_dragon(char *u)
        notice(s_GameServ, u, "You're dead. Wait until tomorrow to see your master!");
        return;
     }
-    else if (user->stats->level < 12)
+    else if (user->stats->level < REALLEVELS)
     {
        notice(s_GameServ, u, "You fool! Only those strong enough "\
                "to vanquish any foe should DARE fight the dragon!");
        notice(s_GameServ, u, "To put it in terms you can understand: "\
-               "You are too weak. You must be Level 12!");
+               "You are too weak. You must be Level %d!", REALLEVELS);
+       return;
     }
 
     updateTS(user->stats);
 
-    char *cmd = strtok(NULL, " ");
     Player *p = user->stats;
-    p->fight = new Monster(boss);
+    p->fight = new Monster(&boss);
     notice(s_GameServ, u, "You approach the dragon's lair cautiously.");
     notice(s_GameServ, u, "The stench of sulfer fills the air as a "\
        "deep, red fog rolls in. The air is filled with the "\
        "heated mist of deadly fire from beyond the cave "\
        "entrance.");
-    notice(s_GameServ, u, "You adjust your %s, tighten your grip on "\ 
+    notice(s_GameServ, u, "You adjust your %s, tighten your grip on "\
        "your %s, and venture into the hot, dark cave. "\
        "You are surprised at the angle of descent as you climb "\
-       "lower and lower, deeper into the dragon's den.");
+       "lower and lower, deeper into the dragon's den.", armors[p->level - 1], weapons[p->level - 1]);
     notice(s_GameServ, u, "You come to the end of the cave to find "\
        "a tooth. It is a large tooth... bigger than your torso."\
        " Suddenly the darkness lifts from the gleam of an eye "\
@@ -2762,7 +2852,7 @@ void do_dragon(char *u)
     notice(s_GameServ, u, "Just then you notice the eye begin to "\
        "glare orange! The tooth is moving... but it is still too "\
        "dark for you to make out.... THE DRAGON! You see it!");
-    display_monsters(u);
+    display_monster(u);
 }
 
 void do_master(char *u)
@@ -2847,9 +2937,10 @@ void do_master(char *u)
            case 11:
                need = 20000000;
                break;
-           case 12:
+
+           case REALLEVELS:
                need = p->exp + 1;
-               notice(s_GameServ, u, "You are at level 12. You are the master. What's left? The DRAGON!");
+               notice(s_GameServ, u, "You are at level %d. You are the master. What's left? The DRAGON!", REALLEVELS);
                return;
                break;
            default:
@@ -3036,10 +3127,15 @@ void resetall()
 
 void reset(Player *p)
 {
+    char *myname;
+    myname = new char[strlen(p->name)];
+    strcpy(myname, p->name);
     if (!p)
        return;
 
     p->reset();
+    strcpy(p->name, myname);
+    delete [] myname;
 }
 
 void updateTS(Player *p)
@@ -3195,7 +3291,7 @@ void do_reset(char *u)
        notice(s_GameServ, u, "Resetting everyone's stats!");
        resetall();
     }
-    else if ((user = findbyrealnick(nick)))
+    else if ((user = findplayer(nick)))
     {
        if (is_playing(user))
        {
@@ -3208,11 +3304,8 @@ void do_reset(char *u)
        }
        else
        {
-           #ifdef P10
-           notice(s_GameServ, u, "%s is not playing.", user->getRealNick());
-           #else
-           notice(s_GameServ, u, "%s is not playing.", user->getNick());
-           #endif
+           notice(s_GameServ, u, "Resetting %s", user->stats->name);
+           reset(user->stats);
        }
     }
     else
@@ -3325,78 +3418,63 @@ void do_admin(char *u)
     }
 }
 
+bool load_levels()
+{
+    char *filename;
+    filename = new char[256];
+
+    for (int x = 1; x <= LEVELS; x++)
+    {
+       sprintf(filename, "data/levels/level%d.dat", x);
+       if (levels[x - 1].loadLevel(filename) == false)
+           return false;
+    }
+
+    delete []filename;
+    return true;
+}
 bool load_monsters()
 {
+    char *filename;
     ifstream infile;
-    infile.open("monsters.dat");
-
     char *buf;
+    buf = new char[2048];
 
-    if (infile.fail())
+  for (int level = 1; level <= LEVELS; level++)
+  {
+    filename = new char[256];
+    sprintf(filename, "data/monsters/level%d.dat", level);
+    infile.open(filename);
+
+    if (!infile)
     {
-       log("Error opening monsters.dat");
+       log("Error opening %s", filename);
        return false;
     }
-    init_monsters();
-    buf = new char[2048];
 
     #ifdef DEBUGMODE
-       log("Loading monsters from monsters.dat");
+       log("Loading monsters from %s", filename);
     #endif
 
-  for (int l = 0; l < REALLEVELS; l++)
-  {
-    for (int m = 0; m < MONSTERS;)
+    while (infile.getline(buf, 2048))
     {
-       infile.getline(buf, 2048);
+       if (buf[0] == '^')
+           break;
        if (buf[0] == '\n' || buf[0] == '\0' || buf[0] == '#')
            continue;
-       else
-       {
-           strcpy(monsters[l][m]->name, strtok(buf, "~"));
-           strcpy(monsters[l][m]->weapon, strtok(NULL, "~"));
-           monsters[l][m]->strength = stringtoint(strtok(NULL, "~"));
-           monsters[l][m]->gold = stringtoint(strtok(NULL, "~"));
-           monsters[l][m]->exp = stringtoint(strtok(NULL, "~"));
-           monsters[l][m]->maxhp = stringtoint(strtok(NULL, "~"));
-           monsters[l][m]->hp = monsters[l][m]->maxhp;
-           strcpy(monsters[l][m]->death, strtok(NULL, ""));
-           m++;
-       }
+       Monster *temp;
+       temp = new Monster;
+
+            strcpy(temp->name, strtok(buf, "~"));
+            strcpy(temp->weapon, strtok(NULL, "~"));
+            strcpy(temp->death, strtok(NULL, "~"));
+
+       levels[level - 1].monsters.insertAtBack_RLN(temp);
+       delete temp;
     }
+    delete [] filename;
+    infile.close();
   }
     delete [] buf;
 return true;
 }
-
-// this will be hash.cpp start
-// thank you wcampbel
-unsigned long sHASH(const unsigned char *name)
-{
-  unsigned long h = 0, g;
-
-  while (*name)
-  {
-    h = (h << 4) + (*name++); // Case sensitive for numerics
-    if ((g = (h & 0xF0000000)))
-      h ^= g >> 24;
-    h &= ~g;
-  }
-  return h % U_TABLE_SIZE;
-}
-
-unsigned long iHASH(const unsigned char *name)
-{
-  unsigned long h = 0, g;
-
-  while (*name)
-  {
-    h = (h << 4) + tolower(*name++);
-    if ((g = (h & 0xF0000000)))
-      h ^= g >> 24;
-    h &= ~g;
-  }
-  return h % U_TABLE_SIZE;
-}
-
-// this will be hash.cpp end