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