home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume13 / dominion / part20 < prev    next >
Encoding:
Text File  |  1992-02-10  |  60.8 KB  |  2,239 lines

  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: v13i056:  dominion - a multi-player world simulation game, Part20/28
  5. Message-ID: <2459@masterCNA.TEK.COM>
  6. Date: 11 Feb 92 18:26:47 GMT
  7. Sender: news@masterCNA.TEK.COM
  8. Lines: 2228
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: rosalia@dirac.physics.sunysb.edu (Mark Galassi)
  12. Posting-number: Volume 13, Issue 56
  13. Archive-name: dominion/Part20
  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 20 (of 28)."
  25. # Contents:  addnation.c mag_Diana movement.c spells.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 'addnation.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'addnation.c'\"
  30. else
  31. echo shar: Extracting \"'addnation.c'\" \(24914 characters\)
  32. sed "s/^X//" >'addnation.c' <<'END_OF_FILE'
  33. X  /* addnation.c -- primitive program to add a nation to the world */
  34. X
  35. X/*
  36. X * Copyright (C) 1990 Free Software Foundation, Inc.
  37. X * Written by the dominion project.
  38. X *
  39. X * This file is part of dominion.
  40. X *
  41. X * dominion is free software; you can redistribute it and/or
  42. X * modify it under the terms of the GNU General Public License as published
  43. X * by the Free Software Foundation; either version 1, or (at your option)
  44. X * any later version.
  45. X *
  46. X * This software is distributed in the hope that it will be useful,
  47. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  48. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  49. X * GNU General Public License for more details.
  50. X *
  51. X * You should have received a copy of the GNU General Public License
  52. X * along with this software; see the file COPYING.  If not, write to
  53. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  54. X */
  55. X
  56. X#include <stdio.h>
  57. X#include <ctype.h>
  58. X#include <signal.h>
  59. X
  60. X#include "dominion.h"
  61. X#include "misc.h"
  62. X#include "army.h"
  63. X
  64. X#define INIT_CIV 10000
  65. X#define RADIUS 8        /* minimum distance from other nations */
  66. X#define MAX_TRIES 10000        /* max tries to find a good capital */
  67. X
  68. Xextern Sworld world;
  69. Xextern Suser user;
  70. Xextern struct race_list *races;    /* list of races */
  71. Xextern struct army_type *army_types; /* array of available armies */
  72. Xextern char libdir[];
  73. Xextern int debug;
  74. Xextern int (*wrapx)(), (*wrapy)();
  75. X
  76. Xchar get_nation_mark ();
  77. Xint sigquit();
  78. X
  79. XSdiplo **allocate_diplo();
  80. X
  81. Xmain(argc, argv)
  82. X     int argc;
  83. X     char *argv[];
  84. X{
  85. X  int npcs_get_mail = 0;
  86. X  extern int interrupt();
  87. X  int n;
  88. X  int c;
  89. X  extern char *optarg;
  90. X  extern int optind;
  91. X  char add_fn[255];        /* get NPCs from this file name */
  92. X
  93. X  stdscr = NULL;        /* to know if curses is initialized */
  94. X  add_fn[0] = '\0';
  95. X  strcpy(libdir, DEF_LIBDIR);
  96. X  while ((c = getopt(argc, argv, "md:f:x")) != EOF) {
  97. X    switch (c) {
  98. X    case 'm':            /* make these NPCs get mail */
  99. X      npcs_get_mail = 1;
  100. X      break;
  101. X    case 'x':            /* set debugging mode */
  102. X      debug = 1;
  103. X      break;
  104. X    case 'd':            /* set the LIBDIR path */
  105. X      strcpy(libdir, optarg);
  106. X      break;
  107. X    case 'f':            /* the name of the file with NPCs */
  108. X      strcpy(add_fn, optarg);
  109. X      break;
  110. X    default:
  111. X      break;
  112. X    }
  113. X  }
  114. X  if (chdir(libdir) == -1) {
  115. X    fprintf(stderr,"Error: cannot cd to directory %s\n",libdir);
  116. X    clean_exit();
  117. X    exit();
  118. X  }
  119. X
  120. X  SRND(time((long *) 0L));    /* initialize random number generator */
  121. X
  122. X  read_world(&world, WORLD_FILE);
  123. X  read_races();
  124. X
  125. X  if (!verify_gamemaster()) {
  126. X    printf("Hey, you can't add a nation!\n");
  127. X    clean_exit();
  128. X    exit(1);
  129. X  }
  130. X
  131. X  if (is_master_lock()) {
  132. X    printf("\nThere is a master lock\n");
  133. X    clean_exit();
  134. X    exit(1);
  135. X  }
  136. X  set_master_lock();
  137. X  if (is_any_lock()) {
  138. X    printf("There is a lock;you should make sure the nation is not playing\n");
  139. X    del_master_lock();
  140. X    clean_exit();
  141. X    exit(1);
  142. X  }
  143. X  /* initialize curses if we are adding a
  144. X     nation interactively (i.e. not NPCs)
  145. X   */
  146. X  if (strlen(add_fn) == 0) {
  147. X    initscr();            /* Initialize curses */
  148. X    cbreak();            /* set cbreak mode */
  149. X    noecho();            /* unset echo mode */
  150. X  }
  151. X  noncritical();
  152. X
  153. X  if ((n = find_free_nation(&world)) == -1) {
  154. X    printf("No free nations, sorry.\n");
  155. X    clean_exit();
  156. X    exit(1);
  157. X  }
  158. X
  159. X  if (debug) {
  160. X    printf("First free nation id is %d.\n", n);
  161. X  }
  162. X
  163. X  fflush(stdin);
  164. X
  165. X  if (stdscr) {
  166. X    refresh();
  167. X  }
  168. X
  169. X  /* check if we are adding NPCs from file add_fn[] */
  170. X  if (strlen(add_fn) != 0) {
  171. X      /* MCG Kludge Time */
  172. X    char full_path_fn[255];
  173. X    strcpy(full_path_fn, "misc/");
  174. X    strcat(full_path_fn, add_fn);
  175. X    printf("\nAdding NPC nations\n\n");
  176. X    add_npcs(full_path_fn, npcs_get_mail);
  177. X  } else {            /* else we add a single player */
  178. X    add_player(n);
  179. X  }
  180. X
  181. X  clean_exit();
  182. X  return 0;
  183. X}
  184. X
  185. X  /* inserts a player into the world with id = n */
  186. Xadd_player(n)
  187. X     int n;
  188. X{
  189. X  Snation tmp_nation;            /* as we form the nation */
  190. X  char racemark;
  191. X  char mag_ord[NAMELEN], pass_try1[NAMELEN], pass_try2[NAMELEN];
  192. X
  193. X  clear();
  194. X
  195. X  tmp_nation.id = n;
  196. X
  197. X  echo();
  198. X  mvaddstr(0, 0, "Nation's name: ");
  199. X  refresh();
  200. X/*  getstr(tmp_nation.name); */
  201. X  wget_string(stdscr,tmp_nation.name,NAMELEN);
  202. X
  203. X  while (!unique_name(tmp_nation.name)) {  
  204. X    clear();
  205. X    mvprintw(0, 0, "Sorry, \"%s\" is already taken.", tmp_nation.name);
  206. X    mvaddstr(2, 0, "Enter nation's name: ");
  207. X    refresh();
  208. X/*    getstr(tmp_nation.name); */
  209. X    wget_string(stdscr,tmp_nation.name,NAMELEN);
  210. X  }
  211. X  noecho();
  212. X
  213. X  get_crypt_pass("\nEnter the password for your nation: ", pass_try1, stdscr,
  214. X         NULL);
  215. X  get_crypt_pass("\nType it once more: ", pass_try2, stdscr, NULL);
  216. X
  217. X
  218. X  /* make sure user knows their pass. */
  219. X  while  (strcmp(pass_try1, pass_try2) != 0){
  220. X    clear();
  221. X    printw("They don't match, try again\n\r");
  222. X    get_crypt_pass("Give nation's password: ", pass_try1, stdscr, NULL);
  223. X    get_crypt_pass("\nPlease type it once more: ", pass_try2, stdscr, NULL);
  224. X  }
  225. X  strcpy(tmp_nation.passwd, pass_try1);
  226. X  echo();
  227. X
  228. X  printw("\n\rGive your leader's name: ");
  229. X  refresh();
  230. X/*   getstr(tmp_nation.leader); */
  231. X  wget_string(stdscr,tmp_nation.leader,NAMELEN);
  232. X  racemark = get_race_mark();
  233. X
  234. X  tmp_nation.mark = get_nation_mark();
  235. X
  236. X  choose_mag_order(mag_ord);
  237. X    /* each magic order brings some advantages.  insert them now */
  238. X  add_special_mag(&tmp_nation, mag_ord);
  239. X
  240. X  clear();
  241. X  refresh();
  242. X
  243. X    /* Set up a new, non-NPC nation */
  244. X  if (setup_new_nation(tmp_nation.name, tmp_nation.passwd, tmp_nation.leader,
  245. X    racemark, tmp_nation.mark, mag_ord, NOT_NPC, 50, 5, 5) < 0) {
  246. X    printw("\n\r  Could not add nation %s\n\r", tmp_nation.name);
  247. X    refresh();
  248. X    noecho();
  249. X  } else {
  250. X    move(0, LINES-1);
  251. X    refresh();
  252. X    endwin();
  253. X    stdscr = NULL;
  254. X    write_world(&world, WORLD_FILE);
  255. X  }
  256. X}
  257. X
  258. X  /* make sure that the guy knows the game master password */
  259. Xverify_gamemaster()
  260. X{
  261. X  char s[NAMELEN], *getpass(), *crypt();
  262. X  
  263. X  get_crypt_pass("Enter game master's password: ", s, NULL, NULL);
  264. X  return !strcmp(s, world.nations[0].passwd);
  265. X}
  266. X
  267. X
  268. Xfind_free_nation(wp)        /* return first free slot, -1 if none */
  269. X     Sworld *wp;
  270. X{
  271. X  int i;
  272. X  for (i = 0; i < NATIONS; ++i) {
  273. X    if (strlen(wp->nations[i].name) == 0) {
  274. X      return i;            /* found a free one! */
  275. X    }
  276. X  }
  277. X  return -1;
  278. X}
  279. X
  280. Xcleanup()
  281. X{
  282. X/*  clear(); */
  283. X  refresh();
  284. X}
  285. X
  286. X  /* cleanup and prepare to exit */
  287. Xclean_exit()
  288. X{
  289. X  del_master_lock();
  290. X  if (stdscr) {
  291. X    refresh();
  292. X    endwin(); /* end curses */
  293. X  }
  294. X}
  295. X
  296. X  /* initial military setup */
  297. X#define INITIAL_SOLDIERS 10*OCCUPYING_SOLDIERS
  298. Xsetup_armies(np)
  299. X     Snation *np;
  300. X{
  301. X  Sarmy army, make_army();
  302. X  int i;
  303. X  char name [NAMELEN];
  304. X
  305. X  load_army_types();
  306. X    /* we make 10 armies of equal size. the first one has special handling. */
  307. X  army = make_army(army_types[0].type, "Cavemen 0", INITIAL_SOLDIERS/10,
  308. X           A_DEFEND, np->id, np->capital);
  309. X  army.mvpts = basic_move_rate(np);
  310. X  army.mvratio = 100;        /* ration of initial to final move points */
  311. X  army.id = 0;            /* make sure, this is FIRST army! */
  312. X  if (debug) {
  313. X    printf("made a new army: owner=%d,x=%d,y=%d,num=%d", army.owner,
  314. X       army.pos.x,army.pos.y,army.n_soldiers);
  315. X  }
  316. X  army.next = NULL;
  317. X  np->armies = (Sarmy *) malloc(sizeof(Sarmy));    /* create army list */
  318. X  *(np->armies) = army;
  319. X  /* the sector must also have a list of armies */
  320. X  world.map[army.pos.x][army.pos.y].alist
  321. X    = (struct armyid *) malloc(sizeof(struct armyid));
  322. X  world.map[army.pos.x][army.pos.y].alist->owner = army.owner;
  323. X  world.map[army.pos.x][army.pos.y].alist->id = army.id;
  324. X  world.map[army.pos.x][army.pos.y].alist->next = NULL;
  325. X  for (i = 1; i < 10; ++i) {
  326. X    sprintf(name, "%s", army_types[0].type);
  327. X    army = make_army(army_types[0].type, name, INITIAL_SOLDIERS/10,
  328. X             A_DEFEND, np->id, np->capital);
  329. X      /* first time around, they move at full rate */
  330. X    army.mvpts = basic_move_rate(np);
  331. X    army.mvratio = 100;
  332. X    army.id = i;
  333. X    army.next = NULL;
  334. X    insert_army_nation(np, &army, i);
  335. X    insert_army_sector(&world.map[army.pos.x][army.pos.y], &army);
  336. X  }
  337. X  np->n_armies = 10;
  338. X    /* figure out bonuses; crude formula for now */
  339. X  np->attack = np->race.strength/4 + np->race.intel/12;
  340. X  np->defense = np->race.strength/4 + np->race.intel/12;
  341. X  np->spy = 0;
  342. X  np->secrecy = 0;
  343. X}
  344. X
  345. X  /* initialize fields in this nation's data structure
  346. X     that are relevant to the economy.
  347. X   */
  348. Xsetup_economy(np)
  349. X     Snation *np;
  350. X{
  351. X  np->taxes = 10;        /* tax rate, % of income */
  352. X  np->charity = 0;        /* money given to the poor */
  353. X  np->money = 100000;        /* initial wealth */
  354. X  np->jewels = 20000;
  355. X  np->metal = 20000;
  356. X  np->food = 100000;
  357. X    /* default values, until user learns how to use her/his budget screen */
  358. X  np->tech_r_d = 30;
  359. X  np->tech_r_d_metal = 40;
  360. X  np->mag_r_d = 30;
  361. X  np->mag_r_d_jewels = 40;
  362. X  np->spy_r_d = 0;
  363. X  np->cur_mag_r_d = 0;
  364. X  np->cur_mag_r_d_jewels = 0;
  365. X  np->cur_tech_r_d = 0;
  366. X  np->cur_tech_r_d_metal = 0;
  367. X  np->cur_spy_r_d = 0;
  368. X}
  369. X
  370. Xget_race_mark()
  371. X{
  372. X  char racemark;
  373. X  int done = 0;
  374. X  int race_counter=0;
  375. X  struct race_list *rlp;    /* to manipulate the list */
  376. X  char tmp_sprintf [70];
  377. X
  378. X  clear ();
  379. X
  380. X  mvaddstr (2, 0, "Races: ");
  381. X  rlp = races;
  382. X  while (rlp != NULL) {
  383. X    sprintf (tmp_sprintf, "(%c) : %s\n", rlp->race.mark, rlp->race.name);
  384. X    mvaddstr (4+race_counter++, 4, tmp_sprintf);
  385. X    rlp = rlp->next;
  386. X  }
  387. X  do {
  388. X    mvaddstr (0, 0, "Pick a race and enter its mark: ");
  389. X    refresh ();
  390. X    racemark = getch();
  391. X    done = 0;
  392. X    rlp = races;
  393. X    while (rlp != NULL) {
  394. X      if (rlp->race.mark == racemark) {
  395. X    done = 1;
  396. X    break;
  397. X      }
  398. X      rlp = rlp->next;
  399. X    }
  400. X  } while (!done);
  401. X  return racemark;
  402. X}
  403. X
  404. Xsetup_race(np,racemark)
  405. X     Snation *np;
  406. X     char racemark;
  407. X{
  408. X  struct race_list *rlp;    /* So we can work with the races list */
  409. X  
  410. X  rlp = races;
  411. X  while(rlp != NULL) {
  412. X    if (rlp->race.mark == racemark) { /* Did we find that race? */
  413. X      np->race = rlp->race;
  414. X      return 1;            /* If we found it, return a 1 */
  415. X    }
  416. X    rlp = rlp->next;
  417. X  }
  418. X  return -1;            /* We didn't find it */
  419. X}
  420. X
  421. Xsetup_skills(np)
  422. X     Snation *np;
  423. X{
  424. X  np->tech_skill = 0;
  425. X  np->mag_skill = 0;
  426. X  
  427. X  /* Nations begin with a certain production and it increases from there */
  428. X  
  429. X  np->farm_skill = np->race.farming;
  430. X  np->mine_skill = np->race.mining;
  431. X
  432. X  np->spell_pts = 0;
  433. X}
  434. X
  435. Xchoose_mag_order(s)
  436. X     char s[];
  437. X{
  438. X  strcpy(s, "");
  439. X  clear ();
  440. X  list_mag_orders();
  441. X
  442. X  do {
  443. X    mvaddstr (0, 0, "Choose one of the listed magical orders: ");
  444. X    clrtoeol ();
  445. X    refresh ();
  446. X    wget_string (stdscr,s,NAMELEN);
  447. X  } while (!is_good_order(s));
  448. X}
  449. X
  450. X  /* sets up the capital and a few outlying sectors; if after
  451. X     MAX_TRIES it does not find a good place, it exits.
  452. X   */
  453. Xsetup_capital(np)
  454. X     Snation *np;
  455. X{
  456. X  int pref, i, j, x, y, distance, tries,
  457. X    remaining_pop = INIT_CIV + RND() % 100, beginning_pop;
  458. X  Ssector *sp;
  459. X  int radius, n_sects;        /* dist. from capital for other sects */
  460. X
  461. X  beginning_pop = remaining_pop;
  462. X  tries = 0;
  463. X  pref = 0;
  464. X  /* a negative capital x-coordinate means we have not found
  465. X     a good location for the capital yet.
  466. X   */
  467. X  x = -1;
  468. X  distance = 7;
  469. X
  470. X  while (x < 0) {
  471. X    distance = max(1, --distance);
  472. X    for (i = 0; i < 10; i++) {
  473. X      do {
  474. X      /* keep trying random sectors as long
  475. X         as things aren't good.
  476. X       */
  477. X    x = RND() % world.xmax;
  478. X    y = RND() % world.ymax;
  479. X    ++tries;
  480. X    if (tries >= MAX_TRIES) {
  481. X      printf("  Cannot find space for capital of nation %s\n", np->name);
  482. X      return -1;
  483. X    }
  484. X      } while ((world.map[x][y].owner != 0) || !isolated(x, y) ||
  485. X           (!good_altitude(&world.map[x][y], np)) ||
  486. X           (world.map[x][y].metal > 0) ||
  487. X           (world.map[x][y].jewels > 0));  /*see if it's taken!*/
  488. X      if (sect_desire(np, x, y) > pref) {
  489. X    pref = sect_desire(np, x, y);
  490. X    np->capital.x = x;
  491. X    np->capital.y = y;
  492. X      }
  493. X    }
  494. X    for (i = np->capital.x - distance; i <= np->capital.x + distance; i++) {
  495. X      for (j = np->capital.y - distance; j <= np->capital.y + distance; j++) {
  496. X    if (np->race.pref_alt < SEA_LEVEL) { /* under water race */
  497. X      if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner != 0 &&
  498. X          world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].altitude >= SEA_LEVEL) {
  499. X        x = -1;        /* water race cannot be on land */
  500. X      }
  501. X    } else {        /* above race */
  502. X      if (world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].owner != 0 &&
  503. X          world.map[(*wrapx)(i,j)][(*wrapy)(i,j)].altitude < SEA_LEVEL) {
  504. X        x = -1;        /* land race canot be underwater */
  505. X      }
  506. X    }
  507. X      }
  508. X    }
  509. X  }
  510. X  x = np->capital.x;
  511. X  y = np->capital.y;
  512. X  putchar('\n');
  513. X  np->ptlist = NULL;
  514. X  addsector(np, x, y);
  515. X  world.map[x][y].n_people = beginning_pop/2; /* half people in capital */
  516. X  remaining_pop -= beginning_pop/2;
  517. X  world.map[x][y].designation = D_CAPITAL;
  518. X  np->n_sects = 1;
  519. X
  520. X  radius = 1;
  521. X  n_sects = 1;
  522. X  while (n_sects < 9) {        /* must give user 9 sectors */
  523. X    for (i=x-radius; i<=x+radius; i++) {
  524. X      for (j=y-radius; j<=y+radius; j++) {
  525. X    if (i != 0 || j != 0) {    /* skip the capital */
  526. X      sp = &world.map[wrapx(i,j)][wrapy(i,j)];
  527. X      if (sp->owner != 0
  528. X          || (np->race.pref_alt >= SEA_LEVEL && sp->altitude < SEA_LEVEL)
  529. X          || (np->race.pref_alt < SEA_LEVEL && sp->altitude >= SEA_LEVEL)
  530. X          || n_sects >= 9) {
  531. X      } else {
  532. X        addsector(np, (*wrapx)(i,j), (*wrapy)(i,j));
  533. X        sp->n_people = beginning_pop/16;
  534. X        remaining_pop -= beginning_pop/16;
  535. X        sp->designation = default_desig(sp);
  536. X/*        printf("rad %d; %d,%d: %d people, remaining_pop=%d (of %d)\n",
  537. X           radius, i, j, sp->n_people, remaining_pop, beginning_pop);
  538. X*/
  539. X        ++n_sects;
  540. X      }
  541. X    }
  542. X      }
  543. X    }
  544. X    ++radius;            /* try bigger and bigger circles */
  545. X  }
  546. X    /* now if any people are left, put them in the capital */
  547. X  world.map[x][y].n_people += remaining_pop;
  548. X/*   printf("Done with nation %s\n", sp->name);*/
  549. X/*  printf("capital has %d people\n", world.map[x][y].n_people); */
  550. X  return 1;
  551. X}
  552. X
  553. X  /* this gives a sector a default designation of
  554. X     D_FARM unless some other resource is present
  555. X   */
  556. Xdefault_desig(sp)
  557. X     Ssector *sp;
  558. X{
  559. X  if (sp->jewels > 0) {
  560. X    if (sp->metal > sp->jewels) {
  561. X      return D_METAL_MINE;
  562. X    } else {
  563. X      return D_JEWEL_MINE;
  564. X    }
  565. X  }
  566. X  if (sp->metal > 0) {
  567. X    return D_METAL_MINE;
  568. X  } else {
  569. X    return D_FARM;
  570. X  }
  571. X}
  572. X
  573. X  /* the workhorse behind addnation */
  574. Xsetup_new_nation(nation_name, nation_pass, leader_name, nation_race,
  575. X         nation_mark, mag_ord, npc_flag, npcagg, npcexp, npciso)
  576. X     char nation_name[NAMELEN],nation_pass[PASSLEN],leader_name[NAMELEN],
  577. X       mag_ord[NAMELEN], nation_race;
  578. X     Symbol nation_mark;
  579. X     int npc_flag, npcagg, npcexp, npciso;
  580. X{
  581. X  Sdiplo **dm_old, **dm_new;
  582. X  Snation tmp;
  583. X  int n;            /* Free nation ID number */
  584. X  char cmd_str[PATHLEN];
  585. X
  586. X  if ((n = find_free_nation(&world)) == -1) {
  587. X    printf("No free nations, sorry.\n");
  588. X    return -1;
  589. X  }
  590. X
  591. X  tmp.id = n;
  592. X  if (!unique_name(nation_name)) { /* Should reject identical names */
  593. X    printf("Already have a nation called %s.\n", nation_name);
  594. X    return -1;
  595. X  }
  596. X  strcpy(tmp.name, nation_name);
  597. X  strcpy(tmp.passwd, nation_pass);
  598. X  strcpy(tmp.leader, leader_name);
  599. X  strcpy(tmp.mag_order, mag_ord);
  600. X
  601. X  setup_race(&tmp, nation_race);
  602. X
  603. X  printf("Doing nation %s\n", nation_name);
  604. X
  605. X  if (!free_nation_mark(&world, nation_mark)) {
  606. X    printf("  Already have a nation using %c as their nation mark.\n",
  607. X       nation_mark);    /* Should reject identical nation marks */
  608. X    return(-1);
  609. X  }
  610. X  tmp.mark = nation_mark;
  611. X
  612. X  setup_economy(&tmp);
  613. X  setup_skills(&tmp);
  614. X
  615. X  tmp.npc_flag = npc_flag;
  616. X  tmp.npc_agg = npcagg;
  617. X  tmp.npc_iso = npciso;
  618. X  tmp.npc_exp = npcexp;
  619. X
  620. X  if (setup_capital(&tmp) < 0) { /* Adds a capital and land */
  621. X    /* if there is no good place for the nation */
  622. X    return -1;
  623. X  }
  624. X  setup_armies(&tmp);        /* must be done after capital */
  625. X
  626. X  world.nations[n] = tmp;    /* OK, now add this nation */
  627. X  ++world.n_nations;
  628. X
  629. X    /* now update the diplo file, so it is bigger */
  630. X  dm_old = allocate_diplo(world.n_nations-1);
  631. X  dm_new = allocate_diplo(world.n_nations);
  632. X  read_in_diplo(dm_old, world.n_nations-1);
  633. X  increase_diplo(dm_old, dm_new, world.n_nations-1, &tmp);
  634. X  dump_diplo(NULL, dm_new, world.n_nations);
  635. X    /* also make a copy of the initial diplomacy file */
  636. X  sprintf(cmd_str, "cp %s %s\n", DIPLO_FILE, INIT_DIPLO_FILE);
  637. X  system(cmd_str);
  638. X  free_diplo(dm_old, world.n_nations-1);
  639. X  free_diplo(dm_new, world.n_nations);
  640. X
  641. X  return 1;
  642. X}
  643. X
  644. Xadd_npcs(npc_fn, npcs_get_mail)
  645. X     char * npc_fn;
  646. X     int npcs_get_mail;
  647. X{
  648. X  FILE *fp;
  649. X  char s[110], racemark, nationmark;
  650. X  char nation_name[NAMELEN], leader_name[NAMELEN], mag_order[NAMELEN];
  651. X  int n_npcs, npc_agg, npc_exp, npc_iso;
  652. X  int i;
  653. X
  654. X  if ((fp = fopen(npc_fn, "r")) == NULL) {
  655. X    printf("Cannot open npc file.\n");
  656. X    return;
  657. X  }
  658. X
  659. X  fgets(s, 100, fp);
  660. X  while (s[0] == '#') {        /* Ignoring the comments */
  661. X    fgets(s, 100, fp);
  662. X  }
  663. X  sscanf(s, "%d", &n_npcs);
  664. X
  665. X  for (i = 0; i < n_npcs; i++) {
  666. X    fgets(s, 100, fp);
  667. X    s[strlen(s)-1] = '\0';
  668. X    if (s[0] != '#') {
  669. X      sscanf(s, "%s : %s : %c : %c : %s : %d : %d : %d", nation_name,
  670. X         leader_name, &racemark, &nationmark, mag_order,
  671. X         &npc_agg, &npc_exp, &npc_iso);
  672. X      if (debug) {
  673. X    printf("  Nation: %s\n  Leader: %s\nRacemark: %c\n Ntnmark: %c\n",
  674. X           nation_name, leader_name, racemark, nationmark);
  675. X    printf("Mag_Ordr: %s\nAgressiv: %d\n  Expand: %d\n Isolate: %d\n\n",
  676. X           mag_order, npc_agg, npc_exp, npc_iso);
  677. X      }
  678. X      if (setup_new_nation(nation_name, world.nations[0].passwd, leader_name,
  679. X               racemark, nationmark, mag_order,
  680. X               npcs_get_mail ? NPC_MAIL : NPC_NOMAIL,
  681. X               npc_agg, npc_exp, npc_iso) < 0) {
  682. X    /* if we cannot set up this NPC for whatever reason */
  683. X    printf("    Did NOT set up nation %s\n\n", nation_name);
  684. X    continue;        /* go on to the next NPC */
  685. X      }
  686. X    }
  687. X  }
  688. X  fclose(fp);
  689. X  printf("\n");
  690. X  write_world(&world, WORLD_FILE);
  691. X}
  692. X
  693. X  /* critical() for the update/make/add is different from the game */
  694. Xcritical()
  695. X{
  696. X  signal(SIGINT, SIG_IGN);
  697. X  signal(SIGQUIT, SIG_IGN);
  698. X}
  699. Xnoncritical()
  700. X{
  701. X  signal(SIGINT, sigquit);
  702. X  signal(SIGQUIT, sigquit);
  703. X}
  704. X
  705. X
  706. Xint sigquit ()
  707. X{
  708. X  if (stdscr) {
  709. X    standout();
  710. X    mvprintw(0, 65, "Quitting...");
  711. X    standend();
  712. X    refresh();
  713. X  } else {
  714. X    printf("\nQuitting...\n");
  715. X  }
  716. X  clean_exit();
  717. X  exit(1);
  718. X}
  719. X
  720. X/* Lifted from misc.c and maglib.c */
  721. Xshow_race_w(rp)
  722. X     Srace *rp;
  723. X{
  724. X}
  725. X
  726. Xlist_mag_orders()
  727. X{
  728. X  int n_orders, i;
  729. X  FILE *fp;
  730. X  char line[200];
  731. X  char **order_list;
  732. X  char mag_counter=0;
  733. X
  734. X  if ((fp = fopen(MAG_ORDERS, "r")) == NULL) {
  735. X    printw("\ncannot find file %s.  this is bad.\n\r", MAG_ORDERS);
  736. X    clean_exit();
  737. X    exit(1);
  738. X  }
  739. X  while (fgets(line, 200, fp) != NULL) {
  740. X    if (line[0] != '#') {
  741. X      sscanf(line, "%d", &n_orders);
  742. X      break;            /* we got the number of orders */
  743. X    }
  744. X  }
  745. X  order_list = (char **) malloc(n_orders*sizeof(char *));
  746. X
  747. X  mvaddstr (2, 0, "Magical orders: ");
  748. X
  749. X  for (i = 0; i < n_orders; ) {
  750. X    fgets(line, NAMELEN, fp);
  751. X    if (line[0] != '#') {
  752. X      mvprintw(3 + mag_counter++, 4, "%s", line);
  753. X      order_list[i] = (char *) malloc(NAMELEN*sizeof(char));
  754. X      strcpy(order_list[i], line);
  755. X      ++i;
  756. X    }
  757. X  }
  758. X
  759. X  fclose(fp);
  760. X}
  761. X
  762. X  /* prompt a user for a nation mark */
  763. X#define valid_nation_mark(c) (strchr(valid_mark_str, c))
  764. Xchar get_nation_mark()
  765. X{
  766. X  int attempt_counter=0;
  767. X  char mark;
  768. X  char valid_mark_str[128];
  769. X
  770. X  form_valid_mark_str(valid_mark_str);
  771. X
  772. X  clear();
  773. X
  774. X  mvaddstr(0, 0, "Which nation mark do you want? ");
  775. X  refresh();
  776. X
  777. X  mark = getch();
  778. X  while (!free_nation_mark(&world, mark) || !valid_nation_mark(mark)) {
  779. X    if (attempt_counter > 15) {
  780. X      attempt_counter = 15;
  781. X    }
  782. X    if (!free_nation_mark(&world, mark)) {
  783. X      mvprintw(2 + attempt_counter++, 0,
  784. X        "Sorry, the nation mark %c is taken already.", mark);
  785. X    } else if (!valid_nation_mark(mark)) {
  786. X      mvprintw(2 + attempt_counter++, 0,
  787. X        "Sorry, the nation mark %c is not valid.", mark);
  788. X      clrtoeol();
  789. X      mvprintw(2 + attempt_counter++, 0, "Valid nation marks are: ");
  790. X      mvprintw(2 + attempt_counter++, 0, "%s", valid_mark_str);
  791. X      ++attempt_counter;
  792. X    }
  793. X    mvaddstr(0, 0, "Which nation mark do you want? ");
  794. X    refresh();
  795. X    mark = getch();
  796. X  }
  797. X  return mark;
  798. X
  799. X#ifdef OLD
  800. X  if (!free_nation_mark(&world, mark))  { /* see if it's already used */
  801. X    do {
  802. X      if (attempt_counter > 20) attempt_counter=20;
  803. X      mvprintw (2 + attempt_counter++, 0,
  804. X                "Sorry, the nation mark %c is taken already.", mark);
  805. X      mvprintw (0, 0, "Which nation mark do you want: ");
  806. X      refresh ();
  807. X      mark = getch ();
  808. X    } while (!free_nation_mark(&world, mark));
  809. X  }
  810. X
  811. X  /* now check if it is a nation mark that is not valid
  812. X     (like a space, or a dash or a dot or twiddle)
  813. X   */
  814. X  if (!valid_nation_mark(mark))  {
  815. X    do {
  816. X      if (attempt_counter > 20) {
  817. X    attempt_counter=20;
  818. X      }
  819. X      mvprintw(2 + attempt_counter++, 0,
  820. X           "Sorry, the nation mark %c is not valid.", mark);
  821. X      mvprintw(2 + attempt_counter++, 0, "Valid nation marks are: ");
  822. X      addstr(valid_mark_str);
  823. X      mvprintw(0, 0, "Which nation mark do you want: ");
  824. X      refresh();
  825. X      mark = getch();
  826. X    } while (!free_nation_mark(&world, mark));
  827. X  }
  828. X  return mark;
  829. X#endif /* OLD */
  830. X}
  831. X
  832. X  /* returns true if there is no owned sector too near this one */
  833. Xisolated(x, y)
  834. X{
  835. X  int i, j;
  836. X
  837. X  for (i = x-RADIUS; i <= x+RADIUS; ++i) {
  838. X    for (j = y-RADIUS; j <= y+RADIUS; ++j) {
  839. X        /* see if one of these nearby sectors is owned */
  840. X      if (world.map[(*wrapx)(i, j)][(*wrapy)(i, j)].owner != 0) {
  841. X    return 0;        /* oops, we are *not* isolated */
  842. X      }
  843. X    }
  844. X  }
  845. X  return 1;
  846. X}
  847. X
  848. X  /* put some stuff into a nation's exec file to get them started with
  849. X     the privilege of their magic order.
  850. X   */
  851. Xadd_special_mag(np, mag_ord)
  852. X     Snation *np;
  853. X     char mag_ord[];
  854. X{
  855. X  char fname[255], line[2*EXECLEN];
  856. X  FILE *magfp, *execfp;
  857. X  int done = 0;
  858. X
  859. X  strcpy(fname, MAG_PREFIX);
  860. X  strcat(fname, mag_ord);
  861. X  if ((magfp = fopen(fname, "r")) == NULL) {
  862. X    clean_exit();
  863. X    exit(1);
  864. X  }
  865. X  sprintf(fname, "exec/exec%d", np->id);
  866. X  if ((execfp = fopen(fname, "a")) == NULL) {
  867. X    clean_exit();
  868. X    exit(1);
  869. X  }
  870. X  while (!done) {
  871. X    if (fgets(line, EXECLEN, magfp) == NULL) {
  872. X      fclose(magfp);
  873. X      fclose(execfp);
  874. X      return;
  875. X    }
  876. X    if (line[0] != '#') {    /* avoid comments */
  877. X      if (strncmp(line, "EXEC:", strlen("EXEC:")) == 0) {
  878. X/*    printf("found an exec line %s\n", line);
  879. X    refresh();
  880. X    getch();
  881. X    getch();
  882. X*/
  883. X    fprintf(execfp, "%s", line+strlen("EXEC:"));
  884. X      }
  885. X    }
  886. X  }
  887. X}
  888. X
  889. X/* Please note that this is the same routine as in cur_stuff.c but linking
  890. X   that into this code would require a plethora of other object files to 
  891. X   successfully compile.
  892. X*/
  893. X  /* gets a string str of max length len */
  894. Xwget_string (w, rets, len)
  895. X     WINDOW * w;
  896. X     char * rets;
  897. X     int len;
  898. X{
  899. X  char s [80];
  900. X  int pos, done;
  901. X  int x, y, i;
  902. X  int oldpos;        /* Used for ^W */
  903. X  noecho ();
  904. X
  905. X  if (w == NULL) {
  906. X    w = stdscr;
  907. X  }
  908. X
  909. X  pos = 0;
  910. X  done = 0;
  911. X
  912. X  getyx (w, y, x);
  913. X  wrefresh (w);
  914. X
  915. X  while (!done) {
  916. X    s [pos] = wgetch (stdscr);
  917. X    switch (s[pos]) {
  918. X    case '\n':
  919. X    case '\r':
  920. X      s [pos] = '\0';
  921. X      done = 1;
  922. X      break;
  923. X    case '\b':
  924. X    case DEL:
  925. X      if (pos > 0) {
  926. X    pos--;
  927. X    s[pos] = '\0';
  928. X    wmove (w, y, x + pos);
  929. X    waddch (w, ' ');
  930. X    wmove (w, y, x + pos);
  931. X      }
  932. X      break;
  933. X    case CTL('U'):
  934. X      wmove (w, y, x);
  935. X      for (i=0; i < pos; i++) {
  936. X    waddch (w, ' ');
  937. X      }
  938. X      wmove (w, y, x);
  939. X      pos = 0;
  940. X      s [pos] = '\0';
  941. X      break;
  942. X    case CTL('W'):
  943. X      oldpos = pos;
  944. X      while (pos != 0 && s[pos] == ' ') {
  945. X    pos --;
  946. X      }
  947. X      if (pos) {
  948. X    pos --;
  949. X      }
  950. X      while (pos != 0 && s[pos] != ' ') {
  951. X    pos --;
  952. X      }
  953. X      wmove (w, y, x + pos);
  954. X      while (oldpos != pos) {
  955. X    oldpos--;
  956. X    waddch (w, ' ');
  957. X      }      
  958. X      wmove (w, y, x + pos);
  959. X      break;
  960. X    default:
  961. X      waddch (w, s [pos]);
  962. X      pos++;
  963. X      break;
  964. X    }
  965. X    wrefresh (w);
  966. X  }
  967. X
  968. X  if (pos == 0) {
  969. X    return 0;
  970. X  }
  971. X  s [len-1] = '\0';
  972. X  strcpy (rets, s); 
  973. X  return 1;
  974. X}
  975. X
  976. X  /* return true if sector (x, y) has at least n connected sectors
  977. X     on land (or in water if (x, y) is in water) surrounding it.
  978. X   */
  979. Xhas_connected_mass(x, y, n)
  980. X     int x, y, n;
  981. X{
  982. X  Ssector *sp = &world.map[x][y];
  983. X  int n_found = 1, prev_n_found = 1; /* count (x, y) */
  984. X  int i, j;
  985. X
  986. X  /* go about (x, y) one circle at a time.  after each circle,
  987. X     see if any new connected sectors were found.  if none were,
  988. X     and n_found < n, then NAH... doesn't work!!  put it off for now.
  989. X   */
  990. X}
  991. X
  992. X  /* makes a list of valid nation marks in the given string;
  993. X     a mark is valid if it doesn't make a [d] [n] (nation mark
  994. X     display) confusing.  For example, <space>, '.' and so on
  995. X     would confuse.
  996. X   */
  997. Xform_valid_mark_str(mark_str)
  998. X     char mark_str[];
  999. X{
  1000. X  char tmp_str[128];
  1001. X
  1002. X  strcpy(tmp_str, "");
  1003. X  /* run through the ascii table (only those chars that are printable) */
  1004. X  strcat(tmp_str, "!\"#$%&'()*+,");
  1005. X  /* skip '-' and '.' */
  1006. X  strcat(tmp_str, "/0123456789:;<=>"); /* now skip '?' */
  1007. X  strcat(tmp_str, "@ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  1008. X  strcat(tmp_str, "[\]^_`abcdefghijklmnopqrstuvwxyz{|}");
  1009. X  strcpy(mark_str, tmp_str);
  1010. X}
  1011. END_OF_FILE
  1012. if test 24914 -ne `wc -c <'addnation.c'`; then
  1013.     echo shar: \"'addnation.c'\" unpacked with wrong size!
  1014. fi
  1015. # end of 'addnation.c'
  1016. fi
  1017. if test -f 'mag_Diana' -a "${1}" != "-c" ; then 
  1018.   echo shar: Will not clobber existing file \"'mag_Diana'\"
  1019. else
  1020. echo shar: Extracting \"'mag_Diana'\" \(686 characters\)
  1021. sed "s/^X//" >'mag_Diana' <<'END_OF_FILE'
  1022. X# this file describes magic powers available to magical order of Diana,
  1023. X# which is mostly concerned with animals and hunting.
  1024. X#
  1025. X# the format is:
  1026. X# name level cost
  1027. X# begin
  1028. X#   series of exec lines
  1029. X# end
  1030. X#
  1031. X# where `level' is the magical skill level at which you get the power,
  1032. X# and `cost' is the cost in spell points to use the power.
  1033. X#
  1034. XEXEC:NEW_ARMY_TYPE:Hunters
  1035. X# terraform 100 20
  1036. Xsummon_wolf 90 1
  1037. Xsummon_swarm 200 3
  1038. Xsummon_mole 200 3
  1039. Xsummon_snake 200 3
  1040. Xsummon_shark 300 3
  1041. Xsummon_hawk 500 5
  1042. Xsummon_bear 800 5
  1043. Xsummon_lion 900 6
  1044. Xsummon_terrasque 2000 13
  1045. X#
  1046. Xhide_army 200 1 2
  1047. Xhide_sector 250 2 8
  1048. Xmag_bonus 300 1 2
  1049. Xfly_army 400 2 2
  1050. Xwater_walk 400 2 2
  1051. Xcaltitude 800 8 6
  1052. X#
  1053. Xfertility 1000 4 6
  1054. END_OF_FILE
  1055. if test 686 -ne `wc -c <'mag_Diana'`; then
  1056.     echo shar: \"'mag_Diana'\" unpacked with wrong size!
  1057. fi
  1058. # end of 'mag_Diana'
  1059. fi
  1060. if test -f 'movement.c' -a "${1}" != "-c" ; then 
  1061.   echo shar: Will not clobber existing file \"'movement.c'\"
  1062. else
  1063. echo shar: Extracting \"'movement.c'\" \(6808 characters\)
  1064. sed "s/^X//" >'movement.c' <<'END_OF_FILE'
  1065. X  /* movement.c - routines that affect movement and move costs */
  1066. X
  1067. X/*
  1068. X * Copyright (C) 1990 Free Software Foundation, Inc.
  1069. X * Written by the dominion project.
  1070. X *
  1071. X * This file is part of dominion.
  1072. X *
  1073. X * dominion is free software; you can redistribute it and/or
  1074. X * modify it under the terms of the GNU General Public License as published
  1075. X * by the Free Software Foundation; either version 1, or (at your option)
  1076. X * any later version.
  1077. X *
  1078. X * This software is distributed in the hope that it will be useful,
  1079. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1080. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1081. X * GNU General Public License for more details.
  1082. X *
  1083. X * You should have received a copy of the GNU General Public License
  1084. X * along with this software; see the file COPYING.  If not, write to
  1085. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1086. X */
  1087. X
  1088. X/* get_move_cost(np,sp) - calculates a sector's move cost for a nation    */
  1089. X/* get_army_move_cost(np,ap,sp) - calculates a sector's move cost
  1090. X   for a given army                                                       */
  1091. X/* good_altitude(sp,np) - TRUE if nation is compatible with sect. alt.    */
  1092. X/* good_army_altitude(np,sp,ap) - TRUE if army is compatible with sect. alt. */
  1093. X
  1094. X#include "dominion.h"
  1095. X#include "misc.h"
  1096. X#include "army.h"
  1097. X#include <stdio.h>
  1098. X
  1099. X#define TOO_MUCH_MOVE_COST 1000    /* basically impenetrable */
  1100. X
  1101. X  /* returns the move cost for a given army over a given sector
  1102. X     if ap is NULL we should consider giving a "generic" move
  1103. X     cost for that sector.
  1104. X   */
  1105. Xget_army_move_cost(np, sp, ap)
  1106. X     Snation *np;
  1107. X     Ssector *sp;
  1108. X     Sarmy *ap;
  1109. X{
  1110. X  int cost = 1;
  1111. X
  1112. X  if (has_impenetrable(sp)) {
  1113. X    return TOO_MUCH_MOVE_COST;
  1114. X  }
  1115. X  cost += alt_mc(np, sp, ap);
  1116. X  cost += climate_mc(np, sp, ap);
  1117. X  cost += terrain_mc(np, sp, ap);
  1118. X  cost += patrol_mc(np, sp, ap);
  1119. X  cost += roads_mc(np, sp, ap);
  1120. X  cost += diplo_mc(np, sp, ap);
  1121. X  return max(1, cost);        /* can't be negative */
  1122. X}
  1123. X
  1124. X  /* generic move cost for a given nation on a given
  1125. X     sector.  this is displayed in the sector window,
  1126. X     but can be quite different from the move
  1127. X     cost for an army with special flags. this value
  1128. X     is the move cost for a basic army type, such
  1129. X     as "Infantry".
  1130. X   */
  1131. Xget_generic_move_cost(np, sp)
  1132. X     Snation *np;
  1133. X     Ssector *sp;
  1134. X{
  1135. X  int cost = 1;
  1136. X
  1137. X  if (has_impenetrable(sp)) {
  1138. X    return 100;
  1139. X  }
  1140. X  cost += alt_mc(np, sp, NULL);
  1141. X  cost += climate_mc(np, sp, NULL);
  1142. X  cost += terrain_mc(np, sp, NULL);
  1143. X  cost += patrol_mc(np, sp, NULL);
  1144. X  cost += roads_mc(np, sp, NULL);
  1145. X  cost += diplo_mc(np, sp, NULL);
  1146. X  return max(1, cost);        /* can't be negative */
  1147. X}
  1148. X
  1149. X  /* here follow a bunch of routines that give the
  1150. X     partial move cost for a given army on a given
  1151. X     sector, due to altitude, climate, diplomacy,
  1152. X     patrols, and so on...  if the army pointer
  1153. X     is NULL, then a "generic" value is returned
  1154. X     which does not account for special army flags
  1155. X   */
  1156. X  /* this macro does the real work */
  1157. X#define alt_cost(pref_alt, sp) (abs(pref_alt - sp->altitude)/2)
  1158. X
  1159. Xalt_mc(np, sp, ap)
  1160. X     Snation *np;
  1161. X     Ssector *sp;
  1162. X     Sarmy *ap;
  1163. X{
  1164. X  int virt_pref_alt = np->race.pref_alt; /* virtual preferred altitude */
  1165. X
  1166. X  if (ap == NULL) {        /* generic value */
  1167. X    return alt_cost(virt_pref_alt, sp);
  1168. X  }
  1169. X    /* if ap is not null, we examine special army properties */
  1170. X  if (is_flight(ap)) {        /* flying armies ignore altitude */
  1171. X    return 0;
  1172. X  }
  1173. X
  1174. X    /* see if army can make it into that sector */
  1175. X  if (!good_army_altitude(np, sp, ap)) {
  1176. X    return TOO_MUCH_MOVE_COST;
  1177. X  }
  1178. X  if (np->race.pref_alt >= SEA_LEVEL && sp->altitude < SEA_LEVEL
  1179. X      && is_water(ap)) {    /* water armies are adapted to shallows */
  1180. X    virt_pref_alt = SHALLOWS;
  1181. X  }
  1182. X  if (np->race.pref_alt < SEA_LEVEL && sp->altitude >= SEA_LEVEL
  1183. X      && is_land(ap)) {        /* land armies are adapted to lowlands */
  1184. X    virt_pref_alt = LOWLANDS;
  1185. X  }
  1186. X
  1187. X  return alt_cost(virt_pref_alt, sp);
  1188. X}
  1189. X
  1190. Xclimate_mc(np, sp, ap)
  1191. X     Snation *np;
  1192. X     Ssector *sp;
  1193. X     Sarmy *ap;
  1194. X{
  1195. X  int cost = 0;
  1196. X
  1197. X  cost += abs(np->race.pref_climate - sp->climate)/3;
  1198. X  return cost;
  1199. X}
  1200. X
  1201. Xterrain_mc(np, sp, ap)
  1202. X     Snation *np;
  1203. X     Ssector *sp;
  1204. X     Sarmy *ap;
  1205. X{
  1206. X  int cost = 0;
  1207. X
  1208. X  cost += abs(np->race.pref_terrain - sp->terrain)/2;
  1209. X  return cost;
  1210. X}
  1211. X
  1212. Xpatrol_mc(np, sp, ap)
  1213. X     Snation *np;
  1214. X     Ssector *sp;
  1215. X     Sarmy *ap;
  1216. X{
  1217. X  int cost = 0;
  1218. X
  1219. X  if (are_patrols(np, ap, sp)) {
  1220. X    cost += 5;
  1221. X  }
  1222. X  return cost;
  1223. X}
  1224. X
  1225. Xroads_mc(np, sp, ap)
  1226. X     Snation *np;
  1227. X     Ssector *sp;
  1228. X     Sarmy *ap;
  1229. X{
  1230. X  int cost = 0;
  1231. X
  1232. X  cost -= sp->roads;
  1233. X  return cost;
  1234. X}
  1235. X
  1236. Xdiplo_mc(np, sp, ap)
  1237. X     Snation *np;
  1238. X     Ssector *sp;
  1239. X     Sarmy *ap;
  1240. X{
  1241. X  int cost = 0;
  1242. X
  1243. X  if (ap && is_flight(ap)) {    /* flying armies ignore diplomacy */
  1244. X    return cost;
  1245. X  }
  1246. X    /* here the move cost goes up if we are not buddy-buddy with the owner */
  1247. X  if (sp->owner != np->id) {
  1248. X    if (sp->owner == 0) {
  1249. X      cost += 2;
  1250. X    } else if (are_allied(np->id, sp->owner)) {
  1251. X      cost += 1;
  1252. X    } else {
  1253. X      cost += 5;        /* non-allied land: mucho move cost */
  1254. X    }
  1255. X  }
  1256. X  return cost;
  1257. X}
  1258. X
  1259. X
  1260. X  /* this takes care of whether a given race can
  1261. X     move to a given sector from the altitude point of view
  1262. X   */
  1263. Xgood_altitude(sp, np)
  1264. X     Ssector *sp;
  1265. X     Snation *np;
  1266. X{
  1267. X  if (sp->altitude >= SEA_LEVEL) { /* if above water */
  1268. X    return (np->race.pref_alt >= SEA_LEVEL || has_bubble(sp));
  1269. X  }
  1270. X  return (np->race.pref_alt < SEA_LEVEL || has_bubble(sp)); /* underwater */
  1271. X}
  1272. X  /* this takes care of whether a given army of a given race can
  1273. X     move to a given sector from the altitude point of view
  1274. X   */
  1275. Xgood_army_altitude(np, sp, ap)
  1276. X     Snation *np;
  1277. X     Ssector *sp;
  1278. X     Sarmy *ap;
  1279. X{
  1280. X  if (has_bubble(sp)) {
  1281. X    return 1;
  1282. X  }
  1283. X  if (is_water(ap) && is_land(ap)) {
  1284. X    return 1;
  1285. X  }
  1286. X  if (is_in_transport(ap)) {
  1287. X    return 1;            /* carried by someone else */
  1288. X  }
  1289. X    /* first look at the case where we are above water */
  1290. X  if (sp->altitude >= SEA_LEVEL) {
  1291. X    if (np->race.pref_alt >= SEA_LEVEL) {
  1292. X        /* water armies can only be in water (for land race) */
  1293. X      if (is_water(ap) && !is_coastal_sect(np, sp, ap)) {
  1294. X    return 0;
  1295. X      }
  1296. X      return 1;            /* it's OK: land army on land. */
  1297. X    }
  1298. X      /* otherwise we are a water race on land */
  1299. X    if (is_land(ap)) {
  1300. X      return 1;
  1301. X    }
  1302. X    if (is_water(ap) && is_coastal_sect(np, sp, ap)) {
  1303. X      return 1;            /* water army can stay on coast */
  1304. X    }
  1305. X    return 0;
  1306. X  }
  1307. X    /* now the case where we are an underwater sector */
  1308. X  if (np->race.pref_alt >= SEA_LEVEL) { /* land race under water */
  1309. X    if (is_water(ap)) {
  1310. X      return 1;
  1311. X    }
  1312. X    return 0;
  1313. X  }
  1314. X    /* now the case of a water race under water */
  1315. X  if (is_land(ap) && !is_coastal_sect(np, sp, ap)) {
  1316. X    return 0;
  1317. X  }
  1318. X  return 1;
  1319. X
  1320. X
  1321. X/*  return (np->race.pref_alt < SEA_LEVEL || has_bubble(sp)); /* underwater */
  1322. X}
  1323. END_OF_FILE
  1324. if test 6808 -ne `wc -c <'movement.c'`; then
  1325.     echo shar: \"'movement.c'\" unpacked with wrong size!
  1326. fi
  1327. # end of 'movement.c'
  1328. fi
  1329. if test -f 'spells.c' -a "${1}" != "-c" ; then 
  1330.   echo shar: Will not clobber existing file \"'spells.c'\"
  1331. else
  1332. echo shar: Extracting \"'spells.c'\" \(24702 characters\)
  1333. sed "s/^X//" >'spells.c' <<'END_OF_FILE'
  1334. X  /* spells.c -- the spells are coded here */
  1335. X
  1336. X/*
  1337. X * Copyright (C) 1990 Free Software Foundation, Inc.
  1338. X * Written by the dominion project.
  1339. X *
  1340. X * This file is part of dominion.
  1341. X *
  1342. X * dominion is free software; you can redistribute it and/or
  1343. X * modify it under the terms of the GNU General Public License as published
  1344. X * by the Free Software Foundation; either version 1, or (at your option)
  1345. X * any later version.
  1346. X *
  1347. X * This software is distributed in the hope that it will be useful,
  1348. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1349. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1350. X * GNU General Public License for more details.
  1351. X *
  1352. X * You should have received a copy of the GNU General Public License
  1353. X * along with this software; see the file COPYING.  If not, write to
  1354. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1355. X */
  1356. X
  1357. X#include "dominion.h"
  1358. X#include "misc.h"
  1359. X#include "army.h"
  1360. X
  1361. X#include <stdio.h>
  1362. X
  1363. X  /* how many new move points the haste spall gives you */
  1364. X#define HASTE_POINTS 8
  1365. X
  1366. Xextern Sworld world;
  1367. Xextern Sh_spell *hanging_spells;
  1368. Xextern Suser user;
  1369. X
  1370. X  /* the spell_structures[] array stores the spell names
  1371. X     together with the function pointers that execute them.
  1372. X   */
  1373. Xint spell_caltitude(), spell_fertility(), spell_hide_army(),
  1374. X  spell_fly_army(), spell_vampire_army(), spell_burrow_army(),
  1375. X  spell_haste_army(), spell_water_walk(),
  1376. X  spell_mag_bonus(), spell_merge(), spell_cmetal(), spell_cjewels(),
  1377. X  spell_fireburst(), spell_inferno(), spell_hide_sector(), spell_castle(),
  1378. X  spell_sacrifice();
  1379. X
  1380. Xstruct spell_struct {  char name[NAMELEN];  int (*func)(); };
  1381. X
  1382. Xstatic struct spell_struct spell_structures[] = {
  1383. X  {"caltitude", spell_caltitude}, {"fertility", spell_fertility},
  1384. X  {"hide_army", spell_hide_army}, {"fly_army", spell_fly_army},
  1385. X  {"vampire_army", spell_vampire_army}, {"burrow_army", spell_burrow_army},
  1386. X  {"water_walk", spell_water_walk}, {"haste_army", spell_haste_army},
  1387. X  {"mag_bonus", spell_mag_bonus}, {"merge", spell_merge},
  1388. X  {"cmetal", spell_cmetal},
  1389. X  {"cjewels", spell_cjewels}, {"fireburst", spell_fireburst},
  1390. X  {"inferno", spell_inferno}, {"hide_sector", spell_hide_sector},
  1391. X  {"castle", spell_castle,}, {"sacrifice", spell_sacrifice}
  1392. X};
  1393. X
  1394. X  /* this actually executes a spell */
  1395. Xexec_spell(spellp, w)
  1396. X     Sspell *spellp;
  1397. X     WINDOW *w;
  1398. X{
  1399. X  int cost = 0, i;
  1400. X  Sh_spell h_spell;
  1401. X  struct argument exec_args[N_EXEC_ARGS];
  1402. X
  1403. X  for (i = 0; i < sizeof(spell_structures)/sizeof(struct spell_struct); ++i) {
  1404. X    if (strcmp(spellp->name, spell_structures[i].name) == 0) {
  1405. X        /* each spell function returns the cost of casting */
  1406. X      cost = spell_structures[i].func(&user, w, spellp, &h_spell);
  1407. X      if (cost > 0) {        /* only if there is a real cost */
  1408. X    user.np->spell_pts -= cost;
  1409. X    cspell_pts(user.np, -cost);
  1410. X      /* add the spell to the list of hanging spells */
  1411. X    add_h_spell(&user.h_spells, &h_spell);
  1412. X    add_h_spell(&hanging_spells, &h_spell);
  1413. X      /* execute the spell */
  1414. X    for (i = 0; i < h_spell.n_lines; ++i) {
  1415. X      if (i % 2 == 0) {
  1416. X        parse_exec_line(h_spell.lines[i], exec_args);
  1417. X        run_exec_line(user.np, exec_args);
  1418. X      }
  1419. X    }
  1420. X      /* should put this in a more efficient place */
  1421. X    write_h_spells();
  1422. X      }
  1423. X      return cost;        /* we found our spell, now return */
  1424. X    }
  1425. X  }
  1426. X  return cost;
  1427. X}
  1428. X
  1429. X  /* terraforming spells */
  1430. Xint spell_caltitude(up, w, spellp, h_spellp)
  1431. X     Suser *up;
  1432. X     WINDOW *w;
  1433. X     Sspell *spellp;
  1434. X     Sh_spell *h_spellp;
  1435. X{
  1436. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1437. X  int cost, change = 0;
  1438. X  char s[EXECLEN];
  1439. X
  1440. X  if (w) {
  1441. X    mvwprintw(w, 4, 1,
  1442. X     "Cost %d spell points.  Do you wish to [+]raise or [-]lower sector? ",
  1443. X     spellp->cost);
  1444. X    wrefresh(w);
  1445. X  } else {
  1446. X    sprintf(s, "Costs %d; [+] or [-]? ", spellp->cost);
  1447. X    statline(s, "cast_spell");
  1448. X    move(LINES-1, strlen(s));
  1449. X  }
  1450. X  cost =  spellp->cost;
  1451. X  switch (getch()) {
  1452. X  case '+':
  1453. X    change = 1;
  1454. X    break;
  1455. X  case '-':
  1456. X    change = -1;
  1457. X    break;
  1458. X  default:
  1459. X    break;
  1460. X  }
  1461. X    /* only apply the spell if the new altitude is good */
  1462. X  if (sp->altitude+change > MOUNTAIN_PEAK ||  sp->altitude+change < TRENCH) {
  1463. X    return 0;
  1464. X  }
  1465. X    /* prepare the h_spell struct, and then insert the exec lines */
  1466. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1467. X  sprintf(h_spellp->lines[0], "CALTITUDE_SECTOR:%d:%d:%d\n",
  1468. X      sp->loc.x, sp->loc.y, change);
  1469. X  sprintf(h_spellp->lines[1], "CALTITUDE_SECTOR:%d:%d:%d\n",
  1470. X      sp->loc.x, sp->loc.y, -change);
  1471. X  return cost;
  1472. X}
  1473. X
  1474. Xint spell_fertility(up, w, spellp, h_spellp)
  1475. X     Suser *up;
  1476. X     WINDOW *w;
  1477. X     Sspell *spellp;
  1478. X     Sh_spell *h_spellp;
  1479. X{
  1480. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1481. X  int cost, change = 0;
  1482. X  char s[EXECLEN];
  1483. X
  1484. X  if (w) {
  1485. X    mvwprintw(w, 4, 1,
  1486. X     "Cost %d spell points.  Do you wish to [+]increase or [-]decrease soil? ",
  1487. X     spellp->cost);
  1488. X    wrefresh(w);
  1489. X  } else {
  1490. X    sprintf(s, "Costs %d; [+] or [-]? ", spellp->cost);
  1491. X    statline(s, "cast_spell");
  1492. X    move(LINES-1, strlen(s));
  1493. X  }
  1494. X  cost =  spellp->cost;
  1495. X  switch (getch()) {
  1496. X  case '+':
  1497. X    change = 1;
  1498. X    break;
  1499. X  case '-':
  1500. X    change = -1;
  1501. X    break;
  1502. X  default:
  1503. X    break;
  1504. X  }
  1505. X
  1506. X    /* prepare the h_spell struct, and then insert the exec lines */
  1507. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1508. X  sprintf(h_spellp->lines[0], "CSOIL_SECTOR:%d:%d:%d\n",
  1509. X      sp->loc.x, sp->loc.y, change);
  1510. X  sprintf(h_spellp->lines[1], "CSOIL_SECTOR:%d:%d:%d\n",
  1511. X      sp->loc.x, sp->loc.y, -change);
  1512. X  return cost;
  1513. X}
  1514. X
  1515. Xint spell_cmetal(up, w, spellp, h_spellp)
  1516. X     Suser *up;
  1517. X     WINDOW *w;
  1518. X     Sspell *spellp;
  1519. X     Sh_spell *h_spellp;
  1520. X{
  1521. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1522. X  int cost, change = 0;
  1523. X  char s[EXECLEN];
  1524. X
  1525. X  if (w) {
  1526. X    mvwprintw(w, 4, 1,
  1527. X    "Cost %d spell points.  Do you wish to [+]increase or [-]decrease metal? ",
  1528. X    spellp->cost);
  1529. X    wrefresh(w);
  1530. X  } else {
  1531. X    sprintf(s, "Costs %d; [+] or [-]? ", spellp->cost);
  1532. X    statline(s, "cast_spell");
  1533. X    move(LINES-1, strlen(s));
  1534. X  }
  1535. X  cost =  spellp->cost;
  1536. X  switch (getch()) {
  1537. X  case '+':
  1538. X    change = 1;
  1539. X    break;
  1540. X  case '-':
  1541. X    change = -1;
  1542. X    break;
  1543. X  default:
  1544. X    break;
  1545. X  }
  1546. X
  1547. X    /* prepare the h_spell struct, and then insert the exec lines */
  1548. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1549. X  sprintf(h_spellp->lines[0], "CMETAL_SECTOR:%d:%d:%d\n",
  1550. X      sp->loc.x, sp->loc.y, change);
  1551. X  sprintf(h_spellp->lines[1], "CMETAL_SECTOR:%d:%d:%d\n",
  1552. X      sp->loc.x, sp->loc.y, -change);
  1553. X  return cost;
  1554. X}
  1555. X
  1556. Xint spell_cjewels(up, w, spellp, h_spellp)
  1557. X     Suser *up;
  1558. X     WINDOW *w;
  1559. X     Sspell *spellp;
  1560. X     Sh_spell *h_spellp;
  1561. X{
  1562. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1563. X  int cost, change = 0;
  1564. X  char s[EXECLEN];
  1565. X
  1566. X
  1567. X  if (w) {
  1568. X    mvwprintw(w, 4, 1,
  1569. X   "Cost %d spell points.  Do you wish to [+]increase or [-]decrease jewels? ",
  1570. X   spellp->cost);
  1571. X    wrefresh(w);
  1572. X  } else {
  1573. X    sprintf(s, "Costs %d; [+] or [-]? ", spellp->cost);
  1574. X    statline(s, "cast_spell");
  1575. X    move(LINES-1, strlen(s));
  1576. X  }
  1577. X  cost =  spellp->cost;
  1578. X  switch (getch()) {
  1579. X  case '+':
  1580. X    change = 1;
  1581. X    break;
  1582. X  case '-':
  1583. X    change = -1;
  1584. X    break;
  1585. X  default:
  1586. X    break;
  1587. X  }
  1588. X
  1589. X    /* prepare the h_spell struct, and then insert the exec lines */
  1590. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1591. X  sprintf(h_spellp->lines[0], "CJEWELS_SECTOR:%d:%d:%d\n",
  1592. X      sp->loc.x, sp->loc.y, change);
  1593. X  sprintf(h_spellp->lines[1], "CJEWELS_SECTOR:%d:%d:%d\n",
  1594. X      sp->loc.x, sp->loc.y, -change);
  1595. X  return cost;
  1596. X}
  1597. X
  1598. X  /* this really messes up a sector */
  1599. Xint spell_fireburst(up, w, spellp, h_spellp)
  1600. X     Suser *up;
  1601. X     WINDOW *w;
  1602. X     Sspell *spellp;
  1603. X     Sh_spell *h_spellp;
  1604. X{
  1605. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1606. X  int cost = 0, change = 0;
  1607. X  char c;
  1608. X  char s[EXECLEN];
  1609. X
  1610. X  if (w) {
  1611. X    mvwprintw(w, 4, 1, "Cost %d spell points.  Go ahead? ", spellp->cost);
  1612. X    wclrtoeol(w);
  1613. X    wrefresh(w);
  1614. X  } else {
  1615. X    sprintf(s, "Costs %d; go ahead? ", spellp->cost);
  1616. X    statline_prompt(s, spellp->name);
  1617. X  }
  1618. X  if ((c = getch()) == 'y' || c == 'Y') {
  1619. X      /* prepare the h_spell struct, and then insert the exec lines */
  1620. X    cost =  spellp->cost;
  1621. X    prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 6);
  1622. X    sprintf(h_spellp->lines[0], "CSOIL_SECTOR:%d:%d:%d\n",
  1623. X        sp->loc.x, sp->loc.y, -sp->soil);
  1624. X    sprintf(h_spellp->lines[1], "CSOIL_SECTOR:%d:%d:%d\n",
  1625. X        sp->loc.x, sp->loc.y, sp->soil);
  1626. X    sprintf(h_spellp->lines[2], "DESIG_SECTOR:%d:%d:%d\n", sp->loc.x,
  1627. X        sp->loc.y, sp->designation == D_CAPITAL ? D_CAPITAL : D_NODESIG);
  1628. X    sprintf(h_spellp->lines[3], "DESIG_SECTOR:%d:%d:%d\n",
  1629. X        sp->loc.x, sp->loc.y, sp->designation);
  1630. X    sprintf(h_spellp->lines[4], "CPEOPLE_SECTOR:%d:%d:%d\n",
  1631. X        sp->loc.x, sp->loc.y, -sp->n_people/3);
  1632. X    sprintf(h_spellp->lines[5], "CPEOPLE_SECTOR:%d:%d:%d\n",
  1633. X        sp->loc.x, sp->loc.y, sp->n_people/3);
  1634. X    user.just_moved = 1;
  1635. X  }
  1636. X  return cost;
  1637. X}
  1638. X  /* makes a sector completely inaccessible */
  1639. Xint spell_inferno(up, w, spellp, h_spellp)
  1640. X     Suser *up;
  1641. X     WINDOW *w;
  1642. X     Sspell *spellp;
  1643. X     Sh_spell *h_spellp;
  1644. X{
  1645. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1646. X  int cost = 0, change = 0;
  1647. X  char c;
  1648. X  char s[EXECLEN];
  1649. X
  1650. X    /* you can only cast inferno on your own sectors */
  1651. X  if (sp->owner != up->id) {
  1652. X    return -1;
  1653. X  }
  1654. X  if (w) {
  1655. X    mvwprintw(w, 4, 1, "Cost %d spell points.  Go ahead? ", spellp->cost);
  1656. X    wclrtoeol(w);
  1657. X    wrefresh(w);
  1658. X  } else {
  1659. X    sprintf(s, "Costs %d; go ahead? ", spellp->cost);
  1660. X    statline_prompt(s, spellp->name);
  1661. X  }
  1662. X  if ((c = getch()) == 'y' || c == 'Y') {
  1663. X      /* prepare the h_spell struct, and then insert the exec lines */
  1664. X    cost =  spellp->cost;
  1665. X    prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 4);
  1666. X    sprintf(h_spellp->lines[2], "DESIG_SECTOR:%d:%d:%d\n", sp->loc.x,
  1667. X        sp->loc.y, sp->designation == D_CAPITAL ? D_CAPITAL : D_NODESIG);
  1668. X    sprintf(h_spellp->lines[3], "DESIG_SECTOR:%d:%d:%d\n", sp->loc.x,
  1669. X        sp->loc.y, sp->designation == D_CAPITAL ? D_CAPITAL : D_NODESIG);
  1670. X    sprintf(h_spellp->lines[0], "FLAG_SET_SECTOR:%d:%d:%d\n",
  1671. X        sp->loc.x, sp->loc.y, SF_IMPENETRABLE);
  1672. X    sprintf(h_spellp->lines[1], "FLAG_CLEAR_SECTOR:%d:%d:%d\n",
  1673. X      sp->loc.x, sp->loc.y, SF_IMPENETRABLE);
  1674. X      /* also:  kill all the people, once and permanently */
  1675. X    cpeople_sector(sp, -sp->n_people);
  1676. X    sp->n_people = 0;
  1677. X    user.just_moved = 1;
  1678. X  }
  1679. X  return cost;
  1680. X}
  1681. X
  1682. X  /* these spells set various army flags */
  1683. Xint spell_hide_army(up, w, spellp, h_spellp)
  1684. X     Suser *up;
  1685. X     WINDOW *w;
  1686. X     Sspell *spellp;
  1687. X     Sh_spell *h_spellp;
  1688. X{
  1689. X  int id, cost;            /* army id and cost of casting */
  1690. X  Sarmy *ap, *get_army();
  1691. X  char s[EXECLEN];
  1692. X
  1693. X  if (w) {
  1694. X    mvwprintw(w, 4, 1,
  1695. X      "Cost: %d spell pts./100 sold.  Which army do you want to hide? ",
  1696. X      spellp->cost);
  1697. X    wrefresh(w);
  1698. X  } else {
  1699. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1700. X    statline_prompt(s, "fly_army");
  1701. X  }
  1702. X  if ( (wget_number(w, &id) <= 0) ||
  1703. X       ((ap = get_army(up->np, id)) == NULL) ||
  1704. X       (ap->pos.x != up->cursor.x) || (ap->pos.y != up->cursor.y) ) {
  1705. X    return -1;
  1706. X  }
  1707. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1708. X  if (cost > up->np->spell_pts) {
  1709. X    return -1;
  1710. X  }
  1711. X  if (w) {
  1712. X    wmove(w, 4, 1);
  1713. X    wclrtoeol(w);
  1714. X  }
  1715. X    /* prepare the h_spell struct, and then insert the exec lines */
  1716. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1717. X  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1718. X      ap->id, AF_HIDDEN);
  1719. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1720. X      ap->id, AF_HIDDEN);
  1721. X  return cost;
  1722. X}
  1723. X
  1724. Xint spell_fly_army(up, w, spellp, h_spellp)
  1725. X     Suser *up;
  1726. X     WINDOW *w;
  1727. X     Sspell *spellp;
  1728. X     Sh_spell *h_spellp;
  1729. X{
  1730. X  int id, cost;            /* army id and cost of casting */
  1731. X  Sarmy *ap, *get_army();
  1732. X  char s[EXECLEN];
  1733. X
  1734. X  if (w) {
  1735. X    mvwprintw(w, 4, 1,
  1736. X        "Cost: %d spell pts./100 sold.  Which army do you want to fly? ",
  1737. X        spellp->cost);
  1738. X    wrefresh(w);
  1739. X  } else {
  1740. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1741. X    statline_prompt(s, "hide_army");
  1742. X  }
  1743. X  if ( (wget_number(w, &id) <= 0) ||
  1744. X       ((ap = get_army(up->np, id)) == NULL) ||
  1745. X       (ap->pos.x != up->cursor.x) || (ap->pos.y != up->cursor.y) ) {
  1746. X    return -1;
  1747. X  }
  1748. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1749. X  if (cost > up->np->spell_pts) {
  1750. X    return -1;
  1751. X  }
  1752. X  if (w) {
  1753. X    wmove(w, 4, 1);
  1754. X    wclrtoeol(w);
  1755. X  }
  1756. X    /* prepare the h_spell struct, and then insert the exec lines */
  1757. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1758. X  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1759. X      ap->id, AF_FLIGHT);
  1760. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1761. X      ap->id, AF_FLIGHT);
  1762. X  return cost;
  1763. X}
  1764. X
  1765. Xint spell_vampire_army(up, w, spellp, h_spellp)
  1766. X     Suser *up;
  1767. X     WINDOW *w;
  1768. X     Sspell *spellp;
  1769. X     Sh_spell *h_spellp;
  1770. X{
  1771. X  int id, cost;            /* army id and cost of casting */
  1772. X  Sarmy *ap, *get_army();
  1773. X  char s[EXECLEN];
  1774. X
  1775. X  if (w) {
  1776. X    mvwprintw(w, 4, 1,
  1777. X      "Cost: %d spell pts./100 sold.  Which army do you want to vampirize? ",
  1778. X       spellp->cost);
  1779. X    wrefresh(w);
  1780. X  } else {
  1781. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1782. X    statline_prompt(s, "vampire_army");
  1783. X  }
  1784. X  if ( (wget_number(w, &id) <= 0) ||
  1785. X       ((ap = get_army(up->np, id)) == NULL) ) {
  1786. X    return -1;
  1787. X  }
  1788. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1789. X  if (w) {
  1790. X    wmove(w, 4, 1);
  1791. X    wclrtoeol(w);
  1792. X  }
  1793. X    /* prepare the h_spell struct, and then insert the exec lines */
  1794. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1795. X  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1796. X      ap->id, AF_VAMPIRE);
  1797. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1798. X      ap->id, AF_VAMPIRE);
  1799. X  return cost;
  1800. X}
  1801. Xint spell_burrow_army(up, w, spellp, h_spellp)
  1802. X     Suser *up;
  1803. X     WINDOW *w;
  1804. X     Sspell *spellp;
  1805. X     Sh_spell *h_spellp;
  1806. X{
  1807. X  int id, cost;            /* army id and cost of casting */
  1808. X  Sarmy *ap, *get_army();
  1809. X  char s[EXECLEN];
  1810. X
  1811. X  if (w) {
  1812. X    mvwprintw(w, 4, 1,
  1813. X      "Cost: %d spell pts./100 sold.  Which army do you want to send underground? ",
  1814. X       spellp->cost);
  1815. X    wrefresh(w);
  1816. X  } else {
  1817. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1818. X    statline_prompt(s, "burrow_army");
  1819. X  }
  1820. X  if ( (wget_number(w, &id) <= 0) ||
  1821. X       ((ap = get_army(up->np, id)) == NULL) ) {
  1822. X    return -1;
  1823. X  }
  1824. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1825. X  if (w) {
  1826. X    wmove(w, 4, 1);
  1827. X    wclrtoeol(w);
  1828. X  }
  1829. X    /* prepare the h_spell struct, and then insert the exec lines */
  1830. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1831. X  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1832. X      ap->id, AF_UNDERGROUND);
  1833. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1834. X      ap->id, AF_UNDERGROUND);
  1835. X  return cost;
  1836. X}
  1837. X
  1838. Xint spell_water_walk(up, w, spellp, h_spellp)
  1839. X     Suser *up;
  1840. X     WINDOW *w;
  1841. X     Sspell *spellp;
  1842. X     Sh_spell *h_spellp;
  1843. X{
  1844. X  int id, cost;            /* army id and cost of casting */
  1845. X  Sarmy *ap, *get_army();
  1846. X  char s[EXECLEN];
  1847. X
  1848. X  if (w) {
  1849. X    mvwprintw(w, 4, 1,
  1850. X    "Cost: %d spell pts./100 sold.  Which army do you want to walk on water? ",
  1851. X       spellp->cost);
  1852. X    wrefresh(w);
  1853. X  } else {
  1854. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1855. X    statline_prompt(s, "walk_water");
  1856. X  }
  1857. X  if ( (wget_number(w, &id) <= 0) ||
  1858. X       ((ap = get_army(up->np, id)) == NULL) ||
  1859. X       (ap->pos.x != up->cursor.x) || (ap->pos.y != up->cursor.y) ) {
  1860. X    return -1;
  1861. X  }
  1862. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1863. X  if (cost > up->np->spell_pts) {
  1864. X    return -1;
  1865. X  }
  1866. X  if (w) {
  1867. X    wmove(w, 4, 1);
  1868. X    wclrtoeol(w);
  1869. X  }
  1870. X    /* prepare the h_spell struct, and then insert the exec lines */
  1871. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1872. X  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1873. X      ap->id, AF_WATER);
  1874. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1875. X      ap->id, AF_WATER);
  1876. X  return cost;
  1877. X}
  1878. X
  1879. Xint spell_haste_army(up, w, spellp, h_spellp)
  1880. X     Suser *up;
  1881. X     WINDOW *w;
  1882. X     Sspell *spellp;
  1883. X     Sh_spell *h_spellp;
  1884. X{
  1885. X  int id, cost;            /* army id and cost of casting */
  1886. X  Sarmy *ap, *get_army();
  1887. X  char s[EXECLEN];
  1888. X
  1889. X  if (w) {
  1890. X    mvwprintw(w, 4, 1,
  1891. X      "Cost: %d spell pts./100 sold.  Which army do you want to hasten? ",
  1892. X       spellp->cost);
  1893. X    wrefresh(w);
  1894. X  } else {
  1895. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1896. X    statline_prompt(s, "haste_army");
  1897. X  }
  1898. X  if ( (wget_number(w, &id) <= 0) ||
  1899. X       ((ap = get_army(up->np, id)) == NULL) ) {
  1900. X    return -1;
  1901. X  }
  1902. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1903. X  if (w) {
  1904. X    wmove(w, 4, 1);
  1905. X    wclrtoeol(w);
  1906. X  }
  1907. X    /* prepare the h_spell struct, and then insert the exec lines */
  1908. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 0);
  1909. X/*  sprintf(h_spellp->lines[0], "AFLAG_SET:%d:%d\n",
  1910. X      ap->id, AF_VAMPIRE);
  1911. X  sprintf(h_spellp->lines[1], "AFLAG_CLEAR:%d:%d\n",
  1912. X      ap->id, AF_VAMPIRE);
  1913. X*/
  1914. X  ap->mvpts += HASTE_POINTS;    /* increase movement */
  1915. X    /* make the exec line for this move point change; we
  1916. X       implement it as a trivial movement with change in move points.
  1917. X     */
  1918. X  sprintf(s, "AMOVE:%d:%d:%d:%d\n",
  1919. X      ap->id, ap->pos.x, ap->pos.y, ap->mvpts);
  1920. X  gen_exec(s);
  1921. X  return cost;
  1922. X}
  1923. X
  1924. Xint spell_mag_bonus(up, w, spellp, h_spellp)
  1925. X     Suser *up;
  1926. X     WINDOW *w;
  1927. X     Sspell *spellp;
  1928. X     Sh_spell *h_spellp;
  1929. X{
  1930. X  int id, cost;            /* army id and cost of casting */
  1931. X  Sarmy *ap, *get_army();
  1932. X  char s[EXECLEN];
  1933. X
  1934. X  if (w) {
  1935. X    mvwprintw(w, 4, 1,
  1936. X       "Cost: %d spell pts./100 sold.  Which army do you want to enhance? ",
  1937. X       spellp->cost);
  1938. X    wrefresh(w);
  1939. X  } else {
  1940. X    sprintf(s, "Cost %d pts/100 men; which army? ", spellp->cost);
  1941. X    statline_prompt(s, "mag_bonus");
  1942. X  }
  1943. X  if ( (wget_number(w, &id) <= 0) ||
  1944. X       ((ap = get_army(up->np, id)) == NULL) ||
  1945. X       (ap->pos.x != up->cursor.x) || (ap->pos.y != up->cursor.y) ) {
  1946. X    return -1;
  1947. X  }
  1948. X  cost = (spellp->cost * ap->n_soldiers + 99)/100;
  1949. X  if (cost > up->np->spell_pts) {
  1950. X    return -1;
  1951. X  }
  1952. X  if (w) {
  1953. X    wmove(w, 4, 1);
  1954. X    wclrtoeol(w);
  1955. X  }
  1956. X    /* prepare the h_spell struct, and then insert the exec lines */
  1957. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  1958. X  sprintf(h_spellp->lines[0], "CABONUS:%d:%d\n", ap->id, 30);
  1959. X  sprintf(h_spellp->lines[1], "CABONUS:%d:%d\n", ap->id, -30);
  1960. X  return cost;
  1961. X}
  1962. X
  1963. X  /* this is a Unity spell which merges people into
  1964. X     an existing spirit.  you can only make the spirit
  1965. X     as big as twice its basic size.  the people
  1966. X     are taken from the current sector.  this is permanent,
  1967. X     it is not a hanging spell.  In fact, it is more of
  1968. X     an ability than a spell.
  1969. X   */
  1970. Xint spell_merge(up, w, spellp, h_spellp)
  1971. X     Suser *up;
  1972. X     WINDOW *w;
  1973. X     Sspell *spellp;
  1974. X     Sh_spell *h_spellp;
  1975. X{
  1976. X  int id, cost, ind;        /* army id, cost of casting and spirit index */
  1977. X  extern struct spirit_type *spirit_types;
  1978. X  Sarmy *ap, *get_army();
  1979. X  char s[EXECLEN];
  1980. X  int n_merged = 0;        /* number of people merged */
  1981. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  1982. X
  1983. X  if (w) {
  1984. X    mvwprintw(w, 4, 1,
  1985. X       "Cost: %d spell pts./100 sold.  Which spirit do you want to enhance? ",
  1986. X       spellp->cost);
  1987. X    wrefresh(w);
  1988. X  } else {
  1989. X    sprintf(s, "Cost %d pts/100 men; which spirit? ", spellp->cost);
  1990. X    statline_prompt(s, "merge");
  1991. X  }
  1992. X  if ( (wget_number(w, &id) <= 0)
  1993. X      || ((ap = get_army(up->np, id)) == NULL)
  1994. X      || (ap->pos.x != up->cursor.x) || (ap->pos.y != up->cursor.y)
  1995. X      || !is_spirit(ap) ) {
  1996. X    return -1;
  1997. X  }
  1998. X  if (has_hostile(sp) || sp->owner != user.id) {
  1999. X    statline2_err ("hit space", "cannot merge on a hostile sector");
  2000. X    return -1;
  2001. X  }
  2002. X  if (is_spelled(ap)) {
  2003. X    statline2_err ("hit space", "cannot merge on a spelled army");
  2004. X    return -1;
  2005. X  }
  2006. X  ind = spirit_type_index(ap->type);
  2007. X  if (w) {
  2008. X    mvwprintw(w, 4, 1,
  2009. X          "How many men do you want to merge (or subtract) (max %d)? ",
  2010. X          2*spirit_types[ind].size - ap->n_soldiers);
  2011. X    wclrtoeol(w);
  2012. X    wrefresh(w);
  2013. X  } else {
  2014. X    sprintf(s, "Merge how many (max %d)? ",
  2015. X        2*spirit_types[ind].size - ap->n_soldiers);
  2016. X    statline_prompt(s, "merge");
  2017. X  }
  2018. X    /* make sure that the spirit will not become too big or too small */
  2019. X  if ( (wget_number(w, &n_merged) <= 0)
  2020. X      || (n_merged > 0 && n_merged > 2*spirit_types[ind].size - ap->n_soldiers)
  2021. X      || n_merged < -ap->n_soldiers+1 || n_merged > sp->n_people) {
  2022. X    return -1;
  2023. X  }
  2024. X  cost = (spellp->cost * ap->n_soldiers + 99)/100; /* rounding up */
  2025. X  if (cost > 0 && cost > up->np->spell_pts) {
  2026. X    return -1;
  2027. X  }
  2028. X  if (w) {
  2029. X    wmove(w, 4, 1);
  2030. X    wclrtoeol(w);
  2031. X  }
  2032. X    /* this is not a hanging spell.  we just do the work once. */
  2033. X  ap->n_soldiers += n_merged;
  2034. X  ap->mvpts = 0;
  2035. X  ap->mvratio = 0;
  2036. X  sprintf(s, "AINCREASE:%d:%d\n", ap->id, n_merged);
  2037. X  gen_exec(s);
  2038. X  sp->n_people -= n_merged;
  2039. X  cpeople_sector(sp, -n_merged);
  2040. X  user.just_moved = 1;
  2041. X  return -1;
  2042. X}
  2043. X
  2044. X  /* hide a sector from view */
  2045. Xint spell_hide_sector(up, w, spellp, h_spellp)
  2046. X     Suser *up;
  2047. X     WINDOW *w;
  2048. X     Sspell *spellp;
  2049. X     Sh_spell *h_spellp;
  2050. X{
  2051. X  Ssector *sp = &world.map[up->cursor.x][up->cursor.y];
  2052. X  int cost;
  2053. X  char s[EXECLEN];
  2054. X
  2055. X  if (w) {
  2056. X    mvwprintw(w, 4, 1,
  2057. X    "Cost %d spell points.  Go ahead (y/n)? ",
  2058. X    spellp->cost);
  2059. X    wrefresh(w);
  2060. X  } else {
  2061. X    sprintf(s, "Costs %d; go ahead (y/n)? ", spellp->cost);
  2062. X    statline_prompt(s, "hide_sector");
  2063. X  }
  2064. X  cost =  spellp->cost;
  2065. X  switch (getch()) {
  2066. X  case 'y':
  2067. X  case 'Y':
  2068. X    break;
  2069. X  default:
  2070. X    return -1;
  2071. X  }
  2072. X
  2073. X  /* prepare the h_spell struct, and then insert the exec lines */
  2074. X  prepare_h_spell(h_spellp, spellp->name, up->id, spellp->duration, 2);
  2075. X  sprintf(h_spellp->lines[0], "FLAG_SET_SECTOR:%d:%d:%d\n",
  2076. X      sp->loc.x, sp->loc.y, SF_HIDDEN);
  2077. X  sprintf(h_spellp->lines[1], "FLAG_CLEAR_SECTOR:%d:%d:%d\n",
  2078. X      sp->loc.x, sp->loc.y, SF_HIDDEN);
  2079. X  user.just_moved = 1;
  2080. X  return cost;
  2081. X}
  2082. X
  2083. X  /* these are used to set and clear army flags (in the exec file) */
  2084. Xaflag_set(ap, flag)
  2085. X     Sarmy *ap;
  2086. X     int flag;
  2087. X{
  2088. X  char s[EXECLEN];
  2089. X
  2090. X  sprintf(s, "AFLAG_SET:%d:%d\n", ap->id, flag);
  2091. X  gen_exec(s);
  2092. X}
  2093. X
  2094. Xaflag_clear(ap, flag)
  2095. X     Sarmy *ap;
  2096. X     int flag;
  2097. X{
  2098. X  char s[EXECLEN];
  2099. X
  2100. X  sprintf(s, "AFLAG_CLEAR:%d:%d\n", ap->id, flag);
  2101. X  gen_exec(s);
  2102. X}
  2103. X
  2104. X/* For chess; transfers the spirit to the nations capital  */
  2105. Xspell_castle (up, w, spellp, h_spellp)
  2106. X     Suser * up;
  2107. X     WINDOW * w;
  2108. X     Sspell * spellp;
  2109. X     Sh_spell * h_spellp;
  2110. X{
  2111. X  Ssector * sp; 
  2112. X  Ssector * capital = &world.map [up->np->capital.x][up->np->capital.y];
  2113. X  Ssector * cur = &world.map [up->cursor.x][up->cursor.y];
  2114. X  Sarmy * ap;
  2115. X  char s [EXECLEN];
  2116. X  int army_num;
  2117. X
  2118. X  if (w) {
  2119. X    mvwprintw (w, 4, 1,
  2120. X           "Costs %d spell points.  Go ahead (y/n)? ", spellp->cost);
  2121. X    wrefresh (w);
  2122. X  } else {
  2123. X    sprintf (s, "Costs %d; go ahead (y/n)? ", spellp->cost);
  2124. X    statline (s, "castle");
  2125. X  }
  2126. X    
  2127. X  switch (getch ()) {
  2128. X  case 'y':
  2129. X  case 'Y':
  2130. X    break;
  2131. X  default:
  2132. X    return -1;
  2133. X  }
  2134. X
  2135. X  sprintf (s, "Castle army #");
  2136. X  if (w) {
  2137. X    wmove (w, 4,1);
  2138. X    wclrtoeol (w);
  2139. X    box (w, '|', '-');
  2140. X    mvwprintw (w, 4, 1, s);
  2141. X  }
  2142. X  else {
  2143. X    statline (s, "castle");
  2144. X    move (LINES-1, strlen (s));
  2145. X    refresh ();
  2146. X  }
  2147. X  if (wget_number (w, &army_num) <= 0) {
  2148. X    return -1;
  2149. X  }
  2150. X  if ((ap = get_army (up->np, army_num)) == NULL) {
  2151. X    return -1;
  2152. X  }
  2153. X      
  2154. X  if (ap->pos.x != up->cursor.x || ap->pos.y != up->cursor.y) {
  2155. X    statline2_err ("Hit space", "Must be on the same sector as army");
  2156. X    return 0;
  2157. X  }
  2158. X
  2159. X  sp = &world.map[ap->pos.x][ap->pos.y];
  2160. X
  2161. X  delete_army_sector (sp, ap);
  2162. X
  2163. X  ap->pos.x = capital->loc.x;
  2164. X  ap->pos.y = capital->loc.y;
  2165. X  
  2166. X  insert_army_sector (capital, ap);
  2167. X
  2168. X  sprintf (s, "ACASTLE:%d\n", ap->id);
  2169. X  gen_exec (s);
  2170. X
  2171. X  cspell_pts (up->np, spellp->cost);
  2172. X  up->np->spell_pts -= spellp->cost;
  2173. X  return -1;
  2174. X}
  2175. X
  2176. Xint spell_sacrifice(up, w, spellp, h_spellp)
  2177. X     Suser * up;
  2178. X     WINDOW * w;
  2179. X     Sspell * spellp;
  2180. X     Sh_spell * h_spellp;
  2181. X{
  2182. X  char s [EXECLEN];
  2183. X  Ssector * sp = &world.map [up->cursor.x][up->cursor.y];
  2184. X  int num;
  2185. X
  2186. X  sprintf (s, "Sacrifice how many people (%d people per sp. point)? ",
  2187. X       SACRIFICED_FRACT);
  2188. X
  2189. X  statline_prompt(s, "sacrifice");
  2190. X  if (wget_number(stdscr, &num) <= 0) {
  2191. X    return 0;
  2192. X  }
  2193. X  if (sp->owner != up->np->id) {
  2194. X    statline2_err ("hit space", "sorry, must sacrifice your own people");
  2195. X    return 0;
  2196. X  } else if (has_hostile (sp)) {
  2197. X    statline2_err ("hit space", "sorry, must sacrifice friendly people");
  2198. X    return 0;
  2199. X  } else if (sp->n_people < num) {
  2200. X    statline2_err ("hit space", "too many!");
  2201. X    return 0;
  2202. X  } else if (num < 0) {
  2203. X    statline2_err ("hit space", "nice try");
  2204. X    return 0;
  2205. X  }
  2206. X
  2207. X  cpeople_sector (sp, -num);
  2208. X  cspell_pts (up->np, (int)(num / SACRIFICED_FRACT));
  2209. X  sp->n_people -= num;
  2210. X  up->np->spell_pts += (int) (num / SACRIFICED_FRACT);
  2211. X  up->just_moved = 1;
  2212. X
  2213. X  return 0;
  2214. X}
  2215. END_OF_FILE
  2216. if test 24702 -ne `wc -c <'spells.c'`; then
  2217.     echo shar: \"'spells.c'\" unpacked with wrong size!
  2218. fi
  2219. # end of 'spells.c'
  2220. fi
  2221. echo shar: End of archive 20 \(of 28\).
  2222. cp /dev/null ark20isdone
  2223. MISSING=""
  2224. 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
  2225.     if test ! -f ark${I}isdone ; then
  2226.     MISSING="${MISSING} ${I}"
  2227.     fi
  2228. done
  2229. if test "${MISSING}" = "" ; then
  2230.     echo You have unpacked all 28 archives.
  2231.     echo "Now execute ./do_cat.sh to build doc files"
  2232.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2233. else
  2234.     echo You still need to unpack the following archives:
  2235.     echo "        " ${MISSING}
  2236. fi
  2237. ##  End of shell archive.
  2238. exit 0
  2239.