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