home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / dominion / part20 / addnation.c next >
C/C++ Source or Header  |  1992-02-11  |  25KB  |  979 lines

  1.   /* addnation.c -- primitive program to add a nation to the world */
  2.  
  3. /*
  4.  * Copyright (C) 1990 Free Software Foundation, Inc.
  5.  * Written by the dominion project.
  6.  *
  7.  * This file is part of dominion.
  8.  *
  9.  * dominion is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License as published
  11.  * by the Free Software Foundation; either version 1, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This software is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this software; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <signal.h>
  27.  
  28. #include "dominion.h"
  29. #include "misc.h"
  30. #include "army.h"
  31.  
  32. #define INIT_CIV 10000
  33. #define RADIUS 8        /* minimum distance from other nations */
  34. #define MAX_TRIES 10000        /* max tries to find a good capital */
  35.  
  36. extern Sworld world;
  37. extern Suser user;
  38. extern struct race_list *races;    /* list of races */
  39. extern struct army_type *army_types; /* array of available armies */
  40. extern char libdir[];
  41. extern int debug;
  42. extern int (*wrapx)(), (*wrapy)();
  43.  
  44. char get_nation_mark ();
  45. int sigquit();
  46.  
  47. Sdiplo **allocate_diplo();
  48.  
  49. main(argc, argv)
  50.      int argc;
  51.      char *argv[];
  52. {
  53.   int npcs_get_mail = 0;
  54.   extern int interrupt();
  55.   int n;
  56.   int c;
  57.   extern char *optarg;
  58.   extern int optind;
  59.   char add_fn[255];        /* get NPCs from this file name */
  60.  
  61.   stdscr = NULL;        /* to know if curses is initialized */
  62.   add_fn[0] = '\0';
  63.   strcpy(libdir, DEF_LIBDIR);
  64.   while ((c = getopt(argc, argv, "md:f:x")) != EOF) {
  65.     switch (c) {
  66.     case 'm':            /* make these NPCs get mail */
  67.       npcs_get_mail = 1;
  68.       break;
  69.     case 'x':            /* set debugging mode */
  70.       debug = 1;
  71.       break;
  72.     case 'd':            /* set the LIBDIR path */
  73.       strcpy(libdir, optarg);
  74.       break;
  75.     case 'f':            /* the name of the file with NPCs */
  76.       strcpy(add_fn, optarg);
  77.       break;
  78.     default:
  79.       break;
  80.     }
  81.   }
  82.   if (chdir(libdir) == -1) {
  83.     fprintf(stderr,"Error: cannot cd to directory %s\n",libdir);
  84.     clean_exit();
  85.     exit();
  86.   }
  87.  
  88.   SRND(time((long *) 0L));    /* initialize random number generator */
  89.  
  90.   read_world(&world, WORLD_FILE);
  91.   read_races();
  92.  
  93.   if (!verify_gamemaster()) {
  94.     printf("Hey, you can't add a nation!\n");
  95.     clean_exit();
  96.     exit(1);
  97.   }
  98.  
  99.   if (is_master_lock()) {
  100.     printf("\nThere is a master lock\n");
  101.     clean_exit();
  102.     exit(1);
  103.   }
  104.   set_master_lock();
  105.   if (is_any_lock()) {
  106.     printf("There is a lock;you should make sure the nation is not playing\n");
  107.     del_master_lock();
  108.     clean_exit();
  109.     exit(1);
  110.   }
  111.   /* initialize curses if we are adding a
  112.      nation interactively (i.e. not NPCs)
  113.    */
  114.   if (strlen(add_fn) == 0) {
  115.     initscr();            /* Initialize curses */
  116.     cbreak();            /* set cbreak mode */
  117.     noecho();            /* unset echo mode */
  118.   }
  119.   noncritical();
  120.  
  121.   if ((n = find_free_nation(&world)) == -1) {
  122.     printf("No free nations, sorry.\n");
  123.     clean_exit();
  124.     exit(1);
  125.   }
  126.  
  127.   if (debug) {
  128.     printf("First free nation id is %d.\n", n);
  129.   }
  130.  
  131.   fflush(stdin);
  132.  
  133.   if (stdscr) {
  134.     refresh();
  135.   }
  136.  
  137.   /* check if we are adding NPCs from file add_fn[] */
  138.   if (strlen(add_fn) != 0) {
  139.       /* MCG Kludge Time */
  140.     char full_path_fn[255];
  141.     strcpy(full_path_fn, "misc/");
  142.     strcat(full_path_fn, add_fn);
  143.     printf("\nAdding NPC nations\n\n");
  144.     add_npcs(full_path_fn, npcs_get_mail);
  145.   } else {            /* else we add a single player */
  146.     add_player(n);
  147.   }
  148.  
  149.   clean_exit();
  150.   return 0;
  151. }
  152.  
  153.   /* inserts a player into the world with id = n */
  154. add_player(n)
  155.      int n;
  156. {
  157.   Snation tmp_nation;            /* as we form the nation */
  158.   char racemark;
  159.   char mag_ord[NAMELEN], pass_try1[NAMELEN], pass_try2[NAMELEN];
  160.  
  161.   clear();
  162.  
  163.   tmp_nation.id = n;
  164.  
  165.   echo();
  166.   mvaddstr(0, 0, "Nation's name: ");
  167.   refresh();
  168. /*  getstr(tmp_nation.name); */
  169.   wget_string(stdscr,tmp_nation.name,NAMELEN);
  170.  
  171.   while (!unique_name(tmp_nation.name)) {  
  172.     clear();
  173.     mvprintw(0, 0, "Sorry, \"%s\" is already taken.", tmp_nation.name);
  174.     mvaddstr(2, 0, "Enter nation's name: ");
  175.     refresh();
  176. /*    getstr(tmp_nation.name); */
  177.     wget_string(stdscr,tmp_nation.name,NAMELEN);
  178.   }
  179.   noecho();
  180.  
  181.   get_crypt_pass("\nEnter the password for your nation: ", pass_try1, stdscr,
  182.          NULL);
  183.   get_crypt_pass("\nType it once more: ", pass_try2, stdscr, NULL);
  184.  
  185.  
  186.   /* make sure user knows their pass. */
  187.   while  (strcmp(pass_try1, pass_try2) != 0){
  188.     clear();
  189.     printw("They don't match, try again\n\r");
  190.     get_crypt_pass("Give nation's password: ", pass_try1, stdscr, NULL);
  191.     get_crypt_pass("\nPlease type it once more: ", pass_try2, stdscr, NULL);
  192.   }
  193.   strcpy(tmp_nation.passwd, pass_try1);
  194.   echo();
  195.  
  196.   printw("\n\rGive your leader's name: ");
  197.   refresh();
  198. /*   getstr(tmp_nation.leader); */
  199.   wget_string(stdscr,tmp_nation.leader,NAMELEN);
  200.   racemark = get_race_mark();
  201.  
  202.   tmp_nation.mark = get_nation_mark();
  203.  
  204.   choose_mag_order(mag_ord);
  205.     /* each magic order brings some advantages.  insert them now */
  206.   add_special_mag(&tmp_nation, mag_ord);
  207.  
  208.   clear();
  209.   refresh();
  210.  
  211.     /* Set up a new, non-NPC nation */
  212.   if (setup_new_nation(tmp_nation.name, tmp_nation.passwd, tmp_nation.leader,
  213.     racemark, tmp_nation.mark, mag_ord, NOT_NPC, 50, 5, 5) < 0) {
  214.     printw("\n\r  Could not add nation %s\n\r", tmp_nation.name);
  215.     refresh();
  216.     noecho();
  217.   } else {
  218.     move(0, LINES-1);
  219.     refresh();
  220.     endwin();
  221.     stdscr = NULL;
  222.     write_world(&world, WORLD_FILE);
  223.   }
  224. }
  225.  
  226.   /* make sure that the guy knows the game master password */
  227. verify_gamemaster()
  228. {
  229.   char s[NAMELEN], *getpass(), *crypt();
  230.   
  231.   get_crypt_pass("Enter game master's password: ", s, NULL, NULL);
  232.   return !strcmp(s, world.nations[0].passwd);
  233. }
  234.  
  235.  
  236. find_free_nation(wp)        /* return first free slot, -1 if none */
  237.      Sworld *wp;
  238. {
  239.   int i;
  240.   for (i = 0; i < NATIONS; ++i) {
  241.     if (strlen(wp->nations[i].name) == 0) {
  242.       return i;            /* found a free one! */
  243.     }
  244.   }
  245.   return -1;
  246. }
  247.  
  248. cleanup()
  249. {
  250. /*  clear(); */
  251.   refresh();
  252. }
  253.  
  254.   /* cleanup and prepare to exit */
  255. clean_exit()
  256. {
  257.   del_master_lock();
  258.   if (stdscr) {
  259.     refresh();
  260.     endwin(); /* end curses */
  261.   }
  262. }
  263.  
  264.   /* initial military setup */
  265. #define INITIAL_SOLDIERS 10*OCCUPYING_SOLDIERS
  266. setup_armies(np)
  267.      Snation *np;
  268. {
  269.   Sarmy army, make_army();
  270.   int i;
  271.   char name [NAMELEN];
  272.  
  273.   load_army_types();
  274.     /* we make 10 armies of equal size. the first one has special handling. */
  275.   army = make_army(army_types[0].type, "Cavemen 0", INITIAL_SOLDIERS/10,
  276.            A_DEFEND, np->id, np->capital);
  277.   army.mvpts = basic_move_rate(np);
  278.   army.mvratio = 100;        /* ration of initial to final move points */
  279.   army.id = 0;            /* make sure, this is FIRST army! */
  280.   if (debug) {
  281.     printf("made a new army: owner=%d,x=%d,y=%d,num=%d", army.owner,
  282.        army.pos.x,army.pos.y,army.n_soldiers);
  283.   }
  284.   army.next = NULL;
  285.   np->armies = (Sarmy *) malloc(sizeof(Sarmy));    /* create army list */
  286.   *(np->armies) = army;
  287.   /* the sector must also have a list of armies */
  288.   world.map[army.pos.x][army.pos.y].alist
  289.     = (struct armyid *) malloc(sizeof(struct armyid));
  290.   world.map[army.pos.x][army.pos.y].alist->owner = army.owner;
  291.   world.map[army.pos.x][army.pos.y].alist->id = army.id;
  292.   world.map[army.pos.x][army.pos.y].alist->next = NULL;
  293.   for (i = 1; i < 10; ++i) {
  294.     sprintf(name, "%s", army_types[0].type);
  295.     army = make_army(army_types[0].type, name, INITIAL_SOLDIERS/10,
  296.              A_DEFEND, np->id, np->capital);
  297.       /* first time around, they move at full rate */
  298.     army.mvpts = basic_move_rate(np);
  299.     army.mvratio = 100;
  300.     army.id = i;
  301.     army.next = NULL;
  302.     insert_army_nation(np, &army, i);
  303.     insert_army_sector(&world.map[army.pos.x][army.pos.y], &army);
  304.   }
  305.   np->n_armies = 10;
  306.     /* figure out bonuses; crude formula for now */
  307.   np->attack = np->race.strength/4 + np->race.intel/12;
  308.   np->defense = np->race.strength/4 + np->race.intel/12;
  309.   np->spy = 0;
  310.   np->secrecy = 0;
  311. }
  312.  
  313.   /* initialize fields in this nation's data structure
  314.      that are relevant to the economy.
  315.    */
  316. setup_economy(np)
  317.      Snation *np;
  318. {
  319.   np->taxes = 10;        /* tax rate, % of income */
  320.   np->charity = 0;        /* money given to the poor */
  321.   np->money = 100000;        /* initial wealth */
  322.   np->jewels = 20000;
  323.   np->metal = 20000;
  324.   np->food = 100000;
  325.     /* default values, until user learns how to use her/his budget screen */
  326.   np->tech_r_d = 30;
  327.   np->tech_r_d_metal = 40;
  328.   np->mag_r_d = 30;
  329.   np->mag_r_d_jewels = 40;
  330.   np->spy_r_d = 0;
  331.   np->cur_mag_r_d = 0;
  332.   np->cur_mag_r_d_jewels = 0;
  333.   np->cur_tech_r_d = 0;
  334.   np->cur_tech_r_d_metal = 0;
  335.   np->cur_spy_r_d = 0;
  336. }
  337.  
  338. get_race_mark()
  339. {
  340.   char racemark;
  341.   int done = 0;
  342.   int race_counter=0;
  343.   struct race_list *rlp;    /* to manipulate the list */
  344.   char tmp_sprintf [70];
  345.  
  346.   clear ();
  347.  
  348.   mvaddstr (2, 0, "Races: ");
  349.   rlp = races;
  350.   while (rlp != NULL) {
  351.     sprintf (tmp_sprintf, "(%c) : %s\n", rlp->race.mark, rlp->race.name);
  352.     mvaddstr (4+race_counter++, 4, tmp_sprintf);
  353.     rlp = rlp->next;
  354.   }
  355.   do {
  356.     mvaddstr (0, 0, "Pick a race and enter its mark: ");
  357.     refresh ();
  358.     racemark = getch();
  359.     done = 0;
  360.     rlp = races;
  361.     while (rlp != NULL) {
  362.       if (rlp->race.mark == racemark) {
  363.     done = 1;
  364.     break;
  365.       }
  366.       rlp = rlp->next;
  367.     }
  368.   } while (!done);
  369.   return racemark;
  370. }
  371.  
  372. setup_race(np,racemark)
  373.      Snation *np;
  374.      char racemark;
  375. {
  376.   struct race_list *rlp;    /* So we can work with the races list */
  377.   
  378.   rlp = races;
  379.   while(rlp != NULL) {
  380.     if (rlp->race.mark == racemark) { /* Did we find that race? */
  381.       np->race = rlp->race;
  382.       return 1;            /* If we found it, return a 1 */
  383.     }
  384.     rlp = rlp->next;
  385.   }
  386.   return -1;            /* We didn't find it */
  387. }
  388.  
  389. setup_skills(np)
  390.      Snation *np;
  391. {
  392.   np->tech_skill = 0;
  393.   np->mag_skill = 0;
  394.   
  395.   /* Nations begin with a certain production and it increases from there */
  396.   
  397.   np->farm_skill = np->race.farming;
  398.   np->mine_skill = np->race.mining;
  399.  
  400.   np->spell_pts = 0;
  401. }
  402.  
  403. choose_mag_order(s)
  404.      char s[];
  405. {
  406.   strcpy(s, "");
  407.   clear ();
  408.   list_mag_orders();
  409.  
  410.   do {
  411.     mvaddstr (0, 0, "Choose one of the listed magical orders: ");
  412.     clrtoeol ();
  413.     refresh ();
  414.     wget_string (stdscr,s,NAMELEN);
  415.   } while (!is_good_order(s));
  416. }
  417.  
  418.   /* sets up the capital and a few outlying sectors; if after
  419.      MAX_TRIES it does not find a good place, it exits.
  420.    */
  421. setup_capital(np)
  422.      Snation *np;
  423. {
  424.   int pref, i, j, x, y, distance, tries,
  425.     remaining_pop = INIT_CIV + RND() % 100, beginning_pop;
  426.   Ssector *sp;
  427.   int radius, n_sects;        /* dist. from capital for other sects */
  428.  
  429.   beginning_pop = remaining_pop;
  430.   tries = 0;
  431.   pref = 0;
  432.   /* a negative capital x-coordinate means we have not found
  433.      a good location for the capital yet.
  434.    */
  435.   x = -1;
  436.   distance = 7;
  437.  
  438.   while (x < 0) {
  439.     distance = max(1, --distance);
  440.     for (i = 0; i < 10; i++) {
  441.       do {
  442.       /* keep trying random sectors as long
  443.          as things aren't good.
  444.        */
  445.     x = RND() % world.xmax;
  446.     y = RND() % world.ymax;
  447.     ++tries;
  448.     if (tries >= MAX_TRIES) {
  449.       printf("  Cannot find space for capital of nation %s\n", np->name);
  450.       return -1;
  451.     }
  452.       } while ((world.map[x][y].owner != 0) || !isolated(x, y) ||
  453.            (!good_altitude(&world.map[x][y], np)) ||
  454.            (world.map[x][y].metal > 0) ||
  455.            (world.map[x][y].jewels > 0));  /*see if it's taken!*/
  456.       if (sect_desire(np, x, y) > pref) {
  457.     pref = sect_desire(np, x, y);
  458.     np->capital.x = x;
  459.     np->capital.y = y;
  460.       }
  461.     }
  462.     for (i = np->capital.x - distance; i <= np->capital.x + distance; i++) {
  463.       for (j = np->capital.y - distance; j <= np->capital.y + distance; j++) {
  464.     if (np->race.pref_alt < SEA_LEVEL) { /* under water race */
  465.       if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner != 0 &&
  466.           world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].altitude >= SEA_LEVEL) {
  467.         x = -1;        /* water race cannot be on land */
  468.       }
  469.     } else {        /* above race */
  470.       if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner != 0 &&
  471.           world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].altitude < SEA_LEVEL) {
  472.         x = -1;        /* land race canot be underwater */
  473.       }
  474.     }
  475.       }
  476.     }
  477.   }
  478.   x = np->capital.x;
  479.   y = np->capital.y;
  480.   putchar('\n');
  481.   np->ptlist = NULL;
  482.   addsector(np, x, y);
  483.   world.map[x][y].n_people = beginning_pop/2; /* half people in capital */
  484.   remaining_pop -= beginning_pop/2;
  485.   world.map[x][y].designation = D_CAPITAL;
  486.   np->n_sects = 1;
  487.  
  488.   radius = 1;
  489.   n_sects = 1;
  490.   while (n_sects < 9) {        /* must give user 9 sectors */
  491.     for (i=x-radius; i<=x+radius; i++) {
  492.       for (j=y-radius; j<=y+radius; j++) {
  493.     if (i != 0 || j != 0) {    /* skip the capital */
  494.       sp = &world.map[wrapx(i,j)][wrapy(i,j)];
  495.       if (sp->owner != 0
  496.           || (np->race.pref_alt >= SEA_LEVEL && sp->altitude < SEA_LEVEL)
  497.           || (np->race.pref_alt < SEA_LEVEL && sp->altitude >= SEA_LEVEL)
  498.           || n_sects >= 9) {
  499.       } else {
  500.         addsector(np, (*wrapx)(i,j), (*wrapy)(i,j));
  501.         sp->n_people = beginning_pop/16;
  502.         remaining_pop -= beginning_pop/16;
  503.         sp->designation = default_desig(sp);
  504. /*        printf("rad %d; %d,%d: %d people, remaining_pop=%d (of %d)\n",
  505.            radius, i, j, sp->n_people, remaining_pop, beginning_pop);
  506. */
  507.         ++n_sects;
  508.       }
  509.     }
  510.       }
  511.     }
  512.     ++radius;            /* try bigger and bigger circles */
  513.   }
  514.     /* now if any people are left, put them in the capital */
  515.   world.map[x][y].n_people += remaining_pop;
  516. /*   printf("Done with nation %s\n", sp->name);*/
  517. /*  printf("capital has %d people\n", world.map[x][y].n_people); */
  518.   return 1;
  519. }
  520.  
  521.   /* this gives a sector a default designation of
  522.      D_FARM unless some other resource is present
  523.    */
  524. default_desig(sp)
  525.      Ssector *sp;
  526. {
  527.   if (sp->jewels > 0) {
  528.     if (sp->metal > sp->jewels) {
  529.       return D_METAL_MINE;
  530.     } else {
  531.       return D_JEWEL_MINE;
  532.     }
  533.   }
  534.   if (sp->metal > 0) {
  535.     return D_METAL_MINE;
  536.   } else {
  537.     return D_FARM;
  538.   }
  539. }
  540.  
  541.   /* the workhorse behind addnation */
  542. setup_new_nation(nation_name, nation_pass, leader_name, nation_race,
  543.          nation_mark, mag_ord, npc_flag, npcagg, npcexp, npciso)
  544.      char nation_name[NAMELEN],nation_pass[PASSLEN],leader_name[NAMELEN],
  545.        mag_ord[NAMELEN], nation_race;
  546.      Symbol nation_mark;
  547.      int npc_flag, npcagg, npcexp, npciso;
  548. {
  549.   Sdiplo **dm_old, **dm_new;
  550.   Snation tmp;
  551.   int n;            /* Free nation ID number */
  552.   char cmd_str[PATHLEN];
  553.  
  554.   if ((n = find_free_nation(&world)) == -1) {
  555.     printf("No free nations, sorry.\n");
  556.     return -1;
  557.   }
  558.  
  559.   tmp.id = n;
  560.   if (!unique_name(nation_name)) { /* Should reject identical names */
  561.     printf("Already have a nation called %s.\n", nation_name);
  562.     return -1;
  563.   }
  564.   strcpy(tmp.name, nation_name);
  565.   strcpy(tmp.passwd, nation_pass);
  566.   strcpy(tmp.leader, leader_name);
  567.   strcpy(tmp.mag_order, mag_ord);
  568.  
  569.   setup_race(&tmp, nation_race);
  570.  
  571.   printf("Doing nation %s\n", nation_name);
  572.  
  573.   if (!free_nation_mark(&world, nation_mark)) {
  574.     printf("  Already have a nation using %c as their nation mark.\n",
  575.        nation_mark);    /* Should reject identical nation marks */
  576.     return(-1);
  577.   }
  578.   tmp.mark = nation_mark;
  579.  
  580.   setup_economy(&tmp);
  581.   setup_skills(&tmp);
  582.  
  583.   tmp.npc_flag = npc_flag;
  584.   tmp.npc_agg = npcagg;
  585.   tmp.npc_iso = npciso;
  586.   tmp.npc_exp = npcexp;
  587.  
  588.   if (setup_capital(&tmp) < 0) { /* Adds a capital and land */
  589.     /* if there is no good place for the nation */
  590.     return -1;
  591.   }
  592.   setup_armies(&tmp);        /* must be done after capital */
  593.  
  594.   world.nations[n] = tmp;    /* OK, now add this nation */
  595.   ++world.n_nations;
  596.  
  597.     /* now update the diplo file, so it is bigger */
  598.   dm_old = allocate_diplo(world.n_nations-1);
  599.   dm_new = allocate_diplo(world.n_nations);
  600.   read_in_diplo(dm_old, world.n_nations-1);
  601.   increase_diplo(dm_old, dm_new, world.n_nations-1, &tmp);
  602.   dump_diplo(NULL, dm_new, world.n_nations);
  603.     /* also make a copy of the initial diplomacy file */
  604.   sprintf(cmd_str, "cp %s %s\n", DIPLO_FILE, INIT_DIPLO_FILE);
  605.   system(cmd_str);
  606.   free_diplo(dm_old, world.n_nations-1);
  607.   free_diplo(dm_new, world.n_nations);
  608.  
  609.   return 1;
  610. }
  611.  
  612. add_npcs(npc_fn, npcs_get_mail)
  613.      char * npc_fn;
  614.      int npcs_get_mail;
  615. {
  616.   FILE *fp;
  617.   char s[110], racemark, nationmark;
  618.   char nation_name[NAMELEN], leader_name[NAMELEN], mag_order[NAMELEN];
  619.   int n_npcs, npc_agg, npc_exp, npc_iso;
  620.   int i;
  621.  
  622.   if ((fp = fopen(npc_fn, "r")) == NULL) {
  623.     printf("Cannot open npc file.\n");
  624.     return;
  625.   }
  626.  
  627.   fgets(s, 100, fp);
  628.   while (s[0] == '#') {        /* Ignoring the comments */
  629.     fgets(s, 100, fp);
  630.   }
  631.   sscanf(s, "%d", &n_npcs);
  632.  
  633.   for (i = 0; i < n_npcs; i++) {
  634.     fgets(s, 100, fp);
  635.     s[strlen(s)-1] = '\0';
  636.     if (s[0] != '#') {
  637.       sscanf(s, "%s : %s : %c : %c : %s : %d : %d : %d", nation_name,
  638.          leader_name, &racemark, &nationmark, mag_order,
  639.          &npc_agg, &npc_exp, &npc_iso);
  640.       if (debug) {
  641.     printf("  Nation: %s\n  Leader: %s\nRacemark: %c\n Ntnmark: %c\n",
  642.            nation_name, leader_name, racemark, nationmark);
  643.     printf("Mag_Ordr: %s\nAgressiv: %d\n  Expand: %d\n Isolate: %d\n\n",
  644.            mag_order, npc_agg, npc_exp, npc_iso);
  645.       }
  646.       if (setup_new_nation(nation_name, world.nations[0].passwd, leader_name,
  647.                racemark, nationmark, mag_order,
  648.                npcs_get_mail ? NPC_MAIL : NPC_NOMAIL,
  649.                npc_agg, npc_exp, npc_iso) < 0) {
  650.     /* if we cannot set up this NPC for whatever reason */
  651.     printf("    Did NOT set up nation %s\n\n", nation_name);
  652.     continue;        /* go on to the next NPC */
  653.       }
  654.     }
  655.   }
  656.   fclose(fp);
  657.   printf("\n");
  658.   write_world(&world, WORLD_FILE);
  659. }
  660.  
  661.   /* critical() for the update/make/add is different from the game */
  662. critical()
  663. {
  664.   signal(SIGINT, SIG_IGN);
  665.   signal(SIGQUIT, SIG_IGN);
  666. }
  667. noncritical()
  668. {
  669.   signal(SIGINT, sigquit);
  670.   signal(SIGQUIT, sigquit);
  671. }
  672.  
  673.  
  674. int sigquit ()
  675. {
  676.   if (stdscr) {
  677.     standout();
  678.     mvprintw(0, 65, "Quitting...");
  679.     standend();
  680.     refresh();
  681.   } else {
  682.     printf("\nQuitting...\n");
  683.   }
  684.   clean_exit();
  685.   exit(1);
  686. }
  687.  
  688. /* Lifted from misc.c and maglib.c */
  689. show_race_w(rp)
  690.      Srace *rp;
  691. {
  692. }
  693.  
  694. list_mag_orders()
  695. {
  696.   int n_orders, i;
  697.   FILE *fp;
  698.   char line[200];
  699.   char **order_list;
  700.   char mag_counter=0;
  701.  
  702.   if ((fp = fopen(MAG_ORDERS, "r")) == NULL) {
  703.     printw("\ncannot find file %s.  this is bad.\n\r", MAG_ORDERS);
  704.     clean_exit();
  705.     exit(1);
  706.   }
  707.   while (fgets(line, 200, fp) != NULL) {
  708.     if (line[0] != '#') {
  709.       sscanf(line, "%d", &n_orders);
  710.       break;            /* we got the number of orders */
  711.     }
  712.   }
  713.   order_list = (char **) malloc(n_orders*sizeof(char *));
  714.  
  715.   mvaddstr (2, 0, "Magical orders: ");
  716.  
  717.   for (i = 0; i < n_orders; ) {
  718.     fgets(line, NAMELEN, fp);
  719.     if (line[0] != '#') {
  720.       mvprintw(3 + mag_counter++, 4, "%s", line);
  721.       order_list[i] = (char *) malloc(NAMELEN*sizeof(char));
  722.       strcpy(order_list[i], line);
  723.       ++i;
  724.     }
  725.   }
  726.  
  727.   fclose(fp);
  728. }
  729.  
  730.   /* prompt a user for a nation mark */
  731. #define valid_nation_mark(c) (strchr(valid_mark_str, c))
  732. char get_nation_mark()
  733. {
  734.   int attempt_counter=0;
  735.   char mark;
  736.   char valid_mark_str[128];
  737.  
  738.   form_valid_mark_str(valid_mark_str);
  739.  
  740.   clear();
  741.  
  742.   mvaddstr(0, 0, "Which nation mark do you want? ");
  743.   refresh();
  744.  
  745.   mark = getch();
  746.   while (!free_nation_mark(&world, mark) || !valid_nation_mark(mark)) {
  747.     if (attempt_counter > 15) {
  748.       attempt_counter = 15;
  749.     }
  750.     if (!free_nation_mark(&world, mark)) {
  751.       mvprintw(2 + attempt_counter++, 0,
  752.         "Sorry, the nation mark %c is taken already.", mark);
  753.     } else if (!valid_nation_mark(mark)) {
  754.       mvprintw(2 + attempt_counter++, 0,
  755.         "Sorry, the nation mark %c is not valid.", mark);
  756.       clrtoeol();
  757.       mvprintw(2 + attempt_counter++, 0, "Valid nation marks are: ");
  758.       mvprintw(2 + attempt_counter++, 0, "%s", valid_mark_str);
  759.       ++attempt_counter;
  760.     }
  761.     mvaddstr(0, 0, "Which nation mark do you want? ");
  762.     refresh();
  763.     mark = getch();
  764.   }
  765.   return mark;
  766.  
  767. #ifdef OLD
  768.   if (!free_nation_mark(&world, mark))  { /* see if it's already used */
  769.     do {
  770.       if (attempt_counter > 20) attempt_counter=20;
  771.       mvprintw (2 + attempt_counter++, 0,
  772.                 "Sorry, the nation mark %c is taken already.", mark);
  773.       mvprintw (0, 0, "Which nation mark do you want: ");
  774.       refresh ();
  775.       mark = getch ();
  776.     } while (!free_nation_mark(&world, mark));
  777.   }
  778.  
  779.   /* now check if it is a nation mark that is not valid
  780.      (like a space, or a dash or a dot or twiddle)
  781.    */
  782.   if (!valid_nation_mark(mark))  {
  783.     do {
  784.       if (attempt_counter > 20) {
  785.     attempt_counter=20;
  786.       }
  787.       mvprintw(2 + attempt_counter++, 0,
  788.            "Sorry, the nation mark %c is not valid.", mark);
  789.       mvprintw(2 + attempt_counter++, 0, "Valid nation marks are: ");
  790.       addstr(valid_mark_str);
  791.       mvprintw(0, 0, "Which nation mark do you want: ");
  792.       refresh();
  793.       mark = getch();
  794.     } while (!free_nation_mark(&world, mark));
  795.   }
  796.   return mark;
  797. #endif /* OLD */
  798. }
  799.  
  800.   /* returns true if there is no owned sector too near this one */
  801. isolated(x, y)
  802. {
  803.   int i, j;
  804.  
  805.   for (i = x-RADIUS; i <= x+RADIUS; ++i) {
  806.     for (j = y-RADIUS; j <= y+RADIUS; ++j) {
  807.         /* see if one of these nearby sectors is owned */
  808.       if (world.map[(*wrapx)(i, j)][(*wrapy)(i, j)].owner != 0) {
  809.     return 0;        /* oops, we are *not* isolated */
  810.       }
  811.     }
  812.   }
  813.   return 1;
  814. }
  815.  
  816.   /* put some stuff into a nation's exec file to get them started with
  817.      the privilege of their magic order.
  818.    */
  819. add_special_mag(np, mag_ord)
  820.      Snation *np;
  821.      char mag_ord[];
  822. {
  823.   char fname[255], line[2*EXECLEN];
  824.   FILE *magfp, *execfp;
  825.   int done = 0;
  826.  
  827.   strcpy(fname, MAG_PREFIX);
  828.   strcat(fname, mag_ord);
  829.   if ((magfp = fopen(fname, "r")) == NULL) {
  830.     clean_exit();
  831.     exit(1);
  832.   }
  833.   sprintf(fname, "exec/exec%d", np->id);
  834.   if ((execfp = fopen(fname, "a")) == NULL) {
  835.     clean_exit();
  836.     exit(1);
  837.   }
  838.   while (!done) {
  839.     if (fgets(line, EXECLEN, magfp) == NULL) {
  840.       fclose(magfp);
  841.       fclose(execfp);
  842.       return;
  843.     }
  844.     if (line[0] != '#') {    /* avoid comments */
  845.       if (strncmp(line, "EXEC:", strlen("EXEC:")) == 0) {
  846. /*    printf("found an exec line %s\n", line);
  847.     refresh();
  848.     getch();
  849.     getch();
  850. */
  851.     fprintf(execfp, "%s", line+strlen("EXEC:"));
  852.       }
  853.     }
  854.   }
  855. }
  856.  
  857. /* Please note that this is the same routine as in cur_stuff.c but linking
  858.    that into this code would require a plethora of other object files to 
  859.    successfully compile.
  860. */
  861.   /* gets a string str of max length len */
  862. wget_string (w, rets, len)
  863.      WINDOW * w;
  864.      char * rets;
  865.      int len;
  866. {
  867.   char s [80];
  868.   int pos, done;
  869.   int x, y, i;
  870.   int oldpos;        /* Used for ^W */
  871.   noecho ();
  872.  
  873.   if (w == NULL) {
  874.     w = stdscr;
  875.   }
  876.  
  877.   pos = 0;
  878.   done = 0;
  879.  
  880.   getyx (w, y, x);
  881.   wrefresh (w);
  882.  
  883.   while (!done) {
  884.     s [pos] = wgetch (stdscr);
  885.     switch (s[pos]) {
  886.     case '\n':
  887.     case '\r':
  888.       s [pos] = '\0';
  889.       done = 1;
  890.       break;
  891.     case '\b':
  892.     case DEL:
  893.       if (pos > 0) {
  894.     pos--;
  895.     s[pos] = '\0';
  896.     wmove (w, y, x + pos);
  897.     waddch (w, ' ');
  898.     wmove (w, y, x + pos);
  899.       }
  900.       break;
  901.     case CTL('U'):
  902.       wmove (w, y, x);
  903.       for (i=0; i < pos; i++) {
  904.     waddch (w, ' ');
  905.       }
  906.       wmove (w, y, x);
  907.       pos = 0;
  908.       s [pos] = '\0';
  909.       break;
  910.     case CTL('W'):
  911.       oldpos = pos;
  912.       while (pos != 0 && s[pos] == ' ') {
  913.     pos --;
  914.       }
  915.       if (pos) {
  916.     pos --;
  917.       }
  918.       while (pos != 0 && s[pos] != ' ') {
  919.     pos --;
  920.       }
  921.       wmove (w, y, x + pos);
  922.       while (oldpos != pos) {
  923.     oldpos--;
  924.     waddch (w, ' ');
  925.       }      
  926.       wmove (w, y, x + pos);
  927.       break;
  928.     default:
  929.       waddch (w, s [pos]);
  930.       pos++;
  931.       break;
  932.     }
  933.     wrefresh (w);
  934.   }
  935.  
  936.   if (pos == 0) {
  937.     return 0;
  938.   }
  939.   s [len-1] = '\0';
  940.   strcpy (rets, s); 
  941.   return 1;
  942. }
  943.  
  944.   /* return true if sector (x, y) has at least n connected sectors
  945.      on land (or in water if (x, y) is in water) surrounding it.
  946.    */
  947. has_connected_mass(x, y, n)
  948.      int x, y, n;
  949. {
  950.   Ssector *sp = &world.map[x][y];
  951.   int n_found = 1, prev_n_found = 1; /* count (x, y) */
  952.   int i, j;
  953.  
  954.   /* go about (x, y) one circle at a time.  after each circle,
  955.      see if any new connected sectors were found.  if none were,
  956.      and n_found < n, then NAH... doesn't work!!  put it off for now.
  957.    */
  958. }
  959.  
  960.   /* makes a list of valid nation marks in the given string;
  961.      a mark is valid if it doesn't make a [d] [n] (nation mark
  962.      display) confusing.  For example, <space>, '.' and so on
  963.      would confuse.
  964.    */
  965. form_valid_mark_str(mark_str)
  966.      char mark_str[];
  967. {
  968.   char tmp_str[128];
  969.  
  970.   strcpy(tmp_str, "");
  971.   /* run through the ascii table (only those chars that are printable) */
  972.   strcat(tmp_str, "!\"#$%&'()*+,");
  973.   /* skip '-' and '.' */
  974.   strcat(tmp_str, "/0123456789:;<=>"); /* now skip '?' */
  975.   strcat(tmp_str, "@ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  976.   strcat(tmp_str, "[\]^_`abcdefghijklmnopqrstuvwxyz{|}");
  977.   strcpy(mark_str, tmp_str);
  978. }
  979.