Beispiel #1
0
    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());
    }
Beispiel #2
0
    private LookaheadNode runawayBehaviour(List <LookaheadNode> possibleNodes)
    {
        Tank targetTank = controller.TargetTank;
        Tank selfTank   = controller.SelfTank;

        float dist = (targetTank.transform.position - selfTank.transform.position).magnitude;

        float maxRange            = selfTank.Hull.GetMaxRange() * 1.5f;
        bool  onlyCloser          = maxRange < dist;
        bool  allWeaponsReloading = selfTank.Hull.IsAllWeaponsReloading();

        List <CostInfo> nodeCosts  = new List <CostInfo>();
        bool            withFilter = true;

        while (nodeCosts.Count == 0)
        {
            foreach (LookaheadNode node in possibleNodes)
            {
                WeaponPart notUsed;
                int        targetTime = AIUtility.CalcMinTimeForAimerToHitAimee(targetTank.StateInfo, node.TankInfo, targetTank.Hull.GetAllWeapons(), out notUsed);

                Vector2 incomingDir = node.GetNodeOneStepAfterRoot().IncomingDir;

                int   cost       = targetTime;
                float futureDist = ((Vector2)targetTank.transform.position - node.TankInfo.Pos).magnitude;
                if (!withFilter || ((onlyCloser && dist > futureDist) || (!onlyCloser && futureDist < maxRange) || allWeaponsReloading))
                {
                    nodeCosts.Add(new CostInfo(node, cost));
                }
            }

            withFilter = false;
        }

        CombatDebugHandler.Instance.RegisterObject("maneuver_runaway_cost_infos", nodeCosts);

        CostInfo bestInfo = null;

        foreach (CostInfo info in nodeCosts)
        {
            if (bestInfo == null || bestInfo.Cost < info.Cost)
            {
                bestInfo = info;
            }
        }

        bestInfo = handleSameCostCostInfos(bestInfo, nodeCosts);

        CombatDebugHandler.Instance.RegisterObject("maneuver_best_node", bestInfo.Node);

        return(bestInfo.Node.GetNodeOneStepAfterRoot());
    }
Beispiel #3
0
    private LookaheadNode goingForItBehaviour(List <LookaheadNode> possibleNodes)
    {
        Tank selfTank   = controller.SelfTank;
        Tank targetTank = controller.TargetTank;

        List <CostInfo> nodeCosts = new List <CostInfo>();

        bool        overlapNodeExists = false;
        Vector2     diffVec           = targetTank.transform.position - selfTank.transform.position;
        List <bool> overlaps          = new List <bool>();

        foreach (LookaheadNode node in possibleNodes)
        {
            bool nodeOverlaps = false;
            foreach (WeaponPart part in selfTank.Hull.GetAllWeapons())
            {
                if (node.HasOverlappedTargetWithWeapon(targetTank.transform.position, part))
                {
                    overlapNodeExists = true;
                    nodeOverlaps      = true;
                    break;
                }
            }

            overlaps.Add(nodeOverlaps);
        }
        Debug.Assert(possibleNodes.Count == overlaps.Count, "Possible nodes and overlap count don't match. Should never happen");

        for (int i = 0; i < possibleNodes.Count; ++i)
        {
            LookaheadNode node = possibleNodes[i];

            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);

            int cost = targetTime - selfTime;

            bool overlapCondition = true;
            if (overlapNodeExists)
            {
                overlapCondition = overlaps[i];
            }

            if (overlapCondition)
            {
                nodeCosts.Add(new CostInfo(node, cost));
            }
        }

        CombatDebugHandler.Instance.RegisterObject("maneuver_going_cost_infos", nodeCosts);

        CostInfo bestInfo = null;

        foreach (CostInfo info in nodeCosts)
        {
            if (bestInfo == null || info.Cost > bestInfo.Cost)
            {
                bestInfo = info;
            }
        }

        bestInfo = handleSameCostCostInfos(bestInfo, nodeCosts);

        CombatDebugHandler.Instance.RegisterObject("maneuver_best_node", bestInfo.Node);

        return(bestInfo.Node.GetNodeOneStepAfterRoot());
    }
Beispiel #4
0
    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);
    }