home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume13 / dominion / part14 < prev    next >
Encoding:
Internet Message Format  |  1992-02-10  |  59.9 KB

  1. Path: uunet!ogicse!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v13i050:  dominion - a multi-player world simulation game, Part14/28
  5. Message-ID: <2453@masterCNA.TEK.COM>
  6. Date: 11 Feb 92 18:24:48 GMT
  7. Article-I.D.: masterCN.2453
  8. Sender: news@masterCNA.TEK.COM
  9. Lines: 1972
  10. Approved: billr@saab.CNA.TEK.COM
  11.  
  12. Submitted-by: rosalia@dirac.physics.sunysb.edu (Mark Galassi)
  13. Posting-number: Volume 13, Issue 50
  14. Archive-name: dominion/Part14
  15. Environment: Unix, curses
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 14 (of 28)."
  26. # Contents:  construct.c update.c
  27. # Wrapped by billr@saab on Tue Feb 11 10:14:54 1992
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'construct.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'construct.c'\"
  31. else
  32. echo shar: Extracting \"'construct.c'\" \(7273 characters\)
  33. sed "s/^X//" >'construct.c' <<'END_OF_FILE'
  34. X/* construct.c -- routines dealing with construction */
  35. X
  36. X/*
  37. X * Copyright (C) 1990 Free Software Foundation, Inc.
  38. X * Written by the dominion project.
  39. X *
  40. X * This file is part of dominion.
  41. X *
  42. X * dominion is free software; you can redistribute it and/or
  43. X * modify it under the terms of the GNU General Public License as published
  44. X * by the Free Software Foundation; either version 1, or (at your option)
  45. X * any later version.
  46. X *
  47. X * This software is distributed in the hope that it will be useful,
  48. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  49. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  50. X * GNU General Public License for more details.
  51. X *
  52. X * You should have received a copy of the GNU General Public License
  53. X * along with this software; see the file COPYING.  If not, write to
  54. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  55. X */
  56. X
  57. X#include "dominion.h"
  58. X#include "misc.h"
  59. X#include "army.h"
  60. X#include "costs.h"
  61. X#include "cur_stuff.h"
  62. X
  63. X#include <stdio.h>
  64. X#include <math.h>
  65. X
  66. Xextern Suser user;
  67. Xextern Sworld world;
  68. Xextern char help_tag[];
  69. Xextern WINDOW * sectw;
  70. X
  71. Xextern int (*wrapx)(), (*wrapy)();
  72. X
  73. X  /* construct a constructible object */
  74. Xconstruct()
  75. X{
  76. X  WINDOW *cw;
  77. X  char c;
  78. X  int done=0;
  79. X  Snation *np = user.np;
  80. X  Ssector *sp =  &world.map[user.cursor.x][user.cursor.y];
  81. X
  82. X  strcpy(help_tag, "Construction");
  83. X
  84. X  if (user.xmode) {
  85. X    cw = NULL;
  86. X  } 
  87. X  else {
  88. X    cw = newwin(6, COLS/2+18, LINES-11, COLS/4-16);
  89. X  }
  90. X
  91. X  while (!done) {
  92. X    if (cw != NULL) {
  93. X      statline("", "construct");
  94. X      mvwprintw(cw, 1, 1, "What type of object do you want to construct? ");
  95. X      mvwprintw(cw, 2, 1, " [f]ortification, [r]oads, [b]ubble");
  96. X      wmove(cw, 3, 1);
  97. X      wclrtobot(cw);
  98. X      box(cw, '|', '-');
  99. X      wrefresh(cw);
  100. X    }
  101. X    else {            /* expert mode */
  102. X      statline_prompt ("Construct: (f,r,b)", "construct");
  103. X    }
  104. X
  105. X    switch (c = mygetch()) {
  106. X    case 'f':
  107. X      construct_fortification(np, sp, cw);
  108. X      break;
  109. X    case 'r':
  110. X      construct_roads(np, sp, cw);
  111. X      break;
  112. X    case 'b':
  113. X      construct_bubble(np, sp, cw);
  114. X      break;
  115. X    case ' ':
  116. X      done = 1;
  117. X      break;
  118. X    default:
  119. X      break;
  120. X    }
  121. X  }
  122. X
  123. X  if (cw != NULL) {
  124. X    wrefresh(cw);
  125. X    delwin(cw);
  126. X  }
  127. X
  128. X  touch_all_wins();
  129. X  statline2("", "");
  130. X  show_armies(sp);
  131. X  return 1;
  132. X}
  133. X
  134. X  /* build fortification on a sector */
  135. Xconstruct_fortification(np, sp, w)
  136. X     Snation *np;
  137. X     Ssector *sp;
  138. X     WINDOW *w;
  139. X{
  140. X  int fort_increase, ret, cost, cost_met;
  141. X  char s[EXECLEN];
  142. X  char c;
  143. X
  144. X  if (sp->owner != user.id) {
  145. X    statline2_err("hit space to go on", "hey dude, this sector is not yours");
  146. X    return -1;
  147. X  }
  148. X  cost = (int) (pow(2.0, (double) sp->defense/10)*FORT_COST_MONEY);
  149. X  cost_met = (int) (pow(2.0, (double) sp->defense/10)*FORT_COST_METAL);
  150. X
  151. X  if (w != NULL) {
  152. X    mvwprintw(w, 3, 1, "Current fort %d; cost for 10 more: %d sk., %d met.",
  153. X          sp->defense, cost, cost_met);
  154. X    mvwprintw(w, 4, 1, "Build ten more (y/n)? ");
  155. X    box(w, '|', '-');
  156. X    wrefresh(w);
  157. X  }
  158. X  else {
  159. X    sprintf (s, "Current: %d, Cost +10 = %d sk., %d met. Build? ",
  160. X         sp->defense, cost, cost_met);
  161. X    statline2 (s, "con_fort");
  162. X  }
  163. X
  164. X  if ((c = getch()) != 'y' && c != 'Y') {
  165. X    statline2 ("", "");
  166. X    return -1;
  167. X  }
  168. X  if (w == NULL) {
  169. X    statline2 ("", "");
  170. X  }
  171. X  fort_increase = 10;
  172. X    /* now see if we can afford the construction */
  173. X  if (cost > user.np->money) {
  174. X    statline2_err("space to go on", "not enough money to construct");
  175. X    return -1;
  176. X  }
  177. X  if (cost_met > user.np->metal) {
  178. X    statline2_err("space to go on", "not enough metal to construct");
  179. X    return -1;
  180. X  }
  181. X
  182. X  /* if we have reached this point, it means we can construct! */
  183. X
  184. X  sp->defense += fort_increase;
  185. X  np->money -= cost;
  186. X  np->metal -= cost_met;
  187. X    /* now prepare the exec string */
  188. X  sprintf(s, "CFORT_SECTOR:%d:%d:%d\n", sp->loc.x, sp->loc.y, fort_increase);
  189. X  gen_exec(s);
  190. X  cmoney(np, -cost);
  191. X  cmetal(np, -cost_met);
  192. X
  193. X  return 1;
  194. X}
  195. X  /* build roads on a sector */
  196. Xconstruct_roads(np, sp, w)
  197. X     Snation *np;
  198. X     Ssector *sp;
  199. X     WINDOW *w;
  200. X{
  201. X  int roads_increase, ret, cost, cost_met;
  202. X  char s[EXECLEN];
  203. X  char c;
  204. X
  205. X  if (sp->owner != user.id) {
  206. X    statline2_err("hit space to go on", "hey dude, this sector is not yours");
  207. X    return -1;
  208. X  }
  209. X  cost = (int) (pow(2.0, (double) sp->roads)*ROADS_COST_MONEY);
  210. X  cost_met = (int) (pow(2.0, (double) sp->roads)*ROADS_COST_METAL);
  211. X
  212. X  if (w != NULL) {
  213. X    mvwprintw(w, 3, 1,
  214. X          "Current roads %d; cost %d sk., %d met.", sp->roads, cost, cost_met);
  215. X    mvwprintw(w, 4, 1, "Build one more (y/n)? ");
  216. X    box(w, '|', '-');
  217. X    wrefresh(w);
  218. X  }
  219. X  else {
  220. X    sprintf (s, "Current: %d, Cost +1 = %d sk., %d met. Build? ",
  221. X         sp->roads, cost, cost_met);
  222. X    statline2 (s, "con_roads");
  223. X  }
  224. X  if ((c = getch()) != 'y' && c != 'Y') {
  225. X    statline2 ("", "");
  226. X    return -1;
  227. X  }
  228. X
  229. X  if (w == NULL) {
  230. X    statline2 ("", "");
  231. X  }
  232. X
  233. X  roads_increase = 1;
  234. X    /* now see if we can afford the construction */
  235. X  if (roads_increase*cost > user.np->money) {
  236. X    statline2_err("space to go on", "not enough money to construct");
  237. X    return -1;
  238. X  }
  239. X  if (roads_increase*cost_met > user.np->metal) {
  240. X    statline2_err("space to go on", "not enough metal to construct");
  241. X    return -1;
  242. X  }
  243. X
  244. X  /* if we have reached this point, it means we can construct! */
  245. X
  246. X  sp->roads += roads_increase;
  247. X  np->money -= roads_increase*cost;
  248. X  np->metal -= roads_increase*cost_met;
  249. X    /* now prepare the exec string */
  250. X  sprintf(s, "CROADS_SECTOR:%d:%d:%d\n", sp->loc.x, sp->loc.y, roads_increase);
  251. X  gen_exec(s);
  252. X  cmoney(np, -roads_increase*cost);
  253. X  cmetal(np, -roads_increase*cost_met);
  254. X
  255. X  return 1;
  256. X}
  257. X
  258. X  /* build a bubble on a sector; allowing a
  259. X     race to live in a sector below (or above)
  260. X     water, when they normally could not.
  261. X   */
  262. Xconstruct_bubble(np, sp, w)
  263. X     Snation *np;
  264. X     Ssector *sp;
  265. X     WINDOW *w;
  266. X{
  267. X  int ret, cost, cost_met;
  268. X  char s[EXECLEN];
  269. X  char c;
  270. X
  271. X  if (sp->owner != user.id) {
  272. X    statline2_err("hit space to go on", "Hey dude, this sector is not yours");
  273. X    return -1;
  274. X  }
  275. X  if (has_bubble(sp)) {
  276. X    statline2_err("hit space to go on", "There already is a bubble!");
  277. X  }
  278. X  cost = BUBBLE_COST;
  279. X  cost_met = BUBBLE_COST_METAL;
  280. X
  281. X  if (w != NULL) {
  282. X    mvwprintw(w, 3, 1, "Cost %d sk., %d met.", cost, cost_met);
  283. X    mvwprintw(w, 4, 1, "Go ahead (y/n)? ");
  284. X    box(w, '|', '-');
  285. X    wrefresh(w);
  286. X  }
  287. X  else {
  288. X    sprintf (s, "Cost = %d sk., %d met. Build? ",
  289. X         cost, cost_met);
  290. X    statline2 (s, "con_bubble");
  291. X  }
  292. X  if ((c = getch()) != 'y' && c != 'Y') {
  293. X    statline2 ("", "");
  294. X    return -1;
  295. X  }
  296. X  if (w == NULL) {
  297. X    statline2 ("", "");
  298. X  }
  299. X
  300. X    /* now see if we can afford the construction */
  301. X  if (cost > user.np->money) {
  302. X    beep();
  303. X    statline2_err("space to go on", "not enough money to construct");
  304. X    return -1;
  305. X  }
  306. X  if (cost_met > user.np->metal) {
  307. X    beep();
  308. X    statline2_err("space to go on", "not enough metal to construct");
  309. X    return -1;
  310. X  }
  311. X
  312. X  /* if we have reached this point, it means we can construct! */
  313. X
  314. X  sp->flags |= SF_BUBBLE;
  315. X  np->money -= cost;
  316. X  np->metal -= cost_met;
  317. X    /* now prepare the exec string */
  318. X  sprintf(s, "FLAG_SET_SECTOR:%d:%d:%d\n", sp->loc.x, sp->loc.y, SF_BUBBLE);
  319. X  gen_exec(s);
  320. X  cmoney(np, -cost);
  321. X  cmetal(np, -cost_met);
  322. X
  323. X  return 1;
  324. X}
  325. X
  326. END_OF_FILE
  327. if test 7273 -ne `wc -c <'construct.c'`; then
  328.     echo shar: \"'construct.c'\" unpacked with wrong size!
  329. fi
  330. # end of 'construct.c'
  331. fi
  332. if test -f 'update.c' -a "${1}" != "-c" ; then 
  333.   echo shar: Will not clobber existing file \"'update.c'\"
  334. else
  335. echo shar: Extracting \"'update.c'\" \(49821 characters\)
  336. sed "s/^X//" >'update.c' <<'END_OF_FILE'
  337. X /* update.c -- update the dominion world */
  338. X
  339. X/*
  340. X * Copyright (C) 1990 Free Software Foundation, Inc.
  341. X * Written by the dominion project.
  342. X *
  343. X * This file is part of dominion.
  344. X *
  345. X * dominion is free software; you can redistribute it and/or
  346. X * modify it under the terms of the GNU General Public License as published
  347. X * by the Free Software Foundation; either version 1, or (at your option)
  348. X * any later version.
  349. X *
  350. X * This software is distributed in the hope that it will be useful,
  351. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  352. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  353. X * GNU General Public License for more details.
  354. X *
  355. X * You should have received a copy of the GNU General Public License
  356. X * along with this software; see the file COPYING.  If not, write to
  357. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  358. X */
  359. X
  360. X#include "dominion.h"
  361. X#include "misc.h"
  362. X#include "army.h"
  363. X#include <stdio.h>
  364. X#include <signal.h>
  365. X#include <math.h>
  366. X
  367. X#define BAKBEFORE 1
  368. X#define BAKAFTER 2
  369. X
  370. Xextern Sworld world;
  371. Xextern Suser user;
  372. Xextern struct race_list *races;    /* list of races */
  373. Xextern struct army_type *army_types; /* array of available armies */
  374. Xextern Sh_spell *hanging_spells;
  375. Xextern char libdir[];
  376. Xextern int debug;
  377. Xextern int (*wrapx)(), (*wrapy)();
  378. XFILE *mailfile;
  379. Xextern struct s_desig_map desig_map[];
  380. Xextern double get_version(), atof();
  381. XSuser *temp_users;
  382. X
  383. Xstruct move_data
  384. X{
  385. X  int moved, adj;
  386. X  double des;
  387. X} **work_data;
  388. X
  389. X
  390. Xmain(argc, argv)
  391. X     int argc;
  392. X     char *argv[];
  393. X{
  394. X  int i, j, k, insector, occuflag, c, bakflag = 0;
  395. X  Snation *np;
  396. X  Ssector *sp;
  397. X  Sarmy *ap, *best;
  398. X  extern char *optarg;
  399. X  extern int optind;
  400. X  char mailname[NAMELEN], passwd[PASSLEN], default_pass[NAMELEN];
  401. X  char mail_subject[80],receiver[NAMELEN];
  402. X
  403. X  strcpy(libdir, DEF_LIBDIR);    /* default libdir */
  404. X  default_pass[0] = '\0';
  405. X
  406. X  if (debug) {
  407. X    printf("libdir=%s,def_libdir=%s\n", libdir, DEF_LIBDIR);
  408. X  }
  409. X
  410. X  while ((c = getopt(argc, argv, "baxp:d:--")) != EOF)
  411. X    switch (c) {
  412. X    case 'b':
  413. X      bakflag |= BAKBEFORE;
  414. X      break;
  415. X    case 'a':
  416. X      bakflag |= BAKAFTER;
  417. X      break;
  418. X    case 'x':
  419. X      debug++;
  420. X      break;
  421. X    case 'd':
  422. X      strcpy(libdir, optarg);
  423. X      break;
  424. X    case 'p':            /* allow user to give passwd on command line */
  425. X      strcpy(default_pass, optarg);
  426. X      break;
  427. X    }
  428. X  if (chdir(libdir) == -1) {
  429. X    fprintf(stderr,"Error: cannot cd to directory %s\n",libdir);
  430. X    clean_exit();
  431. X    exit();
  432. X  }
  433. X
  434. X  if (is_master_lock()) {
  435. X    printf("There is a master lock\n");
  436. X    exit(1);
  437. X  }
  438. X  set_master_lock();
  439. X  if (is_any_lock()) {
  440. X    printf("There is a lock; you should see if the nation is still playing\n");
  441. X    clean_exit();
  442. X    exit(1);
  443. X  }
  444. X  set_update_time();
  445. X  SRND(time(0L));
  446. X  load_army_types();        /* it is important to load these in */
  447. X  load_spirit_types();        /* these must also be loaded */
  448. X
  449. X  if (bakflag & BAKBEFORE) {
  450. X    printf("Backing up data in 'bakbefore' directory\n");
  451. X    backuplib("bakbefore"); }
  452. X  printf("\n\n dominion : Update Module : COMMENCING\n");
  453. X  printf("----------------------------------\n");
  454. X
  455. X  read_world(&world, WORLD_FILE);
  456. X
  457. X  get_crypt_pass("Gamemaster password: ", passwd, NULL, default_pass);
  458. X  if (strcmp(world.nations[0].passwd, passwd)) {
  459. X    printf("\r\nTry again\r\n");
  460. X    get_crypt_pass("Gamemaster password: ", passwd, NULL, default_pass);
  461. X    if (strcmp(world.nations[0].passwd, passwd)) {
  462. X      printf("You must be a gamemaster to update the world!\n");
  463. X      exit(1);
  464. X    }
  465. X  }
  466. X
  467. X  printf("Updating from thon %d to thon %d.\n", world.turn, world.turn+1);
  468. X  world.turn++; /* HAPPY NEW THON */
  469. X
  470. X  /* Run through each nation doing calculations for money, etc. */
  471. X  /* this is a kludge:  we need the user struct for things like spells */
  472. X
  473. X/*  update_npc_diplo(); /* we don't use this any more */
  474. X  load_master_execs();
  475. X  init_work_data(world.xmax, world.ymax);
  476. X    /* you must load each nation before you can load the hanging
  477. X       spells, in case a user cast a spell on an army s/he just made
  478. X       this turn.
  479. X     */
  480. X  for (i=1; i<world.n_nations; ++i) {
  481. X    np = &world.nations[i];
  482. X    if (is_active_ntn(np)) {
  483. X      user.spirit_list = NULL;
  484. X      user.np = np;
  485. X      get_spirits(&user, np->mag_skill);
  486. X      load_nation(i, np);
  487. X
  488. X      if (gets_mail(np)) {
  489. X    sprintf(mailname, "mail%d", i);
  490. X    mailfile = fopen(mailname, "a");
  491. X    fprintf(mailfile,"\n---------MESSAGE FROM UPDATE PROGRAM---------\n");
  492. X    fprintf(mailfile, "During the time between thon %d and thon %d...\n",
  493. X         world.turn-1, world.turn);
  494. X    fclose(mailfile);
  495. X      } else {
  496. X    mailfile = NULL;
  497. X      }
  498. X    }
  499. X  }
  500. X  load_h_spells(NULL);
  501. X  docargos();            /* picks up cargos dropped by caravans */
  502. X  for (i = 1; i < world.n_nations; ++i) {
  503. X    np = &world.nations[i];
  504. X    if (is_active_ntn(np)) {
  505. X
  506. X      user.id = i;
  507. X      user.np = &world.nations[i];
  508. X
  509. X      /* start the user off with all spells s/he deserves.
  510. X         note that, because of spirits, this has to be done
  511. X         before load_nation(), since the spirit list is used
  512. X         in the exec parsing.  THIS MIGHT NOT BE TRUE ANY MORE.
  513. X         It still is true. moreso than ever -SHU
  514. X        */
  515. X      user.spell_list = NULL;
  516. X      user.spirit_list = NULL;
  517. X        /* prepare for sending them mail */
  518. X      if (gets_mail(np)) {
  519. X    sprintf (mailname, "mail%d", i);
  520. X    mailfile = fopen(mailname, "a");
  521. X      } else {
  522. X    mailfile = NULL;
  523. X      }
  524. X      printf(" - - - - - - updating nation %s (%d) %s - - - - - -\n",
  525. X          np->name, i, (np->npc_flag)?"[npc]":" ");
  526. X      fflush(stdout);
  527. X      if (np->npc_flag) {
  528. X    npc_moves(np);
  529. X      }
  530. X      dotechno (np, mailfile);
  531. X      dospy(np, mailfile);
  532. X      domagic(np, mailfile);
  533. X      domoney(np);
  534. X      dometal(np);
  535. X      dojewels(np);
  536. X      dofood(np);
  537. X      docivilians(np);
  538. X      load_dead_hspells(&user,1);
  539. X
  540. X      if (mailfile) { fclose (mailfile); }
  541. X    }
  542. X  }
  543. X  dobattles();
  544. X  take_sectors();
  545. X  update_diplo();
  546. X  reset_armies();
  547. X  send_mail();
  548. X  post_statistics();
  549. X    /* clears the hanging spells before writing the world */
  550. X  clear_dead_hspells();
  551. X
  552. X  clear_h_spells();
  553. X  write_h_spells();
  554. X  
  555. X  printf("Saving world data...\n");
  556. X  fflush(stdout);
  557. X  write_world(&world, WORLD_FILE);
  558. X
  559. X  system("rm -f exec/exec*");
  560. X
  561. X  if (bakflag & BAKAFTER) {
  562. X    printf("Backing up data in 'bakafter' directory.\n");
  563. X    backuplib("bakafter"); }
  564. X  printf("----------------------------------\n");
  565. X  printf(" dominion : Update module : COMPLETE\n\n");
  566. X    /* at the end, remove the cargo file */
  567. X    /* remove the master lock file */
  568. X  del_master_lock();
  569. X}
  570. X
  571. X  /* This will send mail to each nation that has a mail temp file. */
  572. Xsend_mail()
  573. X{
  574. X  char mailname[200], receiver[200], mail_subject[200];
  575. X  int i;
  576. X
  577. X  printf("Sending mail... "); fflush(stdout);
  578. X
  579. X  sprintf(mail_subject,"Update to thon %d", world.turn);
  580. X  for (i = 1; i < world.n_nations; i++) {
  581. X    sprintf(mailname, "mail%d", i);
  582. X    mailfile = fopen(mailname, "r");
  583. X    if (mailfile) {
  584. X      fclose (mailfile);
  585. X      sprintf(receiver,"%s of %s",
  586. X          world.nations[i].leader, world.nations[i].name);
  587. X      if (debug) {
  588. X    printf("Sending mail to %s using file %s.\n",world.nations[i].name,
  589. X           mailname);
  590. X    printf("Receiver => %s\n",receiver);
  591. X      }
  592. X        /* make sure we send no mail to NPCs */
  593. X      if (gets_mail(&world.nations[i])) {
  594. X    if (mail_send(mailname, 0, i, mail_subject) > 0) {
  595. X      fprintf(stderr,"Couldn't send mail to nation %d\n",i);
  596. X    }
  597. X      }
  598. X      unlink(mailname);
  599. X    }
  600. X  }
  601. X  printf("done.\n");
  602. X  fflush(stdout);
  603. X}
  604. X
  605. X
  606. X/* This will backup the lib directory either before an update, after an
  607. X   update, or both.  */
  608. Xbackuplib(dirname)
  609. X     char dirname[];
  610. X{
  611. X  char cmdstr[200];
  612. X
  613. X  sprintf(cmdstr, "/bin/rm -fr %s\n", dirname);
  614. X  if (debug) printf("%s", cmdstr);
  615. X  system(cmdstr);
  616. X  sprintf(cmdstr, "/bin/mkdir %s\n", dirname);
  617. X  if (debug) printf("%s", cmdstr);
  618. X  system(cmdstr);
  619. X  sprintf(cmdstr,
  620. X       "/bin/cp -r doc magic misc exec mail news world dom_diplo %s\n",
  621. X       dirname);
  622. X  if (debug) { printf("%s", cmdstr); }
  623. X  system(cmdstr);
  624. X}
  625. X
  626. X
  627. X/* This function is called at the end of the update to change all armies
  628. X   that are in occupy mode to defend mode.  It also restores full move
  629. X   points to all armies.
  630. X */
  631. X
  632. X/* HOLD IT:  shouldn't this be done with the nation army lists instead
  633. X   of sector army lists?  many sectors will have no armies, so it is
  634. X   a waste to traverse the whole map.
  635. X */
  636. Xreset_armies()
  637. X{
  638. X  Sarmy *ap, *next_ap;
  639. X  Sspirit *spiritp = NULL, *get_spirit_from_type();
  640. X  struct army_type this_atype;
  641. X  extern struct army_type *army_types;
  642. X  struct spirit_type this_spirit_type;
  643. X  extern struct spirit_type *spirit_types;
  644. X  Snation *np;
  645. X  Ssector *sp;
  646. X  int i, j;
  647. X  FILE *mfile, *fopen();
  648. X  char mailfname[PATHLEN];
  649. X
  650. X  printf("Resetting armies...\n");
  651. X  fflush(stdout);
  652. X  for(j = 0; j < world.n_nations; ++j) {
  653. X    np = &world.nations[j];
  654. X    sprintf(mailfname, "mail%d", j);
  655. X    mfile = fopen(mailfname, "a");
  656. X    ap = np->armies;
  657. X    for(i=0; ap != NULL; ++i) {
  658. X      next_ap = ap->next;
  659. X      sp = &world.map[ap->pos.x][ap->pos.y];
  660. X      if (ap->status == A_OCCUPY) {
  661. X    ap->status = A_DEFEND;
  662. X      }
  663. X      ap->mvpts = army_move_rate(np, ap);
  664. X        /* make sure that armies are not too small for patrol/intercept */
  665. X      if ((ap->status == A_PATROL || ap->status == A_INTERCEPT)
  666. X      && !can_patrol(ap)) {
  667. X    ap->status = A_DEFEND;
  668. X      }
  669. X        /* patrol and garrison move less */
  670. X      if (ap->status == A_PATROL || ap->status == A_GARRISON) {
  671. X    ap->mvpts /= 2;
  672. X      }
  673. X      if (ap->status == A_INTERCEPT) {
  674. X    ap->mvpts = 0;
  675. X      }
  676. X        /* if they were in a fort, add some bonus */
  677. X      if (is_army(ap)) {
  678. X    if (sp->owner == np->id && sp->designation == D_FORT) {
  679. X      ap->sp_bonus += FORT_BONUS_INCREASE;
  680. X    }
  681. X      }
  682. X        /* make sure that armies and spirits have their permanent flags */
  683. X      if (is_army(ap)) {
  684. X    this_atype = army_types[army_type_index(ap->type)];
  685. X    ap->flags |= this_atype.flags;
  686. X      }
  687. X      if (is_spirit(ap)) {
  688. X    this_spirit_type = spirit_types[spirit_type_index(ap->type)];
  689. X    ap->flags |= this_spirit_type.flags;
  690. X      }
  691. X      if (is_mage(ap)) {
  692. X    ap->flags |= AF_WIZARD;
  693. X      }
  694. X        /* special handling of the INVERSE_ALT flag:  if they
  695. X       are a land race, it becomes a WATER flag;  if they
  696. X       are a water race, it becomes a LAND flag.
  697. X     */
  698. X      if (ap->flags & AF_INVERSE_ALT) {
  699. X    if (np->race.pref_alt >= SEA_LEVEL) {
  700. X      ap->flags |= AF_WATER;
  701. X    } else {
  702. X      ap->flags |= AF_LAND;
  703. X    }
  704. X      }
  705. X        /* if they are underwater without the right flag, make them drown */
  706. X      if (!good_army_altitude(np, sp, ap)) {
  707. X    printf("Army %d (%s) in %s %s.  x%d,y%d\n", ap->id, ap->name, np->name,
  708. X           (sp->altitude < SEA_LEVEL) ? "drowned" : "suffocated",
  709. X           ap->pos.x, ap->pos.y);
  710. X    if (mfile) {        /* elaborate printing statement!! */
  711. X      fprintf(mfile, "Your army %d (%s) %s.\n", ap->id, ap->name,
  712. X          (sp->altitude < SEA_LEVEL) ? "drowned" : "suffocated");
  713. X    }
  714. X    delete_army_sector(sp, ap);
  715. X    delete_army_nation(np, ap);
  716. X      }
  717. X
  718. X      ap = next_ap;
  719. X    }
  720. X    if (mailfile) { fclose(mailfile); }
  721. X  }
  722. X  if (mfile) { fclose(mfile); }
  723. X  printf("done.\n");
  724. X  fflush(stdout);
  725. X}
  726. X
  727. X
  728. X
  729. X/* This will check which sectors have armies in them in occupy mode.  If there
  730. X   are two armies in occupy mode, the one with the highest move ratio gets the
  731. X   sector... */
  732. Xtake_sectors()
  733. X{
  734. X  int i, j, k, occuflag, availflag;
  735. X  Ssector *sp;
  736. X  int old_owner;        /* old owner of the sector that was taken */
  737. X  Sarmy *ap, *best, *get_army();
  738. X  int n_armies;            /* how many are in sector */
  739. X  struct armyid *alist;        /* to run through the sector's army list */
  740. X  char mailname[200];
  741. X  Sdiplo **dm, **allocate_diplo();
  742. X
  743. X  dm = allocate_diplo(world.n_nations);
  744. X  read_in_diplo(dm,world.n_nations);
  745. X  
  746. X  for (i = 0; i < world.ymax; i++) /* check each sector for armies */
  747. X    for (j = 0; j < world.xmax; j++) {
  748. X      sp = &(world.map[j][i]);
  749. X      sp->flags &= ~SF_HOSTILE; /* Turn off the old hostility */
  750. X      if (sp->alist != NULL) {     /* we have some armies in this sector */
  751. X    occuflag = 0;        /* is anyone trying to occupy this sector?  */
  752. X    availflag = 1;        /* is this sector available */
  753. X    best = NULL;        /* this keeps track of army with best ratio */
  754. X    alist = sp->alist;
  755. X
  756. X    /* Now we'll run though each army in the sector and try to find      */
  757. X    /* which (if any) are attempting to occupy that sector.  An army can */
  758. X    /* only occupy a sector if it's status is OCCUPY, it has enough      */
  759. X    /* soldiers (OCCUPYING_SOLDIERS) and either the sector is unowned or */
  760. X    /* the nation which owns the sector is the foe of the army and the   */
  761. X    /* sector owner has no armies remaining in the sector.               */
  762. X
  763. X    n_armies = sect_n_armies(sp);
  764. X    for (k = 0; k < n_armies; k++) {
  765. X      ap = get_army(&world.nations[alist->owner], alist->id);
  766. X
  767. X      if (ap->status == A_OCCUPY && ap->n_soldiers >= OCCUPYING_SOLDIERS &&
  768. X          (sp->owner == 0 || 
  769. X           (sp->owner != 0 && 
  770. X        (get_diplo_status(dm,ap->owner,sp->owner) == WAR || 
  771. X         get_diplo_status(dm,ap->owner,sp->owner) == JIHAD)))) {
  772. X
  773. X        if (best == NULL) best = ap; /* if first army checked, best yet */
  774. X        occuflag = 1;    /* yes, someone's trying to get the sector */
  775. X        if (ap->mvratio > best->mvratio) best = ap;
  776. X      }
  777. X
  778. X      /* If sector owner has an army remaining on it, nobody can take it */
  779. X      if (ap->owner == sp->owner) {
  780. X        availflag = 0;
  781. X      }
  782. X      alist = alist->next;    /* now get the next army */
  783. X    }
  784. X
  785. X    if (occuflag && availflag) {
  786. X      old_owner = sp->owner;
  787. X      if (debug) printf("Winner is %s's army %d... ",
  788. X                 world.nations[best->owner].name, best->id);
  789. X      if (best->owner != sp->owner) {
  790. X        if (sp->owner != 0) subtsector(&world.nations[sp->owner], j, i);
  791. X        addsector(&world.nations[best->owner], j, i);
  792. X            if (sp->n_people) {
  793. X            /* If there were any civilians in the sector */
  794. X              sp->flags |= SF_HOSTILE; /* It's hostile for 1 update */
  795. X        }
  796. X        if (gets_mail(&world.nations[old_owner]) && old_owner != 0) {
  797. X          sprintf(mailname, "mail%d", old_owner);
  798. X          mailfile = fopen(mailname, "a");
  799. X        } else {mailfile = NULL; }
  800. X        if (sp->designation == D_CAPITAL) {
  801. X          take_capital(&(world.nations[old_owner]),
  802. X               &(world.nations[best->owner]), mailfile);
  803. X        } else {
  804. X          if (mailfile) {
  805. X        fprintf(mailfile,
  806. X            "Sector %d, %d has been taken from you by %s!\n",
  807. X            xrel(j,i,world.nations[old_owner].capital),
  808. X            yrel(j,i,world.nations[old_owner].capital),
  809. X            world.nations[best->owner].name);
  810. X          }
  811. X        }
  812. X        if (mailfile) {
  813. X          fclose(mailfile);
  814. X        }
  815. X        if (gets_mail(&world.nations[best->owner])) {
  816. X          sprintf(mailname, "mail%d", best->owner);
  817. X          if ((mailfile = fopen(mailname, "a")) == NULL)
  818. X              {
  819. X                fprintf(stderr,"Error: cannot append to %s\n",mailname);
  820. X                clean_exit();
  821. X                exit(1);
  822. X              }
  823. X          fprintf(mailfile, "You successfully captured sector %d, %d!\n",
  824. X              xrel(j,i,world.nations[best->owner].capital),
  825. X              yrel(j,i,world.nations[best->owner].capital));
  826. X          fclose(mailfile);
  827. X        }
  828. X      }
  829. X      else if (debug) printf("They already own that sector!\n");
  830. X    }
  831. X      }
  832. X    }
  833. X  free_diplo(dm,world.n_nations);
  834. X}
  835. X
  836. X/* nation np2 takes capital of nation np1.  mfile is mail file of nation
  837. X   np1.  If np1 has any cities, make the first one their new capital.
  838. X   1/2 of np1's metal, jewels, and money are transferred to np2. */
  839. Xtake_capital(np1, np2, mfile)
  840. X     Snation *np1, *np2;
  841. X     FILE *mfile;
  842. X{
  843. X  struct pt_list *ptlist, *bestpt;
  844. X  int done = 0, x = np1->capital.x, y = np1->capital.y;
  845. X  FILE *news_fp, *fopen();    /* to print this to the news */
  846. X  FILE * sacker;
  847. X  char tmp_name[100];
  848. X  char * contents ();
  849. X  char subj[100];
  850. X
  851. X    /* A temporary file name for this news posting */
  852. X/*  tmp_name = tmpnam(NULL, "dominion"); */
  853. X  strcpy(tmp_name, "dominionXXXXXX");
  854. X  mktemp(tmp_name);
  855. X
  856. X  if (strlen(tmp_name) == 0) {
  857. X    fprintf(stderr, "Error getting temp file name\n");
  858. X    return;
  859. X  }
  860. X  if ((news_fp = fopen(tmp_name, "w")) == NULL) {
  861. X    fprintf(stderr, "Error opening file %s for writing\n", tmp_name);
  862. X    return;
  863. X  }
  864. X  sprintf (subj, "mail%d", np2->id);
  865. X  if ((sacker = fopen (subj, "a")) == NULL) {
  866. X    fprintf (stderr, "Error opening file %s for writing\n", subj);
  867. X    return;
  868. X  }
  869. X  sprintf(subj, "Capital of %s sacked", np1->name);
  870. X  fprintf(news_fp,"\n\nCapital of %s was sacked by %s\n",np1->name,np2->name);
  871. X  fclose(news_fp);
  872. X  post_news_file(tmp_name, NEWS_GROUP,subj,0);
  873. X
  874. X  if (mfile) {
  875. X    fprintf(mfile, "Your capital was captured by %s!\n", np2->name);
  876. X  }
  877. X  printf("   ** %s has lost their capital to %s! **\n", np1->name, np2->name);
  878. X  ptlist = np1->ptlist;
  879. X    /* first we see if we can get another city for capital */
  880. X  while (ptlist != NULL && !done) {
  881. X    if (world.map[ptlist->pt.x][ptlist->pt.y].designation == D_CITY) {
  882. X      done = 1;
  883. X      world.map[ptlist->pt.x][ptlist->pt.y].designation = D_CAPITAL;
  884. X      break;
  885. X    }
  886. X    ptlist = ptlist->next;
  887. X  }
  888. X  if (done) {            /* found a replacement city */
  889. X    if (mfile) {
  890. X      fprintf(mfile, "Your city at %d,%d is your new capital\n",
  891. X          xrel(ptlist->pt.x, ptlist->pt.y, np1->capital),
  892. X          yrel(ptlist->pt.x, ptlist->pt.y, np1->capital));
  893. X    }
  894. X    world.map[ptlist->pt.x][ptlist->pt.y].designation = D_CAPITAL;
  895. X    np1->capital = ptlist->pt;
  896. X  } else {            /* np1 had no more cities!! */
  897. X    if (mfile) {
  898. X      fprintf(mfile, "You have no cities to put your new capital!\n");
  899. X    }
  900. X
  901. X    ptlist = np1->ptlist;       /* give them the most populated sector */
  902. X    if (ptlist) {               /* if they have any left!! */
  903. X      bestpt = ptlist;
  904. X      while (ptlist != NULL) {
  905. X        if (world.map[ptlist->pt.x][ptlist->pt.y].n_people >
  906. X            world.map[bestpt->pt.x][bestpt->pt.y].n_people)
  907. X          bestpt = ptlist;
  908. X    ptlist = ptlist->next;
  909. X      }
  910. X      if (mfile) {
  911. X    fprintf(mfile, "I am putting your new capital at (%d,%d)\n",
  912. X        xrel(bestpt->pt.x, bestpt->pt.y, np1->capital),
  913. X        yrel(bestpt->pt.x, bestpt->pt.y, np1->capital));
  914. X      }
  915. X      np1->capital.x = bestpt->pt.x;
  916. X      np1->capital.y = bestpt->pt.y;
  917. X      world.map[bestpt->pt.x][bestpt->pt.y].designation = D_CAPITAL;
  918. X    } else {            /* if you have no sectors... you die */
  919. X      if (mfile) {
  920. X    fprintf(mfile,"You have no sectors left. Your nation is destroyed.\n");
  921. X      }
  922. X      destroy_nation(np1->id);
  923. X      printf("*** nation %d is destroyed ***\n", np1->id);
  924. X    }
  925. X  }
  926. X  world.map[x][y].designation = D_CITY; /* old capital -> city (for new guy) */
  927. X
  928. X  /* deplete nation */
  929. X  fprintf (sacker, "\nSacked capital of %s.  Gained:\n", np1->name);
  930. X  fprintf (sacker, "\t%s\n\n", contents(max(np1->money/2, 0),
  931. X                      max(np1->metal/2, 0),
  932. X                      max(np1->jewels/2, 0),
  933. X                      max(np1->food/2, 0), 0, -1, NULL, 0));
  934. X  fclose (sacker);
  935. X
  936. X  np2->money += max(np1->money/2, 0); /* don't acquire debts */
  937. X  np1->money = np1->money/2;
  938. X  np2->jewels += max(np1->jewels/2, 0);
  939. X  np1->jewels = np1->jewels/2;
  940. X  np2->metal += max(np1->metal/2, 0);
  941. X  np1->metal = np1->metal/2;
  942. X  np2->food += max(np1->food/2, 0);
  943. X  np1->food =np1->food/2;                      
  944. X}
  945. X
  946. X  /* runs throught the list of sectors belonging to a nation
  947. X     and does things like reproduction and such.
  948. X   */
  949. Xdocivilians(np)
  950. X     Snation *np;
  951. X{
  952. X  int current, born, died, tborn, tdied, rep, mort, i, j;
  953. X  Ssector *sp;
  954. X  struct pt_list *lp;
  955. X
  956. X  rep  = np->race.repro;
  957. X  mort = np->race.mortality;
  958. X  tborn = tdied = 0;
  959. X  lp = np->ptlist;
  960. X  while (lp != NULL) {
  961. X    sp = &world.map[lp->pt.x][lp->pt.y];
  962. X    if (debug) printf ("Doing population in %d,%d\n", lp->pt.x, lp->pt.y);
  963. X    current = sp->n_people;
  964. X    born = (int) (current * rep  / 100.0);
  965. X    died = (int) (current * mort / 100.0);
  966. X    tborn += born;
  967. X    tdied += died;
  968. X    sp->n_people += born - died;
  969. X      /* they might suffocate or drown */
  970. X    if (sp->n_people > 0 && !good_altitude(sp, np)) {
  971. X      printf("%d people %s in sector (%d, %d)\n", sp->n_people,
  972. X         (sp->altitude < SEA_LEVEL) ? "drowned" : "suffocated",
  973. X         sp->loc.x, sp->loc.y);
  974. X      if (mailfile) {
  975. X    fprintf(mailfile, "%d people %s in sector (%d, %d)\n", sp->n_people,
  976. X        (sp->altitude < SEA_LEVEL) ? "drowned" : "suffocated",
  977. X        xrel(sp->loc.x, sp->loc.y, np->capital),
  978. X        yrel(sp->loc.x, sp->loc.y, np->capital) );
  979. X      }
  980. X      sp->n_people = 0;
  981. X    }
  982. X/* Old civ movement code.  Has been replaced.
  983. X    for (i=sp->loc.x-1; i<=sp->loc.x+1; i++)
  984. X      for (j=sp->loc.y-1; j<=sp->loc.y+1; j++) { 
  985. X    if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner == np->id)
  986. X      movepeople(np, sp->loc.x, sp->loc.y, (*wrapx)(i,j), (*wrapy)(i,j));
  987. X      }
  988. X*/
  989. X    lp = lp->next;
  990. X  }
  991. X  clear_work_data(); /* Setup for moving */
  992. X  switch(np->opts->civ_movemode) {
  993. X    case 1: { move_people_restrict(np); break; }
  994. X    case 2: { move_people_free(np); break; }
  995. X    default: { /* the default (0) is to not move at all */; }
  996. X  }
  997. X  if (mailfile) {
  998. X    fprintf(mailfile,
  999. X     "There were %d births and %d deaths, for a population change of %d\n",
  1000. X     tborn, tdied, tborn-tdied);
  1001. X    fprintf(mailfile, "Your nation now has %d civilians\n", get_n_civil(np));
  1002. X  }
  1003. X}
  1004. X
  1005. Xmovepeople(np, a, b, x, y)
  1006. X/* This routine is outdated and should be removed */
  1007. X     Snation *np;
  1008. X     int a, b, x, y;
  1009. X{
  1010. X  int p1, p2, pt2, moved, des1, des2;
  1011. X
  1012. X  if ((a != x || b != y) && world.map[x][y].owner == world.map[a][b].owner) {
  1013. X/*    des1 = max(0,sect_desire(np, a, b));
  1014. X    des2 = max(0,sect_desire(np, x, y));
  1015. X*/
  1016. X      /* desireability = % of people employed */
  1017. X    des1 = emp_desire(np, a, b);
  1018. X    des2 = emp_desire(np, x, y);
  1019. X    p1 = world.map[a][b].n_people;
  1020. X    p2 = world.map[x][y].n_people;
  1021. X/*    pt2 = (des2*(p1+p2))/(des1+des2); /* Potential change in p2 */
  1022. X
  1023. X/*    moved = (pt2 - p2)/4; /* Move 1/4 of potential change to p2 */
  1024. X/*    moved /= 4;            /* make even fewer people move */
  1025. X    moved = (p1*(100-des1))/400 - (p2*(100-des2))/400;
  1026. X    moved = min(moved, p1);
  1027. X      /* hold it!! we cannot move people underwater without bubbles */
  1028. X    if (!good_altitude(&world.map[a][b], np)
  1029. X    || !good_altitude(&world.map[x][y], np)) {
  1030. X      moved = 0;
  1031. X    }
  1032. X    p2 += moved;
  1033. X    p1 -= moved;
  1034. X    world.map[a][b].n_people = p1;
  1035. X    world.map[x][y].n_people = p2;
  1036. X    if (debug) printf ("Moved %d people from %d,%d to %d,%d\n", moved, a, b, x, y);
  1037. X  }
  1038. X}
  1039. X
  1040. Xdomoney(np)
  1041. X     Snation *np;
  1042. X{
  1043. X  int temp;
  1044. X
  1045. X  temp = np->money;
  1046. X  np->money = next_thon_money(np);
  1047. X    temp / 100;
  1048. X
  1049. X  if (mailfile) fprintf(mailfile, "Your net MONEY change is %d, bringing your total to %d\n", np->money-temp, np->money);
  1050. X}
  1051. X
  1052. X
  1053. Xdometal(np)
  1054. X     Snation *np;
  1055. X{
  1056. X  int temp;
  1057. X
  1058. X  temp = np->metal;
  1059. X  np->metal = next_thon_metal(np);
  1060. X
  1061. X  if (mailfile) fprintf(mailfile, "Your net METAL change is %d, bringing your total to %d\n", np->metal-temp, np->metal);
  1062. X}
  1063. X
  1064. X  /* calculates the new amount of jewels a nation has,
  1065. X     and if it is negative, it kills off some mages
  1066. X   */
  1067. Xdojewels(np)
  1068. X     Snation *np;
  1069. X{
  1070. X  int temp;
  1071. X  Sarmy *ap, *get_first_mage();
  1072. X  Ssector *sp;
  1073. X
  1074. X  temp = np->jewels;
  1075. X
  1076. X  np->jewels = next_thon_jewels(np);
  1077. X
  1078. X  while (np->jewels < 0) {
  1079. X    if ((ap = get_first_mage (np)) == NULL) {
  1080. X      break;
  1081. X    }
  1082. X    sp = &world.map[ap->pos.x][ap->pos.y];
  1083. X    printf ("\ndeleting mage %d\n", ap->id);
  1084. X
  1085. X    if (mailfile) {
  1086. X      fprintf (mailfile,
  1087. X           "\nYou lost your mage %d because you had no jewels...\n",
  1088. X           ap->id);
  1089. X    }
  1090. X
  1091. X    delete_army_sector (sp, ap);
  1092. X    delete_army_nation (np, ap);
  1093. X    np->jewels += MAGE_JEWELS_MAINT;
  1094. X  }
  1095. X
  1096. X  /* now we have the final data on jewels: report it to mail file */
  1097. X  if (mailfile) {
  1098. X    fprintf(mailfile,
  1099. X        "Your net JEWEL change is %d, bringing your total to %d\n",
  1100. X        np->jewels-temp, np->jewels);
  1101. X  }
  1102. X}
  1103. X
  1104. X
  1105. X  /* calculate the new amount of food.  also takes care of starving */
  1106. Xdofood(np)
  1107. X     Snation *np;
  1108. X{
  1109. X  int n_should_starve, n_starved, n_sold_starved;
  1110. X  int oldfood, n_civil, n_sold, x;
  1111. X  double starved_fraction;
  1112. X  Ssector *sp;
  1113. X  struct pt_list *ptlist = np->ptlist;
  1114. X  Sarmy *ap, *next;        /* for army starvation */
  1115. X  struct argument args[N_EXEC_ARGS];
  1116. X  char s[EXECLEN];
  1117. X
  1118. X  n_civil = get_n_civil(np);
  1119. X  n_sold = get_n_soldiers(np);
  1120. X
  1121. X  oldfood = np->food;
  1122. X  np->food += calc_food(np) - calc_expend_food(np);
  1123. X  if (mailfile) {
  1124. X    if (oldfood == np->food)
  1125. X      fprintf(mailfile, "Your farmers produced as much food as was needed\n");
  1126. X    else if (oldfood < np->food) {
  1127. X      fprintf(mailfile,    "Your farmers produced more food than was consumed\n");
  1128. X      fprintf(mailfile, "Your food in storage increased %d tons, to %d\n",
  1129. X          np->food-oldfood, np->food);
  1130. X    } else if (oldfood > np->food) {
  1131. X      fprintf(mailfile,
  1132. X          "Your farmers did not produce enough to feed everyone\n");
  1133. X      if (np->food >= 0) {
  1134. X    fprintf(mailfile,
  1135. X        "%d tons of food were used from storage, leaving %d tons\n",
  1136. X        oldfood-np->food, np->food);
  1137. X      } else {
  1138. X    fprintf(mailfile, "Your remaining storage, %d tons, was used up\n",
  1139. X           oldfood);
  1140. X      }
  1141. X    }
  1142. X  }
  1143. X  if (np->food < 0) {
  1144. X    printf("people starving in nation %s\n", np->name);
  1145. X      /* all those in cities who cannot eat starve */
  1146. X    n_should_starve = - (int) (np->food / EAT);
  1147. X    if (n_civil == 0) {
  1148. X      starved_fraction = 0;
  1149. X    } else {
  1150. X      starved_fraction = (1.0*n_should_starve)/(1.0*get_n_civil(np));
  1151. X    }
  1152. X      
  1153. X    if (starved_fraction > 1.0) {
  1154. X      starved_fraction = 1.0;
  1155. X    }
  1156. X    n_starved = 0;
  1157. X    while (ptlist != NULL) {
  1158. X      sp = &world.map[ptlist->pt.x][ptlist->pt.y];
  1159. X    n_starved += (int) (starved_fraction*sp->n_people);
  1160. X    sp->n_people -= (int) (starved_fraction*sp->n_people);
  1161. X    if (sp->n_people < 0) {
  1162. X      sp->n_people = 0;
  1163. X    }
  1164. X      ptlist = ptlist->next;
  1165. X    }
  1166. X    if (mailfile) {
  1167. X      fprintf(mailfile,
  1168. X      "%d people starve in your %d sectors, leaving %d surviving civilians.\n",
  1169. X           n_starved, np->n_sects, get_n_civil(np));
  1170. X    }
  1171. X      /* if there is still not enough food, starve soldiers */
  1172. X    if (n_should_starve > n_civil) {
  1173. X      n_sold_starved = (int) (n_should_starve-n_starved)/SOLD_EAT_FACTOR;
  1174. X    } else {
  1175. X      n_sold_starved = 0;
  1176. X    }
  1177. X    
  1178. X    if (get_n_soldiers(np) == 0) {
  1179. X      starved_fraction = 0;
  1180. X    } else {
  1181. X      starved_fraction = (1.0*n_sold_starved)/(1.0*get_n_soldiers(np));
  1182. X    }
  1183. X    if (starved_fraction > 1.0) {
  1184. X      starved_fraction = 1.0;
  1185. X    }
  1186. X    if (n_sold_starved > 0) {
  1187. X      if (mailfile) {
  1188. X    fprintf(mailfile,
  1189. X        "%d of your soldiers will starve too\n", n_sold_starved);
  1190. X      }
  1191. X      ap = np->armies;
  1192. X      while (ap && n_sold_starved > 0) {
  1193. X    x = starved_fraction*ap->n_soldiers;
  1194. X    ap->n_soldiers -= x;
  1195. X    n_sold_starved -= x;
  1196. X    if (x > 0 && mailfile) {
  1197. X      fprintf(mailfile,"in army %d, %d soldiers starve\n", ap->id, x);
  1198. X    }
  1199. X    next = ap->next;
  1200. X    if (ap->n_soldiers <= 0) {
  1201. X      sprintf(s, "ADISBAND:%d\n", ap->id);
  1202. X      parse_exec_line(s,args);
  1203. X      run_exec_line(np,args);
  1204. X    }
  1205. X    ap = next;
  1206. X      }
  1207. X    }
  1208. X    np->food = 0;
  1209. X  }
  1210. X}
  1211. X
  1212. Xcleanup()
  1213. X{
  1214. X  /* not much to do here */
  1215. X}
  1216. X
  1217. Xclean_exit()
  1218. X{
  1219. X  del_master_lock();
  1220. X};
  1221. X
  1222. X  /* reads in the cargo file, then it gives the recipient
  1223. X     nation all the stuff.  if there is an army, it reads
  1224. X     in that army and inserts it into the sector and nation
  1225. X   */
  1226. Xdocargos()
  1227. X{
  1228. X  Scargo cargo;            /* the cargo that is being traded */
  1229. X  int from_id, to_id;
  1230. X  Snation *from_np, *to_np;
  1231. X  char mailname[NAMELEN];
  1232. X  FILE *fp, *fopen(), *mailf, *newsf;
  1233. X  Sarmy army;            /* was an army traded? */
  1234. X  Ssector *traded_sp;        /* was a sector traded? */
  1235. X  Ssector *sp;            /* on which sector does it happen? */
  1236. X  int x, y;            /* location of the trade */
  1237. X  char * contents ();        /* returns string of cargo_contents */
  1238. X
  1239. X  if ((fp = fopen(CARGO_FILE, "r")) == NULL) {
  1240. X    printf("No cargo file\n");
  1241. X    return;
  1242. X  }
  1243. X  critical();
  1244. X  while (fread(&x, sizeof(int), 1, fp) > 0) {
  1245. X    fread(&y, sizeof(int), 1, fp);
  1246. X    fread(&from_id, sizeof(int), 1, fp);
  1247. X    fread(&to_id, sizeof(int), 1, fp);
  1248. X    from_np = &world.nations[from_id];
  1249. X    to_np = &world.nations[to_id];
  1250. X    fread(&cargo, sizeof(Scargo), 1, fp);
  1251. X      /* send mail to the donor, if it does not go to root */
  1252. X    if (to_id != 0) {
  1253. X      if (gets_mail(&world.nations[from_id])) {
  1254. X    sprintf(mailname, "mail%d", from_id);
  1255. X    mailf = fopen(mailname, "a");
  1256. X      } else {mailf = NULL; }
  1257. X      if (mailf) {
  1258. X    fprintf(mailf,
  1259. X        "Cargo given by %s to %s:\n", from_np->name, to_np->name);
  1260. X    fprintf(mailf,"\tCargo=%s\n",
  1261. X        contents (cargo.money, cargo.metal, cargo.jewels,
  1262. X              cargo.food, cargo.people, cargo.army,
  1263. X              &cargo.title, 0));
  1264. X    fclose(mailf);
  1265. X      }
  1266. X        /* send mail to the recipient */
  1267. X      if (gets_mail(&world.nations[to_id])) {
  1268. X    sprintf(mailname, "mail%d", to_id);
  1269. X    mailf = fopen(mailname, "a");
  1270. X      } else {mailf = NULL; }
  1271. X      if (mailf) {
  1272. X    fprintf(mailf,
  1273. X        "Cargo given by %s to %s:\n", from_np->name, to_np->name);
  1274. X    fprintf(mailf,"\tCargo=%s\n",
  1275. X        contents (cargo.money, cargo.metal, cargo.jewels,
  1276. X              cargo.food, cargo.people, cargo.army,
  1277. X              &cargo.title, 0));
  1278. X    fclose(mailf);
  1279. X    printf("wrote to mail files about cargo\n");
  1280. X      }
  1281. X    }
  1282. X    if (debug) {
  1283. X      printf("Got a cargo from nation %d to nation %d\n", from_id, to_id);
  1284. X      printf("\tCargo=%s\n",
  1285. X         contents (cargo.money, cargo.metal, cargo.jewels,
  1286. X               cargo.food, cargo.people, cargo.army,
  1287. X               &cargo.title, 0));
  1288. X    }
  1289. X    fflush(stdout);
  1290. X    to_np->money += cargo.money;
  1291. X    to_np->metal += cargo.metal;
  1292. X    to_np->jewels += cargo.jewels;
  1293. X    to_np->food += cargo.food;
  1294. X      /* put people in the sector */
  1295. X    sp = &world.map[x][y];
  1296. X    sp->n_people += cargo.people;
  1297. X      /* if an army is there, read it in from the file */
  1298. X    if (cargo.army != -1) {
  1299. X      fread(&army, sizeof(Sarmy), 1, fp);
  1300. X      army.owner = to_np->id;
  1301. X      army.flags &= ~AF_IN_TRANSPORT;
  1302. X      insert_army_nation(to_np, &army, -1);
  1303. X      ++to_np->n_armies;
  1304. X      insert_army_sector(sp, &army);
  1305. X    }
  1306. X      /* if there is a sector, give it to the new nation */
  1307. X    if (cargo.title.x != -1 && cargo.title.y != -1) {
  1308. X      Ssector *sp = &world.map[cargo.title.x][cargo.title.y];
  1309. X      subtsector(from_np, cargo.title.x, cargo.title.y);
  1310. X      addsector(to_np, cargo.title.x, cargo.title.y);
  1311. X      sp->flags &= ~SF_TRADED;
  1312. X    }
  1313. X  }
  1314. X  fclose(fp);
  1315. X  unlink(CARGO_FILE);
  1316. X  noncritical();
  1317. X}
  1318. X
  1319. X  /* update the nation's spy values */
  1320. Xdospy(np, mailfile)
  1321. X     Snation *np;
  1322. X     FILE *mailfile;
  1323. X{
  1324. X  int stealth = np->race.stealth;
  1325. X
  1326. X  np->spy += stealth * (sqrt(1.0 * np->spy_r_d * calc_revenue(np) / 100 +
  1327. X                 np->cur_spy_r_d * np->money / 100)) *
  1328. X                 SPY_MONEY_FACTOR;
  1329. X  np->secrecy += (stealth*stealth) * 
  1330. X    (sqrt (1.0*np->spy_r_d * calc_revenue(np) / 100 +
  1331. X       (np->cur_spy_r_d * np->money / 100)) * SPY_SECRECY_FACTOR);
  1332. X}
  1333. X
  1334. X/* undo hanging spells, decrease the thons_left param */
  1335. Xclear_h_spells()
  1336. X{
  1337. X  Sh_spell *h_spells;
  1338. X  int i;
  1339. X  struct argument exec_args[N_EXEC_ARGS];
  1340. X
  1341. X  for (h_spells=hanging_spells; h_spells != NULL; h_spells = h_spells->next) {
  1342. X    for (i = 0; i < h_spells->n_lines; ++i) {
  1343. X      if (i % 2 == 1) {        /* odd number means undo */
  1344. X    parse_exec_line(h_spells->lines[i], exec_args);
  1345. X    run_exec_line(&world.nations[h_spells->nat_id], exec_args);
  1346. X      }
  1347. X    }
  1348. X    if (h_spells->thons_left >= 0) {
  1349. X      --h_spells->thons_left;
  1350. X    }
  1351. X  }
  1352. X}
  1353. X
  1354. X  /* critical() for the update/make/add is different from the game */
  1355. Xcritical()
  1356. X{
  1357. X  signal(SIGINT, SIG_IGN);
  1358. X  signal(SIGQUIT, SIG_IGN);
  1359. X}
  1360. Xnoncritical()
  1361. X{
  1362. X  signal(SIGINT, SIG_DFL);
  1363. X  signal(SIGQUIT, SIG_DFL);
  1364. X}
  1365. X
  1366. X  /* posts some news articles of general interest */
  1367. Xpost_statistics()
  1368. X{
  1369. X  FILE *tmp_fp, *fopen();
  1370. X  char tmp_name[PATHLEN];
  1371. X  char subj[100];
  1372. X
  1373. X  /* a temporary file name for this news posting */
  1374. X/*  tmp_name = tmpnam(NULL, "dominion"); */
  1375. X  strcpy(tmp_name, "dominionXXXXXX");
  1376. X  mktemp(tmp_name);
  1377. X
  1378. X  if (strlen(tmp_name) == 0) {
  1379. X    fprintf(stderr, "Error getting temp file name\n");
  1380. X    return;
  1381. X  }
  1382. X  if ((tmp_fp = fopen(tmp_name, "w")) == NULL) {
  1383. X    fprintf(stderr, "Error opening file %s for writing\n", tmp_name);
  1384. X    return;
  1385. X  }
  1386. X  sprintf(subj, "statistics at thon %d", world.turn);
  1387. X  fprintf(tmp_fp, "\nThere are %d active nations.\n", get_n_act_ntn(&world));
  1388. X  fprintf(tmp_fp, "Average population: %d\n", get_avg_civil(&world));
  1389. X  fprintf(tmp_fp, "Average soldiers:   %d\n", get_avg_soldiers(&world));
  1390. X  fprintf(tmp_fp, "Average treasury:   %d\n", get_avg_money(&world));
  1391. X  fprintf(tmp_fp, "Average metal:      %d\n", get_avg_metal(&world));
  1392. X  fprintf(tmp_fp, "Average jewels:     %d\n", get_avg_jewels(&world));
  1393. X  fprintf(tmp_fp, "Average food:       %d\n", get_avg_food(&world));
  1394. X  fprintf(tmp_fp, "Average sectors:    %d\n", get_avg_sectors(&world));
  1395. X  fprintf(tmp_fp, "World occupation:   %d%% of land\n",
  1396. X      get_per_occu_land(&world));
  1397. X  fprintf(tmp_fp, "                    %d%% of water\n",
  1398. X      get_per_occu_water(&world));
  1399. X  fclose(tmp_fp);
  1400. X  post_news_file(tmp_name, NEWS_GROUP,subj,0);
  1401. X}
  1402. X
  1403. Xinit_work_data(xmax, ymax)
  1404. X/*
  1405. X   Allocate the memory for the temporary array the size of the world
  1406. X   (with one extra for wrap around) for manipulation before scaling 
  1407. X*/
  1408. Xint xmax,ymax;
  1409. X{
  1410. X  int i;
  1411. X  
  1412. X  if ((work_data = (struct move_data **) malloc((xmax) * 
  1413. X                           (sizeof(struct move_data *)))) == NULL)
  1414. X  {
  1415. X    mem_error();
  1416. X  }
  1417. X  for (i=0; i <xmax ; i++)
  1418. X  {
  1419. X    if ((work_data[i] = (struct move_data *) malloc((ymax) * 
  1420. X                                  (sizeof(struct move_data)))) == NULL)
  1421. X    {
  1422. X      mem_error();
  1423. X    }
  1424. X  }
  1425. X}
  1426. X
  1427. Xclear_work_data()
  1428. X/* Clear the work_peop array */
  1429. X{
  1430. X  int x,y;
  1431. X
  1432. X  for (x = 0 ; x < world.xmax ; x++)
  1433. X  {
  1434. X    for (y = 0 ; y < world.ymax ; y++)
  1435. X    {
  1436. X      work_data[x][y].moved = 0;
  1437. X      work_data[x][y].adj = 0;
  1438. X      work_data[x][y].des = 0.0;
  1439. X    }
  1440. X  }
  1441. X}
  1442. X
  1443. X#define MOVE_FREE 1
  1444. X
  1445. Xmove_people_free(np)
  1446. XSnation *np;
  1447. X{
  1448. X  struct pt_list *curr_pt;
  1449. X  int tot_peop, tot_emp,x,y,moving,i,j,xx,yy;
  1450. X  double race_factor, desire,divisor;
  1451. X
  1452. X  race_factor = sqrt(world.nations[np->id].race.repro/10.0);
  1453. X  curr_pt = np->ptlist;
  1454. X/* Loop over every point the user has. */
  1455. X  while (curr_pt != NULL)
  1456. X  {
  1457. X    if (!good_altitude(&world.map[curr_pt->pt.x][curr_pt->pt.y],np))
  1458. X    {
  1459. X      curr_pt = curr_pt->next;
  1460. X      continue;
  1461. X    }
  1462. X    x = curr_pt->pt.x;
  1463. X    y = curr_pt->pt.y; 
  1464. X    work_data[x][y].des = desig_map[world.map[x][y].designation].max_employed;
  1465. X    work_data[x][y].des *= race_factor;
  1466. X    desire = (double)sect_desire(np,x,y);
  1467. X    /* Determine the desireability of the sector */
  1468. X    desire = (desire - 650.0)/1000.0;
  1469. X    /* And have that modify the % of people wanting to live there */
  1470. X    work_data[x][y].des *= (1.0 + desire);
  1471. X    for (i = 0 ; i < (MOVE_FREE * 2) + 1  ; i++)
  1472. X    {
  1473. X      for (j = 0 ; j < (MOVE_FREE * 2) + 1 ; j++)
  1474. X      {
  1475. X        x = (*wrapx)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1476. X        y = (*wrapy)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1477. X        if (world.map[x][y].owner == np->id)
  1478. X        { 
  1479. X          work_data[curr_pt->pt.x][curr_pt->pt.y].adj++;
  1480. X    }
  1481. X      }
  1482. X    }
  1483. X    curr_pt = curr_pt->next;
  1484. X  }    
  1485. X  curr_pt = np->ptlist;
  1486. X  while (curr_pt != NULL)
  1487. X  {
  1488. X    tot_peop = 0;  /* Sum up the total owned people in a 1 sector radius */
  1489. X    tot_emp = 0;  /* Sum up the total available employment in a 1 sect rad */ 
  1490. X/* If the sector cannot suport civilians, then we don't move to or from it */
  1491. X    if (!good_altitude(&world.map[curr_pt->pt.x][curr_pt->pt.y],np))
  1492. X    {
  1493. X      curr_pt = curr_pt->next;
  1494. X      continue;
  1495. X    }
  1496. X/* First loop over the neighboorhod and find totals */
  1497. X    for (i = 0 ; i < (MOVE_FREE * 2) + 1  ; i++)
  1498. X    {
  1499. X      for (j = 0 ; j < (MOVE_FREE * 2) + 1 ; j++)
  1500. X      {
  1501. X        x = (*wrapx)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1502. X        y = (*wrapy)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1503. X        if (world.map[x][y].owner == np->id)
  1504. X        { 
  1505. X          /* Start with the number of people employable */
  1506. X          tot_peop += world.map[x][y].n_people;
  1507. X          tot_emp += work_data[x][y].des;
  1508. X    }
  1509. X      }
  1510. X    }
  1511. X/* Find the max divisor for this neighboorhood */
  1512. X    divisor = 1.0;
  1513. X    for (i = 0 ; i < (MOVE_FREE * 2) + 1  ; i++)
  1514. X    {
  1515. X      for (j = 0 ; j < (MOVE_FREE * 2) + 1 ; j++)
  1516. X      {
  1517. X        x = (*wrapx)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1518. X        y = (*wrapy)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1519. X        if (work_data[x][y].adj > divisor)
  1520. X        {
  1521. X          divisor = work_data[x][y].adj;
  1522. X        }
  1523. X      }
  1524. X    }
  1525. X/* Then distribute people over the neighboorhood. */
  1526. X    for (i = 0 ; i < (MOVE_FREE * 2) + 1  ; i++)
  1527. X    {
  1528. X      for (j = 0 ; j < (MOVE_FREE * 2) + 1 ; j++)
  1529. X      {
  1530. X        x = (*wrapx)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1531. X        y = (*wrapy)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1532. X/* Again, only work with sectors owned.  No inter-national movement */
  1533. X        if ((world.map[x][y].owner == np->id) && 
  1534. X             good_altitude(&world.map[x][y],np))
  1535. X        {
  1536. X/*
  1537. X   The percentage of modified available employment times the number of
  1538. X   people available is the number of people who want to be in that sector 
  1539. X*/
  1540. X          moving = (int)( (work_data[x][y].des/tot_emp) * tot_peop);
  1541. X
  1542. X/* Then adjust for the people already in that sector */
  1543. X          moving -= world.map[x][y].n_people;
  1544. X/* 
  1545. X  If we are working with a sector with N adjacent sectors, then we
  1546. X  only move 1/N th of the people we'd like, since the other adjacent
  1547. X  sectors may decide to all do the same thing.
  1548. X*/
  1549. X          moving =(int)((double)moving/(double)divisor);
  1550. X/*
  1551. X   And lastly put the people into the array stating that they will be moving.
  1552. X   this is important since all moves are considered before they see where
  1553. X   everybody else is moving.
  1554. X*/
  1555. X          work_data[x][y].moved += moving;
  1556. X          work_data[curr_pt->pt.x][curr_pt->pt.y].moved -= moving;
  1557. X    }
  1558. X      }
  1559. X    }
  1560. X    curr_pt = curr_pt->next;
  1561. X  }
  1562. X/* Loop over all points again */
  1563. X  curr_pt = np->ptlist;
  1564. X  while (curr_pt != NULL)
  1565. X  {
  1566. X    x = curr_pt->pt.x;
  1567. X    y = curr_pt->pt.y;
  1568. X/* Now add all the movement of people to the state of the world */
  1569. X    world.map[x][y].n_people += work_data[x][y].moved;
  1570. X    work_data[x][y].moved = 0;
  1571. X/* If we less than zero people (roundoff error happens) */
  1572. X    if (world.map[x][y].n_people < 0)
  1573. X    {
  1574. X      if ((debug) || (world.map[x][y].n_people < -9))
  1575. X      {
  1576. X        fprintf(stderr,"Error: Point %d, %d has %d people\n",x,y,
  1577. X                       world.map[x][y].n_people);
  1578. X      }
  1579. X/* Look around the neighboorhood for a place to get the people from */
  1580. X      for (i=0 ; (i < (MOVE_FREE*2)+1) && (world.map[x][y].n_people < 0); i++)
  1581. X      {
  1582. X        for (j=0 ;(j < (MOVE_FREE*2)+1) && (world.map[x][y].n_people < 0); j++)
  1583. X        {
  1584. X          xx=(*wrapx)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1585. X          yy=(*wrapy)(i+(curr_pt->pt.x-MOVE_FREE),j+(curr_pt->pt.y-MOVE_FREE));
  1586. X/* If they have people to spare */
  1587. X          if (world.map[xx][yy].n_people + work_data[xx][yy].moved > 0)
  1588. X          {
  1589. X/* Then we move as many as we can, up to as many as we need */
  1590. X            moving = min(world.map[xx][yy].n_people + work_data[xx][yy].moved,
  1591. X                         -1 * world.map[x][y].n_people);
  1592. X            world.map[xx][yy].n_people -= moving;
  1593. X            world.map[x][y].n_people += moving;
  1594. X      }
  1595. X    }
  1596. X      }
  1597. X    }
  1598. X/* If we still have not enough people, then the algorithm is buggy */
  1599. X    if (world.map[x][y].n_people < 0)
  1600. X    {
  1601. X       fprintf(stderr,"Error: Point %d, %d still has %d people\n",x,y,
  1602. X                       world.map[x][y].n_people);
  1603. X    }
  1604. X    curr_pt = curr_pt->next;
  1605. X  }
  1606. X}
  1607. X
  1608. Xfill_work_data(np)
  1609. XSnation *np;
  1610. X{
  1611. X  struct pt_list *curr_pt;
  1612. X  double desire,race_factor;
  1613. X  int x,y;
  1614. X
  1615. X  race_factor = sqrt(world.nations[np->id].race.repro/10.0);
  1616. X  curr_pt = np->ptlist;
  1617. X  while (curr_pt != NULL)
  1618. X  {
  1619. X    if (!good_altitude(&world.map[curr_pt->pt.x][curr_pt->pt.y],np)) {
  1620. X      curr_pt = curr_pt->next;
  1621. X      continue;
  1622. X    }
  1623. X    x = curr_pt->pt.x;
  1624. X    y = curr_pt->pt.y; 
  1625. X    work_data[x][y].des = desig_map[world.map[x][y].designation].max_employed;
  1626. X    work_data[x][y].des *= race_factor;
  1627. X/* the adj holds the number of jobs available in that sector */
  1628. X    work_data[x][y].adj = work_data[x][y].des - world.map[x][y].n_people;
  1629. X    desire = (double)sect_desire(np,x,y);
  1630. X    /* Determine the desireability of the sector */
  1631. X    desire = (desire - 650.0)/1000.0;
  1632. X    /* And have that modify the % of people wanting to live there */
  1633. X    work_data[x][y].des *= (1.0 + desire);
  1634. X    curr_pt = curr_pt->next;
  1635. X  }    
  1636. X}
  1637. X
  1638. X#define MOVE_RESTR 2
  1639. X
  1640. Xmove_the_people(np)
  1641. XSnation *np;
  1642. X{
  1643. X  struct pt_list *curr_pt;
  1644. X  int x,y, xx,yy,i,j, moving;
  1645. X
  1646. X  curr_pt = np->ptlist;
  1647. X  while (curr_pt != NULL)
  1648. X  {
  1649. X    x = curr_pt->pt.x;
  1650. X    y = curr_pt->pt.y;
  1651. X/* Now add all the movement of people to the state of the world */
  1652. X    world.map[x][y].n_people += work_data[x][y].moved;
  1653. X    work_data[x][y].moved = 0;
  1654. X/* If we less than zero people (roundoff error happens) */
  1655. X    if (world.map[x][y].n_people < 0)
  1656. X    {
  1657. X      if ((debug) || (world.map[x][y].n_people < -9))
  1658. X      {
  1659. X        fprintf(stderr,"Error: Point %d, %d has %d people\n",x,y,
  1660. X                       world.map[x][y].n_people);
  1661. X      }
  1662. X/* Look around the neighboorhood for a place to get the people from */
  1663. X      for (i=0;(i < (MOVE_RESTR*2)+1) && (world.map[x][y].n_people < 0); i++)
  1664. X      {
  1665. X        for (j=0;(j < (MOVE_RESTR*2)+1) && (world.map[x][y].n_people < 0); j++)
  1666. X        {
  1667. X          xx=(*wrapx)(i+(curr_pt->pt.x-MOVE_RESTR),
  1668. X                                           j+(curr_pt->pt.y-MOVE_RESTR));
  1669. X          yy=(*wrapy)(i+(curr_pt->pt.x-MOVE_RESTR),
  1670. X                                           j+(curr_pt->pt.y-MOVE_RESTR));
  1671. X/* If they have people to spare */
  1672. X          if (world.map[xx][yy].n_people + work_data[xx][yy].moved > 0)
  1673. X          {
  1674. X/* Then we move as many as we can, up to as many as we need */
  1675. X            moving = min(world.map[xx][yy].n_people + work_data[xx][yy].moved,
  1676. X                         -1 * world.map[x][y].n_people);
  1677. X            world.map[xx][yy].n_people -= moving;
  1678. X            world.map[x][y].n_people += moving;
  1679. X      }
  1680. X    }
  1681. X      }
  1682. X    }
  1683. X/* If we still have not enough people, then the algorithm is buggy */
  1684. X    if (world.map[x][y].n_people < 0)
  1685. X    {
  1686. X       fprintf(stderr,"Error: Point %d, %d still has %d people\n",x,y,
  1687. X                       world.map[x][y].n_people);
  1688. X    }
  1689. X    curr_pt = curr_pt->next;
  1690. X  }
  1691. X}
  1692. X
  1693. Xmove_space_avail(np,curr_pt,peop,tot_emp,tot_peop)
  1694. XSnation *np;
  1695. Xstruct pt_list *curr_pt;
  1696. Xint tot_emp, *peop,tot_peop;
  1697. X{
  1698. X  struct pt_list *nhbd_list,*curr_plist;
  1699. X  int moving,i,j,x,y,peop_left = *peop;
  1700. X  double desire;
  1701. X
  1702. X  nhbd_list = NULL;
  1703. X  for (i = 0 ; i < (MOVE_RESTR * 2) + 1 ; i++) {
  1704. X    for (j = 0 ; j < (MOVE_RESTR * 2) + 1 ; j++) {
  1705. X      x = (*wrapx) (i+(curr_pt->pt.x-MOVE_RESTR),
  1706. X                                      j+(curr_pt->pt.y-MOVE_RESTR));
  1707. X      y = (*wrapy) (i+(curr_pt->pt.x-MOVE_RESTR),
  1708. X                                      j+(curr_pt->pt.y-MOVE_RESTR));
  1709. X/* Again, only work with sectors owned.  No inter-national movement */
  1710. X      if ((world.map[x][y].owner == np->id) && good_altitude(
  1711. X           &world.map[x][y],np) && ((i != j) || (i != MOVE_RESTR))) {
  1712. X         moving = (work_data[x][y].adj * tot_peop / (2 *tot_emp));
  1713. X         if (moving < 0) { moving = 0; }
  1714. X         peop_left -= moving;
  1715. X         work_data[x][y].moved += moving;
  1716. X         add_to_plist(&nhbd_list, x, y);
  1717. X      }
  1718. X    }
  1719. X  }
  1720. X  sort_ptlist(&nhbd_list);
  1721. X  curr_plist = nhbd_list;
  1722. X  while ((curr_plist != NULL) && (peop_left != 0))
  1723. X  {
  1724. X    x = curr_plist->pt.x;
  1725. X    y = curr_plist->pt.y;
  1726. X/* First figure out how many were moved here already */
  1727. X    moving = (work_data[x][y].adj * tot_peop / (2 *tot_emp));
  1728. X/* Then figure out how many more can move there. */
  1729. X    moving = work_data[x][y].adj - moving;
  1730. X    if (moving < 0 ) { moving = 0 ; }
  1731. X    if (moving > peop_left) {
  1732. X      moving = peop_left;
  1733. X      peop_left = 0;
  1734. X    } else {
  1735. X      peop_left -= moving; 
  1736. X    }
  1737. X    work_data[x][y].moved += moving;
  1738. X    curr_plist = curr_plist->next;
  1739. X  }
  1740. X  free_ptlist(&nhbd_list);
  1741. X  *peop = peop_left;
  1742. X}
  1743. X
  1744. Xmove_somespace_avail(np,curr_pt,peop)
  1745. XSnation *np;
  1746. Xstruct pt_list *curr_pt;
  1747. Xint *peop;
  1748. X{
  1749. X  int i,j,x,y,moving,peop_left = *peop;
  1750. X
  1751. X  for (i = 0 ; i < (MOVE_RESTR * 2) + 1 ; i++) {
  1752. X    for (j = 0 ; j < (MOVE_RESTR * 2) + 1 ; j++) {
  1753. X      x = (*wrapx)(i+(curr_pt->pt.x-MOVE_RESTR),j+(curr_pt->pt.y-MOVE_RESTR));
  1754. X      y = (*wrapy)(i+(curr_pt->pt.x-MOVE_RESTR),j+(curr_pt->pt.y-MOVE_RESTR));
  1755. X      if ((world.map[x][y].owner == np->id) && good_altitude(
  1756. X           &world.map[x][y],np) && ((i != j) || (i != MOVE_RESTR))) {
  1757. X         moving = work_data[x][y].adj;
  1758. X         if (moving < 0 ) { moving = 0; }
  1759. X         if (moving > peop_left ) {
  1760. X           moving = peop_left;
  1761. X           peop_left = 0; 
  1762. X         } else {
  1763. X           peop_left -= moving;
  1764. X         }
  1765. X         work_data[x][y].moved += moving;
  1766. X      }
  1767. X    }
  1768. X  }
  1769. X  *peop = peop_left;
  1770. X}
  1771. X
  1772. Xmove_people_restrict(np)
  1773. XSnation *np;
  1774. X{
  1775. X  struct pt_list *curr_pt;
  1776. X  int tot_peop, peop_left, tot_emp,x,y,moving,i,j,xx,yy;
  1777. X  double race_factor, desire,divisor;
  1778. X  struct pt_list *nhbd_list, *curr_plist;
  1779. X
  1780. X  race_factor = sqrt(world.nations[np->id].race.repro/10.0);
  1781. X  fill_work_data(np);
  1782. X/* Loop over every point the user has. */
  1783. X  curr_pt = np->ptlist;
  1784. X  while (curr_pt != NULL)
  1785. X  {
  1786. X    tot_emp = 0;  /* Sum up the total available employment in a 1 sect rad */ 
  1787. X/* If the sector cannot suport civilians, then we don't move to or from it */
  1788. X    if (!good_altitude(&world.map[curr_pt->pt.x][curr_pt->pt.y],np)) {
  1789. X      curr_pt = curr_pt->next;
  1790. X      continue;
  1791. X    }
  1792. X/* If there are no unemployed people here, then go on. */
  1793. X    if ((tot_peop = work_data[curr_pt->pt.x][curr_pt->pt.y].adj) >= 0) {
  1794. X      curr_pt = curr_pt->next;
  1795. X      continue;
  1796. X    }
  1797. X    tot_peop *= -1;
  1798. X    peop_left = tot_peop;
  1799. X    work_data[curr_pt->pt.x][curr_pt->pt.y].moved -= peop_left; 
  1800. X
  1801. X/* First loop over the neighboorhod and find totals */
  1802. X    for (i = 0 ; i < (MOVE_RESTR * 2) + 1  ; i++)
  1803. X    {
  1804. X      for (j = 0 ; j < (MOVE_RESTR * 2) + 1 ; j++)
  1805. X      {
  1806. X        x =(*wrapx)(i+(curr_pt->pt.x-MOVE_RESTR),j+(curr_pt->pt.y-MOVE_RESTR));
  1807. X        y =(*wrapy)(i+(curr_pt->pt.x-MOVE_RESTR),j+(curr_pt->pt.y-MOVE_RESTR));
  1808. X        if ((world.map[x][y].owner == np->id) && ((i!=j) || (i != MOVE_RESTR)))
  1809. X        { 
  1810. X          /* Start with the number of available jobs */
  1811. X          if (work_data[x][y].adj > 0) {
  1812. X            tot_emp += work_data[x][y].adj;
  1813. X      }
  1814. X    }
  1815. X      }
  1816. X    }
  1817. X    if (tot_emp > 0) {
  1818. X      if (tot_emp > tot_peop) {
  1819. X        move_space_avail(np,curr_pt,&peop_left,tot_emp,tot_peop);
  1820. X      } else {
  1821. X        move_somespace_avail(np,curr_pt,&peop_left);
  1822. X      }
  1823. X    }
  1824. X    if (peop_left > 0) {
  1825. X      tot_peop = peop_left; 
  1826. X      desire = 0.0;
  1827. X      for (i = 0 ; i < (MOVE_RESTR * 2) + 1 ; i++) {
  1828. X        for (j = 0 ; j < (MOVE_RESTR * 2) + 1 ; j++) {
  1829. X          x =(*wrapx)(i+(curr_pt->pt.x-MOVE_RESTR),
  1830. X                                          j+(curr_pt->pt.y-MOVE_RESTR));
  1831. X          y =(*wrapy)(i+(curr_pt->pt.x-MOVE_RESTR),
  1832. X                                          j+(curr_pt->pt.y-MOVE_RESTR));
  1833. X          if ((world.map[x][y].owner == np->id) && good_altitude(
  1834. X               &world.map[x][y],np) && ((i != j) || (i != MOVE_RESTR))) {
  1835. X            desire += work_data[x][y].des;
  1836. X          }
  1837. X        }
  1838. X      }
  1839. X      for (i = 0 ; i < (MOVE_RESTR * 2) + 1 ; i++) {
  1840. X        for (j = 0 ; j < (MOVE_RESTR * 2) + 1 ; j++) {
  1841. X          x =(*wrapx)(i+(curr_pt->pt.x-MOVE_RESTR),
  1842. X                                          j+(curr_pt->pt.y-MOVE_RESTR));
  1843. X          y =(*wrapy)(i+(curr_pt->pt.x-MOVE_RESTR),
  1844. X                                          j+(curr_pt->pt.y-MOVE_RESTR));
  1845. X          if ((world.map[x][y].owner == np->id) && good_altitude(
  1846. X               &world.map[x][y],np) && ((i != j) || (i != MOVE_RESTR))) {
  1847. X            moving = (int)((work_data[x][y].des * tot_peop)/desire);
  1848. X            if (moving < 0 ) { moving = 0; } 
  1849. X            peop_left -= moving;
  1850. X            work_data[x][y].moved += moving;
  1851. X          }
  1852. X        }
  1853. X      }
  1854. X      work_data[curr_pt->pt.x][curr_pt->pt.y].moved += peop_left;
  1855. X    }
  1856. X    curr_pt = curr_pt->next;
  1857. X  }
  1858. X  move_the_people(np);
  1859. X/* Loop over all points again */
  1860. X}
  1861. X
  1862. Xint sort_ptlist(ptlist)
  1863. Xstruct pt_list **ptlist;
  1864. X{
  1865. X  struct pt_list *pnext, *pprev, *pcurr, *ptemp;
  1866. X  int switched;
  1867. X
  1868. X  if (*ptlist == NULL) { return; }
  1869. X  if ((*ptlist)->next == NULL) {return; }
  1870. X  do {
  1871. X    switched = 0;
  1872. X    pcurr = *ptlist;
  1873. X    pnext = pcurr->next;
  1874. X    if (work_data[pcurr->pt.x][pcurr->pt.y].des <
  1875. X                  work_data[pnext->pt.x][pnext->pt.y].des) {
  1876. X      switched++;
  1877. X      ptemp = pnext->next;
  1878. X      *ptlist = pnext;
  1879. X      (*ptlist)->next = pcurr;
  1880. X      (*ptlist)->next->next = ptemp;
  1881. X    }
  1882. X    pprev = *ptlist;
  1883. X    pcurr = (*ptlist)->next;
  1884. X    while (pcurr->next != NULL) {
  1885. X      pnext = pcurr->next;
  1886. X      if (work_data[pcurr->pt.x][pcurr->pt.y].des <
  1887. X                         work_data[pnext->pt.x][pnext->pt.y].des) {
  1888. X        ptemp = pnext->next;
  1889. X        pprev->next = pnext;
  1890. X        pprev->next->next = pcurr;
  1891. X        pprev->next->next->next = ptemp;
  1892. X        switched++;
  1893. X      }
  1894. X      pprev = pprev->next;
  1895. X      pcurr = pprev->next;
  1896. X    }
  1897. X  } while (switched > 0) ;
  1898. X  return;
  1899. X}
  1900. X
  1901. Xfree_ptlist(ptlist)
  1902. Xstruct pt_list **ptlist;
  1903. X{
  1904. X  struct pt_list *pt_list = *ptlist, *tmp_pt;
  1905. X  
  1906. X  while (pt_list != NULL) {
  1907. X    tmp_pt = pt_list->next;
  1908. X    free(pt_list);
  1909. X    pt_list = tmp_pt;
  1910. X  }
  1911. X}
  1912. X
  1913. Xadd_to_plist(ptlist, x, y)
  1914. Xstruct pt_list **ptlist;
  1915. Xint x,y;
  1916. X{
  1917. X  struct pt_list *ptemp = *ptlist; 
  1918. X
  1919. X  if (*ptlist == NULL) {
  1920. X    if ((*ptlist = (struct pt_list *)malloc(sizeof(struct pt_list)))== NULL) {
  1921. X      mem_error();
  1922. X    }
  1923. X    (*ptlist)->pt.x = x;
  1924. X    (*ptlist)->pt.y = y;
  1925. X    (*ptlist)->next = NULL;
  1926. X    return;
  1927. X  }
  1928. X  while (ptemp->next != NULL) {
  1929. X    ptemp = ptemp->next;
  1930. X  }
  1931. X  if ((ptemp->next = (struct pt_list *)malloc(sizeof(struct pt_list)))
  1932. X            == NULL) { mem_error(); }
  1933. X  ptemp = ptemp->next;
  1934. X  ptemp->pt.x = x;
  1935. X  ptemp->pt.y = y;
  1936. X  ptemp->next = NULL;
  1937. X  return;
  1938. X}
  1939. X    
  1940. Xsetup_user_arr(num)
  1941. Xint num;
  1942. X{
  1943. X  if ((temp_users = (Suser *)malloc(num * sizeof(Suser))) == NULL) {
  1944. X    mem_error();
  1945. X  }
  1946. X}
  1947. X
  1948. Xcopy_to_user_arr(val)
  1949. Xint val;
  1950. X{
  1951. X  temp_users[val] = user;
  1952. X}
  1953. X
  1954. Xcopy_from_user_arr(val)
  1955. Xint val;
  1956. X{
  1957. X  user = temp_users[val];
  1958. X}
  1959. X
  1960. END_OF_FILE
  1961. if test 49821 -ne `wc -c <'update.c'`; then
  1962.     echo shar: \"'update.c'\" unpacked with wrong size!
  1963. fi
  1964. # end of 'update.c'
  1965. fi
  1966. echo shar: End of archive 14 \(of 28\).
  1967. cp /dev/null ark14isdone
  1968. MISSING=""
  1969. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ; do
  1970.     if test ! -f ark${I}isdone ; then
  1971.     MISSING="${MISSING} ${I}"
  1972.     fi
  1973. done
  1974. if test "${MISSING}" = "" ; then
  1975.     echo You have unpacked all 28 archives.
  1976.     echo "Now execute ./do_cat.sh to build doc files"
  1977.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1978. else
  1979.     echo You still need to unpack the following archives:
  1980.     echo "        " ${MISSING}
  1981. fi
  1982. ##  End of shell archive.
  1983. exit 0
  1984.