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

  1. Path: uunet!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v13i055:  dominion - a multi-player world simulation game, Part19/28
  5. Message-ID: <2458@masterCNA.TEK.COM>
  6. Date: 11 Feb 92 18:26:24 GMT
  7. Sender: news@masterCNA.TEK.COM
  8. Lines: 2091
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: rosalia@dirac.physics.sunysb.edu (Mark Galassi)
  12. Posting-number: Volume 13, Issue 55
  13. Archive-name: dominion/Part19
  14. Environment: Unix, curses
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 19 (of 28)."
  25. # Contents:  ChangeLog battle.c misc.c
  26. # Wrapped by billr@saab on Tue Feb 11 10:14:56 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'ChangeLog' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'ChangeLog'\"
  30. else
  31. echo shar: Extracting \"'ChangeLog'\" \(4115 characters\)
  32. sed "s/^X//" >'ChangeLog' <<'END_OF_FILE'
  33. XThu Jan 30 16:00:06 1992  Mark Galassi  (rosalia at max)
  34. X
  35. X    * root.c: now root windows are cleared when created on BSD
  36. X    systems.
  37. X
  38. X    * cur_stuff.c: fixed problem with return value of wget_number()
  39. X    function and friends.
  40. X
  41. X    * spells.c: fixed a bug with the merge spell which allowed you to
  42. X    steal other nations' population by merging on hostile sectors.
  43. X
  44. X    * mail.c and commands.c: fixed problem with permissions/uids
  45. X    etc...  now sending mail works both when forwarding and when
  46. X    sending locally.
  47. X
  48. XTue Jan 28 22:58:44 1992  Douglas J. Novellano  (doug at max)
  49. X
  50. X    * c_news.c: write_newsrc(): Fixed (?) the .tmprc.n error bug.
  51. X                   Changed mv system call to cp and rm.
  52. X
  53. XMon Jan 27 04:30:09 1992  C. Titus Brown  (brown at dirac)
  54. X
  55. X    * commands.c: Fixed aforementioned bug
  56. X
  57. X    * c_news.c: Fixed the previously mentioned major bug
  58. X
  59. X    * mail.c: Fixed the major bug with the init_screen and edit()
  60. X
  61. X    * int_mail.c: Now, when the mail reader deletes all the messages
  62. X              in the mailbox, the change is kept
  63. X              (formerly, it tried to copy the deleted file)
  64. X
  65. X    * int_mail.c: Fixed the major bug with the init_screen and
  66. X              edit().
  67. X
  68. XSat Jan 25 18:59:55 1992  C. Titus Brown  (brown at dirac)
  69. X
  70. X    * army.c: added routine "statline2_prompt" to all the relevant places
  71. X
  72. X    * army.c: fixed problem with army status' running over into bonus'
  73. X          in zoom_army.
  74. X
  75. X    * misc.c: added routine "statline2_prompt" 
  76. X
  77. XFri Jan 24 02:30:43 1992  C. Titus Brown  (brown at dirac)
  78. X
  79. X    * mktables.c: checked in (not in makefile)
  80. X
  81. X    * dominion.tex: added in new army_types table (see mktable)
  82. X
  83. X    * ext.c: changed description for army_examine, spelling, etc.
  84. X
  85. XThu Jan 23 23:36:33 1992  C. Titus Brown  (brown at dirac)
  86. X
  87. X    * nation.c: new_army_type now checks to see if the army_type
  88. X            being added already is there.
  89. X
  90. X        * armylib.c: add_army_type now checks to see if the army_type
  91. X             being added is already there.
  92. X
  93. XThu Jan 23 18:03:05 1992  Michael D Fischer  (greendog at max)
  94. X
  95. X    * ext.c: changed some <a>rmy <e>xamine descriptions
  96. X
  97. XThu Jan 23 15:46:41 1992  Stephen H. Underwood  (heechee at max)
  98. X
  99. X    * misc.h: removed extern declarations of index/strchr
  100. X
  101. X    * army.c: added typecast to remove warning.
  102. X
  103. XFri Jan 17 13:50:42 1992  Stephen H. Underwood  (heechee at max)
  104. X
  105. X    * army.h, spelllib.c: Fixed the problem with spells & merge
  106. X    so it is not possible to split or merge armies or spritis
  107. X    which are currently being affected by a spell.
  108. X
  109. XTue Jan 14 16:40:01 1992  Stephen H. Underwood  (heechee at max)
  110. X
  111. X    * dominion.h, cur_stuff.c, Makefile: Added supporrt for PMAX, 
  112. X    fixing bug in the curses desplay for ultrix
  113. X
  114. X    * dominion.c, printmap.c: Added support for ANDREW style
  115. X    authenticaion (since setuid/setgid doesn't function on AFS)
  116. X
  117. X    * army.c, ext.c, menus.c, nation.c, addnation.c, file.c,
  118. X    amry.h, update.c, mail.c, user.c, spelllib.c
  119. X    Remove the slew of meaningless comments I left lying around.
  120. X
  121. XMon Jan 13 23:04:10 EST 1992 Stephen Underwood (heechee at max)
  122. X
  123. X    * army.c: removed direct reference to strchr that would not
  124. X    compile under BSD.  
  125. X
  126. X    * misc.h: Made sure that strchr or index were defined correctly
  127. X    as a proper fix to the above problems.
  128. X
  129. XFri Jan 10 15:58:17 1992  Michael D Fischer  (greendog at max)
  130. X
  131. X    * printmap.c: Changed scaling from c-code to ps-code, and
  132. X    added axes to borders of map.
  133. X
  134. XTue Jan  7 22:36:35 1992  Michael D Fischer  (greendog at max)
  135. X
  136. X    * printmap.c: Changes back to real userid to be able to write
  137. X    to user's directory.  Also a few minor changes.
  138. X
  139. XTue Jan  7 14:09:51 1992  Mark Galassi  (rosalia at max)
  140. X
  141. X    * Addnation: now doesn't infinite-loop if there is no
  142. X    space of a new nation.  Behaves well on this count.
  143. X
  144. XFri Dec 13 08:11:54 1991  Mark Galassi  (rosalia at max)
  145. X
  146. X    * Makefile: added the ChangeLog in the distribution
  147. X
  148. X    * Makefile: now compiling as version 1.06beta
  149. X
  150. X    * cinfo.c: fixed bug that find_info_file() was not returning
  151. X    the file pointer as it should have been. this caused core
  152. X    dumps on suns, and worked by miracle on MIPS/SGI.
  153. X
  154. X    * armylib.c: fixed (finally) bug in army_is_in_sector() which
  155. X    caused all sorts of trouble with armies not being properly
  156. X    inserted into sectors.
  157. END_OF_FILE
  158. if test 4115 -ne `wc -c <'ChangeLog'`; then
  159.     echo shar: \"'ChangeLog'\" unpacked with wrong size!
  160. fi
  161. # end of 'ChangeLog'
  162. fi
  163. if test -f 'battle.c' -a "${1}" != "-c" ; then 
  164.   echo shar: Will not clobber existing file \"'battle.c'\"
  165. else
  166. echo shar: Extracting \"'battle.c'\" \(27165 characters\)
  167. sed "s/^X//" >'battle.c' <<'END_OF_FILE'
  168. X/* battle.c -- functions relating to resolving battles between nations    */
  169. X
  170. X/*
  171. X * Copyright (C) 1990 Free Software Foundation, Inc.
  172. X * Written by the dominion project.
  173. X *
  174. X * This file is part of dominion.
  175. X *
  176. X * dominion is free software; you can redistribute it and/or
  177. X * modify it under the terms of the GNU General Public License as published
  178. X * by the Free Software Foundation; either version 1, or (at your option)
  179. X * any later version.
  180. X *
  181. X * This software is distributed in the hope that it will be useful,
  182. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  183. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  184. X * GNU General Public License for more details.
  185. X *
  186. X * You should have received a copy of the GNU General Public License
  187. X * along with this software; see the file COPYING.  If not, write to
  188. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  189. X */
  190. X
  191. X/* against(dm,list,nation) - checks a list of armies (in a sector) for    */
  192. X/*         any army which the nation specified is against (at WAR/JIHAD)  */
  193. X/* count_force(np,sp,ap) - calculates the EFFECTIVE force of an army      */
  194. X/*         which a unit represents including nation, sector, army bonuses */
  195. X/* free_list(list) - frees up memory which was used in the list           */
  196. X/* status_check(list,status) - checks a 'sector list' of armies for a     */
  197. X/*         particular status and returns one if it occurs, else zero      */
  198. X/* supports(dm,list,nation) - checks a list of armies for any army which  */
  199. X/*         the nation specified supports (TREATY)                         */
  200. X/**************************************************************************/
  201. X/* These remaining functions are probably useless for other purposes      */
  202. X/**************************************************************************/
  203. X/* dobattles() - resolves all battles in the world during an update       */
  204. X/* move_intercepts(dm) - moves each army with INTERCEPT status to         */
  205. X/*         bordering hostile armies and sets to ATTACK status.  If there  */
  206. X/*         is no hostile army locally, keep army in INTERCEPT mode.       */
  207. X/* add_to_list(list,army,mail_list) - adds the army to the list specified */
  208. X/*         and also to the mail list IF it does not already occur there.  */
  209. X/* extract_losses(list,pct_loss,mail_list,type) - Extracts losses from    */
  210. X/*         armies in a sector.  If type is 3, the army list is of neutrals*/
  211. X/* total_bonus(np,sp,ap) - gets TOTAL bonus for that army                 */
  212. X/* battle_mail(mail_list,s) - adds string s to mail for nations in list   */
  213. X/* intro_battle_mail(mail_list,x,y) - sends intro message with rel coord. */
  214. X/* intro_battle_news(...) - posts news about the battle                   */
  215. X/* single_mail(nation,s) - adds string s to mail for nation #nation       */
  216. X/* is_war(dm,x,y) - sees if any war should happen in this sector          */
  217. X/* battle(dm,x,y,fp) - main routine which deals with all battles in a sector */
  218. X
  219. X#include "dominion.h"
  220. X#include "misc.h"
  221. X#include "army.h"
  222. X
  223. X#include <stdio.h>
  224. X
  225. X/* used as type parameter values passed to extract_losses */
  226. X
  227. X#define ALLIES 1
  228. X#define ENEMIES 2
  229. X#define NEUTRALS 3
  230. X
  231. X
  232. Xextern Sworld world;
  233. Xint (*wrapx)(), (*wrapy)();
  234. XFILE *mailfile;
  235. X
  236. Xdobattles()
  237. X{
  238. X  int x,y;
  239. X  Sdiplo **dm, **allocate_diplo();
  240. X  FILE *tmp_fp, *fopen();    /* for the news posting */
  241. X  char tmp_name[100];
  242. X  char subj[100];
  243. X  dm = allocate_diplo(world.n_nations);
  244. X  read_in_diplo(dm,world.n_nations);
  245. X
  246. X  printf("Doing battles...\n");
  247. X  fflush(stdout);
  248. X
  249. X    /* a temporary file name for this news posting */
  250. X/*  tmp_name = tmpnam(NULL, "dominion"); */
  251. X  strcpy(tmp_name, "dominionXXXXXX");
  252. X  mktemp(tmp_name);
  253. X
  254. X  if (strlen(tmp_name) == 0) {
  255. X    fprintf(stderr, "Error getting temp file name\n");
  256. X    return;
  257. X  }
  258. X  if ((tmp_fp = fopen(tmp_name, "w")) == NULL) {
  259. X    fprintf(stderr, "Error opening file %s for writing\n", tmp_name);
  260. X    return;
  261. X  }
  262. X/*  fprintf(tmp_fp, "Date: Thon %d\n", world.turn);
  263. X  fprintf(tmp_fp, "From: Update\n");
  264. X  fprintf(tmp_fp, "Subj: battles from thon %d to thon %d\n", world.turn-1,
  265. X      world.turn);*/
  266. X  sprintf(subj, "battles from thon %d to thon %d",world.turn-1,world.turn);
  267. X
  268. X  move_intercepts(dm);
  269. X
  270. X  for (x = 0; x < world.xmax; x++) {
  271. X    for (y = 0; y < world.ymax; y++) {
  272. X      if (world.map[x][y].alist && world.map[x][y].alist->next
  273. X      && is_war(dm, x, y, tmp_fp)) {
  274. X/*    battle(dm, x, y, tmp_fp); */
  275. X      }
  276. X    }
  277. X  }
  278. X  fclose(tmp_fp);
  279. X  post_news_file(tmp_name, NEWS_GROUP,subj,0);
  280. X  printf("just posted file to newsgroup <%s>\n", NEWS_GROUP);
  281. X}
  282. X
  283. X  /* takes all armies in intercept mode and sees if
  284. X     it can move them to attack an enemy army.
  285. X   */
  286. Xmove_intercepts(dm)
  287. X     Sdiplo **dm;
  288. X{
  289. X  int nation,x,y;
  290. X  Snation *np;
  291. X  Ssector *sp;
  292. X  Sarmy *ap;
  293. X
  294. X  for (nation = 1; nation < world.n_nations; nation++) {
  295. X    np = &world.nations[nation];
  296. X    ap = np->armies;
  297. X    while (ap != NULL) {
  298. X      if (ap->status == A_INTERCEPT) {
  299. X    for (x = ap->pos.x - 1; x <= ap->pos.x + 1; x++) {
  300. X      for (y = ap->pos.y - 1; y <= ap->pos.y + 1; y++) {
  301. X        sp = &world.map[(*wrapx)(x,y)][(*wrapy)(x,y)];
  302. X          /* army might not be in intercept mode any more,
  303. X         in which case we don't make it move.  that way
  304. X         an intercept army will only move once.
  305. X           */
  306. X        if (ap->status == A_INTERCEPT && against(dm, sp->alist, nation)
  307. X          /* be careful about moving into bad altitude */
  308. X        && (good_army_altitude(np, sp, ap) || is_kamikaze(ap))) {
  309. X          printf("%s army %d is intercepting from (%d,%d) to (%d,%d)\n",
  310. X             np->name, ap->id, ap->pos.x, ap->pos.y, x, y);
  311. X          ap->status = A_ATTACK;
  312. X/*          if (sect_n_armies(&world.map[ap->pos.x][ap->pos.y]) > 1) { */
  313. X          delete_army_sector(&world.map[ap->pos.x][ap->pos.y],ap);
  314. X/*          } else {
  315. X        free(sp->alist);
  316. X        sp->alist = NULL;
  317. X          }
  318. X*/
  319. X          ap->pos.x = (*wrapx)(x,y);
  320. X          ap->pos.y = (*wrapy)(x,y);
  321. X          insert_army_sector(sp, ap);
  322. X        }
  323. X      }
  324. X    }
  325. X      }
  326. X      ap = ap->next;
  327. X    }
  328. X  }
  329. X}
  330. X
  331. X/*
  332. X     against(): searches throught the list of armies
  333. X                and checks for their diplomatic status
  334. X        with 'nation' and vice versa.  When
  335. X        the nation status is either WAR or JIHAD
  336. X        then it returns 1 else 0
  337. X                This routine is called from battle()
  338. X*/
  339. X
  340. Xagainst(dm,list,nation)
  341. X     Sdiplo **dm;
  342. X     struct armyid *list;
  343. X     int nation;
  344. X{
  345. X  struct armyid *tmp;
  346. X  int ds1,ds2;
  347. X  
  348. X  tmp = list;
  349. X  while (tmp != NULL) {
  350. X    ds1 = get_diplo_status(dm,nation,tmp->owner);
  351. X    ds2 = get_diplo_status(dm,tmp->owner,nation);
  352. X    if (ds1 == WAR || ds1 == JIHAD || ds2 == WAR || ds2 == JIHAD) {
  353. X      return 1;
  354. X    }
  355. X    tmp = tmp->next;
  356. X  }
  357. X  return 0;
  358. X}
  359. X
  360. X/*  this routine is being called from battle() */
  361. X
  362. Xsupports(dm,list,nation)
  363. X     Sdiplo **dm;
  364. X     struct armyid *list;
  365. X     int nation;
  366. X{
  367. X  struct armyid *tmp;
  368. X  int ds1,ds2;
  369. X  
  370. X  tmp = list;
  371. X  while (tmp != NULL) {
  372. X    if (tmp->owner == nation) {    /* a nation is allied with itself */
  373. X      return 1;
  374. X    }
  375. X    ds1 = get_diplo_status(dm,nation,tmp->owner);
  376. X    ds2 = get_diplo_status(dm,tmp->owner,nation);
  377. X    if (ds1 == TREATY && ds2 == TREATY) {
  378. X      return 1;
  379. X    }
  380. X    tmp = tmp->next;
  381. X  }
  382. X  return 0;
  383. X}
  384. X
  385. X/* this routine is being called from battle() as well */
  386. X/* also being called from battle() */
  387. X
  388. Xadd_to_list(list,army,mail_list)
  389. X     struct armyid **list, *army, **mail_list;
  390. X{
  391. X  struct armyid *tmp;
  392. X
  393. X  tmp = (struct armyid *) malloc(sizeof(struct armyid));
  394. X  *tmp = *army;
  395. X  tmp->next = (*list);
  396. X  (*list) = tmp;
  397. X
  398. X  tmp = (*mail_list);
  399. X  while (tmp != NULL) {
  400. X    if (tmp->owner == army->owner) {
  401. X      return;
  402. X    }
  403. X    tmp = tmp->next;
  404. X  }
  405. X  tmp = (struct armyid *) malloc(sizeof(struct armyid));
  406. X  *tmp = *army;
  407. X  tmp->next = (*mail_list);
  408. X  (*mail_list) = tmp;
  409. X}
  410. X
  411. X/***************************************************
  412. X     total_bonus() returns all bonuses of an army
  413. X     if an army is in TREATY with the owner of the 
  414. X     sector then they can enjoy sector defense bonuses
  415. X     and have a choice of being in DEFEND, GARRISON,
  416. X     AMBUSH etc.
  417. X     if an army is in garrison mode they get extra 10
  418. X     this function has the flexibility in case we want
  419. X     other modes.  For starters I will add some experimental
  420. X     stuff with ALLIED status with sector's owner
  421. X     ALLIED will give 1/2 of sector bonuses and +5 for
  422. X     garrison mode.   A nation with very strong 
  423. X     sector bonuses will invite more nations to be in
  424. X     treaty with him because any time they fight in a sector
  425. X     owned by this strong nation will enjoy the sector
  426. X     bonuses as well.
  427. X     This routine is called from battle() and from extract_losses
  428. X*************************************************************/
  429. X
  430. Xtotal_bonus(np,sp,ap,dm)
  431. XSnation *np;
  432. XSsector *sp;
  433. XSarmy *ap;
  434. XSdiplo **dm;
  435. X
  436. X{
  437. X  int bonus = 0;
  438. X  int ds1,ds2;  /* test to see if army is in trearty with sector owner */
  439. X     /* if they are in treaty with each other then the army can share the*/
  440. X     /* sector's defense bonuses. */
  441. X
  442. X  if (sp->owner == np->id) {
  443. X     bonus += np->defense;
  444. X     bonus += sp->defense;
  445. X     if (ap->status == A_GARRISON)
  446. X       bonus += 10;
  447. X   } else {
  448. X  ds1 = get_diplo_status(dm,sp->owner,np->id);
  449. X  ds2 = get_diplo_status(dm,np->id,sp->owner);  
  450. X
  451. X    /* count the nation's bonus */
  452. X   if ((ds1 == TREATY || ds1 == ALLIED) && (ds2 == TREATY || ds2 == ALLIED)) {
  453. X      switch(ap->status) {
  454. X        case A_DEFEND: bonus += np->defense;
  455. X                     if (ds1 == TREATY)
  456. X                       bonus += sp->defense;
  457. X                     else /* ALLIED */
  458. X                       bonus += (sp->defense)/2;
  459. X                    break;
  460. X        case A_ATTACK:
  461. X                    { bonus += np->attack;
  462. X                       if (ds1 == TREATY)
  463. X                         bonus += sp->defense;
  464. X                       else /* ALLIED */
  465. X                         bonus += (sp->defense)/2;
  466. X            }
  467. X                     break;
  468. X        case A_GARRISON:
  469. X                   { bonus += np->defense;
  470. X                     if (ds1 == TREATY) {
  471. X                       bonus += sp->defense;
  472. X                       bonus += 10; }
  473. X                     else {/* ALLIED */
  474. X                       bonus += (sp->defense)/2;
  475. X                       bonus += 5; }
  476. X            }
  477. X                     break;
  478. X        default: break;
  479. X      } /* end switch */
  480. X    } else 
  481. X        bonus += np->attack;  /* not allied with owner */
  482. X                                /* just attack bonuses */
  483. X  }
  484. X
  485. X  bonus += ap->sp_bonus;    /* army's special bonus */
  486. X
  487. X  return bonus;
  488. X}
  489. X
  490. X  /* returns the force of that army (minimum 1) */
  491. X  /* this is being called by battle() and extract_losses()
  492. X     and makes a call to total bonus.  It is important to
  493. X     know that **dm is being passed along and not used
  494. X     until it reaches total_bonus() */
  495. X
  496. Xcount_force(np,sp,ap,dm)
  497. X     Snation *np;
  498. X     Ssector *sp;
  499. X     Sarmy *ap;
  500. X     Sdiplo **dm;  /* passed along to total bonus */
  501. X{
  502. X  int      force;  
  503. X
  504. X  force = (ap->n_soldiers*(100+total_bonus(np,sp,ap,dm)))/100;
  505. X  if (force < 1) {
  506. X    return 1;            /* return at least 1 */
  507. X  }
  508. X  return force;
  509. X}
  510. X
  511. Xcount_men(force_list,flags)
  512. X/*
  513. X   This counts the nubmer of units in a given force counting only those
  514. X   units without the flags in flags set.
  515. X*/
  516. Xstruct armyid *force_list;
  517. Xint flags;
  518. X{
  519. X  struct armyid *tmp_alist;
  520. X  Sarmy *ap = NULL, *get_army();
  521. X  Snation *np;
  522. X  int total = 0;
  523. X
  524. X  for (tmp_alist= force_list; tmp_alist != NULL; tmp_alist = tmp_alist->next) {
  525. X    np = &world.nations[tmp_alist->owner];
  526. X    ap = get_army(np, tmp_alist->id);
  527. X    if ((!(ap->flags & flags)) && !(is_spirit(ap))) {
  528. X      total += ap->n_soldiers;
  529. X    }
  530. X  }
  531. X  return total;
  532. X}
  533. X
  534. Xcount_machine(force_list)
  535. X/*
  536. X   This counts the nubmer of units in a given force counting only those
  537. X   units without the flags in flags set.
  538. X*/
  539. Xstruct armyid *force_list;
  540. X{
  541. X  struct armyid *tmp_alist;
  542. X  Sarmy *ap = NULL, *get_army();
  543. X  Snation *np;
  544. X  int total = 0;
  545. X
  546. X  for (tmp_alist= force_list; tmp_alist != NULL; tmp_alist = tmp_alist->next) {
  547. X    np = &world.nations[tmp_alist->owner];
  548. X    ap = get_army(np, tmp_alist->id);
  549. X    if (is_machine(ap)) {
  550. X      total += ap->n_soldiers;
  551. X    }
  552. X  }
  553. X  return total;
  554. X}
  555. X
  556. Xmach_bonus_avg(force_list)
  557. X/*
  558. X   This computes the average bonus gained from machines.
  559. X*/
  560. Xstruct armyid *force_list;
  561. X{
  562. X  struct armyid *tmp_alist;
  563. X  Sarmy *ap = NULL, *get_army();
  564. X  Snation *np;
  565. X  int tot_mach_bonus = 0, total_units = 0;
  566. X
  567. X  for (tmp_alist= force_list; tmp_alist != NULL; tmp_alist = tmp_alist->next) {
  568. X    np = &world.nations[tmp_alist->owner];
  569. X    ap = get_army(np, tmp_alist->id);
  570. X    if (is_machine(ap))
  571. X    {
  572. X      tot_mach_bonus += ap->sp_bonus * ap->n_soldiers;
  573. X      total_units += ap->n_soldiers;
  574. X    }
  575. X  }
  576. X  return (tot_mach_bonus / total_units);
  577. X}
  578. X
  579. X/* This function is being called from battle() */
  580. X
  581. Xextract_losses(list, pct_loss, mail_list, type, dm)
  582. X     struct armyid *list;
  583. X     float pct_loss;
  584. X     struct armyid *mail_list;
  585. X     int type;
  586. X     Sdiplo **dm;
  587. X{
  588. X  struct armyid *tmp_aid;
  589. X  Snation *np;
  590. X  Ssector *sp;
  591. X  Sarmy *ap, *get_army();
  592. X  int killed, dead = 0;
  593. X  char s[EXECLEN], name[NAMELEN];
  594. X
  595. X  tmp_aid = list;
  596. X  if (tmp_aid != NULL) {
  597. X    if (type == NEUTRALS) {
  598. X      sprintf(s, "---<<< NEUTRAL FORCES IN THE REGION >>>---\n");
  599. X    } else {
  600. X        if (type == ALLIES)
  601. X          sprintf(s, "---<<<  First force >>>---\n");
  602. X        else
  603. X          sprintf(s, "---<<< Second force >>>---\n");
  604. X    }
  605. X    battle_mail(mail_list,s);
  606. X  }
  607. X  while (tmp_aid != NULL) {
  608. X    np = &world.nations[tmp_aid->owner];
  609. X    ap = get_army(np,tmp_aid->id);
  610. X    sp = &world.map[ap->pos.x][ap->pos.y];
  611. X      /* special case for mages and ships:  they
  612. X     only die if more than 80% of supporting armies
  613. X     are killed.
  614. X       */
  615. X    if ((strcmp(ap->type, "Mage") == 0) || is_cargo(ap)) {
  616. X      if (pct_loss > 0.8) {
  617. X    killed = ap->n_soldiers;
  618. X      } else {
  619. X    killed = 0;
  620. X      }
  621. X    } else {
  622. X      killed = (int) (ap->n_soldiers * pct_loss + .5);
  623. X        /* if less than 5 soldiers, or if kamikaze unit, kill them */
  624. X      if ((ap->n_soldiers - killed) < 5 || is_kamikaze(ap)) {
  625. X    killed = ap->n_soldiers;
  626. X      }
  627. X    }
  628. X
  629. X    if (strlen(ap->name) == 0) {
  630. X      strcpy(ap->name, "(no name)");
  631. X    } else {
  632. X      sprintf(name, " \"%s\" ", ap->name);
  633. X    }
  634. X    sprintf(s,
  635. X    "\t%s: Army %s (%d):\n\t\t%d %s\n",
  636. X        np->name, name, ap->id, ap->n_soldiers, ap->type);
  637. X    battle_mail(mail_list,s);
  638. X
  639. X/* AH YOU LITTLE BUGGER, the cause of the segmentation fault mystery
  640. X   I didn't look at this sprintf() funtion and it does in fact call
  641. X   total_bonus() and count_force.  So I just added an extra parameter
  642. X   **dm
  643. X */
  644. X    sprintf(s, "\t\tbonus %d, force %d;\n\t\tloses %d men.\n",
  645. X        total_bonus(np, sp, ap, dm), count_force(np, sp, ap, dm), killed);
  646. X    battle_mail(mail_list,s);
  647. X
  648. X    ap->n_soldiers -= killed;
  649. X    dead += killed;
  650. X    if (ap->n_soldiers == 0) {    /* Army destroyed */
  651. X      delete_army_sector(sp, ap);
  652. X      delete_army_nation(np, ap);
  653. X    }
  654. X    tmp_aid = tmp_aid->next;
  655. X  }
  656. X    /* now that we have the dead count, we can raise some of them
  657. X       to join with the vampire units.  this code is primitive:
  658. X       just for example, it does not take into account that more
  659. X       people may rise than actually died (if there are lots of
  660. X       vampire units).
  661. X     */
  662. X  for (tmp_aid = list; tmp_aid != NULL; tmp_aid = tmp_aid->next) {
  663. X    np = &world.nations[tmp_aid->owner];
  664. X     /* only if we *do* get the army can we go on. it might have been killed */
  665. X    if (ap = get_army(np, tmp_aid->id)) {
  666. X/*      sp = &world.map[ap->pos.x][ap->pos.y]; why??? */
  667. X      if (is_vampire(ap)) {
  668. X          /* notice that an army canot grow by more than a certain amount */
  669. X    ap->n_soldiers += min((int) (dead*VAMPIRE_FRACT), 10*ap->n_soldiers);
  670. X      }
  671. X    }
  672. X  }
  673. X  return dead;
  674. X}
  675. X
  676. Xfree_list(list)
  677. X     struct armyid *list;
  678. X{
  679. X  struct armyid *tmp;
  680. X
  681. X  while (list != NULL) {
  682. X    tmp = list;
  683. X    list = list->next;
  684. X    free(tmp);
  685. X  }
  686. X}
  687. X
  688. Xstatus_check(list,status)
  689. X     struct armyid *list;
  690. X     int status;
  691. X{
  692. X  struct armyid *tmp;
  693. X  Sarmy *ap, *get_army();
  694. X  
  695. X  tmp = list;
  696. X  while (tmp != NULL) {
  697. X    ap = get_army(&world.nations[tmp->owner],tmp->id);
  698. X    if (ap->status == status) {
  699. X      return 1;
  700. X    }
  701. X    tmp = tmp->next;
  702. X  }
  703. X  return 0;
  704. X}
  705. X
  706. Xbattle_mail(mail_list,s)
  707. X     struct armyid *mail_list;
  708. X     char s[];
  709. X{
  710. X  struct armyid *alist;
  711. X
  712. X  alist = mail_list;
  713. X  while (alist != NULL) {
  714. X    single_mail(alist->owner,s);
  715. X    alist = alist->next;
  716. X  }
  717. X}
  718. X
  719. X  /* prints the introductory message, with relative
  720. X     coordinates for each nation.
  721. X   */
  722. Xintro_battle_mail(mail_list, x, y)
  723. X     struct armyid *mail_list;
  724. X     int x, y;
  725. X{
  726. X  Snation *np;
  727. X  struct armyid *alist = mail_list;
  728. X  char s[EXECLEN];
  729. X
  730. X  while (alist) {
  731. X    Snation *sect_owner = &world.nations[world.map[x][y].owner];
  732. X
  733. X    np = &world.nations[alist->owner];
  734. X    sprintf(s, "\nBattle Reported in Sector (%d, %d) [owner: %s]:\n",
  735. X        xrel(x, y, np->capital), yrel(x, y, np->capital),
  736. X        sect_owner->id == 0 ? "unowned" : sect_owner->name);
  737. X    single_mail(alist->owner, s);
  738. X    alist = alist->next;
  739. X  }
  740. X}
  741. X
  742. X  /* prints some stuff to the News about the battle */
  743. Xintro_battle_news(news_fp, x, y, ally_list, enemy_list, neutral_list)
  744. X     FILE *news_fp;
  745. X     int x, y;
  746. X     struct armyid *ally_list, *enemy_list, *neutral_list;
  747. X{
  748. X  Snation *np;
  749. X  struct armyid *alist;        /* to run through the lists */
  750. X  Sarmy *ap, *get_army();
  751. X  Ssector *sp = &world.map[x][y];
  752. X  char s[EXECLEN];
  753. X
  754. X  np = &world.nations[world.map[x][y].owner]; /* nation in which it happens */
  755. X  fprintf(news_fp, "\nBattle Reported in %s", np->id ? np->name
  756. X      : "unowned land");
  757. X  if (strlen(sp->name) > 0) {
  758. X    fprintf(news_fp, " (\"%s\")", sp->name);
  759. X  }
  760. X
  761. X  fprintf(news_fp, ".\nInvolved armies:\n");
  762. X/*  fprintf(news_fp,   "**************\n"); */
  763. X  alist = ally_list;
  764. X  while (alist) {        /* run through the participants */
  765. X    np = &world.nations[alist->owner];
  766. X    ap = get_army(np, alist->id);
  767. X    if (is_spirit(ap)) {
  768. X      fprintf(news_fp, "\t%s (spirit %s)\n", np->name, ap->name);
  769. X    } else {
  770. X      fprintf(news_fp, "\t%s (army %s)\n", np->name, ap->name);
  771. X    }
  772. X    alist = alist->next;
  773. X  }
  774. X  fprintf(news_fp, "versus\n");
  775. X  alist = enemy_list;
  776. X  while (alist) {        /* run through the participants */
  777. X    np = &world.nations[alist->owner];
  778. X    ap = get_army(np, alist->id);
  779. X    if (is_spirit(ap)) {
  780. X      fprintf(news_fp, "\t%s (spirit %s)\n", np->name, ap->name);
  781. X    } else {
  782. X      fprintf(news_fp, "\t%s (army %s)\n", np->name, ap->name);
  783. X    }
  784. X    alist = alist->next;
  785. X  }
  786. X  if (neutral_list) {
  787. X    fprintf(news_fp, "Neutral Armies:\n");
  788. X    fprintf(news_fp, "--------------:\n");
  789. X  }
  790. X  alist = neutral_list;
  791. X  while (alist) {        /* run through the participants */
  792. X    np = &world.nations[alist->owner];
  793. X    fprintf(news_fp, "\t%s\n", np->name);
  794. X    alist = alist->next;
  795. X  }
  796. X}
  797. X
  798. Xsingle_mail(nation,s)
  799. X     int nation;
  800. X     char s[];
  801. X{
  802. X  char mailname[NAMELEN];
  803. X
  804. X  if (world.nations[nation].npc_flag != 0) return;
  805. X
  806. X  sprintf(mailname, "mail%d", nation);
  807. X  if ( (mailfile = fopen(mailname, "a") ) == NULL)
  808. X  {
  809. X    fprintf(stderr,"Error: Cannot reopen mail file %s\n",mailname);
  810. X    clean_exit();
  811. X    exit(1);
  812. X  }
  813. X  fprintf(mailfile, s);
  814. X  fclose(mailfile);
  815. X}
  816. X
  817. Xbattle(dm, x, y, news_fp, ally_list, enemy_list, neutral_list, mail_list)
  818. X     Sdiplo **dm;
  819. X     int x,y;
  820. X     FILE *news_fp;            /* for reporting to the news */
  821. X     struct armyid *ally_list, *enemy_list, *neutral_list, *mail_list;
  822. X{
  823. X  Snation *np = NULL;
  824. X  Ssector *sp = &world.map[x][y];
  825. X  Sarmy *ap = NULL, *get_army();
  826. X/*  struct armyid *ally_list, *enemy_list, *neutral_list, *mail_list, *tmp; */
  827. X  struct armyid *tmp_alist;
  828. X  int ally_force, enemy_force, neutral_force;
  829. X  int ally_dead, enemy_dead, neutral_dead;
  830. X  int enemy_act_mach, ally_act_mach, neutral_act_mach, mach_force_fact;
  831. X  double defense_loss = 0.0;
  832. X
  833. X  float ally_losses, enemy_losses, neutral_losses;
  834. X  int nation;
  835. X
  836. X  char mailname[NAMELEN], s[EXECLEN];
  837. X
  838. X  /* Initialize the three lists for armies in the sector's battle */
  839. X
  840. X/*  ally_list = enemy_list = neutral_list = mail_list = NULL; */
  841. X  ally_force = enemy_force = neutral_force = 0;
  842. X  ally_dead = enemy_dead = neutral_dead = 0;
  843. X  ally_losses = enemy_losses = neutral_losses = 0.0;
  844. X
  845. X  /* Now begin breaking the armies up by affiliations and sum forces */
  846. X  for (tmp_alist = ally_list; tmp_alist != NULL; tmp_alist = tmp_alist->next) {
  847. X    np = &world.nations[tmp_alist->owner];
  848. X    ap = get_army(np, tmp_alist->id);
  849. X    ally_force += count_force(np,sp,ap,dm);
  850. X  }
  851. X  for(tmp_alist = enemy_list; tmp_alist != NULL; tmp_alist = tmp_alist->next) {
  852. X    np = &world.nations[tmp_alist->owner];
  853. X    ap = get_army(np, tmp_alist->id);
  854. X    enemy_force += count_force(np,sp,ap,dm);
  855. X  }
  856. X  for(tmp_alist=neutral_list; tmp_alist != NULL; tmp_alist = tmp_alist->next){
  857. X    np = &world.nations[tmp_alist->owner];
  858. X    ap = get_army(np, tmp_alist->id);
  859. X    neutral_force += count_force(np,sp,ap,dm);
  860. X  }
  861. X
  862. X/*  tmp = sp->alist;
  863. X  while (tmp != NULL) {
  864. X    np = &world.nations[tmp->owner];
  865. X    ap = get_army(np,tmp->id);
  866. X    nation = tmp->owner;
  867. X    if (ally_list == NULL
  868. X    || supports(dm,ally_list,nation)
  869. X        || against(dm,enemy_list,nation)) {
  870. X      add_to_list(&ally_list,tmp,&mail_list);
  871. X      ally_force += count_force(np,sp,ap,dm);
  872. X    } else {
  873. X      if (supports(dm,enemy_list,nation) 
  874. X         || against(dm,ally_list,nation)) {
  875. X    add_to_list(&enemy_list,tmp,&mail_list);
  876. X    enemy_force += count_force(np,sp,ap,dm);
  877. X      } else {
  878. X    add_to_list(&neutral_list,tmp,&mail_list);
  879. X    neutral_force += count_force(np,sp,ap,dm);
  880. X      }
  881. X    }
  882. X    tmp = tmp->next;
  883. X  }
  884. X*/
  885. X/* Now adjust the forces for the presence of macines */
  886. X  if ((ally_act_mach = min(count_machine(ally_list) * MEN_PER_MACHINE,
  887. X                        count_men(ally_list,(AF_MACHINE)))) != 0)
  888. X  {
  889. X    ally_force += ally_act_mach * mach_bonus_avg(ally_list) / 100;
  890. X  }
  891. X  if ((enemy_act_mach = min(count_machine(enemy_list) * MEN_PER_MACHINE,
  892. X                     count_men(enemy_list,(AF_MACHINE)))) != 0)
  893. X  {
  894. X    enemy_force += enemy_act_mach * mach_bonus_avg(enemy_list) / 100;
  895. X  }
  896. X  if ((neutral_act_mach = min(count_machine(neutral_list) * MEN_PER_MACHINE,
  897. X                            count_men(neutral_list,(AF_MACHINE)))) != 0)
  898. X  {
  899. X    neutral_force += neutral_act_mach * mach_bonus_avg(neutral_list) / 100;
  900. X  }
  901. X  /* Now calculate loss percentages for each side */
  902. X  if (ally_force != 0 && enemy_force != 0 && 
  903. X     (status_check(ally_list,A_ATTACK) || status_check(enemy_list,A_ATTACK) ||
  904. X      status_check(ally_list,A_OCCUPY) || status_check(enemy_list,A_OCCUPY))) {
  905. X
  906. X      /* send an introductory message to all users,
  907. X     giving the relative coords of sector in which
  908. X     battle happens.  also send out some news.
  909. X       */
  910. X    intro_battle_mail(mail_list, x, y);
  911. X    intro_battle_news(news_fp, x, y, ally_list, enemy_list, neutral_list);
  912. X
  913. X    ally_losses = (1.0*enemy_force*enemy_force)
  914. X      /(1.0*(ally_force*ally_force + enemy_force*enemy_force));
  915. X    enemy_losses = (1.0*ally_force*ally_force)
  916. X      /(1.0*(ally_force*ally_force + enemy_force*enemy_force));
  917. X    if (ally_losses < enemy_losses) {
  918. X      neutral_losses = ally_losses/10.0;
  919. X    } else {
  920. X      neutral_losses = enemy_losses/10.0;
  921. X    }
  922. X/* Now we mess with the fortifications. */
  923. X  np = &world.nations[enemy_list->owner];
  924. X  defense_loss = 0.0;
  925. X  if (sp->owner == np->id)
  926. X  {
  927. X    if (ally_act_mach != 0)
  928. X    { 
  929. X      defense_loss = count_men(ally_list,AF_MACHINE);
  930. X      defense_loss = defense_loss/ally_act_mach;
  931. X      defense_loss *= enemy_losses;
  932. X      defense_loss = (int)(sp->defense * defense_loss);
  933. X      sp->defense -= (int)defense_loss;
  934. X    }
  935. X  }
  936. X  np = &world.nations[ally_list->owner];
  937. X  if (sp->owner == np->id)
  938. X  {
  939. X    if (enemy_act_mach != 0)
  940. X    { 
  941. X      defense_loss = count_men(enemy_list,AF_MACHINE);
  942. X      defense_loss = defense_loss/enemy_act_mach;
  943. X      defense_loss *= ally_losses;
  944. X      defense_loss = (int)(sp->defense * defense_loss);
  945. X      sp->defense -= (int)defense_loss;
  946. X    }
  947. X  }
  948. X
  949. X    /* Now extract losses from each group */
  950. X    /* calls to extract_losses() */
  951. X
  952. X    ally_dead = extract_losses(ally_list,ally_losses,mail_list,ALLIES,dm);
  953. X    enemy_dead = extract_losses(enemy_list,enemy_losses,mail_list,ENEMIES,dm);
  954. X    neutral_dead =
  955. X      extract_losses(neutral_list,neutral_losses,mail_list,NEUTRALS,dm);
  956. X  } 
  957. X  if (defense_loss != 0.0)
  958. X  {
  959. X    sprintf(s, "\nSector Defenses reduced by %d to %d\n",
  960. X                               (int)defense_loss,sp->defense);
  961. X    battle_mail(mail_list,s);
  962. X  }
  963. X
  964. X  /* Now free up all the memory we ate with our army lists! */
  965. X  free_list(ally_list);
  966. X  free_list(enemy_list);
  967. X  free_list(neutral_list);
  968. X  free_list(mail_list);
  969. X}
  970. X
  971. X  /* this is an ugly routine which goes into great detail
  972. X     to see if a war is actually taking place in a given
  973. X     sector.  it is totally inefficient, but until we
  974. X     redo the battle code, it will have to do.  the previous
  975. X     code used to not yield battles in some cases.
  976. X   */
  977. Xis_war(dm, x, y, news_fp)
  978. X     Sdiplo **dm;
  979. X     int x, y;
  980. X     FILE *news_fp;
  981. X{
  982. X  Ssector *sp = &world.map[x][y];
  983. X  Snation *np, *tmp_np;
  984. X  struct armyid *alist, *tmp_alist;
  985. X  int id1, id2, stat1, stat2;
  986. X
  987. X/*  printf("**********sector (%d,%d)***************\n", x, y); */
  988. X  alist = sp->alist;
  989. X  while (alist != NULL) {
  990. X/*    printf("alist = (%d,%d)\n", alist->owner, alist->id); */
  991. X    np = &world.nations[alist->owner];
  992. X    id1 = np->id;
  993. X    tmp_alist = sp->alist;
  994. X    while (tmp_alist != NULL) {
  995. X/*      printf("\ttmp_alist = (%d,%d)\n", tmp_alist->owner, tmp_alist->id); */
  996. X      tmp_np = &world.nations[tmp_alist->owner];
  997. X      id2 = tmp_np->id;
  998. X      stat1 = get_diplo_status(dm, id1, id2);
  999. X/*      printf("stat1 = %d\n", stat1); */
  1000. X      stat2 = get_diplo_status(dm, id2, id1);
  1001. X/*      printf("stat2 = %d\n", stat2); */
  1002. X      if (stat1 == WAR || stat1 == JIHAD || stat2 == WAR || stat2 == JIHAD) {
  1003. X    struct armyid *other_tmp_alist;
  1004. X    struct armyid *ally_list, *enemy_list, *neutral_list, *mail_list;
  1005. X    int nation;
  1006. X
  1007. X    ally_list = enemy_list = neutral_list = mail_list = NULL;
  1008. X
  1009. X    printf("Found battle between %s and %s\n", np->name, tmp_np->name);
  1010. X    add_to_list(&ally_list, tmp_alist, &mail_list);
  1011. X    other_tmp_alist = sp->alist;
  1012. X      /* now we add everything else in this sector to some list */
  1013. X    while (other_tmp_alist != NULL) {
  1014. X        /* bad kludge */
  1015. X      nation = other_tmp_alist->owner;
  1016. X      /* remember:  we have already added an ally.  don't
  1017. X         duplicate him.
  1018. X       */
  1019. X      if (other_tmp_alist->owner != tmp_alist->owner
  1020. X          || other_tmp_alist->id != tmp_alist->id) {
  1021. X        if (ally_list == NULL
  1022. X        || supports(dm,ally_list,nation)
  1023. X        || against(dm,enemy_list,nation)) {
  1024. X          add_to_list(&ally_list,other_tmp_alist,&mail_list);
  1025. X/*          ally_force += count_force(np,sp,ap,dm); */
  1026. X        } else {
  1027. X          if (supports(dm,enemy_list,nation) 
  1028. X          || against(dm,ally_list,nation)) {
  1029. X        add_to_list(&enemy_list,other_tmp_alist,&mail_list);
  1030. X/*        enemy_force += count_force(np,sp,ap,dm); */
  1031. X          } else {
  1032. X        add_to_list(&neutral_list,other_tmp_alist,&mail_list);
  1033. X/*        neutral_force += count_force(np,sp,ap,dm); */
  1034. X          }
  1035. X        }
  1036. X      }
  1037. X      other_tmp_alist = other_tmp_alist->next;
  1038. X    }
  1039. X    battle(dm, x, y, news_fp,
  1040. X           ally_list, enemy_list, neutral_list, mail_list);
  1041. X    return 1;
  1042. X      }
  1043. X      tmp_alist = tmp_alist->next;
  1044. X    }
  1045. X    alist = alist->next;
  1046. X  }
  1047. X  return 0;
  1048. X}
  1049. END_OF_FILE
  1050. if test 27165 -ne `wc -c <'battle.c'`; then
  1051.     echo shar: \"'battle.c'\" unpacked with wrong size!
  1052. fi
  1053. # end of 'battle.c'
  1054. fi
  1055. if test -f 'misc.c' -a "${1}" != "-c" ; then 
  1056.   echo shar: Will not clobber existing file \"'misc.c'\"
  1057. else
  1058. echo shar: Extracting \"'misc.c'\" \(25699 characters\)
  1059. sed "s/^X//" >'misc.c' <<'END_OF_FILE'
  1060. X/* misc.c -- routines for which a better place has yet to be found */
  1061. X/*           or routines which are needed in many places           */
  1062. X
  1063. X/*
  1064. X * Copyright (C) 1990 Free Software Foundation, Inc.
  1065. X * Written by the dominion project.
  1066. X *
  1067. X * This file is part of dominion.
  1068. X *
  1069. X * dominion is free software; you can redistribute it and/or
  1070. X * modify it under the terms of the GNU General Public License as published
  1071. X * by the Free Software Foundation; either version 1, or (at your option)
  1072. X * any later version.
  1073. X *
  1074. X * This software is distributed in the hope that it will be useful,
  1075. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1076. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1077. X * GNU General Public License for more details.
  1078. X *
  1079. X * You should have received a copy of the GNU General Public License
  1080. X * along with this software; see the file COPYING.  If not, write to
  1081. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1082. X */
  1083. X
  1084. X
  1085. X/* int interrupt() - handles interupts                             */
  1086. X/* show_nation(np) - displays a nation's characteristics           */
  1087. X/* free_nation_mark(wp,c) - tell us if the symbol is available     */
  1088. X/* getline(s,n) - read a line from stdin, remove \n                */
  1089. X/* get_crypt_pass(prompt,s,w) - get password and encrypt           */
  1090. X/* critical() - while writing, don't bug me!!                      */
  1091. X/* noncritical() - normal operation                                */
  1092. X/* which_mark(x,y,up) - determine which mark is to be shown for    */
  1093. X/*           the sector in question based on display modes, etc.   */
  1094. X/* addsector(np,x,y) - adds sector x,y to nation's list of owned   */
  1095. X/*           sectors.  Also changes owner of sector to nation->id. */
  1096. X/* subtsector(np,x,y) - deletes sector x,y from nation's list of   */
  1097. X/*           owned sectors.                                        */
  1098. X/* destroy_nation(np) - frees all memory used by that nation       */
  1099. X/* get_n_cities(np) - return number of cities in nation            */
  1100. X/* get_n_civil(np) - return number of civilians in nation          */
  1101. X/* unique_name(name) - returns true if a nation with this name     */
  1102. X/*           does not exist yet                                    */
  1103. X/* free_army_id(np) - finds first free army id for a nation        */
  1104. X/* get_space() - waits for the user to type a space                */
  1105. X/* statline(s,s) - places information on the statline              */
  1106. X/* statline2(s,s) - places information on statline 2               */
  1107. X/* get_spirit_from_type(up,type) - returns a spirit pointer, given a type */
  1108. X/* gen_exec(s) - puts the exec line into the exec list (and later file)   */
  1109. X/* is_good_order(name) - TRUE if this is a valid name for a magic order   */
  1110. X/* find_visible_sectors(visible_sectors) - updates visibility matrix      */
  1111. X
  1112. X#include "dominion.h"
  1113. X#include "misc.h"
  1114. X#include "army.h"
  1115. X#include "cur_stuff.h"
  1116. X#include <stdio.h>
  1117. X#include <ctype.h>
  1118. X#include <signal.h>
  1119. X
  1120. Xextern int (*wrapx)(), (*wrapy)();
  1121. X
  1122. Xextern Sworld world;
  1123. Xextern struct s_desig_map desig_map[];
  1124. Xextern struct s_altitude_map altitude_map[];
  1125. Xextern struct item_map terrains[];
  1126. Xextern struct item_map climates[];
  1127. Xextern Suser user;
  1128. Xint viewall;
  1129. Xextern int debug;
  1130. X
  1131. XWINDOW *sectw;
  1132. X
  1133. X/* handles interrupts */
  1134. Xint interrupt()
  1135. X{
  1136. X  printf("\r\ngot an interrupt.  quitting nicely...\r\n");
  1137. X  cleanup();        /* cleanup depends on which program you are in */
  1138. X  clean_exit();
  1139. X  exit(0);
  1140. X}
  1141. X
  1142. X/* show a nation's characteristics */
  1143. Xshow_nation(np)
  1144. X     Snation *np;        /* nation pointer */
  1145. X{
  1146. X  printf("\n\tname: %s (id = %d)\n", np->name, np->id);
  1147. X  printf("\tleader: %s\n", np->leader);
  1148. X  printf("\tpasswd: %s\n", np->passwd);
  1149. X  printf("\tcapital is at (%d, %d)\n", np->capital.x, np->capital.y);
  1150. X  printf("\trace is %s\n", np->race.name);
  1151. X  printf("\tnation mark is %c\n", np->mark);
  1152. X  printf("\t%d civilians; %d soldiers; %d armies.\n",
  1153. X     get_n_civil(np), get_n_soldiers(np), np->n_armies);
  1154. X  printf("\tmagical order %s\n", np->mag_order);
  1155. X}
  1156. X
  1157. X
  1158. X    /* tell us if the symbol is available */
  1159. Xfree_nation_mark(wp, c)
  1160. X     Sworld *wp;
  1161. X     Symbol c;
  1162. X{
  1163. X  int i;
  1164. X
  1165. X  if (!isprint(c)) {
  1166. X    return 0;
  1167. X  }
  1168. X  for (i = 0; i < wp->n_nations; ++i) {
  1169. X    if (wp->nations[i].mark == c) {
  1170. X      return 0;
  1171. X    }
  1172. X  }
  1173. X  return 1;
  1174. X}
  1175. X
  1176. Xgetline(s, n)            /* read a line from stdin, remove \n */
  1177. X     char s[];
  1178. X     int n;
  1179. X{
  1180. X  fgets(s, n, stdin);
  1181. X  if (s[strlen(s)-1] == '\n') {    /* remove \n if it is there */
  1182. X    s[strlen(s)-1] = '\0';
  1183. X  }
  1184. X}
  1185. X
  1186. X  /* get a password and encrypt it.  if the parameter "default"
  1187. X     has a string in it, use that instead of getting it from
  1188. X     the terminal.  if "w" is not NULL, get the string from
  1189. X     the window "w".
  1190. X   */
  1191. Xget_crypt_pass(prompt, pass, w, def_pass)
  1192. X     char prompt[], pass[];
  1193. X     WINDOW *w;
  1194. X     char def_pass[];
  1195. X{
  1196. X  char *s1, s2[PASSLEN], *getpass(), *crypt();
  1197. X
  1198. X    /* if there is already a password, it is passed in the string def_pass */
  1199. X  if (def_pass != NULL && strlen(def_pass) > 0) {
  1200. X    strcpy(s2, def_pass);
  1201. X    s1 = crypt(s2, SALT);
  1202. X    strcpy(pass, s1+2);
  1203. X    return;
  1204. X  }
  1205. X    /* if no password was given us, get it from input */
  1206. X  if (w == NULL) {
  1207. X    s1 = getpass(prompt);
  1208. X    strcpy(s2, s1);
  1209. X    s1 = crypt(s2, SALT);
  1210. X    strcpy(pass, s1 + 2);    /* final crypted pass. without salt */
  1211. X  } else {
  1212. X    wprintw(w, "%s", prompt);
  1213. X    wrefresh(w);
  1214. X    wscanw(w, "%s", s2);
  1215. X    s1 = crypt(s2, SALT);
  1216. X    strcpy(pass, s1+2);
  1217. X  }
  1218. X}
  1219. X
  1220. Xcpass(np, pass)
  1221. X     Snation *np;
  1222. X     char pass[];
  1223. X{
  1224. X  char s[EXECLEN];
  1225. X  sprintf(s, "CPASS:%d:%s\n", np->id, pass);
  1226. X  gen_exec(s);
  1227. X}
  1228. X
  1229. Xwhich_mark(x, y, up)
  1230. X     int x, y;
  1231. X     Suser *up;
  1232. X{
  1233. X  int highlight = 1;        /* should we highlight? 1=no,-1=yes */
  1234. X  int owner = world.map[x][y].owner, mark = '\0';
  1235. X  Ssector *sectp = &world.map[x][y];
  1236. X  int visibility = user.visible_sectors[x][y];
  1237. X  int cost;
  1238. X  Sarmy *ap, *get_army();
  1239. X  struct armyid *alist;
  1240. X
  1241. X    /* figure out what to draw */
  1242. X    /* should find a clean way of dealing with above/under water */
  1243. X  if (!user.underwater && sectp->altitude < SEA_LEVEL) {
  1244. X    mark = '~';            /* if not underwater, water looks like ~ */
  1245. X  }
  1246. X  if (user.underwater && sectp->altitude >= SEA_LEVEL) {
  1247. X    mark = '.';        /* if underwater, land looks like # */
  1248. X  }
  1249. X
  1250. X  if (!mark) {            /* only if mark is not yet set */
  1251. X    switch (up->display) {
  1252. X    case DESIGNATION:
  1253. X      if (owner == up->id) {
  1254. X    mark = desig_map[sectp->designation].mark;
  1255. X      } else {
  1256. X    if (world.nations[owner].mark == '-') {
  1257. X      mark = altitude_map[map_alt(sectp->altitude)].mark;
  1258. X    } else {
  1259. X      mark = world.nations[owner].mark;
  1260. X    }
  1261. X      }
  1262. X    break;
  1263. X    case NATION_MARK:
  1264. X/*    if (world.nations[owner].mark == '-' || !(visibility & SEE_OWNER)) {
  1265. X      mark = altitude_map[map_alt(sectp->altitude)].mark;
  1266. X      } else {
  1267. X      mark = world.nations[owner].mark;
  1268. X      }
  1269. X   */
  1270. X      mark = world.nations[owner].mark;
  1271. X      break;
  1272. X    case SOIL:
  1273. X      if (visibility & SEE_RESOURCES) {
  1274. X    mark = (sectp->soil <= 9) ? sectp->soil + '0' : '+';
  1275. X      } else {
  1276. X    mark = '?';
  1277. X      }
  1278. X      break;
  1279. X    case METAL:
  1280. X      if (visibility & SEE_RESOURCES) {
  1281. X    mark = (sectp->metal <= 9) ? sectp->metal + '0' : '+';
  1282. X      } else {
  1283. X    mark = '?';
  1284. X      }
  1285. X      break;
  1286. X    case JEWELS:
  1287. X      if (visibility & SEE_RESOURCES) {
  1288. X    mark = (sectp->jewels <= 9) ? sectp->jewels + '0' : '+';
  1289. X      } else {
  1290. X    mark = '?';
  1291. X      }
  1292. X      break;
  1293. X    case ALTITUDE:
  1294. X      if (visibility & SEE_LAND_WATER) {
  1295. X/*      mark = (sectp->altitude <= 9) ? sectp->altitude + '0' : '+'; */
  1296. X    if (sectp->altitude > 9) {
  1297. X      mark = '+';
  1298. X    } else if (sectp->altitude >= 0) {
  1299. X      mark = sectp->altitude + '0';
  1300. X    } else {
  1301. X      mark = (-1 * sectp->altitude) + '0';
  1302. X    }
  1303. X      } else {
  1304. X    mark = '?';
  1305. X      }
  1306. X      break;
  1307. X    case CLIMATE:
  1308. X      if (visibility & SEE_LAND_WATER) {
  1309. X    mark = climates[sectp->climate].mark;
  1310. X      } else {
  1311. X    mark = '?';
  1312. X      }
  1313. X      break;
  1314. X    case POPULATION:
  1315. X      if (visibility & SEE_POPULATION) {
  1316. X    if (sectp->n_people < 950) {
  1317. X      mark =(sectp->n_people < 950) ? (sectp->n_people + 50)/100+'0' : '+';
  1318. X    } else {
  1319. X      mark = 'I';
  1320. X    }
  1321. X      } else {
  1322. X    mark = '?';
  1323. X      }
  1324. X      break;
  1325. X    case ARMY_MOVECOST:
  1326. X      if (visibility & SEE_LAND_WATER) {
  1327. X    if ((ap=get_army (&world.nations[up->id], user.current_army))
  1328. X        == NULL) {
  1329. X      cost = get_generic_move_cost (&world.nations[up->id], sectp);
  1330. X    } else {
  1331. X      cost = get_army_move_cost (&world.nations[up->id], sectp, ap);
  1332. X    }
  1333. X    mark = (cost <= 9) ? cost + '0' : '+';
  1334. X      } else {
  1335. X    mark = '?';
  1336. X      }
  1337. X      break;
  1338. X    case MOVECOST:
  1339. X      if (visibility & SEE_LAND_WATER) {
  1340. X    cost = get_generic_move_cost(&world.nations[up->id], sectp);
  1341. X    mark = (cost <= 9) ? cost + '0' : '+';
  1342. X      } else {
  1343. X    mark = '?';
  1344. X      }
  1345. X      break;
  1346. X    case TERRAIN:
  1347. X      if (visibility & SEE_LAND_WATER) {
  1348. X    mark = terrains[sectp->terrain - MIN_TERRAIN].mark;
  1349. X      } else {
  1350. X    mark = '?';
  1351. X      }
  1352. X      break;
  1353. X    default:            /* this should never happen */
  1354. X      break;
  1355. X    }
  1356. X  }
  1357. X
  1358. X    /* here set the highlighting; we know user owns sector */
  1359. X  switch (up->highlight) {
  1360. X  case H_OWNED:
  1361. X    if (sectp->owner == up->id) {
  1362. X      highlight = -1;        /* if user owns, highlight */
  1363. X    }
  1364. X    break;
  1365. X  case H_ARMIES:
  1366. X    if ((user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)
  1367. X     && has_visible_army(sectp, &user)) {
  1368. X      highlight = -1;
  1369. X    } 
  1370. X/*    if (sectp->alist != NULL
  1371. X    && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  1372. X      highlight = -1;
  1373. X    } else {
  1374. X      highlight = 1;
  1375. X    }
  1376. X*/
  1377. X    break;
  1378. X  case H_HOSTILE:
  1379. X    if (has_hostile (sectp)) {
  1380. X      highlight = -1;
  1381. X    }
  1382. X    break;
  1383. X  case H_YOUR_ARMIES:
  1384. X    if (sectp->alist != NULL
  1385. X    && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  1386. X      alist = sectp->alist;
  1387. X      while (alist != NULL) {
  1388. X    if (alist->owner == user.id) {
  1389. X      highlight = -1;
  1390. X      break;
  1391. X    }
  1392. X    alist = alist->next;
  1393. X      }
  1394. X    }
  1395. X    break;
  1396. X  case H_OTHER_ARMIES:
  1397. X    if (sectp->alist != NULL
  1398. X    && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  1399. X      alist = sectp->alist;
  1400. X      ap = get_army(&world.nations[alist->owner], alist->id);
  1401. X      while (alist != NULL) {
  1402. X    if (alist->owner != user.id && !is_hidden(ap)) {
  1403. X      highlight = -1;
  1404. X      break;
  1405. X    }
  1406. X    alist = alist->next;
  1407. X      }
  1408. X    }
  1409. X    break;
  1410. X  case H_MOVE_LEFT:
  1411. X    if (sectp->alist != NULL
  1412. X    && (user.visible_sectors[sectp->loc.x][sectp->loc.y] & SEE_ARMIES)) {
  1413. X      highlight = 1;
  1414. X      alist = sectp->alist;
  1415. X      while (alist != NULL) {
  1416. X    if (alist->owner == user.id) {
  1417. X      ap = get_army(&world.nations[alist->owner], alist->id);
  1418. X      if (ap->mvpts > 0) {
  1419. X        highlight = -1;
  1420. X      }
  1421. X    }
  1422. X    alist = alist->next;
  1423. X      }
  1424. X    } else {
  1425. X      highlight = 1;
  1426. X    }
  1427. X    break;
  1428. X  case H_UNEMP:
  1429. X    if ((sectp->n_people > n_workers(sectp)) && (sectp->owner == up->id)) {
  1430. X      highlight = -1;
  1431. X    }
  1432. X    break;
  1433. X  case H_NONE:
  1434. X    highlight = 1;
  1435. X    break;
  1436. X  default:
  1437. X    break;
  1438. X  }
  1439. X
  1440. X  return highlight*mark;    /* highlight can be +- 1 */
  1441. X}
  1442. X
  1443. X/********************************************************************/
  1444. X/* adds sector x,y to nation's list of owned sectors. Also changes  */
  1445. X/* owner of sector to nation->id.                                   */
  1446. X/********************************************************************/
  1447. Xaddsector(np, x, y)
  1448. X     Snation *np;
  1449. X     int x, y;
  1450. X{
  1451. X  struct pt_list *sect;
  1452. X
  1453. X  sect = (struct pt_list *) malloc(sizeof(struct pt_list));
  1454. X  sect->pt.x = x;
  1455. X  sect->pt.y = y;
  1456. X  sect->next = np->ptlist;
  1457. X  np->ptlist = sect;
  1458. X  np->n_sects++;
  1459. X  world.map[x][y].owner = np->id;
  1460. X}
  1461. X
  1462. X
  1463. Xsubtsector(np, x, y)
  1464. X     Snation *np;
  1465. X     int x, y;
  1466. X{
  1467. X  struct pt_list *sect, *temp;
  1468. X
  1469. X  sect = np->ptlist;
  1470. X  if (sect->pt.x == x && sect->pt.y == y) {
  1471. X    temp = sect;
  1472. X    np->ptlist = sect->next;
  1473. X    (np->n_sects)--;
  1474. X    free(temp);
  1475. X  } else {
  1476. X    temp = sect;
  1477. X    while (sect->pt.x != x || sect->pt.y != y && sect->next != NULL) {
  1478. X      temp = sect;
  1479. X      sect = sect->next;
  1480. X    }
  1481. X    if (sect->pt.x == x && sect->pt.y == y) {
  1482. X      temp->next = sect->next;
  1483. X      free(sect);
  1484. X      (np->n_sects)--;
  1485. X    } else printf("Error - deleting sector not in list!\n");
  1486. X  }
  1487. X  if (np->n_sects == 0) {
  1488. X    np->ptlist = NULL;
  1489. X  }
  1490. X}
  1491. X
  1492. X  /* Destroy a nation:  these things have to be done:
  1493. X     1. Free up its point list, and return the sectors to owner 0
  1494. X     2. Free up its army list, and also its army entires in the
  1495. X        various sector army lists.  This can be done by disbanding
  1496. X    them all. (?)
  1497. X     3. Set the coordinates of its capital to (-1, -1), which alerts
  1498. X        the program that this nation is no more.
  1499. X   */
  1500. Xdestroy_nation(id)
  1501. X     int id;
  1502. X{
  1503. X  struct pt_list *ptlist, *pt_tmp;
  1504. X  Sarmy *army_list, *ap_tmp;
  1505. X  Snation *np = &world.nations[id];
  1506. X  Ssector *sp;
  1507. X  struct army_id *sect_alist;
  1508. X  char s[EXECLEN];
  1509. X
  1510. X  if (np->id == 0) {
  1511. X    return;            /* don't destroy nation 0, ever */
  1512. X  }
  1513. X  ptlist = np->ptlist;
  1514. X
  1515. X  while (ptlist) {
  1516. X      /* return all the sectors */
  1517. X    world.map[ptlist->pt.x][ptlist->pt.y].owner = 0;
  1518. X    world.map[ptlist->pt.x][ptlist->pt.y].designation = D_NODESIG;
  1519. X    world.map[ptlist->pt.x][ptlist->pt.y].n_people = 0;
  1520. X    pt_tmp = ptlist->next;
  1521. X    free(ptlist);
  1522. X    --np->n_sects;
  1523. X    ptlist = pt_tmp;
  1524. X  }
  1525. X  np->ptlist = NULL;
  1526. X
  1527. X  army_list = np->armies;
  1528. X    /* delete armies while we still have armies in the nation */
  1529. X  while (army_list) {
  1530. X    ap_tmp = army_list->next;
  1531. X    sp = &world.map[army_list->pos.x][army_list->pos.y];
  1532. X    delete_army_sector(sp, army_list);
  1533. X    delete_army_nation(np, army_list);
  1534. X    /*    free(army_list); */
  1535. X    /*    army_list = ap_tmp; */
  1536. X    army_list = np->armies;
  1537. X  }
  1538. X  np->armies = NULL;
  1539. X
  1540. X    /* set capital to (-1,-1):  this tells dominion that
  1541. X       the parrot (i mean, nation) is no more
  1542. X     */
  1543. X  np->capital.x = -1;
  1544. X  np->capital.y = -1;
  1545. X}
  1546. X
  1547. X  /* returns the number of cities in this nation */
  1548. Xget_n_cities(np)
  1549. X     Snation *np;
  1550. X{
  1551. X  Ssector *sp;
  1552. X  struct pt_list *ptlist = np->ptlist;
  1553. X  int n_cities = 0;
  1554. X
  1555. X  while (ptlist != NULL) {
  1556. X    sp = &world.map[ptlist->pt.x][ptlist->pt.y];
  1557. X    if (sp->designation == D_CITY || sp->designation == D_CAPITAL) {
  1558. X      ++n_cities;
  1559. X    }
  1560. X    ptlist = ptlist->next;
  1561. X  }
  1562. X  return n_cities;
  1563. X}
  1564. X
  1565. X  /* returns the number of civilians in this nation */
  1566. Xget_n_civil(np)
  1567. X     Snation *np;
  1568. X{
  1569. X  Ssector *sp;
  1570. X  struct pt_list *ptlist = np->ptlist;
  1571. X  int n_civil = 0;
  1572. X
  1573. X  while (ptlist != NULL) {
  1574. X    sp = &world.map[ptlist->pt.x][ptlist->pt.y];
  1575. X    n_civil += sp->n_people;
  1576. X    ptlist = ptlist->next;
  1577. X  }
  1578. X  return n_civil;
  1579. X}
  1580. X
  1581. X  /* returns the number of soldiers in this nation (includes spirits) */
  1582. Xget_n_soldiers(np)
  1583. X     Snation *np;
  1584. X{
  1585. X  Sarmy *armies = np->armies;
  1586. X  int n_sold = 0;
  1587. X
  1588. X  while (armies != NULL) {
  1589. X    n_sold += armies->n_soldiers;
  1590. X    armies = armies->next;
  1591. X  }
  1592. X  return n_sold;
  1593. X}
  1594. X
  1595. X  /* returns true if a nation with this name does not yet exist */
  1596. Xunique_name(name)
  1597. X     char name[];
  1598. X{
  1599. X  int i;
  1600. X  for (i = 0; i < NATIONS; ++i) {
  1601. X    if (strcmp(world.nations[i].name, name) == 0) {
  1602. X      return 0;            /* found a conflicting name */
  1603. X    }
  1604. X  }
  1605. X  return 1;            /* didn't find it any conflict */
  1606. X}
  1607. X
  1608. X  /* this is for when the user hits a harmless key, don't give error */
  1609. Xnull_key()
  1610. X{
  1611. X}
  1612. X
  1613. X  /* returns the first free army id for a nation */
  1614. Xfree_army_id(np)
  1615. X     Snation *np;
  1616. X{
  1617. X  Sarmy *ap = np->armies, *ap_prev = np->armies;
  1618. X  int id;
  1619. X
  1620. X  if (ap == NULL) {
  1621. X    return 0;
  1622. X  }
  1623. X  if (ap->id > 0) {        /* if first slot is unused */
  1624. X    return 0;
  1625. X  }
  1626. X  if (ap->next == NULL) {
  1627. X    return 1;
  1628. X  }
  1629. X  
  1630. X  while (ap != NULL) {
  1631. X    if (ap->id > ap_prev->id+1) { /* a space!! */
  1632. X      id = ap_prev->id + 1;
  1633. X      return id;
  1634. X    }
  1635. X    ap_prev = ap;
  1636. X    ap = ap->next;
  1637. X  }
  1638. X    /* if we have not yet found it, it must be the last one!! */
  1639. X/*  beep(); refresh(); */
  1640. X  id = ap_prev->id + 1;
  1641. X  return id;
  1642. X}
  1643. X
  1644. X  /* this waits for the user to type a space */
  1645. Xget_space()
  1646. X{
  1647. X  fflush(stdin);
  1648. X  while (getch() != ' ') {
  1649. X  }
  1650. X}
  1651. X
  1652. X#ifndef min
  1653. Xmin(a,b)
  1654. X     int a,b;
  1655. X{
  1656. X  return (a < b) ? a : b;
  1657. X}
  1658. X
  1659. Xmax(a,b)
  1660. X     int a,b;
  1661. X{
  1662. X  return (a > b) ? a : b;
  1663. X}
  1664. X#endif
  1665. X
  1666. Xstatline(s1, s2)        /* print status line with s1 and s2 */
  1667. X     char s1[], s2[];
  1668. X{
  1669. X    /* the stat line goes at the bottom of the screen */
  1670. X  mvaddstr(LINES-1, 0, s1); /* first string at beginning */
  1671. X  clrtoeol();
  1672. X    /* second string at end of line */
  1673. X  standout();
  1674. X  mvaddstr(LINES-1, COLS-strlen(s2)-2, s2);
  1675. X  standend();
  1676. X  refresh();
  1677. X}
  1678. X
  1679. X  /* statline2 is like statline, but prints on the second-last line.
  1680. X     statline2 should be used for instructions while a command is being run,
  1681. X        (like a move_army).
  1682. X   */
  1683. Xstatline2(s1, s2)
  1684. X     char s1[], s2[];
  1685. X{
  1686. X    /* the stat line goes at the bottom of the screen */
  1687. X  mvprintw(LINES-2, 0, "%s", s1); /* first string at beginning */
  1688. X  clrtoeol();
  1689. X    /* second string at end of line */
  1690. X  standout();
  1691. X  mvprintw(LINES-2, COLS-strlen(s2)-2, "%s", s2);
  1692. X  standend();
  1693. X  refresh();
  1694. X}
  1695. X
  1696. X  /* this runs a statline, and then moves to just
  1697. X     after s1, for a prompt.  used a lot in xmode
  1698. X   */
  1699. Xstatline_prompt(s1, s2)
  1700. X     char s1[], s2[];
  1701. X{
  1702. X  statline(s1, s2);
  1703. X  move(LINES-1, strlen(s1));
  1704. X  refresh();
  1705. X}
  1706. X
  1707. X  /* this runs a statline2, and then moves to just
  1708. X     after s1, for a prompt.  used a lot in xmode
  1709. X   */
  1710. Xstatline2_prompt(s1, s2)
  1711. X     char s1[], s2[];
  1712. X{
  1713. X  statline2(s1, s2);
  1714. X  move(LINES-2, strlen(s1));
  1715. X  refresh();
  1716. X}
  1717. X
  1718. X  /* runs a statline2, waits for a space to be typed,
  1719. X     then cleans the statline2 and returns
  1720. X   */
  1721. Xstatline2_err(s1, s2)
  1722. X     char s1[], s2[];
  1723. X{
  1724. X  statline2(s1, s2);
  1725. X  get_space();
  1726. X  statline2("", "");
  1727. X}
  1728. X
  1729. X    /* curses interface */
  1730. Xinit_screen()
  1731. X{
  1732. X  printf("initializing screen...\r\n");
  1733. X  initscr();
  1734. X  savetty();
  1735. X/*  nonl(); */
  1736. X  cbreak();
  1737. X  noecho();
  1738. X  clear();
  1739. X  /* OK, now the stdscr is made, must make a couple other windows */
  1740. X  sectw = newwin(SECTW_SIZE_Y, SECTW_SIZE_X, SECTW_Y, SECTW_X);
  1741. X  /*  armyw = newwin(ARMYW_SIZE_Y, ARMYW_SIZE_X, ARMYW_Y, ARMYW_X); */
  1742. X  /* move the point to the user's capital (to start) */
  1743. X  if (user.map_style == NORMAL_MAP) {
  1744. X    move(user.cursor.y, user.cursor.x);
  1745. X  } else {
  1746. X    move(2*user.cursor.y, user.cursor.x);
  1747. X  }
  1748. X  /* refresh(); */
  1749. X}
  1750. X
  1751. X  /* returns a pointer to the spirit pointer of that given type */
  1752. Xstruct spirit_type *get_spirit_type(up, type)
  1753. X     Suser *up;
  1754. X     char type[];
  1755. X{
  1756. X  int i;
  1757. X  extern struct spirit_type *spirit_types;
  1758. X
  1759. X/*  printf("user.n_spirit_types = %d\n", up->n_spirit_types); */
  1760. X  for (i = 0; i < up->n_spirit_types; ++i) {
  1761. X/* printf("type=%s, spirit_types[%d].type = %s\n", type, i, spirit_types[i].type); */
  1762. X    if (strcmp(type, spirit_types[i].type) == 0) {
  1763. X      return &(spirit_types[i]);
  1764. X    }
  1765. X  }
  1766. X  return NULL;
  1767. X}
  1768. X
  1769. X  /* add to the user's exec_list; write it to file if full.
  1770. X     If passed string is NULL, DON'T generate exec, and
  1771. X     write out the whole thing anyway.
  1772. X   */
  1773. Xgen_exec(s)
  1774. X     char *s;
  1775. X{
  1776. X  FILE *fp, *fopen();
  1777. X  char exec_file[NAMELEN];
  1778. X  int i;
  1779. X  
  1780. X  sprintf(exec_file, "exec/exec%d", user.id);  
  1781. X
  1782. X    /* first add the string s to the user's exec_lines;
  1783. X       special case if string is empty or NULL:
  1784. X       if empty, do nothing;
  1785. X       if NULL, write out to file.
  1786. X     */
  1787. X  if ((s != NULL) && (strlen(s) == 0)) {
  1788. X    return;
  1789. X  }
  1790. X  if (s != NULL) {
  1791. X    strcpy(user.exec_lines[user.n_execs], s);
  1792. X    ++user.n_execs;
  1793. X  }
  1794. X  if ((user.n_execs >= N_EXECS) || (s == NULL) ) {
  1795. X    if ((fp = fopen(exec_file, "a")) == NULL) {
  1796. X      printf("cannot open your exec file, this is serious\n");
  1797. X      clean_exit();
  1798. X      exit(1);
  1799. X    }
  1800. X    critical();
  1801. X    for (i = 0; i < user.n_execs; ++i) {
  1802. X      fprintf(fp, "%s", user.exec_lines[i]);
  1803. X      /*      printf("debug: writing to exec file: %s", user.exec_lines[i]); */
  1804. X    }
  1805. X    fclose(fp);
  1806. X    noncritical();
  1807. X    user.n_execs = 0;        /* reset count */
  1808. X  }
  1809. X}
  1810. X
  1811. X
  1812. X/* This just displays the title/intro screen */
  1813. Xintro(wp, np)
  1814. X     Sworld *wp;
  1815. X     Snation *np;
  1816. X{
  1817. X  FILE *mail;
  1818. X  char txt[200];
  1819. X
  1820. X  sprintf(txt, "mail/mail.%d", np->id);
  1821. X  mail = fopen(txt, "r");
  1822. X  strcpy(txt, "Dominion");
  1823. X  mvprintw((LINES-12)/2, (COLS-strlen(txt))/2, txt);
  1824. X  sprintf(txt, "Version %s", VERSION);
  1825. X  mvprintw((LINES-10)/2, (COLS-strlen(txt))/2, txt);
  1826. X  standout();
  1827. X  strcpy(txt, "Copyright (c) 1990, Free Software Foundation");
  1828. X  mvprintw((LINES-6)/2, (COLS-strlen(txt))/2, txt);
  1829. X  standend();
  1830. X  sprintf(txt, "Thon %d", wp->turn);
  1831. X  mvprintw((LINES-2)/2, (COLS-strlen(txt))/2, txt);
  1832. X  sprintf(txt, "%d nations", wp->n_nations);
  1833. X  mvprintw(LINES/2, (COLS-strlen(txt))/2, txt);
  1834. X  sprintf(txt, "world size is %d across, %d down", wp->xmax, wp->ymax);
  1835. X  mvprintw((LINES-2)/2, (COLS-strlen(txt))/2, txt);
  1836. X  standout();
  1837. X  if (mail) {
  1838. X    strcpy(txt, "You have mail!");
  1839. X    mvprintw((LINES+6)/2, (COLS-strlen(txt))/2, txt);
  1840. X    fclose(mail);
  1841. X  }
  1842. X  strcpy(txt, "Press any key to begin");
  1843. X  mvprintw((LINES+10)/2, (COLS-strlen(txt))/2, txt);
  1844. X  standend();
  1845. X  refresh();
  1846. X  getch();
  1847. X  clear();
  1848. X}
  1849. X
  1850. X  /* check the mag_Orders file, and see if this is a valid magic order */
  1851. Xis_good_order(name)
  1852. X     char name[];
  1853. X{
  1854. X  int good = 0;
  1855. X  FILE *fp, *fopen();
  1856. X  char line[200];
  1857. X  int i, n_orders;
  1858. X
  1859. X  if ((fp = fopen(MAG_ORDERS, "r")) == NULL) {
  1860. X    printf("cannot find file %s.  this is bad.\n", MAG_ORDERS);
  1861. X    clean_exit();
  1862. X    exit(1);
  1863. X  }
  1864. X  while (fgets(line, 200, fp) != NULL) {
  1865. X    /*    printf("%s", line); */
  1866. X    if (line[0] != '#') {
  1867. X      sscanf(line, "%d", &n_orders);
  1868. X      break;            /* we got the number of orders */
  1869. X    }
  1870. X  }
  1871. X  /*  printf("there are %d magical orders\n", n_orders); */
  1872. X  for (i = 0; i < n_orders; ) {
  1873. X    fgets(line, NAMELEN, fp);
  1874. X    if (line[strlen(line)-1] == '\n') {
  1875. X      line[strlen(line)-1] = '\0';
  1876. X    }
  1877. X    if (line[0] != '#') {
  1878. X      if (strncmp(line, name, NAMELEN) == 0) {
  1879. X    good = 1;
  1880. X      }
  1881. X      ++i;
  1882. X    }
  1883. X  }
  1884. X  return good;
  1885. X}
  1886. X
  1887. X  /* returns true if there is at least one
  1888. X     non-hidden army on this sector.
  1889. X   */
  1890. Xhas_visible_army(sp, up)
  1891. X     Ssector *sp;
  1892. X     Suser *up;
  1893. X{
  1894. X  struct armyid *alist = sp->alist;
  1895. X  Sarmy *ap, *get_army();
  1896. X  int found = 0;
  1897. X
  1898. X  while (alist) {
  1899. X    ap = get_army(&world.nations[alist->owner], alist->id);
  1900. X    if (!is_hidden(ap)) {
  1901. X      found = 1;
  1902. X      break;
  1903. X    }
  1904. X    alist = alist->next;
  1905. X  }
  1906. X  return found;
  1907. X}
  1908. X
  1909. X  /* this routine goes through the entire map and figures out
  1910. X     which sectors are visible by the user.
  1911. X   */
  1912. Xfind_visible_sectors(visible_sectors)
  1913. X     int **visible_sectors;
  1914. X{
  1915. X  int x, y, i, j;
  1916. X  struct pt_list *plist;
  1917. X  Sarmy *ap;
  1918. X  Ssector *sp;
  1919. X
  1920. X  for (i = 0; i < world.xmax; ++i) {
  1921. X    for (j = 0; j < world.ymax; ++j) {
  1922. X      visible_sectors[i][j] = viewall ? SEE_ALL : SEE_NOTHING;
  1923. X    }
  1924. X  }
  1925. X  for (plist = user.np->ptlist; plist != NULL; plist = plist->next) {
  1926. X    x = plist->pt.x;
  1927. X    y = plist->pt.y;
  1928. X    visible_sectors[x][y] = SEE_ALL;
  1929. X    for (i = x-LAND_SIGHT; i <= x+LAND_SIGHT; ++i) {
  1930. X      for (j = y-LAND_SIGHT; j <= y+LAND_SIGHT; ++j) {
  1931. X    sp = &world.map[(*wrapx)(i,j)][(*wrapy)(i,j)];
  1932. X    if (has_hidden(sp) && sp->owner != user.id) {
  1933. X      visible_sectors[x][y] |= SEE_ARMIES;
  1934. X    } else {
  1935. X      visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |=
  1936. X        (SEE_LAND_WATER | SEE_OWNER | SEE_DESIG | SEE_POPULATION);
  1937. X    }
  1938. X    if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner == 0) {
  1939. X      visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |= SEE_RESOURCES;
  1940. X    }
  1941. X      }
  1942. X    }
  1943. X  }
  1944. X  for (ap = user.np->armies; ap != NULL; ap = ap->next) {
  1945. X    x = ap->pos.x;
  1946. X    y = ap->pos.y;
  1947. X    sp = &world.map[x][y];
  1948. X    if (has_hidden(sp) && sp->owner != user.id) {
  1949. X      visible_sectors[x][y] = SEE_ARMIES;
  1950. X    } else {
  1951. X      visible_sectors[x][y] = SEE_ALL;
  1952. X    }
  1953. X    for (i = x-ARMY_SIGHT; i <= x+ARMY_SIGHT; ++i) {
  1954. X      for (j = y-ARMY_SIGHT; j <= y+ARMY_SIGHT; ++j) {
  1955. X    sp = &world.map[(*wrapx)(i,j)][(*wrapy)(i,j)];
  1956. X    if (!has_hidden(sp)) {
  1957. X      visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |=
  1958. X        (SEE_LAND_WATER | SEE_OWNER | SEE_DESIG |
  1959. X         SEE_POPULATION | SEE_ARMIES);
  1960. X    }
  1961. X    if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner == 0) {
  1962. X      visible_sectors[(*wrapx)(i,j)][(*wrapy)(i,j)] |= SEE_RESOURCES;
  1963. X    }
  1964. X      }
  1965. X    }
  1966. X  }
  1967. X}
  1968. X
  1969. X/* Returns a string that formats the arguments */
  1970. X
  1971. Xchar * contents (money, metal, jewels, food, people, army, title, sp)
  1972. X
  1973. Xint money, metal, jewels, food, people, army, sp;
  1974. XPt * title;
  1975. X{
  1976. X  char * rcontents;
  1977. X  char tmps [60];
  1978. X
  1979. X  if ((rcontents = (char *)malloc (sizeof (char) * 100)) == NULL) {
  1980. X    clean_exit();
  1981. X    exit (-1);
  1982. X  }
  1983. X
  1984. X  sprintf (rcontents, "");
  1985. X
  1986. X  if (money > 0) {
  1987. X    sprintf (tmps, "/%d sk.", money);
  1988. X    strcat (rcontents, tmps);
  1989. X  }
  1990. X  if (metal > 0) {
  1991. X    sprintf (tmps, "/%d met", metal);
  1992. X    strcat (rcontents, tmps);
  1993. X  }
  1994. X  if (jewels > 0) {
  1995. X    sprintf (tmps, "/%d jwl", jewels);
  1996. X    strcat (rcontents, tmps);
  1997. X  }
  1998. X  if (food > 0) {
  1999. X    sprintf (tmps, "/%d food", food);
  2000. X    strcat (rcontents, tmps);
  2001. X  }
  2002. X  if (people > 0) {
  2003. X    sprintf (tmps, "/%d peop", people);
  2004. X    strcat (rcontents, tmps);
  2005. X  }
  2006. X  if (army >= 0) {
  2007. X    sprintf (tmps, "/army %d", army);
  2008. X    strcat (rcontents, tmps);
  2009. X  }
  2010. X  if (title && title->x != -1) {
  2011. X    sprintf (tmps, "/sect %d,%d",
  2012. X         xrel (title->x, title->y, user.np->capital),
  2013. X         yrel (title->x, title->y, user.np->capital));
  2014. X    strcat (rcontents, tmps);
  2015. X  }
  2016. X  if (sp > 0) {
  2017. X    sprintf (tmps, "/%d sp", sp);
  2018. X    strcat (rcontents, tmps);
  2019. X  }
  2020. X
  2021. X  if (rcontents [0] == '/') {
  2022. X    strcpy (rcontents, rcontents + 1);
  2023. X  }
  2024. X
  2025. X  return rcontents;
  2026. X}
  2027. X
  2028. Xint univ_intel (np)
  2029. X
  2030. XSnation * np;
  2031. X{
  2032. X  double sqrt ();
  2033. X  int ret;
  2034. X
  2035. X  if (get_n_civil (np)) {
  2036. X    ret = (int) (100 * get_n_students (np) / get_n_civil (np));
  2037. X  }
  2038. X  else { ret = 0; }
  2039. X
  2040. X  return ret;
  2041. X}
  2042. X
  2043. X  
  2044. X/*
  2045. X  if (get_n_civil (np)) {
  2046. X    ret = (int) sqrt ((double)(get_n_students (np) / 5));
  2047. X    if (ret > 100) {
  2048. X      ret = 100;
  2049. X    }
  2050. X    return ret;
  2051. X  }
  2052. X  return 0;
  2053. X*/
  2054. X
  2055. Xint priestliness (np)
  2056. X
  2057. XSnation * np;
  2058. X{
  2059. X  double sqrt ();
  2060. X  int ret;
  2061. X
  2062. X  if (get_n_civil (np)) {
  2063. X    ret = (int) (100 * get_n_priests (np) / get_n_civil (np));
  2064. X  }
  2065. X  else { ret = 0; }
  2066. X
  2067. X  return ret;
  2068. X}
  2069. X/*  if (get_n_civil (np)) {
  2070. X    ret = (int) sqrt ((double)(get_n_priests (np) / 5));
  2071. X    if (ret > 100) {
  2072. X      ret = 100;
  2073. X    }
  2074. X    return ret;
  2075. X    }
  2076. X  return 0;
  2077. X*/
  2078. END_OF_FILE
  2079. if test 25699 -ne `wc -c <'misc.c'`; then
  2080.     echo shar: \"'misc.c'\" unpacked with wrong size!
  2081. fi
  2082. # end of 'misc.c'
  2083. fi
  2084. echo shar: End of archive 19 \(of 28\).
  2085. cp /dev/null ark19isdone
  2086. MISSING=""
  2087. 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
  2088.     if test ! -f ark${I}isdone ; then
  2089.     MISSING="${MISSING} ${I}"
  2090.     fi
  2091. done
  2092. if test "${MISSING}" = "" ; then
  2093.     echo You have unpacked all 28 archives.
  2094.     echo "Now execute ./do_cat.sh to build doc files"
  2095.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2096. else
  2097.     echo You still need to unpack the following archives:
  2098.     echo "        " ${MISSING}
  2099. fi
  2100. ##  End of shell archive.
  2101. exit 0
  2102.