home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume13 / dominion / part01 < prev    next >
Encoding:
Internet Message Format  |  1992-02-10  |  59.8 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: v13i037:  dominion - a multi-player world simulation game, Part01/28
  5. Message-ID: <2440@masterCNA.TEK.COM>
  6. Date: 11 Feb 92 18:21:43 GMT
  7. Sender: news@masterCNA.TEK.COM
  8. Lines: 2029
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: rosalia@dirac.physics.sunysb.edu (Mark Galassi)
  12. Posting-number: Volume 13, Issue 37
  13. Archive-name: dominion/Part01
  14. Environment: Unix, curses
  15.  
  16.  
  17. [From the author(s)...]
  18. [[Dominion is a multi-player world simulation game.  Each user is the
  19. leader of a nation, and makes decisions for that nation.  The
  20. decisions are political, military, diplomatic and economic, and all
  21. these are extremely important for the well-being of a nation.  The
  22. game is not real-time: a user plays her/his turn and then an update is
  23. run periodically to incorporate changes of all players.
  24.  
  25. Dominion has features from both fantasy role-playing games, educational
  26. games, and war games: a user needs to develop a character as leader of
  27. a nation, keep a healty economy, and can then develop a strong
  28. military force using magic or technology.
  29.  
  30. Dominion has been tested on several versions of UNIX: System V.2
  31. (Ridge and UNIX PC), HPUX (HP 3000 and 9000 series), System V.3 (MIPS
  32. and SGI), System V.4 (386 boxes), SCO Xenix system V (386 boxes), Sun
  33. OS 4.1 (sun sparcstation), ULTRIX (vax, DEC 5000), mach (NeXT), AIX
  34. (IBM RS6000).  A previous version was ported to the amiga, though the
  35. port would have to be redone from scratch now.]]
  36.  
  37.  
  38. #! /bin/sh
  39. # This is a shell archive.  Remove anything before this line, then unpack
  40. # it by saving it into a file and typing "sh file".  To overwrite existing
  41. # files, type "sh file -c".  You can also feed this as standard input via
  42. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  43. # will see the following message at the end:
  44. #        "End of archive 1 (of 28)."
  45. # Contents:  README MANIFEST army.c npcs
  46. # Wrapped by billr@saab on Tue Feb 11 10:14:48 1992
  47. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  48. if test -f 'README' -a "${1}" != "-c" ; then 
  49.   echo shar: Will not clobber existing file \"'README'\"
  50. else
  51. echo shar: Extracting \"'README'\" \(11007 characters\)
  52. sed "s/^X//" >'README' <<'END_OF_FILE'
  53. XWHAT IS THIS?
  54. X-------------
  55. X
  56. XThis is release of Dominion (version 1.06), a world simulation and
  57. Xconquest game.  Dominion runs on every version of UNIX on which we
  58. Xhave tested it.
  59. X
  60. XThe dominion source code is available by anonymous ftp on
  61. Xmax.physics.sunysb.edu [129.49.21.100], in the directory
  62. Xpub/dominion-version.  For example, to get version 1.06 you would
  63. Xtype:
  64. X
  65. X    ftp -i max.physics.sunysb.edu        (or ftp -i 129.49.21.100)
  66. X    <log in as "anonymous", with any password you want>
  67. X    cd pub/dominion-1.06
  68. X    ls
  69. X    binary
  70. X    mget DOM*
  71. X
  72. XThe files you will retrieve are "shell archives", so after
  73. Xuncompressing, you un-bundle them with the Bourne shell.
  74. X
  75. XSend bug reports to:
  76. X    rosalia@max.physics.sunysb.edu
  77. X
  78. XSend flames to /dev/tty :-).
  79. X
  80. XDon't forget that this is copylefted free software.  Read the file COPYING.
  81. X
  82. X
  83. XHOW DO YOU COMPILE DOMINION?
  84. X----------------------------
  85. X
  86. XOnce you have unpacked all the files, you might be lucky and just be
  87. Xable to type "make all" and "make new-world".  Even better would be
  88. X"gmake" and "gmake new-world" if you have GNU Make.  If not:
  89. X
  90. XYou should browse the Makefile, and modify the top part of it.  There are
  91. Xsome customization options:
  92. X
  93. X0.  if you don't have GNU make, remove the 2 lines that refer to RCS.
  94. X    otherwise, you can always type "make" with some target, such
  95. X    as "make all" or "make install" or "make new-world".
  96. X
  97. X1.  if you have Berkeley UNIX, or sunOS, you should put -DBSD in the
  98. X    CFLAGS, rather than -DSYSV.  We have noticed that on mach (NeXT)
  99. X    and ULTRIX (VAX, DEC 5000) we need -DBSD, whereas AIX and System V
  100. X    will compile with -DSYSV.
  101. X
  102. X2.  you should also set the LIBDIR (essential), THIS_GAME_LIBDIR
  103. X    (typically equal to LIBDIR), and BINDIR (not so essential).  You
  104. X    should also set the DEBUGFLAGS to "-O" if you want your compiler to
  105. X    optimize.  when dominion is shipped, the "-g" flag is specified.
  106. X
  107. X3.  get the name of a basic mail program on your system, and set the
  108. X    Makefile variable DEFAULT_MAIL to be that.  This can be overruled
  109. X    with the DOMINION_MAIL environment variable, or in the dominion
  110. X    [O]ptions menu.
  111. X
  112. X4.  do the same as step 3, with a basic visual editor:  the Makefile
  113. X    variable DEFAULT_EDITOR should be the editor most people
  114. X    use.  This can be overruled with the VISUAL environment variable,
  115. X    or in the dominion [O]ptions menu.
  116. X
  117. X5.  There are some other Makefile variables that you might want to
  118. X    change, though they are not essential.  Some of the things we
  119. X    have in the Makefile are for software development.
  120. X
  121. X    If you do not have LaTeXinfo, or you just want to use the manual
  122. X    as we shipt it, you should comment out the lines that generate
  123. X    dominion-man.info.  If you have LaTeXinfo, then you should set
  124. X    EMACS to be the name of GNU emacs on your system, and
  125. X    LTI_START to the name of the file with your LaTeXinfo lisp
  126. X    code.
  127. X
  128. X    There is a newsgroup in which general things are posted.  This is
  129. X    called "News" by default, but it can be changed with the NEWS_GROUP
  130. X    variable in Makefile.
  131. X
  132. X6.  Run "make all", and it will make 5 programs:
  133. X      "dom_make", "dom_add", "dominion", "dom_update" and "dom_print".
  134. X
  135. X7.  Make sure that the file "dominion.info" is there.  We provide
  136. X    a copy of it with the distribution, in case you don't have the
  137. X    emacs lisp code needed to generate this file from "dominion.tex".
  138. X    This emacs lisp code comes with the LaTeXinfo package.
  139. X
  140. X8.  Run "make new-world" to make a new world, then run "dom_add" to add
  141. X    a nation, then run "dominion" to play that nation, and
  142. X    "dom_update" to update the world after you run a turn etc...  It
  143. X    is convenient to run "make new-world" instead of manually typing
  144. X    "dom_make", since "make new-world" will copy all the relevant files
  145. X    to the LIBDIR.
  146. X
  147. X9.  If you want to play with NPCs (nations run by the computer),
  148. X    type "dom_add -f npcs", where "npcs" is the name of the file
  149. X    with all information on these Non Player Countries.  From version
  150. X    1.05 on, the computer playes a pretty good game for the NPCs:
  151. X    they will definitely be a challenge!!  If you want to put in
  152. X    your own file for NPCs, just copy it to $LIBDIR/misc.
  153. X
  154. X    The "npcs" file we distribute has 26 NPCs in it.  If you are
  155. X    running a small world, you might want to comment some of them
  156. X    out: do so by editing the file $LIBDIR/misc/npcs putting a '#'
  157. X    at the beginning of the line for each NPC you don't want.
  158. X
  159. X10. If you don't like some of the hard-coded parameters, you can
  160. X    change them by editing the "dominion.h" and "costs.h" files.
  161. X    Other parameters are defined in "techno_levels", "army_types",
  162. X    "spirit_types", "npcs", and any file that starts with "mag_".
  163. X    If you change "dominion.h" or "costs.h", re-compile.  If you
  164. X    have modified the other files, just run "make lib-files".
  165. X
  166. X11. To make a hardcopy of the manual dominion.tex, you must run LaTeX
  167. X    with the LaTeXinfo document style.  If you do not have this, you
  168. X    can get a copy of the two files "latexinfo.sty" and "tabular.sty"
  169. X    by anonymous ftp from
  170. X        max.physics.sunysb.edu [129.49.21.100]
  171. X    in the directory pub/dominion.  If you don't want to bother running
  172. X    LaTeX, you can find (in the same ftp directory) the files
  173. X    dominion.dvi.Z and dominion.PS.Z, and if you need it we can provide
  174. X    files ready for other laser printers.
  175. X
  176. X12. We also supply a Game Master manual in the file "gm.tex".  This is
  177. X    formatted with ordinary LaTeX, and you can just use latex to format
  178. X    it and print it out.  This manual is just an initial sketch.
  179. X
  180. XWHAT IS IT ALL ABOUT?
  181. X---------------------
  182. X
  183. XThis is a world simulation game developed by students at SUNY at Stony
  184. XBrook.  The intention is to write a game which offers the role playing
  185. Xpotential and complexity of relations found in conquer (written by Ed
  186. XBarlow, then picked up by Adam Bryant).  The plan is to extend the
  187. Xgame by offering general descriptions of many features (such as races,
  188. Xmagic spells, armies, spirits and technology powers).  For example,
  189. Xthe races of the world are not limited to 4 hard-coded races, but are
  190. Xdescribed in a file which can be modified at any point in the game by
  191. Xthe Game Master.  The same goes for army and spirit types.
  192. X
  193. XDominion is *not* another version of conquer; things work quite
  194. Xdifferently, and we have *never* looked at the conquer source.  Still,
  195. Xwe acknowledge this most creative game which gave us our inspiration.
  196. XIn September 1990, the author of conquer version 5 has heard of many
  197. Xof the features of dominion, and has included them in conquer version
  198. X5.  He has acknowledged that these ideas come from Dominion.
  199. X
  200. XThe Game Master is given a nation, but this nation is sort of
  201. X"fragile", since it has no sectors, and such stuff.  We will make it
  202. Xmore solid, but meanwhile it is to be used mostly for its [E] command,
  203. Xwhich allows the Game Master (who logs into the game as "Gamemaster")
  204. Xto change the properties of a sector or of a nation.
  205. X
  206. XDominion development started in the spring of 1990, when we were
  207. Xrunning a game of conquer at Stony Brook.  After the data file kept
  208. Xcrashing, and a whole lot of inconsistencies were discovered, and we
  209. Xfound that the source was too complex to be fixed, we decided to write
  210. Xour own replacement.  Ed Barlow did a great job with conquer, and it
  211. Xis a great game, but it was his first C program, and people who added
  212. Xto it kept the endless case statements, and the special cases, and
  213. Xworked on new features rather than re-writing.  The original name of
  214. XDominion was Stony Brook World (sbw), but it has been named Dominion
  215. Xsince version 1.02.
  216. X
  217. XOne goal of dominion is that the ruler of a nation should always have
  218. Xmany choices available on how to invest resources, each one presenting
  219. Xstrong but distinct advantages.  Conquer contains both a good and a
  220. Xbad example of this: you can invest metal in cities, ships or armies.
  221. XEither way you get advantages, and you have to choose.  On the other
  222. Xhand, jewels are really not used for much else than getting magic
  223. Xpowers.  You can also use them to support monsters, but that is a
  224. Xdifferent order of magnitude, and few players get the monsters.  In
  225. Xdominion, there should be several decisions you can make to invest all
  226. Xyour resources.
  227. X
  228. XKevin Hart has been working on the NPC code which allows the computer
  229. Xto play various nations.  Starting with version 1.05, the
  230. Xcomputer-played NPCs have begun posing a real challenge in the game.
  231. X
  232. X
  233. XABOUT THE DEVELOPERS
  234. X--------------------
  235. X
  236. XPeople who have written code or documentation so far are:
  237. X
  238. XMark Galassi (rosalia@dirac.physics.sunysb.edu)
  239. XMike Fischer (greendog@max.physics.sunysb.edu)
  240. XDoug Novellano (doug@max.physics.sunysb.edu)
  241. XKeith Messing (keith@max.physics.sunysb.edu)
  242. XAlan Saporta (gandalf@max.physics.sunysb.edu)
  243. XJoanne Rosenshein (raven@max.physics.sunysb.edu)
  244. XStephen Bae (sbae@max.physics.sunysb.edu)
  245. XChris Coligado (noel@max.physics.sunysb.edu)
  246. XStephen Underwood (su11+@andrew.cmu.edu)
  247. XKevin Hart (hart@cs.andrews.edu)
  248. XC. Titus Brown (brown@dirac.physics.sunysb.edu)
  249. XCharles Ofria (charles@max.physics.sunysb.edu)
  250. X
  251. XWe keep in touch electronically and meeting in the Stony Brook
  252. XInstitute for Theoretical Physics.  We also meet once a week for 1
  253. Xhour, and some times have parties on Saturdays.  The tuesday meetings
  254. Xare strictly for discussing code, the saturday parties are for
  255. Xfantasizing about what we would like to do.
  256. X
  257. XThere is also a creative team of D&D and war-game players who are
  258. Xgiving suggestions on how magic, technology and battle should work.
  259. XWe also hope to use some simple econometric models to calculate
  260. Xparameters of the economy.
  261. X
  262. X
  263. XABOUT THE CODE
  264. X--------------
  265. X
  266. XThere are 5 programs: dom_make, dom_add, dominion dom_update and
  267. Xdom_print.  These all share some files, such as misc.c, nation.c and
  268. Xfile.c.
  269. X
  270. XIt would be nice to get, some day, some real graphical interfaces for
  271. Xwidely available personal computers (Amiga, Atari ST, Macintosh, IBM
  272. XPC) and windowing systems such as X and NeWS.  But for now we only
  273. Xhave the curses interface, and this is supported as the common
  274. Xdenominator.  There exist, of course, curses implementations for all
  275. Xsorts of personal computers.
  276. X
  277. X
  278. XABOUT SUPPORT AND MAINTAINANCE
  279. X------------------------------
  280. X
  281. XWe will definitely try to fix any bugs that are reported.  When
  282. Xreporting a bug you should mention on which version of UNIX you found
  283. Xit, and be precise.  A fix would be nice.
  284. X
  285. XAs for new ideas, we intend to move slowly in that area because
  286. Xaccepting innovations indiscriminately can be harmful in the long run.
  287. XAny idea which does not make the game more complicated is welcome, and
  288. Xwill be considered.  If you make your own modifications to the game,
  289. Xremember to do so in accordance with the GNU General Public Licence
  290. X(see the file COPYING).
  291. X
  292. X
  293. XWHAT HAS BEEN DONE SO FAR?
  294. X--------------------------
  295. X
  296. XWe feel that the game is complete as it is, though lots of things
  297. Xcould be improved.  There is a file called TASKS with a list of
  298. Xjobs for the enterprising hacker who wants to help with Dominion.
  299. END_OF_FILE
  300. if test 11007 -ne `wc -c <'README'`; then
  301.     echo shar: \"'README'\" unpacked with wrong size!
  302. fi
  303. # end of 'README'
  304. fi
  305. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  306.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  307. else
  308. echo shar: Extracting \"'MANIFEST'\" \(3059 characters\)
  309. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  310. X   File Name        Archive #    Description
  311. X-----------------------------------------------------------
  312. X COPYING                   25    
  313. X ChangeLog                 19    
  314. X MANIFEST                   1    This shipping list
  315. X Makefile                  15    
  316. X README                     1    
  317. X TASKS                     27    
  318. X THE_STORY                 23    
  319. X addnation.c               20    
  320. X addnews.sh                26    
  321. X army.c                     1    
  322. X army.h                    27    
  323. X army_types                28    
  324. X armylib.c                 17    
  325. X battle.c                  19    
  326. X budget.c                  23    
  327. X c_news.c                  21    
  328. X cinfo.c                   25    
  329. X commands.c                23    
  330. X construct.c               14    
  331. X costs.h                    4    
  332. X cur_stuff.c               22    
  333. X cur_stuff.h               13    
  334. X diplolib.c                25    
  335. X diplomacy.c               26    
  336. X do_cat.sh                  3    
  337. X dom_info.aa                2    
  338. X dom_info.ab                3    
  339. X dom_ps.aa                 12    
  340. X dom_ps.ab                 11    
  341. X dom_ps.ac                 10    
  342. X dom_ps.ad                  8    
  343. X dom_ps.ae                  5    
  344. X dom_ps.af                  4    
  345. X dom_ps.ag                  6    
  346. X dom_ps.ah                  9    
  347. X dom_ps.ai                  7    
  348. X dom_ps.aj                 13    
  349. X dom_tex.aa                16    
  350. X dom_tex.ab                17    
  351. X dominion.6                28    
  352. X dominion.c                27    
  353. X dominion.h                24    
  354. X economy.c                 21    
  355. X ext.c                     27    
  356. X file.c                    16    
  357. X gm.tex                    27    
  358. X help.c                    28    
  359. X info_intro                12    
  360. X init.c                    28    
  361. X int_mail.c                24    
  362. X mag_Aule                   9    
  363. X mag_Avian                 28    
  364. X mag_Chess                 27    
  365. X mag_Demonology            10    
  366. X mag_Diana                 20    
  367. X mag_Inferno               28    
  368. X mag_Insects               12    
  369. X mag_Master                18    
  370. X mag_Monsters              22    
  371. X mag_Necromancy             7    
  372. X mag_Neptune               11    
  373. X mag_Time                  28    
  374. X mag_Unity                 22    
  375. X mag_Yavanna                8    
  376. X mag_orders                 8    
  377. X maglib.c                  25    
  378. X mail.c                    26    
  379. X makeworld.c               15    
  380. X menus.c                   22    
  381. X misc.c                    19    
  382. X misc.h                    26    
  383. X movement.c                20    
  384. X nation.c                  18    
  385. X news.c                    27    
  386. X news.h                     5    
  387. X npc.c                     21    
  388. X npclib.c                  22    
  389. X npcs                       1    
  390. X printmap.c                24    
  391. X races                     24    
  392. X refcard                    6    
  393. X reports.c                 23    
  394. X root.c                    25    
  395. X spelllib.c                24    
  396. X spells.c                  20    
  397. X spirit_types              27    
  398. X spy.c                     26    
  399. X techno.c                  27    
  400. X techno_levels             27    
  401. X trade.c                   27    
  402. X trademenu.c               27    
  403. X transport.c               18    
  404. X update.c                  14    
  405. X user.c                    26    
  406. X world.c                   26    
  407. END_OF_FILE
  408. if test 3059 -ne `wc -c <'MANIFEST'`; then
  409.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  410. fi
  411. # end of 'MANIFEST'
  412. fi
  413. if test -f 'army.c' -a "${1}" != "-c" ; then 
  414.   echo shar: Will not clobber existing file \"'army.c'\"
  415. else
  416. echo shar: Extracting \"'army.c'\" \(40121 characters\)
  417. sed "s/^X//" >'army.c' <<'END_OF_FILE'
  418. X  /* army.c -- visual army stuff;  see also armylib.c */
  419. X
  420. X/*
  421. X * Copyright (C) 1990 Free Software Foundation, Inc.
  422. X * Written by the dominion project.
  423. X *
  424. X * This file is part of dominion.
  425. X *
  426. X * dominion is free software; you can redistribute it and/or
  427. X * modify it under the terms of the GNU General Public License as published
  428. X * by the Free Software Foundation; either version 1, or (at your option)
  429. X * any later version.
  430. X *
  431. X * This software is distributed in the hope that it will be useful,
  432. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  433. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  434. X * GNU General Public License for more details.
  435. X *
  436. X * You should have received a copy of the GNU General Public License
  437. X * along with this software; see the file COPYING.  If not, write to
  438. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  439. X */
  440. X
  441. X#include "dominion.h"
  442. X#include "misc.h"
  443. X#include "army.h"
  444. X#include "cur_stuff.h"
  445. X
  446. X#include <stdio.h>
  447. X#ifdef AMIGA
  448. X# include <stdlib.h>
  449. X#endif
  450. X
  451. Xextern Sworld world;
  452. Xextern Suser user;
  453. Xextern char help_tag[];
  454. X
  455. Xint legal_move();
  456. XSarmy *get_army();
  457. Xextern struct army_type *army_types;
  458. Xextern struct army_flags army_flags [];
  459. X
  460. X  /* this shows the armies inside the current sector.
  461. X     the info is put in the the main window.
  462. X   */
  463. Xshow_armies(sp)
  464. X     Ssector *sp;
  465. X{
  466. X  Sarmy *ap;
  467. X  Snation *np;
  468. X  struct armyid *alist;
  469. X    /* we need to know how many are hidden, for display purposes */
  470. X  int i, n_hidden = 0, n_armies;
  471. X  char s[NAMELEN];
  472. X  char apparent_type[NAMELEN];    /* if an army is disguised */
  473. X  int visibility = user.visible_sectors[sp->loc.x][sp->loc.y];
  474. X  int n_shown, first_shown = 0, current_index; /* to handle scrolling */
  475. X  Sarmy **army_array;
  476. X
  477. X  if (user.current_army == -1) {
  478. X    user.current_army = first_sect_army(sp);
  479. X  }
  480. X
  481. X  if (!(visibility & SEE_ARMIES)) {
  482. X    user.last_n_armies = 0;
  483. X    return;
  484. X  }
  485. X
  486. X    /* we use this array to store all pointers, because it is useful
  487. X       to access the armies as an array for the scrolling display
  488. X     */
  489. X  alist = sp->alist;
  490. X  current_index = 0;
  491. X  n_armies = sect_n_armies(sp);
  492. X  army_array = (Sarmy **) malloc(n_armies * sizeof(Sarmy *));
  493. X  for (i = 0; i < n_armies; ++i) {
  494. X    np = &world.nations[alist->owner];
  495. X    ap = get_army(np, alist->id);
  496. X    army_array[i] = ap;
  497. X      /* we want to know which the current army is,
  498. X     so that we can highlight it.
  499. X       */
  500. X    if (ap->id == user.current_army && ap->owner == user.id) {
  501. X      current_index = i;
  502. X    }
  503. X    alist = alist->next;
  504. X  }
  505. X
  506. X    /* cycle through armies and show them */
  507. X  alist = sp->alist;
  508. X  n_shown = min(7, n_armies);
  509. X  if ((n_armies - current_index) <= n_shown/2) { /* are we near end of list */
  510. X    first_shown = n_armies - n_shown;
  511. X  } else {
  512. X    first_shown = max(current_index-n_shown/2, 0);
  513. X  }
  514. X  for (i = 0; i < n_shown; ++i) {
  515. X    ap = army_array[i+first_shown];
  516. X    if ((ap->owner == user.id) && (ap->id == user.current_army)) {
  517. X      standout();
  518. X    }
  519. X    if (ap->owner == user.id || user.id == 0) {    /* your armies */
  520. X      if (ap->id == user.current_army) {
  521. X    mvprintw(2*(i-n_hidden), ARMYW_X,
  522. X         ">%.10s:%d %.8s", world.nations[ap->owner].name,
  523. X         ap->n_soldiers, ap->type);
  524. X      } else {
  525. X    mvprintw(2*(i-n_hidden), ARMYW_X,
  526. X         " %.10s:%d %.8s", world.nations[ap->owner].name,
  527. X         ap->n_soldiers, ap->type);
  528. X      }
  529. X      clrtoeol();
  530. X    } else if (!is_hidden(ap)) { /* other people's armies */
  531. X      get_apparent_type(ap, apparent_type);
  532. X      mvprintw(2*(i-n_hidden), ARMYW_X,
  533. X           " %.10s:%d %.8s", world.nations[ap->owner].name,
  534. X           ap->n_soldiers, apparent_type);
  535. X    } else {            /* is hidden */
  536. X      ++n_hidden;
  537. X    }
  538. X    clrtoeol();
  539. X      /* we have printed the first army description
  540. X     line; now print the other one.
  541. X       */
  542. X    if (ap->owner == user.id || user.id == 0) {
  543. X      get_army_status(ap, s);
  544. X      mvprintw(2*(i-n_hidden)+1, ARMYW_X,
  545. X           " #%d; mv=%d;%s", ap->id, ap->mvpts, s);
  546. X    } else {
  547. X      move(2*(i-n_hidden)+1, ARMYW_X);
  548. X    }
  549. X      /* tricky line;  if it is there it causes this bug
  550. X     with hidden armies; I try only clearing if the
  551. X     army is not hidden.  that might solve the problem,
  552. X     but still cause trouble if the army is hidden and
  553. X     belongs to me.  I will test it.
  554. X       */
  555. X    if (!(is_hidden(ap) && ap->owner != user.id)) {
  556. X      clrtoeol();        /* do it for non-enemy hidden armies */
  557. X    }
  558. X    if ((ap->owner == user.id) && (ap->id == user.current_army)) {
  559. X      standend();
  560. X    }
  561. X    alist = alist->next;
  562. X  }
  563. X  if (n_shown < user.last_n_armies) {
  564. X    for (i = n_armies-n_hidden; i < user.last_n_armies; i++) {
  565. X      move(2*i, ARMYW_X);
  566. X      clrtoeol();
  567. X      move(2*i+1, ARMYW_X);
  568. X      clrtoeol();
  569. X    }
  570. X  }
  571. X  user.last_n_armies = n_shown;    /* n_armies - n_hidden; */
  572. X  free(army_array);
  573. X}
  574. X
  575. X  /* this is the general army menu, which allows
  576. X     you to choose an army action.
  577. X   */
  578. Xarmy_menu()
  579. X{
  580. X  WINDOW *aw;
  581. X  int x, y;
  582. X  char c;
  583. X  int done = 0;
  584. X  Ssector *sp;            /* current sector */
  585. X  Sarmy *ap;
  586. X
  587. X  x = user.cursor.x;
  588. X  y = user.cursor.y;
  589. X  sp = &world.map[x][y];
  590. X
  591. X  if (!user.xmode) {
  592. X    aw = newwin(8, COLS-2, LINES-10, 1);
  593. X  }
  594. X  while (!done) {
  595. X    if (user.xmode) {
  596. X      statline("(d,D,E,n,p,N,P,m,s,t,l,z,Z,-,+)", "army_menu");
  597. X    } else {
  598. X      statline("Choose the army action you want (space to exit)", "army_menu");
  599. X      mvwaddstr(aw, 1, 1,
  600. X"  Choose Army: [n]ext, [p]revious, [N]/[P] (absolute), [j]ump to #");
  601. X      mvwaddstr(aw, 2, 1,
  602. X" Command Army: [m]ove, change [s]tatus, [t]ransport, [D]isband army");
  603. X      mvwaddstr(aw, 3, 1,
  604. X"    Army Info: [l]ist available army types,[z]oom,[Z] global zoom,[E]xamine");
  605. X      mvwaddstr(aw, 4, 1,
  606. X"Army Creation: [d]raft troops, [-]split army, [+]merge armies");
  607. X      box(aw, '|', '-');
  608. X      wrefresh(aw);
  609. X    }
  610. X    set_cursor();
  611. X    strcpy(help_tag, "Diplomacy and war");
  612. X    switch (c = mygetch()) {
  613. X    case ' ':
  614. X      done = 1;
  615. X      break;
  616. X    case 'j':
  617. X      done = jarmy ();
  618. X      break;
  619. X    case 'm':
  620. X      if (!user.xmode) {
  621. X    werase(aw);
  622. X    touch_all_wins();
  623. X      }
  624. X      critical();        /* make sure people don't exit while moving */
  625. X      move_army(user.current_army, user.xmode ? NULL : aw);
  626. X      noncritical();        /* now they can exit:  move is saved */
  627. X      break;
  628. X    case 't':            /* allow access to the transp. menu */
  629. X      transport();
  630. X      break;
  631. X    case 'p':
  632. X      previous_army();        /* pick the previous army */
  633. X      if (user.display == ARMY_MOVECOST) {
  634. X    draw_map ();
  635. X      }
  636. X      break;
  637. X    case 'n':
  638. X      next_army();        /* pick the next army */
  639. X      if (user.display == ARMY_MOVECOST) {
  640. X    draw_map ();
  641. X      }
  642. X      break;
  643. X    case 'N':            /* pick the next army, no matter where */
  644. X      if (ap=get_army(user.np,next_nation_army(user.np, user.current_army))) {
  645. X    user.current_army = ap->id;
  646. X    user.cursor = ap->pos;
  647. X    just_moved();
  648. X    re_center(ap->pos.x, ap->pos.y);
  649. X    draw_map();
  650. X      } else {
  651. X    user.current_army = -1;
  652. X      }
  653. X      break;
  654. X    case 'P':
  655. X      if (ap=get_army(user.np,prev_nation_army(user.np, user.current_army))) {
  656. X    user.current_army = ap->id;
  657. X    user.cursor = ap->pos;
  658. X    just_moved();
  659. X    re_center(ap->pos.x, ap->pos.y);
  660. X    draw_map();
  661. X      } else {
  662. X    user.current_army = -1;
  663. X      }
  664. X      break;
  665. X    case 's':
  666. X      change_army_status(user.xmode ? NULL : aw, user.current_army);
  667. X      break;
  668. X    case 'd':
  669. X      list_available_armies(&user, user.xmode ? NULL : aw);
  670. X      draft_army(user.np);
  671. X      if (user.current_army == -1) {
  672. X        user.current_army = first_sect_army(sp);
  673. X      }
  674. X      break;
  675. X    case 'D':
  676. X      if ((ap = get_army(user.np, user.current_army)) == NULL) {
  677. X    return 0;
  678. X      }
  679. X      army_disband (sp, ap);
  680. X      break;
  681. X    case 'E':
  682. X      if ((ap = get_army(user.np, user.current_army)) == NULL) {
  683. X    return 0;
  684. X      }
  685. X      army_examine(ap);
  686. X      break;
  687. X    case 'l':
  688. X        /* if we pass NULL, it means we are in xmode */
  689. X      list_available_armies(&user, user.xmode ? NULL : aw);
  690. X      get_space();
  691. X      break;
  692. X    case 'z':
  693. X      zoom_armies(&user, sp);
  694. X      break;
  695. X    case 'Z':
  696. X      zoom_armies(&user, NULL);
  697. X                     /* with a null pointer for sector... */
  698. X      break;
  699. X    case '+':
  700. X      ap = get_army (user.np, user.current_army);
  701. X      if (ap == NULL) {
  702. X    break;
  703. X      }
  704. X      army_merge (ap);
  705. X      break;
  706. X    case '-':
  707. X      ap = get_army (user.np, user.current_army);
  708. X      if (ap == NULL) {
  709. X    break;
  710. X      }
  711. X      army_split (ap);
  712. X      break;
  713. X    default:
  714. X      break;
  715. X    }
  716. X    ap = get_army(user.np,user.current_army);
  717. X    if (ap != NULL) {
  718. X      sp = &world.map[ap->pos.x][ap->pos.y];
  719. X    }
  720. X    if (!user.xmode) {
  721. X      wmove(aw, 3, 1);
  722. X      wclrtobot(aw);
  723. X      touchwin(aw);
  724. X    }
  725. X    statline2("", "");
  726. X    show_armies(sp);
  727. X    refresh();
  728. X  }
  729. X  if (!user.xmode) {
  730. X    delwin(aw);
  731. X    touch_all_wins();
  732. X  }
  733. X}
  734. X
  735. X/* Merge selected army with another army */
  736. X
  737. Xarmy_merge (ap)
  738. X
  739. XSarmy * ap;
  740. X{
  741. X  struct argument args[N_EXEC_ARGS];
  742. X  Sarmy * ap2;
  743. X  Ssector * sp;
  744. X  char stmp [EXECLEN];
  745. X  int army_num;
  746. X
  747. X  sp = &world.map[user.cursor.x][user.cursor.y];
  748. X
  749. X  sprintf (stmp, "Merge army %d into army #? ", ap->id);
  750. X  statline2_prompt (stmp, "army_merge");
  751. X  if (wget_number (stdscr, &army_num) <= 0) {
  752. X    statline2 ("", "");
  753. X    return 0;
  754. X  }
  755. X  ap2 = get_army (user.np, army_num);
  756. X  if (ap2 == NULL) {
  757. X    statline2 ("", "");
  758. X    return 0;
  759. X  }
  760. X  if (is_in_transport(ap) || is_in_transport (ap2)) {
  761. X    statline2_err("Hit space to get back", "Army is in transport");
  762. X    statline2 ("", "");
  763. X    return 0;
  764. X  }
  765. X  if (cargo_not_empty(&ap->cargo) || cargo_not_empty (&ap2->cargo)) {
  766. X    statline2_err("Hit space to get back", "Army has a cargo");
  767. X    statline2 ("", "");
  768. X    return 0;
  769. X  }
  770. X  if (is_spelled(ap) || is_spelled(ap2))
  771. X  {
  772. X    statline2_err("Hit space to get back", "Army is under a Spell");
  773. X    statline2 ("", "");
  774. X    return 0;
  775. X  }     
  776. X  if (ap2->pos.x != sp->loc.x || ap2->pos.y != sp->loc.y ||
  777. X      strcmp(ap->type,ap2->type) != 0 || ap == ap2) {
  778. X    statline2 ("", "");
  779. X    return 0;
  780. X  }
  781. X  sprintf(stmp, "AMERGE:%d:%d\n", ap->id, ap2->id);
  782. X  gen_exec(stmp);
  783. X    /* have the exec routine do the work!! */
  784. X  parse_exec_line(stmp,args);
  785. X  run_exec_line(user.np,args);
  786. X    /* make sure there is a current army selected */
  787. X  user.current_army = ap2->id;
  788. X  return 1;
  789. X}
  790. X
  791. Xarmy_split (ap)
  792. X
  793. XSarmy * ap;
  794. X{
  795. X  struct argument args[N_EXEC_ARGS];
  796. X  Ssector * sp;
  797. X  char stmp [EXECLEN];
  798. X  int num_troops;
  799. X
  800. X  sp = &world.map[user.cursor.x][user.cursor.y];
  801. X
  802. X  sprintf (stmp, "Split how many units from army %d? ", ap->id);
  803. X
  804. X  statline2_prompt (stmp, "army_split");
  805. X  if (wget_number (stdscr, &num_troops) <= 0) {
  806. X    statline2 ("", "");
  807. X    return 0;
  808. X  }
  809. X  if (num_troops < 1 || num_troops > ap->n_soldiers - 1) {
  810. X    statline2 ("", "");
  811. X    return 0;
  812. X  }    
  813. X  if (is_in_transport(ap)) {
  814. X    statline2_err("Hit space to get back", "Army is in transport");
  815. X    statline2 ("", "");
  816. X    return 0;
  817. X  }
  818. X  if (cargo_not_empty(&ap->cargo)) {
  819. X    statline2_err("Hit space to get back", "Army has a cargo");
  820. X    statline2 ("", "");
  821. X    return 0;
  822. X  }
  823. X  if (is_spirit (ap)) {
  824. X    statline2_err ("Hit space to get back", "Cannot split spirits");
  825. X    statline2 ("", "");
  826. X    return 0;
  827. X  }
  828. X  if (is_spelled(ap))
  829. X  {
  830. X    statline2_err("Hit space to get back", "Army is under a Spell");
  831. X    statline2 ("", "");
  832. X    return 0;
  833. X  }     
  834. X  sprintf(stmp, "ASPLIT:%d:%d\n", ap->id, num_troops);
  835. X  gen_exec(stmp);
  836. X    /* have the exec routine do the work!! */
  837. X  parse_exec_line(stmp,args);
  838. X  run_exec_line(user.np,args);
  839. X    /* make sure there is a current army selected */
  840. X  return 1;
  841. X}
  842. X
  843. X  /* allow the user to move an army */
  844. Xmove_army(id,aw)
  845. X     int id;
  846. X     WINDOW *aw;
  847. X{
  848. X  int army_move_comment();
  849. X    /* army being moved (and cargo if there) */
  850. X  Sarmy *ap, *cargo_ap, *get_army();
  851. X  Ssector *sp_initial, *sp_final;
  852. X  Pt pos;
  853. X  char s[EXECLEN];
  854. X  int /* mv_initial, */ mv_final;
  855. X
  856. X  strcpy(help_tag, "Moving your armies");
  857. X
  858. X  ap = get_army(user.np, id);
  859. X  if ((ap == NULL) || (ap->id != id)) {
  860. X    beep();
  861. X    statline("Type space to continue", "No Army Selected");
  862. X    get_space();
  863. X    return;
  864. X  }
  865. X  if ((ap->owner != user.id)) {
  866. X    beep();
  867. X    statline2_err("Type space to continue", "Army not yours");
  868. X    return;
  869. X  }
  870. X  if ((ap->mvpts <= 0)) {
  871. X    beep();
  872. X    statline2_err("Type space to continue", "No movement left");
  873. X    return;
  874. X  }
  875. X  if (is_in_transport(ap)) {
  876. X    beep();
  877. X    statline2_err("Type space to continue", "This army is loaded");
  878. X    return;
  879. X  }
  880. X
  881. X    /* remove it from old sector */
  882. X  pos = user.cursor;        /* old position */
  883. X  sp_initial = &world.map[pos.x][pos.y];
  884. X    /* see if there is still something in the list */
  885. X    delete_army_sector(sp_initial, ap); /* remove from sector list of armies */
  886. X
  887. X    /* now for the guts of it: drag the army along,
  888. X       and get new position at the end.
  889. X     */
  890. X  pos = drag_cursor(ap->pos, DRAG_REL, army_move_comment, legal_move);
  891. X  ap->pos = pos;        /* army is in a new place!! */
  892. X  mv_final = ap->mvpts;
  893. X    /* adding army to new sector */
  894. X  sp_final = &world.map[pos.x][pos.y];
  895. X  insert_army_sector(sp_final, ap);
  896. X    /* put the user's cursor at new position */
  897. X  user.cursor = pos;
  898. X    /* make the exec line for this army movement */
  899. X  sprintf(s, "AMOVE:%d:%d:%d:%d\n",
  900. X      ap->id, pos.x, pos.y, mv_final);
  901. X  gen_exec(s);
  902. X    /* not sure if I should call this here or in insert_army_sector() */
  903. X  find_visible_sectors(user.visible_sectors);
  904. X  user.current_army = ap->id;
  905. X
  906. X    /* now see if we should also move the cargo (recursively) */
  907. X  if (is_cargo(ap) && ap->cargo.army >= 0) {
  908. X    cargo_ap = ap;
  909. X    while (cargo_ap = get_army(user.np, cargo_ap->cargo.army)) {
  910. X    delete_army_sector(sp_initial, cargo_ap);
  911. X      cargo_ap->pos = sp_final->loc;
  912. X      insert_army_sector(sp_final, cargo_ap);
  913. X      /* make the exec line for this army movement */
  914. X      sprintf(s, "AMOVE:%d:%d:%d:%d\n",
  915. X          cargo_ap->id, pos.x, pos.y, cargo_ap->mvpts);
  916. X      gen_exec(s);
  917. X    }
  918. X  }
  919. X    /* now some code to allow an army in TRADED mode to
  920. X       give itself to the recipient.  this only happens
  921. X       on other peoples' trade posts.
  922. X     */
  923. X  if (ap->status == A_TRADED) donate_army(ap, sp_final);
  924. X}
  925. X
  926. X  /* run through the armies in a sector and pick the next */
  927. Xnext_army()
  928. X{
  929. X  int old_id;
  930. X  Sarmy *ap = get_army(user.np, user.current_army);
  931. X  Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  932. X
  933. X  if ((ap == NULL) || (sp->alist == NULL)) {
  934. X    return;
  935. X  }
  936. X  old_id = ap->id;
  937. X
  938. X  if ((user.current_army = next_sect_army(sp, ap)) == -1) {
  939. X    user.current_army = old_id;
  940. X  }
  941. X}
  942. X  /* run through the armies in a sector and pick the previous */
  943. Xprevious_army()
  944. X{
  945. X  Sarmy *ap = get_army(user.np, user.current_army);
  946. X  Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  947. X
  948. X  if ((ap == NULL) || (sp->alist == NULL)) {
  949. X    return;
  950. X  }
  951. X
  952. X  if ((user.current_army = prev_sect_army(sp, ap)) == -1) {
  953. X    user.current_army = first_sect_army(sp);
  954. X  }
  955. X}
  956. X  /* run through the armies in a nation and pick the next */
  957. Xnext_nation_army(np, old_id)
  958. X     Snation *np;
  959. X     int old_id;
  960. X{
  961. X  Sarmy *ap = get_army(np, old_id);
  962. X
  963. X  if (np->armies == NULL) {
  964. X    return -1;
  965. X  }
  966. X  if (ap == NULL) {
  967. X    return np->armies->id;    /* go to the start */
  968. X  }
  969. X  if (ap->next == NULL) {    /* we are at the end of the line */
  970. X    return old_id;
  971. X  }
  972. X  return ap->next->id;        /* the next army id!! */
  973. X}
  974. X  /* run through the armies in a nation and pick the previous */
  975. Xprev_nation_army(np, old_id)
  976. X     Snation *np;
  977. X     int old_id;
  978. X{
  979. X  Sarmy *ap = np->armies;
  980. X
  981. X  while (ap) {
  982. X    if (ap->next && ap->next->id == old_id) {
  983. X      return ap->id;
  984. X    }
  985. X    ap = ap->next;
  986. X  }
  987. X  return old_id;
  988. X}
  989. X
  990. X  /* change the status of the army as it appears in both
  991. X     the nation's army list and the sector army list.
  992. X   */
  993. Xchange_army_status(aw,id)
  994. X     WINDOW *aw;
  995. X     int id;            /* army id */
  996. X{
  997. X  char c;
  998. X  Sarmy *ap;
  999. X  Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  1000. X  char execstr[EXECLEN];
  1001. X
  1002. X  if ((ap = get_army(user.np, id)) == NULL) {
  1003. X    beep();
  1004. X    statline("type space to continue", "army not yours");
  1005. X    get_space();
  1006. X    return;
  1007. X  }
  1008. X
  1009. X  if (aw) {
  1010. X    statline2("Enter your new status.", "change_army_status");
  1011. X    wmove(aw, 5, 2);
  1012. X    wclrtoeol(aw);
  1013. X    mvwprintw(aw, 5, 2, " [a]ttack, [d]efend, [o]ccupy,");
  1014. X    mvwprintw(aw, 6, 2, " [p]atrol, [i]ntercept, [g]arrison or [t]raded");
  1015. X    box(aw,'|','-');
  1016. X    wrefresh(aw);
  1017. X  } else {
  1018. X    statline2("[a,d,o,n,p,i,g,t]", "change_army_status");
  1019. X  }
  1020. X  switch(c = getch()) {
  1021. X  case 'a':
  1022. X    ap->status = A_ATTACK;
  1023. X    sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1024. X    gen_exec(execstr);
  1025. X    break;
  1026. X  case 'd':
  1027. X    ap->status = A_DEFEND;
  1028. X    sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1029. X    gen_exec(execstr);
  1030. X    break;
  1031. X  case 'o':
  1032. X    if (can_occupy(ap)) {
  1033. X      if (sp->owner != ap->owner) {
  1034. X    ap->status = A_OCCUPY;
  1035. X    ap->mvpts = 0;
  1036. X    sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1037. X    gen_exec(execstr);
  1038. X      } else {
  1039. X    statline2_err("type space to continue", "cannot occupy your sector!");
  1040. X      }
  1041. X    } else {
  1042. X      statline2("type space to continue", "this army cannot occupy");
  1043. X      get_space();
  1044. X    }
  1045. X    break;
  1046. X  case 'p':
  1047. X    if (can_patrol(ap)) {
  1048. X      ap->status = A_PATROL;
  1049. X      sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1050. X      gen_exec(execstr);
  1051. X    } else {
  1052. X      statline2_err("type space to continue", "this army cannot patrol");
  1053. X    }
  1054. X    break;
  1055. X  case 'i':
  1056. X    if (can_intercept(ap)) {
  1057. X      ap->status = A_INTERCEPT;
  1058. X      sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1059. X      gen_exec(execstr);
  1060. X    } else {
  1061. X      statline2_err("type space to continue", "this army cannot intercept");
  1062. X    }
  1063. X    break;
  1064. X  case 'g':
  1065. X    if (can_garrison(ap)) {
  1066. X      ap->status = A_GARRISON;
  1067. X      sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1068. X      gen_exec(execstr);
  1069. X    } else {
  1070. X      statline2_err("type space to continue", "this army cannot garrison");
  1071. X    }
  1072. X    break;
  1073. X  case 't':
  1074. X    ap->status = A_TRADED;
  1075. X      /* see if the army is ready to be traded */
  1076. X    if (sp->owner != user.id && sp->designation == D_TRADE_POST) {
  1077. X      sprintf(execstr, "ASTAT:%d:%d\n", ap->id, ap->status);
  1078. X      gen_exec(execstr);
  1079. X      donate_army(ap, sp);
  1080. X    }
  1081. X    break;
  1082. X  default:
  1083. X    break;
  1084. X  }
  1085. X  show_armies(&world.map[user.cursor.x][user.cursor.y]);
  1086. X}
  1087. X
  1088. X  /* this function is used by move_army() with drag_cursor(),
  1089. X     and returns 0 if the given point cannot be moved to
  1090. X     by the given army.
  1091. X   */
  1092. Xlegal_move(pt, np, id)
  1093. X     Pt pt;
  1094. X     Snation *np;
  1095. X     int id;            /* army id */
  1096. X{
  1097. X  Sarmy *ap;
  1098. X  Ssector *sp = &world.map[pt.x][pt.y], *old_sp;
  1099. X  int cost;
  1100. X
  1101. X  wrap(&pt);
  1102. X    /* find the army we are moving around */
  1103. X  ap = get_army(np, id);
  1104. X
  1105. X  /* this is if we want to make it that armies cannot go
  1106. X     more than 1 step from land that they own.  for now, we
  1107. X     jack up the move cost instead, so this is commented out.
  1108. X   */
  1109. X
  1110. X  cost = get_army_move_cost(np, sp, ap);
  1111. X  if (ap->mvpts < cost) {
  1112. X    return 0;
  1113. X  }
  1114. X
  1115. X  ap->pos = pt;
  1116. X  user.cursor = pt;        /* so the map is drawn right */
  1117. X  army_visibility(user.visible_sectors, ap); /* update the visibility */
  1118. X  ap->mvpts -= cost;
  1119. X  return 1;            /* if we are here, must be a legal move */
  1120. X}
  1121. X
  1122. X  /* this function returns the status of the army, so it
  1123. X     can be put in the statline while the army is moved.  it
  1124. X     will also return a 0 if move points are over, or 1 if
  1125. X     there are still move points.
  1126. X   */
  1127. Xarmy_move_comment(s)
  1128. X     char *s;
  1129. X{
  1130. X  Sarmy *ap = get_army(user.np, user.current_army);
  1131. X  int cost;
  1132. X
  1133. X  cost = get_army_move_cost(user.np, &world.map[ap->pos.x][ap->pos.y], ap);
  1134. X
  1135. X  sprintf(s, "army %d; move points left: %d; cost %d", ap->id, ap->mvpts,cost);
  1136. X  return (ap->mvpts > 0) ? 0 : 1;
  1137. X}
  1138. X
  1139. X  /* draft an army for that nation */
  1140. Xdraft_army(np)
  1141. X     Snation *np;
  1142. X{
  1143. X  WINDOW *w;
  1144. X  int size, ret, i;
  1145. X  Sarmy army, make_army();    /* the new army!! */
  1146. X  Ssector *sp = &world.map[user.cursor.x][user.cursor.y];
  1147. X    /* exec string, army's type and army's name */
  1148. X  char s[EXECLEN], type[NAMELEN], name[NAMELEN], c;
  1149. X  extern struct s_desig_map desig_map[];
  1150. X
  1151. X  strcpy(help_tag, "Army types");
  1152. X
  1153. X  if (sp->owner != user.np->id) {
  1154. X    statline2_err("hit space to continue", "Must be your sector");
  1155. X    return;
  1156. X  }
  1157. X/* Make sure the sector is not hostile */
  1158. X  if (has_hostile(sp)) {
  1159. X    statline2_err("hit space to continue", "Cannot draft from hostile sector");
  1160. X    return;
  1161. X  }
  1162. X  
  1163. X  statline("choose your army/navy/caravan type", "draft_army");
  1164. X  if (!user.xmode) {
  1165. X    w = newwin(6, 60, LINES-14, COLS/5);
  1166. X    mvwprintw(w, 1, 1, "You have %d armies;  first free one is #%d",
  1167. X          np->n_armies, free_army_id(np));
  1168. X    mvwprintw(w, 2, 1, "What type of army/navy/caravan do you want? ");
  1169. X    box(w, '|', '-');
  1170. X    wrefresh(w);
  1171. X  }
  1172. X  noecho();
  1173. X  cbreak();
  1174. X  c = getch();
  1175. X  if (c == '?') {
  1176. X    online_info();
  1177. X    return -1;
  1178. X  } else if (c == ' ') {
  1179. X    if (!user.xmode) {
  1180. X      wrefresh(w);
  1181. X      delwin(w);
  1182. X      touch_all_wins();
  1183. X    }
  1184. X    return -1;
  1185. X  }
  1186. X  for(i = 0; i < user.n_army_types; i++) {
  1187. X    if (army_types[i].type_char == c) {
  1188. X      strcpy(type, army_types[i].type);
  1189. X      break;
  1190. X    }
  1191. X  }
  1192. X                /* While it is still the same army_types... */
  1193. X  if (!strchr (army_types [i].draft_places, desig_map[sp->designation].mark)) {
  1194. X    statline2_err ("hit space", "bad place to draft");
  1195. X    if (!user.xmode) {
  1196. X      wrefresh (w);
  1197. X      delwin (w);
  1198. X    }
  1199. X    return -1;
  1200. X  }
  1201. X  if (!is_avail_army_type(&user, type)) {
  1202. X    statline2_err("Hit space to get back", "Bad army type");
  1203. X    if (!user.xmode) {
  1204. X      wrefresh(w);
  1205. X      delwin(w);
  1206. X      touch_all_wins();
  1207. X    }
  1208. X    return -1;
  1209. X  }
  1210. X  if (!user.xmode) {
  1211. X    wprintw(w, "%s", type);
  1212. X  }
  1213. X
  1214. X  strcpy (name, type);
  1215. X
  1216. X  if (user.xmode) {
  1217. X    sprintf(s, "(default: %s): ", name);
  1218. X    statline2_prompt(s, "Name your army");
  1219. X    ret = wget_name(stdscr, name);
  1220. X  } else {
  1221. X    mvwprintw(w, 3, 1, "Name your army (default: %s):  ", name);
  1222. X    ret = wget_name(w, name);
  1223. X  }
  1224. X    /* if they just type return, use the default name */
  1225. X  if (ret <= 0) {
  1226. X    sprintf(name, "%s", type, free_army_id(np));
  1227. X  }
  1228. X
  1229. X  if (user.xmode) {
  1230. X    statline("", "How many units?");
  1231. X    move(LINES-1, 0);
  1232. X    ret = wget_number(stdscr, &size);
  1233. X  } else {
  1234. X    mvwprintw(w, 4, 1, "How many units do you want? ");
  1235. X    box(w, '|', '-');
  1236. X    ret = wget_number(w, &size);
  1237. X  }
  1238. X  if ((ret <= 0) || (size <= 0)) {
  1239. X    if (!user.xmode) {
  1240. X      wrefresh(w);
  1241. X      delwin(w);
  1242. X      touch_all_wins();
  1243. X    }
  1244. X    return -1;
  1245. X  }
  1246. X  army = make_army(type, name, size, A_DEFEND, np->id, sp->loc);
  1247. X  army.id = free_army_id(np);
  1248. X  army.next = NULL;
  1249. X    /* now see if we can afford the army */
  1250. X  if (army.n_soldiers
  1251. X      > (sp->n_people - desig_map[sp->designation].min_employed)) {
  1252. X    beep();
  1253. X    statline2("space to go on", "not enough people in sector");
  1254. X    get_space();
  1255. X    if (!user.xmode) {
  1256. X      wrefresh(w);
  1257. X      delwin(w);
  1258. X      touch_all_wins();
  1259. X    }
  1260. X    return -1;
  1261. X  }
  1262. X  if (army_cost(&army) > user.np->money) {
  1263. X    beep();
  1264. X    statline2("space to go on", "not enough money to draft");
  1265. X    get_space();
  1266. X    if (!user.xmode) {
  1267. X      wrefresh(w);
  1268. X      delwin(w);
  1269. X      touch_all_wins();
  1270. X    }
  1271. X    return -1;
  1272. X  }
  1273. X  if (army_cost_metal(&army) > user.np->metal) {
  1274. X    beep();
  1275. X    statline2("space to go on", "not enough metal to draft");
  1276. X    get_space();
  1277. X    if (!user.xmode) {
  1278. X      wrefresh(w);
  1279. X      delwin(w);
  1280. X      touch_all_wins();
  1281. X    }
  1282. X    return -1;
  1283. X  }
  1284. X
  1285. X    /* well, if we have reached this point, it means that we
  1286. X       can afford this army, so let us insert it into the lists
  1287. X     */
  1288. X  np->n_armies++;
  1289. X  if (np->armies == NULL) {    /* special case:  empty list */
  1290. X    np->armies = (Sarmy *) malloc(sizeof(Sarmy));
  1291. X    *(np->armies) = army;
  1292. X    np->armies->next = NULL;
  1293. X  } else {
  1294. X    insert_army_nation(np, &army, -1);
  1295. X  }
  1296. X  insert_army_sector(sp, &army);
  1297. X  sp->n_people -= army.n_soldiers;
  1298. X  np->money -= army_cost(&army);
  1299. X  np->metal -= army_cost_metal(&army);
  1300. X    /* now prepare the exec string for making the army and costs */
  1301. X  sprintf(s, "AMAKE:%d:%d:%d:%d:%s:%s\n", army.id, army.n_soldiers,
  1302. X      army.pos.x, army.pos.y, army.type, army.name);
  1303. X  gen_exec(s);
  1304. X  cpeople_sector(sp, -army.n_soldiers);
  1305. X  cmoney(np, -army_cost(&army));
  1306. X  cmetal(np, -army_cost_metal(&army));
  1307. X
  1308. X  show_armies(sp);
  1309. X
  1310. X  if (!user.xmode) {
  1311. X    wrefresh(w);
  1312. X    delwin(w);
  1313. X    touch_all_wins();
  1314. X  }
  1315. X  just_moved();
  1316. X  return 1;
  1317. X}
  1318. X
  1319. X  /* get the first army in that sector that belongs to you */
  1320. Xfirst_sect_army(sp)
  1321. X     Ssector *sp;
  1322. X{
  1323. X  int id = -1;            /* default:  no army selected */
  1324. X  struct armyid *alist = sp->alist;
  1325. X  char s[100];
  1326. X
  1327. X  while (alist != NULL) {
  1328. X    if (alist->owner == user.id) {
  1329. X/* this routine sometimes messes up */
  1330. X      id = alist->id;
  1331. X      break;
  1332. X    }
  1333. X    alist = alist->next;
  1334. X  }
  1335. X
  1336. X  return id;
  1337. X}
  1338. X
  1339. X  /* takes a sector, an army (possibly in that sector), and
  1340. X     returns the id of the next army you own in that sector,
  1341. X     or -1 if you don't have any more
  1342. X   */
  1343. Xnext_sect_army(sp, ap)
  1344. X     Ssector *sp;
  1345. X     Sarmy *ap;
  1346. X{
  1347. X  struct armyid *alist = sp->alist;
  1348. X  char s[100];
  1349. X
  1350. X  if (ap == NULL) {        /* in case the army given was bogus */
  1351. X    return first_sect_army(sp);
  1352. X  }
  1353. X
  1354. X    /* first get up to the given army */
  1355. X  while ((alist != NULL) &&
  1356. X     !((alist->id == ap->id) && (alist->owner == ap->owner))) {
  1357. X    alist = alist->next;
  1358. X  }
  1359. X/*  if (alist->next == NULL) {    /* we are at the end of the list */
  1360. X/*    return -1;
  1361. X  }
  1362. X*/
  1363. X
  1364. X  if ((alist == NULL) || (alist = alist->next) == NULL) {
  1365. X    return -1;
  1366. X  }
  1367. X    /* now look for the next army owned by the current user */
  1368. X  while ((alist != NULL) && (alist->owner != ap->owner)) {
  1369. X    alist = alist->next;
  1370. X  }
  1371. X  if (alist == NULL) {
  1372. X    return -1;
  1373. X  }
  1374. X  return alist->id;        /* in this case, we have a valid next army */
  1375. X}
  1376. X
  1377. X  /* takes a sector, an army (should be in that sector), and
  1378. X     returns the id of the previous army you own in that sector,
  1379. X     or -1 if you don't have any more.
  1380. X   */
  1381. Xprev_sect_army(sp, ap)
  1382. X     Ssector *sp;
  1383. X     Sarmy *ap;
  1384. X{
  1385. X  struct armyid *alist = sp->alist, *previous = sp->alist;
  1386. X  previous = NULL;
  1387. X
  1388. X  if ((ap == NULL) || (alist == NULL)) {
  1389. X    return first_sect_army(sp);
  1390. X  }
  1391. X    /* now get up to the given army */
  1392. X  while ((alist != NULL) &&
  1393. X     !((alist->owner == ap->owner) && (alist->id == ap->id))) {
  1394. X    if (alist->owner == ap->owner) {
  1395. X      previous = alist;
  1396. X    }
  1397. X    alist = alist->next;
  1398. X  }
  1399. X
  1400. X  return (previous == NULL) ? -1 : previous->id;
  1401. X}
  1402. X
  1403. X  /* gives a list of army types available to this user */
  1404. Xlist_available_armies(up, aw)
  1405. X     Suser *up;
  1406. X     WINDOW *aw;        /* army window */
  1407. X{
  1408. X  int i, count = 0;
  1409. X  Savail_army *avail_armies = up->avail_armies;
  1410. X  char s[200];
  1411. X
  1412. X  strcpy(s, " ");
  1413. X  if (aw) {
  1414. X    wmove(aw, 1, 1);
  1415. X    wclrtobot(aw);
  1416. X    mvwprintw(aw, 1, 20, "AVAILABLE ARMIES");
  1417. X    wmove(aw, 2, 1);
  1418. X  }
  1419. X  while (avail_armies != NULL) {
  1420. X    if ((i = army_type_index(avail_armies->type)) >= 0) {
  1421. X      if (aw) {
  1422. X    wprintw(aw, " %s(%c) ", army_types[i].type, army_types[i].type_char);
  1423. X      } else {
  1424. X    sprintf(s, "%s%c ", s, army_types[i].type_char);
  1425. X      }
  1426. X      if (aw && avail_armies->next != NULL) {
  1427. X    waddstr(aw, ",");
  1428. X      }
  1429. X      if (aw) { wclrtoeol(aw); }
  1430. X      ++count;
  1431. X      if (aw && (count % 5) == 0) { /* new line */
  1432. X    wmove(aw, 2+count/5, 1);
  1433. X      }
  1434. X    }
  1435. X    avail_armies = avail_armies->next;
  1436. X  }
  1437. X  if (aw) {
  1438. X    box(aw, '|', '-');
  1439. X    wrefresh(aw);
  1440. X    statline2("Type space to get back", "list_available_armies");
  1441. X  } else {
  1442. X    statline2(s, "list_available_armies");
  1443. X  }
  1444. X}
  1445. X
  1446. X
  1447. Xarmy_disband(sp, ap)
  1448. X
  1449. XSsector *sp;
  1450. XSarmy * ap;
  1451. X{
  1452. X  int army_num, done, index, metal_return;
  1453. X  Snation *np = user.np;
  1454. X  char s[EXECLEN], c;
  1455. X  struct argument args[N_EXEC_ARGS];
  1456. X
  1457. X  if (sp->owner != np->id) {
  1458. X    statline2_err("Hit space to get back", "You don't own sector");
  1459. X    return 0;
  1460. X  }
  1461. X
  1462. X  if (is_in_transport(ap)) {
  1463. X    statline2_err("Hit space to get back", "Army is in transport");
  1464. X    return 0;
  1465. X  }
  1466. X  if (is_cargo(ap) && cargo_not_empty(&ap->cargo)) {
  1467. X    statline2_err("Hit space to get back", "Caravan has stuff loaded");
  1468. X    return 0;
  1469. X  }
  1470. X  if (is_spelled(ap)) {
  1471. X    statline2_err("Hit space to get back", "Army under a spell");
  1472. X    return 0;
  1473. X  }
  1474. X  sprintf (s, "Disband army %d.  Are you sure? ", ap->id);
  1475. X  statline2_prompt (s, "army_disband");
  1476. X
  1477. X  switch (c = getch()) {
  1478. X  case 'Y':
  1479. X  case 'y':
  1480. X    sprintf(s, "ADISBAND:%d\n", ap->id);
  1481. X    index = army_type_index (ap->type);
  1482. X    if (index != -1) {  /* If it's not a spirit */
  1483. X      metal_return = (army_types [index].metal_draft * ap->n_soldiers) *
  1484. X    DISBAND_RETURN;
  1485. X      np->metal +=metal_return;
  1486. X      cmetal (np, metal_return);
  1487. X    }
  1488. X
  1489. X    gen_exec(s);
  1490. X    parse_exec_line(s,args);
  1491. X    run_exec_line(np,args);
  1492. X    break;
  1493. X  case 'N': case 'n':
  1494. X  default: 
  1495. X    break;
  1496. X  }
  1497. X
  1498. X  if (get_army(user.np, user.current_army) == NULL) {
  1499. X    user.current_army = first_sect_army(sp);
  1500. X  }
  1501. X  just_moved ();
  1502. X}
  1503. X
  1504. X  /* give a name to an army */
  1505. Xarmy_name (ap)
  1506. X     Sarmy * ap;
  1507. X{
  1508. X  char name[NAMELEN], s[EXECLEN];
  1509. X  int ret;
  1510. X
  1511. X  statline2_prompt ("Give army name: ", "");
  1512. X  ret = wget_name(stdscr, name);
  1513. X  if (ret > 0) {
  1514. X    strcpy(ap->name, name);
  1515. X      /* now generate the exec instruction */
  1516. X    sprintf(s, "ANAME:%d:%s\n", ap->id, ap->name);
  1517. X    gen_exec(s);
  1518. X  }
  1519. X  noecho();
  1520. X  cbreak();
  1521. X}
  1522. X
  1523. X  /* give a detailed description of all armies in a nation,
  1524. X     or just those in the "current_sp".
  1525. X   */
  1526. Xzoom_armies(up, sp)
  1527. X     
  1528. XSuser *up;
  1529. XSsector *sp;
  1530. X{
  1531. X  WINDOW *azlw, * azmw;
  1532. X  Sarmy * armies;
  1533. X  int army_count, maxlen_win;
  1534. X  int num_shown;
  1535. X  int show_cargo = 0;
  1536. X  int done = 0;
  1537. X  int page = 1;
  1538. X  int maxpage;
  1539. X
  1540. X  armies = up->np->armies;
  1541. X  army_count = 0;
  1542. X
  1543. X  while (armies != NULL) {    /* Count the number of armies to be shown  */
  1544. X    if (sp != NULL) {
  1545. X      if (armies->pos.x == sp->loc.x
  1546. X          && armies->pos.y == sp->loc.y) {
  1547. X    army_count ++;
  1548. X      }
  1549. X    } else {
  1550. X      army_count++;
  1551. X    }
  1552. X    armies = armies->next;
  1553. X  }
  1554. X
  1555. X  if (army_count == 0) {
  1556. X    return 0;
  1557. X  }
  1558. X
  1559. X  maxlen_win = LINES - 3;
  1560. X  if (!user.xmode) {        /* Allow for the non-expert menu */
  1561. X    maxlen_win -= 4;
  1562. X  }
  1563. X
  1564. X  if (army_count <= maxlen_win - 4) { /* Don't use the entire window len? */
  1565. X    maxlen_win = army_count + 4;
  1566. X    num_shown = army_count;
  1567. X    if (user.xmode) {
  1568. X      azlw = newwin (maxlen_win, COLS, LINES - (2 + maxlen_win), 0);
  1569. X    }
  1570. X    else {
  1571. X      azlw = newwin (maxlen_win, COLS, LINES - (2 + 4 + maxlen_win), 0);
  1572. X    }
  1573. X  }
  1574. X  else {
  1575. X    num_shown = maxlen_win - 4;
  1576. X    azlw = newwin (maxlen_win, COLS, 1, 0);
  1577. X  }
  1578. X  maxpage = army_count / (maxlen_win - 4); 
  1579. X  maxpage ++;
  1580. X  
  1581. X  box (azlw, '|', '-');
  1582. X
  1583. X  mvwprintw (azlw, 1, 1, 
  1584. X" ID Name       Size Type        Status  Bonus       ");
  1585. X  mvwprintw (azlw, 1, 47, "%s", show_cargo ? "Cargo" : "Maint");
  1586. X  mvwprintw (azlw, 2, 1, 
  1587. X"--- ---------  ---- ----------- ------- ----  ------------------------------");
  1588. X
  1589. X
  1590. X  while (!done) {
  1591. X    char c;
  1592. X    int i;
  1593. X    char s [EXECLEN];
  1594. X    Sarmy * ap;
  1595. X    Ssector * sp2;
  1596. X    
  1597. X    sp2 = &world.map[user.cursor.x][user.cursor.y];
  1598. X
  1599. X    statline2 ("", "");
  1600. X    for (i = 3; i < maxlen_win - 1; i++) {
  1601. X      wmove (azlw, i, 0);
  1602. X      wclrtoeol (azlw);
  1603. X    }
  1604. X    if (user.xmode) {
  1605. X      azmw = NULL;
  1606. X      statline ("[>,<,c,D,E,N,+,-]", "zoom_armies");
  1607. X    } else {
  1608. X      azmw = newwin (4, COLS, LINES - 6, 0);
  1609. X      box (azmw, '|', '-');
  1610. X      mvwprintw(azmw, 1, 1,
  1611. X        " [>]/[.]next pg, [<]/[,]prev pg,[N]ame army, [c] examine %s ",
  1612. X        show_cargo ? "costs" : "cargo");
  1613. X      mvwprintw(azmw, 2, 1,
  1614. X    " [D]isband army, [-]split army, [+]merge army [E]xamine army");
  1615. X      statline ("Choose zoom_army command (space to exit)", "zoom_armies");
  1616. X      wrefresh (azmw);
  1617. X    }
  1618. X
  1619. X    box (azlw, '|', '-');
  1620. X    zoom_army_page (azlw, up->np->armies, sp, page,maxlen_win-4, show_cargo);
  1621. X
  1622. X    do { c = getch (); } while (strchr (" <>.,NcD-+E", c) == NULL);
  1623. X
  1624. X    switch (c) {
  1625. X    case ' ':
  1626. X      done = 1;
  1627. X      break;
  1628. X    case 'c':
  1629. X      show_cargo = !show_cargo;
  1630. X      mvwprintw (azlw, 1, 47, "%s", show_cargo ? "Cargo" : "Maint");
  1631. X      wrefresh (azlw);
  1632. X      if (azmw) {
  1633. X    mvwprintw(azmw, 1, 1,
  1634. X      " [>]/[.]next pg, [<]/[,]prev pg,[N]ame army, [c] examine %s ",
  1635. X          show_cargo ? "costs" : "cargo");
  1636. X    wrefresh (azmw);
  1637. X      }
  1638. X      break;
  1639. X    case '>':
  1640. X    case '.':
  1641. X      if (page != maxpage) {
  1642. X    page ++;
  1643. X      }
  1644. X      break;
  1645. X    case '<':
  1646. X    case ',':
  1647. X      if (page != 1) {
  1648. X    page --;
  1649. X      }
  1650. X      break;
  1651. X    case 'N':
  1652. X      statline2_prompt ("Name army #", "army_name"); 
  1653. X      if (((wget_number (stdscr, &i)) <= 0) || 
  1654. X    ((ap  = get_army (user.np, i)) == NULL)) {
  1655. X    break;
  1656. X      }
  1657. X      army_name (ap);
  1658. X      break;
  1659. X    case 'E':
  1660. X      statline2_prompt ("Examine army #", "army_examine"); 
  1661. X      if (((wget_number (stdscr, &i)) <= 0) || 
  1662. X    ((ap  = get_army (user.np, i)) == NULL)) {
  1663. X    break;
  1664. X      }
  1665. X      army_examine(ap);
  1666. X      break;
  1667. X    case 'D':
  1668. X      statline2_prompt ("Disband army #", "army_disband"); 
  1669. X      if (((wget_number (stdscr, &i)) <= 0) || 
  1670. X    ((ap  = get_army (user.np, i)) == NULL)) {
  1671. X    break;
  1672. X      }
  1673. X      army_disband (sp2, ap);
  1674. X      break;
  1675. X    case '-':
  1676. X      statline2_prompt ("Split army #", "army_split"); 
  1677. X      if (((wget_number (stdscr, &i)) <= 0) || 
  1678. X    ((ap  = get_army (user.np, i)) == NULL)) {
  1679. X    break;
  1680. X      }
  1681. X      army_split (ap);
  1682. X      break;
  1683. X    case '+':
  1684. X      statline2_prompt ("Merge army #", "army_merge"); 
  1685. X      if (((wget_number (stdscr, &i)) <= 0) || 
  1686. X    ((ap  = get_army (user.np, i)) == NULL)) {
  1687. X    break;
  1688. X      }
  1689. X      army_merge (ap);
  1690. X      break;
  1691. X    }
  1692. X  }
  1693. X
  1694. X  if (azmw) { delwin(azmw); }
  1695. X  delwin(azlw);
  1696. X  touch_all_wins();
  1697. X  return 0;
  1698. X}
  1699. X
  1700. X/* This function is used by zoom_armies to select the page of armies you want*/
  1701. X
  1702. Xzoom_army_page (azlw, armies, sp, page, len_page, show_cargo)
  1703. X
  1704. XWINDOW * azlw;
  1705. XSarmy * armies;
  1706. XSsector * sp;
  1707. Xint page, len_page, show_cargo;
  1708. X{
  1709. X  int army_count, i;
  1710. X  Sarmy * ap = armies;
  1711. X
  1712. X  while (ap != NULL) {
  1713. X    if (sp != NULL) {
  1714. X      if (sp->loc.x == ap->pos.x && sp->loc.y == ap->pos.y) {
  1715. X    army_count ++;
  1716. X      }
  1717. X    }
  1718. X    else {
  1719. X      army_count ++;
  1720. X    }
  1721. X    ap = ap->next;
  1722. X  }
  1723. X
  1724. X  if (army_count <= len_page) {
  1725. X    zoom_list_armies (azlw, armies, sp, 0, len_page, show_cargo);
  1726. X    return 0;
  1727. X  }
  1728. X  if ((page - 2) * len_page > army_count) {    /* Too high a page number */
  1729. X    return 1;
  1730. X  }
  1731. X  ap = armies;
  1732. X
  1733. X  for (i=0; i < (page-1) * len_page; i++) {
  1734. X    ap = ap->next;
  1735. X  }
  1736. X  if (ap != NULL) {
  1737. X    zoom_list_armies (azlw, armies, sp, ap->id, len_page, show_cargo);
  1738. X  }
  1739. X  return 0;
  1740. X}
  1741. X
  1742. X/* This function is used by zoom_armies to list armies in the azlw win */
  1743. X
  1744. Xzoom_list_armies (azlw, armies, sp, start_army, len_win, cargo)
  1745. X
  1746. XWINDOW * azlw;
  1747. XSarmy * armies;
  1748. XSsector * sp;
  1749. Xint start_army;            /* Starting army number */
  1750. Xint len_win;            /* Number of army lines allowed in window */
  1751. Xint cargo;            /* Cargo mode? */
  1752. X{
  1753. X  int army_count;
  1754. X  int row;
  1755. X  char * slash_pos;
  1756. X  Scargo * snails;        /* Sorry for the pun :-) */
  1757. X  char * contents ();        /* Returns string of stuff, nicely formatted */
  1758. X  char s [EXECLEN];
  1759. X  char zooms [EXECLEN];
  1760. X
  1761. X  while (armies != NULL) {    /* Get to the starting army number */
  1762. X    if (armies->id >= start_army) { /* In case it doesn't actually exist... */
  1763. X      break;
  1764. X    }
  1765. X    armies = armies->next;
  1766. X  }
  1767. X
  1768. X  if (sp != NULL) {        /* If not zoom ALL armies, */
  1769. X    do {            /* Check that the first army is on sector */
  1770. X      if (armies->pos.x == sp->loc.x && armies->pos.y == sp->loc.y) {
  1771. X    break;
  1772. X      }
  1773. X      armies = armies->next;
  1774. X    } while (armies != NULL);
  1775. X  }
  1776. X
  1777. X  /* Now display the armies */
  1778. X
  1779. X  row = 3;
  1780. X  while (armies != NULL && row-3 < len_win) {
  1781. X    mvwprintw(azlw, row,  1, "%3d    ", armies->id);
  1782. X    mvwprintw(azlw, row,  5, "%s                   ", armies->name);
  1783. X    mvwprintw(azlw, row, 16, "%4d  ", armies->n_soldiers);
  1784. X    mvwprintw(azlw, row, 21, "%s           ", armies->type);
  1785. X    get_army_status(armies, s);
  1786. X    slash_pos = (char *) strchr (s, (int) '/');
  1787. X    if (slash_pos != NULL) {
  1788. X      *slash_pos = '\0';
  1789. X    }
  1790. X    mvwprintw(azlw, row, 33, "%s     ", s);
  1791. X    mvwprintw(azlw, row, 42, "%3d    ", armies->sp_bonus);
  1792. X
  1793. X    strcpy (zooms, "");
  1794. X    if (cargo) {
  1795. X      if (!is_cargo (armies)) {
  1796. X    sprintf (zooms, "   not a transport");
  1797. X      }
  1798. X      else {
  1799. X    snails = &armies->cargo;
  1800. X    sprintf (zooms, "%s", 
  1801. X         contents (snails->money, snails->metal, snails->jewels,
  1802. X               snails->food, snails->people, snails->army,
  1803. X               &snails->title, 0));
  1804. X      }
  1805. X    }
  1806. X    else {
  1807. X      sprintf (zooms, "%s",
  1808. X           contents (armies->money_maint * armies->n_soldiers,
  1809. X             armies->metal_maint * armies->n_soldiers,
  1810. X             armies->jewel_maint * armies->n_soldiers, 0,
  1811. X             0, -1, NULL, get_spell_pts_maint (armies))); 
  1812. X    }
  1813. X
  1814. X    mvwprintw(azlw, row, 47, zooms);
  1815. X
  1816. X    armies = armies->next;
  1817. X    if (sp != NULL && armies) {    /* Again, check if we want to discriminate...*/
  1818. X      do {
  1819. X    if (armies->pos.x == sp->loc.x && armies->pos.y == sp->loc.y) {
  1820. X      break;
  1821. X    }
  1822. X    armies = armies->next;
  1823. X      } while (armies != NULL);
  1824. X    }
  1825. X    row ++;
  1826. X  }
  1827. X  wrefresh (azlw);
  1828. X}
  1829. X
  1830. X    /* now some code to allow an army in TRADED mode to
  1831. X       give itself to the recipient.  this only happens
  1832. X       on other peoples' trade posts.
  1833. X     */
  1834. Xdonate_army(ap, sp)
  1835. X     Sarmy *ap;
  1836. X     Ssector *sp;
  1837. X{
  1838. X  if (is_cargo (ap) && cargo_not_empty (&ap->cargo)) {
  1839. X    statline2_err ("Error: transport still has a cargo", "donate_army");
  1840. X  } 
  1841. X  else if (ap->flags & AF_IN_TRANSPORT) {
  1842. X    statline2_err ("Error: army is still in transport", "donate_army");
  1843. X  }
  1844. X  else if ((ap->status == A_TRADED) && (sp->designation == D_TRADE_POST)
  1845. X      && (sp->owner !=  user.np->id)) {
  1846. X    statline2("Do you want to trade this army right here [y/n]? ", "");
  1847. X    switch (getch()) {
  1848. X      Scargo cargo;
  1849. X    case 'y':
  1850. X    case 'Y':
  1851. X      cargo.money = cargo.metal = cargo.jewels = cargo.food = 0;
  1852. X      cargo.people = 0;
  1853. X      cargo.army = ap->id;
  1854. X      cargo.title.x = -1;
  1855. X      cargo.title.y = -1;
  1856. X      donate_cargo(sp->loc.x, sp->loc.y,
  1857. X           user.np->id, sp->owner, &cargo);
  1858. X      break;
  1859. X    default:
  1860. X      break;
  1861. X    }
  1862. X  }
  1863. X}
  1864. X
  1865. Xextern int (*wrapx)(), (*wrapy)();
  1866. X
  1867. Xint jarmy ()
  1868. X{
  1869. X  char s[100];
  1870. X  int army_num;
  1871. X  Sarmy * ap;
  1872. X  int x, y;
  1873. X
  1874. X  ap = user.np->armies;
  1875. X
  1876. X  statline2 ("Army number to jump to? ", "jump_army");
  1877. X  move (LINES-2, 25);
  1878. X  refresh ();
  1879. X  if (wget_number(stdscr, &army_num) < 1) {
  1880. X    statline2("", "");
  1881. X    return;
  1882. X  }
  1883. X
  1884. X  while (ap != NULL) {
  1885. X    if (ap->id == army_num) {
  1886. X      break;
  1887. X    }
  1888. X    ap = ap->next;
  1889. X  }
  1890. X
  1891. X  if (ap == NULL) {
  1892. X    statline2_err ("Hit space to continue", "army does not exist");
  1893. X    return 0;
  1894. X  }
  1895. X  if (ap->id == army_num) {
  1896. X    x = ap->pos.x;
  1897. X    y = ap->pos.y;
  1898. X    user.cursor.x = (*wrapx)(x,y);
  1899. X    user.cursor.y = (*wrapy)(x,y);
  1900. X    user.center = user.cursor;
  1901. X    user.current_army = ap->id;
  1902. X    just_moved();
  1903. X  }
  1904. X  statline2("", "");
  1905. X  return 1;
  1906. X}
  1907. X
  1908. Xarmy_examine(ap)
  1909. X     Sarmy * ap;
  1910. X{
  1911. X  WINDOW * flagw, * infow;
  1912. X  char s [NAMELEN], * slash_pos;
  1913. X  int n_flags = 0;
  1914. X  int i, rowpos;
  1915. X  char * flags [20];
  1916. X  Snation * np = &world.nations [ap->owner];
  1917. X
  1918. X  infow = newwin (9, 32, 0, 0);
  1919. X  box (infow, '|', '-');
  1920. X
  1921. X  get_army_status (ap, s);
  1922. X
  1923. X  slash_pos = (char *)strchr (s, (int)'/');
  1924. X  n_flags = 0;
  1925. X  if (slash_pos != NULL) {
  1926. X    n_flags = strlen(slash_pos) - 1;
  1927. X    *slash_pos = '\0';
  1928. X  }
  1929. X
  1930. X  mvwprintw (infow, 1, 2, "Name: %8s (#%d)", ap->name, ap->id);
  1931. X  mvwprintw (infow, 2, 2, "%d Movepoints, %d left",
  1932. X         army_move_rate (np, ap), ap->mvpts);
  1933. X  mvwprintw (infow, 3, 2, "Type: %d %s", ap->n_soldiers, ap->type);
  1934. X  mvwprintw (infow, 4, 2, "Status: %s  Bonus: %d",
  1935. X         s, ap->sp_bonus);
  1936. X  if (is_cargo (ap)) {
  1937. X    mvwprintw (infow, 5,2, "Capacity: %d/Weight: %d",
  1938. X           ap->n_soldiers * CARAVAN_CAPACITY, army_weight (ap));
  1939. X  }
  1940. X  else {
  1941. X    mvwprintw (infow, 5,2, "Weight: %d", army_weight (ap));
  1942. X  }
  1943. X  mvwprintw (infow, 6,2, "Maintenance per thon:");
  1944. X  mvwprintw (infow, 7,2, "  %s",
  1945. X         contents (ap->money_maint * ap->n_soldiers,
  1946. X               ap->metal_maint * ap->n_soldiers,
  1947. X               ap->jewel_maint * ap->n_soldiers, 0,
  1948. X               0, -1, NULL, get_spell_pts_maint (ap))); 
  1949. X  wrefresh (infow);
  1950. X
  1951. X  if (n_flags > 0) {
  1952. X    flagw = newwin (n_flags + 2, COLS - 40, 0, 40);
  1953. X
  1954. X    rowpos = 1;
  1955. X    for (i = 0; i < 32; i++) {
  1956. X      if (strlen (army_flags [i].description) > 0 &&
  1957. X          ap->flags & (0x1 << i)) {
  1958. X    mvwprintw (flagw, rowpos, 1, "%s", army_flags [i].description);
  1959. X    rowpos++;
  1960. X      }
  1961. X    }
  1962. X    box (flagw, '|', '-');
  1963. X    wrefresh (flagw);
  1964. X  }
  1965. X  else {
  1966. X    flagw = NULL;
  1967. X  }
  1968. X
  1969. X  statline2_err ("hit space to continue", "army_examine");
  1970. X  werase (infow);
  1971. X  if (flagw) {
  1972. X    werase (flagw);
  1973. X  }
  1974. X  touch_all_wins ();
  1975. X}
  1976. END_OF_FILE
  1977. if test 40121 -ne `wc -c <'army.c'`; then
  1978.     echo shar: \"'army.c'\" unpacked with wrong size!
  1979. fi
  1980. # end of 'army.c'
  1981. fi
  1982. if test -f 'npcs' -a "${1}" != "-c" ; then 
  1983.   echo shar: Will not clobber existing file \"'npcs'\"
  1984. else
  1985. echo shar: Extracting \"'npcs'\" \(1103 characters\)
  1986. sed "s/^X//" >'npcs' <<'END_OF_FILE'
  1987. X# Format of NPC descriptions
  1988. X# Nation :Leader :Race:Mark:Order :Aggr:Expan:Iso
  1989. X26
  1990. XAsterix     :Sariture    :E:a:Chess    :40:8:5
  1991. XBrukhan     :Derikus    :S:b:Unity    :60:4:5
  1992. XCerelias :Erisp_Dalidus    :A:c:Diana    :35:5:5
  1993. XDusitari :Gruite    :D:d:Unity    :55:6:5
  1994. XErigat     :Anvlak    :o:e:Inferno    :65:8:5
  1995. XFusigade :Lurivar    :S:f:Chess    :50:6:5
  1996. XGrenzell :Tarni        :h:g:Time    :30:3:5
  1997. XHezra     :Zerilla    :y:h:Insects    :75:5:5
  1998. XIcbrek     :Ynavo_Pgirish    :I:i:Demonology    :70:4:5
  1999. XJezertok :Grash        :O:j:Monsters    :95:3:5
  2000. XKrell     :Zucchini    :A:k:Yavanna    :40:6:5
  2001. XLhuvadan :Freziqua    :H:l:Avian    :25:9:5
  2002. XMurdika     :Thrarish    :D:m:Aule    :50:4:5
  2003. XNerisent :Namdas    :I:n:Yavanna    :20:5:5
  2004. XOriesca     :Bresk_Tinkerson :G:o:Aule    :40:3:5
  2005. XPnafari     :Screrc    :y:p:Avian    :65:7:5
  2006. XQuavish     :Wavariaus    :W:q:Insects    :80:6:5
  2007. XRushard     :Herni_Vaserus    :M:r:Demonology    :70:7:5
  2008. XSyntharc :Fondin    :E:s:Inferno    :55:5:5
  2009. XTuvric     :Walvrus    :W:t:Neptune    :65:5:5
  2010. XUtoprus     :Savyur    :h:u:Diana    :15:1:5
  2011. XVertuhl     :Vortalk    :H:v:Time    :55:6:5
  2012. XWendivar :Turugu    :o:w:Necromancy    :65:7:5
  2013. XXeribar     :Xerine    :G:x:Monsters    :60:4:5
  2014. XYeperion :Hergi_Bendfin    :M:y:Neptune    :40:6:5
  2015. XZuruiten :Jezikus    :O:z:Necromancy    :65:5:5
  2016. END_OF_FILE
  2017. if test 1103 -ne `wc -c <'npcs'`; then
  2018.     echo shar: \"'npcs'\" unpacked with wrong size!
  2019. fi
  2020. # end of 'npcs'
  2021. fi
  2022. echo shar: End of archive 1 \(of 28\).
  2023. cp /dev/null ark1isdone
  2024. MISSING=""
  2025. 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
  2026.     if test ! -f ark${I}isdone ; then
  2027.     MISSING="${MISSING} ${I}"
  2028.     fi
  2029. done
  2030. if test "${MISSING}" = "" ; then
  2031.     echo You have unpacked all 28 archives.
  2032.     echo "Now execute ./do_cat.sh to build doc files"
  2033.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2034. else
  2035.     echo You still need to unpack the following archives:
  2036.     echo "        " ${MISSING}
  2037. fi
  2038. ##  End of shell archive.
  2039. exit 0
  2040.