home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / spiele / FreeCiv / src / freeciv-1.7.0 / server / unithand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  33.1 KB  |  937 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 <settlers.h>
  37. void do_unit_goto(struct player *pplayer, struct unit *punit);
  38.  
  39. /**************************************************************************
  40. ...
  41. **************************************************************************/
  42. void handle_unit_goto_tile(struct player *pplayer, 
  43.                struct packet_unit_request *req)
  44. {
  45.   struct unit *punit;
  46.   
  47.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  48.     punit->goto_dest_x=req->x;
  49.     punit->goto_dest_y=req->y;
  50.  
  51.     punit->activity=ACTIVITY_GOTO;
  52.     punit->activity_count=0;
  53.  
  54.     send_unit_info(0, punit, 0);
  55.       
  56.     do_unit_goto(pplayer, punit);  
  57.   }
  58. }
  59.  
  60. /**************************************************************************
  61. ...
  62. **************************************************************************/
  63. void handle_upgrade_unit_request(struct player *pplayer, 
  64.                 struct packet_unittype_info *packet)
  65. {
  66.   int cost;
  67.   int to_unit;
  68.   int upgraded = 0;
  69.   if ((to_unit =can_upgrade_unittype(pplayer, packet->type)) == -1) {
  70.     notify_player(pplayer, "Game: illegal package, can't upgrade %s (yet).", 
  71.           unit_types[packet->type].name);
  72.     return;
  73.   }
  74.   cost = unit_upgrade_price(pplayer, packet->type, to_unit);
  75.   unit_list_iterate(pplayer->units, punit) {
  76.     if (cost > pplayer->economic.gold)
  77.       break;
  78.     if (punit->type == packet->type && map_get_city(punit->x, punit->y)) {
  79.       pplayer->economic.gold -= cost;
  80.       if (punit->hp==get_unit_type(punit->type)->hp) {
  81.     punit->hp=get_unit_type(to_unit)->hp;
  82.       }
  83.       punit->type = to_unit;
  84.       send_unit_info(0, punit, 0);
  85.       upgraded++;
  86.     }
  87.   }
  88.   unit_list_iterate_end;
  89.   if (upgraded > 0) {
  90.     notify_player(pplayer, "Game: %d %s upgraded to %s for %d credits", 
  91.           upgraded, unit_types[packet->type].name, 
  92.           unit_types[to_unit].name, cost * upgraded);
  93.     send_player_info(pplayer, pplayer);
  94.   } else {
  95.     notify_player(pplayer, "Game: No units could be upgraded.");
  96.   }
  97. }
  98.  
  99. /***************************************************************
  100. ...  Tell the client the cost of inciting a revolt
  101.      or bribing a unit
  102. ***************************************************************/
  103. void handle_incite_inq(struct player *pplayer,
  104.                struct packet_generic_integer *packet)
  105. {
  106.   struct city *pcity=find_city_by_id(packet->value);
  107.   struct unit *punit=find_unit_by_id(packet->value);
  108.   struct packet_generic_values req;
  109.  
  110.   if(pcity)  {
  111.     city_incite_cost(pcity);
  112.     req.id=packet->value;
  113.     req.value1=pcity->incite_revolt_cost;
  114.     send_packet_generic_values(pplayer->conn, PACKET_INCITE_COST, &req);
  115.     return;
  116.   }
  117.   if(punit)  {
  118.     punit->bribe_cost = unit_bribe_cost(punit);
  119.     req.id=packet->value;
  120.     req.value1=punit->bribe_cost;
  121.     send_packet_generic_values(pplayer->conn, PACKET_INCITE_COST, &req);
  122.   }
  123. }
  124.  
  125. /***************************************************************
  126. ...
  127. ***************************************************************/
  128. void handle_diplomat_action(struct player *pplayer, 
  129.                 struct packet_diplomat_action *packet)
  130. {
  131.   struct unit *pdiplomat=unit_list_find(&pplayer->units, packet->diplomat_id);
  132.   struct unit *pvictim=find_unit_by_id(packet->target_id);
  133.   struct city *pcity=find_city_by_id(packet->target_id);
  134.   if (!pdiplomat) return;
  135.   if (!unit_flag(pdiplomat->type, F_DIPLOMAT)) 
  136.     return;
  137.   if(pdiplomat && pdiplomat->moves_left>0) {
  138.     pdiplomat->moves_left=0;
  139.     send_unit_info(pplayer, pdiplomat, 0);
  140.     switch(packet->action_type) {
  141.      case DIPLOMAT_BRIBE:
  142.        if(pvictim && diplomat_can_do_action(pdiplomat, DIPLOMAT_BRIBE,
  143.                       pvictim->x, pvictim->y))
  144.      diplomat_bribe(pplayer, pdiplomat, pvictim);
  145.       break;
  146.      case DIPLOMAT_SABOTAGE:
  147.        if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_SABOTAGE, 
  148.                       pcity->x, pcity->y))
  149.      diplomat_sabotage(pplayer, pdiplomat, pcity);
  150.        break;
  151.     case SPY_POISON:
  152.       if(pcity && diplomat_can_do_action(pdiplomat, SPY_POISON,
  153.                      pcity->x, pcity->y))
  154.     spy_poison(pplayer, pdiplomat, pcity);
  155.       break;
  156.     case DIPLOMAT_EMBASSY:
  157.       if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_EMBASSY, 
  158.                      pcity->x, pcity->y)) {
  159.     pplayer->embassy|=(1<<pcity->owner);
  160.     send_player_info(pplayer, pplayer);
  161.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  162.              "Game: You have established an embassy in %s",
  163.              pcity->name);
  164.     
  165.     notify_player_ex(&game.players[pcity->owner], pcity->x, pcity->y, E_DIPLOMATED, "Game: The %s have established an embassy in %s",
  166.               get_race_name_plural(pplayer->race),
  167.               pcity->name);
  168.       }
  169.       wipe_unit(0, pdiplomat);
  170.       break;
  171.      case DIPLOMAT_INCITE:
  172.        if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_INCITE, 
  173.                       pcity->x, pcity->y))
  174.      diplomat_incite(pplayer, pdiplomat, pcity);
  175.       break;
  176.      case DIPLOMAT_STEAL:
  177.        if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_STEAL, 
  178.                       pcity->x, pcity->y))
  179.      diplomat_get_tech(pplayer, pdiplomat, pcity);
  180.       break;
  181.     }
  182.   }
  183. }
  184. /**************************************************************************
  185. ...
  186. **************************************************************************/
  187. void handle_unit_change_homecity(struct player *pplayer, 
  188.                  struct packet_unit_request *req)
  189. {
  190.   struct unit *punit;
  191.   
  192.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  193.     struct city *pcity;
  194.     if((pcity=city_list_find_id(&pplayer->cities, req->city_id))) {
  195.       unit_list_insert(&pcity->units_supported, punit);
  196.       
  197.       if((pcity=city_list_find_id(&pplayer->cities, punit->homecity)))
  198.     unit_list_unlink(&pcity->units_supported, punit);
  199.       
  200.       punit->homecity=req->city_id;
  201.       send_unit_info(pplayer, punit, 0);
  202.     }
  203.   }
  204. }
  205.  
  206. /**************************************************************************
  207. ...
  208. **************************************************************************/
  209. void handle_unit_disband(struct player *pplayer, 
  210.              struct packet_unit_request *req)
  211. {
  212.   struct unit *punit;
  213.   struct city *pcity;
  214.   /* give 1/2 of the worth of the unit, to the currently builded thing 
  215.      have to be on the location of the city_square
  216.    */
  217.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  218.     if ((pcity=map_get_city(punit->x, punit->y))) {
  219.       pcity->shield_stock+=(get_unit_type(punit->type)->build_cost/2);
  220.       send_city_info(pplayer, pcity, 0);
  221.     }
  222.     wipe_unit(pplayer, punit);
  223.   }
  224. }
  225.  
  226. /**************************************************************************
  227. ...
  228. **************************************************************************/
  229. void handle_unit_build_city(struct player *pplayer, 
  230.                 struct packet_unit_request *req)
  231. {
  232.   struct unit *punit;
  233.   char *name;
  234.   struct city *pcity;
  235.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  236.     if (!unit_flag(punit->type, F_SETTLERS)) {
  237.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  238.             "Game: You need a settler to build a city.");
  239.       return;
  240.     }  
  241.  
  242.     if(!punit->moves_left)  {
  243.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  244.                        "Game: Settler has no moves left to build city.");
  245.       return;
  246.     }
  247.     
  248.     if ((pcity=map_get_city(punit->x, punit->y))) {
  249.       if (pcity->size>8) {
  250.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, 
  251.             "Game: Your settlers doesn't feel comfortable here.");
  252.     return;
  253.       }
  254.       else {
  255.     pcity->size++;
  256.       if (!add_adjust_workers(pcity))
  257.         auto_arrange_workers(pcity);
  258.         wipe_unit(0, punit);
  259.     send_city_info(pplayer, pcity, 0);
  260.     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  261.               "Game: Settlers added to aid %s in growing", 
  262.               pcity->name);
  263.     return;
  264.       }
  265.     }
  266.     
  267.     if(can_unit_build_city(punit)) {
  268.       if(!(name=get_sane_name(req->name))) {
  269.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, 
  270.               "Game: Let's not build a city with such a stupid name.");
  271.     return;
  272.       }
  273.  
  274.       send_remove_unit(0, req->unit_id);
  275.       map_set_special(punit->x, punit->y, S_ROAD);
  276.       if (get_invention(pplayer, A_RAILROAD)==TECH_KNOWN)
  277.     map_set_special(punit->x, punit->y, S_RAILROAD);
  278.       send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  279.       create_city(pplayer, punit->x, punit->y, name);
  280.       game_remove_unit(req->unit_id);
  281.     } else
  282.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  283.             "Game: Can't place city here.");
  284.   }
  285. }
  286. /**************************************************************************
  287. ...
  288. **************************************************************************/
  289. void handle_unit_info(struct player *pplayer, struct packet_unit_info *pinfo)
  290. {
  291.   struct unit *punit;
  292.  
  293.   punit=unit_list_find(&pplayer->units, pinfo->id);
  294.  
  295.   if(punit) {
  296.     if(punit->ai.control) {
  297.       punit->ai.control=0;
  298.     }
  299.     if(punit->activity!=pinfo->activity)
  300.       handle_unit_activity_request(pplayer, punit, pinfo->activity);
  301.     else if (!same_pos(punit->x, punit->y, pinfo->x, pinfo->y))
  302.       handle_unit_move_request(pplayer, punit, pinfo->x, pinfo->y);
  303.   }
  304. }
  305. /**************************************************************************
  306. ...
  307. **************************************************************************/
  308. void handle_move_unit(struct player *pplayer, struct packet_move_unit *pmove)
  309. {
  310.   struct unit *punit;
  311.  
  312.   punit=unit_list_find(&pplayer->units, pmove->unid);
  313.   if(punit)  {
  314.     handle_unit_move_request(pplayer, punit, pmove->x, pmove->y);
  315.   }
  316. }
  317. /**************************************************************************
  318. ...
  319. **************************************************************************/
  320. void handle_unit_attack_request(struct player *pplayer, struct unit *punit,
  321.                 struct unit *pdefender)
  322. {
  323.   int o;
  324.   struct packet_unit_combat combat;
  325.   struct unit *plooser, *pwinner;
  326.   struct city *pcity;
  327.   struct city *incity, *nearcity1, *nearcity2;
  328.   incity = map_get_city(pdefender->x, pdefender->y);
  329.   punit->moves_left-=3;
  330.     
  331.   if(punit->moves_left<0)
  332.     punit->moves_left=0;
  333.   
  334.  
  335.   if(punit->type==U_NUCLEAR) {
  336.     struct packet_nuke_tile packet;
  337.     
  338.     packet.x=pdefender->x;
  339.     packet.y=pdefender->y;
  340.     if ((pcity=sdi_defense_close(punit->owner, pdefender->x, pdefender->y))) {
  341.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Your Nuclear missile has been shot down by SDI, what a waste.");
  342.       notify_player_ex(&game.players[pcity->owner], 
  343.                pdefender->x, pdefender->y, E_NOEVENT, 
  344.              "Game: The nuclear attack on %s was avoided by your SDI defense",
  345.                pcity->name); 
  346.       wipe_unit(0, punit);
  347.       return;
  348.     } 
  349.  
  350.     for(o=0; o<game.nplayers; o++)
  351.       send_packet_nuke_tile(game.players[o].conn, &packet);
  352.     
  353.     do_nuclear_explosion(pdefender->x, pdefender->y);
  354.     return;
  355.   }
  356.   
  357.   unit_versus_unit(punit, pdefender);
  358.  
  359.   if (punit->hp && (pcity=map_get_city(pdefender->x, pdefender->y)) && pcity->size>1 && !city_got_citywalls(pcity) && is_ground_unit(punit)) {
  360.     pcity->size--;
  361.     city_auto_remove_worker(pcity);
  362.     city_refresh(pcity);
  363.     send_city_info(0, pcity, 0);
  364.   }
  365.   if (unit_flag(punit->type, F_ONEATTACK)) 
  366.     punit->moves_left = 0;
  367.   pwinner=(punit->hp) ?     punit : pdefender;
  368.   plooser=(pdefender->hp) ? punit : pdefender;
  369.     
  370.   combat.attacker_unit_id=punit->id;
  371.   combat.defender_unit_id=pdefender->id;
  372.   combat.attacker_hp=punit->hp;
  373.   combat.defender_hp=pdefender->hp;
  374.   combat.make_winner_veteran=pwinner->veteran?1:0;
  375.   
  376.   for(o=0; o<game.nplayers; o++)
  377.     if(map_get_known(punit->x, punit->y, &game.players[o]) ||
  378.        map_get_known(pdefender->x, pdefender->y, &game.players[o]))
  379.       send_packet_unit_combat(game.players[o].conn, &combat);
  380.  
  381.   nearcity1 = dist_nearest_enemy_city(get_player(pwinner->owner), pdefender->x, pdefender->y);
  382.   nearcity2 = dist_nearest_enemy_city(get_player(plooser->owner), pdefender->x, pdefender->y);
  383.   
  384.   if(punit==plooser) {
  385.     if (incity) notify_player_ex(&game.players[pwinner->owner], 
  386.              pwinner->x, pwinner->y, E_UNIT_WIN, 
  387.           "Game: Your %s in %s survived the pathetic attack from %s's %s.",
  388.                   unit_name(pwinner->type), incity->name,
  389.           game.players[plooser->owner].name,
  390.           unit_name(punit->type));
  391.     else if (nearcity1 && is_tiles_adjacent(pdefender->x, pdefender->y, nearcity1->x,
  392.          nearcity1->y)) notify_player_ex(&game.players[pwinner->owner], 
  393.              pwinner->x, pwinner->y, E_UNIT_WIN, 
  394.           "Game: Your %s outside %s survived the pathetic attack from %s's %s.",
  395.                   unit_name(pwinner->type), nearcity1->name,
  396.           game.players[plooser->owner].name,
  397.           unit_name(punit->type));
  398.     else if (nearcity1) notify_player_ex(&game.players[pwinner->owner], 
  399.              pwinner->x, pwinner->y, E_UNIT_WIN, 
  400.           "Game: Your %s near %s survived the pathetic attack from %s's %s.",
  401.                   unit_name(pwinner->type), nearcity1->name,
  402.           game.players[plooser->owner].name,
  403.           unit_name(punit->type));
  404.     else notify_player_ex(&game.players[pwinner->owner], 
  405.              pwinner->x, pwinner->y, E_UNIT_WIN, 
  406.           "Game: Your %s survived the pathetic attack from %s's %s.",
  407.                   unit_name(pwinner->type),
  408.           game.players[plooser->owner].name,
  409.           unit_name(punit->type));
  410.     if (incity) notify_player_ex(&game.players[plooser->owner], 
  411.              pdefender->x, pdefender->y, E_NOEVENT, 
  412.              "Game: Your attacking %s failed against %s's %s at %s!",
  413.                       unit_name(plooser->type),
  414.           game.players[pwinner->owner].name,
  415.           unit_name(pwinner->type), incity->name);
  416.     else if (nearcity2 && is_tiles_adjacent(pdefender->x, pdefender->y,
  417.       nearcity2->x, nearcity2->y)) notify_player_ex(&game.players[plooser->owner], 
  418.              pdefender->x, pdefender->y, E_NOEVENT, 
  419.              "Game: Your attacking %s failed against %s's %s outside %s!",
  420.                       unit_name(plooser->type),
  421.           game.players[pwinner->owner].name,
  422.           unit_name(pwinner->type), nearcity2->name);
  423.     else if (nearcity2) notify_player_ex(&game.players[plooser->owner], 
  424.              pdefender->x, pdefender->y, E_NOEVENT, 
  425.              "Game: Your attacking %s failed against %s's %s near %s!",
  426.                       unit_name(plooser->type),
  427.           game.players[pwinner->owner].name,
  428.           unit_name(pwinner->type), nearcity2->name);
  429.     else notify_player_ex(&game.players[plooser->owner], 
  430.              pdefender->x, pdefender->y, E_NOEVENT, 
  431.              "Game: Your attacking %s failed against %s's %s!",
  432.                       unit_name(plooser->type),
  433.           game.players[pwinner->owner].name,
  434.           unit_name(pwinner->type));
  435.     wipe_unit(pplayer, plooser);
  436.   }
  437.   else {
  438.     if (incity) notify_player_ex(&game.players[pwinner->owner], 
  439.              punit->x, punit->y, E_NOEVENT, 
  440.              "Game: Your attacking %s was successful against %s's %s at %s!",
  441.                       unit_name(pwinner->type),
  442.           game.players[plooser->owner].name,
  443.           unit_name(plooser->type), incity->name);
  444.     else if (nearcity1 && is_tiles_adjacent(pdefender->x, pdefender->y,
  445.        nearcity1->x, nearcity1->y)) notify_player_ex(&game.players[pwinner->owner], 
  446.              punit->x, punit->y, E_NOEVENT, 
  447.              "Game: Your attacking %s was successful against %s's %s outside %s!",
  448.                       unit_name(pwinner->type),
  449.           game.players[plooser->owner].name,
  450.           unit_name(plooser->type), nearcity1->name);
  451.     else if (nearcity1) notify_player_ex(&game.players[pwinner->owner], 
  452.              punit->x, punit->y, E_NOEVENT, 
  453.              "Game: Your attacking %s was successful against %s's %s near %s!",
  454.                       unit_name(pwinner->type),
  455.           game.players[plooser->owner].name,
  456.           unit_name(plooser->type), nearcity1->name);
  457.     else notify_player_ex(&game.players[pwinner->owner], 
  458.              punit->x, punit->y, E_NOEVENT, 
  459.              "Game: Your attacking %s was successful against %s's %s!",
  460.                       unit_name(pwinner->type),
  461.           game.players[plooser->owner].name,
  462.           unit_name(plooser->type));
  463.     kill_unit(pwinner, plooser); /* no longer pplayer - want better msgs -- Syela */
  464.   }
  465.   if (pwinner == punit && unit_flag(punit->type, F_MISSILE)) {
  466.     wipe_unit(pplayer, pwinner);
  467.     return;
  468.   }
  469.   send_unit_info(0, pwinner, 0);
  470. }
  471.  
  472. /**************************************************************************
  473. ...
  474. **************************************************************************/
  475. void handle_unit_enter_hut(struct unit *punit)
  476. {
  477.   struct player *pplayer=&game.players[punit->owner];
  478.   if (is_air_unit(punit))
  479.     return;
  480.   map_get_tile(punit->x, punit->y)->special^=S_HUT;
  481.   
  482.   send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  483.   
  484.   switch (myrand(12)) {
  485.   case 0:
  486.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, 
  487.              "Game: You found 25 credits.");
  488.     pplayer->economic.gold+=25;
  489.     break;
  490.   case 1:
  491.   case 2:
  492.   case 3:
  493.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  494.           "Game: You found 50 credits.");
  495.     pplayer->economic.gold+=50;
  496.     break;
  497.   case 4:
  498.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  499.              "Game: You found 100 credits"); 
  500.     pplayer->economic.gold+=100;
  501.     break;
  502.   case 5:
  503.   case 6:
  504.   case 7:
  505. /*this function is hmmm a hack */
  506.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  507.           "Game: You found ancient scrolls of wisdom."); 
  508.     {
  509.       int res=pplayer->research.researched;
  510.       int wasres=pplayer->research.researching;
  511.  
  512.       choose_random_tech(pplayer);
  513.  
  514.       pplayer->research.researchpoints++;
  515.       if (pplayer->research.researching!=A_NONE) {
  516.        notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  517.                         "Game: You gain knowledge about %s.", 
  518.                         advances[pplayer->research.researching].name);
  519.        if (pplayer->research.researching==A_RAILROAD) {
  520. /*         struct city_list cl=pplayer->cities;*/
  521.          struct genlist_iterator myiter;
  522.          genlist_iterator_init(&myiter, &pplayer->cities.list, 0);
  523.          notify_player(pplayer, "Game: New hope sweeps like fire through the country as the discovery of railroad is announced.\n      Workers spontaneously gather and upgrade all cities with railroads.");
  524.          for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) {
  525.            struct city *pcity=(struct city *)ITERATOR_PTR(myiter);
  526.            map_set_special(pcity->x, pcity->y, S_RAILROAD);
  527.            send_tile_info(0, pcity->x, pcity->y, TILE_KNOWN);
  528.          }
  529.        }
  530.        set_invention(pplayer, pplayer->research.researching, TECH_KNOWN);
  531.       }
  532.       else {
  533.        pplayer->future_tech++;
  534.        notify_player(pplayer,
  535.                      "Game: You gain knowledge about Future Tech. %d.",
  536.                      pplayer->future_tech);
  537.       }
  538.       remove_obsolete_buildings(pplayer);
  539.       
  540.       if (get_invention(pplayer,wasres)==TECH_KNOWN) {
  541.     if (!choose_goal_tech(pplayer))
  542.       choose_random_tech(pplayer);
  543.     pplayer->research.researched=res;
  544.       }  else {
  545.     pplayer->research.researched=res;
  546.     pplayer->research.researching=wasres;
  547.       }
  548.      do_free_cost(pplayer);
  549.     }
  550.     break;
  551.   case 8:
  552.   case 9:
  553.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  554.              "Game: A band of friendly mercenaries joins your cause.");
  555.     create_unit(pplayer, punit->x, punit->y, find_a_unit_type(), 0, punit->homecity, -1);
  556.     break;
  557.   case 10:
  558.     if (in_city_radius(punit->x, punit->y))
  559.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  560.                "Game: An abandoned village is here.");
  561.     else {
  562.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  563.                "Game: Your unit has been cowardly slaughtered by a band of barbarians");
  564.       wipe_unit(pplayer, punit);
  565.     }
  566.     break;
  567.   case 11:
  568.     if (is_ok_city_spot(punit->x, punit->y)) {
  569.       map_set_special(punit->x, punit->y, S_ROAD);
  570.       send_tile_info(0, punit->x, punit->y, TILE_KNOWN);
  571.  
  572.       create_city(pplayer, punit->x, punit->y, city_name_suggestion(pplayer));
  573.     } else {
  574.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  575.            "Game: Friendly nomads are impressed by you, and join you");
  576.       create_unit(pplayer, punit->x, punit->y, U_SETTLERS, 0, punit->homecity, -1);
  577.     }
  578.     break;
  579.   }
  580.   send_player_info(pplayer, pplayer);
  581. }
  582. /**************************************************************************
  583.   Will try to move to/attack the tile dest_x,dest_y.  Returns true if this
  584.   could be done, false if it couldn't for some reason.
  585. **************************************************************************/
  586. int handle_unit_move_request(struct player *pplayer, struct unit *punit,
  587.                   int dest_x, int dest_y)
  588. {
  589.   int unit_id;
  590.   struct unit *pdefender, *ferryboat, *bodyguard;
  591.   struct unit_list cargolist;
  592.   
  593.   unit_id=punit->id;
  594.   if (do_airline(punit, dest_x, dest_y))
  595.     return 1;
  596.   pdefender=get_defender(pplayer, punit, dest_x, dest_y);
  597.  
  598.   if(pdefender && pdefender->owner!=punit->owner) {
  599.     if(can_unit_attack_tile(punit,dest_x , dest_y)) {
  600.       if(punit->moves_left<=0)  {
  601.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  602.              "Game: This unit has no moves left.");
  603.         return 0;
  604.       } else if (pplayer->ai.control && punit->activity == ACTIVITY_GOTO) {
  605. /* DO NOT Auto-attack.  Findvictim routine will decide if we should. */
  606.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  607.              "Game: Aborting GOTO for AI attack procedures.");
  608.         return 0;
  609.       } else {
  610. if (pplayer->ai.control && get_transporter_capacity(punit))
  611. printf("Hey, idiot! What's wrong with you?? %s\n", unit_types[99999999].name);
  612.     handle_unit_attack_request(pplayer, punit, pdefender);
  613.         return 1;
  614.       };
  615.     } else {
  616.       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  617.                "Game: You can't attack there.");
  618.       return 0;
  619.     };
  620.   } else if (punit->ai.bodyguard > 0 && (bodyguard = unit_list_find(&map_get_tile(punit->x,
  621.       punit->y)->units, punit->ai.bodyguard)) && !bodyguard->moves_left) {
  622.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  623.        "Game: %s doesn't want to leave its bodyguard.", unit_types[punit->type].name);
  624.   } else if(can_unit_move_to_tile(punit, dest_x, dest_y) && try_move_unit(punit, dest_x, dest_y)) {
  625.     int src_x, src_y;
  626.     struct city *pcity;
  627.     
  628.     if((pcity=map_get_city(dest_x, dest_y))) {
  629.       if ((pcity->owner!=punit->owner && (is_air_unit(punit) || 
  630.                       !is_military_unit(punit)))) {
  631.     notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
  632.              "Game: Only ground troops can take over a city.");
  633.     return 0;
  634.       }
  635.     }
  636.  
  637.     if(!unit_list_find(&pplayer->units, unit_id))
  638.       return 0; /* diplomat or caravan action killed unit */
  639.  
  640.     connection_do_buffer(pplayer->conn);
  641.  
  642.     /* light the squares the unit is entering */
  643.     light_square(pplayer, dest_x, dest_y, 
  644.          get_unit_type(punit->type)->vision_range);
  645.     
  646.     /* ok now move the unit */
  647.  
  648.     if (punit->ai.ferryboat) {
  649.       ferryboat = unit_list_find(&map_get_tile(punit->x, punit->y)->units,
  650.                   punit->ai.ferryboat);
  651.       if (ferryboat) {
  652. /*printf("%d disembarking from ferryboat %d\n", punit->id, punit->ai.ferryboat);*/
  653.         ferryboat->ai.passenger = 0;
  654.         punit->ai.ferryboat = 0;
  655.       }
  656.     } /* just clearing that up */
  657.  
  658.     src_x=punit->x;
  659.     src_y=punit->y;
  660.  
  661.     unit_list_unlink(&map_get_tile(src_x, src_y)->units, punit);
  662.  
  663.     if(get_transporter_capacity(punit)) {
  664.       transporter_cargo_to_unitlist(punit, &cargolist);
  665.       unit_list_iterate(cargolist, pcarried) { 
  666.     pcarried->x=dest_x;
  667.     pcarried->y=dest_y;
  668.     send_unit_info(0, pcarried, 1);
  669.       }
  670.       unit_list_iterate_end;
  671.     }
  672.       
  673.     if((punit->moves_left-=map_move_cost(punit, dest_x, dest_y))<0)
  674.       punit->moves_left=0;
  675.  
  676.     punit->x=dest_x;
  677.     punit->y=dest_y;
  678.  
  679.     send_unit_info(0, punit, 1);
  680.     
  681.     unit_list_insert(&map_get_tile(dest_x, dest_y)->units, punit);
  682.  
  683.     if(get_transporter_capacity(punit)) {
  684.       move_unit_list_to_tile(&cargolist, punit->x, punit->y);
  685.       genlist_unlink_all(&cargolist.list); 
  686.     }
  687.       
  688.     /* ok entered new tile */
  689.     
  690.     if(pcity)
  691.       handle_unit_enter_city(pplayer, pcity);
  692.  
  693.     if((map_get_tile(dest_x, dest_y)->special&S_HUT))
  694.       handle_unit_enter_hut(punit);
  695.     
  696.     connection_do_unbuffer(pplayer->conn);
  697.  
  698. /* bodyguard code */
  699.     if(unit_list_find(&pplayer->units, unit_id)) {
  700.       if (punit->ai.bodyguard > 0) {
  701.         bodyguard = unit_list_find(&(map_get_tile(src_x, src_y)->units),
  702.                     punit->ai.bodyguard);
  703.         if (bodyguard) {
  704.           handle_unit_activity_request(pplayer, bodyguard, ACTIVITY_IDLE);
  705. /* may be fortifying, have to FIX this eventually -- Syela */
  706. /*printf("Dragging %s from (%d,%d)->(%d,%d) (Success=%d)\n",
  707. unit_types[bodyguard->type].name, src_x, src_y, dest_x, dest_y,
  708. handle_unit_move_request(pplayer, bodyguard, dest_x, dest_y));*/
  709.           handle_unit_move_request(pplayer, bodyguard, dest_x, dest_y);
  710.           handle_unit_activity_request(pplayer, bodyguard, ACTIVITY_FORTIFY);
  711.         }
  712.       }
  713.     }
  714.     return 1;
  715.   }
  716.   return 0;
  717. }
  718. /**************************************************************************
  719. ...
  720. **************************************************************************/
  721. void handle_unit_help_build_wonder(struct player *pplayer, 
  722.                    struct packet_unit_request *req)
  723. {
  724.   struct unit *punit;
  725.   
  726.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  727.     struct city *pcity_dest;
  728.     
  729.     pcity_dest=find_city_by_id(req->city_id);
  730.     
  731.     if(unit_flag(punit->type, F_CARAVAN) && pcity_dest &&
  732.        unit_can_help_build_wonder(punit, pcity_dest)) {
  733.       pcity_dest->shield_stock+=50;
  734.       if (build_points_left(pcity_dest) < 0) {
  735.     pcity_dest->shield_stock = improvement_value(pcity_dest->currently_building);
  736.       }
  737.  
  738.       notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT,
  739.           "Game: Your %s help building the %s in %s. (%d remaining)", 
  740.                unit_name(punit->type),
  741.                get_improvement_type(pcity_dest->currently_building)->name,
  742.                pcity_dest->name, 
  743.                build_points_left(pcity_dest)
  744.                );
  745.  
  746.       wipe_unit(0, punit);
  747.       send_player_info(pplayer, pplayer);
  748.       send_city_info(pplayer, pcity_dest, 0);
  749.     }
  750.   }
  751. }
  752.  
  753. /**************************************************************************
  754. ...
  755. **************************************************************************/
  756. void handle_unit_establish_trade(struct player *pplayer, 
  757.                  struct packet_unit_request *req)
  758. {
  759.   struct unit *punit;
  760.   
  761.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  762.     
  763.     struct city *pcity_homecity, *pcity_dest;
  764.     
  765.     pcity_homecity=city_list_find_id(&pplayer->cities, punit->homecity);
  766.     pcity_dest=find_city_by_id(req->city_id);
  767.     
  768.     if(unit_flag(punit->type, F_CARAVAN) && pcity_homecity && pcity_dest && 
  769.        is_tiles_adjacent(punit->x, punit->y, pcity_dest->x, pcity_dest->y) &&
  770.        can_establish_trade_route(pcity_homecity, pcity_dest)) {
  771.       int revenue;
  772.  
  773.       revenue=establish_trade_route(pcity_homecity, pcity_dest);
  774.       notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT,
  775.                "Game: Your %s has arrived in %s, and revenues amount to %d in gold.", 
  776.                unit_name(punit->type), pcity_dest->name, revenue);
  777.       wipe_unit(0, punit);
  778.       pplayer->economic.gold+=revenue;
  779.       send_player_info(pplayer, pplayer);
  780.       city_refresh(pcity_homecity);
  781.       city_refresh(pcity_dest);
  782.       send_city_info(pplayer, pcity_homecity, 0);
  783.       send_city_info(city_owner(pcity_dest), pcity_dest, 0);
  784.     }
  785.   }
  786. }
  787. /**************************************************************************
  788. ...
  789. **************************************************************************/
  790. void handle_unit_enter_city(struct player *pplayer, struct city *pcity)
  791. {
  792.   int i, x, y, old_id;
  793.   int coins;
  794.   struct city *pc2;
  795.   struct player *cplayer;
  796.   if(pplayer->player_no!=pcity->owner) {
  797.     struct city *pnewcity;
  798.     cplayer=&game.players[pcity->owner];
  799.     pcity->size--;
  800.     if (pcity->size<1) {
  801.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
  802.                "Game: You destroy %s completely.", pcity->name);
  803.       notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, 
  804.             "Game: %s has been destroyed by %s", 
  805.             pcity->name, pplayer->name);
  806.       remove_city_from_minimap(pcity->x, pcity->y);
  807.       remove_city(pcity);
  808.       return;
  809.     }
  810.     city_auto_remove_worker(pcity);
  811.     get_a_tech(pplayer, cplayer);
  812.     coins=cplayer->economic.gold;
  813.     coins=myrand((coins/20)+1)+(coins*(pcity->size))/200;
  814.     pplayer->economic.gold+=coins;
  815.     cplayer->economic.gold-=coins;
  816.     send_player_info(cplayer, cplayer);
  817.     if (pcity->owner != pplayer->player_no) {
  818.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  819.                "Game: You conquer %s, your lootings accumulate to %d gold", 
  820.                pcity->name, coins);
  821.       notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, 
  822.                "Game: %s conquered %s and looted %d gold from the city.",
  823.                pplayer->name, pcity->name, coins);
  824.     } else {
  825.       notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, 
  826.                "Game: You have liberated %s!! lootings accumulate to %d gold",                pcity->name, coins);
  827.       
  828.       notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, 
  829.                "Game: %s liberated %s and looted %d gold from the city.",               pplayer->name, pcity->name, coins);
  830.     }
  831.  
  832.     pnewcity=(struct city *)malloc(sizeof(struct city));
  833.     make_partisans(pcity);
  834.     *pnewcity=*pcity;
  835.     remove_city(pcity);
  836.     for (i=0;i<4;i++) {
  837.       pc2=find_city_by_id(pnewcity->trade[i]);
  838.       if (can_establish_trade_route(pnewcity, pc2))    
  839.     establish_trade_route(pnewcity, pc2);
  840.     }
  841.     /* now set things up for the new owner */
  842.     
  843.     old_id = pnewcity->id;
  844.  
  845.     pnewcity->id=get_next_id_number();
  846.     add_city_to_cache(pnewcity);
  847.     for (i = 0; i < B_LAST; i++) {
  848.       if (is_wonder(i) && city_got_building(pnewcity, i))
  849.         game.global_wonders[i] = pnewcity->id;
  850.     } /* Once I added this block, why was the below for() needed? -- Syela */
  851.     pnewcity->owner=pplayer->player_no;
  852.  
  853.     unit_list_init(&pnewcity->units_supported);
  854.     city_list_insert(&pplayer->cities, pnewcity);
  855.     
  856.     /* Transfer wonders to new owner - Kris Bubendorfer*/
  857.  
  858.     for(i = B_APOLLO;i <= B_WOMENS; i++)
  859.       if(game.global_wonders[i] == old_id)
  860.     game.global_wonders[i] = pnewcity->id;
  861.     map_set_city(pnewcity->x, pnewcity->y, pnewcity);
  862.  
  863.     if ((get_invention(pplayer, A_RAILROAD)==TECH_KNOWN) &&
  864.        (get_invention(cplayer, A_RAILROAD)!=TECH_KNOWN) &&
  865.        (!(map_get_special(pnewcity->x,pnewcity->y)&S_RAILROAD))) {
  866.       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);
  867.       map_set_special(pnewcity->x, pnewcity->y, S_RAILROAD);
  868.       send_tile_info(0, pnewcity->x, pnewcity->y, TILE_KNOWN);
  869.     }
  870.  
  871.     raze_city(pnewcity);
  872.  
  873.     if (pplayer->ai.control) { /* let there be light! */
  874.       for (y=0;y<5;y++) {
  875.         for (x=0;x<5;x++) {
  876.           if ((x==0 || x==4) && (y==0 || y==4))
  877.             continue;
  878.           light_square(pplayer, x+pnewcity->x-2, y+pnewcity->y-2, 0);
  879.         }
  880.       }
  881.     }
  882.  
  883. /* maybe should auto_arr or otherwise reset ->worked? -- Syela */
  884.  
  885.     city_refresh(pnewcity);
  886.     initialize_infrastructure_cache(pnewcity);
  887.     send_city_info(0, pnewcity, 0);
  888.     send_player_info(pplayer, pplayer);
  889.   }
  890. }
  891.  
  892. /**************************************************************************
  893. ...
  894. **************************************************************************/
  895. void handle_unit_auto_request(struct player *pplayer, 
  896.                   struct packet_unit_request *req)
  897. {
  898.   struct unit *punit;
  899.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  900.     punit->ai.control=1;
  901.     send_unit_info(pplayer, punit, 0);
  902.   }
  903. }
  904.  
  905. /**************************************************************************
  906. ...
  907. **************************************************************************/
  908. void handle_unit_activity_request(struct player *pplayer, struct unit *punit, 
  909.                   enum unit_activity new_activity)
  910. {
  911.   if((punit->moves_left>0 || punit->activity==ACTIVITY_GOTO ||
  912.       new_activity == ACTIVITY_EXPLORE) && 
  913.      can_unit_do_activity(punit, new_activity)) {
  914.     punit->activity=new_activity;
  915.     punit->activity_count=0;
  916.     send_unit_info(0, punit, 0);
  917.   }
  918. }
  919.  
  920. /**************************************************************************
  921. ...
  922. **************************************************************************/
  923. void handle_unit_unload_request(struct player *pplayer, 
  924.                 struct packet_unit_request *req)
  925. {
  926.   struct unit *punit;
  927.   if((punit=unit_list_find(&pplayer->units, req->unit_id))) {
  928.     unit_list_iterate(map_get_tile(punit->x, punit->y)->units, punit2) {
  929.       if(punit2->activity==ACTIVITY_SENTRY) {
  930.     set_unit_activity(punit2, ACTIVITY_IDLE);
  931.     send_unit_info(0, punit2, 0);
  932.       }
  933.     }
  934.     unit_list_iterate_end;
  935.   }
  936. }
  937.