NetBSD Problem Report #52974

From www@NetBSD.org  Fri Feb  2 11:34:09 2018
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 675EC7A1CC
	for <gnats-bugs@gnats.NetBSD.org>; Fri,  2 Feb 2018 11:34:09 +0000 (UTC)
Message-Id: <20180202113408.584E27A224@mollari.NetBSD.org>
Date: Fri,  2 Feb 2018 11:34:08 +0000 (UTC)
From: lists@eitanadler.com
Reply-To: lists@eitanadler.com
To: gnats-bugs@NetBSD.org
Subject: [hangman] fix several bugs with word selection
X-Send-Pr-Version: www-1.0

>Number:         52974
>Category:       bin
>Synopsis:       [hangman] fix several bugs with word selection
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 02 11:35:00 +0000 2018
>Last-Modified:  Wed Feb 20 05:24:16 +0000 2019
>Originator:     Eitan Adler
>Release:        HEAD
>Organization:
>Environment:
>Description:
There are several bugs in the current word selection for hangman:
- the first word will never be selected (as there are two fgets to find a complete word)
- if a minimum length that is longer than all words in the dictionary is selected hangman will... hang
- word selection is not uniformly random since longer words are less likely to be picked (and words after longer words are more likely to be picked)
>How-To-Repeat:

>Fix:
be aware: its 3:30am when I wrote this. There is a good chance I messed up:

Index: extern.c
===================================================================
RCS file: /cvsroot/src/games/hangman/extern.c,v
retrieving revision 1.8
diff -u -r1.8 extern.c
--- extern.c	7 Aug 2003 09:37:20 -0000	1.8
+++ extern.c	2 Feb 2018 11:33:41 -0000
@@ -42,7 +42,8 @@

 bool    Guessed[26];

-char    Word[BUFSIZ], Known[BUFSIZ];
+char    *Word;
+char	Known[BUFSIZ];
 const char *const Noose_pict[] = {
 	"     ______",
 	"     |    |",
@@ -75,4 +76,6 @@

 FILE   *Dict = NULL;

-off_t   Dict_size;
+char **Dict_array;
+
+int Dict_count;
Index: getword.c
===================================================================
RCS file: /cvsroot/src/games/hangman/getword.c,v
retrieving revision 1.10
diff -u -r1.10 getword.c
--- getword.c	19 Jun 2012 05:45:00 -0000	1.10
+++ getword.c	2 Feb 2018 11:33:41 -0000
@@ -47,27 +47,11 @@
 void
 getword(void)
 {
-	FILE *inf;
 	char *wp, *gp;
 	long pos;

-	inf = Dict;
-	for (;;) {
-		pos = (double) rand() / (RAND_MAX + 1.0) * (double) Dict_size;
-		fseek(inf, pos, SEEK_SET);
-		if (fgets(Word, BUFSIZ, inf) == NULL)
-			continue;
-		if (fgets(Word, BUFSIZ, inf) == NULL)
-			continue;
-		Word[strlen(Word) - 1] = '\0';
-		if (strlen(Word) < Minlen)
-			continue;
-		for (wp = Word; *wp; wp++)
-			if (!islower((unsigned char)*wp))
-				goto cont;
-		break;
-cont:		;
-	}
+	pos = (double) rand() / (RAND_MAX + 1.0) * (double) Dict_count;
+	Word = Dict_array[pos];
 	gp = Known;
 	wp = Word;
 	while (*wp) {
Index: hangman.h
===================================================================
RCS file: /cvsroot/src/games/hangman/hangman.h,v
retrieving revision 1.14
diff -u -r1.14 hangman.h
--- hangman.h	26 Aug 2011 06:18:17 -0000	1.14
+++ hangman.h	2 Feb 2018 11:33:41 -0000
@@ -65,7 +65,8 @@

 extern bool Guessed[];

-extern char Word[], Known[];
+extern char *Word;
+extern char Known[];
 extern const char *const Noose_pict[];

 extern int Errors, Wordnum;
@@ -79,7 +80,9 @@

 extern FILE *Dict;

-extern off_t Dict_size;
+extern char **Dict_array;
+
+extern int Dict_count;

 void    die(int) __dead;
 void    endgame(void);
Index: setup.c
===================================================================
RCS file: /cvsroot/src/games/hangman/setup.c,v
retrieving revision 1.11
diff -u -r1.11 setup.c
--- setup.c	19 Jun 2012 05:45:00 -0000	1.11
+++ setup.c	2 Feb 2018 11:33:41 -0000
@@ -50,6 +50,8 @@
 setup(void)
 {
 	const char *const *sp;
+	char line[BUFSIZ];
+	int nlines;
 	static struct stat sbuf;

 	noecho();
@@ -73,5 +75,16 @@
 		err(1, "fopen %s", Dict_name);
 	}
 	fstat(fileno(Dict), &sbuf);
-	Dict_size = sbuf.st_size;
+	Dict_array = malloc(sizeof (char*) * (sbuf.st_size/2));
+	Dict_count = 0;
+
+	while(fgets(line, BUFSIZ, Dict) != NULL) {
+		if (strlen(line) >= Minlen) {
+			Dict_array[Dict_count] = strdup(line);
+			Dict_count++;
+		}
+	}
+	if (Dict_count == 0) {
+		errx(1, "no words with minimum length");
+	}
 }

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: bin-bug-people->eadler
Responsible-Changed-By: eadler@NetBSD.org
Responsible-Changed-When: Sun, 04 Mar 2018 21:43:56 +0000
Responsible-Changed-Why:


Responsible-Changed-From-To: eadler->bin-bug-people
Responsible-Changed-By: eadler@NetBSD.org
Responsible-Changed-When: Wed, 20 Feb 2019 05:24:16 +0000
Responsible-Changed-Why:
I don't time right now


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.