Beispiel #1
0
        ////// END: very easy ai functionality
        /////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////
        ////// START: easy ai functionality
        #region easy AI
        public void invokeEasyAI()
        {
            VirtualBoard virtualBoard = game.getVirtualBoard();
            int          rowCount     = virtualBoard.getRowCount();
            int          colCount     = virtualBoard.getColCount();

            // [SC] using copy since indices in playerTiles may change due to removed tiles
            List <TileZeroTile> tempPlayerTiles = playerTiles.listShallowClone();

            bool tilePlacedFlag = false;
            bool shouldDropFlag = true;

            foreach (TileZeroTile tile in tempPlayerTiles)
            {
                // [SC] check if the tile is playable
                if (!tile.getPlayable())
                {
                    continue;
                }

                // [SC] add some daly before making next move
                if (tilePlacedFlag)
                {
                    tilePlacedFlag = false;
                }

                for (int currRowIndex = 0; currRowIndex < rowCount && !tilePlacedFlag; currRowIndex++)
                {
                    for (int currColIndex = 0; currColIndex < colCount; currColIndex++)
                    {
                        int resultScore = virtualBoard.isValidMove(currRowIndex, currColIndex, tile, true, null, false);

                        if (resultScore != Cfg.NONE)
                        {
                            setSelectedTile(tile);
                            game.setSelectedCell(currRowIndex, currColIndex, playerIndex);
                            game.placePlayerTileOnBoard(playerIndex);
                            tilePlacedFlag = true;
                            shouldDropFlag = false;
                            break;
                        }
                    }
                }
            }

            if (shouldDropFlag)
            {
                // [SC] dropping a random tile
                setSelectedTile(playerTiles.getRandomElement());
                game.dropPlayerTile(playerIndex);
                //Cfg.showMsg(getPlayerName() + " dropped a tile.");
            }
        }
Beispiel #2
0
 public Game()
 {
     virtualBoard = new VirtualBoard(this);
     rnd          = new Random();
 }
