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