home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / dominion / part19 / misc.c < prev   
C/C++ Source or Header  |  1992-02-11  |  26KB  |  1,019 lines

  1. /* misc.c -- routines for which a better place has yet to be found */
  2. /*           or routines which are needed in many places           */
  3.  
  4. /*
  5.  * Copyright (C) 1990 Free Software Foundation, Inc.
  6.  * Written by the dominion project.
  7.  *
  8.  * This file is part of dominion.
  9.  *
  10.  * dominion is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License as published
  12.  * by the Free Software Foundation; either version 1, or (at your option)
  13.  * any later version.
  14.  *
  15.  * This software is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this software; see the file COPYING.  If not, write to
  22.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  */
  24.  
  25.  
  26. /* int interrupt() - handles interupts                             */
  27. /* show_nation(np) - displays a nation's characteristics           */
  28. /* free_nation_mark(wp,c) - tell us if the symbol is available     */
  29. /* getline(s,n) - read a line from stdin, remove \n                */
  30. /* get_crypt_pass(prompt,s,w) - get password and encrypt           */
  31. /* critical() - while writing, don't bug me!!                      */
  32. /* noncritical() - normal operation                                */
  33. /* which_mark(x,y,up) - determine which mark is to be shown for    */
  34. /*           the sector in question based on display modes, etc.   */
  35. /* addsector(np,x,y) - adds sector x,y to nation's list of owned   */
  36. /*           sectors.  Also changes owner of sector to nation->id. */
  37. /* subtsector(np,x,y) - deletes sector x,y from nation's list of   */
  38. /*           owned sectors.                                        */
  39. /* destroy_nation(np) - frees all memory used by that nation       */
  40. /* get_n_cities(np) - return number of cities in nation            */
  41. /* get_n_civil(np) - return number of civilians in nation          */
  42. /* unique_name(name) - returns true if a nation with this name     */
  43. /*           does not exist yet                                    */
  44. /* free_army_id(np) - finds first free army id for a nation        */
  45. /* get_space() - waits for the user to type a space                */
  46. /* statline(s,s) - places information on the statline              */
  47. /* statline2(s,s) - places information on statline 2               */
  48. /* get_spirit_from_type(up,type) - returns a spirit pointer, given a type */
  49. /* gen_exec(s) - puts the exec line into the exec list (and later file)   */
  50. /* is_good_order(name) - TRUE if this is a valid name for a magic order   */
  51. /* find_visible_sectors(visible_sectors) - updates visibility matrix      */
  52.  
  53. #include "dominion.h"
  54. #include "misc.h"
  55. #include "army.h"
  56. #include "cur_stuff.h"
  57. #include <stdio.h>
  58. #include <ctype.h>
  59. #include <signal.h>
  60.  
  61. extern int (*wrapx)(), (*wrapy)();
  62.  
  63. extern Sworld world;
  64. extern struct s_desig_map desig_map[];
  65. extern struct s_altitude_map altitude_map[];
  66. extern struct item_map terrains[];
  67. extern struct item_map climates[];
  68. extern Suser user;
  69. int viewall;
  70. extern int debug;
  71.  
  72. WINDOW *sectw;
  73.  
  74. /* handles interrupts */
  75. int interrupt()
  76. {
  77.   printf("\r\ngot an interrupt.  quitting nicely...\r\n");
  78.   cleanup();        /* cleanup depends on which program you are in */
  79.   clean_exit();
  80.   exit(0);
  81. }
  82.  
  83. /* show a nation's characteristics */
  84. show_nation(np)
  85.      Snation *np;        /* nation pointer */
  86. {
  87.   printf("\n\tname: %s (id = %d)\n", np->name, np->id);
  88.   printf("\tleader: %s\n", np->leader);
  89.   printf("\tpasswd: %s\n", np->passwd);
  90.   printf("\tcapital is at (%d, %d)\n", np->capital.x, np->capital.y);
  91.   printf("\trace is %s\n", np->race.name);
  92.   printf("\tnation mark is %c\n", np->mark);
  93.   printf("\t%d civilians; %d soldiers; %d armies.\n",
  94.      get_n_civil(np), get_n_soldiers(np), np->n_armies);
  95.   printf("\tmagical order %s\n", np->mag_order);
  96. }
  97.  
  98.  
  99.     /* tell us if the symbol is available */
  100. free_nation_mark(wp, c)
  101.      Sworld *wp;
  102.      Symbol c;
  103. {
  104.   int i;
  105.  
  106.   if (!isprint(c)) {
  107.     return 0;
  108.   }
  109.   for (i = 0; i < wp->n_nations; ++i) {
  110.     if (wp->nations[i].mark == c) {
  111.       return 0;
  112.     }
  113.   }
  114.   return 1;
  115. }
  116.  
  117. getline(s, n)            /* read a line from stdin, remove \n */
  118.      char s[];
  119.      int n;
  120. {
  121.   fgets(s, n, stdin);
  122.   if (s[strlen(s)-1] == '\n') {    /* remove \n if it is there */
  123.     s[strlen(s)-1] = '\0';
  124.   }
  125. }
  126.  
  127.   /* get a password and encrypt it.  if the parameter "default"
  128.      has a string in it, use that instead of getting it from
  129.      the terminal.  if "w" is not NULL, get the string from
  130.      the window "w".
  131.    */
  132. get_crypt_pass(prompt, pass, w, def_pass)
  133.      char prompt[], pass[];
  134.      WINDOW *w;
  135.      char def_pass[];
  136. {
  137.   char *s1, s2[PASSLEN], *getpass(), *crypt();
  138.  
  139.     /* if there is already a password, it is passed in the string def_pass */
  140.   if (def_pass != NULL && strlen(def_pass) > 0) {
  141.     strcpy(s2, def_pass);
  142.     s1 = crypt(s2, SALT);
  143.     strcpy(pass, s1+2);
  144.     return;
  145.   }
  146.     /* if no password was given us, get it from input */
  147.   if (w == NULL) {
  148.     s1 = getpass(prompt);
  149.     strcpy(s2, s1);
  150.     s1 = crypt(s2, SALT);
  151.     strcpy(pass, s1 + 2);    /* final crypted pass. without salt */
  152.   } else {
  153.     wprintw(w, "%s", prompt);
  154.     wrefresh(w);
  155.     wscanw(w, "%s", s2);
  156.     s1 = crypt(s2, SALT);
  157.     strcpy(pass, s1+2);
  158.   }
  159. }
  160.  
  161. cpass(np, pass)
  162.      Snation *np;
  163.      char pass[];
  164. {
  165.   char s[EXECLEN];
  166.   sprintf(s, "CPASS:%d:%s\n", np->id, pass);
  167.   gen_exec(s);
  168. }
  169.  
  170. which_mark(x, y, up)
  171.      int x, y;
  172.      Suser *up;
  173. {
  174.   int highlight = 1;        /* should we highlight? 1=no,-1=yes */
  175.   int owner = world.map[x][y].owner, mark = '\0';
  176.   Ssector *sectp = &world.map[x][y];
  177.   int visibility = user.visible_sectors[x][y];
  178.   int cost;
  179.   Sarmy *ap, *get_army();
  180.   struct armyid *alist;
  181.  
  182.     /* figure out what to draw */
  183.     /* should find a clean way of dealing with above/under water */
  184.   if (!user.underwater && sectp->altitude < SEA_LEVEL) {
  185.     mark = '~';            /* if not underwater, water looks like ~ */
  186.   }
  187.   if (user.underwater && sectp->altitude >= SEA_LEVEL) {
  188.     mark = '.';        /* if underwater, land looks like # */
  189.   }
  190.  
  191.   if (!mark) {            /* only if mark is not yet set */
  192.     switch (up->display) {
  193.     case DESIGNATION:
  194.       if (owner == up->id) {
  195.     mark = desig_map[sectp->designation].mark;
  196.       } else {
  197.     if (world.nations[owner].mark == '-') {
  198.       mark = altitude_map[map_alt(sectp->altitude)].mark;
  199.     } else {
  200.       mark = world.nations[owner].mark;
  201.     }
  202.       }
  203.     break;
  204.     case NATION_MARK:
  205. /*    if (world.nations[owner].mark == '-' || !(visibility & SEE_OWNER)) {
  206.       mark = altitude_map[map_alt(sectp->altitude)].mark;
  207.       } else {
  208.       mark = world.nations[owner].mark;
  209.       }
  210.    */
  211.       mark = world.nations[owner].mark;
  212.       break;
  213.     case SOIL:
  214.       if (visibility & SEE_RESOURCES) {
  215.     mark = (sectp->soil <= 9) ? sectp->soil + '0' : '+';
  216.       } else {
  217.     mark = '?';
  218.       }
  219.       break;
  220.     case METAL:
  221.       if (visibility & SEE_RESOURCES) {
  222.     mark = (sectp->metal <= 9) ? sectp->metal + '0' : '+';
  223.       } else {
  224.     mark = '?';
  225.       }
  226.       break;
  227.     case JEWELS:
  228.       if (visibility & SEE_RESOURCES) {
  229.     mark = (sectp->jewels <= 9) ? sectp->jewels + '0' : '+';
  230.       } else {
  231.     mark = '?';
  232.       }
  233.       break;
  234.     case ALTITUDE:
  235.       if (visibility & SEE_LAND_WATER) {
  236. /*      mark = (sectp->altitude <= 9) ? sectp->altitude + '0' : '+'; */
  237.     if (sectp->altitude > 9) {
  238.       mark = '+';
  239.     } else if (sectp->altitude >= 0) {
  240.       mark = sectp->altitude + '0';
  241.     } else {
  242.       mark = (-1 * sectp->altitude) + '0';
  243.     }
  244.       } else {
  245.     mark = '?';
  246.       }
  247.       break;
  248.     case CLIMATE:
  249.       if (visibility & SEE_LAND_WATER) {
  250.     mark = climates[sectp->climate].mark;
  251.       } else {
  252.     mark = '?';
  253.       }
  254.       break;
  255.     case POPULATION:
  256.       if (visibility & SEE_POPULATION) {
  257.     if (sectp->n_people < 950) {
  258.       mark =(sectp->n_people < 950) ? (sectp->n_people + 50)/100+'0' : '+';
  259.     } else {
  260.       mark = 'I';
  261.     }
  262.       } else {
  263.     mark = '?';
  264.       }
  265.       break;
  266.     case ARMY_MOVECOST:
  267.       if (visibility & SEE_LAND_WATER) {
  268.     if ((ap=get_army (&world.nations[up->id], user.current_army))
  269.         == NULL) {
  270.       cost = get_generic_move_cost (&world.nations[up->id], sectp);
  271.     } else {
  272.       cost = get_army_move_cost (&world.nations[up->id], sectp, ap);
  273.     }
  274.     mark = (cost <= 9) ? cost + '0' : '+';
  275.       } else {
  276.     mark = '?';
  277.       }
  278.       break;
  279.     case MOVECOST:
  280.       if (visibility & SEE_LAND_WATER) {
  281.     cost = get_generic_move_cost(&world.nations[up->id], sectp);
  282.     mark = (cost <= 9) ? cost + '0' : '+';
  283.       } else {
  284.     mark = '?';
  285.       }
  286.       break;
  287.     case TERRAIN:
  288.       if (visibility & SEE_LAND_WATER) {
  289.     mark = terrains[sectp->terrain - MIN_TERRAIN].mark;
  290.       } else {
  291.     mark = '?';
  292.       }
  293.       break;
  294.     default:            /* this should never happen */
  295.       break;
  296.     }
  297.   }
  298.  
  299.     /* here set the highlighting; we know user owns sector */
  300.   switch (up->highlight) {
  301.   case H_OWNED:
  302.     if (sectp->owner == up->id) {
  303.       highlight = -1;        /* if user owns, highlight */
  304.     }
  305.     break;
  306.   case H_ARMIES:
  307.     if ((user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)
  308.      && has_visible_army(sectp, &user)) {
  309.       highlight = -1;
  310.     } 
  311. /*    if (sectp->alist != NULL
  312.     && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  313.       highlight = -1;
  314.     } else {
  315.       highlight = 1;
  316.     }
  317. */
  318.     break;
  319.   case H_HOSTILE:
  320.     if (has_hostile (sectp)) {
  321.       highlight = -1;
  322.     }
  323.     break;
  324.   case H_YOUR_ARMIES:
  325.     if (sectp->alist != NULL
  326.     && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  327.       alist = sectp->alist;
  328.       while (alist != NULL) {
  329.     if (alist->owner == user.id) {
  330.       highlight = -1;
  331.       break;
  332.     }
  333.     alist = alist->next;
  334.       }
  335.     }
  336.     break;
  337.   case H_OTHER_ARMIES:
  338.     if (sectp->alist != NULL
  339.     && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  340.       alist = sectp->alist;
  341.       ap = get_army(&world.nations[alist->owner], alist->id);
  342.       while (alist != NULL) {
  343.     if (alist->owner != user.id && !is_hidden(ap)) {
  344.       highlight = -1;
  345.       break;
  346.     }
  347.     alist = alist->next;
  348.       }
  349.     }
  350.     break;
  351.   case H_MOVE_LEFT:
  352.     if (sectp->alist != NULL
  353.     && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  354.       highlight = 1;
  355.       alist = sectp->alist;
  356.       while (alist != NULL) {
  357.     if (alist->owner == user.id) {
  358.       ap = get_army(&world.nations[alist->owner], alist->id);
  359.       if (ap->mvpts > 0) {
  360.         highlight = -1;
  361.       }
  362.     }
  363.     alist = alist->next;
  364.       }
  365.     } else {
  366.       highlight = 1;
  367.     }
  368.     break;
  369.   case H_UNEMP:
  370.     if ((sectp->n_people > n_workers(sectp)) && (sectp->owner == up->id)) {
  371.       highlight = -1;
  372.     }
  373.     break;
  374.   case H_NONE:
  375.     highlight = 1;
  376.     break;
  377.   default:
  378.     break;
  379.   }
  380.  
  381.   return highlight*mark;    /* highlight can be +- 1 */
  382. }
  383.  
  384. /********************************************************************/
  385. /* adds sector x,y to nation's list of owned sectors. Also changes  */
  386. /* owner of sector to nation->id.                                   */
  387. /********************************************************************/
  388. addsector(np, x, y)
  389.      Snation *np;
  390.      int x, y;
  391. {
  392.   struct pt_list *sect;
  393.  
  394.   sect = (struct pt_list *) malloc(sizeof(struct pt_list));
  395.   sect->pt.x = x;
  396.   sect->pt.y = y;
  397.   sect->next = np->ptlist;
  398.   np->ptlist = sect;
  399.   np->n_sects++;
  400.   world.map[x][y].owner = np->id;
  401. }
  402.  
  403.  
  404. subtsector(np, x, y)
  405.      Snation *np;
  406.      int x, y;
  407. {
  408.   struct pt_list *sect, *temp;
  409.  
  410.   sect = np->ptlist;
  411.   if (sect->pt.x == x && sect->pt.y == y) {
  412.     temp = sect;
  413.     np->ptlist = sect->next;
  414.     (np->n_sects)--;
  415.     free(temp);
  416.   } else {
  417.     temp = sect;
  418.     while (sect->pt.x != x || sect->pt.y != y && sect->next != NULL) {
  419.       temp = sect;
  420.       sect = sect->next;
  421.     }
  422.     if (sect->pt.x == x && sect->pt.y == y) {
  423.       temp->next = sect->next;
  424.       free(sect);
  425.       (np->n_sects)--;
  426.     } else printf("Error - deleting sector not in list!\n");
  427.   }
  428.   if (np->n_sects == 0) {
  429.     np->ptlist = NULL;
  430.   }
  431. }
  432.  
  433.   /* Destroy a nation:  these things have to be done:
  434.      1. Free up its point list, and return the sectors to owner 0
  435.      2. Free up its army list, and also its army entires in the
  436.         various sector army lists.  This can be done by disbanding
  437.     them all. (?)
  438.      3. Set the coordinates of its capital to (-1, -1), which alerts
  439.         the program that this nation is no more.
  440.    */
  441. destroy_nation(id)
  442.      int id;
  443. {
  444.   struct pt_list *ptlist, *pt_tmp;
  445.   Sarmy *army_list, *ap_tmp;
  446.   Snation *np = &world.nations[id];
  447.   Ssector *sp;
  448.   struct army_id *sect_alist;
  449.   char s[EXECLEN];
  450.  
  451.   if (np->id == 0) {
  452.     return;            /* don't destroy nation 0, ever */
  453.   }
  454.   ptlist = np->ptlist;
  455.  
  456.   while (ptlist) {
  457.       /* return all the sectors */
  458.     world.map[ptlist->pt.x][ptlist->pt.y].owner = 0;
  459.     world.map[ptlist->pt.x][ptlist->pt.y].designation = D_NODESIG;
  460.     world.map[ptlist->pt.x][ptlist->pt.y].n_people = 0;
  461.     pt_tmp = ptlist->next;
  462.     free(ptlist);
  463.     --np->n_sects;
  464.     ptlist = pt_tmp;
  465.   }
  466.   np->ptlist = NULL;
  467.  
  468.   army_list = np->armies;
  469.     /* delete armies while we still have armies in the nation */
  470.   while (army_list) {
  471.     ap_tmp = army_list->next;
  472.     sp = &world.map[army_list->pos.x][army_list->pos.y];
  473.     delete_army_sector(sp, army_list);
  474.     delete_army_nation(np, army_list);
  475.     /*    free(army_list); */
  476.     /*    army_list = ap_tmp; */
  477.     army_list = np->armies;
  478.   }
  479.   np->armies = NULL;
  480.  
  481.     /* set capital to (-1,-1):  this tells dominion that
  482.        the parrot (i mean, nation) is no more
  483.      */
  484.   np->capital.x = -1;
  485.   np->capital.y = -1;
  486. }
  487.  
  488.   /* returns the number of cities in this nation */
  489. get_n_cities(np)
  490.      Snation *np;
  491. {
  492.   Ssector *sp;
  493.   struct pt_list *ptlist = np->ptlist;
  494.   int n_cities = 0;
  495.  
  496.   while (ptlist != NULL) {
  497.     sp = &world.map[ptlist->pt.x][ptlist->pt.y];
  498.     if (sp->designation == D_CITY || sp->designation == D_CAPITAL) {
  499.       ++n_cities;
  500.     }
  501.     ptlist = ptlist->next;
  502.   }
  503.   return n_cities;
  504. }
  505.  
  506.   /* returns the number of civilians in this nation */
  507. get_n_civil(np)
  508.      Snation *np;
  509. {
  510.   Ssector *sp;
  511.   struct pt_list *ptlist = np->ptlist;
  512.   int n_civil = 0;
  513.  
  514.   while (ptlist != NULL) {
  515.     sp = &world.map[ptlist->pt.x][ptlist->pt.y];
  516.     n_civil += sp->n_people;
  517.     ptlist = ptlist->next;
  518.   }
  519.   return n_civil;
  520. }
  521.  
  522.   /* returns the number of soldiers in this nation (includes spirits) */
  523. get_n_soldiers(np)
  524.      Snation *np;
  525. {
  526.   Sarmy *armies = np->armies;
  527.   int n_sold = 0;
  528.  
  529.   while (armies != NULL) {
  530.     n_sold += armies->n_soldiers;
  531.     armies = armies->next;
  532.   }
  533.   return n_sold;
  534. }
  535.  
  536.   /* returns true if a nation with this name does not yet exist */
  537. unique_name(name)
  538.      char name[];
  539. {
  540.   int i;
  541.   for (i = 0; i < NATIONS; ++i) {
  542.     if (strcmp(world.nations[i].name, name) == 0) {
  543.       return 0;            /* found a conflicting name */
  544.     }
  545.   }
  546.   return 1;            /* didn't find it any conflict */
  547. }
  548.  
  549.   /* this is for when the user hits a harmless key, don't give error */
  550. null_key()
  551. {
  552. }
  553.  
  554.   /* returns the first free army id for a nation */
  555. free_army_id(np)
  556.      Snation *np;
  557. {
  558.   Sarmy *ap = np->armies, *ap_prev = np->armies;
  559.   int id;
  560.  
  561.   if (ap == NULL) {
  562.     return 0;
  563.   }
  564.   if (ap->id > 0) {        /* if first slot is unused */
  565.     return 0;
  566.   }
  567.   if (ap->next == NULL) {
  568.     return 1;
  569.   }
  570.   
  571.   while (ap != NULL) {
  572.     if (ap->id > ap_prev->id+1) { /* a space!! */
  573.       id = ap_prev->id + 1;
  574.       return id;
  575.     }
  576.     ap_prev = ap;
  577.     ap = ap->next;
  578.   }
  579.     /* if we have not yet found it, it must be the last one!! */
  580. /*  beep(); refresh(); */
  581.   id = ap_prev->id + 1;
  582.   return id;
  583. }
  584.  
  585.   /* this waits for the user to type a space */
  586. get_space()
  587. {
  588.   fflush(stdin);
  589.   while (getch() != ' ') {
  590.   }
  591. }
  592.  
  593. #ifndef min
  594. min(a,b)
  595.      int a,b;
  596. {
  597.   return (a < b) ? a : b;
  598. }
  599.  
  600. max(a,b)
  601.      int a,b;
  602. {
  603.   return (a > b) ? a : b;
  604. }
  605. #endif
  606.  
  607. statline(s1, s2)        /* print status line with s1 and s2 */
  608.      char s1[], s2[];
  609. {
  610.     /* the stat line goes at the bottom of the screen */
  611.   mvaddstr(LINES-1, 0, s1); /* first string at beginning */
  612.   clrtoeol();
  613.     /* second string at end of line */
  614.   standout();
  615.   mvaddstr(LINES-1, COLS-strlen(s2)-2, s2);
  616.   standend();
  617.   refresh();
  618. }
  619.  
  620.   /* statline2 is like statline, but prints on the second-last line.
  621.      statline2 should be used for instructions while a command is being run,
  622.         (like a move_army).
  623.    */
  624. statline2(s1, s2)
  625.      char s1[], s2[];
  626. {
  627.     /* the stat line goes at the bottom of the screen */
  628.   mvprintw(LINES-2, 0, "%s", s1); /* first string at beginning */
  629.   clrtoeol();
  630.     /* second string at end of line */
  631.   standout();
  632.   mvprintw(LINES-2, COLS-strlen(s2)-2, "%s", s2);
  633.   standend();
  634.   refresh();
  635. }
  636.  
  637.   /* this runs a statline, and then moves to just
  638.      after s1, for a prompt.  used a lot in xmode
  639.    */
  640. statline_prompt(s1, s2)
  641.      char s1[], s2[];
  642. {
  643.   statline(s1, s2);
  644.   move(LINES-1, strlen(s1));
  645.   refresh();
  646. }
  647.  
  648.   /* this runs a statline2, and then moves to just
  649.      after s1, for a prompt.  used a lot in xmode
  650.    */
  651. statline2_prompt(s1, s2)
  652.      char s1[], s2[];
  653. {
  654.   statline2(s1, s2);
  655.   move(LINES-2, strlen(s1));
  656.   refresh();
  657. }
  658.  
  659.   /* runs a statline2, waits for a space to be typed,
  660.      then cleans the statline2 and returns
  661.    */
  662. statline2_err(s1, s2)
  663.      char s1[], s2[];
  664. {
  665.   statline2(s1, s2);
  666.   get_space();
  667.   statline2("", "");
  668. }
  669.  
  670.     /* curses interface */
  671. init_screen()
  672. {
  673.   printf("initializing screen...\r\n");
  674.   initscr();
  675.   savetty();
  676. /*  nonl(); */
  677.   cbreak();
  678.   noecho();
  679.   clear();
  680.   /* OK, now the stdscr is made, must make a couple other windows */
  681.   sectw = newwin(SECTW_SIZE_Y, SECTW_SIZE_X, SECTW_Y, SECTW_X);
  682.   /*  armyw = newwin(ARMYW_SIZE_Y, ARMYW_SIZE_X, ARMYW_Y, ARMYW_X); */
  683.   /* move the point to the user's capital (to start) */
  684.   if (user.map_style == NORMAL_MAP) {
  685.     move(user.cursor.y, user.cursor.x);
  686.   } else {
  687.     move(2*user.cursor.y, user.cursor.x);
  688.   }
  689.   /* refresh(); */
  690. }
  691.  
  692.   /* returns a pointer to the spirit pointer of that given type */
  693. struct spirit_type *get_spirit_type(up, type)
  694.      Suser *up;
  695.      char type[];
  696. {
  697.   int i;
  698.   extern struct spirit_type *spirit_types;
  699.  
  700. /*  printf("user.n_spirit_types = %d\n", up->n_spirit_types); */
  701.   for (i = 0; i < up->n_spirit_types; ++i) {
  702. /* printf("type=%s, spirit_types[%d].type = %s\n", type, i, spirit_types[i].type); */
  703.     if (strcmp(type, spirit_types[i].type) == 0) {
  704.       return &(spirit_types[i]);
  705.     }
  706.   }
  707.   return NULL;
  708. }
  709.  
  710.   /* add to the user's exec_list; write it to file if full.
  711.      If passed string is NULL, DON'T generate exec, and
  712.      write out the whole thing anyway.
  713.    */
  714. gen_exec(s)
  715.      char *s;
  716. {
  717.   FILE *fp, *fopen();
  718.   char exec_file[NAMELEN];
  719.   int i;
  720.   
  721.   sprintf(exec_file, "exec/exec%d", user.id);  
  722.  
  723.     /* first add the string s to the user's exec_lines;
  724.        special case if string is empty or NULL:
  725.        if empty, do nothing;
  726.        if NULL, write out to file.
  727.      */
  728.   if ((s != NULL) && (strlen(s) == 0)) {
  729.     return;
  730.   }
  731.   if (s != NULL) {
  732.     strcpy(user.exec_lines[user.n_execs], s);
  733.     ++user.n_execs;
  734.   }
  735.   if ((user.n_execs >= N_EXECS) || (s == NULL) ) {
  736.     if ((fp = fopen(exec_file, "a")) == NULL) {
  737.       printf("cannot open your exec file, this is serious\n");
  738.       clean_exit();
  739.       exit(1);
  740.     }
  741.     critical();
  742.     for (i = 0; i < user.n_execs; ++i) {
  743.       fprintf(fp, "%s", user.exec_lines[i]);
  744.       /*      printf("debug: writing to exec file: %s", user.exec_lines[i]); */
  745.     }
  746.     fclose(fp);
  747.     noncritical();
  748.     user.n_execs = 0;        /* reset count */
  749.   }
  750. }
  751.  
  752.  
  753. /* This just displays the title/intro screen */
  754. intro(wp, np)
  755.      Sworld *wp;
  756.      Snation *np;
  757. {
  758.   FILE *mail;
  759.   char txt[200];
  760.  
  761.   sprintf(txt, "mail/mail.%d", np->id);
  762.   mail = fopen(txt, "r");
  763.   strcpy(txt, "Dominion");
  764.   mvprintw((LINES-12)/2, (COLS-strlen(txt))/2, txt);
  765.   sprintf(txt, "Version %s", VERSION);
  766.   mvprintw((LINES-10)/2, (COLS-strlen(txt))/2, txt);
  767.   standout();
  768.   strcpy(txt, "Copyright (c) 1990, Free Software Foundation");
  769.   mvprintw((LINES-6)/2, (COLS-strlen(txt))/2, txt);
  770.   standend();
  771.   sprintf(txt, "Thon %d", wp->turn);
  772.   mvprintw((LINES-2)/2, (COLS-strlen(txt))/2, txt);
  773.   sprintf(txt, "%d nations", wp->n_nations);
  774.   mvprintw(LINES/2, (COLS-strlen(txt))/2, txt);
  775.   sprintf(txt, "world size is %d across, %d down", wp->xmax, wp->ymax);
  776.   mvprintw((LINES-2)/2, (COLS-strlen(txt))/2, txt);
  777.   standout();
  778.   if (mail) {
  779.     strcpy(txt, "You have mail!");
  780.     mvprintw((LINES+6)/2, (COLS-strlen(txt))/2, txt);
  781.     fclose(mail);
  782.   }
  783.   strcpy(txt, "Press any key to begin");
  784.   mvprintw((LINES+10)/2, (COLS-strlen(txt))/2, txt);
  785.   standend();
  786.   refresh();
  787.   getch();
  788.   clear();
  789. }
  790.  
  791.   /* check the mag_Orders file, and see if this is a valid magic order */
  792. is_good_order(name)
  793.      char name[];
  794. {
  795.   int good = 0;
  796.   FILE *fp, *fopen();
  797.   char line[200];
  798.   int i, n_orders;
  799.  
  800.   if ((fp = fopen(MAG_ORDERS, "r")) == NULL) {
  801.     printf("cannot find file %s.  this is bad.\n", MAG_ORDERS);
  802.     clean_exit();
  803.     exit(1);
  804.   }
  805.   while (fgets(line, 200, fp) != NULL) {
  806.     /*    printf("%s", line); */
  807.     if (line[0] != '#') {
  808.       sscanf(line, "%d", &n_orders);
  809.       break;            /* we got the number of orders */
  810.     }
  811.   }
  812.   /*  printf("there are %d magical orders\n", n_orders); */
  813.   for (i = 0; i < n_orders; ) {
  814.     fgets(line, NAMELEN, fp);
  815.     if (line[strlen(line)-1] == '\n') {
  816.       line[strlen(line)-1] = '\0';
  817.     }
  818.     if (line[0] != '#') {
  819.       if (strncmp(line, name, NAMELEN) == 0) {
  820.     good = 1;
  821.       }
  822.       ++i;
  823.     }
  824.   }
  825.   return good;
  826. }
  827.  
  828.   /* returns true if there is at least one
  829.      non-hidden army on this sector.
  830.    */
  831. has_visible_army(sp, up)
  832.      Ssector *sp;
  833.      Suser *up;
  834. {
  835.   struct armyid *alist = sp->alist;
  836.   Sarmy *ap, *get_army();
  837.   int found = 0;
  838.  
  839.   while (alist) {
  840.     ap = get_army(&world.nations[alist->owner], alist->id);
  841.     if (!is_hidden(ap)) {
  842.       found = 1;
  843.       break;
  844.     }
  845.     alist = alist->next;
  846.   }
  847.   return found;
  848. }
  849.  
  850.   /* this routine goes through the entire map and figures out
  851.      which sectors are visible by the user.
  852.    */
  853. find_visible_sectors(visible_sectors)
  854.      int **visible_sectors;
  855. {
  856.   int x, y, i, j;
  857.   struct pt_list *plist;
  858.   Sarmy *ap;
  859.   Ssector *sp;
  860.  
  861.   for (i = 0; i < world.xmax; ++i) {
  862.     for (j = 0; j < world.ymax; ++j) {
  863.       visible_sectors[i][j] = viewall ? SEE_ALL : SEE_NOTHING;
  864.     }
  865.   }
  866.   for (plist = user.np->ptlist; plist != NULL; plist = plist->next) {
  867.     x = plist->pt.x;
  868.     y = plist->pt.y;
  869.     visible_sectors[x][y] = SEE_ALL;
  870.     for (i = x-LAND_SIGHT; i <= x+LAND_SIGHT; ++i) {
  871.       for (j = y-LAND_SIGHT; j <= y+LAND_SIGHT; ++j) {
  872.     sp = &world.map[(*wrapx)(i,j)][(*wrapy)(i,j)];
  873.     if (has_hidden(sp) && sp->owner != user.id) {
  874.       visible_sectors[x][y] |= SEE_ARMIES;
  875.     } else {
  876.       visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |=
  877.         (SEE_LAND_WATER | SEE_OWNER | SEE_DESIG | SEE_POPULATION);
  878.     }
  879.     if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner == 0) {
  880.       visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |= SEE_RESOURCES;
  881.     }
  882.       }
  883.     }
  884.   }
  885.   for (ap = user.np->armies; ap != NULL; ap = ap->next) {
  886.     x = ap->pos.x;
  887.     y = ap->pos.y;
  888.     sp = &world.map[x][y];
  889.     if (has_hidden(sp) && sp->owner != user.id) {
  890.       visible_sectors[x][y] = SEE_ARMIES;
  891.     } else {
  892.       visible_sectors[x][y] = SEE_ALL;
  893.     }
  894.     for (i = x-ARMY_SIGHT; i <= x+ARMY_SIGHT; ++i) {
  895.       for (j = y-ARMY_SIGHT; j <= y+ARMY_SIGHT; ++j) {
  896.     sp = &world.map[(*wrapx)(i,j)][(*wrapy)(i,j)];
  897.     if (!has_hidden(sp)) {
  898.       visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |=
  899.         (SEE_LAND_WATER | SEE_OWNER | SEE_DESIG |
  900.          SEE_POPULATION | SEE_ARMIES);
  901.     }
  902.     if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner == 0) {
  903.       visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |= SEE_RESOURCES;
  904.     }
  905.       }
  906.     }
  907.   }
  908. }
  909.  
  910. /* Returns a string that formats the arguments */
  911.  
  912. char * contents (money, metal, jewels, food, people, army, title, sp)
  913.  
  914. int money, metal, jewels, food, people, army, sp;
  915. Pt * title;
  916. {
  917.   char * rcontents;
  918.   char tmps [60];
  919.  
  920.   if ((rcontents = (char *)malloc (sizeof (char) * 100)) == NULL) {
  921.     clean_exit();
  922.     exit (-1);
  923.   }
  924.  
  925.   sprintf (rcontents, "");
  926.  
  927.   if (money > 0) {
  928.     sprintf (tmps, "/%d sk.", money);
  929.     strcat (rcontents, tmps);
  930.   }
  931.   if (metal > 0) {
  932.     sprintf (tmps, "/%d met", metal);
  933.     strcat (rcontents, tmps);
  934.   }
  935.   if (jewels > 0) {
  936.     sprintf (tmps, "/%d jwl", jewels);
  937.     strcat (rcontents, tmps);
  938.   }
  939.   if (food > 0) {
  940.     sprintf (tmps, "/%d food", food);
  941.     strcat (rcontents, tmps);
  942.   }
  943.   if (people > 0) {
  944.     sprintf (tmps, "/%d peop", people);
  945.     strcat (rcontents, tmps);
  946.   }
  947.   if (army >= 0) {
  948.     sprintf (tmps, "/army %d", army);
  949.     strcat (rcontents, tmps);
  950.   }
  951.   if (title && title->x != -1) {
  952.     sprintf (tmps, "/sect %d,%d",
  953.          xrel (title->x, title->y, user.np->capital),
  954.          yrel (title->x, title->y, user.np->capital));
  955.     strcat (rcontents, tmps);
  956.   }
  957.   if (sp > 0) {
  958.     sprintf (tmps, "/%d sp", sp);
  959.     strcat (rcontents, tmps);
  960.   }
  961.  
  962.   if (rcontents [0] == '/') {
  963.     strcpy (rcontents, rcontents + 1);
  964.   }
  965.  
  966.   return rcontents;
  967. }
  968.  
  969. int univ_intel (np)
  970.  
  971. Snation * np;
  972. {
  973.   double sqrt ();
  974.   int ret;
  975.  
  976.   if (get_n_civil (np)) {
  977.     ret = (int) (100 * get_n_students (np) / get_n_civil (np));
  978.   }
  979.   else { ret = 0; }
  980.  
  981.   return ret;
  982. }
  983.  
  984.   
  985. /*
  986.   if (get_n_civil (np)) {
  987.     ret = (int) sqrt ((double)(get_n_students (np) / 5));
  988.     if (ret > 100) {
  989.       ret = 100;
  990.     }
  991.     return ret;
  992.   }
  993.   return 0;
  994. */
  995.  
  996. int priestliness (np)
  997.  
  998. Snation * np;
  999. {
  1000.   double sqrt ();
  1001.   int ret;
  1002.  
  1003.   if (get_n_civil (np)) {
  1004.     ret = (int) (100 * get_n_priests (np) / get_n_civil (np));
  1005.   }
  1006.   else { ret = 0; }
  1007.  
  1008.   return ret;
  1009. }
  1010. /*  if (get_n_civil (np)) {
  1011.     ret = (int) sqrt ((double)(get_n_priests (np) / 5));
  1012.     if (ret > 100) {
  1013.       ret = 100;
  1014.     }
  1015.     return ret;
  1016.     }
  1017.   return 0;
  1018. */
  1019.