1 /* $NetBSD: hack.do_name.c,v 1.11 2009/08/12 07:28:40 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.do_name.c,v 1.11 2009/08/12 07:28:40 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include "hack.h" 71 #include "extern.h" 72 73 static void do_oname(struct obj *); 74 static char *xmonnam(struct monst *, int); 75 static char *lmonnam(struct monst *); 76 static char *visctrl(int); 77 78 coord 79 getpos(int force, const char *goal) 80 { 81 int cx, cy, i, c; 82 coord cc; 83 pline("(For instructions type a ?)"); 84 cx = u.ux; 85 cy = u.uy; 86 curs(cx, cy + 2); 87 while ((c = readchar()) != '.') { 88 for (i = 0; i < 8; i++) 89 if (sdir[i] == c) { 90 if (1 <= cx + xdir[i] && cx + xdir[i] <= COLNO) 91 cx += xdir[i]; 92 if (0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO - 1) 93 cy += ydir[i]; 94 goto nxtc; 95 } 96 if (c == '?') { 97 pline("Use [hjkl] to move the cursor to %s.", goal); 98 pline("Type a . when you are at the right place."); 99 } else { 100 pline("Unknown direction: '%s' (%s).", 101 visctrl(c), 102 force ? "use hjkl or ." : "aborted"); 103 if (force) 104 goto nxtc; 105 cc.x = -1; 106 cc.y = 0; 107 return (cc); 108 } 109 nxtc: ; 110 curs(cx, cy + 2); 111 } 112 cc.x = cx; 113 cc.y = cy; 114 return (cc); 115 } 116 117 int 118 do_mname(void) 119 { 120 char buf[BUFSZ]; 121 coord cc; 122 int cx, cy, lth; 123 unsigned i; 124 struct monst *mtmp, *mtmp2; 125 cc = getpos(0, "the monster you want to name"); 126 cx = cc.x; 127 cy = cc.y; 128 if (cx < 0) 129 return (0); 130 mtmp = m_at(cx, cy); 131 if (!mtmp) { 132 if (cx == u.ux && cy == u.uy) 133 pline("This ugly monster is called %s and cannot be renamed.", 134 plname); 135 else 136 pline("There is no monster there."); 137 return (1); 138 } 139 if (mtmp->mimic) { 140 pline("I see no monster there."); 141 return (1); 142 } 143 if (!cansee(cx, cy)) { 144 pline("I cannot see a monster there."); 145 return (1); 146 } 147 pline("What do you want to call %s? ", lmonnam(mtmp)); 148 getlin(buf); 149 clrlin(); 150 if (!*buf || *buf == '\033') 151 return (1); 152 lth = strlen(buf) + 1; 153 if (lth > 63) { 154 buf[62] = 0; 155 lth = 63; 156 } 157 mtmp2 = newmonst(mtmp->mxlth + lth); 158 *mtmp2 = *mtmp; 159 for (i = 0; i < mtmp->mxlth; i++) 160 ((char *) mtmp2->mextra)[i] = ((char *) mtmp->mextra)[i]; 161 mtmp2->mnamelth = lth; 162 (void) strcpy(NAME(mtmp2), buf); 163 replmon(mtmp, mtmp2); 164 return (1); 165 } 166 167 /* 168 * This routine changes the address of obj . Be careful not to call it 169 * when there might be pointers around in unknown places. For now: only 170 * when obj is in the inventory. 171 */ 172 static void 173 do_oname(struct obj *obj) 174 { 175 struct obj *otmp, *otmp2; 176 int lth; 177 char buf[BUFSZ]; 178 pline("What do you want to name %s? ", doname(obj)); 179 getlin(buf); 180 clrlin(); 181 if (!*buf || *buf == '\033') 182 return; 183 lth = strlen(buf) + 1; 184 if (lth > 63) { 185 buf[62] = 0; 186 lth = 63; 187 } 188 otmp2 = newobj(lth); 189 *otmp2 = *obj; 190 otmp2->onamelth = lth; 191 (void) strcpy(ONAME(otmp2), buf); 192 193 setworn((struct obj *) 0, obj->owornmask); 194 setworn(otmp2, otmp2->owornmask); 195 196 /* 197 * do freeinv(obj); etc. by hand in order to preserve the position of 198 * this object in the inventory 199 */ 200 if (obj == invent) 201 invent = otmp2; 202 else 203 for (otmp = invent;; otmp = otmp->nobj) { 204 if (!otmp) 205 panic("Do_oname: cannot find obj."); 206 if (otmp->nobj == obj) { 207 otmp->nobj = otmp2; 208 break; 209 } 210 } 211 #if 0 212 obfree(obj, otmp2); /* now unnecessary: no pointers on bill */ 213 #endif 214 free((char *) obj); /* let us hope nobody else saved a pointer */ 215 } 216 217 int 218 ddocall(void) 219 { 220 struct obj *obj; 221 222 pline("Do you want to name an individual object? [ny] "); 223 switch (readchar()) { 224 case '\033': 225 break; 226 case 'y': 227 obj = getobj("#", "name"); 228 if (obj) 229 do_oname(obj); 230 break; 231 default: 232 obj = getobj("?!=/", "call"); 233 if (obj) 234 docall(obj); 235 } 236 return (0); 237 } 238 239 void 240 docall(struct obj *obj) 241 { 242 char buf[BUFSZ]; 243 struct obj otemp; 244 char **str1; 245 char *str; 246 247 otemp = *obj; 248 otemp.quan = 1; 249 otemp.onamelth = 0; 250 str = xname(&otemp); 251 pline("Call %s %s: ", strchr(vowels, *str) ? "an" : "a", str); 252 getlin(buf); 253 clrlin(); 254 if (!*buf || *buf == '\033') 255 return; 256 str = newstring(strlen(buf) + 1); 257 (void) strcpy(str, buf); 258 str1 = &(objects[obj->otyp].oc_uname); 259 if (*str1) 260 free(*str1); 261 *str1 = str; 262 } 263 264 static const char *const ghostnames[] = { 265 /* these names should have length < PL_NSIZ */ 266 "adri", "andries", "andreas", "bert", "david", "dirk", "emile", 267 "frans", "fred", "greg", "hether", "jay", "john", "jon", "kay", 268 "kenny", "maud", "michiel", "mike", "peter", "robert", "ron", 269 "tom", "wilmar" 270 }; 271 272 static char * 273 xmonnam(struct monst *mtmp, int vb) 274 { 275 static char buf[BUFSZ]; /* %% */ 276 if (mtmp->mnamelth && !vb) { 277 (void) strlcpy(buf, NAME(mtmp), sizeof(buf)); 278 return (buf); 279 } 280 switch (mtmp->data->mlet) { 281 case ' ': 282 { 283 const char *gn = (char *) mtmp->mextra; 284 if (!*gn) { /* might also look in scorefile */ 285 gn = ghostnames[rn2(SIZE(ghostnames))]; 286 if (!rn2(2)) 287 (void) 288 strlcpy((char *) mtmp->mextra, !rn2(5) ? plname : gn, mtmp->mxlth); 289 } 290 (void) snprintf(buf, sizeof(buf), "%s's ghost", gn); 291 } 292 break; 293 case '@': 294 if (mtmp->isshk) { 295 (void) strlcpy(buf, shkname(mtmp), sizeof(buf)); 296 break; 297 } 298 /* fall into next case */ 299 default: 300 (void) snprintf(buf, sizeof(buf), "the %s%s", 301 mtmp->minvis ? "invisible " : "", 302 mtmp->data->mname); 303 } 304 if (vb && mtmp->mnamelth) { 305 (void) strlcat(buf, " called ", sizeof(buf)); 306 (void) strlcat(buf, NAME(mtmp), sizeof(buf)); 307 } 308 return (buf); 309 } 310 311 static char * 312 lmonnam(struct monst *mtmp) 313 { 314 return (xmonnam(mtmp, 1)); 315 } 316 317 char * 318 monnam(struct monst *mtmp) 319 { 320 return (xmonnam(mtmp, 0)); 321 } 322 323 char * 324 Monnam(struct monst *mtmp) 325 { 326 char *bp = monnam(mtmp); 327 if ('a' <= *bp && *bp <= 'z') 328 *bp += ('A' - 'a'); 329 return (bp); 330 } 331 332 char * 333 amonnam(struct monst *mtmp, const char *adj) 334 { 335 char *bp = monnam(mtmp); 336 static char buf[BUFSZ]; /* %% */ 337 338 if (!strncmp(bp, "the ", 4)) 339 bp += 4; 340 (void) snprintf(buf, sizeof(buf), "the %s %s", adj, bp); 341 return (buf); 342 } 343 344 char * 345 Amonnam(struct monst *mtmp, const char *adj) 346 { 347 char *bp = amonnam(mtmp, adj); 348 349 *bp = 'T'; 350 return (bp); 351 } 352 353 char * 354 Xmonnam(struct monst *mtmp) 355 { 356 char *bp = Monnam(mtmp); 357 if (!strncmp(bp, "The ", 4)) { 358 bp += 2; 359 *bp = 'A'; 360 } 361 return (bp); 362 } 363 364 static char * 365 visctrl(int c) 366 { 367 static char ccc[3]; 368 if (c < 040) { 369 ccc[0] = '^'; 370 ccc[1] = c + 0100; 371 ccc[2] = 0; 372 } else { 373 ccc[0] = c; 374 ccc[1] = 0; 375 } 376 return (ccc); 377 } 378