protected override void CheckingNewRevealed(Vector2Int currentnewrevealed)
    {
        //count the number of neighbores of this tile
        List <Vector2Int> newClosedHiddenNeighbors = new List <Vector2Int>();

        ClosedHiddenNeighbores.Add(currentnewrevealed, newClosedHiddenNeighbors);

        for (int j = 0; j < Operators.Length; j++)
        {
            Vector2Int current = currentnewrevealed + Operators[j];
            if (Flaged.Contains(current))
            {
                Closed[currentnewrevealed]--;
            }
            else if (MinesweeperElementInfo.InBounds(current, BoardSize.x, BoardSize.y))
            {
                if (Open.ContainsKey(current) || Safe.Contains(current) || Mine.Contains(current))
                {
                    newClosedHiddenNeighbors.Add(current);
                    List <Vector2Int> clist = HiddenClosedRelations[current];
                    clist.Add(currentnewrevealed);
                }
                else if (!InvalidTiles[current.x, current.y] && !Closed.ContainsKey(current))
                {
                    Open.Add(current, 0);
                    newClosedHiddenNeighbors.Add(current);
                    List <Vector2Int> clist = new List <Vector2Int>();
                    HiddenClosedRelations.Add(current, clist);
                    clist.Add(currentnewrevealed);
                }
            }
        }
    }
    protected bool NextToInvalidTile(Vector2Int tile)
    {
        int maxx = BoardSize.x;
        int maxy = BoardSize.y;

        for (int i = 0; i < Operators.Length; i++)
        {
            Vector2Int current = tile + Operators[i];
            if (MinesweeperElementInfo.InBounds(current, maxx, maxy) && InvalidTiles[current.x, current.y])
            {
                return(true);
            }
        }
        return(false);
    }
 GetRequestedMinesweeperElementInfos(MinesweeperGamestate gamestate, KeyValuePair <AIDataType, Vector2Int[]>[] request)
 {
     KeyValuePair <AIDataType, KeyValuePair <Vector2Int, MinesweeperElementInfo>[]>[] newanswer
         = new KeyValuePair <AIDataType, KeyValuePair <Vector2Int, MinesweeperElementInfo>[]> [request.Length];
     for (int i = 0; i < request.Length; i++)
     {
         KeyValuePair <Vector2Int, MinesweeperElementInfo>[] currentrequest = MinesweeperElementInfo.GetFilteredTiles(gamestate, request[i].Value);
         newanswer[i] = new KeyValuePair <AIDataType, KeyValuePair <Vector2Int, MinesweeperElementInfo>[]>
                        (
             request[i].Key,
             currentrequest
                        );
     }
     return(newanswer);
 }
