]> 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 e8bc8b4171f27ae2619a91c37b2927359211b21e..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);
@@ -111,6 +106,7 @@ void do_register(char *u);
 void do_list(char *u);
 void do_logout(char *u);
 void do_master(char *u);
+void do_dragon(char *u);
 void do_play(char *u);
 void do_quitg(char *u);
 void do_reset(char *u);
@@ -164,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;
@@ -197,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) {
@@ -207,6 +191,8 @@ void gameserv(char *source, char *buf)
        do_inventory(source);
     } else if (stricmp(cmd, "MASTER") == 0) {
        do_master(source);
+    } else if (stricmp(cmd, "DRAGON") == 0) {
+       do_dragon(source);
     } else if (stricmp(cmd, "STORE") == 0) {
        do_store(source);
     } else if (stricmp(cmd, "BANK") == 0) {
@@ -223,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) {
@@ -315,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;
@@ -401,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
     {
@@ -470,7 +480,7 @@ void notice(const char *source, const char *dest, const char *fmt, ...)
        if (isUsePrivmsg())
            strcpy(commanduse, "P");
        else
-           strcpy(commanduse, "N");
+           strcpy(commanduse, "O");
     #else
 
        if (isUsePrivmsg())
@@ -573,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);
@@ -591,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();
        }
@@ -783,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);
@@ -858,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);
     }
 }
 
@@ -915,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;
@@ -924,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;
@@ -933,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;
@@ -943,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;
@@ -952,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;
@@ -961,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;
@@ -971,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;
@@ -980,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;
@@ -990,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;
@@ -999,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;
@@ -1008,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;
@@ -1016,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()
@@ -1220,19 +1243,21 @@ void do_fight(char *u)
     {
        notice(s_GameServ, u, "You can't attack %s while they aren't playing!", nick);
     }
-/*
- * Offline fighting not implemented yet.
- *   else if (!(fight = finduser(nick)))
- *   {
- *       ni->stats->battle = battle;
- *       battle->battle = ni;
- *       ni->yourturn = 1;
- *       battle->yourturn = 0;
- *       notice(s_GameServ, u, "You decide to fight %s while they're not online!",
- *                battle->stats->name);
- *       display_players(u);
- *   }
- */
+
+/* offline fighting not available yet
+    else if (!(fight = finduser(nick)))
+    {
+        ni->stats->battle = battle;
+        battle->battle = ni;
+       setYourTurn(ni->stats);
+        clearYourTurn(battle->stats);
+
+        notice(s_GameServ, u, "You decide to fight %s while they're "\
+                             "not in the realm!",
+                 battle->stats->name);
+        display_players(u);
+    }
+*/
     else if (stricmp(ni->stats->name, battle->stats->name) == 0)
     {
        notice(s_GameServ, u, "Are you trying to commit suicide!?");
@@ -1326,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)
     {
@@ -1353,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)
     {
@@ -1367,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)
     {
@@ -1382,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;
     }
 
@@ -1497,6 +1553,7 @@ void end_turn(aClient *user)
                         "of your experience!");
                 user->stats->gold = 0;
                 user->stats->exp -= (long int)(user->stats->exp * .10);
+               user->stats->hp = 0;
                 user->stats->fight = NULL;
                clearAlive(user->stats);
                 goto endturn;
@@ -1604,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);
 
@@ -1616,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))
         {
@@ -1630,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];
@@ -1644,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;
         }
@@ -1674,8 +1738,11 @@ 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;
                 ni->stats->fight = NULL;
                clearAlive(ni->stats);
                 return;
@@ -1684,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;
@@ -1799,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);
@@ -1821,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)
         {
@@ -1852,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;
@@ -1862,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;
     }
    }
@@ -2041,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();
     }
    }
@@ -2065,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;
@@ -2112,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;
@@ -2407,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");
@@ -2442,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)
        {
@@ -2462,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;
@@ -2477,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!");
@@ -2488,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!");
@@ -2499,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!");
@@ -2510,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!");
@@ -2587,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)
@@ -2695,6 +2792,69 @@ void do_bank(char *u)
 
 }
 
+void do_dragon(char *u)
+{
+    aClient *user;
+
+    if (!(user = find(u)))
+    {
+       notice(s_GameServ, u, "Fatal error. Contact a(n) %S admin. buf: %s", strtok(NULL, ""));
+       return;
+    }
+    else if (isIgnore(user))
+    {
+       #ifdef DEBUGMODE
+           log("Ignoring %s.", user->getNick());
+       #endif
+       return;
+    }
+    else if (!is_playing(user))
+    {
+       notice(s_GameServ, u, "You must be playing to fight the dragon!");
+       return;
+    }
+    else if (is_fighting(user))
+    {
+       notice(s_GameServ, u, "You are already in a fight. How will you fight the almighty dragon!?");
+       return;
+    }
+    else if (!isAlive(user->stats))
+    {
+       notice(s_GameServ, u, "You're dead. Wait until tomorrow to see your master!");
+       return;
+    }
+    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 %d!", REALLEVELS);
+       return;
+    }
+
+    updateTS(user->stats);
+
+    Player *p = user->stats;
+    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 "\
+       "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.", 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 "\
+       " staring into your soul! The eye is large... HUGE!");
+    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_monster(u);
+}
+
 void do_master(char *u)
 {
     aClient *user;
@@ -2745,41 +2905,43 @@ void do_master(char *u)
        switch(p->level)
        {
            case 1:
-               need = 100;
+               need = 200;
                break;
            case 2:
-               need = 400;
+               need = 800;
                break;
            case 3:
-               need = 1000;
+               need = 2000;
                break;
            case 4:
-               need = 4000;
+               need = 8000;
                break;
            case 5:
-               need = 10000;
+               need = 20000;
                break;
            case 6:
-               need = 40000;
+               need = 80000;
                break;
            case 7:
-               need = 100000;
+               need = 200000;
                break;
            case 8:
-               need = 400000;
+               need = 800000;
                break;
            case 9:
-               need = 1000000;
+               need = 2000000;
                break;
            case 10:
-               need = 4000000;
+               need = 8000000;
                break;
            case 11:
-               need = 10000000;
+               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:
                need = p->exp + 1; // Unknown level... don't let them fight a fake master!
@@ -2965,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)
@@ -3124,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))
        {
@@ -3137,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
@@ -3254,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