home *** CD-ROM | disk | FTP | other *** search
Wrap
/********************************************************************** Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ***********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <player.h> #include <unithand.h> #include <unittools.h> #include <unitfunc.h> #include <packets.h> #include <civserver.h> #include <map.h> #include <maphand.h> #include <cityhand.h> #include <citytools.h> #include <cityturn.h> #include <unit.h> #include <plrhand.h> #include <city.h> #include <log.h> #include <mapgen.h> #include <events.h> #include <shared.h> #include <aiunit.h> #include <settlers.h> void do_unit_goto(struct player *pplayer, struct unit *punit); /************************************************************************** ... **************************************************************************/ void handle_unit_goto_tile(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { punit->goto_dest_x=req->x; punit->goto_dest_y=req->y; punit->activity=ACTIVITY_GOTO; punit->activity_count=0; send_unit_info(0, punit, 0); do_unit_goto(pplayer, punit); } } /************************************************************************** ... **************************************************************************/ void handle_upgrade_unit_request(struct player *pplayer, struct packet_unittype_info *packet) { int cost; int to_unit; int upgraded = 0; if ((to_unit =can_upgrade_unittype(pplayer, packet->type)) == -1) { notify_player(pplayer, "Game: illegal package, can't upgrade %s (yet).", unit_types[packet->type].name); return; } cost = unit_upgrade_price(pplayer, packet->type, to_unit); unit_list_iterate(pplayer->units, punit) { if (cost > pplayer->economic.gold) break; if (punit->type == packet->type && map_get_city(punit->x, punit->y)) { pplayer->economic.gold -= cost; if (punit->hp==get_unit_type(punit->type)->hp) { punit->hp=get_unit_type(to_unit)->hp; } punit->type = to_unit; send_unit_info(0, punit, 0); upgraded++; } } unit_list_iterate_end; if (upgraded > 0) { notify_player(pplayer, "Game: %d %s upgraded to %s for %d credits", upgraded, unit_types[packet->type].name, unit_types[to_unit].name, cost * upgraded); send_player_info(pplayer, pplayer); } else { notify_player(pplayer, "Game: No units could be upgraded."); } } /*************************************************************** ... Tell the client the cost of inciting a revolt or bribing a unit ***************************************************************/ void handle_incite_inq(struct player *pplayer, struct packet_generic_integer *packet) { struct city *pcity=find_city_by_id(packet->value); struct unit *punit=find_unit_by_id(packet->value); struct packet_generic_values req; if(pcity) { city_incite_cost(pcity); req.id=packet->value; req.value1=pcity->incite_revolt_cost; send_packet_generic_values(pplayer->conn, PACKET_INCITE_COST, &req); return; } if(punit) { punit->bribe_cost = unit_bribe_cost(punit); req.id=packet->value; req.value1=punit->bribe_cost; send_packet_generic_values(pplayer->conn, PACKET_INCITE_COST, &req); } } /*************************************************************** ... ***************************************************************/ void handle_diplomat_action(struct player *pplayer, struct packet_diplomat_action *packet) { struct unit *pdiplomat=unit_list_find(&pplayer->units, packet->diplomat_id); struct unit *pvictim=find_unit_by_id(packet->target_id); struct city *pcity=find_city_by_id(packet->target_id); if (!pdiplomat) return; if (!unit_flag(pdiplomat->type, F_DIPLOMAT)) return; if(pdiplomat && pdiplomat->moves_left>0) { pdiplomat->moves_left=0; send_unit_info(pplayer, pdiplomat, 0); switch(packet->action_type) { case DIPLOMAT_BRIBE: if(pvictim && diplomat_can_do_action(pdiplomat, DIPLOMAT_BRIBE, pvictim->x, pvictim->y)) diplomat_bribe(pplayer, pdiplomat, pvictim); break; case DIPLOMAT_SABOTAGE: if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_SABOTAGE, pcity->x, pcity->y)) diplomat_sabotage(pplayer, pdiplomat, pcity); break; case SPY_POISON: if(pcity && diplomat_can_do_action(pdiplomat, SPY_POISON, pcity->x, pcity->y)) spy_poison(pplayer, pdiplomat, pcity); break; case DIPLOMAT_EMBASSY: if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_EMBASSY, pcity->x, pcity->y)) { pplayer->embassy|=(1<<pcity->owner); send_player_info(pplayer, pplayer); notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: You have established an embassy in %s", pcity->name); notify_player_ex(&game.players[pcity->owner], pcity->x, pcity->y, E_DIPLOMATED, "Game: The %s have established an embassy in %s", get_race_name_plural(pplayer->race), pcity->name); } wipe_unit(0, pdiplomat); break; case DIPLOMAT_INCITE: if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_INCITE, pcity->x, pcity->y)) diplomat_incite(pplayer, pdiplomat, pcity); break; case DIPLOMAT_STEAL: if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_STEAL, pcity->x, pcity->y)) diplomat_get_tech(pplayer, pdiplomat, pcity); break; } } } /************************************************************************** ... **************************************************************************/ void handle_unit_change_homecity(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { struct city *pcity; if((pcity=city_list_find_id(&pplayer->cities, req->city_id))) { unit_list_insert(&pcity->units_supported, punit); if((pcity=city_list_find_id(&pplayer->cities, punit->homecity))) unit_list_unlink(&pcity->units_supported, punit); punit->homecity=req->city_id; send_unit_info(pplayer, punit, 0); } } } /************************************************************************** ... **************************************************************************/ void handle_unit_disband(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; struct city *pcity; /* give 1/2 of the worth of the unit, to the currently builded thing have to be on the location of the city_square */ if((punit=unit_list_find(&pplayer->units, req->unit_id))) { if ((pcity=map_get_city(punit->x, punit->y))) { pcity->shield_stock+=(get_unit_type(punit->type)->build_cost/2); send_city_info(pplayer, pcity, 0); } wipe_unit(pplayer, punit); } } /************************************************************************** ... **************************************************************************/ void handle_unit_build_city(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; char *name; struct city *pcity; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { if (!unit_flag(punit->type, F_SETTLERS)) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You need a settler to build a city."); return; } if(!punit->moves_left) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Settler has no moves left to build city."); return; } if ((pcity=map_get_city(punit->x, punit->y))) { if (pcity->size>8) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Your settlers doesn't feel comfortable here."); return; } else { pcity->size++; if (!add_adjust_workers(pcity)) auto_arrange_workers(pcity); wipe_unit(0, punit); send_city_info(pplayer, pcity, 0); notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: Settlers added to aid %s in growing", pcity->name); return; } } if(can_unit_build_city(punit)) { if(!(name=get_sane_name(req->name))) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Let's not build a city with such a stupid name."); return; } send_remove_unit(0, req->unit_id); map_set_special(punit->x, punit->y, S_ROAD); if (get_invention(pplayer, A_RAILROAD)==TECH_KNOWN) map_set_special(punit->x, punit->y, S_RAILROAD); send_tile_info(0, punit->x, punit->y, TILE_KNOWN); create_city(pplayer, punit->x, punit->y, name); game_remove_unit(req->unit_id); } else notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Can't place city here."); } } /************************************************************************** ... **************************************************************************/ void handle_unit_info(struct player *pplayer, struct packet_unit_info *pinfo) { struct unit *punit; punit=unit_list_find(&pplayer->units, pinfo->id); if(punit) { if(punit->ai.control) { punit->ai.control=0; } if(punit->activity!=pinfo->activity) handle_unit_activity_request(pplayer, punit, pinfo->activity); else if (!same_pos(punit->x, punit->y, pinfo->x, pinfo->y)) handle_unit_move_request(pplayer, punit, pinfo->x, pinfo->y); } } /************************************************************************** ... **************************************************************************/ void handle_move_unit(struct player *pplayer, struct packet_move_unit *pmove) { struct unit *punit; punit=unit_list_find(&pplayer->units, pmove->unid); if(punit) { handle_unit_move_request(pplayer, punit, pmove->x, pmove->y); } } /************************************************************************** ... **************************************************************************/ void handle_unit_attack_request(struct player *pplayer, struct unit *punit, struct unit *pdefender) { int o; struct packet_unit_combat combat; struct unit *plooser, *pwinner; struct city *pcity; struct city *incity, *nearcity1, *nearcity2; incity = map_get_city(pdefender->x, pdefender->y); punit->moves_left-=3; if(punit->moves_left<0) punit->moves_left=0; if(punit->type==U_NUCLEAR) { struct packet_nuke_tile packet; packet.x=pdefender->x; packet.y=pdefender->y; if ((pcity=sdi_defense_close(punit->owner, pdefender->x, pdefender->y))) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Your Nuclear missile has been shot down by SDI, what a waste."); notify_player_ex(&game.players[pcity->owner], pdefender->x, pdefender->y, E_NOEVENT, "Game: The nuclear attack on %s was avoided by your SDI defense", pcity->name); wipe_unit(0, punit); return; } for(o=0; o<game.nplayers; o++) send_packet_nuke_tile(game.players[o].conn, &packet); do_nuclear_explosion(pdefender->x, pdefender->y); return; } unit_versus_unit(punit, pdefender); if (punit->hp && (pcity=map_get_city(pdefender->x, pdefender->y)) && pcity->size>1 && !city_got_citywalls(pcity) && is_ground_unit(punit)) { pcity->size--; city_auto_remove_worker(pcity); city_refresh(pcity); send_city_info(0, pcity, 0); } if (unit_flag(punit->type, F_ONEATTACK)) punit->moves_left = 0; pwinner=(punit->hp) ? punit : pdefender; plooser=(pdefender->hp) ? punit : pdefender; combat.attacker_unit_id=punit->id; combat.defender_unit_id=pdefender->id; combat.attacker_hp=punit->hp; combat.defender_hp=pdefender->hp; combat.make_winner_veteran=pwinner->veteran?1:0; for(o=0; o<game.nplayers; o++) if(map_get_known(punit->x, punit->y, &game.players[o]) || map_get_known(pdefender->x, pdefender->y, &game.players[o])) send_packet_unit_combat(game.players[o].conn, &combat); nearcity1 = dist_nearest_enemy_city(get_player(pwinner->owner), pdefender->x, pdefender->y); nearcity2 = dist_nearest_enemy_city(get_player(plooser->owner), pdefender->x, pdefender->y); if(punit==plooser) { if (incity) notify_player_ex(&game.players[pwinner->owner], pwinner->x, pwinner->y, E_UNIT_WIN, "Game: Your %s in %s survived the pathetic attack from %s's %s.", unit_name(pwinner->type), incity->name, game.players[plooser->owner].name, unit_name(punit->type)); else if (nearcity1 && is_tiles_adjacent(pdefender->x, pdefender->y, nearcity1->x, nearcity1->y)) notify_player_ex(&game.players[pwinner->owner], pwinner->x, pwinner->y, E_UNIT_WIN, "Game: Your %s outside %s survived the pathetic attack from %s's %s.", unit_name(pwinner->type), nearcity1->name, game.players[plooser->owner].name, unit_name(punit->type)); else if (nearcity1) notify_player_ex(&game.players[pwinner->owner], pwinner->x, pwinner->y, E_UNIT_WIN, "Game: Your %s near %s survived the pathetic attack from %s's %s.", unit_name(pwinner->type), nearcity1->name, game.players[plooser->owner].name, unit_name(punit->type)); else notify_player_ex(&game.players[pwinner->owner], pwinner->x, pwinner->y, E_UNIT_WIN, "Game: Your %s survived the pathetic attack from %s's %s.", unit_name(pwinner->type), game.players[plooser->owner].name, unit_name(punit->type)); if (incity) notify_player_ex(&game.players[plooser->owner], pdefender->x, pdefender->y, E_NOEVENT, "Game: Your attacking %s failed against %s's %s at %s!", unit_name(plooser->type), game.players[pwinner->owner].name, unit_name(pwinner->type), incity->name); else if (nearcity2 && is_tiles_adjacent(pdefender->x, pdefender->y, nearcity2->x, nearcity2->y)) notify_player_ex(&game.players[plooser->owner], pdefender->x, pdefender->y, E_NOEVENT, "Game: Your attacking %s failed against %s's %s outside %s!", unit_name(plooser->type), game.players[pwinner->owner].name, unit_name(pwinner->type), nearcity2->name); else if (nearcity2) notify_player_ex(&game.players[plooser->owner], pdefender->x, pdefender->y, E_NOEVENT, "Game: Your attacking %s failed against %s's %s near %s!", unit_name(plooser->type), game.players[pwinner->owner].name, unit_name(pwinner->type), nearcity2->name); else notify_player_ex(&game.players[plooser->owner], pdefender->x, pdefender->y, E_NOEVENT, "Game: Your attacking %s failed against %s's %s!", unit_name(plooser->type), game.players[pwinner->owner].name, unit_name(pwinner->type)); wipe_unit(pplayer, plooser); } else { if (incity) notify_player_ex(&game.players[pwinner->owner], punit->x, punit->y, E_NOEVENT, "Game: Your attacking %s was successful against %s's %s at %s!", unit_name(pwinner->type), game.players[plooser->owner].name, unit_name(plooser->type), incity->name); else if (nearcity1 && is_tiles_adjacent(pdefender->x, pdefender->y, nearcity1->x, nearcity1->y)) notify_player_ex(&game.players[pwinner->owner], punit->x, punit->y, E_NOEVENT, "Game: Your attacking %s was successful against %s's %s outside %s!", unit_name(pwinner->type), game.players[plooser->owner].name, unit_name(plooser->type), nearcity1->name); else if (nearcity1) notify_player_ex(&game.players[pwinner->owner], punit->x, punit->y, E_NOEVENT, "Game: Your attacking %s was successful against %s's %s near %s!", unit_name(pwinner->type), game.players[plooser->owner].name, unit_name(plooser->type), nearcity1->name); else notify_player_ex(&game.players[pwinner->owner], punit->x, punit->y, E_NOEVENT, "Game: Your attacking %s was successful against %s's %s!", unit_name(pwinner->type), game.players[plooser->owner].name, unit_name(plooser->type)); kill_unit(pwinner, plooser); /* no longer pplayer - want better msgs -- Syela */ } if (pwinner == punit && unit_flag(punit->type, F_MISSILE)) { wipe_unit(pplayer, pwinner); return; } send_unit_info(0, pwinner, 0); } /************************************************************************** ... **************************************************************************/ void handle_unit_enter_hut(struct unit *punit) { struct player *pplayer=&game.players[punit->owner]; if (is_air_unit(punit)) return; map_get_tile(punit->x, punit->y)->special^=S_HUT; send_tile_info(0, punit->x, punit->y, TILE_KNOWN); switch (myrand(12)) { case 0: notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You found 25 credits."); pplayer->economic.gold+=25; break; case 1: case 2: case 3: notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You found 50 credits."); pplayer->economic.gold+=50; break; case 4: notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You found 100 credits"); pplayer->economic.gold+=100; break; case 5: case 6: case 7: /*this function is hmmm a hack */ notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You found ancient scrolls of wisdom."); { int res=pplayer->research.researched; int wasres=pplayer->research.researching; choose_random_tech(pplayer); pplayer->research.researchpoints++; if (pplayer->research.researching!=A_NONE) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You gain knowledge about %s.", advances[pplayer->research.researching].name); if (pplayer->research.researching==A_RAILROAD) { /* struct city_list cl=pplayer->cities;*/ struct genlist_iterator myiter; genlist_iterator_init(&myiter, &pplayer->cities.list, 0); 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."); for(; ITERATOR_PTR(myiter); ITERATOR_NEXT(myiter)) { struct city *pcity=(struct city *)ITERATOR_PTR(myiter); map_set_special(pcity->x, pcity->y, S_RAILROAD); send_tile_info(0, pcity->x, pcity->y, TILE_KNOWN); } } set_invention(pplayer, pplayer->research.researching, TECH_KNOWN); } else { pplayer->future_tech++; notify_player(pplayer, "Game: You gain knowledge about Future Tech. %d.", pplayer->future_tech); } remove_obsolete_buildings(pplayer); if (get_invention(pplayer,wasres)==TECH_KNOWN) { if (!choose_goal_tech(pplayer)) choose_random_tech(pplayer); pplayer->research.researched=res; } else { pplayer->research.researched=res; pplayer->research.researching=wasres; } do_free_cost(pplayer); } break; case 8: case 9: notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: A band of friendly mercenaries joins your cause."); create_unit(pplayer, punit->x, punit->y, find_a_unit_type(), 0, punit->homecity, -1); break; case 10: if (in_city_radius(punit->x, punit->y)) notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: An abandoned village is here."); else { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Your unit has been cowardly slaughtered by a band of barbarians"); wipe_unit(pplayer, punit); } break; case 11: if (is_ok_city_spot(punit->x, punit->y)) { map_set_special(punit->x, punit->y, S_ROAD); send_tile_info(0, punit->x, punit->y, TILE_KNOWN); create_city(pplayer, punit->x, punit->y, city_name_suggestion(pplayer)); } else { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Friendly nomads are impressed by you, and join you"); create_unit(pplayer, punit->x, punit->y, U_SETTLERS, 0, punit->homecity, -1); } break; } send_player_info(pplayer, pplayer); } /************************************************************************** Will try to move to/attack the tile dest_x,dest_y. Returns true if this could be done, false if it couldn't for some reason. **************************************************************************/ int handle_unit_move_request(struct player *pplayer, struct unit *punit, int dest_x, int dest_y) { int unit_id; struct unit *pdefender, *ferryboat, *bodyguard; struct unit_list cargolist; unit_id=punit->id; if (do_airline(punit, dest_x, dest_y)) return 1; pdefender=get_defender(pplayer, punit, dest_x, dest_y); if(pdefender && pdefender->owner!=punit->owner) { if(can_unit_attack_tile(punit,dest_x , dest_y)) { if(punit->moves_left<=0) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: This unit has no moves left."); return 0; } else if (pplayer->ai.control && punit->activity == ACTIVITY_GOTO) { /* DO NOT Auto-attack. Findvictim routine will decide if we should. */ notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Aborting GOTO for AI attack procedures."); return 0; } else { if (pplayer->ai.control && get_transporter_capacity(punit)) printf("Hey, idiot! What's wrong with you?? %s\n", unit_types[99999999].name); handle_unit_attack_request(pplayer, punit, pdefender); return 1; }; } else { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: You can't attack there."); return 0; }; } else if (punit->ai.bodyguard > 0 && (bodyguard = unit_list_find(&map_get_tile(punit->x, punit->y)->units, punit->ai.bodyguard)) && !bodyguard->moves_left) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: %s doesn't want to leave its bodyguard.", unit_types[punit->type].name); } else if(can_unit_move_to_tile(punit, dest_x, dest_y) && try_move_unit(punit, dest_x, dest_y)) { int src_x, src_y; struct city *pcity; if((pcity=map_get_city(dest_x, dest_y))) { if ((pcity->owner!=punit->owner && (is_air_unit(punit) || !is_military_unit(punit)))) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, "Game: Only ground troops can take over a city."); return 0; } } if(!unit_list_find(&pplayer->units, unit_id)) return 0; /* diplomat or caravan action killed unit */ connection_do_buffer(pplayer->conn); /* light the squares the unit is entering */ light_square(pplayer, dest_x, dest_y, get_unit_type(punit->type)->vision_range); /* ok now move the unit */ if (punit->ai.ferryboat) { ferryboat = unit_list_find(&map_get_tile(punit->x, punit->y)->units, punit->ai.ferryboat); if (ferryboat) { /*printf("%d disembarking from ferryboat %d\n", punit->id, punit->ai.ferryboat);*/ ferryboat->ai.passenger = 0; punit->ai.ferryboat = 0; } } /* just clearing that up */ src_x=punit->x; src_y=punit->y; unit_list_unlink(&map_get_tile(src_x, src_y)->units, punit); if(get_transporter_capacity(punit)) { transporter_cargo_to_unitlist(punit, &cargolist); unit_list_iterate(cargolist, pcarried) { pcarried->x=dest_x; pcarried->y=dest_y; send_unit_info(0, pcarried, 1); } unit_list_iterate_end; } if((punit->moves_left-=map_move_cost(punit, dest_x, dest_y))<0) punit->moves_left=0; punit->x=dest_x; punit->y=dest_y; send_unit_info(0, punit, 1); unit_list_insert(&map_get_tile(dest_x, dest_y)->units, punit); if(get_transporter_capacity(punit)) { move_unit_list_to_tile(&cargolist, punit->x, punit->y); genlist_unlink_all(&cargolist.list); } /* ok entered new tile */ if(pcity) handle_unit_enter_city(pplayer, pcity); if((map_get_tile(dest_x, dest_y)->special&S_HUT)) handle_unit_enter_hut(punit); connection_do_unbuffer(pplayer->conn); /* bodyguard code */ if(unit_list_find(&pplayer->units, unit_id)) { if (punit->ai.bodyguard > 0) { bodyguard = unit_list_find(&(map_get_tile(src_x, src_y)->units), punit->ai.bodyguard); if (bodyguard) { handle_unit_activity_request(pplayer, bodyguard, ACTIVITY_IDLE); /* may be fortifying, have to FIX this eventually -- Syela */ /*printf("Dragging %s from (%d,%d)->(%d,%d) (Success=%d)\n", unit_types[bodyguard->type].name, src_x, src_y, dest_x, dest_y, handle_unit_move_request(pplayer, bodyguard, dest_x, dest_y));*/ handle_unit_move_request(pplayer, bodyguard, dest_x, dest_y); handle_unit_activity_request(pplayer, bodyguard, ACTIVITY_FORTIFY); } } } return 1; } return 0; } /************************************************************************** ... **************************************************************************/ void handle_unit_help_build_wonder(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { struct city *pcity_dest; pcity_dest=find_city_by_id(req->city_id); if(unit_flag(punit->type, F_CARAVAN) && pcity_dest && unit_can_help_build_wonder(punit, pcity_dest)) { pcity_dest->shield_stock+=50; if (build_points_left(pcity_dest) < 0) { pcity_dest->shield_stock = improvement_value(pcity_dest->currently_building); } notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, "Game: Your %s help building the %s in %s. (%d remaining)", unit_name(punit->type), get_improvement_type(pcity_dest->currently_building)->name, pcity_dest->name, build_points_left(pcity_dest) ); wipe_unit(0, punit); send_player_info(pplayer, pplayer); send_city_info(pplayer, pcity_dest, 0); } } } /************************************************************************** ... **************************************************************************/ void handle_unit_establish_trade(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { struct city *pcity_homecity, *pcity_dest; pcity_homecity=city_list_find_id(&pplayer->cities, punit->homecity); pcity_dest=find_city_by_id(req->city_id); if(unit_flag(punit->type, F_CARAVAN) && pcity_homecity && pcity_dest && is_tiles_adjacent(punit->x, punit->y, pcity_dest->x, pcity_dest->y) && can_establish_trade_route(pcity_homecity, pcity_dest)) { int revenue; revenue=establish_trade_route(pcity_homecity, pcity_dest); notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, "Game: Your %s has arrived in %s, and revenues amount to %d in gold.", unit_name(punit->type), pcity_dest->name, revenue); wipe_unit(0, punit); pplayer->economic.gold+=revenue; send_player_info(pplayer, pplayer); city_refresh(pcity_homecity); city_refresh(pcity_dest); send_city_info(pplayer, pcity_homecity, 0); send_city_info(city_owner(pcity_dest), pcity_dest, 0); } } } /************************************************************************** ... **************************************************************************/ void handle_unit_enter_city(struct player *pplayer, struct city *pcity) { int i, x, y, old_id; int coins; struct city *pc2; struct player *cplayer; if(pplayer->player_no!=pcity->owner) { struct city *pnewcity; cplayer=&game.players[pcity->owner]; pcity->size--; if (pcity->size<1) { notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: You destroy %s completely.", pcity->name); notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, "Game: %s has been destroyed by %s", pcity->name, pplayer->name); remove_city_from_minimap(pcity->x, pcity->y); remove_city(pcity); return; } city_auto_remove_worker(pcity); get_a_tech(pplayer, cplayer); coins=cplayer->economic.gold; coins=myrand((coins/20)+1)+(coins*(pcity->size))/200; pplayer->economic.gold+=coins; cplayer->economic.gold-=coins; send_player_info(cplayer, cplayer); if (pcity->owner != pplayer->player_no) { notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: You conquer %s, your lootings accumulate to %d gold", pcity->name, coins); notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, "Game: %s conquered %s and looted %d gold from the city.", pplayer->name, pcity->name, coins); } else { notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: You have liberated %s!! lootings accumulate to %d gold", pcity->name, coins); notify_player_ex(cplayer, pcity->x, pcity->y, E_CITY_LOST, "Game: %s liberated %s and looted %d gold from the city.", pplayer->name, pcity->name, coins); } pnewcity=(struct city *)malloc(sizeof(struct city)); make_partisans(pcity); *pnewcity=*pcity; remove_city(pcity); for (i=0;i<4;i++) { pc2=find_city_by_id(pnewcity->trade[i]); if (can_establish_trade_route(pnewcity, pc2)) establish_trade_route(pnewcity, pc2); } /* now set things up for the new owner */ old_id = pnewcity->id; pnewcity->id=get_next_id_number(); add_city_to_cache(pnewcity); for (i = 0; i < B_LAST; i++) { if (is_wonder(i) && city_got_building(pnewcity, i)) game.global_wonders[i] = pnewcity->id; } /* Once I added this block, why was the below for() needed? -- Syela */ pnewcity->owner=pplayer->player_no; unit_list_init(&pnewcity->units_supported); city_list_insert(&pplayer->cities, pnewcity); /* Transfer wonders to new owner - Kris Bubendorfer*/ for(i = B_APOLLO;i <= B_WOMENS; i++) if(game.global_wonders[i] == old_id) game.global_wonders[i] = pnewcity->id; map_set_city(pnewcity->x, pnewcity->y, pnewcity); if ((get_invention(pplayer, A_RAILROAD)==TECH_KNOWN) && (get_invention(cplayer, A_RAILROAD)!=TECH_KNOWN) && (!(map_get_special(pnewcity->x,pnewcity->y)&S_RAILROAD))) { 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); map_set_special(pnewcity->x, pnewcity->y, S_RAILROAD); send_tile_info(0, pnewcity->x, pnewcity->y, TILE_KNOWN); } raze_city(pnewcity); if (pplayer->ai.control) { /* let there be light! */ for (y=0;y<5;y++) { for (x=0;x<5;x++) { if ((x==0 || x==4) && (y==0 || y==4)) continue; light_square(pplayer, x+pnewcity->x-2, y+pnewcity->y-2, 0); } } } /* maybe should auto_arr or otherwise reset ->worked? -- Syela */ city_refresh(pnewcity); initialize_infrastructure_cache(pnewcity); send_city_info(0, pnewcity, 0); send_player_info(pplayer, pplayer); } } /************************************************************************** ... **************************************************************************/ void handle_unit_auto_request(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { punit->ai.control=1; send_unit_info(pplayer, punit, 0); } } /************************************************************************** ... **************************************************************************/ void handle_unit_activity_request(struct player *pplayer, struct unit *punit, enum unit_activity new_activity) { if((punit->moves_left>0 || punit->activity==ACTIVITY_GOTO || new_activity == ACTIVITY_EXPLORE) && can_unit_do_activity(punit, new_activity)) { punit->activity=new_activity; punit->activity_count=0; send_unit_info(0, punit, 0); } } /************************************************************************** ... **************************************************************************/ void handle_unit_unload_request(struct player *pplayer, struct packet_unit_request *req) { struct unit *punit; if((punit=unit_list_find(&pplayer->units, req->unit_id))) { unit_list_iterate(map_get_tile(punit->x, punit->y)->units, punit2) { if(punit2->activity==ACTIVITY_SENTRY) { set_unit_activity(punit2, ACTIVITY_IDLE); send_unit_info(0, punit2, 0); } } unit_list_iterate_end; } }