[comp.sources.games.bugs] Some more omega bug fixes.

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);
===================================================================