Here are the bugs from the list that I saved code fragments for. Many of the bugs are easy to fix and no code fragments exist. Lastly, special thanks to all who contributed to the bug list. ===== refuse an order if charmee is wait-stated ===== In comm.c in void write_to_buffer: the line at the bottom that says: strcpy( d->outbuf + d->outtop, txt ); should read: strncpy( d->outbuf + d->outtop, txt, length ); It was causing me the exact kind of weird stuff happening that has been mentioned in today's "It's NULL how in the hell did it get inside the loop?" thread, and other various random interesting Undefined results. It may look tiny, but causes MAJOR problems when it starts writing over mem, if "txt" isn't ended with a '\0'. > memory allocation is flaky Anyone has more details about this? (which function is flaky?) ===== Object with no flags (eg Glow, Magic etc) and no long description will have a strange wonderful random description displayed everytime someone look at it. (check obj vnum 1336 (altar) in ROM/Merc22) bugfix: char *format_obj_to_char(), add these line before return buf; if (strlen(buf)<=0)) strcat(buf,"This object has no description. Please inform the IMP."); return buf; ===== In comm.c in close_socket, there is something that looks like: else free_char( dclose->character ) shouldn't it be?: free_char( dclose->original ? dclose->original : dclose->character ); ===== Please add the bug that it is impossible to steal from blind characters. The fix to this is to give all characters the same vision as the thief while the inventory is being checked. By same vision, I mean DETECT INVIS and HOLY LIGHT. ===== /* put this in */ if (skill_table[sn].spell_fun == spell_null) { send_to_char( "That's not a spell!\n\r", ch ); return; } ===== ROM 2.3 base IMP's... Player wants to make big money! Player saves Player drops 100,000 gold Player opens second session and enters same ch->name Player waits at password prompt, pfile is loaded already Player switches back to old session and quits Pile of gold is sitting on floor In second session, player enters password and logs in Player picks up pile of gold Player is now twice as rich as they once were. ----- Declare in do_quit: DESCRIPTOR_DATA *d,*d_next; add this to the end of do_quit: /* * After extract_char the ch is no longer valid! */ save_char_obj( ch ); id = ch->id; d = ch->desc; extract_char( ch, TRUE ); if ( d != NULL ) close_socket( d ); for (d = descriptor_list; d != NULL; d = d_next) { CHAR_DATA *tch; d_next = d->next; tch = d->original ? d->original : d->character; if (tch && tch->id == id && ch != tch) { extract_char(tch,TRUE); close_socket(d); } } return; } ===== First, in fight.c, xp_compute(): > if (IS_SET(victim->act,ACT_NOALIGN)) > xp = base_exp; > > else if (gch->alignment > 500) /* for goodie two shoes */ > { > if (victim->alignment < -750) > xp = base_exp * 4/3; > > else if (victim->alignment < -500) > xp = base_exp * 5/4; > > else if (victim->alignment > 250) > xp = base_exp * 3/4; > > else if (victim->alignment > 750) > xp = base_exp / 4; > > else if (victim->alignment > 500) > xp = base_exp / 2; > > else > xp = base_exp; The two last if-tests will never be tested, because if victim->alignment > 500 or 750 then its > 250 too... (I was in doubt wether to say this, as I usually play good chars :-) ===== Second, also in fight.c, do_bash(): > /* speed */ > if (IS_SET(ch->off_flags,OFF_FAST)) > chance += 10; > if (IS_SET(ch->off_flags,OFF_FAST)) > chance -= 20; the second if should be if (IS_SET(victim->off_flags,OFF_FAST)) ===== While looking at this in do_dirt() I found a third bug (I think..) > if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) > chance += 10; > if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,OFF_FAST)) > chance -= 25; Shouldn't the last OR be IS_AFFECTED(victim,OFF_HASTE) ? ===== ObNotSoSeriousBug: in fread_obj() in save.c if (!str_cmp(word, "End") ) { if ( !fNest || !fVnum || obj->pIndexData == NULL) { bug("Fread_obj: incomplete object.", 0); /* This shouldnt be the way to remove an obj which is create by create_object(). Doesnt free extra description, reduce object count etc - Ender free_string(obj->name ); free_string(obj->description); free_string(obj->short_descr); obj->next = obj_free; obj_free = obj; */ extract_obj(obj); /* this should be the way */ return; } } ===== And also, concerning the save, it calls that if obj->pObjIndex is NULL too, better at least make sure it checks if it's null in extract_obj or it will crash where it accesses --obj->pObjIndex->count. ===== the !can_see(ch,d->character) condition is the cause of a slight bug. If an invis imm switches into a mob, the imm shows up on the who list. The easy solution to this is to move the wch = (d->original != NULL)? d->original : d->character; line above the conditional, and change !can_see(ch,d->character) to !can_see(ch,wch). If you really want to optimize for speed, then change !can_see(ch,wch) to !can_see(ch,wch=(d->original!=NULL)?d->original:d->character) This is a little faster, since the initialization is only performed for those people in the CON_PLAYING connected state. Still were, talking about maybe 10 connections not playing, and a saving of only 10 instructions or so per connection not checked. ===== In fight.c, do_dirt() the line: act("$n kickes dirt in your eyes!",ch,victim,NULL,TO_VICT); should read: act("$n kickes dirt in your eyes!",ch,NULL,victim,TO_VICT); Check if it's backwards in your ROM 2.3 code, may be. ===== In act_info.c: procedure: show_char_to_char_0() the line: if ( IS_SET(victim->act, PLR_WIZINVIS) ) strcat( buf, "(Wizi) " ); should read: if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_WIZINVIS) ) strcat ( buf, "(Wizi) " ); Since the act bit vector is different for PCs and for NPCs. This bug causes any mob who has ACT_UNDEAD (defined in merc.h as O, same as PLR_WIZINVIS) set to show up as "(Wizi)" when someone sees them in a room. ===== add this to end of case P in area_reset /* * Ensure that the container gets reset. */ obj_to->value[1] = obj_to->pIndexData->value[1]; break; ===== Yes, there's a bug in 'affect_remove' in Merc 2.1. At the end of 'affect_remove' the linked-list update code is broken. BAD: paf->next = affect_free; affect_free = paf->next; CHANGE TO: paf->next = affect_free; affect_free = paf; I believe Alander was the first to find this. This is what happens when one writes linked-list code all over the code instead of using C++ and having a linked-list template class. Argh. Seems to be in affect_remove_obj too. ===== When player dies, racial affects are lost until player logs on again. ===== dunno if it is mention here before (havent been keeping up with the list...can i have an copy of the lastest bug list?) anyway, there is a small memory leak that ch->pnote is not free if the player quit halfway thru writing the note. The patch is in free_char() in db.c just after the section on if ( ch->pcdata != NULL) { ... } add if ( ch->pnote != NULL ) { free_string( ch->pnote->text ); ch->pnote->text=NULL; free_string( ch->pnote->subject ); free_string( ch->pnote->to_list ); free_string( ch->pnote->date ); free_string( ch->pnote->sender ); ch->pnote->next = note_free; note_free = ch->pnote; ch->pnote = NULL; } ===== The problem was that objects in corpses were being extracted if the corpse decayed while it was being held or when it was in another object. if (obj->item_type == ITEM_CORPSE_PC && obj->contains) { /* save the contents */ OBJ_DATA *t_obj, *next_obj; for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj) { next_obj = t_obj->next_content; obj_from_obj(t_obj); if (obj->in_obj) /* in another object */ obj_to_obj(t_obj,obj->in_obj); else if (obj->carried_by) /* carried */ ^^^^ obj_to_char(t_obj,obj->carried_by); else if (obj->in_room == NULL) /* destroy it */ ^^^^ extract_obj(t_obj); else /* to a room */ obj_to_room(t_obj,obj->in_room); } } ===== I happened upon a bug which Im surprised noone has seen in act_info.c around line 500-550 depending on your base. Try loading an invis sword and turning holylight off so you cant see it. Then 'look sword'. You can still look at something if you know it is there. Drop it and look at it also works. Very easy to fix, just move 1 bracket. In the if( can_see_obj( ch, obj ) ) block where it checks for extra descriptions, just move the close bracket down to include the 'if ( is_name( arg1, obj->name ) )' block and it is done. Do the same for ' obj = ch->in_room->contents' for in room stuff. Sorry for no exact line numbers, I dont do that anymore since my code bears little resemblance to yours. Fusion of Lost Realms ===== Inside the nannyObBug: someone posted the code on the problem of extract_obj(). While i am tracing a bug which corrupting my char_list link list, i notice a similar problem with extract_char() too. Generally, the problem occurs when victim died while in the loop aggr_update(). In aggr_update(), there is a loop which goes thru the char_list something like for (vch=char_list; vch; vch=vch_next) { vch_next=ch->next; .... .... } the problem occurs when victim = ch->next. So in the loop, vch_next is been defined as ch->next (ie, the victim), and victim died (ie extract_char() is been called), then what happen is the loop will go crazy thereafter....since vch_next is pointing to an 'freed' CHAR_DATA. This problem should occurs in other cases where there is iteration thru char_list and within the iteration, victim might die() function, in the case: CON_DEFAULT_CHOICE, if the > new player picks to customize their character, the function allocates a > gen_data PERM. This perm is NOT recycled. Should it be an alloc_mem() and > deallocated when the player chooses 'done'? > -Tomasin > ===== in extract_obj() handler.c: There exists a memory leak in the loop that removes obj->extra_descr for (ed = obj->extra_descr; ed != NULL; ed = ed_next) { ed_next=ed->next; free_string(ed->descriptino); free_string(ed->keyword); ed->next=extra_descr_free; <--- Insert this line here! extra_descr_free=ed; } ===== Here is a bug list for ROM 2.3. Most of the fixes have been posted or are easy to implement. Email if you get stuck on any of them. acid blast damages caster's eq instead of targets login duplication bug crashes when switched immortal logs into to link-dead original body light in room fades when link is lost link is lost by excessive spam dispel magic has syntax errors near detect hidden can find invisible imms with locate object eq in corpses is lost if it decays while held casting a skill nodelay for charmees check for overflow: mwhere, locate, who, note list, list (at shops) memory allocation is flaky give the victim same vision as thief when stealing look at an obj with no flags (Glow, Magic) and no long description invis imms who switch into mobs show up on who fight.c, xp_compute(), ordering of elseifs for good chars fight.c, do_bash(), should be victim->off_flags for the -20 chance fight.c, do_dirt(), one OFF_FAST should be AFF_HASTE for -25 chance fight.c, do_dirt(), act("$n kicks dirt in your eyes!",ch,NULL,victim,TO_VICT); fread_obj() in save.c should use extract_obj (check for null pIndexData) act_info.c: show_char_to_char_0(), wizi should be checked for PC's only area resets do not close or lock containers affect_remove in handler.c, linked-list update at end, affect_free = paf affect_remove_obj in handler.c, same as affect_remove comm.c in act() terminate strings and use new len for write_buffer() handler.c in get_skill should be else if after the sneak check for mobs when player dies, racial affects are lost until player logs on again. free_char() in db.c check for note in progress to be freed obj_update() in update.c extracted objects if corpse decayed in cont or held invis items can be referenced in room if you know they are there in nanny() CON_DEFAULT_CHOICE after customize, gen_data PERM is not recycled all looping thru char list code is bad if next next char is freed memleak extract_obj() in handler.c need to link ed->next to extra_descr_free