Index: engine_gui.c
===================================================================
--- engine_gui.c	(revision 676)
+++ engine_gui.c	(working copy)
@@ -15,15 +15,17 @@
 
 StringID GetEngineCategoryName(byte engine)
 {
-	if (engine < NUM_NORMAL_RAIL_ENGINES)
-		return STR_8102_RAILROAD_LOCOMOTIVE;
+	if (engine < NUM_TRAIN_ENGINES) {
+		switch (_engines[engine].railtype) {
+			case 0:
+				return STR_8102_RAILROAD_LOCOMOTIVE;
+			case 1:
+				return STR_8106_MONORAIL_LOCOMOTIVE;
+			case 2:
+				return STR_8107_MAGLEV_LOCOMOTIVE;
+		}
+	}
 
-	if (engine < NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES)
-		return STR_8106_MONORAIL_LOCOMOTIVE;
-
-	if (engine < NUM_TRAIN_ENGINES)
-		return STR_8107_MAGLEV_LOCOMOTIVE;
-
 	if (engine < NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES)
 		return STR_8103_ROAD_VEHICLE;
 
Index: train_gui.c
===================================================================
--- train_gui.c	(revision 676)
+++ train_gui.c	(working copy)
@@ -14,24 +14,7 @@
 
 int _traininfo_vehicle_pitch = 0;
 
-static Engine * const _rail_engines[3] = {
-	&_engines[0],
-	&_engines[NUM_NORMAL_RAIL_ENGINES],
-	&_engines[NUM_MONORAIL_ENGINES + NUM_NORMAL_RAIL_ENGINES],
-};
 
-const byte _rail_engines_count[3] = {
-	NUM_NORMAL_RAIL_ENGINES,
-	NUM_MONORAIL_ENGINES,
-	NUM_MAGLEV_ENGINES,
-};
-
-const byte _rail_engines_start[3] = {
-	0,
-	NUM_NORMAL_RAIL_ENGINES,
-	NUM_MONORAIL_ENGINES + NUM_NORMAL_RAIL_ENGINES,
-};
-
 static void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2)
 {
 	Vehicle *v,*found;
@@ -85,12 +68,15 @@
 
 		{
 			int count = 0;
-			int num = _rail_engines_count[WP(w,buildtrain_d).railtype];
-			Engine *e = _rail_engines[WP(w,buildtrain_d).railtype];
-			do {
-				if (HASBIT(e->player_avail, _local_player))
+			byte railtype = WP(w,buildtrain_d).railtype;
+			int i;
+
+			for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
+				Engine *e = &_engines[i];
+				if (e->railtype == railtype
+				    && HASBIT(e->player_avail, _local_player))
 					count++;
-			} while (++e,--num);
+			}
 			SetVScrollCount(w, count);
 		}
 
@@ -98,27 +84,38 @@
 		DrawWindowWidgets(w);
 
 		{
-			int num = _rail_engines_count[WP(w,buildtrain_d).railtype];
-			Engine *e = _rail_engines[WP(w,buildtrain_d).railtype];
+			byte railtype = WP(w,buildtrain_d).railtype;
 			int sel = WP(w,buildtrain_d).sel_index;
 			int pos = w->vscroll.pos;
 			int x = 1;
 			int y = 15;
-			int engine_id = _rail_engines_start[WP(w,buildtrain_d).railtype];
 			int selected_id = -1;
+			int i;
 
-			do {
-				if (HASBIT(e->player_avail, _local_player)) {
-					if (sel==0) selected_id = engine_id;
-					if (IS_INT_INSIDE(--pos, -8, 0)) {
-						DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel==0 ? 0xC : 0x10);
-						DrawTrainEngine(x+29, y+6+_traininfo_vehicle_pitch, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
-						y += 14;
-					}
-					sel--;
-				}
-			} while (++engine_id, ++e,--num);
+			/* Ensure that custom engines which substituted wagons
+			 * are sorted correctly. */
+#define engine_drawing_loop(cmp_) \
+			for (i = 0; i < NUM_TRAIN_ENGINES; i++) { \
+				Engine *e = &_engines[i]; \
+				RailVehicleInfo *rvi = &_rail_vehicle_info[i]; \
+ \
+ 				if (e->railtype != railtype || (rvi->flags & RVI_WAGON) cmp_ 0 \
+				    || !HASBIT(e->player_avail, _local_player)) \
+					continue; \
+ \
+				if (sel == 0) selected_id = i; \
+				if (IS_INT_INSIDE(--pos, -8, 0)) { \
+					DrawString(x+59, y+2, GetCustomEngineName(i), sel == 0 ? 0xC : 0x10); \
+					DrawTrainEngine(x+29, y+6+_traininfo_vehicle_pitch, i, \
+					                SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player))); \
+					y += 14; \
+				} \
+				sel--; \
+			}
 
+			engine_drawing_loop(!=); // True engines
+			engine_drawing_loop(==); // Feeble wagons
+
 			WP(w,buildtrain_d).sel_engine = selected_id;
 
 			if (selected_id != -1) {
Index: ai.c
===================================================================
--- ai.c	(revision 676)
+++ ai.c	(working copy)
@@ -113,25 +113,19 @@
 	p->ai.state_counter = 0;
 }
 
-// XXX
-static const byte _rail_locos_count[3] = {
-	27, 3, 5
-};
-extern const byte _rail_engines_start[3];
-
 static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag)
 {
 	int best_veh_index = -1;
 	byte best_veh_score = 0;
 	int32 r;
+	int i;
 
-	int i = _rail_engines_start[railtype];
-	int end = i + _rail_locos_count[railtype];
-	Engine *e = &_engines[i];
-	do {
-		assert(!(_rail_vehicle_info[i].flags & RVI_WAGON));
+	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
+		RailVehicleInfo *rvi = &_rail_vehicle_info[i];
+		Engine *e = &_engines[i];
 
-		if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
+		if (e->railtype != railtype || rvi->flags & RVI_WAGON
+		    || !HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
 			continue;
 
 		r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_RAIL_VEHICLE);
@@ -142,7 +136,7 @@
 			best_veh_score = _cmd_build_rail_veh_score;
 			best_veh_index = i;
 		}
-	} while (++e, ++i != end);
+	}
 
 	return best_veh_index;
 }
