[Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity()
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13384 >
This patch replaces ground_unit_transporter_capacity() and
is_ground_units_transport() with more generic
unit_class_transporter_capacity() and can_unit_type_transport().
Biggest change is that ground_unit_transporter_capacity() used to
subtract even not transported units from capacity, for instance when
transporter is in a city, but unit_class_transporter_capacity() returns
actual free space in transporters. As a side effect #11064 is solved to
the extend that it does not cause real problems (allied transporter
filled with allys allies is not considered empty)
Developed on top of #13344, patch may apply without it or maybe not.
- ML
diff -Nurd -X.diff_ignore freeciv/ai/advmilitary.c freeciv/ai/advmilitary.c
--- freeciv/ai/advmilitary.c 2005-06-29 02:13:46.328125000 +0300
+++ freeciv/ai/advmilitary.c 2005-06-30 00:33:18.890625000 +0300
@@ -489,7 +489,7 @@
}
if ((is_ground_unit(punit) && vulnerability != 0)
- || (is_ground_units_transport(punit))) {
+ || (can_unit_type_transport(punit->type, UCL_LAND))) {
if (dist <= move_rate * 3 || dist <= paramove + move_rate) {
urgency++;
}
diff -Nurd -X.diff_ignore freeciv/ai/aidata.c freeciv/ai/aidata.c
--- freeciv/ai/aidata.c 2005-06-29 02:13:46.328125000 +0300
+++ freeciv/ai/aidata.c 2005-06-30 00:33:18.984375000 +0300
@@ -458,7 +458,7 @@
if (is_sailing_unit(punit)) {
/* If the enemy has not started sailing yet, or we have total
* control over the seas, don't worry, keep attacking. */
- if (is_ground_units_transport(punit)) {
+ if (can_unit_type_transport(punit->type, UCL_LAND)) {
ai->threats.invasions = TRUE;
}
diff -Nurd -X.diff_ignore freeciv/ai/aiferry.c freeciv/ai/aiferry.c
--- freeciv/ai/aiferry.c 2005-06-29 02:13:46.343750000 +0300
+++ freeciv/ai/aiferry.c 2005-06-30 00:33:19.109375000 +0300
@@ -76,7 +76,7 @@
ai->stats.available_boats = 0;
unit_list_iterate(pplayer->units, punit) {
- if (is_sailing_unit(punit) && is_ground_units_transport(punit)) {
+ if (is_sailing_unit(punit) && can_unit_type_transport(punit->type,
UCL_LAND)) {
ai->stats.boats++;
if (punit->ai.passenger == FERRY_AVAILABLE) {
ai->stats.available_boats++;
@@ -103,8 +103,8 @@
freelog(LOG_NORMAL, "Registered: %d free out of total %d",
ai->stats.available_boats, ai->stats.boats);
unit_list_iterate(pplayer->units, punit) {
- if (is_sailing_unit(punit) && is_ground_units_transport(punit)) {
- freelog(LOG_NORMAL, "#%d. %s[%d], psngr=%d",
+ if (is_sailing_unit(punit) && can_unit_type_transport(punit->type,
UCL_LAND)) {
+ freelog(LOG_NORMAL, "#%d. %s[%d], psngr=%d",
n, unit_type(punit)->name, punit->id, punit->ai.passenger);
n++;
}
@@ -203,7 +203,7 @@
int boats = 0;
unit_list_iterate(pplayer->units, punit) {
- if (is_sailing_unit(punit) && is_ground_units_transport(punit)
+ if (is_sailing_unit(punit) && can_unit_type_transport(punit->type,
UCL_LAND)
&& punit->ai.passenger == FERRY_AVAILABLE) {
boats++;
}
diff -Nurd -X.diff_ignore freeciv/common/aicore/pf_tools.c
freeciv/common/aicore/pf_tools.c
--- freeciv/common/aicore/pf_tools.c 2005-06-29 02:13:46.343750000 +0300
+++ freeciv/common/aicore/pf_tools.c 2005-06-30 00:33:19.203125000 +0300
@@ -126,7 +126,7 @@
int move_cost;
if (is_ocean(terrain1)) {
- if (ground_unit_transporter_capacity(ptile1, param->owner) > 0) {
+ if (unit_class_transporter_capacity(ptile1, param->owner, UCL_LAND) > 0) {
move_cost = SINGLE_MOVE;
} else {
move_cost = PF_IMPOSSIBLE_MC;
@@ -159,7 +159,7 @@
if (is_ocean(tgt_tile->terrain)) {
/* Any-to-Sea */
- if (ground_unit_transporter_capacity(tgt_tile, param->owner) > 0) {
+ if (unit_class_transporter_capacity(tgt_tile, param->owner, UCL_LAND) > 0)
{
move_cost = SINGLE_MOVE;
} else {
move_cost = PF_IMPOSSIBLE_MC;
@@ -245,7 +245,7 @@
int move_cost = PF_IMPOSSIBLE_MC;
if (is_ocean(terrain1)) {
- if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
+ if (unit_class_transporter_capacity(ptile, param->owner, UCL_LAND) > 0) {
/* Landing */
move_cost = get_tile_type(terrain0)->movement_cost * SINGLE_MOVE;
} else {
@@ -273,7 +273,7 @@
int move_cost;
if (is_ocean(ptile1->terrain)) {
- if (ground_unit_transporter_capacity(ptile1, param->owner) > 0) {
+ if (unit_class_transporter_capacity(ptile1, param->owner, UCL_LAND) > 0) {
move_cost = MOVE_COST_ROAD;
} else {
move_cost = PF_IMPOSSIBLE_MC;
@@ -306,7 +306,7 @@
int move_cost;
if (is_ocean(tile_get_terrain(ptile))) {
- if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
+ if (unit_class_transporter_capacity(ptile, param->owner, UCL_LAND) > 0) {
/* Landing */
move_cost = MOVE_COST_ROAD;
} else {
diff -Nurd -X.diff_ignore freeciv/common/movement.c freeciv/common/movement.c
--- freeciv/common/movement.c 2005-06-30 00:32:36.234375000 +0300
+++ freeciv/common/movement.c 2005-06-30 00:36:32.953125000 +0300
@@ -23,6 +23,7 @@
#include "support.h"
#include "fc_types.h"
+#include "game.h"
#include "map.h"
#include "movement.h"
#include "unit.h"
@@ -30,9 +31,6 @@
#include "terrain.h"
-static bool can_unit_type_transport(Unit_type_id transporter,
- Unit_type_id transported);
-
/****************************************************************************
This function calculates the move rate of the unit, taking into
account the penalty for reduced hitpoints (affects sea and land
@@ -354,10 +352,11 @@
return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT;
}
+ /* 4) */
if (unit_types[type].move_type == LAND_MOVING) {
- /* 4) */
- if (is_ocean(dst_tile->terrain) &&
- ground_unit_transporter_capacity(dst_tile, unit_owner) <= 0) {
+ if (is_ocean(dst_tile->terrain)
+ && unit_class_transporter_capacity(dst_tile, unit_owner,
+ get_unit_type(type)->class) <= 0) {
/* Ground units can't move onto ocean tiles unless there's enough
* room on transporters for them. */
return MR_NO_SEA_TRANSPORTER_CAPACITY;
@@ -423,20 +422,24 @@
bool can_unit_transport(const struct unit *transporter,
const struct unit *transported)
{
- return can_unit_type_transport(transporter->type, transported->type);
+ return can_unit_type_transport(transporter->type,
+ get_unit_type(transported->type)->class);
}
/**************************************************************************
- Return TRUE iff transporter type has ability to transport transported type.
+ Return TRUE iff transporter type has ability to transport transported class
**************************************************************************/
-static bool can_unit_type_transport(Unit_type_id transporter,
- Unit_type_id transported)
+bool can_unit_type_transport(Unit_type_id transporter,
+ Unit_Class_id transported)
{
+ struct unit_class *pclass = unit_class_from_id(transported);
+
if (get_unit_type(transporter)->transport_capacity <= 0) {
return FALSE;
}
- if (get_unit_type(transported)->move_type == LAND_MOVING) {
+ /* TODO: Should not be hardcoded into class enum */
+ if (pclass->id == UCL_LAND) {
if ((unit_type_flag(transporter, F_CARRIER)
|| unit_type_flag(transporter, F_MISSILE_CARRIER))) {
return FALSE;
@@ -444,26 +447,53 @@
return TRUE;
}
- if (!unit_type_flag(transported, F_MISSILE)
- && unit_type_flag(transporter, F_MISSILE_CARRIER)) {
+ if (pclass->id != UCL_MISSILE && pclass->id != UCL_NUCLEAR
+ && unit_type_flag(transporter, F_MISSILE_CARRIER)) {
return FALSE;
}
- if (unit_type_flag(transported, F_MISSILE)) {
+ if (pclass->id == UCL_MISSILE || pclass->id == UCL_NUCLEAR) {
if (!unit_type_flag(transporter, F_MISSILE_CARRIER)
&& !unit_type_flag(transporter, F_CARRIER)) {
return FALSE;
}
- } else if ((get_unit_type(transported)->move_type == AIR_MOVING
- || get_unit_type(transported)->move_type == HELI_MOVING)
+ } else if ((pclass->id == UCL_AIR || pclass->id == UCL_HELICOPTER)
&& !unit_type_flag(transporter, F_CARRIER)) {
return FALSE;
}
- if (get_unit_type(transported)->move_type == SEA_MOVING) {
+ if (pclass->id == UCL_SEA) {
/* No unit can transport sea units at the moment */
return FALSE;
}
return TRUE;
}
+
+/**************************************************************************
+ Returns the number of free spaces for units of given class.
+ Can be 0.
+**************************************************************************/
+int unit_class_transporter_capacity(const struct tile *ptile,
+ const struct player *pplayer,
+ Unit_Class_id class)
+{
+ int availability = 0;
+
+ unit_list_iterate(ptile->units, punit) {
+ if (unit_owner(punit) == pplayer
+ || pplayers_allied(unit_owner(punit), pplayer)) {
+
+ if (can_unit_type_transport(punit->type, class)) {
+ availability += get_transporter_capacity(punit);
+ unit_list_iterate(ptile->units, cargo) {
+ if (cargo->transported_by == punit->id) {
+ availability--;
+ }
+ } unit_list_iterate_end;
+ }
+ }
+ } unit_list_iterate_end;
+
+ return availability;
+}
diff -Nurd -X.diff_ignore freeciv/common/movement.h freeciv/common/movement.h
--- freeciv/common/movement.h 2005-06-29 02:13:46.359375000 +0300
+++ freeciv/common/movement.h 2005-06-30 00:33:19.421875000 +0300
@@ -49,5 +49,10 @@
const struct tile *dst_tile,
bool igzoc);
bool can_unit_transport(const struct unit *transporter, const struct unit
*transported);
+bool can_unit_type_transport(Unit_type_id transporter,
+ Unit_Class_id transported);
+int unit_class_transporter_capacity(const struct tile *ptile,
+ const struct player *pplayer,
+ Unit_Class_id class);
#endif /* FC__MOVEMENT_H */
diff -Nurd -X.diff_ignore freeciv/common/unit.c freeciv/common/unit.c
--- freeciv/common/unit.c 2005-06-29 02:13:46.359375000 +0300
+++ freeciv/common/unit.c 2005-06-30 00:33:19.546875000 +0300
@@ -213,31 +213,6 @@
&& can_cities_trade(phomecity, pdestcity));
}
-
-/**************************************************************************
-Returns the number of free spaces for ground units. Can be 0 or negative.
-**************************************************************************/
-int ground_unit_transporter_capacity(const struct tile *ptile,
- const struct player *pplayer)
-{
- int availability = 0;
-
- unit_list_iterate(ptile->units, punit) {
- if (unit_owner(punit) == pplayer
- || pplayers_allied(unit_owner(punit), pplayer)) {
- if (is_ground_units_transport(punit)
- && !(is_ground_unit(punit) && is_ocean(ptile->terrain))) {
- availability += get_transporter_capacity(punit);
- } else if (is_ground_unit(punit)) {
- availability--;
- }
- }
- }
- unit_list_iterate_end;
-
- return availability;
-}
-
/**************************************************************************
Return the number of units the transporter can hold (or 0).
**************************************************************************/
@@ -247,16 +222,6 @@
}
/**************************************************************************
- Return TRUE iff the unit is a transporter of ground units.
-**************************************************************************/
-bool is_ground_units_transport(const struct unit *punit)
-{
- return (get_transporter_capacity(punit) > 0
- && !unit_flag(punit, F_MISSILE_CARRIER)
- && !unit_flag(punit, F_CARRIER));
-}
-
-/**************************************************************************
Is the unit capable of attacking?
**************************************************************************/
bool is_attack_unit(const struct unit *punit)
@@ -1580,7 +1545,7 @@
if (get_transporter_occupancy(punit) >
unit_types[to_unittype].transport_capacity) {
/* TODO: allow transported units to be reassigned. Check for
- * ground_unit_transporter_capacity here and make changes to
+ * unit_class_transporter_capacity(UCL_LAND) here and make changes to
* upgrade_unit. */
return UR_NOT_ENOUGH_ROOM;
}
diff -Nurd -X.diff_ignore freeciv/common/unit.h freeciv/common/unit.h
--- freeciv/common/unit.h 2005-06-29 02:13:46.375000000 +0300
+++ freeciv/common/unit.h 2005-06-30 00:33:19.640625000 +0300
@@ -287,10 +287,7 @@
bool kills_citizen_after_attack(const struct unit *punit);
const char *unit_activity_text(const struct unit *punit);
-int ground_unit_transporter_capacity(const struct tile *ptile,
- const struct player *pplayer);
int get_transporter_capacity(const struct unit *punit);
-bool is_ground_units_transport(const struct unit *punit);
int missile_carrier_capacity(const struct tile *ptile,
const struct player *pplayer,
bool count_units_with_extra_fuel);
diff -Nurd -X.diff_ignore freeciv/common/unittype.c freeciv/common/unittype.c
--- freeciv/common/unittype.c 2005-06-30 00:32:36.328125000 +0300
+++ freeciv/common/unittype.c 2005-06-30 00:33:19.765625000 +0300
@@ -61,7 +61,7 @@
"Sea",
"Helicopter",
"Air",
- "Nuclear",
+ "Nuclear"
};
struct unit_class unit_classes[] = {
@@ -685,3 +685,11 @@
{
return &unit_classes[get_unit_type(type)->class];
}
+
+/***************************************************************
+ Returns unit class structure
+***************************************************************/
+struct unit_class *unit_class_from_id(Unit_Class_id class)
+{
+ return &unit_classes[class];
+}
diff -Nurd -X.diff_ignore freeciv/common/unittype.h freeciv/common/unittype.h
--- freeciv/common/unittype.h 2005-06-30 00:32:36.421875000 +0300
+++ freeciv/common/unittype.h 2005-06-30 00:33:19.875000000 +0300
@@ -230,6 +230,8 @@
int unit_pop_value(Unit_type_id id);
struct unit_class *get_unit_class(Unit_type_id type);
+struct unit_class *unit_class_from_id(Unit_Class_id class);
+
const char *unit_name(Unit_type_id id);
const char *unit_name_orig(Unit_type_id id);
const char *unit_class_name(Unit_Class_id id);
diff -Nurd -X.diff_ignore freeciv/server/gotohand.c freeciv/server/gotohand.c
--- freeciv/server/gotohand.c 2005-06-29 02:13:46.390625000 +0300
+++ freeciv/server/gotohand.c 2005-06-30 00:33:20.000000000 +0300
@@ -306,7 +306,7 @@
continue; /* No need for all the calculations */
if (is_ocean(tile_get_terrain(tile1))) {
- if (punit && ground_unit_transporter_capacity(tile1, pplayer) > 0)
+ if (punit && unit_class_transporter_capacity(tile1, pplayer,
UCL_LAND) > 0)
move_cost = SINGLE_MOVE;
else
continue;
@@ -650,7 +650,7 @@
RR loops, ie you can't create a cycle with the same
move_cost */
if (is_ocean(pdesttile->terrain)) {
- if (ground_unit_transporter_capacity(tile1, unit_owner(punit)) <= 0)
+ if (unit_class_transporter_capacity(tile1, unit_owner(punit),
UCL_LAND) <= 0)
continue;
else
move_cost = 3;
@@ -1247,7 +1247,7 @@
if (is_ocean(tile_get_terrain(ptile))) {
/* Going to a sea tile, the target should be next to our continent
* and with a boat */
- if (ground_unit_transporter_capacity(ptile, pplayer) > 0) {
+ if (unit_class_transporter_capacity(ptile, pplayer, UCL_LAND) > 0) {
adjc_iterate(ptile, tmp_tile) {
if (tile_get_continent(tmp_tile) == tile_get_continent(punit->tile))
/* The target is adjacent to our continent! */
diff -Nurd -X.diff_ignore freeciv/server/settlers.c freeciv/server/settlers.c
--- freeciv/server/settlers.c 2005-06-29 02:13:46.406250000 +0300
+++ freeciv/server/settlers.c 2005-06-30 00:33:20.093750000 +0300
@@ -666,8 +666,6 @@
The "virtual boats" code is not used. It is probably too unreliable,
since the AI switches its production back and forth continously.
- FIXME: if there is a (free) boat in a city filled with units,
- ground_unit_transporter_capacity will return negative.
TODO: Kill me. There is a reliable version of this, find_ferry.
**************************************************************************/
Unit_type_id find_boat(struct player *pplayer, struct tile **ptile, int cap)
@@ -675,11 +673,11 @@
int best = 22; /* arbitrary maximum distance, I will admit! */
Unit_type_id id = 0;
unit_list_iterate(pplayer->units, aunit)
- if (is_ground_units_transport(aunit)) {
+ if (can_unit_type_transport(aunit->type, UCL_LAND)) {
if (WARMAP_COST(aunit->tile) < best &&
(WARMAP_COST(aunit->tile) == 0 ||
- ground_unit_transporter_capacity(aunit->tile,
- pplayer) >= cap)) {
+ unit_class_transporter_capacity(aunit->tile,
+ pplayer, UCL_LAND) >= cap)) {
id = aunit->id;
best = WARMAP_COST(aunit->tile);
*ptile = aunit->tile;
diff -Nurd -X.diff_ignore freeciv/server/unittools.c freeciv/server/unittools.c
--- freeciv/server/unittools.c 2005-06-30 00:32:36.515625000 +0300
+++ freeciv/server/unittools.c 2005-06-30 00:52:36.515625000 +0300
@@ -926,8 +926,8 @@
/* look for nearby transport */
adjc_iterate(ptile, ptile2) {
if (is_ocean(ptile2->terrain)
- && ground_unit_transporter_capacity(ptile2,
- unit_owner(punit2)) > 0) {
+ && unit_class_transporter_capacity(ptile2, unit_owner(punit2),
+ UCL_LAND) > 0) {
if (get_transporter_capacity(punit2) > 0)
sentry_transported_idle_units(punit2);
freelog(LOG_VERBOSE,
@@ -1641,6 +1641,19 @@
struct tile *ptile = punit->tile;
struct player *pplayer = unit_owner(punit);
struct unit_type *ptype = unit_type(punit);
+ int capacity = 0;
+
+ if (wipe_cargo) {
+ if (can_unit_type_transport(punit->type, UCL_LAND)) {
+ /* Old free capacity */
+ capacity = unit_class_transporter_capacity(ptile, pplayer, UCL_LAND);
+ /* Minus capacity of removed transporter */
+ capacity -= get_transporter_capacity(punit);
+ } else {
+ /* No need to wipe the cargo unless it's a ground transporter. */
+ wipe_cargo = FALSE;
+ }
+ }
/* First pull all units off of the transporter. */
if (get_transporter_capacity(punit) > 0) {
@@ -1660,9 +1673,6 @@
} unit_list_iterate_end;
}
- /* No need to wipe the cargo unless it's a ground transporter. */
- wipe_cargo &= is_ground_units_transport(punit);
-
/* Now remove the unit. */
server_remove_unit(punit);
@@ -1672,7 +1682,6 @@
&& is_ocean(tile_get_terrain(ptile))
&& !tile_get_city(ptile)) {
struct city *pcity = NULL;
- int capacity = ground_unit_transporter_capacity(ptile, pplayer);
/* Get rid of excess standard units. */
if (capacity < 0) {
@@ -1720,7 +1729,7 @@
/* Reassign existing units. This is an O(n^2) operation as written. */
unit_list_iterate(ptile->units, ptrans) {
- if (is_ground_units_transport(ptrans)) {
+ if (can_unit_type_transport(ptrans->type, UCL_LAND)) {
int occupancy = get_transporter_occupancy(ptrans);
unit_list_iterate(ptile->units, pcargo) {
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity(),
Marko Lindqvist <=
|
|