stratagus-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Stratagus-CVS] stratagus/src action/action_attack.c action/act...


From: address@hidden
Subject: [Stratagus-CVS] stratagus/src action/action_attack.c action/act...
Date: 15 Jan 2004 09:31:16 +1100

CVSROOT:        /home/strat
Module name:    stratagus
Changes by:      <address@hidden>       04/01/15 09:31:12

Modified files:
        src/action     : action_attack.c action_board.c action_build.c 
                         action_die.c action_follow.c action_move.c 
                         action_repair.c action_resource.c 
                         action_spellcast.c action_still.c 
                         action_upgradeto.c actions.c command.c 
        src/ai         : ai.c ai_plan.c ai_resource.c 
        src/editor     : editloop.c 
        src/include    : actions.h map.h player.h ui.h unit.h 
        src/map        : map.c map_fog.c minimap.c 
        src/network    : network.c 
        src/stratagus  : mainloop.c selection.c spells.c 
        src/ui         : mainscr.c mouse.c 
        src/unit       : ccl_unit.c unit.c unit_draw.c unit_find.c 
                         unitcache.c 

Log message:
        New Visibility tracking.

Patches:
Index: stratagus/src/action/action_attack.c
diff -u stratagus/src/action/action_attack.c:1.92 
stratagus/src/action/action_attack.c:1.93
--- stratagus/src/action/action_attack.c:1.92   Sun Dec 14 19:10:36 2003
+++ stratagus/src/action/action_attack.c        Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_attack.c,v 1.92 2003/12/14 08:10:36 wizzard Exp $
+//      $Id: action_attack.c,v 1.93 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -77,7 +77,7 @@
 
        flags = UnitShowAnimation(unit, attack);
 
