public void AlwaysAdvanceToEndNoPiecePlacing()
        {
            var state = new SimulationState(SimulationHelpers.GetRandomPieces(), 0);

            state.Fidelity = SimulationFidelity.NoPiecePlacing;
            var runner = new SimulationRunner(state, new PlayerDecisionMaker(AlwaysAdvanceMoveMaker.Instance, null), new PlayerDecisionMaker(AlwaysAdvanceMoveMaker.Instance, null));

            //The game definitely ends within 200 steps
            for (var i = 0; i < 200 && !state.GameHasEnded; i++)
            {
                runner.PerformNextStep();

                Assert.InRange(state.PlayerPosition[0], 0, SimulationState.EndLocation);
                Assert.InRange(state.PlayerPosition[1], 0, SimulationState.EndLocation);
            }

            //Both players should be at the end
            Assert.Equal(SimulationState.EndLocation, state.PlayerPosition[0]);
            Assert.Equal(SimulationState.EndLocation, state.PlayerPosition[1]);

            //Game should have ended
            Assert.True(state.GameHasEnded);

            //Players should have one button for each place they moved
            Assert.Equal(SimulationState.EndLocation + SimulationState.PlayerStartingButtons, state.PlayerButtonAmount[0]);
            Assert.Equal(SimulationState.EndLocation + SimulationState.PlayerStartingButtons, state.PlayerButtonAmount[1]);

            //non-starting player should have won by collecting all of the leather patches (https://boardgamegeek.com/thread/1703957/how-break-stalemate)
            Assert.Equal(1, state.WinningPlayer);

            //Check the ending points are correct
            Assert.Equal(SimulationState.EndLocation - BoardState.Width * BoardState.Height * 2 + SimulationState.PlayerStartingButtons, state.CalculatePlayerEndGameWorth(0));
            Assert.Equal(SimulationState.EndLocation - BoardState.Width * BoardState.Height * 2 + SimulationState.PlayerStartingButtons + 2 * SimulationState.LeatherPatches.Length, state.CalculatePlayerEndGameWorth(1));
        }
Beispiel #2
0
        /// <summary>
        /// Returns the amount of wins the challenger got (from 100)
        /// </summary>
        private static int CalculateChallengerWinsFrom100(IMoveDecisionMaker best, IMoveDecisionMaker challenger)
        {
            int challengerWins = 0;

            Parallel.For(0, 200, (i) =>
            {
                var state          = new SimulationState(SimulationHelpers.GetRandomPieces(i / 2), 0);
                state.ActivePlayer = i % 2;
                state.Fidelity     = SimulationFidelity.NoPiecePlacing;
                //TODO: May need a cheaper placement engine
                var runner = new SimulationRunner(state,
                                                  new PlayerDecisionMaker(best, null),
                                                  new PlayerDecisionMaker(challenger, null));

                while (!state.GameHasEnded)
                {
                    runner.PerformNextStep();
                }

                if (state.WinningPlayer == 1)
                {
                    Interlocked.Increment(ref challengerWins);
                }
            });

            return(challengerWins);
        }
Beispiel #3
0
        public void Run()
        {
            Evaluate();

            var req = new TrainRequest();


            for (var g = 0; g < 1000; g++)
            {
                var timer = Stopwatch.StartNew();

                //Parallel.For(0, 8, (i) =>
                for (var i = 0; i < 8; i++)
                {
                    Console.WriteLine("Starting game " + i);
                    var p0Samples = new List <TrainSample>();
                    var p1Samples = new List <TrainSample>();

                    var state = new SimulationState(SimulationHelpers.GetRandomPieces(), 0);
                    state.Fidelity = SimulationFidelity.NoPiecePlacing;

                    while (!state.GameHasEnded)
                    {
                        var sampleSet = state.ActivePlayer == 0 ? p0Samples : p1Samples;

                        var sample = _ai.MakeMoveWithResult(state);
                        sampleSet.Add(sample);
                    }

                    //Set the winner on the samples from the winner
                    var winningSamples = state.WinningPlayer == 0 ? p0Samples : p1Samples;
                    for (var j = 0; j < winningSamples.Count; j++)
                    {
                        winningSamples[j].IsWin = true;
                    }

                    //TODO: AddRange is terrible performance
                    lock (req)
                    {
                        req.Samples.AddRange(p0Samples);
                        req.Samples.AddRange(p1Samples);
                    }
                }                //);
                timer.Stop();
                Console.WriteLine("Took " + timer.ElapsedMilliseconds);

                //if (req.Samples.Count >= 256)
                {
                    Console.WriteLine("Training " + req.Samples.Count);

                    _client.Train(req);

                    req.Samples.Clear();

                    Evaluate();
                }
            }
            Console.WriteLine("Hi");
            Console.ReadLine();
        }
