[Freeciv-Dev] Re: (PR#2464) patch: restrict techs by nation
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Per I. Mathisen via RT wrote:
> This patch adds the ability to restrict the availability of certain techs
> to certain nations. Just add a new field "nations" to the [tech_name] box
> of tech.ruleset which, if it has any entries, is a list of nations that
> have this tech exclusively. Other nations cannot research it, steal it,
> conquer it, find it or otherwise obtain it.
>
> Testers and reviewers wanted. Comments on design desired.
I went over v6 of the patch pretty thoroughly...adding some comments,
fixing some style, and removing some unnecessary (style-only) changes
(including all of advdomestic.c).
Then I noticed a potential bug: in the loading of technologies, when
techs are propagated upward, this propagation can fail if the
technologies are out-of-order (so that tech i requires tech j, where
i<j). I added a quick workaround for this code (this means propagation
is still O(n^2) but may take up to twice as long).
Another problem is that A_LAST and A_NONE are used more-or-less
interchangably for root_tech's. If "None" is specified as the root tech
then A_NONE will be explicitly set for that tech, whereas if A_LAST is
specified then the root tech will be inherited. But once the game has
started this means a rootless technology may have either A_NONE
(==A_ROOT) or A_LAST as its root. This seems unnecessarily complicated
(it should all be A_NONE IMO).
Yet, the A_NONE special-case is probably not handled correctly. The
propagation code will fail if a conflicting root_tech is found for any
technology. Yet, this is the only situation in which A_NONE is helpful
(to override a different root). The solution is to special-case A_NONE
here as well (a->root_req != i && a->root_req != A_NONE).
Finally, it is difficult to tell if all the client cases have been
found. There's not much that can be done about this; if any problems do
turn up they should be easy to fix.
jason
Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.38
diff -u -r1.38 aitech.c
--- ai/aitech.c 2003/01/13 23:27:03 1.38
+++ ai/aitech.c 2003/02/07 00:50:50
@@ -50,8 +50,10 @@
&& !wonder_obsolete(building)) {
Tech_Type_id tech = improvement_types[building].tech_req;
- if (tech_exists(tech) && get_invention(plr, tech) != TECH_KNOWN)
+ if (tech_is_available(plr, tech)
+ && get_invention(plr, tech) != TECH_KNOWN) {
return tech;
+ }
}
return A_UNSET;
}
@@ -70,8 +72,10 @@
for (i = 0 ; i < MAX_NUM_TECH_GOALS; i++) {
Tech_Type_id j = prace->goals.tech[i];
- if (!tech_exists(j) || get_invention(pplayer, j) == TECH_KNOWN)
+ if (!tech_is_available(pplayer, j)
+ || get_invention(pplayer, j) == TECH_KNOWN) {
continue;
+ }
dist = num_unknown_techs_for_goal(pplayer, j);
if (dist < bestdist) {
bestdist = dist;
@@ -154,11 +158,18 @@
} else goal_values[i] = 0;
}
- l = A_UNSET;
- k = A_UNSET;
+ l = A_UNSET; /* currently researched tech */
+ k = A_UNSET; /* current tech goal */
for (i = A_FIRST; i < game.num_tech_types; i++) {
- if (values[i] > values[l] && get_invention(pplayer, i) == TECH_REACHABLE)
l = i;
- if (goal_values[i] > goal_values[k]) k = i;
+ if (values[i] > values[l]
+ && tech_is_available(pplayer, i)
+ && get_invention(pplayer, i) == TECH_REACHABLE) {
+ l = i;
+ }
+ if (goal_values[i] > goal_values[k]
+ && tech_is_available(pplayer, i)) {
+ k = i;
+ }
}
freelog(LOG_DEBUG, "%s wants %s with desire %d (%d).", pplayer->name,
advances[l].name, values[l], pplayer->ai.tech_want[l]);
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.59
diff -u -r1.59 helpdata.c
--- client/helpdata.c 2003/01/29 05:10:49 1.59
+++ client/helpdata.c 2003/02/07 00:50:51
@@ -785,7 +785,7 @@
_("If we would now start with %s we would need %d bulbs."),
advances[i].name,
base_total_bulbs_required(game.player_ptr, i));
- } else {
+ } else if (tech_is_available(game.player_ptr, i)) {
sprintf(buf + strlen(buf),
_("To reach %s we need to obtain %d other "
"technologies first. The whole project "
@@ -793,8 +793,11 @@
advances[i].name,
num_unknown_techs_for_goal(game.player_ptr, i) - 1,
total_bulbs_required_for_goal(game.player_ptr, i));
+ } else {
+ sprintf(buf + strlen(buf),
+ _("You cannot research this technology."));
}
- if (!techs_have_fixed_costs()) {
+ if (!techs_have_fixed_costs() && tech_is_available(game.player_ptr, i)) {
sprintf(buf + strlen(buf),
_(" This number may vary depending on what "
"other players will research.\n"));
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.284
diff -u -r1.284 packhand.c
--- client/packhand.c 2003/02/04 23:12:30 1.284
+++ client/packhand.c 2003/02/07 00:50:52
@@ -1818,10 +1818,10 @@
sz_strlcpy(a->graphic_alt, p->graphic_alt);
a->req[0] = p->req[0];
a->req[1] = p->req[1];
+ a->root_req = p->root_req;
a->flags = p->flags;
a->preset_cost = p->preset_cost;
a->num_reqs = p->num_reqs;
-
a->helptext = p->helptext; /* pointer assignment */
tilespec_setup_tech_type(p->id);
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 2002/11/15 21:24:28 1.38
+++ client/gui-gtk/diplodlg.c 2003/02/07 00:50:52
@@ -218,10 +218,10 @@
int i, flag;
for(i=1, flag=0; i<game.num_tech_types; i++) {
- if(get_invention(plr0, i)==TECH_KNOWN &&
- (get_invention(plr1, i)==TECH_UNKNOWN ||
- get_invention(plr1, i)==TECH_REACHABLE))
- {
+ if (get_invention(plr0, i) == TECH_KNOWN
+ && (get_invention(plr1, i) == TECH_UNKNOWN
+ || get_invention(plr1, i) == TECH_REACHABLE)
+ && tech_is_available(plr1, i)) {
GtkWidget *item=gtk_menu_item_new_with_label(advances[i].name);
gtk_menu_append(GTK_MENU(popupmenu),item);
Index: client/gui-gtk/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/repodlgs.c,v
retrieving revision 1.69
diff -u -r1.69 repodlgs.c
--- client/gui-gtk/repodlgs.c 2003/01/13 23:27:03 1.69
+++ client/gui-gtk/repodlgs.c 2003/02/07 00:50:53
@@ -491,9 +491,10 @@
*/
hist=0;
for(i=A_FIRST; i<game.num_tech_types; i++) {
- if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
if (i==game.player_ptr->ai.tech_goal)
hist=i;
sorting_list = g_list_append(sorting_list, GINT_TO_POINTER(i));
Index: client/gui-gtk-2.0/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/diplodlg.c,v
retrieving revision 1.8
diff -u -r1.8 diplodlg.c
--- client/gui-gtk-2.0/diplodlg.c 2002/12/30 02:32:02 1.8
+++ client/gui-gtk-2.0/diplodlg.c 2003/02/07 00:50:53
@@ -216,10 +216,10 @@
int i, flag;
for(i=1, flag=0; i<game.num_tech_types; i++) {
- if(get_invention(plr0, i)==TECH_KNOWN &&
- (get_invention(plr1, i)==TECH_UNKNOWN ||
- get_invention(plr1, i)==TECH_REACHABLE))
- {
+ if (get_invention(plr0, i) == TECH_KNOWN
+ && (get_invention(plr1, i) == TECH_UNKNOWN
+ || get_invention(plr1, i) == TECH_REACHABLE)
+ && tech_is_available(plr1, i)) {
GtkWidget *item=gtk_menu_item_new_with_label(advances[i].name);
gtk_menu_append(GTK_MENU(popupmenu),item);
Index: client/gui-gtk-2.0/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/repodlgs.c,v
retrieving revision 1.24
diff -u -r1.24 repodlgs.c
--- client/gui-gtk-2.0/repodlgs.c 2003/01/13 23:27:03 1.24
+++ client/gui-gtk-2.0/repodlgs.c 2003/02/07 00:50:54
@@ -491,9 +491,10 @@
*/
hist=0;
for(i=A_FIRST; i<game.num_tech_types; i++) {
- if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
if (i==game.player_ptr->ai.tech_goal)
hist=i;
sorting_list = g_list_append(sorting_list, GINT_TO_POINTER(i));
Index: client/gui-mui/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/diplodlg.c,v
retrieving revision 1.15
diff -u -r1.15 diplodlg.c
--- client/gui-mui/diplodlg.c 2003/01/11 16:24:42 1.15
+++ client/gui-mui/diplodlg.c 2003/02/07 00:50:54
@@ -262,7 +262,10 @@
for(i=1, flag=0; i<game.num_tech_types; i++)
{
- if(get_invention(plr0, i)==TECH_KNOWN && (get_invention(plr1,
i)==TECH_UNKNOWN || get_invention(plr1, i)==TECH_REACHABLE))
+ if (get_invention(plr0, i) == TECH_KNOWN
+ && (get_invention(plr1, i) == TECH_UNKNOWN
+ || get_invention(plr1, i) == TECH_REACHABLE)
+ && tech_is_available(plr1, i))
{
entry = MUI_MakeObject(MUIO_Menuitem,advances[i].name,NULL,0,0);
set(entry,MUIA_UserData,i);
Index: client/gui-mui/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/repodlgs.c,v
retrieving revision 1.28
diff -u -r1.28 repodlgs.c
--- client/gui-mui/repodlgs.c 2003/01/13 23:27:03 1.28
+++ client/gui-mui/repodlgs.c 2003/02/07 00:50:54
@@ -240,9 +240,10 @@
for (i = A_FIRST, j = 0; i < game.num_tech_types; i++)
{
- if (get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11)
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN &&
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11)
j++;
}
if (game.player_ptr->ai.tech_goal == A_UNSET) {
Index: client/gui-sdl/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/repodlgs.c,v
retrieving revision 1.8
diff -u -r1.8 repodlgs.c
--- client/gui-sdl/repodlgs.c 2003/02/01 12:10:33 1.8
+++ client/gui-sdl/repodlgs.c 2003/02/07 00:50:55
@@ -846,9 +846,10 @@
*/
count = 0;
for (i = A_FIRST; i < game.num_tech_types; i++) {
- if (get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
pStr = create_str16_from_char(advances[i].name, 10);
pStr->style |= TTF_STYLE_BOLD;
Index: client/gui-win32/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/diplodlg.c,v
retrieving revision 1.12
diff -u -r1.12 diplodlg.c
--- client/gui-win32/diplodlg.c 2002/11/17 19:22:24 1.12
+++ client/gui-win32/diplodlg.c 2003/02/07 00:50:55
@@ -184,9 +184,10 @@
plr1=plr?pdialog->treaty.plr0:pdialog->treaty.plr1;
menu=CreatePopupMenu();
for(i=1, flag=0; i<game.num_tech_types; i++) {
- if(get_invention(plr0, i)==TECH_KNOWN &&
- (get_invention(plr1, i)==TECH_UNKNOWN ||
- get_invention(plr1, i)==TECH_REACHABLE)) {
+ if (get_invention(plr0, i) == TECH_KNOWN
+ && (get_invention(plr1, i) == TECH_UNKNOWN ||
+ || get_invention(plr1, i) == TECH_REACHABLE)
+ && tech_is_available(plr1, i)) {
AppendMenu(menu,MF_STRING,ID_ADVANCES_BASE+i,advances[i].name);
iteminfo.dwItemData=plr0->player_no*10000+plr1->player_no*100+i;
iteminfo.fMask = MIIM_DATA;
Index: client/gui-win32/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/repodlgs.c,v
retrieving revision 1.26
diff -u -r1.26 repodlgs.c
--- client/gui-win32/repodlgs.c 2003/01/13 23:27:04 1.26
+++ client/gui-win32/repodlgs.c 2003/02/07 00:50:56
@@ -144,9 +144,10 @@
ComboBox_ResetContent(GetDlgItem(science_dlg,ID_SCIENCE_GOAL));
hist=0;
for(i=A_FIRST; i<game.num_tech_types; i++) {
- if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
id=ComboBox_AddString(GetDlgItem(science_dlg,ID_SCIENCE_GOAL),
advances[i].name);
ComboBox_SetItemData(GetDlgItem(science_dlg,ID_SCIENCE_GOAL),
Index: client/gui-xaw/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/diplodlg.c,v
retrieving revision 1.34
diff -u -r1.34 diplodlg.c
--- client/gui-xaw/diplodlg.c 2002/11/15 21:24:29 1.34
+++ client/gui-xaw/diplodlg.c 2003/02/07 00:50:56
@@ -252,9 +252,10 @@
int i, flag;
for(i=A_FIRST, flag=0; i<game.num_tech_types; i++) {
- if(get_invention(plr0, i)==TECH_KNOWN &&
- (get_invention(plr1, i)==TECH_UNKNOWN ||
- get_invention(plr1, i)==TECH_REACHABLE)) {
+ if (get_invention(plr0, i) == TECH_KNOWN
+ && (get_invention(plr1, i) == TECH_UNKNOWN
+ || get_invention(plr1, i) == TECH_REACHABLE)
+ && tech_is_available(plr1, i)) {
Widget entry=
XtVaCreateManagedWidget(advances[i].name, smeBSBObjectClass,
popupmenu, NULL);
Index: client/gui-xaw/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/repodlgs.c,v
retrieving revision 1.47
diff -u -r1.47 repodlgs.c
--- client/gui-xaw/repodlgs.c 2002/11/29 20:11:59 1.47
+++ client/gui-xaw/repodlgs.c 2003/02/07 00:50:56
@@ -333,9 +333,10 @@
XtSetSensitive(science_change_menu_button, FALSE);
for(i=A_FIRST, flag=0; i<game.num_tech_types; i++)
- if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
- advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
- num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+ if (tech_is_available(game.player_ptr, i)
+ && get_invention(game.player_ptr, i) != TECH_KNOWN
+ && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+ && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
Widget entry=
XtVaCreateManagedWidget(advances[i].name, smeBSBObjectClass,
goalmenu, NULL);
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 2003/01/29 05:10:50 1.38
+++ common/government.c 2003/02/07 00:50:57
@@ -246,7 +246,10 @@
government >= 0 && government < game.government_count);
req = governments[government].required_tech;
- if (!tech_exists(req)) {
+ if (!tech_is_available(pplayer, req)) {
+ /* If the technology doesn't "exist" or if there is no way we can
+ * ever get it, then we can't change to the gov type even if we have
+ * a wonder that would otherwise allow it. */
return FALSE;
} else {
return (get_invention(pplayer, req) == TECH_KNOWN
Index: common/packets.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v
retrieving revision 1.235
diff -u -r1.235 packets.c
--- common/packets.c 2003/02/04 23:12:31 1.235
+++ common/packets.c 2003/02/07 00:50:58
@@ -2047,6 +2047,9 @@
dio_put_uint8(&dout, packet->id);
dio_put_uint8(&dout, packet->req[0]);
dio_put_uint8(&dout, packet->req[1]);
+ if (has_capability("root_tech", pc->capability)) {
+ dio_put_uint8(&dout, packet->root_req);
+ }
dio_put_uint32(&dout, packet->flags);
dio_put_uint32(&dout, packet->preset_cost);
dio_put_uint32(&dout, packet->num_reqs);
@@ -2077,6 +2080,9 @@
dio_get_uint8(&din, &packet->id);
dio_get_uint8(&din, &packet->req[0]);
dio_get_uint8(&din, &packet->req[1]);
+ if (has_capability("root_tech", pc->capability)) {
+ dio_get_uint8(&din, &packet->root_req);
+ }
dio_get_uint32(&din, &packet->flags);
dio_get_uint32(&din, &packet->preset_cost);
dio_get_uint32(&din, &packet->num_reqs);
Index: common/packets.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v
retrieving revision 1.136
diff -u -r1.136 packets.h
--- common/packets.h 2003/02/04 23:12:31 1.136
+++ common/packets.h 2003/02/07 00:50:58
@@ -15,6 +15,7 @@
#include "connection.h" /* struct connection, MAX_LEN_* */
#include "map.h"
+#include "nation.h"
#include "player.h"
#include "shared.h" /* MAX_LEN_NAME, MAX_LEN_ADDR */
#include "spaceship.h"
@@ -633,7 +634,7 @@
};
struct packet_ruleset_tech {
- int id, req[2]; /* indices for advances[] */
+ int id, req[2], root_req; /* indices for advances[] */
int flags;
char name[MAX_LEN_NAME];
char graphic_str[MAX_LEN_NAME];
Index: common/tech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tech.c,v
retrieving revision 1.56
diff -u -r1.56 tech.c
--- common/tech.c 2003/01/22 19:55:08 1.56
+++ common/tech.c 2003/02/07 00:50:58
@@ -94,7 +94,8 @@
{
/* The is_tech_a_req_for_goal condition is true if the tech is
* already marked */
- if (!tech_exists(tech) || get_invention(pplayer, tech) == TECH_KNOWN
+ if (!tech_is_available(pplayer, tech)
+ || get_invention(pplayer, tech) == TECH_KNOWN
|| is_tech_a_req_for_goal(pplayer, tech, goal)) {
return;
}
@@ -155,6 +156,25 @@
}
/**************************************************************************
+ Returns TRUE iff the given tech is ever reachable by the given player
+ by checking tech tree limitations.
+**************************************************************************/
+bool tech_is_available(struct player *pplayer, Tech_Type_id id)
+{
+ if (!tech_exists(id)) {
+ return FALSE;
+ }
+
+ if (advances[id].root_req != A_NONE && advances[id].root_req != A_LAST
+ && get_invention(pplayer, advances[id].root_req) != TECH_KNOWN) {
+ /* This tech requires knowledge of another tech before being
+ * available. Prevents sharing of untransferable techs. */
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**************************************************************************
Marks reachable techs. Calls build_required_techs to update the
cache of requirements.
**************************************************************************/
@@ -164,7 +184,7 @@
enum tech_flag_id flag;
for (i = 0; i < game.num_tech_types; i++) {
- if (!tech_exists(i)) {
+ if (!tech_is_available(pplayer, i)) {
set_invention(pplayer, i, TECH_UNKNOWN);
} else {
if (get_invention(pplayer, i) == TECH_REACHABLE) {
@@ -199,7 +219,8 @@
{
Tech_Type_id sub_goal;
- if (!tech_exists(goal) || get_invention(pplayer, goal) == TECH_KNOWN) {
+ if (!tech_is_available(pplayer, goal)
+ || get_invention(pplayer, goal) == TECH_KNOWN) {
return A_UNSET;
}
if (get_invention(pplayer, goal) == TECH_REACHABLE) {
@@ -221,7 +242,8 @@
**************************************************************************/
Tech_Type_id get_next_tech(struct player *pplayer, Tech_Type_id goal)
{
- if (!tech_exists(goal) || get_invention(pplayer, goal) == TECH_KNOWN) {
+ if (!tech_is_available(pplayer, goal)
+ || get_invention(pplayer, goal) == TECH_KNOWN) {
return A_UNSET;
}
return (get_next_tech_rec(pplayer, goal));
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 2003/01/13 23:27:12 1.38
+++ common/tech.h 2003/02/07 00:50:58
@@ -15,6 +15,8 @@
#include "shared.h"
+#include "nation.h" /* Nation_Type_id */
+
struct player;
typedef int Tech_Type_id;
@@ -77,7 +79,8 @@
char name_orig[MAX_LEN_NAME]; /* untranslated */
char graphic_str[MAX_LEN_NAME]; /* which named sprite to use */
char graphic_alt[MAX_LEN_NAME]; /* alternate icon name */
- int req[2];
+ Tech_Type_id req[2];
+ Tech_Type_id root_req; /* A_NONE/A_LAST => unrestricted */
unsigned int flags;
char *helptext;
@@ -107,6 +110,7 @@
void update_research(struct player *pplayer);
Tech_Type_id get_next_tech(struct player *pplayer, Tech_Type_id goal);
+bool tech_is_available(struct player *pplayer, Tech_Type_id id);
bool tech_exists(Tech_Type_id id);
Tech_Type_id find_tech_by_name(const char *s);
Index: data/default/techs.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/techs.ruleset,v
retrieving revision 1.21
diff -u -r1.21 techs.ruleset
--- data/default/techs.ruleset 2003/01/03 08:58:48 1.21
+++ data/default/techs.ruleset 2003/02/07 00:50:59
@@ -22,6 +22,9 @@
;
; name = name as seen by user
; req1, req2 = advances required before researching this one
+; root_req = advance required before acquiring this one, inherited
+; by all techs that require this tech in turn unless
+; "None" is given explicitly
; flags = special flag strings
; graphic = icon for technology
; graphic_alt = alternate icon
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 2002/11/15 21:24:30 1.65
+++ server/diplhand.c 2003/02/07 00:51:00
@@ -147,6 +147,18 @@
if (pclause->from == pplayer) {
switch(pclause->type) {
case CLAUSE_ADVANCE:
+ if (!tech_is_available(other, pclause->value)) {
+ /* It is impossible to give a technology to a civilization that
+ * can never possess it (the client should enforce this). */
+ freelog(LOG_ERROR, "Treaty: The %s can't have tech %s",
+ get_nation_name_plural(other->nation),
+ advances[pclause->value].name);
+ notify_player(pplayer,
+ _("Game: The %s can't accept %s."),
+ get_nation_name_plural(other->nation),
+ advances[pclause->value].name);
+ return;
+ }
if (get_invention(pplayer, pclause->value) != TECH_KNOWN) {
freelog(LOG_ERROR,
"The %s don't know tech %s, but try to give it to the %s.",
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.34
diff -u -r1.34 diplomats.c
--- server/diplomats.c 2003/02/04 23:12:31 1.34
+++ server/diplomats.c 2003/02/07 00:51:01
@@ -559,8 +559,9 @@
/* Examine the civilization for technologies to steal. */
count = 0;
for (index = A_FIRST; index < game.num_tech_types; index++) {
- if ((get_invention (pplayer, index) != TECH_KNOWN) &&
- (get_invention (cplayer, index) == TECH_KNOWN)) {
+ if (get_invention(pplayer, index) != TECH_KNOWN
+ && get_invention(cplayer, index) == TECH_KNOWN
+ && tech_is_available(pplayer, index)) {
count++;
}
}
@@ -590,8 +591,9 @@
target = -1;
which = myrand (count);
for (index = A_FIRST; index < game.num_tech_types; index++) {
- if ((get_invention (pplayer, index) != TECH_KNOWN) &&
- (get_invention (cplayer, index) == TECH_KNOWN)) {
+ if (get_invention(pplayer, index) != TECH_KNOWN
+ && get_invention(cplayer, index) == TECH_KNOWN
+ && tech_is_available(pplayer, index)) {
if (which > 0) {
which--;
} else {
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.258
diff -u -r1.258 plrhand.c
--- server/plrhand.c 2003/01/29 09:39:38 1.258
+++ server/plrhand.c 2003/02/07 00:51:02
@@ -127,7 +127,8 @@
if (find_city_wonder(B_GREAT)) {
if (pplayer->player_no==find_city_wonder(B_GREAT)->owner) {
for (i=0;i<game.num_tech_types;i++) {
- if (get_invention(pplayer, i)!=TECH_KNOWN
+ if (get_invention(pplayer, i) != TECH_KNOWN
+ && tech_is_available(pplayer, i)
&& game.global_advances[i]>=2) {
notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
_("Game: %s acquired from The Great Library!"),
@@ -215,6 +216,8 @@
&& get_invention(plr, tech_found) != TECH_KNOWN)
|| tech_found == A_FUTURE);
+ assert(tech_is_available(plr, tech_found));
+
plr->got_tech = TRUE;
plr->research.techs_researched++;
was_first = (game.global_advances[tech_found] == 0);
@@ -580,8 +583,9 @@
int i;
int j=0;
for (i=0;i<game.num_tech_types;i++) {
- if (get_invention(pplayer, i)!=TECH_KNOWN &&
- get_invention(target, i)== TECH_KNOWN) {
+ if (get_invention(pplayer, i) != TECH_KNOWN
+ && get_invention(target, i) == TECH_KNOWN
+ && tech_is_available(pplayer, i)) {
j++;
}
}
@@ -598,8 +602,9 @@
/* pick random tech */
j = myrand(j) + 1;
for (i = 0; i < game.num_tech_types; i++) {
- if (get_invention(pplayer, i) != TECH_KNOWN &&
- get_invention(target, i) == TECH_KNOWN) {
+ if (get_invention(pplayer, i) != TECH_KNOWN
+ && get_invention(target, i) == TECH_KNOWN
+ && tech_is_available(pplayer, i)) {
j--;
}
if (j == 0) {
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.136
diff -u -r1.136 ruleset.c
--- server/ruleset.c 2003/02/04 22:13:28 1.136
+++ server/ruleset.c 2003/02/07 00:51:03
@@ -204,8 +204,8 @@
char *sval;
int i;
- sval = secfile_lookup_str(file, "%s.%s", prefix, entry);
- if (!required && strcmp(sval, "Never")==0) {
+ sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
+ if (!sval || (!required && strcmp(sval, "Never") == 0)) {
i = A_LAST;
} else {
i = find_tech_by_name(sval);
@@ -495,6 +495,7 @@
advances[A_NONE].req[0] = A_NONE;
advances[A_NONE].req[1] = A_NONE;
advances[A_NONE].flags = 0;
+ advances[A_NONE].root_req = A_LAST;
a = &advances[A_FIRST];
@@ -504,7 +505,9 @@
a->req[0] = lookup_tech(file, sec[i], "req1", FALSE, filename, a->name);
a->req[1] = lookup_tech(file, sec[i], "req2", FALSE, filename, a->name);
-
+ a->root_req = lookup_tech(file, sec[i], "root_req", FALSE,
+ filename, a->name);
+
if ((a->req[0]==A_LAST && a->req[1]!=A_LAST) ||
(a->req[0]!=A_LAST && a->req[1]==A_LAST)) {
freelog(LOG_ERROR, "for tech %s: \"Never\" with non-\"Never\" (%s)",
@@ -550,6 +553,42 @@
a++;
}
+ /* Propagate a root tech up into the tech tree. Thus if a technology
+ * X has Y has a root tech, then any technology requiring X also has
+ * Y as a root tech. */
+restart:
+ for (i = A_FIRST; i < num_techs; i++) {
+ a = &advances[i];
+ if (a->root_req != A_LAST && tech_exists(i)) {
+ int j;
+ bool out_of_order = FALSE;
+
+ /* Now find any tech depending on this technology and update it's
+ * root_tech. */
+ for(j = 0; j < num_techs; j++) {
+ a = &advances[j];
+ if (a->req[0] == i || a->req[1] == i) {
+ if (a->root_req == A_LAST) {
+ a->root_req = i;
+ if (j < i) {
+ out_of_order = TRUE;
+ }
+ } else if (a->root_req != i) {
+ die("Tech %s has two root technologies - this is illegal.",
+ a->name);
+ }
+ }
+ }
+
+ if (out_of_order) {
+ /* HACK: If we just changed the root_tech of a lower-numbered
+ * technology, we need to go back so that we can propagate the
+ * root_tech up to that technology's parents... */
+ goto restart;
+ }
+ }
+ }
+
/* Some more consistency checking:
Non-removed techs depending on removed techs is too
broken to fix by default, so die.
@@ -2487,6 +2526,7 @@
sz_strlcpy(packet.graphic_alt, a->graphic_alt);
packet.req[0] = a->req[0];
packet.req[1] = a->req[1];
+ packet.root_req = a->root_req;
packet.flags = a->flags;
packet.preset_cost = a->preset_cost;
packet.num_reqs = a->num_reqs;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] Re: (PR#2464) patch: restrict techs by nation,
Jason Short via RT <=
|
|