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