From 087c4c85e9cc8dd586b1507207943321fb494bac Mon Sep 17 00:00:00 2001
From: mr-russ <>
Date: Thu, 8 Jul 2004 22:34:31 +0000
Subject: [PATCH] Removed MAX_ORDERS, units can have as many orders as they
 require. Added Memory management for Orders, so they are reused, less
 mallocs.

Remove MustRedraw and EnableRedraw, they are not used, everything is redrawn each frame.

Remove TrainingQueue LIMIT, you can train as many units as you like if the training queue is enable.
This needs further configuration work.  But operates correctly.
---
 src/action/action_move.cpp  |   2 -
 src/action/action_train.cpp |  24 ++----
 src/action/actions.cpp      |   4 +-
 src/action/command.cpp      | 147 +++++++++++++++++++++---------------
 src/ai/ai.cpp               |   1 -
 src/editor/editloop.cpp     |   8 +-
 src/include/editor.h        |  10 ++-
 src/include/stratagus.h     |  16 +---
 src/include/unit.h          |  22 +++---
 src/map/map.cpp             |   2 -
 src/map/map_rock.cpp        |   3 -
 src/map/map_wall.cpp        |   4 -
 src/map/map_wood.cpp        |   3 -
 src/pathfinder/astar.cpp    |   4 +
 src/stratagus/mainloop.cpp  |   3 +-
 src/stratagus/stratagus.cpp |  11 +--
 src/ui/botpanel.cpp         |   6 +-
 src/ui/interface.cpp        |   4 -
 src/ui/mainscr.cpp          |  22 +++---
 src/ui/menus.cpp            |   9 +--
 src/ui/mouse.cpp            |  18 ++---
 src/unit/script_unit.cpp    |  35 ++-------
 src/unit/unit.cpp           |  54 +++++++++----
 src/unit/unit_draw.cpp      |   2 +-
 src/unit/upgrade.cpp        |  16 ++--
 25 files changed, 211 insertions(+), 219 deletions(-)

diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp
index 1f8b438db..97edd9744 100644
--- a/src/action/action_move.cpp
+++ b/src/action/action_move.cpp
@@ -125,8 +125,6 @@ static int ActionMoveGeneric(Unit* unit, const Animation* anim)
 		y = unit->Y + yd;
 		MoveUnitToXY(unit, x, y);
 
-		MustRedraw |= RedrawMinimap;
-
 		// Remove unit from the current selection
 		if (unit->Selected && !IsMapFieldVisible(ThisPlayer, x, y)) {
 			if (NumSelected == 1) { //  Remove building cursor
diff --git a/src/action/action_train.cpp b/src/action/action_train.cpp
index efae665ad..cd67fcae9 100644
--- a/src/action/action_train.cpp
+++ b/src/action/action_train.cpp
@@ -102,20 +102,18 @@ void HandleActionTrain(Unit* unit)
 	//
 	if (!unit->SubAction) {
 		unit->Data.Train.Ticks = 0;
-		unit->Data.Train.What[0] = unit->Orders[0].Type;
-		unit->Data.Train.Count = 1;
 		unit->SubAction = 1;
 	}
 	unit->Data.Train.Ticks += SpeedTrain;
 	// FIXME: Should count down
 	if (unit->Data.Train.Ticks >=
-		unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost]) {
+		unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost]) {
 		//
 		// Check if there are still unit slots.
 		//
 		if (NumUnits >= UnitMax) {
 			unit->Data.Train.Ticks =
-				unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost];
+				unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost];
 			unit->Reset = 1;
 			unit->Wait = CYCLES_PER_SECOND / 6;
 			return;
@@ -124,20 +122,20 @@ void HandleActionTrain(Unit* unit)
 		//
 		// Check if enough supply available.
 		//
-		food = PlayerCheckLimits(player, unit->Data.Train.What[0]);
+		food = PlayerCheckLimits(player, unit->Orders[0].Type);
 		if (food < 0) {
 			if (food == -3 && unit->Player->AiEnabled) {
 				AiNeedMoreSupply(unit, unit->Orders[0].Type);
 			}
 
 			unit->Data.Train.Ticks =
-				unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost];
+				unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost];
 			unit->Reset = 1;
 			unit->Wait = CYCLES_PER_SECOND / 6;
 			return;
 		}
 
-		nunit = MakeUnit(unit->Data.Train.What[0], player);
+		nunit = MakeUnit(unit->Orders[0].Type, player);
 		nunit->X = unit->X;
 		nunit->Y = unit->Y;
 		type = unit->Type;
@@ -166,16 +164,8 @@ void HandleActionTrain(Unit* unit)
 
 		unit->Reset = unit->Wait = 1;
 
