diff -Naurd ../nethack-3.3.1/win/gnome/gnbind.c ./win/gnome/gnbind.c
--- ../nethack-3.3.1/win/gnome/gnbind.c Sat Aug 5 11:53:32 2000
+++ ./win/gnome/gnbind.c Fri Mar 22 14:41:13 2002
@@ -21,6 +21,7 @@
 /* Interface definition, for windows.c */
 struct window_procs Gnome_procs = {
     "Gnome",
+    WC_COLOR|WC_HILITE_PET|WC_INVERSE,
     gnome_init_nhwindows,
     gnome_player_selection,
     gnome_askname,
@@ -69,6 +70,7 @@
     gnome_start_screen,
     gnome_end_screen,
     gnome_outrip,
+    genl_preference_update,
 };
 
 /*  
@@ -110,49 +112,222 @@
    offers a Quit option, it is its responsibility to clean up and terminate
    the process. You need to fill in pl_character[0].
 */
-void gnome_player_selection()
+void
+gnome_player_selection()
 {
-  int num_roles, availcount, i, nRole;
-  const char** choices;
+    int n, i, sel;
+    const char** choices;
+    int* pickmap;
 
-  /* select a role */
-  for (num_roles = 0; roles[num_roles].name.m; ++num_roles) continue;
-  choices = (const char **)alloc(sizeof(char *) * (num_roles+1));
-  for (;;) {
-    availcount = 0;
-    for (i = 0; i < num_roles; i++) {
-      choices[i] = 0;
-      if (ok_role(i, flags.initrace,
-		  flags.initgend, flags.initalign)) {
-	choices[i] = roles[i].name.m;
-	if (flags.initgend >= 0 && flags.female && roles[i].name.f)
-	  choices[i] = roles[i].name.f;
-	++availcount;
-      }
-    }
-    if (availcount > 0) break;
-    else if (flags.initalign >= 0) flags.initalign = -1;    /* reset */
-    else if (flags.initgend >= 0) flags.initgend = -1;
-    else if (flags.initrace >= 0) flags.initrace = -1;
-    else panic("no available ROLE+race+gender+alignment combinations");
-  }
-  choices[num_roles] = (const char *) 0;
-  nRole=ghack_player_sel_dialog(choices);
+    /* prevent an unnecessary prompt */
+    rigid_role_checks();
+
+    if (!flags.randomall && flags.initrole < 0) {
+
+	/* select a role */
+	for (n = 0; roles[n].name.m; n++) continue;
+	choices = (const char **)alloc(sizeof(char *) * (n+1));
+	pickmap = (int*)alloc(sizeof(int) * (n+1));
+	for (;;) {
+	    for (n = 0, i = 0; roles[i].name.m; i++) {
+		if (ok_role(i, flags.initrace,
+			    flags.initgend, flags.initalign)) {
+		    if (flags.initgend >= 0 && flags.female && roles[i].name.f)
+			choices[n] = roles[i].name.f;
+		    else
+			choices[n] = roles[i].name.m;
+		    pickmap[n++] = i;
+		}
+	    }
+	    if (n > 0) break;
+	    else if (flags.initalign >= 0) flags.initalign = -1;    /* reset */
+	    else if (flags.initgend >= 0) flags.initgend = -1;
+	    else if (flags.initrace >= 0) flags.initrace = -1;
+	    else panic("no available ROLE+race+gender+alignment combinations");
+	}
+	choices[n] = (const char *) 0;
+	if (n > 1)
+	    sel = ghack_player_sel_dialog(choices,
+		_("Player selection"), _("Choose one of the following roles:"));
+	else sel = 0;
+	if (sel >= 0) sel = pickmap[sel];
+	else if (sel == ROLE_NONE) {		/* Quit */
+	    clearlocks();
+	    gnome_exit_nhwindows(0);
+	}
+	free(choices);
+	free(pickmap);
+    } else if (flags.initrole < 0) sel = ROLE_RANDOM;
+    else sel = flags.initrole;
   
-  /* Quit */
-  if ( nRole == -1 )
-    {
-      clearlocks();
-      gnome_exit_nhwindows(0);
+    if (sel == ROLE_RANDOM) {	/* Random role */
+	sel = pick_role(flags.initrace, flags.initgend,
+			  flags.initalign, PICK_RANDOM);
+	if (sel < 0) sel = randrole();
     }
-  /* Random role */
-  if ( nRole == -2)
-    {
-      nRole = rn2(num_roles);
-      pline("This game you will be %s", an(choices[nRole]));
+
+    flags.initrole = sel;
+
+    /* Select a race, if necessary */
+    /* force compatibility with role, try for compatibility with
+     * pre-selected gender/alignment */
+    if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
+	if (flags.initrace == ROLE_RANDOM || flags.randomall) {
+	    flags.initrace = pick_race(flags.initrole, flags.initgend,
+				       flags.initalign, PICK_RANDOM);
+	    if (flags.initrace < 0) flags.initrace = randrace(flags.initrole);
+	} else {
+	    /* Count the number of valid races */
+	    n = 0;	/* number valid */
+	    for (i = 0; races[i].noun; i++) {
+		if (ok_race(flags.initrole, i, flags.initgend, flags.initalign))
+		    n++;
+	    }
+	    if (n == 0) {
+		for (i = 0; races[i].noun; i++) {
+		    if (validrace(flags.initrole, i)) n++;
+		}
+	    }
+
+	    choices = (const char **)alloc(sizeof(char *) * (n+1));
+	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
+	    for (n = 0, i = 0; races[i].noun; i++) {
+		if (ok_race(flags.initrole, i, flags.initgend,
+			    flags.initalign)) {
+		    choices[n] = races[i].noun;
+		    pickmap[n++] = i;
+		}
+	    }
+	    choices[n] = (const char *) 0;
+	    /* Permit the user to pick, if there is more than one */
+	    if (n > 1)
+		sel = ghack_player_sel_dialog(choices, _("Race selection"),
+			_("Choose one of the following races:"));
+	    else sel = 0;
+	    if (sel >= 0) sel = pickmap[sel];
+	    else if (sel == ROLE_NONE) { /* Quit */
+		clearlocks();
+		gnome_exit_nhwindows(0);
+	    }
+	    flags.initrace = sel;
+	    free(choices);
+	    free(pickmap);
+	}
+	if (flags.initrace == ROLE_RANDOM) {	/* Random role */
+	    sel = pick_race(flags.initrole, flags.initgend,
+			    flags.initalign, PICK_RANDOM);
+	    if (sel < 0) sel = randrace(flags.initrole);
+	    flags.initrace = sel;
+	}
+    }
+
+    /* Select a gender, if necessary */
+    /* force compatibility with role/race, try for compatibility with
+     * pre-selected alignment */
+    if (flags.initgend < 0 ||
+	!validgend(flags.initrole, flags.initrace, flags.initgend)) {
+	if (flags.initgend == ROLE_RANDOM || flags.randomall) {
+	    flags.initgend = pick_gend(flags.initrole, flags.initrace,
+				       flags.initalign, PICK_RANDOM);
+	    if (flags.initgend < 0)
+		flags.initgend = randgend(flags.initrole, flags.initrace);
+	} else {
+	    /* Count the number of valid genders */
+	    n = 0;	/* number valid */
+	    for (i = 0; i < ROLE_GENDERS; i++) {
+		if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign))
+		    n++;
+	    }
+	    if (n == 0) {
+		for (i = 0; i < ROLE_GENDERS; i++) {
+		    if (validgend(flags.initrole, flags.initrace, i)) n++;
+		}
+	    }
+
+	    choices = (const char **)alloc(sizeof(char *) * (n+1));
+	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
+	    for (n = 0, i = 0; i < ROLE_GENDERS; i++) {
+		if (ok_gend(flags.initrole, flags.initrace, i,
+				flags.initalign)) {
+		    choices[n] = genders[i].adj;
+		    pickmap[n++] = i;
+		}
+	    }
+	    choices[n] = (const char *) 0;
+	    /* Permit the user to pick, if there is more than one */
+	    if (n > 1)
+		sel = ghack_player_sel_dialog(choices, _("Gender selection"),
+			_("Choose one of the following genders:"));
+	    else sel = 0;
+	    if (sel >= 0) sel = pickmap[sel];
+	    else if (sel == ROLE_NONE) { /* Quit */
+		clearlocks();
+		gnome_exit_nhwindows(0);
+	    }
+	    flags.initgend = sel;
+	    free(choices);
+	    free(pickmap);
+	}
+	if (flags.initgend == ROLE_RANDOM) {	/* Random gender */
+	    sel = pick_gend(flags.initrole, flags.initrace,
+			    flags.initalign, PICK_RANDOM);
+	    if (sel < 0) sel = randgend(flags.initrole, flags.initrace);
+	    flags.initgend = sel;
+	}
+    }
+
+    /* Select an alignment, if necessary */
+    /* force compatibility with role/race/gender */
+    if (flags.initalign < 0 ||
+	!validalign(flags.initrole, flags.initrace, flags.initalign)) {
+	if (flags.initalign == ROLE_RANDOM || flags.randomall) {
+	    flags.initalign = pick_align(flags.initrole, flags.initrace,
+					 flags.initgend, PICK_RANDOM);
+	    if (flags.initalign < 0)
+		flags.initalign = randalign(flags.initrole, flags.initrace);
+	} else {
+	    /* Count the number of valid alignments */
+	    n = 0;	/* number valid */
+	    for (i = 0; i < ROLE_ALIGNS; i++) {
+		if (ok_align(flags.initrole, flags.initrace, flags.initgend, i))
+		    n++;
+	    }
+	    if (n == 0) {
+		for (i = 0; i < ROLE_ALIGNS; i++)
+		    if (validalign(flags.initrole, flags.initrace, i)) n++;
+	    }
+
+	    choices = (const char **)alloc(sizeof(char *) * (n+1));
+	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
+	    for (n = 0, i = 0; i < ROLE_ALIGNS; i++) {
+		if (ok_align(flags.initrole,
+			     flags.initrace, flags.initgend, i)) {
+		    choices[n] = aligns[i].adj;
+		    pickmap[n++] = i;
+		}
+	    }
+	    choices[n] = (const char *) 0;
+	    /* Permit the user to pick, if there is more than one */
+	    if (n > 1)
+		sel = ghack_player_sel_dialog(choices, _("Alignment selection"),
+			_("Choose one of the following alignments:"));
+	    else sel = 0;
+	    if (sel >= 0) sel = pickmap[sel];
+	    else if (sel == ROLE_NONE) { /* Quit */
+		clearlocks();
+		gnome_exit_nhwindows(0);
+	    }
+	    flags.initalign = sel;
+	    free(choices);
+	    free(pickmap);
+	}
+	if (flags.initalign == ROLE_RANDOM) {
+	    sel = pick_align(flags.initrole, flags.initrace,
+			     flags.initgend, PICK_RANDOM);
+	    if (sel < 0) sel = randalign(flags.initrole, flags.initrace);
+	    flags.initalign = sel;
+	}
     }
