home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / dominion / part24 / spelllib.c < prev   
C/C++ Source or Header  |  1992-02-11  |  13KB  |  521 lines

  1.   /* spelllib.c -- handls loading spells for a nation, and keeping
  2.                    them "hanging" for a certain number of turns.
  3.    */
  4.  
  5. /*
  6.  * Copyright (C) 1990 Free Software Foundation, Inc.
  7.  * Written by the dominion project.
  8.  *
  9.  * This file is part of dominion.
  10.  *
  11.  * dominion is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU General Public License as published
  13.  * by the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  *
  16.  * This software is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this software; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "dominion.h"
  27. #include "misc.h"
  28. #include "army.h"
  29.  
  30. #include <stdio.h>
  31.  
  32.   /* army and spirit types */
  33. extern struct army_type *army_types;
  34. extern struct spirit_type *spirit_types;
  35.  
  36. extern Sworld world;
  37. extern int debug;
  38. extern Sh_spell *hanging_spells;
  39.  
  40. extern Sh_spell *dead_spells;
  41. extern Suser user;
  42.  
  43.  
  44.   /* this writes out the hanging spells after the update, decreasing
  45.      the thons_left parameter by one, and removing the spell
  46.      once the thons_left reaches zero.
  47.    */
  48. write_h_spells()
  49. {
  50.   FILE *hang_fp, *fopen();
  51.   char line[EXECLEN];
  52.   int i;
  53.   Sh_spell *h_spells;
  54.  
  55.   if ((hang_fp = fopen(HANGING_SPELLS_FILE, "w")) == NULL) {
  56.     printf("cannot write file %s\n", HANGING_SPELLS_FILE);
  57.     return -1;
  58.   }
  59.   for (h_spells=hanging_spells; h_spells != NULL; h_spells = h_spells->next) {
  60.       /* only write them out if they have not expired */
  61.     if (h_spells->thons_left != -1) {
  62.       fprintf(hang_fp, "%s\n", h_spells->name);
  63.       fprintf(hang_fp, "%d\n", h_spells->nat_id);
  64.       fprintf(hang_fp, "%d\n", h_spells->thons_left);
  65.       fprintf(hang_fp, "%d\n", h_spells->n_lines);
  66.       for (i = 0; i < h_spells->n_lines; ++i) { /* write out the exec lines */
  67.     fprintf(hang_fp, "%s", h_spells->lines[i]);
  68.       /* we might need to tack on a newline */
  69.     if (h_spells->lines[i][strlen(h_spells->lines[i])-1] != '\n') {
  70.       fprintf(hang_fp, "\n");
  71.     }
  72.       }
  73.     }
  74.   }
  75.   fclose(hang_fp);
  76. }
  77.  
  78.   /* we need list as a pointer to pointer, so as to add at
  79.      the start of the list (which is easy and fast)
  80.    */
  81. add_h_spell(listp, h_spellp)
  82.      Sh_spell **listp, *h_spellp;
  83. {
  84.   Sh_spell *tmp;
  85.  
  86.   if (listp) {            /* list should not be null in this func. */
  87.     tmp = (Sh_spell *)malloc(sizeof(Sh_spell));
  88.     *tmp = *h_spellp;
  89.     tmp->next = *listp;
  90.     *listp = tmp;
  91.   }
  92. }
  93.  
  94.   /* removes a hanging spell from the list */
  95. delete_h_spell(listp, h_spellp)
  96.      Sh_spell **listp, *h_spellp;
  97. {
  98. }
  99.  
  100.   /* prepares a new hanging spell structure, to be
  101.      filled in with its exec lines
  102.    */
  103. prepare_h_spell(h_spellp, name, nat_id, thons_left, n_lines)
  104.      Sh_spell *h_spellp;
  105.      char name[];
  106.      int nat_id, thons_left, n_lines;
  107. {
  108.   int i;
  109.  
  110.   strcpy(h_spellp->name, name);
  111.   h_spellp->next = NULL;
  112.   h_spellp->nat_id = nat_id;
  113.   h_spellp->thons_left = thons_left;
  114.   h_spellp->n_lines = n_lines;
  115.   h_spellp->lines = (char **)malloc(h_spellp->n_lines*sizeof(char*));
  116.   for (i = 0; i < h_spellp->n_lines; ++i) {
  117.     h_spellp->lines[i] = (char *)malloc(EXECLEN*sizeof(char));
  118.     strcpy(h_spellp->lines[i], "");
  119.   }
  120. }
  121.  
  122. /* compares 2 hanging spells and returns 0 if same 1 if not */
  123. h_spell_compare(sp1, sp2)
  124. Sh_spell *sp1, *sp2;
  125. {
  126.   int i;
  127.  
  128.   if (sp1->nat_id != sp2->nat_id) return 1;
  129.   if (sp1->thons_left != sp2->thons_left) return 1;
  130.   if (sp1->n_lines != sp2->n_lines) return 1;
  131.   if (strncmp(sp1->name, sp2->name,NAMELEN) != 0) return 1;
  132.   for (i = 0 ; i < sp1->n_lines; i++)
  133.   {  
  134.     if (strcmp(sp1->lines[i], sp2->lines[i]) != 0) return 1;
  135.   }
  136.   return 0;
  137. };
  138.  
  139. is_dead_spell(sp,flag)
  140. int flag;
  141. Sh_spell *sp;
  142. {
  143.   Sh_spell *tmp;
  144.  
  145.   tmp = dead_spells;
  146.   while (tmp != NULL)
  147.   {
  148.     if (h_spell_compare(tmp,sp) == 0)
  149.     { 
  150.       got_dead_h_spell(tmp);
  151.       return 1;
  152.     }
  153.     tmp = tmp->next;
  154.   }
  155.   return 0;
  156. }
  157.  
  158. load_dead_hspells(up,flag)
  159. int flag;
  160.      Suser *up;            /* up can also be NULL */
  161. {
  162.   FILE *dead_fp, *fopen();
  163.   int done = 0, i;
  164.   char line[EXECLEN], filename[PATHLEN];
  165.   Sh_spell h_spell;
  166.  
  167.   sprintf(filename,"exec/%s.%d","dead_spells",up->id);
  168.   if ((dead_fp = fopen(filename, "r")) == NULL) {
  169.     if (debug) printf("no file %s\n", filename);
  170.     return -1;
  171.   }
  172.   while (!done) {
  173.     h_spell.next = NULL;
  174.     if (fscanf(dead_fp, "%s", h_spell.name) < 0) {
  175.       done = 1;            /* useless? */
  176.       break;
  177.     }
  178.     fscanf(dead_fp, "%d", &h_spell.nat_id);
  179.     fscanf(dead_fp, "%d", &h_spell.thons_left);
  180.     fscanf(dead_fp, "%d", &h_spell.n_lines);
  181.     if (debug) {
  182.       printf("nation id %d, spell <%s>, time_left = %d, n_lines = %d\n",
  183.        h_spell.nat_id, h_spell.name, h_spell.thons_left, h_spell.n_lines);
  184.     }
  185.     h_spell.lines = (char **)malloc(h_spell.n_lines * sizeof(char *));
  186.  
  187.     for (i = 0; i < h_spell.n_lines; ++i) { /* read in the exec lines */
  188.       h_spell.lines[i] = (char *)malloc(EXECLEN*sizeof(char));
  189.       fscanf(dead_fp, "%s", h_spell.lines[i]);
  190.     }
  191.     add_h_spell(&dead_spells, &h_spell);
  192.   }
  193.   fclose(dead_fp);
  194.   if (flag == 1) { unlink(filename); }
  195. }
  196.  
  197.   /* this is fundamental:  it loads all spells from the global
  198.      "hanging_spells" file and runs the exec lines it finds.
  199.      Note:  it must load all the spells, not just those for the
  200.      current user, because spells by other users affect the current
  201.      user too.  One effect is that spells, like diplomacy, take
  202.      immediate effect, rather than waiting for the update.  Hmm,
  203.      is that good or bad?
  204.  
  205.      At the same time, the spells of the current user (if we are in
  206.      the game rather than the update) are stored into a list for that
  207.      user to examine, apart from the global list.
  208.    */
  209.  
  210. load_h_spells(up)
  211.      Suser *up;            /* up can also be NULL */
  212. {
  213.   FILE *hang_fp, *fopen();
  214.   int done = 0, i;
  215.   char line[EXECLEN];
  216.   Sh_spell h_spell;
  217.   struct argument exec_args[N_EXEC_ARGS];
  218.   Snation *np;
  219.  
  220.     /* start with the global list being NULL */
  221.   hanging_spells = NULL;
  222.   if (up) {
  223.     up->h_spells = NULL;
  224.   }
  225.   if ((hang_fp = fopen(HANGING_SPELLS_FILE, "r")) == NULL) {
  226.     if (debug) printf("no file %s\n", HANGING_SPELLS_FILE);
  227.     return -1;
  228.   }
  229.   while (!done) {
  230.     h_spell.next = NULL;
  231.     if (fscanf(hang_fp, "%s", h_spell.name) < 0) {
  232.       done = 1;            /* useless? */
  233.       break;
  234.     }
  235.     fscanf(hang_fp, "%d", &h_spell.nat_id);
  236.     fscanf(hang_fp, "%d", &h_spell.thons_left);
  237.     fscanf(hang_fp, "%d", &h_spell.n_lines);
  238.     if (debug) {
  239.       printf("nation id %d, spell <%s>, time_left = %d, n_lines = %d\n",
  240.        h_spell.nat_id, h_spell.name, h_spell.thons_left, h_spell.n_lines);
  241.     }
  242.     h_spell.lines = (char **)malloc(h_spell.n_lines * sizeof(char *));
  243.  
  244.     for (i = 0; i < h_spell.n_lines; ++i) { /* read in the exec lines */
  245.       h_spell.lines[i] = (char *)malloc(EXECLEN*sizeof(char));
  246.       fscanf(hang_fp, "%s", h_spell.lines[i]);
  247.     }
  248.     if (!is_dead_spell(&h_spell,1))
  249.     {
  250.       for (i = 0 ; i < h_spell.n_lines; ++i)
  251.       {
  252.         if (i % 2 == 0) {
  253.       parse_exec_line(h_spell.lines[i], exec_args);
  254.           np = &world.nations[h_spell.nat_id];
  255.           run_exec_line(np, exec_args);
  256.         }
  257.       }
  258.       add_h_spell(&hanging_spells, &h_spell);
  259.       if (up && (up->id == h_spell.nat_id || up->id == 0)) {
  260.     add_h_spell(&up->h_spells, &h_spell);
  261.       }
  262.     }
  263.   }
  264.   fclose(hang_fp);
  265. }
  266.  
  267. delete_hanging_spell(sp1)
  268. Sh_spell *sp1;
  269. {
  270.   Sh_spell *prev, *next, *tmp, *tmp2;
  271.   struct argument exec_args[N_EXEC_ARGS];
  272.   int i;
  273.  
  274.   tmp = user.h_spells; tmp2 = NULL; prev = NULL;
  275.   while ((tmp != NULL) && (tmp2 == NULL))
  276.   {
  277.     if (h_spell_compare(sp1, tmp) == 0)
  278.     {
  279.       tmp2 = tmp;
  280.     } else
  281.     {
  282.       prev = tmp;
  283.       tmp = tmp->next;
  284.     }
  285.   }
  286.   if (prev == NULL)
  287.   { 
  288.     user.h_spells = tmp2->next;
  289.   } else
  290.   {
  291.     prev->next = tmp2->next;
  292.   }
  293.   for (i = 0 ; i < tmp2->n_lines; i++)
  294.   {
  295.     if (i % 2 == 1)
  296.     {
  297.       parse_exec_line(tmp2->lines[i], exec_args);
  298.       run_exec_line(user.np, exec_args);
  299.     }
  300.   }
  301.   write_dead_spell(tmp2);
  302.   if (is_army_spell(tmp2)) reset_spelled_flags();
  303.   free_h_spell(tmp2);
  304. }
  305.  
  306. got_dead_h_spell(sp1)
  307. Sh_spell *sp1;
  308. {
  309.   Sh_spell *prev, *tmp, *tmp2;
  310.  
  311.   tmp = dead_spells; tmp2 = NULL; prev = NULL;
  312.   while ((tmp != NULL) && (tmp2 == NULL))
  313.   {
  314.     if (sp1 == tmp)
  315.     {
  316.       tmp2 = tmp;
  317.     } else
  318.     {
  319.       prev = tmp;
  320.       tmp = tmp->next;
  321.     }
  322.   }
  323.   if (tmp2 != NULL)
  324.   {
  325.     if (prev == NULL)
  326.     { 
  327.       dead_spells = tmp2->next;
  328.     } else
  329.     {
  330.       prev->next = tmp2->next;
  331.     }
  332.     free_h_spell(tmp2);
  333.   }
  334. }
  335.  
  336. free_h_spell(sp1)
  337. Sh_spell *sp1;
  338. {
  339.   int i;  
  340.  
  341.   for (i = 0 ; i < sp1->n_lines ; i++)
  342.   {
  343.     free(sp1->lines[i]);
  344.   }
  345.   free(sp1);
  346. }
  347.  
  348. reset_spelled_flags()
  349. {
  350.   Sh_spell *tmp;
  351.   
  352.   tmp = user.h_spells;
  353.  
  354.   while (tmp != NULL)
  355.   {
  356.     reset_one_spell(tmp);
  357.     tmp = tmp -> next;
  358.   }
  359. }
  360.  
  361. reset_one_spell(sp1)
  362. Sh_spell *sp1;
  363. {
  364.   struct argument exec_args[N_EXEC_ARGS];
  365.  
  366.   if (strcmp(sp1->name, "hide_army") == 0)
  367.   {
  368.     if (sp1->n_lines < 4) return;
  369.     parse_exec_line(sp1->lines[2], exec_args);
  370.     run_exec_line(user.np, exec_args);
  371.   }
  372.   else if (strcmp(sp1->name, "fly_army") == 0)
  373.   {
  374.     if (sp1->n_lines < 4) return;
  375.     parse_exec_line(sp1->lines[2], exec_args);
  376.     run_exec_line(user.np, exec_args);
  377.   }
  378.   else if (strcmp(sp1->name, "vampire_army")== 0 )
  379.   {
  380.     if (sp1->n_lines < 4) return;
  381.     parse_exec_line(sp1->lines[2], exec_args);
  382.     run_exec_line(user.np, exec_args);
  383.   }
  384.   else if (strcmp(sp1->name, "burrow_army")== 0 )
  385.   {
  386.     if (sp1->n_lines < 4) return;
  387.     parse_exec_line(sp1->lines[2], exec_args);
  388.     run_exec_line(user.np, exec_args);
  389.   }
  390.   else if (strcmp(sp1->name, "water_walk") == 0)
  391.   {
  392.     if (sp1->n_lines < 4) return;
  393.     parse_exec_line(sp1->lines[2], exec_args);
  394.     run_exec_line(user.np, exec_args);
  395.   }
  396.   else if (strcmp(sp1->name, "mag_bonus") == 0)
  397.   {
  398.     if (sp1->n_lines < 4) return;
  399.     parse_exec_line(sp1->lines[2], exec_args);
  400.     run_exec_line(user.np, exec_args);
  401.   }
  402. }
  403.  
  404. is_army_spell(sp1)
  405. Sh_spell *sp1;
  406. {
  407.   struct argument exec_args[N_EXEC_ARGS];
  408.  
  409.   if (strcmp(sp1->name, "hide_army") == 0)
  410.   {
  411.     return 1;
  412.   }
  413.   else if (strcmp(sp1->name, "fly_army") == 0)
  414.   {
  415.     return 1;
  416.   }
  417.   else if (strcmp(sp1->name, "vampire_army")== 0 )
  418.   {
  419.     return 1;
  420.   }
  421.   else if (strcmp(sp1->name, "burrow_army")== 0 )
  422.   {
  423.     return 1;
  424.   } 
  425.   else if (strcmp(sp1->name, "water_walk") == 0)
  426.   {
  427.     return 1;
  428.   }
  429.   else if (strcmp(sp1->name, "mag_bonus") == 0)
  430.   {
  431.     return 1;
  432.   }
  433.   return 0;
  434. }
  435.  
  436. write_dead_spell(sp1)
  437. Sh_spell *sp1;
  438. {
  439.   FILE *dead_fp, *fopen();
  440.   char line[EXECLEN], filename[PATHLEN];
  441.   int i;
  442.  
  443.   sprintf(filename,"exec/%s.%d","dead_spells",user.id);
  444.   if ((dead_fp = fopen(filename, "a")) == NULL) {
  445.     if (debug) printf("no file %s\n", filename);
  446.     return -1;
  447.   }
  448.   fprintf(dead_fp, "%s\n", sp1->name);
  449.   fprintf(dead_fp, "%d\n", sp1->nat_id);
  450.   fprintf(dead_fp, "%d\n", sp1->thons_left);
  451.   fprintf(dead_fp, "%d\n", sp1->n_lines);
  452.   for (i = 0; i < sp1->n_lines; ++i) { /* write out the exec lines */
  453.     fprintf(dead_fp, "%s", sp1->lines[i]);
  454.      /* we might need to tack on a newline */
  455.     if (sp1->lines[i][strlen(sp1->lines[i])-1] != '\n') {
  456.     fprintf(dead_fp, "\n");
  457.     }
  458.   }
  459.   fclose(dead_fp);
  460. }
  461.  
  462. clear_dead_hspells()
  463. {
  464.   Sh_spell *h_spells;
  465.   int i,end;
  466.   struct argument exec_args[N_EXEC_ARGS];
  467.  
  468.   for (h_spells=hanging_spells; h_spells != NULL; h_spells = h_spells->next)
  469.   {
  470.     for (i = 0; i < h_spells->n_lines; ++i) { /* check the exec lines */
  471. /* Remove that goddman newline */
  472.       end = strlen(h_spells->lines[i]);
  473.       if (h_spells->lines[i][end-1] == '\n') {
  474.         h_spells->lines[i][end - 1] = '\0';
  475.       }
  476.     }
  477.     if (is_dead_spell(h_spells,1))
  478.     {
  479.       h_spells->thons_left = 0;
  480.     }
  481.   }
  482. }
  483.  
  484. /* This routine checks to see if this army has a spell cast on it by  */
  485. /* checking to see if the flags are different from the default.       */
  486. /* If new spells are developed that change things besides flags, then */
  487. /* other mechanism's will need to be used.                            */
  488. is_spelled(ap)
  489. Sarmy *ap;
  490. {
  491.   int i;
  492.   int def_flags;
  493.   Snation *np = user.np;
  494.  
  495.   i = army_type_index(ap->type);
  496.   if (i != -1 ) {
  497.     def_flags = army_types[i].flags;
  498.     if (def_flags & AF_INVERSE_ALT) {
  499.       if (np->race.pref_alt >= SEA_LEVEL) {
  500.         def_flags |= AF_WATER;
  501.       } else {
  502.         def_flags |= AF_LAND;
  503.       }
  504.     }
  505.     if (def_flags != ap->flags) {
  506.       return 1;
  507.     } else {
  508.       return 0;
  509.     }
  510.   } else {
  511.     if ((i = spirit_type_index(ap->type)) < 0) {
  512.       return 0;  /* We can't figure out what it is, so it's not spelled */
  513.     }
  514.     if (spirit_types[i].flags != ap->flags) {
  515.       return 1;
  516.     } else {
  517.       return 0;
  518.     }
  519.   }
  520. }
  521.