Index: server/unitfunc.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unitfunc.c,v retrieving revision 1.91 diff -u -r1.91 unitfunc.c --- unitfunc.c 1999/03/13 11:42:09 1.91 +++ unitfunc.c 1999/03/19 04:03:09 @@ -317,27 +317,92 @@ diplomat_leave_city(pplayer, pdiplomat, pcity); } +/************************************************************************** +compute_subversion_strength + +Computes the `power' of a spy or diplomat. Spies are 50% more sneakier +than diplomats, veteran spies are twice as sneaky. Diplomats can be +verterans after defeating an attacking diplomat or by being communist. +Spies can become veterans for those reasons plus surviving a mission. + +Virgin Diplomat 10 +Veteran Diplomat 15 +Virgin Spy 15 +Veteran Spy 20 + - Kris Bubendorfer + +**************************************************************************/ + +int compute_subversion_strength(struct unit *pdiplomat){ + int odds = 10; + + /* Spies are sneakier */ + + odds += (!(!unit_flag(pdiplomat->type, F_SPY))) * 5; + + /* Spies can be veteran, but so can communist Diplomats*/ + + odds += (pdiplomat->veteran * 5); + + return odds; +} + +/************************************************************************** +spy_versus_spy +Appologies to Mad Magazine :) Computes the outcome of a spy attacking a spy. +This is loosely based on unit_versus_unit, but fixes some variables. By +using the loop and reducing the hp of both the attacking and defending +spies, we more realistically model Bond vs Goldfinger - that is, both get +tired :) + - Kris Bubendorfer +**************************************************************************/ + +void spy_versus_spy(struct unit *attacker, struct unit *defender) +{ + int attackstrength=compute_subversion_strength(attacker); + int defensestrength=compute_subversion_strength(defender); + + freelog(LOG_DEBUG, "%s attack:%d, %s defense:%d", unit_name(attacker->type), + attackstrength, unit_name(defender->type), defensestrength); + + while (attacker->hp>0 && defender->hp>0) + if (myrand(attackstrength+defensestrength)>= defensestrength) + defender->hp -= 1; + else + attacker->hp -= 1; + + if (attacker->hp) + maybe_make_veteran(attacker); + else if (defender->hp) + maybe_make_veteran(defender); +} + /************************************************************************** diplomat_infiltrate_city This code determines if a subverting diplomat/spy succeeds in infiltrating -the city, that is - if there are defending diplomats/spies they have a -n-1/n chance of defeating the infiltrator. +the city, that is - if there are defending diplomats/spies they have a chance +of defeating the infiltrator. Diplchance now only applies to the **************************************************************************/ int diplomat_infiltrate_city(struct player *pplayer, struct player *cplayer, struct unit *pdiplomat, struct city *pcity) { - /* For EVERY diplomat/spy on a square, there is a 1/N chance of succeeding. - * This needs to be changed to take into account veteran status. + /* + * EVERY diplomat/spy on a city gets to defend against the attacking + * Diplomat or Spy. */ + unit_list_iterate(map_get_tile(pcity->x, pcity->y)->units, punit) - if (unit_flag(punit->type, F_DIPLOMAT)) { - if (myrand(game.diplchance)) { - - /* Attacking Spy/Diplomat dies (N-1:N) */ - + if (unit_flag(punit->type, F_DIPLOMAT) || unit_flag(punit->type, F_SPY)) { + /* Fight it out */ + spy_versus_spy(pdiplomat, punit); + + if (!pdiplomat->hp) { + + /* Attacking Spy/Diplomat dies */ + notify_player_ex(pplayer, pcity->x, pcity->y, E_MY_DIPLOMAT, "Game: Your %s was eliminated" " by a defending %s in %s.", @@ -351,11 +416,12 @@ get_race_name(pplayer->race), unit_name(pdiplomat->type), pcity->name); + send_unit_info(0,punit,0); wipe_unit(0, pdiplomat); return 0; } else { - /* Defending Spy/Diplomat dies (1:N) */ + /* Defending Spy/Diplomat dies */ notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED, "Game: Your %s has been eliminated defending" @@ -363,6 +429,7 @@ unit_name(punit->type), unit_name(pdiplomat->type), pcity->name); + send_unit_info(0,pdiplomat,0); wipe_unit(0, punit); } } @@ -374,7 +441,9 @@ diplomat_leave_city This code determines if a subverting diplomat/spy survives infiltrating a -city. A diplomats always dies, a spy has a 1/game.diplchance +city. A diplomats always dies, a spy has a 1/game.diplchance - this +reflects the chance of the spy being captured by the civil authorities +after commiting the offence. **************************************************************************/ void diplomat_leave_city(struct player *pplayer, struct unit *pdiplomat, @@ -891,13 +960,15 @@ /************************************************************************** after a battle this routine is called to decide whether or not the unit should become a veteran, if unit isn't already. - there is a 50/50% chance for it to happend, (100% if player got SUNTZU) + there is a 50/50% chance for it to happend, (100% if player got SUNTZU + unless the unit is a spy/diplomat) **************************************************************************/ void maybe_make_veteran(struct unit *punit) { if (punit->veteran) return; - if(player_owns_active_wonder(get_player(punit->owner), B_SUNTZU)) + if(player_owns_active_wonder(get_player(punit->owner), B_SUNTZU) + && !(unit_flag(punit->type,F_DIPLOMAT)||unit_flag(punit->type,F_SPY))) punit->veteran = 1; else punit->veteran=myrand(2);