00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <ctype.h>
00010 #include <string.h>
00011 #include "advent.h"
00012 #include "advdec.h"
00013
00014
00015
00016
00017 boolean ajar(item)
00018 int item;
00019 {
00020 return ((bitset(g.obj_state[item], OPENBT))
00021 || (vessel(item) && !hinged(item)));
00022 }
00023
00024
00025
00026
00027 boolean at(item)
00028 int item;
00029 {
00030 if (item < 1 || item > MAXOBJ)
00031 return (FALSE);
00032 else
00033 return (g.place[item] == g.loc || g.fixed[item] == g.loc);
00034 }
00035
00036
00037
00038
00039
00040 boolean athand(item)
00041 int item;
00042 {
00043 int contnr;
00044 boolean aaa;
00045
00046 contnr = -g.place[item];
00047 aaa = enclosed(item) && ajar(contnr);
00048
00049 return ((g.place[item] == g.loc) || holding(item)
00050 || (aaa && ((g.place[contnr] == g.loc)
00051 || (toting(item) && holding(contnr)))));
00052 }
00053
00054
00055
00056
00057 void bitoff(obj, bit)
00058 int obj, bit;
00059 {
00060 long val;
00061
00062 val = 1L << bit;
00063 g.obj_state[obj] &= ~val;
00064 }
00065
00066
00067
00068
00069 void biton(obj, bit)
00070 int obj, bit;
00071 {
00072 long val;
00073
00074 val = 1L << bit;
00075 g.obj_state[obj] |= val;
00076 }
00077
00078
00079
00080
00081 boolean bitset(state, bit)
00082 long state;
00083 int bit;
00084 {
00085 return (((state >> bit) & 1) == 1);
00086 }
00087
00088
00089
00090
00091 boolean blind()
00092 {
00093 return (dark() || (g.loc == 200
00094 && athand(LAMP) && (g.prop[LAMP] == 1)));
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 int burden(obj)
00113 int obj;
00114 {
00115 int i, sum, temp;
00116
00117 sum = 0;
00118 if (obj == 0) {
00119 for (i = 1; i < MAXOBJ; i++) {
00120 if (toting(i) && (g.place[i] != -BOAT))
00121 sum += g.weight[i];
00122 }
00123 } else {
00124 if (obj != BOAT) {
00125 sum = g.weight[obj];
00126 temp = g.holder[obj];
00127 while (temp != 0) {
00128 sum += g.weight[temp];
00129 temp = g.hlink[temp];
00130 }
00131 }
00132 }
00133 return (sum);
00134 }
00135
00136
00137
00138
00139
00140
00141
00142 void carry(obj, where)
00143 int obj, where;
00144 {
00145 int temp;
00146
00147 if (obj < MAXOBJ) {
00148 if (g.place[obj] == -1)
00149 return;
00150 g.place[obj] = -1;
00151 }
00152 if (g.atloc[where] == obj)
00153 g.atloc[where] = g.link[obj];
00154 else {
00155 temp = g.atloc[where];
00156 while (g.link[temp] != obj) {
00157 temp = g.link[temp];
00158 if (temp == 0)
00159 bug(35);
00160 }
00161 g.link[temp] = g.link[obj];
00162 }
00163 return;
00164 }
00165
00166
00167
00168
00169 int confuz()
00170 {
00171 int msg;
00172
00173 msg = 60;
00174 if (pct(50))
00175 msg = 61;
00176 if (pct(33))
00177 msg = 13;
00178 if (pct(25))
00179 msg = 347;
00180 if (pct(20))
00181 msg = 195;
00182 return (msg);
00183 }
00184
00185
00186
00187
00188 boolean dark()
00189 {
00190 return (!(g.loc_attrib[g.loc] & LIGHT) &&
00191 (!g.prop[LAMP] || !athand(LAMP)));
00192 }
00193
00194
00195
00196
00197
00198 int dcheck()
00199 {
00200 int i;
00201
00202 for (i = 1; i < (DWARFMAX); ++i)
00203 if (g.dloc[i] == g.loc)
00204 return (i);
00205 return (0);
00206 }
00207
00208
00209
00210
00211 boolean dead(obj)
00212 int obj;
00213 {
00214 return (bitset(g.obj_state[obj], 10));
00215 }
00216
00217
00218
00219
00220 void drop(obj, where)
00221 int obj, where;
00222 {
00223 if (obj > MAXOBJ)
00224 g.fixed[obj - MAXOBJ] = where;
00225 else
00226 g.place[obj] = where;
00227 if (where > 0) {
00228 g.link[obj] = g.atloc[where];
00229 g.atloc[where] = obj;
00230 }
00231 return;
00232 }
00233
00234
00235
00236
00237
00238 void destroy(obj)
00239 int obj;
00240 {
00241 move(obj, 0);
00242 return;
00243 }
00244
00245
00246
00247
00248 boolean edible(obj)
00249 int obj;
00250 {
00251 return (bitset(g.obj_state[obj], 7));
00252 }
00253
00254
00255
00256
00257 boolean enclosed(item)
00258 int item;
00259 {
00260 if (item < 1 || item > MAXOBJ)
00261 return (FALSE);
00262 else
00263 return (g.place[item] < -1);
00264 }
00265
00266
00267
00268
00269
00270 void extract(obj)
00271 int obj;
00272 {
00273 int contnr, temp;
00274
00275 contnr = -g.place[obj];
00276 g.place[obj] = -1;
00277 if (g.holder[contnr] == obj)
00278 g.holder[contnr] = g.hlink[obj];
00279 else {
00280 temp = g.holder[contnr];
00281 while (g.hlink[temp] != obj) {
00282 temp = g.hlink[temp];
00283 if (temp == 0)
00284 bug(35);
00285 }
00286 g.hlink[temp] = g.hlink[obj];
00287 }
00288 return;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 int forced(at_loc)
00298 int at_loc;
00299 {
00300 return ((g.loc_attrib[at_loc] & 10) == 2);
00301 }
00302
00303
00304
00305
00306 boolean here(item)
00307 int item;
00308 {
00309 return (g.place[item] == g.loc || toting(item));
00310 }
00311
00312
00313
00314
00315 boolean hinged(object)
00316 int object;
00317 {
00318 return (bitset(g.obj_state[object], 1));
00319 }
00320
00321
00322
00323
00324 boolean holding(item)
00325 int item;
00326 {
00327 if (item < 1 || item > MAXOBJ)
00328 return (FALSE);
00329 else
00330 return (g.place[item] == -1);
00331 }
00332
00333
00334
00335
00336 void insert(obj, contnr)
00337 int obj, contnr;
00338 {
00339 int temp;
00340
00341 if (contnr == obj)
00342 bug(32);
00343 carry(obj, g.loc);
00344
00345 temp = g.holder[contnr];
00346 g.holder[contnr] = obj;
00347 g.hlink[obj] = temp;
00348 g.place[obj] = -contnr;
00349 }
00350
00351
00352
00353
00354 boolean inside(loc)
00355 int loc;
00356 {
00357 return (!outside(loc) && !portal(loc));
00358 }
00359
00360
00361
00362
00363
00364
00365 void juggle(obj)
00366 int obj;
00367 {
00368 int i, j;
00369
00370 i = g.place[obj];
00371 j = g.fixed[obj];
00372 move(obj, i);
00373 move(obj + MAXOBJ, j);
00374 return;
00375 }
00376
00377
00378
00379
00380 int liq(item)
00381 int item;
00382 {
00383 int liquid;
00384
00385 if ((item == BOTTLE) || (item == CASK))
00386 liquid = liq2(((int) g.prop[item] >> 1) & 7);
00387 else
00388 liquid = 0;
00389
00390 return (liquid);
00391 }
00392
00393
00394
00395
00396 int liq2(liquid)
00397 int liquid;
00398 {
00399 switch (liquid) {
00400 case 4:
00401 return (WATER);
00402 case 5:
00403 return (OIL);
00404 case 6:
00405 return (WINE);
00406 default:
00407 return (0);
00408 }
00409 }
00410
00411
00412
00413
00414 int liqloc(loc)
00415 int loc;
00416 {
00417 return (liq2((int) ((g.loc_attrib[loc] >> 1) & 7)));
00418 }
00419
00420
00421
00422
00423 boolean living(obj)
00424 int obj;
00425 {
00426 return (bitset(g.obj_state[obj], 9));
00427 }
00428
00429
00430
00431
00432 boolean locked(item)
00433 int item;
00434 {
00435 return (bitset(g.obj_state[item], 4));
00436 }
00437
00438
00439
00440
00441 boolean locks(item)
00442 int item;
00443 {
00444 return (bitset(g.obj_state[item], 3));
00445 }
00446
00447
00448
00449
00450 void lookin(contnr)
00451 int contnr;
00452 {
00453 int temp;
00454 boolean first_time;
00455
00456 if (vessel(contnr) && (ajar(contnr) || !opaque(contnr))) {
00457 temp = g.holder[contnr];
00458 first_time = TRUE;
00459 while (temp != 0) {
00460 if (first_time)
00461 rspeak(360);
00462 printf(" ");
00463 pspeak(temp, -1);
00464 temp = g.hlink[temp];
00465 first_time = FALSE;
00466 }
00467 }
00468 return;
00469 }
00470
00471
00472
00473
00474 void move(obj, where)
00475 int obj, where;
00476 {
00477 int from;
00478
00479 if (obj > MAXOBJ)
00480 from = g.fixed[obj - MAXOBJ];
00481 else {
00482 if (enclosed(obj))
00483 extract(obj);
00484 from = g.place[obj];
00485 }
00486 if ((from > 0) && (from < MAXOBJ * 2))
00487 carry(obj, from);
00488 drop(obj, where);
00489 return;
00490 }
00491
00492
00493
00494
00495 int noway()
00496 {
00497 int msg;
00498
00499 msg = 14;
00500 if (pct(50))
00501 msg = 110;
00502 if (pct(33))
00503 msg = 147;
00504 if (pct(25))
00505 msg = 250;
00506 if (pct(20))
00507 msg = 262;
00508 if (pct(17))
00509 msg = 25;
00510 if (pct(14))
00511 msg = 345;
00512 if (pct(12))
00513 msg = 346;
00514 return (msg);
00515 }
00516
00517
00518
00519
00520 boolean opaque(obj)
00521 int obj;
00522 {
00523 return (bitset(g.obj_state[obj], 6));
00524 }
00525
00526
00527
00528
00529 boolean outside(loc)
00530 int loc;
00531 {
00532 return (bitset(g.loc_attrib[loc], 6));
00533 }
00534
00535
00536
00537
00538 int pct(x)
00539 int x;
00540 {
00541 return (ranz(100) < x);
00542 }
00543
00544
00545
00546
00547 boolean plural(obj)
00548 int obj;
00549 {
00550 return (bitset(g.obj_state[obj], 13));
00551 }
00552
00553
00554
00555
00556 boolean portal(loc)
00557 int loc;
00558 {
00559 return (bitset(g.loc_attrib[loc], 5));
00560 }
00561
00562
00563
00564
00565 boolean printed(obj)
00566 int obj;
00567 {
00568 return (bitset(g.obj_state[obj], 8));
00569 }
00570
00571
00572
00573
00574
00575
00576 int put(obj, where, pval)
00577 int obj, where, pval;
00578 {
00579 move(obj, where);
00580 return ((-1) - pval);
00581 }
00582
00583
00584
00585
00586 int ranz(range)
00587 int range;
00588 {
00589 return (rand() % range);
00590 }
00591
00592
00593
00594
00595 boolean small(obj)
00596 int obj;
00597 {
00598 return (bitset(g.obj_state[obj], 5));
00599 }
00600
00601
00602
00603
00604 int toting(item)
00605 int item;
00606 {
00607 boolean aaa, bbb, ccc;
00608 int contnr, outer, outer2;
00609
00610 contnr = -g.place[item];
00611 outer = -g.place[contnr];
00612 outer2 = -g.place[outer];
00613
00614 aaa = holding(contnr);
00615 bbb = enclosed(contnr) && holding(outer);
00616 ccc = enclosed(outer) && holding(outer2);
00617
00618 return (holding(item) || (enclosed(item) && (aaa || bbb || ccc)));
00619 }
00620
00621
00622
00623
00624 boolean treasr(obj)
00625 int obj;
00626 {
00627 return (bitset(g.obj_state[obj], 14));
00628 }
00629
00630
00631
00632
00633 boolean vessel(obj)
00634 int obj;
00635 {
00636 return (bitset(g.obj_state[obj], 15));
00637 }
00638
00639
00640
00641
00642 boolean wearng(item)
00643 int item;
00644 {
00645 return (bitset(g.obj_state[item], WEARBT));
00646 }
00647
00648
00649
00650
00651 boolean worn(obj)
00652 int obj;
00653 {
00654 return (bitset(g.obj_state[obj], 11));
00655 }
00656
00657 static char *e_msg[] = {
00658 "message line > 70 characters",
00659 "null line in message",
00660 "too many words of messages",
00661 "too many travel options",
00662 "too many vocabulary words",
00663 "required vocabulary word not found",
00664 "too many rtext or mtext messages",
00665 "too many hints",
00666 "location has loc_attrib bit being set twice",
00667 "invalid section number in database",
00668 "out of order locs or rspeak entries.",
00669 "illegal motion word in travel table",
00670 "** unused **.",
00671 "unknown or illegal word in adjective table.",
00672 "illegal word in prep/obj table",
00673 "too many entries in prep/obj table",
00674 "object has condition bit set twice",
00675 "object number too large",
00676 "too many entries in adjective/noun table.",
00677 "** unused **.",
00678 "special travel (500>l>300) exceeds goto list",
00679 "ran off end of vocabulary table",
00680 "verb class (n/1000) not between 1 and 3",
00681 "intransitive action verb exceeds goto list",
00682 "transitive action verb exceeds goto list",
00683 "conditional travel entry with no alternative",
00684 "location has no travel entries",
00685 "hint number exceeds goto list",
00686 "invalid month returned by date function",
00687 "action verb 'leave' has no object.",
00688 "preposition found in unexpected table",
00689 "received an unexpected word terminator from a1toa5",
00690 "trying to put a container into itself (tricky!)",
00691 "unknown word class in getwds",
00692 "** unused **.",
00693 "trying to carry a non-existent object"};
00694
00695
00696
00697
00698 void bug(n)
00699 unsigned int n;
00700 {
00701 if (n < 36 && *e_msg[n] != '*')
00702 fprintf(stderr, "Fatal error, probable cause: %s\n", e_msg[n]);
00703 else
00704 fprintf(stderr, "Fatal error number %d - Unused error number!\n", n);
00705 panic((char *) 0, TRUE);
00706 }
00707
00708
00709
00710
00711
00712
00713 char *
00714 ask(prompt, buf, buflen)
00715 char *prompt, *buf;
00716 int buflen;
00717 {
00718 fputs(prompt, stdout);
00719 fflush(stdout);
00720 if (!fgets(buf, buflen, stdin))
00721 panic("end of input", FALSE);
00722 if (*buf) {
00723 int c;
00724 char *end = buf + strlen(buf);
00725 if (end[-1] != '\n')
00726
00727 while ((c = getchar()) != '\n' && c != EOF);
00728 while (*buf && isspace(*buf))
00729 buf++;
00730 while (buf <= --end && isspace(*end))
00731 *end = '\0';
00732 }
00733 return buf;
00734 }
00735
00736
00737
00738
00739
00740 void panic(msg, save)
00741 char *msg;
00742 boolean save;
00743 {
00744 fprintf(stderr, "\nPANIC: %s%s\n",
00745 msg ? msg : "", save ? ". Save..." : msg ? "" : "aborting.");
00746 if (save)
00747 saveadv("advpanic.sav");
00748 exit(EXIT_FAILURE);
00749 }