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