--- common/game.h.orig Fri Dec 10 11:34:13 1999 +++ common/game.h Fri Dec 10 11:41:58 1999 @@ -55,6 +55,7 @@ int min_players, max_players, nplayers; int aifill; int barbarians; + int occupychance; int unhappysize; char *startmessage; int player_idx; @@ -256,6 +257,10 @@ #define GAME_DEFAULT_BARBARIAN 1 #define GAME_MIN_BARBARIAN 0 #define GAME_MAX_BARBARIAN 3 + +#define GAME_DEFAULT_OCCUPYCHANCE 0 +#define GAME_MIN_OCCUPYCHANCE 0 +#define GAME_MAX_OCCUPYCHANCE 100 #define GAME_DEFAULT_RULESET "default" --- server/unithand.c.orig Fri Dec 10 12:16:44 1999 +++ server/unithand.c Fri Dec 10 14:49:22 1999 @@ -515,8 +515,8 @@ 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); + struct city *nearcity1, *nearcity2; + int def_x = pdefender->x, def_y = pdefender->y; freelog(LOG_DEBUG, "Start attack: %s's %s against %s's %s.", pplayer->name, unit_types[punit->type].name, @@ -526,14 +526,14 @@ if(unit_flag(punit->type, F_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))) { + packet.x=def_x; + packet.y=def_y; + if ((pcity=sdi_defense_close(punit->owner, def_x, def_y))) { notify_player_ex(pplayer, punit->x, punit->y, E_UNIT_LOST_ATT, _("Game: Your Nuclear missile was shot down by" " SDI defences, what a waste.")); notify_player_ex(&game.players[pcity->owner], - pdefender->x, pdefender->y, E_UNIT_WIN, + def_x, def_y, E_UNIT_WIN, _("Game: The nuclear attack on %s was avoided by" " your SDI defense."), pcity->name); @@ -544,7 +544,7 @@ for(o=0; ox, pdefender->y); + do_nuclear_explosion(def_x, def_y); return; } @@ -557,7 +557,7 @@ if(punit->moves_left<0) punit->moves_left=0; - if (punit->hp && (pcity=map_get_city(pdefender->x, pdefender->y)) && pcity->size>1 && !city_got_citywalls(pcity) && is_ground_unit(punit)) { + if (punit->hp && (pcity=map_get_city(def_x, def_y)) && pcity->size>1 && !city_got_citywalls(pcity) && is_ground_unit(punit)) { pcity->size--; city_auto_remove_worker(pcity); city_refresh(pcity); @@ -576,11 +576,11 @@ for(o=0; ox, punit->y, &game.players[o]) || - map_get_known(pdefender->x, pdefender->y, &game.players[o])) + map_get_known(def_x, def_y, &game.players[o])) send_packet_unit_combat(game.players[o].conn, &combat); - nearcity1 = dist_nearest_city(get_player(pwinner->owner), pdefender->x, pdefender->y, 0, 0); - nearcity2 = dist_nearest_city(get_player(plooser->owner), pdefender->x, pdefender->y, 0, 0); + nearcity1 = dist_nearest_city(get_player(pwinner->owner), def_x, def_y, 0, 0); + nearcity2 = dist_nearest_city(get_player(plooser->owner), def_x, def_y, 0, 0); if(punit==plooser) { /* The attacker lost */ @@ -600,7 +600,7 @@ unit_name(plooser->type)); notify_player_ex(get_player(plooser->owner), - pdefender->x, pdefender->y, E_UNIT_LOST_ATT, + def_x, def_y, E_UNIT_LOST_ATT, _("Game: Your attacking %s failed against %s's %s%s!"), unit_name(plooser->type), get_player(pwinner->owner)->name, @@ -634,6 +634,27 @@ wipe_unit(pplayer, pwinner); return; } + + /* If attacker wins, and occupychance > 0, it might move in. Don't move in + if there are enemy units in the tile (a fortress or city with multiple + defenders and unstacked combat). Note that this could mean capturing (or + destroying) a city. -GJW */ + + if (pwinner == punit && myrand(100) < game.occupychance && + !is_enemy_unit_tile (def_x, def_y, punit->owner)) { + + /* Hack: make sure the unit has enough moves_left for the move to succeed, + and set moves_left to 0 afterward (if successful). */ + + int old_moves = punit->moves_left; + punit->moves_left = unit_move_rate (punit); + if (handle_unit_move_request (pplayer, punit, def_x, def_y)) { + punit->moves_left = 0; + } else { + punit->moves_left = old_moves; + } + } + send_unit_info(0, pwinner, 0); } --- server/gamehand.c.orig Fri Dec 10 11:59:00 1999 +++ server/gamehand.c Fri Dec 10 12:40:08 1999 @@ -348,6 +348,8 @@ "game.turnblock"); game.barbarians = secfile_lookup_int_default(file, game.barbarians, "game.barbarians"); + game.occupychance = secfile_lookup_int_default(file, game.occupychance, + "game.occupychance"); if(has_capability("unirandom", savefile_options)) { game.randseed = secfile_lookup_int(file, "game.randseed"); @@ -544,6 +546,7 @@ secfile_insert_int(file, game.randseed, "game.randseed"); secfile_insert_int(file, game.turnblock, "game.turnblock"); secfile_insert_int(file, game.barbarians, "game.barbarians"); + secfile_insert_int(file, game.occupychance, "game.occupychance"); secfile_insert_str(file, game.ruleset.techs, "game.ruleset.techs"); secfile_insert_str(file, game.ruleset.units, "game.ruleset.units"); secfile_insert_str(file, game.ruleset.buildings, "game.ruleset.buildings"); --- server/stdinhand.c.orig Fri Dec 10 11:28:43 1999 +++ server/stdinhand.c Fri Dec 10 13:52:58 1999 @@ -435,6 +435,16 @@ " 2 - frequent barbarian uprising \n" " 3 - raging hordes, lots of barbarians") }, + { "occupychance", &game.occupychance, + SSET_RULES, SSET_TO_CLIENT, + GAME_MIN_OCCUPYCHANCE, GAME_MAX_OCCUPYCHANCE, GAME_DEFAULT_OCCUPYCHANCE, + N_("Chance of moving into tile after attack"), + N_(" If set to 0, combat is Civ2-style (when you attack, you remain in\n" + " place). If set to 100, attacking units will always move into the\n" + " tile they attacked if they win the combat (and no enemy units remain\n" + " in the tile). If set to a value between 0 and 100, this will be used\n" + " as the percent chance of \"occupying\" territory.") }, + /* Flexible rules: these can be changed after the game has started. * Should such flexible rules exist? diplchance is included here * to duplicate its previous behaviour (and note diplchance is only used