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