Home | History | Annotate | Line # | Download | only in hack
      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 (at) 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.13 2011/08/07 06:03:45 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;
    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  */
    173 static void
    174 do_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 
    218 int
    219 ddocall(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 
    240 void
    241 docall(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 
    265 static 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 
    273 static char *
    274 xmonnam(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 
    312 static char *
    313 lmonnam(struct monst *mtmp)
    314 {
    315 	return (xmonnam(mtmp, 1));
    316 }
    317 
    318 char           *
    319 monnam(struct monst *mtmp)
    320 {
    321 	return (xmonnam(mtmp, 0));
    322 }
    323 
    324 char           *
    325 Monnam(struct monst *mtmp)
    326 {
    327 	char           *bp = monnam(mtmp);
    328 	if ('a' <= *bp && *bp <= 'z')
    329 		*bp += ('A' - 'a');
    330 	return (bp);
    331 }
    332 
    333 char           *
    334 amonnam(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 
    345 char           *
    346 Amonnam(struct monst *mtmp, const char *adj)
    347 {
    348 	char           *bp = amonnam(mtmp, adj);
    349 
    350 	*bp = 'T';
    351 	return (bp);
    352 }
    353 
    354 char           *
    355 Xmonnam(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 
    365 static char *
    366 visctrl(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