-		if (--unit->Data.Train.Count) {
-			int z;
-			for (z = 0; z < unit->Data.Train.Count; ++z) {
-				unit->Data.Train.What[z] = unit->Data.Train.What[z + 1];
-			}
-			unit->Data.Train.Ticks = 0;
-		} else {
-			unit->Orders[0].Action = UnitActionStill;
-			unit->SubAction = 0;
-		}
+		unit->Orders[0].Action = UnitActionStill;
+		unit->SubAction = 0;
 
 		if (!CanHandleOrder(nunit, &unit->NewOrder)) {
 			DebugPrint("Wrong order for unit\n");
diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index c9a32d48b..e9dc9e267 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -555,7 +555,7 @@ void UnitActions(void)
 		fprintf(logf, "%d %s S%d/%d-%d P%d Refs %d: %X %d,%d %d,%d\n",
 			UnitNumber(unit), unit->Type ? unit->Type->Ident : "unit-killed",
 			unit->State, unit->SubAction,
-			unit->Orders[0].Action,
+			unit->Orders ? unit->Orders[0].Action : -1,
 			unit->Player ? unit->Player->Player : -1, unit->Refs,SyncRandSeed,
 			unit->X, unit->Y, unit->IX, unit->IY);
 
@@ -569,7 +569,7 @@ void UnitActions(void)
 		// Calculate some hash.
 		//
 		SyncHash = (SyncHash << 5) | (SyncHash >> 27);
-		SyncHash ^= unit->Orders[0].Action << 18;
+		SyncHash ^= unit->Orders ? unit->Orders[0].Action << 18 : 0;
 		SyncHash ^= unit->State << 12;
 		SyncHash ^= unit->SubAction << 6;
 		SyncHash ^= unit->Refs << 3;
diff --git a/src/action/command.cpp b/src/action/command.cpp
index 900a6e950..8fba311a6 100644
--- a/src/action/command.cpp
+++ b/src/action/command.cpp
@@ -36,6 +36,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "stratagus.h"
 #include "unittype.h"
@@ -96,21 +97,57 @@ static void ReleaseOrders(Unit* unit)
 */
 static Order* GetNextOrder(Unit* unit, int flush)
 {
+	Order *OldOrders;
 	if (flush) {
 		// empty command queue
 		ReleaseOrders(unit);
-	} else if (unit->OrderCount == MAX_ORDERS) {
-		// FIXME: johns: wrong place for an error message.
-		// FIXME: johns: should be checked by AI or the user interface
-		// NOTE: But must still be checked here.
-		NotifyPlayer(unit->Player, NotifyYellow, unit->X, unit->Y,
-			"Unit order list is full");
-		return NULL;
+	} else if (unit->OrderCount == unit->TotalOrders) {
+		// Expand Order Queue if filled
+		OldOrders = unit->Orders;
+		unit->Orders = realloc(unit->Orders, sizeof(Order) * unit->TotalOrders * 2);
+		// Realloc failed, fail gracefully
+		if (!unit->Orders) {
+			unit->Orders = OldOrders;
+			NotifyPlayer(unit->Player, NotifyYellow, unit->X, unit->Y,
+				"Unable to add order to list");
+			return NULL;
+		}
+		memset(&unit->Orders[unit->TotalOrders], 0, sizeof(Order) * unit->TotalOrders);
+		unit->TotalOrders *= 2;
 	}
 
 	return &unit->Orders[(int)unit->OrderCount++];
 }
 
+/*
+**  Remove an order from the list of orders pending
+**
+**  @param unit   pointer to unit
+**  @param order  number of the order to remove
+*/
+static void RemoveOrder(Unit* unit, int order)
+{
+	int i;
+	
+	i = order;
+	while(i < unit->OrderCount - 1) {
+		unit->Orders[i] = unit->Orders[i + 1];
+		++i;
+	}
+
+	if (unit->OrderCount > 1) {
+		--unit->OrderCount;
+	} else {
+		unit->Orders[i].Action = UnitActionStill;
+		unit->Orders[i].X = unit->Orders[i].Y = -1;
+		unit->SubAction = 0;
+		unit->Orders[i].Type = NULL;
+		unit->Orders[i].Arg1 = NULL;
+	}
+
+	return;
+}
+
 /**
 **  Clear the saved action.
 **
@@ -839,6 +876,8 @@ void CommandReturnGoods(Unit* unit, Unit* goal, int flush)
 void CommandTrainUnit(Unit* unit, UnitType* type,
 	int flush __attribute__((unused)))
 {
+	Order* order;
+
 	//
 	// Check if unit is still valid? (NETWORK!)
 	//
@@ -855,32 +894,19 @@ void CommandTrainUnit(Unit* unit, UnitType* type,
 		//
 		// Not already training?
 		//
-		if (unit->Orders[0].Action != UnitActionTrain) {
-			if (unit->OrderCount == 2 && unit->Orders[1].Action == UnitActionTrain) {
-				DebugPrint("FIXME: not supported. Unit queue full!\n");
-				return;
-			} else {
-				ReleaseOrders(unit);
-				unit->Orders[1].Action = UnitActionTrain;
-			}
-			Assert(unit->OrderCount == 1 && unit->OrderFlush == 1);
-
-			unit->OrderCount = 2;
-			unit->Orders[1].Type = type;
-			unit->Orders[1].X = unit->Orders[1].Y = -1;
-			unit->Orders[1].Goal = NoUnitP;
-			unit->Orders[1].Arg1 = NULL;
-		} else {
-			//
-			// Training slots are all already full. (NETWORK!)
-			//
-			if (!EnableTrainingQueue || unit->Data.Train.Count >= MAX_UNIT_TRAIN) {
-				DebugPrint("Unit queue full!\n");
-				return;
-			}
-
-			unit->Data.Train.What[unit->Data.Train.Count++] = type;
+		if (!EnableTrainingQueue && unit->Orders[0].Action == UnitActionTrain) {
+			DebugPrint("Unit queue full!\n");
+			return;
 		}
+		if (!(order = GetNextOrder(unit, 0))) {
+			return;
+		}
+
+		order->Action = UnitActionTrain;
+		order->Type = type;
+		order->X = order->Y = -1;
+		order->Goal = NoUnitP;
+		order->Arg1 = NULL;
 		// FIXME: if you give quick an other order, the resources are lost!
 		PlayerSubUnitType(unit->Player, type);
 	}
@@ -896,8 +922,6 @@ void CommandTrainUnit(Unit* unit, UnitType* type,
 */
 void CommandCancelTraining(Unit* unit, int slot, const UnitType* type)
 {
-	int i;
-	int n;
 
 	DebugPrint("Cancel %d type: %s\n" _C_ slot _C_
 		type ? type->Ident : "-any-");
@@ -907,42 +931,45 @@ void CommandCancelTraining(Unit* unit, int slot, const UnitType* type)
 	//
 	// Check if unit is still training 'slot'? (NETWORK!)
 	//
-	if (unit->Orders[0].Action == UnitActionTrain) {
-		n = unit->Data.Train.Count;
-		Assert(n >= 1);
-		if (slot == -1) { // default last slot!
-			slot += n;
+
+	if (slot == -1) {
+		// Cancel All training
+		while(unit->Orders[0].Action == UnitActionTrain) {
+			PlayerAddCostsFactor(unit->Player,
+				unit->Orders[0].Type->Stats[unit->Player->Player].Costs,
+				CancelTrainingCostsFactor);
+			RemoveOrder(unit, 0);
+		}	
+		unit->Data.Train.Ticks = 0;
+		unit->Wait = unit->Reset = 1; // immediately start next training
+		if (unit->Player == ThisPlayer && unit->Selected) {
+			SelectedUnitChanged();
 		}
-		//
-		// Check if slot and unit-type is still trained? (NETWORK!)
-		//
-		if (slot >= n || (type && unit->Data.Train.What[slot] != type)) {
-			// FIXME: we can look if this is now in an earlier slot.
+	} else if (unit->OrderCount < slot) {
+		// Order has moved
+		return;
+	} else if (unit->Orders[slot].Action != UnitActionTrain) {
+		// Order has moved, we are not training
+		return;
+	} else if (unit->Orders[slot].Action == UnitActionTrain) {
+		// Still training this order, same unit?
+		if (type && unit->Orders[slot].Type != type) {
+			// Different unit being trained
 			return;
 		}
 
 		DebugPrint("Cancel training\n");
 
 		PlayerAddCostsFactor(unit->Player,
-			unit->Data.Train.What[slot]->Stats[unit->Player->Player].Costs,
+			unit->Orders[slot].Type->Stats[unit->Player->Player].Costs,
 			CancelTrainingCostsFactor);
 
-		if (--n) {
-			// Copy the other slots down
-			for (i = slot; i < n; ++i) {
-				unit->Data.Train.What[i] = unit->Data.Train.What[i + 1];
-			}
-			if (!slot) { // Canceled in work slot
-				unit->Data.Train.Ticks = 0;
-				unit->Wait = unit->Reset = 1; // immediately start next training
-			}
-			unit->Data.Train.Count = n;
-		} else {
-			DebugPrint("Last slot\n");
-			unit->Orders[0].Action = UnitActionStill;
-			unit->SubAction = 0;
-			unit->Wait = unit->Reset = 1;
+	
+		if (!slot) { // Canceled in work slot
+			unit->Data.Train.Ticks = 0;
+			unit->Wait = unit->Reset = 1; // immediately start next training
 		}
+		RemoveOrder(unit, slot);
 
 		//
 		// Update interface.
diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index 32e597280..8fe361631 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -1513,7 +1513,6 @@ static int FindTransporterOnZone(int waterzone, ZoneSet* destzones,
 		// If transporter is moving, check if it is moving on our coast
 		if (!unitok &&
 				unit->OrderCount + (unit->OrderFlush ? 1 : 0) >= 2 &&
-				unit->OrderCount < MAX_ORDERS - 1 &&
 				unit->Orders[unit->OrderFlush ? 1 : 0].Action == UnitActionFollow &&
 				unit->Orders[unit->OrderCount - 1].Action == UnitActionUnload &&
 				unit->BoardCount + unit->OrderCount - (unit->OrderFlush ? 1 : 0) <= unit->Type->MaxOnBoard) {
diff --git a/src/editor/editloop.cpp b/src/editor/editloop.cpp
index a51451439..e5881364e 100644
--- a/src/editor/editloop.cpp
+++ b/src/editor/editloop.cpp
@@ -77,10 +77,10 @@ static int IconWidth;                       /// Icon width in panels
 static int IconHeight;                      /// Icon height in panels
 
 
-char EditorRunning;    /// True editor is running
 char EditorMapLoaded;  /// Map loaded in editor
 
-EditorStateType EditorState;  /// Current editor state.
+EditorStateType EditorState;                /// Current editor state.
+EditorRunningType EditorRunning;  /// Running State of editor.
 
 static char TileToolRandom;      /// Tile tool draws random
 static char TileToolDecoration;  /// Tile tool draws with decorations
@@ -201,7 +201,6 @@ void EditTile(int x, int y, int tile)
 
 	UpdateMinimapSeenXY(x, y);
 	UpdateMinimapXY(x, y);
-	MustRedraw |= RedrawMinimap;
 
 	EditorTileChanged(x, y);
 }
@@ -1168,7 +1167,6 @@ static void EditorCallbackButtonDown(unsigned button __attribute__ ((unused)))
 			if (TheMap.Info->PlayerType[CursorPlayer] != PlayerNobody) {
 				SelectedPlayer = CursorPlayer;
 				ThisPlayer = Players + SelectedPlayer;
-				MustRedraw |= RedrawMinimap;
 			}
 			return;
 		}
@@ -2025,7 +2023,7 @@ void EditorMainLoop(void)
 
 	while (1) {
 		EditorMapLoaded = 0;
-		EditorRunning = 1;
+		EditorRunning = EditorEditing;
 
 		CreateEditor();
 
diff --git a/src/include/editor.h b/src/include/editor.h
index 153c7d4ec..7295f86f5 100644
--- a/src/include/editor.h
+++ b/src/include/editor.h
@@ -38,7 +38,15 @@
 ----------------------------------------------------------------------------*/
 
 	/// Editor is running
-extern char EditorRunning;
+typedef enum _editor_running_state_ {
+	EditorNotRunning = 0,   ///< Not Running
+	EditorStarted = 1,      ///< Editor Enabled at all
+	EditorCommandLine = 2,  ///< Called from Command Line
+	EditorEditing = 4       ///< Editor is fully running
+} EditorRunningType;
+
+extern EditorRunningType EditorRunning;
+
 	/// Map loaded in editor
 extern char EditorMapLoaded;
 	/// Current editor state type.
diff --git a/src/include/stratagus.h b/src/include/stratagus.h
index 0462fde78..0698508f7 100644
--- a/src/include/stratagus.h
+++ b/src/include/stratagus.h
@@ -248,6 +248,7 @@ extern char NameLine[];
 	/// Game cycles per second to simulate (original 30-40)
 #define CYCLES_PER_SECOND  30  // 1/30s 0.33ms
 
+#define DEFAULT_START_ORDERS 4  // The number of Orders allocated on unit creation
 	/// Must redraw flags
 enum _must_redraw_flags_ {
 	RedrawNothing   = 1 << 0,           ///< Nothing to do
@@ -275,21 +276,6 @@ enum _must_redraw_flags_ {
 	RedrawEverything    = -1,           ///< Must redraw everything
 };
 
-	/// Must redraw all maps
-#define RedrawMaps        (RedrawMinimap | RedrawMap)
-	/// Must redraw all cursors
-#define RedrawCursors     (RedrawMinimapCursor | RedrawCursor)
-	/// Must redraw all panels
-#define RedrawPanels      (RedrawInfoPanel | RedrawButtonPanel)
-	/// Must redraw after color cycle
-#define RedrawColorCycle  (RedrawMap | RedrawInfoPanel | RedrawButtonPanel | RedrawResources)
-
-	/// Invalidated redraw flags
-extern int MustRedraw;
-
-	/// Enable redraw flags
-extern int EnableRedraw;
-
 /*----------------------------------------------------------------------------
 --  clone.c
 ----------------------------------------------------------------------------*/
diff --git a/src/include/unit.h b/src/include/unit.h
index 795ef657d..9cb37f6cc 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -331,18 +331,23 @@
 **  Unit::OrderCount
 **
 **  The number of the orders unit to process. An unit has atleast
-**  one order. Unit::OrderCount should be a number between 1 and
-**  ::MAX_ORDERS. The orders are in Unit::Orders[].
+**  one order. Unit::OrderCount should be a number at least 1.
+**  The orders are in Unit::Orders[].
 **
 **  Unit::OrderFlush
 **
 **  A flag, which tells the unit to stop with the current order
 **  and immediately start with the next order.
 **
+**  Unit::TotalOrders
+**
+**  The number of Orders allocated for this unit to use.
+**  Default is 4, but is dynamically updated if more orders are
+**  given.
+**
 **  Unit::Orders
 **
 **  Contains all orders of the unit. Slot 0 is always used.
-**  Up to ::MAX_ORDERS can be stored.
 **
 **  Unit::SavedOrder
 **
@@ -596,10 +601,10 @@ struct _unit_ {
 	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
+	int  TotalOrders;           ///< Total Number of orders available
+	Order* Orders;              ///< orders to process
 	Order SavedOrder;           ///< order to continue after current
 	Order NewOrder;             ///< order for new trained units
 	char* AutoCastSpell;        ///< spells to auto cast
@@ -632,10 +637,6 @@ struct _unit_ {
 	} UpgradeTo; ///< Upgrade to action
 	struct _order_train_ {
 		int Ticks;                      ///< Ticks to complete
-		int Count;                      ///< Units in training queue
-		// TODO: vladi: later we should train more units or automatic
-#define MAX_UNIT_TRAIN 6 ///< max number of units in queue
-		UnitType* What[MAX_UNIT_TRAIN]; ///< Unit trained
 	} Train; ///< Train units action
 	} Data; ///< Storage room for different commands
 
@@ -729,6 +730,9 @@ extern int    NumTeamSelected[PlayerMax];  ///< Number of Units a team member ha
 extern Unit* ReleasedHead;                 ///< Head of the released unit list.
 extern Unit* ReleasedTail;                 ///< Tail of the released unit list.
 
+extern Order* ReleasedOrderHead;           ///< Head of the released orders list.
+extern Order* ReleasedOrderTail;           ///< Tail of the released unit list.
+
 /*----------------------------------------------------------------------------
 -- Functions
 ----------------------------------------------------------------------------*/
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 7dfa0395a..a1d25711e 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -207,8 +207,6 @@ void ViewportSetViewpoint(Viewport* vp, int x, int y, int offsetx, int offsety)
 	vp->OffsetY = y % TileSizeY;
 	vp->MapWidth = ((vp->EndX - vp->X) + vp->OffsetX - 1) / TileSizeX + 1;
 	vp->MapHeight = ((vp->EndY - vp->Y) + vp->OffsetY - 1) / TileSizeY + 1;
-
-	MustRedraw |= RedrawMinimap | RedrawMinimapCursor;
 }
 
 /**
diff --git a/src/map/map_rock.cpp b/src/map/map_rock.cpp
index aa4a2187c..6dede6f02 100644
--- a/src/map/map_rock.cpp
+++ b/src/map/map_rock.cpp
@@ -178,7 +178,6 @@ void MapFixSeenRockTile(int x, int y)
 	// FIXME: can this only happen if seen?
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 }
 
@@ -317,7 +316,6 @@ void MapFixRockTile(int x, int y)
 		if (IsMapFieldVisible(ThisPlayer, x, y)) {
 			UpdateMinimapSeenXY(x, y);
 			MapMarkSeenTile(x, y);
-			MustRedraw |= RedrawMinimap;
 		}
 	}
 }
@@ -344,7 +342,6 @@ void MapRemoveRock(unsigned x, unsigned y)
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
 		MapMarkSeenTile(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 #ifdef MAP_REGIONS
 	MapSplitterTilesCleared(x, y, x, y);
diff --git a/src/map/map_wall.cpp b/src/map/map_wall.cpp
index af194631d..d2585767e 100644
--- a/src/map/map_wall.cpp
+++ b/src/map/map_wall.cpp
@@ -165,7 +165,6 @@ void MapFixSeenWallTile(int x, int y)
 		// FIXME: can this only happen if seen?
 		if (IsMapFieldVisible(ThisPlayer, x, y)) {
 			UpdateMinimapSeenXY(x, y);
-			MustRedraw |= RedrawMinimap;
 		}
 	}
 }
@@ -265,7 +264,6 @@ void MapFixWallTile(int x, int y)
 		if (IsMapFieldVisible(ThisPlayer, x, y)) {
 			UpdateMinimapSeenXY(x, y);
 			MapMarkSeenTile(x, y);
-			MustRedraw |= RedrawMinimap;
 		}
 	}
 }
@@ -305,7 +303,6 @@ void MapRemoveWall(unsigned x, unsigned y)
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
 		MapMarkSeenTile(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 #ifdef MAP_REGIONS
 	MapSplitterTilesCleared(x, y, x, y);
@@ -347,7 +344,6 @@ void MapSetWall(unsigned x, unsigned y, int humanwall)
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
 		MapMarkSeenTile(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 #ifdef MAP_REGIONS
 	MapSplitterTilesOccuped(x, y, x, y);
diff --git a/src/map/map_wood.cpp b/src/map/map_wood.cpp
index 01b4e57f7..65df1de80 100644
--- a/src/map/map_wood.cpp
+++ b/src/map/map_wood.cpp
@@ -176,7 +176,6 @@ void MapFixSeenWoodTile(int x, int y)
 	// FIXME: can this only happen if seen?
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 }
 
@@ -313,7 +312,6 @@ void MapFixWoodTile(int x, int y)
 		if (IsMapFieldVisible(ThisPlayer, x, y)) {
 			UpdateMinimapSeenXY(x, y);
 			MapMarkSeenTile(x, y);
-			MustRedraw |= RedrawMinimap;
 		}
 	}
 }
@@ -341,7 +339,6 @@ void MapRemoveWood(unsigned x, unsigned y)
 	if (IsMapFieldVisible(ThisPlayer, x, y)) {
 		UpdateMinimapSeenXY(x, y);
 		MapMarkSeenTile(x, y);
-		MustRedraw |= RedrawMinimap;
 	}
 #ifdef MAP_REGIONS
 	MapSplitterTilesCleared(x, y, x, y);
diff --git a/src/pathfinder/astar.cpp b/src/pathfinder/astar.cpp
index 802edc551..6ce0b276f 100644
--- a/src/pathfinder/astar.cpp
+++ b/src/pathfinder/astar.cpp
@@ -729,6 +729,10 @@ int AStarFindPath(Unit* unit, int gx, int gy, int gw, int gh, int minrange, int
 
 	// let's clean up the matrix now
 	AStarCleanUp(num_in_close);
+	if ((TheMap.Width*TheMap.Height) - counter > 500) {
+		DebugPrint("%s:%d Visited %d tiles\n" _C_ unit->Type->Name _C_ UnitNumber(unit) 
+			_C_ (TheMap.Width*TheMap.Height) - counter);
+	}
 	return path_length;
 }
 
diff --git a/src/stratagus/mainloop.cpp b/src/stratagus/mainloop.cpp
index c81dd8090..f82a2a540 100644
--- a/src/stratagus/mainloop.cpp
+++ b/src/stratagus/mainloop.cpp
@@ -67,6 +67,7 @@
 #include "commands.h"
 #include "cdaudio.h"
 #include "pathfinder.h"
+#include "editor.h"
 
 #ifdef USE_SDLCD
 #include "SDL.h"
@@ -336,7 +337,7 @@ void DrawMapArea(void)
 */
 void UpdateDisplay(void)
 {
-	if (EnableRedraw != RedrawMenu) {
+	if (GameRunning || EditorRunning == EditorEditing) {
 		int i;
 
 		DrawMapArea();
diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp
index 4ab71eba2..43f2d01fd 100644
--- a/src/stratagus/stratagus.cpp
+++ b/src/stratagus/stratagus.cpp
@@ -257,10 +257,6 @@ int SpeedResearch = 1;               ///< speed factor for researching
 ==  DISPLAY
 ============================================================================*/
 
-// FIXME: not the correct place
-int MustRedraw = RedrawEverything;   ///< Redraw flags
-int EnableRedraw = RedrawEverything; ///< Enable flags
-
 unsigned long GameCycle;             ///< Game simulation cycle counter
 unsigned long FastForwardCycle;      ///< Cycle to fastforward to in a replay
 
@@ -664,8 +660,6 @@ void MenuLoop(char* filename, WorldMap* map)
 				PlayMusic(MenuMusic);
 			}
 
-			EnableRedraw = RedrawMenu;
-
 			GuiGameStarted = 0;
 			while (GuiGameStarted == 0) {
 				int old_video_sync;
@@ -673,7 +667,7 @@ void MenuLoop(char* filename, WorldMap* map)
 				old_video_sync = VideoSyncSpeed;
 				VideoSyncSpeed = 100;
 				SetVideoSync();
-				if (EditorRunning == 2) {
+				if (EditorRunning == EditorCommandLine) {
 					SetupEditor();
 				}
 				if (EditorRunning) {
@@ -685,7 +679,6 @@ void MenuLoop(char* filename, WorldMap* map)
 				SetVideoSync();
 			}
 
-			EnableRedraw = RedrawEverything;
 			DebugPrint("Menu start: NetPlayers %d\n" _C_ NetPlayers);
 			filename = CurrentMapPath;
 		} else {
@@ -983,7 +976,7 @@ int main(int argc, char** argv)
 				}
 				continue;
 			case 'e':
-				EditorRunning = 2;
+				EditorRunning = EditorCommandLine;
 				continue;
 			case 'E':
 				EditorStartFile = optarg;
diff --git a/src/ui/botpanel.cpp b/src/ui/botpanel.cpp
index d03172ac7..efccd6173 100644
--- a/src/ui/botpanel.cpp
+++ b/src/ui/botpanel.cpp
@@ -811,8 +811,7 @@ void DoButtonButtonClicked(int button)
 			break;
 
 		case ButtonCancelTrain:
-			Assert(Selected[0]->Orders[0].Action == UnitActionTrain &&
-				Selected[0]->Data.Train.Count);
+			Assert(Selected[0]->Orders[0].Action == UnitActionTrain);
 			SendCommandCancelTraining(Selected[0], -1, NULL);
 			ClearStatusLine();
 			ClearCosts();
@@ -848,8 +847,7 @@ void DoButtonButtonClicked(int button)
 			// FIXME: training queue full check is not correct for network.
 			// FIXME: this can be correct written, with a little more code.
 			if (Selected[0]->Orders[0].Action == UnitActionTrain &&
-					(Selected[0]->Data.Train.Count == MAX_UNIT_TRAIN ||
-						!EnableTrainingQueue)) {
+					!EnableTrainingQueue) {
 				NotifyPlayer(Selected[0]->Player, NotifyYellow, Selected[0]->X,
 					Selected[0]->Y, "Unit training queue is full");
 			} else if (PlayerCheckLimits(Selected[0]->Player, type) >= 0 &&
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 7d248e29c..be79ff7ef 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -461,8 +461,6 @@ static void UiToggleBigMap(void)
 
 		SetViewportMode(TheUI.ViewportMode);
 
-		EnableRedraw = RedrawMap | RedrawCursor | RedrawMessage | RedrawMenu |
-			RedrawTimer | RedrawAll;
 		SetStatusLine("Big map enabled");
 	} else {
 		TheUI.MapArea.X = mapx;
@@ -472,7 +470,6 @@ static void UiToggleBigMap(void)
 
 		SetViewportMode(TheUI.ViewportMode);
 
-		EnableRedraw = RedrawEverything;
 		SetStatusLine("Returning to old map");
 	}
 }
@@ -559,7 +556,6 @@ static void UiToggleTerrain(void)
 	} else {
 		SetStatusLine("Terrain hidden.");
 	}
-	MustRedraw |= RedrawMinimap;
 }
 
 /**
diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp
index 48b7ccc0a..c97cbee79 100644
--- a/src/ui/mainscr.cpp
+++ b/src/ui/mainscr.cpp
@@ -375,20 +375,20 @@ static void DrawUnitInfo(const Unit* unit)
 		//  Building training units.
 		//
 		if (unit->Orders[0].Action == UnitActionTrain) {
-			if (unit->Data.Train.Count == 1) {
+			if (unit->Orders[1].Action != UnitActionTrain) {
 				if (TheUI.SingleTrainingText) {
 					VideoDrawText(TheUI.SingleTrainingTextX, TheUI.SingleTrainingTextY,
 						TheUI.SingleTrainingFont, TheUI.SingleTrainingText);
 				}
 				if (TheUI.SingleTrainingButton) {
-					DrawUnitIcon(unit->Player, unit->Data.Train.What[0]->Icon.Icon,
+					DrawUnitIcon(unit->Player, unit->Orders[0].Type->Icon.Icon,
 						(ButtonAreaUnderCursor == ButtonAreaTraining &&
 							ButtonUnderCursor == 0) ?
 							(IconActive | (MouseButtons & LeftButton)) : 0,
 						TheUI.SingleTrainingButton->X, TheUI.SingleTrainingButton->Y);
 				}
 
-				UiDrawCompletedBar(unit->Data.Train.What[0]->Stats[
+				UiDrawCompletedBar(unit->Orders[0].Type->Stats[
 					unit->Player->Player].Costs[TimeCost],
 					unit->Data.Train.Ticks);
 			} else {
@@ -397,17 +397,19 @@ static void DrawUnitInfo(const Unit* unit)
 						TheUI.TrainingFont, TheUI.TrainingText);
 				}
 				if (TheUI.TrainingButtons) {
-					for (i = 0; i < unit->Data.Train.Count &&
+					for (i = 0; i < unit->OrderCount &&
 							i < TheUI.NumTrainingButtons; ++i) {
-						DrawUnitIcon(unit->Player, unit->Data.Train.What[i]->Icon.Icon,
-							(ButtonAreaUnderCursor == ButtonAreaTraining &&
-								ButtonUnderCursor == i) ?
-								(IconActive | (MouseButtons & LeftButton)) : 0,
-							TheUI.TrainingButtons[i].X, TheUI.TrainingButtons[i].Y);
+						if (unit->Orders[i].Action == UnitActionTrain) {
+							DrawUnitIcon(unit->Player, unit->Orders[i].Type->Icon.Icon,
+								(ButtonAreaUnderCursor == ButtonAreaTraining &&
+									ButtonUnderCursor == i) ?
+									(IconActive | (MouseButtons & LeftButton)) : 0,
+								TheUI.TrainingButtons[i].X, TheUI.TrainingButtons[i].Y);
+						}
 					}
 				}
 
-				UiDrawCompletedBar(unit->Data.Train.What[0]->Stats[
+				UiDrawCompletedBar(unit->Orders[0].Type->Stats[
 					unit->Player->Player].Costs[TimeCost],
 					unit->Data.Train.Ticks);
 			}
diff --git a/src/ui/menus.cpp b/src/ui/menus.cpp
index 3a56d6b6f..c388a0701 100644
--- a/src/ui/menus.cpp
+++ b/src/ui/menus.cpp
@@ -1837,7 +1837,6 @@ static void SetFogOfWar(Menuitem *mi __attribute__((unused)))
 		UpdateFogOfWarChange();
 		CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, "fow on", -1);
 	}
-	MustRedraw &= ~RedrawMinimap;
 }
 
 /**
@@ -4718,7 +4717,7 @@ static void StartEditor(void)
 {
 	SetupEditor();
 
-	EditorRunning = 1;
+	EditorRunning = EditorStarted;
 	EndMenu();
 }
 
@@ -4763,7 +4762,7 @@ void SetupEditor(void)
 static void EditorSelectCancel(void)
 {
 	QuitToMenu = 1;
-	EditorRunning = 0;
+	EditorRunning = EditorNotRunning;
 	EndMenu();
 }
 
@@ -5349,7 +5348,7 @@ void EditorLoadMenu(void)
 	}
 
 	EditorMapLoaded = 1;
-	EditorRunning = 0;
+	EditorRunning = EditorNotRunning;
 	EndMenu();
 }
 
@@ -6193,7 +6192,7 @@ static void EditorSaveConfirmCancel(void)
 static void EditorQuitToMenu(void)
 {
 	QuitToMenu = 1;
-	EditorRunning = 0;
+	EditorRunning = EditorNotRunning;
 	EndMenu();
 }
 
diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp
index 75475d855..32978d53f 100644
--- a/src/ui/mouse.cpp
+++ b/src/ui/mouse.cpp
@@ -445,7 +445,7 @@ static void HandleMouseOn(int x, int y)
 	}
 	if (NumSelected == 1 && Selected[0]->Type->Building && !BigMapMode) {
 		if (Selected[0]->Orders[0].Action == UnitActionTrain) {
-			if (Selected[0]->Data.Train.Count == 1) {
+			if (Selected[0]->OrderCount == 1) {
 				if (TheUI.SingleTrainingButton &&
 						x >= TheUI.SingleTrainingButton->X &&
 						x < TheUI.SingleTrainingButton->X + TheUI.SingleTrainingButton->Width + 7 &&
@@ -457,10 +457,10 @@ static void HandleMouseOn(int x, int y)
 					return;
 				}
 			} else {
-				i = (TheUI.NumTrainingButtons < Selected[0]->Data.Train.Count) ?
-					TheUI.NumTrainingButtons : Selected[0]->Data.Train.Count;
-				for (--i; i >= 0; --i) {
-					if (x >= TheUI.TrainingButtons[i].X &&
+				for (i = 0; i < Selected[0]->OrderCount &&
+					i < TheUI.NumTrainingButtons; ++i) {
+					if (Selected[0]->Orders[i].Action == UnitActionTrain &&
+							x >= TheUI.TrainingButtons[i].X &&
 							x < TheUI.TrainingButtons[i].X + TheUI.TrainingButtons[i].Width + 7 &&
 							y >= TheUI.TrainingButtons[i].Y &&
 							y < TheUI.TrainingButtons[i].Y + TheUI.TrainingButtons[i].Height + 7) {
@@ -1482,7 +1482,6 @@ void UIHandleButtonDown(unsigned button)
 			if (NumSelected && Selected[0]->Player == ThisPlayer &&
 					CursorState == CursorStatePoint) {
 				CursorState = CursorStatePieMenu;
-				MustRedraw |= RedrawCursor;
 			}
 		} else if (MouseButtons & LeftButton) { // enter select mode
 			CursorStartX = CursorX;
@@ -1587,13 +1586,14 @@ void UIHandleButtonDown(unsigned button)
 			} else if (ButtonAreaUnderCursor == ButtonAreaTraining) {
 				if (!GameObserve && !GamePaused &&
 					PlayersTeamed(ThisPlayer->Player, Selected[0]->Player->Player)) {
-					if (ButtonUnderCursor < Selected[0]->Data.Train.Count) {
+					if (ButtonUnderCursor < Selected[0]->OrderCount &&
+						Selected[0]->Orders[ButtonUnderCursor].Action == UnitActionTrain) {
 						DebugPrint("Cancel slot %d %s\n" _C_
 							ButtonUnderCursor _C_
-							Selected[0]->Data.Train.What[ButtonUnderCursor]->Ident);
+							Selected[0]->Orders[ButtonUnderCursor].Type->Ident);
 						SendCommandCancelTraining(Selected[0],
 							ButtonUnderCursor,
-							Selected[0]->Data.Train.What[ButtonUnderCursor]);
+							Selected[0]->Orders[ButtonUnderCursor].Type);
 					}
 				}
 			//
diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp
index bc8fa1792..cbdcd3dcb 100644
--- a/src/unit/script_unit.cpp
+++ b/src/unit/script_unit.cpp
@@ -348,12 +348,9 @@ void CclParseOrder(lua_State* l, Order* order)
 */
 static void CclParseOrders(lua_State* l, Unit* unit)
 {
-	int args;
 	int j;
 
-	args = luaL_getn(l, -1);
-	Assert(args == MAX_ORDERS);
-	for (j = 0; j < args; ++j) {
+	for (j = 0; j < unit->TotalOrders; ++j) {
 		lua_rawgeti(l, -1, j + 1);
 		CclParseOrder(l, &unit->Orders[j]);
 		lua_pop(l, 1);
@@ -514,7 +511,6 @@ static void CclParseUpgradeTo(lua_State* l, Unit* unit)
 static void CclParseTrain(lua_State* l, Unit* unit)
 {
 	const char* value;
-	int i;
 	int args;
 	int j;
 
@@ -531,30 +527,6 @@ static void CclParseTrain(lua_State* l, Unit* unit)
 			lua_rawgeti(l, -1, j + 1);
 			unit->Data.Train.Ticks = LuaToNumber(l, -1);
 			lua_pop(l, 1);
-		} else if (!strcmp(value, "count")) {
-			lua_rawgeti(l, -1, j + 1);
-			unit->Data.Train.Count = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "queue")) {
-			int subargs;
-			int k;
-
-			lua_rawgeti(l, -1, j + 1);
-			if (!lua_istable(l, -1)) {
-				LuaError(l, "incorrect argument");
-			}
-			subargs = luaL_getn(l, -1);
-			for (i = 0, k = 0; i < MAX_UNIT_TRAIN && k < subargs; ++i, ++k) {
-				lua_rawgeti(l, -1, k + 1);
-				value = LuaToString(l, -1);
-				lua_pop(l, 1);
-				if (!strcmp(value, "unit-none")) {
-					unit->Data.Train.What[i] = NULL;
-				} else {
-					unit->Data.Train.What[i] = UnitTypeByIdent(value);
-				}
-			}
-			lua_pop(l, 1);
 		}
 	}
 }
@@ -859,6 +831,11 @@ static int CclUnit(lua_State* l)
 			unit->OrderCount = LuaToNumber(l, j + 1);
 		} else if (!strcmp(value, "order-flush")) {
 			unit->OrderFlush = LuaToNumber(l, j + 1);
+		} else if (!strcmp(value, "order-total")) {
+			unit->TotalOrders = LuaToNumber(l, j + 1);
+			free(unit->Orders);
+			// Allocate the space for orders
+			unit->Orders = calloc(unit->TotalOrders, sizeof(Order));
 		} else if (!strcmp(value, "orders")) {
 			int hp;
 
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 54514d33c..7fcd5e759 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -74,6 +74,9 @@ Unit** UnitSlotFree;                      ///< First free unit slot
 Unit* ReleasedHead;                       ///< List of released units.
 Unit* ReleasedTail;                       ///< List tail of released units.
 
+Order* ReleasedOrderHead;                 ///< List of released Orders.
+Order* ReleasedOrderTail;                 ///< List tail of released orders.
+
 Unit* Units[MAX_UNIT_SLOTS];              ///< Array of used slots
 int NumUnits;                             ///< Number of slots used
 
@@ -225,6 +228,18 @@ void ReleaseUnit(Unit* unit)
 	unit->Refs = GameCycle + (NetworkMaxLag << 1); // could be reuse after this time
 	unit->Type = 0;  // for debugging.
 	free(unit->CacheLinks);
+
+	if (ReleasedOrderHead) {
+		ReleasedOrderTail->Arg1 = unit->Orders;
+		ReleasedOrderTail = unit->Orders;
+		unit->Orders->Arg1 = NULL;
+	} else {
+		ReleasedOrderHead = ReleasedOrderTail = unit->Orders;
+		unit->Orders->Arg1 = NULL;
+	}
+	unit->Orders->X = GameCycle + (NetworkMaxLag << 1); // could be reuse after this time
+	unit->Orders->Y = unit->TotalOrders; // store order count for when reused
+	unit->Orders = NULL;
 }
 
 /**
@@ -339,6 +354,18 @@ void InitUnit(Unit* unit, UnitType* type)
 
 	unit->Rs = MyRand() % 100; // used for fancy buildings and others
 
+	// Init Orders and Default to Still/None
+	if (ReleasedOrderHead && (unsigned)ReleasedOrderHead->X < GameCycle) {
+		unit->Orders = ReleasedOrderHead;
+		unit->TotalOrders = ReleasedOrderHead->Y;
+		ReleasedOrderHead = (Order*)ReleasedOrderHead->Arg1;
+	} else {
+		// No Available Orders in Memory, create new ones
+		unit->TotalOrders = DEFAULT_START_ORDERS;
+		unit->Orders = calloc(unit->TotalOrders, sizeof(Order));
+	}
+
+
 	unit->OrderCount = 1; // No orders
 	unit->Orders[0].Action = UnitActionStill;
 	unit->Orders[0].X = unit->Orders[0].Y = -1;
@@ -596,7 +623,6 @@ static void MarkUnitFieldFlags(const Unit* unit)
 		MapSplitterTilesOccuped(x, y, x + type->TileWidth - 1, y + type->TileHeight - 1);
 	}
 #endif
-
 }
 
 /**
@@ -761,7 +787,6 @@ void PlaceUnit(Unit* unit, int x, int y)
 	// Vision
 	MapMarkUnitSight(unit);
 
-	MustRedraw |= RedrawMinimap;
 	UnitCountSeen(unit);
 }
 
@@ -832,7 +857,6 @@ void RemoveUnit(Unit* unit, Unit* host)
 	if (unit == UnitUnderCursor) {
 		UnitUnderCursor = NULL;
 	}
-	MustRedraw |= RedrawMinimap;
 }
 
 /**
@@ -3576,8 +3600,9 @@ void SaveUnit(const Unit* unit, CLFile* file)
 	}
 	CLprintf(file, "\"order-count\", %d,\n  ", unit->OrderCount);
 	CLprintf(file, "\"order-flush\", %d,\n  ", unit->OrderFlush);
+	CLprintf(file, "\"order-total\", %d,\n	", unit->TotalOrders);
 	CLprintf(file, "\"orders\", {");
-	for (i = 0; i < MAX_ORDERS; ++i) {
+	for (i = 0; i < unit->TotalOrders; ++i) {
 		CLprintf(file, "\n ");
 		SaveOrder(&unit->Orders[i], file);
 		CLprintf(file, ",");
@@ -3643,17 +3668,7 @@ void SaveUnit(const Unit* unit, CLFile* file)
 		case UnitActionTrain:
 			CLprintf(file, ",\n  \"data-train\", {");
 			CLprintf(file, "\"ticks\", %d, ", unit->Data.Train.Ticks);
-			CLprintf(file, "\"count\", %d, ", unit->Data.Train.Count);
-			CLprintf(file, "\"queue\", {");
-			for (i = 0; i < MAX_UNIT_TRAIN; ++i) {
-				if (i < unit->Data.Train.Count) {
-					CLprintf(file, "\"%s\", ", unit->Data.Train.What[i]->Ident);
-				} else {
-					/* this slot is currently unused */
-					CLprintf(file, "\"unit-none\", ");
-				}
-			}
-			CLprintf(file, "}}");
+			CLprintf(file, "}");
 			break;
 		default:
 			CLprintf(file, ",\n  \"data-move\", {");
@@ -3791,6 +3806,7 @@ void CleanUnits(void)
 {
 	Unit** table;
 	Unit* unit;
+	Order* order;
 
 	//
 	//  Free memory for all units in unit table.
@@ -3809,6 +3825,14 @@ void CleanUnits(void)
 		ReleasedHead = unit->Next;
 		free(unit);
 	}
+
+	//
+	//  Release memory of Orders in the release queue.
+	while ((order = ReleasedOrderHead)) {
+		ReleasedOrderHead = order->Arg1;
+		free(order);
+	}
+
 	InitUnitsMemory();
 
 	XpDamage = 0;
diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp
index 031350545..6aafa52fe 100644
--- a/src/unit/unit_draw.cpp
+++ b/src/unit/unit_draw.cpp
@@ -1083,7 +1083,7 @@ static void DrawDecoration(const Unit* unit, const UnitType* type, int x, int y)
 	if (unit->Orders[0].Action == UnitActionTrain) {
 		unit->Variable[TRAINING_INDEX].Value = unit->Data.Train.Ticks;
 		unit->Variable[TRAINING_INDEX].Max =
-			unit->Data.Train.What[0]->Stats[unit->Player->Player].Costs[TimeCost];
+			unit->Orders[0].Type->Stats[unit->Player->Player].Costs[TimeCost];
 	}
 
 	// UpgradeTo
diff --git a/src/unit/upgrade.cpp b/src/unit/upgrade.cpp
index 8f6f1646e..46a04d139 100644
--- a/src/unit/upgrade.cpp
+++ b/src/unit/upgrade.cpp
@@ -1165,16 +1165,16 @@ static void ConvertUnitTypeTo(Player* player, const UnitType* src, UnitType* dst
 		//  FIXME: what about buildings?
 		//
 		} else {
-			if (unit->Orders[0].Action == UnitActionTrain) {
-				for (j = 0; j < unit->Data.Train.Count; ++j) {
-					if (unit->Data.Train.What[j] == src) {
-						unit->Data.Train.What[j] = dst;
-					}
-				}
-			}
-			for (j = 1; j < unit->OrderCount; ++j) {
+			for (j = 0; j < unit->OrderCount; ++j) {
 				if (unit->Orders[j].Action == UnitActionTrain &&
 						unit->Orders[j].Type == src) {
+						if (j == 0) {
+							// Must Adjust Ticks to the fraction that was trained
+							unit->Data.Train.Ticks = 
+								unit->Data.Train.Ticks *
+								dst->Stats[player->Player].Costs[TimeCost] /
+								src->Stats[player->Player].Costs[TimeCost];
+						}
 					unit->Orders[j].Type = dst;
 				}
 			}