Beispiel #1
0
 private static bool Check(Board board, Rack rack, PlayPath path, bool verbose = true)
 {
     try
     {
         board.Play(path);
         var letters = new List <char>(rack.Letters);
         foreach (LetterPlay lp in path.Played)
         {
             if (!letters.Contains(lp.Letter))
             {
                 throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} not in rack ({1})", lp.Letter, rack.Value));
             }
             letters.Remove(lp.Letter);
         }
         return(true);
     }
     catch (OutOfBoardException e)
     {
         if (verbose)
         {
             Log(e);
         }
         return(false);
     }
     catch (ArgumentException e)
     {
         if (verbose)
         {
             Log(e);
         }
         return(false);
     }
 }
Beispiel #2
0
        private static IEnumerable <Tuple <Fix, Cell> > GetFixCells(PlayPath path)
        {
            Direction direction = path.Main.Direction;
            var       start     = new List <Tuple <Fix, Cell> >();

            switch (direction)
            {
            case Direction.Right:
                if (path.Main.First.HasLeft)
                {
                    start.Add(new Tuple <Fix, Cell>(Fix.Prefix, path.Main.First.Left));
                }
                if (path.Main.Last.HasRight)
                {
                    start.Add(new Tuple <Fix, Cell>(Fix.Suffix, path.Main.Last.Right));
                }
                break;

            case Direction.Down:
                if (path.Main.First.HasTop)
                {
                    start.Add(new Tuple <Fix, Cell>(Fix.Prefix, path.Main.First.Up));
                }
                if (path.Main.Last.HasBottom)
                {
                    start.Add(new Tuple <Fix, Cell>(Fix.Suffix, path.Main.Last.Down));
                }
                break;
            }
            return(start);
        }
Beispiel #3
0
        [Test] public void TestPlaySecondNovice()
        {
            var part1  = new WordPart("LETTRE", new Cell(4, 3), Direction.Right);
            var board1 = new Board().Play(part1);
            var part2  = new WordPart("LE", new Cell(4, 3), Direction.Down);
            var play   = new PlayPath(part2, new LetterPlay(new Cell(5, 3), 'E'), new ConstantList <char>("MOTUR".ToList()));
            var board2 = board1.Play(play);

            Assert.AreEqual(new PlayerScore(5, 1), board2.Score.Current);
            Assert.AreEqual(new PlayerScore(2, 0), board2.Score.Other);
        }
Beispiel #4
0
        [Test] public void TestGetPathArgumentException()
        {
            var board = new Board();
            var part1 = new WordPart("YEWS", new Cell(4, 4), Direction.Right);

            board = board.Play(part1);
            var      rack  = new Rack("ESZZZZ");
            PlayPath path2 = Shell.GetPath(board, rack, "YES", 4, 4, null);

            Assert.IsNotNull(path2);
        }
Beispiel #5
0
        [Test] public void TestPlaySecondSameDirection()
        {
            var part1  = new WordPart("ET", new Cell(4, 3), Direction.Right);
            var board1 = new Board().Play(part1);
            var part2  = new WordPart("LETTRE", new Cell(4, 2), Direction.Right);
            var played = LetterPlayTest.GetPlayed(part2, 1, 2);
            var play   = new PlayPath(part2, new WordPartCollection(), played, new ConstantList <char>());
            var board2 = board1.Play(play);

            Assert.AreEqual(new PlayerScore(0, 0), board2.Score.Current);
            Assert.AreEqual(new PlayerScore(6, 0), board2.Score.Other);
        }
Beispiel #6
0
        [Test] public void TestPlayVortexAddStars()
        {
            var part1  = new WordPart("LETTRE", new Cell(4, 2), Direction.Right);
            var board1 = new Board().Play(part1);
            var part2  = new WordPart("JOUES", new Cell(0, 8), Direction.Down);
            var played = LetterPlayTest.GetPlayed(part2);
            var extra  = part1.Play(new Cell(4, 8), 'S');
            var play   = new PlayPath(part2, new WordPartCollection(extra), played.ToConstant(), new ConstantList <char>());
            var board2 = board1.Play(play);

            Assert.AreEqual(new PlayerScore(0, 0), board2.Score.Current);
            Assert.AreEqual(new PlayerScore(12, 0), board2.Score.Other);
        }