Esempio n. 4
0
    private static Vector2Int[] OnReveal(MinesweeperGamestate tiles, Vector2Int tile, Vector2Int[] operators)
    {
        //creating local variable resuting in mminimal performance boost
        int maxx = tiles.LengthX;
        int maxy = tiles.LengthY;

        List <Vector2Int> NeedUpdate = new List <Vector2Int>();
        List <Vector2Int> opentiles  = new List <Vector2Int>();

        if (tiles[tile].hidden && !tiles[tile].flaged)
        {
            if (tiles[tile].value == 0)
            {
                opentiles.Add(tile);
            }
            else if (tiles[tile].value >= 9)
            {
                Debug.Log("Game Over");
                tiles.GameOver = true;
            }
            tiles[tile].hidden = false;
            NeedUpdate.Add(tile);
        }
        while (opentiles.Count != 0)
        {
            for (int i = 0; i < operators.Length; i++)
            {
                Vector2Int current = opentiles[0] + operators[i];
                if (MinesweeperElementInfo.InBounds(current, maxx, maxy))
                {
                    if (tiles[current].hidden)
                    {
                        tiles[current].hidden = false;
                        NeedUpdate.Add(current);
                        if (tiles[current].value == 0)
                        {
                            opentiles.Add(current);
                        }
                    }
                }
            }
            opentiles.RemoveAt(0);
        }
        return(NeedUpdate.ToArray());
    }
 private int GetSpriteId(MinesweeperElementInfo msei)
 {
     if (msei.hidden)
     {
         if (msei.flaged)
         {
             return(10);
         }
         else
         {
             return(9);
         }
     }
     else
     {
         return(msei.value >= 9 ? 12 : msei.value);
     }
 }
 /// <summary>
 /// Iterates through 'currentnewrevealed', checking if 'currentnewrevealed' can be discarded,
 /// while adding new open tile
 /// </summary>
 /// <param name="currentnewrevealed"></param>
 protected virtual void CheckingNewRevealed(Vector2Int currentnewrevealed)
 {
     for (int j = 0; j < Operators.Length; j++)
     {
         Vector2Int current = currentnewrevealed + Operators[j];
         if (Flaged.Contains(current))
         {
             Closed[currentnewrevealed]--;
         }
         else if (MinesweeperElementInfo.InBounds(current, BoardSize.x, BoardSize.y))
         {
             //i wanted to make the minesweeper and the solver independent from eachother, thats why i didn't simply passed the minesweeperelementinfo object at 'current' tile
             if (!InvalidTiles[current.x, current.y] && !Open.ContainsKey(current) && !Closed.ContainsKey(current) && !Safe.Contains(current) && !Mine.Contains(current))
             {
                 Open.Add(current, 0);
             }
         }
     }
 }
    /// <summary>
    /// Updates only the tiles directly affected by an action, send List of needed elements
    /// (Only for when revealing new tiles)
    /// </summary>
    /// <param name="toupdate">Information about newly revealed tiles</param>
    /// <param name="mat">The newly revealed tiles of the minesweeper table</param>
    public override void GetRelevantBoard(KeyValuePair <Vector2Int, MinesweeperElementInfo>[] toupdate, MinesweeperActionType mat)
    {
        if (mat == MinesweeperActionType.Uncover)
        {
            for (int i = 0; i < toupdate.Length; i++)
            {
                //note that every item in toupdate are revealed
                Vector2Int             currentnewrevealed = toupdate[i].Key;
                MinesweeperElementInfo currentmsei        = toupdate[i].Value;

                //there is always a possibility that the newly revealed tiles are in Open or Safe (when multiple tiles revealed)
                RemoveForSafety(currentnewrevealed);
                //add non-empties to 'Closed'
                if (currentmsei.value != 0)
                {
                    Closed.Add(currentnewrevealed, currentmsei.value);

                    //iterating  through currently revealed tile, finding new tiles while trying to eliminate currentnewrevealed
                    CheckingNewRevealed(currentnewrevealed);
                    //remove from closed if after iteration value become 0 or less
                    if (Closed[currentnewrevealed] <= 0)
                    {
                        WhenRemovingClosedNeighborCheck(currentnewrevealed);
                    }
                }
                else
                {
                    InvalidTiles[currentnewrevealed.x, currentnewrevealed.y] = true;
                }
            }
        }
        else if (mat == MinesweeperActionType.Flag)
        {
            for (int i = 0; i < toupdate.Length; i++)
            {
                Vector2Int currentmine = toupdate[i].Key;
                OnAddingFlaged(currentmine);
            }
        }
    }
    /// <summary>
    /// This method was used before Invalidtiles
    /// </summary>
    /// <param name="answer">Data received from AIRequestProvider.GetRequestedMinesweeperElementInfos method</param>
    public void AnswerProcecessor(KeyValuePair <AIDataType, KeyValuePair <Vector2Int, MinesweeperElementInfo>[]>[] answer)
    {
        for (int i = 0; i < answer.Length; i++)
        {
            AIDataType requestType = answer[i].Key;
            KeyValuePair <Vector2Int, MinesweeperElementInfo>[] currentanswer = answer[i].Value;

            for (int j = 0; j < currentanswer.Length; j++)
            {
                Vector2Int             currenttile = currentanswer[j].Key;
                MinesweeperElementInfo currentmsei = currentanswer[j].Value;
                if (currentmsei.hidden)
                {
                    switch (requestType)
                    {
                    case AIDataType.Open:
                    {
                        //for safety, i only allow tiles to be considered safe if they were previusly open
                        //so here i check if they belong to 'Safe'
                        if (NextToInvalidTile(currenttile))
                        {
                            Safe.Add(currenttile);
                        }
                        else
                        {
                            Open.Add(currenttile, 0);
                        }
                        break;
                    }

                    case AIDataType.Safe:
                    {
                        Safe.Add(currenttile);
                        break;
                    }
                    }
                }
            }
        }
    }
    /// <summary>
    /// Checks the whole board
    /// </summary>
    /// <param name="table"> The whole minesweeper table</param>
    public override void GetBoard(MinesweeperElementInfo[,] table)
    {
        List <Vector2Int> newpositions = new List <Vector2Int>();

        for (int y = 0; y < table.GetLength(1); y++)
        {
            for (int x = 0; x < table.GetLength(0); x++)
            {
                MinesweeperElementInfo current    = table[x, y];
                Vector2Int             currentpos = new Vector2Int(x, y);
                if (!current.hidden && current.value > 0)
                {
                    if (!Closed.ContainsKey(currentpos))
                    {
                        newpositions.Add(currentpos);
                    }
                }
            }
        }
        for (int i = 0; i < newpositions.Count; i++)
        {
            for (int j = 0; j < Operators.Length; j++)
            {
                Vector2Int current = newpositions[i] + Operators[j];
                //in bounds
                if (current.x >= 0 && current.y >= 0 && current.x < table.GetLength(1) && current.y < table.GetLength(0))
                {
                    if (table[current.x, current.y].hidden && !table[current.x, current.y].flaged && !Open.ContainsKey(current))
                    {
                        Open.Add(current, 0);
                    }
                }
            }
            Closed.Add(newpositions[i], table[newpositions[i].x, newpositions[i].y].value);
        }
    }