Beispiel #4
0
		private static void RunMoveMakerForPerformance()
		{
			var sw = Stopwatch.StartNew();

#if PERF_PARALLEL
			Parallel.For(0, 10, (run) => //5900
			#else
			for (var run = 0; run < 4; run++) //13000
#endif
			{
				//var a = new PlayerDecisionMaker(new MoveOnlyMonteCarloTreeSearchMoveMaker(10000), PlacementMaker.FirstPossibleInstance);
				//var b = new PlayerDecisionMaker(new MoveOnlyMonteCarloTreeSearchMoveMaker(5000), PlacementMaker.FirstPossibleInstance);

				var mctsA = new MonteCarloTreeSearchMoveMaker(5000, TuneableUtilityMoveMaker.Tuning1, new TightBoardEvaluator(true), 2);
				var a = new PlayerDecisionMaker(mctsA, new PlacementMaker(mctsA.PlacementStrategy));

				var mctsB = new MonteCarloTreeSearchMoveMaker(5000, TuneableUtilityMoveMaker.Tuning1, new TightBoardEvaluator(true), 2);
				var b = new PlayerDecisionMaker(mctsB, new PlacementMaker(mctsB.PlacementStrategy));


				var state = new SimulationState(SimulationHelpers.GetRandomPieces(run / 2), 0);
				var runner = new SimulationRunner(state, run % 2 == 0 ? a : b, run % 2 == 1 ? a : b);
				while (!state.GameHasEnded)
				{
					runner.PerformNextStep();
				}
				Console.WriteLine(state.WinningPlayer);
			}
        public void BuyFirstPossibleMoveMakerNoPiecePlacing()
        {
            var state = new SimulationState(SimulationHelpers.GetRandomPieces(3), 0);

            state.Fidelity = SimulationFidelity.NoPiecePlacing;
            var runner = new SimulationRunner(state, new PlayerDecisionMaker(BuyFirstPossibleMoveMaker.Instance, null), new PlayerDecisionMaker(BuyFirstPossibleMoveMaker.Instance, null));

            while (!state.GameHasEnded)
            {
                runner.PerformNextStep();
            }

            //Check someone bought something
            Assert.True(state.Pieces.Count < PieceDefinition.AllPieceDefinitions.Length);
        }
Beispiel #6
0
        internal (SimulationState state, int gameId) CreateSimulation(int?randomSeed, int mctsIterations)
        {
            lock (this)
            {
                var id = ++_nextSim;

                var state = new SimulationState(SimulationHelpers.GetRandomPieces(randomSeed), 0);
                state.Fidelity = SimulationFidelity.NoPiecePlacing;
                var opp = new MoveOnlyMonteCarloTreeSearchMoveMaker(mctsIterations);

                _simulations[id] = state;
                _opponents[id]   = opp;

                return(state, id);
            }
        }
        private void TestStrategy(IPlacementStrategy strategy, int expectPiecesPlaced)
        {
            var pieces = new PieceCollection();

            pieces.Populate(SimulationHelpers.GetRandomPieces(1));
            int placed = 0;

            var board = new BoardState();

            for (var i = 0; i < pieces.Count; i++)
            {
                if (strategy.TryPlacePiece(board, PieceDefinition.AllPieceDefinitions[pieces[i]], in pieces, i + 1, out var bitmap, out var x, out var y))
                {
                    placed++;
                    board.Place(bitmap, x, y);
                }
        public void BuyFirstPossibleMoveMakerPlacing()
        {
            var state  = new SimulationState(SimulationHelpers.GetRandomPieces(1), 0);
            var runner = new SimulationRunner(state, new PlayerDecisionMaker(BuyFirstPossibleMoveMaker.Instance, PlacementMaker.FirstPossibleInstance), new PlayerDecisionMaker(BuyFirstPossibleMoveMaker.Instance, PlacementMaker.FirstPossibleInstance));

            while (!state.GameHasEnded)
            {
                runner.PerformNextStep();
            }

            //Check someone bought something
            Assert.True(state.Pieces.Count < PieceDefinition.AllPieceDefinitions.Length);

            Assert.Equal(11, state.PlayerButtonIncome[0]);
            Assert.Equal(37, state.PlayerButtonAmount[0]);
        }
Beispiel #9
0
        static void TestPlacementOnly()
        {
            var stopwatch = Stopwatch.StartNew();

            var strategies = new IPlacementStrategy[]
            {
                //FirstPossiblePlacementStrategy.Instance,
                //SimpleClosestToWallAndCornerStrategy.Instance,
                //ClosestToCornerLeastHolesTieBreakerPlacementStrategy.Instance,
                //NextToPieceEdgeLeastHolesTieBreakerPlacementStrategy.Instance,
                //TightPlacementStrategy.InstanceDoubler,
                //TightPlacementStrategy.InstanceIncrement,
                ExhaustiveMostFuturePlacementsPlacementStrategy.Instance1_1,
                ExhaustiveMostFuturePlacementsPlacementStrategy.Instance1_6,
                new BestEvaluatorStrategy(TuneablePattern2x2BoardEvaluator.HandTuned),
                new BestEvaluatorStrategy(TuneablePattern2x2BoardEvaluator.Tuning1),
            };

            //foreach (var strategy in strategies)
            Parallel.ForEach(strategies, (strategy) =>
            {
                //var rand = new Random(0);
                int totalPlaced = 0;

                for (var i = 0; i < 100; i++)
                {
                    var pieces = new PieceCollection();
                    pieces.Populate(SimulationHelpers.GetRandomPieces(i));
                    int index  = 0;
                    int placed = 0;

                    var board = new BoardState();

                    while (true)
                    {
                        var piece = pieces[index];
                        pieces.RemoveAt(index);
                        index = index % pieces.Count;

                        if (strategy.TryPlacePiece(board, PieceDefinition.AllPieceDefinitions[piece], in pieces, index, out var bitmap, out var x, out var y))
                        {
                            placed++;
                            board.Place(bitmap, x, y);

                            //Advance to a random one in the next 6 pieces (TODO: Would be good to bias this towards 1-3 as these are more likely)
                            //index = (index + rand.Next(0, 6)) % pieces.Count;
                        }
Beispiel #10
0
        public void GetRandomPiecesPlaces0AtEnd()
        {
            for (var i = 0; i < 1000; i++)
            {
                var pieces = SimulationHelpers.GetRandomPieces(i);

                //0 at end
                Assert.Equal(0, pieces[pieces.Count - 1]);

                //Array contains all pieces
                pieces = pieces.OrderBy(p => p).ToList();
                for (var j = 0; j < pieces.Count; j++)
                {
                    Assert.Equal(j, pieces[j]);
                }
            }
        }
        public void AdvanceToEndPlacingSinglePatches()
        {
            var state = new SimulationState(SimulationHelpers.GetRandomPieces(), 0);

            state.Fidelity = SimulationFidelity.FullSimulation;
            var runner = new SimulationRunner(state, new PlayerDecisionMaker(AlwaysAdvanceMoveMaker.Instance, PlacementMaker.FirstPossibleInstance), new PlayerDecisionMaker(AlwaysAdvanceMoveMaker.Instance, PlacementMaker.FirstPossibleInstance));

            while (!state.GameHasEnded)
            {
                runner.PerformNextStep();
            }

            //Both players should be at the end
            Assert.Equal(SimulationState.EndLocation, state.PlayerPosition[0]);
            Assert.Equal(SimulationState.EndLocation, state.PlayerPosition[1]);

            //Game should have ended
            Assert.True(state.GameHasEnded);

            //Players should have one button for each place they moved
            Assert.Equal(SimulationState.EndLocation + SimulationState.PlayerStartingButtons, state.PlayerButtonAmount[0]);
            Assert.Equal(SimulationState.EndLocation + SimulationState.PlayerStartingButtons, state.PlayerButtonAmount[1]);

            //non-starting player should have won by collecting all of the leather patches (https://boardgamegeek.com/thread/1703957/how-break-stalemate)
            Assert.Equal(1, state.WinningPlayer);

            //Check the ending points are correct
            Assert.Equal(SimulationState.EndLocation - BoardState.Width * BoardState.Height * 2 + SimulationState.PlayerStartingButtons, state.CalculatePlayerEndGameWorth(0));
            Assert.Equal(SimulationState.EndLocation - BoardState.Width * BoardState.Height * 2 + SimulationState.PlayerStartingButtons + 2 * SimulationState.LeatherPatches.Length, state.CalculatePlayerEndGameWorth(1));

            //Check the pieces are on their board
            int sum = 0;

            for (var x = 0; x < BoardState.Width; x++)
            {
                for (var y = 0; y < BoardState.Height; y++)
                {
                    if (state.PlayerBoardState[1][x, y])
                    {
                        sum++;
                    }
                }
            }
            Assert.Equal(SimulationState.LeatherPatches.Length, sum);
        }
Beispiel #12
0
        private void Evaluate()
        {
            Console.WriteLine($"Evaluating vs " + _opp.Name);

            var players = new IMoveDecisionMaker[] { _ai, _opp };

            //Play X games (even amount), each player gets to start on each of the boards once
            for (var game = 0; game < 4; game++)
            {
                var state = new SimulationState(SimulationHelpers.GetRandomPieces(game / 2), 0);
                state.Fidelity     = SimulationFidelity.NoPiecePlacing;
                state.ActivePlayer = game % 2;

                while (!state.GameHasEnded)
                {
                    players[state.ActivePlayer].MakeMove(state);
                }

                Console.WriteLine($"Game {game}. Winner {state.WinningPlayer}. Scores: {state.CalculatePlayerEndGameWorth(0)} / {state.CalculatePlayerEndGameWorth(1)}");
            }
        }
Beispiel #13
0
        static void TestFullAi()
        {
            var aiToTest = new Func <PlayerDecisionMaker>[]
            {
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(-1), PlacementMaker.TightDoublerInstance),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(0), PlacementMaker.TightDoublerInstance),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(1), PlacementMaker.TightDoublerInstance),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(2), PlacementMaker.TightDoublerInstance),
                //
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(-1), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(0), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(1), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new GreedyCardValueUtilityMoveMaker(2), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),

                //() => new PlayerDecisionMaker(new QuickRandomSearchMoveMaker(6, 1000), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new QuickRandomSearchMoveMaker(10, 2000), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new QuickRandomSearchMoveMaker(20, 5000), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                //() => new PlayerDecisionMaker(new QuickRandomSearchMoveMaker(30, 10000), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),

                //() => new PlayerDecisionMaker(new MoveOnlyMonteCarloTreeSearchMoveMaker(1000, TuneableUtilityMoveMaker.Tuning1), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),

                () => new PlayerDecisionMaker(new MoveOnlyMonteCarloTreeSearchMoveMaker(10000, TuneableUtilityMoveMaker.Tuning1), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                () => new PlayerDecisionMaker(new MoveOnlyMonteCarloTreeSearchMoveMaker(10000, TuneableUtilityMoveMaker.Tuning1), new PlacementMaker(new BestEvaluatorStrategy(TuneablePattern2x2BoardEvaluator.Tuning1))),

                () =>
                {
                    var p = new PreplacerStrategy(new EvaluatorTreeSearchPreplacer(TuneablePattern2x2BoardEvaluator.Tuning1, 4, 4, true));
                    var m = new MoveOnlyMonteCarloTreeSearchWithPreplacerMoveMaker(10000, TuneableUtilityMoveMaker.Tuning1, p);
                    return(new PlayerDecisionMaker(m, new PlacementMaker(p)));
                },

                () => new PlayerDecisionMaker(new AlphaBetaMoveMaker(15, TuneableByBoardPositionUtilityCalculator.Tuning1), PlacementMaker.ExhaustiveMostFuturePlacementsInstance1_6),
                () => new PlayerDecisionMaker(new AlphaBetaMoveMaker(15, TuneableByBoardPositionUtilityCalculator.Tuning1), new PlacementMaker(new BestEvaluatorStrategy(TuneablePattern2x2BoardEvaluator.Tuning1))),
                //
                //() =>
                //{
                //	var p = new PreplacerStrategy(new EvaluatorTreeSearchPreplacer(new Pattern2x2BoardEvaluator(), 4, 4, true));
                //	var m = new MoveOnlyMinimaxWithAlphaBetaPruningWithPreplacerMoveMaker(13, TuneableByBoardPositionUtilityCalculator.Tuning1, p);
                //	return new PlayerDecisionMaker(m, new PlacementMaker(p));
                //},

                () =>
                {
                    var p = new PreplacerStrategy(new EvaluatorTreeSearchPreplacer(TuneablePattern2x2BoardEvaluator.Tuning1, 4, 4, true));
                    var m = new MoveOnlyAlphaBetaWithPreplacerMoveMaker(15, TuneableByBoardPositionUtilityCalculator.Tuning1, p);
                    return(new PlayerDecisionMaker(m, new PlacementMaker(p)));
                },
            };

            const int  TotalRuns            = 500;
            const bool enableConsoleLogging = false;

            //TODO: Play each AI against each other AI 100 times and print a table of results

            var totalWins      = new int[aiToTest.Length, aiToTest.Length];
            var totalTimeTaken = new long[aiToTest.Length];

            Console.WriteLine($"Running {aiToTest.Length * (aiToTest.Length - 1) / 2} * {TotalRuns} Games");
            int gameNumber = 0;

            for (var a = 0; a < aiToTest.Length; a++)
            {
                for (var b = a; b < aiToTest.Length; b++)
                {
                    if (a == b)
                    {
                        continue;
                    }

                    long aiATime = 0;
                    long aiBTime = 0;
                    var  aiA     = aiToTest[a];
                    var  aiB     = aiToTest[b];
                    Console.WriteLine($"{++gameNumber} {aiA().Name} vs {aiB().Name}");

                    Parallel.For(0, TotalRuns, new ParallelOptions {
                        MaxDegreeOfParallelism = 6
                    }, (run) =>
                                 //for (var run = 0; run < TotalRuns; run++)
                    {
                        var state            = new SimulationState(SimulationHelpers.GetRandomPieces(run / 2), 0);
                        ConsoleLogger logger = null;
                        if (enableConsoleLogging)
                        {
                            state.Logger = logger = new ConsoleLogger(state);
                        }
                        //state.Fidelity = SimulationFidelity.NoPiecePlacing;
                        //Let each Ai have half of the goes first and half second
                        var runner = new SimulationRunner(state, run % 2 == 0 ? aiA() : aiB(), run % 2 == 1 ? aiA() : aiB());

                        while (!state.GameHasEnded)
                        {
                            runner.PerformNextStep();
                            if (logger != null)
                            {
                                logger.PrintBoards(true);
                            }
                        }

                        var aWin = run % 2 == state.WinningPlayer;

                        lock (totalWins)
                        {
                            if (aWin)
                            {
                                totalWins[a, b]++;
                            }
                            else
                            {
                                totalWins[b, a]++;
                            }
                        }

                        Interlocked.Add(ref aiATime, runner.Stopwatches[run % 2].ElapsedMilliseconds);
                        Interlocked.Add(ref aiBTime, runner.Stopwatches[(run + 1) % 2].ElapsedMilliseconds);
                        //Console.WriteLine(aWin);
                    }
                                 );
                    Console.WriteLine(totalWins[a, b]);

                    totalTimeTaken[a] += aiATime;
                    totalTimeTaken[b] += aiBTime;
                }
            }

            //Calculate the total points for each
            var total = Enumerable.Range(0, aiToTest.Length).Select(ai => Enumerable.Range(0, aiToTest.Length).Sum(opponent => totalWins[ai, opponent])).ToArray();

            //Dump a CSV with the results
            var filename = "result_" + DateTimeOffset.Now.Ticks + ".csv";
            var res      = new List <string>();

            res.Add("," + string.Join(", ", aiToTest.Select(ai => ai().Name)) + ",Win%,Rank,Total Time");
            for (var a = 0; a < aiToTest.Length; a++)
            {
                var line = aiToTest[a]().Name;
                for (var b = 0; b < aiToTest.Length; b++)
                {
                    if (a == b)
                    {
                        line += ",";
                    }
                    else
                    {
                        line += "," + totalWins[a, b];
                    }
                }

                //Win%, rank, time
                line += "," + (total[a] / (float)(aiToTest.Length - 1) * 100 / TotalRuns).ToString("0.0");
                line += "," + (aiToTest.Length - total.Count(c => c < total[a]));
                line += "," + totalTimeTaken[a];

                res.Add(line);
            }

            Console.WriteLine("Saving results as " + filename);
            File.WriteAllLines(filename, res);

            Process.Start(filename);
        }