cjs@moncsbruce.oz (Chris Stuart) (08/04/88)
The following unofficial omega bug fixes are presented for public consumption. Changes are made to the following files from the distributed version. oinv.c osave.c osite1.c ocom1.c ofile.c =================================================================== There are 10 distinct fixes. Numbers 1, 4, 6, 7 and 10 really matter. Fixes 2, 3, 5, 8 and 9 are more for consistency. 1) All calls to free are deleted for strings. There are plenty of places where object records are copied, which of course copies the string pointers too. The strings cannot be freed unless you are sure there is no other current pointer to them. I know this means you eventually run out of memory. So save your game occassionally. Or do a major rewrite. But as it is has potential for disaster. At best, the names of objects will suddenly change for no apparent reason. (changes near lines 391 and 407) 2) A money object may be freed after it is used. (near line 557) 3) When you take a two handed weapon out of your pack into your weapon hand, you will wield it if the ready hand is vacant. This makes retrieval from a pack consistent for one and two handed weapons. (near line 650) 4) Prevents you from dropping used cursed objects when you are in inventory mode. (near line 908 and 917) 5) Prevents you from wielding a two handed weapon when you take it into your ready hand. This makes the code a little more consistent. For ANY weapon you wield (if possible) by taking it into the weapon hand, and you only hold it by taking it into the ready hand. (near line 995) 6) You cannot merge objects if they are in use. This is needed to prevent you from wielding 6 broad swords or whatever. (near line 1000) 7) This need for this patch was also discovered and posted by Charles Martin. It prevents you from putting stuff in a slot where it is not usable. (And also from being able to use scrolls arbitrarily often.) (near line 1006) 8) Another instance in which an object may be freed. (near line 1082) 9) For consistency. To take a weapon into the ready hand is to hold it, not wield it. (near line 1170) 10) Fixes a bug in the original, where an object might be dropped without being initialized. (near line 1304, and 1307) diff -c orig/oinv.c new/oinv.c *** orig/oinv.c Thu Aug 4 11:19:58 1988 --- new/oinv.c Thu Aug 4 11:19:59 1988 *************** *** 388,394 int n; pob obj; { ! int i,conformed=FALSE,subtracted=FALSE,freetrue,freecurse; if (obj != NULL) for(i=0;i<MAXITEMS;i++) if (Player.possessions[i] == obj) { if (! subtracted) { --- 388,394 ----- int n; pob obj; { ! int i,conformed=FALSE,subtracted=FALSE; if (obj != NULL) for(i=0;i<MAXITEMS;i++) if (Player.possessions[i] == obj) { if (! subtracted) { *************** *** 404,415 } } if (obj->number < 1) { - freetrue=(obj->objstr != obj->truename); - freecurse=((obj->objstr != obj->cursestr)&& - (obj->cursestr != obj->truename)); - free(obj->objstr); - if (freetrue) free(obj->truename); - if (freecurse) free(obj->cursestr); free((char *) obj); } } --- 404,409 ----- } } if (obj->number < 1) { free((char *) obj); } } *************** *** 554,559 if (o->objchar == CASH) { print2("You gained some cash."); Player.cash += o->basevalue; dataprint(); } else if (optionp(PACKADD)) { --- 548,554 ----- if (o->objchar == CASH) { print2("You gained some cash."); Player.cash += o->basevalue; + free((char *)o); dataprint(); } else if (optionp(PACKADD)) { *************** *** 647,652 morewait(); Command_Duration += 2; item = Player.possessions[slot] = Player.pack[response-'A']; for(i=response-'A';i<Player.packptr-1;i++) Player.pack[i] = Player.pack[i+1]; Player.pack[--Player.packptr] = NULL; --- 642,650 ----- morewait(); Command_Duration += 2; item = Player.possessions[slot] = Player.pack[response-'A']; + if (slot == O_WEAPON_HAND && Player.possessions[O_READY_HAND] == NULL + && twohandedp(item->id) ) + Player.possessions[O_READY_HAND] = item; for(i=response-'A';i<Player.packptr-1;i++) Player.pack[i] = Player.pack[i+1]; Player.pack[--Player.packptr] = NULL; *************** *** 905,918 { int n,waitflag; if (Player.possessions[slot] != NULL) { ! n = Player.possessions[slot]->number; ! if (n > 1) n = get_item_number(Player.possessions[slot]); ! if (n > 0) { ! p_drop_at(Player.x,Player.y,n,Player.possessions[slot]); ! waitflag = (Player.possessions[slot]->used && ! (Player.possessions[slot]->number == n)); ! conform_lost_objects(n,Player.possessions[slot]); ! if (waitflag) morewait(); } else print3("Didn't drop anything."); } --- 903,921 ----- { int n,waitflag; if (Player.possessions[slot] != NULL) { ! if(cursed(Player.possessions[slot]) == TRUE + TRUE) ! print3("It sticks to your fingers!"); ! else { ! n = Player.possessions[slot]->number; ! if (n > 1) n = get_item_number(Player.possessions[slot]); ! if (n > 0) { ! p_drop_at(Player.x,Player.y,n,Player.possessions[slot]); ! waitflag = (Player.possessions[slot]->used && ! (Player.possessions[slot]->number == n)); ! conform_lost_objects(n,Player.possessions[slot]); ! if (waitflag) morewait(); ! } ! else print3("Didn't drop anything."); } } else print3("Didn't drop anything."); *************** *** 914,920 conform_lost_objects(n,Player.possessions[slot]); if (waitflag) morewait(); } - else print3("Didn't drop anything."); } else print3("Didn't drop anything."); } --- 917,922 ----- } else print3("Didn't drop anything."); } } else print3("Didn't drop anything."); } *************** *** 992,999 Player.possessions[O_WEAPON_HAND]); if (! airnull) ! a2h = (twohandedp(oair->id) && ! ((slot == O_READY_HAND) || (slot == O_WEAPON_HAND))); /* figure out which action to take */ --- 994,1000 ----- Player.possessions[O_WEAPON_HAND]); if (! airnull) ! a2h = twohandedp(oair->id) && (slot == O_WEAPON_HAND); /* figure out which action to take */ *************** *** 998,1005 /* figure out which action to take */ ! /* merge if both are same kind of object */ ! merge = objequal(oslot,oair); take = ((!merge) && (!slotnull) && airnull); --- 999,1006 ----- /* figure out which action to take */ ! /* merge if both are same kind of object AND NOT IN USE */ ! merge = objequal(oslot,oair) && ! oslot->used; take = ((!merge) && (!slotnull) && airnull); *************** *** 1003,1009 take = ((!merge) && (!slotnull) && airnull); ! put = ((!merge) && slotnull && (!airnull)); trade = ((!merge) && (!slotnull) && (!airnull) && slottable(oair,slot)); --- 1004,1010 ----- take = ((!merge) && (!slotnull) && airnull); ! put = ((!merge) && slotnull && (!airnull) && slottable(oair,slot)); trade = ((!merge) && (!slotnull) && (!airnull) && slottable(oair,slot)); *************** *** 1079,1084 { Player.possessions[slot]->number += Player.possessions[O_UP_IN_AIR]->number; Player.possessions[O_UP_IN_AIR] = NULL; } --- 1080,1086 ----- { Player.possessions[slot]->number += Player.possessions[O_UP_IN_AIR]->number; + free((char *)Player.possessions[O_UP_IN_AIR]); Player.possessions[O_UP_IN_AIR] = NULL; } *************** *** 1167,1174 else if ((o->objchar == WEAPON) || (o->objchar == MISSILEWEAPON)) { ! if (twohandedp(o->id) && ! ((slot==O_READY_HAND)||(slot==O_WEAPON_HAND))) { if (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND]) { print1("You heft the weapon and find you must use both hands."); --- 1169,1175 ----- else if ((o->objchar == WEAPON) || (o->objchar == MISSILEWEAPON)) { ! if (twohandedp(o->id) && slot==O_WEAPON_HAND) { if (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND]) { print1("You heft the weapon and find you must use both hands."); *************** *** 1301,1306 pob item; { pob extra=((pob) malloc(sizeof(objtype))); if (Player.packptr < MAXPACK) { print3("Putting extra items back in pack."); morewait(); --- 1302,1310 ----- pob item; { pob extra=((pob) malloc(sizeof(objtype))); + *extra = *item; + extra->number = item->number-1; + item->number = 1; if (Player.packptr < MAXPACK) { print3("Putting extra items back in pack."); morewait(); *************** *** 1304,1312 if (Player.packptr < MAXPACK) { print3("Putting extra items back in pack."); morewait(); - *extra = *item; - extra->number = item->number-1; - item->number = 1; Player.pack[Player.packptr++] = extra; } else if (Player.possessions[O_UP_IN_AIR] == NULL) { --- 1308,1313 ----- if (Player.packptr < MAXPACK) { print3("Putting extra items back in pack."); morewait(); Player.pack[Player.packptr++] = extra; } else if (Player.possessions[O_UP_IN_AIR] == NULL) { =================================================================== This patch fixes the problem with two handed weapons, which i previously and incorrectly blamed on oinv.c (sorry). The problem comes when you save and restore a game in which a two handed weapon is wielded. Objects in the left and right hands, which were identical, become duplicates. This patch makes them identical again. diff -c orig/osave.c new/osave.c *** orig/osave.c Thu Aug 4 11:21:27 1988 --- new/osave.c Thu Aug 4 11:21:28 1988 *************** *** 397,402 fread((char *)Spells,sizeof(Spells),1,fd); for(i=0;i<MAXITEMS;i++) Player.possessions[i] = restore_item(fd); for(i=0;i<MAXPACK;i++) Player.pack[i] = restore_item(fd); for(i=0;i<PAWNITEMS;i++) --- 397,415 ----- fread((char *)Spells,sizeof(Spells),1,fd); for(i=0;i<MAXITEMS;i++) Player.possessions[i] = restore_item(fd); + if(Player.possessions[O_WEAPON_HAND] != NULL && + Player.possessions[O_WEAPON_HAND]->used && + twohandedp(Player.possessions[O_WEAPON_HAND]->id)){ + if(!objequal(Player.possessions[O_WEAPON_HAND], + Player.possessions[O_READY_HAND])){ + mprint("BUG. Strange case for wielding two handed weapon."); + morewait(); + } + else{ + free((char *)Player.possessions[O_READY_HAND]); + Player.possessions[O_READY_HAND] = Player.possessions[O_WEAPON_HAND]; + } + } for(i=0;i<MAXPACK;i++) Player.pack[i] = restore_item(fd); for(i=0;i<PAWNITEMS;i++) =================================================================== This patch solves a problem which arises when you sell some but not all of a group of identical objects to the pawn shop. Previously, the left over objects got lost. diff -c orig/osite1.c new/osite1.c *** orig/osite1.c Thu Aug 4 11:21:50 1988 --- new/osite1.c Thu Aug 4 11:21:51 1988 *************** *** 1058,1064 Pawnitems[9]->number = number; Pawnitems[9]->known = 2; Player.pack[i]->number -= number; ! if (Player.pack[i]->number < 1) free((char *)Player.pack[i]); Player.pack[i] = NULL; dataprint(); --- 1058,1064 ----- Pawnitems[9]->number = number; Pawnitems[9]->known = 2; Player.pack[i]->number -= number; ! if (Player.pack[i]->number < 1){ free((char *)Player.pack[i]); Player.pack[i] = NULL; } *************** *** 1060,1066 Player.pack[i]->number -= number; if (Player.pack[i]->number < 1) free((char *)Player.pack[i]); ! Player.pack[i] = NULL; dataprint(); } } --- 1060,1067 ----- Player.pack[i]->number -= number; if (Player.pack[i]->number < 1){ free((char *)Player.pack[i]); ! Player.pack[i] = NULL; ! } dataprint(); } } =================================================================== This patch is a confident guess at a potential problem. drawvision needs two args, and was originally called here with none. diff -c orig/ocom1.c new/ocom1.c *** orig/ocom1.c Thu Aug 4 11:17:39 1988 --- new/ocom1.c Thu Aug 4 11:17:40 1988 *************** *** 16,22 if (Player.status[BERSERK]) if (goberserk()) { setgamestatus(SKIP_PLAYER); ! drawvision(); } if (! gamestatusp(SKIP_PLAYER)) { if (searchval > 0) { --- 16,22 ----- if (Player.status[BERSERK]) if (goberserk()) { setgamestatus(SKIP_PLAYER); ! drawvision(Player.x, Player.y); } if (! gamestatusp(SKIP_PLAYER)) { if (searchval > 0) { =================================================================== Three calls to morewait are inserted, which ensure you get to see the final message at the end of a game before the screen clears. diff -c orig/ofile.c new/ofile.c *** orig/ofile.c Thu Aug 4 11:18:38 1988 --- new/ofile.c Thu Aug 4 11:18:39 1988 *************** *** 315,320 if (Hiscore < points) { morewait(); mprint("Yow! A new high score!"); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%s\n",descrip); fprintf(fd,"%d\n",points); --- 315,321 ----- if (Hiscore < points) { morewait(); mprint("Yow! A new high score!"); + morewait(); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%s\n",descrip); fprintf(fd,"%d\n",points); *************** *** 334,339 if (Player.alignment < Chaos) { morewait(); mprint("Criminy! A new Lord of Chaos!"); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%d\n",Player.level); fprintf(fd,"%d\n",Player.alignment); --- 335,341 ----- if (Player.alignment < Chaos) { morewait(); mprint("Criminy! A new Lord of Chaos!"); + morewait(); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%d\n",Player.level); fprintf(fd,"%d\n",Player.alignment); *************** *** 354,359 if (Player.alignment > Law) { morewait(); mprint("Gosh! A new Lord of Law!"); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%d\n",Player.level); fprintf(fd,"%d\n",Player.alignment); --- 356,362 ----- if (Player.alignment > Law) { morewait(); mprint("Gosh! A new Lord of Law!"); + morewait(); fprintf(fd,"%s\n",Player.name); fprintf(fd,"%d\n",Player.level); fprintf(fd,"%d\n",Player.alignment); ===================================================================