home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / games / spl / src / splbook.cpp < prev    next >
C/C++ Source or Header  |  1993-08-10  |  19KB  |  697 lines

  1. /* spellbook.cpp: routines for spell and spellbook manipulation
  2.  
  3.     Copyright (C) 1993 John-Marc Chandonia
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include "splbook.hpp"
  24. #include "general.hpp"
  25.  
  26. // get a spell description from the appropriate file
  27. void spell::get_desc() {
  28.     char buffer[256];
  29.     FILE *infile;
  30.     int lenname=strlen(name);
  31.     
  32.     // figure out what file the spell will be in
  33.     sprintf(buffer,"%c%d",type,level);
  34.     
  35.     if ((infile=fopen(buffer,"r"))==NULL)
  36.     return;
  37.     
  38.     do {
  39.     fgets(buffer,256,infile);
  40.     } while (strncmp(buffer,name,lenname) && !feof(infile));
  41.     
  42.     if (feof(infile)) {
  43.     fclose(infile);
  44.     return;
  45.     }
  46.     
  47.     do {
  48.     fgets(buffer,256,infile);
  49.     } while (!feof(infile) && strncmp(buffer,"Sav",3));
  50.     
  51.     if (feof(infile)) {
  52.     fclose(infile);
  53.     return;
  54.     }
  55.     
  56.     fgets(buffer,256,infile);
  57.     fgets(buffer,256,infile);
  58.     
  59.     while (strncmp(buffer,"-----",5)==0) {
  60.     add_desc(buffer);
  61.     fgets(buffer,256,infile);
  62.     }
  63.     
  64.     fclose(infile);
  65. }
  66.  
  67. // kill off a spell's description
  68. void spell::kill_desc() {
  69.     int i;
  70.     
  71.     for (i=0; i<lines; i++)
  72.     delete(description[i]);
  73.     lines=0;
  74. }
  75.  
  76. // search for a string in the description
  77. // if ignore_case, have string in upper case to save time!
  78. boolean spell::desc_search(char *str, boolean ignore_case) {
  79.     int i;
  80.     char *tmpstr;
  81.  
  82.     if (ignore_case) {
  83.     for (i=0; i<lines; i++) {
  84.         tmpstr=strdup(description[i]);
  85.         upstr(tmpstr);
  86.         if (strstr(tmpstr,str)!=0) return(true);
  87.     }
  88.     }
  89.     else for (i=0; i<lines; i++)
  90.     if (strstr(description[i],str)!=0) return(true);
  91.    
  92.     return(false);
  93. }
  94.  
  95. spell::spell() {
  96.     name=source=range=area=NULL;
  97.     type=' ';
  98.     level=lines=0;
  99. }
  100.  
  101. spell::~spell() {
  102.     delete(name);
  103.     delete(source);
  104.     delete(range);
  105.     delete(area);
  106.     for (int i=0; i<lines; i++)
  107.     delete(description[i]);
  108. }
  109.  
  110. void spell::add_desc(char *x) {
  111.     if (lines>255) return;
  112.  
  113.     // kluge to remove " " as a description... take out space.
  114.     if ((strlen(x)==2) && (x[0]==' ')) {
  115.     description[lines]=new char[strlen(x)];
  116.     strcpy(description[lines++],x+1);
  117.     }
  118.     else {
  119.     description[lines]=new char[strlen(x)+1];
  120.     strcpy(description[lines++],x);
  121.     }
  122. }
  123.  
  124. magespell::magespell() {
  125.     school=components=duration=casttime=save=NULL;
  126.     reversible=false;
  127.     type='M';
  128. };
  129.  
  130. magespell::~magespell() {
  131.     delete(school);
  132.     delete(components);
  133.     delete(duration);
  134.     delete(casttime);
  135.     delete(save);
  136. };
  137.  
  138. void magespell::print_stats() {
  139.     printf("%s (%s)\r\n",name,school);
  140.     if (reversible) printf("Reversible\r\n");
  141.     printf("  from %s\r\n",source);
  142.     printf("Range: %s\r\n",range);
  143.     printf("Components: %s\r\n",components);
  144.     printf("Duration: %s\r\n",duration);
  145.     printf("Casting Time: %s\r\n",casttime);
  146.     printf("Area of Effect: %s\r\n",area);
  147.     printf("Saving Throw: %s\r\n",save);
  148. }
  149.  
  150. void magespell::f_print(FILE *outfile) {
  151.     fprintf(outfile,"%s (%s)\n",name,school);
  152.     if (reversible) fprintf(outfile,"Reversible\n");
  153.     if (source) fprintf(outfile,"  from %s\n",source);
  154.     if (level) fprintf(outfile,"Level: %d\n",level);
  155.     if (range) fprintf(outfile,"Range: %s\n",range);
  156.     if (components) fprintf(outfile,"Components: %s\n",components);
  157.     if (duration) fprintf(outfile,"Duration: %s\n",duration);
  158.     if (casttime) fprintf(outfile,"Casting Time: %s\n",casttime);
  159.     if (area) fprintf(outfile,"Area of Effect: %s\n",area);
  160.     if (save) fprintf(outfile,"Saving Throw: %s\n",save);
  161.     fprintf(outfile,"\n");
  162.     for (int i=0; i<lines; i++)
  163.     fprintf(outfile,"%s\n",description[i]);
  164. }
  165.  
  166. void magespell::s_print(char *buffer) {
  167.     int i;
  168.  
  169.     sprintf(buffer,"%s (%s)\n",name,school);
  170.     i=strlen(buffer);
  171.     if (reversible) sprintf(buffer+i,"Reversible\n");
  172.     i=strlen(buffer);
  173.     if (source) sprintf(buffer+i,"  from %s\n",source);
  174.     i=strlen(buffer);
  175.     if (level) sprintf(buffer+i,"Level: %d\n",level);
  176.     i=strlen(buffer);
  177.     if (range) sprintf(buffer+i,"Range: %s\n",range);
  178.     i=strlen(buffer);
  179.     if (components) sprintf(buffer+i,"Components: %s\n",components);
  180.     i=strlen(buffer);
  181.     if (duration) sprintf(buffer+i,"Duration: %s\n",duration);
  182.     i=strlen(buffer);
  183.     if (casttime) sprintf(buffer+i,"Casting Time: %s\n",casttime);
  184.     i=strlen(buffer);
  185.     if (area) sprintf(buffer+i,"Area of Effect: %s\n",area);
  186.     i=strlen(buffer);
  187.     if (save) sprintf(buffer+i,"Saving Throw: %s\n",save);
  188.     i=strlen(buffer);
  189.     sprintf(buffer+i," \n");
  190.     i=strlen(buffer);
  191.     for (int j=0; j<lines; j++) {
  192.     if ((strlen(description[j])==0) || 
  193.         ((strlen(description[j])==1) && (description[j][0]==' '))) 
  194.         sprintf(buffer+i," \n");
  195.     else {
  196.         sprintf(buffer+i,"%s ",description[j]);
  197.         i=strlen(buffer);
  198.         if ((j<lines-1) && 
  199.         ((description[j+1][0]==' ') || 
  200.          (strlen(description[j+1])<2) ||
  201.          (description[j+1][0]=='\t')))
  202.         sprintf(buffer+i," \n");
  203.     }
  204.     i=strlen(buffer);
  205.     }
  206. }
  207.  
  208. void magespell::f_print_header(FILE *outfile) {
  209.     fprintf(outfile,"%17.17s ",name);
  210.     if (reversible) fprintf(outfile,"(R) ");
  211.     else fprintf(outfile,"    ");
  212.     fprintf(outfile,"%5.5s ",casttime);
  213.     fprintf(outfile,"%7.7s ",components);
  214.     fprintf(outfile,"%15.15s ",range);
  215.     fprintf(outfile,"%15.15s ",duration);
  216.     fprintf(outfile,"%15.15s ",area);
  217.     fprintf(outfile,"%4.4s ",save);
  218.     fprintf(outfile,"\n");
  219. }
  220.  
  221. void magespell::f_read(FILE *infile) {
  222.     char buffer[256];
  223.     
  224.     do {
  225.     fgets(buffer,256,infile);
  226.     } while ((strlen(buffer)<=1) && !feof(infile));
  227.     if (feof(infile)) return;
  228.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  229.  
  230.     char *l=strrchr(buffer,'(');
  231.     char *m=strrchr(buffer,')');
  232.     if ((m==NULL) || (l==NULL))
  233.     name = strdup(buffer);
  234.     else {
  235.     int namelen=strlen(buffer)-strlen(l);
  236.     name=new char[namelen];
  237.     name[namelen-1]=(char)0;
  238.     strncpy(name,buffer,namelen-1);
  239.     int schoollen=strlen(l)-strlen(m);
  240.     school=new char[schoollen];
  241.     school[schoollen-1]=(char)0;
  242.     strncpy(school,l+1,schoollen-1);
  243.     }
  244.     fgets(buffer,256,infile);
  245.     if (strncmp(buffer,"Reversible",10)==0) {
  246.     reversible=true;
  247.     fgets(buffer,256,infile);
  248.     }
  249.     while ((strlen(buffer)>2) && !feof(infile)) {
  250.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  251.     
  252.     if (strstr(buffer,"Range:"))
  253.         range=strdup(buffer+7);
  254.     else if (strstr(buffer,"Components:"))
  255.         components=strdup(buffer+12);
  256.     else if (strstr(buffer,"Duration:"))
  257.         duration=strdup(buffer+10);
  258.     else if (strstr(buffer,"Casting Time:"))
  259.         casttime=strdup(buffer+14);
  260.     else if (strstr(buffer,"Area of Effect:"))
  261.         area=strdup(buffer+16);
  262.     else if (strstr(buffer,"Saving Throw:"))
  263.         save=strdup(buffer+14);
  264.     else if (strstr(buffer,"School:"))
  265.         school=strdup(buffer+8);
  266.     else if (strstr(buffer,"  from "))
  267.         source=strdup(buffer+7);
  268.     else if (strstr(buffer,"Level:"))
  269.         sscanf(buffer+7,"%d",&level);
  270.     
  271.     fgets(buffer,256,infile);
  272.     }
  273.     fgets(buffer,256,infile);
  274.     while ((strncmp(buffer,"-----",5)!=0) && !feof(infile)) {
  275.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  276.     add_desc(buffer);
  277.     fgets(buffer,256,infile);
  278.     }
  279. }
  280.  
  281. priestspell::priestspell() {
  282.     sphere=NULL;
  283.     type='P';
  284. };
  285.  
  286. priestspell::~priestspell() {
  287.     delete(sphere);
  288. };
  289.  
  290. void priestspell::print_stats() {
  291.     printf("%s (%s)\r\n",name,school);
  292.     if (reversible) printf("Reversible\r\n");
  293.     printf("  from %s\r\n",source);
  294.     printf("Sphere: %s\r\n",sphere);
  295.     printf("Range: %s\r\n",range);
  296.     printf("Components: %s\r\n",components);
  297.     printf("Duration: %s\r\n",duration);
  298.     printf("Casting Time: %s\r\n",casttime);
  299.     printf("Area of Effect: %s\r\n",area);
  300.     printf("Saving Throw: %s\r\n",save);
  301. }
  302.  
  303. void priestspell::f_print(FILE *outfile) {
  304.     fprintf(outfile,"%s (%s)\n",name,school);
  305.     if (reversible) fprintf(outfile,"Reversible\n");
  306.     fprintf(outfile,"  from %s\n",source);
  307.     fprintf(outfile,"Sphere:  %s\n",sphere);
  308.     fprintf(outfile,"Range: %s\n",range);
  309.     fprintf(outfile,"Components: %s\n",components);
  310.     fprintf(outfile,"Duration: %s\n",duration);
  311.     fprintf(outfile,"Casting Time: %s\n",casttime);
  312.     fprintf(outfile,"Area of Effect: %s\n",area);
  313.     fprintf(outfile,"Saving Throw: %s\n\n",save);
  314.     for (int i=0; i<lines; i++)
  315.     fprintf(outfile,"%s\n",description[i]);
  316. }
  317.  
  318. void priestspell::s_print(char *buffer) {
  319.     int i;
  320.  
  321.     sprintf(buffer,"%s (%s)\n",name,school);
  322.     i=strlen(buffer);
  323.     if (reversible) sprintf(buffer+i,"Reversible\n");
  324.     i=strlen(buffer);
  325.     if (source) sprintf(buffer+i,"  from %s\n",source);
  326.     i=strlen(buffer);
  327.     if (level) sprintf(buffer+i,"Level: %d\n",level);
  328.     i=strlen(buffer);
  329.     if (sphere) sprintf(buffer+i,"Sphere: %s\n",sphere);
  330.     i=strlen(buffer);
  331.     if (range) sprintf(buffer+i,"Range: %s\n",range);
  332.     i=strlen(buffer);
  333.     if (components) sprintf(buffer+i,"Components: %s\n",components);
  334.     i=strlen(buffer);
  335.     if (duration) sprintf(buffer+i,"Duration: %s\n",duration);
  336.     i=strlen(buffer);
  337.     if (casttime) sprintf(buffer+i,"Casting Time: %s\n",casttime);
  338.     i=strlen(buffer);
  339.     if (area) sprintf(buffer+i,"Area of Effect: %s\n",area);
  340.     i=strlen(buffer);
  341.     if (save) sprintf(buffer+i,"Saving Throw: %s\n",save);
  342.     i=strlen(buffer);
  343.     sprintf(buffer+i," \n");
  344.     i=strlen(buffer);
  345.     for (int j=0; j<lines; j++) {
  346.     if ((strlen(description[j])==0) || 
  347.         ((strlen(description[j])==1) && (description[j][0]==' '))) 
  348.         sprintf(buffer+i," \n");
  349.     else {
  350.         sprintf(buffer+i,"%s ",description[j]);
  351.         i=strlen(buffer);
  352.         if ((j<lines-1) && 
  353.         ((description[j+1][0]==' ') || 
  354.          (strlen(description[j+1])<2) ||
  355.          (description[j+1][0]=='\t')))
  356.         sprintf(buffer+i," \n");
  357.     }
  358.     i=strlen(buffer);
  359.     }
  360. }
  361.  
  362. void priestspell::f_print_header(FILE *outfile) {
  363.     fprintf(outfile,"%17.17s ",name);
  364.     if (reversible) fprintf(outfile,"(R) ");
  365.     else fprintf(outfile,"    ");
  366.     fprintf(outfile,"15.15s ",school);
  367.     fprintf(outfile,"%5.5s ",casttime);
  368.     fprintf(outfile,"%7.7s ",components);
  369.     fprintf(outfile,"%15.15s ",range);
  370.     fprintf(outfile,"%15.15s ",duration);
  371.     fprintf(outfile,"%15.15s ",area);
  372.     fprintf(outfile,"%4.4s ",save);
  373.     fprintf(outfile,"\n");
  374. }
  375.  
  376. void priestspell::f_read(FILE *infile) {
  377.     char buffer[256];
  378.     
  379.     do {
  380.     fgets(buffer,256,infile);
  381.     } while ((strlen(buffer)<=1) && !feof(infile));
  382.     if (feof(infile)) return;
  383.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  384.  
  385.     char *l=strrchr(buffer,'(');
  386.     char *m=strrchr(buffer,')');
  387.     if ((m==NULL) || (l==NULL))
  388.     name = strdup(buffer);
  389.     else {
  390.     int namelen=strlen(buffer)-strlen(l);
  391.     name=new char[namelen];
  392.     name[namelen-1]=(char)0;
  393.     strncpy(name,buffer,namelen-1);
  394.     int schoollen=strlen(l)-strlen(m);
  395.     school=new char[schoollen];
  396.     school[schoollen-1]=(char)0;
  397.     strncpy(school,l+1,schoollen-1);
  398.     }
  399.     fgets(buffer,256,infile);
  400.     if (strncmp(buffer,"Reversible",10)==0) {
  401.     reversible=true;
  402.     fgets(buffer,256,infile);
  403.     }
  404.     while ((strlen(buffer)>2) && !feof(infile)) {
  405.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  406.     
  407.     if (strstr(buffer,"Range:"))
  408.         range=strdup(buffer+7);
  409.     else if (strstr(buffer,"Components:"))
  410.         components=strdup(buffer+12);
  411.     else if (strstr(buffer,"Duration:"))
  412.         duration=strdup(buffer+10);
  413.     else if (strstr(buffer,"Casting Time:"))
  414.         casttime=strdup(buffer+14);
  415.     else if (strstr(buffer,"Area of Effect:"))
  416.         area=strdup(buffer+16);
  417.     else if (strstr(buffer,"Saving Throw:"))
  418.         save=strdup(buffer+14);
  419.     else if (strstr(buffer,"Sphere:"))
  420.         sphere=strdup(buffer+8);
  421.     else if (strstr(buffer,"School:"))
  422.         school=strdup(buffer+8);
  423.     else if (strstr(buffer,"  from "))
  424.         source=strdup(buffer+7);
  425.     else if (strstr(buffer,"Level:"))
  426.         sscanf(buffer+7,"%d",&level);
  427.     
  428.     fgets(buffer,256,infile);
  429.     }
  430.     fgets(buffer,256,infile);
  431.     while ((strncmp(buffer,"-----",5)!=0) && !feof(infile)) {
  432.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  433.     add_desc(buffer);
  434.     fgets(buffer,256,infile);
  435.     }
  436. }
  437.  
  438. void priest_to_mage(magespell &y, priestspell &x) {
  439.   if (x.name) y.name=strdup(x.name);
  440.   y.level=x.level;
  441.   if (x.range) y.range=strdup(x.range);
  442.   if (x.area) y.area=strdup(x.area);
  443.   if (x.source) y.source=strdup(x.source);
  444.   if (x.school) y.school=strdup(x.school);
  445.   if (x.duration) y.duration=strdup(x.duration);
  446.   if (x.components) y.components=strdup(x.components);
  447.   if (x.casttime) y.casttime=strdup(x.casttime);
  448.   if (x.save) y.save=strdup(x.save);
  449.   y.reversible=x.reversible;
  450.   for (int i=0; i<x.lines; i++)
  451.     y.add_desc(x.description[i]);
  452. }
  453.  
  454. spellbook::spellbook(spellbook &s) {
  455.   first=last=NULL;
  456.   if (s.name) name=strdup(s.name);
  457.   else name=NULL;
  458.   *this += s;
  459. }
  460.  
  461. spellbook::~spellbook() {
  462.   spelllist *i=first;
  463.   spelllist *j;
  464.     
  465.   while (i!=NULL) {
  466.     j=i->next;
  467.     delete i;
  468.     i=j;
  469.   }
  470.   delete name;
  471. }
  472.  
  473. spelllist *spellbook::add_spell(spell &x, spelllist *where) {
  474.     spelllist *sl;
  475.  
  476.     sl=new spelllist;
  477.  
  478.     // spell is given.
  479.     sl->s=&x;
  480.  
  481.     if (where==NULL) {   // add at end.
  482.     sl->next=NULL;
  483.     sl->prev=last;
  484.     if (last!=NULL) last->next=sl;
  485.     if (first==NULL) first=sl;
  486.     last=sl;
  487.     } else {  // add after "where"
  488.     sl->next=where->next;
  489.     sl->prev=where;
  490.     if (where->next!=NULL) where->next->prev=sl;
  491.     where->next=sl;
  492.     if (where==last) last=sl;
  493.     }
  494.     return(sl);
  495. }
  496.  
  497.  
  498. // delete a spell given its spelllist entry
  499. void spellbook::del_spell(spelllist *sl) {
  500.   if (sl->next!=NULL) sl->next->prev=sl->prev;
  501.   if (sl->prev!=NULL) sl->prev->next=sl->next;
  502.   if (first==sl) first=sl->next;
  503.   if (last==sl) last=sl->prev;
  504.   delete sl;
  505. }
  506.  
  507. // find and delete one reference to spell x in book
  508. void spellbook::del_spell(spell &x) {
  509.   spelllist *i;
  510.   
  511.   for (i=first; i!=NULL; i=i->next) 
  512.     if (i->s==&x) {
  513.       del_spell(i);
  514.       return;
  515.     }
  516.  
  517. }
  518.  
  519. spellbook& spellbook::operator +=(spell &x) {
  520.     add_spell(x);
  521.     return(*this);
  522. }
  523.  
  524. spellbook& spellbook::operator +=(spellbook &x) {
  525.     for (spelllist *i=x.first; i!=NULL; i=i->next) 
  526.     add_spell(*(i->s));
  527.     return(*this);
  528. }
  529.  
  530. spellbook& spellbook::operator -=(spell &x) {
  531.   del_spell(x);
  532.   return(*this);
  533. }
  534.  
  535. spellbook& spellbook::operator -=(spellbook &x) {
  536.     for (spelllist *i=x.first; i!=NULL; i=i->next) 
  537.     del_spell(*(i->s));
  538.     return(*this);
  539. }
  540.  
  541. boolean spellbook::read_book(char *filename) {
  542.     FILE *infile;
  543.     fpos_t pos;
  544.     char buffer[256];
  545.  
  546.     // clear out old book, if present.
  547.     this->~spellbook();
  548.     first=last=NULL;
  549.     if ((infile=fopen(filename,"r"))==NULL) return(false);
  550.  
  551.     // get spellbook name from first line of file, if there
  552.     fgetpos(infile,&pos);
  553.     fgets(buffer,256,infile);
  554.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  555.     if (strstr(buffer,"Title:  ")==NULL) {
  556.     name=NULL;
  557.     fsetpos(infile,&pos);
  558.     }
  559.     else name=strdup(buffer+8);
  560.  
  561.     while (!feof(infile)) {
  562.       priestspell *x;
  563.       x = new priestspell;
  564.       x->f_read(infile);
  565.       if (x->sphere) add_spell(*x);
  566.       else {  // was actually a magespell.
  567.     magespell *y;
  568.     y=new magespell;
  569.     priest_to_mage(*y,*x);
  570.     delete x;
  571.     add_spell(*y);
  572.       }
  573.     }
  574.     fclose(infile);
  575.     return(true);
  576. }
  577.  
  578.  
  579. // look up a spell by title.
  580. spell *spellbook::lookup(char *sname) {
  581.     for (spelllist *i=first; i!=NULL; i=i->next) 
  582.     if (strcmp(i->s->name,sname)==0) return(i->s);
  583.     return(NULL);
  584. }
  585.  
  586. // read spellbook from list of spells
  587. boolean spellbook::read_titles(char *filename, spellbook *masterlist) {
  588.     FILE *infile;
  589.     fpos_t pos;
  590.     char buffer[256];
  591.  
  592.     // clear out old book, if present.
  593.     this->~spellbook();
  594.     first=last=NULL;
  595.     if ((infile=fopen(filename,"r"))==NULL) return(false);
  596.  
  597.     // get spellbook name from first line of file, if there
  598.     fgetpos(infile,&pos);
  599.     fgets(buffer,256,infile);
  600.     if (strlen(buffer)) buffer[strlen(buffer)-1]=(char)0;
  601.     if (strstr(buffer,"Title:  ")==NULL) {
  602.     name=NULL;
  603.     fsetpos(infile,&pos);
  604.     }
  605.     else name=strdup(buffer+8);
  606.  
  607.     while (!feof(infile)) {
  608.     fgets(buffer,256,infile);
  609.     if (!feof(infile)) {
  610.         spell *ns;
  611.         buffer[strlen(buffer)-1]=(char)0;
  612.         ns=masterlist->lookup(buffer);
  613.         if (ns!=NULL) add_spell(*ns);
  614.     }
  615.     }
  616. }
  617.  
  618. void spellbook::print_titles(char *filename) {
  619.     FILE *outfile;
  620.     
  621.     if ((outfile=fopen(filename,"w"))==NULL) {
  622.     error("Can't open output file %s",filename);
  623.     return;
  624.     }
  625.     
  626.     if (name) fprintf(outfile,"Title:  %s\n",name);
  627.     else fprintf(outfile,"\n");
  628.     for (spelllist *i=first; i!=NULL; i=i->next)
  629.     fprintf(outfile,"%s\n",i->s->name);
  630.     
  631.     fclose(outfile);
  632. }
  633.  
  634. // save an entire spellbook 
  635. void spellbook::print_book(char *filename) {
  636.     FILE *outfile;
  637.     
  638.     if ((outfile=fopen(filename,"w"))==NULL) {
  639.     error("Can't open output file %s",filename);
  640.     return;
  641.     }
  642.     
  643.     if (name) fprintf(outfile,"Title:  %s\n",name);
  644.     for (spelllist *i=first; i!=NULL; i=i->next) {
  645.     i->s->f_print(outfile);
  646.     if (i->next!=NULL) fprintf(outfile,"-----\n");
  647.     }
  648.     
  649.     fclose(outfile);
  650. }
  651.  
  652. // print out abbreviated spellbook
  653. void spellbook::print_abbrev(char *filename) {
  654.     FILE *outfile;
  655.     
  656.     if ((outfile=fopen(filename,"w"))==NULL) {
  657.     error("Can't open output file %s",filename);
  658.     return;
  659.     }
  660.     
  661.     if (name) fprintf(outfile,"%s\n",name);
  662.     else fprintf(outfile,"\n");
  663.     for (spelllist *i=first; i!=NULL; i=i->next) {
  664.     i->s->f_print_header(outfile);
  665.     }
  666.     
  667.     fclose(outfile);
  668. }
  669.  
  670.  
  671. // get master list of spells from ALLSPELLS
  672. spellbook *get_master_list() {
  673.     spellbook *ml;
  674.     spellbook *x;
  675.     char buffer[256];
  676.     FILE *infile;
  677.  
  678.     ml=new spellbook;    
  679.     if (ml==NULL) return(NULL);
  680.     ml->name=strdup("Master list of spells");
  681.     x=new spellbook;
  682.     if (x==NULL) return(NULL);
  683.  
  684.     if ((infile=fopen(ALLSPELLS,"r"))==NULL) return(NULL);
  685.  
  686.     while (!feof(infile)) {
  687.     fgets(buffer,256,infile);
  688.     if ((!feof(infile)) && (buffer[0]!=';')) {
  689.         x->read_book(buffer);
  690.         (*ml)+=(*x);
  691.     }
  692.     }
  693.     
  694.     return(ml);
  695. }
  696.  
  697.