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