xref: /netbsd-src/games/hack/hack.do_name.c (revision e77448e07be3174235c13f58032a0d6d0ab7638d)
1 /*	$NetBSD: hack.do_name.c,v 1.7 2008/01/28 06:55:41 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.7 2008/01/28 06:55:41 dholland Exp $");
67 #endif				/* not lint */
68 
69 #include <stdlib.h>
70 #include "hack.h"
71 #include "extern.h"
72 
73 coord
74 getpos(force, goal)
75 	int             force;
76 	const char           *goal;
77 {
78 	int             cx, cy, i, c;
79 	coord           cc;
80 	pline("(For instructions type a ?)");
81 	cx = u.ux;
82 	cy = u.uy;
83 	curs(cx, cy + 2);
84 	while ((c = readchar()) != '.') {
85 		for (i = 0; i < 8; i++)
86 			if (sdir[i] == c) {
87 				if (1 <= cx + xdir[i] && cx + xdir[i] <= COLNO)
88 					cx += xdir[i];
89 				if (0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO - 1)
90 					cy += ydir[i];
91 				goto nxtc;
92 			}
93 		if (c == '?') {
94 			pline("Use [hjkl] to move the cursor to %s.", goal);
95 			pline("Type a . when you are at the right place.");
96 		} else {
97 			pline("Unknown direction: '%s' (%s).",
98 			      visctrl(c),
99 			      force ? "use hjkl or ." : "aborted");
100 			if (force)
101 				goto nxtc;
102 			cc.x = -1;
103 			cc.y = 0;
104 			return (cc);
105 		}
106 nxtc:		;
107 		curs(cx, cy + 2);
108 	}
109 	cc.x = cx;
110 	cc.y = cy;
111 	return (cc);
112 }
113 
114 int
115 do_mname()
116 {
117 	char            buf[BUFSZ];
118 	coord           cc;
119 	int             cx, cy, lth;
120 	unsigned        i;
121 	struct monst   *mtmp, *mtmp2;
122 	cc = getpos(0, "the monster you want to name");
123 	cx = cc.x;
124 	cy = cc.y;
125 	if (cx < 0)
126 		return (0);
127 	mtmp = m_at(cx, cy);
128 	if (!mtmp) {
129 		if (cx == u.ux && cy == u.uy)
130 			pline("This ugly monster is called %s and cannot be renamed.",
131 			      plname);
132 		else
133 			pline("There is no monster there.");
134 		return (1);
135 	}
136 	if (mtmp->mimic) {
137 		pline("I see no monster there.");
138 		return (1);
139 	}
140 	if (!cansee(cx, cy)) {
141 		pline("I cannot see a monster there.");
142 		return (1);
143 	}
144 	pline("What do you want to call %s? ", lmonnam(mtmp));
145 	getlin(buf);
146 	clrlin();
147 	if (!*buf || *buf == '\033')
148 		return (1);
149 	lth = strlen(buf) + 1;
150 	if (lth > 63) {
151 		buf[62] = 0;
152 		lth = 63;
153 	}
154 	mtmp2 = newmonst(mtmp->mxlth + lth);
155 	*mtmp2 = *mtmp;
156 	for (i = 0; i < mtmp->mxlth; i++)
157 		((char *) mtmp2->mextra)[i] = ((char *) mtmp->mextra)[i];
158 	mtmp2->mnamelth = lth;
159 	(void) strcpy(NAME(mtmp2), buf);
160 	replmon(mtmp, mtmp2);
161 	return (1);
162 }
163 
164 /*
165  * This routine changes the address of  obj . Be careful not to call it
166  * when there might be pointers around in unknown places. For now: only
167  * when  obj  is in the inventory.
168  */
169 void
170 do_oname(obj)
171 	struct obj     *obj;
172 {
173 	struct obj     *otmp, *otmp2;
174 	int lth;
175 	char            buf[BUFSZ];
176 	pline("What do you want to name %s? ", doname(obj));
177 	getlin(buf);
178 	clrlin();
179 	if (!*buf || *buf == '\033')
180 		return;
181 	lth = strlen(buf) + 1;
182 	if (lth > 63) {
183 		buf[62] = 0;
184 		lth = 63;
185 	}
186 	otmp2 = newobj(lth);
187 	*otmp2 = *obj;
188 	otmp2->onamelth = lth;
189 	(void) strcpy(ONAME(otmp2), buf);
190 
191 	setworn((struct obj *) 0, obj->owornmask);
192 	setworn(otmp2, otmp2->owornmask);
193 
194 	/*
195 	 * do freeinv(obj); etc. by hand in order to preserve the position of
196 	 * this object in the inventory
197 	 */
198 	if (obj == invent)
199 		invent = otmp2;
200 	else
201 		for (otmp = invent;; otmp = otmp->nobj) {
202 			if (!otmp)
203 				panic("Do_oname: cannot find obj.");
204 			if (otmp->nobj == obj) {
205 				otmp->nobj = otmp2;
206 				break;
207 			}
208 		}
209 #if 0
210 	obfree(obj, otmp2);	/* now unnecessary: no pointers on bill */
211 #endif
212 	free((char *) obj);	/* let us hope nobody else saved a pointer */
213 }
214 
215 int
216 ddocall()
217 {
218 	struct obj     *obj;
219 
220 	pline("Do you want to name an individual object? [ny] ");
221 	switch (readchar()) {
222 	case '\033':
223 		break;
224 	case 'y':
225 		obj = getobj("#", "name");
226 		if (obj)
227 			do_oname(obj);
228 		break;
229 	default:
230 		obj = getobj("?!=/", "call");
231 		if (obj)
232 			docall(obj);
233 	}
234 	return (0);
235 }
236 
237 void
238 docall(obj)
239 	struct obj     *obj;
240 {
241 	char            buf[BUFSZ];
242 	struct obj      otemp;
243 	char          **str1;
244 	char           *str;
245 
246 	otemp = *obj;
247 	otemp.quan = 1;
248 	otemp.onamelth = 0;
249 	str = xname(&otemp);
250 	pline("Call %s %s: ", strchr(vowels, *str) ? "an" : "a", str);
251 	getlin(buf);
252 	clrlin();
253 	if (!*buf || *buf == '\033')
254 		return;
255 	str = newstring(strlen(buf) + 1);
256 	(void) strcpy(str, buf);
257 	str1 = &(objects[obj->otyp].oc_uname);
258 	if (*str1)
259 		free(*str1);
260 	*str1 = str;
261 }
262 
263 const char *const ghostnames[] = {/* these names should have length < PL_NSIZ */
264 	"adri", "andries", "andreas", "bert", "david", "dirk", "emile",
265 	"frans", "fred", "greg", "hether", "jay", "john", "jon", "kay",
266 	"kenny", "maud", "michiel", "mike", "peter", "robert", "ron",
267 	"tom", "wilmar"
268 };
269 
270 char           *
271 xmonnam(mtmp, vb)
272 	struct monst   *mtmp;
273 	int             vb;
274 {
275 	static char     buf[BUFSZ];	/* %% */
276 	if (mtmp->mnamelth && !vb) {
277 		(void) strcpy(buf, NAME(mtmp));
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 						strcpy((char *) mtmp->mextra, !rn2(5) ? plname : gn);
289 			}
290 			(void) sprintf(buf, "%s's ghost", gn);
291 		}
292 		break;
293 	case '@':
294 		if (mtmp->isshk) {
295 			(void) strcpy(buf, shkname(mtmp));
296 			break;
297 		}
298 		/* fall into next case */
299 	default:
300 		(void) sprintf(buf, "the %s%s",
301 			       mtmp->minvis ? "invisible " : "",
302 			       mtmp->data->mname);
303 	}
304 	if (vb && mtmp->mnamelth) {
305 		(void) strcat(buf, " called ");
306 		(void) strcat(buf, NAME(mtmp));
307 	}
308 	return (buf);
309 }
310 
311 char           *
312 lmonnam(mtmp)
313 	struct monst   *mtmp;
314 {
315 	return (xmonnam(mtmp, 1));
316 }
317 
318 char           *
319 monnam(mtmp)
320 	struct monst   *mtmp;
321 {
322 	return (xmonnam(mtmp, 0));
323 }
324 
325 char           *
326 Monnam(mtmp)
327 	struct monst   *mtmp;
328 {
329 	char           *bp = monnam(mtmp);
330 	if ('a' <= *bp && *bp <= 'z')
331 		*bp += ('A' - 'a');
332 	return (bp);
333 }
334 
335 char           *
336 amonnam(mtmp, adj)
337 	struct monst   *mtmp;
338 	const char           *adj;
339 {
340 	char           *bp = monnam(mtmp);
341 	static char     buf[BUFSZ];	/* %% */
342 
343 	if (!strncmp(bp, "the ", 4))
344 		bp += 4;
345 	(void) sprintf(buf, "the %s %s", adj, bp);
346 	return (buf);
347 }
348 
349 char           *
350 Amonnam(mtmp, adj)
351 	struct monst   *mtmp;
352 	const char           *adj;
353 {
354 	char           *bp = amonnam(mtmp, adj);
355 
356 	*bp = 'T';
357 	return (bp);
358 }
359 
360 char           *
361 Xmonnam(mtmp)
362 	struct monst   *mtmp;
363 {
364 	char           *bp = Monnam(mtmp);
365 	if (!strncmp(bp, "The ", 4)) {
366 		bp += 2;
367 		*bp = 'A';
368 	}
369 	return (bp);
370 }
371 
372 char           *
373 visctrl(c)
374 	char            c;
375 {
376 	static char     ccc[3];
377 	if (c < 040) {
378 		ccc[0] = '^';
379 		ccc[1] = c + 0100;
380 		ccc[2] = 0;
381 	} else {
382 		ccc[0] = c;
383 		ccc[1] = 0;
384 	}
385 	return (ccc);
386 }
387