Beispiel #7
0
        [Test] public void TestPlaySecondExpert()
        {
            var part1  = new WordPart("LETTRE", new Cell(4, 2), Direction.Right);
            var board1 = new Board().Play(part1);
            var part2  = new WordPart("MOTEUR", new Cell(1, 8), Direction.Down);
            var played = LetterPlayTest.GetPlayed(part2);
            var extra  = part1.Play(new Cell(4, 8), 'E');
            var play   = new PlayPath(part2, new WordPartCollection(extra), played, new ConstantList <char>());
            var board2 = board1.Play(play);

            Assert.AreEqual(new PlayerScore(0, 0), board2.Score.Current);
            Assert.AreEqual(new PlayerScore(12, 1), board2.Score.Other);
        }
Beispiel #8
0
            public Choices(WordGraph graph, Board board, PlayPath path, Fix fix, Cell cell)
            {
                this.fix  = fix;
                this.cell = cell;
                Direction direction      = path.Main.Direction;
                var       otherDirection = direction == Direction.Down ? Direction.Right : Direction.Down;
                var       playable       = new PlayableLetters(path.Pending);
                WordPart  before         = fix == Fix.Suffix ? path.Main : null;
                WordPart  after          = fix == Fix.Prefix ? path.Main : null;

                main    = GetBeforeAfter(board, cell, direction, graph, playable, before, after);
                extra   = GetBeforeAfter(board, cell, otherDirection, graph, playable);
                letters = playable.Choices.ToConstant();
            }
Beispiel #9
0
        internal static PlayPath GetPath(Board board, Rack rack, string word, int row, int column, Direction?direction = null)
        {
            Cell cell = GetCell(row, column);

            if (cell == null)
            {
                return(null);
            }
            PlayPath path = GetPath(board, rack, word, cell, direction);

            if (path == null)
            {
                return(null);
            }
            return(path);
        }