-       if ((flags & AnimationSound) && (UnitVisibleOnMap(unit) || 
ReplayRevealMap)) {
+       if ((flags & AnimationSound) && (UnitVisible(unit, ThisPlayer) || 
ReplayRevealMap)) {
                PlayUnitSound(unit, VoiceAttacking);
        }
 
@@ -120,7 +120,7 @@
        // Do we have a goal?
        //
        if ((goal = unit->Orders[0].Goal)) {
-               if (GoalGone(unit, goal)) {
+               if (!UnitVisibleAsGoal(goal, unit->Player)) {
                        //
                        // Goal is destroyed
                        //
@@ -129,7 +129,7 @@
                        unit->Orders[0].MinRange = 0;
                        unit->Orders[0].Range = 0;
 
-                       DebugLevel0Fn("attack target %d(%s) gone for %d(%s)\n" 
_C_
+                       DebugLevel3Fn("attack target %d(%s) gone for %d(%s)\n" 
_C_
                                UnitNumber(goal) _C_ goal->Type->Name _C_
                                UnitNumber(unit) _C_ unit->Type->Name);
                        RefsDecrease(goal);
Index: stratagus/src/action/action_board.c
diff -u stratagus/src/action/action_board.c:1.47 
stratagus/src/action/action_board.c:1.48
--- stratagus/src/action/action_board.c:1.47    Sun Dec 14 19:10:36 2003
+++ stratagus/src/action/action_board.c Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_board.c,v 1.47 2003/12/14 08:10:36 wizzard Exp $
+//      $Id: action_board.c,v 1.48 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -98,7 +98,7 @@
                return 0;
        }
 
-       if (GoalGone(unit, trans)) {
+       if (!UnitVisibleAsGoal(trans, unit->Player)) {
                DebugLevel0Fn("Transporter Gone\n");
                RefsDecrease(trans);
                unit->Orders[0].Goal = NoUnitP;
@@ -142,7 +142,7 @@
        unit->SubAction = 0;
 
        transporter = unit->Orders[0].Goal;
-       if (GoalGone(unit,transporter)) {
+       if (!UnitVisibleAsGoal(transporter, unit->Player)) {
                DebugLevel0Fn("Transporter gone\n");
                RefsDecrease(transporter);
                unit->Orders[0].Goal = NoUnitP;
Index: stratagus/src/action/action_build.c
diff -u stratagus/src/action/action_build.c:1.106 
stratagus/src/action/action_build.c:1.107
--- stratagus/src/action/action_build.c:1.106   Sat Dec 13 18:09:39 2003
+++ stratagus/src/action/action_build.c Thu Jan 15 09:31:01 2004
@@ -27,7 +27,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_build.c,v 1.106 2003/12/13 07:09:39 wizzard Exp $
+//      $Id: action_build.c,v 1.107 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -80,7 +80,6 @@
                unit->Data.Builded.Frame = cframe;
                unit->Frame = cframe->Frame;
                CheckUnitToBeDrawn(unit);
-               UnitMarkSeen(unit);
        }
 }
 
@@ -279,12 +278,10 @@
                unit->SubAction = 0;
                unit->Wait = 1;
                RefsIncrease(build);
-               UnitMarkSeen(unit);
                // Mark the new building seen.
                MapMarkUnitSight(build);
        }
        UpdateConstructionFrame(build);
-       UnitMarkSeen(build);
 }
 
 /**
Index: stratagus/src/action/action_die.c
diff -u stratagus/src/action/action_die.c:1.55 
stratagus/src/action/action_die.c:1.56
--- stratagus/src/action/action_die.c:1.55      Sat Dec 13 19:27:02 2003
+++ stratagus/src/action/action_die.c   Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_die.c,v 1.55 2003/12/13 08:27:02 wizzard Exp $
+//      $Id: action_die.c,v 1.56 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -72,16 +72,12 @@
                DebugLevel3("Die complete %d\n" _C_ UnitNumber(unit));
 
                if (!unit->Type->CorpseType) {
-                       UnitMarkSeen(unit);
                        ReleaseUnit(unit);
                        return;
                }
 
                // Fixes sight from death
                MapUnmarkUnitSight(unit);
-#if 0
-               unit->CurrentSightRange = unit->Type->Stats->SightRange;
-#endif
 
                unit->State = unit->Type->CorpseScript;
                unit->Type = unit->Type->CorpseType;
@@ -104,7 +100,6 @@
                ChangeUnitOwner(unit, &Players[PlayerNumNeutral]);
 #endif
        }
-       UnitMarkSeen(unit);
 }
 
 //@}
Index: stratagus/src/action/action_follow.c
diff -u stratagus/src/action/action_follow.c:1.35 
stratagus/src/action/action_follow.c:1.36
--- stratagus/src/action/action_follow.c:1.35   Sun Dec 14 19:10:36 2003
+++ stratagus/src/action/action_follow.c        Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_follow.c,v 1.35 2003/12/14 08:10:36 wizzard Exp $
+//      $Id: action_follow.c,v 1.36 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -66,7 +66,7 @@
        //
        if (unit->SubAction == 128) {
                goal = unit->Orders[0].Goal;
-               if (!goal || GoalGone(unit,goal)) {
+               if (!goal || !UnitVisibleAsGoal(goal, unit->Player)) {
                        DebugLevel0Fn("Goal gone\n");
                        if (goal) {
                                RefsDecrease(goal);
@@ -219,7 +219,7 @@
        //
        // Target destroyed?
        //
-       if ((goal = unit->Orders[0].Goal) && GoalGone(unit, goal)) {
+       if ((goal = unit->Orders[0].Goal) && !UnitVisibleAsGoal(goal, 
unit->Player)) {
                DebugLevel0Fn("Goal gone\n");
                unit->Orders[0].X = goal->X + goal->Type->TileWidth / 2;
                unit->Orders[0].Y = goal->Y + goal->Type->TileHeight / 2;
Index: stratagus/src/action/action_move.c
diff -u stratagus/src/action/action_move.c:1.78 
stratagus/src/action/action_move.c:1.79
--- stratagus/src/action/action_move.c:1.78     Sun Dec 14 19:10:36 2003
+++ stratagus/src/action/action_move.c  Thu Jan 15 09:31:01 2004
@@ -21,7 +21,7 @@
 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 //      GNU General Public License for more details.
 //
-//      $Id: action_move.c,v 1.78 2003/12/14 08:10:36 wizzard Exp $
+//      $Id: action_move.c,v 1.79 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -143,12 +143,28 @@
 
                UnitCacheRemove(unit);
 
-               MapUnmarkUnitSight(unit);
-               // ummark sight for units inside too.
-               uninside = unit->UnitInside;
-               for (i = unit->InsideCount; i; uninside = 
uninside->NextContained, --i) {
-                       MapUnmarkUnitOnBoardSight(uninside, unit);
-               }
+               //
+               //      Trick for fog of war speed. first mark the new location 
then unmark the first.
+               //
+                       x = unit->X += xd;
+                       y = unit->Y += yd;
+                       // Mark sight.
+                       MapMarkUnitSight(unit);
+                       uninside = unit->UnitInside;
+                       for (i = unit->InsideCount; i; uninside = 
uninside->NextContained, --i) {
+                               MapMarkUnitOnBoardSight(uninside, unit);
+                       }
+                       x = unit->X -= xd;
+                       y = unit->Y -= yd;
+                       // Unmark sight.
+                       MapUnmarkUnitSight(unit);
+                       uninside = unit->UnitInside;
+                       for (i = unit->InsideCount; i; uninside = 
uninside->NextContained, --i) {
+                               MapUnmarkUnitOnBoardSight(uninside, unit);
+                       }
+               //
+               //      End fog of war trick
+               //
 
                x = unit->X += xd;
                y = unit->Y += yd;
@@ -158,7 +174,6 @@
 
                MustRedraw |= RedrawMinimap;
 
-               MapMarkUnitSight(unit);
                // Remove unit from the current selection
                if (unit->Selected && !IsMapFieldVisible(ThisPlayer, unit->X, 
unit->Y)) {
                        if (NumSelected == 1) { //  Remove building cursor
@@ -168,21 +183,12 @@
                        SelectionChanged();
                }
 
-               // Remark sight for units inside too.
-               uninside = unit->UnitInside;
-               for (i = unit->InsideCount; i; uninside = 
uninside->NextContained, --i) {
-                       MapMarkUnitOnBoardSight(uninside, unit);
-               }
-
-               // Reveal cloaked units.
-               if (unit->Type->DetectCloak) {
-                       MapDetectCloakedUnits(unit);
-               }
-
                unit->IX = -xd * TileSizeX;
                unit->IY = -yd * TileSizeY;
                unit->Frame = 0;
                UnitHeadingFromDeltaXY(unit, xd, yd);
+               //  Recalculate the seen count.
+               UnitCountSeen(unit);
        } else {
                xd = Heading2X[unit->Direction / NextDirection];
                yd = Heading2Y[unit->Direction / NextDirection];
Index: stratagus/src/action/action_repair.c
diff -u stratagus/src/action/action_repair.c:1.63 
stratagus/src/action/action_repair.c:1.64
--- stratagus/src/action/action_repair.c:1.63   Wed Dec 17 16:40:37 2003
+++ stratagus/src/action/action_repair.c        Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_repair.c,v 1.63 2003/12/17 05:40:37 jsalmon3 Exp $
+//      $Id: action_repair.c,v 1.64 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -207,7 +207,7 @@
                                //
                                // Check if goal is correct unit.
                                if (goal) {
-                                       if (GoalGone(unit, goal)) {
+                                       if (!UnitVisibleAsGoal(goal, 
unit->Player)) {
                                                DebugLevel0Fn("repair target 
gone. Booohooo\n");
                                                unit->Orders[0].X = goal->X;
                                                unit->Orders[0].Y = goal->Y;
@@ -266,7 +266,7 @@
                                // Check if goal is correct unit.
                                // FIXME: should I do a function for this?
                                if (goal) {
-                                       if (GoalGone(unit, goal)) {
+                                       if (!UnitVisibleAsGoal(goal, 
unit->Player)) {
                                                DebugLevel0Fn("repair goal is 
gone\n");
                                                unit->Orders[0].X = goal->X;
                                                unit->Orders[0].Y = goal->Y;
Index: stratagus/src/action/action_resource.c
diff -u stratagus/src/action/action_resource.c:1.73 
stratagus/src/action/action_resource.c:1.74
--- stratagus/src/action/action_resource.c:1.73 Sun Dec 14 19:10:36 2003
+++ stratagus/src/action/action_resource.c      Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_resource.c,v 1.73 2003/12/14 08:10:36 wizzard Exp $
+//      $Id: action_resource.c,v 1.74 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -128,7 +128,7 @@
                                break;
                        default:
                                // Goal gone or something.
-                               if (!unit->Reset || !GoalGone(unit, goal)) {
+                               if (!unit->Reset || UnitVisibleAsGoal(goal, 
unit->Player)) {
                                        return 0;
                                }
                                break;
@@ -176,7 +176,7 @@
        //
        // Target is dead, stop getting resources.
        //
-       if (GoalGone(unit, goal)) {
+       if (!UnitVisibleAsGoal(goal, unit->Player)) {
                DebugLevel3Fn("Destroyed resource goal, stop gathering.\n");
                RefsDecrease(goal);
                // Find an alternative, but don't look too far.
@@ -226,7 +226,6 @@
        // Activate the resource
        goal->Data.Resource.Active++;
 
-       UnitMarkSeen(goal);
        //
        // Place unit inside the resource
        //
@@ -260,7 +259,7 @@
                
DebugCheck(!unit->Type->Animations->Harvest[unit->CurrentResource]);
                flags = UnitShowAnimation(unit,
                        unit->Type->Animations->Harvest[unit->CurrentResource]);
-               if ((flags & AnimationSound) && (UnitVisibleOnMap(unit) || 
ReplayRevealMap)) {
+               if ((flags & AnimationSound) && (UnitVisible(unit, ThisPlayer) 
|| ReplayRevealMap)) {
                        PlayUnitSound(unit, VoiceHarvesting);
                }
        }
@@ -415,7 +414,7 @@
                        //
                        // Target is not dead, getting resources.
                        //
-                       if (!GoalGone(unit, source)) {
+                       if (UnitVisibleAsGoal(source, unit->Player)) {
                                // Don't load more that there is.
                                if (addload > source->Value) {
                                        addload = source->Value;
@@ -425,7 +424,6 @@
                                unit->Value += addload;
                                source->Value -= addload;
 
-                               UnitMarkSeen(source);
                                if (IsOnlySelected(source)) {
                                        MustRedraw |= RedrawInfoPanel;
                                }
@@ -435,7 +433,7 @@
                        // End of resource: destroy the resource.
                        // FIXME: implement depleted resources.
                        //
-                       if (GoalGone(unit, source) || (source->Value == 0)) {
+                       if ((!UnitVisibleAsGoal(source, unit->Player)) || 
(source->Value == 0)) {
                                DebugLevel0Fn("Resource is destroyed for unit 
%d\n" _C_ unit->Slot);
                                uins = source->UnitInside;
                                //
@@ -448,7 +446,7 @@
 
                                // Don't destroy the resource twice.
                                // This only happens when it's empty.
-                               if (!GoalGone(unit, source)){
+                               if (UnitVisibleAsGoal(source, unit->Player)){
                                        LetUnitDie(source);
                                        // FIXME: make the workers inside look 
for a new resource.
                                }
@@ -580,7 +578,7 @@
                case PF_REACHED:
                        break;
                default:
-                       if (!unit->Reset || !GoalGone(unit, goal)) {
+                       if (!unit->Reset || UnitVisibleAsGoal(goal, 
unit->Player)) {
                                return 0;
                        }
                        break;
@@ -589,7 +587,7 @@
        //
        // Target is dead, stop getting resources.
        //
-       if (GoalGone(unit, goal)) {
+       if (!UnitVisibleAsGoal(goal, unit->Player)) {
                DebugLevel0Fn("Destroyed depot\n");
                RefsDecrease(goal);
                unit->Orders[0].Goal = NoUnitP;
@@ -689,6 +687,7 @@
                        unit->Orders[0].Range = 1;
                        unit->Orders[0].X = unit->Orders[0].Y = -1;
                } else {
+                       DebugLevel0Fn("Unit %d Resource gone. Sit and play 
dumb.\n" _C_ unit->Slot);
                        DropOutOnSide(unit, LookingW, depot->Type->TileWidth, 
depot->Type->TileHeight);
                        unit->Orders[0].Action = UnitActionStill;
                        unit->SubAction = 0;
Index: stratagus/src/action/action_spellcast.c
diff -u stratagus/src/action/action_spellcast.c:1.40 
stratagus/src/action/action_spellcast.c:1.41
--- stratagus/src/action/action_spellcast.c:1.40        Sun Dec 14 20:44:12 2003
+++ stratagus/src/action/action_spellcast.c     Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_spellcast.c,v 1.40 2003/12/14 09:44:12 wizzard Exp $
+//      $Id: action_spellcast.c,v 1.41 2004/01/14 22:31:01 nobody_ Exp $
 
 /*
 ** This is inherited from action_attack.c, actually spell casting will
@@ -231,7 +231,7 @@
                                flags = UnitShowAnimation(unit, 
unit->Type->Animations->Attack);
                                if (flags & AnimationMissile) {
                                        // FIXME: what todo, if unit/goal is 
removed?
-                                       if (unit->Orders[0].Goal && 
GoalGone(unit,unit->Orders->Goal)) {
+                                       if (unit->Orders[0].Goal && 
!UnitVisibleAsGoal(unit->Orders->Goal, unit->Player)) {
                                                unit->Value = 0;
                                        } else {
                                                spell = unit->Orders[0].Arg1;
@@ -244,7 +244,7 @@
                                }
                        } else {
                                // FIXME: what todo, if unit/goal is removed?
-                               if (unit->Orders[0].Goal && GoalGone(unit, 
unit->Orders->Goal)) {
+                               if (unit->Orders[0].Goal && 
!UnitVisibleAsGoal(unit->Orders->Goal, unit->Player)) {
                                        unit->Value = 0;
                                } else {
                                        spell = unit->Orders[0].Arg1;
Index: stratagus/src/action/action_still.c
diff -u stratagus/src/action/action_still.c:1.77 
stratagus/src/action/action_still.c:1.78
--- stratagus/src/action/action_still.c:1.77    Sun Dec 14 19:10:37 2003
+++ stratagus/src/action/action_still.c Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_still.c,v 1.77 2003/12/14 08:10:37 wizzard Exp $
+//      $Id: action_still.c,v 1.78 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -100,7 +100,6 @@
                if (unit->State == 1 && type->GivesResource == OilCost) {
                        unit->Frame = unit->Data.Resource.Active ? 2 : 0;
                }
-               UnitMarkSeen(unit);
        }
 
        if (!unit->Reset) { // animation can't be aborted here
Index: stratagus/src/action/action_upgradeto.c
diff -u stratagus/src/action/action_upgradeto.c:1.43 
stratagus/src/action/action_upgradeto.c:1.44
--- stratagus/src/action/action_upgradeto.c:1.43        Sun Dec 14 19:10:37 2003
+++ stratagus/src/action/action_upgradeto.c     Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: action_upgradeto.c,v 1.43 2003/12/14 08:10:37 wizzard Exp $
+//      $Id: action_upgradeto.c,v 1.44 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -70,7 +70,6 @@
        type = unit->Orders[0].Type;
        stats = &type->Stats[player->Player];
 
-       UnitMarkSeen(unit);
        // FIXME: Should count down here
        unit->Data.UpgradeTo.Ticks += SpeedUpgrade;
        if (unit->Data.UpgradeTo.Ticks >= stats->Costs[TimeCost]) {
Index: stratagus/src/action/actions.c
diff -u stratagus/src/action/actions.c:1.111 
stratagus/src/action/actions.c:1.112
--- stratagus/src/action/actions.c:1.111        Mon Dec 15 08:17:04 2003
+++ stratagus/src/action/actions.c      Thu Jan 15 09:31:01 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: actions.c,v 1.111 2003/12/14 21:17:04 jsalmon3 Exp $
+//      $Id: actions.c,v 1.112 2004/01/14 22:31:01 nobody_ Exp $
 
 //@{
 
@@ -58,65 +58,6 @@
 --  Functions
 ----------------------------------------------------------------------------*/
 
-/**
-**  Check if the unit can still *see* the goal or not
-**  This first of all checks dead/dying units, and then
-**  Invisibility, cloaking, going under fow and the like.
-**
-**  @param unit  Unit that is looking for the goal
-**  @param goal  Goal unit to check if there
-**
-**  @returns     1, gone  0, Still available
-*/
-global int GoalGone(const Unit* unit, const Unit* goal)
-{
-       //
-       // Check for dead/removed goals.
-       //
-       if (goal->Destroyed || !goal->HP || goal->Removed ||
-                       goal->Orders[0].Action == UnitActionDie) {
-               return 1;
-       }
-       //
-       // Check if we have an unit for this goal.
-       //
-       if (unit) {
-               // SharedVision makes all the rest of the checks meaningless
-               if (IsSharedVision(unit->Player, goal) || unit->Player == 
goal->Player) {
-                       return 0;
-               } else {
-                       int x;
-                       int y;
-
-                       // Goal is invisible (by spell)
-                       if (goal->Invisible) {
-                               return 1;
-                       }
-                       // Goal is cloaked for this player
-                       if (!(goal->Visible & (1 << unit->Player->Player))) {
-                               return 1;
-                       }
-                       //
-                       // Check if under fog of war.
-                       // Don't bother for goals visible under fog.
-                       //
-                       if (goal->Type->VisibleUnderFog) {
-                               return 0;
-                       }
-                       for (x = goal->X; x < goal->X + goal->Type->TileWidth; 
++x) {
-                               for (y = goal->Y; y < goal->Y + 
goal->Type->TileHeight; ++y) {
-                                       if (IsMapFieldVisible(unit->Player, x, 
y)) {
-                                               return 0;
-                                       }
-                               }
-                       }
-                       return 1;
-               }
-       } else {
-               return 0;
-       }
-}
-
 /*----------------------------------------------------------------------------
 --  Animation
 ----------------------------------------------------------------------------*/
@@ -697,35 +638,6 @@
                SyncHash ^= unit->State << 12;
                SyncHash ^= unit->SubAction << 6;
                SyncHash ^= unit->Refs << 3;
-       }
-}
-
-/**
-**  Handle Marking and Unmarking of Cloak
-**
-**  @note Must be handled outside the drawing fucntions and
-**  @note all at once.
-*/
-global void HandleCloak(void)
-{
-       Unit* unit;
-       int i;
-
-       for (i = 0; i < NumUnits; ++i) {
-               unit = Units[i];
-               if (unit->Type->PermanentCloak) {
-                       if ((unit->Visible & (1 << ThisPlayer->Player))) {
-                               CheckUnitToBeDrawn(unit);
-                       }
-                       unit->Visible = 0;
-               }
-       }
-       for (i = 0; i < NumUnits; ++i) {
-               unit = Units[i];
-               if (unit->Type->DetectCloak && !unit->Removed &&
-                               unit->Orders[0].Action != UnitActionBuilded) {
-                       MapDetectCloakedUnits(unit);
-               }
        }
 }
 
Index: stratagus/src/action/command.c
diff -u stratagus/src/action/command.c:1.124 
stratagus/src/action/command.c:1.125
--- stratagus/src/action/command.c:1.124        Sat Dec 13 18:03:01 2003
+++ stratagus/src/action/command.c      Thu Jan 15 09:31:02 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: command.c,v 1.124 2003/12/13 07:03:01 wizzard Exp $
+//      $Id: command.c,v 1.125 2004/01/14 22:31:02 nobody_ Exp $
 
 //@{
 
@@ -133,50 +133,6 @@
 ----------------------------------------------------------------------------*/
 
 /**
-**  Player quit.
-**
-**  @param player  Player number that quit.
-*/
-global void CommandQuit(int player)
-{
-       int i;
-       int j;
-
-       if (Players[player].TotalNumUnits != 0) {
-               // Set player to neutral, remove allied/enemy/shared vision 
status
-               Players[player].Type = PlayerNeutral;
-               for (i = 0; i < NumPlayers; ++i) {
-                       if (i == player) {
-                               continue;
-                       }
-                       Players[i].Allied &= ~(1 << player);
-                       Players[i].Enemy &= ~(1 << player);
-                       // Check all tiles and mark unseen ones as explored.
-                       if (Players[player].SharedVision & (1 << i) &&
-                                       (Players[i].SharedVision & (1 << 
player))) {
-                               for (j = 0; j < TheMap.Width*TheMap.Height; 
++j) {
-                                       if (TheMap.Fields[j].Visible[i] &&
-                                                       
!TheMap.Fields[j].Visible[player]) {
-                                               
TheMap.Fields[j].Visible[player] = 1;
-                                       }
-                                       if (TheMap.Fields[j].Visible[player] &&
-                                                       
!TheMap.Fields[j].Visible[i]) {
-                                               TheMap.Fields[j].Visible[i] = 1;
-                                       }
-                               }
-                       }
-                       Players[i].SharedVision &= ~(1 << player);
-                       Players[player].Allied &= ~(1 << i);
-                       Players[player].Enemy &= ~(1 << i);
-                       Players[player].SharedVision &= ~(1 << i);
-               }
-               SetMessage("Player \"%s\" has left the game", 
Players[player].Name);
-       } else {
-               SetMessage("Player \"%s\" has been killed", 
Players[player].Name);
-       }
-}
-
-/**
 **  Stop unit.
 **
 **  @param unit  pointer to unit.
@@ -1339,49 +1295,91 @@
 */
 global void CommandSharedVision(int player, int state, int opponent)
 {
+       int before;
+       int after;
+       int x;
+       int y;
        int i;
-       Unit* unit;
 
+       //
+       //      Do a real hardcore seen recount. First we unmark EVERYTHING.
+       //
+       for (i = 0; i < NumUnits; ++i) {
+               MapUnmarkUnitSight(Units[i]);
+       }
+
+       //
+       //      Compute Before and after.
+       //
+       before = PlayersShareVision(player, opponent);
        if (state == 0) {
-               // Check all tiles and mark unseen ones as explored.
-               if (Players[player].SharedVision & (1 << opponent) &&
-                               (Players[opponent].SharedVision & (1 << 
player))) {
-                       for (i = 0; i < TheMap.Width * TheMap.Height; ++i) {
-                               if (TheMap.Fields[i].Visible[opponent] &&
-                                               
!TheMap.Fields[i].Visible[player]) {
-                                       TheMap.Fields[i].Visible[player] = 1;
-                               }
-                               if (TheMap.Fields[i].Visible[player] &&
-                                               
!TheMap.Fields[i].Visible[opponent]) {
-                                       TheMap.Fields[i].Visible[opponent] = 1;
-                               }
-                       }
-               }
                Players[player].SharedVision &= ~(1 << opponent);
        } else {
                Players[player].SharedVision |= (1 << opponent);
-               // Check all tiles and mark SeenTiles for wood
-               if (Players[player].SharedVision & (1 << opponent) &&
-                               Players[opponent].SharedVision & (1 << player) 
&&
-                               (player == ThisPlayer->Player ||
-                                       opponent == ThisPlayer->Player)) {
-                       int y;
-                       for (i = 0; i < TheMap.Width; ++i) {
-                               for (y = 0; y < TheMap.Height; ++y) {
-                                       if (IsMapFieldVisible(ThisPlayer, i, 
y)) {
-                                               MapMarkSeenTile(i, y);
-                                               UnitsMarkSeen(i, y);
+       }
+       after = PlayersShareVision(player, opponent);
+
+       if (before && !after) {
+               //
+               //      Don't share vision anymore. Give each other explored 
terrain for good-bye.
+               //
+               for (x = 0; x < TheMap.Width; ++x) {
+                       for (y = 0; y < TheMap.Height; ++y) {
+                               i = x + y * TheMap.Width;
+                               if (TheMap.Fields[i].Visible[player] && 
!TheMap.Fields[i].Visible[opponent]) {
+                                       TheMap.Fields[i].Visible[opponent] = 1;
+                                       if (opponent == ThisPlayer->Player) {
+                                               MapMarkSeenTile(x, y);
+                                       }
+                               }
+                               if (TheMap.Fields[i].Visible[opponent] && 
!TheMap.Fields[i].Visible[player]) {
+                                       TheMap.Fields[i].Visible[player] = 1;
+                                       if (player == ThisPlayer->Player) {
+                                               MapMarkSeenTile(x, y);
                                        }
                                }
                        }
                }
        }
-       // MUST update seen buildings when vision is shared or unshared
+
+       //
+       //      Do a real hardcore seen recount. Now we remark EVERYTHING
+       //
        for (i = 0; i < NumUnits; ++i) {
-               unit = Units[i];
-               UnitMarkSeen(unit);
+               MapMarkUnitSight(Units[i]);
        }
+}
 
+/**
+**  Player quit.
+**
+**  @param player  Player number that quit.
+*/
+global void CommandQuit(int player)
+{
+       int i;
+
+       // Set player to neutral, remove allied/enemy/shared vision status
+       // If the player doesn't have any units then this is pointless?
+       Players[player].Type = PlayerNeutral;
+       for (i = 0; i < NumPlayers; ++i) {
+               if (i != player) {
+                       Players[i].Allied &= ~(1 << player);
+                       Players[i].Enemy &= ~(1 << player);
+                       Players[player].Enemy &= ~(1 << i);
+                       Players[player].Allied &= ~(1 << i);
+                       //  We clear Shared vision by sending fake shared 
vision commands.
+                       //  We do this because Shared vision is a bit complex.
+                       CommandSharedVision(i, 0, player);
+                       CommandSharedVision(player, 0, i);
+               }
+       }
+       
+       if (Players[player].TotalNumUnits != 0) {
+               SetMessage("Player \"%s\" has left the game", 
Players[player].Name);
+       } else {
+               SetMessage("Player \"%s\" has been killed", 
Players[player].Name);
+       }
 }
 
 //@}
Index: stratagus/src/ai/ai.c
diff -u stratagus/src/ai/ai.c:1.108 stratagus/src/ai/ai.c:1.109
--- stratagus/src/ai/ai.c:1.108 Sun Jan  4 09:33:24 2004
+++ stratagus/src/ai/ai.c       Thu Jan 15 09:31:02 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai.c,v 1.108 2004/01/03 22:33:24 jsalmon3 Exp $
+//      $Id: ai.c,v 1.109 2004/01/14 22:31:02 nobody_ Exp $
 
 
 //@{
@@ -821,7 +821,7 @@
 {
        CLprintf(file, "\n--- -----------------------------------------\n");
        CLprintf(file,
-               "--- MODULE: AI $Id: ai.c,v 1.108 2004/01/03 22:33:24 jsalmon3 
Exp $\n\n");
+               "--- MODULE: AI $Id: ai.c,v 1.109 2004/01/14 22:31:02 nobody_ 
Exp $\n\n");
 #if 0
        SaveAiTypesWcName(file);
        SaveAiHelper(file);
@@ -1610,7 +1610,7 @@
        int minrange;
        int maxrange;
 
-       DebugLevel2Fn("%s at %d %d\n" _C_ unit->Type->Ident _C_ unit->X _C_ 
unit->Y);
+       DebugLevel3Fn("%s at %d %d\n" _C_ unit->Type->Ident _C_ unit->X _C_ 
unit->Y);
 
        AiPlayer = unit->Player->Ai;
 
@@ -1636,7 +1636,7 @@
        if (PlaceReachable(unit, gx, gy, gw, gh, minrange, maxrange) ||
                        unit->Type->UnitType == UnitTypeFly) {
                // Path probably closed by unit here
-               DebugLevel2Fn("Place reacheable, move unit in the way.\n");
+               DebugLevel3Fn("Place reacheable, move unit in the way.\n");
                AiMoveUnitInTheWay(unit);
                return;
        }
Index: stratagus/src/ai/ai_plan.c
diff -u stratagus/src/ai/ai_plan.c:1.28 stratagus/src/ai/ai_plan.c:1.29
--- stratagus/src/ai/ai_plan.c:1.28     Fri Jan  2 08:24:03 2004
+++ stratagus/src/ai/ai_plan.c  Thu Jan 15 09:31:03 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_plan.c,v 1.28 2004/01/01 21:24:03 jsalmon3 Exp $
+//      $Id: ai_plan.c,v 1.29 2004/01/14 22:31:03 nobody_ Exp $
 
 //@{
 
@@ -80,7 +80,7 @@
                // FIXME: did SelectUnitsOnTile already filter this?
                // Invisible and not Visible
                if (unit->Removed || unit->Invisible || !unit->HP ||
-                               !(unit->Visible & (1 << 
source->Player->Player)) ||
+                               //(!UnitVisible(unit, source->Player)) ||
                                unit->Orders[0].Action == UnitActionDie) {
                        continue;
                }
Index: stratagus/src/ai/ai_resource.c
diff -u stratagus/src/ai/ai_resource.c:1.87 stratagus/src/ai/ai_resource.c:1.88
--- stratagus/src/ai/ai_resource.c:1.87 Sat Jan  3 11:26:19 2004
+++ stratagus/src/ai/ai_resource.c      Thu Jan 15 09:31:03 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ai_resource.c,v 1.87 2004/01/03 00:26:19 jsalmon3 Exp $
+//      $Id: ai_resource.c,v 1.88 2004/01/14 22:31:03 nobody_ Exp $
 
 //@{
 
@@ -217,13 +217,10 @@
        for (e = i = 0; i < n; ++i) {
                dest = table[i];
                //
-               // unusable unit
+               // Those can't attack anyway.
                //
-               // FIXME: did SelectUnits already filter this.
                if (dest->Removed || dest->Invisible || !unit->HP
-                       || !(dest->Visible & (1 << player->Player))
-                       || dest->Orders[0].Action == UnitActionDie) {
-                       DebugLevel0Fn("NO\n");
+                               || dest->Orders[0].Action == UnitActionDie) {
                        continue;
                }
 
Index: stratagus/src/editor/editloop.c
diff -u stratagus/src/editor/editloop.c:1.153 
stratagus/src/editor/editloop.c:1.154
--- stratagus/src/editor/editloop.c:1.153       Fri Jan  2 08:24:05 2004
+++ stratagus/src/editor/editloop.c     Thu Jan 15 09:31:03 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: editloop.c,v 1.153 2004/01/01 21:24:05 jsalmon3 Exp $
+//      $Id: editloop.c,v 1.154 2004/01/14 22:31:03 nobody_ Exp $
 
 //@{
 
@@ -1385,6 +1385,7 @@
                                Unit* unit;
 
                                RemoveUnit(unit = UnitUnderCursor, NULL);
+                               UnitCacheRemove(unit);
                                UnitLost(unit);
                                UnitClearOrders(unit);
                                ReleaseUnit(unit);
Index: stratagus/src/include/actions.h
diff -u stratagus/src/include/actions.h:1.62 
stratagus/src/include/actions.h:1.63
--- stratagus/src/include/actions.h:1.62        Mon Dec 22 08:34:25 2003
+++ stratagus/src/include/actions.h     Thu Jan 15 09:31:04 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: actions.h,v 1.62 2003/12/21 21:34:25 wizzard Exp $
+//      $Id: actions.h,v 1.63 2004/01/14 22:31:04 nobody_ Exp $
 
 #ifndef __ACTIONS_H__
 #define __ACTIONS_H__
@@ -186,8 +186,6 @@
 --  Actions: actions.c
 ----------------------------------------------------------------------------*/
 
-       /// Check if a goal is gone/dead/invisible ?under-fow?
-extern int GoalGone(const Unit* unit, const Unit* goal);
        /// Handle the animation of a unit
 extern int UnitShowAnimation(Unit* unit,const Animation* animation);
        /// Handle the actions of all units each game cycle
Index: stratagus/src/include/map.h
diff -u stratagus/src/include/map.h:1.112 stratagus/src/include/map.h:1.113
--- stratagus/src/include/map.h:1.112   Thu Jan 15 01:06:39 2004
+++ stratagus/src/include/map.h Thu Jan 15 09:31:04 2004
@@ -27,7 +27,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: map.h,v 1.112 2004/01/14 14:06:39 nobody_ Exp $
+//      $Id: map.h,v 1.113 2004/01/14 22:31:04 nobody_ Exp $
 
 #ifndef __MAP_H__
 #define __MAP_H__
@@ -227,6 +227,7 @@
        //        different.
        unsigned char  Value;     /// HP for walls/ Wood Regeneration
        unsigned char Visible[PlayerMax];  /// Seen counter 0 unexplored
+       unsigned char VisCloak[PlayerMax];  /// Visiblity for cloaking.
 #ifdef UNIT_ON_MAP
        union {
                Unit*      Units;  /// An unit on the map field
@@ -415,8 +416,11 @@
 extern void MapMarkTileSight(const Player* player, int x, int y);
        /// Unmark a tile for normal sight
 extern void MapUnmarkTileSight(const Player* player, int x, int y);
-       /// Mark Cloaked units on a tile as detected.
-extern void MapDetectUnitsOnTile(const Player* player, int x, int y);
+       /// Mark a tile for cloak detection
+extern void MapMarkTileDetectCloak(const Player* player,int x,int y);
+       /// Unmark a tile for cloak detection
+extern void MapUnmarkTileDetectCloak(const Player* player,int x,int y);
+
        /// Mark sight changes
 extern void MapSight(const Player* player, int x, int y, int w, int h, int 
range, void (*marker)(const Player*, int, int));
        /// Find if a tile is visible (With shared vision)
@@ -566,14 +570,29 @@
 #define CanMoveToMask(x,y,mask) \
                !(TheMap.Fields[(x)+(y)*TheMap.Width].Flags&(mask))
 
-#define MapDetectCloakedUnits(unit) 
MapSight((unit)->Player,(unit)->X,(unit)->Y, \
-       
(unit)->Type->TileWidth,(unit)->Type->TileHeight,(unit)->CurrentSightRange,MapDetectUnitsOnTile)
 #define MapMarkSight(player,x,y,w,h,range) 
MapSight((player),(x),(y),(w),(h),(range),MapMarkTileSight)
 #define MapUnmarkSight(player,x,y,w,h,range) 
MapSight((player),(x),(y),(w),(h),(range),MapUnmarkTileSight)
-#define MapMarkUnitSight(unit) MapSight((unit)->Player,(unit)->X,(unit)->Y, \
-       
(unit)->Type->TileWidth,(unit)->Type->TileHeight,(unit)->CurrentSightRange,MapMarkTileSight)
-#define MapUnmarkUnitSight(unit) MapSight((unit)->Player,(unit)->X,(unit)->Y, \
-       
(unit)->Type->TileWidth,(unit)->Type->TileHeight,(unit)->CurrentSightRange,MapUnmarkTileSight)
+
+#define MapMarkUnitSight(unit) \
+{ \
+       MapSight((unit)->Player, (unit)->X,(unit)->Y, (unit)->Type->TileWidth,\
+                       (unit)->Type->TileHeight, (unit)->CurrentSightRange, 
MapMarkTileSight); \
+       if (unit->Type->DetectCloak) { \
+               MapSight((unit)->Player, (unit)->X,(unit)->Y, 
(unit)->Type->TileWidth,\
+                               (unit)->Type->TileHeight, 
(unit)->CurrentSightRange, MapMarkTileDetectCloak); \
+       }\
+}
+
+#define MapUnmarkUnitSight(unit) \
+{ \
+       MapSight((unit)->Player,(unit)->X,(unit)->Y, (unit)->Type->TileWidth,\
+                       
(unit)->Type->TileHeight,(unit)->CurrentSightRange,MapUnmarkTileSight); \
+       if (unit->Type->DetectCloak) { \
+               MapSight((unit)->Player, (unit)->X,(unit)->Y, 
(unit)->Type->TileWidth,\
+                               (unit)->Type->TileHeight, 
(unit)->CurrentSightRange, MapUnmarkTileDetectCloak); \
+       }\
+}
+
 #define MapMarkUnitOnBoardSight(unit,host) 
MapSight((unit)->Player,(host)->X,(host)->Y, \
        
(host)->Type->TileWidth,(host)->Type->TileHeight,(unit)->CurrentSightRange,MapMarkTileSight)
 #define MapUnmarkUnitOnBoardSight(unit,host) 
MapSight((unit)->Player,(host)->X,(host)->Y, \
Index: stratagus/src/include/player.h
diff -u stratagus/src/include/player.h:1.82 stratagus/src/include/player.h:1.83
--- stratagus/src/include/player.h:1.82 Fri Jan  9 16:44:37 2004
+++ stratagus/src/include/player.h      Thu Jan 15 09:31:04 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: player.h,v 1.82 2004/01/09 05:44:37 jsalmon3 Exp $
+//      $Id: player.h,v 1.83 2004/01/14 22:31:04 nobody_ Exp $
 
 #ifndef __PLAYER_H__
 #define __PLAYER_H__
@@ -117,6 +117,11 @@
 **    are combined, if none bit is set, the player is neutral.
 **    @note You can be allied to a player, which sees you as enemy.
 **
+**  Player::SharedVision
+**
+**    A bit field which contains shared vision for this player.
+**    Shared vision only works when it's activated both ways. Really.
+**
 **  Player::StartX Player::StartY
 **
 **    The tile map coordinates of the player start position. 0,0 is
@@ -537,6 +542,9 @@
 
        /// register ccl features
 extern void PlayerCclRegister(void);
+
+       /// Two players share vision
+#define PlayersShareVision(a, b) ((Players[a].SharedVision & (1 << (b))) && 
(Players[b].SharedVision & (1 << (a))) )
 
 //@}
 
Index: stratagus/src/include/ui.h
diff -u stratagus/src/include/ui.h:1.84 stratagus/src/include/ui.h:1.85
--- stratagus/src/include/ui.h:1.84     Thu Jan 15 01:06:39 2004
+++ stratagus/src/include/ui.h  Thu Jan 15 09:31:04 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: ui.h,v 1.84 2004/01/14 14:06:39 nobody_ Exp $
+//     $Id: ui.h,v 1.85 2004/01/14 22:31:04 nobody_ Exp $
 
 #ifndef __UI_H__
 #define __UI_H__
@@ -400,9 +400,6 @@
 extern void ViewportSetViewpoint(Viewport* vp, int x, int y);
        /// Center map on point in viewport
 extern void ViewportCenterViewpoint(Viewport* vp, int x, int y);
-
-       /// Returns true, if unit is visible on current map view
-extern int UnitVisibleInViewport(const Viewport* vp, const Unit* unit);
 
 //@}
 
Index: stratagus/src/include/unit.h
diff -u stratagus/src/include/unit.h:1.243 stratagus/src/include/unit.h:1.244
--- stratagus/src/include/unit.h:1.243  Sun Jan  4 09:31:50 2004
+++ stratagus/src/include/unit.h        Thu Jan 15 09:31:05 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: unit.h,v 1.243 2004/01/03 22:31:50 jsalmon3 Exp $
+//      $Id: unit.h,v 1.244 2004/01/14 22:31:05 nobody_ Exp $
 
 #ifndef __UNIT_H__
 #define __UNIT_H__
@@ -200,11 +200,20 @@
 **
 **                             If Burning is non-zero, the unit is burning.
 **
-**             Unit::Visible
+**             Unit::VisCount[PlayerMax]
 **
-**                             Used for submarines. It is a bit field for all 
players. If
-**                             Unit::Visible&(1<<player-nr) is non-zero, the 
unit could be
-**                             seen on the map.
+**              Used to keep track of visible units on the map, it counts the
+**              Number of seen tiles for each player. This is only modified
+**              in UnitsMarkSeen and UnitsUnmarkSeen, from fow.
+**                             We keep track of visilibty for each player, and 
combine with
+**                             Shared vision ONLY when querying and such.
+**
+**      Unit::SeenByPlayer
+**
+**              This is a bitmask of 1 and 0 values. SeenByPlayer & (1<<p) is 0
+**              If p never saw the unit and 1 if it did. This is important for
+**              keeping track of dead units under fog. We only keep track of 
units
+**                             that are visible under fog with this.
 **
 **             Unit::Destroyed
 **
@@ -506,7 +515,6 @@
        int                             Y;                                      
        /// Map position Y
 
        UnitType*               Type;                                           
/// Pointer to unit-type (peon,...)
-       UnitType*               SeenType;                               /// 
Pointer to last seen unit-type
        Player*  Player;                                                /// 
Owner of this unit
        UnitStats*              Stats;                                          
/// Current unit stats
        int                             CurrentSightRange;              /// 
Unit's Current Sight Range
@@ -516,80 +524,86 @@
        signed char             IX;                                             
/// X image displacement to map position
        signed char             IY;                                             
/// Y image displacement to map position
        int                             Frame;                                  
        /// Image frame: <0 is mirrored
-       int                             SeenFrame;                              
/// last seen frame/stage of buildings
-       signed char             SeenIX;                                         
/// Seen X image displacement to map position
-       signed char             SeenIY;                                         
/// seen Y image displacement to map position
 
        unsigned                Direction : 8;                          /// 
angle (0-255) unit looking
 
-       unsigned long Attacked;                         /// gamecycle unit was 
last attacked
+       unsigned long Attacked;                                 /// gamecycle 
unit was last attacked
 
-       unsigned                Burning : 1;                            /// 
unit is burning
-       unsigned                Destroyed : 1;                          /// 
unit is destroyed pending reference
-       unsigned                Removed : 1;                            /// 
unit is removed (not on map)
-       unsigned                Selected : 1;                           /// 
unit is selected
+       unsigned                Burning : 1;                    /// unit is 
burning
+       unsigned                Destroyed : 1;                  /// unit is 
destroyed pending reference
+       unsigned                Removed : 1;                    /// unit is 
removed (not on map)
+       unsigned                Selected : 1;                   /// unit is 
selected
 
-       unsigned                Visible : 16;                           /// 
Unit is visible (submarine)
        unsigned                Constructed : 1;                /// Unit is in 
construction
-       unsigned                SeenConstructed : 1;            /// Unit seen 
construction
-       unsigned                SeenState : 3;                          /// 
Unit seen build/upgrade state
-       unsigned                SeenDestroyed : 1;              /// Unit seen 
destroyed or not
        unsigned                Active : 1;                             /// 
Unit is active for AI
-       Player*  RescuedFrom;                   /// The original owner of a 
rescued unit.
+       Player*  RescuedFrom;                                   /// The 
original owner of a rescued unit.
                                                                                
        /// NULL if the unit was not rescued.
+       /* Seen stuff. */
+       char                    VisCount[PlayerMax];    /// Unit visibility 
counts
+       struct _seen_stuff_ {
+               unsigned                    ByPlayer : 16;              /// 
Track unit seen by player
+               int                             Frame;                          
/// last seen frame/stage of buildings
+               UnitType*               Type;                           /// 
Pointer to last seen unit-type
+               signed char                 IX;                                 
/// Seen X image displacement to map position
+               signed char                 IY;                                 
/// seen Y image displacement to map position
+               unsigned                    Constructed : 1;    /// Unit seen 
construction
+               unsigned                    State : 3;                  /// 
Unit seen build/upgrade state
+               unsigned            Destroyed : PlayerMax;      /// Unit seen 
destroyed or not
+               ConstructionFrame*  CFrame;                             /// 
Seen construction frame
+       } Seen;
 
        int                             Mana;                                   
        /// mana points
-       int                             HP;                                     
        /// hit points
-       int                             XP;                                     
        /// experience points
+       int                             HP;                                     
                /// hit points
+       int                             XP;                                     
                /// experience points
        int                             Kills;                                  
        /// how many unit has this unit killed
 
-       unsigned long           TTL;                            /// time to live
-       int                             Bloodlust;                              
/// ticks bloodlust
+       unsigned long           TTL;                                    /// 
time to live
+       int                             Bloodlust;                              
        /// ticks bloodlust
        int                             Haste;                                  
        /// ticks haste (disables slow)
        int                             Slow;                                   
        /// ticks slow (disables haste)
-       int                             Invisible;                              
/// ticks invisible
+       int                             Invisible;                              
        /// ticks invisible
        int                             FlameShield;                            
/// ticks flame shield
        int                             UnholyArmor;                            
/// ticks unholy armor
 
-       int                             GroupId;                                
/// unit belongs to this group id
-       int                             LastGroup;                              
/// unit belongs to this last group
+       int                             GroupId;                                
        /// unit belongs to this group id
+       int                             LastGroup;                              
        /// unit belongs to this last group
 
        int                             Value;                                  
        /// value used for much
 
        unsigned                SubAction : 8;                          /// 
sub-action of unit
        unsigned                Wait;                                           
/// action counter
-       unsigned                State : 8;                              /// 
action state
-#define MAX_UNIT_STATE         255                             /// biggest 
state for action
-       unsigned                Reset : 1;                              /// can 
process new command
-       unsigned                Blink : 3;                              /// Let 
selection rectangle blink
-       unsigned                Moving : 1;                             /// The 
unit is moving
+       unsigned                State : 8;                                      
/// action state
+#define MAX_UNIT_STATE         255                                     /// 
biggest state for action
+       unsigned                Reset : 1;                                      
/// can process new command
+       unsigned                Blink : 3;                                      
/// Let selection rectangle blink
+       unsigned                Moving : 1;                                     
/// The unit is moving
                                                                                
/** set to random 1..100 when MakeUnit()
                                                                                
** used for fancy buildings
                                                                                
*/
        unsigned                Rs : 8;
        unsigned char           CurrentResource;
 
-#define MAX_ORDERS 16                                          /// How many 
outstanding orders?
-       char            OrderCount;                             /// how many 
orders in queue
-       char            OrderFlush;                             /// cancel 
current order, take next
-       Order           Orders[MAX_ORDERS];             /// orders to process
-       Order           SavedOrder;                             /// order to 
continue after current
-       Order           NewOrder;                               /// order for 
new trained units
+#define MAX_ORDERS 16                                                  /// How 
many outstanding orders?
+       char            OrderCount;                                             
/// how many orders in queue
+       char            OrderFlush;                                             
/// cancel current order, take next
+       Order           Orders[MAX_ORDERS];                             /// 
orders to process
+       Order           SavedOrder;                                             
/// order to continue after current
+       Order           NewOrder;                                               
/// order for new trained units
        struct _spell_type_*    AutoCastSpell;          /// spell to auto cast
 
        union _order_data_ {
        struct _order_move_ {
                char            Fast;                                           
/// Flag fast move (one step)
                char            Length;                                         
/// stored path length
-#define MAX_PATH_LENGTH 28                             /// max length of 
precalculated path
+#define MAX_PATH_LENGTH 28                                             /// max 
length of precalculated path
                char            Path[MAX_PATH_LENGTH];          /// directions 
of stored path
        }                               Move;                                   
        /// ActionMove,...
        struct _order_builded_ {
                Unit*           Worker;                                         
/// Worker building this unit
-               int             Progress;                               /// 
Progress counter, in 1/100 cycles.
-               int             Cancel;                                         
/// Cancel construction
-               ConstructionFrame* Frame;               /// Construction frame
-       }                               Builded;                                
/// ActionBuilded,...
+               int             Progress;                                       
        /// Progress counter, in 1/100 cycles.
+               int             Cancel;                                         
        /// Cancel construction
+               ConstructionFrame* Frame;                               /// 
Construction frame
+       }                               Builded;                                
        /// ActionBuilded,...
        struct _order_resource_ {
                int             Active;                                         
/// how many units are harvesting from the resource.
        }                               Resource;                               
/// Resource still
@@ -692,8 +706,6 @@
 
 extern Unit* Units[MAX_UNIT_SLOTS];            /// Units used
 extern int NumUnits;                                           /// Number of 
units used
-extern Unit* DestroyedBuildings;               /// List of DestroyedBuildings
-extern Unit* CorpseList;                               /// List of Corpses On 
Map
 
 //             in unit_draw.c (FIXME: could be moved into the user interface?)
 extern int ShowHealthBar;                              /// Flag: show health 
bar
@@ -765,17 +777,24 @@
 extern void UpdateForNewUnit(const Unit* unit, int upgrade);
        /// FIXME: more docu
 extern void NearestOfUnit(const Unit* unit, int tx, int ty, int *dx, int *dy);
-       /// Returns true, if unit is visible on the map
-extern int UnitVisibleOnMap(const Unit* unit);
-       /// Returns true, if building is known on the map
-extern int BuildingVisibleOnMap(const Unit* unit);
-
-       /// Updates seen data
-extern void UnitsMarkSeen(int x, int y);
-       /// Checks and updates if a Unit's seen information
-extern void UnitMarkSeen(Unit* unit);
-       /// Returns true, if unit is known on the map
-extern int UnitKnownOnMap(const Unit* unit);
+
+       /// Marks an unit as seen
+extern void UnitsOnTileMarkSeen(const Player* player, int x, int y, int p);
+       /// Unmarks an unit as seen
+extern void UnitsOnTileUnmarkSeen(const Player* player, int x, int y, int p);
+       /// Does a recount for VisCount
+extern void UnitCountSeen(Unit* unit);
+
+       /// Returns true, if unit is directly seen by an allied unit.
+extern int UnitVisible(const Unit* unit, const Player* player);
+       /// Returns true, if unit is visible as a goal.
+extern int UnitVisibleAsGoal(const Unit* unit, const Player* player);
+       /// Returns true, if unit is Visible for game logic on the map.
+extern int UnitVisibleOnMap(const Unit* unit, const Player* player);
+       /// Returns true if unit is visible on minimap. Only for ThisPlayer.
+extern int UnitVisibleOnMinimap(const Unit* unit);
+       /// Returns true if unit is visible in an viewport. Only for ThisPlayer.
+extern int UnitVisibleInViewport(const Unit* unit, const Viewport* vp);
 
        /// To be called when the look of the unit changes.
 extern int CheckUnitToBeDrawn(Unit* unit);
@@ -889,22 +908,6 @@
 extern void UnitCacheStatistic(void);
        /// Initialize unit-cache
 extern void InitUnitCache(void);
-       /// Inserts a corpse into the corpse list cache
-extern void DeadCacheInsert(Unit* unit, Unit** List);
-       /// Removes a corpse from the corpse cache
-extern void DeadCacheRemove(Unit* unit, Unit** List);
-
-#define CorpseCacheInsert(unit) \
-               (DeadCacheInsert((unit),&CorpseList))
-
-#define DeadBuildingCacheInsert(unit) \
-               (DeadCacheInsert((unit),&DestroyedBuildings))
-
-#define CorpseCacheRemove(unit) \
-               (DeadCacheRemove((unit),&CorpseList))
-
-#define DeadBuildingCacheRemove(unit) \
-               (DeadCacheRemove((unit),&DestroyedBuildings))
 
 //             in unit_draw.c
 //--------------------
Index: stratagus/src/map/map.c
diff -u stratagus/src/map/map.c:1.71 stratagus/src/map/map.c:1.72
--- stratagus/src/map/map.c:1.71        Wed Dec 24 11:35:21 2003
+++ stratagus/src/map/map.c     Thu Jan 15 09:31:05 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: map.c,v 1.71 2003/12/24 00:35:21 wizzard Exp $
+//     $Id: map.c,v 1.72 2004/01/14 22:31:05 nobody_ Exp $
 
 //@{
 
@@ -134,43 +134,27 @@
 */
 global void RevealMap(void)
 {
-       int ix;
-       int iy;
-       Unit* unit;
-
-       for (ix = 0; ix < TheMap.Width; ++ix) {
-               for (iy = 0; iy < TheMap.Height; ++iy) {
+       int x;
+       int y;
+       //
+       //      Mark every explored tile as visible. 1 turns into 2.
+       //
+       for (x = 0; x < TheMap.Width; ++x) {
+               for (y = 0; y < TheMap.Height; ++y) {
                        int i;
                        for (i = 0; i < PlayerMax; ++i) {
-                               if 
(!TheMap.Fields[ix+iy*TheMap.Width].Visible[i]) {
-                                       
TheMap.Fields[ix+iy*TheMap.Width].Visible[i] = 1;
+                               if 
(!TheMap.Fields[x+y*TheMap.Width].Visible[i]) {
+                                       
TheMap.Fields[x+y*TheMap.Width].Visible[i] = 1;
                                }
                        }
-                       MapMarkSeenTile(ix, iy);
-                       UnitsMarkSeen(ix, iy);
+                       MapMarkSeenTile(x, y);
                }
        }
-       for (ix = 0; ix < Players[PlayerNumNeutral].TotalNumUnits; ++ix) {
-               unit = Players[PlayerNumNeutral].Units[ix];
-               unit->SeenIY = unit->IY;
-               unit->SeenIX = unit->IX;
-               if (unit->SeenFrame == UnitNotSeen) {
-                       DebugLevel3Fn("unit %d at %d,%d first seen at %lu.\n" 
_C_
-                               unit->Slot _C_ unit->X _C_ unit->Y _C_ 
GameCycle);
-               }
-               unit->SeenFrame = unit->Frame;
-               unit->SeenState = (unit->Orders[0].Action == UnitActionBuilded) 
|
-                       ((unit->Orders[0].Action == UnitActionUpgradeTo) << 1);
-               if (unit->Orders[0].Action == UnitActionDie) {
-                       unit->SeenState = 3;
-               }
-               if (unit->SeenState == 2) {
-                       unit->SeenType = unit->Orders[0].Type;
-               } else {
-                       unit->SeenType = unit->Type;
-               }
-               unit->SeenConstructed = unit->Constructed;
-               unit->SeenDestroyed = unit->Destroyed;
+       //
+       //      Global seen recount. Simple and effective.
+       //
+       for (x = 0; x < NumUnits; ++x) {
+               UnitCountSeen(Units[x]);
        }
 }
 
Index: stratagus/src/map/map_fog.c
diff -u stratagus/src/map/map_fog.c:1.139 stratagus/src/map/map_fog.c:1.140
--- stratagus/src/map/map_fog.c:1.139   Thu Jan 15 06:48:19 2004
+++ stratagus/src/map/map_fog.c Thu Jan 15 09:31:05 2004
@@ -11,7 +11,7 @@
 /address@hidden map_fog.c      -       The map fog of war handling. */
 //
 //      (c) Copyright 1999-2003 by Lutz Sammer, Vladi Shabanski,
-//                                   Russell Smith, and Jimmy Salmon
+//                                                               Russell 
Smith, and Jimmy Salmon
 //
 //      This program is free software; you can redistribute it and/or modify
 //      it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: map_fog.c,v 1.139 2004/01/14 19:48:19 nobody_ Exp $
+//      $Id: map_fog.c,v 1.140 2004/01/14 22:31:05 nobody_ Exp $
 
 //@{
 
@@ -187,7 +187,8 @@
 }
 
 /**
-**             Find out if a field is seen (By me, or by shared vision)
+**             Find out if a field is seen (By player, or by shared vision)
+**             This function will return > 1 with no fog of war.
 **
 **             @param player           Player to check for.
 **             @param x                X tile to check.
@@ -239,52 +240,25 @@
 global void MapMarkTileSight(const Player* player, int x, int y)
 {
        unsigned char v;
-       Unit* unit;
-       Unit* remove;
-       Unit** corpses;
-       int w;
-       int h;
 
        v = TheMap.Fields[x + y * TheMap.Width].Visible[player->Player];
-
        switch (v) {
-               case 0:                         // Unexplored
-               case 1:                         // Unseen
-               // FIXME: mark for screen update
-                       v = 2;
-                       if (player->Type == PlayerPerson) {
-                               corpses = &DestroyedBuildings;
-                               while (*corpses) {
-                                       unit = *corpses;
-                                       if ((unit->Visible & 1 << 
player->Player)) {
-                                               w = unit->Type->TileWidth;
-                                               h = unit->Type->TileHeight;
-                                               if (x >= unit->X && y >= 
unit->Y &&
-                                                               x < unit->X+w 
&& y < unit->Y+h) {
-                                                       unit->Visible &= ~(1 << 
player->Player);
-                                                       UnitMarkSeen(unit);
-                                               }
-                                       }
-                                       remove = unit;
-                                       unit = unit->Next;
-                                       corpses = &unit;
-                                       if (remove->Visible == 0x0000 && 
!remove->Refs) {
-                                               ReleaseUnit(remove);
-                                       }
-                               }
+               case 0:         // Unexplored
+               case 1:         // Unseen
+                       //  When there is NoFogOfWar only unexplored tiles are 
marked.
+                       if ((!TheMap.NoFogOfWar) || (v == 0)) {
+                               UnitsOnTileMarkSeen(player, x, y, 0);
                        }
+                       v = 2;
                        TheMap.Fields[x + y * 
TheMap.Width].Visible[player->Player] = v;
                        if (IsTileVisible(ThisPlayer, x, y) > 1) {
                                MapMarkSeenTile(x, y);
-                               UnitsMarkSeen(x, y);
                        }
-
                        return;
-               case 255:                               // Overflow
+               case 255:               // Overflow
                        DebugLevel0Fn("Visible overflow (Player): %d\n" _C_ 
player->Player);
                        break;
-
-               default:                                // seen -> seen
+               default:                // seen -> seen
                        ++v;
                        break;
        }
@@ -310,18 +284,21 @@
                        v = LookupSight(player, x, y);
                        DebugCheck(v < 254);
                        break;
-               case 0:                         // Unexplored
+               case 0:         // Unexplored
                case 1:
                        // We are at minimum, don't do anything shouldn't 
happen.
                        DebugCheck(1);
                        break;
                case 2:
+                       //  When there is NoFogOfWar units never get unmarked.
+                       if (!TheMap.NoFogOfWar) {
+                               UnitsOnTileUnmarkSeen(player, x, y, 0);
+                       }
                        // Check visible Tile, then deduct...
                        if (IsTileVisible(ThisPlayer, x, y) > 1) {
                                MapMarkSeenTile(x, y);
-                               UnitsMarkSeen(x, y);
                        }
-               default:                                // seen -> seen
+               default:                // seen -> seen
                        v--;
                        break;
        }
@@ -329,24 +306,43 @@
 }
 
 /**
-**             Mark cloacked units on a tile as detected.
+**     Mark a tile for cloak detection.
 **
-**             @param player           Player to mark sight.
-**             @param x                X tile to mark.
-**             @param y                Y tile to mark.
+**     @param player   Player to mark sight.
+**     @param x        X tile to mark.
+**     @param y        Y tile to mark.
 */
-global void MapDetectUnitsOnTile(const Player* player, int x, int y)
+global void MapMarkTileDetectCloak(const Player* player, int x, int y)
 {
-       Unit* table[UnitMax];
-       int n;
-       int i;
-       int pm;
+       unsigned char v;
+
+       v = TheMap.Fields[x + y * TheMap.Width].VisCloak[player->Player];
+       if (v == 0) {
+               UnitsOnTileMarkSeen(player, x, y, 1);
+       }
+       DebugCheck(v == 255);
+       ++v;
+       TheMap.Fields[x + y * TheMap.Width].VisCloak[player->Player] = v;
+}
+
+/**
+**     Unmark a tile for cloak detection.
+**
+**     @param player   Player to mark sight.
+**     @param x        X tile to mark.
+**     @param y        Y tile to mark.
+*/
+global void MapUnmarkTileDetectCloak(const Player* player, int x, int y)
+{
+       unsigned char v;
 
-       n = SelectUnitsOnTile(x, y, table);
-       pm = ((1 << player->Player) | player->SharedVision);
-       for (i = 0; i < n; ++i) {
-               table[i]->Visible |= pm;
+       v = TheMap.Fields[x + y * TheMap.Width].VisCloak[player->Player];
+       DebugCheck(v == 0);
+       if (v == 1) {
+               UnitsOnTileUnmarkSeen(player, x, y, 1);
        }
+       --v;
+       TheMap.Fields[x + y * TheMap.Width].VisCloak[player->Player] = v;
 }
 
 /**
@@ -462,8 +458,9 @@
        int y;
        int w;
 
+       DebugLevel0Fn("\n");
        //
-       //              Mark all explored fields as visible.
+       //              Mark all explored fields as visible again.
        //
        if (TheMap.NoFogOfWar) {
                w = TheMap.Width;
@@ -471,10 +468,15 @@
                        for (x = 0; x < TheMap.Width; ++x) {
                                if (IsMapFieldExplored(ThisPlayer, x, y)) {
                                        MapMarkSeenTile(x, y);
-                                       UnitsMarkSeen(x, y);
                                }
                        }
                }
+       }
+       //
+       //      Global seen recount.
+       //
+       for (x = 0; x < NumUnits; ++x) {
+               UnitCountSeen(Units[x]);
        }
        MarkDrawEntireMap();
 }
Index: stratagus/src/map/minimap.c
diff -u stratagus/src/map/minimap.c:1.89 stratagus/src/map/minimap.c:1.90
--- stratagus/src/map/minimap.c:1.89    Thu Jan 15 04:49:58 2004
+++ stratagus/src/map/minimap.c Thu Jan 15 09:31:06 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: minimap.c,v 1.89 2004/01/14 17:49:58 jsalmon3 Exp $
+//     $Id: minimap.c,v 1.90 2004/01/14 22:31:06 nobody_ Exp $
 
 //@{
 
@@ -270,21 +270,74 @@
        SDL_UnlockSurface(MinimapTerrainSurface);
 }
 
-global void UpdateMinimap(void)
+/**
+**      Draw an unit on the minimap. 
+*/
+local void DrawUnitOnMinimap(Unit* unit, int red_phase)
 {
-       static int red_phase;
-       int red_phase_changed;
+       UnitType* type;
        int mx;
        int my;
-       UnitType* type;
-       Unit** table;
-       Unit* unit;
        int w;
        int h;
        int h0;
-       int visiontype; // 0 unexplored, 1 explored, >1 visible.
-       SDL_Color c;
        Uint32 color;
+       SDL_Color c;
+
+       if (!UnitVisibleOnMinimap(unit)) {
+               return ;
+       }
+       type = unit->Type;
+       //
+       //  FIXME: We should force unittypes to have a certain color on the 
minimap.
+       //
+       if (unit->Player->Player == PlayerNumNeutral) {
+               color = SDL_MapRGB(TheScreen->format,
+                       unit->Type->NeutralMinimapColorRGB.r,
+                       unit->Type->NeutralMinimapColorRGB.g,
+                       unit->Type->NeutralMinimapColorRGB.b);
+       } else if (unit->Player == ThisPlayer) {
+               if (unit->Attacked && unit->Attacked + ATTACK_BLINK_DURATION > 
GameCycle &&
+                               (red_phase || unit->Attacked + 
ATTACK_RED_DURATION > GameCycle)) {
+                       color = ColorRed;
+               } else if (MinimapShowSelected && unit->Selected) {
+                       color = ColorWhite;
+               } else {
+                       color = ColorGreen;
+               }
+       } else {
+               color = unit->Player->Color;
+       }
+
+       mx = 1 + MinimapX + Map2MinimapX[unit->X];
+       my = 1 + MinimapY + Map2MinimapY[unit->Y];
+       w = Map2MinimapX[type->TileWidth];
+       if (mx + w >= TheUI.MinimapW) {                         // clip right 
side
+               w = TheUI.MinimapW - mx;
+       }
+       h0 = Map2MinimapY[type->TileHeight];
+       if (my + h0 >= TheUI.MinimapH) {                // clip bottom side
+               h0 = TheUI.MinimapH - my;
+       }
+       while (w-- >= 0) {
+               h = h0;
+               while (h-- >= 0) {
+                       SDL_GetRGB(color, TheScreen->format, &c.r, &c.g, &c.b);
+                       ((Uint8*)MinimapSurface->pixels)[mx + w + (my + h) * 
TheUI.MinimapW] =
+                               SDL_MapRGB(MinimapSurface->format, c.r, c.g, 
c.b);
+               }
+       }
+}
+
+global void UpdateMinimap(void)
+{
+       static int red_phase;
+       int red_phase_changed;
+       int mx;
+       int my;
+       int n;
+       Unit* table[UnitMax];
+       int visiontype; // 0 unexplored, 1 explored, >1 visible.
 
        red_phase_changed = red_phase != (int)((FrameCounter / 
FRAMES_PER_SECOND) & 1);
        if (red_phase_changed) {
@@ -317,114 +370,13 @@
 
        //
        //              Draw units on map
-       //              FIXME: I should rewrite this completely
-       //              FIXME: make a bitmap of the units, and update it with 
the moves
-       //              FIXME: and other changes
+       //              FIXME: We should rewrite this completely
        //
-
-       table = &CorpseList;
-
-       while (*table) {
-
-               // Only for buildings?
-               if (!(*table)->Type->Building) {
-                       table = &(*table)->Next;
-                       continue;
-               }
-               if (!BuildingVisibleOnMap(*table) && (*table)->SeenState != 3
-                               && !(*table)->SeenDestroyed && (type = 
(*table)->SeenType) ) {
-                       if( (*table)->Player->Player == PlayerNumNeutral ) {
-                               color = SDL_MapRGB(TheScreen->format,
-                                       
(*table)->Type->NeutralMinimapColorRGB.r,
-                                       
(*table)->Type->NeutralMinimapColorRGB.g,
-                                       
(*table)->Type->NeutralMinimapColorRGB.b);
-                       } else {
-                               color = (*table)->Player->Color;
-                       }
-
-                       mx = 1 + MinimapX + Map2MinimapX[(*table)->X];
-                       my = 1 + MinimapY + Map2MinimapY[(*table)->Y];
-                       w = Map2MinimapX[type->TileWidth];
-                       if (mx + w >= TheUI.MinimapW) {         // clip right 
side
-                               w = TheUI.MinimapW - mx;
-                       }
-                       h0 = Map2MinimapY[type->TileHeight];
-                       if (my + h0 >= TheUI.MinimapH) {                // clip 
bottom side
-                               h0 = TheUI.MinimapH - my;
-                       }
-                       while (w-- >= 0) {
-                               h = h0;
-                               while (h-- >= 0) {
-                                       SDL_GetRGB(color, TheScreen->format, 
&c.r, &c.g, &c.b);
-                                       ((Uint8*)MinimapSurface)[mx + w + (my + 
h) * TheUI.MinimapW] =
-                                               
SDL_MapRGB(MinimapSurface->format, c.r, c.g, c.b);
-                               }
-                       }
-               }
-               table = &(*table)->Next;
+       n = UnitCacheSelect(0, 0, TheMap.Height, TheMap.Width, table);
+       while (n--) {
+               DrawUnitOnMinimap(table[n], red_phase);
        }
 
-       for (table = Units; table < Units + NumUnits; ++table) {
-
-               unit = *table;
-
-               if (unit->Removed) {                            // Removed, 
inside another building
-                       continue;
-               }
-               if (unit->Invisible) {                          // Can't be seen
-                       continue;
-               }
-               if (!(unit->Visible & (1 << ThisPlayer->Player))) {
-                       continue;                                               
// Cloaked unit not visible
-               }
-
-               if (!UnitKnownOnMap(unit) && !ReplayRevealMap) {
-                       continue;
-               }
-
-               // FIXME: submarine not visible
-
-               type = unit->Type;
-               //
-               //  FIXME: We should force unittypes to have a certain color on 
the minimap.
-               //
-               if (unit->Player->Player == PlayerNumNeutral) {
-                       color = SDL_MapRGB(TheScreen->format,
-                               (*table)->Type->NeutralMinimapColorRGB.r,
-                               (*table)->Type->NeutralMinimapColorRGB.g,
-                               (*table)->Type->NeutralMinimapColorRGB.b);
-               } else if (unit->Player == ThisPlayer) {
-                       if (unit->Attacked && unit->Attacked + 
ATTACK_BLINK_DURATION > GameCycle &&
-                                       (red_phase || unit->Attacked + 
ATTACK_RED_DURATION > GameCycle)) {
-                               color = ColorRed;
-                       } else if (MinimapShowSelected && unit->Selected) {
-                               color = ColorWhite;
-                       } else {
-                               color = ColorGreen;
-                       }
-               } else {
-                       color = unit->Player->Color;
-               }
-
-               mx = 1 + MinimapX + Map2MinimapX[unit->X];
-               my = 1 + MinimapY + Map2MinimapY[unit->Y];
-               w = Map2MinimapX[type->TileWidth];
-               if (mx + w >= TheUI.MinimapW) {                         // clip 
right side
-                       w = TheUI.MinimapW - mx;
-               }
-               h0 = Map2MinimapY[type->TileHeight];
-               if (my + h0 >= TheUI.MinimapH) {                // clip bottom 
side
-                       h0 = TheUI.MinimapH - my;
-               }
-               while (w-- >= 0) {
-                       h = h0;
-                       while (h-- >= 0) {
-                               SDL_GetRGB(color, TheScreen->format, &c.r, 
&c.g, &c.b);
-                               ((Uint8*)MinimapSurface->pixels)[mx + w + (my + 
h) * TheUI.MinimapW] =
-                                       SDL_MapRGB(MinimapSurface->format, c.r, 
c.g, c.b);
-                       }
-               }
-       }
        SDL_UnlockSurface(MinimapSurface);
 }
 
@@ -821,61 +773,17 @@
        //              FIXME: and other changes
        //
 
-       //              Draw Destroyed Buildings On Map
-       table = &DestroyedBuildings;
-       while (*table) {
-               VMemType color;
-
-               if (!BuildingVisibleOnMap(*table) && (*table)->SeenState != 3
-                               && !(*table)->SeenDestroyed && (type = 
(*table)->SeenType) ) {
-                       if( (*table)->Player->Player == PlayerNumNeutral ) {
-                               color = 
VideoMapRGB((*table)->Type->NeutralMinimapColorRGB.D24.a,
-                                               
(*table)->Type->NeutralMinimapColorRGB.D24.b,
-                                               
(*table)->Type->NeutralMinimapColorRGB.D24.c);
-                       } else {
-                               color = (*table)->Player->Color;
-                       }
-
-                       mx = 1 + MinimapX + Map2MinimapX[(*table)->X];
-                       my = 1 + MinimapY + Map2MinimapY[(*table)->Y];
-                       w = Map2MinimapX[type->TileWidth];
-                       if (mx + w >= TheUI.MinimapW) {         // clip right 
side
-                               w = TheUI.MinimapW - mx;
-                       }
-                       h0 = Map2MinimapY[type->TileHeight];
-                       if (my + h0 >= TheUI.MinimapH) {                // clip 
bottom side
-                               h0 = TheUI.MinimapH - my;
-                       }
-                       while (w-- >= 0) {
-                               h = h0;
-                               while (h-- >= 0) {
-                                       MinimapGraphic[mx + w + (my + h) * 
TheUI.MinimapW] = color;
-                               }
-                       }
-               }
-               table = &(*table)->Next;
-       }
-
        for (table = Units; table < Units + NumUnits; ++table) {
                VMemType color;
 
                unit = *table;
 
-               if (unit->Removed) {                            // Removed, 
inside another building
-                       continue;
-               }
-               if (unit->Invisible) {                          // Can't be seen
+               //  This function is only called from here, but it's better to 
have all
+               //  UnitVisible functions in the same place (unit.c). Hopefully 
it will help 
+               //  reduce the confusion around them.
+               if (!UnitVisibleOnMinimap(unit)) {
                        continue;
                }
-               if (!(unit->Visible & (1 << ThisPlayer->Player))) {
-                       continue;                                               
// Cloaked unit not visible
-               }
-
-               if (!UnitKnownOnMap(unit) && !ReplayRevealMap) {
-                       continue;
-               }
-
-               // FIXME: submarine not visible
 
                type = unit->Type;
                //
Index: stratagus/src/network/network.c
diff -u stratagus/src/network/network.c:1.125 
stratagus/src/network/network.c:1.126
--- stratagus/src/network/network.c:1.125       Mon Dec 22 18:52:10 2003
+++ stratagus/src/network/network.c     Thu Jan 15 09:31:07 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: network.c,v 1.125 2003/12/22 07:52:10 wizzard Exp $
+//     $Id: network.c,v 1.126 2004/01/14 22:31:07 nobody_ Exp $
 
 //@{
 
@@ -749,7 +749,7 @@
                        // FIXME: not neccessary to send this packet multiple 
times!!!!
                        //              other side sends re-send until it gets 
an answer.
 
-                       DebugLevel2Fn("Resend for %lu got\n" _C_ n);
+                       DebugLevel3Fn("Resend for %lu got\n" _C_ n);
                        if (n != NetworkIn[n & 
0xFF][ThisPlayer->Player][0].Time) {
                                // Asking for a cycle we haven't gotten to yet, 
ignore for now
                                return;
Index: stratagus/src/stratagus/mainloop.c
diff -u stratagus/src/stratagus/mainloop.c:1.176 
stratagus/src/stratagus/mainloop.c:1.177
--- stratagus/src/stratagus/mainloop.c:1.176    Fri Jan  9 16:44:40 2004
+++ stratagus/src/stratagus/mainloop.c  Thu Jan 15 09:31:08 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: mainloop.c,v 1.176 2004/01/09 05:44:40 jsalmon3 Exp $
+//     $Id: mainloop.c,v 1.177 2004/01/14 22:31:08 nobody_ Exp $
 
 //@{
 
@@ -399,7 +399,7 @@
                CurrentViewport = vp;
                while (i < nunits && j < nmissiles) {
                        if (table[i]->Type->DrawLevel <= 
missiletable[j]->Type->DrawLevel) {
-                               if (UnitVisibleInViewport(vp, table[i])) {
+                               if (UnitVisibleInViewport(table[i], vp)) {
                                        DrawUnit(table[i]);
                                }
                                ++i;
@@ -424,7 +424,7 @@
                        }
                }
                for (; i < nunits; ++i) {
-                       if (UnitVisibleInViewport(vp, table[i])) {
+                       if (UnitVisibleInViewport(table[i], vp)) {
                                DrawUnit(table[i]);
                        }
                }
@@ -804,7 +804,6 @@
                                        CclGarbageCollect(1);
                                        break;
                                case 1:
-                                       HandleCloak();
                                        break;
                                case 2:
                                        break;
Index: stratagus/src/stratagus/selection.c
diff -u stratagus/src/stratagus/selection.c:1.65 
stratagus/src/stratagus/selection.c:1.66
--- stratagus/src/stratagus/selection.c:1.65    Sat Jan  3 11:30:48 2004
+++ stratagus/src/stratagus/selection.c Thu Jan 15 09:31:08 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: selection.c,v 1.65 2004/01/03 00:30:48 jsalmon3 Exp $
+//     $Id: selection.c,v 1.66 2004/01/14 22:31:08 nobody_ Exp $
 
 //@{
 
@@ -677,12 +677,12 @@
        for (i = 0; i < r; ++i) {
                unit = table[i];
                // Unit visible FIXME: write function UnitSelectable
-               if (!UnitVisibleInViewport(TheUI.SelectedViewport, unit)) {
+               if (!UnitVisibleInViewport(unit, TheUI.SelectedViewport)) {
                        continue;
                }
                type = unit->Type;
                // Buildings are visible but not selectable
-               if (type->Building && !UnitVisibleOnMap(unit)) {
+               if (type->Building && !UnitVisibleOnMap(unit, ThisPlayer)) {
                        continue;
                }
                if ((type->GivesResource && !unit->Removed)) { // no built 
resources.
@@ -697,11 +697,11 @@
        for (i = 0; i < r; ++i) {
                unit = table[i];
                // Unit visible FIXME: write function UnitSelectable
-               if (!UnitVisibleInViewport(TheUI.SelectedViewport, unit)) {
+               if (!UnitVisibleInViewport(unit, TheUI.SelectedViewport)) {
                        continue;
                }
                // Buildings are visible but not selectable
-               if (unit->Type->Building && !UnitVisibleOnMap(unit)) {
+               if (unit->Type->Building && !UnitVisibleOnMap(unit, 
ThisPlayer)) {
                        continue;
                }
                if (!unit->Removed && unit->Orders[0].Action != UnitActionDie) {
@@ -978,7 +978,7 @@
        char* ref;
 
        CLprintf(file, "\n--- -----------------------------------------\n");
-       CLprintf(file, "--- MODULE: selection $Id: selection.c,v 1.65 
2004/01/03 00:30:48 jsalmon3 Exp $\n\n");
+       CLprintf(file, "--- MODULE: selection $Id: selection.c,v 1.66 
2004/01/14 22:31:08 nobody_ Exp $\n\n");
 
        CLprintf(file, "SetGroupId(%d)\n", GroupId);
        CLprintf(file, "Selection(%d, {", NumSelected);
Index: stratagus/src/stratagus/spells.c
diff -u stratagus/src/stratagus/spells.c:1.135 
stratagus/src/stratagus/spells.c:1.136
--- stratagus/src/stratagus/spells.c:1.135      Fri Jan  2 08:24:15 2004
+++ stratagus/src/stratagus/spells.c    Thu Jan 15 09:31:08 2004
@@ -27,7 +27,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: spells.c,v 1.135 2004/01/01 21:24:15 jsalmon3 Exp $
+//     $Id: spells.c,v 1.136 2004/01/14 22:31:08 nobody_ Exp $
 
 /*
 **             And when we cast our final spell
@@ -410,7 +410,9 @@
        missile->Delay = action->Data.SpawnMissile.Delay;
        missile->Damage = action->Data.SpawnMissile.Damage;
        missile->SourceUnit = caster;
-       missile->TargetUnit = target;
+       if ((missile->TargetUnit = target)) {
+               RefsIncrease(target);
+       }
        RefsIncrease(caster);
        return 1;
 }
@@ -615,8 +617,9 @@
 {
        int ttl;
        int cansummon;
-       Unit** corpses;
-       Unit* tempcorpse;
+       int n;
+       Unit* table[UnitMax];
+       Unit* unit;
        UnitType* unittype;
 
        DebugCheck(!caster);
@@ -628,26 +631,20 @@
        ttl = spell->Action->Data.Summon.TTL;
 
        if (spell->Action->Data.Summon.RequireCorpse) {
-               corpses = &CorpseList;
+               n = UnitCacheSelect(x - 1, y - 1, x + 2, y + 2, table);
                cansummon = 0;
-               while (*corpses) {
-                       // FIXME: this tries to raise all corps, I can raise 
ships?
-                       if ((*corpses)->Orders[0].Action == UnitActionDie &&
-                                       !(*corpses)->Type->Building &&
-                                       (*corpses)->X >= x - 1 && (*corpses)->X 
<= x + 1 &&
-                                       (*corpses)->Y >= y - 1 && (*corpses)->Y 
<= y + 1) {
+               while (n) {
+                       n--;
+                       unit = table[n];
+                       if (unit->Orders[0].Action == UnitActionDie && 
!unit->Type->Building) {
                                //
                                //  Found a corpse. eliminate it and proceed to 
summoning.
                                //
-                               x = (*corpses)->X;
-                               y = (*corpses)->Y;
-                               tempcorpse = *corpses;
-                               corpses = &(*corpses)->Next;
-                               ReleaseUnit(tempcorpse);
+                               x = unit->X;
+                               y = unit->Y;
+                               ReleaseUnit(unit);
                                cansummon = 1;
                                break;
-                       } else {
-                               corpses = &(*corpses)->Next;
                        }
                }
        } else {
Index: stratagus/src/ui/mainscr.c
diff -u stratagus/src/ui/mainscr.c:1.150 stratagus/src/ui/mainscr.c:1.151
--- stratagus/src/ui/mainscr.c:1.150    Fri Jan  9 16:44:42 2004
+++ stratagus/src/ui/mainscr.c  Thu Jan 15 09:31:09 2004
@@ -27,7 +27,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: mainscr.c,v 1.150 2004/01/09 05:44:42 jsalmon3 Exp $
+//     $Id: mainscr.c,v 1.151 2004/01/14 22:31:09 nobody_ Exp $
 
 //@{
 
@@ -1165,7 +1165,7 @@
        //              Nothing selected
 
        DrawInfoPanelBackground(0);
-       if (UnitUnderCursor && UnitVisibleOnMap(UnitUnderCursor)  &&
+       if (UnitUnderCursor && UnitVisible(UnitUnderCursor, ThisPlayer)  &&
                (UnitUnderCursor->Type->Selectable || !GameRunning)) {
                        // FIXME: not correct for enemies units
                        DrawUnitInfo(UnitUnderCursor);
Index: stratagus/src/ui/mouse.c
diff -u stratagus/src/ui/mouse.c:1.167 stratagus/src/ui/mouse.c:1.168
--- stratagus/src/ui/mouse.c:1.167      Fri Jan  9 16:44:45 2004
+++ stratagus/src/ui/mouse.c    Thu Jan 15 09:31:09 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: mouse.c,v 1.167 2004/01/09 05:44:45 jsalmon3 Exp $
+//     $Id: mouse.c,v 1.168 2004/01/14 22:31:09 nobody_ Exp $
 
 //@{
 
@@ -754,7 +754,7 @@
        //NOTE: vladi: if unit is invisible, no cursor hint should be allowed
        // FIXME: johns: not corrrect? Should I get informations about
        // buildings under fog of war?
-       if (UnitUnderCursor && !UnitVisibleOnMap(UnitUnderCursor) &&
+       if (UnitUnderCursor && !UnitVisibleAsGoal(UnitUnderCursor, ThisPlayer) 
&&
                        !ReplayRevealMap) {
                UnitUnderCursor = NULL;
        }
@@ -793,7 +793,7 @@
                //
                //              Map
                //
-               if (UnitUnderCursor && (UnitVisibleOnMap(UnitUnderCursor) ||
+               if (UnitUnderCursor && (UnitVisible(UnitUnderCursor, 
ThisPlayer) ||
                                ReplayRevealMap)) {
                        if (NumSelected == 0) {
                                MustRedraw |= RedrawInfoPanel;
Index: stratagus/src/unit/ccl_unit.c
diff -u stratagus/src/unit/ccl_unit.c:1.91 stratagus/src/unit/ccl_unit.c:1.92
--- stratagus/src/unit/ccl_unit.c:1.91  Sun Jan  4 09:31:51 2004
+++ stratagus/src/unit/ccl_unit.c       Thu Jan 15 09:31:10 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: ccl_unit.c,v 1.91 2004/01/03 22:31:51 jsalmon3 Exp $
+//      $Id: ccl_unit.c,v 1.92 2004/01/14 22:31:10 nobody_ Exp $
 
 //@{
 
@@ -678,7 +678,7 @@
                        DebugCheck(!type);
                        unit = UnitSlots[slot];
                        InitUnit(unit, type);
-                       unit->SeenType = seentype;
+                       unit->Seen.Type = seentype;
                        unit->Active = 0;
                        unit->Removed = 0;
                        unit->Reset = 0;                                // 
JOHNS ????
@@ -740,21 +740,21 @@
                                lua_error(l);
                        }
                        lua_rawgeti(l, j + 1, 1);
-                       unit->SeenIX = LuaToNumber(l, -1);
+                       unit->Seen.IX = LuaToNumber(l, -1);
                        lua_pop(l, 1);
                        lua_rawgeti(l, j + 1, 2);
-                       unit->SeenIY = LuaToNumber(l, -1);
+                       unit->Seen.IY = LuaToNumber(l, -1);
                        lua_pop(l, 1);
                } else if (!strcmp(value, "frame")) {
                        unit->Frame = LuaToNumber(l, j + 1);
                } else if (!strcmp(value, "flipped-frame")) {
                        unit->Frame = -LuaToNumber(l, j + 1);
                } else if (!strcmp(value, "seen")) {
-                       unit->SeenFrame = LuaToNumber(l, j + 1);
+                       unit->Seen.Frame = LuaToNumber(l, j + 1);
                } else if (!strcmp(value, "flipped-seen")) {
-                       unit->SeenFrame = -LuaToNumber(l, j + 1);
+                       unit->Seen.Frame = -LuaToNumber(l, j + 1);
                } else if (!strcmp(value, "not-seen")) {
-                       unit->SeenFrame = UnitNotSeen;
+                       unit->Seen.Frame = UnitNotSeen;
                        --j;
                } else if (!strcmp(value, "direction")) {
                        unit->Direction = LuaToNumber(l, j + 1);
@@ -767,9 +767,6 @@
                } else if (!strcmp(value, "destroyed")) {
                        unit->Destroyed = 1;
                        --j;
-               } else if (!strcmp(value, "seen-destroyed")) {
-                       unit->SeenDestroyed = 1;
-                       --j;
                } else if (!strcmp(value, "removed")) {
                        unit->Removed = 1;
                        --j;
@@ -778,23 +775,34 @@
                        --j;
                } else if (!strcmp(value, "rescued-from")) {
                        unit->RescuedFrom = &Players[(int)LuaToNumber(l, j + 
1)];
-               } else if (!strcmp(value, "visible")) {
+               } else if (!strcmp(value, "seen-by-player")) {
+                       s = LuaToString(l, j + 1);
+                       unit->Seen.ByPlayer = 0;
+                       for (i = 0; i < PlayerMax && *s; ++i, ++s) {
+                               if (*s == '-' || *s == '_' || *s == ' ') {
+                                       unit->Seen.ByPlayer &= ~(1 << i);
+                               } else {
+                                       unit->Seen.ByPlayer |= (1 << i);
+                               }
+                       }
+               } else if (!strcmp(value, "seen-destroyed")) {
                        s = LuaToString(l, j + 1);
+                       unit->Seen.Destroyed = 0;
                        for (i = 0; i < PlayerMax && *s; ++i, ++s) {
                                if (*s == '-' || *s == '_' || *s == ' ') {
-                                       unit->Visible &= ~(1 << i);
+                                       unit->Seen.Destroyed &= ~(1 << i);
                                } else {
-                                       unit->Visible |= (1 << i);
+                                       unit->Seen.Destroyed |= (1 << i);
                                }
                        }
                } else if (!strcmp(value, "constructed")) {
                        unit->Constructed = 1;
                        --j;
                } else if (!strcmp(value, "seen-constructed")) {
-                       unit->SeenConstructed = 1;
+                       unit->Seen.Constructed = 1;
                        --j;
                } else if (!strcmp(value, "seen-state")) {
-                       unit->SeenState = LuaToNumber(l, j + 1);
+                       unit->Seen.State = LuaToNumber(l, j + 1);
                } else if (!strcmp(value, "active")) {
                        unit->Active = 1;
                        --j;
@@ -887,19 +895,6 @@
                                // HACK: the building is not ready yet
                                unit->Player->UnitTypesCount[type->Type]--;
                        }
-                       // FIXME: (mr-russ) Does not load CorpseList Properly
-                       if (unit->Type->Building &&
-                                       (unit->Orders[0].Action == 
UnitActionDie || unit->Destroyed)) {
-                               DeadBuildingCacheInsert(unit);
-                       } else if (unit->Orders[0].Action == UnitActionDie) {
-                               CorpseCacheInsert(unit);
-                       }
-#if 0
-                       if (unit->Orders[0].Action == UnitActionDie &&
-                                       unit->Type->CorpseScript) {
-                               MapMarkUnitSight(unit);
-                       }
-#endif
                } else if (!strcmp(value, "saved-order")) {
                        lua_pushvalue(l, j + 1);
                        CclParseOrder(l, &unit->SavedOrder);
Index: stratagus/src/unit/unit.c
diff -u stratagus/src/unit/unit.c:1.355 stratagus/src/unit/unit.c:1.356
--- stratagus/src/unit/unit.c:1.355     Sun Jan  4 09:31:51 2004
+++ stratagus/src/unit/unit.c   Thu Jan 15 09:31:10 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: unit.c,v 1.355 2004/01/03 22:31:51 jsalmon3 Exp $
+//      $Id: unit.c,v 1.356 2004/01/14 22:31:10 nobody_ Exp $
 
 //@{
 
@@ -76,8 +76,6 @@
 
 global Unit* Units[MAX_UNIT_SLOTS];            /// Array of used slots
 global int NumUnits;                                           /// Number of 
slots used
-global Unit* DestroyedBuildings;               /// List of DestroyedBuildings
-global Unit* CorpseList;                               /// List of Corpses On 
Map
 
 global int XpDamage;                                           /// Hit point 
regeneration for all units
 global char EnableTrainingQueue;               /// Config: training queues 
enabled
@@ -111,8 +109,6 @@
 
        ReleasedTail = &ReleasedHead;                           // list of 
unfreed units.
        NumUnits = 0;
-       DestroyedBuildings = NULL;
-       CorpseList = NULL;
 }
 
 #if 0
@@ -187,6 +183,7 @@
        //
        if (!unit->Destroyed) {
                Unit* temp;
+               DebugLevel0Fn("First release %d\n" _C_ unit->Slot);
 
                //
                //              Remove the unit from the global units table.
@@ -201,54 +198,13 @@
                //
                unit->Destroyed = 1;                            // mark as 
destroyed
 
-               // Mark building as can't be destroyed, since it's still seen
-               if (unit->Type->Building) {
-                       int i;
-                       int x;
-                       int y;
-                       int w;
-                       int w0;
-                       int h;
-
-                       // Mark the Destroyed building, with who has seen it 
destroyed.
-                       x = unit->X;
-                       y = unit->Y;
-                       unit->Visible = 0x0000;
-                       for (i = 0; i < PlayerMax; ++i) {
-                               w = w0 = unit->Type->TileWidth;
-                               h = unit->Type->TileHeight;
-                               for (; h-- > 0;) {
-                                       for (w = w0; w-- > 0;) {
-                                               if 
(!IsMapFieldVisible(&Players[i], x + w, y + h) &&
-                                                               
IsMapFieldExplored(&Players[i], x + w, y + h) &&
-                                                               Players[i].Type 
== PlayerPerson) {
-                                                       unit->Visible |= (1 << 
i);
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               if (unit->Type->Building && unit->Visible != 0x0000) {
-                       return;
-               }
-               RefsDebugCheck(!unit->Refs);
-               if (--unit->Refs > 0) {
-                       DebugLevel2Fn("%lu:More references of %d #%d\n" _C_ 
GameCycle _C_
-                               UnitNumber(unit) _C_ unit->Refs);
-                       return;
-               }
 #ifdef HIERARCHIC_PATHFINDER
                PfHierReleaseData(unit);
 #endif
-       }
-
-       // Update Corpse Cache
-       if (unit->Orders[0].Action == UnitActionDie) {
-               if (unit->Type->Building) {
-                       DeadBuildingCacheRemove(unit);
-               } else {
-                       CorpseCacheRemove(unit);
+               if (--unit->Refs > 0) {
+                       DebugLevel2Fn("%lu:More references of %d #%d\n" _C_ 
GameCycle _C_
+                       UnitNumber(unit) _C_ unit->Refs);
+                       return;
                }
        }
 
@@ -260,14 +216,15 @@
        //              memory.
        //
        *ReleasedTail = unit;
-       unit->Next = NULL;                              // Ensure unit does not 
refer to another.
+       if (!EditorRunning) {
+               UnitCacheRemove(unit);
+       }
+       unit->Next = 0;
        ReleasedTail = &unit->Next;
        unit->Refs = GameCycle + NetworkMaxLag;         // could be reuse after 
this time
-#ifdef DEBUG
-       DebugLevel2Fn("%lu:No more references %d\n" _C_
+       DebugLevel2Fn("%lu:No more references, only wait for network lag, unit 
%d\n" _C_
                GameCycle _C_ UnitNumber(unit));
-       // unit->Type = NULL;                                           // for 
debugging.
-#endif
+       unit->Type = NULL;                                              // for 
debugging.
 }
 
 /**
@@ -343,7 +300,7 @@
        //  Initialise unit structure (must be zero filled!)
        //
        unit->Type = type;
-       unit->SeenFrame = UnitNotSeen;                          // Unit isn't 
yet seen
+       unit->Seen.Frame = UnitNotSeen;                         // Unit isn't 
yet seen
 
        unit->Frame = unit->Type->Animations->Still[0].Frame +
                (type->Building ? 0 : type->NumDirections / 2 + 1 - 1);
@@ -362,11 +319,6 @@
        unit->Reset = 1;
        unit->Removed = 1;
 
-       // Invisible as default for submarines
-       if (!type->PermanentCloak) {
-               unit->Visible = -1;                             // Visible as 
default
-       }
-
        unit->Rs = MyRand() % 100;                              // used for 
fancy buildings and others
 
        unit->OrderCount = 1;                           // No orders
@@ -521,18 +473,15 @@
                }
                unit->CurrentSightRange = unit->Stats->SightRange;
                MapMarkUnitSight(unit);
-
-               if (type->DetectCloak) {
-                       MapDetectCloakedUnits(unit);
-               }
        }
 
        unit->Removed = 0;
+       unit->Next = 0;
        UnitCacheInsert(unit);
 
        MustRedraw |= RedrawMinimap;
        CheckUnitToBeDrawn(unit);
-       UnitMarkSeen(unit);
+       UnitCountSeen(unit);
 }
 
 /**
@@ -567,7 +516,7 @@
 }
 
 /**
-**             Add unit to a container. It only updates linked list stuff
+**             Add unit to a container. It only updates linked list stuff
 **
 **             @param unit             Pointer to unit.
 **             @param host             Pointer to container.
@@ -592,7 +541,7 @@
 }
 
 /**
-**             Remove unit from a container. It only updates linked list stuff
+**             Remove unit from a container. It only updates linked list stuff
 **
 **             @param unit             Pointer to unit.
 */
@@ -704,9 +653,11 @@
 #endif
 
        DebugLevel3Fn("%d %p %p\n" _C_ UnitNumber(unit) _C_ unit _C_ 
unit->Next);
-       UnitCacheRemove(unit);
-       // UnitCache uses Next, need to set next again
-       unit->Next = host;
+
+       if (host) {
+               UnitCacheRemove(unit);
+               unit->Next = host;
+       }
 
        MustRedraw |= RedrawMinimap;
        CheckUnitToBeDrawn(unit);
@@ -942,299 +893,416 @@
 }
 
 /**
-**             Returns true, if unit is visible for this player on the map.
-**             An unit is visible, if any field could be seen.
-**
-**             @warning                This is only true for ::ThisPlayer.
+**             Copy the unit look in Seen variables. This should be called when
+**             buildings go under fog of war for ThisPlayer.
 **
-**             @param unit             Unit to be checked.
-**             @return                         True if visible, false 
otherwise.
+**      @param unit            The unit to work on
 */
-global int UnitVisibleOnMap(const Unit* unit)
+local void UnitFillSeenValues(Unit* unit)
 {
-       int x;
-       int y;
-       int w;
-       int w0;
-       int h;
-
-       DebugCheck(!unit->Type);
-
-       //
-       //              Unit invisible (by spell), removed or submarine.
-       //
-       if (unit->Invisible || unit->Removed ||
-                       !(unit->Visible & (1 << ThisPlayer->Player))) {
-               return 0;
+       //      Seen values are undefined for visible units.
+       unit->Seen.IY = unit->IY;
+       unit->Seen.IX = unit->IX;
+       unit->Seen.Frame = unit->Frame;
+       unit->Seen.State = (unit->Orders[0].Action == UnitActionBuilded) |
+                       ((unit->Orders[0].Action == UnitActionUpgradeTo) << 1);
+       if (unit->Orders[0].Action == UnitActionDie) {
+               unit->Seen.State = 3;
        }
+       unit->Seen.Type = unit->Type;
+       unit->Seen.Constructed = unit->Constructed;
+       unit->Seen.CFrame = unit->Data.Builded.Frame;
+}
 
-       x = unit->X;
-       y = unit->Y;
-       w = w0 = unit->Type->TileWidth;
-       h = unit->Type->TileHeight;
-
-       //
-       //              Check if visible, not under fog of war.
-       //
-       for (; h-- > 0;) {
-               for (w = w0; w-- > 0;) {
-                       if (IsMapFieldVisible(ThisPlayer, x + w, y + h)) {
-                               return 1;
-                       }
+/**
+**     This function should get called when an unit goes under fog of war.
+**
+**     @param unit     The unit that goes under fog.
+**     @param p        The player the unit goes out of fog for.
+*/
+local void UnitGoesUnderFog(Unit* unit, const Player* player)
+{
+       DebugLevel3Fn("Unit %d(%s) at %d %d goes under fog for %d\n" _C_
+                       unit->Slot _C_ unit->Type->Name _C_ unit->X _C_ unit->Y 
_C_ player->Player);
+       if (unit->Type->VisibleUnderFog) {
+               if (player->Type == PlayerPerson && !unit->Destroyed) {
+                       DebugLevel3Fn("unit %d(%s): got a ref from player %d\n" 
_C_
+                                       unit->Slot _C_ unit->Type->Name _C_ p);
+                       RefsIncrease(unit);
+               }
+               //
+               //      Icky yucky icky Seen.Destroyed trickery.
+               //      We track for each player if he's seen the unit as 
destroyed.
+               //      Remember, an unit is marked Destroyed when it's gone as 
in
+               //      completely gone, the corpses vanishes. In that case the 
unit
+               //      only survives since some players did NOT see the unit 
destroyed.
+               //      Keeping trackof that is hard, mostly due to complex 
shared vision
+               //      configurations.
+               //      A unit does NOT get a reference when it goes under fog 
if it's
+               //      Destroyed. Furthermore, it shouldn't lose a reference 
if it was
+               //      Seen destroyed. That only happend with complex shared 
vision, and
+               //      it's sort of the whole point of this tracking.
+               //
+               if (unit->Destroyed) {
+                       unit->Seen.Destroyed |= (1 << player->Player);
+               }
+               if (player == ThisPlayer) {
+                       UnitFillSeenValues(unit);
                }
        }
-       return 0;
 }
 
 /**
-**             Returns true, if unit is visible for this player on the map.
-**             An unit is visible, if any field could be seen.
+**     This function should get called when an unit goes out of fog of war.
 **
-**             @warning                This is only true for ::ThisPlayer.
+**     @param unit     The unit that goes out of fog.
+**     @param p        The player the unit goes out of fog for.
 **
-**             @param unit             Unit to be checked.
-**             @return                         True if visible, false 
otherwise.
+**     @note For units that are visible under fog (mostly buildings)
+**     we use reference counts, from the players that know about
+**     the building. When an building goes under fog it gets a refs
+**     increase, and when it shows up it gets a decrease. It must
+**     not get an decrease the first time it's seen, so we have to
+**     keep track of what player saw what units, with SeenByPlayer.
 */
-global int BuildingVisibleOnMap(const Unit* unit)
+local void UnitGoesOutOfFog(Unit* unit, const Player* player)
 {
-       int x;
-       int y;
-       int w;
-       int w0;
-       int h;
-
-       DebugCheck(!unit->Type);                // FIXME: Can this happen, if 
yes it is a bug
-
-       x = unit->X;
-       y = unit->Y;
-       w = w0 = unit->Type->TileWidth;
-       h = unit->Type->TileHeight;
-
-       //
-       //              Check if visible, not under fog of war.
-       //
-       for (; h-- > 0;) {
-               for (w = w0; w-- > 0;) {
-                       if (IsMapFieldVisible(ThisPlayer, x + w, y + h)) {
-                               return 1;
+       DebugLevel3Fn("Unit %d(%s) at %d %d goes out of fog for %d.\n" _C_
+                       unit->Slot _C_ unit->Type->Name _C_ unit->X _C_ unit->Y 
_C_ player->Player);
+       if (unit->Type->VisibleUnderFog) {
+               if (unit->Seen.ByPlayer & (1 << (player->Player))) {
+                       if ((player->Type == PlayerPerson) &&
+                                       (!(   unit->Seen.Destroyed & (1 << 
player->Player)   )) ) {
+                               DebugLevel3Fn("unit %d(%s): cleaned a ref from 
player %d\n" _C_
+                                               unit->Slot _C_ unit->Type->Name 
_C_ player->Player);
+                               RefsDecrease(unit);
                        }
+               } else {
+                       DebugLevel3Fn("Player %d discovers unit %d(%s) at %d 
%d.\n" _C_ player->Player _C_
+                                       unit->Slot _C_ unit->Type->Name _C_ 
unit->X _C_ unit->Y);
+                       unit->Seen.ByPlayer |= (1 << (player->Player));
                }
        }
-       return 0;
 }
 
 /**
-**             FIXME: docu
+**             Mark all units on a tile as now visible.
 **
-**             @param x                x location to check if building is on, 
and mark as seen
-**             @param y                y location to check if building is on, 
and mark as seen
+**             @param p                The player this is for.
+**             @param x                x location to check
+**             @param y                y location to check
+**             @param clock    If we mark cloaked units too.
 */
-global void UnitsMarkSeen(int x, int y)
+global void UnitsOnTileMarkSeen(const Player* player, int x, int y, int cloak)
 {
+       int p;
        int n;
        Unit* units[UnitMax];
        Unit* unit;
 
-       if (IsMapFieldVisible(ThisPlayer, x, y)) {
-               n = SelectUnitsOnTile(x, y,units);
-               DebugLevel3Fn("I can see %d units from here.\n" _C_ n);
-               // FIXME: need to handle Dead buldings
-               while (n) {
-                       unit = units[n - 1];
-                       if (unit->SeenFrame == UnitNotSeen) {
-                               DebugLevel3Fn("unit %d at %d,%d first seen at 
%lu.\n" _C_
-                                       unit->Slot _C_ unit->X _C_ unit->Y _C_ 
GameCycle);
-                       }
-                       unit->SeenIY = unit->IY;
-                       unit->SeenIX = unit->IX;
-                       unit->SeenFrame = unit->Frame;
-                       unit->SeenState = (unit->Orders[0].Action == 
UnitActionBuilded) |
-                               ((unit->Orders[0].Action == 
UnitActionUpgradeTo) << 1);
-                       if (unit->Orders[0].Action == UnitActionDie) {
-                               unit->SeenState = 3;
-                       }
-                       if (unit->SeenState == 2) {
-                               unit->SeenType = unit->Orders[0].Type;
-                       } else {
-                               unit->SeenType = unit->Type;
+       n = SelectUnitsOnTile(x, y,units);
+       DebugLevel3Fn("I can see %d units from here.\n" _C_ n);
+       while (n) {
+               unit = units[--n];
+               if (cloak != (int)unit->Type->PermanentCloak) {
+                       continue;
+               }
+               DebugLevel3("Unit %d(%d, %d) player %d seen %d -> %d (%d, 
%d)\n" _C_ unit->Slot _C_ unit->X _C_ unit->Y _C_
+                               player->Player _C_ 
unit->VisCount[player->Player] _C_ unit->VisCount[player->Player] + 1 _C_ x _C_ 
y);
+               //
+               //  If the unit goes out of fog, this can happen for any player 
that
+               //  this player shares vision with, and can't YET see the unit.
+               //  It will be able to see the unit after the Unit->VisCount ++
+               //
+               for (p = 0; p < PlayerMax; ++p) {
+                       if (PlayersShareVision(player->Player, p) || (p == 
player->Player)) {
+                               if (!UnitVisible(unit, Players + p)) {
+                                       UnitGoesOutOfFog(unit, Players + p);
+                               }
                        }
-                       unit->SeenConstructed = unit->Constructed;
-                       unit->SeenDestroyed = unit->Destroyed;
-                       --n;
                }
+               unit->VisCount[player->Player]++;
        }
 }
 
 /**
-**             FIXME: docu
+**     This function unmarks units on x, y as seen. It uses a reference count.
 **
-**             @param unit             pointer to the unit to check if seen
+**     @param player   The player to mark for.
+**     @param x        x location to check if building is on, and mark as seen
+**     @param y        y location to check if building is on, and mark as seen
+**     @param cloak    If this is for cloaked units.
 */
-global void UnitMarkSeen(Unit* unit)
+global void UnitsOnTileUnmarkSeen(const Player* player, int x, int y, int 
cloak)
 {
-       int x;
-       int y;
+       int p;
+       int n;
+       Unit* units[UnitMax];
+       Unit* unit;
 
-       // Update Building Seen
-       if (!unit->Type) {
-               DebugLevel0Fn("UnitMarkSeen: Type is NULL\n");
-               return;
-       }
-       for (x = 0; x < unit->Type->TileWidth; ++x) {
-               for (y = 0; y < unit->Type->TileHeight; ++y) {
-                       if (IsMapFieldVisible(ThisPlayer, unit->X + x, unit->Y 
+ y)) {
-                               unit->SeenIY = unit->IY;
-                               unit->SeenIX = unit->IX;
-                               if (unit->SeenFrame == UnitNotSeen) {
-                                       DebugLevel3Fn("unit %d at %d,%d first 
seen at %lu.\n" _C_
-                                               unit->Slot _C_ unit->X _C_ 
unit->Y _C_ GameCycle);
-                               }
-                               unit->SeenFrame = unit->Frame;
-                               unit->SeenState = (unit->Orders[0].Action == 
UnitActionBuilded) |
-                                       ((unit->Orders[0].Action == 
UnitActionUpgradeTo) << 1);
-                               if (unit->Orders[0].Action == UnitActionDie) {
-                                       unit->SeenState = 3;
-                               }
-                               if (unit->SeenState == 2) {
-                                       unit->SeenType = unit->Orders[0].Type;
-                               } else {
-                                       unit->SeenType = unit->Type;
+       n = SelectUnitsOnTile(x, y, units);
+       DebugLevel3Fn("I can see %d units from here.\n" _C_ n);
+       while (n) {
+               unit = units[--n];
+               if ((unit->X > x || unit->X + unit->Type->TileWidth - 1 < x ||
+                               unit->Y > y || unit->Y + unit->Type->TileHeight 
- 1 < y)) {
+                       DebugLevel0Fn("Wrong cache %d %d -> %d %d\n" _C_ x _C_ 
y _C_ unit->X _C_ unit->Y);
+               }
+               DebugCheck((unit->X > x || unit->X + unit->Type->TileWidth - 1 
< x ||
+                               unit->Y > y || unit->Y + unit->Type->TileHeight 
- 1 < y));
+               if (cloak != (int)unit->Type->PermanentCloak) {
+                       continue;
+               }
+               p = player->Player;
+               DebugLevel3("Unit %d(%d, %d) player %d seen %d -> %d (%d, 
%d)\n" _C_ unit->Slot _C_ unit->X _C_ unit->Y _C_
+                               p _C_ unit->VisCount[p] _C_ unit->VisCount[p] - 
1 _C_ x _C_ y);
+               DebugCheck(!unit->VisCount[p]);
+               unit->VisCount[p]--;
+               //
+               //  If the unit goes under of fog, this can happen for any 
player that
+               //  this player shares vision to. First of all, before 
unmarking,
+               //  every player that this player shares vision to can see the 
unit.
+               //  Now we have to check who can't see the unit anymore.
+               //
+               if (!unit->VisCount[p]) {
+                       for (p = 0; p < PlayerMax; ++p) {
+                               if (PlayersShareVision(player->Player, p) || p 
== player->Player) {
+                                       if (!UnitVisible(unit, Players + p)) {
+                                               UnitGoesUnderFog(unit, Players 
+ p);
+                                       }
                                }
-                               unit->SeenConstructed = unit->Constructed;
-                               unit->SeenDestroyed = unit->Destroyed;
-                               x = unit->Type->TileWidth;
-                               y = unit->Type->TileHeight;
-                               //  If we found one visible square, END.
-                               break;
                        }
                }
        }
 }
 
 /**
-**             Returns true, if unit is known on the map. Special case for 
buildings.
+**     Recalculates an units visiblity count. This happens really often,
+**     Like every time an unit moves. It's really fast though, since we
+**     have per-tile counts.
 **
-**             @param unit             Unit to be checked.
-**             @return                         True if known, false otherwise.
+**     @param unit     pointer to the unit to check if seen
 */
-global int UnitKnownOnMap(const Unit* unit)
+global void UnitCountSeen(Unit* unit)
 {
        int x;
        int y;
-       int w;
-       int w0;
-       int h;
+       int p;
+       int oldv[PlayerMax];
+       int newv;
 
        DebugCheck(!unit->Type);
 
-       if (unit->Player != ThisPlayer) {
-               //FIXME: vladi: should handle teams and shared vision
-               // Invisible by spell
-               if (unit->Invisible) {
-                       return 0;
+       //      FIXME: optimize, only work on certain players?
+       //      This is for instance good for updating shared vision...
+
+       //
+       //  Store old values in oldv[p]. This store if the player could see the 
+       //  unit before this calc.
+       // 
+       for (p = 0; p < PlayerMax; ++p) {
+               if (Players[p].Type != PlayerNobody) {
+                       oldv[p] = UnitVisible(unit, &Players[p]);
                }
-               // Visible submarine
-               if (!(unit->Visible & (1 << ThisPlayer->Player))) {
-                       return 0;
+       }
+
+       //  Calculate new VisCount values.
+       for (p = 0; p < PlayerMax; ++p) {
+               if (Players[p].Type != PlayerNobody) {
+                       newv = 0;
+                       for (x = 0; x < unit->Type->TileWidth; ++x) {
+                               for (y = 0; y < unit->Type->TileHeight; ++y) {
+                                       if (unit->Type->PermanentCloak) {
+                                               if (TheMap.Fields[(unit->Y + y) 
* TheMap.Width + unit->X + x].VisCloak[p]) {
+                                                       newv++;
+                                               }
+                                       } else {
+                                               //  Icky ugly code trick. With 
NoFogOfWar we haveto be > 0;
+                                               if (TheMap.Fields[(unit->Y + y) 
* TheMap.Width + unit->X + x].Visible[p] > 1 - TheMap.NoFogOfWar) {
+                                                       newv++;
+                                               }
+                                       }
+                               }
+                       }
+                       unit->VisCount[p] = newv;
                }
        }
 
        //
-       //              Check if visible on screen.
-       //                              FIXME: This could be better checked, 
tells to much!
-       //                              FIXME: This is needed to show moving 
units.
-       //                              FIXME: flyers disappears to fast.
-       //
-       x = unit->X;
-       y = unit->Y;
-       w = w0 = unit->Type->TileWidth;
-       h = unit->Type->TileHeight;
-       //
-       //              Check explored or if visible (building) under fog of 
war.
-       //                              FIXME: need only check the boundary, 
not the complete rectangle.
+       //      Now here comes the tricky part. We have to go in and out of fog
+       //      for players. Hopefully this works with shared vision just great.
        //
-       for (; h-- > 0;) {
-               for (w = w0; w-- > 0;) {
-                       if (IsMapFieldVisible(ThisPlayer, x + w, y + h) ||
-                                       (unit->Type->Building && 
unit->SeenFrame != UnitNotSeen
-                                               && 
IsMapFieldExplored(ThisPlayer, x + w, y + h))) {
-                               return 1;
+       for (p = 0; p < PlayerMax; ++p) {
+               if (Players[p].Type != PlayerNobody) {
+                       newv = UnitVisible(unit, Players + p);
+                       if ((!oldv[p]) &&  (newv)) {
+                               UnitGoesOutOfFog(unit, Players + p);
+                       }
+                       if ( (oldv[p]) && (!newv)) {
+                               UnitGoesUnderFog(unit, Players + p);
                        }
                }
        }
+}
 
+/**
+**      Returns true, if the unit is visible. It check the Viscount of
+**             the player and everyone who shares vision with him.
+**             FIXME: optimize this a lot.
+**
+**             @note   This understands shared vision, and should be used all 
around.
+**
+**             @param unit                             The unit to check.
+**             @param player                   The player to check.
+*/
+global int UnitVisible(const Unit* unit, const Player* player)
+{
+       int p;
+       int cp;
+       //      Current player.
+       cp = player->Player;
+       if (unit->VisCount[cp]) {
+               return 1;
+       }
+       for (p = 0; p < PlayerMax; p++) {
+               if (PlayersShareVision(p, cp)) {
+                       if (unit->VisCount[p]) {
+                               return 1;
+                       }
+               }
+       }
        return 0;
 }
 
 /**
-**             Returns true, if unit is visible in viewport.
+**      Returns ture, if unit is visible as an action goal for a player
+**      on the map.
 **
-**             @param vp               Viewport number.
 **             @param unit             Unit to be checked.
-**             @return                         True if visible, false 
otherwise.
+**             @param player   Player to check for.
+**             @return                 True if visible, false otherwise.
 */
-global int UnitVisibleInViewport(const Viewport* vp, const Unit* unit)
+global int UnitVisibleAsGoal(const Unit* unit, const Player* player)
 {
-       int x;
-       int y;
-       int w;
-       int w0;
-       int h;
-
-       DebugCheck(!unit->Type);
+       //
+       //      Invisibility
+       //
+       if (unit->Invisible && (player != unit->Player) &&
+                       (!PlayersShareVision(player->Player, 
unit->Player->Player))) {
+               return 0;
+       }
+       if (UnitVisible(unit, player)) {
+               return  (!unit->Removed) &&
+                               (!unit->Destroyed) &&
+                               (unit->Orders->Action != UnitActionDie);
+       } else {
+               return unit->Type->VisibleUnderFog &&
+                       (unit->Seen.ByPlayer & (1 << player->Player)) &&
+                       !(unit->Seen.Destroyed & (1 << player->Player));
+       }
+}
 
-       if (!ThisPlayer) {
-               //FIXME: ARI: Added here for early game setup state by
-               //              MakeAndPlaceUnit() from LoadMap(). ThisPlayer 
not yet set,
-               //              so don't show anything until first real 
map-draw.
+/**
+**             Returns true, if unit is visible for this player on the map.
+**             The unit has to be out of fog of war and alive
+**
+**             @param unit             Unit to be checked.
+**             @param player   Player to check for.
+**             @return                 True if visible, false otherwise.
+*/
+global int UnitVisibleOnMap(const Unit* unit, const Player* player)
+{
+       //
+       //      Invisible units.
+       //
+       if (unit->Invisible && (player != unit->Player) &&
+                       (!PlayersShareVision(player->Player, 
unit->Player->Player))) {
                return 0;
        }
 
-       // FIXME: Need to be able to see enemy submarines seen by my shared 
vision
-       //                              partners
-       if (ThisPlayer != unit->Player &&
-                       !(unit->Player->SharedVision & (1 << 
ThisPlayer->Player) &&
-                               ThisPlayer->SharedVision & (1 << 
unit->Player->Player))) {
-               // Invisible by spell
-               if (unit->Invisible) {
-                       return 0;
-               }
-               // Visible submarine
-               if (!(unit->Visible & (1 << ThisPlayer->Player)) && 
!unit->Type->Building) {
+       return  (!unit->Removed) &&
+                       (!unit->Destroyed) &&
+                       (unit->HP) &&
+                       (unit->Orders->Action != UnitActionDie) &&
+                       (UnitVisible(unit, player));
+}
+
+/**
+**             Returns true, if unit is shown on minimap.
+**
+**             @warning This is for ::ThisPlayer only.
+**             @todo   radar support
+**
+**             @param unit             Unit to be checked.
+**             @return                 True if wisible, false otherwise.
+*/
+global int UnitVisibleOnMinimap(const Unit* unit)
+{
+       //
+       //      Invisible units.
+       //
+       if (unit->Invisible && (ThisPlayer != unit->Player) &&
+                       (!PlayersShareVision(ThisPlayer->Player, 
unit->Player->Player))) {
+               return 0;
+       }
+       if (UnitVisible(unit, ThisPlayer) || ReplayRevealMap) {
+               return  (!unit->Removed) &&
+                               (!unit->Destroyed) &&
+                               (unit->Orders->Action != UnitActionDie);
+       } else {
+               if (!unit->Type->VisibleUnderFog) {
                        return 0;
                }
+               return ((unit->Seen.ByPlayer & (1 << ThisPlayer->Player)) && 
+                               (!(unit->Seen.Destroyed & (1 << 
ThisPlayer->Player))) );
        }
+}
 
+/**
+**             Returns true, if unit is visible in viewport.
+**
+**             @warning This is only true for ::ThisPlayer
+**             @param vp                       Viewport pointer.
+**             @param unit                     Unit to be checked.
+**             @return                         True if visible, false 
otherwise.
+*/
+global int UnitVisibleInViewport(const Unit* unit, const Viewport* vp)
+{
        //
-       //              Check if visible on screen.
-       //                              FIXME: This could be better checked, 
tells to much!
-       //                              FIXME: This is needed to show moving 
units.
-       //                              FIXME: flyers disappears to fast.
+       //      Check if it's at least inside the damn viewport.
        //
-       x = unit->X;
-       y = unit->Y;
-       w = w0 = unit->Type->TileWidth;
-       h = unit->Type->TileHeight;
-       if ((x + w) < vp->MapX || x > (vp->MapX + vp->MapWidth) ||
-                       (y + h) < vp->MapY || y > (vp->MapY + vp->MapHeight)) {
+       if ((unit->X + unit->Type->TileWidth < vp->MapX) ||
+                       (unit->X > vp->MapX + vp->MapWidth) ||
+                       (unit->Y + unit->Type->TileHeight < vp->MapY) ||
+                       (unit->Y > vp->MapY + vp->MapHeight)) {
                return 0;
        }
 
-       //
-       //              Check explored or if visible (building) under fog of 
war.
-       //                              FIXME: need only check the boundary, 
not the complete rectangle.
-       //
-       for (; h-- > 0;) {
-               for (w = w0; w-- > 0;) {
-                       if (IsMapFieldVisible(ThisPlayer, x + w, y + h) || 
ReplayRevealMap ||
-                                       (unit->Type->VisibleUnderFog && 
unit->SeenFrame != UnitNotSeen &&
-                                               IsMapFieldExplored(ThisPlayer, 
x + w, y + h))) {
-                               return 1;
-                       }
-               }
+       if (!ThisPlayer) {
+               //FIXME: ARI: Added here for early game setup state by
+               //              MakeAndPlaceUnit() from LoadMap(). ThisPlayer 
not yet set,
+               //              so don't show anything until first real 
map-draw.
+               DebugLevel0Fn("Fix ME ThisPlayer not set yet?!\n");
+               return 0;
        }
 
-       return 0;
+       //      Those are never ever visible.
+       if (unit->Invisible && (ThisPlayer != unit->Player) &&
+                       (!PlayersShareVision(ThisPlayer->Player, 
unit->Player->Player))) {
+               return 0;
+       }
+
+       if (UnitVisible(unit, ThisPlayer) || ReplayRevealMap) {
+               return !unit->Destroyed;
+       } else {
+               //      Unit has to be 'discovered'
+               //      Destroyed units ARE visible under fog of war, if we 
haven't seen them like that.
+               if (!unit->Destroyed || !(unit->Seen.Destroyed & (1 << 
ThisPlayer->Player))) {
+                       return (unit->Type->VisibleUnderFog && 
(unit->Seen.ByPlayer & (1 << ThisPlayer->Player)));
+               } else {
+                       return 0;
+               }
+       }
 }
 
 /**
@@ -1248,7 +1316,7 @@
        const Viewport* vp;
 
        for (vp = TheUI.Viewports; vp < TheUI.Viewports + TheUI.NumViewports; 
++vp) {
-               if (UnitVisibleInViewport(vp, unit)) {
+               if (UnitVisibleInViewport(unit, vp)) {
                        DebugLevel3Fn("unit %d(%s) is visibile\n" _C_ 
unit->Slot _C_ unit->Type->Ident);
                        return 1;
                }
@@ -2317,7 +2385,7 @@
 **             @param range    Maximum distance to the resource.
 **             @param resource The resource id.
 **
-**             @note                           This will return an usable 
resource building that
+**             @note                           This will return an usable 
resource building that
 **                                             belongs to "player" or is 
neutral.
 **
 **             @return                         NoUnitP or resource unit
@@ -2538,7 +2606,7 @@
                                        continue;
                                }
                                //
-                               //              Look if there is a mine
+                               //              Look if there is a deposit
                                //
                                if ((depot = ResourceDepositOnMap(x, y, 
resource)) &&
                                                ((IsAllied(unit->Player, 
depot)) ||
@@ -2670,9 +2738,7 @@
        }
        for (table = Units; table < Units + NumUnits; ++table) {
                unit = *table;
-               // We don't use UnitUnusable() to be able to select
-               // a building under construction.
-               if (unit->Removed || unit->Orders[0].Action == UnitActionDie) {
+               if (!UnitVisibleAsGoal(unit, ThisPlayer)) {
                        continue;
                }
                type = unit->Type;
@@ -2794,22 +2860,11 @@
                                !unit->Type->Animations->Die);
                        UnitShowAnimation(unit, unit->Type->Animations->Die);
                        DebugLevel0Fn("Frame %d\n" _C_ unit->Frame);
-                       unit->Visible = 0xffff;
-                       DeadBuildingCacheInsert(unit);          //Insert into 
corpse list
-                       // FIXME: (mr-russ) Hack to make sure we see our own 
building destroyed
-                       MapMarkUnitSight(unit);
-                       UnitMarkSeen(unit);
-                       MapUnmarkUnitSight(unit);
-                       UnitMarkSeen(unit);
-                       return;
                }
-
                // no corpse available
                // FIXME: (mr-russ) Hack to make sure we see our own building 
destroyed
                MapMarkUnitSight(unit);
-               UnitMarkSeen(unit);
                MapUnmarkUnitSight(unit);
-               ReleaseUnit(unit);
                return;
        }
 
@@ -2832,7 +2887,6 @@
        unit->Reset = 0;
        unit->Wait = 1;
        unit->Orders[0].Action = UnitActionDie;
-       CorpseCacheInsert(unit);                //Insert into corpse list
 
        if (unit->Type->CorpseType) {
                unit->CurrentSightRange = 
unit->Type->CorpseType->Stats->SightRange;
@@ -2858,7 +2912,6 @@
                UnitClearOrders(unit);
                ReleaseUnit(unit);
        }
-
 }
 
 
@@ -2983,7 +3036,7 @@
                CommandStopUnit(attacker);              // Attacker shouldn't 
continue attack!
        }
 
-       if ((UnitVisibleOnMap(target) || ReplayRevealMap) && DamageMissile) {
+       if ((UnitVisibleOnMap(target, ThisPlayer) || ReplayRevealMap) && 
DamageMissile) {
                MakeLocalMissile(MissileTypeByIdent(DamageMissile),
                                target->X * TileSizeX + target->Type->TileWidth 
* TileSizeX / 2,
                                target->Y * TileSizeY + 
target->Type->TileHeight * TileSizeY / 2,
@@ -3451,8 +3504,8 @@
 
        // 'type and 'player must be first, needed to create the unit slot
        CLprintf(file, "\"type\", \"%s\", ", unit->Type->Ident);
-       if (unit->SeenType) {
-               CLprintf(file, "\"seen-type\", \"%s\", ", 
unit->SeenType->Ident);
+       if (unit->Seen.Type) {
+               CLprintf(file, "\"seen-type\", \"%s\", ", 
unit->Seen.Type->Ident);
        }
 
        CLprintf(file, "\"player\", %d,\n  ", unit->Player->Player);
@@ -3479,14 +3532,14 @@
        CLprintf(file, "\"stats\", %d,\n  ", unit->Player->Player);
 #endif
        CLprintf(file, "\"pixel\", {%d, %d}, ", unit->IX, unit->IY);
-       CLprintf(file, "\"seen-pixel\", {%d, %d}, ", unit->SeenIX, 
unit->SeenIY);
+       CLprintf(file, "\"seen-pixel\", {%d, %d}, ", unit->Seen.IX, 
unit->Seen.IY);
        CLprintf(file, "\"%sframe\", %d, ",
                unit->Frame < 0 ? "flipped-" : "",
                unit->Frame < 0 ? -unit->Frame : unit->Frame);
-       if (unit->SeenFrame != UnitNotSeen) {
+       if (unit->Seen.Frame != UnitNotSeen) {
                CLprintf(file, "\"%sseen\", %d, ",
-                       unit->SeenFrame < 0 ? "flipped-" : "",
-                       unit->SeenFrame < 0 ? -unit->SeenFrame : 
unit->SeenFrame);
+                       unit->Seen.Frame < 0 ? "flipped-" : "",
+                       unit->Seen.Frame < 0 ? -unit->Seen.Frame : 
unit->Seen.Frame);
        } else {
                CLprintf(file, "\"not-seen\", ");
        }
@@ -3499,9 +3552,6 @@
        if (unit->Destroyed) {
                CLprintf(file, " \"destroyed\",");
        }
-       if (unit->SeenDestroyed) {
-               CLprintf(file, " \"seen-destroyed\",");
-       }
        if (unit->Removed) {
                CLprintf(file, " \"removed\",");
        }
@@ -3521,18 +3571,23 @@
                        unit->Container->Type->TileWidth,
                        unit->Container->Type->TileHeight);
        }
-       CLprintf(file, " \"visible\", \"");
+       CLprintf(file, " \"seen-by-player\", \"");
+       for (i = 0; i < PlayerMax; ++i) {
+               CLprintf(file, "%c", (unit->Seen.ByPlayer & (1 << i)) ? 'X' : 
'_');
+       }
+       CLprintf(file, "\",\n ");
+       CLprintf(file, " \"seen-destroyed\", \"");
        for (i = 0; i < PlayerMax; ++i) {
-               CLprintf(file, "%c", (unit->Visible & (1 << i)) ? 'X' : '_');
+               CLprintf(file, "%c", (unit->Seen.Destroyed & (1 << i)) ? 'X' : 
'_');
        }
        CLprintf(file, "\",\n ");
        if (unit->Constructed) {
                CLprintf(file, " \"constructed\",");
        }
-       if (unit->SeenConstructed) {
+       if (unit->Seen.Constructed) {
                CLprintf(file, " \"seen-constructed\",");
        }
-       CLprintf(file, " \"seen-state\", %d, ", unit->SeenState);
+       CLprintf(file, " \"seen-state\", %d, ", unit->Seen.State);
        if (unit->Active) {
                CLprintf(file, " \"active\",");
        }
@@ -3702,7 +3757,7 @@
        int j;
 
        CLprintf(file, "\n--- -----------------------------------------\n");
-       CLprintf(file, "--- MODULE: units $Id: unit.c,v 1.355 2004/01/03 
22:31:51 jsalmon3 Exp $\n\n");
+       CLprintf(file, "--- MODULE: units $Id: unit.c,v 1.356 2004/01/14 
22:31:10 nobody_ Exp $\n\n");
 
 #if 0
        //
Index: stratagus/src/unit/unit_draw.c
diff -u stratagus/src/unit/unit_draw.c:1.203 
stratagus/src/unit/unit_draw.c:1.204
--- stratagus/src/unit/unit_draw.c:1.203        Thu Jan 15 04:50:05 2004
+++ stratagus/src/unit/unit_draw.c      Thu Jan 15 09:31:11 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//      $Id: unit_draw.c,v 1.203 2004/01/14 17:50:05 jsalmon3 Exp $
+//      $Id: unit_draw.c,v 1.204 2004/01/14 22:31:11 nobody_ Exp $
 
 //@{
 
@@ -744,7 +744,7 @@
 {
 #if 0
        CLprintf(file, "\n;;; -----------------------------------------\n");
-       CLprintf(file, ";;; MODULE: decorations $Id: unit_draw.c,v 1.203 
2004/01/14 17:50:05 jsalmon3 Exp $\n\n");
+       CLprintf(file, ";;; MODULE: decorations $Id: unit_draw.c,v 1.204 
2004/01/14 22:31:11 nobody_ Exp $\n\n");
 
        CLprintf(file, "(mana-sprite \"%s\"  %d %d  %d %d)\n",
                ManaSprite.File, ManaSprite.HotX, ManaSprite.HotY,
@@ -1744,6 +1744,15 @@
        const UnitStats* stats;
        int r;
 
+#if 0 // This is for showing vis counts and refs.
+       char buf[10];
+       sprintf(buf, "%d%c%c%d", unit->VisCount[ThisPlayer->Player],
+               unit->Seen.ByPlayer & (1 << ThisPlayer->Player) ? 'Y' : 'N',
+               unit->Seen.Destroyed & (1 << ThisPlayer->Player) ? 'Y' : 'N',
+               unit->Refs);
+       VideoDrawTextClip(x + 10, y + 10, 1, buf);
+#endif
+
        stats = unit->Stats;
 
        //
@@ -1980,40 +1989,30 @@
 **             @param x                X position.
 **             @param y                Y position.
 */
-local void DrawConstruction(const Unit* unit, int frame, int x, int y)
+local void DrawConstruction(const Unit* unit, const ConstructionFrame* cframe,
+               const UnitType* type, int frame, int x, int y)
 {
-       ConstructionFrame* cframe;
-
-       cframe = unit->Data.Builded.Frame;
        if (cframe->File == ConstructionFileConstruction) {
                const Construction* construction;
 
-               construction = unit->Type->Construction;
+               construction = type->Construction;
                x -= construction->Width / 2;
                y -= construction->Height / 2;
                GraphicUnitPixels(unit, construction->Sprite);
                VideoDrawClip(construction->Sprite, frame, x, y);
        } else {
-               x -= unit->Type->TileWidth * TileSizeX / 2;
-               y -= unit->Type->TileHeight * TileSizeY / 2;
-               GraphicUnitPixels(unit, unit->Type->Sprite);
-               DrawUnitType(unit->Type, unit->Type->Sprite, frame, x, y);
+               x -= type->TileWidth * TileSizeX / 2;
+               y -= type->TileHeight * TileSizeY / 2;
+               GraphicUnitPixels(unit, type->Sprite);
+               DrawUnitType(type, type->Sprite, frame, x, y);
 #ifdef USE_OPENGL
-               DrawUnitPlayerColor(unit->Type, unit->Player->Player, frame, x, 
y);
+               DrawUnitPlayerColor(type, unit->Player->Player, frame, x, y);
 #endif
        }
 }
 
 /**
 **             Units on map:
-**
-**             1) Must draw underground/underwater units. (FUTURE extension)
-**             2) Must draw buildings and corpse.
-**             3) Must draw land/sea units.
-**             4) Must draw decoration units. (FUTURE extension)
-**             5) Must draw low air units.
-**             6) Must draw middle air units. (FUTURE extension)
-**             7) Must draw hight air units. (FUTURE extension)
 */
 
 /**
@@ -2030,14 +2029,18 @@
        int constructed;
        Graphic* sprite;
        ResourceInfo* resinfo;
+       ConstructionFrame* cframe;
        const UnitType* type;
-
+       
        if (unit->Type->Revealer) {                             // Revealers 
are not drawn
                DebugLevel3Fn("Drawing revealer %d\n" _C_ UnitNumber(unit));
                return;
        }
 
-       if (ReplayRevealMap || !unit->Type->VisibleUnderFog) {
+       //  Those should have been filtered. Check doesn't make sense with 
ReplayRevealMap
+       DebugCheck((!ReplayRevealMap) && (!unit->Type->VisibleUnderFog) && 
(!UnitVisible(unit, ThisPlayer)));
+
+       if (ReplayRevealMap || UnitVisible(unit, ThisPlayer)) {
                type = unit->Type;
                frame = unit->Frame;
                y = unit->IY;
@@ -2045,16 +2048,19 @@
                state = (unit->Orders[0].Action == UnitActionBuilded) |
                        ((unit->Orders[0].Action == UnitActionUpgradeTo) << 1);
                constructed = unit->Constructed;
+               // This is trash unless the unit is being built, and that's 
when we use it.
+               cframe = unit->Data.Builded.Frame;
        } else {
-               y = unit->SeenIY;
-               x = unit->SeenIX;
-               frame = unit->SeenFrame;
-               type = unit->SeenType;
-               constructed = unit->SeenConstructed;
-               state = unit->SeenState;
+               y = unit->Seen.IY;
+               x = unit->Seen.IX;
+               frame = unit->Seen.Frame;
+               type = unit->Seen.Type;
+               constructed = unit->Seen.Constructed;
+               state = unit->Seen.State;
+               cframe = unit->Seen.CFrame;
        }
 
-       if (frame == UnitNotSeen) {
+       if ((!UnitVisible(unit, ThisPlayer)) && frame == UnitNotSeen) {
                DebugLevel0Fn("FIXME: Something is wrong, unit %d not seen but 
drawn time %lu?.\n" _C_
                        unit->Slot _C_ GameCycle);
                return;
@@ -2106,7 +2112,7 @@
        //
        if (state == 1) {
                if (constructed) {
-                       DrawConstruction(unit, frame,
+                       DrawConstruction(unit, cframe, type, frame,
                                x + (type->TileWidth * TileSizeX) / 2,
                                y + (type->TileHeight * TileSizeY) / 2);
                }
@@ -2175,7 +2181,6 @@
 */
 global int FindAndSortUnits(const Viewport* vp, Unit** table)
 {
-       Unit** corpses;
        int n;
 
        //
@@ -2184,30 +2189,6 @@
        n = SelectUnits(vp->MapX - 1, vp->MapY - 1, vp->MapX + vp->MapWidth + 1,
                vp->MapY + vp->MapHeight + 1, table);
 
-       //
-       //  Add Corpses to the list.
-       //
-       corpses = &CorpseList;
-       while (*corpses) {
-               if (UnitVisibleInViewport(vp,*corpses) && 
!(*corpses)->Destroyed) {
-                       table[n++] = *corpses;
-               }
-               corpses = &(*corpses)->Next;
-       }
-
-       //
-       //  Add Destroyed Buildings
-       //
-       corpses = &DestroyedBuildings;
-       while (*corpses) {
-               if (UnitVisibleInViewport(vp, *corpses) && 
!(*corpses)->SeenDestroyed &&
-                               (((*corpses)->Visible & 1 << 
ThisPlayer->Player) ||
-                                       !(*corpses)->Destroyed)) {
-                       table[n++] = *corpses;
-               }
-               corpses = &(*corpses)->Next;
-       }
-       // Only draw if there are units to draw :)
        if (n) {
                qsort((void *)table, n, sizeof(Unit*), DrawLevelCompare);
        }
Index: stratagus/src/unit/unit_find.c
diff -u stratagus/src/unit/unit_find.c:1.67 stratagus/src/unit/unit_find.c:1.68
--- stratagus/src/unit/unit_find.c:1.67 Sat Dec 20 16:33:21 2003
+++ stratagus/src/unit/unit_find.c      Thu Jan 15 09:31:11 2004
@@ -26,7 +26,7 @@
 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //      02111-1307, USA.
 //
-//     $Id: unit_find.c,v 1.67 2003/12/20 05:33:21 jsalmon3 Exp $
+//     $Id: unit_find.c,v 1.68 2004/01/14 22:31:11 nobody_ Exp $
 
 //@{
 
@@ -239,7 +239,7 @@
        best = NoUnitP;
        for (i = 0; i < n; ++i) {
                unit = table[i];
-               if (GoalGone(source, unit)) {
+               if (!UnitVisibleAsGoal(unit, source->Player)) {
                        continue;
                }
                type = unit->Type;
@@ -286,7 +286,7 @@
        best = NoUnitP;
        for (i = 0; i < n; ++i) {
                unit = table[i];
-               if (GoalGone(source, unit)) {
+               if (!UnitVisibleAsGoal(unit, source->Player)) {
                        continue;
                }
                type = unit->Type;
@@ -527,7 +527,7 @@
        for (i = 0; i < n; ++i) {
                dest = table[i];
                dtype = dest->Type;
-               if (GoalGone(u, dest)) {
+               if (!UnitVisibleAsGoal(dest, u->Player)) {
                        table[i] = 0;
                        continue;
                }
@@ -768,7 +768,10 @@
 
        for (i = 0; i < n; ++i) {
                dest = table[i];
-               if (GoalGone(unit, dest)) {             // unit attackable
+
+               // Do NOT check vision.
+               if (dest->Removed || dest->Invisible || !unit->HP
+                               || dest->Orders[0].Action == UnitActionDie) {
                        continue;
                }
 
Index: stratagus/src/unit/unitcache.c
diff -u stratagus/src/unit/unitcache.c:1.40 stratagus/src/unit/unitcache.c:1.41
--- stratagus/src/unit/unitcache.c:1.40 Sat Dec 20 16:33:21 2003
+++ stratagus/src/unit/unitcache.c      Thu Jan 15 09:31:11 2004
@@ -33,7 +33,7 @@
 //       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //       02111-1307, USA.
 //
-//             $Id: unitcache.c,v 1.40 2003/12/20 05:33:21 jsalmon3 Exp $
+//             $Id: unitcache.c,v 1.41 2004/01/14 22:31:11 nobody_ Exp $
 
 //@{
 
@@ -796,42 +796,6 @@
 //****************************************************************************/
 
 /**
-**             Inserts a dieing unit into the current dead list
-**             it may be into the building or corpse list
-**
-**             @param unit             Unit pointer to insert into list
-**             @param list             The list to insert into
-*/
-global void DeadCacheInsert(Unit* unit,Unit** list)
-{
-       unit->Next=*list;
-       *list=unit;
-}
-
-/**
-**             Removes a corpse from the current corpse list
-**
-**             @param unit             Unit pointer to remove from list
-**             @param list             The list to remove from
-*/
-global void DeadCacheRemove(Unit* unit, Unit** list)
-{
-       Unit** prev;
-
-       prev=list;
-       DebugCheck( !*prev );
-       while( *prev ) {                                                // find 
the unit, be bug friendly
-               if( *prev==unit ) {
-                       *prev=unit->Next;
-                       unit->Next=NULL;
-                       return;
-               }
-               prev=&(*prev)->Next;
-               DebugCheck( !*prev );
-       }
-}
-
-/**
 **             Insert new unit into cache.
 **
 **             @param unit             Unit pointer to place in cache.
@@ -840,6 +804,9 @@
 {
        MapField* mf;
 
+       DebugCheck(unit->Next);
+       DebugLevel3Fn("%d,%d %d %s\n" _C_ unit->X _C_ unit->Y _C_ unit->Slot 
_C_ unit->Type->Name);
+
        mf=TheMap.Fields+unit->Y*TheMap.Width+unit->X;
        unit->Next=mf->Here.Units;
        mf->Here.Units=unit;
@@ -853,19 +820,23 @@
 */
 global void UnitCacheRemove(Unit* unit)
 {
-       Unit** prev;
+       DebugLevel3Fn("%d,%d %d %s\n" _C_ unit->X _C_ unit->Y _C_ unit->Slot 
_C_ unit->Type->Name);
 
-       prev=&TheMap.Fields[unit->Y*TheMap.Width+unit->X].Here.Units;
-       DebugCheck( !*prev );
-       while( *prev ) {                                                // find 
the unit, be bug friendly
-               if( *prev==unit ) {
-                       *prev=unit->Next;
-                       unit->Next=NULL;
+       Unit* prev;
+       prev = TheMap.Fields[unit->Y * TheMap.Width + unit->X].Here.Units;
+       if (prev == unit) {
+               TheMap.Fields[unit->Y * TheMap.Width + unit->X].Here.Units = 
unit->Next;
+               unit->Next = 0;
+               return;
+       }
+       for (; prev; prev = prev->Next) {
+               if (prev->Next == unit) {
+                       prev->Next = unit->Next;
+                       unit->Next = 0;
                        return;
                }
-               prev=&(*prev)->Next;
-               DebugCheck( !*prev );
        }
+       DebugLevel0Fn("Try to remove unit not in cache.\n");
 }
 
 /**




reply via email to

[Prev in Thread] Current Thread [Next in Thread]