xref: /dragonfly/games/hack/hack.do_name.c (revision 0db87cb7)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.do_name.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.do_name.c,v 1.5 1999/11/16 10:26:36 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.do_name.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */
5 
6 #include "hack.h"
7 
8 static void do_oname(struct obj *);
9 static char *xmonnam(struct monst *, int);
10 static char *lmonnam(struct monst *);
11 static char *visctrl(char);
12 
13 coord
14 getpos(int force, const char *goal)
15 {
16 	int cx, cy, i, c;
17 	coord cc;
18 
19 	pline("(For instructions type a ?)");
20 	cx = u.ux;
21 	cy = u.uy;
22 	curs(cx, cy + 2);
23 	while ((c = readchar()) != '.') {
24 		for (i = 0; i < 8; i++)
25 			if (sdir[i] == c) {
26 				if (1 <= cx + xdir[i] && cx + xdir[i] <= COLNO)
27 					cx += xdir[i];
28 				if (0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO - 1)
29 					cy += ydir[i];
30 				goto nxtc;
31 			}
32 		if (c == '?') {
33 			pline("Use [hjkl] to move the cursor to %s.", goal);
34 			pline("Type a . when you are at the right place.");
35 		} else {
36 			pline("Unknown direction: '%s' (%s).",
37 			      visctrl(c),
38 			      force ? "use hjkl or ." : "aborted");
39 			if (force)
40 				goto nxtc;
41 			cc.x = -1;
42 			cc.y = 0;
43 			return (cc);
44 		}
45 nxtc:
46 		curs(cx, cy + 2);
47 	}
48 	cc.x = cx;
49 	cc.y = cy;
50 	return (cc);
51 }
52 
53 int
54 do_mname(void)
55 {
56 	char buf[BUFSZ];
57 	coord cc;
58 	int cx, cy, lth, i;
59 	struct monst *mtmp, *mtmp2;
60 
61 	cc = getpos(0, "the monster you want to name");
62 	cx = cc.x;
63 	cy = cc.y;
64 	if (cx < 0)
65 		return (0);
66 	mtmp = m_at(cx, cy);
67 	if (!mtmp) {
68 		if (cx == u.ux && cy == u.uy)
69 			pline("This ugly monster is called %s and cannot be renamed.",
70 			    plname);
71 		else
72 			pline("There is no monster there.");
73 		return (1);
74 	}
75 	if (mtmp->mimic) {
76 		pline("I see no monster there.");
77 		return (1);
78 	}
79 	if (!cansee(cx, cy)) {
80 		pline("I cannot see a monster there.");
81 		return (1);
82 	}
83 	pline("What do you want to call %s? ", lmonnam(mtmp));
84 	getlin(buf);
85 	clrlin();
86 	if (!*buf || *buf == '\033')
87 		return (1);
88 	lth = strlen(buf) + 1;
89 	if (lth > 63) {
90 		buf[62] = 0;
91 		lth = 63;
92 	}
93 	mtmp2 = newmonst(mtmp->mxlth + lth);
94 	*mtmp2 = *mtmp;
95 	for (i = 0; (unsigned)i < mtmp->mxlth; i++)
96 		((char *)mtmp2->mextra)[i] = ((char *)mtmp->mextra)[i];
97 	mtmp2->mnamelth = lth;
98 	strcpy(NAME(mtmp2), buf);
99 	replmon(mtmp, mtmp2);
100 	return (1);
101 }
102 
103 /*
104  * This routine changes the address of  obj . Be careful not to call it
105  * when there might be pointers around in unknown places. For now: only
106  * when  obj  is in the inventory.
107  */
108 static void
109 do_oname(struct obj *obj)
110 {
111 	struct obj *otmp, *otmp2;
112 	int lth;
113 	char buf[BUFSZ];
114 
115 	pline("What do you want to name %s? ", doname(obj));
116 	getlin(buf);
117 	clrlin();
118 	if (!*buf || *buf == '\033')
119 		return;
120 	lth = strlen(buf) + 1;
121 	if (lth > 63) {
122 		buf[62] = 0;
123 		lth = 63;
124 	}
125 	otmp2 = newobj(lth);
126 	*otmp2 = *obj;
127 	otmp2->onamelth = lth;
128 	strcpy(ONAME(otmp2), buf);
129 
130 	setworn(NULL, obj->owornmask);
131 	setworn(otmp2, otmp2->owornmask);
132 
133 	/*
134 	 * do freeinv(obj); etc. by hand in order to preserve the position of
135 	 * this object in the inventory
136 	 */
137 	if (obj == invent)
138 		invent = otmp2;
139 	else
140 		for (otmp = invent;; otmp = otmp->nobj) {
141 			if (!otmp)
142 				panic("Do_oname: cannot find obj.");
143 			if (otmp->nobj == obj) {
144 				otmp->nobj = otmp2;
145 				break;
146 			}
147 		}
148 	/*obfree(obj, otmp2);*/	/* now unnecessary: no pointers on bill */
149 	free(obj);		/* let us hope nobody else saved a pointer */
150 }
151 
152 int
153 ddocall(void)
154 {
155 	struct obj *obj;
156 
157 	pline("Do you want to name an individual object? [ny] ");
158 	switch (readchar()) {
159 	case '\033':
160 		break;
161 	case 'y':
162 		obj = getobj("#", "name");
163 		if (obj)
164 			do_oname(obj);
165 		break;
166 	default:
167 		obj = getobj("?!=/", "call");
168 		if (obj)
169 			docall(obj);
170 	}
171 	return (0);
172 }
173 
174 void
175 docall(struct obj *obj)
176 {
177 	char buf[BUFSZ];
178 	struct obj otemp;
179 	char **str1;
180 	char *str;
181 
182 	otemp = *obj;
183 	otemp.quan = 1;
184 	otemp.onamelth = 0;
185 	str = xname(&otemp);
186 	pline("Call %s %s: ", strchr(vowels, *str) ? "an" : "a", str);
187 	getlin(buf);
188 	clrlin();
189 	if (!*buf || *buf == '\033')
190 		return;
191 	str = newstring(strlen(buf) + 1);
192 	strcpy(str, buf);
193 	str1 = &(objects[obj->otyp].oc_uname);
194 	if (*str1)
195 		free(*str1);
196 	*str1 = str;
197 }
198 
199 /* these names should have length < PL_NSIZ */
200 const char *ghostnames[] = {
201 	"adri", "andries", "andreas", "bert", "david", "dirk", "emile",
202 	"frans", "fred", "greg", "hether", "jay", "john", "jon", "kay",
203 	"kenny", "maud", "michiel", "mike", "peter", "robert", "ron",
204 	"tom", "wilmar"
205 };
206 
207 static char *
208 xmonnam(struct monst *mtmp, int vb)
209 {
210 	static char buf[BUFSZ];		/* %% */
211 
212 	if (mtmp->mnamelth && !vb) {
213 		strcpy(buf, NAME(mtmp));
214 		return (buf);
215 	}
216 	switch (mtmp->data->mlet) {
217 	case ' ':
218 		{
219 			const char *gn = (const char *)mtmp->mextra;
220 			if (!*gn) {	/* might also look in scorefile */
221 				gn = ghostnames[rn2(SIZE(ghostnames))];
222 				if (!rn2(2))
223 					strcpy((char *)mtmp->mextra,
224 					    !rn2(5) ? plname : gn);
225 			}
226 			sprintf(buf, "%s's ghost", gn);
227 		}
228 		break;
229 	case '@':
230 		if (mtmp->isshk) {
231 			strcpy(buf, shkname(mtmp));
232 			break;
233 		}
234 	/* fall into next case */
235 	default:
236 		sprintf(buf, "the %s%s",
237 			mtmp->minvis ? "invisible " : "",
238 			mtmp->data->mname);
239 	}
240 	if (vb && mtmp->mnamelth) {
241 		strcat(buf, " called ");
242 		strcat(buf, NAME(mtmp));
243 	}
244 	return (buf);
245 }
246 
247 static char *
248 lmonnam(struct monst *mtmp)
249 {
250 	return (xmonnam(mtmp, 1));
251 }
252 
253 char *
254 monnam(struct monst *mtmp)
255 {
256 	return (xmonnam(mtmp, 0));
257 }
258 
259 char *
260 Monnam(struct monst *mtmp)
261 {
262 	char *bp = monnam(mtmp);
263 
264 	if ('a' <= *bp && *bp <= 'z')
265 		*bp += ('A' - 'a');
266 	return (bp);
267 }
268 
269 char *
270 amonnam(struct monst *mtmp, const char *adj)
271 {
272 	char *bp = monnam(mtmp);
273 	static char buf[BUFSZ];		/* %% */
274 
275 	if (!strncmp(bp, "the ", 4))
276 		bp += 4;
277 	sprintf(buf, "the %s %s", adj, bp);
278 	return (buf);
279 }
280 
281 char *
282 Amonnam(struct monst *mtmp, const char *adj)
283 {
284 	char *bp = amonnam(mtmp, adj);
285 
286 	*bp = 'T';
287 	return (bp);
288 }
289 
290 char *
291 Xmonnam(struct monst *mtmp)
292 {
293 	char *bp = Monnam(mtmp);
294 
295 	if (!strncmp(bp, "The ", 4)) {
296 		bp += 2;
297 		*bp = 'A';
298 	}
299 	return (bp);
300 }
301 
302 static char *
303 visctrl(char c)
304 {
305 	static char ccc[3];
306 
307 	if (c < 040) {
308 		ccc[0] = '^';
309 		ccc[1] = c + 0100;
310 		ccc[2] = 0;
311 	} else {
312 		ccc[0] = c;
313 		ccc[1] = 0;
314 	}
315 	return (ccc);
316 }
317