예제 #1
0
    public List <Nodo> ExpandirOffline(BoardInfo board)
    {
        var result  = new List <Nodo>();
        var vecinos = estado.WalkableNeighbours(board);

        for (var i = 0; i < vecinos.Length; i++)
        {
            var vecino = vecinos[i];
            if (vecino != null)
            {
                var nuevo = new Nodo(vecino, this, (Locomotion.MoveDirection)i, vecino.WalkCost);
                result.Add(nuevo);
            }
        }

        return(result);
    }
예제 #2
0
        /*
         *      Regresa la posición y dirección en que se encuantran los vecinos a los que se puede acceder
         *      utilizando el metodo de CellInfo WalkableNeighbours
         */
        private List <int[]> GetNeighbours(Node node, BoardInfo board)
        {
            List <int[]> neighbours  = new List <int[]>();
            CellInfo     currentCell = board.CellInfos[node.position[0], node.position[1]];

            CellInfo[] walkNeighbours = currentCell.WalkableNeighbours(board);
            for (int i = 0; i < 4; i++)
            {
                if (walkNeighbours[i] != null)
                {
                    neighbours.Add(new int[] { walkNeighbours[i].ColumnId, walkNeighbours[i].RowId, i });
                }
            }
            return(neighbours);
        }
예제 #3
0
    /*
     * Este método lo que hace es actualizar Qtable teniendo en cuenta la posición actual y la acción siguiente y aplicando la fórmula
     * que tenemos en los apuntes para QLearning
     */
    private void learn(CellInfo currentPos, Vector2 nextPos, BoardInfo board)
    {
        Vector2 row          = currentPos.GetPosition - nextPos;
        float   currentValue = Qtable[(int)currentPos.GetPosition.x, (int)currentPos.GetPosition.y];
        float   recompensa   = RewardTable[(int)nextPos.x, (int)nextPos.y];
        float   maxvalue     = Qtable[(int)currentPos.GetPosition.x, (int)currentPos.GetPosition.y];

        CellInfo[] step = currentPos.WalkableNeighbours(board);
        int        pos  = -1;

        /*
         * Como pasamos como parámetro un vector2 y necesitamos expandir la siguiente posición, tenemos que buscar entre las celdas
         * vecinas de la posición actual aquella que coincida con la siguiente posición y guardamos su posición, así obtendremos una
         * variable de tipo CellInfo que nos permitirá expandir sus vecinos que serán los valores para la acción siguiente
         */
        for (int i = 0; i < step.Length; i++)
        {
            if (step[i] != null)
            {
                if (step[i].GetPosition == nextPos)
                {
                    pos = i;
                }
            }
        }
        //Array con los vecinos de la siguiente posición (nextPos)
        CellInfo[] nuevostep = step[pos].WalkableNeighbours(board);

        //Recorro el array nuevoStep que consideramos son las posibles acciones que puede realizar y obtenemos el valor máximo
        for (int i = 0; i < nuevostep.Length; i++)
        {
            if (nuevostep[i] != null)
            {
                if (Qtable[nuevostep[i].ColumnId, nuevostep[i].RowId] > maxvalue)
                {
                    maxvalue = Qtable[nuevostep[i].ColumnId, nuevostep[i].RowId];
                }
            }
        }
        //Aplicamos la fórmula y utilizamos la posición nextPos de la Qtable con el valor calculado
        float updatedValue = (1 - alfa) * currentValue + alfa * (recompensa + (gamma * maxvalue));

        Qtable[(int)nextPos.x, (int)nextPos.y] = updatedValue;
    }
예제 #4
0
        public override Locomotion.MoveDirection GetNextMove(BoardInfo boardInfo, CellInfo currentPos, CellInfo[] goals)
        {
            CellInfo[] adyacentes = currentPos.WalkableNeighbours(boardInfo);

            int  val  = 0;
            bool free = false;

            while (!free)
            {
                val = Random.Range(0, 4);
                if (adyacentes[val] != null)
                {
                    if (adyacentes[val].ItemInCell != null)
                    {
                        if (adyacentes[val].ItemInCell.Type != PlaceableItem.ItemType.Enemy)
                        {
                            free = true;
                        }
                    }
                    else
                    {
                        free = true;
                    }
                }
            }



            if (val == 0)
            {
                return(Locomotion.MoveDirection.Up);
            }
            if (val == 1)
            {
                return(Locomotion.MoveDirection.Right);
            }
            if (val == 2)
            {
                return(Locomotion.MoveDirection.Down);
            }
            return(Locomotion.MoveDirection.Left);
        }
