From 6c801713e696b27960dff0995754a1bd30ac8769 Mon Sep 17 00:00:00 2001
From: jarod42 <>
Date: Mon, 25 Oct 2004 16:05:05 +0000
Subject: [PATCH] s/unit->Building/!CanMove(unit) for movement check. Some
 CleanUp Now resouce and depot can call harvesters with right click.

---
 src/action/action_attack.cpp    |  23 ++----
 src/action/action_move.cpp      |  27 +++++--
 src/action/action_spellcast.cpp |   2 +-
 src/action/action_still.cpp     |   2 +-
 src/action/command.cpp          |   6 +-
 src/ai/ai.cpp                   |   3 +-
 src/ai/ai_plan.cpp              |   2 +-
 src/ai/ai_resource.cpp          |   6 +-
 src/editor/editloop.cpp         |   5 +-
 src/include/unit.h              |   4 +-
 src/ui/botpanel.cpp             |   7 +-
 src/ui/button_checks.cpp        |   4 +-
 src/ui/mainscr.cpp              |  13 ++-
 src/ui/mouse.cpp                | 136 ++++++++++++++++++++------------
 src/unit/script_unittype.cpp    |   2 +-
 src/unit/unit.cpp               |  45 ++++++-----
 src/unit/unit_draw.cpp          |  43 ++--------
 17 files changed, 169 insertions(+), 161 deletions(-)

diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index 2bc906295..e3f69b92d 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -240,12 +240,12 @@ static void MoveToTarget(Unit* unit)
 	Unit* goal;
 	int err;
 
-	if (!unit->Orders[0].Goal) {
-		if (unit->Orders[0].X == -1 || unit->Orders[0].Y == -1) {
-			DebugPrint("FIXME: Wrong goal position, check where set!\n");
-			unit->Orders[0].X = unit->Orders[0].Y = 0;
-		}
-	}
+	Assert(unit);
+	Assert(!unit->Type->Vanishes && !unit->Destroyed && !unit->Removed);
+	Assert(unit->Orders[0].Action == UnitActionAttack ||
+		unit->Orders[0].Action == UnitActionAttackGround);
+	Assert(CanMove(unit));
+	Assert(unit->Orders[0].Goal || (unit->Orders[0].X != -1 && unit->Orders[0].Y != -1));
 
 	err = DoActionMove(unit);
 
@@ -330,9 +330,6 @@ static void MoveToTarget(Unit* unit)
 
 		return;
 	}
