home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / spiele / FreeCiv / src / freeciv-1.7.0 / server / unittools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  17.3 KB  |  542 lines

  1. /********************************************************************** 
  2.  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2, or (at your option)
  6.    any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12. ***********************************************************************/
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #include <player.h>
  18. #include <unithand.h>
  19. #include <packets.h>
  20. #include <civserver.h>
  21. #include <map.h>
  22. #include <maphand.h>
  23. #include <cityhand.h>
  24. #include <citytools.h>
  25. #include <cityturn.h>
  26. #include <unit.h>
  27. #include <plrhand.h>
  28. #include <city.h>
  29. #include <log.h>
  30. #include <mapgen.h>
  31. #include <events.h>
  32. #include <shared.h>
  33. #include <aiunit.h>
  34. #include <unittools.h>
  35. #include <unitfunc.h>
  36.  
  37. /**************************************************************************
  38.   unit can be moved if:
  39.   1) the unit is idle or on goto
  40.   2) the target location is on the map
  41.   3) the target location is next to the unit
  42.   4) ground unit can only move to ocean squares if there is a transporter
  43.      with free capacity
  44.   5) marines are the only units that can attack from a ocean square
  45.   6) naval units can only be moved to ocean squares or city squares
  46.   7) if there is no enemy units blocking (zoc)
  47. **************************************************************************/
  48. int can_unit_move_to_tile(struct unit *punit, int x, int y)
  49. {
  50.   struct tile *ptile,*ptile2;
  51.   int zoc;
  52.  
  53.   if(punit->activity!=ACTIVITY_IDLE && punit->activity!=ACTIVITY_GOTO)
  54.     return 0;
  55.   
  56.   if(x<0 || x>=map.xsize || y<0 || y>=map.ysize)
  57.     return 0;
  58.   
  59.   if(!is_tiles_adjacent(punit->x, punit->y, x, y))
  60.     return 0;
  61.  
  62.   if(is_enemy_unit_tile(x,y,punit->owner))
  63.     return 0;
  64.  
  65.   ptile=map_get_tile(x, y);
  66.   ptile2=map_get_tile(punit->x, punit->y);
  67.   if(is_ground_unit(punit)) {
  68.     /* Check condition 4 */
  69.     if(ptile->terrain==T_OCEAN &&
  70.        !is_transporter_with_free_space(&game.players[punit->owner], x, y))
  71.     return 0;
  72.  
  73.     /* Moving from ocean */
  74.     if(ptile2->terrain==T_OCEAN) {
  75.       /* Can't attack a city from ocean unless marines */
  76.       if(!unit_flag(punit->type, F_MARINES) && is_enemy_city_tile(x,y,punit->owner)) {
  77.         notify_player_ex(&game.players[punit->owner], punit->x, punit->y, E_NOEVENT, "Game: Only Marines can attack from sea.");
  78.     return 0;
  79.       }
  80.     }
  81.   } else if(is_sailing_unit(punit)) {
  82.     if(ptile->terrain!=T_OCEAN && ptile->terrain!=T_UNKNOWN)
  83.       if(!is_friendly_city_tile(x,y,punit->owner))
  84.     return 0;
  85.   } 
  86.   zoc = zoc_ok_move(punit, x, y);
  87.   if (!zoc) 
  88.     notify_player_ex(&game.players[punit->owner], punit->x, punit->y, E_NOEVENT,
  89.     "Game: %s can only move into your own zone of control.", unit_types[punit->type].name);
  90.   return zoc;
  91. }
  92.  
  93. /**************************************************************************
  94.  is there an enemy city on this tile?
  95. **************************************************************************/
  96. int is_enemy_city_tile(int x, int y, int owner)
  97. {
  98.     struct city *pcity;
  99.  
  100.     pcity=map_get_city(x,y);
  101.  
  102.     if(pcity==NULL) return 0;
  103.  
  104.     return(pcity->owner != owner);
  105. }
  106.  
  107. /**************************************************************************
  108.  is there an enemy unit on this tile?
  109. **************************************************************************/
  110. int is_enemy_unit_tile(int x, int y, int owner)
  111. {
  112.     struct unit_list *punit_list;
  113.     struct unit *punit;
  114.  
  115.     punit_list=&map_get_tile(x, y)->units;
  116.     punit = unit_list_get(punit_list, 0);
  117.  
  118.     if(!punit) return 0;
  119.     return(punit->owner != owner);
  120. }
  121.  
  122. /**************************************************************************
  123.  is there an friendly unit on this tile?
  124. **************************************************************************/
  125. int is_friendly_unit_tile(int x, int y, int owner)
  126. {
  127.     struct unit_list *punit_list;
  128.     struct unit *punit;
  129.  
  130.     punit_list=&map_get_tile(x, y)->units;
  131.     punit = unit_list_get(punit_list, 0);
  132.  
  133.     if(!punit) return 0;
  134.     return(punit->owner == owner);
  135. }
  136.  
  137. /**************************************************************************
  138.  is there an friendly city on this tile?
  139. **************************************************************************/
  140. int is_friendly_city_tile(int x, int y, int owner)
  141. {
  142.     struct city *pcity;
  143.  
  144.     pcity=map_get_city(x,y);
  145.  
  146.     if(pcity==NULL) return 0;
  147.  
  148.     return(pcity->owner == owner);
  149. }
  150.  
  151. /**************************************************************************
  152.   is this square controlled by the units owner
  153. **************************************************************************/
  154. int is_my_zoc(struct unit *myunit, int x0, int y0)
  155. {
  156.   int x,y;
  157.   int ax,ay;
  158.   int owner=myunit->owner;
  159.  
  160.   for (x=x0-1;x<x0+2;x++) for (y=y0-1;y<y0+2;y++) {
  161.     ax=map_adjust_x(x); ay=map_adjust_y(y);
  162.     if (is_enemy_city_tile(ax,ay,owner))
  163.       return 0;
  164.     if (is_enemy_unit_tile(ax,ay,owner))
  165.       if((is_sailing_unit(myunit) && (map_get_terrain(ax,ay)==T_OCEAN)) ||
  166.      (!is_sailing_unit(myunit) && (map_get_terrain(ax,ay)!=T_OCEAN)) )
  167.         return 0;
  168.   }
  169.   return 1;
  170. }
  171.  
  172. /**************************************************************************
  173.   return whether or not the square the unit wants to enter is blocked by
  174.   enemy units? 
  175.   You CAN move if:
  176.   1. You have units there already
  177.   2. Your unit isn't a ground unit
  178.   3. Your unit ignores ZOC (diplomat, freight, etc.)
  179.   4. You're moving from or to a city
  180.   5. The spot you're moving from or to is in your ZOC
  181. **************************************************************************/
  182. int zoc_ok_move(struct unit *punit,int x, int y)
  183. {
  184.   struct unit_list *punit_list;
  185.  
  186.   punit_list=&map_get_tile(x, y)->units;
  187.   /* if you have units there, you can move */
  188.   if (is_friendly_unit_tile(x,y,punit->owner))
  189.     return 1;
  190.   if (!is_ground_unit(punit) || unit_flag(punit->type, F_IGZOC))
  191.     return 1;
  192.   if (map_get_city(x,y) || map_get_city(punit->x, punit->y))
  193.     return 1;
  194.   return(is_my_zoc(punit, punit->x, punit->y) || 
  195.          is_my_zoc(punit, x, y)); 
  196. }
  197.  
  198. /**************************************************************************
  199.  calculate how expensive it is to bribe the unit
  200.  depends on distance to the capital, and government form
  201.  settlers are half price
  202. **************************************************************************/
  203. int unit_bribe_cost(struct unit *punit)
  204. {  
  205.   int cost;
  206.   struct city *capital;
  207.   int dist;
  208.  
  209.   cost = (&game.players[punit->owner])->economic.gold+750;
  210.   capital=find_palace(&game.players[punit->owner]);
  211.   if (capital)
  212.     dist=min(32, map_distance(capital->x, capital->y, punit->x, punit->y)); 
  213.   else
  214.     dist=32;
  215.     if (get_government(punit->owner)==G_COMMUNISM)
  216.       dist = min(10, dist);
  217.   cost=(cost/(dist+2))*(get_unit_type(punit->type)->build_cost/10);
  218.   if (unit_flag(punit->type, F_SETTLERS)) 
  219.     cost/=2;
  220.   return cost;
  221. }
  222.  
  223. /**************************************************************************
  224.  return whether or not there is a diplomat on this square
  225. **************************************************************************/
  226. int diplomat_on_tile(int x, int y)
  227. {
  228.   unit_list_iterate(map_get_tile(x, y)->units, punit)
  229.     if (unit_flag(punit->type, F_DIPLOMAT))
  230.       return 1;
  231.   unit_list_iterate_end;
  232.   return 0;
  233. }
  234.  
  235. /**************************************************************************
  236.   returns how many hp's a unit will gain on this square
  237.   depends on whether or not it's inside city or fortress.
  238.   barracks will regen landunits completely
  239.   airports will regen airunits  completely
  240.   ports    will regen navalunits completely
  241.   fortify will add a little extra.
  242. ***************************************************************************/
  243. int hp_gain_coord(struct unit *punit)
  244. {
  245.   int hp;
  246.   struct city *pcity;
  247.   if (unit_on_fortress(punit))
  248.     hp=get_unit_type(punit->type)->hp/4;
  249.   else
  250.     hp=0;
  251.   if((pcity=map_get_city(punit->x,punit->y))) {
  252.     if ((city_got_barracks(pcity) && is_ground_unit(punit)) ||
  253.     (city_got_building(pcity, B_AIRPORT) && is_air_unit(punit)) || 
  254.     (city_got_building(pcity, B_AIRPORT) && is_heli_unit(punit)) || 
  255.     (city_got_building(pcity, B_PORT) && is_sailing_unit(punit))) {
  256.       hp=get_unit_type(punit->type)->hp;
  257.     }
  258.     else
  259.       hp=get_unit_type(punit->type)->hp/3;
  260.   }
  261.   else if (is_heli_unit(punit))
  262.     hp-=(get_unit_type(punit->type)->hp/10);
  263.   else
  264.     hp++;
  265.  
  266.   if(punit->activity==ACTIVITY_FORTIFY)
  267.     hp++;
  268.   
  269.   return hp;
  270. }
  271.  
  272. /**************************************************************************
  273.   this is a crude function!!!! 
  274.   used to find the best defensive unit on a square
  275. **************************************************************************/
  276. int rate_unit(struct unit *punit, struct unit *against)
  277. {
  278.   int val;
  279.  
  280.   if(!punit) return 0;
  281.   val = get_total_defense_power(against,punit);
  282.  
  283. /*  return val*100+punit->hp;       This is unnecessarily crude. -- Syela */
  284.   val *= punit->hp;
  285.   val *= val;
  286.   val /= get_unit_type(punit->type)->build_cost;
  287.   return val; /* designed to minimize expected losses */
  288. }
  289.  
  290. /**************************************************************************
  291. get best defending unit which is NOT owned by pplayer
  292. **************************************************************************/
  293. struct unit *get_defender(struct player *pplayer, struct unit *aunit, 
  294.               int x, int y)
  295. {
  296.   struct unit *bestdef = 0;
  297.   int bestvalue=-1;
  298.   unit_list_iterate(map_get_tile(x, y)->units, punit) {
  299.     if (pplayer->player_no==punit->owner)
  300.       return 0;
  301.     if(unit_can_defend_here(punit) && rate_unit(punit, aunit)>bestvalue) {
  302.       bestvalue=rate_unit(punit, aunit);
  303.       bestdef=punit;
  304.     }
  305.   }
  306.   unit_list_iterate_end;
  307.   return bestdef;
  308. }
  309.  
  310. /**************************************************************************
  311.  returns the attack power, modified by moves left, and veteran status.
  312. **************************************************************************/
  313. int get_attack_power(struct unit *punit)
  314. {
  315.   int power;
  316.   power=get_unit_type(punit->type)->attack_strength*10;
  317.   if (punit->veteran)
  318.     power*=1.5;
  319.   if (punit->moves_left==1)
  320.     return power/3;
  321.   if (punit->moves_left==2)
  322.     return (power*2)/3;
  323.   return power;
  324. }
  325.  
  326. /**************************************************************************
  327.   returns the defense power, modified by terrain and veteran status
  328. **************************************************************************/
  329. int get_defense_power(struct unit *punit)
  330. {
  331.   int power;
  332.   int terra;
  333.   if (!punit || punit->type<0 || punit->type>=U_LAST)
  334.     abort();
  335.   power=get_unit_type(punit->type)->defense_strength*10;
  336.   if (punit->veteran)
  337.     power*=1.5;
  338.   
  339.   terra=map_get_terrain(punit->x, punit->y);
  340.   power=(power*get_tile_type(terra)->defense_bonus)/10;
  341.   return power;
  342. }
  343.  
  344. /**************************************************************************
  345.   a wrapper that returns whether or not a unit ignores citywalls
  346. **************************************************************************/
  347. int unit_ignores_citywalls(struct unit *punit)
  348. {
  349.   return (unit_flag(punit->type, F_IGWALL));
  350. }
  351.  
  352. /**************************************************************************
  353.  a wrapper function that returns whether or not the unit is on a citysquare
  354.  with citywalls
  355. **************************************************************************/
  356. int unit_behind_walls(struct unit *punit)
  357. {
  358.   struct city *pcity;
  359.   
  360.   if((pcity=map_get_city(punit->x, punit->y)))
  361.     return city_got_citywalls(pcity);
  362.   
  363.   return 0;
  364. }
  365.  
  366. /**************************************************************************
  367.  a wrapper function returns 1 if the unit is on a square with fortress
  368. **************************************************************************/
  369. int unit_on_fortress(struct unit *punit)
  370. {
  371.   return (map_get_special(punit->x, punit->y)&S_FORTRESS);
  372. }
  373.  
  374. /**************************************************************************
  375.  a wrapper function returns 1 if the unit is on a square with coastal defense
  376. **************************************************************************/
  377. int unit_behind_coastal(struct unit *punit)
  378. {
  379.   struct city *pcity;
  380.   if((pcity=map_get_city(punit->x, punit->y)))
  381.     return city_got_building(pcity, B_COASTAL);
  382.   return 0;
  383. }
  384.  
  385. /**************************************************************************
  386.  a wrapper function returns 1 if the unit is on a square with sam site
  387. **************************************************************************/
  388. int unit_behind_sam(struct unit *punit)
  389. {
  390.   struct city *pcity;
  391.   if((pcity=map_get_city(punit->x, punit->y)))
  392.     return city_got_building(pcity, B_SAM);
  393.   return 0;
  394. }
  395.  
  396. /**************************************************************************
  397.  a wrapper function returns 1 if the unit is on a square with sdi defense
  398. **************************************************************************/
  399. int unit_behind_sdi(struct unit *punit)
  400. {
  401.   struct city *pcity;
  402.   if((pcity=map_get_city(punit->x, punit->y)))
  403.     return city_got_building(pcity, B_SDI);
  404.   return 0;
  405. }
  406.  
  407. /**************************************************************************
  408.   a wrapper function returns 1 if there is a sdi-defense close to the square
  409. **************************************************************************/
  410. struct city *sdi_defense_close(int owner, int x, int y)
  411. {
  412.   struct city *pcity;
  413.   int lx, ly;
  414.   for (lx=x-2;lx<x+3;lx++)
  415.     for (ly=y-2;ly<y+3;ly++) {
  416.       pcity=map_get_city(lx,ly);
  417.       if (pcity && (pcity->owner!=owner) && city_got_building(pcity, B_SDI))
  418.     return pcity;
  419.     }
  420.   return NULL;
  421. }
  422.  
  423. /**************************************************************************
  424.   returns a unit type for the goodie huts
  425. **************************************************************************/
  426. int find_a_unit_type()
  427.  {
  428.   int num;
  429.   
  430.   num = 2;
  431.   if (game.global_advances[A_CHIVALRY])
  432.     num = 3;
  433.   if (game.global_advances[A_GUNPOWDER]) 
  434.     num = 4;
  435.  
  436.   switch (myrand(num)) {
  437.   case 0:
  438.     return U_HORSEMEN;
  439.   case 1:
  440.     return U_LEGION;
  441.   case 2:
  442.     return U_CHARIOT;
  443.   case 3:
  444.     return U_KNIGHTS;
  445.   case 4:
  446.     return U_MUSKETEERS;
  447.   default:
  448.     return U_HORSEMEN;
  449.   }
  450. }
  451.  
  452. /**************************************************************************
  453.   unit can't attack if :
  454.  1) it don't have any attack power
  455.  2) it's not a fighter and the defender is a flying unit
  456.  3) if it's not a marine (and ground unit) and it attacks from ocean
  457.  4) a ground unit can't attack a ship on an ocean square
  458. **************************************************************************/
  459. int can_unit_attack_unit_at_tile(struct unit *punit, struct unit *pdefender, int dest_x, int dest_y)
  460. {
  461.   int fromtile=map_get_terrain(punit->x, punit->y);
  462.   int totile=map_get_terrain(dest_x, dest_y);
  463.  
  464.   if(!is_military_unit(punit))
  465.     return 0;
  466.  
  467.   /*only fighters can attack planes, except for city attacks */
  468.   if (!unit_flag(punit->type, F_FIGHTER) && is_air_unit(pdefender) && !map_get_city(dest_x, dest_y)) {
  469.     return 0;
  470.   }
  471.   /* can't attack with ground unit from ocean */
  472.   if(fromtile==T_OCEAN && is_ground_unit(punit) && !unit_flag(punit->type, F_MARINES)) {
  473.     return 0;
  474.   }
  475.  
  476.   if(totile==T_OCEAN && is_ground_unit(punit)) {
  477.     return 0;
  478.   }
  479.  
  480.   if (unit_flag(punit->type, F_SUBMARINE) && totile!=T_OCEAN)  {
  481.     return 0;
  482.   }
  483.   
  484.   /* Shore bombardement */
  485.   if (fromtile==T_OCEAN && is_sailing_unit(punit) && totile!=T_OCEAN)
  486.     return (get_attack_power(punit)>0);
  487.   return 1;
  488. }
  489.  
  490.  
  491. int can_unit_attack_tile(struct unit *punit, int dest_x, int dest_y)
  492. {
  493.   struct unit *pdefender;
  494.   pdefender=get_defender(&game.players[punit->owner], punit, dest_x, dest_y);
  495.   return(can_unit_attack_unit_at_tile(punit, pdefender, dest_x, dest_y));
  496. }
  497.  
  498. /**************************************************************************
  499.   calculate the remaining build points 
  500. **************************************************************************/
  501. int build_points_left(struct city *pcity)
  502. {
  503.  return (improvement_value(pcity->currently_building) - pcity->shield_stock);
  504. }
  505.  
  506. /**************************************************************************
  507.   return if it's possible to place a partisan on this square 
  508.   possible if:
  509.   1) square isn't a city square
  510.   2) there is no units on this square
  511.   3) it's not an ocean square 
  512. **************************************************************************/
  513. int can_place_partisan(int x, int y) 
  514. {
  515.   struct tile *ptile;
  516.   ptile = map_get_tile(x, y);
  517.   return (!map_get_city(x, y) && !unit_list_size(&ptile->units) && map_get_terrain(x,y) != T_OCEAN && map_get_terrain(x, y) < T_UNKNOWN); 
  518. }
  519.  
  520. int enemies_at(struct unit *punit, int x, int y)
  521. {
  522.   int i, j, a = 0, d;
  523.   struct player *pplayer = get_player(punit->owner);
  524.   d = unit_vulnerability_virtual(punit) *
  525.       get_tile_type(map_get_terrain(x, y))->defense_bonus;
  526.   for (j = y - 1; j <= y + 1; j++) {
  527.     if (j < 0 || j >= map.ysize) continue;
  528.     for (i = x - 1; i <= x + 1; i++) {
  529.       if (!pplayer->ai.control && !map_get_known(x, y, pplayer)) continue;
  530.       if (is_enemy_city_tile(i, j, punit->owner)) return 1;
  531.       unit_list_iterate(map_get_tile(i, j)->units, enemy)
  532.         if (enemy->owner != punit->owner &&
  533.             can_unit_attack_unit_at_tile(enemy, punit, x, y)) {
  534.           a += unit_belligerence_basic(enemy);
  535.           if ((a * a * 10) >= d) return 1;
  536.         }
  537.       unit_list_iterate_end;
  538.     }
  539.   }
  540.   return 0; /* as good a quick'n'dirty should be -- Syela */
  541. }
  542.