U
U
Uncle Bogdan2021-08-23 19:07:15
Neural networks
Uncle Bogdan, 2021-08-23 19:07:15

How to fix a neural network for a turn-based strategy?

I will be grateful if you help. Hello, Never wrote neural networks. And I decided to make a neural network for a turn-based strategy. Looked, respected. Found this thing

Decided to use it.

Wrote this:

The code
private void SetBrain(NeuralNetwork brain) // Создаю нейросеть
    {
        Brain = brain;
    }

    private void Awake()
    {
        SetBrain(new NeuralNetwork(new int[] { 5, 5, 5, 1 })); // Задаю значения

        var load = GridAction.PlayerTurn.LoadNeuralNetwork(this); // Загружаю сохраненную нейросеть

        if (!load) // Если нету сохраненной, тогда создать новую.
        {
            SetBrain(new NeuralNetwork(new int[] { 5, 5, 5, 1 }));
        }
    }

public IEnumerator UseNeuralNetwork()
    {
        if(IsAI)
        {
            yield return new WaitForSeconds(1);

            CalculateAttackVariant(CurrentCell);
            CalculateMoveVariant(CurrentCell);

            float[] inputs = new float[5];

            inputs[0] = MoveVariants.Count; // Количество возможных ходов.
            inputs[1] = AttackVariants.Count; // Количество возможных ходов для атаки.
            inputs[2] = Health; // Здоровье персонажа.
            inputs[3] = Damage; // Урон персонажа.
            inputs[4] = GridAction.PlayerTurn.CalculateMinimalDistance(GridAction.PlayerTurn.PlayerUnits, transform.position); // Дистанция до ближайшего персонажа
            Brain.fitness = Fitness; // Передаю текущую полезность в нейросеть

            var output = Brain.FeedForward(inputs); // Результат нейросети

            if (MoveVariants.Count == 0 && AttackVariants.Count != 0) // Если нету ходов, но есть ходы для атаки, то атаковать.
            {
                output[0] = -1;
            }

            if (MoveVariants.Count == 0 && AttackVariants.Count == 0) // Если вообще нету ходов, то пропустить
            {
                yield break;
            }

            if (AttackVariants.Count == 0 && output[0] < 0) // Если нету ходов для атаки, а вывод был меньше нуля, тогда переводить на положительное и говорить что это не правильно
            {
                Fitness -= 1;

                output[0] = 1;
            }

            if (output[0] > 0) // Если вывод больше нуля, то ходить
            {
                inputs[0] = MoveVariants.Count; // такие же параметры
                inputs[1] = AttackVariants.Count;
                inputs[2] = Health;
                inputs[3] = Damage;
                inputs[4] = GridAction.PlayerTurn.CalculateMinimalDistance(GridAction.PlayerTurn.PlayerUnits, transform.position);
                Brain.fitness = Fitness;

                output = Brain.FeedForward(inputs); // результат

                float MinimalValue = 1f / MoveVariants.Count; // делим количество вариантов хода на 1 и потом прибавляем это к переменной CurrentValue, чтобы понять куда нужно пойти ( сам до этого додумался и надеюсь это нормально )
                float CurrentValue = MinimalValue;
                int VariantIndex = 0;

                int i = MoveVariants.Count + AttackVariants.Count; // количество итераций

                while (i > 0)
                {
                    if (CurrentValue < CurrentValue + MinimalValue)
                    {
                        break;
                    }

                    CurrentValue += MinimalValue;

                    VariantIndex++;
                    i--;
                }

                // Логика ходьбы
                GridAction.SelectedCell = CurrentCell;

                GridAction.OnPlayerMove(ref CurrentCell.UnitInCell, MoveVariants[VariantIndex]);

                // Говорю что ходить - это не правильно чтобы нейросеть пыталась как можно быстрее закончить игру.
                Fitness -= 3;
            }
            else
            {
                inputs[0] = MoveVariants.Count;
                inputs[1] = AttackVariants.Count;
                inputs[2] = Health;
                inputs[3] = Damage;
                inputs[4] = GridAction.PlayerTurn.CalculateMinimalDistance(GridAction.PlayerTurn.PlayerUnits, transform.position);
                Brain.fitness = Fitness;

                output = Brain.FeedForward(inputs);

                // Тоже самое что и с ходьбой

                float MinimalValue = 1f / AttackVariants.Count;
                float CurrentValue = MinimalValue;
                int VariantIndex = 0;

                int i = MoveVariants.Count + AttackVariants.Count;

                while (i > 0)
                {
                    if (CurrentValue < CurrentValue + MinimalValue)
                    {
                        break;
                    }

                    CurrentValue += MinimalValue;

                    VariantIndex++;
                    i--;
                }

                // Логика атаки
                GridAction.SelectedCell = CurrentCell;

                GridAction.OnPlayerAttack(AttackVariants[VariantIndex], this);

                // Говорю что атака это хорошо
                Fitness += 60;
            }
        }
    }


Scene restart
public void Gameover()
    {
        if (PlayerUnits.Count == 0) // Добавление правильности при выйгрыше определенной команды
        {
            foreach (UnitBase unit in EnemyUnits)
            {
                unit.Fitness += 200;
                unit.Brain.fitness = unit.Fitness;
            }
        }
        else
        {
            foreach (UnitBase unit in PlayerUnits)
            {
                unit.Fitness += 200;
                unit.Brain.fitness = unit.Fitness;
            }
        }

        // Выбор лучшего юнита по количеству очкой правильности

        UnitBase highEnemy = null;

        float fitness = 0;

        foreach (UnitBase unit in EnemyUnits)
        {
            if (unit.Fitness > fitness)
            {
                highEnemy = unit;

                fitness = highEnemy.Fitness;
            }
        }

        foreach (UnitBase unit in PlayerUnits)
        {
            if (unit.Fitness > fitness)
            {
                highEnemy = unit;

                fitness = highEnemy.Fitness;
            }
        }


        // Сохранять текущую нейросеть

        highEnemy.Brain.Save([email protected]"C:\Users\forgu\Desktop\Нейросеть\high.txt");

        // Перезапуск сцены

        SceneManager.LoadScene(0);
    }


-------------------------------------------------- -------------------------------------------------- ----------------------------------------------------

I have the following problems:

The neural network does not go to the character if he is not next to him, but goes back and forth.

I think I'm giving her the wrong input. What to change.

My questions are:

Am I processing the result correctly?

Does the neural network learn at all? Does save work?

Thanks in advance!

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question