1 /* $NetBSD: hack.options.c,v 1.9 2009/06/07 20:13:18 dholland 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 <sys/cdefs.h> 65 #ifndef lint 66 __RCSID("$NetBSD: hack.options.c,v 1.9 2009/06/07 20:13:18 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include <unistd.h> 71 #include "hack.h" 72 #include "extern.h" 73 74 void 75 initoptions(void) 76 { 77 char *opts; 78 79 flags.time = flags.nonews = flags.notombstone = flags.end_own = 80 flags.standout = flags.nonull = FALSE; 81 flags.no_rest_on_space = TRUE; 82 flags.invlet_constant = TRUE; 83 flags.end_top = 5; 84 flags.end_around = 4; 85 flags.female = FALSE; /* players are usually male */ 86 87 if ((opts = getenv("HACKOPTIONS")) != NULL) 88 parseoptions(opts, TRUE); 89 } 90 91 void 92 parseoptions(char *opts, boolean from_env) 93 { 94 char *op, *op2; 95 unsigned num; 96 boolean negated; 97 98 if ((op = strchr(opts, ',')) != NULL) { 99 *op++ = 0; 100 parseoptions(op, from_env); 101 } 102 if ((op = strchr(opts, ' ')) != NULL) { 103 op2 = op; 104 while (*op++) 105 if (*op != ' ') 106 *op2++ = *op; 107 } 108 if (!*opts) 109 return; 110 negated = FALSE; 111 while ((*opts == '!') || !strncmp(opts, "no", 2)) { 112 if (*opts == '!') 113 opts++; 114 else 115 opts += 2; 116 negated = !negated; 117 } 118 119 if (!strncmp(opts, "standout", 8)) { 120 flags.standout = !negated; 121 return; 122 } 123 if (!strncmp(opts, "null", 3)) { 124 flags.nonull = negated; 125 return; 126 } 127 if (!strncmp(opts, "tombstone", 4)) { 128 flags.notombstone = negated; 129 return; 130 } 131 if (!strncmp(opts, "news", 4)) { 132 flags.nonews = negated; 133 return; 134 } 135 if (!strncmp(opts, "time", 4)) { 136 flags.time = !negated; 137 flags.botl = 1; 138 return; 139 } 140 if (!strncmp(opts, "restonspace", 4)) { 141 flags.no_rest_on_space = negated; 142 return; 143 } 144 if (!strncmp(opts, "fixinv", 4)) { 145 if (from_env) 146 flags.invlet_constant = !negated; 147 else 148 pline("The fixinvlet option must be in HACKOPTIONS."); 149 return; 150 } 151 if (!strncmp(opts, "male", 4)) { 152 flags.female = negated; 153 return; 154 } 155 if (!strncmp(opts, "female", 6)) { 156 flags.female = !negated; 157 return; 158 } 159 /* name:string */ 160 if (!strncmp(opts, "name", 4)) { 161 if (!from_env) { 162 pline("The playername can be set only from HACKOPTIONS."); 163 return; 164 } 165 op = strchr(opts, ':'); 166 if (!op) 167 goto bad; 168 (void) strncpy(plname, op + 1, sizeof(plname) - 1); 169 return; 170 } 171 /* endgame:5t[op] 5a[round] o[wn] */ 172 if (!strncmp(opts, "endgame", 3)) { 173 op = strchr(opts, ':'); 174 if (!op) 175 goto bad; 176 op++; 177 while (*op) { 178 num = 1; 179 if (digit(*op)) { 180 num = atoi(op); 181 while (digit(*op)) 182 op++; 183 } else if (*op == '!') { 184 negated = !negated; 185 op++; 186 } 187 switch (*op) { 188 case 't': 189 flags.end_top = num; 190 break; 191 case 'a': 192 flags.end_around = num; 193 break; 194 case 'o': 195 flags.end_own = !negated; 196 break; 197 default: 198 goto bad; 199 } 200 while (letter(*++op)); 201 if (*op == '/') 202 op++; 203 } 204 return; 205 } 206 bad: 207 if (!from_env) { 208 if (!strncmp(opts, "help", 4)) { 209 pline("%s%s%s", 210 "To set options use `HACKOPTIONS=\"<options>\"' in your environment, or ", 211 "give the command 'O' followed by the line `<options>' while playing. ", 212 "Here <options> is a list of <option>s separated by commas."); 213 pline("%s%s%s", 214 "Simple (boolean) options are rest_on_space, news, time, ", 215 "null, tombstone, (fe)male. ", 216 "These can be negated by prefixing them with '!' or \"no\"."); 217 pline("%s", 218 "A string option is name, as in HACKOPTIONS=\"name:Merlin-W\"."); 219 pline("%s%s%s", 220 "A compound option is endgame; it is followed by a description of what ", 221 "parts of the scorelist you want to see. You might for example say: ", 222 "`endgame:own scores/5 top scores/4 around my score'."); 223 return; 224 } 225 pline("Bad option: %s.", opts); 226 pline("Type `O help<cr>' for help."); 227 return; 228 } 229 puts("Bad syntax in HACKOPTIONS."); 230 puts("Use for example:"); 231 puts( 232 "HACKOPTIONS=\"!restonspace,notombstone,endgame:own/5 topscorers/4 around me\"" 233 ); 234 getret(); 235 } 236 237 int 238 doset(void) 239 { 240 char buf[BUFSZ]; 241 size_t pos; 242 243 pline("What options do you want to set? "); 244 getlin(buf); 245 if (!buf[0] || buf[0] == '\033') { 246 (void) strcpy(buf, "HACKOPTIONS="); 247 (void) strcat(buf, flags.female ? "female," : "male,"); 248 if (flags.standout) 249 (void) strlcat(buf, "standout,", sizeof(buf)); 250 if (flags.nonull) 251 (void) strlcat(buf, "nonull,", sizeof(buf)); 252 if (flags.nonews) 253 (void) strlcat(buf, "nonews,", sizeof(buf)); 254 if (flags.time) 255 (void) strlcat(buf, "time,", sizeof(buf)); 256 if (flags.notombstone) 257 (void) strlcat(buf, "notombstone,", sizeof(buf)); 258 if (flags.no_rest_on_space) 259 (void) strlcat(buf, "!rest_on_space,", sizeof(buf)); 260 if (flags.end_top != 5 || flags.end_around != 4 || flags.end_own) { 261 pos = strlen(buf); 262 (void) snprintf(buf+pos, sizeof(buf)-pos, 263 "endgame: %u topscores/%u around me", 264 flags.end_top, flags.end_around); 265 if (flags.end_own) 266 (void) strlcat(buf, "/own scores", sizeof(buf)); 267 } else { 268 char *eop = eos(buf); 269 if (*--eop == ',') 270 *eop = 0; 271 } 272 pline(buf); 273 } else 274 parseoptions(buf, FALSE); 275 276 return (0); 277 } 278