[Freeciv-Dev] (PR#11672) unit reqs
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=11672 >
Here is a priliminary and incomplete patch that adds reqs
(requirements.h) for units. The reqs replace the tech_req, gov_req, and
bldg_req.
For the core code this is easy. But for the AI this kind of design
doesn't work so well. Most AI code assumes that a unit has just one
req, so if the unit has a certain want that want can be transferred
directly to the req. My code in this patch divides the want among
several tech reqs but doesn't work well with mixed reqs. I think we
want something like:
void assign_desire_for_reqs(struct requirement *reqs, int desire)
{
int count = 0;
req_iterate(reqs) {
if (!is_req_active(..., req)) {
count++;
}
} req_iterate_end;
req_iterate(reqs) {
if (!is_req_active(..., req)) {
switch (req.type) {
case REQ_TECH:
tech_want[req->value.tech] += desire / count;
break;
case REQ_BUILDING:
building_want[req->value.building] += desire / count;
break;
/* etc, etc. */
}
}
} req_iterate_end;
}
but this is rather complicated since we need to account for the req's
range and rarity. As an example we can't really assign a want to a
terrain req since the AI doesn't know how to satisfy a terrain req:
instead we should realize that this simply cannot be met. This is
additionally a problem since reqs are recursive. We can assign a desire
to a building required to build a unit, but if that building requires a
tech we can't get or a terrain we can't make, then the desire is simply
lost. This is the correct thing to do so long as we don't spend effort
meeting the other requirements.
-jason
Index: ai/advdomestic.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
retrieving revision 1.124
diff -u -r1.124 advdomestic.c
--- ai/advdomestic.c 10 Dec 2004 21:19:20 -0000 1.124
+++ ai/advdomestic.c 23 Dec 2004 22:27:08 -0000
@@ -126,10 +126,16 @@
ai_choose_role_unit(pplayer, pcity, choice, F_HELP_WONDER, dist / 2);
}
} else {
- int tech_req = get_unit_type(unit_type)->tech_requirement;
+ int i;
+ struct unit_type *ut = get_unit_type(unit_type);
- /* XXX (FIXME): Had to add the scientist guess here too. -- Syela */
- pplayer->ai.tech_want[tech_req] += want;
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ /* FIXME: add wants for other types of reqs. */
+ if (ut->req[i].type == REQ_TECH
+ && ut->req[i].range == REQ_RANGE_PLAYER) {
+ pplayer->ai.tech_want[ut->req[i].value.tech] += want;
+ }
+ }
}
}
} city_list_iterate_end;
Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.182
diff -u -r1.182 advmilitary.c
--- ai/advmilitary.c 19 Dec 2004 19:44:39 -0000 1.182
+++ ai/advmilitary.c 23 Dec 2004 22:27:09 -0000
@@ -655,6 +655,48 @@
}
/**************************************************************************
+ Return the number of unknown techs required to meet the given reqs.
+ The reqs value is an array of size MAX_NUM_REQS.
+**************************************************************************/
+static int num_unknown_techs_for_reqs(const struct player *pplayer,
+ const struct requirement *reqs)
+{
+ int i, tech_dist = 0;
+
+ for (i = 0; i < MAX_NUM_REQS && reqs[i].type != REQ_NONE; i++) {
+ /* This only counts tech reqs; it doesn't recurse into other reqs. It
+ * will double-count if there is more than one req. */
+ if (reqs[i].type == REQ_TECH) {
+ Tech_Type_id tech = reqs[i].value.tech;
+
+ tech_dist += num_unknown_techs_for_goal(pplayer, tech);
+ }
+ }
+
+ return tech_dist;
+}
+
+/**************************************************************************
+ Return the number of bulbs required to meet techs in the given reqs.
+ The reqs value is an array of size MAX_NUM_REQS.
+**************************************************************************/
+static int num_unknown_bulbs_for_reqs(const struct player *pplayer,
+ const struct requirement *reqs)
+{
+ int i, tech_cost = 0;
+
+ for (i = 0; i < MAX_NUM_REQS && reqs[i].type != REQ_NONE; i++) {
+ if (reqs[i].type == REQ_TECH) {
+ Tech_Type_id tech = reqs[i].value.tech;
+
+ tech_cost += total_bulbs_required_for_goal(pplayer, tech);
+ }
+ }
+
+ return tech_cost;
+}
+
+/**************************************************************************
What would be the best defender for that city? Records the best defender
type in choice. Also sets the technology want for the units we can't
build yet.
@@ -676,8 +718,8 @@
int move_type = unit_types[unit_type].move_type;
/* How many technologies away it is? */
- int tech_dist = num_unknown_techs_for_goal(pplayer,
- unit_types[unit_type].tech_requirement);
+ int tech_dist = num_unknown_techs_for_reqs(pplayer,
+ get_unit_type(unit_type)->req);
/* How much we want the unit? */
int desire = ai_unit_defence_desirability(unit_type);
@@ -708,17 +750,16 @@
best_unit_type = unit_type;
}
- } else if (tech_dist > 0 && (shore || move_type == LAND_MOVING)
- && unit_types[unit_type].tech_requirement != A_LAST) {
+ } else if (tech_dist > 0 && (shore || move_type == LAND_MOVING)) {
/* We first need to develop the tech required by the unit... */
+ int tech_cost = num_unknown_bulbs_for_reqs(pplayer,
+ get_unit_type(unit_type)->req);
/* Cost (shield equivalent) of gaining these techs. */
/* FIXME? Katvrr advises that this should be weighted more heavily in
* big danger. */
- int tech_cost = total_bulbs_required_for_goal(pplayer,
- unit_types[unit_type].tech_requirement) / 4
- / city_list_size(&pplayer->cities);
-
+ tech_cost /= (4 * city_list_size(&pplayer->cities));
+
/* Contrary to the above, we don't care if walls are actually built
* - we're looking into the future now. */
if (move_type == LAND_MOVING) {
@@ -743,15 +784,30 @@
/* Update tech_want for appropriate techs for units we want to build. */
simple_ai_unit_type_iterate (unit_type) {
if (tech_desire[unit_type] > 0) {
- Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
+ int count = 0, i;
+ struct unit_type *ut = get_unit_type(unit_type);
int desire = tech_desire[unit_type]
* unit_build_shield_cost(best_unit_type) / best;
+
+ /* Divide the desire among all tech reqs. FIXME: we should account
+ * for non-tech reqs as well. */
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ count++;
+ }
+ }
+ assert(count > 0);
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ Tech_Type_id tech_req = ut->req[i].value.tech;
+
+ pplayer->ai.tech_want[tech_req] += desire / count;
- pplayer->ai.tech_want[tech_req] += desire;
-
- freelog(LOG_DEBUG, "%s wants %s for defense with desire %d <%d>",
- pcity->name, get_tech_name(pplayer, tech_req), desire,
- tech_desire[unit_type]);
+ freelog(LOG_DEBUG, "%s wants %s for defense with desire %d <%d>",
+ pcity->name, get_tech_name(pplayer, tech_req), desire,
+ tech_desire[unit_type]);
+ }
+ }
}
} simple_ai_unit_type_iterate_end;
@@ -808,18 +864,11 @@
}
simple_ai_unit_type_iterate (unit_type) {
- Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
int move_type = unit_types[unit_type].move_type;
- int tech_dist;
-
- if (tech_req != A_LAST) {
- tech_dist = num_unknown_techs_for_goal(pplayer, tech_req);
- } else {
- tech_dist = 0;
- }
+ struct unit_type *ut = get_unit_type(unit_type);
+ int tech_dist = num_unknown_techs_for_reqs(pplayer, ut->req);
if ((move_type == LAND_MOVING || (move_type == SEA_MOVING && shore))
- && tech_req != A_LAST
&& (tech_dist > 0
|| unit_types[unit_type].obsoleted_by == U_NOT_OBSOLETED
|| !can_build_unit_direct(pcity,
@@ -832,9 +881,9 @@
/* Cost (shield equivalent) of gaining these techs. */
/* FIXME? Katvrr advises that this should be weighted more heavily in big
* danger. */
- int tech_cost = total_bulbs_required_for_goal(pplayer,
- unit_types[unit_type].tech_requirement) / 4
- / city_list_size(&pplayer->cities);
+ struct unit_type *ut = get_unit_type(unit_type);
+ int tech_cost = (num_unknown_bulbs_for_reqs(pplayer, ut->req)
+ / (4 * city_list_size(&pplayer->cities)));
int move_rate = unit_types[unit_type].move_rate;
int move_time;
int bcost_balanced = build_cost_balanced(unit_type);
@@ -919,15 +968,32 @@
if (want > 0) {
if (tech_dist > 0) {
- /* This is a future unit, tell the scientist how much we need it */
- pplayer->ai.tech_want[tech_req] += want;
-
- CITY_LOG(LOG_DEBUG, pcity, "wants %s to build %s to punish
%s@(%d,%d)"
- " with desire %d", get_tech_name(pplayer, tech_req),
- unit_name(unit_type), (acity ? acity->name : "enemy"),
- TILE_XY(ptile), want);
+ int i, count = 0;
- } else if (want > best_choice->want) {
+ /* Divide the desire among all tech reqs. FIXME: we should account
+ * for non-tech reqs as well. */
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ count++;
+ }
+ }
+ assert(count > 0);
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ Tech_Type_id tech_req = ut->req[i].value.tech;
+
+ /* This is a future unit -
+ * tell the scientist how much we need it */
+ pplayer->ai.tech_want[tech_req] += want / count;
+
+ CITY_LOG(LOG_DEBUG, pcity,
+ "wants %s to build %s to punish %s@(%d,%d)"
+ " with desire %d", get_tech_name(pplayer, tech_req),
+ unit_name(unit_type), (acity ? acity->name : "enemy"),
+ TILE_XY(ptile), want);
+ }
+ }
+ } else if (want > best_choice->want) {
if (can_build_unit(pcity, unit_type)) {
/* This is a real unit and we really want it */
@@ -940,22 +1006,33 @@
best_choice->choice = unit_type;
best_choice->want = want;
best_choice->type = CT_ATTACKER;
- } else if (can_build_improvement(pcity,
- get_unit_type(unit_type)->impr_requirement)) {
- /* Building this unit requires a specific type of improvement.
- * So we build this improvement instead. This may not be the
- * best behavior. */
- Impr_Type_id id = get_unit_type(unit_type)->impr_requirement;
-
- CITY_LOG(LOG_DEBUG, pcity, "building %s to build %s",
- get_improvement_type(id)->name,
- get_unit_type(unit_type)->name);
- best_choice->choice = id;
- best_choice->want = want;
- best_choice->type = CT_BUILDING;
} else {
- /* This should never happen? */
- }
+ struct unit_type *ut = get_unit_type(unit_type);
+ int i;
+
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE;
+ i++) {
+ if (ut->req[i].type == REQ_BUILDING
+ && !is_req_active(TARGET_CITY, city_owner(pcity), pcity,
+ B_LAST, NULL, &ut->req[i])) {
+ /* Building this unit requires a specific type of
+ * improvement. So we build this improvement instead. This
+ * may not be the best behavior. */
+ Impr_Type_id id = ut->req[i].value.building;
+
+ if (can_build_improvement(pcity, id)) {
+
+ CITY_LOG(LOG_DEBUG, pcity, "building %s to build %s",
+ get_improvement_type(id)->name,
+ get_unit_type(unit_type)->name);
+ best_choice->choice = id;
+ best_choice->want = want;
+ best_choice->type = CT_BUILDING;
+ break;
+ }
+ }
+ }
+ } /* if can_build_unit ... else ... */
}
}
}
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.187
diff -u -r1.187 aicity.c
--- ai/aicity.c 21 Dec 2004 04:18:53 -0000 1.187
+++ ai/aicity.c 23 Dec 2004 22:27:09 -0000
@@ -661,9 +661,22 @@
/* Choose among those made available through other civ's research */
for(i = 0; i < num_role_units(L_BARBARIAN_BUILD_TECH); i++) {
Unit_Type_id iunit = get_role_unit(L_BARBARIAN_BUILD_TECH, i);
+ int j;
+ struct unit_type *ut = get_unit_type(iunit);
+ bool missing_tech = FALSE;
- if (game.global_advances[get_unit_type(iunit)->tech_requirement] != 0
- && get_unit_type(iunit)->attack_strength > bestattack) {
+ if (get_unit_type(iunit)->attack_strength <= bestattack) {
+ continue;
+ }
+ for (j = 0; j < MAX_NUM_REQS; j++) {
+ if (ut->req[i].type == REQ_TECH
+ && !game.global_advances[ut->req[i].value.tech]) {
+ missing_tech = TRUE;
+ break;
+ }
+ }
+
+ if (!missing_tech) {
bestunit = iunit;
bestattack = get_unit_type(iunit)->attack_strength;
}
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.43
diff -u -r1.43 aidiplomat.c
--- ai/aidiplomat.c 19 Dec 2004 19:44:39 -0000 1.43
+++ ai/aidiplomat.c 23 Dec 2004 22:27:09 -0000
@@ -115,13 +115,21 @@
choice->type = CT_DEFENDER;
choice->choice = u;
} else if (num_role_units(F_DIPLOMAT) > 0) {
+ struct unit_type *ut;
+ int i;
+
/* We don't know diplomats yet... */
freelog(LOG_DIPLOMAT_BUILD,
"A defensive diplomat is wanted badly in city %s.", pcity->name);
u = get_role_unit(F_DIPLOMAT, 0);
+ ut = get_unit_type(u);
/* 3000 is a just a large number, but not hillariously large as the
previously used one. This is important for diplomacy later - Per */
- pplayer->ai.tech_want[get_unit_type(u)->tech_requirement] += 3000;
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ pplayer->ai.tech_want[ut->req[i].value.tech] += 3000;
+ }
+ }
}
}
}
Index: ai/aisettler.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aisettler.c,v
retrieving revision 1.14
diff -u -r1.14 aisettler.c
--- ai/aisettler.c 9 Dec 2004 21:27:48 -0000 1.14
+++ ai/aisettler.c 23 Dec 2004 22:27:10 -0000
@@ -587,9 +587,16 @@
if (boattype == U_LAST) {
/* Sea travel not possible yet. Bump tech want for ferries. */
Unit_Type_id boattype = get_role_unit(L_FERRYBOAT, 0);
- Tech_Type_id tech_req = unit_types[boattype].tech_requirement;
+ struct unit_type *ut = get_unit_type(boattype);
+ int i;
- pplayer->ai.tech_want[tech_req] += FERRY_TECH_WANT;
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ if (ut->req[i].type == REQ_TECH) {
+ Tech_Type_id tech_req = ut->req[i].value.tech;
+
+ pplayer->ai.tech_want[tech_req] += FERRY_TECH_WANT;
+ }
+ }
return;
}
ferry = create_unit_virtual(pplayer, NULL, boattype, 0);
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.342
diff -u -r1.342 aiunit.c
--- ai/aiunit.c 20 Dec 2004 23:50:58 -0000 1.342
+++ ai/aiunit.c 23 Dec 2004 22:27:10 -0000
@@ -2235,9 +2235,17 @@
return iunit;
} else {
/* careful; might be unable to build for non-tech reason... */
- itech = get_unit_type(iunit)->tech_requirement;
- if (get_invention(pplayer, itech) != TECH_KNOWN) {
- pplayer->ai.tech_want[itech] += want;
+ int j;
+ struct unit_type *ut = get_unit_type(iunit);
+
+ for (j = 0; j < MAX_NUM_REQS && ut->req[j].type != REQ_NONE; j++) {
+ if (ut->req[j].type == REQ_TECH) {
+ itech = ut->req[i].value.tech;
+
+ if (get_invention(pplayer, itech) != TECH_KNOWN) {
+ pplayer->ai.tech_want[itech] += want;
+ }
+ }
}
}
}
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.455
diff -u -r1.455 packhand.c
--- client/packhand.c 21 Dec 2004 03:36:18 -0000 1.455
+++ client/packhand.c 23 Dec 2004 22:27:11 -0000
@@ -2154,9 +2154,10 @@
u->attack_strength = p->attack_strength;
u->defense_strength = p->defense_strength;
u->move_rate = p->move_rate;
- u->tech_requirement = p->tech_requirement;
- u->impr_requirement = p->impr_requirement;
- u->gov_requirement = p->gov_requirement;
+ for (i = 0; i < MAX_NUM_REQS; i++) {
+ u->req[i] = req_from_values(p->req_type[i], p->req_range[i],
+ p->req_survives[i], p->req_value[i]);
+ }
u->vision_range = p->vision_range;
u->transport_capacity = p->transport_capacity;
u->hp = p->hp;
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.292
diff -u -r1.292 city.c
--- common/city.c 21 Dec 2004 20:06:27 -0000 1.292
+++ common/city.c 23 Dec 2004 22:27:11 -0000
@@ -470,17 +470,22 @@
**************************************************************************/
bool can_build_unit_direct(const struct city *pcity, Unit_Type_id id)
{
- Impr_Type_id impr_req;
+ struct unit_type *ut;
+ int i;
if (!can_player_build_unit_direct(city_owner(pcity), id)) {
return FALSE;
}
/* Check to see if the unit has a building requirement. */
- impr_req = get_unit_type(id)->impr_requirement;
- assert(impr_req <= B_LAST && impr_req >= 0);
- if (impr_req != B_LAST && !city_got_building(pcity, impr_req)) {
- return FALSE;
+ ut = get_unit_type(id);
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ /* Reqs with >= player range are checked earlier. */
+ if (ut->req[i].range < REQ_RANGE_PLAYER
+ && !is_req_active(TARGET_CITY, city_owner(pcity), pcity, B_LAST,
+ NULL, &ut->req[i])) {
+ return FALSE;
+ }
}
/* You can't build naval units inland. */
Index: common/fc_types.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fc_types.h,v
retrieving revision 1.12
diff -u -r1.12 fc_types.h
--- common/fc_types.h 16 Dec 2004 20:37:49 -0000 1.12
+++ common/fc_types.h 23 Dec 2004 22:27:11 -0000
@@ -41,4 +41,6 @@
#define SP_MAX 20
+#define MAX_NUM_REQS 2
+
#endif /* FC__FC_TYPES_H */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.85
diff -u -r1.85 packets.def
--- common/packets.def 21 Dec 2004 03:36:18 -0000 1.85
+++ common/packets.def 23 Dec 2004 22:27:11 -0000
@@ -939,9 +939,10 @@
UINT8 attack_strength;
UINT8 defense_strength;
UINT8 move_rate;
- TECH tech_requirement;
- UINT8 impr_requirement;
- GOVERNMENT gov_requirement;
+ REQ_TYPE req_type[MAX_NUM_REQS];
+ REQ_RANGE req_range[MAX_NUM_REQS];
+ BOOL req_survives[MAX_NUM_REQS];
+ SINT16 req_value[MAX_NUM_REQS];
UINT8 vision_range;
UINT8 transport_capacity;
UINT8 hp;
Index: common/unittype.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v
retrieving revision 1.47
diff -u -r1.47 unittype.c
--- common/unittype.c 8 Dec 2004 14:36:22 -0000 1.47
+++ common/unittype.c 23 Dec 2004 22:27:13 -0000
@@ -444,8 +444,8 @@
**************************************************************************/
bool can_player_build_unit_direct(struct player *p, Unit_Type_id id)
{
- Impr_Type_id impr_req;
- Tech_Type_id tech_req;
+ struct unit_type *ut;
+ int i;
CHECK_UNIT_TYPE(id);
if (unit_type_flag(id, F_NUCLEAR)
@@ -454,16 +454,20 @@
if (unit_type_flag(id, F_NOBUILD)) {
return FALSE;
}
- if (unit_types[id].gov_requirement != G_MAGIC
- && unit_types[id].gov_requirement != p->government) {
- return FALSE;
- }
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)
- return FALSE;
+
+ ut = get_unit_type(id);
+ for (i = 0; i < MAX_NUM_REQS && ut->req[i].type != REQ_NONE; i++) {
+ /* Reqs with < player range are checked later. */
+ if (ut->req[i].range >= REQ_RANGE_PLAYER
+ && !is_req_active(TARGET_PLAYER, p, NULL, B_LAST, NULL,
+ &ut->req[i])) {
+ return FALSE;
+ }
+ }
if (unit_type_flag(id, F_UNIQUE)) {
/* FIXME: This could be slow if we have lots of units. We could
* consider keeping an array of unittypes updated with this info
@@ -475,15 +479,6 @@
} unit_list_iterate_end;
}
- /* 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
- * that building, so they still may not be able to build the unit. */
- impr_req = unit_types[id].impr_requirement;
- tech_req = get_improvement_type(impr_req)->tech_req;
- if (impr_req != B_LAST && get_invention(p, tech_req) != TECH_KNOWN) {
- return FALSE;
- }
-
return TRUE;
}
Index: common/unittype.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.h,v
retrieving revision 1.38
diff -u -r1.38 unittype.h
--- common/unittype.h 8 Dec 2004 14:36:22 -0000 1.38
+++ common/unittype.h 23 Dec 2004 22:27:13 -0000
@@ -16,6 +16,7 @@
#include "shared.h"
#include "fc_types.h"
+#include "requirements.h"
struct Sprite; /* opaque; client-gui specific */
@@ -189,9 +190,7 @@
int attack_strength;
int defense_strength;
int move_rate;
- int tech_requirement;
- int impr_requirement; /* should be Impr_Type_id */
- int gov_requirement;
+ struct requirement req[MAX_NUM_REQS];
int vision_range;
int transport_capacity;
int hp;
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.224
diff -u -r1.224 ruleset.c
--- server/ruleset.c 21 Dec 2004 03:36:19 -0000 1.224
+++ server/ruleset.c 23 Dec 2004 22:27:14 -0000
@@ -876,18 +876,31 @@
free(def_vblist);
}
- /* Tech and Gov requirements */
+ /* Requirements. */
unit_type_iterate(i) {
+ int r;
+
u = &unit_types[i];
- u->tech_requirement = lookup_tech(file, sec[i], "tech_req",
- TRUE, filename, u->name);
- if (section_file_lookup(file, "%s.gov_req", sec[i])) {
- char tmp[200] = "\0";
- mystrlcat(tmp, sec[i], 200);
- mystrlcat(tmp, ".gov_req", 200);
- u->gov_requirement = lookup_government(file, tmp, filename);
- } else {
- u->gov_requirement = G_MAGIC; /* no requirement */
+ for (r = 0; r < MAX_NUM_REQS; r++) {
+ const char *type
+ = secfile_lookup_str_default(file, NULL, "%s.req%d.type", sec[i], r);
+ const char *range
+ = secfile_lookup_str_default(file, "", "%s.req%d.range", sec[i], r);
+ bool survives
+ = secfile_lookup_bool_default(file, FALSE, "%s.req%d.survives",
+ sec[i], r);
+ const char *value
+ = secfile_lookup_str_default(file, "", "%s.req%d.value", sec[i], r);
+ struct requirement req = req_from_str(type, range, survives, value);
+
+ if (req.type == REQ_LAST) {
+ freelog(LOG_ERROR,
+ "Unit %s has unknoqn req: \"%s\" \"%s\" \"%s\" %d (%s)",
+ sec[i], type, range, value, survives, filename);
+ req.type = REQ_NONE;
+ }
+
+ u->req[i] = req;
}
} unit_type_iterate_end;
@@ -901,10 +914,6 @@
unit_type_iterate(i) {
u = &unit_types[i];
- u->impr_requirement =
- find_improvement_by_name(secfile_lookup_str_default(file, "None",
- "%s.impr_req", sec[i]));
-
sval = secfile_lookup_str(file, "%s.move_type", sec[i]);
ival = unit_move_type_from_str(sval);
if (ival==0) {
@@ -1024,17 +1033,6 @@
lookup_tech_list(file, "u_specials", "partisan_req",
game.rtech.partisan_req, filename);
- /* Some more consistency checking: */
- unit_type_iterate(i) {
- u = &unit_types[i];
- if (!tech_exists(u->tech_requirement)) {
- freelog(LOG_ERROR,
- "unit_type \"%s\" depends on removed tech \"%s\" (%s)",
- u->name, advances[u->tech_requirement].name, filename);
- u->tech_requirement = A_LAST;
- }
- } unit_type_iterate_end;
-
/* Setup roles and flags pre-calcs: */
role_unit_precalcs();
@@ -1095,10 +1093,20 @@
for(i=0; i<num_role_units(L_FERRYBOAT); i++) {
j = get_role_unit(L_FERRYBOAT,i);
if (!unit_type_flag(j, F_TRIREME)) {
- j = get_unit_type(j)->tech_requirement;
- freelog(LOG_DEBUG, "nav tech is %s", advances[j].name);
- game.rtech.nav = j;
- break;
+ int r;
+ struct unit_type *ut = get_unit_type(j);
+
+ for (r = 0; r < MAX_NUM_REQS && ut->req[r].type != REQ_NONE; r++) {
+ if (ut->req[r].type == REQ_TECH) {
+ j = ut->req[r].value.tech;
+ freelog(LOG_DEBUG, "nav tech is %s", advances[j].name);
+ game.rtech.nav = j;
+ break;
+ }
+ }
+ if (game.rtech.nav != A_LAST) {
+ break;
+ }
}
}
@@ -1107,9 +1115,18 @@
if (num_role_units(L_PARTISAN)==0) {
game.rtech.u_partisan = A_LAST;
} else {
+ struct unit_type *ut;
+ int r;
+
j = get_role_unit(L_PARTISAN, 0);
- j = game.rtech.u_partisan = get_unit_type(j)->tech_requirement;
- freelog(LOG_DEBUG, "partisan tech is %s", advances[j].name);
+ ut = get_unit_type(j);
+ for (r = 0; r < MAX_NUM_REQS && ut->req[r].type != REQ_NONE; r++) {
+ if (ut->req[r].type == REQ_TECH) {
+ j = game.rtech.u_partisan = ut->req[r].value.tech;
+ freelog(LOG_DEBUG, "partisan tech is %s", advances[j].name);
+ break;
+ }
+ }
}
update_simple_ai_types();
@@ -2755,9 +2772,16 @@
packet.attack_strength = u->attack_strength;
packet.defense_strength = u->defense_strength;
packet.move_rate = u->move_rate;
- packet.tech_requirement = u->tech_requirement;
- packet.impr_requirement = u->impr_requirement;
- packet.gov_requirement = u->gov_requirement;
+ for (i = 0; i < MAX_NUM_REQS; i++) {
+ int type, range, value;
+ bool survives;
+
+ req_get_values(&u->req[i], &type, &range, &survives, &value);
+ packet.req_type[i] = type;
+ packet.req_range[i] = range;
+ packet.req_survives[i] = survives;
+ packet.req_value[i] = value;
+ }
packet.vision_range = u->vision_range;
packet.transport_capacity = u->transport_capacity;
packet.hp = u->hp;
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.314
diff -u -r1.314 unittools.c
--- server/unittools.c 16 Dec 2004 23:18:48 -0000 1.314
+++ server/unittools.c 23 Dec 2004 22:27:15 -0000
@@ -95,12 +95,22 @@
int find_a_unit_type(int role, int role_tech)
{
int which[U_LAST];
- int i, num=0;
+ int i, num=0, r;
if (role_tech != -1) {
for(i=0; i<num_role_units(role_tech); i++) {
int iunit = get_role_unit(role_tech, i);
- if (game.global_advances[get_unit_type(iunit)->tech_requirement] >= 2) {
+ struct unit_type *ut = get_unit_type(iunit);
+ bool missing_tech = FALSE;
+
+ for (r = 0; r < MAX_NUM_REQS && ut->req[r].type != REQ_NONE; r++) {
+ if (ut->req[r].type == REQ_TECH
+ && game.global_advances[ut->req[r].value.tech] < 2) {
+ missing_tech = TRUE;
+ break;
+ }
+ }
+ if (!missing_tech) {
which[num++] = iunit;
}
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#11672) unit reqs,
Jason Short <=
|
|