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