----------------------------------------------------------------------------------------------------------
-- 
-- 学習スレッド
-- 
-- 続きで覚えないでフラットに覚えるように変更。
-- learning_motion.luaもあわせてみてね。
-- 
----------------------------------------------------------------------------------------------------------
--learningTarget  = TARGET_ENEMY;
learningTarget  = TARGET_MY;

--rootRelation = MotionRelation.new(0);

-- 学習テーブル総元締め
learnTableManager = LearnTableManager.new();

----------------------------------------------------------------------------------------------------------
-- 行動学習スレッド総元締め
----------------------------------------------------------------------------------------------------------
function learningThread()

	-- tracerの初期化が終わるまで待つ。
	yield();

	logger:info("学習スレッド", "総元締めスレッド起動。学習対象:" .. learningTarget);

	------------------------------------------
	-- 学習テーブル登録
	------------------------------------------
	learnTableManager:addLearnTable(AI_NAME_OFFENSIVE,		300);
	learnTableManager:addLearnTable(AI_NAME_KATAME,			300);
	learnTableManager:addLearnTable(AI_NAME_OIUCHI,			300);
	--learnTableManager:addLearnTable(AI_NAME_DEFENSIVE,		300);
	--learnTableManager:addLearnTable(AI_NAME_KAIHIKEKKAI,	300);
	--learnTableManager:addLearnTable(AI_NAME_RECOVERY,		300);
	-- こいつらはFlatに覚える
	--learnTableManager:addFlatLearnTable(AI_NAME_GUARD,		300);
	learnTableManager:addFlatLearnTable(AI_NAME_GUREIZU,	300);

	------------------------------------------
	-- 学習結果の復元
	------------------------------------------
	-- デシリアライズはMainではなくLearnTable初期化後 Factoryとかだるいからね。
	logger:talk("学習結果復元中…。");
	deserializeMotionTable();
	logger:talk("学習結果復元完了。");

	------------------------------------------
	-- 個別学習スレッド起動
	------------------------------------------
	create_thread(learnMotionThread, AI_NAME_OFFENSIVE,		learningTarget, runningLearning, offensiveSituation, learnAttackCondition);
	create_thread(learnMotionThread, AI_NAME_KATAME,		learningTarget, runningLearning, katameSituation, learnAttackCondition);
	create_thread(learnMotionThread, AI_NAME_OIUCHI,		learningTarget, runningLearning, oiuchiSituation, learnAttackCondition);
	--[[
	create_thread(learnMotionThread, AI_NAME_DEFENSIVE,		learningTarget, runningLearning, defensiveSituation, learnAttackCondition);
	create_thread(learnMotionThread, AI_NAME_KAIHIKEKKAI,	learningTarget, runningLearning, kaihikekkaiSituation, learnAttackCondition);
	create_thread(learnMotionThread, AI_NAME_RECOVERY,		learningTarget, runningLearning, recoverySituation, learnAttackCondition);
	create_thread(learnMotionThread, AI_NAME_GUARD,			learningTarget, runningLearning, everyTime);
	]]--
	create_thread(learnMotionThread, AI_NAME_GUREIZU,		learningTarget, runningLearning, everyTime, learnGureizuCondition);

	------------------------------------------
	-- 個別行動連鎖学習スレッド起動
	------------------------------------------
	create_thread(learnRelationThread, AI_NAME_OFFENSIVE,	learningTarget, runningLearning, offensiveSituation, learnAttackCondition);
	create_thread(learnRelationThread, AI_NAME_KATAME,		learningTarget, runningLearning, katameSituation, learnAttackCondition);
	create_thread(learnRelationThread, AI_NAME_OIUCHI,		learningTarget, runningLearning, oiuchiSituation, learnAttackCondition);
	--[[
	create_thread(learnRelationThread, AI_NAME_DEFENSIVE,	learningTarget, runningLearning, defensiveSituation, learnAttackCondition);
	create_thread(learnRelationThread, AI_NAME_KAIHIKEKKAI,	learningTarget, runningLearning, kaihikekkaiSituation);
	create_thread(learnRelationThread, AI_NAME_RECOVERY,	learningTarget, runningLearning, recoverySituation);
	]]--
	-- ガード、グレイズはなし。

	while (not battleFinished())
	do
		if (battle_time % 100 == 0)
		then
			--logger:info("学習スレッド総元締め", "基本:" .. #BASIC_MOTIONS .. " 攻撃:" .. #ATTACK_MOTIONS .. " ガード:" .. #GUARD_MOTIONS .. " 被ダメ:" .. #DAMAGE_MOTIONS);
		end
		yield();
	end
	logger:info("学習スレッド", "総元締めスレッド終了");
end

-----------------------------------------------------------------------------------------------------------------------
-- 状況学習 共通関数
-----------------------------------------------------------------------------------------------------------------------
function learnMotionThread(aiName, target, running, learnSituation, learnCondition)
	local learnInstance = LearnMotion.new(aiName, target, running, learnSituation, learnCondition);
	learnInstance:learn();
end

-----------------------------------------------------------------------------------------------------------------------
-- 行動連鎖学習 共通関数
-----------------------------------------------------------------------------------------------------------------------
function learnRelationThread(aiName, target, running, learnSituation, learnCondition)
	local learnInstance = LearnRelation.new(aiName, target, running, learnSituation, learnCondition);
	learnInstance:learn();
end

-----------------------------------------------------------------------------------------------------------------------
-- 学習判定
-----------------------------------------------------------------------------------------------------------------------
-- 攻撃的、チキン、端攻めなどの行動の学習判定
function learnAttackCondition(target)
	local targetEnemy = getReverseTarget(target);
	local currentCaptureInfo = tracer[target]:current();
	local tracedCaptureInfo  = tracer[target]:tracedCurrent();
	
	-- 前回行動の結果、被ダメージなら学習しない
	if (isDamageMotion(currentCaptureInfo.act))
	then
		return false;
	end

	-- マッピングに無いモーションは覚えない。
	local motion = motionMapping:get(tracedCaptureInfo.act);
	if (motion == nil)
	then
		return false;
	end

	-- 持続行動の場合、ゴミがたまらないようフレーム数制限
	if ((motion.disableKeyReset) and (tracedCaptureInfo.frame <= LEARNING_FRAME_BORDER))
	then
		return false;
	end

	-- 打撃行動の結果、相手がダメージかガードなら覚える。
	local history = nil;
	local currentTraceMotion = tracer[targetEnemy]:current();
	if (isBlowMotion(tracedCaptureInfo.act))
	then
		-- 過去4つの行動履歴さかのぼる
		for i = 0, 3
		do
			history = tracer[targetEnemy]:history(i);
			if (history == nil)
			then
				-- これ以上さかのぼれないので･･･。
				break;
			end
			-- 履歴見て攻撃行動時間内に相手がダメージかガードだったら覚える。
			if ((history:getParameter(CaptureInfo_battle_time) >= tracedCaptureInfo:getParameter(CaptureInfo_battle_time)) and
				(history:getParameter(CaptureInfo_battle_time) <= (tracedCaptureInfo:getParameter(CaptureInfo_battle_time) + tracedCaptureInfo.frame))
				or
				-- Aコンボなどで自分だけ切り替わり相手のダメージモーションが前回から継続中の場合
				(history:equals(currentTraceMotion) and 
				 (tracedCaptureInfo:getParameter(CaptureInfo_battle_time) + tracedCaptureInfo.frame <= history:getParameter(CaptureInfo_battle_time) + history.frame))
			   )
			then
				print("historyscanbefore:", isDamageMotion(history.act));
				if (tracedCaptureInfo:getParameter(CaptureInfo_weather) ~= 13)
				then
					print("historyscan:", isDamageMotion(history.act));
					if (isDamageMotion(history.act))
					then
						tracedCaptureInfo.evaluate = 100;
						return true;
					elseif (isGuardMotion(history.act))
					then
						tracedCaptureInfo.evaluate = 50;
						return true;
					end
				else
					-- TODO 台風時のヒット確認
					return true;
				end
			end
		end
		return false;
	end


	-- あとはべつになんでも覚えちゃってください。
	return true;
end

-- グレイズ学習判定
function learnGureizuCondition(target)
	local targetEnemy = getReverseTarget(target);
	local currentCaptureInfo = tracer[target]:current();
	local tracedCaptureInfo  = tracer[target]:tracedCurrent();
	
	-- 前回行動の結果被ダメージなら学習しない
	if (isDamageMotion(currentCaptureInfo.act))
	then
		return false;
	end
	return isGureizuMotionEffective(target);
end

----------------------------------------------------------------------------------------------------------
-- モーション種別判定
--  グレイズモーションでかつグレイズが有効である場合 true。
--  HJは上昇中のみ有効であるため。
----------------------------------------------------------------------------------------------------------
function isGureizuMotionEffective(target)
	local captureInfo = tracer[target]:tracedCurrent();
	local customAct = captureInfo.act;
	return	(
				(customAct == 200) and 
				--(customAct == 201) and  -- 201 ﾊﾞｸｽﾃは除外。
				(customAct == 202) and
				(customAct == 203)
			)
			or 
			(
				-- トレース直後の状態も条件に加味。たぶん急激な方向転換だと無理じゃないかな･･･。
				(customAct >= 208) and (customAct <= 210) and (getTargetY(target) > 0) and (getTargetYspeed(target) > 0)
			)
			or
			(
				(customAct >= 2140) and (customAct <= 2149)
			);
end

