xref: /netbsd/games/hack/hack.do_name.c (revision 759cbe51)
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@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
getpos(int force,const char * goal)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
do_mname(void)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
do_oname(struct obj * obj)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
ddocall(void)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
docall(struct obj * obj)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 *
xmonnam(struct monst * mtmp,int vb)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 *
lmonnam(struct monst * mtmp)313 lmonnam(struct monst *mtmp)
314 {
315 	return (xmonnam(mtmp, 1));
316 }
317 
318 char           *
monnam(struct monst * mtmp)319 monnam(struct monst *mtmp)
320 {
321 	return (xmonnam(mtmp, 0));
322 }
323 
324 char           *
Monnam(struct monst * mtmp)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           *
amonnam(struct monst * mtmp,const char * adj)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           *
Amonnam(struct monst * mtmp,const char * adj)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           *
Xmonnam(struct monst * mtmp)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 *
visctrl(int c)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