[Freeciv-Dev] Re: (PR#4645) Silent Hunter and Sonar code.
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] Re: (PR#4645) Silent Hunter and Sonar code. |
From: |
"Rafa³ Bursig" <bursig@xxxxxxxxx> |
Date: |
Thu, 24 Jul 2003 05:08:53 -0700 |
Reply-to: |
rt@xxxxxxxxxxxxxx |
Dnia 2003.07.23 16:13, Per I. Mathisen napisa³(a):
>
> On Tue, 22 Jul 2003, Rafa³ Bursig wrote:
> > Secundo: This will make sub and destroyer units usefull again, as I
> > know current we have problem with it.
>
> Actually, subs should be quite useful in the cvs version already.
> They have been upgraded rather much. In fact, I do _not_ think that
> further invisibility rules is going to make the sub much better.
> Attack and movement are much more important, the major disadvantage
> with of is that they cannot attack land targets.
>
and what you got :
- attack stronger that battelship
- fast like cruiser
- can carry missels
- cost like Destroyer
this is best ship in game and is avilable before others
> > Secundo: what happen when you try enter on tile with one ally unit
> and one at_peace unit (you know about this unit) ?
>
> It is not allowed.
>
and SH should not allow it.
> > > Finally, the AI will have to see these units with its
> omniscience.
> > > Otherwise a lot of AI code must be rewritten.
> > > But that removes muchof the point of adding them in the first
> > > place, since they cannot beused for single-player. (The same is
> > > already the case for F_PARTIAL_INVIS, BTW, but I plan to fix that
> one
> > > day. That won't be hard.)
> > hmm... why it can be use with single-player ?
> > you can always use it agians AI.
>
> No, my point is: The AI can see all invisible units. So this new
> ability will not work against the AI.
>
> > > The concepts are interesting, but I do not think we should be
> > > introducing them at this time. We have enough code-breaking
> > > patches queued up for the nextrelease as it is.
>
> > I know about it and I plan this change after our primary 1.15
> changes :)
>
> Well, for the record, I am against the switching of attack and
> defense feature. I would like total invisibility to go in some time
> in the future, but not 1.15 and not as any high priority. They should
> also be called F_INVIS and F_SEE_INVIS, I think, to be more general.
this wont switch any parms only normal SH units will auto attack any
'finder' units and I don't care what will be the names.
But you have right we have much work with primary 1.15 code then I'm
stop working on SH now.
Now I sent my last devel version of this code , it has many bugs but
some nice ideas too then please look on it.
Rafal
diff -u -r freeciv/client/clinet.c fc/client/clinet.c
--- freeciv/client/clinet.c Thu Jul 10 13:36:39 2003
+++ fc/client/clinet.c Wed Jul 23 17:37:12 2003
@@ -217,6 +217,8 @@
/* call gui-dependent stuff in gui_main.c */
add_net_input(aconnection.sock);
+ aconnection.player = game.player_ptr;
+
/* now send join_request package */
sz_strlcpy(req.short_name, username);
diff -u -r freeciv/client/control.c fc/client/control.c
--- freeciv/client/control.c Thu Jul 24 12:24:09 2003
+++ fc/client/control.c Wed Jul 23 18:08:30 2003
@@ -1247,8 +1225,8 @@
**************************************************************************/
void do_move_unit(struct unit *punit, struct packet_unit_info *pinfo)
{
- int x, y;
- bool was_teleported;
+ int x, y, vision_range;
+ bool was_teleported, sonar;
was_teleported=!is_tiles_adjacent(punit->x, punit->y, pinfo->x, pinfo->y);
x=punit->x;
@@ -1261,20 +1239,23 @@
unit_list_unlink(&map_get_tile(x, y)->units, punit);
- if(!pinfo->carried)
+ if (!pinfo->carried) {
refresh_tile_mapcanvas(x, y, FALSE);
+ }
- if(game.player_idx==punit->owner && punit->activity!=ACTIVITY_GOTO &&
+ if (game.player_idx==punit->owner && punit->activity!=ACTIVITY_GOTO &&
auto_center_on_unit && punit->activity!=ACTIVITY_SENTRY &&
- !tile_visible_and_not_on_border_mapcanvas(pinfo->x, pinfo->y))
+ !tile_visible_and_not_on_border_mapcanvas(pinfo->x, pinfo->y)) {
center_tile_mapcanvas(pinfo->x, pinfo->y);
+ }
- if(!pinfo->carried && !was_teleported) {
+ if (!pinfo->carried && !was_teleported) {
int dx, dy;
map_distance_vector(&dx, &dy, punit->x, punit->y, pinfo->x, pinfo->y);
- if(smooth_move_units)
+ if (smooth_move_units) {
move_unit_map_canvas(punit, x, y, dx, dy);
+ }
refresh_tile_mapcanvas(x, y, FALSE);
}
@@ -1284,10 +1265,16 @@
punit->hp=pinfo->hp;
unit_list_insert(&map_get_tile(punit->x, punit->y)->units, punit);
- square_iterate(punit->x, punit->y, 2, x, y) {
+ vision_range = get_unit_vision_range(punit);
+ sonar = unit_flag(punit, F_SONAR);
+ square_iterate(punit->x, punit->y, vision_range, x, y) {
bool refresh = FALSE;
+ if (x == punit->x && y == punit->y) {
+ continue;
+ }
unit_list_iterate(map_get_tile(x, y)->units, pu) {
- if (unit_flag(pu, F_PARTIAL_INVIS)) {
+ if (unit_flag(pu, F_PARTIAL_INVIS)
+ || (sonar && unit_flag(pu, F_SILENT_HUNTER))) {
refresh = TRUE;
goto out;
}
@@ -1298,10 +1285,13 @@
}
} square_iterate_end;
- if(!pinfo->carried && tile_get_known(punit->x,punit->y) == TILE_KNOWN)
+ if (!pinfo->carried && tile_get_known(punit->x, punit->y) == TILE_KNOWN) {
refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
+ }
- if(get_unit_in_focus()==punit) update_menus();
+ if (get_unit_in_focus()==punit) {
+ update_menus();
+ }
}
/**************************************************************************
diff -u -r freeciv/client/packhand.c fc/client/packhand.c
--- freeciv/client/packhand.c Thu Jul 24 12:24:10 2003
+++ fc/client/packhand.c Wed Jul 23 16:03:57 2003
@@ -981,8 +981,7 @@
moved = TRUE;
if(tile_get_known(packet->x, packet->y) == TILE_KNOWN
- && player_can_see_unit_at_location(game.player_ptr, punit,
- packet->x, packet->y)) {
+ && TEST_BIT(packet->seen, game.player_ptr->player_no)) {
do_move_unit(punit, packet);
update_unit_focus();
}
@@ -1090,6 +1089,16 @@
}
}
+ /* initialize client side unit 'seen' parm. */
+ players_iterate(pplayer) {
+ if(pplayer == unit_owner(punit)) {
+ continue;
+ }
+ punit->seen |=
+ COND_SET_BIT(pplayers_allied(unit_owner(punit), pplayer),
+ pplayer->player_no);
+ } players_iterate_end
+
if (punit && punit == get_unit_in_focus()) {
update_unit_info_label(punit);
} else if (get_unit_in_focus()
diff -u -r freeciv/common/packets.c fc/common/packets.c
--- freeciv/common/packets.c Thu Jul 24 12:24:14 2003
+++ fc/common/packets.c Wed Jul 23 17:03:04 2003
@@ -1265,7 +1259,8 @@
dio_put_uint16(&dout, req->id);
dio_put_uint8(&dout, req->owner);
- pack = (COND_SET_BIT(req->carried, 3) |
+ pack = (COND_SET_BIT(TEST_BIT(req->seen, pc->player->player_no), 2) |
+ COND_SET_BIT(req->carried, 3) |
COND_SET_BIT(req->veteran, 4) |
COND_SET_BIT(req->ai, 5) |
COND_SET_BIT(req->paradropped, 6) |
@@ -1543,7 +1538,8 @@
dio_get_uint16(&din, &packet->id);
dio_get_uint8(&din, &packet->owner);
dio_get_uint8(&din, &pack);
-
+
+ packet->seen = COND_SET_BIT(TEST_BIT(pack, 2), pc->player->player_no);
packet->carried = TEST_BIT(pack, 3);
packet->veteran = TEST_BIT(pack, 4);
packet->ai = TEST_BIT(pack, 5);
diff -u -r freeciv/common/packets.h fc/common/packets.h
--- freeciv/common/packets.h Thu Jul 24 12:24:14 2003
+++ fc/common/packets.h Wed Jul 23 15:53:51 2003
@@ -307,6 +307,7 @@
int owner;
int x, y;
bool veteran;
+ unsigned int seen;
int homecity;
int type;
int movesleft;
@@ -317,10 +318,10 @@
int upkeep;
int upkeep_food;
int upkeep_gold;
- bool ai;
int fuel;
int goto_dest_x, goto_dest_y;
enum tile_special_type activity_target;
+ bool ai;
bool paradropped;
bool connecting;
/* in packet only, not in unit struct */
diff -u -r freeciv/common/player.c fc/common/player.c
--- freeciv/common/player.c Mon Jul 7 18:58:17 2003
+++ fc/common/player.c Wed Jul 23 16:17:11 2003
@@ -214,44 +214,12 @@
}
/***************************************************************
- Returns TRUE iff the player can see the unit at (x,y), i.e. if
- the unit is not invisible or if it is adjacent to one of our
- cities or units. No map visibility check here! The unit does
- not have to be at (x,y)!
- Allied units and cities can be used for sub hunting.
-***************************************************************/
-bool player_can_see_unit_at_location(struct player *pplayer,
- struct unit *punit,
- int x, int y)
-{
- if (pplayers_allied(unit_owner(punit), pplayer)
- || !is_hiding_unit(punit)) {
- return TRUE;
- }
-
- /* Search for units/cities that might be able to see the sub/missile */
- adjc_iterate(x, y, x1, y1) {
- struct city *pcity = map_get_city(x1, y1);
- unit_list_iterate(map_get_tile(x1, y1)->units, punit2) {
- if (pplayers_allied(unit_owner(punit2), pplayer)) {
- return TRUE;
- }
- } unit_list_iterate_end;
-
- if (pcity && pplayers_allied(city_owner(pcity), pplayer)) {
- return TRUE;
- }
- } adjc_iterate_end;
-
- return FALSE;
-}
-
-/***************************************************************
- Same thing as above only the location is the unit's current one.
+ Returns TRUE if the player can see the unit, it check units
+ knowledge obout it.
***************************************************************/
bool player_can_see_unit(struct player *pplayer, struct unit *punit)
{
- return player_can_see_unit_at_location(pplayer, punit, punit->x, punit->y);
+ return TEST_BIT(punit->seen, pplayer->player_no);
}
/***************************************************************
diff -u -r freeciv/common/player.h fc/common/player.h
--- freeciv/common/player.h Sun Jun 1 09:52:16 2003
+++ fc/common/player.h Wed Jul 23 16:17:17 2003
@@ -221,9 +221,6 @@
bool player_has_embassy(struct player *pplayer, struct player *pplayer2);
bool player_can_see_unit(struct player *pplayer, struct unit *punit);
-bool player_can_see_unit_at_location(struct player *pplayer,
- struct unit *punit,
- int x, int y);
bool player_owns_city(struct player *pplayer, struct city *pcity);
diff -u -r freeciv/common/unit.c fc/common/unit.c
--- freeciv/common/unit.c Mon Jul 21 17:05:11 2003
+++ fc/common/unit.c Wed Jul 23 14:25:32 2003
@@ -400,10 +400,13 @@
**************************************************************************/
bool is_hiding_unit(struct unit *punit)
{
- struct unit *transporter = find_unit_by_id(punit->transported_by);
+ struct unit *transporter;
return (unit_flag(punit, F_PARTIAL_INVIS)
- || (transporter && unit_flag(transporter, F_PARTIAL_INVIS)));
+ || unit_flag(punit, F_SILENT_HUNTER)
+ || ((transporter = find_unit_by_id(punit->transported_by))
+ && (unit_flag(transporter, F_PARTIAL_INVIS)
+ || unit_flag(transporter, F_SILENT_HUNTER))));
}
/**************************************************************************
@@ -1477,7 +1479,7 @@
punit->ord_map = 0;
punit->ord_city = 0;
set_unit_activity(punit, ACTIVITY_IDLE);
-
+ punit->seen = (1u << (pplayer->player_no));
return punit;
}
@@ -1494,3 +1496,26 @@
}
free(punit);
}
+
+/**************************************************************************
+ Get real unit vision range.
+**************************************************************************/
+int get_unit_vision_range(struct unit *punit)
+{
+ int base_vision = unit_type(punit)->vision_range;
+
+ assert(base_vision > 0);
+
+ if (map_has_special(punit->x, punit->y, S_FORTRESS)
+ && is_ground_unit(punit)
+ && player_knows_techs_with_flag(unit_owner(punit), TF_WATCHTOWER))
+ {
+ assert(game.watchtower_vision > 0);
+ assert(game.watchtower_extra_vision >= 0);
+ return MAX(base_vision,
+ MAX(game.watchtower_vision,
+ base_vision + game.watchtower_extra_vision));
+ }
+
+ return base_vision;
+}
diff -u -r freeciv/common/unit.h fc/common/unit.h
--- freeciv/common/unit.h Thu Jul 17 20:27:19 2003
+++ fc/common/unit.h Wed Jul 23 12:09:24 2003
@@ -118,9 +118,12 @@
int upkeep;
int upkeep_food;
int upkeep_gold;
- bool foul;
int fuel;
int bribe_cost;
+ bool foul;
+ bool moved;
+ bool paradropped;
+ bool connecting;
struct unit_ai ai;
enum unit_activity activity;
struct {
@@ -133,10 +136,8 @@
int ord_map, ord_city;
/* ord_map and ord_city are the order index of this unit in tile.units
and city.units_supported; they are only used for save/reload */
- bool moved;
- bool paradropped;
- bool connecting;
int transported_by;
+ unsigned int seen; /* A bitvector on the server side, Player_no is index */
struct goto_route *pgr;
};
@@ -284,4 +285,5 @@
Unit_Type_id type, bool make_veteran);
void destroy_unit_virtual(struct unit *punit);
+int get_unit_vision_range(struct unit *punit);
#endif /* FC__UNIT_H */
diff -u -r freeciv/common/unittype.c fc/common/unittype.c
--- freeciv/common/unittype.c Fri Apr 11 13:17:16 2003
+++ fc/common/unittype.c Wed Jul 23 17:27:58 2003
@@ -45,7 +45,7 @@
"AEGIS", "Fighter", "Marines", "Partial_Invis", "Settlers", "Diplomat",
"Trireme", "Nuclear", "Spy", "Transform", "Paratroopers",
"Airbase", "Cities", "IgTired", "Missile_Carrier", "No_Land_Attack",
- "AddToCity", "Fanatic"
+ "AddToCity", "Fanatic", "Silent_Hunter", "Sonar"
};
static const char *role_names[] = {
"FirstBuild", "Explorer", "Hut", "HutTech", "Partisan",
diff -u -r freeciv/common/unittype.h fc/common/unittype.h
--- freeciv/common/unittype.h Thu Jul 3 10:58:11 2003
+++ fc/common/unittype.h Mon Jul 21 18:33:47 2003
@@ -93,7 +93,7 @@
F_AEGIS,
F_FIGHTER,
F_MARINES,
- F_PARTIAL_INVIS, /* Invisibile except when adjacent (Submarine) */
+ F_PARTIAL_INVIS, /* Invisibile except when adjacent (Stealth) */
F_SETTLERS, /* Does not include ability to found cities */
F_DIPLOMAT,
F_TRIREME, /* Trireme sinking effect */
@@ -109,8 +109,13 @@
F_ADD_TO_CITY, /* unit can add to city population */
F_FANATIC, /* Only Fundamentalist government can build
these units */
+ F_SILENT_HUNTER, /* like F_PARTIAL_INVIS but Invisibile untill enemy
+ enter on unit( start combat (attack) this unit)
+ or find by sonnar (Submarine) */
+ F_SONAR, /* Can detect F_SILENT_HUNTERs (Destroyer/Heli) */
F_LAST
};
+
#define F_MAX 64
/* Unit "roles": these are similar to unit flags but differ in that
diff -u -r freeciv/data/default/units.ruleset fc/data/default/units.ruleset
--- freeciv/data/default/units.ruleset Tue Jun 17 02:11:32 2003
+++ fc/data/default/units.ruleset Tue Jul 22 11:04:22 2003
@@ -1026,7 +1026,7 @@
uk_shield = 1
uk_food = 0
uk_gold = 0
-flags = "FieldUnit", "OneAttack"
+flags = "FieldUnit", "OneAttack", "Sonar"
roles = ""
helptext = _("\
The Helicopter is a very powerful unit, as it can both fly and\
@@ -1264,7 +1264,7 @@
uk_shield = 1
uk_food = 0
uk_gold = 0
-flags = ""
+flags = "Sonar"
roles = ""
helptext = _("\
TIP: A very fast unit, which is very useful for hunting down enemy\
@@ -1380,7 +1380,7 @@
uk_shield = 1
uk_food = 0
uk_gold = 0
-flags = "Partial_Invis",
+flags = "Silent_Hunter",
"Missile_Carrier", "No_Land_Attack"
roles = ""
helptext = _("\
diff -u -r freeciv/server/maphand.c fc/server/maphand.c
--- freeciv/server/maphand.c Thu Jul 24 12:24:19 2003
+++ fc/server/maphand.c Wed Jul 23 12:21:22 2003
@@ -686,17 +675,9 @@
**************************************************************************/
void remove_unit_sight_points(struct unit *punit)
{
- int x = punit->x, y = punit->y;
- struct player *pplayer = unit_owner(punit);
-
freelog(LOG_DEBUG, "Removing unit sight points at %i,%i", punit->x,
punit->y);
-
- if (map_has_special(punit->x, punit->y, S_FORTRESS)
- && unit_profits_of_watchtower(punit))
- fog_area(pplayer, x, y, get_watchtower_vision(punit));
- else
- fog_area(pplayer, x, y, unit_type(punit)->vision_range);
+ fog_area(unit_owner(punit), punit->x, punit->y,
get_unit_vision_range(punit));
}
/**************************************************************************
diff -u -r freeciv/server/unithand.c fc/server/unithand.c
--- freeciv/server/unithand.c Sun Jul 20 23:16:01 2003
+++ fc/server/unithand.c Wed Jul 23 17:13:05 2003
@@ -927,7 +927,7 @@
{
struct player *pplayer = unit_owner(punit);
struct tile *pdesttile = map_get_tile(dest_x, dest_y);
- struct unit *pdefender = get_defender(punit, dest_x, dest_y);
+ struct unit *pdefender = NULL;
struct city *pcity = pdesttile->city;
if (!is_normal_map_pos(dest_x, dest_y)) {
@@ -996,7 +996,32 @@
return FALSE;
}
}
-
+
+ /* are there any units that player have no idea about it *
+ if(unit_list_size(&pdesttile->units)
+ && !unit_list_size(&map_get_player_tile(dest_x, dest_y, pplayer)->units)
+ && (pdefender = get_attacker(punit, dest_x, dest_y))
+ && unit_flag(pdefender, F_SILENT_HUNTER)) {
+
+ send_unit_info(pplayer, pdefender);
+ if (pplayers_at_war(unit_owner(punit), unit_owner(pdefender))
+ && can_unit_attack_unit_at_tile(pdefender, punit, punit->x, punit->y)) {
+ notify_player_ex(pplayer, pdefender->x, pdefender->y, E_NOEVENT,
+ _("Game: %s's %s attack our %s"),
+ unit_owner(pdefender)->name,
+ get_unit_type(pdefender->type)->name,
+ get_unit_type(punit->type)->name);
+ handle_unit_attack_request(pdefender, punit);
+ } else {
+ notify_player_ex(pplayer, pdefender->x, pdefender->y, E_NOEVENT,
+ _("Game: Our %s found %s's %s"),
+ get_unit_type(punit->type)->name,
unit_owner(pdefender)->name,
+ get_unit_type(pdefender->type)->name);
+ }
+ return FALSE;
+ }
+ */
+ pdefender = get_defender(punit, dest_x, dest_y);
/*** Try to attack if there is an enemy unit on the target tile ***/
if (pdefender
&& pplayers_at_war(unit_owner(punit), unit_owner(pdefender))) {
diff -u -r freeciv/server/unittools.c fc/server/unittools.c
--- freeciv/server/unittools.c Mon Jul 21 17:05:11 2003
+++ fc/server/unittools.c Wed Jul 23 18:30:08 2003
@@ -71,7 +71,9 @@
struct unit *punit2);
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
static int hp_gain_coord(struct unit *punit);
-
+static void update_unit_seen_status(struct unit *punit);
+static void unit_search_hidden_units(struct unit *punit);
+
/**************************************************************************
returns a unit type with a given role, use -1 if you don't want a tech
role. Always try tech role and only if not available, return role unit.
@@ -1419,15 +1421,10 @@
void upgrade_unit(struct unit *punit, Unit_Type_id to_unit)
{
struct player *pplayer = unit_owner(punit);
- int range;
-
+
/* save old vision range */
- if (map_has_special(punit->x, punit->y, S_FORTRESS)
- && unit_profits_of_watchtower(punit))
- range = get_watchtower_vision(punit);
- else
- range = unit_type(punit)->vision_range;
-
+ int range = get_unit_vision_range(punit);
+
/* Scale HP and MP, rounding down. Be careful with integer arithmetic,
* and don't kill the unit. */
punit->hp = MAX(punit->hp * get_unit_type(to_unit)->hp
@@ -1439,13 +1436,7 @@
punit->type = to_unit;
/* apply new vision range */
- if (map_has_special(punit->x, punit->y, S_FORTRESS)
- && unit_profits_of_watchtower(punit))
- unfog_area(pplayer, punit->x, punit->y, get_watchtower_vision(punit));
- else
- unfog_area(pplayer, punit->x, punit->y,
- get_unit_type(to_unit)->vision_range);
-
+ unfog_area(pplayer, punit->x, punit->y, get_unit_vision_range(punit));
fog_area(pplayer,punit->x,punit->y,range);
send_unit_info(NULL, punit);
@@ -1516,13 +1507,17 @@
send_city_info(pplayer, pcity);
}
- if (map_has_special(x, y, S_FORTRESS)
- && unit_profits_of_watchtower(punit)) {
- unfog_area(pplayer, punit->x, punit->y, get_watchtower_vision(punit));
- } else {
- unfog_area(pplayer, x, y, unit_type(punit)->vision_range);
- }
-
+ players_iterate(pplayer) {
+ if(pplayer == unit_owner(punit)) {
+ continue;
+ }
+ punit->seen |=
+ COND_SET_BIT(pplayers_allied(unit_owner(punit), pplayer),
+ pplayer->player_no);
+ } players_iterate_end
+
+ unfog_area(pplayer, punit->x, punit->y, get_unit_vision_range(punit));
+
send_unit_info(NULL, punit);
maybe_make_contact(x, y, unit_owner(punit));
wakeup_neighbor_sentries(punit);
@@ -1766,7 +1761,7 @@
/* a 16-bit unsigned number, never zero */
if (new_serial_num) {
- serial_num = (serial_num + 1) & 0xFFFF;
+ serial_num = (serial_num + 1) & MAX_UINT16;
if (serial_num == 0)
serial_num++;
}
@@ -1803,34 +1798,73 @@
packet->packet_use = packet_use;
packet->info_city_id = info_city_id;
packet->serial_num = serial_num;
+ packet->seen = punit->seen;
}
-/**************************************************************************
- A helper function for send_info_to_onlookers below.
+/***************************************************************
Checks if a unit can be seen by pplayer at (x,y).
A player can see a unit if he:
- (a) can see the tile AND
- (b) can see the unit at the tile (i.e. unit not invisible at this tile) AND
- (c) the unit is not in an unallied city
-
- TODO: the name is confusingly similar to player_can_see_unit_at_location
- But we need to rename p_c_s_u_a_t because it is really
- is_unit_visible_to_player_at.
-**************************************************************************/
-static bool can_player_see_unit_at(struct player *pplayer, struct unit *punit,
- int x, int y)
+ (a) unit isn't transported (cargo) AND
+ (b) can see the tile AND
+ (c) can see the unit at the tile (i.e. unit not invisible at this tile) AND
+ (d) the unit is not in an unallied city
+
+ The unit does not have to be at (x,y) !
+ Allied units and cities can be used for sub hunting.
+***************************************************************/
+static bool can_player_see_unit_at_location(struct player *pplayer,
+ struct unit *punit,
+ int x, int y)
{
+ bool silent;
+ struct tile *ptile;
+
if (!pplayer) {
- freelog(LOG_ERROR, "NULL pointer in can_player_see_unit_at");
+ freelog(LOG_ERROR, "NULL pointer in can_player_see_unit_at_location");
return FALSE;
- } else {
- bool see_tile = map_get_known_and_seen(x, y, pplayer);
- bool see_unit = player_can_see_unit_at_location(pplayer, punit, x, y);
- bool not_in_city = (pplayers_allied(unit_owner(punit), pplayer)
- || !map_get_city(x, y));
-
- return (see_tile && see_unit && not_in_city);
}
+
+ silent = pplayers_allied(unit_owner(punit), pplayer);
+ if((!silent && punit->transported_by != -1)
+ || !map_get_known_and_seen(x, y, pplayer)) {
+ return FALSE;
+ }
+ if (silent || !is_hiding_unit(punit) || !map_get_city(x, y)) {
+ return TRUE;
+ }
+
+ /*
+ * Search for units/cities that might be able to see the sub/missile
+ * I hardcoded 2 here as max unit vision range becouse :
+ * - I can make 2 checks in one loop (cities and units)
+ * - It is impossible to determine max vision range of units that
+ * might be able to see the sub/missile.
+ */
+ silent = unit_flag(punit, F_SILENT_HUNTER);
+ square_iterate(x, y, 2, x1, y1) {
+ if ((x == x1 && y == y1) || !map_get_known_and_seen(x1, y1, pplayer)) {
+ continue;
+ }
+
+ ptile = map_get_tile(x1, y1);
+
+ /* Note: This will check tiles not belong to city map too ! */
+ if (ptile->city && pplayers_allied(city_owner(ptile->city), pplayer)) {
+ return TRUE;
+ }
+
+ unit_list_iterate(ptile->units, punit2) {
+ if (pplayers_allied(unit_owner(punit2), pplayer)
+ && (!silent || (silent && unit_flag(punit2, F_SONAR)))
+ && (map_distance(x, y, punit2->x, punit2->y) <=
+ get_unit_vision_range(punit2))) {
+ return TRUE;
+ }
+ } unit_list_iterate_end;
+
+ } square_iterate_end;
+
+ return FALSE;
}
/**************************************************************************
@@ -1852,12 +1886,11 @@
conn_list_iterate(*dest, pconn) {
struct player *pplayer = pconn->player;
- bool see_pos =
- can_player_see_unit_at(pplayer, punit, punit->x, punit->y);
+ bool see_pos = player_can_see_unit(pplayer, punit);
bool see_xy = see_pos;
if (!same_pos(x, y, punit->x, punit->y)) {
- see_xy = can_player_see_unit_at(pplayer, punit, x, y);
+ see_xy = can_player_see_unit_at_location(pplayer, punit, x, y);
}
if ((!pplayer && pconn->observer) || see_pos || see_xy) {
send_packet_unit_info(pconn, &info);
@@ -1884,6 +1917,30 @@
void send_all_known_units(struct conn_list *dest)
{
int p;
+
+ for(p=0; p<game.nplayers; p++) { /* rebuild players units visions */
+ struct player *pplayer = &game.players[p];
+
+ unit_list_iterate(pplayer->units, punit) {
+ int vision_range = get_unit_vision_range(punit);
+ bool sonar = unit_flag(punit, F_SONAR);
+ square_iterate(punit->x, punit->y, vision_range, x, y) {
+ if ((x == punit->x && y == punit->y)
+ || !map_get_known_and_seen(x, y, pplayer)) {
+ continue;
+ }
+ unit_list_iterate(map_get_tile(x, y)->units, punit2) {
+ if (!pplayers_allied(unit_owner(punit2), pplayer)
+ && (punit2->transported_by != -1
+ || unit_flag(punit2, F_PARTIAL_INVIS)
+ || (sonar && unit_flag(punit2, F_SILENT_HUNTER)))) {
+ continue;
+ }
+ punit2->seen |= (1u << pplayer->player_no);
+ } unit_list_iterate_end;
+ } square_iterate_end;
+ } unit_list_iterate_end;
+ }
conn_list_do_buffer(dest);
conn_list_iterate(*dest, pconn) {
@@ -1908,11 +1965,6 @@
flush_packets();
}
-
-
-
-
-
/**************************************************************************
For all units which are transported by the given unit and that are
currently idle, sentry them.
@@ -2610,15 +2662,9 @@
wake them up if the punit is farther away than 3. */
square_iterate(punit->x, punit->y, 3, x, y) {
unit_list_iterate(map_get_tile(x, y)->units, penemy) {
- int range;
+ int range = get_unit_vision_range(penemy);
enum unit_move_type move_type = unit_type(penemy)->move_type;
enum tile_terrain_type terrain = map_get_terrain(x, y);
-
- if (map_has_special(x, y, S_FORTRESS)
- && unit_profits_of_watchtower(penemy))
- range = get_watchtower_vision(penemy);
- else
- range = unit_type(penemy)->vision_range;
if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
&& penemy->activity == ACTIVITY_SENTRY
@@ -2762,6 +2808,56 @@
}
/**************************************************************************
+ ...
+**************************************************************************/
+static void update_unit_seen_status(struct unit *punit)
+{
+ punit->seen = (1u << (unit_owner(punit)->player_no));
+ players_iterate(pplayer) {
+ if(pplayer == unit_owner(punit)) {
+ continue;
+ }
+ punit->seen |=
+ COND_SET_BIT(can_player_see_unit_at_location(pplayer, punit,
+ punit->x, punit->y), pplayer->player_no);
+ } players_iterate_end
+}
+
+/**************************************************************************
+ Search hidden unit in unit vision range.
+**************************************************************************/
+static void unit_search_hidden_units(struct unit *punit)
+{
+ int range = get_unit_vision_range(punit);
+ bool sonar = unit_flag(punit, F_SONAR);
+
+ /* searach in unit vision range */
+ square_iterate(punit->x, punit->y, range, x, y) {
+ struct tile *ptile = map_get_tile(x, y);
+
+ if (ptile->city || (x == punit->x && y == punit->y)) {
+ continue;
+ }
+ unit_list_iterate(ptile->units, punit2) {
+ if (unit_flag(punit2, F_PARTIAL_INVIS)
+ || (sonar && unit_flag(punit2, F_SILENT_HUNTER))) {
+ /* punit2 seen by punit owner and all his ally */
+ punit2->seen |= (1u << (unit_owner(punit)->player_no));
+ players_iterate(pplayer) {
+ if(pplayer == unit_owner(punit)) {
+ continue;
+ }
+ punit2->seen |=
+ COND_SET_BIT(pplayers_allied(unit_owner(punit), pplayer),
+ pplayer->player_no);
+ } players_iterate_end
+ }
+ } unit_list_iterate_end;
+ } square_iterate_end;
+
+}
+
+/**************************************************************************
Moves a unit. No checks whatsoever! This is meant as a practical function
for other functions, like do_airline, which do the checking themselves.
If you move a unit you should always use this function, as it also sets the
@@ -2844,6 +2940,7 @@
unit_list_insert(&pdesttile->units, pcargo);
check_unit_activity(pcargo);
+ update_unit_seen_status(pcargo);
send_unit_info_to_onlookers(NULL, pcargo, src_x, src_y, TRUE);
fog_area(unit_owner(pcargo), src_x, src_y,
unit_type(pcargo)->vision_range);
handle_unit_move_consequences(pcargo, src_x, src_y, dest_x, dest_y);
@@ -2873,7 +2970,9 @@
punit->moves_left = MAX(0, punit->moves_left - move_cost);
unit_list_insert(&pdesttile->units, punit);
check_unit_activity(punit);
-
+ update_unit_seen_status(punit);
+ unit_search_hidden_units(punit);
+
/* set activity to sentry if boarding a ship unless the unit is just
* passing through the ship on its way somewhere else. If the unit is
* GOTOing and the ship isn't the final destination, then don't go
@@ -2931,13 +3030,7 @@
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
{
bool cancel = FALSE;
- int range;
-
- if (map_has_special(punit->x, punit->y, S_FORTRESS)
- && unit_profits_of_watchtower(punit))
- range = get_watchtower_vision(punit);
- else
- range = unit_type(punit)->vision_range;
+ int range = get_unit_vision_range(punit);
square_iterate(punit->x, punit->y, range, x, y) {
struct unit *penemy =
|
|