home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / spiele / FreeCiv / src / freeciv-1.7.0 / server / unitfunc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  45.8 KB  |  1,265 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 <unittools.h>
  20. #include <unitfunc.h>
  21. #include <packets.h>
  22. #include <civserver.h>
  23. #include <map.h>
  24. #include <maphand.h>
  25. #include <cityhand.h>
  26. #include <citytools.h>
  27. #include <cityturn.h>
  28. #include <unit.h>
  29. #include <plrhand.h>
  30. #include <city.h>
  31. #include <log.h>
  32. #include <mapgen.h>
  33. #include <events.h>
  34. #include <shared.h>
  35. #include <aiunit.h>
  36. #include <sys/time.h>
  37. #include <gotohand.h>
  38. #include <settlers.h>
  39. #include <aiunit.h>
  40.  
  41. extern struct move_cost_map warmap;
  42.  
  43. /******************************************************************************
  44.  A spy (but not a diplomat) can poison a cities water supply.  There is 
  45.  no protection from this other than a defending spy/diplomat.
  46.  
  47.  For now, this wipes the foodstock and one worker.  However, a 
  48.  city of size one will not be destroyed - only the foodstock
  49.  will be effected.
  50.  
  51.  - Kris Bubendorfer
  52. ****************************************************************************/
  53.  
  54.  
  55. void spy_poison(struct player *pplayer, struct unit *pdiplomat, struct city *pcity){
  56.   
  57.   struct player *cplayer = city_owner(pcity);
  58.   
  59.   fprintf(stderr,"in spy_poison");
  60.  
  61.   if(pdiplomat->type == U_SPY){
  62.     if(!diplomat_infiltrate_city(pplayer, cplayer, pdiplomat, pcity))
  63.       return;  /* failed against defending diplomats/spies */
  64.     
  65.      /* Kill off a worker (population unit) */
  66.  
  67.     if (pcity->size >1) {
  68.       pcity->size--;
  69.       city_auto_remove_worker(pcity);
  70.     } 
  71.     
  72.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  73.              "Game: Your spy poisoned the water supply of %s.", pcity->name);
  74.     
  75.     notify_player_ex(cplayer, pcity->x, pcity->y, E_NOEVENT,
  76.              "Game: %s is suspected of poisoning the water supply of %s.",pplayer->name, pcity->name);
  77.     
  78.     diplomat_leave_city(pplayer, pdiplomat, pcity);
  79.     city_refresh(pcity);  
  80.     send_city_info(0, pcity, 0);
  81.  
  82.   }
  83. }
  84.  
  85. /******************************************************************************
  86.   bribe an enemy unit
  87.   rules:
  88.   1) can't bribe a unit if owner runs a democracy
  89.   2) if player don't have enough money
  90.   3) can't bribe a unit unless it's the only unit on the square. 
  91.      (this is handled outside this function)
  92.   if these conditions are fulfilled, the unit will be bribed
  93. ****************************************************************************/
  94. void diplomat_bribe(struct player *pplayer, struct unit *pdiplomat, struct unit *pvictim)
  95. {
  96.   if(pplayer->economic.gold>=pvictim->bribe_cost) {
  97.     if(game.players[pvictim->owner].government==G_DEMOCRACY)
  98.       notify_player_ex(pplayer, pdiplomat->x, pdiplomat->y, E_NOEVENT, 
  99.     "Game: You can't bribe a unit from a democratic nation.");
  100.     else {
  101.       pplayer->economic.gold-=pvictim->bribe_cost;
  102.       notify_player_ex(&game.players[pvictim->owner], 
  103.             pvictim->x, pvictim->y, E_DIPLOMATED, 
  104.             "Game: One of your units was bribed!");
  105.       notify_player_ex(pplayer, pvictim->x, pvictim->y, E_NOEVENT, 
  106.             "Game: Succeeded in bribing the enemy unit.");
  107.       
  108.       create_unit(pplayer, pvictim->x, pvictim->y,
  109.           pvictim->type, pvictim->veteran, pdiplomat->homecity,
  110.           pvictim->moves_left);
  111.       light_square(pplayer, pvictim->x, pvictim->y,
  112.                    get_unit_type(pvictim->type)->vision_range);
  113.       wipe_unit(0, pvictim);
  114.       pdiplomat->moves_left=0;
  115.       send_unit_info(pplayer, pdiplomat, 0);
  116.       send_player_info(pplayer, pplayer);
  117.     }
  118.   }
  119. }
  120.  
  121. /****************************************************************************
  122.   diplomat try to steal a tech from an enemy city
  123.   rules:
  124.   1) if there is a spy in the city the attempt will fail.
  125.   2) if there has already been stolen from this city the attempt will fail
  126.  
  127.   That is, you can only steal tech from a city once!  Ever.
  128.  
  129. ****************************************************************************/
  130. void diplomat_get_tech(struct player *pplayer, struct unit *pdiplomat, 
  131.                struct city  *pcity)
  132. {
  133.   int tec;
  134.   int i;
  135.   int j=0;
  136.   struct player *target=&game.players[pcity->owner];
  137.   struct player *cplayer = city_owner(pcity);
  138.  
  139.   if (pplayer==target)
  140.     return;
  141.   
  142.   /* Check if the Diplomat/Spy succeeds against defending Diplomats or Spies */
  143.   /* - Kris Bubendorfer <Kris.Bubendorfer@MCS.VUW.AC.NZ>                     */
  144.  
  145.   if(!diplomat_infiltrate_city(pplayer, cplayer, pdiplomat, pcity))
  146.     return;  /* failed against defending diplomats/spies */
  147.   
  148.   for (i=1;i<A_LAST;i++) {
  149.     if (get_invention(pplayer, i)!=TECH_KNOWN && get_invention(target, i)== TECH_KNOWN) {
  150.       j++;
  151.     }
  152.   }
  153.   if (!j)
  154.     if (target->future_tech > pplayer->future_tech) {
  155.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  156.                       "Game: Your diplomat stole Future Tech. %d from %s",
  157.                       ++(pplayer->future_tech), target->name);
  158.       notify_player_ex(target, pcity->x, pcity->y, E_DIPLOMATED,
  159.                       "Game: %s diplomat stole Future Tech. %d in %s.", 
  160.                       pplayer->name, pplayer->future_tech, pcity->name);
  161.       return;
  162.     } else {
  163.  
  164.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  165.                "Game: No new technology found in %s", pcity->name);
  166.       return;
  167.     }
  168.  
  169.   if (pcity->steal) {
  170.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  171.                "Game: Your diplomat was caught in the attempt of stealing technology in %s.", pcity->name);
  172.     notify_player_ex(target, pcity->x, pcity->y, E_DIPLOMATED,
  173.              "Game: %s diplomat failed in stealing technology in %s", pplayer->name, pcity->name);
  174.     wipe_unit(0,pdiplomat);
  175.     return;
  176.   }
  177.  
  178.   j=myrand(j)+1;
  179.   for (i=1;i<A_LAST;i++) {
  180.     if (get_invention(pplayer, i)!=TECH_KNOWN && 
  181.     get_invention(target, i)== TECH_KNOWN) 
  182.       j--;
  183.     if (!j) break;
  184.   }
  185.   if (i==A_LAST) {
  186.     printf("Bug in diplomat_a_tech\n");
  187.     return;
  188.   }
  189.   pcity->steal=1;
  190.   notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  191.            "Game: Your diplomat stole %s from %s",
  192.            advances[i].name, target->name); 
  193.   notify_player_ex(target, pcity->x, pcity->y, E_DIPLOMATED,
  194.            "Game: %s diplomat stole %s in %s.", 
  195.            pplayer->name, advances[i].name, pcity->name); 
  196.   if (i==A_RAILROAD) {
  197. /*    struct city_list cl=pplayer->cities;*/
  198.     struct genlist_iterator myiter;
  199.     genlist_iterator_init(&myiter, &pplayer->cities.list, 0);
  200.     notify_player(pplayer, "Game: The people are pleased to hear that your scientists finally know about railroads.\n      Workers spontaneously gather and upgrade all cities with railroads.", pcity->name);
  201.     for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) {
  202.       struct city *pcity1=(struct city *)ITERATOR_PTR(myiter);
  203.       map_set_special(pcity1->x, pcity1->y, S_RAILROAD);
  204.       send_tile_info(0, pcity1->x, pcity1->y, TILE_KNOWN);
  205.     }
  206.   }
  207.   set_invention(pplayer, i, TECH_KNOWN);
  208.   update_research(pplayer);
  209.   do_conquer_cost(pplayer);
  210.   pplayer->research.researchpoints++;
  211.   if (pplayer->research.researching==i) {
  212.     tec=pplayer->research.researched;
  213.     if (!choose_goal_tech(pplayer))
  214.       choose_random_tech(pplayer);
  215.     pplayer->research.researched=tec;
  216.   }
  217.  
  218.   /* Check if a spy survives her mission                 */
  219.   /* - Kris Bubendorfer <Kris.Bubendorfer@MCS.VUW.AC.NZ> */
  220.   
  221.   diplomat_leave_city(pplayer, pdiplomat, pcity);
  222. }
  223.  
  224.  
  225. /**************************************************************************
  226. diplomat_infiltrate_city
  227.  
  228. This code determines if a subverting diplomat/spy succeeds in infiltrating
  229. the city, that is - if there are defending diplomats/spies they have a 
  230. n-1/n chance of defeating the infiltrator.
  231. **************************************************************************/
  232.  
  233. int diplomat_infiltrate_city(struct player *pplayer, struct player *cplayer, struct unit *pdiplomat, struct city *pcity)
  234. {
  235.   /* For EVERY diplomat/spy on a square, there is a 1/N chance of succeeding.
  236.    * This needs to be changed to take into account veteran status.
  237.    */
  238.   unit_list_iterate(map_get_tile(pcity->x, pcity->y)->units, punit)
  239.     if (unit_flag(punit->type, F_DIPLOMAT))
  240.       if (myrand(game.diplchance)) {
  241.     
  242.     /* Attacking Spy/Diplomat dies (N-1:N) */
  243.     
  244.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  245.              "Game: Your spy has been eliminated by a defending spy in %s.", pcity->name);
  246.     notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED,
  247.              "Game: A%s spy has been eliminated while attempting to subvert %s.", n_if_vowel(get_race_name(cplayer->race)[0]), pcity->name);
  248.     wipe_unit(0, pdiplomat);
  249.     return 0;
  250.       } else {
  251.     
  252.     /* Defending Spy/Diplomat dies (1:N) */
  253.     
  254.     notify_player_ex(cplayer, pcity->x, pcity->y, E_NOEVENT, 
  255.              "Game: Your spy has been eliminated defending against a spy in %s.", pcity->name);
  256.     wipe_unit(0, punit);
  257.       }
  258.   
  259.   unit_list_iterate_end; 
  260.   return 1;
  261. }
  262.  
  263. /**************************************************************************
  264. diplomat_leave_city
  265.  
  266. This code determines if a subverting diplomat/spy survives infiltrating a 
  267. city.  A diplomats always dies, a spy has a 1/game.diplchance
  268. **************************************************************************/
  269.  
  270. void diplomat_leave_city(struct player *pplayer, struct unit *pdiplomat,
  271.              struct city *pcity)
  272. {
  273.   if (pdiplomat->type == U_SPY) {
  274.     if (myrand(game.diplchance)) {
  275.       
  276.       /* Attacking Spy/Diplomat dies (N-1:N) chance */
  277.       
  278.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  279.              "Game: Your spy was captured after completing her mission in %s.", pcity->name);
  280.     } else {
  281.  
  282.       /* Survived (1:N) chance */
  283.       
  284.       struct city *spyhome = find_city_by_id(pdiplomat->homecity);
  285.  
  286.       if(!spyhome){
  287.     printf("Bug in diplomat_leave_city\n");
  288.     return;
  289.       }
  290.       
  291.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  292.                "Game: Your spy has successfully completed her mission and returned unharmed to  %s.", spyhome->name);
  293.       
  294.       create_unit(pplayer, spyhome->x, spyhome->y,
  295.           pdiplomat->type, 1, spyhome->id, 0);
  296.     }
  297.   }
  298.   wipe_unit(0, pdiplomat);
  299. }
  300.  
  301. /**************************************************************************
  302.  Inciting a revolution will fail if
  303.  1) the attacked player is running a democracy
  304.  2) the attacker don't have enough credits
  305.  3) 1/n probabilty of elminating a defending spy 
  306. **************************************************************************/
  307. void diplomat_incite(struct player *pplayer, struct unit *pdiplomat, struct city *pcity)
  308. {
  309.   struct player *cplayer;
  310.   struct city *pnewcity, *pc2;
  311.   int i;
  312.  
  313.   if (!pcity)
  314.     return;
  315.  
  316.   cplayer=city_owner(pcity);
  317.   if (cplayer==pplayer || cplayer==NULL) 
  318.     return;
  319.   if(game.players[cplayer->player_no].government==G_DEMOCRACY) {
  320.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  321.                "Game: You can't subvert a city from a democratic nation.");
  322.       return;
  323.   }
  324.   if (pplayer->economic.gold<pcity->incite_revolt_cost) { 
  325.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  326.              "Game: You don't have enough credits to subvert %s.", pcity->name);
  327.     
  328.     return;
  329.   }
  330.   if (diplomat_on_tile(pcity->x, pcity->y)) {
  331.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  332.              "Game: Your spy has been eliminated by a defending spy in %s.", pcity->name);
  333.     notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED,
  334.              "Game: A%s spy has been eliminated in %s..", n_if_vowel(get_race_name(cplayer->race)[0]), pcity->name);
  335.     wipe_unit(0, pdiplomat);
  336.     return;
  337.   }
  338.  
  339.   /* Check if the Diplomat/Spy succeeds against defending Diplomats or Spies */
  340.  
  341.   if (!diplomat_infiltrate_city(pplayer, cplayer, pdiplomat, pcity))
  342.     return;  /* failed against defending diplomats/spies */
  343.  
  344.   pplayer->economic.gold-=pcity->incite_revolt_cost;
  345.   if (pcity->size >1) {
  346.     pcity->size--;
  347.     city_auto_remove_worker(pcity);
  348.   }
  349.   notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  350.            "Game: Revolt incited in %s, you now rule the city!", 
  351.            pcity->name);
  352.   notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED, 
  353.            "Game: %s has revolted, %s influence suspected", pcity->name, get_race_name(pplayer->race));
  354.   pnewcity=(struct city *)malloc(sizeof(struct city));
  355.   *pnewcity=*pcity;
  356.  
  357.   for (i=0;i<4;i++) {
  358.     pc2=find_city_by_id(pnewcity->trade[i]);
  359.     if (can_establish_trade_route(pnewcity, pc2))    
  360.       establish_trade_route(pnewcity, pc2);
  361.   }
  362.  
  363.   pnewcity->id=get_next_id_number();
  364.   add_city_to_cache(pnewcity);
  365.   for (i = 0; i < B_LAST; i++) {
  366.     if (is_wonder(i) && city_got_building(pnewcity, i))
  367.       game.global_wonders[i] = pnewcity->id;
  368.   }
  369.   pnewcity->owner=pplayer->player_no;
  370.   unit_list_init(&pnewcity->units_supported);
  371.   city_list_insert(&pplayer->cities, pnewcity);
  372.  
  373.   /* Transfer units supported by this city to the new owner */
  374.  
  375.   transfer_city_units(pplayer, cplayer, pnewcity, pcity);
  376.  
  377.   /* Transfer wonders to new owner */
  378.  
  379.   for(i = B_APOLLO;i <= B_WOMENS; i++)
  380.     if(game.global_wonders[i] == pcity->id)
  381.       game.global_wonders[i] = pnewcity->id;
  382.  
  383.   remove_city(pcity);
  384.  
  385.   /* buying a city should result in getting new tech from the victim too */
  386.   /* but not money!                                                      */
  387.  
  388.   get_a_tech(pplayer, cplayer);
  389.    
  390.   map_set_city(pnewcity->x, pnewcity->y, pnewcity);
  391.   if ((get_invention(pplayer,A_RAILROAD)==TECH_KNOWN) &&
  392.       (get_invention(cplayer, A_RAILROAD)!=TECH_KNOWN) &&
  393.       (!(map_get_special(pnewcity->x, pnewcity->y)&S_RAILROAD))) {
  394.     notify_player(pplayer, "Game: The people in %s are stunned by your technological insight!\n      Workers spontaneously gather and upgrade the city with railroads.",pnewcity->name);
  395.     map_set_special(pnewcity->x, pnewcity->y, S_RAILROAD);
  396.     send_tile_info(0, pnewcity->x, pnewcity->y, TILE_KNOWN);
  397.   }
  398.  
  399.   pnewcity->shield_stock=0;
  400.   city_check_workers(pplayer,pnewcity);
  401.   city_refresh(pnewcity);
  402.   initialize_infrastructure_cache(pnewcity);
  403.   send_city_info(0, pnewcity, 0);
  404.   send_player_info(pplayer, pplayer);
  405.  
  406.   /* Check if a spy survives her mission */
  407.   diplomat_leave_city(pplayer, pdiplomat, pnewcity);
  408. }  
  409.  
  410. /**************************************************************************
  411. Sabotage of enemy building, build order will fail if:
  412.  1) there is a defending spy in the city.
  413.  2) there is a chance it'll fail if the sabotage is a building
  414.  The sabotage will be 50/50 between wiping the current production or
  415.  an existing building.
  416.  NOTE: Wonders and palace can't be sabotaged
  417. **************************************************************************/
  418. void diplomat_sabotage(struct player *pplayer, struct unit *pdiplomat, struct city *pcity)
  419. {
  420.   struct player *cplayer;
  421.   char *prod;
  422.   if (!pcity)
  423.     return;
  424.   cplayer=city_owner(pcity);
  425.   if (cplayer==pplayer ||cplayer==NULL) return;
  426.  
  427.   /* Check if the Diplomat/Spy succeeds against defending Diplomats or Spies */
  428.  
  429.   if (!diplomat_infiltrate_city(pplayer, cplayer, pdiplomat, pcity))
  430.     return;  /* failed against defending diplomats/spies */
  431.  
  432.   switch (myrand(2)) {
  433.   case 0:
  434.     pcity->shield_stock=0;
  435.     if (pcity->is_building_unit) 
  436.       prod=unit_name(pcity->currently_building);
  437.     else
  438.       prod=get_improvement_name(pcity->currently_building);
  439.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  440.     "Game: Your Diplomat succeeded destroying the production of %s in %s", 
  441.     prod, pcity->name);
  442.     notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED, 
  443.              "Game: The production of %s was destroyed in %s, %s are suspected of sabotage.", 
  444.              prod, pcity->name, get_race_name_plural(pplayer->race));
  445.  
  446.     break;
  447.   case 1:
  448.     {
  449.       int building;
  450.       int i;
  451.       for (i=0;i<10;i++) {
  452.     building=myrand(B_LAST);
  453.     if (city_got_building(pcity, building) 
  454.         && !is_wonder(building) && building!=B_PALACE) {
  455.       pcity->improvements[building]=0;
  456.       break;
  457.     }
  458.       }
  459.       if (i<10) {
  460.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  461.              "Game: Your Diplomat destroyed %s in %s.", 
  462.              get_improvement_name(building), pcity->name);
  463.     notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED,
  464.              "Game: The %s destroyed %s in %s.", 
  465.              get_race_name_plural(pplayer->race),
  466.                          get_improvement_name(building), pcity->name);
  467.       } else {
  468.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  469.               "Game: Your Diplomat was caught in the attempt of industrial sabotage!");
  470.     notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED,
  471.              "Game: You caught a%s %s diplomat in industrial sabotage!",
  472.              n_if_vowel(get_race_name(pplayer->race)[0]),
  473.              get_race_name(pplayer->race));
  474.  
  475.     wipe_unit(0, pdiplomat);
  476.     return;
  477.       }
  478.     }
  479.     break;
  480.   }
  481.   send_city_info(cplayer, pcity, 1);
  482.   
  483.   /* Check if a spy survives her mission */
  484.   
  485.   diplomat_leave_city(pplayer, pdiplomat, pcity);
  486. }
  487.  
  488. /***************************************************************************
  489. Restore adds move points/hitpoints and upgrade units if player
  490. have leonardo's workshop.
  491. Air units have to be on carriers or cities or they'll be wiped.
  492. Missiles will have to be on submarines or in citites or they'll be wiped
  493. choppers out of city will loose 1 hitpoint every turn.
  494. triremes will be wiped with 50% chance 
  495. if they're not close to land, and player  don't have lighthouse.
  496. ****************************************************************************/
  497. void player_restore_units(struct player *pplayer)
  498. {
  499.   struct city *pcity;
  500.   int leonardo=0;
  501.   struct unit_list list;
  502.   struct unit *next_unit;
  503.  
  504.   pcity=city_list_find_id(&pplayer->cities, 
  505.               game.global_wonders[B_LEONARDO]);
  506.   if ((pcity && !wonder_obsolete(B_LEONARDO))) 
  507.     leonardo=1;
  508.   unit_list_iterate(pplayer->units, punit) {
  509.     if (leonardo && can_upgrade_unittype(pplayer, punit->type)!=-1) {
  510.       if (punit->hp==get_unit_type(punit->type)->hp) 
  511.     punit->hp = get_unit_type(can_upgrade_unittype(pplayer, punit->type))->hp;
  512.       notify_player(pplayer, "Game: Leonardo's workshop has upgraded %s to %s ",
  513.             unit_types[punit->type].name, 
  514.             unit_types[can_upgrade_unittype(pplayer, punit->type)].name);
  515.       punit->type = can_upgrade_unittype(pplayer, punit->type);
  516.       punit->veteran = 0;
  517.       leonardo = 0;
  518.     }
  519.  
  520.     unit_restore_hitpoints(pplayer, punit);
  521.     unit_restore_movepoints(pplayer, punit);
  522.     
  523.     if(is_air_unit(punit)) {
  524.       punit->fuel--;
  525.       if(map_get_city(punit->x, punit->y))
  526.     punit->fuel=get_unit_type(punit->type)->fuel;
  527.       else {
  528.     unit_list_iterate(map_get_tile(punit->x, punit->y)->units, punit2)
  529.       if (unit_flag(punit2->type,F_CARRIER))
  530.         punit->fuel=get_unit_type(punit->type)->fuel;
  531.       else if (unit_flag(punit->type, F_MISSILE) && 
  532.            unit_flag(punit2->type, F_SUBMARINE))
  533.         punit->fuel=get_unit_type(punit->type)->fuel;
  534.     unit_list_iterate_end;
  535.       }
  536.       if(punit->fuel<=0) {
  537.     send_remove_unit(0, punit->id);
  538.     notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_LOST, 
  539.              "Game: Your %s has run out of fuel",
  540.              unit_name(punit->type));
  541.     wipe_unit(0, punit);
  542.       }
  543.     } else if (punit->type==U_TRIREME) {
  544.       struct city *pcity;
  545.       pcity=city_list_find_id(&pplayer->cities, 
  546.                 game.global_wonders[B_LIGHTHOUSE]);
  547.       if (!(pcity && !wonder_obsolete(B_LIGHTHOUSE))) { 
  548.     if (!is_coastline(punit->x, punit->y) && (myrand(100) >= 50)) {
  549.       notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_LOST, 
  550.                "Game: Your Trireme has been lost on the high seas");
  551.           transporter_cargo_to_unitlist(punit, &list);
  552.           printf("Trireme has gone Kaput!\n");
  553.           while (1) {
  554.             next_unit = (struct unit *)ITERATOR_PTR(myiter);
  555.             if (next_unit && unit_list_find(&list, next_unit->id)) {
  556.               ITERATOR_NEXT(myiter);
  557.               printf("Iterating %d->%d\n", next_unit->id, (ITERATOR_PTR(myiter) ? 
  558.                   ((struct unit *)ITERATOR_PTR(myiter))->id : 0));
  559.             } else break;
  560.           }
  561. /* following filched from wipe_unit since t_c_2_u unlinks the damned -- Syela */
  562.           unit_list_iterate(list, punit2) {
  563.             send_remove_unit(0, punit2->id);
  564.             game_remove_unit(punit2->id);
  565.           }
  566.           unit_list_iterate_end;
  567. /* only now can we proceed to */
  568.       wipe_unit(pplayer, punit);
  569.     }
  570.       }
  571.     }
  572.   }
  573.   unit_list_iterate_end;
  574. }
  575.  
  576. /****************************************************************************
  577.   add hitpoints to the unit, hp_gain_coord returns the amount to add
  578.   united nations will speed up the process by 2 hp's / turn, means helicopters
  579.   will actually not loose hp's every turn if player have that wonder.
  580. *****************************************************************************/
  581. void unit_restore_hitpoints(struct player *pplayer, struct unit *punit)
  582. {
  583.   struct city *pcity;
  584.   
  585.   punit->hp+=hp_gain_coord(punit);
  586.   
  587.   pcity=city_list_find_id(&pplayer->cities, game.global_wonders[B_UNITED]);
  588.  
  589.   if(pcity && !wonder_obsolete(B_UNITED))
  590.     punit->hp+=2;
  591.     
  592.   if(punit->hp>get_unit_type(punit->type)->hp)
  593.     punit->hp=get_unit_type(punit->type)->hp;
  594.   if(punit->hp<0)
  595.     punit->hp=0;
  596. }
  597.   
  598.  
  599. /***************************************************************************
  600.  move points are trivial, only modifiers to the base value is if it's
  601.   sea units and the player has certain wonders/techs
  602. ***************************************************************************/
  603. void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
  604. {
  605.   punit->moves_left=unit_move_rate(punit);
  606. }
  607.  
  608. /**************************************************************************
  609.   after a battle this routine is called to decide whether or not the unit
  610.   should become a veteran, if unit isn't already.
  611.   there is a 50/50% chance for it to happend, (100% if player got SUNTZU)
  612. **************************************************************************/
  613. void maybe_make_veteran(struct unit *punit)
  614. {
  615.     struct city *pcity;
  616.     if (punit->veteran) 
  617.       return;
  618.     pcity=city_list_find_id(&game.players[punit->owner].cities, 
  619.                 game.global_wonders[B_SUNTZU]);
  620.     if(pcity && !wonder_obsolete(B_SUNTZU)) 
  621.       punit->veteran = 1;
  622.     else
  623.       punit->veteran=myrand(2);
  624. }
  625.  
  626. /**************************************************************************
  627.   This is the basic unit versus unit combat routine.
  628.   1) ALOT of modifiers bonuses etc is added to the 2 units rates.
  629.   2) the combat loop, which continues until one of the units are dead
  630.   3) the aftermath, the looser (and potentially the stack which is below it)
  631.      is wiped, and the winner gets a chance of gaining veteran status
  632. **************************************************************************/
  633. void unit_versus_unit(struct unit *attacker, struct unit *defender)
  634. {
  635.   int attackpower=get_total_attack_power(attacker,defender);
  636.   int defensepower=get_total_defense_power(attacker,defender);
  637.  
  638.   log(LOG_DEBUG, "attack:%d, defense:%d\n", attackpower, defensepower);
  639.   if (!attackpower) {
  640.       attacker->hp=0; 
  641.   } else if (!defensepower) {
  642.       defender->hp=0;
  643.   }
  644.   while (attacker->hp>0 && defender->hp>0) {
  645.     if (myrand(attackpower+defensepower)>= defensepower) {
  646.       defender->hp=defender->hp-get_unit_type(attacker->type)->firepower;
  647.     } else {
  648.       if (is_sailing_unit(defender) && map_get_city(defender->x, defender->y))
  649.     attacker->hp=attacker->hp-1;              /* pearl harbour */
  650.       else
  651.     attacker->hp=attacker->hp-get_unit_type(defender->type)->firepower;
  652.     }
  653.   }
  654.   if (attacker->hp<0) attacker->hp=0;
  655.   if (defender->hp<0) defender->hp=0;
  656.  
  657.   if (attacker->hp)
  658.     maybe_make_veteran(attacker); 
  659.   else if (defender->hp)
  660.     maybe_make_veteran(defender);
  661. }
  662.  
  663. /***************************************************************************
  664.  return the modified attack power of a unit.  Currently they aren't any
  665.  modifications...
  666. ***************************************************************************/
  667. int get_total_attack_power(struct unit *attacker, struct unit *defender)
  668. {
  669.   int attackpower=get_attack_power(attacker);
  670.  
  671.   return attackpower;
  672. }
  673.  
  674. int get_virtual_defense_power(int a_type, int d_type, int x, int y)
  675. {
  676.   int defensepower=unit_types[d_type].defense_strength;
  677.   int m_type = unit_types[a_type].move_type;
  678.   struct city *pcity = map_get_city(x, y);
  679.   enum tile_terrain_type t = map_get_terrain(x, y);
  680.  
  681.   if (unit_types[d_type].move_type == LAND_MOVING && t == T_OCEAN) return 0;
  682. /* I had this dorky bug where transports with mech inf aboard would go next
  683. to enemy ships thinking the mech inf would defend them adequately. -- Syela */
  684.  
  685.   defensepower *= get_tile_type(t)->defense_bonus;
  686.  
  687.   if (unit_flag(d_type, F_PIKEMEN) && unit_flag(a_type, F_HORSE)) 
  688.     defensepower*=2;
  689.   if (unit_flag(d_type, F_AEGIS) &&
  690.        (m_type == AIR_MOVING || m_type == HELI_MOVING)) defensepower*=2;
  691.   if (m_type == AIR_MOVING && pcity) {
  692.     if (city_got_building(pcity, B_SAM))
  693.       defensepower*=2;
  694.     if (city_got_building(pcity, B_SDI) && unit_flag(a_type, F_MISSILE))
  695.       defensepower*=2;
  696.   } else if (m_type == SEA_MOVING && pcity) {
  697.     if (city_got_building(pcity, B_COASTAL))
  698.       defensepower*=2;
  699.   } else if (!unit_flag(a_type, F_IGWALL) &&
  700.           (m_type == LAND_MOVING || m_type == HELI_MOVING) &&
  701.           pcity && city_got_citywalls(pcity))
  702.     defensepower*=3;
  703.   if (map_get_special(x, y)&S_FORTRESS && !pcity)
  704.     defensepower*=2;
  705.   if (pcity && unit_types[d_type].move_type == LAND_MOVING)
  706.     defensepower*=1.5;
  707.  
  708.   return defensepower;
  709. }
  710.  
  711. /***************************************************************************
  712.  return the modified defense power of a unit.
  713.  An veteran aegis cruiser in a mountain city with SAM and SDI defense 
  714.  being attacked by a missile gets defense 288.
  715. ***************************************************************************/
  716. int get_total_defense_power(struct unit *attacker, struct unit *defender)
  717. {
  718.   int defensepower=get_defense_power(defender);
  719.   if (unit_flag(defender->type, F_PIKEMEN) && unit_flag(attacker->type, F_HORSE)) 
  720.     defensepower*=2;
  721.   if (unit_flag(defender->type, F_AEGIS) && (is_air_unit(attacker) || is_heli_unit(attacker)))
  722.     defensepower*=2;
  723.   if (is_air_unit(attacker)) {
  724.     if (unit_behind_sam(defender))
  725.       defensepower*=2;
  726.     if (unit_behind_sdi(defender) && unit_flag(attacker->type, F_MISSILE))
  727.       defensepower*=2;
  728.   } else if (is_sailing_unit(attacker)) {
  729.     if (unit_behind_coastal(defender))
  730.       defensepower*=2;
  731.   } else if (!unit_ignores_citywalls(attacker) && 
  732.          (is_heli_unit(attacker) || is_ground_unit(attacker)) && 
  733.          unit_behind_walls(defender)) 
  734.     defensepower*=3;
  735.   if (unit_on_fortress(defender) && 
  736.       !map_get_city(defender->x, defender->y)) 
  737.     defensepower*=2;
  738.   if ((defender->activity == ACTIVITY_FORTIFY || 
  739.        map_get_city(defender->x, defender->y)) && 
  740.       is_ground_unit(defender))
  741.     defensepower*=1.5;
  742.  
  743.   return defensepower;
  744. }
  745.  
  746. /**************************************************************************
  747.  creates a unit, and set it's initial values, and put it into the right 
  748.  lists.
  749.  TODO: Maybe this procedure should refresh its homecity? so it'll show up 
  750.  immediately on the clients? (refresh_city + send_city_info)
  751. **************************************************************************/
  752. void create_unit(struct player *pplayer, int x, int y, enum unit_type_id type,
  753.          int make_veteran, int homecity_id, int moves_left)
  754. {
  755.   struct unit *punit;
  756.   struct city *pcity;
  757.   punit=(struct unit *)malloc(sizeof(struct unit));
  758.   punit->type=type;
  759.   punit->id=get_next_id_number();
  760.   punit->owner=pplayer->player_no;
  761.   punit->x = map_adjust_x(x); /* was = x, caused segfaults -- Syela */
  762.   punit->y=y;
  763.   if (y < 0 || y >= map.ysize) printf("Whoa!  Creating %s at illegal loc (%d, %d)\n",
  764.          get_unit_type(type)->name, x, y);
  765.   punit->goto_dest_x=0;
  766.   punit->goto_dest_y=0;
  767.   
  768.   pcity=game_find_city_by_id(homecity_id);
  769.   punit->veteran=make_veteran;
  770.   punit->homecity=homecity_id;
  771.   punit->hp=get_unit_type(punit->type)->hp;
  772.   punit->activity=ACTIVITY_IDLE;
  773.   punit->activity_count=0;
  774.   punit->upkeep=0;
  775.   punit->unhappiness=0;
  776.   punit->fuel=get_unit_type(punit->type)->fuel;
  777.   punit->ai.control=0;
  778.   punit->ai.ai_role = AIUNIT_NONE;
  779.   punit->ai.ferryboat = 0;
  780.   punit->ai.passenger = 0;
  781.   punit->ai.bodyguard = 0;
  782.   punit->ai.charge = 0;
  783.   unit_list_insert(&pplayer->units, punit);
  784.   unit_list_insert(&map_get_tile(x, y)->units, punit);
  785.   if (pcity)
  786.     unit_list_insert(&pcity->units_supported, punit);
  787.   punit->bribe_cost=unit_bribe_cost(punit);
  788.   if(moves_left < 0)  
  789.     punit->moves_left=unit_move_rate(punit);
  790.   else
  791.     punit->moves_left=moves_left;
  792.   send_unit_info(0, punit, 0);
  793. }
  794.  
  795.  
  796. /**************************************************************************
  797.   Removes the unit from the game, and notifies the clients.
  798.   TODO: Find out if the homecity is refreshed and resend when this happends
  799.   otherwise (refresh_city(homecity) + send_city(homecity))
  800. **************************************************************************/
  801. void send_remove_unit(struct player *pplayer, int unit_id)
  802. {
  803.   int o;
  804.   
  805.   struct packet_generic_integer packet;
  806.  
  807.   packet.value=unit_id;
  808.  
  809.   for(o=0; o<game.nplayers; o++)           /* dests */
  810.     if(!pplayer || &game.players[o]==pplayer)
  811.       send_packet_generic_integer(game.players[o].conn, PACKET_REMOVE_UNIT,
  812.                   &packet);
  813. }
  814.  
  815. /**************************************************************************
  816.   iterate through all units and update them.
  817. **************************************************************************/
  818. void update_unit_activities(struct player *pplayer)
  819. {
  820.   unit_list_iterate(pplayer->units, punit)
  821.     update_unit_activity(pplayer, punit);
  822.   unit_list_iterate_end;
  823. }
  824.  
  825. /**************************************************************************
  826.   assign a new task to a unit.
  827. **************************************************************************/
  828. void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
  829. {
  830.   punit->activity=new_activity;
  831.   punit->activity_count=0;
  832. }
  833.  
  834. /**************************************************************************
  835.   progress settlers in their current tasks, 
  836.   and units that is pillaging.
  837.   also move units that is on a goto.
  838. **************************************************************************/
  839. void update_unit_activity(struct player *pplayer, struct unit *punit)
  840. {
  841.   int id = punit->id;
  842.   punit->activity_count+= (get_unit_type(punit->type)->move_rate)/3;
  843.  
  844.   if (punit->activity == ACTIVITY_EXPLORE) {
  845.     ai_manage_explorer(pplayer, punit);
  846.     if (unit_list_find(&pplayer->units, id))
  847.       handle_unit_activity_request(pplayer, punit, ACTIVITY_EXPLORE);
  848.     else return;
  849.   }
  850.   
  851.    if(punit->activity==ACTIVITY_PILLAGE && punit->activity_count>=1) {
  852.       if(map_get_special(punit->x, punit->y)&S_IRRIGATION)
  853.     map_clear_special(punit->x, punit->y, S_IRRIGATION);
  854.       else if(map_get_special(punit->x, punit->y)&S_MINE)
  855.         map_clear_special(punit->x, punit->y, S_MINE);
  856.       else if(map_get_special(punit->x, punit->y)&S_RAILROAD)
  857.     map_clear_special(punit->x, punit->y, S_RAILROAD);
  858.       else 
  859.     map_clear_special(punit->x, punit->y, S_ROAD);
  860.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  861.     set_unit_activity(punit, ACTIVITY_IDLE);
  862.    }
  863.  
  864.   if(punit->activity==ACTIVITY_POLLUTION && punit->activity_count>=3) {
  865.     map_clear_special(punit->x, punit->y, S_POLLUTION);
  866.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  867.     set_unit_activity(punit, ACTIVITY_IDLE);
  868.   }
  869.  
  870.   if(punit->activity==ACTIVITY_FORTRESS && punit->activity_count>=3) {
  871.     map_set_special(punit->x, punit->y, S_FORTRESS);
  872.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  873.     set_unit_activity(punit, ACTIVITY_IDLE);
  874.   }
  875.   
  876.   if(punit->activity==ACTIVITY_IRRIGATE && 
  877.      punit->activity_count>=map_build_irrigation_time(punit->x, punit->y)) {
  878.     map_irrigate_tile(punit->x, punit->y);
  879.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  880.     punit->activity=ACTIVITY_IDLE;
  881.     set_unit_activity(punit, ACTIVITY_IDLE);
  882.   }
  883.  
  884.   if(punit->activity==ACTIVITY_ROAD && 
  885.      punit->activity_count>map_build_road_time(punit->x, punit->y)) {
  886.     map_set_special(punit->x, punit->y, S_ROAD);
  887.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  888.     punit->activity=ACTIVITY_IDLE;
  889.     set_unit_activity(punit, ACTIVITY_IDLE);
  890.   }
  891.  
  892.   if(punit->activity==ACTIVITY_RAILROAD && punit->activity_count>=3) {
  893.     map_set_special(punit->x, punit->y, S_RAILROAD);
  894.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  895.     punit->activity=ACTIVITY_IDLE;
  896.     handle_unit_activity_request(pplayer, punit, ACTIVITY_IDLE);
  897.     set_unit_activity(punit, ACTIVITY_IDLE);
  898.   }
  899.   
  900.   if(punit->activity==ACTIVITY_MINE && 
  901.      punit->activity_count>=map_build_mine_time(punit->x, punit->y)) {
  902.     map_mine_tile(punit->x, punit->y);
  903.     send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  904.     set_unit_activity(punit, ACTIVITY_IDLE);
  905.   }
  906.  
  907.   if(punit->activity==ACTIVITY_GOTO) {
  908.     if (!punit->ai.control && (!is_military_unit(punit) ||
  909.        !is_ground_unit(punit) || !pplayer->ai.control)) {
  910. /* autosettlers otherwise waste time; idling them breaks assignment */
  911. /* Stalling infantry on GOTO so I can see where they're GOing TO. -- Syela */
  912.       do_unit_goto(pplayer, punit);
  913.     }
  914.     return;
  915.   }
  916.   
  917.   if(punit->activity==ACTIVITY_IDLE && 
  918.      map_get_terrain(punit->x, punit->y)==T_OCEAN &&
  919.      is_ground_unit(punit))
  920.     set_unit_activity(punit, ACTIVITY_SENTRY);
  921.   send_unit_info(0, punit, 0);
  922. }
  923.  
  924.  
  925. /**************************************************************************
  926.  nuke a square
  927.  1) remove all units on the square
  928.  2) half the size of the city on the square
  929.  if it isn't a city square or an ocean square then with 50% chance 
  930.  add some pollution, then notify the client about the changes.
  931. **************************************************************************/
  932. void do_nuke_tile(int x, int y)
  933. {
  934.   struct unit_list *punit_list;
  935.   struct city *pcity;
  936.   punit_list=&map_get_tile(x, y)->units;
  937.   
  938.   while(unit_list_size(punit_list)) {
  939.     struct unit *punit=unit_list_get(punit_list, 0);
  940.     wipe_unit(0, punit);
  941.   }
  942.  
  943.   if((pcity=game_find_city_by_coor(x,y))) {
  944.     if (pcity->size > 1) { /* size zero cities are ridiculous -- Syela */
  945.       pcity->size/=2;
  946.       auto_arrange_workers(pcity);
  947.       send_city_info(0, pcity, 0);
  948.     }
  949.   }
  950.   else if ((map_get_terrain(x,y)!=T_OCEAN && map_get_terrain(x,y)<=T_TUNDRA) &&
  951.            (!(map_get_special(x,y)&S_POLLUTION)) && myrand(2)) { 
  952.     map_set_special(x,y, S_POLLUTION);
  953.     send_tile_info(0, x, y, TILE_KNOWN);
  954.   }
  955. }
  956.  
  957. /**************************************************************************
  958.   nuke all the squares in a 3x3 square around the center of the explosion
  959. **************************************************************************/
  960. void do_nuclear_explosion(int x, int y)
  961. {
  962.   int i,j;
  963.   for (i=0;i<3;i++)
  964.     for (j=0;j<3;j++)
  965.       do_nuke_tile(map_adjust_x(x+i-1),map_adjust_y(y+j-1));
  966. }
  967.  
  968.  
  969. /**************************************************************************
  970. Move the unit if possible 
  971.   if the unit has less moves than it costs to enter a square, we roll the dice:
  972.   1) either succeed
  973.   2) or have it's moves set to 0
  974.   a unit can always move atleast once
  975. **************************************************************************/
  976. int try_move_unit(struct unit *punit, int dest_x, int dest_y) 
  977. {
  978.   if (myrand(1+map_move_cost(punit, dest_x, dest_y))>punit->moves_left && punit->moves_left<unit_move_rate(punit)) {
  979.     punit->moves_left=0;
  980.     send_unit_info(&game.players[punit->owner], punit, 0);
  981.   }
  982.   return punit->moves_left;
  983. }
  984. /**************************************************************************
  985.   go by airline, if both cities have an airport and neither has been used this
  986.   turn the unit will be transported by it and have it's moves set to 0
  987. **************************************************************************/
  988. int do_airline(struct unit *punit, int x, int y)
  989. {
  990.   struct city *city1, *city2;
  991.   
  992.   if (!punit->moves_left)
  993.     return 0;
  994.   if (!(city1=map_get_city(punit->x, punit->y))) 
  995.     return 0;
  996.   if (!(city2=map_get_city(x,y)))
  997.     return 0;
  998.   if (city1->owner != city2->owner) 
  999.     return 0;
  1000.   if (city1->airlift + city2->airlift < 2) 
  1001.     return 0;
  1002.   city1->airlift=0;
  1003.   city2->airlift=0;
  1004.   punit->moves_left = 0;
  1005.   unit_list_unlink(&map_get_tile(punit->x, punit->y)->units, punit);
  1006.   punit->x = x;
  1007.   punit->y = y;
  1008.   send_unit_info(&game.players[punit->owner], punit, 0);
  1009.   unit_list_insert(&map_get_tile(x, y)->units, punit);
  1010.   notify_player_ex(&game.players[punit->owner], punit->x, punit->y, E_NOEVENT,
  1011.            "Game: unit transported succesfully.");
  1012.   return 1;
  1013. }
  1014.  
  1015.  
  1016. /**************************************************************************
  1017.   called when a player conquers a city, remove buildings (not wonders and always palace) with game.razechance% chance
  1018.   set the city's shield stock to 0
  1019. **************************************************************************/
  1020. void raze_city(struct city *pcity)
  1021. {
  1022.   int i;
  1023.   pcity->improvements[B_PALACE]=0;
  1024.   for (i=0;i<B_LAST;i++) {
  1025.     if (city_got_building(pcity, i) && !is_wonder(i) 
  1026.     && (myrand(100) < game.razechance)) {
  1027.       pcity->improvements[i]=0;
  1028.     }
  1029.   }
  1030.   if (pcity->shield_stock > 0)
  1031.     pcity->shield_stock=0;
  1032.   /*  advisor_choose_build(pcity);  we add the civ bug here :)*/
  1033. }
  1034.  
  1035. /**************************************************************************
  1036.   if target has more techs than pplayer, pplayer will get a random of these
  1037.   the clients will both be notified.
  1038.   TODO: Players with embassies in these countries should be notified aswell
  1039. **************************************************************************/
  1040. void get_a_tech(struct player *pplayer, struct player *target)
  1041. {
  1042.   int tec;
  1043.   int i;
  1044.   int j=0;
  1045.   for (i=0;i<A_LAST;i++) {
  1046.     if (get_invention(pplayer, i)!=TECH_KNOWN && 
  1047.     get_invention(target, i)== TECH_KNOWN) {
  1048.       j++;
  1049.     }
  1050.   }
  1051.   if (!j)
  1052.     if (target->future_tech > pplayer->future_tech) {
  1053.       notify_player(pplayer, "Game: You acquire Future Tech %d from %s",
  1054.                    ++(pplayer->future_tech), target->name);
  1055.       notify_player(target, "Game: %s discovered Future Tech. %d in the city.", 
  1056.                    pplayer->name, pplayer->future_tech);
  1057.     }
  1058.   return;
  1059.   j=myrand(j)+1;
  1060.   for (i=0;i<A_LAST;i++) {
  1061.     if (get_invention(pplayer, i)!=TECH_KNOWN && 
  1062.     get_invention(target, i)== TECH_KNOWN) 
  1063.       j--;
  1064.     if (!j) break;
  1065.   }
  1066.   if (i==A_LAST) 
  1067.     printf("Bug in get_a_tech\n");
  1068.   set_invention(pplayer, i, TECH_KNOWN);
  1069.   update_research(pplayer);
  1070.   do_conquer_cost(pplayer);
  1071.   pplayer->research.researchpoints++;
  1072.   notify_player(pplayer, "Game: You acquired %s from %s",
  1073.         advances[i].name, target->name); 
  1074.   notify_player(target, "Game: %s discovered %s in the city.", pplayer->name, 
  1075.         advances[i].name); 
  1076.   if (pplayer->research.researching==i) {
  1077.     tec=pplayer->research.researched;
  1078.     if (!choose_goal_tech(pplayer))
  1079.       choose_random_tech(pplayer);
  1080.     pplayer->research.researched=tec;
  1081.   }
  1082. }
  1083.  
  1084. /**************************************************************************
  1085.   finds a spot around pcity and place a partisan.
  1086. **************************************************************************/
  1087. void place_partisans(struct city *pcity,int count)
  1088. {
  1089.   int x,y,i;
  1090.   int ok[25];
  1091.   int total=0;
  1092.  
  1093.   for (i = 0,x = pcity->x -2; x < pcity->x + 3; x++) {
  1094.     for (y = pcity->y - 2; y < pcity->y + 3; y++, i++) {
  1095.       ok[i]=can_place_partisan(map_adjust_x(x), map_adjust_y(y));
  1096.       if(ok[i]) total++;
  1097.     }
  1098.   }
  1099.  
  1100.   while(count && total)  {
  1101.     for(i=0,x=myrand(total)+1;x;i++) if(ok[i]) x--;
  1102.     ok[--i]=0; x=(i/5)-2+pcity->x; y=(i%5)-2+pcity->y;
  1103.     create_unit(&game.players[pcity->owner], map_adjust_x(x), map_adjust_y(y),
  1104.         U_PARTISAN, 0, 0, -1);
  1105.     count--; total--;
  1106.   }
  1107. }
  1108.  
  1109. /**************************************************************************
  1110.   if requirements to make partisans when a city is conquered is fullfilled
  1111.   this routine makes a lot of partisans based on the city's size.
  1112.   To be candidate for partisans the following things must be satisfied:
  1113.   1) Guerilla warfare must be known by atleast 1 player
  1114.   2) The owner of the city is the original player.
  1115.   3) The player must know about communism and gunpowder
  1116.   4) the player must run either a democracy or a communist society.
  1117. **************************************************************************/
  1118. void make_partisans(struct city *pcity)
  1119. {
  1120.   int partisans;
  1121.   if (!game.global_advances[A_GUERILLA] || pcity->original != pcity->owner)
  1122.     return;
  1123.   if (get_invention(city_owner(pcity), A_COMMUNISM) != TECH_KNOWN 
  1124.       && get_invention(city_owner(pcity), A_GUNPOWDER) != TECH_KNOWN)
  1125.     return;
  1126.   if (get_government(pcity->owner)!=G_DEMOCRACY
  1127.       && get_government(pcity->owner)!=G_COMMUNISM) 
  1128.     return;
  1129.   
  1130.   partisans = myrand(1 + pcity->size/2) + 1;
  1131.   if (partisans > 8) 
  1132.     partisans = 8;
  1133.   
  1134.   place_partisans(pcity,partisans);
  1135. }
  1136.  
  1137.  
  1138. /**************************************************************************
  1139. this is a highlevel routine
  1140. **************************************************************************/
  1141. void wipe_unit(struct player *dest, struct unit *punit)
  1142. {
  1143.   if(get_transporter_capacity(punit) && 
  1144.      map_get_terrain(punit->x, punit->y)==T_OCEAN) {
  1145.     struct unit_list list;
  1146.     
  1147.     transporter_cargo_to_unitlist(punit, &list);
  1148.     
  1149.     unit_list_iterate(list, punit2) {
  1150.       send_remove_unit(0, punit2->id);
  1151.       game_remove_unit(punit2->id);
  1152.     }
  1153.     unit_list_iterate_end;
  1154.   }
  1155.   send_remove_unit(0, punit->id);
  1156.   game_remove_unit(punit->id);
  1157. }
  1158.  
  1159. /**************************************************************************
  1160. this is a highlevel routine
  1161. the unit has been killed in combat => all other units on the
  1162. tile dies unless ...
  1163. **************************************************************************/
  1164. void kill_unit(struct unit *pkiller, struct unit *punit)
  1165. {
  1166.   int klaf;
  1167.   struct city *nearcity = dist_nearest_enemy_city(get_player(punit->owner), punit->x, punit->y);
  1168.   struct city *incity = map_get_city(punit->x, punit->y);
  1169.   struct player *dest = &game.players[pkiller->owner];
  1170.   klaf=unit_list_size(&(map_get_tile(punit->x, punit->y)->units));
  1171.   if( (incity) || 
  1172.       (map_get_special(punit->x, punit->y)&S_FORTRESS) || 
  1173.       (klaf == 1)) {
  1174.     if (incity) 
  1175.       notify_player_ex(&game.players[punit->owner], 
  1176.                punit->x, punit->y, E_UNIT_LOST,
  1177.                "Game: You lost a%s %s under an attack from %s's %s, in %s",
  1178.                n_if_vowel(get_unit_type(punit->type)->name[0]),
  1179.                get_unit_type(punit->type)->name, dest->name,
  1180.                        unit_name(pkiller->type), incity->name);
  1181.     else if (nearcity && is_tiles_adjacent(punit->x, punit->y, nearcity->x, nearcity->y))
  1182.       notify_player_ex(&game.players[punit->owner], 
  1183.                punit->x, punit->y, E_UNIT_LOST,
  1184.                "Game: You lost a%s %s under an attack from %s's %s, outside %s",
  1185.                n_if_vowel(get_unit_type(punit->type)->name[0]),
  1186.                get_unit_type(punit->type)->name, dest->name,
  1187.                        unit_name(pkiller->type), nearcity->name);
  1188.     else if (nearcity)
  1189.       notify_player_ex(&game.players[punit->owner], 
  1190.                punit->x, punit->y, E_UNIT_LOST,
  1191.                "Game: You lost a%s %s under an attack from %s's %s, near %s",
  1192.                n_if_vowel(get_unit_type(punit->type)->name[0]),
  1193.                get_unit_type(punit->type)->name, dest->name,
  1194.                        unit_name(pkiller->type), nearcity->name);
  1195.     else
  1196.       notify_player_ex(&game.players[punit->owner], 
  1197.                punit->x, punit->y, E_UNIT_LOST,
  1198.                "Game: You lost a%s %s under an attack from %s's %s",
  1199.                n_if_vowel(get_unit_type(punit->type)->name[0]),
  1200.                get_unit_type(punit->type)->name, dest->name,
  1201.                        unit_name(pkiller->type));
  1202.     send_remove_unit(0, punit->id);
  1203.     game_remove_unit(punit->id);
  1204.   }  else {
  1205.       if (nearcity && is_tiles_adjacent(punit->x, punit->y, nearcity->x,
  1206.         nearcity->y)) notify_player_ex(&game.players[punit->owner], 
  1207.                punit->x, punit->y, E_UNIT_LOST,
  1208.                "Game: You lost %d units under an attack from %s's %s, outside %s",
  1209.                klaf, dest->name, unit_name(pkiller->type), nearcity->name);
  1210.       else if (nearcity) notify_player_ex(&game.players[punit->owner], 
  1211.                punit->x, punit->y, E_UNIT_LOST,
  1212.                "Game: You lost %d units under an attack from %s's %s, near %s",
  1213.                klaf, dest->name, unit_name(pkiller->type), nearcity->name);
  1214.       else notify_player_ex(&game.players[punit->owner], 
  1215.                punit->x, punit->y, E_UNIT_LOST, 
  1216.                "Game: You lost %d units under an attack from %s's %s",
  1217.                klaf, dest->name, unit_name(pkiller->type));
  1218.       unit_list_iterate(map_get_tile(punit->x, punit->y)->units, punit2) {
  1219.     notify_player_ex(&game.players[punit2->owner], 
  1220.              punit->x, punit->y, E_UNIT_LOST,
  1221.              "Game: You lost a%s %s under an attack from %s's %s",
  1222.              n_if_vowel(get_unit_type(punit2->type)->name[0]),
  1223.              get_unit_type(punit2->type)->name, dest->name,
  1224.                          unit_name(pkiller->type));
  1225.     send_remove_unit(0, punit2->id);
  1226.     game_remove_unit(punit2->id);
  1227.       }
  1228.       unit_list_iterate_end;
  1229.   } 
  1230. }
  1231.  
  1232. /**************************************************************************
  1233.   send the unit to the players who need the info 
  1234.   dest = NULL means all players, dosend means send even if the player 
  1235.   can't see the unit.
  1236. **************************************************************************/
  1237. void send_unit_info(struct player *dest, struct unit *punit, int dosend)
  1238. {
  1239.   int o;
  1240.   struct packet_unit_info info;
  1241.  
  1242.   info.id=punit->id;
  1243.   info.owner=punit->owner;
  1244.   info.x=punit->x;
  1245.   info.y=punit->y;
  1246.   info.homecity=punit->homecity;
  1247.   info.veteran=punit->veteran;
  1248.   info.type=punit->type;
  1249.   info.movesleft=punit->moves_left;
  1250.   info.hp=punit->hp;
  1251.   info.activity=punit->activity;
  1252.   info.activity_count=punit->activity_count;
  1253.   info.unhappiness=punit->unhappiness;
  1254.   info.upkeep=punit->upkeep;
  1255.   info.ai=punit->ai.control;
  1256.   info.fuel=punit->fuel;
  1257.   info.goto_dest_x=punit->goto_dest_x;
  1258.   info.goto_dest_y=punit->goto_dest_y;
  1259.     
  1260.   for(o=0; o<game.nplayers; o++)           /* dests */
  1261.     if(!dest || &game.players[o]==dest)
  1262.       if(dosend || map_get_known(info.x, info.y, &game.players[o]))
  1263.      send_packet_unit_info(game.players[o].conn, &info);
  1264. }
  1265.