-  
-  flags.initrole = nRole;
 }
 
 
@@ -973,7 +1148,8 @@
     Strcat(ripString, buf);
     
     /* Put $ on stone */
-    Sprintf(buf, "%ld Au\n", u.ugold);
+    Sprintf(buf, "%ld Au\n",
+		u.ugold);
     Strcat(ripString, buf);
 
     /* Put together death description */
@@ -1001,6 +1177,3 @@
 
     ghack_text_window_rip_string( ripString);
 }
-
-
-
diff -Naurd ../nethack-3.3.1/win/gnome/gnglyph.c ./win/gnome/gnglyph.c
--- ../nethack-3.3.1/win/gnome/gnglyph.c Sat Aug 5 11:53:33 2000
+++ ./win/gnome/gnglyph.c Fri Mar 22 14:40:55 2002
@@ -1,8 +1,9 @@
-/*	SCCS Id: @(#)gnglyph.c	3.3	2000/07/16	*/
+/*	SCCS Id: @(#)gnglyph.c	3.4	2000/07/16	*/
 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "gnglyph.h"
+#include "tile2x11.h"
 
 static GHackGlyphs     ghack_glyphs;
 static GdkImlibImage** ghack_tiles = NULL;
@@ -28,8 +29,9 @@
  * NOTES:
  *     The glyphs (tiles) must be in the image in a certain way: the
  *     glyphs must be stacked such that the resultant image is
