xref: /openbsd/games/adventure/vocab.c (revision 5af055cd)
1 /*	$OpenBSD: vocab.c,v 1.15 2016/03/08 10:48:39 mestre Exp $	*/
2 /*	$NetBSD: vocab.c,v 1.2 1995/03/21 12:05:13 cgd Exp $	*/
3 
4 /*-
5  * Copyright (c) 1991, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * The game adventure was originally written in Fortran by Will Crowther
9  * and Don Woods.  It was later translated to C and enhanced by Jim
10  * Gillogly.  This code is derived from software contributed to Berkeley
11  * by Jim Gillogly at The Rand Corporation.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 /*	Re-coding of advent in C: data structure routines		*/
39 
40 #include <err.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 
44 #include "extern.h"
45 #include "hdr.h"
46 
47 void
48 dstroy(int object)
49 {
50 	move(object, 0);
51 }
52 
53 void
54 juggle(int object)
55 {
56 	int	i, j;
57 
58 	i = place[object];
59 	j = fixed[object];
60 	move(object, i);
61 	move(object + 100, j);
62 }
63 
64 
65 void
66 move(int object, int where)
67 {
68 	int	from;
69 
70 	if (object <= 100)
71 		from = place[object];
72 	else
73 		from = fixed[object - 100];
74 	if (from > 0 && from <= 300)
75 		carry(object, from);
76 	drop(object, where);
77 }
78 
79 
80 int
81 put(int object, int where, int pval)
82 {
83 	move(object, where);
84 	return (-1 - pval);
85 }
86 
87 
88 void
89 carry(int object, int where)
90 {
91 	int	temp;
92 
93 	if (object <= 100) {
94 		if (place[object] == -1)
95 			return;
96 		place[object] = -1;
97 		holdng++;
98 	}
99 	if (atloc[where] == object) {
100 		atloc[where] = linkx[object];
101 		return;
102 	}
103 	for (temp = atloc[where]; linkx[temp] != object; temp = linkx[temp])
104 		;
105 	linkx[temp] = linkx[object];
106 }
107 
108 
109 void
110 drop(int object, int where)
111 {
112 	if (object > 100)
113 		fixed[object - 100] = where;
114 	else {
115 		if (place[object] == -1)
116 			holdng--;
117 		place[object] = where;
118 	}
119 	if (where <= 0)
120 		return;
121 	linkx[object] = atloc[where];
122 	atloc[where] = object;
123 }
124 
125 /*
126  * Look up or store a word
127  * type: -2 for store, -1 for user word, >=0 for canned lookup
128  * value: used for storing only
129  */
130 int
131 vocab(const char *word, int type, int value)
132 {
133 	int	adr;
134 	const char *s;
135 	char	*t;
136 	int	hash, i;
137 	struct hashtab *h;
138 
139 	for (hash = 0, s = word, i = 0; i < 5 && *s; i++)  /* some kind of hash */
140 		hash += *s++;		/* add all chars in the word	*/
141 	hash = (hash * 3719) & 077777;	/* pulled that one out of a hat */
142 	hash %= HTSIZE;			/* put it into range of table	*/
143 
144 	for (adr = hash; ; adr++) {	/* look for entry in table	*/
145 		if (adr == HTSIZE)
146 			adr = 0; /* wrap around			*/
147 		h = &voc[adr];		/* point at the entry		*/
148 		switch (type) {
149 		case -2:		/* fill in entry		*/
150 			if (h->val)	/* already got an entry?	*/
151 				goto exitloop2;
152 			h->val = value;
153 			if ((h->atab = malloc(length(word))) == NULL)
154 				err(1, NULL);
155 			for (s = word, t = h->atab; *s;)
156 				*t++ = *s++ ^ '=';
157 			*t = 0 ^ '=';
158 			/* obfuscate slightly to frustrate core reader	*/
159 		/*	printf("Stored \"%s\" (%d ch) as entry %d\n",	*/
160 		/*		word, length(word), adr);		*/
161 			return (0);	/* entry unused			*/
162 		case -1:		/* looking up user word		*/
163 			if (h->val == 0)
164 				return (-1);	/* not found	*/
165 			for (s = word, t = h->atab; *t ^ '=';)
166 				if ((*s++ ^ '=') != *t++)
167 					goto exitloop2;
168 			if ((*s ^ '=') != *t && s - word < 5)
169 				goto exitloop2;
170 			/* the word matched o.k.			*/
171 			return (h->val);
172 		default:		/* looking up known word	*/
173 			if (h->val == 0)
174 				errx(1, "Unable to find %s in vocab", word);
175 			for (s = word, t = h->atab; *t ^ '=';)
176 				if ((*s++ ^ '=') != *t++)
177 					goto exitloop2;
178 			/* the word matched o.k.			*/
179 			if (h->val / 1000 != type)
180 				continue;
181 			return (h->val%1000);
182 		}
183 
184 exitloop2:			/* hashed entry does not match	*/
185 		if (adr + 1 == hash || hash == 0)
186 			errx(1, "Hash table overflow");
187 	}
188 }
189 
190 void
191 prht(void)				/* print hash table		*/
192 {
193 	int	i, j, l;
194 	char	*c;
195 	struct hashtab *h;
196 
197 	for (i = 0; i < HTSIZE / 10 + 1; i++) {
198 		printf("%4d", i * 10);
199 		for (j = 0; j < 10; j++) {
200 			if (i * 10 + j >= HTSIZE)
201 				break;
202 			h = &voc[i * 10 + j];
203 			putchar(' ');
204 			if (h->val == 0) {
205 				printf("-----");
206 				continue;
207 			}
208 			for (l = 0, c = h->atab; l < 5; l++)
209 				if ((*c ^ '='))
210 					putchar(*c++ ^ '=');
211 				else
212 					putchar(' ');
213 		}
214 		putchar('\n');
215 	}
216 }
217