1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* char.c */
3 /* Player generation */
4 
5 #ifndef MSDOS_SUPPORTED_ANTIQUE
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include <pwd.h>
9 #endif
10 
11 #include "glob.h"
12 
13 /* set player to begin with */
initplayer()14 void initplayer()
15 {
16   int i;
17   int oldchar=FALSE;
18   FILE *fd;
19   char *lname;
20 #ifndef MSDOS
21   struct passwd *dastuff;
22 #endif
23 
24   lname = getlogin();
25 #ifndef MSDOS
26   if (!lname || strlen(lname) == 0)
27   {
28        dastuff = getpwuid(getuid());
29        lname = dastuff->pw_name;
30   }
31 #endif
32   strcpy(Player.name,lname);
33   if (Player.name[0] >= 'a' && Player.name[0] <= 'z')
34        Player.name[0] += 'A'-'a'; /* capitalise 1st letter */
35   Player.itemweight = 0;
36   Player.food = 36;
37   Player.packptr = 0;
38   Behavior = -1;
39   Player.options = 0;
40   for (i=0;i<MAXITEMS;i++)
41     Player.possessions[i] = NULL;
42   for (i=0;i<MAXPACK;i++)
43     Player.pack[i] = NULL;
44   for (i=0;i<NUMIMMUNITIES;i++) Player.immunity[i] = 0;
45   for (i=0;i<NUMSTATI;i++) Player.status[i] = 0;
46   for (i=0;i<NUMRANKS;i++) {
47     Player.rank[i] = 0;
48     Player.guildxp[i] = 0;
49   }
50   Player.patron = 0;
51   Player.alignment = 0;
52   Player.cash = 250;
53   change_to_user_perms();
54   if ((fd=omegarc_check())!=NULL) {
55     fread((char *)&i,sizeof(int),1,fd);
56     if (i != VERSION) {
57 #if defined(MSDOS) || defined(AMIGA)
58       print1("Out of date omega.rc! Make another!");
59 #else
60       print1("Out of date .omegarc! Make another!");
61 #endif
62       morewait();
63     }
64     else {
65       oldchar = TRUE;
66       fread((char *)&Player,sizeof(Player),1,fd);
67       fread((char *)&Searchnum,sizeof(int),1,fd);
68       fread((char *)&Verbosity,sizeof(char),1,fd);
69       strcpy(Player.name,lname);
70       if (Player.name[0] >= 'a' && Player.name[0] <= 'z')
71 	   Player.name[0] += 'A'-'a'; /* capitalise 1st letter */
72     }
73     fclose(fd);
74   }
75   change_to_game_perms();
76   if (! oldchar) {
77     optionset(RUNSTOP);
78     optionset(CONFIRM);
79 #ifdef COMPRESS_SAVE_FILES
80     optionset(COMPRESS_OPTION);
81 #endif
82     optionset(SHOW_COLOUR);
83     initstats();
84   }
85   Searchnum = max(1,min(9,Searchnum));
86   Player.hp = Player.maxhp = Player.maxcon;
87   Player.mana = Player.maxmana = calcmana();
88   Player.click = 1;
89   strcpy(Player.meleestr,"CCBC");
90   calc_melee();
91   ScreenOffset = -1000;	/* to force a redraw */
92 }
93 
94 
omegarc_check()95 FILE *omegarc_check()
96 {
97   FILE *fd;
98 #if defined(MSDOS) || defined(AMIGA)
99   if ((fd = fopen("omega.rc","rb")) != NULL) {
100     print2("Use omega.rc charcter record in current directory? [yn] ");
101 #else
102   sprintf(Str1, "%s/.omegarc", getenv("HOME"));
103   if ((fd = fopen(Str1,"r")) != NULL) {
104     print2("Use .omegarc in home directory? [yn] ");
105 #endif
106     if (ynq2()!='y') {
107       fclose(fd);
108       fd = NULL;
109     }
110   }
111   clearmsg();
112   return(fd);
113 }
114 
115 void initstats()
116 {
117   char response;
118   print1("Do you want to run a character [c] or play yourself [p]?");
119   do response = (char) mcigetc(); while ((response!='c')&&(response != 'p'));
120   if (response == 'c') omegan_character_stats();
121   else {
122     user_character_stats();
123     user_intro();
124 #if defined(MSDOS) || defined(AMIGA)
125     print1("Do you want to save this set-up to omega.rc in this directory? [yn] ");
126 #else
127     print1("Do you want to save this set-up to .omegarc in your home directory? [yn] ");
128 #endif
129     if (ynq1()=='y')
130       save_omegarc();
131   }
132   xredraw();
133 }
134 
135 void save_omegarc()
136 {
137   int i=VERSION;
138   FILE *fd;
139   change_to_user_perms();
140 #if defined(MSDOS) || defined(AMIGA)
141   fd = fopen("omega.rc","wb");
142 #else
143   sprintf(Str1, "%s/.omegarc", getenv("HOME"));
144   fd = fopen(Str1,"w");
145 #endif
146   if (fd == NULL)
147 #if defined(MSDOS) || defined(AMIGA)
148     print1("Sorry, couldn't save omega.rc for some reason.");
149 #else
150     print1("Sorry, couldn't save .omegarc for some reason.");
151 #endif
152   else {
153     fwrite((char *)&i,sizeof(int),1,fd);
154     print1("First, set options.");
155     setoptions();
156     fwrite((char *)&Player,sizeof(Player),1,fd);
157     fwrite((char *)&Searchnum,sizeof(int),1,fd);
158     fwrite((char *)&Verbosity,sizeof(char),1,fd);
159     fclose(fd);
160   }
161   change_to_game_perms();
162 }
163 
164 
165 
166 long calcmana()
167 {
168   return(Player.pow * (long)(Player.level+1));
169 }
170 
171 
172 /*  npcbehavior digits 1234
173 
174 4 : alignment (LAWFUL,CHAOTIC, or NEUTRAL)
175 3 : primary combat action (melee,missile,spell,thief,flight,1..5)
176 2 : competence at 4 (0..9, 0 = incompetent, 9 = masterful)
177 1 : conversation mode
178 
179 status : 1 = dead, 2 = saved, 3 = retired, 4 = still playing
180 */
181 int fixnpc(status)
182 int status;
183 {
184   int npcbehavior=0;
185   char response;
186   if (status == 1) { /* player is dead, all undead are chaotic */
187     npcbehavior+=CHAOTIC;
188     npcbehavior+=10; /* melee */
189     npcbehavior+=100*min(9,((int) (Player.level/3)));
190     npcbehavior+=1000; /* threaten */
191   }
192   else if (Behavior >= 0)
193     npcbehavior = Behavior;
194   else {
195     menuclear();
196     menuprint("NPC Behavior Determination Module\n\n");
197     menuprint("Your overall NPC behavior is:");
198     if (Player.alignment < -10) {
199       npcbehavior += CHAOTIC;
200       menuprint("\n\n CHAOTIC");
201     }
202     else if (Player.alignment > 10) {
203       npcbehavior += LAWFUL;
204       menuprint("\n\n LAWFUL");
205     }
206     else {
207       npcbehavior += NEUTRAL;
208       menuprint("\n\n NEUTRAL");
209     }
210     menuprint("\n\n1: hand-to-hand combat");
211     menuprint("\n2: missile combat");
212     menuprint("\n3: spellcasting");
213     menuprint("\n4: thieving");
214     menuprint("\n5: escape");
215     menuprint("\n\nEnter NPC response to combat: ");
216     showmenu();
217     response = '0';
218     while ((response != '1') &&
219 	   (response != '2') &&
220 	   (response != '3') &&
221 	   (response != '4') &&
222 	   (response != '5'))
223       response = menugetc();
224     menuaddch(response);
225     npcbehavior+=10*(response - '0');
226     npcbehavior+=100*competence_check(response-'0');
227     response = '0';
228     menuclear();
229     menuprint("1: threaten");
230     menuprint("\n2: greet");
231     menuprint("\n3: aid");
232     menuprint("\n4: beg");
233     menuprint("\n5: silence");
234     menuprint("\n\nEnter NPC response to conversation: ");
235     showmenu();
236     while ((response != '1') &&
237 	   (response != '2') &&
238 	   (response != '3') &&
239 	   (response != '4') &&
240 	   (response != '5'))
241       response = menugetc();
242     menuaddch(response);
243     npcbehavior+=1000*(response - '0');
244     xredraw();
245   }
246   Behavior = npcbehavior;
247   return(npcbehavior);
248 }
249 
250 
251 /* estimates on a 0..9 scale how good a player is at something */
252 int competence_check(attack)
253 int attack;
254 {
255   int ability = 0;
256   switch(attack) {
257   case 1: /* melee */
258     ability += statmod(Player.str);
259   case 2: /* missle */
260     ability += statmod(Player.dex);
261     ability += Player.rank[LEGION];
262     ability += ((int) (Player.dmg / 10) - 1);
263     break;
264   case 3: /* spellcasting */
265     ability += statmod(Player.iq);
266     ability += statmod(Player.pow);
267     ability += Player.rank[CIRCLE];
268     ability += Player.rank[COLLEGE];
269     ability += Player.rank[PRIEST];
270     break;
271   case 4: /* thieving */
272     ability += statmod(Player.dex);
273     ability += statmod(Player.agi);
274     ability += Player.rank[THIEVES];
275     break;
276   case 5: /* escape */
277     ability += 2 * statmod(Player.agi);
278     break;
279   }
280   ability += ((int) (Player.level / 5));
281   if (ability < 0) ability = 0;
282   if (ability > 9) ability = 9;
283   return(ability);
284 }
285 
286 void user_character_stats()
287 {
288   int num,iqpts=0,numints=0,ok,agipts=0,dexpts=0,powpts=0,conpts=0;
289   print1("OK, now try to answer the following questions honestly:");
290   morewait();
291   print1("How many pounds can you bench press? ");
292   num = (int) parsenum();
293   if (num < 30) Player.str = Player.maxstr = 3;
294   else if (num < 90) Player.str = Player.maxstr = num/10;
295   else Player.str = Player.maxstr = 9+((num-120)/30);
296   if (Player.str > 18) {
297     print2("Even if it's true, I don't believe it.");
298     morewait();
299     clearmsg();
300     Player.str = Player.maxstr = 18;
301   }
302 
303   print1("Took an official IQ test? [yn] ");
304   if (ynq1()=='y') {
305     print1("So, whadja get? ");
306     num = (int) parsenum()/10;
307     if (num > 18) {
308       print2("Even if it's true, I don't believe it.");
309       morewait();
310       clearmsg();
311       num = 18;
312     }
313     iqpts+=num;
314     numints++;
315   }
316 
317   print1("Took Undergraduate entrance exams? [yn] ");
318   if (ynq1()=='y') {
319     do {
320       print1("So, what percentile? ");
321       num = (int) parsenum();
322       ok = (num < 100);
323       if (! ok) {
324 	print2("That's impossible!");
325 	morewait();
326 	clearmsg();
327       }
328     } while (! ok);
329     iqpts += (num - 49)*9/50 + 9;
330     numints++;
331   }
332   print1("Took Graduate entrance exams? [yn] ");
333   if (ynq1()=='y') {
334     do {
335       print1("So, what percentile? ");
336       num = (int) parsenum();
337       ok = (num < 100);
338       if (! ok) {
339 	print2("That's impossible!");
340 	morewait();
341 	clearmsg();
342       }
343     } while (! ok);
344     iqpts += (num - 49)*9/50 + 9;
345     numints++;
346   }
347 
348   if (numints == 0) {
349     print1("Pretty dumb, aren't you? [yn] ");
350     if (ynq1()=='y') {
351       Player.iq = random_range(3)+3;
352       print2("I thought so....");
353     }
354     else {
355       Player.iq = random_range(6)+8;
356       print2("Well, not *that* dumb.");
357     }
358     morewait();
359     clearmsg();
360   }
361   else Player.iq = iqpts/numints;
362   Player.maxiq = Player.iq;
363   agipts = 0;
364   print1("Can you dance? [yn] ");
365   if (ynq1()=='y') {
366     agipts++;
367     nprint1(" Well? [yn] ");
368     if (ynq1()=='y') agipts+=2;
369   }
370   print1("Do you have training in a martial art or gymnastics? [yn] ");
371   if (ynq1()=='y') {
372     agipts+=2;
373     print2("Do you have dan rank or equivalent? [yn] ");
374     if (ynq2()=='y') agipts+=4;
375   }
376   clearmsg();
377   print1("Do you play some field sport? [yn] ");
378   if (ynq1()=='y') {
379     agipts++;
380     nprint1(" Are you good? [yn] ");
381     if (ynq1()=='y') agipts++;
382   }
383   print1("Do you cave, mountaineer, etc.? [yn] ");
384   if (ynq1()=='y')
385     agipts+=3;
386   print1("Do you skate or ski? [yn] ");
387   if (ynq1()=='y') {
388     agipts+=2;
389     nprint1(" Well? [yn] ");
390     if (ynq1()=='y') agipts+=2;
391   }
392   print1("Are you physically handicapped? [yn] ");
393   if (ynq1()=='y')
394     agipts-=4;
395   print1("Are you accident prone? [yn] ");
396   if (ynq1()=='y')
397     agipts-=4;
398   print1("Can you use a bicycle? [yn] ");
399   if (ynq1()!='y')
400     agipts-=4;
401   Player.agi = Player.maxagi = 9 + agipts/2;
402   print1("Do you play video games? [yn] ");
403   if (ynq1()=='y') {
404     dexpts+=2;
405     print2("Do you get high scores? [yn] ");
406     if (ynq2()=='y') dexpts+=4;
407   }
408   clearmsg();
409   print1("Are you an archer, fencer, or marksman? [yn] ");
410   if (ynq1()=='y') {
411     dexpts+=2;
412     print2("A good one? [yn] ");
413     if (ynq2()=='y') dexpts+=4;
414   }
415   clearmsg();
416   print1("Have you ever picked a lock? [yn] ");
417   if (ynq1()=='y') {
418     dexpts+=2;
419     print2("Really. Well, the police are being notified.");
420   }
421   morewait();
422   clearmsg();
423   print1("What's your typing speed (words per minute) ");
424   num = (int) parsenum();
425   if (num > 125) {
426     print2("Tell me another one....");
427     morewait();
428     clearmsg();
429     num = 125;
430   }
431   dexpts += num/25;
432   print1("Hold your arm out. Tense your fist. Hand shaking? [yn] ");
433   if (ynq1()=='y')
434     dexpts-=3;
435   print1("Ambidextrous, are you? [yn] ");
436   if (ynq1()=='y')
437     dexpts+=4;
438   print1("Can you cut a deck of cards with one hand? [yn] ");
439   if (ynq1()=='y')
440     dexpts+=2;
441   print1("Can you tie your shoes blindfolded? [yn] ");
442   if (ynq1()!='y')
443     dexpts-=3;
444   Player.dex = Player.maxdex = 6 + dexpts/2;
445   print1("Do you ever get colds? [yn] ");
446   if (ynq1()!='y')
447     conpts+=4;
448   else {
449     nprint1(" Frequently? [yn] ");
450     if (ynq1() == 'y') conpts -=4;
451   }
452   print1("Had any serious accident or illness this year? [yn] ");
453   if (ynq1()=='y') conpts -=4;
454   else conpts +=4;
455   print1("Have a chronic disease? [yn] ");
456   if (ynq1() =='y') conpts -=4;
457   print1("Overweight or underweight by more than 20 percent? [yn] ");
458   if (ynq1() =='y') conpts -=2;
459   print1("High Blood Pressure? [yn] ");
460   if (ynq1() =='y') conpts -=2;
461   print1("Smoke? [yn] ");
462   if (ynq1() =='y') conpts -=3;
463   print1("Take aerobics classes? [yn] ");
464   if (ynq1() =='y') conpts +=2;
465   print1("How many miles can you run? ");
466   num = (int) parsenum();
467   if (num > 25) {
468     print2("Right. Sure. Give me a break.");
469     morewait();
470     clearmsg();
471     conpts += 8;
472   }
473   else if (num < 1) conpts -= 3;
474   else if (num < 5) conpts += 2;
475   else if (num < 10) conpts += 4;
476   else conpts += 8;
477   Player.con = Player.maxcon = 12 + conpts/3;
478   print1("Do animals react oddly to your presence? [yn] ");
479   if (ynq1()=='y') {
480     print2("How curious that must be.");
481     morewait();
482     clearmsg();
483     powpts += 2;
484   }
485   print1("Can you see auras? [yn] ");
486   if (ynq1()=='y') {
487     nprint1(" How strange.");
488     morewait();
489     powpts += 3;
490   }
491   print1("Ever have an out-of-body experience? [yn] ");
492   if (ynq1()=='y') {
493     print2("Wow, man. Fly the friendly skies....");
494     morewait();
495     clearmsg();
496     powpts += 3;
497   }
498   print1("Did you ever cast a spell? [yn] ");
499   if (ynq1()=='y') {
500     powpts += 3;
501     nprint1(" Did it work? [yn] ");
502     if (ynq1()=='y') {
503       powpts+=7;
504       print2("Sure it did.");
505       morewait();
506       clearmsg();
507     }
508   }
509   print1("Do you have ESP? [yn] ");
510   if (ynq1()=='y') {
511     powpts += 3;
512     print2("Somehow, I knew you were going to say that.");
513     morewait();
514     clearmsg();
515   }
516   print1("Do you have PK? [yn] ");
517   if (ynq1()=='y') {
518     powpts+= 6;
519     print2("I can't tell you how much that moves me.");
520     morewait();
521     clearmsg();
522   }
523   print1("Do you believe in ghosts? [yn] ");
524   if (ynq1()=='y') {
525     powpts+=2;
526     print2("I do! I do! I do believe in ghosts!");
527     morewait();
528     clearmsg();
529   }
530   print1("Are you Irish? [yn] ");
531   if (ynq1()=='y') {
532     powpts+=2;
533     nprint1(" Is that blarney or what?");
534     morewait();
535   }
536   Player.pow = Player.maxpow = 3 + powpts/2;
537   print1("Are you sexually interested in males or females? [mf] ");
538   do Player.preference = (char) mcigetc();
539   while ((Player.preference != 'm') && (Player.preference != 'f') &&
540 	(Player.preference != 'y') && (Player.preference != 'n')); /* :-) */
541 }
542 
543 
544 
545 void omegan_character_stats()
546 {
547   int share1,share2,i=0;
548   print1("To reroll hit ESCAPE; hit any other key to accept these stats.");
549   do {
550     i++;
551     sprintf(Str1, "You have only %d chance%s to reroll... ", REROLLS - i,
552             (i == (REROLLS-1) ) ? "":"s");
553     print2(Str1);
554     Player.iq = Player.maxiq = 4 + random_range(5)+
555       (share1 = random_range(6)) + (share2 = random_range(6));
556     Player.pow = Player.maxpow = 4 + random_range(5) + share1 +share2;
557     Player.dex = Player.maxdex = 4 + random_range(5)+
558       (share1 = random_range(6)) + (share2 = random_range(6));
559     Player.agi = Player.maxagi = 4 + random_range(5) + share1 +share2;
560     Player.str = Player.maxstr = 4 + random_range(5)+
561       (share1 = random_range(6)) + (share2 = random_range(6));
562     Player.con = Player.maxcon = 4 + random_range(5) + share1 +share2;
563     Player.cash = random_range(100)+random_range(100)+
564       random_range(100)+random_range(100)+random_range(100);
565     calc_melee();
566     dataprint();
567   } while ((i < REROLLS) && (mgetc() == ESCAPE));
568   clearmsg();
569   print1("Please enter your character's name: ");
570   strcpy(Player.name,msgscanstring());
571   if (Player.name[0] >= 'a' && Player.name[0] <= 'z')
572     Player.name[0] += 'A'-'a'; /* capitalise 1st letter */
573   print1("Is your character sexually interested in males or females? [mf] ");
574   do Player.preference = (char) mcigetc();
575   while ((Player.preference != 'm') && (Player.preference != 'f') &&
576 	(Player.preference != 'y') && (Player.preference != 'n')); /* :-) */
577 
578 }
579 
580