- *     TILE_X wide, and TILE_Y * (number of glyphs) high.  In this
- *     sense, TILE_X == TILE_Y, and can be any reasonable integer--
+ *     TILE_X * TILES_PER_ROW wide, and
+ *     TILE_Y * (number of glyphs) / TILES_PER_ROW high (rounded up).
+ *     In this sense, TILE_X == TILE_Y, and can be any reasonable integer
  *     say, 16 <= TILE_X <= 64.  Because the glyph number is tightly
  *     coupled to the Nethack object it represents, the order of the
  *     glyphs in the image is imporant: Glyph 1 is at the top of the
@@ -55,12 +57,19 @@
   gdk_imlib_render(ghack_glyphs.im, ghack_glyphs.im->rgb_width,
 	  ghack_glyphs.im->rgb_height);
 
-  ghack_glyphs.count = ghack_glyphs.im->rgb_height / ghack_glyphs.im->rgb_width;
-  ghack_glyphs.width  = ghack_glyphs.im->rgb_width;
-  ghack_glyphs.height = ghack_glyphs.im->rgb_height / ghack_glyphs.count;
+  if (ghack_glyphs.im->rgb_width % TILES_PER_ROW) {
+      g_error("%s is not a multiple of %d (number of tiles/row) pixels wide",
+	      xpmFile, TILES_PER_ROW);
+      return -1;
+  }
+  ghack_glyphs.width = ghack_glyphs.im->rgb_width / TILES_PER_ROW;
+  ghack_glyphs.height = ghack_glyphs.width;
+  ghack_glyphs.count =
+      (ghack_glyphs.im->rgb_height * ghack_glyphs.im->rgb_width) /
+      (ghack_glyphs.width * ghack_glyphs.height);
 
 
-  /* Assume the tiles are stacked vertically.
+  /* Assume the tiles are organized in rows of TILES_PER_ROW
    * Further, assume that the tiles are SQUARE
    */
   ghack_tiles = g_new0( GdkImlibImage*, ghack_glyphs.count );
