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