home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 8 / amigaformatcd08.iso / screenplay / utilities / scott / source / source.lha / SCOTT_A.C < prev    next >
C/C++ Source or Header  |  1996-10-14  |  11KB  |  612 lines

  1. /*
  2.  *  ScottFree Revision 1.14b
  3.  *
  4.  *
  5.  *  This program is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU General Public License
  7.  *  as published by the Free Software Foundation; either version
  8.  *  2 of the License, or (at your option) any later version.
  9.  *
  10.  *
  11.  *  You must have an ANSI C compiler to build this program.
  12.  *
  13.  *  ===================================================================
  14.  *
  15.  *  Version History AMIGA:
  16.  *  Ver ,     Date,     Author, Comment
  17.  *  -------------------------------------------------------------------
  18.  *  1.0 , 28/07/96, Andreas Aumayr, First public release
  19.  *  1.1 , 30/08/96, Andreas Aumayr, Minor changes for new amiga.c
  20.  *  ___________________________________________________________________
  21.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <ctype.h>
  28. #include <stdarg.h>
  29. #include <time.h>
  30.  
  31. #include "Scott.h"
  32. #include "ansi.c"
  33. #include "amiga5.c"
  34.  
  35. void Fatal(char *x)
  36. {
  37.     sprintf(str_buf,"\n\n%s!\n",x);
  38.     WriteCON(str_buf);
  39.     Delay(200);
  40.     close_all();
  41.     exit(1);
  42. }
  43.  
  44. void put_choice(void)
  45. {
  46.     if (RESTART) OutBuf("\nDo you want to (R)estore, re(S)tart or (E)xit the game? ");
  47.     else OutBuf("\nDo you want to (R)estore or (E)xit the game? ");
  48.     cursor(TRUE);
  49. }
  50.  
  51. int RandomPercent(int n)
  52. {
  53.     unsigned int rv=rand()<<6;
  54.     rv=rv%100;
  55.     if(rv<n)
  56.         return(1);
  57.     return(0);
  58. }
  59.  
  60. int CountCarried()
  61. {
  62.     int ct=0;
  63.     int n=0;
  64.     while(ct<=GameHeader.NumItems)
  65.     {
  66.         if(Items[ct].Location==CARRIED)
  67.             n++;
  68.         ct++;
  69.     }
  70.     return(n);
  71. }
  72.  
  73. char *MapSynonym(char *word)
  74. {
  75.     int n=1;
  76.     char *tp;
  77.     static char lastword[16];   /* Last non synonym */
  78.     while(n<=GameHeader.NumWords)
  79.     {
  80.         tp=Nouns[n];
  81.         if(*tp=='*')
  82.             tp++;
  83.         else
  84.             strcpy(lastword,tp);
  85.         if(Strnicmp(word,tp,GameHeader.WordLength)==0)
  86.             return(lastword);
  87.         n++;
  88.     }
  89.     return(NULL);
  90. }
  91.  
  92. int MatchUpItem(char *text, int loc)
  93. {
  94.     char *word=MapSynonym(text);
  95.     int ct=0;
  96.  
  97.         if(word==NULL)
  98.         word=text;
  99.  
  100.         while(ct<=GameHeader.NumItems)
  101.     {
  102.         if(Items[ct].AutoGet && Items[ct].Location==loc &&
  103.             Strnicmp(Items[ct].AutoGet,word,GameHeader.WordLength)==0)
  104.             return(ct);
  105.         ct++;
  106.     }
  107.     return(-1);
  108. }
  109.  
  110. char *ReadString(FILE *f)
  111. {
  112.     char tmp[1024];
  113.     char *t;
  114.     int c,nc;
  115.     int ct=0;
  116. oops:   do
  117.     {
  118.         c=fgetc(f);
  119.     }
  120.     while(c!=EOF && isspace(c));
  121.     if(c!='"')
  122.     {
  123.         Fatal("Initial quote expected");
  124.     }
  125.     do
  126.     {
  127.         c=fgetc(f);
  128.         if(c==EOF)
  129.             Fatal("EOF in string");
  130.         if(c=='"')
  131.         {
  132.             nc=fgetc(f);
  133.             if(nc!='"')
  134.             {
  135.                 ungetc(nc,f);
  136.                 break;
  137.             }
  138.         }
  139.         if(c==0x60)
  140.             c='"'; /* pdd */
  141.         tmp[ct++]=c;
  142.     }
  143.     while(1);
  144.     tmp[ct]=0;
  145.     t=MemAlloc(ct+1);
  146.     memcpy(t,tmp,ct+1);
  147.     return(t);
  148. }
  149.  
  150. void Look()
  151. {
  152.     static char *ExitNames[6]=
  153.     {
  154.         "North","South","East","West","Up","Down"
  155.     };
  156.     Room *r;
  157.     int ct,f;
  158.     int pos;
  159.  
  160.     CON_handle = env_hdl;
  161.     clrscr();
  162.  
  163.     if((BitFlags&(1L<<DARKBIT)) && Items[LIGHT_SOURCE].Location!= CARRIED
  164.             && Items[LIGHT_SOURCE].Location!= MyLoc)
  165.     {
  166.         if(Options&YOUARE)
  167.             WriteCON("You can't see. It is too dark!\n");
  168.         else
  169.             WriteCON("I can't see. It is too dark!\n");
  170.         if (Options & TRS80_STYLE)
  171.             WriteCON(TRS80_LINE);
  172.         CON_handle = act_hdl;
  173.         return;
  174.     }
  175.     r=&Rooms[MyLoc];
  176.     if(*r->Text=='*') {
  177.         sprintf(str_buf,"%s\n",r->Text+1);
  178.         WriteCON(str_buf);
  179.     }
  180.     else
  181.     {
  182.         if(Options&YOUARE) {
  183.             sprintf(str_buf,"You are %s\n",r->Text);
  184.             WriteCON(str_buf);
  185.         }
  186.         else {
  187.             sprintf(str_buf,"I'm in a %s\n",r->Text);
  188.             WriteCON(str_buf);
  189.         }
  190.     }
  191.     ct=0;
  192.     f=0;
  193.     WriteCON("\nObvious exits: ");
  194.     while(ct<6)
  195.     {
  196.         if(r->Exits[ct]!=0)
  197.         {
  198.             if(f==0)
  199.                 f=1;
  200.             else
  201.                 WriteCON(", ");
  202.             WriteCON(ExitNames[ct]);
  203.         }
  204.         ct++;
  205.     }
  206.     if(f==0)
  207.         WriteCON("none");
  208.     WriteCON(".\n");
  209.     ct=0;
  210.     f=0;
  211.     pos=0;
  212.     while(ct<=GameHeader.NumItems)
  213.     {
  214.         if(Items[ct].Location==MyLoc)
  215.         {
  216.             if(f==0)
  217.             {
  218.                 if(Options&YOUARE)
  219.                     WriteCON("\nYou can also see: ");
  220.                 else
  221.                     WriteCON("\nI can also see: ");
  222.                 pos=16;
  223.                 f++;
  224.             }
  225.             else if (!(Options & TRS80_STYLE))
  226.             {
  227.                 WriteCON(" - ");
  228.                 pos+=3;
  229.             }
  230.             if(pos+strlen(Items[ct].Text)>(Width-10))
  231.             {
  232.                 pos=0;
  233.                 WriteCON("\n");
  234.             }
  235.             WriteCON(Items[ct].Text);
  236.             pos += strlen(Items[ct].Text);
  237.             if (Options & TRS80_STYLE)
  238.             {
  239.                 WriteCON(". ");
  240.                 pos+=2;
  241.             }
  242.         }
  243.         ct++;
  244.     }
  245.     if (Options & TRS80_STYLE) {
  246.         //WriteCON("\n");
  247.         WriteCON(TRS80_LINE);
  248.     }
  249.     CON_handle = act_hdl;
  250. }
  251.  
  252. void LoadDatabase(FILE *f, int loud)
  253. {
  254.     char buf[32];
  255.     int ni,na,nw,nr,mc,pr,tr,wl,lt,mn,trm;
  256.     int ct;
  257.     short lo;
  258.     Action *ap;
  259.     Room *rp;
  260.     Item *ip;
  261. /* Load the header */
  262.  
  263.     if(fscanf(f,"%*d %d %d %d %d %d %d %d %d %d %d %d",
  264.         &ni,&na,&nw,&nr,&mc,&pr,&tr,&wl,<,&mn,&trm,&ct)<10)
  265.         Fatal("Invalid database(bad header)");
  266.     GameHeader.NumItems=ni;
  267.     Items=(Item *)MemAlloc(sizeof(Item)*(ni+1));
  268.     GameHeader.NumActions=na;
  269.     Actions=(Action *)MemAlloc(sizeof(Action)*(na+1));
  270.     GameHeader.NumWords=nw;
  271.     GameHeader.WordLength=wl;
  272.     Verbs=(char **)MemAlloc(sizeof(char *)*(nw+1));
  273.     Nouns=(char **)MemAlloc(sizeof(char *)*(nw+1));
  274.     GameHeader.NumRooms=nr;
  275.     Rooms=(Room *)MemAlloc(sizeof(Room)*(nr+1));
  276.     GameHeader.MaxCarry=mc;
  277.     GameHeader.PlayerRoom=pr;
  278.     GameHeader.Treasures=tr;
  279.     GameHeader.LightTime=lt;
  280.     LightRefill=lt;
  281.     GameHeader.NumMessages=mn;
  282.     Messages=(char **)MemAlloc(sizeof(char *)*(mn+1));
  283.     GameHeader.TreasureRoom=trm;
  284.  
  285. /* Load the actions */
  286.  
  287.     ct=0;
  288.     ap=Actions;
  289.     if(loud)
  290.         printf("Reading %d actions.\n",na);
  291.     sprintf(buf,"Actions: %d\n",na);
  292.     strcat(GameInfoStr,buf);
  293.     while(ct<na+1)
  294.     {
  295.         if(fscanf(f,"%hd %hd %hd %hd %hd %hd %hd %hd",
  296.             &ap->Vocab,
  297.             &ap->Condition[0],
  298.             &ap->Condition[1],
  299.             &ap->Condition[2],
  300.             &ap->Condition[3],
  301.             &ap->Condition[4],
  302.             &ap->Action[0],
  303.             &ap->Action[1])!=8)
  304.         {
  305.             printf("Bad action line (%d)\n",ct);
  306.             exit(1);
  307.         }
  308.         ap++;
  309.         ct++;
  310.     }
  311.     ct=0;
  312.     if(loud)
  313.         printf("Reading %d word pairs.\n",nw);
  314.     sprintf(buf,"Word Pairs: %d\n",nw);
  315.     strcat(GameInfoStr,buf);
  316.     while(ct<nw+1)
  317.     {
  318.         Verbs[ct]=ReadString(f);
  319.         Nouns[ct]=ReadString(f);
  320.         ct++;
  321.     }
  322.     ct=0;
  323.     rp=Rooms;
  324.     if(loud)
  325.         printf("Reading %d rooms.\n",nr);
  326.     sprintf(buf,"Rooms: %d\n",nr);
  327.     strcat(GameInfoStr,buf);
  328.     while(ct<nr+1)
  329.     {
  330.         fscanf(f,"%hd %hd %hd %hd %hd %hd",
  331.             &rp->Exits[0],&rp->Exits[1],&rp->Exits[2],
  332.             &rp->Exits[3],&rp->Exits[4],&rp->Exits[5]);
  333.         rp->Text=ReadString(f);
  334.         ct++;
  335.         rp++;
  336.     }
  337.     ct=0;
  338.     if(loud)
  339.         printf("Reading %d messages.\n",mn);
  340.     sprintf(buf,"Messages: %d\n",mn);
  341.     strcat(GameInfoStr,buf);
  342.     while(ct<mn+1)
  343.     {
  344.         Messages[ct]=ReadString(f);
  345.         ct++;
  346.     }
  347.     ct=0;
  348.     if(loud)
  349.         printf("Reading %d items.\n",ni);
  350.     sprintf(buf,"Items: %d\n",ni);
  351.     strcat(GameInfoStr,buf);
  352.     ip=Items;
  353.     while(ct<ni+1)
  354.     {
  355.         ip->Text=ReadString(f);
  356.         ip->AutoGet=strchr(ip->Text,'/');
  357.         /* Some games use // to mean no auto get/drop word! */
  358.         if(ip->AutoGet && strcmp(ip->AutoGet,"//") && strcmp(ip->AutoGet,"/*"))
  359.         {
  360.             char *t;
  361.             *ip->AutoGet++=0;
  362.             t=strchr(ip->AutoGet,'/');
  363.             if(t!=NULL)
  364.                 *t=0;
  365.         }
  366.         fscanf(f,"%hd",&lo);
  367.         ip->Location=(unsigned char)lo;
  368.         ip->InitialLoc=ip->Location;
  369.         ip++;
  370.         ct++;
  371.     }
  372.     ct=0;
  373.     /* Discard Comment Strings */
  374.     while(ct<na+1)
  375.     {
  376.         free(ReadString(f));
  377.         ct++;
  378.     }
  379.     fscanf(f,"%d",&ct);
  380.     if(loud)
  381.         printf("Version %d.%02d of Adventure ",ct/100,ct%100);
  382.     sprintf(buf,"Version: %d.%02d\n",ct/100,ct%100);
  383.     strcat(GameInfoStr,buf);
  384.     fscanf(f,"%d",&ct);
  385.     if(loud)
  386.         printf("%d.\nLoad Complete.\n\n",ct);
  387.     sprintf(buf,"Game Nr.: %2d",ct);
  388.     strcat(GameInfoStr,buf);
  389. }
  390.  
  391. int OutputPos=0;
  392.  
  393. void OutReset()
  394. {
  395.     OutputPos=0;
  396.     gotoxy(1,BottomHeight);
  397.     clreol();
  398. }
  399.  
  400. void NextLine()
  401. {
  402.     WriteCON("\n");
  403.     OutReset();
  404. }
  405.  
  406. /*
  407. void NextLine()
  408. {
  409.     OutputPos=0;
  410.     gotoxy(1,BottomHeight);
  411.     WriteCON("\n");
  412.     clreol();
  413. }
  414. */
  415.  
  416. void OutBuf(char *buffer)
  417. {
  418.     char word[80];
  419.     int wp,len;
  420.  
  421.     len = strlen(buffer);
  422.     while(*buffer)
  423.     {
  424.         if(OutputPos==0)
  425.         {
  426.             while(*buffer && isspace(*buffer))
  427.             {
  428.                 if (*buffer=='\n') NextLine();
  429.                 buffer++;
  430.             }
  431.         }
  432.         if(*buffer==0) {
  433.             return;
  434.         }
  435.         wp=0;
  436.         while(*buffer && ((!isspace(*buffer)) || (*(buffer-1) == '*') || (*(buffer+1) == '*')))
  437.         {
  438.             word[wp++]=*buffer++;
  439.         }
  440.         word[wp]=0;
  441.         //printf("Word '%s' at %d\n",word,OutputPos);
  442.         //if ((OutputPos + strlen(word) > Width - 1) && (*word != '.')) NextLine();
  443.         if (((OutputPos + strlen(word) > Width - 2)  && (*word != '.') && (len <= Width)) || (OutputPos == Width)) NextLine();
  444.         else gotoxy(OutputPos+1,BottomHeight);
  445.         WriteCON(word);
  446.         OutputPos+=strlen(word);
  447.         if (OutputPos >= Width) OutputPos = OutputPos - Width;
  448.  
  449.         if(*buffer==0) {
  450.             return;
  451.         }
  452.  
  453.         if (*buffer=='\n') NextLine();
  454.         else
  455.         {
  456.             OutputPos++;
  457.             if(OutputPos < (Width-1))
  458.                 WriteCON(" ");
  459.         }
  460.         buffer++;
  461.     }
  462. }
  463.  
  464. void Output(char *a)
  465. {
  466.     char block[512];
  467.     strcpy(block,a);
  468.     OutBuf(block);
  469. }
  470.  
  471. void OutputNumber(int a)
  472. {
  473.     char buf[16];
  474.     sprintf(buf,"%d ",a);
  475.     OutBuf(buf);
  476. }
  477.  
  478. void GetInput(int *vb, int *no)
  479. {
  480.     char buf[256];
  481.     char verb[10],noun[10];
  482.     int vc,nc;
  483.     int num;
  484.  
  485.     do
  486.     {
  487.         do
  488.         {
  489.             Output("\nTell me what to do ? ");
  490.             cursor(TRUE);
  491.             LineInput2(buf);
  492.             cursor(FALSE);
  493.             OutReset();
  494.             num=sscanf(buf,"%9s %9s",verb,noun);
  495.         }
  496.         while(num==0||*buf=='\n'||*buf==0);
  497.         //printf("%d, %s, %s\n",num,verb,noun);
  498.         if(num==1)
  499.             *noun=0;
  500.         if(*noun==0 && strlen(verb)==1)
  501.         {
  502.             switch(isupper(*verb)?tolower(*verb):*verb)
  503.             {
  504.                 case 'n':strcpy(verb,"NORTH");break;
  505.                 case 'e':strcpy(verb,"EAST");break;
  506.                 case 's':strcpy(verb,"SOUTH");break;
  507.                 case 'w':strcpy(verb,"WEST");break;
  508.                 case 'u':strcpy(verb,"UP");break;
  509.                 case 'd':strcpy(verb,"DOWN");break;
  510.                 /* Brian Howarth interpreter also supports this */
  511.                 case 'i':strcpy(verb,"INVENTORY");break;
  512.                 /* AMIGA interpreter extension */
  513.                 case 'l':strcpy(verb,"LOOK");break;
  514.             }
  515.         }
  516.         nc=WhichWord(verb,Nouns);
  517.         /* The Scott Adams system has a hack to avoid typing 'go' */
  518.         if(nc>=1 && nc <=6)
  519.         {
  520.             vc=1;
  521.         }
  522.         else
  523.         {
  524.             vc=WhichWord(verb,Verbs);
  525.             nc=WhichWord(noun,Nouns);
  526.         }
  527.         *vb=vc;
  528.         *no=nc;
  529.         if(vc==-1)
  530.         {
  531.             Output("\"");
  532.             Output(verb);
  533.             Output("\" is a word I don't know...sorry!\n");
  534.         }
  535.     }
  536.     while(vc==-1);
  537.     strcpy(NounText,noun);  /* Needed by GET/DROP hack */
  538. }
  539.  
  540. void SaveGame(void)
  541. {
  542.     FILE *f;
  543.  
  544.     if (Open_ASL(save_game,save_dir,1) == FALSE) {
  545.         Output("Save game canceled.\n");
  546.         return;
  547.     }
  548.     Make_FFP(save_game,save_dir);
  549.     f=fopen(FFP,"w");
  550.     if(f==NULL)
  551.     {
  552.         sprintf(str_buf,"Unable to create save file '%s'.\n",FFP);
  553.         Output(str_buf);
  554.         return;
  555.     }
  556.     SaveBody(f);
  557.     sprintf(str_buf,"Saved '%s'.\n",FFP);
  558.     Output(str_buf);
  559.     return;
  560. }
  561.  
  562. BOOL LoadGame(char *name)
  563. {
  564.     FILE *f=fopen(name,"r");
  565.  
  566.     if(f==NULL)
  567.     {
  568.         sprintf(str_buf,"Unable to restore game '%s'.\n\n",name);
  569.         Output(str_buf);
  570.         return(TRUE);
  571.     }
  572.     LoadBody(f);
  573.     sprintf(str_buf,"Restored '%s'.\n",name);
  574.     Output(str_buf);
  575.     return(FALSE);
  576. }
  577.  
  578. BOOL RestoreGame()
  579. {
  580.     if (Open_ASL(save_game,save_dir,0) == FALSE) return(TRUE);
  581.     Make_FFP(save_game,save_dir);
  582.     return(LoadGame(FFP));
  583. }
  584.  
  585. int WhichWord(char *word, char **list)
  586. {
  587.     int n=1;
  588.     int ne=1;
  589.     char *tp;
  590.  
  591.     /* quick & dirty workaround for missing feature 'RESTORE'
  592.        no more need for quit/restart game. */
  593.     if(Strnicmp(word,"!RESTORE",GameHeader.WordLength)==0) {
  594.         RestoreGame();
  595.         strcpy(word,"LOOK");
  596.     }
  597.  
  598.     while(ne<=GameHeader.NumWords)
  599.     {
  600.         tp=list[ne];
  601.         if(*tp=='*')
  602.             tp++;
  603.         else
  604.             n=ne;
  605.         if(Strnicmp(word,tp,GameHeader.WordLength)==0)
  606.             return(n);
  607.         ne++;
  608.     }
  609.     return(-1);
  610. }
  611.  
  612.