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