Search code examples
c#processing-efficiencyspace-efficiency

Is there a way to make this more efficient?


So I am working on a text adventure to improve my programming skills (Just a beginner) and I was working on a new combat system for it because the old one was really boring. So I came across a rock paper scissors system but I wanted something that used a rock paper scissors like system with 5 options for the player to choose from, and the enemy or monster attacking the player.

I used a lot of if statements, which actually didn't take too long, but I'm wondering if there's a better way to do this so that my code is more efficient, and not so large.

        public static void ResultsOfMoves(string PlayerMove, string MonsterMove, Monster CurrentMonster, Weapon CurrentWeapon, Armor CurrentArmor, Player CurrentPlayer)
    {
        //Monster Responses to Player
        if (PlayerMove == "dodge" && MonsterMove == "heavy"||MonsterMove == "stealth")
        {
            if (MonsterMove == "heavy") { MonsterHeavyAttack(); }
            if (MonsterMove == "stealth") { MonsterStealthAttack(); }
        }
        else if (PlayerMove == "charge" && MonsterMove == "dodge"||MonsterMove == "stealth")
        {
            if (MonsterMove == "dodge") { MonsterDodge(); }
            if (MonsterMove == "stealth") { MonsterStealthAttack(); }
        }
        else if (PlayerMove == "block" && MonsterMove == "charge" || MonsterMove == "dodge")
        {
            if (MonsterMove == "charge") { MonsterChargeAttack(); }
            if (MonsterMove == "dodge") { MonsterDodge(); }
        }
        else if (PlayerMove == "heavy" && MonsterMove == "block" || MonsterMove == "charge")
        {
            if (MonsterMove == "block") { MonsterBlock(); }
            if (MonsterMove == "charge") { MonsterChargeAttack(); }
        }
        else if (PlayerMove == "stealth" && MonsterMove == "heavy" || MonsterMove == "block")
        {
            if (MonsterMove == "heavy") { MonsterHeavyAttack(); }
            if (MonsterMove == "block") { MonsterBlock(); }
        }

        //Players Responses To Monster
        if (MonsterMove == "dodge" && PlayerMove == "heavy" || PlayerMove == "stealth")
        {
            if (PlayerMove == "heavy") { MonsterHeavyAttack(); }
            if (PlayerMove == "stealth") { MonsterStealthAttack(); }
        }
        else if (MonsterMove == "charge" && PlayerMove == "dodge" || PlayerMove == "stealth")
        {
            if (PlayerMove == "dodge") { MonsterDodge(); }
            if (PlayerMove == "stealth") { MonsterStealthAttack(); }
        }
        else if (MonsterMove == "block" && PlayerMove == "charge" || PlayerMove == "dodge")
        {
            if (PlayerMove == "charge") { MonsterChargeAttack(); }
            if (PlayerMove == "dodge") { MonsterDodge(); }
        }
        else if (MonsterMove == "heavy" && PlayerMove == "block" || PlayerMove == "charge")
        {
            if (PlayerMove == "block") { MonsterBlock(); }
            if (PlayerMove == "charge") { MonsterChargeAttack(); }
        }
        else if (MonsterMove == "stealth" && PlayerMove == "heavy" || PlayerMove == "block")
        {
            if (PlayerMove == "heavy") { MonsterHeavyAttack(); }
            if (PlayerMove == "block") { MonsterBlock(); }
        }

    }

Solution

  • First create a Move enum, rather than using strings:

    public enum Moves
    {
        Charge,
        Dodge,
        Heavy,
        Steath,
        Block
    }
    

    Next, use a Dictionary to determine the moves:

    var moveResolution = new Dictionary<Tuple<Moves, Moves>, Action>
    {
        { new Tuple<Moves, Moves>(Moves.Dodge, Moves.Heavy), MonsterHeavyAttack },
        { new Tuple<Moves, Moves>(Moves.Dodge, Moves.Steath), MonsterStealthAttack },
        { new Tuple<Moves, Moves>(Moves.Charge, Moves.Dodge), MonsterDodge },
        ...
    };
    

    Then to determine the appropriate move, simply do:

    var moveCombination = new Tuple<Moves, Moves>(playerMove, monsterMove);
    if (moveResolution.ContainsKey(moveCombination))
    {
        moveResolution[moveCombination]();
    }
    

    This code could then be further improved by replacing the lazy Tuple<Moves, Moves> with a MoveCombination struct. Note, use a struct to ensure the moveResolution.ContainsKey(moveCombination) part works as you need to compare by value, not by reference.