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