-	Assert(!unit->Type->Vanishes && !unit->Destroyed && !unit->Removed);
-	Assert(unit->Orders[0].Action == UnitActionAttack ||
-		unit->Orders[0].Action == UnitActionAttackGround);
 }
 
 /**
@@ -345,12 +342,8 @@ static void AttackTarget(Unit* unit)
 	Unit* goal;
 	Unit* temp;
 
-	if (!unit->Orders[0].Goal) {
-		if (unit->Orders[0].X == -1 || unit->Orders[0].Y == -1) {
-			DebugPrint("FIXME: Wrong goal position, check where set!\n");
-			unit->Orders[0].X = unit->Orders[0].Y = 0;
-		}
-	}
+	Assert(unit);
+	Assert(unit->Orders[0].Goal || (unit->Orders[0].X != -1 && unit->Orders[0].Y != -1));
 
 	AnimateActionAttack(unit);
 	if (unit->Reset) {
diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp
index 97edd9744..7b11e7df3 100644
--- a/src/action/action_move.cpp
+++ b/src/action/action_move.cpp
@@ -181,6 +181,22 @@ static int ActionMoveGeneric(Unit* unit, const Animation* anim)
 	return d;
 }
 
+/**
+**  Test if unit can move.
+**  For the moment only check for move animation.
+**
+**  @param unit unit to test if it can move.
+**
+**  @return 0 if unit cannot move.
+*/
+int CanMove(const Unit* unit)
+{
+	Assert(unit);
+	Assert(unit->Type);
+	return (unit->Type->Animations && unit->Type->Animations->Move);
+}
+
+
 /**
 **  Unit moves! Generic function called from other actions.
 **
@@ -191,13 +207,8 @@ static int ActionMoveGeneric(Unit* unit, const Animation* anim)
 */
 int DoActionMove(Unit* unit)
 {
-	if (unit->Type->Animations && unit->Type->Animations->Move) {
-		return ActionMoveGeneric(unit, unit->Type->Animations->Move);
-	}
-
-	DebugPrint("Warning tried to move an object, which can't move\n");
-
-	return PF_UNREACHABLE;
+	Assert(CanMove(unit));
+	return ActionMoveGeneric(unit, unit->Type->Animations->Move);
 }
 
 /**
@@ -214,6 +225,8 @@ void HandleActionMove(Unit* unit)
 {
 	Unit* goal;
 
+	Assert(unit);
+	Assert(CanMove(unit));
 	if (!unit->SubAction) { // first entry
 		unit->SubAction = 1;
 		NewResetPath(unit);
diff --git a/src/action/action_spellcast.cpp b/src/action/action_spellcast.cpp
index 34126a062..afc4cf0a4 100644
--- a/src/action/action_spellcast.cpp
+++ b/src/action/action_spellcast.cpp
@@ -101,7 +101,7 @@ static void SpellMoveToTarget(Unit* unit)
 
 	// Unit can't move
 	err = 1;
-	if (unit->Type->Animations && unit->Type->Animations->Move) {
+	if (CanMove(unit)) {
 		err = DoActionMove(unit);
 		if (!unit->Reset) {
 			return;
diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp
index 9afa622da..beec4cf70 100644
--- a/src/action/action_still.cpp
+++ b/src/action/action_still.cpp
@@ -187,7 +187,7 @@ void ActionStillGeneric(Unit* unit, int ground)
 		// Normal units react in reaction range.
 		// Removed units can only attack in AttackRange, from bunker
 		//
-		if (!type->Building && !unit->Removed && !ground) {
+		if (CanMove(unit) && !unit->Removed && !ground) {
 			if ((goal = AttackUnitsInReactRange(unit))) {
 				// Weak goal, can choose other unit, come back after attack
 				CommandAttack(unit, goal->X, goal->Y, NULL, FlushCommands);
diff --git a/src/action/command.cpp b/src/action/command.cpp
index 2b3a819b9..2c31aa5ff 100644
--- a/src/action/command.cpp
+++ b/src/action/command.cpp
@@ -290,7 +290,7 @@ void CommandFollow(Unit* unit, Unit* dest, int flush)
 	// Check if unit is still valid? (NETWORK!)
 	//
 	if (!unit->Removed && unit->Orders[0].Action != UnitActionDie) {
-		if (unit->Type->Building) {
+		if (!CanMove(unit)) {
 			// FIXME: should find a better way for pending orders.
 			order = &unit->NewOrder;
 			ReleaseOrder(order);
@@ -339,7 +339,7 @@ void CommandMove(Unit* unit, int x, int y, int flush)
 	//  Check if unit is still valid? (NETWORK!)
 	//
 	if (!unit->Removed && unit->Orders[0].Action != UnitActionDie) {
-		if (unit->Type->Building) {
+		if (!CanMove(unit)) {
 			// FIXME: should find a better way for pending orders.
 			order = &unit->NewOrder;
 			ReleaseOrder(order);
@@ -542,7 +542,7 @@ void CommandPatrolUnit(Unit* unit, int x, int y, int flush)
 	// Check if unit is still valid? (NETWORK!)
 	//
 	if (!unit->Removed && unit->Orders[0].Action != UnitActionDie) {
-		if (unit->Type->Building) {
+		if (!CanMove(unit)) {
 			// FIXME: should find a better way for pending orders.
 			order = &unit->NewOrder;
 			ReleaseOrder(order);
diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index 8a7f4981d..47e5fb9a2 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -1392,8 +1392,7 @@ static void AiMoveUnitInTheWay(Unit* unit)
 			continue;
 		}
 
-		// FIXME : check movement from animation
-		if (blockertype->Building) {
+		if (!CanMove(blocker)) {
 			continue;
 		}
 
diff --git a/src/ai/ai_plan.cpp b/src/ai/ai_plan.cpp
index eb00792b7..2bbc9f3d1 100644
--- a/src/ai/ai_plan.cpp
+++ b/src/ai/ai_plan.cpp
@@ -697,7 +697,7 @@ void AiSendExplorers(void)
 
 			type = (*unit)->Type;
 
-			if (type->Building) {
+			if (!CanMove(*unit)) {
 				continue;
 			}
 
diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp
index 8f0e57f75..0db8929fa 100644
--- a/src/ai/ai_resource.cpp
+++ b/src/ai/ai_resource.cpp
@@ -153,10 +153,8 @@ static int AiCheckSupply(const PlayerAi* pai, const UnitType* type)
 	// Count what we train.
 	//
 	for (queue = pai->UnitTypeBuilded; queue; queue = queue->Next) {
-		if (!queue->Type->Building) {
-			if ((remaining -= queue->Made * queue->Type->Demand) < 0) {
-				return 0;
-			}
+		if ((remaining -= queue->Made * queue->Type->Demand) < 0) {
+			return 0;
 		}
 	}
 	return 1;
diff --git a/src/editor/editloop.cpp b/src/editor/editloop.cpp
index b3e684844..ca2512c09 100644
--- a/src/editor/editloop.cpp
+++ b/src/editor/editloop.cpp
@@ -1200,11 +1200,10 @@ static void EditorCallbackButtonDown(unsigned button __attribute__ ((unused)))
 		if ((MouseButtons & RightButton && UnitUnderCursor)) {
 			if (UnitUnderCursor->Type->GivesResource) {
 				EditorEditResource();
-				return;
-			}
-			if (!UnitUnderCursor->Type->Building && UnitUnderCursor->HP > 0) {
+			} else {
 				EditorEditAiProperties();
 			}
+			return;
 		}
 	}
 
diff --git a/src/include/unit.h b/src/include/unit.h
index 0c463b042..d7a75b791 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -563,7 +563,7 @@ struct _unit_ {
 	/* Seen stuff. */
 	char VisCount[PlayerMax]; ///< Unit visibility counts
 	struct _seen_stuff_ {
-		unsigned            ByPlayer : 16;           ///< Track unit seen by player
+		unsigned            ByPlayer : PlayerMax;    ///< Track unit seen by player
 		int                 Frame;                   ///< last seen frame/stage of buildings
 		struct _unit_type_* Type;                    ///< Pointer to last seen unit-type
 		signed char         IX;                      ///< Seen X image displacement to map position
@@ -888,6 +888,8 @@ extern int CanTarget(const struct _unit_type_* type, const struct _unit_type_* d
 	/// Can transporter transport the other unit
 extern int CanTransport(const Unit* transporter, const Unit* unit);
 
+	/// Check if unit can move.
+extern int CanMove(const Unit*);
 
 	/// Generate a unit reference, a printable unique string for unit
 extern char* UnitReference(const Unit*);
diff --git a/src/ui/botpanel.cpp b/src/ui/botpanel.cpp
index 150c5bf6f..cc80914b3 100644
--- a/src/ui/botpanel.cpp
+++ b/src/ui/botpanel.cpp
@@ -725,7 +725,7 @@ void DoButtonButtonClicked(int button)
 			//  That or a bunker.
 			//
 			if ((NumSelected == 1 && Selected[0]->Orders[0].Action == UnitActionStill &&
-					CoastOnMap(Selected[0]->X, Selected[0]->Y)) || Selected[0]->Type->Building) {
+					CoastOnMap(Selected[0]->X, Selected[0]->Y)) || !CanMove(Selected[0])) {
 				SendCommandUnload(Selected[0],
 					Selected[0]->X, Selected[0]->Y, NoUnitP,
 					!(KeyModifiers & ModifierShift));
@@ -799,7 +799,7 @@ void DoButtonButtonClicked(int button)
 
 		case ButtonCancel:
 		case ButtonCancelUpgrade:
-			if (NumSelected == 1 && Selected[0]->Type->Building) {
+			if (NumSelected == 1) {
 				if (Selected[0]->Orders[0].Action == UnitActionUpgradeTo) {
 					SendCommandCancelUpgradeTo(Selected[0]);
 				} else if (Selected[0]->Orders[0].Action == UnitActionResearch) {
@@ -824,7 +824,8 @@ void DoButtonButtonClicked(int button)
 
 		case ButtonCancelBuild:
 			// FIXME: johns is this not sure, only building should have this?
-			if (NumSelected == 1 && Selected[0]->Type->Building) {
+			Assert(Selected[0]->Orders[0].Action == UnitActionBuild);
+			if (NumSelected == 1) {
 				SendCommandDismiss(Selected[0]);
 			}
 			ClearStatusLine();
diff --git a/src/ui/button_checks.cpp b/src/ui/button_checks.cpp
index 0a12d92b8..fca3bcceb 100644
--- a/src/ui/button_checks.cpp
+++ b/src/ui/button_checks.cpp
@@ -187,7 +187,7 @@ int ButtonCheckNoNetwork(const Unit* unit __attribute__((unused)),
 int ButtonCheckNoWork(const Unit* unit,
 	const ButtonAction* button __attribute__((unused)))
 {
-	return unit->Type->Building &&
+	return
 		unit->Orders[0].Action != UnitActionTrain &&
 		unit->Orders[0].Action != UnitActionUpgradeTo &&
 		unit->Orders[0].Action != UnitActionResearch;
@@ -204,7 +204,7 @@ int ButtonCheckNoWork(const Unit* unit,
 int ButtonCheckNoResearch(const Unit* unit,
 	const ButtonAction* button __attribute__((unused)))
 {
-	return unit->Type->Building &&
+	return
 		unit->Orders[0].Action != UnitActionUpgradeTo &&
 		unit->Orders[0].Action != UnitActionResearch;
 }
diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp
index a396b5091..485ce2e88 100644
--- a/src/ui/mainscr.cpp
+++ b/src/ui/mainscr.cpp
@@ -606,9 +606,9 @@ static void DrawUnitInfo(const Unit* unit)
 	x = TheUI.InfoPanelX;
 	y = TheUI.InfoPanelY;
 	//
-	//  Show progress for buildings only, if they are selected.
+	//  Show progress if they are selected.
 	//
-	if (type->Building && NumSelected == 1 && Selected[0] == unit) {
+	if (NumSelected == 1 && Selected[0] == unit) {
 		//
 		//  Building training units.
 		//
@@ -1283,11 +1283,10 @@ void DrawInfoPanel(void)
 					PlayersTeamed(ThisPlayer->Player, Selected[0]->Player->Player) ||
 					PlayersAllied(ThisPlayer->Player, Selected[0]->Player->Player) ||
 					ReplayRevealMap) {
-				if (Selected[0]->Type->Building &&
-						(Selected[0]->Orders[0].Action == UnitActionBuilded ||
-							Selected[0]->Orders[0].Action == UnitActionResearch ||
-							Selected[0]->Orders[0].Action == UnitActionUpgradeTo ||
-							Selected[0]->Orders[0].Action == UnitActionTrain)) {
+				if (Selected[0]->Orders[0].Action == UnitActionBuilded ||
+					Selected[0]->Orders[0].Action == UnitActionResearch ||
+					Selected[0]->Orders[0].Action == UnitActionUpgradeTo ||
+					Selected[0]->Orders[0].Action == UnitActionTrain) {
 					i = 3;
 				} else if (Selected[0]->Type->_MaxMana) {
 					i = 2;
diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp
index 7215a51d3..592432a5f 100644
--- a/src/ui/mouse.cpp
+++ b/src/ui/mouse.cpp
@@ -104,35 +104,26 @@ void CancelBuildingMode(void)
 */
 void DoRightButton(int sx, int sy)
 {
-	int i;
-	int x;
-	int y;
-	Unit* dest;
-	Unit* unit;
-	Unit* desttransporter;
-	UnitType* type;
-	int action;
-	int acknowledged;
-	int flush;
-	int res;
-	int spellnum;
+	int i;                  // iterator for selected units.
+	int x;                  // coordonate in tile.
+	int y;                  // coordonate in tile.
+	Unit* dest;             // unit under the cursor if any.
+	Unit* unit;             // one of the selected unit.
+	Unit* desttransporter;  // dest if it could transport any unit.
+	UnitType* type;         // type of unit.
+	int action;             // default action for unit.
+	int acknowledged;       // to play sound
+	int flush;              // append command to old command.
+	int res;                // resource id for harvester.
+	int spellnum;           // spell id for spell cast
 
 	// No unit selected
 	if (!NumSelected) {
 		return;
 	}
 
-	//
-	//  Unit selected isn't owned by the player.
-	//  You can't select your own units + foreign unit(s).
-	//
-	if (!CanSelectMultipleUnits(Selected[0]->Player)) {
-		return;
-	}
-
 	x = sx / TileSizeX;
 	y = sy / TileSizeY;
-	desttransporter = NoUnitP;
 
 	//
 	//  Right mouse with SHIFT appends command to old commands.
@@ -145,6 +136,30 @@ void DoRightButton(int sx, int sy)
 		dest = NULL;
 	}
 
+	//
+	//  Unit selected isn't owned by the player.
+	//  You can't select your own units + foreign unit(s)
+	//  except if it is neutral and it is a resource.
+	//
+	if (!CanSelectMultipleUnits(Selected[0]->Player)) {
+		unit = Selected[0];
+		if (unit->Player->Player != PlayerNumNeutral || dest == NULL) {
+			return ;
+		}
+		// tell to go and harvest from a unit
+		if (dest->Type->Harvester &&
+				(res = unit->Type->GivesResource) &&
+				dest->Type->ResInfo[res] &&
+				dest->ResourcesHeld < dest->Type->ResInfo[res]->ResourceCapacity &&
+				unit->Type->CanHarvest) {
+			unit->Blink = 4;
+			SendCommandResource(dest, unit, flush);
+			return;
+		}
+		return;
+	}
+
+	desttransporter = NoUnitP;
 	if (dest && dest->Type->CanTransport) {
 		for (i = 0; i < NumSelected; i++) {
 			if (CanTransport(dest, Selected[i])) {
@@ -184,7 +199,7 @@ void DoRightButton(int sx, int sy)
 		//
 		//  Control + right click on unit is follow anything.
 		//
-		if ((KeyModifiers & ModifierControl) && dest && dest!=unit) {
+		if ((KeyModifiers & ModifierControl) && dest && dest != unit) {
 			dest->Blink = 4;
 			SendCommandFollow(unit, dest, flush);
 			continue;
@@ -197,9 +212,8 @@ void DoRightButton(int sx, int sy)
 			dest->Blink = 4;
 			DebugPrint("Board transporter\n");
 			// Let the transporter move to the unit. And QUEUE!!!
-			// Don't do it for buildings.
-			if (!dest->Type->Building) {
-				DebugPrint("Send command follow");
+			if (CanMove(dest)) {
+				DebugPrint("Send command follow\n");
 				SendCommandFollow(dest, unit, 0);
 			}
 			SendCommandBoard(unit, -1, -1, dest, flush);
@@ -210,7 +224,7 @@ void DoRightButton(int sx, int sy)
 		//  Handle resource workers.
 		//
 		if (action == MouseActionHarvest) {
-			if (unit->Type->Harvester) {
+			if (type->Harvester) {
 				if (dest) {
 					// Return a loaded harvester to deposit
 					if (unit->ResourcesHeld > 0 &&
@@ -220,10 +234,10 @@ void DoRightButton(int sx, int sy)
 						SendCommandReturnGoods(unit, dest, flush);
 						continue;
 					}
-					// Go and harvest from a building
+					// Go and harvest from a unit
 					if ((res = dest->Type->GivesResource) &&
-							unit->Type->ResInfo[res] &&
-							unit->ResourcesHeld < unit->Type->ResInfo[res]->ResourceCapacity &&
+							type->ResInfo[res] &&
+							unit->ResourcesHeld < type->ResInfo[res]->ResourceCapacity &&
 							dest->Type->CanHarvest &&
 							(dest->Player == unit->Player ||
 								(dest->Player->Player == PlayerNumNeutral))) {
@@ -234,12 +248,12 @@ void DoRightButton(int sx, int sy)
 				} else {
 					// FIXME: support harvesting more types of terrain.
 					for (res = 0; res < MaxCosts; ++res) {
-						if (unit->Type->ResInfo[res] &&
-								unit->Type->ResInfo[res]->TerrainHarvester &&
+						if (type->ResInfo[res] &&
+								type->ResInfo[res]->TerrainHarvester &&
 								IsMapFieldExplored(unit->Player, x, y) &&
 								ForestOnMap(x, y) &&
 								((unit->CurrentResource != res) ||
-									(unit->ResourcesHeld < unit->Type->ResInfo[res]->ResourceCapacity))) {
+									(unit->ResourcesHeld < type->ResInfo[res]->ResourceCapacity))) {
 							SendCommandResourceLoc(unit, x, y,flush);
 							break;
 						}
@@ -250,7 +264,7 @@ void DoRightButton(int sx, int sy)
 				}
 			}
 			// Go and repair
-			if (unit->Type->RepairRange && dest &&
+			if (type->RepairRange && dest &&
 					dest->Type->RepairHP &&
 					dest->HP < dest->Stats->HitPoints &&
 					(dest->Player == unit->Player || IsAllied(dest->Player, dest))) {
@@ -280,12 +294,12 @@ void DoRightButton(int sx, int sy)
 					if (action == MouseActionSpellCast) {
 						// This is for demolition squads and such
 						Assert(unit->Type->CanCastSpell);
-						for (spellnum = 0; !unit->Type->CanCastSpell[spellnum] &&
+						for (spellnum = 0; !type->CanCastSpell[spellnum] &&
 								spellnum < SpellTypeCount ; spellnum++) ;
 						Assert(spellnum != SpellTypeCount);
 						SendCommandSpellCast(unit, x, y, dest, spellnum, flush);
 					} else {
-						if (CanTarget(unit->Type, dest->Type)) {
+						if (CanTarget(type, dest->Type)) {
 							SendCommandAttack(unit, x, y, dest, flush);
 						} else { // No valid target
 							SendCommandAttack(unit, x, y, NoUnitP, flush);
@@ -344,22 +358,44 @@ void DoRightButton(int sx, int sy)
 			continue;
 		}
 
-		//
-		//  Buildings
-		//
-		if (type->Building) {
-			if (dest && dest->Type->GivesResource && dest->Type->CanHarvest) {
+		// Manage harvester from the destination side.
+		if (dest && dest->Type->Harvester) {
+			// tell to return a loaded harvester to deposit
+			if (dest->ResourcesHeld > 0 &&
+					type->CanStore[dest->CurrentResource] &&
+					dest->Player == unit->Player) {
+				dest->Blink = 4;
+				SendCommandReturnGoods(dest, unit, flush);
+				continue;
+			}
+			// tell to go and harvest from a building
+			if ((res = type->GivesResource) &&
+					dest->Type->ResInfo[res] &&
+					dest->ResourcesHeld < dest->Type->ResInfo[res]->ResourceCapacity &&
+					type->CanHarvest &&
+					dest->Player == unit->Player) {
+				unit->Blink = 4;
+				SendCommandResource(dest, unit, flush);
+				continue;
+			}
+		}
+
+		// Manaage new order.
+		if (!CanMove(unit)) {
+			// Go and harvest from a unit
+			if (dest && dest->Type->GivesResource && dest->Type->CanHarvest &&
+					(dest->Player == unit->Player || dest->Player->Player == PlayerNumNeutral)) {
 				dest->Blink = 4;
 				SendCommandResource(unit, dest, flush);
 				continue;
 			}
+			// FIXME: support harvesting more types of terrain.
 			if (IsMapFieldExplored(unit->Player, x, y) && ForestOnMap(x, y)) {
-				SendCommandResourceLoc(unit, x, y, flush);
-				continue;
+				SendCommandResourceLoc(unit, x, y,flush);
+				break;
 			}
-			SendCommandMove(unit, x, y, flush);
-			continue;
 		}
+
 		SendCommandMove(unit, x, y, flush);
 	}
 	ShowOrdersCount = GameCycle + ShowOrders * CYCLES_PER_SECOND;
@@ -465,7 +501,7 @@ static void HandleMouseOn(int x, int y)
 			}
 		}
 	}
-	if (NumSelected == 1 && Selected[0]->Type->Building && !BigMapMode) {
+	if (NumSelected == 1 && !BigMapMode) {
 		if (Selected[0]->Orders[0].Action == UnitActionTrain) {
 			if (Selected[0]->OrderCount == 1) {
 				if (OnButton(x, y, TheUI.SingleTrainingButton)) {
@@ -943,7 +979,7 @@ static int SendAttack(int sx, int sy)
 	y = sy / TileSizeY;
 	for (i = 0; i < NumSelected; ++i) {
 		unit = Selected[i];
-		if (unit->Type->CanAttack || unit->Type->Building) {
+		if (unit->Type->CanAttack) {
 			if ((dest = UnitUnderCursor) && CanTarget(unit->Type, dest->Type)) {
 				dest->Blink = 4;
 			} else {
@@ -955,8 +991,10 @@ static int SendAttack(int sx, int sy)
 				ret = 1;
 			}
 		} else {
-			SendCommandMove(unit, x, y, !(KeyModifiers & ModifierShift));
-			ret = 1;
+			if (CanMove(unit)) {
+				SendCommandMove(unit, x, y, !(KeyModifiers & ModifierShift));
+				ret = 1;
+			}
 		}
 	}
 	return ret;
@@ -1069,7 +1107,7 @@ static int SendResource(int sx, int sy)
 				}
 			}
 		}
-		if (unit->Type->Building) {
+		if (!CanMove(unit)) {
 			if (dest && dest->Type->GivesResource && dest->Type->CanHarvest) {
 				dest->Blink = 4;
 				SendCommandResource(unit, dest, !(KeyModifiers & ModifierShift));
diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp
index 35ad159c5..b49258098 100644
--- a/src/unit/script_unittype.cpp
+++ b/src/unit/script_unittype.cpp
@@ -1705,7 +1705,7 @@ void UpdateUnitVariables(const Unit* unit)
 		unit->Variable[i].Enable = 1;
 	}
 
-	// HP (do also building under construction :) ).
+	// HP.
 	unit->Variable[HP_INDEX].Value = unit->HP;
 	unit->Variable[HP_INDEX].Max = unit->Stats->HitPoints;
 
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 15b52001e..cb775e084 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -389,31 +389,35 @@ void InitUnit(Unit* unit, UnitType* type)
 }
 
 /**
-** FIXME: Docu
+**  FIXME: Docu
+**
+**  @param unit    unit assigned to player.
+**  @param player  player which have the unit.
+**
+**  @todo FIXME DOCU.
 */
 void AssignUnitToPlayer(Unit* unit, Player* player)
 {
-	UnitType* type;
+	UnitType* type;  // type of unit.
 
+	Assert(player);
 	type = unit->Type;
 
 	//
 	// Build player unit table
 	//
-	if (player && !type->Vanishes && unit->Orders[0].Action != UnitActionDie) {
+	if (!type->Vanishes && unit->Orders[0].Action != UnitActionDie) {
 		unit->PlayerSlot = player->Units + player->TotalNumUnits++;
 		if (!SaveGameLoading) {
-			if (type->_HitPoints != 0) {
-				// If unit is dieing, it's already been lost by all players
-				// don't count again
-				if (type->Building && unit->Orders[0].Action != UnitActionDie) {
-					// FIXME: support more races
-					if (type != UnitTypeOrcWall && type != UnitTypeHumanWall) {
-						player->TotalBuildings++;
-					}
-				} else if (unit->Orders[0].Action != UnitActionDie) {
-					player->TotalUnits++;
+			// If unit is dieing, it's already been lost by all players
+			// don't count again
+			if (type->Building) {
+				// FIXME: support more races
+				if (type != UnitTypeOrcWall && type != UnitTypeHumanWall) {
+					player->TotalBuildings++;
 				}
+			} else {
+				player->TotalUnits++;
 			}
 		}
 		*unit->PlayerSlot = unit;
@@ -431,7 +435,6 @@ void AssignUnitToPlayer(Unit* unit, Player* player)
 			player->NumBuildings++;
 		}
 	}
-
 	unit->Player = player;
 	unit->Stats = &type->Stats[unit->Player->Player];
 	unit->Colors = &player->UnitColors;
@@ -627,7 +630,7 @@ static void MarkUnitFieldFlags(const Unit* unit)
 	}
 #ifdef MAP_REGIONS
 	// Update map splitting.
-	if (type->Building && (flags &
+	if (!CanMove(unit) && (flags &
 		 (MapFieldLandUnit | MapFieldSeaUnit | MapFieldBuilding |
 		  MapFieldUnpassable | MapFieldWall | MapFieldRocks | MapFieldForest))) {
 		MapSplitterTilesOccuped(x, y, x + type->TileWidth - 1, y + type->TileHeight - 1);
@@ -661,7 +664,7 @@ static void UnmarkUnitFieldFlags(const Unit* unit)
 	}
 #ifdef MAP_REGIONS
 	// Update map splitting.
-	if (type->Building && (flags &
+	if (!CanMove(unit) && (flags &
 		 (MapFieldLandUnit | MapFieldSeaUnit | MapFieldBuilding |
 		  MapFieldUnpassable | MapFieldWall | MapFieldRocks | MapFieldForest))){
 		MapSplitterTilesCleared(x, y, x + type->TileWidth - 1, y + type->TileHeight - 1);
@@ -1219,10 +1222,6 @@ void UnitsOnTileUnmarkSeen(const Player* player, int x, int y, int cloak)
 	n = UnitCacheOnTile(x, y, units);
 	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)) {
-			DebugPrint("Wrong cache %d %d -> %d %d\n" _C_ x _C_ y _C_ unit->X _C_ unit->Y);
-		}
 		Assert(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) {
@@ -3153,7 +3152,7 @@ void HitUnit(Unit* attacker, Unit* target, int damage)
 	// Attack units in range (which or the attacker?)
 	//
 	if (attacker && !type->Coward) {
-		if (type->CanAttack && !target->Type->Building) {
+		if (type->CanAttack) {
 			if (RevealAttacker && CanTarget(target->Type, attacker->Type)) {
 				// Reveal Unit that is attacking
 				goal = attacker;
@@ -3176,7 +3175,7 @@ void HitUnit(Unit* attacker, Unit* target, int damage)
 	//
 	// FIXME: Can't attack run away.
 	//
-	if (!type->Building) {
+	if (CanMove(target)) {
 		int x;
 		int y;
 		int d;
@@ -3411,7 +3410,7 @@ int CanTransport(const Unit* transporter, const Unit* unit)
 {
 	int i;
 
-	if (!transporter->Type->CanTransport || unit->Type->Building) {
+	if (!transporter->Type->CanTransport) {
 		return 0;
 	}
 	if (transporter->BoardCount >= transporter->Type->MaxOnBoard) { // full
diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp
index c9726f0fb..3f0ef3b67 100644
--- a/src/unit/unit_draw.cpp
+++ b/src/unit/unit_draw.cpp
@@ -195,7 +195,7 @@ void DrawUnitSelection(const Unit* unit)
 				color = Players[i].Color;
 			}
 		}
-	} else if (CursorBuilding && unit->Type->Building && 
+	} else if (CursorBuilding && unit->Type->Building &&
 			unit->Orders[0].Action != UnitActionDie &&
 			(unit->Player == ThisPlayer ||
 				PlayersTeamed(ThisPlayer->Player, unit->Player->Player))) {
@@ -1170,43 +1170,10 @@ void DrawShadow(const Unit* unit, const UnitType* type, int frame,
 		Assert(unit);
 		type = unit->Type;
 	}
-	Assert(!unit || !type || unit->Type == type);
-
-	//
-	//  A building can be under construction and is drawn with construction
-	//  frames.
-	//
-	if (type->Building) {
-		// Draw normal shadow
-		if (type->ShadowSprite) {
-			// FIXME: this can be combined with the unit else part.
-			x -= (type->ShadowWidth -
-				type->TileWidth * TileSizeX) / 2;
-			y -= (type->ShadowHeight -
-				type->TileHeight * TileSizeY) / 2;
-			x += type->ShadowOffsetX;
-			y += type->ShadowOffsetY;
-			if (type->Flip) {
-				if (frame < 0) {
-					VideoDrawClipX(type->ShadowSprite, -frame - 1, x, y);
-				} else {
-					VideoDrawClip(type->ShadowSprite, frame, x, y);
-				}
-			} else {
-				int row;
-
-				row = type->NumDirections / 2 + 1;
-				if (frame < 0) {
-					frame = ((-frame - 1) / row) * type->NumDirections + type->NumDirections - (-frame - 1) % row;
-				} else {
-					frame = (frame / row) * type->NumDirections + frame % row;
-				}
-				VideoDrawClip(type->ShadowSprite, frame, x, y);
-			}
-		}
-		return;
-	}
+	Assert(type);
+	Assert(!unit || unit->Type == type);
 
+	// unit == NULL for the editor
 	if (unit && unit->Orders[0].Action == UnitActionDie) {
 		return;
 	}
@@ -1590,7 +1557,7 @@ void ShowOrder(const Unit* unit)
 		ShowSingleOrder(unit, x1, y1, unit->Orders + i);
 	}
 #endif
-	if (unit->Type->Building) {
+	if (!CanMove(unit)) {
 		ShowSingleOrder(unit, x1, y1, &unit->NewOrder);
 	}
 }