Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        public double CalculateValueOfPurchasing(SimulationState state, int pieceIndex, PieceDefinition piece)
        {
            var offset = OffsetForPosition(state);

            var value = piece.TotalUsedLocations * _value[offset + UsedLocationUtilityOffset];

            value += piece.ButtonCost * _value[offset + ButtonCostUtilityOffset];

            value += piece.TimeCost * _value[offset + TimeCostUtilityOffset];

            //TODO: Should we have piece income and total income utilities?
            value += SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[state.ActivePlayer]) * piece.ButtonsIncome * _value[offset + IncomeUtilityOffset];

            value += SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[state.ActivePlayer]) * piece.ButtonsIncome * piece.ButtonsIncome * _value[offset + IncomeSquaredUtilityOffset];

            //TODO: Should this be boolean or vary by difference in location?
            if (state.PlayerPosition[state.NonActivePlayer] >= (state.PlayerPosition[state.ActivePlayer] + piece.TimeCost))
            {
                value += _value[offset + GetAnotherTurnUtilityOffset];
            }

            //TODO: Should this be boolean or vary by income amount?
            if (SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[state.ActivePlayer]) != SimulationHelpers.ButtonIncomeAmountAfterPosition(Math.Min(SimulationState.EndLocation, state.PlayerPosition[state.ActivePlayer] + piece.TimeCost)))
            {
                value += _value[offset + ReceiveIncomeUtilityOffset];
            }

            return(value);            //TODO Clamp? Divide by total utilities?
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 4
0
        public static GameState CreateGameState(SimulationState sim)
        {
            var res = new GameState();

            var ap = sim.ActivePlayer;
            var na = sim.NonActivePlayer;

            res.Observation.Add(sim.PlayerButtonIncome[ap] / ButtonIncomeScale);
            res.Observation.Add(sim.PlayerButtonIncome[na] / ButtonIncomeScale);
            res.Observation.Add(sim.PlayerButtonAmount[ap] / ButtonAmountScale);
            res.Observation.Add(sim.PlayerButtonAmount[na] / ButtonAmountScale);
            res.Observation.Add(sim.PlayerBoardUsedLocationsCount[ap] / UsedLocationsScale);
            res.Observation.Add(sim.PlayerBoardUsedLocationsCount[na] / UsedLocationsScale);
            res.Observation.Add(sim.PlayerPosition[ap] / PlayerPositionScale);
            res.Observation.Add(sim.PlayerPosition[na] / PlayerPositionScale);
            res.Observation.Add(SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[ap]) / IncomesRemainingScale);
            res.Observation.Add(SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[na]) / IncomesRemainingScale);

            for (var i = 0; i < LookAheadPieceAmount; i++)
            {
                var piece = Helpers.GetNextPiece(sim, i);

                res.Observation.Add(piece.ButtonCost / PieceButtonCostScale);
                res.Observation.Add(piece.ButtonsIncome / PieceButtonIncomeScale);
                res.Observation.Add(piece.TotalUsedLocations / PieceUsedLocationsScale);
            }

            return(res);
        }
Ejemplo n.º 5
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);
			}
Ejemplo n.º 6
0
        private void PopulateObservation(Observation res, SimulationState sim)
        {
            res.ObservationForNextMove    = new float[PlayerObservations + LookAheadPieceAmount * PieceFields];
            res.ObservationForNextMove[0] = sim.PlayerButtonIncome[0] / ButtonIncomeScale;
            res.ObservationForNextMove[1] = sim.PlayerButtonIncome[1] / ButtonIncomeScale;
            res.ObservationForNextMove[2] = sim.PlayerButtonAmount[0] / ButtonAmountScale;
            res.ObservationForNextMove[3] = sim.PlayerButtonAmount[1] / ButtonAmountScale;
            res.ObservationForNextMove[4] = sim.PlayerBoardUsedLocationsCount[0] / UsedLocationsScale;
            res.ObservationForNextMove[5] = sim.PlayerBoardUsedLocationsCount[1] / UsedLocationsScale;
            res.ObservationForNextMove[6] = sim.PlayerPosition[0] / PlayerPositionScale;
            res.ObservationForNextMove[7] = sim.PlayerPosition[1] / PlayerPositionScale;
            res.ObservationForNextMove[8] = SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[0]) / IncomesRemainingScale;
            res.ObservationForNextMove[9] = SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[1]) / IncomesRemainingScale;

            int baseIndex = PlayerObservations;

            for (var i = 0; i < LookAheadPieceAmount; i++)
            {
                var piece = PatchworkSim.AI.Helpers.GetNextPiece(sim, i);

                var b = baseIndex + (i * PieceFields);
                res.ObservationForNextMove[b + 0] = piece.ButtonCost / ButtonAmountScale;
                res.ObservationForNextMove[b + 1] = piece.ButtonsIncome / ButtonIncomeScale;
                res.ObservationForNextMove[b + 2] = piece.TotalUsedLocations / UsedLocationsScale;
            }
        }
