/* Explored Room Code * This snippet is intended for just plain old ROM, though it'll probably work on just about any codebase * that uses a unique number to identify the room. * Written By Davion Kalhen of MudBytes.net one boring Saturday morning! */ /*** **In act_move.c at the top with the other #include's add */ #include <malloc.h> /*** **In act_move.c just toss these functions in at the bottom. */ //Check to see if a vnum has been explored bool explored_vnum(CHAR_DATA *ch, int vnum) { int mask = vnum / 32; //Get which bucket the bit is in unsigned int bit = vnum % 32; //Get which bit in the bucket we're playing with EXPLORE_HOLDER *pExp; //The buckets bucket. if(bit == 0 ) // % 32 will return 0 if vnum == 32, instead make it the last bit of the previous mask { mask--; bit = 32; } for(pExp = ch->pcdata->explored->bits ; pExp ; pExp = pExp->next ) //Iterate through the buckets { if(pExp->mask != mask) continue; //Found the right bucket, might be explored. if(IS_SET(pExp->bits, ( 1 << bit ) ) ) //Convert bit to 2^(bit-1) and see if it's set. return TRUE; return FALSE; //Return immediately. This value wont be in any other bucket. } return FALSE; } //Explore a vnum. Assume it's not explored and just set it. void explore_vnum(CHAR_DATA *ch, int vnum ) { int mask = vnum / 32; //Get which bucket it will be in unsigned int bit = vnum % 32; // Get which bit to set EXPLORE_HOLDER *pExp; //The buckets bucket. if(bit == 0 ) // % 32 will return 0 if vnum is a multiple 32, instead make it the last bit of the previous mask { mask--; bit = 32; } //Find the bucket. for(pExp = ch->pcdata->explored->bits ; pExp ; pExp = pExp->next ) if(pExp->mask == mask) break; if(!pExp) //If it's null, bucket not found, we'll whip one up. { pExp = (EXPLORE_HOLDER *)calloc(sizeof(*pExp), 1); //Alloc and zero pExp->mask = mask; pExp->next = ch->pcdata->explored->bits; //Add to ch->pcdata->explored->bits = pExp; //the list } SET_BIT(pExp->bits, ( 1 << bit ) ); //Convert bit to 2^(bit-1) and set ch->pcdata->explored->set++; //Tell how many rooms we've explored } //Explore a vnum. void check_explore( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoom ) { if(IS_NPC(ch) ) return; if(explored_vnum(ch, pRoom->vnum) ) return; explore_vnum(ch, pRoom->vnum); } void do_explored(CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; sprintf(buf, "You have explored %d room%s!{x\r\n", ch->pcdata->explored->set, (ch->pcdata->explored->set == 1 ? "" : "s") ); send_to_char(buf,ch); //This shows all the rooms they've explored. Probably don't need mortals seeing this, and for immortals... it'd get really spammy. Mostly an example. /* for(pExp = ch->pcdata->explored->bits ; pExp ; pExp = pExp->next ) { for(bit = 1 ; bit <= 32 ; ++bit ) { if(IS_SET(pExp->bits, (1 << bit) ) ) { sprintf(buf, "[%-5d]", (pExp->mask * 32 + bit) ); send_to_char(buf,ch); } } send_to_char("\r\n",ch); } */ return; } /*** **Now open up merc.h and add this above the struct pcdata definition. */ //Exploration holder. //Basically just a linked list of int's where we only use the bits. typedef struct explore_holder { struct explore_holder *next; unsigned int bits; int mask; } EXPLORE_HOLDER; typedef struct exploration_data { EXPLORE_HOLDER *bits; int set; } EXPLORE_DATA; /*** **Add this to the bottom of the pcdata struct. */ EXPLORE_DATA *explored; /*** **Lower down in merc.h look for the prototypes and add these under act_move.c */ void check_explore args( ( CHAR_DATA *, ROOM_INDEX_DATA * ) ); void explore_vnum args( (CHAR_DATA *, int ) ); bool explored_vnum args( (CHAR_DATA *, int ) ); /*** **In recycle.c locate new_pcdata and add this right above the call to VALIDATE(pcdata); */ pcdata->explored = (EXPLORE_DATA *)calloc(1, sizeof(*(pcdata->explored) ) ); //Allocate explored data /*** **Right below in free_pcdata() add this before INVALIDATE(pcdata); */ { EXPLORE_HOLDER *pExp, *e_next; for(pExp = pcdata->explored->bits ; pExp ; pExp = e_next ) { e_next = pExp->next; free(pExp); } } /*** **Open up handler.c and find char_to_room. Add this right after a player is added to the list (pRoomIndex->people = ch;) */ check_explore(ch, pRoomIndex); //Explore the room /*** **Open up save.c and under fwrite_char, and before it writes alias' add */ if(ch->pcdata->explored->set > 0 ) { EXPLORE_HOLDER *pExp; fprintf(fp, "Explored %d\n", ch->pcdata->explored->set); for(pExp = ch->pcdata->explored->bits ; pExp ; pExp = pExp->next ) fprintf(fp, "%d %d\n", pExp->mask, pExp->bits ); fprintf(fp, "-1 -1\n" ); } /*** **Look down farther for fread_char under case 'E' add this */ if(!str_cmp(word, "Explored") ) { int mask, bit; EXPLORE_HOLDER *pExp; ch->pcdata->explored->set = fread_number(fp); while(1) { mask = fread_number(fp); bit = fread_number(fp); if(mask == -1) break; for(pExp = ch->pcdata->explored->bits ; pExp ; pExp = pExp->next ) if(pExp->mask == mask) break; if(!pExp) { pExp = (EXPLORE_HOLDER *)calloc(1, sizeof(*pExp) ); pExp->next = ch->pcdata->explored->bits; ch->pcdata->explored->bits = pExp; pExp->mask = mask; } pExp->bits = bit; } fMatch = TRUE; } /*** **Open up interp.c and throw this in the command table (I put mine near kill, cuz the functions are similar!) */ { "explored", do_explored, POS_RESTING, 0, LOG_NORMAL, 1 }, /*** **Add this in interp.h wherever */ DECLARE_DO_FUN( do_explored ); /*** **All you have to do now is do a clean make, and copyover! Everything should start working automatically! */