public override AIAction[] CalcActionsToPerform() { Tank selfTank = controller.SelfTank; Tank targetTank = controller.TargetTank; Map map = controller.Map; List <TreeSearchMoveInfo> possibleMoves = new List <TreeSearchMoveInfo>(); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, -1), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(90f), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(-90f), true)); LookaheadTree tree = new LookaheadTree(); tree.PopulateTree(selfTank, map, LookaheadTime, LookaheadTimeStep, possibleMoves); List <LookaheadNode> possibleNodes = tree.FindAllNodesAtSearchTime(LookaheadTime); possibleNodes = AIUtility.FilterByPathNotObstructed(possibleNodes); possibleNodes = AIUtility.FilterByDestNotObstructed(possibleNodes, map); possibleNodes = AIUtility.FilterByPassingBullet(possibleNodes, map); possibleNodes = AIUtility.FilterByAwayFromWall(possibleNodes, selfTank.StateInfo); LookaheadNode bestNode = null; float bestCost = 0; foreach (LookaheadNode node in possibleNodes) { WeaponPart notUsed; int targetTime = AIUtility.CalcMinTimeForAimerToHitAimee(targetTank.StateInfo, node.TankInfo, targetTank.Hull.GetAllWeapons(), out notUsed); int selfTime = AIUtility.CalcMinTimeForAimerToHitAimee(node.TankInfo, targetTank.StateInfo, selfTank.Hull.GetAllWeapons(), out notUsed); float cost = targetTime - selfTime; if (bestNode == null || bestCost < cost) { bestNode = node; bestCost = cost; } } timeSinceLastJet = Time.time; List <AIAction> actions = new List <AIAction>(); actions.Add(new JetInDirAction(bestNode.IncomingDir, controller)); return(actions.ToArray()); }
private LookaheadNode pickDirToPursue() { Tank selfTank = controller.SelfTank; Tank targetTank = controller.TargetTank; Map map = controller.Map; WeaponPart targetWeapon; WeaponPart selfWeapon; int timeForTargetToHitSelf = AIUtility.CalcMinTimeForAimerToHitAimee(targetTank.StateInfo, selfTank.StateInfo, targetTank.Hull.GetAllWeapons(), out targetWeapon); int timeForSelfToHitTarget = AIUtility.CalcMinTimeForAimerToHitAimee(selfTank.StateInfo, targetTank.StateInfo, selfTank.Hull.GetAllWeapons(), out selfWeapon); int weaponDmgDiff = selfWeapon.Schematic.Damage - targetWeapon.Schematic.Damage; float stepRatio = weaponDmgDiff / 10f; int thresh = 50 - Mathf.RoundToInt(stepRatio * 10); if (weaponDmgDiff > 0) { thresh = Math.Min(thresh, 100); } else { thresh = Math.Max(thresh, -100); } int diff = timeForSelfToHitTarget - timeForTargetToHitSelf; bool runaway = diff < thresh && timeForTargetToHitSelf < 50; Debug.Log("diff=" + diff + " thresh=" + thresh + (runaway ? " Running away" : " Going for it") + "\n" + "timeForTargetToHitSelf=" + timeForTargetToHitSelf); List <TreeSearchMoveInfo> possibleMoves = new List <TreeSearchMoveInfo>(); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, -1), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(45f), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(135f), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(-45f), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(-135f), false)); if (!runaway) { possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(90f), false)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(-90f), false)); } float dist = (selfTank.transform.position - targetTank.transform.position).magnitude; if (!runaway && selfTank.Hull.EnergyAvailableForUsage(selfTank.Hull.Schematic.JetEnergyUsage) && selfTank.FindMaxWeaponRange() >= dist && selfTank.FireableWeaponExists()) { possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, -1), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(90f), true)); possibleMoves.Add(new TreeSearchMoveInfo(new Vector2(0, 1).Rotate(-90f), true)); } clearManeuverBehaviourDebugObjects(); LookaheadTree tree = new LookaheadTree(); tree.PopulateTree(selfTank, map, LookaheadTime, LookaheadTimeStep, possibleMoves); List <LookaheadNode> possibleNodes = tree.FindAllNodesAtSearchTime(LookaheadTime); CombatDebugHandler.Instance.RegisterObject("maneuver_nodes_at_searchtime", possibleNodes); // First perform general filter possibleNodes = AIUtility.FilterByPathNotObstructed(possibleNodes); CombatDebugHandler.Instance.RegisterObject("maneuver_path_unobstructed_filter", possibleNodes); possibleNodes = AIUtility.FilterByDestNotObstructed(possibleNodes, map); CombatDebugHandler.Instance.RegisterObject("maneuver_dest_not_obstructed_filter", possibleNodes); possibleNodes = AIUtility.FilterByPassingBullet(possibleNodes, map); CombatDebugHandler.Instance.RegisterObject("maneuver_bullet_filter", possibleNodes); possibleNodes = AIUtility.FilterByAwayFromWall(possibleNodes, selfTank.StateInfo); CombatDebugHandler.Instance.RegisterObject("maneuver_away_from_wall_filter", possibleNodes); LookaheadNode requestNode; if (runaway) { requestNode = runawayBehaviour(possibleNodes); controller.PrevManeuverBehaviour = Behaviour.Runaway; } else { requestNode = goingForItBehaviour(possibleNodes); controller.PrevManeuverBehaviour = Behaviour.GoingforIt; } return(requestNode); }