Ejemplo n.º 7
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();
        }
        protected override double CalculateValue(SimulationState state, int pieceIndex, PieceDefinition piece)
        {
            var value = piece.TotalUsedLocations * 2 - piece.ButtonCost - piece.TimeCost * _timeCostValue;

            value += SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[state.ActivePlayer]) * piece.ButtonsIncome;
            //TODO: We should value gaining buttons more near the start of the game because they let us buy more, not sure if we need to put some extra stuff in for that

            return(value);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
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);
            }
        }
Ejemplo n.º 11
0
        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]);
        }
Ejemplo n.º 12
0
        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);
                }
Ejemplo n.º 13
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;
                        }
Ejemplo n.º 14
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]);
                }
            }
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
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)}");
            }
        }
Ejemplo n.º 17
0
        private void PopulateObservation(Observation res, SimulationState sim)
        {
            res.ObservationForNextMove.Add(sim.PlayerButtonIncome[0] / ButtonIncomeScale);
            res.ObservationForNextMove.Add(sim.PlayerButtonIncome[1] / ButtonIncomeScale);
            res.ObservationForNextMove.Add(sim.PlayerButtonAmount[0] / ButtonAmountScale);
            res.ObservationForNextMove.Add(sim.PlayerButtonAmount[1] / ButtonAmountScale);
            res.ObservationForNextMove.Add(sim.PlayerBoardUsedLocationsCount[0] / UsedLocationsScale);
            res.ObservationForNextMove.Add(sim.PlayerBoardUsedLocationsCount[1] / UsedLocationsScale);
            res.ObservationForNextMove.Add(sim.PlayerPosition[0] / PlayerPositionScale);
            res.ObservationForNextMove.Add(sim.PlayerPosition[1] / PlayerPositionScale);
            res.ObservationForNextMove.Add(SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[0]) / IncomesRemainingScale);
            res.ObservationForNextMove.Add(SimulationHelpers.ButtonIncomeAmountAfterPosition(sim.PlayerPosition[1]) / IncomesRemainingScale);

            for (var i = 0; i < LookAheadPieceAmount; i++)
            {
                var piece = PatchworkSim.AI.Helpers.GetNextPiece(sim, i);

                res.ObservationForNextMove.Add(piece.ButtonCost / ButtonAmountScale);
                res.ObservationForNextMove.Add(piece.ButtonsIncome / ButtonIncomeScale);
                res.ObservationForNextMove.Add(piece.TotalUsedLocations / UsedLocationsScale);
            }
        }
Ejemplo n.º 18
0
 private float CalculateValue(SimulationState state, int player)
 {
     return(state.PlayerBoardUsedLocationsCount[player] * 2 / UsedLocationsScale +
            state.PlayerButtonAmount[player] / ButtonAmountScale +
            state.PlayerButtonIncome[player] * SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[player]) / ButtonIncomeScale);
 }
Ejemplo n.º 19
0
 public void ButtonIncomeAfter()
 {
     Assert.Equal(SimulationState.ButtonIncomeMarkers.Length, SimulationHelpers.ButtonIncomeAmountAfterPosition(0));
     Assert.Equal(SimulationState.ButtonIncomeMarkers.Length - 1, SimulationHelpers.ButtonIncomeAmountAfterPosition(SimulationState.ButtonIncomeMarkers[0]));
     Assert.Equal(0, SimulationHelpers.ButtonIncomeAmountAfterPosition(SimulationState.EndLocation));
 }
Ejemplo n.º 20
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);
        }
Ejemplo n.º 21
0
 public static int EstimateEndgameValueUnbiased(SimulationState state, int player)
 {
     //space used * 2 + buttons + income * incomes remaining
     return(state.PlayerBoardUsedLocationsCount[player] * 2 + state.PlayerButtonAmount[player] + state.PlayerButtonIncome[player] * SimulationHelpers.ButtonIncomeAmountAfterPosition(state.PlayerPosition[player]));
 }