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); }
/* * 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); }
/* * 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; }
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); }
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); }
//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"); } } }
//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"); } } } }