home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume15 / dinkum2 / part06 / parse.c < prev   
C/C++ Source or Header  |  1993-01-27  |  17KB  |  834 lines

  1. #define PARSE
  2. #include "dink_sym.h"
  3. #include "dink_glb.h"
  4. #include <string.h>
  5.  
  6. void parse()
  7. /*********************************************************/
  8. /*                                                       */
  9. /*      --- English Language Parsing Subroutine ---      */
  10. /*                                                       */
  11. /*  This subroutine parses a sentence of up to nineteen  */
  12. /*  words and decodes the words into integers and passes */
  13. /*  a twenty element vector back to the calling          */
  14. /*  program.  The digit 0, implies an unused word.  The  */
  15. /*  digit -1 (V_LINE_END), indicates end of sentence.    */
  16. /*                                                       */
  17. /*      Program by Gary A. Allen, Jr.  17 December 1992  */
  18. /*        (c) Copyright 1992 by Gary A. Allen, Jr.       */
  19. /*                                                       */
  20. /*********************************************************/
  21. {
  22. #if (PROTOTYPE)
  23. char getche(void) ;
  24. int synonym(int) ;
  25. void purge(int, int*) ;
  26. #endif
  27.  
  28. register int i, j ;
  29.  
  30. int m, n, jacc, i_ws, sw_purge, j_purge, sw_loop, sw_decode ;
  31.  
  32. /* a sentence can have 19 words of 15 letters */ 
  33. char words[20][15], word[15] ;
  34. char letter, buffer[300], *pnt ;
  35.  
  36. /* flush the "sent vector" */
  37. for (i = 0; i <= 19; i++) sent[i] = 0 ;
  38.  
  39. /* flush the tag vector */
  40. for (i = 0; i <= tag_max; i++) tag[i] = FALSE ;
  41.  
  42. /* Outer infinite "for" loop to parse and load in the words */
  43. for(;;) {
  44.  
  45. /* Keyboard input "for" loop */
  46. for (i = 0; i <= 299; i++) {
  47.     if (sw_playing) {
  48.         if (feof(fp)) {
  49.             sw_playing = FALSE ;
  50.             continue ;
  51.         }
  52.         letter = fgetc(fp) ;
  53.         putchar(letter) ;
  54.     }
  55.     else {
  56. #ifndef __TURBOC__
  57.         letter = getchar() ;    
  58. #endif
  59. #ifdef __TURBOC__
  60.         letter = getche() ;    
  61. #endif
  62.         if (sw_recording) {
  63.             if ((letter == '\n') || (letter == 13)) {
  64.                 fprintf(fp,"\n") ;
  65.             }
  66.             else fputc(letter, fp) ;
  67.         }
  68.     }
  69.  
  70.     buffer[i] = letter ;
  71.  
  72.     /* First pass "switch" block */
  73.     switch(letter) {
  74.  
  75.     /* Carriage return */
  76.     case '\n':
  77.     case 13:
  78.         break ;
  79.  
  80.     /* Backspace */
  81.     case 8:
  82.         i -= 2 ;
  83.         if (i < 0) {
  84.             i = -1 ;
  85. #ifdef __TURBOC__
  86.             putchar(0x07) ; /* ring bell */
  87. /* "{" --- this is to balance the parenthesis below for Vi */
  88.         }
  89.         putchar(' ') ;
  90.         putchar(0x08) ;
  91. #endif
  92. #ifndef __TURBOC__
  93.         }
  94. #endif
  95.         continue ;
  96.  
  97.     default:
  98.         continue ;
  99.     } /* end of the first pass "switch" block */
  100.     break ;
  101. } /* end of keyboard input "for" loop */
  102.  
  103. /* Deal with goofy long strings */
  104. if (i > 299) {
  105.     printf("\n\nHuh? That last sentence was a long one!\n") ;
  106.     printf("Try making it a bit shorter.\n\n") ;
  107.     continue ;
  108. }
  109.  
  110. sw_loop = FALSE ;
  111. sw_decode = FALSE ;
  112. pnt = buffer ;
  113.  
  114. /* Outer word counting "for" loop */
  115. for (i = 0; i <= 18; i++) {
  116.     /* Inner letter counting "for" loop */
  117.     for (j = 0; j <= 14; j++) {
  118.         /* Letter type "switch" block */
  119.         switch (letter = *(pnt++)) {
  120.             case '\n':
  121.             case 13 :
  122.                 sw_loop = TRUE ;
  123.                 if ((i == 0) && (j == 0)) break ;
  124.                 words[i][j] = '\0' ;  
  125.                 sw_decode = TRUE ; 
  126.                 break ;
  127.  
  128.             /* White spaces and punctuation for cutting out words */
  129.             case '\"':
  130.             case ' ':
  131.             case ',':
  132.             case '.':
  133.             case ';':
  134.             case ':':
  135.             case '?':
  136.             case '!':
  137.             case '&':
  138.             case '{':
  139.             case '}':
  140.             case '[':
  141.             case ']':
  142.             case ')':
  143.             case '(':
  144.             case '\'':
  145.             case '`':
  146.             case '\t':
  147.                 words[i][j] = '\0' ;  
  148.                 break;
  149.  
  150.             default:
  151.                 words[i][j] = letter ;
  152.                 continue ;
  153.         } /* end of letter type "switch" block */
  154.         break ;
  155.     } /* end of inner letter counting "for" loop */
  156.     if (sw_loop) break ;
  157.     if (j > 14) {
  158. printf("\nYou're saying nonsense! Type the sentence again. \n");
  159.         break ;
  160.     }
  161.     if (j == 0) i-- ;
  162. } /* end of outer word counting "for" loop */
  163.  
  164. /* Bad sentence handling block */
  165. if (!sw_decode) {
  166.     if (sw_loop) continue ;
  167.  
  168.     if (i > 18) 
  169. printf ("\nYour sentence is too long. Type something shorter! \n") ;
  170.  
  171. #ifndef __TURBOC__
  172.     /* Purge the input buffer */
  173.     for (;;) if ('\n' == getchar()) break ;
  174. #endif
  175.  
  176.     continue ; /* resume the infinite "for" loop */
  177. } /* end of bad sentence handling block */
  178.  
  179. #ifdef __TURBOC__
  180. printf("\n") ;
  181. #endif
  182.  
  183. /* Decode the words from the known vocabulary */
  184. m = i ;
  185. jacc = 0;
  186. for (i = 0; i <= m; i++) {
  187.     for (j = 0; j <= 14; j++) {
  188.         word[j] = words[i][j] ; 
  189.     }
  190.     for (j = 0; j <= letmax; j++) {
  191.         n = strcmp (word,vocab[j]);
  192.         if (n == 0) {
  193.             if ((j > 9)&&(j < 20)) j -= 10;
  194.             sent[jacc++] = j+1 ;
  195.             break; 
  196.         }
  197.     }
  198. } /* end of vobaulary decode block */
  199.  
  200. if (jacc == 0) {
  201.     printf ("Nothing you said was understandable! Try again. \n");
  202.     continue ;
  203. }
  204.  
  205. /* mark last word */
  206. sent[jacc] = V_LINE_END ;
  207.  
  208. /* Check to see if this is a simple move command */
  209. if (sent[0] <= 10) {
  210.     tag[V_MOVE] = TRUE ;
  211.     tag[V_DIRECTION] = TRUE ;
  212.     verb = sent[0] ;
  213.     return ; 
  214. } /* end of the simple move block */
  215.  
  216. /* adjective and "in/out" preposition "for" loop */
  217. sw_purge = FALSE ;
  218. for (j = 0; j <= jacc-1; j++) {
  219.  
  220.     /* check for adjectives */
  221.     for (i = 0; i <= adj_max; i++) {
  222.         if (sent[j] == adjective[i][Aj_adj]) {
  223.  
  224.         /* Does a noun have to be ignored ? */
  225.         if ((adjective[i][Aj_adj_cmd] == F_ignore) &&
  226.             (adjective[i][Aj_trig_noun] != sent[j+1])) break ;
  227.  
  228.         /* Does a noun have to be replaced? */
  229.         if ((adjective[i][Aj_adj_cmd] == F_replace) &&
  230.             (adjective[i][Aj_trig_noun] == sent[j+1])) {
  231.                 sent[j+1] = adjective[i][Aj_act_noun] ;
  232.         }
  233.         sw_purge = TRUE ;
  234.         j_purge = j ;
  235.         }
  236.     } 
  237. } /* end of adjective and "in/out" preposition "for" loop */
  238.  
  239. /* purge processed adjective from sentence */
  240. if (sw_purge) purge(j_purge, &jacc) ;
  241.  
  242. /* Verb grammer check "for" loop */
  243. /* see if the sentence is of a command sentax */
  244. sw_loop = FALSE ;
  245. for (i = 0; i <= verb_max; i++) {
  246.     if (sent[0] == verb_table[i]) {
  247.         if (synonym(jacc)) {
  248.             sw_loop = TRUE ;
  249.             break ;
  250.         }
  251.         return ;
  252.     }
  253. } /* end of verb grammer check "for" loop */
  254. if (sw_loop) continue ;
  255.  
  256. /* First word is not a verb so check to see if this is a "question" sentence */
  257. for (i = 0; i <= quest_max; i++) {
  258.     if (sent[0] == quest[i]) {
  259.         /* shift the sentence over and load in "question" */ 
  260.         for (j = jacc; j >= 0; j--) sent[j+1] = sent[j] ;
  261.         sent[0] = V_QUESTION ;
  262.         tag[V_QUESTION] = TRUE ; 
  263.         if (++jacc == 2) {
  264.         /* Sentence is a one word command */
  265.             tag[V_VERB_ONLY] = TRUE ;
  266.             tag[sent[1]] = TRUE ;
  267.             verb = V_QUESTION ;
  268.             return ;
  269.         }
  270.         if (synonym(jacc)) {
  271.             sw_loop = TRUE ;
  272.             break ;
  273.         }
  274.         return ;
  275.     } 
  276. } /* end of first word not a verb so check if "question" block */
  277. if (sw_loop) continue ;
  278.  
  279. /* This is not a question and the first word is --not-- a verb. */
  280. /*     Therefore a verb is embedded and must be swapped in. */
  281. if (jacc != 1) for (j = 1; j <= jacc-1; j++) {
  282.     /* Check to see if the word is a move command */
  283.     if (sent[j] <= 10) {
  284.         tag[V_MOVE] = TRUE ;
  285.         i_ws = sent[0] ;
  286.         sent[0] = sent[j] ;
  287.         sent[j] = i_ws ;
  288.         if (synonym(jacc)) {
  289.             sw_loop = TRUE ;
  290.             break ;
  291.         }
  292.         return ;
  293.     } /* end of simple move command block */
  294.  
  295.     /* if not a move command then check the verb table */
  296.     for (i = 0; i <= verb_max; i++) {
  297.         if (sent[j] == verb_table[i]) {
  298.             i_ws = sent[0] ;
  299.             sent[0] = sent[j] ;
  300.             sent[j] = i_ws ;
  301.             if (synonym(jacc)) {
  302.                 sw_loop = TRUE ;
  303.                 break ;
  304.             }
  305.             return ;
  306.         }
  307.     }
  308.     if (sw_loop) break ;
  309. } /* end of verb is embedded and must be swapped in block */
  310. if (sw_loop) continue ;
  311.  
  312. /* Verb error routine */
  313. printf ("If there was a verb in that sentence, I didn't understand ") ;
  314. printf ("it.\n") ;
  315.  
  316. } /* end of outer most infinite "for" loop to parse in the words */
  317.  
  318. } /* --- end of "parse" subroutine --- */
  319.  
  320.  
  321. int synonym(jacc)
  322. /**************************************/
  323. /*                                    */
  324. /*         Synonym Function           */
  325. /*                                    */
  326. /* Version: Mk 1.0    6 December 1992 */
  327. /*                                    */
  328. /**************************************/
  329.  
  330. int jacc ;
  331.  
  332. {
  333. register int i, j ;
  334. int j_point ;
  335. int sw_movement, sw_adverb, sw_adverb_fnd ;
  336.  
  337. #if (PROTOTYPE)
  338. void purge(int, int*) ;
  339. #endif
  340.  
  341. /* prescan for verb connected movement commands */
  342. switch(sent[0]) { 
  343. case V_go:
  344. case V_move:
  345. case V_walk:
  346. case V_run:
  347. case V_jump:
  348. case V_bop:
  349. case V_hop:
  350. case V_stroll:
  351. case V_saunter:
  352. case V_swagger:
  353.     sw_movement = TRUE ;
  354.     break ;
  355. default:
  356.     sw_movement = FALSE ;
  357. }
  358.  
  359. /* adverb scan, sent[0] is the verb */
  360. sw_adverb = FALSE ;
  361. sw_adverb_fnd = FALSE ;
  362. for (i = 0; i <= adv_max; i++) {
  363.     for (j = 1; j <= jacc-1; j++) {
  364.         /* see if this is an adverb */
  365.         if (sent[j] == adverb[i][Av_adv]) {
  366.             j_point = j ;
  367.             sw_adverb = TRUE ;
  368.  
  369.             /* does the sentence have the companion verb? */
  370.             if (adverb[i][Av_verb_old] == sent[0]) {
  371.                 sent[0] = adverb[i][Av_verb_new] ;
  372.                 sw_adverb = FALSE ;
  373.                 sw_adverb_fnd = TRUE ;
  374.  
  375.             /* purge processed adverb from sentence */
  376.                 purge(j, &jacc) ;
  377.             }
  378.         }
  379.     }
  380. }
  381.  
  382. /* purge unprocessed adverb from sentence */
  383. if (sw_adverb && (!sw_movement)) purge(j_point, &jacc) ;
  384.  
  385. /* scan the sentence for the movement direction */
  386. if ((!sw_adverb_fnd) && sw_movement) {
  387.     for (j = 0; j <= jacc-1; j++) {
  388.         if (sent[j] <= 10) {
  389.             tag[V_MOVE] = TRUE ;
  390.             tag[V_DIRECTION] = TRUE ;
  391.             verb = sent[j] ;
  392.             return(FALSE) ;
  393.         }
  394.         if (sent[j] == V_LINE_END) break ;
  395.     }
  396.     printf("Where to?  In what direction?\n") ;
  397.     return(TRUE) ;
  398.  
  399. tag[sent[0]] = TRUE ;  /* activate the tag for the verb */
  400.  
  401. if (jacc == 1) {
  402. /* Sentence is a one word command */
  403.     tag[V_VERB_ONLY] = TRUE ;
  404.     verb = sent[0] ;
  405.     if (sent[0] <= 4) return(FALSE) ; /* first 5 elements are reserved */
  406.     return(FALSE) ;
  407. }
  408.  
  409. /* Load the "tag" matrix for detected words and synonyms */
  410. for (j = 1; j <= 19; j++) {
  411.     if (sent[j] == V_LINE_END) break ;
  412.     if (sent[j] <= 10) tag[V_DIRECTION] = TRUE ;
  413.     if (sent[j] <= 4) continue ; /* first 5 elements are reserved */
  414.     tag[sent[j]] = TRUE ;  /* activate an element for each word */
  415.  
  416.     /* Deal with synonym nouns */
  417.     switch(sent[j]) {
  418.  
  419.     case V_automatic:
  420.     case V_AUTO:
  421.         tag[V_auto] = TRUE ;
  422.         continue ;
  423.  
  424.     case V_bar:
  425.         tag[V_gold] = TRUE ;
  426.         continue ;
  427.  
  428.     case V_beer:
  429.     case V_fourex:
  430.     case V_Fourex:
  431.         tag[V_can] = TRUE ;
  432.         continue ;
  433.  
  434.     case V_cockroaches:
  435.         tag[V_PLURAL] = TRUE ;
  436.         tag[V_cockroach] = TRUE ;
  437.         continue ;
  438.  
  439.     case V_diamond:
  440.         tag[V_ring] = TRUE ;
  441.         continue ;
  442.  
  443.     case V_doormat:
  444.         tag[V_mat] = TRUE ;
  445.         continue ;
  446.  
  447.     case V_drop:
  448.         tag[V_bear] = TRUE ;
  449.         continue ;
  450.  
  451.     case V_everything:
  452.         tag[V_all] = TRUE ;
  453.         continue ;
  454.  
  455.     case V_lager:
  456.         tag[V_bottle] = TRUE ;
  457.         continue ;
  458.  
  459.     case V_fuze:
  460.     case V_fuse:
  461.         tag[V_cap] = TRUE ;
  462.         continue ;
  463.  
  464.     case V_gleeps:
  465.         tag[V_PLURAL] = TRUE ;
  466.         tag[V_gleep] = TRUE ;
  467.         continue ;
  468.  
  469.     case V_hoop:
  470.         tag[V_snake] = TRUE ;
  471.         continue ;
  472.  
  473.     case V_M16:
  474.     case V_m16:
  475.     case V_gun:
  476.         tag[V_rifle] = TRUE ;
  477.         continue ;
  478.  
  479.     case V_kangaroos:
  480.         tag[V_PLURAL] = TRUE ;
  481.         tag[V_kangaroo] = TRUE ;
  482.         continue ;
  483.  
  484.     case V_magazine:
  485.     case V_ammo:
  486.         tag[V_clip] = TRUE ;
  487.         continue ;
  488.  
  489.     case V_mail:
  490.     case V_envelope:
  491.         tag[V_letter] = TRUE ;
  492.         continue ;
  493.  
  494.     case V_matchbox:
  495.         tag[V_matches] = TRUE ;
  496.     case V_matches:
  497.         tag[V_PLURAL] = TRUE ;
  498.         tag[V_match] = TRUE ;
  499.         continue ;
  500.  
  501.     case V_Ned:
  502.     case V_kelly:
  503.     case V_Kelly:
  504.         tag[V_ned] = TRUE ;
  505.         continue ;
  506.  
  507.     case V_off_q:
  508.         tag[V_off] = TRUE ;
  509.         continue ;
  510.  
  511.     case V_on_q:
  512.         tag[V_on] = TRUE ;
  513.         continue ;
  514.  
  515.     case V_plan:
  516.         tag[V_map] = TRUE ;
  517.         continue ;
  518.  
  519.     case V_painting:
  520.         tag[V_picture] = TRUE ;
  521.         continue ;
  522.  
  523.     case V_picture:
  524.         tag[V_photo] = TRUE ;
  525.         continue ;
  526.  
  527.     case V_doors:
  528.         tag[V_PLURAL] = TRUE ;
  529.         tag[V_door] = TRUE ;
  530.         continue ;
  531.  
  532.     case V_pills:
  533.     case V_packet:
  534.         tag[V_PLURAL] = TRUE ;
  535.     case V_atropine:
  536.         tag[V_pill] = TRUE ;
  537.         continue ;
  538.  
  539.     case V_safety:
  540.     case V_SAFE:
  541.         tag[V_safe] = TRUE ;
  542.         continue ;
  543.  
  544.     case V_silver:
  545.         tag[V_coin] = TRUE ;
  546.         continue ;
  547.  
  548.     case V_spinifexes:
  549.         tag[V_PLURAL] = TRUE ;
  550.         tag[V_spinifex] = TRUE ;
  551.         continue ;
  552.  
  553.     case V_stick:
  554.         tag[V_dynamite] = TRUE ;
  555.         continue ;
  556.  
  557.     case V_switch:
  558.         tag[V_button] = TRUE ;
  559.         continue ;
  560.  
  561.     case V_treasure:
  562.         tag[V_all] = TRUE ;
  563.         continue ;
  564.  
  565.     case V_I:
  566.         tag[V_single] = TRUE ;
  567.         continue ;
  568.  
  569.     case V_III:
  570.         tag[V_triple] = TRUE ;
  571.         continue ;
  572.  
  573.     case V_zero:
  574.         tag[V_0] = TRUE ;
  575.         continue ;
  576.  
  577.     case V_forty_nine:
  578.         tag[V_49] = TRUE ;
  579.         continue ;
  580.  
  581.     case V_sixty_seven:
  582.         tag[V_67] = TRUE ;
  583.         continue ;
  584.  
  585.     case V_eighty_two:
  586.         tag[V_82] = TRUE ;
  587.         continue ;
  588.  
  589.     default:
  590.         continue ;
  591.     }
  592. } /* end of sentence tag word scan */
  593. verb = sent[0] ;
  594. return(FALSE) ;
  595.  
  596. } /* --- end of "synonym" subroutine --- */
  597.  
  598. void purge(k_start, k_finish)
  599. /***********************************/
  600. /*                                 */
  601. /*   Sentence Purging Subroutine   */
  602. /*                                 */
  603. /* Version: Mk 1.0  3 March 1990   */
  604. /*                                 */
  605. /***********************************/
  606.  
  607. int k_start, *k_finish ;
  608. {
  609. register int k ;
  610. int k_end ;
  611.  
  612. k_end = *k_finish ;
  613. for (k = k_start; k <= k_end-1; k++) sent[k] = sent[k+1] ;
  614. *k_finish = --k_end ;
  615. } /* --- end of "purge" subroutine --- */
  616.  
  617. void filler()
  618. /***********************************/
  619. /*                                 */
  620. /*        Looker Subroutine        */
  621. /*                                 */
  622. /* Version: Mk 1.0  18 August 1989 */
  623. /*                                 */
  624. /***********************************/
  625. {
  626.  
  627. if (tag[V_VERB_ONLY]) {
  628.     printf("Fill what?\n") ;
  629.     return ;
  630. }
  631. if (tag[V_can]) {
  632.     if (object[O_can][J_loc] != B_have) 
  633. printf("You don't have the Fourex can in your possession!\n") ;
  634. else printf("I can't do it!  There's a hole in the can's bottom.\n") ;
  635.     return ;
  636. }
  637. if (tag[V_bottle]) {
  638.     if (object[O_bottle][J_loc] != B_have) 
  639. printf("You don't have the bottle in your possession!\n") ;
  640. else printf("I can't do it!  The bottle has a crack in it's bottom.\n");
  641.     return ;
  642. }
  643. printf("I can't fill that!\n") ;
  644. } /* --- end of the "filler" subroutine --- */
  645.  
  646. void looker(n)
  647. /***********************************/
  648. /*                                 */
  649. /*        Looker Subroutine        */
  650. /*                                 */
  651. /* Version: Mk 1.0  18 August 1989 */
  652. /*                                 */
  653. /***********************************/
  654. int n ;
  655. {
  656. int m ;
  657.  
  658. #if (PROTOTYPE)
  659. void long_descp(int), describe(int), objlooker(int), gleeper(int) ;
  660. void actor(int), rdtxt(int) ;
  661. #endif
  662.  
  663. /* an isolated "look" means to just look at the room */
  664. if (tag[V_VERB_ONLY]) { 
  665.     /* Check for long description */
  666.     if ((room[n][M_rm_type] == T_was_long)||(n == R_lift_inside))
  667.        long_descp(n);
  668.     else describe (n) ;
  669.     objlooker(n) ; /* Check if there are objects in the room */
  670.     gleeper(n) ;   /* check for gleeps and update the gleep count */
  671.     /* describe unmovable action objects and status */
  672.     if (room[n][M_rm_type] == T_action_obj) actor(n) ;
  673.     return ;
  674. }
  675.  
  676. /* Gleep tank */
  677. if (tag[V_tank]) {
  678.     if (n == R_gleep_tank) {
  679. printf("You look inside the gleep tank and see a blue fluid which\n") ;
  680. printf("smells of chlorine") ;
  681.         if (gleep_score == 0) {
  682. printf(".\n") ;
  683.             return ;
  684.         }
  685.         if (gleep_score == 1) {
  686. printf(" and a single gleep submerged in the fluid.\n") ;
  687.             return ;
  688.         }
  689. printf(" and %d gleeps submerged in the fluid.\n",
  690.         gleep_score) ;
  691.         return ;
  692.     }
  693.     else {
  694.         printf("There is no gleep tank here!\n") ;
  695.         return ;
  696.     }
  697. }
  698.  
  699. /* wall safe */
  700. if (tag[V_safe]) {
  701.     if ((n == R_office_mang)&&
  702.         (room[R_office_mang][M_rm_status] >= S_revealed)) {
  703.         m = O_safe ;
  704.         rdtxt(m);
  705.     }
  706.     else printf("I see no safe here for me to describe.\n");
  707.     return ;
  708. }
  709.  
  710. for (;;) {
  711.     /* map from the manager's office */
  712.     if (tag[V_map]) {
  713.         m = O_map_frag ;
  714.         break ;
  715.     }
  716.  
  717.     /* Fourex can */
  718.     if (tag[V_can]) {
  719.         m = O_can ;
  720.         break ;
  721.     }
  722.  
  723.     /* recorder */
  724.     if (tag[V_recorder]) {
  725.         m = O_recorder ;
  726.         break ;
  727.     }
  728.  
  729.     /* Atropine pills */
  730.     if (tag[V_pill]) {
  731.         m = O_pills ;
  732.         break ;
  733.     }
  734.  
  735.     /* Qadaffi's letter bomb */
  736.     if (tag[V_letter]) {
  737.         m = O_letter ;
  738.         break ;
  739.     }
  740.  
  741.     /* paper from the safe */
  742.     if (tag[V_paper]) {
  743.          m = O_paper ;
  744.         break ;
  745.     }
  746.  
  747.     /* cube */            
  748.     if (tag[V_cube]) {
  749.         m = O_cube ;
  750.         break ;
  751.     }
  752.  
  753.     /* ammo clip */            
  754.     if (tag[V_clip]) {
  755.         m = O_clip ;
  756.         break ;
  757.     }
  758.  
  759.     /* orange clip */
  760.     if (tag[V_org_clip]) {
  761.         m = O_org_clip ;
  762.         break ;
  763.     }
  764.  
  765.     /* rifle */
  766.     if (tag[V_rifle]) {
  767.         m = O_rifle ;
  768.         break ;
  769.     }
  770.  
  771.     /* Semtex detector */
  772.     if (tag[V_detector]) {
  773.         m = O_detector ;
  774.         break ;
  775.     }
  776.  
  777.     /* Deal with unreadable objects */
  778.     printf("There is nothing more that I can describe about it.\n");
  779.     return ;
  780. } /* end of infinite for block */
  781.  
  782. if (object[m][J_loc] == B_have) rdtxt(m);
  783. else 
  784. printf("I can examine an object only if it is in my possession.\n");
  785.  
  786. } /* --- end of the "looker" subroutine --- */
  787.  
  788. void pass()
  789. /***********************************/
  790. /*                                 */
  791. /*        Password Subroutine      */
  792. /*                                 */
  793. /* Version: Mk 1.0  29 July 1989   */
  794. /*                                 */
  795. /***********************************/
  796. {
  797. register int i ;
  798. char chr ;
  799. static char *passwd = "2Xngootx7Ysd4Du9" ;
  800.  
  801. #if (PROTOTYPE)
  802. void exit(int);
  803. char getch(void) ;
  804. #endif
  805.  
  806. /* Request password */
  807. printf("Enter password:  ") ;
  808.  
  809. #ifndef __TURBOC__
  810. for (i = 2; i <= 7; i++) {
  811.     chr = getchar() ;
  812.     if (chr+i-1 != passwd[i]) exit(0) ;
  813. }    
  814. if (getchar() != '\n') exit(0) ;
  815. printf(".\n") ;  /* indicate that the password was accepted */
  816. #endif
  817.  
  818. #ifdef __TURBOC__
  819. for (i = 2; i <= 7; i++) {
  820.     chr = getch() ;
  821.     if (chr+i-1 != passwd[i]) { 
  822.         for (;;) if (getch() == 3) break ;
  823.         printf("\r                    \n") ;
  824.         exit(0) ;
  825.     }
  826. }
  827. printf("\r.                     \n") ;
  828. #endif
  829.  
  830. sw_wizard = TRUE ; /* toggle wizard switch */
  831.  
  832. } /* --- end of the "pass" subroutine */
  833.