? -g Index: common/game.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/game.c,v retrieving revision 1.21 diff -u -r1.21 game.c --- game.c 1998/10/29 09:34:20 1.21 +++ game.c 1998/11/10 22:58:05 @@ -329,6 +329,7 @@ game.conquercost = GAME_DEFAULT_CONQUERCOST; game.settlers = GAME_DEFAULT_SETTLERS; game.cityfactor = GAME_DEFAULT_CITYFACTOR; + game.civilwarsize= GAME_DEFAULT_CIVILWARSIZE; game.explorer = GAME_DEFAULT_EXPLORER; game.unhappysize = GAME_DEFAULT_UNHAPPYSIZE; game.rail_trade = GAME_DEFAULT_RAILTRADE; Index: common/game.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/game.h,v retrieving revision 1.13 diff -u -r1.13 game.h --- game.h 1998/10/29 09:34:22 1.13 +++ game.h 1998/11/10 22:58:05 @@ -52,6 +52,7 @@ int diplcost, freecost, conquercost; int diplchance; int cityfactor; + int civilwarsize; int min_players, max_players, nplayers; int aifill; int unhappysize; Index: common/map.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/map.h,v retrieving revision 1.20 diff -u -r1.20 map.h --- map.h 1998/11/07 02:35:28 1.20 +++ map.h 1998/11/10 22:58:05 @@ -278,6 +278,10 @@ #define GAME_MIN_CITYFACTOR 6 #define GAME_MAX_CITYFACTOR 100 +#define GAME_DEFAULT_CIVILWARSIZE 10 +#define GAME_MIN_CIVILWARSIZE 6 +#define GAME_MAX_CIVILWARSIZE 1000 + #define GAME_DEFAULT_RAILFOOD 0 #define GAME_MIN_RAILFOOD 0 #define GAME_MAX_RAILFOOD 100 Index: common/unit.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v retrieving revision 1.27 diff -u -r1.27 unit.c --- unit.c 1998/11/09 11:14:58 1.27 +++ unit.c 1998/11/10 22:58:07 @@ -256,6 +256,27 @@ return(total_capacity>none_transporters ? total_capacity-none_transporters : 0); } +/************************************************************************** +The above one isn't quite what I want - Kris +**************************************************************************/ +int is_enough_transporter_space (struct player *pplayer, int x, int y) +{ + int none_transporters, total_capacity=0; + none_transporters=0; + total_capacity=0; + unit_list_iterate(map_get_tile(x, y)->units, punit) { + if(get_transporter_capacity(punit) + && !unit_flag(punit->type, F_SUBMARINE| F_CARRIER) + && punit->owner == pplayer->player_no) + total_capacity+=get_transporter_capacity(punit); + else if (is_ground_unit(punit)) + none_transporters++; + } + unit_list_iterate_end; + + return(total_capacity>=none_transporters ? 1 : 0); +} + /************************************************************************** can't use the unit_list_iterate macro here Index: common/unit.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v retrieving revision 1.12 diff -u -r1.12 unit.h --- unit.h 1998/11/05 07:28:58 1.12 +++ unit.h 1998/11/10 22:58:07 @@ -228,6 +228,7 @@ char *unit_activity_text(struct unit *punit); char *unit_description(struct unit *punit); int is_transporter_with_free_space(struct player *pplayer, int x, int y); +int is_enough_transporter_space(struct player *pplayer, int x, int y); int get_transporter_capacity(struct unit *punit); void move_unit_list_to_tile(struct unit_list *units, int x, int y); Index: data/helpdata.txt =================================================================== RCS file: /home/freeciv/CVS/freeciv/data/helpdata.txt,v retrieving revision 1.34 diff -u -r1.34 helpdata.txt --- helpdata.txt 1998/11/07 02:55:28 1.34 +++ helpdata.txt 1998/11/10 22:58:09 @@ -644,6 +644,9 @@ Corruption in other cities is related to how far away from the capitol they are, except when the Government is a Democracy or under Communism. + +Keep good care of your capital, as the loss of it may result in your +empire being plunged into civil war. --- # Police Station Reduces the unhappiness generated by units in a city by 1. @@ -1559,6 +1562,21 @@ governments. Consider switching to the Republic as soon as you can; gaining advanced technology early in the game puts you at an advantage. +--- +# Civil War + +Civil war is devastating to any empire, and is triggered by +the loss of your capital. Up to half of your cities will +rebel and declare allegiance to a rebel leader, who will +loot half of your treasury and retain all of your scientific +advantages. + +Players remain in this state for just one turn, after which +the government enters a state of anarchy. The best means of +avoiding Civil War is to defend your capital at all costs. + +Empires with fewer than 6 cities are immune from civil war. + --- # Anarchy Anarchy is simply the absence of any recognizable government. Index: server/citytools.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v retrieving revision 1.23 diff -u -r1.23 citytools.c --- citytools.c 1998/11/09 11:15:00 1.23 +++ citytools.c 1998/11/10 22:58:10 @@ -598,33 +598,289 @@ */ void transfer_city_units(struct player *pplayer, struct player *pvictim, - struct city *pcity, struct city *vcity) + struct city *pcity, struct city *vcity, + int kill_outside) { int x = vcity->x; int y = vcity->y; /* Transfer units in the city to the new owner */ unit_list_iterate(map_get_tile(x, y)->units, vunit) { + fprintf(stderr,"1. Transfered %s in %s from %s to %s\n", unit_name(vunit->type), vcity->name, pvictim->name, pplayer->name); create_unit_full(pplayer, x, y, vunit->type, vunit->veteran, pcity->id, vunit->moves_left, vunit->hp); wipe_unit(0, vunit); } unit_list_iterate_end; /* Any remaining units supported by the city are either given new home - * cities or destroyed */ + * cities or maybe destroyed */ unit_list_iterate(vcity->units_supported, vunit) { struct city* new_home_city = map_get_city(vunit->x, vunit->y); if(new_home_city) { /* unit is in another city: make that the new homecity */ - + + fprintf(stderr,"2. Transfered %s in %s from %s to %s\n", unit_name(vunit->type), new_home_city->name, pvictim->name, pplayer->name); create_unit_full(pvictim, vunit->x, vunit->y, vunit->type, - vunit->veteran, new_home_city->id, vunit->moves_left, - vunit->hp); + vunit->veteran, new_home_city->id, vunit->moves_left, + vunit->hp); + }else if(!kill_outside){ + + fprintf(stderr,"3. Transfered %s at (%d, %d) from %s to %s\n", unit_name(vunit->type), x, y, pvictim->name, pplayer->name); + create_unit_full(pplayer, vunit->x, vunit->y, vunit->type, + vunit->veteran, pcity->id, vunit->moves_left, + vunit->hp); } - /* unit isn't in a city - Civ2 deletes it - seems like a good idea to - * prevent the city being immediately retaken. We don't actually have to - * do anything here as remove_city deletes all supported units. */ - wipe_unit_safe(0, vunit, &myiter); + wipe_unit_spec_safe(0, vunit, NULL, 0); } unit_list_iterate_end; +} + + +/* + * dist_nearest_city (in ai.c) does not seem to do what I want or expect + * this function finds the closest friendly city to pos x,y. I'm sure + * there must be a similar function somewhere, I just can't find it. + * + * - Kris Bubendorfer + */ + +struct city *find_closest_owned_city(struct player *pplayer, int x, int y){ + int i, dist; + struct city *rcity = city_list_get(&pplayer->cities, 0); + + if(rcity){ + dist = real_map_distance(x, y, rcity->x, rcity->y); + + city_list_iterate(pplayer->cities, pcity) + if (real_map_distance(x, y, pcity->x, pcity->y) < dist){ + dist = real_map_distance(x, y, pcity->x, pcity->y); + rcity = pcity; + } + city_list_iterate_end; + } + return rcity; +} + +/* + * This function creates a new player and copies all of it's science + * research etc. Players are both thrown into anarchy and gold is + * split between both players. + * - Kris Bubendorfer + */ + + +struct player *split_player(struct player *pplayer){ + int races_used[R_LAST], i, num_races_avail=R_LAST, pick; + int newplayer = game.nplayers; + struct player *cplayer = &game.players[newplayer]; + + /* make a new player */ + + player_init(cplayer); + + /* select a new name and race for the copied player. */ + + for(i=0; irace = races_used[i]; + pick_ai_player_name(cplayer->race,cplayer->name); + + cplayer->is_connected=0; + cplayer->conn = NULL; + cplayer->government=G_ANARCHY; + cplayer->capital=1; + + /* Split the resources */ + + cplayer->economic.gold = pplayer->economic.gold/2; + + /* Copy the research */ + + cplayer->research.researched = 0; + cplayer->research.researchpoints = pplayer->research.researchpoints; + cplayer->research.researching = pplayer->research.researching; + + for(i = 0; iresearch.inventions[i] = pplayer->research.inventions[i]; + cplayer->turn_done = 1; /* Have other things to think about - paralysis*/ + cplayer->embassy = 0; /* all embassys destroyed */ + + /* Do the ai */ + + cplayer->ai.control = 1; + cplayer->ai.tech_goal = pplayer->ai.tech_goal; + cplayer->ai.prev_gold = pplayer->ai.prev_gold; + cplayer->ai.maxbuycost = pplayer->ai.maxbuycost; + cplayer->ai.handicap = pplayer->ai.handicap; + cplayer->ai.skill_level = pplayer->ai.skill_level; + cplayer->ai.warmth = pplayer->ai.warmth; + + for(i = 0; iai.tech_want[i] = pplayer->ai.tech_want[i]; + cplayer->ai.tech_turns[i] = pplayer->ai.tech_turns[i]; + } + + /* change the original player */ + + pplayer->government=G_ANARCHY; + pplayer->economic.tax=PLAYER_DEFAULT_TAX_RATE; + pplayer->economic.science=PLAYER_DEFAULT_SCIENCE_RATE; + pplayer->economic.luxury=PLAYER_DEFAULT_LUXURY_RATE; + pplayer->economic.gold = cplayer->economic.gold; + pplayer->research.researched = 0; + pplayer->turn_done = 1; /* Have other things to think about - paralysis*/ + pplayer->embassy = 0; /* all embassys destroyed */ + + /* copy the maps */ + + give_map_from_player_to_player(pplayer, cplayer); + + game.nplayers++; + game.max_players = game.nplayers; + return cplayer; +} + +/* + * Capturing a nations capital is a devistating blow. This function + * creates a new AI player, and randomly splits the original players + * city list into two. Of course this results in a real mix up of + * teritory - but since when have civil wars ever been tidy, or civil. + * + * Embassies: All embassies with other players are lost. Other players + * retain their embassies with pplayer. + * + * Units: Units inside cities are assigned to the new owner + * of the city. Units outside are lost. + * + * Cities: Are split randomly into 2. This results in a real + * mix up of teritory - but since when have civil wars + * ever been tidy, or for any matter civil? + * + * + * One caveat, since the spliting of cities is random, you can + * conceive that this could result in either the original player + * or the rebel getting 0 cities. To prevent this, the hack below + * ensures that each side gets roughly half, which ones is still + * determined randomly. + * - Kris Bubendorfer + */ + +void civil_war(struct player *pplayer){ + + int i; + char player_name[MAX_LENGTH_NAME]; + struct city *pnewcity; + struct player *cplayer = split_player(pplayer); + + /* Now split the empire */ + + fprintf(stderr,"%s's Nation in thrust into civil war, created AI player %s\n", pplayer->name, cplayer->name); + + i = city_list_size(&pplayer->cities)/2; + + city_list_iterate(pplayer->cities, pcity) + if (!city_got_building(pcity, B_PALACE)) + if(myrand(2) && i > 0){ + + /* Transfer city and units supported by this city to the new owner */ + + pnewcity = transfer_city(cplayer,pplayer,pcity); + + fprintf(stderr,"%s declares allegiance to %s\n",pnewcity->name,cplayer->name); + map_set_city(pnewcity->x, pnewcity->y, pnewcity); + transfer_city_units(cplayer, pplayer, pnewcity, pcity, 0); + remove_city(pcity); /* don't forget this! */ + map_set_city(pnewcity->x, pnewcity->y, pnewcity); + + city_check_workers(cplayer,pnewcity); + city_refresh(pnewcity); + initialize_infrastructure_cache(pnewcity); + send_city_info(0, pnewcity, 0); + i--; + } + city_list_iterate_end; + + /* Resolve Stack conflicts */ + + i = 0; + + unit_list_iterate(pplayer->units, punit) + resolve_unit_stack(punit->x, punit->y); + unit_list_iterate_end; + + notify_player(0, "%s's empire has been racked by civil war. The upstart %s now holds power in %d rebel provinces.", pplayer->name, cplayer->name, city_list_size(&cplayer->cities)); + + send_player_info(cplayer, NULL); + send_player_info(pplayer, NULL); + + notify_player(pplayer, "With the capture of your capital, your nation falls into civil war. %s now controls %d of your former cities.", cplayer->name, city_list_size(&cplayer->cities)); + +} + + +/* + * Transfers pcity from dest, srcplayer. No units are moved. This + * is vanila. It is now used for incite, and I suspect it could + * be used to trade cities in the diplomatic section too. + * + * - Kris Bubendorfer + */ + +struct city *transfer_city(struct player *pplayer, struct player *cplayer, struct city *pcity){ + + struct city *pnewcity, *pc2; + int i; + + if (!pcity) + return; + + if(pcity->owner != cplayer->player_no) + return; + + if (cplayer==pplayer || cplayer==NULL) + return; + + pnewcity=(struct city *)malloc(sizeof(struct city)); + *pnewcity=*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); + } + + 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; + } + pnewcity->owner=pplayer->player_no; + unit_list_init(&pnewcity->units_supported); + city_list_insert(&pplayer->cities, pnewcity); + + /* Transfer wonders to new owner */ + + for(i = B_APOLLO;i <= B_WOMENS; i++) + if(game.global_wonders[i] == pcity->id) + game.global_wonders[i] = pnewcity->id; + + return pnewcity; } Index: server/citytools.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/citytools.h,v retrieving revision 1.8 diff -u -r1.8 citytools.h --- citytools.h 1998/10/09 07:44:07 1.8 +++ citytools.h 1998/11/10 22:58:10 @@ -53,7 +53,11 @@ int wants_to_be_bigger(struct city *pcity); int worst_worker_tile_value(struct city *pcity); void transfer_city_units(struct player *pplayer, struct player *pvictim, - struct city *pcity, struct city *vcity); + struct city *pcity, struct city *vcity, int kill_outside); +void civil_war(struct player *pplayer); +struct city *transfer_city(struct player *pplayer, struct player *cplayer, struct city *pcity); +struct city *find_closest_owned_city(struct player *pplayer, int x, int y); + #endif Index: server/civserver.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/civserver.c,v retrieving revision 1.48 diff -u -r1.48 civserver.c --- civserver.c 1998/11/08 00:32:52 1.48 +++ civserver.c 1998/11/10 22:58:11 @@ -644,8 +644,13 @@ void ai_start_turn() { int i; + + if(!shuffled[game.nplayers-1]) + shuffle_players(); + for (i = 0; i < game.nplayers; i++) { - if (shuffled[i]->ai.control) ai_do_first_activities(shuffled[i]); + if(shuffled[i] && shuffled[i]->ai.control) + ai_do_first_activities(shuffled[i]); } } Index: server/gamehand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v retrieving revision 1.21 diff -u -r1.21 gamehand.c --- gamehand.c 1998/10/31 10:09:44 1.21 +++ gamehand.c 1998/11/10 22:58:11 @@ -241,6 +241,7 @@ if (game.version >= 10100) { game.cityfactor = secfile_lookup_int(file, "game.cityfactor"); + game.civilwarsize = secfile_lookup_int(file, "game.civilwarsize"); game.diplcost = secfile_lookup_int(file, "game.diplcost"); game.freecost = secfile_lookup_int(file, "game.freecost"); game.conquercost = secfile_lookup_int(file, "game.conquercost"); @@ -383,6 +384,7 @@ secfile_insert_int(file, game.warminglevel, "game.warminglevel"); secfile_insert_int(file, game.unhappysize, "game.unhappysize"); secfile_insert_int(file, game.cityfactor, "game.cityfactor"); + secfile_insert_int(file, game.civilwarsize, "game.civilwarsize"); secfile_insert_int(file, game.diplcost, "game.diplcost"); secfile_insert_int(file, game.freecost, "game.freecost"); secfile_insert_int(file, game.conquercost, "game.conquercost"); Index: server/stdinhand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v retrieving revision 1.31 diff -u -r1.31 stdinhand.c --- stdinhand.c 1998/11/07 02:23:58 1.31 +++ stdinhand.c 1998/11/10 22:58:11 @@ -138,6 +138,11 @@ { "cityfactor", "How many cities will it take to increase unhappy faces in cities.", &game.cityfactor, 0, 1, GAME_MIN_CITYFACTOR, GAME_MAX_CITYFACTOR, GAME_DEFAULT_CITYFACTOR}, + + { "civilwarsize", "How many cities a player must have before capturing their capital will cause a civil war.", + &game.civilwarsize, 0, + GAME_MIN_CIVILWARSIZE, GAME_MAX_CIVILWARSIZE, GAME_DEFAULT_CIVILWARSIZE}, + { "railfood", "How many % railroads modifies food production.", &game.rail_food, 0, 1, GAME_MIN_RAILFOOD, GAME_MAX_RAILFOOD, GAME_DEFAULT_RAILFOOD}, Index: server/unitfunc.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unitfunc.c,v retrieving revision 1.57 diff -u -r1.57 unitfunc.c --- unitfunc.c 1998/11/09 11:15:01 1.57 +++ unitfunc.c 1998/11/10 22:58:13 @@ -372,15 +372,13 @@ notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: Your spy has successfully completed her mission and returned unharmed to %s.", spyhome->name); - /* being teleported costs 1 move */ - - if(pdiplomat->moves_left > 3) - pdiplomat->moves_left -= 3; - else - pdiplomat->moves_left = 0; - - create_unit(pplayer, spyhome->x, spyhome->y, - pdiplomat->type, 1, spyhome->id, pdiplomat->moves_left); + /* being teleported costs 1 move */ + + maybe_make_veteran(pdiplomat); + + teleport_unit_to_city(pdiplomat, spyhome, 3); + + return; } } wipe_unit(0, pdiplomat); @@ -395,8 +393,7 @@ void diplomat_incite(struct player *pplayer, struct unit *pdiplomat, struct city *pcity) { struct player *cplayer; - struct city *pnewcity, *pc2; - int i; + struct city *pnewcity; if (!pcity) return; @@ -415,6 +412,9 @@ return; } + + /* Who put this back ? + if (diplomat_on_tile(pcity->x, pcity->y)) { notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: Your spy has been eliminated by a defending spy in %s.", pcity->name); @@ -426,6 +426,8 @@ return; } + */ + /* Check if the Diplomat/Spy succeeds against defending Diplomats or Spies */ if (!diplomat_infiltrate_city(pplayer, cplayer, pdiplomat, pcity)) @@ -442,39 +444,23 @@ notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED, "Game: %s has revolted, %s influence suspected", pcity->name, get_race_name(pplayer->race)); - pnewcity=(struct city *)malloc(sizeof(struct city)); - *pnewcity=*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); - } - - 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; - } - pnewcity->owner=pplayer->player_no; - unit_list_init(&pnewcity->units_supported); - city_list_insert(&pplayer->cities, pnewcity); - - /* Transfer units supported by this city to the new owner */ - transfer_city_units(pplayer, cplayer, pnewcity, pcity); - /* Transfer wonders to new owner */ + /* Transfer city and units supported by this city to the new owner */ - for(i = B_APOLLO;i <= B_WOMENS; i++) - if(game.global_wonders[i] == pcity->id) - game.global_wonders[i] = pnewcity->id; + pnewcity = transfer_city(pplayer,cplayer,pcity); + pnewcity->shield_stock=0; /* this is not done automatically */ + transfer_city_units(pplayer, cplayer, pnewcity, pcity, 0); + remove_city(pcity); /* don't forget this! */ - remove_city(pcity); + /* Resolve Stack conflicts */ + unit_list_iterate(pplayer->units, punit) + resolve_unit_stack(punit->x, punit->y); + unit_list_iterate_end; + /* buying a city should result in getting new tech from the victim too */ - /* but not money! */ + /* but no money! */ get_a_tech(pplayer, cplayer); @@ -487,7 +473,6 @@ send_tile_info(0, pnewcity->x, pnewcity->y, TILE_KNOWN); } - pnewcity->shield_stock=0; city_check_workers(pplayer,pnewcity); city_refresh(pnewcity); initialize_infrastructure_cache(pnewcity); @@ -1406,11 +1391,13 @@ city supported, or player units, is ok. (For the map units list, would have to pass iter on inside transporter_min_cargo_to_unitlist().) **************************************************************************/ -void wipe_unit_safe(struct player *dest, struct unit *punit, - struct genlist_iterator *iter) +void wipe_unit_spec_safe(struct player *dest, struct unit *punit, + struct genlist_iterator *iter, int wipe_cargo) { - if(get_transporter_capacity(punit) && - map_get_terrain(punit->x, punit->y)==T_OCEAN) { + if(get_transporter_capacity(punit) + && map_get_terrain(punit->x, punit->y)==T_OCEAN + && wipe_cargo) { + struct unit_list list; transporter_min_cargo_to_unitlist(punit, &list); @@ -1440,10 +1427,21 @@ /************************************************************************** ... **************************************************************************/ + +void wipe_unit_safe(struct player *dest, struct unit *punit, + struct genlist_iterator *iter){ + wipe_unit_spec_safe(dest, punit, NULL, 1); +} + + +/************************************************************************** +... +**************************************************************************/ void wipe_unit(struct player *dest, struct unit *punit) { wipe_unit_safe(dest, punit, NULL); } + /************************************************************************** this is a highlevel routine Index: server/unitfunc.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unitfunc.h,v retrieving revision 1.12 diff -u -r1.12 unitfunc.h --- unitfunc.h 1998/11/09 11:15:02 1.12 +++ unitfunc.h 1998/11/10 22:58:13 @@ -49,6 +49,9 @@ void wipe_unit(struct player *dest, struct unit *punit); void wipe_unit_safe(struct player *dest, struct unit *punit, struct genlist_iterator *iter); +void wipe_unit_spec_safe(struct player *dest, struct unit *punit, + struct genlist_iterator *iter, int wipe_cargo); + void kill_unit(struct unit *pkiller, struct unit *punit); void send_unit_info(struct player *dest, struct unit *punit, int dosend); Index: server/unithand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v retrieving revision 1.41 diff -u -r1.41 unithand.c --- unithand.c 1998/11/09 11:15:03 1.41 +++ unithand.c 1998/11/10 22:58:13 @@ -959,6 +959,16 @@ struct city *pnewcity; cplayer=&game.players[pcity->owner]; pcity->size--; + + /* If a capital is captured, then spark off a civil war + - Kris Bubendorfer*/ + + if(city_got_building(pcity, B_PALACE) + && city_list_size(&cplayer->cities) >= game.civilwarsize + && game.nplayers < R_LAST + && game.civilwarsize < GAME_MAX_CIVILWARSIZE) + civil_war(cplayer); + if (pcity->size<1) { notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT, "Game: You destroy %s completely.", pcity->name); @@ -1011,17 +1021,12 @@ 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) && Index: server/unittools.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v retrieving revision 1.28 diff -u -r1.28 unittools.c --- unittools.c 1998/11/09 11:15:04 1.28 +++ unittools.c 1998/11/10 22:58:15 @@ -593,3 +593,101 @@ } return 0; /* as good a quick'n'dirty should be -- Syela */ } + + + +/************************************************************************** + Return first unit on square that is not owned by player. + + - Kris Bubendorfer +**************************************************************************/ + +struct unit *is_enemy_unit_on_tile(int x, int y, int owner) +{ + unit_list_iterate(map_get_tile(x, y)->units, punit) + if (owner!=punit->owner) + return punit; + unit_list_iterate_end; + + return 0; +} + +/************************************************************************** +Teleport punit to city at cost specified. Returns success. + - Kris Bubendorfer +**************************************************************************/ + +int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost){ + if(pcity->owner == punit->owner){ + unit_list_unlink(&map_get_tile(punit->x, punit->y)->units, punit); + punit->x = pcity->x; + punit->y = pcity->y; + if(punit->moves_left < mov_cost) + punit->moves_left = 0; + else + punit->moves_left -= mov_cost; + + send_unit_info(0, punit, 1); + + unit_list_insert(&map_get_tile(pcity->x, pcity->y)->units, punit); + return 1; + } + return 0; +} + +/************************************************************************** + Resolve unit stack + + When in civil war (or an alliance breaks) there will potentially be units + from both sides coexisting on the same squares. This routine resolves + this by teleporting the units in multiowner stacks to the closest city. + + That is, if a unit is closer to it's city than the coexistent enemy unit + then the enemy unit is teleported home. + + - Kris Bubendorfer +**************************************************************************/ + +void resolve_unit_stack(int x, int y) +{ + + struct unit *punit = unit_list_get(&map_get_tile(x, y)->units, 0); + struct unit *cunit = is_enemy_unit_on_tile(x, y, punit->owner); + + while(punit && cunit){ + struct city *pcity = find_closest_owned_city(get_player(punit->owner), x, y); + struct city *ccity = find_closest_owned_city(get_player(cunit->owner), x, y); + + if(map_distance(x, y, pcity->x, pcity->y) + < map_distance(x, y, ccity->x, ccity->y)){ + teleport_unit_to_city(cunit, ccity, 0); + fprintf(stderr,"Teleported %s's %s from (%d, %d) to %s\n",get_player(cunit->owner)->name, unit_name(cunit->type), x, y,ccity->name); + }else{ + teleport_unit_to_city(punit, pcity, 0); + fprintf(stderr,"Teleported %s's %s from (%d, %d) to %s\n",get_player(punit->owner)->name, unit_name(punit->type), x, y, pcity->name); + } + + punit = unit_list_get(&map_get_tile(x, y)->units, 0); + cunit = is_enemy_unit_on_tile(x, y, punit->owner); + } + + /* There is only one players units left on this square. If there is not + enough transporter capacity left , send surplus to the closest friendly + city. */ + + if(!punit && cunit) + punit = cunit; + + if(punit && map_get_terrain(punit->x, punit->y)==T_OCEAN && + !is_enough_transporter_space(get_player(punit->owner), x, y)){ + unit_list_iterate(map_get_tile(x, y)->units, vunit){ + struct city *vcity = find_closest_owned_city(get_player(vunit->owner), x, y); + if(is_ground_unit(vunit)){ + teleport_unit_to_city(vunit, vcity, 0); + fprintf(stderr,"Teleported %s's %s to %s as there is no transport space on square (%d, %d)\n",get_player(vunit->owner)->name, unit_name(vunit->type),vcity->name, x, y); + } + } + unit_list_iterate_end; + } +} + Index: server/unittools.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v retrieving revision 1.9 diff -u -r1.9 unittools.h --- unittools.h 1998/08/16 02:02:01 1.9 +++ unittools.h 1998/11/10 22:58:15 @@ -46,5 +46,7 @@ int build_points_left(struct city *pcity); int can_place_partisan(int x, int y); int enemies_at(struct unit *punit, int x, int y); - +int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost); +struct unit *is_enemy_unit_on_tile(int x, int y, int owner); +void resolve_unit_stack(int x, int y); #endif