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