xref: /dragonfly/games/hack/hack.options.c (revision 029e6489)
1 /*	$NetBSD: hack.options.c,v 1.11 2011/05/23 22:53:25 joerg Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdlib.h>
65 #include <unistd.h>
66 #include "hack.h"
67 #include "extern.h"
68 
69 static void parseoptions(char *, boolean);
70 
71 void
72 initoptions(void)
73 {
74 	char           *opts;
75 
76 	flags.time = flags.nonews = flags.notombstone = flags.end_own =
77 		flags.standout = flags.nonull = FALSE;
78 	flags.no_rest_on_space = TRUE;
79 	flags.invlet_constant = TRUE;
80 	flags.end_top = 5;
81 	flags.end_around = 4;
82 	flags.female = FALSE;	/* players are usually male */
83 
84 	if ((opts = getenv("HACKOPTIONS")) != NULL)
85 		parseoptions(opts, TRUE);
86 }
87 
88 static void
89 parseoptions(char *opts, boolean from_env)
90 {
91 	char           *op, *op2;
92 	unsigned        num;
93 	boolean         negated;
94 
95 	if ((op = strchr(opts, ',')) != NULL) {
96 		*op++ = 0;
97 		parseoptions(op, from_env);
98 	}
99 	if ((op = strchr(opts, ' ')) != NULL) {
100 		op2 = op;
101 		while (*op++)
102 			if (*op != ' ')
103 				*op2++ = *op;
104 	}
105 	if (!*opts)
106 		return;
107 	negated = FALSE;
108 	while ((*opts == '!') || !strncmp(opts, "no", 2)) {
109 		if (*opts == '!')
110 			opts++;
111 		else
112 			opts += 2;
113 		negated = !negated;
114 	}
115 
116 	if (!strncmp(opts, "standout", 8)) {
117 		flags.standout = !negated;
118 		return;
119 	}
120 	if (!strncmp(opts, "null", 3)) {
121 		flags.nonull = negated;
122 		return;
123 	}
124 	if (!strncmp(opts, "tombstone", 4)) {
125 		flags.notombstone = negated;
126 		return;
127 	}
128 	if (!strncmp(opts, "news", 4)) {
129 		flags.nonews = negated;
130 		return;
131 	}
132 	if (!strncmp(opts, "time", 4)) {
133 		flags.time = !negated;
134 		flags.botl = 1;
135 		return;
136 	}
137 	if (!strncmp(opts, "restonspace", 4)) {
138 		flags.no_rest_on_space = negated;
139 		return;
140 	}
141 	if (!strncmp(opts, "fixinv", 4)) {
142 		if (from_env)
143 			flags.invlet_constant = !negated;
144 		else
145 			pline("The fixinvlet option must be in HACKOPTIONS.");
146 		return;
147 	}
148 	if (!strncmp(opts, "male", 4)) {
149 		flags.female = negated;
150 		return;
151 	}
152 	if (!strncmp(opts, "female", 6)) {
153 		flags.female = !negated;
154 		return;
155 	}
156 	/* name:string */
157 	if (!strncmp(opts, "name", 4)) {
158 		if (!from_env) {
159 			pline("The playername can be set only from HACKOPTIONS.");
160 			return;
161 		}
162 		op = strchr(opts, ':');
163 		if (!op)
164 			goto bad;
165 		(void) strncpy(plname, op + 1, sizeof(plname) - 1);
166 		return;
167 	}
168 	/* endgame:5t[op] 5a[round] o[wn] */
169 	if (!strncmp(opts, "endgame", 3)) {
170 		op = strchr(opts, ':');
171 		if (!op)
172 			goto bad;
173 		op++;
174 		while (*op) {
175 			num = 1;
176 			if (digit(*op)) {
177 				num = atoi(op);
178 				while (digit(*op))
179 					op++;
180 			} else if (*op == '!') {
181 				negated = !negated;
182 				op++;
183 			}
184 			switch (*op) {
185 			case 't':
186 				flags.end_top = num;
187 				break;
188 			case 'a':
189 				flags.end_around = num;
190 				break;
191 			case 'o':
192 				flags.end_own = !negated;
193 				break;
194 			default:
195 				goto bad;
196 			}
197 			while (letter(*++op));
198 			if (*op == '/')
199 				op++;
200 		}
201 		return;
202 	}
203 bad:
204 	if (!from_env) {
205 		if (!strncmp(opts, "help", 4)) {
206 			pline("%s%s%s",
207 			      "To set options use `HACKOPTIONS=\"<options>\"' in your environment, or ",
208 			      "give the command 'O' followed by the line `<options>' while playing. ",
209 			      "Here <options> is a list of <option>s separated by commas.");
210 			pline("%s%s%s",
211 			      "Simple (boolean) options are rest_on_space, news, time, ",
212 			      "null, tombstone, (fe)male. ",
213 			      "These can be negated by prefixing them with '!' or \"no\".");
214 			pline("%s",
215 			      "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\".");
216 			pline("%s%s%s",
217 			      "A compound option is endgame; it is followed by a description of what ",
218 			      "parts of the scorelist you want to see. You might for example say: ",
219 			      "`endgame:own scores/5 top scores/4 around my score'.");
220 			return;
221 		}
222 		pline("Bad option: %s.", opts);
223 		pline("Type `O help<cr>' for help.");
224 		return;
225 	}
226 	puts("Bad syntax in HACKOPTIONS.");
227 	puts("Use for example:");
228 	puts(
229 	     "HACKOPTIONS=\"!restonspace,notombstone,endgame:own/5 topscorers/4 around me\""
230 		);
231 	getret();
232 }
233 
234 int
235 doset(void)
236 {
237 	char buf[BUFSZ];
238 	size_t pos;
239 
240 	pline("What options do you want to set? ");
241 	getlin(buf);
242 	if (!buf[0] || buf[0] == '\033') {
243 		(void) strcpy(buf, "HACKOPTIONS=");
244 		(void) strcat(buf, flags.female ? "female," : "male,");
245 		if (flags.standout)
246 			(void) strlcat(buf, "standout,", sizeof(buf));
247 		if (flags.nonull)
248 			(void) strlcat(buf, "nonull,", sizeof(buf));
249 		if (flags.nonews)
250 			(void) strlcat(buf, "nonews,", sizeof(buf));
251 		if (flags.time)
252 			(void) strlcat(buf, "time,", sizeof(buf));
253 		if (flags.notombstone)
254 			(void) strlcat(buf, "notombstone,", sizeof(buf));
255 		if (flags.no_rest_on_space)
256 			(void) strlcat(buf, "!rest_on_space,", sizeof(buf));
257 		if (flags.end_top != 5 || flags.end_around != 4 || flags.end_own) {
258 			pos = strlen(buf);
259 			(void) snprintf(buf+pos, sizeof(buf)-pos,
260 				       "endgame: %u topscores/%u around me",
261 				       flags.end_top, flags.end_around);
262 			if (flags.end_own)
263 				(void) strlcat(buf, "/own scores", sizeof(buf));
264 		} else {
265 			char           *eop = eos(buf);
266 			if (*--eop == ',')
267 				*eop = 0;
268 		}
269 		pline("%s", buf);
270 	} else
271 		parseoptions(buf, FALSE);
272 
273 	return (0);
274 }
275