public bool GetNode(NodeType type, out APActionNode newNode) { // 첫 접근 if (pool.Count == 0) { pool.Add(NodeType.Move, new Dictionary <APActionNode, bool>()); pool.Add(NodeType.Attack, new Dictionary <APActionNode, bool>()); pool.Add(NodeType.Item, new Dictionary <APActionNode, bool>()); pool.Add(NodeType.Skill, new Dictionary <APActionNode, bool>()); } Dictionary <APActionNode, bool> dic = pool[type]; foreach (var node in dic.Keys) { if (dic[node] == false) { dic[node] = true; newNode = node; return(true); } } newNode = null; return(false); }
public override bool IsAvailable(APActionNode prevNode) { if (_gameState.self.actionPoint < _gameState.self.owner.GetActionSlot(ActionType.Attack).cost) { return(false); } else { return(true); } }
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 void AddNode(APActionNode newNode) { if (newNode is ActionNode_Move) { pool[NodeType.Move].Add(newNode, false); } else if (newNode is ActionNode_Attack) { pool[NodeType.Attack].Add(newNode, false); } // TODO //else if (newNode is ActionNode_Item) //{ //pool[NodeType.Item].Add(newNode, false); //} //else if (newNode is ActionNode_Skill) //{ //pool[NodeType.Skill].Add(newNode, false); //} }
private IEnumerator ExecuteAction() { if (_actions.Count <= 0) { yield break; } float sec = UnityEngine.Random.Range(0.5f, 1.5f); yield return(new WaitForSeconds(sec)); // 다음 액션 _currAction = _actions.Dequeue(); // 액션 실행 unit.EnqueueCommand(_currAction.Command); // 커맨드의 성공여부이벤트를 wait List <KeyValuePair <Predicate <EventParam>, TurnMgr_State_> > branches = new List <KeyValuePair <Predicate <EventParam>, TurnMgr_State_> >(); // Command가 성공했을 경우 유닛의 Action의 끝을 Wait TurnMgr_State_ waitIdleEnterState = new TurnMgr_WaitSingleEvent_( owner, unit, EventMgr.Instance.onUnitIdleEnter, this, WaitUnitIdleEnterPredicate, _currAction.OnWaitEnter, _currAction.OnWaitExecute, _currAction.OnWaitExit); var successBranch = new KeyValuePair <Predicate <EventParam>, TurnMgr_State_>((param) => CommandResultPredicate(param), waitIdleEnterState); branches.Add(successBranch); // Command가 실패했을 경우 Replan으로 State전환 var failBranch = new KeyValuePair <Predicate <EventParam>, TurnMgr_State_>((param) => !CommandResultPredicate(param), new TurnMgr_AIPlan_(owner, unit)); branches.Add(failBranch); // BranchSingleEvent owner.stateMachine.ChangeState( new TurnMgr_BranchSingleEvent_(owner, unit, EventMgr.Instance.onUnitCommandResult, branches, (param) => ((CommandResultParam)param)._subject != unit), StateMachine <TurnMgr> .StateTransitionMethod.PopNPush); }
public abstract bool IsAvailable(APActionNode prevNode);
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;