Beispiel #3
0
        // [SC] 1. Create lists of tiles where each list is a group of tiles with the same color or shape.
        // [SC] 2. For each group of tiles, create lists of tile sequences where each list contains a sequence of tiles in a unique order.
        // [SC] 3. For each tile sequence, create a combination of unique board positions.
        public CandidateTilePos calculateMoves(bool considerColor, bool considerShape, bool suboptiomal)
        {
            List <CandidateTileSeq> candTileSeqList = new List <CandidateTileSeq>(); // [TODO]

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            List <List <TileZeroTile> > colorTileLists = new List <List <TileZeroTile> >(); // [SC] each list contains player's tiles of the same color
            List <List <TileZeroTile> > shapeTileLists = new List <List <TileZeroTile> >(); // [SC] each list contains player's tiles of the same shape

            for (int index = 0; index < Cfg.MAX_VAL_INDEX; index++)
            {
                colorTileLists.Add(new List <TileZeroTile>());
                shapeTileLists.Add(new List <TileZeroTile>());
            }

            foreach (TileZeroTile tile in playerTiles)
            {
                colorTileLists[tile.getColorIndex()].Add(tile);
                shapeTileLists[tile.getShapeIndex()].Add(tile);
            }

            colorTileLists.RemoveAll(p => p.Count == 0);                    // [SC] remove empty tile combos
            shapeTileLists.RemoveAll(p => p.Count == 0);                    // [SC] remove empty tile combos

            colorTileLists = colorTileLists.OrderBy(p => p.Count).ToList(); // [SC] order by size of tile combos
            shapeTileLists = shapeTileLists.OrderBy(p => p.Count).ToList(); // [SC] order by size of tile combos

            if (considerColor)
            {
                // [SC] remove all color tile combos that are subsets of another color or shape combo
                for (int indexOne = 0; indexOne < colorTileLists.Count; indexOne++)
                {
                    List <TileZeroTile> tileComboOne = colorTileLists[indexOne];

                    for (int indexTwo = indexOne + 1; indexTwo < colorTileLists.Count; indexTwo++)
                    {
                        List <TileZeroTile> tileComboTwo = colorTileLists[indexTwo];

                        if (tileComboOne.All(p => tileComboTwo.Contains(p)))
                        {
                            tileComboOne.Clear();
                            continue;
                        }
                    }

                    if (tileComboOne.Count == 0)
                    {
                        continue;
                    }

                    if (considerShape)
                    {
                        for (int indexTwo = 0; indexTwo < shapeTileLists.Count; indexTwo++)
                        {
                            List <TileZeroTile> tileComboTwo = shapeTileLists[indexTwo];

                            // [SC] true if combo one is a subset of combo two
                            if (tileComboOne.Count <= tileComboTwo.Count && tileComboOne.All(p => tileComboTwo.Contains(p)))
                            {
                                tileComboOne.Clear();
                                continue;
                            }
                        }
                    }
                }
                colorTileLists.RemoveAll(p => p.Count == 0); // [SC] remove empty tile combos
            }

            if (considerShape)
            {
                // [SC] remove all shape tile combos that are subsets of another color or shape combo
                for (int indexOne = 0; indexOne < shapeTileLists.Count; indexOne++)
                {
                    List <TileZeroTile> tileComboOne = shapeTileLists[indexOne];

                    for (int indexTwo = indexOne + 1; indexTwo < shapeTileLists.Count; indexTwo++)
                    {
                        List <TileZeroTile> tileComboTwo = shapeTileLists[indexTwo];

                        if (tileComboOne.All(p => tileComboTwo.Contains(p)))
                        {
                            tileComboOne.Clear();
                            continue;
                        }
                    }

                    if (tileComboOne.Count == 0)
                    {
                        continue;
                    }

                    if (considerColor)
                    {
                        for (int indexTwo = 0; indexTwo < colorTileLists.Count; indexTwo++)
                        {
                            List <TileZeroTile> tileComboTwo = colorTileLists[indexTwo];

                            // [SC] true if combo one is a subset of combo two
                            if (tileComboOne.Count <= tileComboTwo.Count && tileComboOne.All(p => tileComboTwo.Contains(p)))
                            {
                                tileComboOne.Clear();
                                continue;
                            }
                        }
                    }
                }
                shapeTileLists.RemoveAll(p => p.Count == 0); // [SC] remove empty tile combos
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            if (considerColor)
            {
                // [SC] iterate through list of tiles with one particular color
                foreach (List <TileZeroTile> tileList in colorTileLists)
                {
                    int colorIndex = tileList[0].getColorIndex();

                    TreeNode rootNode = new TreeNode(null);
                    for (int tileIndex = 0; tileIndex < tileList.Count; tileIndex++)
                    {
                        tileListPermAddChildNodes(tileList, tileIndex, rootNode);
                    }

                    tileListPermTraverseTreePaths(rootNode, new List <TileZeroTile>(), colorIndex, Cfg.COLOR_ATTR, candTileSeqList);
                }
            }

            if (considerShape)
            {
                // [SC] iterate through list of tiles with one particular shape
                foreach (List <TileZeroTile> tileList in shapeTileLists)
                {
                    int shapeIndex = tileList[0].getShapeIndex();

                    TreeNode rootNode = new TreeNode(null);
                    for (int tileIndex = 0; tileIndex < tileList.Count; tileIndex++)
                    {
                        tileListPermAddChildNodes(tileList, tileIndex, rootNode);
                    }

                    tileListPermTraverseTreePaths(rootNode, new List <TileZeroTile>(), shapeIndex, Cfg.SHAPE_ATTR, candTileSeqList);
                }
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            int maxCTS = 10;

            if (candTileSeqList.Count > maxCTS)
            {
                candTileSeqList = candTileSeqList.OrderByDescending(p => p.getTileCount()).ToList();
                candTileSeqList.RemoveRange(maxCTS, candTileSeqList.Count - maxCTS);
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            VirtualBoard virtualBoard = game.getVirtualBoard();

            TileZeroTile[,] tileArray = virtualBoard.getBoardCopy();

            List <CandidateTilePos> chosenPosComboList   = new List <CandidateTilePos>();
            List <CandidateTilePos> maxScorePosComboList = new List <CandidateTilePos>();

            foreach (CandidateTileSeq candTileSeq in candTileSeqList)
            {
                TreeNode rootNode = new TreeNode(null);

                boardPosPermAddChildNodes(candTileSeq, 0, rootNode, tileArray, virtualBoard);
                if (suboptiomal)
                {
                    boardPosPermTraverseTreePaths(rootNode, new List <AbstractPos>(), candTileSeq, 0, chosenPosComboList, maxScorePosComboList);
                }
                else
                {
                    boardPosPermTraverseTreePaths(rootNode, new List <AbstractPos>(), candTileSeq, 0, chosenPosComboList);
                }
            }

            return(chosenPosComboList.getRandomElement());
        }
Beispiel #4
0
        /////////////////////////////////////////////////////////////////
        ////// START: A code for creating all possible permutations of board positions
        ////// of tiles in given list, starting from left-most tile in the array

        private void boardPosPermAddChildNodes(CandidateTileSeq candTileSeq, int currTileIndex, TreeNode parentNode, TileZeroTile[,] tileArray, VirtualBoard virtualBoard)
        {
            if (currTileIndex >= candTileSeq.getTileCount())
            {
                return;
            }

            TileZeroTile tile = candTileSeq.getTileAt(currTileIndex);

            for (int currRowIndex = 0; currRowIndex < tileArray.GetLength(0); currRowIndex++)
            {
                for (int currColIndex = 0; currColIndex < tileArray.GetLength(1); currColIndex++)
                {
                    int resultScore = virtualBoard.isValidMove(currRowIndex, currColIndex, tile, true, tileArray, false);

                    if (resultScore != Cfg.NONE)
                    {
                        TileZeroTile[,] newTileArray = Cfg.createBoardCopy(tileArray);
                        virtualBoard.addTile(currRowIndex, currColIndex, tile, false, newTileArray);
                        TreeNode childNode = parentNode.addChildNodeValue(new AbstractPos(currTileIndex, currRowIndex, currColIndex, resultScore));
                        boardPosPermAddChildNodes(candTileSeq, currTileIndex + 1, childNode, newTileArray, virtualBoard);
                    }
                }
            }

            boardPosPermAddChildNodes(candTileSeq, currTileIndex + 1, parentNode, tileArray, virtualBoard); // [SC][2016.12.08] new code
        }