Subject: bin/5806: [PATCH] Rogue bug report against Linux port of NetBSD games (fwd)
To: None <gnats-bugs@gnats.netbsd.org>
From: Joseph Myers <jsm@octomino.demon.co.uk>
List: netbsd-bugs
Date: 07/20/1998 17:21:55
>Number:         5806
>Category:       bin
>Synopsis:       [PATCH] Rogue bug report against Linux port of NetBSD games (fwd)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 20 10:35:00 1998
>Last-Modified:
>Originator:     Joseph Samuel Myers
>Organization:
Trinity College, University of Cambridge, UK
>Release:        NetBSD-current of 1998-03-21
>Environment:
	
[
System: Linux octomino 2.0.35 #1 Tue Jul 14 19:09:50 UTC 1998 i586 unknown
Architecture: i586
]
>Description:
I have received the following bug report and (reversed) patch for a
bug in rogue from a user of the Linux port of the NetBSD games.  Please
apply the patch or otherwise fix the bug in NetBSD.

>How-To-Repeat:

See appended message.

>Fix:

See appended message.

If you have any queries about the patch or the problem reported, it would
be best to contact the person who originally reported it, lash@tellabs.com.

Original bug description and patch:
Date: Sun, 19 Jul 1998 16:30:46 -0500 (CDT)
From: lash@tellabs.com
To: jsm28@cam.ac.uk
Subject: A fix (I think) for that rogue problem I was having


Joseph,

It took me longer than I thought, but I think I have a solution for the 
rogue problem I was having.  Initially I was just looking to fix the symptoms,
but I think I found the root cause of the problem.  When I just tried to treat
the symptoms I ran into other issues, and my engineer side just wouldn't let
me stop until I found the root cause.

The symptoms of the problem were that the dungeon array could have spaces marked
as containing a monster even though there were no matching monsters in the
level_monsters list.  This only seemed to happen when dragons were around,
and now I know why.

Dragons breathe fire, and are the only monsters that can kill other monsters.
looking at how mv_mons() works, it moves each monster in the level_monsters
list.  It works around one possible problem for Leprechans and Nymphs which
can disappear, by determining what the next monster in the list will be before
moving the current monster, that way if the current monster is removed from
the level_monsters list, there is no problem determining what the next monster
should be.  Unfotunately, if a dragon kills the next monster in the list, problems
can begin.

When this occurs, the killed monster is moved to the free_list which contains
things like killed monsters and used objects.  This means that if the dragon 
kills the next monster in the level_monsters list, mv_mons will start moving the
things in the free_list.  This can cause several problems, including the one that
I was seeing.

To reproduce the problem, we can play in wizard mode until we get to to level
20 or 21 where "there be dragons".  You need to have a scare monster, and a ring
of slow digestion helps.  Then just stand on the scare monster scroll and wait
for a whole bunch of monsters to come around you.  Basically you need to have 
one dragon, and let it kill all the other monsters.  Keep doing this and eventually
you should get a message from "object_at(): Inconsistent ...", at this point the
game is likely to crash, or you will see "&" appear on the screen, etc.


My patch basically checks that the next monster is on the level_monsters list
before trying to move the monster.  If it is not, no more monsters will be moved.

I realize this isn't necessarily the best of all possible ways of handling the 
problem, but it does avoid the problem, and really isn't noticeable from a game play
point of view.

I also have changed the seeding of the random number generator since I play on
a laptop and usually turn it on, log in, and start rogue, it always got the
same pid, so I would play the same game all the time.  I seed it using time
as suggested.  I guess I would at least like to see this as a compile time option.

Anyway, the patch is attatced to the end of this mail.

Bill Lash
lash@tellabs.com



diff -rc rogue/machdep.c rogue.orig/machdep.c
*** rogue/machdep.c	Wed Jul  8 18:11:43 1998
--- rogue.orig/machdep.c	Wed Jun 24 18:07:30 1998
***************
*** 436,445 ****
  int
  md_gseed()
  {
! 	time_t seconds;
! 
! 	time(&seconds);
! 	return((int) seconds);
  }
  
  /* md_exit():
--- 436,442 ----
  int
  md_gseed()
  {
! 	return(getpid());
  }
  
  /* md_exit():
diff -rc rogue/monster.c rogue.orig/monster.c
*** rogue/monster.c	Wed Jul  8 16:02:16 1998
--- rogue.orig/monster.c	Wed Jun 24 18:07:30 1998
***************
*** 174,180 ****
  void
  mv_mons()
  {
! 	object *monster, *next_monster, *test_mons;
  	boolean flew;
  
  	if (haste_self % 2) {
--- 174,180 ----
  void
  mv_mons()
  {
! 	object *monster, *next_monster;
  	boolean flew;
  
  	if (haste_self % 2) {
***************
*** 213,229 ****
  		if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
  			mv_1_monster(monster, rogue.row, rogue.col);
  		}
! NM:		test_mons = level_monsters.next_monster;
! 		monster = NULL;
! 		while(test_mons)
! 		{
! 			if(next_monster == test_mons)
! 			{
! 				monster = next_monster;
! 				break;
! 			}
! 			test_mons = test_mons->next_monster;
! 		}
  	}
  }
  
--- 213,219 ----
  		if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
  			mv_1_monster(monster, rogue.row, rogue.col);
  		}
! NM:		monster = next_monster;
  	}
  }
  
>Audit-Trail:
>Unformatted: