diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index 8b02d496e..6de7a80ba 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -336,7 +336,7 @@ CUnit *const COrder_Attack::BestTarget(const CUnit &unit, CUnit *const target1,
 	Assert(target1 != NULL);
 	Assert(target2 != NULL);
 
-	return (Preference.SimplifiedAutoTargeting 
+	return (GameSettings.SimplifiedAutoTargeting 
 				? ((TargetPriorityCalculate(&unit, target1) > TargetPriorityCalculate(&unit, target2)) ? target1 : target2)
 				: ((ThreatCalculate(unit, *target1) < ThreatCalculate(unit, *target2)) ?  target1 : target2));
 }
@@ -447,7 +447,7 @@ void COrder_Attack::SetAutoTarget(CUnit &unit, CUnit *target)
 		this->SkirmishRange = this->Range;
 	}
 	// Set threshold value only for aggressive units (Prevent to change target)
-	if (!Preference.SimplifiedAutoTargeting && target->IsAgressive())
+	if (!GameSettings.SimplifiedAutoTargeting && target->IsAgressive())
 	{
 		unit.Threshold = 30;
 	}
@@ -503,7 +503,7 @@ bool COrder_Attack::AutoSelectTarget(CUnit &unit)
 			if (unit.UnderAttack && !newTarget->IsAgressive()) {
 				return true;
 			}
-			if (Preference.SimplifiedAutoTargeting) {
+			if (GameSettings.SimplifiedAutoTargeting) {
 				const int goal_priority			= TargetPriorityCalculate(&unit, goal);
 				const int newTarget_priority 	= TargetPriorityCalculate(&unit, newTarget);
 
diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp
index 6ca25d3f3..51801b6da 100644
--- a/src/ai/ai_resource.cpp
+++ b/src/ai/ai_resource.cpp
@@ -34,6 +34,7 @@
 --  Includes
 ----------------------------------------------------------------------------*/
 
+#include "settings.h"
 #include "stratagus.h"
 
 #include "ai_local.h"
@@ -806,7 +807,7 @@ static bool AiUpgradeTo(const CUnitType &type, CUnitType &what)
 {
 	std::vector<CUnit *> table;
 
-	if (Preference.AiChecksDependencies || IsNetworkGame()) {
+	if (GameSettings.AiChecksDependencies || IsNetworkGame()) {
 		if (!CheckDependByType(*AiPlayer->Player, what)) {
 			return false;
 		}
@@ -1467,7 +1468,7 @@ void AiAddUnitTypeRequest(CUnitType &type, int count)
 */
 void AiExplore(const Vec2i &pos, int mask)
 {
-	if (!Preference.AiExplores) {
+	if (!GameSettings.AiExplores) {
 		return;
 	}
 	AiExplorationRequest req(pos, mask);
diff --git a/src/include/settings.h b/src/include/settings.h
index 794df0ad8..99256ad7a 100644
--- a/src/include/settings.h
+++ b/src/include/settings.h
@@ -246,7 +246,10 @@ struct Settings {
 		struct {
 			unsigned NoFogOfWar:1;        /// if dynamic fog of war is disabled
 			unsigned Inside:1;            /// if game uses interior tileset or is generally "inside" for the purpose of obstacles
-			unsigned UserGameSettings:30; /// A bitfield for use by games and their settings
+			unsigned AiExplores:1;        /// If true, AI sends explorers to search for resources (almost useless thing)
+			unsigned SimplifiedAutoTargeting:1; /// Use alternate target choosing algorithm for auto attack mode (idle, attack-move, patrol, etc.)
+			unsigned AiChecksDependencies:1; /// If false, the AI can do upgrades even if the dependencies are not met. This can be desirable to simplify AI scripting.
+			unsigned UserGameSettings:27; /// A bitfield for use by games and their settings
 		};
 		uint32_t _Bitfield;
 	};
@@ -340,6 +343,9 @@ struct Settings {
 		DefeatReveal = RevealTypes::cAllUnits;
 		NoFogOfWar = 0;
 		Inside = 0;
+		AiExplores = 1;
+		AiChecksDependencies = 0;
+		SimplifiedAutoTargeting = 0;
 		UserGameSettings = 0;
 	}
 };
diff --git a/src/include/unit.h b/src/include/unit.h
index 755a67382..8f5db6602 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -36,6 +36,7 @@
 --  Includes
 ----------------------------------------------------------------------------*/
 
+#include "settings.h"
 #include <vector>
 
 #ifndef __UNITTYPE_H__
@@ -445,10 +446,10 @@ class CPreference
 public:
 	CPreference() : ShowSightRange(false), ShowReactionRange(false),
 		ShowAttackRange(false), ShowMessages(true), ShowNoSelectionStats(true), BigScreen(false),
-		PauseOnLeave(true), AiExplores(true), GrayscaleIcons(false),
+		PauseOnLeave(true), GrayscaleIcons(false),
 		IconsShift(false), StereoSound(true), MineNotifications(false),
-		DeselectInMine(false), NoStatusLineTooltips(false), SimplifiedAutoTargeting(false),
-		AiChecksDependencies(false), SelectionRectangleIndicatesDamage(false),
+		DeselectInMine(false), NoStatusLineTooltips(false),
+		SelectionRectangleIndicatesDamage(false),
 		IconFrameG(NULL), PressedIconFrameG(NULL), HardwareCursor(false),
 		ShowOrders(0), ShowNameDelay(0), ShowNameTime(0), AutosaveMinutes(5) {};
 
@@ -459,15 +460,12 @@ public:
 	bool ShowNoSelectionStats; /// Show stats when no selection is active
 	bool BigScreen;			   /// If true, shows the big screen(without panels)
 	bool PauseOnLeave;         /// If true, game pauses when cursor is gone
-	bool AiExplores;           /// If true, AI sends explorers to search for resources (almost useless thing)
 	bool GrayscaleIcons;       /// Use grayscaled icons for unavailable units, upgrades, etc
 	bool IconsShift;           /// Shift icons slightly when you press on them
 	bool StereoSound;          /// Enables/disables stereo sound effects
 	bool MineNotifications;    /// Show mine is running low/depleted messages
 	bool DeselectInMine;       /// Deselect peasants in mines
 	bool NoStatusLineTooltips; /// Don't show messages on status line
-	bool SimplifiedAutoTargeting; /// Use alternate target choosing algorithm for auto attack mode (idle, attack-move, patrol, etc.)
-	bool AiChecksDependencies; /// If false, the AI can do upgrades even if the dependencies are not met. This can be desirable to simplify AI scripting.
 	bool HardwareCursor;    /// If true, uses the hardware to draw the cursor. Shaders do no longer apply to the cursor, but this way it's decoupled from the game refresh rate
 	bool SelectionRectangleIndicatesDamage; /// If true, the selection rectangle interpolates color to indicate damage
 
@@ -475,9 +473,27 @@ public:
 	int ShowNameDelay;		/// How many cycles need to wait until unit's name popup will appear.
 	int ShowNameTime;		/// How many cycles need to show unit's name popup.
 	int AutosaveMinutes;	/// Autosave the game every X minutes; autosave is disabled if the value is 0
-
 	CGraphic *IconFrameG;
 	CGraphic *PressedIconFrameG;
+
+#if USING_TOLUAPP
+	// these are "preferences" in the sense that the user wants to set these
+	// persistently across launches for single player games. However, they are
+	// relevant for network sync and replays, so the actually relevant storage
+	// is in GameSettings, and we just have properties for the lua code here
+private:
+	bool AiExplores;
+	bool SimplifiedAutoTargeting;
+	bool AiChecksDependencies;
+
+public:
+	bool get_AiExplores() { return AiExplores; }
+	void set_AiExplores(bool v) { AiExplores = GameSettings.AiExplores = v; }
+	bool get_SimplifiedAutoTargeting() { return SimplifiedAutoTargeting; }
+	void set_SimplifiedAutoTargeting(bool v) { SimplifiedAutoTargeting = GameSettings.SimplifiedAutoTargeting = v; }
+	bool get_AiChecksDependencies() { return AiChecksDependencies; }
+	void set_AiChecksDependencies(bool v) { AiChecksDependencies = GameSettings.AiChecksDependencies = v; }
+#endif
 };
 
 extern CPreference Preference;
diff --git a/src/map/fov.cpp b/src/map/fov.cpp
index a73a5afaa..efea78a82 100644
--- a/src/map/fov.cpp
+++ b/src/map/fov.cpp
@@ -137,7 +137,7 @@ void CFieldOfView::Refresh(const CPlayer &player, const CUnit &unit, const Vec2i
 	if (!range) {
 		return;
 	}
-	if (GameSettings.FoV == FieldOfViewTypes::cShadowCasting && !unit.Type->AirUnit) { 
+	if (GameSettings.FoV == FieldOfViewTypes::cShadowCasting && !unit.Type->AirUnit) {
 		/// FIXME: add high-/lowground
 		OpaqueFields = unit.Type->BoolFlag[ELEVATED_INDEX].value ? 0 : this->Settings.OpaqueFields;
 		if (GameSettings.Inside) {
diff --git a/src/network/commands.cpp b/src/network/commands.cpp
index bea363402..e1dc5a375 100644
--- a/src/network/commands.cpp
+++ b/src/network/commands.cpp
@@ -806,7 +806,7 @@ void ExecExtendedCommand(unsigned char type, int status,
 		case ExtendedMessageAutoTargetingDB:
 			/// arg1: 0:true / 1:false
 			if (arg1 == 0 || arg1 == 1) {
-				Preference.SimplifiedAutoTargeting = arg1 ? true : false;
+				GameSettings.SimplifiedAutoTargeting = arg1 ? true : false;
 				/// CommandLog(...);
 			} else {
 				/// CommandLog(...);
diff --git a/src/tolua/unit.pkg b/src/tolua/unit.pkg
index 0e6ba23d1..4b220e26c 100644
--- a/src/tolua/unit.pkg
+++ b/src/tolua/unit.pkg
@@ -25,15 +25,15 @@ class CPreference
 	bool ShowNoSelectionStats;
 	bool BigScreen;
 	bool PauseOnLeave;
-	bool AiExplores;
+	tolua_property bool AiExplores;
 	bool GrayscaleIcons;
 	bool IconsShift;
 	bool StereoSound;
 	bool MineNotifications;
 	bool DeselectInMine;
 	bool NoStatusLineTooltips;
-	bool SimplifiedAutoTargeting;
-	bool AiChecksDependencies;
+	tolua_property bool SimplifiedAutoTargeting;
+	tolua_property bool AiChecksDependencies;
 	bool HardwareCursor;
 	bool SelectionRectangleIndicatesDamage;
 
diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp
index f0dd3f3db..84ceef76a 100644
--- a/src/unit/script_unit.cpp
+++ b/src/unit/script_unit.cpp
@@ -1516,7 +1516,7 @@ static int CclEnableSimplifiedAutoTargeting(lua_State *l)
 	LuaCheckArgs(l, 1);
 	const bool isSimplified = LuaToBoolean(l, 1);
 	if (!IsNetworkGame()) {
-		Preference.SimplifiedAutoTargeting = isSimplified;
+		GameSettings.SimplifiedAutoTargeting = isSimplified;
 	} else {
 		NetworkSendExtendedCommand(ExtendedMessageAutoTargetingDB, 
 								   int(isSimplified), 0, 0, 0, 0);
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index ab7d853c5..21cedacae 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -2553,7 +2553,7 @@ void DestroyAllInside(CUnit &source)
 int ThreatCalculate(const CUnit &unit, const CUnit &dest)
 {
 
-	if (Preference.SimplifiedAutoTargeting) {
+	if (GameSettings.SimplifiedAutoTargeting) {
 		// Original algorithm return smaler values for better targets
 		return -TargetPriorityCalculate(&unit, &dest);
 	}
@@ -3157,7 +3157,7 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage, const Missile *missile)
 		return;
 	}
 
-	if (Preference.SimplifiedAutoTargeting) {
+	if (GameSettings.SimplifiedAutoTargeting) {
 		target.Threshold = 0;
 	} else {		
 		const int threshold = 30;
diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp
index c83fd647c..52d2d6eb0 100644
--- a/src/unit/unit_find.cpp
+++ b/src/unit/unit_find.cpp
@@ -692,12 +692,12 @@ private:
 	CUnit *Find(Iterator begin, Iterator end) const
 	{
 		CUnit *enemy = NULL;
-		int best_cost = Preference.SimplifiedAutoTargeting ? INT_MIN : INT_MAX;
+		int best_cost = GameSettings.SimplifiedAutoTargeting ? INT_MIN : INT_MAX;
 
 		for (Iterator it = begin; it != end; ++it) {
-			int cost = Preference.SimplifiedAutoTargeting ? TargetPriorityCalculate(attacker, *it) : ComputeCost(*it);
+			int cost = GameSettings.SimplifiedAutoTargeting ? TargetPriorityCalculate(attacker, *it) : ComputeCost(*it);
 
-			if (Preference.SimplifiedAutoTargeting ? (cost > best_cost) : (cost < best_cost)) {
+			if (GameSettings.SimplifiedAutoTargeting ? (cost > best_cost) : (cost < best_cost)) {
 				enemy = *it;
 				best_cost = cost;
 			}
@@ -975,7 +975,7 @@ public:
 
 	CUnit *Find(std::vector<CUnit *> &table)
 	{
-		if (!Preference.SimplifiedAutoTargeting) {
+		if (!GameSettings.SimplifiedAutoTargeting) {
 			FillBadGood(*attacker, range, good, bad, size).Fill(table.begin(), table.end());
 		}
 		return Find(table.begin(), table.end());
@@ -1005,7 +1005,7 @@ private:
 			return;
 		}
 
-		if (Preference.SimplifiedAutoTargeting) {
+		if (GameSettings.SimplifiedAutoTargeting) {
 			const int cost = TargetPriorityCalculate(attacker, dest);
 			if (cost > best_cost) {
 				best_unit = dest;