예제 #5
0
        public override Locomotion.MoveDirection GetNextMove(BoardInfo boardInfo, CellInfo currentPos, CellInfo[] goals)
        {
            CellInfo[] adyacentes = currentPos.WalkableNeighbours(boardInfo);
            var        val        = Random.Range(0, 4);


            if (val == 0)
            {
                return(Locomotion.MoveDirection.Up);
            }
            if (val == 1)
            {
                return(Locomotion.MoveDirection.Down);
            }
            if (val == 2)
            {
                return(Locomotion.MoveDirection.Left);
            }
            return(Locomotion.MoveDirection.Right);
        }
예제 #6
0
    //Calcula un valor random que no nos dirija a muros sino a casillas transitables
    private int RandomStep(CellInfo currentPos, BoardInfo board)
    {
        //Genera una semilla distinta cada vez, así evitamos patrones de movimiento
        System.Random rand = new System.Random(Guid.NewGuid().GetHashCode());
        //paso inicial = -1
        int  next      = -1;
        bool validstep = false;

        //pasos posibles
        CellInfo[] possibleSteps = currentPos.WalkableNeighbours(board);

        if (possibleSteps.Length > 0)
        {
            //Permaneceremos en el bucle mientras el valor del array en la posición generada por Random no sea válida
            do
            {
                //random entre 0 y 4
                next = rand.Next(0, 4);
                //Si la posición del array no es null el movimiento es válido
                if (possibleSteps[next] != null)
                {
                    validstep = true;
                }
            } while (!validstep);
        }
        else
        {
            return(-1);
        }

        /*
         * En este paso lo que hacemos es calcular en que dirección nos hemos movido para retornar el valor exacto hacia donde debemos movernos
         */
        int columnpos = currentPos.ColumnId - possibleSteps[next].ColumnId;
        int filapos   = currentPos.RowId - possibleSteps[next].RowId;

        if (columnpos != 0)
        {
            if (columnpos > 0)
            {
                return(2);
                //Debug.Log("Nos movemos a la iquierda");
            }

            else
            {
                return(3);
                //Debug.Log("Nos movemos a la derecha");
            }
        }
        else
        {
            if (filapos > 0)
            {
                return(1);
                //Debug.Log("Nos movemos abajo");
            }
            else
            {
                return(0);
                //Debug.Log("Nos movemos arriba");
            }
        }
    }
예제 #7
0
    //Calcula el máximo valor cercano dentro de Qtable
    private int MaxValueClose(CellInfo currentPos, BoardInfo board)
    {
        //Obtenemos los vecinos de la posición actual
        CellInfo[] neighbours = currentPos.WalkableNeighbours(board);
        float      maxvalue   = 0;
        bool       first      = false;
        int        pos        = -1;

        //Vector2 ant = new Vector2(AnteriorPosX, AnteriorPosY);
        for (int i = 0; i < neighbours.Length; ++i)
        {
            if (neighbours[i] != null)
            {
                //Le decimos que al menos coja la primera posición de los vecinos y almacenamos su posición
                //y cambiamos el buleano first a true para que no vuelva a entrar
                if (!first)
                {
                    maxvalue = Qtable[neighbours[i].ColumnId, neighbours[i].RowId];
                    pos      = i;
                    first    = true;
                }
                //Si el valor de Qtable en la posición de neighbours[i] es mayor a maxvalue, actualizamos maxvalue y guardamos la posición
                if (Qtable[neighbours[i].ColumnId, neighbours[i].RowId] > maxvalue)
                {
                    maxvalue = Qtable[neighbours[i].ColumnId, neighbours[i].RowId];
                    pos      = i;
                    //Debug.Log("Vecino elegido " + i + " Columna: " + neighbours[i].ColumnId + " fila: " + neighbours[i].RowId);
                }
            }
        }
        //Si pos == -1 devuelve -1 y no haría nada, aquí no vamos a entrar pero está concebido como elemento de seguridad
        if (pos == -1)
        {
            return(-1);
        }
        else
        {
            /*
             * En este paso lo que hacemos es calcular en que dirección nos hemos movido para retornar el valor exacto hacia donde debemos movernos
             */
            int columnpos = currentPos.ColumnId - neighbours[pos].ColumnId;
            int filapos   = currentPos.RowId - neighbours[pos].RowId;
            //Nos movemos en horizontal
            if (columnpos != 0)
            {
                if (columnpos > 0)
                {
                    return(2);
                    //Debug.Log("Nos movemos a la iquierda");
                }

                else
                {
                    return(3);
                    //Debug.Log("Nos movemos a la derecha");
                }
            }
            //Nos movemos en vertical
            else
            {
                if (filapos > 0)
                {
                    return(1);
                    //Debug.Log("Nos movemos abajo");
                }
                else
                {
                    return(0);
                    //Debug.Log("Nos movemos arriba");
                }
            }
        }
    }