1/*	$NetBSD: hack.do_name.c,v 1.12 2011/08/06 20:29:37 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@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.12 2011/08/06 20:29:37 dholland Exp $");
67#endif				/* not lint */
68
69#include <stdlib.h>
70#include "hack.h"
71#include "extern.h"
72
73static void do_oname(struct obj *);
74static char *xmonnam(struct monst *, int);
75static char *lmonnam(struct monst *);
76static char *visctrl(int);
77
78coord
79getpos(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		}
109nxtc:		;
110		curs(cx, cy + 2);
111	}
112	cc.x = cx;
113	cc.y = cy;
114	return (cc);
115}
116
117int
118do_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 */
173static void
174do_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
218int
219ddocall(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
240void
241docall(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
265static 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
273static char *
274xmonnam(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
312static char *
313lmonnam(struct monst *mtmp)
314{
315	return (xmonnam(mtmp, 1));
316}
317
318char           *
319monnam(struct monst *mtmp)
320{
321	return (xmonnam(mtmp, 0));
322}
323
324char           *
325Monnam(struct monst *mtmp)
326{
327	char           *bp = monnam(mtmp);
328	if ('a' <= *bp && *bp <= 'z')
329		*bp += ('A' - 'a');
330	return (bp);
331}
332
333char           *
334amonnam(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
345char           *
346Amonnam(struct monst *mtmp, const char *adj)
347{
348	char           *bp = amonnam(mtmp, adj);
349
350	*bp = 'T';
351	return (bp);
352}
353
354char           *
355Xmonnam(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
365static char *
366visctrl(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