home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume13 / dominion / part26 / world.c < prev   
C/C++ Source or Header  |  1992-02-11  |  11KB  |  467 lines

  1. /* world.c -- function dealing with the world; its use and implementation */
  2.  
  3. /*
  4. * Copyright (C) 1990 Free Software Foundation, Inc.
  5. * Written by the dominion project.
  6. *
  7. * This file is part of dominion.
  8. *
  9. * dominion is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as published
  11. * by the Free Software Foundation; either version 1, or (at your option)
  12. * any later version.
  13. *
  14. * This software is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this software; see the file COPYING.  If not, write to
  21. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23.  
  24. /* wrap(pp) - wraps a point to its proper location                        */
  25. /* latitude(x,y) - returns the latitude of a particular point             */
  26. /* map_alt(altitude) - maps the altitude value to the correct data entry  */
  27. /* xrel(x,y) - gives the relative x coordinate from nation's capital      */
  28. /* yrel(x,y) - gives the relative y coordinate from nation's capital      */
  29. /* xdist(x,y,x1,y1) - gives the x distance between (x,y) and (x1,y1)      */
  30. /* ydist(x,y,x1,y1) - gives the y distance between (x,y) and (x1,y1)      */
  31. /* sect_desire(np,x,y) - gives the desireability value of x,y for nation  */
  32. /* is_coastal_sect(np,sp,ap) - is this coast (for given nation and army)? */
  33. /* is_active_ntn(np) - returns 1 if the nation has not been destroyed     */
  34. /* are_patrols(np, moving_ap, sp) - returns true if moving_ap gets slowed */
  35.  
  36. #include "dominion.h"
  37. #include "misc.h"
  38. #include "army.h"
  39.  
  40. #include <stdio.h>
  41. #include <math.h>
  42.  
  43. extern Sworld world;
  44. extern Suser user;
  45. extern struct s_altitude_map altitude_map[];
  46. extern struct s_desig_map desig_map[];
  47. extern int (*wrapx)(), (*wrapy)();
  48.  
  49. /* Wrapping functions are the heart and soul of the world's shape */
  50. /* these main functions, wrapx and wrapy, choose the proper function for */
  51. /* the proper shape of the world in question. */
  52.  
  53. /* This function wraps the entire point */
  54.  
  55. wrap(pp)
  56. Pt *pp;
  57. {
  58. pp->x = (*wrapx)(pp->x,pp->y);
  59. pp->y = (*wrapy)(pp->x,pp->y);
  60. }
  61.  
  62. /* Wrap functions for a TORUS world */
  63.  
  64. torus_wrapx(x,y)  /* produce new value of x, if x is too big or negative */
  65. int x,y;
  66. {
  67. if (x >= world.xmax) {
  68. return x % world.xmax;
  69. }
  70. while (x < 0) {
  71. x += world.xmax;
  72. }
  73. return x;
  74. }
  75.  
  76. torus_wrapy(x,y)  /* produce new value of y, if y is too big or negative*/
  77. int x,y;
  78. {
  79. if (y >= world.ymax) {
  80. return y % world.ymax;
  81. }
  82. while (y < 0) {
  83. y += world.ymax;
  84. }
  85. return y;
  86. }
  87.  
  88. /* Wrap function for a pinched cylinder world */
  89.  
  90. pinch_wrapx(x,y)
  91. int x,y;
  92. {
  93. return pinch_wrapxy(x,y,1);
  94. }
  95.  
  96. pinch_wrapy(x,y)
  97. int x,y;
  98. {
  99. return pinch_wrapxy(x,y,2);
  100. }
  101.  
  102. pinch_wrapxy(x,y,which) /* if which=1 then return x */
  103. int x,y,which;
  104. {
  105. while (y < 0) {
  106. y = -(y + 1);
  107. x = x + (world.xmax / 2);
  108. }
  109. while (y >= world.ymax) {
  110. y = 2 * world.ymax - (y + 1);
  111. x = x + (world.xmax / 2);
  112. }
  113. while (x < 0) {
  114. x = x + world.xmax;
  115. }
  116. if (x >= world.xmax) {
  117. x = x % world.xmax;
  118. }
  119. if (which == 1) {
  120. return x;
  121. } else {
  122. return y;
  123. }
  124. }
  125.  
  126. /* A latitude function for the world which returns a float angle of the */
  127. /* latitude of the y-coordinate given.  Equator is 0 degrees and the poles */
  128. /* are 90 degrees (north pole) and negative 90 degrees (south pole) */
  129.  
  130. latitude(x,y)
  131. int x,y;
  132. {
  133. float angle;
  134. switch(world.geo.topology) {
  135. case TORUS:
  136. angle = torus_latitude(y); break;
  137. }
  138. return angle;
  139. }
  140.  
  141. /* Returns the latitude of a y-coordinate for a pinched cylinder. */
  142.  
  143. pinch_latitude(y)
  144. int y;
  145. {
  146. float eq_dist, angle;
  147. eq_dist = y - (world.ymax / 2.0);
  148. if (eq_dist < 0) {
  149. eq_dist = eq_dist + 1.0;
  150. }
  151. angle = 90.0 * (eq_dist / (world.ymax / 2.0));
  152. return -(angle);
  153. }
  154.  
  155. /* Returns the latitude of a y-coordinate for a torus */
  156.  
  157. torus_latitude(y)
  158. int y;
  159. {
  160. float eq_dist, angle;
  161. eq_dist = y - (world.ymax / 2.0);
  162. angle = 90.0 * (eq_dist / (world.ymax / 2.0));
  163. return angle;
  164. }
  165.  
  166. int map_alt(altitude)
  167. int altitude;
  168. {
  169. altitude -= altitude_map[0].value;
  170. return altitude;
  171. }
  172.  
  173. /* These functions give the coordinates of a sector relative to the user's */
  174. /* capital.  They differ depending on which type of world you use! */
  175. int xrel(x, y, cap)
  176. int x, y;
  177. Pt cap;
  178. {
  179. x=xdist(x, y, cap.x, cap.y);
  180. /*  if (x < 0) {
  181. return(x + world.xmax);
  182. } */
  183. return(x);
  184. }
  185.  
  186. int yrel(x, y, cap)
  187. int x,y;
  188. Pt cap;
  189. {
  190. y = ydist(x, y, cap.x, cap.y);
  191. /*  if (y < 0) {
  192. return(y + world.ymax);
  193. } */
  194. return(y);
  195. }
  196.  
  197. /* Functions to return the how far (x,y) is from (x1,y1) */
  198. int xdist(x,y,x1,y1)
  199. int x,y,x1,y1;
  200. {
  201. switch (world.geo.topology) {
  202. case TORUS:
  203. x = x - x1;
  204. if (x <= (0 - world.xmax / 2)) {
  205. x += world.xmax;
  206. }
  207. if (x > world.xmax / 2) {
  208. x = x - world.xmax;
  209. }
  210. return x;
  211. break;    
  212. }
  213. }
  214.  
  215. int ydist(x,y,x1,y1)
  216. int x,y,x1,y1;
  217. {
  218. switch (world.geo.topology) {
  219. case TORUS:
  220. y = y - y1;
  221. if (y <= (0 - world.ymax / 2)) {
  222. y += world.ymax;
  223. }
  224. if (y > world.ymax / 2) {
  225. y = y - world.ymax;
  226. }
  227. return y;
  228. break;
  229. }
  230. }
  231.  
  232. pinched_dist(x,y,x1,y1,choice)
  233. int x,y,x1,y1,choice;
  234. {
  235. int dx,dy,dx2,dy2;
  236. float r1,r2;
  237. dx = x - x1;
  238. dy = y - y1;
  239. if (dx > world.xmax / 2) {
  240. dx = dx - world.xmax;
  241. }
  242. if (dx <= (0 - world.xmax / 2)) {
  243. dx = dx + world.xmax;
  244. }
  245.  
  246. dy2 = y + y1 + 1;
  247. if (dy2 > world.ymax) {
  248. dy2 = world.ymax * 2 - dy2;
  249. } else {
  250. dy2 = -(dy2);
  251. }
  252. dx2 = x - x1 + world.xmax / 2;
  253. if (dx2 >= world.xmax / 2) {
  254. dx2 = dx2 - world.xmax;
  255. }
  256.  
  257. r1 = sqrt(dx*dx + dy*dy);
  258. r2 = sqrt(dx2*dx2 + dy2*dy2);
  259. if (r1 <= r2) {
  260. if (choice == 1) {
  261. return dx;
  262. } else {
  263. return dy;
  264. }
  265. } else {
  266. if (choice == 1) {
  267. return dx2;
  268. } else {
  269. return dy2;
  270. }
  271. }
  272. }
  273.  
  274. /* Old Sector Desire
  275. int sect_desire(np, x, y)
  276. Snation *np;
  277. int x, y;
  278. {
  279. int terrain_d,climate_d,altitude_d,total_d;
  280.  
  281. terrain_d = abs(world.map[x][y].terrain - np->race.pref_terrain);
  282. climate_d = abs(world.map[x][y].climate - np->race.pref_climate);
  283. altitude_d = abs(world.map[x][y].altitude - np->race.pref_alt);
  284. total_d  = max(0,300-(terrain_d*terrain_d)*10);
  285. total_d += max(0,50-climate_d*3);
  286. total_d += max(0,300-(altitude_d*altitude_d)*8);
  287. total_d += world.map[x][y].metal*5;
  288. total_d += world.map[x][y].soil*4;
  289. total_d += world.map[x][y].jewels*6;
  290. if (world.map[x][y].designation == D_CITY || world.map[x][y].designation == D_CAPITAL) {
  291. total_d *= 3;
  292. }
  293. return total_d;
  294. }
  295. */
  296.  
  297. int sect_desire(np, x, y)
  298. Snation *np;
  299. int x, y;
  300. {
  301.   int terrain_d,climate_d,altitude_d,total_d;
  302.  
  303.   terrain_d = abs(world.map[x][y].terrain - np->race.pref_terrain);
  304.   climate_d = abs(world.map[x][y].climate - np->race.pref_climate);
  305.   altitude_d = abs(world.map[x][y].altitude - np->race.pref_alt);
  306.  
  307.   total_d  = max(0,230-(terrain_d*terrain_d)*10);
  308.   total_d += max(0,250-(climate_d*climate_d)*10);
  309.   total_d += max(0,250-(altitude_d*altitude_d)*20);
  310.   if (user.id == world.map[x][y].owner)
  311.   {
  312.     switch (world.map[x][y].designation)
  313.     {
  314.       case D_FARM: total_d += world.map[x][y].soil * 9; break;
  315.       case D_METAL_MINE: total_d += world.map[x][y].metal * 11; break;
  316.       case D_JEWEL_MINE: total_d += world.map[x][y].jewels * 13; break;
  317.       default:
  318.       { 
  319.         total_d += 37;
  320.         total_d += world.map[x][y].soil;
  321.         total_d += world.map[x][y].metal;
  322.         total_d += world.map[x][y].jewels;
  323.       }
  324.     }
  325.   } else
  326.   {
  327.     total_d += world.map[x][y].soil * 7;
  328.     total_d += world.map[x][y].metal * 9;
  329.     total_d += world.map[x][y].jewels * 11;
  330.   }
  331.   return total_d;
  332. }
  333.  
  334. /* this function returns true if there is a non-treaty army
  335.    in patrol/intercept mode in the neighbourhood of the given sector.
  336.    if none is found, it returns 0.  If the "moving_ap" is NULL,
  337.    then you ignore the issue of whether moving_ap is in flight.
  338.  */
  339. are_patrols(np, moving_ap, sp)
  340.      Snation *np;
  341.      Sarmy *moving_ap;
  342.      Ssector *sp;
  343. {
  344.   int found = 0, done = 0, x, y;
  345.   Sarmy *ap, *get_army();
  346.   struct armyid *alist;
  347.  
  348.   if (moving_ap && is_underground(moving_ap)) {
  349.     return 0;            /* underground armies can't be intercepted */
  350.   }
  351.     /* here we check if there are patrol or intercept units around */
  352.   for (x = sp->loc.x - 1; ((x <= sp->loc.x + 1) && (done == 0)); x++) {
  353.     for (y = sp->loc.y - 1; ((y <= sp->loc.y + 1) && (done == 0)); y++) {
  354.       done = 0;
  355.       if (np->npc_flag
  356.           || user.visible_sectors[(*wrapx)(x,y)][(*wrapy)(x,y)] & SEE_ARMIES) {
  357.     alist = world.map[(*wrapx)(x,y)][(*wrapy)(x,y)].alist;
  358.     while (alist != NULL) {
  359.       if (alist->owner == sp->owner) {
  360.         ap = get_army(&world.nations[alist->owner],alist->id);
  361.         if ( (ap->status == A_PATROL || ap->status == A_INTERCEPT) &&
  362.             /* OK, we got an army on intercept or patrol.
  363.            now check the issue of flight.
  364.          */
  365.         (!(moving_ap && is_flight(moving_ap)) || is_missiles(ap))
  366.         /* make sure that we only slow down armies that are
  367.            not our own.  In the future, this should
  368.            also let TREATY armies pass...
  369.          */
  370.         && (moving_ap && (ap->owner != moving_ap->owner))
  371.         && (get_diplo_status(user.diplo_matrix,
  372.                     ap->owner, moving_ap->owner != TREATY))) {
  373.           alist = NULL;
  374.           found = 1;
  375.           done = 1;
  376.         } else {
  377.           alist = alist->next;
  378.         }
  379.       } else {
  380.         alist = alist->next;
  381.       }
  382.     }
  383.       }
  384.     }
  385.   }
  386.   return found;
  387. }
  388.  
  389. init_wrap() 
  390. {
  391.   int torus_wrapx(), torus_wrapy();
  392.   switch(world.geo.topology) {
  393.   case TORUS:
  394.     wrapx = torus_wrapx;
  395.     wrapy = torus_wrapy;
  396.     break;
  397.   default:
  398.     printf("What world is this???\n");
  399.     wrapx = torus_wrapx;
  400.     wrapy = torus_wrapy;
  401.     break;
  402.   }
  403. }
  404.  
  405.   /* returns 1 if this is a coastal sector (for that race and army),
  406.      0 otherwise.  Note that this only applies if the army has the
  407.      L or W flag, since other armies don't get any benefit from
  408.      coastal sectors:  they should drown anyway.
  409.    */
  410. is_coastal_sect(np, sp, ap)
  411.      Snation *np;        /* nation that wants to go there */
  412.      Ssector *sp;
  413.      Sarmy *ap;
  414. {
  415.   int land, i, j, x, y;
  416.  
  417.   if (is_land(ap) && is_water(ap)) {
  418.     return 0;            /* amphibious don't have a coastline */
  419.   }
  420.   if (is_land(ap)) {
  421.     land = 1;
  422.   } else if (is_water(ap)) {
  423.     land = 0;
  424.   } else {            /* coast only applies to L and W flags */
  425.     return 0;
  426.   }
  427.     /* case: we are land army in water; look for land nearby! */
  428.   if (land && sp->altitude < SEA_LEVEL) {
  429.     for (i = sp->loc.x-1; i <= sp->loc.x+1; ++i) {
  430.       for (j = sp->loc.y-1; j <= sp->loc.y+1; ++j) {
  431.     x = wrapx(i, j);
  432.     y = wrapy(i, j);
  433.     if (world.map[x][y].altitude >= SEA_LEVEL) {
  434.       return 1;
  435.     }
  436.       }
  437.     }
  438.     return 0;            /* no shore nearby */
  439.   }
  440.     /* case: we are water army on land; look for water nearby! */
  441.   if (!land && sp->altitude >= SEA_LEVEL) {
  442.     for (i = sp->loc.x-1; i <= sp->loc.x+1; ++i) {
  443.       for (j = sp->loc.y-1; j <= sp->loc.y+1; ++j) {
  444.     x = wrapx(i, j);
  445.     y = wrapy(i, j);
  446.     if (world.map[x][y].altitude < SEA_LEVEL) {
  447.       return 1;
  448.     }
  449.       }
  450.     }
  451.     return 0;            /* no shor nearby */
  452.   }
  453. }
  454.  
  455.   /* tells you if a nation has not been destroyed */
  456. is_active_ntn(np)
  457.      Snation *np;
  458. {
  459.   if (np->id == 0) {
  460.     return 1;
  461.   }
  462.   if (!(np->capital.x == -1 && np->capital.y == -1)) {
  463.     return 1;
  464.   }
  465.   return 0;
  466. }
  467.