Esempio n. 10
0
    /// <summary>
    /// The first action commited by the player
    /// </summary>
    /// <param name="tiles"></param>
    /// <param name="firststep"></param>
    /// <param name="rule"></param>
    /// <param name="operators"></param>
    public static Vector2Int[] FirstOnReveal(MinesweeperGamestate tiles, Vector2Int firststep, MinesweeperFirstStepRule rule, Vector2Int[] operators)
    {
        //creating local variable resuting in miminimal performance boost
        int maxx = tiles.LengthX;
        int maxy = tiles.LengthY;

        if (rule == MinesweeperFirstStepRule.SafeSouranding)
        {
            //finding the 'safe tiles'
            List <Vector2Int> safe = new List <Vector2Int>();
            for (int i = 0; i < operators.Length; i++)
            {
                Vector2Int current = firststep + operators[i];
                if (MinesweeperElementInfo.InBounds(current, maxx, maxy))
                {
                    safe.Add(current);
                }
            }
            safe.Add(firststep);
            //remove mines from 'safe tiles'
            List <Vector2Int> bombpositions = new List <Vector2Int>();
            for (int i = 0; i < safe.Count; i++)
            {
                if (tiles[safe[i]].value >= 9)
                {
                    tiles[safe[i]].value = 0;
                    bombpositions.Add(safe[i]);
                }
            }
            //recalculate value of mines inside, and the souranding of 'safe' tiles
            for (int i = 0; i < bombpositions.Count; i++)
            {
                for (int j = 0; j < operators.Length; j++)
                {
                    Vector2Int current = bombpositions[i] + operators[j];
                    if (MinesweeperElementInfo.InBounds(current, maxx, maxy))
                    {
                        if (tiles[current].value >= 9)
                        {
                            tiles[bombpositions[i]].value++;
                        }
                        else if (!bombpositions.Contains(current))
                        {
                            tiles[current].value--;
                        }
                    }
                }
            }
            //reassigning mines [not fixed time], but faster
            List <Vector2Int> newbombs = new List <Vector2Int>();
            while (bombpositions.Count != newbombs.Count)
            {
                Vector2Int current = new Vector2Int(Random.Range(0, maxx), Random.Range(0, maxy));
                if (tiles[current].value < 9 && !safe.Contains(current))
                {
                    tiles[current].value = 9;
                    newbombs.Add(current);
                }
            }
            //recalculate souranding of the new mines
            for (int i = 0; i < newbombs.Count; i++)
            {
                for (int j = 0; j < operators.Length; j++)
                {
                    Vector2Int current = newbombs[i] + operators[j];
                    if (MinesweeperElementInfo.InBounds(current, maxx, maxy))
                    {
                        tiles[current].value++;
                    }
                }
            }
        }
        else if (rule == MinesweeperFirstStepRule.SafeTile)
        {
            //firststep
            if (tiles[firststep].value >= 9)
            {
                tiles[firststep].value = 0;
                //recalculate value of firststep, and it's souranding
                for (int i = 0; i < operators.Length; i++)
                {
                    Vector2Int current = firststep + operators[i];
                    if (MinesweeperElementInfo.InBounds(current, maxx, maxy))
                    {
                        if (tiles[current].value >= 9)
                        {
                            tiles[firststep].value++;
                        }
                        else
                        {
                            tiles[current].value--;
                        }
                    }
                }
                //reassigning mine, and recalculate it's souranding
                while (true)
                {
                    Vector2Int current = new Vector2Int(Random.Range(0, maxx), Random.Range(0, maxy));
                    if (tiles[current].value < 9 && current != firststep)
                    {
                        tiles[current].value = 9;
                        for (int i = 0; i < operators.Length; i++)
                        {
                            Vector2Int current2 = current + operators[i];
                            if (MinesweeperElementInfo.InBounds(current2, maxx, maxy))
                            {
                                tiles[current2].value++;
                            }
                        }
                        break;
                    }
                }
                if (tiles[firststep].value >= 9)
                {
                    throw new System.Exception();
                }
            }
        }
        return(OnReveal(tiles, firststep, operators));
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            InfoPanel.SetActive(!InfoPanel.activeInHierarchy);
        }
        if (!useai)
        {
            if (Input.GetMouseButtonDown(0))
            {
                MinesweeperInteractionManager.OnStep(new KeyValuePair <MinesweeperActionType, Vector2Int>(MinesweeperActionType.Uncover, new Vector2Int(updatepos.x, -updatepos.y + settings.y - 1)),
                                                     gamestate, settings.Operators);
                vh.UpdateVisualMinesweeperComplete(gamestate);
            }
            else if (Input.GetMouseButtonDown(1))
            {
                MinesweeperInteractionManager.OnStep(new KeyValuePair <MinesweeperActionType, Vector2Int>(MinesweeperActionType.Flag, new Vector2Int(updatepos.x, -updatepos.y + settings.y - 1)),
                                                     gamestate, settings.Operators);
                vh.UpdateVisualMinesweeperComplete(gamestate);
            }
        }
        if (sampleindex <= samplesize)
        {
            currenttime = updatetime;
        }
        while (useai && currenttime >= 0 && !requireclick)
        {
            if (!gamestate.GameOver)
            {
                Vector2Int[] needtobeupdated;
                KeyValuePair <MinesweeperActionType, Vector2Int> aistep = af.ChooseStep();
                //Debug.Log(aistep);
                if (gamestate.FirstStep)
                {
                    needtobeupdated     = MinesweeperInteractionManager.FirstOnReveal(gamestate, aistep.Value, settings.FirstStepRule, settings.Operators);
                    gamestate.FirstStep = false;
                }
                else
                {
                    needtobeupdated = MinesweeperInteractionManager.OnStep(aistep, gamestate, settings.Operators);
                }
                //update database, and request tiles
                af.GetRelevantBoard(MinesweeperElementInfo.GetFilteredTiles(gamestate, needtobeupdated), aistep.Key);
                //answer to requested tiles
                //KeyValuePair<AIRequestType, KeyValuePair<Vector2Int, MinesweeperElementInfo>[]>[] answertiles = AIRequestProvider.GetRequestedMinesweeperElementInfos(gamestate, requestedtiles);
                //update database with requested tiles
                //af.AnswerProcecessor(answertiles);

                vh.UpdateVisualMinesweeperQuick(MinesweeperElementInfo.GetFilteredTiles(gamestate, needtobeupdated));
            }

            if (sampleindex <= samplesize)
            {
                if (gamestate.GameOver)
                {
                    NewGame();
                    SetUpSolver();
                }
                else if (af.Flaged.Count == settings.NumberOfMines)
                {
                    samplewins++;
                    NewGame();
                    SetUpSolver();
                }
            }
            if (ClickToStep)
            {
                requireclick = true;
            }

            currenttime -= Time.deltaTime;
        }

        //helps to see the current state of the game
        if (useai && settings.Rendering)
        {
            Vector2Int[] v2is = af.InvalidTiles.GetPositions(true);
            vh.HighlightTiles(af.Mine.ToArray(), AIDataType.Mine);
            vh.HighlightTiles(af.Safe.ToArray(), AIDataType.Safe);
            vh.HighlightTiles(af.Open.Keys.ToArray(), AIDataType.Open);
            vh.HighlightTiles(af.Closed.Keys.ToArray(), AIDataType.Closed);
            vh.HighlightTiles(v2is, AIDataType.Invalid);

            vh.FinalizeUpdate();
        }


        if (sleeptime > 0)
        {
            Thread.Sleep(sleeptime);
        }
        indextext.text = (sampleindex - 1).ToString();
        wintext.text   = samplewins.ToString();
        //fps
        fpsText.text = ((int)(1.0f / Time.deltaTime)).ToString();
    }