/// <summary> /// If there is a signInARow that has the same steepness then it will remove that first then add this /// </summary> public void AddSignInARow(SignInARow inARow, out SignInARow removed) { removed = null; // We remove the one with the same steepness because they overlap and so the longer one should be added (which we think is the new InARow) for (int i = signsInARow.Count - 1; i >= 0; i--) { // We have a signinarow which has the same steepness so if (signsInARow[i].Steepness == inARow.Steepness) { removed = signsInARow[i]; signsInARow.RemoveAt(i); break; } } signsInARow.Add(inARow); }
public int[] StartEvaluation() { // ________________________________________ FIRST POINT __________________________________________________ // There is only one placed in the game so just randomize it because otherwise it only places where we examine first if (pointsInGame.Count < 2) { System.Random rand = new System.Random(); IntVector2 random; do { random = new IntVector2(rand.Next(0, 3) - 1, rand.Next(0, 3) - 1); } while (random.x == 0 && random.y == 0); return(LocalAIToGridPos(pointsInGame[0] + random)); } // _____________________________________ DEFENSE EVAL __________________________________________ // It' only a defending mechanism so only checks for human pointsinrow // try places where we surely have to place // it has a smaller chance that it skips that position SignInARow humThree = null, humFour = null; SignInARow aiThree = null, aiFour = null; int tillI = pointsInGame.Count; float exponentialChance = Mathf.Pow(leaveOutChance, 1.55f); for (int i = 0; i < tillI; i++) { List <SignInARow> list = gameField[pointsInGame[i].x, pointsInGame[i].y].signsInARow; for (int k = 0; k < list.Count; k++) { // skip at random if (rand.NextDouble() < exponentialChance) { continue; } int length = list[k].Length; int blockCount = list[k].BlockCount(); if (length == 3 && blockCount == 0) { // Store it so if after this loop we don't find a four (we don't return) place there if (list[k].Type == HumanType) { humThree = list[k]; } else { aiThree = list[k]; } } else if (length == 4 && blockCount != 2) { // It prioritizes the fours so if it finds one place there if (list[k].Type == HumanType) { humFour = list[k]; } else // There is a 4 length that is AIType so place there { aiFour = list[k]; } } } } // First if there is a four type ai where we can place win the game if (aiFour != null) { return(LocalAIToGridPos(aiFour.GetUnblockedPos())); } // If there is a four that is type of human we should really place there if (humFour != null) { return(LocalAIToGridPos(humFour.GetUnblockedPos())); } // If there is a signinarow with aitype that is length of three decide which is better and return that if (aiThree != null) { return(LocalAIToGridPos(WhichIsBetter(aiThree.GetBlockField1Pos(), aiThree.GetBlockField2Pos(), AIType))); } // If there is no three with AI type but there is one for the human decide which is better if (humThree != null) // We are going to decide which position is better { return(LocalAIToGridPos(WhichIsBetter(humThree.GetBlockField1Pos(), humThree.GetBlockField2Pos(), AIType))); } // Come here is everything else fails // ___________________ NORMAL EVAL _____________________________- EvaluationResult result = new EvaluationResult(); try { result = EvaluateField(gameField, AIType, 1, pointsInGame, int.MinValue, int.MaxValue); } catch (Exception e) { UnityEngine.Debug.Log(e.Message + "\n" + e.StackTrace); } return(LocalAIToGridPos(result.fieldPos)); }
public PlaceData(IntVector2 pos, SignInARow signInARow) { this.fieldPos = pos; this.signInARow = signInARow; }
/// <summary> /// Adds the new signsInARow and removes the ones which overlap /// </summary> private void NewSignPlaced(EvaluationField[,] field, IntVector2 where, out List <PlaceData> placed, out List <PlaceData> removed) { Cell.CellOcc currentType = field[where.x, where.y].type; List <PlaceData> _placed = new List <PlaceData>(); List <PlaceData> _removed = new List <PlaceData>(); // Check how many signs there are in a row that contains the where sign for (int i = 0; i < checkDirections.GetLength(0); i++) { int count = 1; IntVector2 endOne = new IntVector2(where), endTwo = new IntVector2(where); // Go through the checkdirection direction for (int j = 1; j < Grid.WIN_CONDITION; j++) { int examineX = where.x + checkDirections[i, 0] * j; int examineY = where.y + checkDirections[i, 1] * j; // We are in bounds //if (examineX >= 0 && examineX < field.GetLength(0) && examineY >= 0 && examineY < field.GetLength(1)) { // It is the same sign if (field[examineX, examineY].type == currentType) { count++; endOne = new IntVector2(examineX, examineY); } else { break; } } // Go through the opposite of checkdirection direction for (int j = 1; j < Grid.WIN_CONDITION; j++) { int examineX = where.x + -checkDirections[i, 0] * j; int examineY = where.y + -checkDirections[i, 1] * j; // We are in bounds //if (examineX >= 0 && examineX < field.GetLength(0) && examineY >= 0 && examineY < field.GetLength(1)) { // It is the same sign if (field[examineX, examineY].type == currentType) { count++; endTwo = new IntVector2(examineX, examineY); } else { break; } } if (count < 2) { continue; } // Now we have the endpoints of this checkdirection in endpoint one and endpoint two // We also have if there are blocks at the end if there is not then the block variables are null SignInARow signsInARow = new SignInARow(endOne, endTwo, currentType); IntVector2 end1 = signsInARow.From - signsInARow.Steepness, end2 = signsInARow.To + signsInARow.Steepness; signsInARow.SetEndEvaluationFields(field[end1.x, end1.y], field[end2.x, end2.y]); SignInARow removedSignInARow = null; field[where.x, where.y].AddSignInARow(signsInARow, out removedSignInARow); _placed.Add(new PlaceData(new IntVector2(where), signsInARow)); if (removedSignInARow != null) { _removed.Add(new PlaceData(new IntVector2(where), removedSignInARow)); } } placed = _placed; removed = _removed; }