build - Significantly improve parallel buildworld times
[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 /* $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 }