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