Index: client/climisc.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v retrieving revision 1.111 diff -u -r1.111 climisc.c --- client/climisc.c 12 Feb 2003 22:22:33 -0000 1.111 +++ client/climisc.c 14 Feb 2003 01:07:59 -0000 @@ -274,7 +274,12 @@ my_snprintf(buf, bufsiz, _("The %s gives shared vision"), get_nation_name_plural(pclause->from->nation)); break; + case CLAUSE_LEASE: + my_snprintf(buf, bufsiz, _("The %s lease their technology"), + get_nation_name_plural(pclause->from->nation)); + break; default: + assert(FALSE); if (bufsiz > 0) *buf = '\0'; break; } Index: client/packhand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v retrieving revision 1.288 diff -u -r1.288 packhand.c --- client/packhand.c 12 Feb 2003 22:22:33 -0000 1.288 +++ client/packhand.c 14 Feb 2003 01:08:00 -0000 @@ -1235,6 +1235,7 @@ pplayer->government=pinfo->government; pplayer->embassy=pinfo->embassy; pplayer->gives_shared_vision = pinfo->gives_shared_vision; + pplayer->gives_lease = pinfo->gives_lease; pplayer->city_style=pinfo->city_style; for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) { Index: client/gui-gtk/diplodlg.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/diplodlg.c,v retrieving revision 1.38 diff -u -r1.38 diplodlg.c --- client/gui-gtk/diplodlg.c 15 Nov 2002 21:24:28 -0000 1.38 +++ client/gui-gtk/diplodlg.c 14 Feb 2003 01:08:00 -0000 @@ -65,6 +65,8 @@ GtkWidget *dip_pact_menu; GtkWidget *dip_vision_button0; GtkWidget *dip_vision_button1; + GtkWidget *dip_lease_button0; + GtkWidget *dip_lease_button1; GtkWidget *dip_label; GtkWidget *dip_clauselabel; @@ -114,6 +116,7 @@ static void diplomacy_dialog_peace_callback(GtkWidget *w, gpointer data); static void diplomacy_dialog_alliance_callback(GtkWidget *w, gpointer data); static void diplomacy_dialog_vision_callback(GtkWidget *w, gpointer data); +static void diplomacy_dialog_lease_callback(GtkWidget *w, gpointer data); static void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog); static void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog); static gint diplomacy_dialog_mbutton_callback(GtkWidget *w, GdkEvent *event); @@ -453,6 +456,26 @@ if (gives_shared_vision(plr1, plr0)) gtk_widget_set_sensitive(pdialog->dip_vision_button1, FALSE); + pdialog->dip_lease_button0 = gtk_button_new_with_label(_("Lease technology")); + gtk_box_pack_start(GTK_BOX(pdialog->dip_vbox0), pdialog->dip_lease_button0, + FALSE, FALSE, 2); + gtk_signal_connect(GTK_OBJECT(pdialog->dip_lease_button0), "clicked", + GTK_SIGNAL_FUNC(diplomacy_dialog_lease_callback), + (gpointer)pdialog); + if (gives_lease(plr0, plr1) || !player_has_embassy(plr1, plr0)) { + gtk_widget_set_sensitive(pdialog->dip_lease_button0, FALSE); + } + + pdialog->dip_lease_button1 = gtk_button_new_with_label(_("Lease technology")); + gtk_box_pack_start(GTK_BOX(pdialog->dip_vbox1), pdialog->dip_lease_button1, + FALSE, FALSE, 2); + gtk_signal_connect(GTK_OBJECT(pdialog->dip_lease_button1), "clicked", + GTK_SIGNAL_FUNC(diplomacy_dialog_lease_callback), + (gpointer)pdialog); + if (gives_lease(plr1, plr0) || !player_has_embassy(plr0, plr1)) { + gtk_widget_set_sensitive(pdialog->dip_lease_button1, FALSE); + } + /* Start of pact button insertion */ pdialog->dip_pact_menu=gtk_menu_new(); @@ -799,6 +822,26 @@ &pa); } +/**************************************************************** + ... +*****************************************************************/ +static void diplomacy_dialog_lease_callback(GtkWidget *w, gpointer data) +{ + struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data; + struct packet_diplomacy_info pa; + struct player *pgiver; + + pgiver = (w == pdialog->dip_lease_button0) ? + pdialog->treaty.plr0 : pdialog->treaty.plr1; + + pa.plrno0 = pdialog->treaty.plr0->player_no; + pa.plrno1 = pdialog->treaty.plr1->player_no; + pa.clause_type = CLAUSE_LEASE; + pa.plrno_from = pgiver->player_no; + pa.value = 0; + send_packet_diplomacy_info(&aconnection, PACKET_DIPLOMACY_CREATE_CLAUSE, + &pa); +} /**************************************************************** ... Index: client/gui-gtk/helpdlg.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/helpdlg.c,v retrieving revision 1.62 diff -u -r1.62 helpdlg.c --- client/gui-gtk/helpdlg.c 30 Jan 2003 19:26:08 -0000 1.62 +++ client/gui-gtk/helpdlg.c 14 Feb 2003 01:08:00 -0000 @@ -232,6 +232,7 @@ case TECH_UNKNOWN: bg = COLOR_STD_RED; break; case TECH_KNOWN: bg = COLOR_STD_GROUND; break; case TECH_REACHABLE: bg = COLOR_STD_YELLOW; break; + case TECH_LEASED: bg = COLOR_STD_OCEAN; break; default: bg = COLOR_STD_WHITE; break; } d->tech = tech; Index: common/capstr.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v retrieving revision 1.124 diff -u -r1.124 capstr.c --- common/capstr.c 12 Feb 2003 18:38:59 -0000 1.124 +++ common/capstr.c 14 Feb 2003 01:08:00 -0000 @@ -76,7 +76,7 @@ #define CAPABILITY "+1.14.0 conn_info +occupied team tech_impr_gfx " \ "city_struct_minor_cleanup obsolete_last class_legend " \ - "+impr_req +waste +fastfocus +continent" + "+impr_req +waste +fastfocus +continent +lease" /* "+1.14.0" is protocol for 1.14.0 release. * @@ -108,7 +108,9 @@ * * "fastfocus" removes the server from client unit focus. * - * +continent": the server gives the client continent information + * "continent" means the server gives the client continent information + * + * "lease" adds a new feature, the technology lend lease pact type */ void init_our_capability(void) Index: common/city.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/city.c,v retrieving revision 1.183 diff -u -r1.183 city.c --- common/city.c 12 Feb 2003 22:22:33 -0000 1.183 +++ common/city.c 14 Feb 2003 01:08:00 -0000 @@ -2242,10 +2242,10 @@ { struct player *p = city_owner(pcity); int power = 3; - if (get_invention(p, game.rtech.cathedral_minus /*A_COMMUNISM */ ) == - TECH_KNOWN) power--; - if (get_invention(p, game.rtech.cathedral_plus /*A_THEOLOGY */ ) == - TECH_KNOWN) power++; + if (get_invention(p, game.rtech.cathedral_minus) == TECH_KNOWN + || get_invention(p, game.rtech.cathedral_minus) == TECH_LEASED) + power--; + if (get_invention(p, game.rtech.cathedral_plus) == TECH_KNOWN) power++; if (improvement_variant(B_MICHELANGELO) == 1 && city_affected_by_wonder(pcity, B_MICHELANGELO)) power *= 2; Index: common/diptreaty.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/diptreaty.h,v retrieving revision 1.9 diff -u -r1.9 diptreaty.h --- common/diptreaty.h 15 Nov 2002 21:24:30 -0000 1.9 +++ common/diptreaty.h 14 Feb 2003 01:08:00 -0000 @@ -18,7 +18,7 @@ enum clause_type { CLAUSE_ADVANCE, CLAUSE_GOLD, CLAUSE_MAP, CLAUSE_SEAMAP, CLAUSE_CITY, CLAUSE_CEASEFIRE, CLAUSE_PEACE, CLAUSE_ALLIANCE, - CLAUSE_VISION}; + CLAUSE_VISION, CLAUSE_LEASE }; #define is_pact_clause(x) \ ((x == CLAUSE_CEASEFIRE) || (x == CLAUSE_PEACE) || (x == CLAUSE_ALLIANCE)) Index: common/government.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/government.c,v retrieving revision 1.38 diff -u -r1.38 government.c --- common/government.c 29 Jan 2003 05:10:50 -0000 1.38 +++ common/government.c 14 Feb 2003 01:08:00 -0000 @@ -250,6 +250,7 @@ return FALSE; } else { return (get_invention(pplayer, req) == TECH_KNOWN + || get_invention(pplayer, req) == TECH_LEASED || player_owns_active_govchange_wonder(pplayer)); } } Index: common/improvement.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v retrieving revision 1.31 diff -u -r1.31 improvement.c --- common/improvement.c 12 Feb 2003 22:22:33 -0000 1.31 +++ common/improvement.c 14 Feb 2003 01:08:00 -0000 @@ -527,7 +527,8 @@ return FALSE; /* Make sure we have the tech /now/.*/ - if (get_invention(p, improvement_types[id].tech_req) == TECH_KNOWN) + if (get_invention(p, improvement_types[id].tech_req) == TECH_KNOWN + || get_invention(p, improvement_types[id].tech_req) == TECH_LEASED) return TRUE; return FALSE; } Index: common/packets.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v retrieving revision 1.237 diff -u -r1.237 packets.c --- common/packets.c 10 Feb 2003 21:43:42 -0000 1.237 +++ common/packets.c 14 Feb 2003 01:08:00 -0000 @@ -900,6 +900,7 @@ dio_put_uint8(&dout, pinfo->barbarian_type); dio_put_uint32(&dout, pinfo->gives_shared_vision); + DIO_BV_PUT(&dout, pinfo->gives_lease); SEND_PACKET_END; } @@ -959,6 +960,7 @@ /* Unfortunately the second argument to iget_uint32 is int, not uint: */ dio_get_uint32(&din, &i); pinfo->gives_shared_vision = i; + DIO_BV_GET(&din, pinfo->gives_lease); RECEIVE_PACKET_END(pinfo); } Index: common/packets.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v retrieving revision 1.138 diff -u -r1.138 packets.h --- common/packets.h 10 Feb 2003 21:43:42 -0000 1.138 +++ common/packets.h 14 Feb 2003 01:08:01 -0000 @@ -482,6 +482,7 @@ bool ai; int barbarian_type; unsigned int gives_shared_vision; + bv_lease gives_lease; }; /************************************************************************** Index: common/player.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/player.c,v retrieving revision 1.111 diff -u -r1.111 player.c --- common/player.c 12 Feb 2003 22:22:33 -0000 1.111 +++ common/player.c 14 Feb 2003 01:08:01 -0000 @@ -104,6 +104,8 @@ plr->gives_shared_vision = 0; plr->really_gives_vision = 0; + BV_CLR_ALL(plr->gives_lease); + /* Initialise list of improvements with Player-wide equiv_range */ improvement_status_init(plr->improvements, ARRAY_SIZE(plr->improvements)); @@ -426,7 +428,8 @@ int t; if (!improvement_exists(id)) return FALSE; t = get_improvement_type(id)->tech_req; - return (get_invention(pplayer, t) == TECH_KNOWN); + return (get_invention(pplayer, t) == TECH_KNOWN + || get_invention(pplayer, t) == TECH_LEASED); } /************************************************************************** @@ -588,4 +591,12 @@ bool gives_shared_vision(struct player *me, struct player *them) { return TEST_BIT(me->gives_shared_vision, them->player_no); +} + +/************************************************************************** + Return TRUE iff the player me gives lend lease to player them. +**************************************************************************/ +bool gives_lease(struct player *me, struct player *them) +{ + return BV_ISSET(me->gives_lease, them->player_no); } Index: common/player.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/player.h,v retrieving revision 1.93 diff -u -r1.93 player.h --- common/player.h 10 Feb 2003 21:43:42 -0000 1.93 +++ common/player.h 14 Feb 2003 01:08:01 -0000 @@ -166,6 +166,7 @@ see doc/HACKING ***************************************************************************/ +BV_DEFINE(bv_lease, MAX_NUM_PLAYERS); struct player { int player_no; char name[MAX_LEN_NAME]; @@ -199,6 +200,7 @@ struct player_tile *private_map; unsigned int gives_shared_vision; /* bitvector those that give you shared vision */ unsigned int really_gives_vision; /* takes into account that p3 may see what p1 has via p2 */ + bv_lease gives_lease; /* bitvector for lend/lease deals */ Impr_Status improvements[B_LAST]; /* improvements with equiv_range==Player */ Impr_Status *island_improv; /* improvements with equiv_range==Island, dimensioned to [map.num_continents][game.num_impr_types] */ @@ -266,6 +268,7 @@ bool is_barbarian(const struct player *pplayer); bool gives_shared_vision(struct player *me, struct player *them); +bool gives_lease(struct player *me, struct player *them); #define players_iterate(PI_player) \ { \ Index: common/tech.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/tech.c,v retrieving revision 1.57 diff -u -r1.57 tech.c --- common/tech.c 12 Feb 2003 22:22:34 -0000 1.57 +++ common/tech.c 14 Feb 2003 01:08:01 -0000 @@ -48,7 +48,16 @@ enum tech_state get_invention(struct player *pplayer, Tech_Type_id tech) { assert(tech >= 0 || tech < game.num_tech_types); - + if (pplayer->research.inventions[tech].state != TECH_KNOWN) { + players_iterate(aplayer) { + if (pplayer != aplayer + && aplayer->is_alive + && gives_lease(aplayer, pplayer) + && aplayer->research.inventions[tech].state == TECH_KNOWN) { + return TECH_LEASED; + } + } players_iterate_end; + } return pplayer->research.inventions[tech].state; } @@ -393,6 +402,11 @@ /* Research becomes more expensive. */ if (game.year > 0) { cost *= 2; + } + + /* Leased technology becomes cheaper. */ + if (get_invention(pplayer, tech) == TECH_LEASED) { + cost /= 2; } switch (game.rgame.tech_leakage) { Index: common/tech.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/tech.h,v retrieving revision 1.38 diff -u -r1.38 tech.h --- common/tech.h 13 Jan 2003 23:27:12 -0000 1.38 +++ common/tech.h 14 Feb 2003 01:08:01 -0000 @@ -69,7 +69,8 @@ enum tech_state { TECH_UNKNOWN = 0, TECH_KNOWN = 1, - TECH_REACHABLE = 2 + TECH_REACHABLE = 2, + TECH_LEASED = 3 }; struct advance { Index: common/unittype.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v retrieving revision 1.26 diff -u -r1.26 unittype.c --- common/unittype.c 1 Feb 2003 02:10:45 -0000 1.26 +++ common/unittype.c 14 Feb 2003 01:08:01 -0000 @@ -429,8 +429,10 @@ if (unit_type_flag(id, F_FANATIC) && !government_has_flag(get_gov_pplayer(p), G_FANATIC_TROOPS)) return FALSE; - if (get_invention(p,unit_types[id].tech_requirement)!=TECH_KNOWN) + if (get_invention(p,unit_types[id].tech_requirement) != TECH_KNOWN + && get_invention(p,unit_types[id].tech_requirement) != TECH_LEASED) { return FALSE; + } /* If the unit has a building requirement, we check to see if the player * can build that building. Note that individual cities may not have Index: server/diplhand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/diplhand.c,v retrieving revision 1.65 diff -u -r1.65 diplhand.c --- server/diplhand.c 15 Nov 2002 21:24:30 -0000 1.65 +++ server/diplhand.c 14 Feb 2003 01:08:02 -0000 @@ -54,6 +54,8 @@ static struct treaty_list treaties; static bool did_init_treaties; +static void give_lease(struct player *me, struct player *them); + /************************************************************************** Checks if the player numbers in the packet are sane. **************************************************************************/ @@ -146,6 +148,13 @@ if (pclause->from == pplayer) { switch(pclause->type) { + case CLAUSE_LEASE: + if (!player_has_embassy(other, pplayer)) { + freelog(LOG_ERROR, "%s tried to lease tech to %s, who has no " + "embassy", pplayer->name, other->name); + return; + } + break; case CLAUSE_ADVANCE: if (get_invention(pplayer, pclause->value) != TECH_KNOWN) { freelog(LOG_ERROR, @@ -381,7 +390,16 @@ pgiver->name); check_city_workers(plr0); check_city_workers(plr1); - break; + break; + case CLAUSE_LEASE: + give_lease(pgiver, pdest); + notify_player_ex(pgiver, -1, -1, E_TREATY_SHARED_VISION, + _("Game: You lease your technology to %s."), + pdest->name); + notify_player_ex(pdest, -1, -1, E_TREATY_SHARED_VISION, + _("Game: %s leases his technology to you!"), + pgiver->name); + break; case CLAUSE_VISION: give_shared_vision(pgiver, pdest); notify_player_ex(pgiver, -1, -1, E_TREATY_SHARED_VISION, @@ -402,6 +420,18 @@ } } +/************************************************************************** + Set lend/lease treaty +**************************************************************************/ +static void give_lease(struct player *me, struct player *them) +{ + assert(me != them); + if (gives_lease(me, them)) { + freelog(LOG_ERROR, "%s attempting to give duplicate tech lease to %s.", + me->name, them->name); + } + BV_SET(me->gives_lease, them->player_no); +} /************************************************************************** ... Index: server/plrhand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v retrieving revision 1.260 diff -u -r1.260 plrhand.c --- server/plrhand.c 12 Feb 2003 22:22:34 -0000 1.260 +++ server/plrhand.c 14 Feb 2003 01:08:02 -0000 @@ -1178,6 +1178,7 @@ packet->embassy = plr->embassy; packet->gives_shared_vision = plr->gives_shared_vision; + packet->gives_lease = plr->gives_lease; for(i=0; idiplstates[i].type = plr->diplstates[i].type; packet->diplstates[i].turns_left = plr->diplstates[i].turns_left;