@@ -186,8 +195,8 @@
 	    (force==TRUE)? "TRUE" : "FALSE");
     }
 
-  if (!ghack_tiles[tile] || force)
-  {
+  if (!ghack_tiles[tile] || force) {
+      int src_x, src_y;
 #if 0
       fprintf( stderr, "crop_and_clone: glyph=%d, tile=%d, ptr=%p, x=%d, y=%d, w=%d, h=%d\n", glyph, tile,
 	      (void*)&(ghack_tiles[tile]), 0,
@@ -197,8 +206,10 @@
 #endif
       if (ghack_glyphs.im->pixmap == NULL)
 	  g_warning( "Aiiee!  ghack_glyphs.im->pixmap==NULL!!!!\n");
-      ghack_tiles[tile] = gdk_imlib_crop_and_clone_image(ghack_glyphs.im, 0,
-	      tile * ghack_glyphs.width,
+      src_x = (tile % TILES_PER_ROW) * ghack_glyphs.width;
+      src_y = (tile / TILES_PER_ROW) * ghack_glyphs.height;
+      ghack_tiles[tile] = gdk_imlib_crop_and_clone_image(ghack_glyphs.im,
+	      src_x, src_y,
 	      ghack_glyphs.height,
 	      ghack_glyphs.width);
   }
@@ -216,4 +227,3 @@
 
   return ghack_tiles[tile];
 }
-
diff -Naurd ../nethack-3.3.1/win/gnome/gnmain.c ./win/gnome/gnmain.c
--- ../nethack-3.3.1/win/gnome/gnmain.c Sat Aug 5 11:53:33 2000
+++ ./win/gnome/gnmain.c Fri Mar 22 14:40:55 2002
@@ -11,6 +11,7 @@
 #include <gdk/gdk.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <signal.h>
 #include "hack.h"
 #include "date.h"
 
@@ -137,7 +138,8 @@
       _("\nSend comments and bug reports to: nethack-bugs@nethack.org\n"
       "This game is free software. See License for details."));
     about = gnome_about_new(_("Nethack"), 
-	    buf1, "(C) 1985-2000 Mike Stephenson", (const char **)authors, buf,
+	    buf1, "Copyright (C) 1985-2002 Mike Stephenson",
+	    (const char **)authors, buf,
 	    NULL);
 
     gtk_signal_connect (GTK_OBJECT (about), "destroy",
@@ -651,9 +653,55 @@
   return;
 }
 
+/*
+ * [ALI] Gnome installs its own handler(s) for SIGBUS, SIGFPE and SIGSEGV.
+ * These handlers will fork and exec a helper program. When that helper
+ * comes to initialize GTK+, it may fail if setuid/setgid. We solve this
+ * by dropping privileges before passing the signal along the chain.
+ * Note: We don't need to either drop or mask the saved ID since this
+ * will be reset when the child process performs the execve() anyway.
+ */
+
+static struct {
+    int signum;
+    void (*handler)(int);
+} ghack_chain[] = {
+    {SIGBUS},
+    {SIGFPE},
+    {SIGSEGV},
+    {SIGILL}		/* Not currently handled by Gnome */
+};
+
+static void ghack_sig_handler(int signum)
+{
+    int i;
+    uid_t uid, euid;
+    gid_t gid, egid;
+    uid = getuid();
+    euid = geteuid();
+    gid = getgid();
+    egid = getegid();
+    if (gid != egid)
+	setgid(gid);
+    if (uid != euid)
+	setuid(uid);
+    for(i = SIZE(ghack_chain) - 1; i >= 0; i--)
+	if (ghack_chain[i].signum == signum) {
+	    ghack_chain[i].handler(signum);
+	    break;
+	}
+    if (i < 0)
+	impossible("Unhandled ghack signal");
+    if (uid != euid)
+	setuid(euid);
+    if (gid != egid)
+	setgid(egid);
+}
+
 /* initialize gnome and fir up the main window */
 void ghack_init_main_window( int argc, char** argv)
 {
+    int i;
     struct timeval tv;
     uid_t uid, euid;
 
@@ -672,7 +720,10 @@
     euid = geteuid();
     if (uid != euid)
       setuid(uid);
+    hide_privileges(TRUE);
+    /* XXX gnome_init must print nethack options for --help, but does not */
     gnome_init ("nethack", VERSION_STRING, argc, argv);
+    hide_privileges(FALSE);
     parse_args (argc, argv);
 
     /* Initialize the i18n stuff (not that gnomehack supperts it yet...) */
@@ -712,6 +763,9 @@
      * has already been shown */
     if (uid != euid)
       setuid(euid);
+    for(i = 0; i < SIZE(ghack_chain); i++)
+	ghack_chain[i].handler =
+	  signal(ghack_chain[i].signum, ghack_sig_handler);
 }
 
 void ghack_main_window_add_map_window(GtkWidget* win) 
@@ -769,4 +823,3 @@
 {
       return( GTK_WIDGET(mainWindow) );
 }
-
diff -Naurd ../nethack-3.3.1/win/gnome/gnmap.c ./win/gnome/gnmap.c
--- ../nethack-3.3.1/win/gnome/gnmap.c Sat Aug 5 11:53:34 2000
+++ ./win/gnome/gnmap.c Fri Mar 22 14:40:55 2002
@@ -180,12 +180,13 @@
 
   /* Tile the map background with a pretty image */ 
   background = gdk_imlib_load_image((char *) "mapbg.xpm");
-  gdk_imlib_render( background, background->rgb_width,
-	  background->rgb_height);
   if (background == NULL) {
       g_warning("Bummer! Failed to load the map background image (mapbg.xpm)!");
   }
   else {
+    gdk_imlib_render(background, background->rgb_width,
+	  background->rgb_height);
+
     /* Tile the map background */
     for (y = 0; y < height+background->rgb_height; y+=background->rgb_height)
     {
@@ -229,15 +230,16 @@
 
    /* Set up the pet mark image */
   petmark = gdk_imlib_create_image_from_xpm_data( pet_mark_xpm);
-  gdk_imlib_render( petmark, petmark->rgb_width,
-	  petmark->rgb_height);
   if (petmark == NULL) {
     g_warning("Bummer! Failed to load the pet_mark image!");
   }
   else {
+      gdk_imlib_render(petmark, petmark->rgb_width,
+	  petmark->rgb_height);
+
       /* ghack_map.overlay is an array of canvas images used to
        * overlay tile images...
-      */
+       */
       for (i=0, y = 0; y < height; y+=ghack_glyph_height())
 	{
 	  for (x = 0; x < width; x+=ghack_glyph_width())
diff -Naurd ../nethack-3.3.1/win/gnome/gnmap.h ./win/gnome/gnmap.h
--- ../nethack-3.3.1/win/gnome/gnmap.h Sat Aug 5 11:53:34 2000
+++ ./win/gnome/gnmap.h Fri Mar 22 14:40:55 2002
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)gnmap.h	3.3	2000/07/16	*/
+/*	SCCS Id: @(#)gnmap.h	3.4	2000/07/16	*/
 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
 /* NetHack may be freely redistributed.  See license for details. */
 
diff -Naurd ../nethack-3.3.1/win/gnome/gnplayer.c ./win/gnome/gnplayer.c
--- ../nethack-3.3.1/win/gnome/gnplayer.c Mon Jul 17 02:38:13 2000
+++ ./win/gnome/gnplayer.c Fri Mar 22 14:40:55 2002
@@ -1,11 +1,11 @@
-/*	SCCS Id: @(#)gnplayer.c	3.3	2000/07/16	*/
+/*	SCCS Id: @(#)gnplayer.c	3.4	2000/07/16	*/
 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
 /* NetHack may be freely redistributed.  See license for details. */
 
-#include "gnplayer.h"
-#include "gnmain.h"
 #include <gnome.h>
 #include <ctype.h>
+#include "gnplayer.h"
+#include "gnmain.h"
 #include "hack.h"
 
 static gint role_number;                                                      
@@ -13,15 +13,15 @@
                                                                               
 static void                                                                   
 player_sel_key_hit (GtkWidget *widget, GdkEventKey *event, gpointer data)     
-{                                                                             
-      const char** roles = data;                                              
-      int i;                                                                  
-      for (i = 0; roles[i] != 0; ++i) {                                       
-              if (roles[i][0] == toupper(event->keyval)) {                    
-                      role_number = i;                                        
-                      gtk_clist_select_row( GTK_CLIST (clist), i, 0);         
-              }                                                               
-      }                                                                       
+{
+    const char** roles = data;                                              
+    int i;                                                                  
+    for (i = 0; roles[i] != 0; ++i) {                                       
+	if (roles[i][0] == toupper(event->keyval)) {                    
+	    role_number = i;                                        
+	    gtk_clist_select_row( GTK_CLIST (clist), i, 0);         
+	}                                                               
+    }                                                                       
 }                                                                             
 
 static void
@@ -31,23 +31,25 @@
 }
 
 int
-ghack_player_sel_dialog( const char** roles)
+ghack_player_sel_dialog(const char** choices,
+			const gchar* title,
+			const gchar* prompt)
 {
     int i;
     static GtkWidget* dialog;
     static GtkWidget* swin;
     static GtkWidget* frame1;
 
-    dialog = gnome_dialog_new (_("Player selection"),
+    dialog = gnome_dialog_new(title,
 			    GNOME_STOCK_BUTTON_OK,
-			    _("Random role"),
+			    _("Random"),
 			    GNOME_STOCK_BUTTON_CANCEL,
 			    NULL);
     gnome_dialog_close_hides (GNOME_DIALOG (dialog), FALSE);
     gtk_signal_connect (GTK_OBJECT (dialog), "key_press_event",               
-                      GTK_SIGNAL_FUNC (player_sel_key_hit), roles );          
+                      GTK_SIGNAL_FUNC (player_sel_key_hit), choices );          
 
-    frame1 = gtk_frame_new (_("Choose one of the following roles:"));
+    frame1 = gtk_frame_new(prompt);
     gtk_object_set_data (GTK_OBJECT (dialog), "frame1", frame1);
     gtk_widget_show (frame1);
     gtk_container_border_width (GTK_CONTAINER (frame1), 3);
@@ -67,10 +69,10 @@
     gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG (dialog)->vbox), frame1);
  
     /* Add the roles into the list here... */
-    for (i=0; roles[i]; i++) {
+    for (i=0; choices[i]; i++) {
 	    gchar accelBuf[BUFSZ];
-	    const char *text[3]={accelBuf, roles[i],NULL};
-	    sprintf( accelBuf, "%c ", tolower(roles[i][0]));
+	    const char *text[3]={accelBuf, choices[i],NULL};
+	    sprintf( accelBuf, "%c ", tolower(choices[i][0]));
 	    gtk_clist_insert (GTK_CLIST (clist), i, (char**)text);
     }
  
@@ -89,11 +91,11 @@
 
     /* Quit on button 2 or error */
     if (i < 0  || i > 1) {
-	return( -1);
+	return(ROLE_NONE);
     }
     /* Random is button 1*/
     if (i == 1 ) {
-	return( -2);
+	return(ROLE_RANDOM);
     }
     return ( role_number);
 }
diff -Naurd ../nethack-3.3.1/win/gnome/gnplayer.h ./win/gnome/gnplayer.h
--- ../nethack-3.3.1/win/gnome/gnplayer.h Sat Aug 5 11:53:35 2000
+++ ./win/gnome/gnplayer.h Fri Mar 22 14:40:55 2002
@@ -1,13 +1,10 @@
-/*	SCCS Id: @(#)gnplayer.h	3.3	2000/07/16	*/
+/*	SCCS Id: @(#)gnplayer.h	3.4	2000/07/16	*/
 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef GnomeHackPlayerSelDialog_h
 #define GnomeHackPlayerSelDialog_h
 
-
-int ghack_player_sel_dialog(const char **);
-
+int ghack_player_sel_dialog(const char **, const gchar*, const gchar*);
 
 #endif /* GnomeHackPlayerSelDialog_h */
-
diff -Naurd ../nethack-3.3.1/win/gnome/gnsignal.c ./win/gnome/gnsignal.c
--- ../nethack-3.3.1/win/gnome/gnsignal.c Mon Jul 17 02:38:13 2000
+++ ./win/gnome/gnsignal.c Fri Mar 22 14:40:55 2002
@@ -248,193 +248,194 @@
 void 
 ghack_handle_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-  int key=0;
-  int ctl=GDK_CONTROL_MASK;
-  int alt=GDK_MOD1_MASK;
+    static int was_pound = 0;
+    int key = 0;
+    int ctl = GDK_CONTROL_MASK;
+    int alt = GDK_MOD1_MASK;
 
-/* Turn this on to debug key events */
+    /* Turn this on to debug key events */
 #if 0
-  g_message("I got a \"%s\" key (%d) %s%s", 
-	    gdk_keyval_name (event->keyval), event->keyval, 
-	    (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":"");
+    g_message("I got a \"%s\" key (%d) %s%s", 
+	      gdk_keyval_name (event->keyval), event->keyval, 
+	      (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":"");
 #endif
 
-  switch (event->keyval) {
-  /* special keys to do stuff with */
+    switch (event->keyval) {
+	/* special keys to do stuff with */
 
-  /* Set up the direction keys */
+	/* Set up the direction keys */
 
-  /* First handle the arrow keys -- these always mean move */
-  case GDK_Right:
-  case GDK_rightarrow:
-      if (iflags.num_pad) key='6'; else  key='l'; break;
-  case GDK_Left:
-  case GDK_leftarrow:
-      if (iflags.num_pad) key='4'; else  key='h'; break;
-  case GDK_Up:
-  case GDK_uparrow:
-      if (iflags.num_pad) key='8'; else  key='k'; break;
-  case GDK_Down:
-  case GDK_downarrow:
-      if (iflags.num_pad) key='2'; else  key='j'; break;
-  case GDK_Home:
-      if (iflags.num_pad) key='7'; else  key='y'; break;
-  case GDK_End:
-      if (iflags.num_pad) key='1'; else  key='b'; break;
-  case GDK_Page_Down:
-      if (iflags.num_pad) key='3'; else  key='n'; break;
-  case GDK_Page_Up:
-      if (iflags.num_pad) key='9'; else  key='u'; break;
-  case ' ':		 key='.'; break;
+	/* First handle the arrow keys -- these always mean move */
+    case GDK_Right:
+    case GDK_rightarrow:
+	if (iflags.num_pad) key='6'; else  key='l'; break;
+    case GDK_Left:
+    case GDK_leftarrow:
+	if (iflags.num_pad) key='4'; else  key='h'; break;
+    case GDK_Up:
+    case GDK_uparrow:
+	if (iflags.num_pad) key='8'; else  key='k'; break;
+    case GDK_Down:
+    case GDK_downarrow:
+	if (iflags.num_pad) key='2'; else  key='j'; break;
+    case GDK_Home:
+	if (iflags.num_pad) key='7'; else  key='y'; break;
+    case GDK_End:
+	if (iflags.num_pad) key='1'; else  key='b'; break;
+    case GDK_Page_Down:
+	if (iflags.num_pad) key='3'; else  key='n'; break;
+    case GDK_Page_Up:
+	if (iflags.num_pad) key='9'; else  key='u'; break;
+    case ' ':		 key='.'; break;
 
-  /* Now, handle the numberpad (move or numbers) */
-  case GDK_KP_Right:
-  case GDK_KP_6:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_6;
-      else
-	  key='6'; 
-      break;
+	/* Now, handle the numberpad (move or numbers) */
+    case GDK_KP_Right:
+    case GDK_KP_6:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_6;
+	else
+	    key='6'; 
+	break;
 
-  case GDK_KP_Left:
-  case GDK_KP_4:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_4;
-      else
-	  key='4'; 
-      break;
+    case GDK_KP_Left:
+    case GDK_KP_4:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_4;
+	else
+	    key='4'; 
+	break;
 
-  case GDK_KP_Up:
-  case GDK_KP_8:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_8;
-      else
-	  key='8'; 
-      break;
+    case GDK_KP_Up:
+    case GDK_KP_8:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_8;
+	else
+	    key='8'; 
+	break;
 
-  case GDK_KP_Down:
-  case GDK_KP_2:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_2;
-      else
-	  key='2'; 
-      break;
+    case GDK_KP_Down:
+    case GDK_KP_2:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_2;
+	else
+	    key='2'; 
+	break;
 
-  /* Move Top-Left */
-  case GDK_KP_Home:
-  case GDK_KP_7:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_7;
-      else
-	  key='7'; 
-      break;
+	/* Move Top-Left */
+    case GDK_KP_Home:
+    case GDK_KP_7:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_7;
+	else
+	    key='7'; 
+	break;
 
-  case GDK_KP_Page_Up:
-  case GDK_KP_9:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_9;
-      else
-	  key='9'; 
-      break;
+    case GDK_KP_Page_Up:
+    case GDK_KP_9:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_9;
+	else
+	    key='9'; 
+	break;
 
-  case GDK_KP_End:
-  case GDK_KP_1:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_1;
-      else
-	  key='1'; 
-      break;
+    case GDK_KP_End:
+    case GDK_KP_1:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_1;
+	else
+	    key='1'; 
+	break;
 
-  case GDK_KP_Page_Down:
-  case GDK_KP_3:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_3;
-      else
-	  key='3'; 
-      break;
+    case GDK_KP_Page_Down:
+    case GDK_KP_3:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_3;
+	else
+	    key='3'; 
+	break;
   
   
-  case GDK_KP_5:
-      if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
-	  key = GDK_KP_5;
-      else
-	  key='5'; 
-      break;
+    case GDK_KP_5:
+	if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad)
+	    key = GDK_KP_5;
+	else
+	    key='5'; 
+	break;
 
-  case GDK_KP_Delete:
-  case GDK_KP_Decimal:
-	  key='.'; 
-      break;
+    case GDK_KP_Delete:
+    case GDK_KP_Decimal:
+	key='.'; 
+	break;
 
-  /* We don't bother using the "#" key for extended commands.  Instead, 
-   * we will just use the ALT key.*/
-  case GDK_numbersign:
-      break;
+	/* can't just ignore "#", it's a core feature */
+    case GDK_numbersign:
+	was_pound = 1;
+	return;
 
-  /* We will probably want to do something with these later... */
-  case GDK_KP_Begin:
-  case GDK_KP_F1:
-  case GDK_F1:
-  case GDK_KP_F2:
-  case GDK_F2:
-  case GDK_KP_F3:
-  case GDK_F3:
-  case GDK_KP_F4:
-  case GDK_F4:
-  case GDK_F5:
-  case GDK_F6:
-  case GDK_F7:
-  case GDK_F8:
-  case GDK_F9:
-  case GDK_F10:
-  case GDK_F11:
-  case GDK_F12:
-    break;
-  /* various keys to ignore */
-  case GDK_KP_Insert:
-  case GDK_Insert:
-  case GDK_Delete:
-  case GDK_Print:
-  case GDK_BackSpace:
-  case GDK_Pause:
-  case GDK_Scroll_Lock:
-  case GDK_Shift_Lock:
-  case GDK_Num_Lock:
-  case GDK_Caps_Lock:
-  case GDK_Control_L:
-  case GDK_Control_R:
-  case GDK_Shift_L:
-  case GDK_Shift_R:
-  case GDK_Alt_L:
-  case GDK_Alt_R:
-  case GDK_Meta_L:
-  case GDK_Meta_R:
-  case GDK_Mode_switch:
-  case GDK_Multi_key:
-    return;
+	/* We will probably want to do something with these later... */
+    case GDK_KP_Begin:
+    case GDK_KP_F1:
+    case GDK_F1:
+    case GDK_KP_F2:
+    case GDK_F2:
+    case GDK_KP_F3:
+    case GDK_F3:
+    case GDK_KP_F4:
+    case GDK_F4:
+    case GDK_F5:
+    case GDK_F6:
+    case GDK_F7:
+    case GDK_F8:
+    case GDK_F9:
+    case GDK_F10:
+    case GDK_F11:
+    case GDK_F12:
+	break;
+	/* various keys to ignore */
+    case GDK_KP_Insert:
+    case GDK_Insert:
+    case GDK_Delete:
+    case GDK_Print:
+    case GDK_BackSpace:
+    case GDK_Pause:
+    case GDK_Scroll_Lock:
+    case GDK_Shift_Lock:
+    case GDK_Num_Lock:
+    case GDK_Caps_Lock:
+    case GDK_Control_L:
+    case GDK_Control_R:
+    case GDK_Shift_L:
+    case GDK_Shift_R:
+    case GDK_Alt_L:
+    case GDK_Alt_R:
+    case GDK_Meta_L:
+    case GDK_Meta_R:
+    case GDK_Mode_switch:
+    case GDK_Multi_key:
+	return;
 
-  default:
-    key = event->keyval;
-  }
+    default:
+	key = event->keyval;
+    }
 
-  if (event->state & alt) {
+    if ((event->state & alt) || was_pound) {
 	key=M(event->keyval);
-  }
-  else if (event->state & ctl) {
+    } else if (event->state & ctl) {
 	key=C(event->keyval);
-  }
+    }
+    if (was_pound) {
+	was_pound = 0;
+    }
  
-  /* Ok, here is where we do clever stuff to overide the default
-   * game behavior */
-  if (g_askingQuestion==0) {
+    /* Ok, here is where we do clever stuff to overide the default
+     * game behavior */
+    if (g_askingQuestion == 0) {
 
-      if (key == 'S' || key == M('S') || key == C('S')) {
-	  ghack_save_game_cb( NULL, NULL);
-	  return;
-      }
-  }
+	if (key == 'S' || key == M('S') || key == C('S')) {
+	    ghack_save_game_cb( NULL, NULL);
+	    return;
+	}
+    }
     g_keyBuffer = g_list_prepend (g_keyBuffer, GINT_TO_POINTER( key));
     g_numKeys++;
 }
-
-
diff -Naurd ../nethack-3.3.1/win/gnome/gntext.c ./win/gnome/gntext.c
--- ../nethack-3.3.1/win/gnome/gntext.c Thu Aug 3 21:03:34 2000
+++ ./win/gnome/gntext.c Fri Mar 22 14:40:55 2002
@@ -40,6 +40,7 @@
 
 void ghack_text_window_destroy()
 {
+    TW_window = NULL;
 }
 
 void ghack_text_window_display(GtkWidget *widget, boolean block,
@@ -50,6 +51,8 @@
 	gtk_window_set_title(GTK_WINDOW( TW_window), "Rest In Peace");
     }
    
+    gtk_signal_connect (GTK_OBJECT (TW_window), "destroy",
+	(GtkSignalFunc) ghack_text_window_destroy, NULL);
     if (block)
 	gnome_dialog_run(GNOME_DIALOG(TW_window));
     else