Beispiel #10
0
        private static PlayPath GetPath(Board board, Rack rack, string word, Cell cell, Direction?direction)
        {
            var directions = new List <Direction>();

            if (!direction.HasValue)
            {
                directions.AddRange(new[] { Direction.Down, Direction.Right });
            }
            else
            {
                directions.Add(direction.Value);
            }
            var paths = new List <PlayPath>();

            foreach (Direction d in directions)
            {
                try
                {
                    var      part = new WordPart(word, cell, d);
                    PlayPath path = GetPath(board, rack, part);
                    if (Check(board, rack, path, false))
                    {
                        paths.Add(path);
                    }
                }
                catch (ArgumentException)
                {
                }
                catch (OutOfBoardException)
                {
                }
            }
            if (paths.Count == 1)
            {
                return(paths[0]);
            }
            if (paths.Count > 1)
            {
                Log(new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Cannot guess direction to play {0} at {1}", word, cell)));
            }
            else
            {
                Log(new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Cannot play {0} at {1}", word, cell)));
            }
            return(null);
        }
Beispiel #11
0
 private static void WriteMoves(IComparer <PlayInfo> comparer, IEnumerable <Tuple <double, PlayInfo, PlayPath> > moves)
 {
     Console.WriteLine(comparer);
     foreach (Tuple <double, PlayInfo, PlayPath> tuple in moves)
     {
         double   weight = tuple.Item1;
         PlayInfo info   = tuple.Item2;
         PlayPath path   = tuple.Item3;
         Console.WriteLine("{0} word: {1} - {2}{3}{4}[{5}] ({6}){7}",
                           weight.ToString("0.###", CultureInfo.InvariantCulture),
                           path.Main,
                           info.HasFixes && !info.HasVortex ? (info.HasOneFixes ? "1" : "") + (info.HasTwoMoreFixes ? "2+" : "") + "fixes " : "",
                           info.HasVortex ? "vortex " : "",
                           info.Points,
                           info.Diff.ToString("+#;-#;0", CultureInfo.InvariantCulture),
                           info.Stars,
                           info.Wins ? " wins" : "");
     }
     Console.WriteLine();
 }
Beispiel #12
0
        public Tuple <Fix, Fix> GetFixes(PlayPath path)
        {
            var min = new Dictionary <Direction, HashSet <int> >();

            min.Add(Direction.Down, new HashSet <int>());
            min.Add(Direction.Right, new HashSet <int>());
            var max = new Dictionary <Direction, HashSet <int> >();

            max.Add(Direction.Down, new HashSet <int>());
            max.Add(Direction.Right, new HashSet <int>());

            //var chrono = new Chrono();
            var done      = new HashSet <WordPart>();
            var allValids = new Dictionary <WordPart, PlayPath>();
            var temp      = new PlayPath(path.Main, path.Extras, path.Played, null);

            GetNewPaths(graph, board, temp, temp, done, allValids, false, min, max);
            //double seconds = Convert.ToInt32(chrono.Elapsed.TotalSeconds * 10) * .1;
            //if (seconds > 0)
            //    Console.WriteLine("Analyzed {0} fix paths in {1} s", done.Count, seconds);
            return(GetFixes(path.Main, allValids.Values));
        }
Beispiel #13
0
        private static Board TestPlayIgnoreExtra(IList <Tuple <string, string, Cell, Direction> > plays)
        {
            var graph = WordGraph.French;
            var board = new Board();
            var rack  = new Rack(plays[0].Item1);

            var part1 = new WordPart(plays[0].Item2, plays[0].Item3, plays[0].Item4);

            board = board.Play(part1);

            for (int i = 1; i < plays.Count; i++)
            {
                rack = new Rack(plays[i].Item1);
                PlayGraph play       = new PlayGraph(graph, board, rack);
                var       moveFinder = new MoveFinder(graph, board, play);
                List <Tuple <PlayInfo, PlayPath> > moves = moveFinder.GetAllMoves();
                foreach (Tuple <PlayInfo, PlayPath> move in moves)
                {
                    PlayPath path = move.Item2;
                    if (plays[i].Item2 != path.Main.Word ||
                        plays[i].Item3 != path.Main.First ||
                        plays[i].Item4 != path.Main.Direction)
                    {
                        continue;
                    }
                    board = board.Play(path);
                    if (i != plays.Count - 1)
                    {
                        continue;
                    }
                    Assert.GreaterOrEqual(board.Score.Other.Points, 0);
                    Assert.GreaterOrEqual(board.Score.Current.Points, 0);
                    return(board);
                }
            }
            throw new InvalidOperationException("Move not found");
        }
Beispiel #14
0
 public Board Play(PlayPath path)
 {
     return(Play(path.Main, path.Played, path.Extras));
 }
Beispiel #15
0
        private PlayPath ReadMove(Board board, Rack rack)
        {
            var regex = new Regex(@"^\s*(?<word>[a-z]+)\s*(?<row>\d),(?<column>\d)\s*(?<direction>(down|right|))\s*$", RegexOptions.IgnoreCase);

            using (DisposableColor.Prompt)
                Console.Write("move? ");
            Console.Write("[word r,c down|right] [play|guess|skip] ");
            while (true)
            {
                try
                {
                    string line = null;
                    using (new DisposableColor(PlayerScore.GetColor(board.Current)))
                        line = ReadLine().Trim();
                    if (line == "skip")
                    {
                        return(null);
                    }
                    if (line == "play" || line == "guess")
                    {
                        if (board.IsEmpty)
                        {
                            var      game = new Game(random, graph);
                            WordPart part = game.GetFirstWord(rack);
                            Console.WriteLine(part);
                            Console.WriteLine();

                            var played  = part.GetPlayed();
                            var pending = new List <char>(rack.Letters);
                            foreach (LetterPlay lp in played)
                            {
                                pending.Remove(lp.Letter);
                            }
                            var path = new PlayPath(part, new WordPartCollection(), part.GetPlayed(), pending.ToConstant());
                            if (line == "play")
                            {
                                return(path);
                            }
                        }
                        else
                        {
                            PlayPath path = FindMove(rack);
                            if (line == "play")
                            {
                                return(path);
                            }
                        }
                    }
                    Match m = regex.Match(line);
                    if (m.Success)
                    {
                        string    word      = m.Groups["word"].Value;
                        int       row       = int.Parse(m.Groups["row"].Value, CultureInfo.InvariantCulture);
                        int       column    = int.Parse(m.Groups["column"].Value, CultureInfo.InvariantCulture);
                        Direction?direction = Parse(m.Groups["direction"].Value);
                        PlayPath  path      = GetPath(board, rack, word, row, column, direction);
                        if (path != null)
                        {
                            Console.WriteLine();
                            return(path);
                        }
                    }
                    Console.Write("? ");
                }
                catch (FormatException e)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("{0} : {1}", e.GetType().Name, e.Message);
                    Console.ForegroundColor = color;
                    Console.Write("? ");
                }
            }
        }
Beispiel #16
0
        internal static void GetNewPaths(WordGraph graph, Board board, PlayPath origin, PlayPath path, ISet <WordPart> done, IDictionary <WordPart, PlayPath> newValids, bool validOnly, Dictionary <Direction, HashSet <int> > min, Dictionary <Direction, HashSet <int> > max)
        {
            if (!validOnly)
            {
                //if (min[path.Main.Direction].Contains(0) && max[path.Main.Direction].Contains(8))
                //    return;

                //Console.WriteLine("{0}{1}", new string('.', path.Main.Direction == Direction.Bottom ? path.Main.First.Row : path.Main.First.Column), path.Main.Word);
            }

            IEnumerable <Tuple <Fix, Cell> > start = GetFixCells(path);

            foreach (Tuple <Fix, Cell> fixCell in start)
            {
                Fix  fix  = fixCell.Item1;
                Cell cell = fixCell.Item2;

                if (!validOnly)
                {
                    if (fix == Fix.Prefix)
                    {
                        if (min[path.Main.Direction].Contains(0))
                        {
                            break;
                        }
                        if (path.Main.Direction == Direction.Right)
                        {
                            if (origin.Main.First.Column - path.Main.First.Column >= 2 || path.Main.First.Column == 0)
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (origin.Main.First.Row - path.Main.First.Row >= 2 || path.Main.First.Row == 0)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (max[path.Main.Direction].Contains(0))
                        {
                            break;
                        }
                        if (path.Main.Direction == Direction.Right)
                        {
                            if (path.Main.Last.Column - origin.Main.Last.Column >= 2 || path.Main.Last.Column == 8)
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (path.Main.Last.Row - origin.Main.Last.Row >= 2 || path.Main.Last.Row == 8)
                            {
                                break;
                            }
                        }
                    }
                }

                var choices = new Choices(graph, board, path, fix, cell);
                if (choices.Letters.Count == 0)
                {
                    continue;
                }
                GetNewPaths(graph, board, origin, path, done, newValids, choices, validOnly, min, max);
            }
        }
Beispiel #17
0
        internal static void GetNewPaths(WordGraph graph, Board board, PlayPath origin, PlayPath path, ISet <WordPart> done, IDictionary <WordPart, PlayPath> newValids, Choices choices, bool validOnly, Dictionary <Direction, HashSet <int> > min, Dictionary <Direction, HashSet <int> > max)
        {
            foreach (char letter in choices.Letters)
            {
                WordPart mainPart = choices.Main.Play(choices.Cell, letter);
                if (done.Contains(mainPart))
                {
                    continue;
                }
                if (!validOnly)
                {
                    if (choices.Fix == Fix.Prefix)
                    {
                        if (min[path.Main.Direction].Contains(0))
                        {
                            break;
                        }
                    }
                    else if (choices.Fix == Fix.Suffix)
                    {
                        if (max[path.Main.Direction].Contains(8))
                        {
                            break;
                        }
                    }
                }
                WordPart extraPart = choices.Extra.Play(choices.Cell, letter);
                if (extraPart != null && (validOnly && !graph.IsValid(extraPart.Word) || !validOnly && !graph.Contains(extraPart.Word)))
                {
                    continue;
                }
                ConstantList <char> pending = null;
                if (path.Pending != null)
                {
                    var temp = new List <char>(path.Pending);
                    temp.Remove(letter);
                    if (temp.Count == 0 && !graph.IsValid(mainPart.Word))
                    {
                        continue;
                    }
                    pending = temp.ToConstant();
                }
                var extras = new List <WordPart>(path.Extras);
                if (extraPart != null)
                {
                    extras.Add(extraPart);
                }
                var letterPlay = new LetterPlay(choices.Cell, letter);
                var played     = new List <LetterPlay>(path.Played);
                if (choices.Fix == Fix.Prefix)
                {
                    played.Insert(0, letterPlay);
                }
                else
                {
                    played.Add(letterPlay);
                }
                bool valid   = mainPart.Word.Length == 1 || graph.IsValid(mainPart.Word);
                var  newPath = new PlayPath(mainPart, new WordPartCollection(extras.ToConstant()), played.ToConstant(), pending);
                if (valid && !newValids.ContainsKey(mainPart))
                {
                    newValids.Add(mainPart, newPath);
                }
                done.Add(mainPart);
                {
                    if (!validOnly && valid)
                    {
                        min[mainPart.Direction].Add(mainPart.Direction == Direction.Right ? newPath.Main.First.Column : newPath.Main.First.Row);
                        max[mainPart.Direction].Add(mainPart.Direction == Direction.Right ? newPath.Main.Last.Column : newPath.Main.Last.Row);

                        if (choices.Fix == Fix.Prefix)
                        {
                            if (path.Main.Direction == Direction.Right)
                            {
                                if (origin.Main.First.Column - path.Main.First.Column >= 2 || path.Main.First.Column == 0)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (origin.Main.First.Row - path.Main.First.Row >= 2 || path.Main.First.Row == 0)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (path.Main.Direction == Direction.Right)
                            {
                                if (path.Main.Last.Column - origin.Main.Last.Column >= 2 || path.Main.Last.Column == 8)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (path.Main.Last.Row - origin.Main.Last.Row >= 2 || path.Main.Last.Row == 8)
                                {
                                    break;
                                }
                            }
                        }
                    }
                    GetNewPaths(graph, board, origin, newPath, done, newValids, validOnly, min, max);
                }
            }
        }
Beispiel #18
0
        public void Run()
        {
            Rack rack = null;

            while (true)
            {
                try
                {
                    bool skipped = false;
                    var  pending = new List <char>();
                    while (!board.Score.Other.Wins)
                    {
                        board.Write();
                        Console.WriteLine();

                        if (!skipped)
                        {
                            rack = ReadRack(pending, board.Current);
                        }
                        skipped = false;
                        PlayPath move = ReadMove(board, rack);
                        if (move == null)
                        {
                            board   = board.Skip();
                            skipped = true;
                            continue;
                        }
                        using (PlayerScore.GetCurrentColor(board.Current))
                            move.Write();
                        board = board.Play(move);
                        pending.Clear();
                        pending.AddRange(move.Pending);

                        bool vortex = false;
                        foreach (LetterPlay lp in move.Played)
                        {
                            vortex |= lp.Cell.IsVortex;
                        }
                        if (vortex)
                        {
                            board.Write();
                            Console.WriteLine();
                            board = board.Clear();
                            pending.Clear();
                        }
                    }
                    board.Write();
                    rack = null;
                    using (new DisposableColor(PlayerScore.GetColor(board.Other)))
                        Console.WriteLine("{0} wins", board.Other);
                    Console.WriteLine();
                }
                catch (GiveUpException)
                {
                    if (board.IsEmpty && rack == null)
                    {
                        return;
                    }
                    rack = null;
                }
                board = new Board();
            }
        }
Beispiel #19
0
        public void Play()
        {
            var board = new Board();
            var rack  = new Rack(graph.GetRandom());

            Console.WriteLine("rack: " + rack.Value);
            WordPart part = GetFirstWord(rack);

            Console.WriteLine("word: {0}", part);
            board = board.Play(part);
            var letters = new List <char>(rack.Letters);

            foreach (char c in part.Word)
            {
                letters.Remove(c);
            }
            board.Write();

            while (!board.Score.Other.Wins)
            {
                var time = new Chrono();

                Console.Write("------------------------------\n");
                rack = new Rack(graph.GetRandom(new string(letters.ToArray())));
                Console.WriteLine("rack: " + rack.Value);

                if (board.IsEmpty)
                {
                    part = GetFirstWord(rack);
                    Console.WriteLine("word: {0}", part);
                    board   = board.Play(part);
                    letters = new List <char>(rack.Letters);
                    foreach (char c in part.Word)
                    {
                        letters.Remove(c);
                    }
                    board.Write();
                }
                else
                {
                    var       chrono  = new Chrono();
                    PlayGraph play    = GetPlayGraph(board, rack);
                    double    seconds = .1 * Convert.ToInt32(chrono.Elapsed.TotalSeconds * 10);
                    Console.WriteLine("{0} moves in {1} s", play.Valids.Count, seconds);
                    chrono = new Chrono();
                    var moveFinder = new MoveFinder(graph, board, play);
                    Tuple <PlayInfo, PlayPath> best = moveFinder.GetBestMove();
                    seconds = .1 * Convert.ToInt32(chrono.Elapsed.TotalSeconds * 10);
                    Console.WriteLine("Analyzed {0} moves in {1} s", play.Valids.Count, seconds);
                    Console.WriteLine();
                    {
                        PlayInfo info = best.Item1;
                        PlayPath path = best.Item2;
                        path.Write();
                        board = board.Play(path);
                        board.Write();
                        if (info.HasVortex)
                        {
                            board = board.Clear();
                            letters.Clear();
                        }
                        else
                        {
                            letters = new List <char>(rack.Letters);
                            foreach (LetterPlay lp in path.Played)
                            {
                                letters.Remove(lp.Letter);
                            }
                        }
                    }
                    if (time.Elapsed.TotalSeconds > 40)
                    {
                        throw new TimeoutException();
                    }
                }
            }
        }