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