public AttackPlanner(APGameState gameState, int prevScore, ActionPointPanel actionPointPanel) : base(gameState, prevScore, actionPointPanel) { _gameState = gameState.Clone(); _prevScore = prevScore; _actionPointPanel = actionPointPanel; }
public void RequestAsync(APGameState gameState, Action <List <PFPath> > OnServe) { List <INavable> navables = new List <INavable>(gameState._cubes); APUnit unit = gameState.self; int maxDistance = unit.actionPoint / unit.owner.GetActionSlot(ActionType.Move).cost; Cube start = gameState._unitPos[unit]; Func <INavable, bool> cubeIgnore = (cube) => { return(cube.IsAccupied() == true); }; StartCoroutine(BFSPathfinding(start, navables, unit.actionPoint, OnServe, cubeIgnore)); }
public void GetState(out APGameState newState) { foreach (var state in pool.Keys) { if (pool[state] == false) { pool[state] = true; newState = state; return; } } newState = new APGameState(); pool.Add(newState, true); }
private void CalcFinalPositionScore(List <APActionNode> leaves, APGameState initialGameState) { foreach (var leaf in leaves) { APGameState finalGameState = leaf._gameState; // 적 유닛들 중에 List <APUnit> eUnitCanAttackMe = new List <APUnit>(); foreach (var unit in finalGameState._units) { if (unit.isSelf) { continue; } if (!finalGameState.self.owner.team.enemyTeams.Contains(unit.owner.team)) { continue; } Cube unitPos = finalGameState._unitPos[unit]; Range attackRange = unit.owner.basicAttackRange; List <Cube> cubesInRange = MapMgr.Instance.GetCubes( attackRange.range, attackRange.centerX, attackRange.centerZ, unitPos); // 만약 일반공격 사정거리가 닿는 적이 있다면 우선 모아놓기 Cube selfPos = finalGameState._unitPos[finalGameState.self]; if (cubesInRange.Contains(selfPos)) { eUnitCanAttackMe.Add(unit); } } // 그리고 적의 기본공격 몇방에 죽을수 있는지에 따라 점수 차감 // 적이 많을수록 조금만 깎기 foreach (var unit in eUnitCanAttackMe) { int attackDmg = unit.owner.BasicAttackDamageAvg; int howManyHit = Mathf.Max(finalGameState.self.health / attackDmg, 1); int scoreToSub = (500 / howManyHit) / eUnitCanAttackMe.Count; leaf._score -= scoreToSub; } } }
public override int GetScoreToAdd(List <APUnit> splashUnits, APGameState prevState, APGameState gameState) { int score = 0; // 체력이 많은 적보다 // 체력이 조금 남은 적을 공격하기 (+ 4000 * (자신의공격력/적의체력)) if (splashUnits.Where(unit => gameState.self.owner.team.enemyTeams.Contains(unit.owner.team)).Count() > 0) { score += (int)(7000 * ( splashUnits .Where(unit => gameState.self.owner.team.enemyTeams.Contains(unit.owner.team)) .Select(unit => (float)unit.health) .Aggregate((accum, health) => accum + gameState.self.owner.skill.amountAvg / health) )); } // 아군에 사용했으면 점수를 깎습니다. // (+ 1500 * (자신의공격력/아군의체력)) if (splashUnits.Where(unit => gameState.self.owner.team == unit.owner.team).Count() > 0) { score -= (int)(1500 * ( splashUnits //.Where(unit => gameState.self.owner.team == unit.owner.team) .Select(unit => (float)unit.health) .Aggregate((accum, health) => accum + gameState.self.owner.skill.amountAvg / health) )); } // 적을 죽이는 plan이면 죽인 유닛당 +2000 if (prevState._units.Where(unit => gameState.self.owner.team.enemyTeams.Contains(unit.owner.team)).Count() // 이전 상태의 적군 유닛 갯수 != gameState._units.Where(unit => gameState.self.owner.team.enemyTeams.Contains(unit.owner.team)).Count()) // 현재 상태의 적군 유닛 갯수 { score += 2000 * (Mathf.Abs(gameState._units.Count - prevState._units.Count)); } return(score); }
public abstract int GetScoreToAdd(APGameState prevState);
protected void SetNode(APGameState prevGameState, int prevScore, ActionPointPanel actionPointPanel) { _gameState = prevGameState.Clone(); _score = prevScore; _actionPointPanel = actionPointPanel; }
protected APActionNode(APGameState prevGameState, int prevScore, ActionPointPanel actionPointPanel) { SetNode(prevGameState, prevScore, actionPointPanel); }
public AttackPlanner(APGameState gameState, int prevScore) : base(gameState, prevScore) { _gameState = gameState.Clone(); _prevScore = prevScore; }
public MovePlanner(APGameState gameState, int prevScore) : base(gameState, prevScore) { }
public APPlanner(APGameState gameState, int prevScore) { _gameState = gameState.Clone(); _prevScore = prevScore; }
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); }
protected void SetNode(APGameState prevGameState, int prevScore) { _gameState = prevGameState.Clone(); _score = prevScore; }
protected APActionNode(APGameState prevGameState, int prevScore) { SetNode(prevGameState, prevScore); }
public MovePlanner(APGameState gameState, int prevScore, ActionPointPanel actionPointPanel) : base(gameState, prevScore, actionPointPanel) { _actionPointPanel = actionPointPanel; }
public virtual int GetScoreToAdd(List <APUnit> splashUnits, APGameState prevState, APGameState gameState) { return(0); }