X-Git-Url: https://jfr.im/git/irc/gameservirc.git/blobdiff_plain/4e5760fd103583efe4d1762b6cf8f8e7036734e6..4025195255323de684e16d0845717a4eee057366:/gameserv/gameserv.cpp?ds=sidebyside diff --git a/gameserv/gameserv.cpp b/gameserv/gameserv.cpp index 6ab518d..0937cd7 100644 --- a/gameserv/gameserv.cpp +++ b/gameserv/gameserv.cpp @@ -10,6 +10,7 @@ using std::ifstream; using std::ofstream; +using std::ios; #if defined(HAVE_CRYPT_H) @@ -21,9 +22,15 @@ using std::ofstream; #endif -List players; +// this will be hash.cpp start +// thank you wcampbel +unsigned long HASH(const unsigned char *name, int size_of_table); +List 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 Monster *masters[LEVELS]; // A master for each level @@ -40,7 +47,6 @@ int stricmp(const char *s1, const char *s2); int strnicmp(const char *s1, const char *s2, size_t len); // String Functions - /********** Password functions **********/ bool passcmp(char *encrypted, char *plaintext); // Compares an encrypted pass with a plain text one @@ -52,6 +58,11 @@ bool check_password(char *name, char *plaintext); // Finds a password for the gi /********** GameServ Booleans **********/ +bool shuttingdown; +bool timedOut(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. bool is_playing(aClient *user); @@ -78,6 +89,7 @@ long int stringtoint(char *number); char *spaces(int len, char *seperator); void refresh(Player *p); void refreshall(); +void updateTS(Player *p); void reset(Player *p); void init_masters(); void init_monsters(); @@ -96,6 +108,7 @@ void do_inventory(char *u); void do_refresh(char *u); void do_register(char *u); void do_list(char *u); +void do_logout(char *u); void do_master(char *u); void do_play(char *u); void do_quitg(char *u); @@ -107,6 +120,7 @@ void do_tavern(char *u); void do_use(char *u); void see_master(char *u); +void logout(aClient *user); void showstats(const char *u, const char *nick); void showinventory(aClient *from, aClient *to); void showBankBalance(const char *u); @@ -125,8 +139,8 @@ char *armors[WNA] = { "Nothing", "Clothes", "Leather Vest", "Chain Mail", "Plate int prices[WNA - 1] = {200, 1000, 3000, 10000, 30000, 100000, 150000, 200000, 400000, 1000000, 4000000, 10000000, 40000000, 100000000, 400000000}; -int webonus[WNA] = {0, 10, 15, 25, 35, 45, 65, 85, 125, 185, 255, 355, 505, 805, 1205, 1805}; -int arbonus[WNA] = {0, 1, 3, 10, 15, 25, 35, 50, 75, 100, 150, 225, 300, 400, 600, 1000}; +int webonus[WNA] = {1, 10, 15, 25, 35, 45, 65, 85, 125, 185, 255, 355, 505, 805, 1205, 1805}; +int arbonus[WNA] = {1, 2, 4, 10, 15, 25, 35, 50, 75, 100, 150, 225, 300, 400, 600, 1000}; int hpbonus[11] = {10, 15, 20, 30, 50, 75, 125, 185, 250, 350, 550}; int strbonus[11] = {5, 7, 10, 12, 20, 35, 50, 75, 110, 150, 200}; @@ -148,13 +162,18 @@ void gameserv(char *source, char *buf) log("Source: %s Command: %s", source, cmd); #endif - long int mn = midnight() - 12 * 3600; // 12 noon ;) + struct tm *tm; + time_t ti; + time(&ti); + tm = localtime(&ti); + + int curday = tm->tm_mday; - if (mn > timestamp) + if (curday != day) { refreshall(); - timestamp = mn; - save_timestamp(); + day = curday; + save_day(); // here i come to save the day! } if (strnicmp(cmd, "\1PING", 6) == 0) @@ -163,7 +182,7 @@ void gameserv(char *source, char *buf) ts = strtok(NULL, "\1"); notice(s_GameServ, source, "\1PING %s\1", ts); } else if (stricmp(cmd, "\1VERSION\1") == 0) { - notice(s_GameServ, source, "\1VERSION %s %s +devel\1", PACKAGE, VERSION); + notice(s_GameServ, source, "\1VERSION %s %s\1", PACKAGE, VERSION); } else if (stricmp(cmd, "SEARCH") == 0) { cmd = strtok(NULL, " "); @@ -200,13 +219,8 @@ void gameserv(char *source, char *buf) do_tavern(source); } else if (stricmp(cmd, "LIST") == 0) { do_list(source); - #ifdef DEBUGMODE - } else if (stricmp(cmd, "PRINT") == 0) { - cout << "Printing the clients list:" << endl; - clients.print(); - cout << "\nPrinting the players list:" << endl; - players.print(); - #endif + } else if (stricmp(cmd, "LOGOUT") == 0) { + do_logout(source); } else if (stricmp(cmd, "REGISTER") == 0) { do_register(source); } else if (stricmp(cmd, "IDENTIFY") == 0) { @@ -235,6 +249,7 @@ void gameserv(char *source, char *buf) #else raw("SQUIT %s :leaving: %s used the Shutdown command.", servername, source); #endif + shuttingdown = true; } } else if (stricmp(cmd, "SAVE") == 0) { aClient *user; @@ -280,6 +295,7 @@ void gameserv(char *source, char *buf) else display_help(source, cmd); } + #ifdef DEBUGMODE } else if (stricmp(cmd, "RAW") == 0) { aClient *user; @@ -297,6 +313,7 @@ void gameserv(char *source, char *buf) char *rest = strtok(NULL, ""); raw("%s", rest); } + #endif } else { notice(s_GameServ, source, "Unknown command \002%s\002. Type /msg %S \002HELP\002 to get a list of commands.", cmd); } @@ -524,13 +541,19 @@ char *strtok(char *str, const char *delim) void do_list(char *u) { ListNode *temp; - temp = players.First(); - if (!players.isEmpty()) + bool header = false; + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + temp = players[x].First(); + if (!players[x].isEmpty()) { - notice(s_GameServ, u, "People Playing:"); + 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); @@ -541,16 +564,94 @@ void do_list(char *u) temp = temp->Next(); } + } + } + if (!header) + notice(s_GameServ, u, "No one is playing"); + else notice(s_GameServ, u, "End of List"); + +} + +void do_logout(char *u) +{ + aClient *user; + if (!(user = find(u))) + { + notice(s_GameServ, u, "Fatal error. Cannot find aClient. "\ + "Buf: %s LOGOUT", u); + log("Could not find aClient Buf: %s LOGOUT", + u); + } + else if (!is_playing(user)) + { + notice(s_GameServ, u, "You're not logged in!"); + } + else if (is_fighting(user)) + { + notice(s_GameServ, u, "You can't logout while fighting!"); } else - notice(s_GameServ, u, "No one is playing"); + { + notice(s_GameServ, u, "You have left the fields. You have lived to kill another day!"); + logout(user); + } } +void logout(aClient *user) +{ + if (is_playing(user)) + { + ListNode *it; + aClient *temp; + unsigned long hv = HASH((unsigned char *) user->stats->name, + U_TABLE_SIZE); + it = players[hv].Find(user); + if (!it) + { + notice(s_GameServ, user->getNick(), "Fatal error. Contact "\ + "%S Admin. Cannot find you in the players list."); + log("Error on logout(). Can't find %s in the players list", + #ifdef P10 + user->getRealNick() + #else + user->getNick() + #endif + ); + return; + } + + temp = new aClient; + temp->stats = new Player; + temp->stats->setData(user->stats); + user->stats->client = NULL; + if (player_fight(user)) + user->stats->battle->stats->battle = NULL; + + delete user->stats; + user->stats = NULL; + temp->stats->client = NULL; + #ifdef P10 + temp->setRealNick("!NULL!"); + #endif + temp->setNick("!NULL!"); + + it->setNewPtr(temp); + #ifdef DEBUGMODE + log("Logged out player %s", + #ifdef P10 + user->getRealNick() + #else + user->getNick() + #endif + ); + #endif + } +} void do_register(char *u) { char *password, *name; - aClient *user, *p; + aClient *user; name = strtok(NULL, " "); password = strtok(NULL, " "); @@ -569,16 +670,22 @@ void do_register(char *u) { notice(s_GameServ, u, "SYNTAX: /msg %S REGISTER NAME PASSWORD"); } + else if ((user = findplayer(name))) + { + notice(s_GameServ, u, "%s is already registered!", name); + notice(s_GameServ, u, "Choose another name!"); + } else if ((user = find(u))) { - p = findplayer(u); - if (!user->stats && !p) + if (!user->stats) { user->stats = new Player(user); - user->stats->user = user; // Set the backwards pointer + user->stats->client = user; // Set the backwards pointer strcpy(user->stats->password, crypt(password, salt)); strcpy(user->stats->name, name); - players.insertAtBack(user); + unsigned long hv = HASH((unsigned char *) name, U_TABLE_SIZE); + updateTS(user->stats); + players[hv].insertAtBack(user); 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); @@ -608,46 +715,43 @@ void do_identify(char *u) } else if (!(p = findplayer(name)) || !p->stats) notice(s_GameServ, u, "Player %s not found", name); + else if (is_playing(user)) + { + notice(s_GameServ, u, "You are already playing!"); + } + else if (p->stats->client != NULL && !isAdmin(user)) + { + notice(s_GameServ, u, "That player has already identified."); + } else if (!check_password(name, password) && !isAdmin(user)) { notice(s_GameServ, u, "Password incorrect"); } - else - { - if (p->stats->user && !isAdmin(user)) + else { + ListNode *temp; + unsigned long hv = HASH((unsigned char *) p->stats->name, + U_TABLE_SIZE); + temp = players[hv].Find(p); + if (!temp) { - notice(s_GameServ, u, "That player has already identified."); + notice(s_GameServ, u, "Fatal error. Contact %S Admin. Buf: %s", + strtok(NULL, "")); return; } - if (!user->stats) - { - ListNode *temp; - temp = players.Find(p); - if (!temp) - { - notice(s_GameServ, u, "Fatal error. Contact %S Admin. Buf: %s", - strtok(NULL, "")); - return; - } - user->stats = new Player(p->stats->name); - #ifdef DEBUGMODE - log("Setting data for identified"); - #endif - user->stats->setData(p->stats); - - #ifdef DEBUGMODE - log("Player Identified"); - #endif + user->stats = new Player(p->stats->name); + #ifdef DEBUGMODE + log("Setting data for identified"); + #endif + updateTS(user->stats); - temp->setPtr(user); + user->stats->setData(p->stats); - notice(s_GameServ, u, "Password Accepted. Identified."); + #ifdef DEBUGMODE + log("Player Identified"); + #endif - } - else - { - notice(s_GameServ, u, "Already identified. Contact a %S admin for help."); - } + temp->setPtr(user); + notice(s_GameServ, u, "Password Accepted. Identified."); } } @@ -672,7 +776,10 @@ void do_stats(char *u) return; } else + { + updateTS(user->stats); showstats(u, user->stats->name); + } } else showstats(u, nick); @@ -841,21 +948,15 @@ void display_monster(char *u) void display_players(char *u) { - if (is_playing(u)) + aClient *user; + if (!(user = find(u))) { - aClient *ni = find(u); - - aClient *battle = ni->stats->battle; - - notice(s_GameServ, u, "Your Hitpoints: %d", ni->stats->hp); - notice(s_GameServ, u, "%s's Hitpoints: %d", battle->stats->name, - battle->stats->hp); - notice(s_GameServ, u, "Here are your commands:"); - notice(s_GameServ, u, "/msg %S attack"); - notice(s_GameServ, u, "/msg %S run"); - notice(s_GameServ, u, "What will you do?"); + log("Fatal error in display_players(): Couldn't find %s", u); } + else + display_players(user); } + void display_players(aClient *user) { char *u = user->getNick(); @@ -876,18 +977,14 @@ bool is_playing(char *u) { aClient *user; if (!(user = find(u))) - { return false; - } else - { - return user->stats != NULL; - } + return is_playing(user); } bool is_playing(aClient *user) { - return user->stats != NULL && (stricmp(user->getNick(), "!NULL!") != 0); + return user->stats != NULL; } bool is_fighting(char *u) @@ -895,17 +992,11 @@ bool is_fighting(char *u) aClient *user; if (!(user = find(u))) - { return false; - } - else if (user->stats) - { - return user->stats->fight != NULL || user->stats->battle != NULL - || user->stats->master != NULL; - } else - return false; + return is_fighting(user); } + bool is_fighting(aClient *user) { if (!is_playing(user)) @@ -920,10 +1011,8 @@ bool player_fight(char *u) if (!(user = find(u))) return false; - else if (user->stats) - return user->stats->battle != NULL; - else - return false; + else + return player_fight(user); } bool player_fight(aClient *user) { @@ -939,11 +1028,10 @@ bool master_fight(char *u) if (!(user = find(u))) return false; - else if (user->stats) - return user->stats->master != NULL; else - return false; + return master_fight(user); } + bool master_fight(aClient *user) { if (!is_playing(user)) @@ -961,22 +1049,35 @@ void do_fight(char *u) if (!nick) { notice(s_GameServ, u, "SYNTAX: /msg %S FIGHT PLAYER"); + return; } else if (!(ni = find(u))) { notice(s_GameServ, u, "Fatal error. Contact a(n) %S admin. buf: %s", strtok(NULL, "")); return; } - else if (!(battle = findbyrealnick(nick))) - { - notice(s_GameServ, u, "You can't attack %s while they aren't playing!", nick); - return; - } else if (!is_playing(ni)) { notice(s_GameServ, u, "You are not playing!"); return; } + + updateTS(ni->stats); + + if (ni->stats->player_fights <= 0) + { + ni->stats->player_fights = 0; // just to be safe + notice(s_GameServ, u, "You are out of player fights for the "\ + "day. You have to wait until tomorrow!"); + } + else if (!(battle = findplayer(nick))) + { + notice(s_GameServ, u, "Player %s not found!", nick); + } + else if (!is_playing(battle)) + { + 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))) @@ -993,19 +1094,38 @@ void do_fight(char *u) else if (!isAlive(ni->stats)) { notice(s_GameServ, u, "You are dead. Wait until tomorrow to fight others!"); - return; + } + else if (stricmp(ni->stats->name, battle->stats->name) == 0) + { + notice(s_GameServ, u, "Are you trying to commit suicide!?"); + } + else if (!isAlive(battle->stats)) + { + notice(s_GameServ, u, "They are dead. Cannot fight dead players!"); } else if (player_fight(battle)) { notice(s_GameServ, u, "%s is fighting %s already!", battle->stats->name, battle->stats->battle->stats->name); - return; } else if (is_fighting(battle)) { notice(s_GameServ, u, "%s is fighting %s already!", battle->stats->name, battle->stats->fight->name); - return; } - else if (is_playing(ni) && is_playing(battle) && stricmp(ni->stats->name, battle->stats->name) != 0) + else if (ni->stats->level - battle->stats->level > maxbfightdistance) + { + // You can't fight someone below you by more than X level(s) + // level 12 can fight level (12 - X) but not < (12 - X) + notice(s_GameServ, u, "You may not fight %s. You're too strong!", + battle->stats->level); + } + else if (battle->stats->level - ni->stats->level > maxafightdistance) + { + // You can't fight someone above you by more than X level(S) + // level 1 can fight level (1 + X), but not > (1 + X) + notice(s_GameServ, u, "%s, do you really have a death wish? Try the forest you "\ + "weakling!", ni->stats->name); + } + else { // Set your battle pointer to the other player ni->stats->battle = battle; @@ -1018,13 +1138,17 @@ void do_fight(char *u) clearYourTurn(battle->stats); // Initiate Battle sequence! + ni->stats->player_fights -= 1; + notice(s_GameServ, u, "You challenge %s to an online duel!", battle->stats->name); notice(s_GameServ, battle->getNick(), "%s has challenged you to an online duel!", ni->stats->name); - notice(s_GameServ, battle->getNick(), "%s gets to go first because he initiated!", ni->stats->name); + notice(s_GameServ, battle->getNick(), "%s gets to go first "\ + "because they initiated!", ni->stats->name); notice(s_GameServ, battle->getNick(), "Please wait while %s decides what to do.", ni->stats->name); - display_players(u); + display_players(ni); } } + void do_use(char *u) { aClient *user; @@ -1049,6 +1173,8 @@ void do_use(char *u) return; } + updateTS(user->stats); + p = &user->stats->inventory; if (stricmp(item, "HEALTH") == 0) @@ -1125,6 +1251,13 @@ void do_run(char *u) return; } + else if (!is_playing(user)) + { + notice(s_GameServ, u, "You must be playing to run!"); + return; + } + + updateTS(user->stats); p = user->stats; if (p->battle) @@ -1271,6 +1404,7 @@ void do_attack(char *u) // One has to be !NULL based on the previous else if // We wouldn't be here if they were all NULL } + updateTS(ni->stats); if (!player_fight(ni)) { @@ -1503,7 +1637,7 @@ void do_attack(char *u) weapons[ni->stats->weapon], hit); clearYourTurn(ni->stats); setYourTurn(battle->stats); - display_players(battle->getNick()); + display_players(battle); } else { @@ -1511,7 +1645,7 @@ void do_attack(char *u) notice(s_GameServ, battle->getNick(), "%s misses you completely!", ni->stats->name); clearYourTurn(ni->stats); setYourTurn(battle->stats); - display_players(battle->getNick()); + display_players(battle); } if (hit >= battle->stats->hp) { @@ -1582,6 +1716,7 @@ void do_heal(char *u) if (!amount) { notice(s_GameServ, u, "SYNTAX: /msg %S HEAL {ALL | #}"); + return; } else if (!(ni = find(u))) { @@ -1601,12 +1736,16 @@ void do_heal(char *u) else if (is_fighting(ni)) { notice(s_GameServ, u, "You can't heal in battle!"); + return; } else if (ni->stats->hp >= ni->stats->maxhp) { notice(s_GameServ, u, "You don't need healing!"); + return; } - else if (stricmp(amount, "ALL") == 0) + + updateTS(ni->stats); + if (stricmp(amount, "ALL") == 0) { price = ni->stats->level * 3; if (ni->stats->gold < (ni->stats->maxhp - ni->stats->hp) * price) @@ -1707,7 +1846,7 @@ long int chartoint(char ch) int save_gs_dbase() { - ListNode *ptr = players.First(); + ListNode *ptr; Player *it; ofstream outfile; @@ -1719,6 +1858,9 @@ int save_gs_dbase() return 0; } + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + ptr = players[x].First(); while(ptr) { it = ptr->getData()->stats; @@ -1730,6 +1872,7 @@ int save_gs_dbase() << ' ' << it->inventory.Strength() << ' ' << it->inventory.Defense() << ' ' << it->inventory.HP() << endl; ptr = ptr->Next(); } + } outfile.close(); return 1; } @@ -1797,8 +1940,10 @@ int load_gs_dbase() tempname = strtok(NULL, " "); if (tempname) p->inventory.setHP(stringtoint(tempname)); + unsigned long hv = HASH((unsigned char *) temp->stats->name, U_TABLE_SIZE); - players.insertAtBack(temp); + temp->stats->client = NULL; + players[hv].insertAtBack(temp); delete temp; } delete [] buf; @@ -1855,15 +2000,21 @@ void do_store(char *u) notice(s_GameServ, u, "SYNTAX: STORE LIST {ARMOR | WEAPONS}"); notice(s_GameServ, u, " STORE SELL {ARMOR | WEAPON}"); notice(s_GameServ, u, " STORE BUY {ARMOR | WEAPON} NUMBER"); + return; } else if (!(user = find(u)) || !is_playing(user)) + { notice(s_GameServ, u, "You must be playing to use the store!"); + return; + } else if (!isAlive(user->stats)) { notice(s_GameServ, u, "You are dead. Wait until tomorrow to purchase weapons and armor!"); return; } - else if (stricmp(cmd, "LIST") == 0) + updateTS(user->stats); + + if (stricmp(cmd, "LIST") == 0) { if (stricmp(item, "WEAPONS") == 0) { @@ -2032,6 +2183,7 @@ void do_inventory(char *u) notice(s_GameServ, u, "You must be playing to check your inventory!"); return; } + updateTS(user->stats); showinventory(user, user); } void showinventory(aClient *from, aClient *to) @@ -2072,7 +2224,10 @@ void do_tavern(char *u) notice(s_GameServ, u, "You cannot go to the Tavern during a fight!"); return; } + + updateTS(user->stats); p = user->stats; + if (!cmd) { notice(s_GameServ, u, "Welcome to Boot Liquors Mystic Apothecary"); @@ -2187,13 +2342,25 @@ void do_bank(char *u) notice (s_GameServ, u, "BANK BALANCE"); return; } - - user = find(u); - if (!is_playing(user)) + else if (!(user = find(u))) + { + notice(s_GameServ, u, "Fatal Error. Couldn't find your aClient. Contact a(n) %S "\ + " admin for help"); + log("Fatal Error. Couldn't find %s while executing do_bank()", u); + return; + } + else if (!is_playing(user)) { notice(s_GameServ, u, "You must be playing to use the bank!"); return; } + + updateTS(user->stats); + if (stricmp(cmd, "BALANCE") == 0) + { + showBankBalance(u); + return; + } else if (!isAlive(user->stats)) { notice(s_GameServ, u, "You are dead. We don't accept gold from dead folk! Wait 'til tomorrow!"); @@ -2207,11 +2374,7 @@ void do_bank(char *u) p = user->stats; - if (stricmp(cmd, "BALANCE") == 0) - { - showBankBalance(u); - } - else if (stricmp(cmd, "DEPOSIT") == 0) + if (stricmp(cmd, "DEPOSIT") == 0) { if (p->bank == 2000000000) { @@ -2341,7 +2504,8 @@ void do_master(char *u) notice(s_GameServ, u, "You must be playing to see your master!"); return; } - + + updateTS(user->stats); char *cmd = strtok(NULL, " "); Player *p = user->stats; long int need = 0; @@ -2470,8 +2634,9 @@ void refreshall() { ListNode *it; Player *p; - - it = players.First(); + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + it = players[x].First(); while (it) { @@ -2479,6 +2644,7 @@ void refreshall() refresh(p); it = it->Next(); } + } } void refresh(Player *p) @@ -2553,7 +2719,9 @@ void resetall() ListNode *it; Player *p; - it = players.First(); + for (unsigned long x = 0; x < U_TABLE_SIZE; x++) + { + it = players[x].First(); while (it) { @@ -2561,6 +2729,7 @@ void resetall() reset(p); it = it->Next(); } + } } void reset(Player *p) @@ -2571,6 +2740,34 @@ void reset(Player *p) p->reset(); } +void updateTS(Player *p) +{ + if (!p) + return; + p->lastcommand = time(NULL); +} + +bool timedOut(Player *p) +{ + if (!p) + return false; + else + return ((time(NULL) - p->lastcommand) >= maxidletime); +} + +void timeOutEvent(Player *p) +{ + aClient *user = p->client; + + if (!user) // then they're not playing + return; + + char *nick = user->getNick(); + + notice(s_GameServ, nick, "You just idle timed out"); + logout(user); +} + void do_reset(char *u) { char *nick = strtok(NULL, " "); @@ -2769,3 +2966,25 @@ bool load_monsters() delete [] buf; return true; } + +// this will be hash.cpp start +// thank you wcampbel +unsigned long HASH(const unsigned char *name, int size_of_table) +{ + unsigned long h = 0, g; + + while (*name) + { + #ifdef P10 + h = (h << 4) + (*name++); // Case sensitive for numerics + #else + h = (h << 4) + tolower(*name++); + #endif + if ((g = (h & 0xF0000000))) + h ^= g >> 24; + h &= ~g; + } + return h % size_of_table; +} + +// this will be hash.cpp end