public override bool IsAvailable(APActionNode prevNode) { if (!_gameState.self.owner.HasAction(ActionType.Attack)) { return(false); } if (prevNode.GetType() == typeof(ActionNode_Move)) { return(false); } if (_gameState.self.actionPoint < _gameState.self.owner.GetActionSlot(ActionType.Move).cost) { return(false); } return(true); }
public IEnumerator Plan_Coroutine(Unit requester, Action <List <APActionNode> > OnPlanCompleted) { APGameState initialGameState = APGameState.Create(requester, TurnMgr.Instance.turns.ToList(), MapMgr.Instance.map.Cubes.ToList()); List <APActionNode> leafNodes = new List <APActionNode>(); // BFS Tree Construction Queue <APActionNode> queue = new Queue <APActionNode>(); queue.Enqueue(new RootNode(initialGameState)); while (queue.Count > 0) { APActionNode parentNode = queue.Dequeue(); int childCount = 0; //************** MOVE NODES **************// MovePlanner movePlanner = new MovePlanner(parentNode._gameState, parentNode._score, actionPointPanel); if (movePlanner.IsAvailable(parentNode)) { // 시뮬레이션 List <APActionNode> moveNodes; bool simulCompleted = false; movePlanner.Simulate(this, () => simulCompleted = true, out moveNodes); // // // // // // // // // // // // // // // // // // // // // // // // while (!simulCompleted) { yield return(null); } // // // // // // // // // // // // // // // // // // // // // // // // // 부모노드 세팅 및 인큐 foreach (var node in moveNodes) { node._parent = parentNode; childCount++; queue.Enqueue(node); } } //************** ATTACK NODES **************// AttackPlanner attackPlanner = new AttackPlanner(parentNode._gameState, parentNode._score, actionPointPanel); if (attackPlanner.IsAvailable(parentNode)) { // 시뮬레이션 List <APActionNode> attackNodes; bool simulCompleted = false; attackPlanner.Simulate(this, () => simulCompleted = true, out attackNodes); // // // // // // // // // // // // // // // // // // // // // // // // while (!simulCompleted) { yield return(null); } // // // // // // // // // // // // // // // // // // // // // // // // // 부모노드 세팅 및 인큐 foreach (var node in attackNodes) { node._parent = parentNode; childCount++; queue.Enqueue(node); } } //************** ITEM NODES **************// //************** SKILL NODES **************// //*** Leaf Check ***// if (childCount == 0) { leafNodes.Add(parentNode); } yield return(null); } //*** 마지막 위치에 따른 점수 계산 ***// //*** Construct Best Action List ***// List <APActionNode> bestSequence = new List <APActionNode>();; // 가장 높은 스코어 추출 int bestScore = leafNodes.Aggregate((acc, curr) => curr._score > acc._score ? curr : acc)._score; // high score leaf들을 추출 List <APActionNode> bestLeaves = leafNodes.FindAll(ln => ln._score == bestScore); // high score leaf들의 마지막 self 위치에 따른 점수변동 CalcFinalPositionScore(bestLeaves, initialGameState); // 점수 변동한 leaf들로 다시 순위매김 int secondBestScore = bestLeaves.Aggregate((acc, curr) => curr._score > acc._score ? curr : acc)._score; bestLeaves = bestLeaves.FindAll(ln => ln._score == secondBestScore); //// 추출한 leaf들중 랜덤하게 고르기위한 idx int randomIdx = UnityEngine.Random.Range(0, bestLeaves.Count); //// 결정한 시퀀스의 leaf노드 APActionNode bestLeaf = bestLeaves[randomIdx]; // 시퀀스 생성 perent를 따라올라감 APActionNode currNode = bestLeaf; while (currNode.GetType() != typeof(RootNode)) // 미자막 RootNode는 안넣을겁니다. { bestSequence.Add(currNode); currNode = currNode._parent; yield return(null); } // leaf - {} - {} - {} - {} // 를 // {} - {} - {} - {} - leaf // 순으로 뒤집기 bestSequence.Reverse(); OnPlanCompleted(bestSequence); }
public override bool IsAvailable(APActionNode prevNode) => prevNode.GetType() != typeof(ActionNode_Move) && _gameState.self.actionPoint > 0;