예제 #1
0
    public static void ProcessQueue()
    {
        float realtimeSinceStartup = Time.get_realtimeSinceStartup();
        float num = AIThinkManager.framebudgetms / 1000f;

        if (AIThinkManager._removalQueue.get_Count() > 0)
        {
            using (IEnumerator <IThinker> enumerator = AIThinkManager._removalQueue.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    IThinker current = enumerator.Current;
                    AIThinkManager._processQueue.Remove(current);
                }
            }
            AIThinkManager._removalQueue.Clear();
        }
        for (; AIThinkManager.lastIndex < AIThinkManager._processQueue.get_Count() && (double)Time.get_realtimeSinceStartup() < (double)realtimeSinceStartup + (double)num; ++AIThinkManager.lastIndex)
        {
            AIThinkManager._processQueue.get_Item(AIThinkManager.lastIndex)?.TryThink();
        }
        if (AIThinkManager.lastIndex != AIThinkManager._processQueue.get_Count())
        {
            return;
        }
        AIThinkManager.lastIndex = 0;
    }
예제 #2
0
    private static void DoProcessing(ListHashSet <IThinker> process, float budgetSeconds, ref int last)
    {
        float realtimeSinceStartup = Time.realtimeSinceStartup;

        while (last < process.Count && Time.realtimeSinceStartup < realtimeSinceStartup + budgetSeconds)
        {
            IThinker thinker = process[last];
            if (thinker != null)
            {
                try
                {
                    thinker.TryThink();
                }
                catch (Exception message)
                {
                    Debug.LogWarning(message);
                }
            }
            last++;
        }
        if (last >= process.Count)
        {
            last = 0;
        }
    }
예제 #3
0
    public static void ProcessQueue()
    {
        float single  = Time.realtimeSinceStartup;
        float single1 = (float)AIThinkManager.framebudgetms / 1000f;

        if (AIThinkManager._removalQueue.Count > 0)
        {
            foreach (IThinker thinker in AIThinkManager._removalQueue)
            {
                AIThinkManager._processQueue.Remove(thinker);
            }
            AIThinkManager._removalQueue.Clear();
        }
        while (AIThinkManager.lastIndex < AIThinkManager._processQueue.Count && Time.realtimeSinceStartup < single + single1)
        {
            IThinker item = AIThinkManager._processQueue[AIThinkManager.lastIndex];
            if (item != null)
            {
                item.TryThink();
            }
            AIThinkManager.lastIndex++;
        }
        if (AIThinkManager.lastIndex == AIThinkManager._processQueue.Count)
        {
            AIThinkManager.lastIndex = 0;
        }
    }
예제 #4
0
        private static void Main(string[] args)
        {
            // ////////////////////////////////////////////////////////////// //
            // Create an instance of our Ultron thinker via ThinkerPrototype. //
            // If we created directly with new, it would not be properly      //
            // configured.                                                    //
            // ////////////////////////////////////////////////////////////// //

            // Create a configuration for a default ColorShapeLinks match
            MatchConfig mc = new MatchConfig();

            // Get the fully qualified name of our basic Ultron thinker
            string ultronFullName = typeof(UltronThinker).FullName;

            // Create a prototype for our thinker
            ThinkerPrototype tp = new ThinkerPrototype(ultronFullName, "", mc);

            // Create an instance of our basic Ultron thinker
            IThinker ultronThinker = tp.Create();

            // //////////////////////////////////////////////////////// //
            // Create a board so we can test how our thinker will play. //
            // //////////////////////////////////////////////////////// //

            // A cancellation token, will be ignored
            CancellationToken ct = new CancellationToken();

            // Create a ColorShapeLinks board with default size
            Board board = new Board();

            // Show initial board
            Console.WriteLine("\n=== Initial board ===\n");
            ShowBoard(board);

            // Make some moves manually
            board.DoMove(PShape.Round, 0);  // White plays round piece in col 0
            board.DoMove(PShape.Square, 4); // Red plays square piece in col 4
            board.DoMove(PShape.Square, 5); // White plays round piece in col 5

            // Show board after our three manual moves
            Console.WriteLine("\n=== Board after three manual moves ===\n");
            ShowBoard(board);

            // What move would Ultron make at this moment?
            FutureMove ultronMove = ultronThinker.Think(board, ct);

            // Show move
            Console.WriteLine($"-> Ultron will play {ultronMove}");

            // Make the move selected by Ultron
            board.DoMove(ultronMove.shape, ultronMove.column);

            // Show board after Ultron made its move
            Console.WriteLine("\n=== Board after Ultron made move ===\n");
            ShowBoard(board);
        }
예제 #5
0
파일: Ticker.cs 프로젝트: Doom2fan/PokesYou
 public void RemoveThinker(IThinker thinker)
 {
     if (thinker.NextThinker != null)
     {
         thinker.NextThinker.PrevThinker = thinker.PrevThinker;
     }
     if (thinker.PrevThinker != null)
     {
         thinker.PrevThinker.NextThinker = thinker.NextThinker;
     }
 }
예제 #6
0
 public bool MoveNext()
 {
     if (cur != null && cur.NextThinker != null)
     {
         cur = cur.NextThinker;
         return(true);
     }
     else
     {
         return(false);
     }
 }
예제 #7
0
        // Raise and invalid play event and return the match winner (which is
        // the opponent of the thinker that made an invalid play)
        private Winner OnInvalidPlay(
            PColor color, IThinker thinker, string reason)
        {
            // Set the other thinker as the winner of the match
            Winner winner = color.Other().ToWinner();

            // Set solution to null
            solution = null;

            // Notify listeners that thinker made an invalid play
            InvalidPlay?.Invoke(color, thinker.ToString(), reason);

            // Return the winner
            return(winner);
        }
예제 #8
0
파일: Ticker.cs 프로젝트: Doom2fan/PokesYou
 public void AddThinker(IThinker thinker)
 {
     if (Thinkers.First == null)
     {
         thinker.PrevThinker = null;
         thinker.NextThinker = null;
         Thinkers.SetFirst(thinker);
     }
     else
     {
         thinker.PrevThinker        = null;
         thinker.NextThinker        = Thinkers.First;
         Thinkers.First.PrevThinker = thinker;
         Thinkers.SetFirst(thinker);
     }
 }
예제 #9
0
 public void SetFirst(IThinker newFirst)
 {
     first = newFirst;
 }
예제 #10
0
 public ThinkerEnumerator(IThinker firstNode)
 {
     first = firstNode;
 }
예제 #11
0
 public void Reset()
 {
     cur = enumerator.first;
 }
예제 #12
0
 public static void Remove(IThinker toRemove)
 {
     _removalQueue.Add(toRemove);
 }
예제 #13
0
        /// Current thinker makes its move
        private Winner Play()
        {
            // Get a reference to the current thinker
            IThinker thinker = matchData.CurrentThinker;

            // Determine the color of the current thinker
            PColor color = board.Turn;

            // Match result so far
            Winner winner = Winner.None;

            // Thinking start time
            DateTime startTime = DateTime.Now;

            // Real think time in milliseconds
            int thinkTimeMillis;

            // Apparent thinking time left
            int timeLeftMillis;

            // Task to execute the thinker in a separate thread
            Task <FutureMove> thinkTask;

            // Notify listeners that next turn is about to start
            NextTurn?.Invoke(color, thinker.ToString());

            // Ask thinker to think about its next move
            thinkTask = Task.Run(
                () => thinker.Think(board.Copy(), ts.Token));

            // The thinking process might throw an exception, so we wrap
            // task waiting in a try/catch block
            try
            {
                // Wait for thinker to think... until the allowed time limit
                if (thinkTask.Wait(timeLimitMillis))
                {
                    // Thinker successfully made a move within the time limit

                    // Get the move selected by the thinker
                    FutureMove move = thinkTask.Result;

                    // Was the thinker able to chose a move?
                    if (move.IsNoMove)
                    {
                        // Thinker was not able to chose a move

                        // Raise an invalid play event and set the other
                        // thinker as the winner of the match
                        winner = OnInvalidPlay(
                            color, thinker,
                            "Thinker unable to perform move");
                    }
                    else
                    {
                        // Thinker was able to chose a move

                        // Perform move in game board, get column where move
                        // was performed
                        int row = board.DoMove(move.shape, move.column);

                        // If the column had space for the move...
                        if (row >= 0)
                        {
                            // Obtain thinking end time
                            thinkTimeMillis = (int)(DateTime.Now - startTime)
                                              .TotalMilliseconds;

                            // How much time left for the minimum apparent move
                            // time?
                            timeLeftMillis =
                                minMoveTimeMillis - thinkTimeMillis;

                            // Was the minimum apparent move time reached
                            if (timeLeftMillis > 0)
                            {
                                // If not, wait until it is reached
                                Thread.Sleep(timeLeftMillis);
                            }

                            // Notify listeners of the move performed
                            MovePerformed?.Invoke(
                                color, thinker.ToString(),
                                move, thinkTimeMillis);

                            // Get possible winner and solution
                            winner = board.CheckWinner(solution);
                        }
                        else
                        {
                            // If we get here, column didn't have space for the
                            // move, which means that thinker made an invalid
                            // move and should lose the game

                            // Raise an invalid play event and set the other
                            // thinker as the winner of the match
                            winner = OnInvalidPlay(
                                color, thinker,
                                "Tried to place piece in column "
                                + $"{move.column}, which is full");
                        }
                    }
                }
                else // Did the time limit expired?
                {
                    // Notify thinker to voluntarily stop thinking
                    ts.Cancel();

                    // Raise an invalid play event and set the other thinker
                    // as the winner of the match
                    winner = OnInvalidPlay(
                        color, thinker, "Time limit expired");
                }
            }
            catch (Exception e)
            {
                // Is this an inner exception?
                if (e.InnerException != null)
                {
                    // If so, use it for error message purposes
                    e = e.InnerException;
                }

                // Raise an invalid play event and set the other thinker as
                // the winner of the match
                winner = OnInvalidPlay(
                    color, thinker,
                    $"Thinker exception: '{e.Message}'");
            }

            // Notify listeners that the board was updated
            BoardUpdate?.Invoke(board);

            // Return winner
            return(winner);
        }
예제 #14
0
 static void Main(string[] args)
 {
     MatchConfig      mc      = new MatchConfig(); // Use default values
     ThinkerPrototype tp      = new ThinkerPrototype(typeof(MyThinker).FullName, "", mc);
     IThinker         thinker = tp.Create();
 }
예제 #15
0
 /// <summary>
 /// This method will be called before a match starts and is used for
 /// instantiating a new <see cref="G10NossaAIThinker"/>.
 /// </summary>
 /// <seealso cref="AIPlayer.Setup"/>
 public override void Setup()
 {
     thinker = new G10NossaAIThinker();
 }
예제 #16
0
 public static void AddAnimal(IThinker toAdd)
 {
     _animalProcessQueue.Add(toAdd);
 }
예제 #17
0
 /// <summary>
 /// This method will be called before a match starts and is used for
 /// instantiating a new <see cref="SequentialAIThinker"/>.
 /// </summary>
 /// <seealso cref="AIPlayer.Setup"/>
 public override void Setup()
 {
     thinker = new SequentialAIThinker();
 }
예제 #18
0
        private static void Main(string[] args)
        {
            // ////////////////////////////////////////////////////////////// //
            // Create an instance of our Oizys thinker via ThinkerPrototype. //
            // If we created directly with new, it would not be properly      //
            // configured.                                                    //
            // ////////////////////////////////////////////////////////////// //

            // Create a configuration for a default ColorShapeLinks match
            MatchConfig mc = new MatchConfig();

            // Get the fully qualified name of our basic Oizys thinker
            string oizysFullName = typeof(OizysThinker).FullName;

            // Create a prototype for our thinker
            ThinkerPrototype tp = new ThinkerPrototype(oizysFullName, "", mc);

            // Create an instance of our basic Oizys thinker
            IThinker oizysThinker = tp.Create();

            // //////////////////////////////////////////////////////// //
            // Create a board so we can test how our thinker will play. //
            // //////////////////////////////////////////////////////// //

            // A cancellation token, will be ignored
            CancellationToken ct = new CancellationToken();

            // Create a ColorShapeLinks board with default size
            Board board = new Board();

            // Show initial board
            Console.WriteLine("\n=== Initial board ===\n");
            ShowBoard(board);

            // Make some moves manually
            board.DoMove(PShape.Round, 3);  // White plays (Round,col 3)
            board.DoMove(PShape.Square, 3); // Red   plays (Square,col 3)
            board.DoMove(PShape.Round, 2);  // White plays (Round,col 2)
            // board.DoMove(PShape.Square, 3); // Red   plays (Square,col 3)
            // board.DoMove(PShape.Round, 1);  // White plays (Round,col 1)
            // board.DoMove(PShape.Square, 3); // Red   plays (Square,col 3)
            // board.DoMove(PShape.Round, 3); // White plays (Round,col 3)

            // Show board after our three manual moves
            Console.WriteLine("\n=== Board after three manual moves ===\n");
            ShowBoard(board);

            // Starts timer
            DateTime startTime = DateTime.Now;

            // What move would Oizys make at this moment?
            FutureMove oizysMove = oizysThinker.Think(board, ct);

            // Show move and time
            Console.WriteLine(string.Format(
                                  "-> Oizys will play {0} after {1} ms.",
                                  oizysMove, (DateTime.Now - startTime).TotalMilliseconds));

            // Make the move selected by Oizys
            board.DoMove(oizysMove.shape, oizysMove.column);

            // Show board after Oizys made its move
            Console.WriteLine("\n=== Board after Oizys made move ===\n");
            ShowBoard(board);
        }
예제 #19
0
 public static void Remove(IThinker toRemove)
 {
     AIThinkManager._removalQueue.Add(toRemove);
 }
예제 #20
0
 public static void Add(IThinker toAdd)
 {
     AIThinkManager._processQueue.Add(toAdd);
 }
예제 #21
0
 public static void RemoveAnimal(IThinker toRemove)
 {
     _animalremovalQueue.Add(toRemove);
 }
예제 #22
0
 public Enumerator(ThinkerEnumerator thinkerEnum)
 {
     enumerator        = thinkerEnum;
     first.NextThinker = enumerator.first;
     cur = first;
 }
예제 #23
0
    // Update is called once per frame
    private void Update()
    {
        // Don't run update if the game's over
        if (matchOver)
        {
            return;
        }

        // Is the current player human? If so, let's see if we're supposed to
        // show him a message or if we've done so already
        if (matchData.CurrentPlayer.IsHuman)
        {
            if (showHumanTurnMessage)
            {
                view.SubmitMessage(
                    $"Attention {CurrPlrNameColor}, it's your turn");
                showHumanTurnMessage = false;
            }
            ;
        }

        // If the current player is an AI, let's see if we have to start
        // the AI thinking task, if the task is running, if it's completed, etc.
        else
        {
            // If the AI task is null, we need to start an AI thinking task
            if (aiTask == null)
            {
                // Submit a message informing the user the AI is thinking
                view.SubmitMessage(
                    $"{CurrPlrNameColor} is thinking, please wait...");

                // Keep note of task start time (both system time and game time)
                taskStartSysTime  = DateTime.Now;
                taskStartGameTime = Time.time;

                // Create a new task cancellation token, so task can be
                // interrupted
                ts = new CancellationTokenSource();

                // Get this AI's thinker
                IThinker thinker = matchData.CurrentPlayer.Thinker;

                // Start task in a separate thread using a copy of the board
                aiTask = Task.Run(() => thinker.Think(board.Copy(), ts.Token));
            }
            else // This else will run if the task is not null
            {
                // Is the AI thinking task completed?
                if (aiTask.IsCompleted)
                {
                    // Register task duration, if we haven't done so yet
                    if (float.IsNaN(lastTaskDuration))
                    {
                        lastTaskDuration =
                            (float)((DateTime.Now - taskStartSysTime).Ticks /
                                    (double)(TimeSpan.TicksPerSecond));
                    }

                    // Did we pass the minimum time between AI moves?
                    if (Time.time >
                        taskStartGameTime + matchData.MinAIGameMoveTime)
                    {
                        // If so, submit a message informing of the move
                        // chosen and the system time it took the AI to think
                        view.SubmitMessage(string.Format(
                                               "{0} placed a {1} piece at column {2} after {3}",
                                               CurrPlrNameColor,
                                               aiTask.Result.shape.ToString().ToLower(),
                                               aiTask.Result.column,
                                               $"thinking for {lastTaskDuration:f4}s"));

                        // Perform the actual move
                        MakeAMove(aiTask.Result);

                        // Set the task to null, so it can be started again
                        aiTask = null;

                        // Reset the last task duration
                        lastTaskDuration = float.NaN;
                    }
                }
                // Did the task throw an exception?
                else if (aiTask.IsFaulted)
                {
                    // If so, notify user
                    view.SubmitMessage(
                        aiTask.Exception.InnerException.Message);

                    // Log exception as an error
                    Debug.LogError(aiTask.Exception.InnerException.Message);

                    // Send a cancellation token to the task in the hope it
                    // might actually terminate
                    ts.Cancel();

                    // Set task to null
                    aiTask = null;

                    // The AI player that throwed the exception will lose the
                    // game, sorry
                    this.Result = board.Turn == PColor.White
                        ? Winner.Red : Winner.White;
                    OnMatchOver();
                }
                // Is the task overdue?
                else if (DateTime.Now - taskStartSysTime > aiTimeLimit)
                {
                    // If so, notify user
                    view.SubmitMessage(
                        $"Time limit exceeded for {CurrPlrNameColor}!");

                    // Inform the task it should cancel its thinking
                    ts.Cancel();

                    // Set task to null
                    aiTask = null;

                    // The AI player that was overdue loses the game
                    this.Result = board.Turn == PColor.White
                        ? Winner.Red : Winner.White;
                    OnMatchOver();
                }
            }
        }
    }
예제 #24
0
 /// <summary>
 /// This method will be called before a match starts and is used for
 /// instantiating a new <see cref="RandomAIThinker"/>.
 /// </summary>
 /// <seealso cref="AIPlayer.Setup"/>
 public override void Setup()
 {
     thinker = new RandomAIThinker();
 }
예제 #25
0
 public override void Setup()
 {
     base.Awake();
     thinker = new G0A1Thinker();
 }
예제 #26
0
 /// <summary>
 /// This method will be called before a match starts and is used for
 /// instantiating a new <see cref="LoserSleeperAIThinker"/>.
 /// </summary>
 /// <seealso cref="AIPlayer.Setup"/>
 public override void Setup()
 {
     thinker = new LoserSleeperAIThinker();
 }
예제 #27
0
        // Update is called once per frame
        private void Update()
        {
            // Don't run update if the game's over
            if (matchOver)
            {
                return;
            }

            // Is the current player human? If so, let's see if we're supposed
            // to show him a message or if we've done so already
            if (matchData.CurrentThinker is HumanThinker)
            {
                if (showHumanTurnMessage)
                {
                    view.SubmitMessage(
                        $"Attention {CurrPlrNameColor}, it's your turn");
                    showHumanTurnMessage = false;
                }
                ;
            }

            // If the current player is an AI, let's see if we have to start
            // the AI thinking task, if the task is running, if it's completed,
            // etc.
            else
            {
                // If the AI task is null, we need to start an AI thinking task
                if (aiTask == null)
                {
                    // Submit a message informing the user the AI is thinking
                    view.SubmitMessage(
                        $"{CurrPlrNameColor} is thinking, please wait...");

                    // Keep note of task start time (both system time and game
                    // time)
                    stopwatch.Restart();
                    taskStartGameTime = Time.time;

                    // Create a new task cancellation token, so task can be
                    // interrupted
                    ts = new CancellationTokenSource();

                    // Get this AI's thinker
                    thinker = matchData.CurrentThinker;

                    // Start task in a separate thread using a copy of the
                    // board
                    aiTask = Task.Run(
                        () => thinker.Think(board.Copy(), ts.Token));
                }
                else // This else will run if the task is not null
                {
                    // Did the task throw an exception?
                    if (aiTask.IsFaulted)
                    {
                        // If so, notify user
                        view.SubmitMessage(string.Format(
                                               "{0} exception: {1}",
                                               CurrPlrNameColor,
                                               aiTask.Exception.InnerException.Message));

                        // Send a cancellation token to the task in the hope it
                        // might actually terminate
                        ts.Cancel();

                        // Set task to null
                        aiTask = null;

                        // The AI player that throwed the exception will lose
                        // the game, sorry
                        OnMatchOver(board.Turn.Other().ToWinner());
                    }
                    // Is the AI thinking task completed in time?
                    else if (aiTask.IsCompleted &&
                             cancellationStopwatch == null)
                    {
                        // Register task duration, if we haven't done so yet
                        if (float.IsNaN(lastTaskDuration))
                        {
                            lastTaskDuration = (float)(
                                stopwatch.ElapsedTicks
                                /
                                (double)(TimeSpan.TicksPerSecond));
                        }

                        // Did we pass the minimum time between AI moves?
                        if (Time.time >
                            taskStartGameTime + matchConfig.MinMoveTimeSeconds)
                        {
                            // Get the move chosen by the thinker
                            FutureMove move = aiTask.Result;

                            // Was the thinker able to chose a move?
                            if (move.IsNoMove)
                            {
                                // Thinker was not able to chose a move,
                                // submit a message informing user of this
                                view.SubmitMessage(string.Format(
                                                       "{0} unable to perform move",
                                                       CurrPlrNameColor));

                                // The AI player unable to move will lose
                                // the game, sorry
                                OnMatchOver(board.Turn.Other().ToWinner());
                            }
                            else
                            {
                                try
                                {
                                    // If so, submit a message informing of
                                    // the move chosen and the system time it
                                    // took the AI to think
                                    view.SubmitMessage(string.Format(
                                                           "{0} placed a {1} piece at column {2} after {3}",
                                                           CurrPlrNameColor,
                                                           aiTask.Result.shape.ToString().ToLower(),
                                                           aiTask.Result.column,
                                                           $"thinking for {lastTaskDuration:f4}s"));

                                    // Player was able to make a move decision,
                                    // let's perform the actual move
                                    MakeAMove(aiTask.Result);
                                }
                                catch (Exception e)
                                {
                                    // The act of making an actual move caused
                                    // an exception, which means the thinker
                                    // chose an invalid move, as such,
                                    // notify user of this
                                    view.SubmitMessage(string.Format(
                                                           "{0} exception: {1}",
                                                           CurrPlrNameColor, e.Message));

                                    // The AI player that caused the exception
                                    // will lose the game, sorry
                                    OnMatchOver(board.Turn.Other().ToWinner());
                                }
                            }

                            // Set the task to null, so it can be
                            // started again
                            aiTask = null;

                            // Reset the last task duration
                            lastTaskDuration = float.NaN;
                        }
                    }
                    // Is the task overdue?
                    else if (stopwatch.Elapsed > aiTimeLimit)
                    {
                        // If so, check the status of the thinking cancellation
                        // process
                        if (cancellationStopwatch is null)
                        {
                            // The thinking cancellation process has not yet
                            // been started, so let's start it

                            // Inform user that the time limit for
                            // the current thinker has been exceeded
                            view.SubmitMessage(
                                $"Time limit exceeded for {CurrPlrNameColor}!");

                            // Notify task it should cancel its thinking
                            ts.Cancel();

                            // Start cancellation stopwatch
                            cancellationStopwatch = Stopwatch.StartNew();
                        }
                        else if (aiTask.IsCompleted)
                        {
                            // The thinking task is completed after the
                            // cancelation request, terminate match normally

                            // Set task to null
                            aiTask = null;

                            // Set cancellation stopwatch to null
                            cancellationStopwatch = null;

                            // The AI player that was overdue loses the game
                            OnMatchOver(board.Turn.Other().ToWinner());
                        }
                        else if (cancellationStopwatch.ElapsedMilliseconds >
                                 UncooperativeThinkerException.HardThinkingLimitMs)
                        {
                            UnityEngine.Debug.LogWarning($"{cancellationStopwatch.ElapsedMilliseconds}ms have passed :(");

                            // If the hard thinking process time limit has been
                            // reached, throw an exception to terminate the app
                            throw new UncooperativeThinkerException(thinker);
                        }
                    }
                }
            }
        }
예제 #28
0
 public override void Setup()
 {
     base.Awake();
     thinker = new G06KiwIAThinker(depth);
 }
예제 #29
0
 /// @copydoc ColorShapeLinks.TextBased.Lib.IThinkerListener.ListenTo
 /// <seealso cref="ColorShapeLinks.TextBased.Lib.IThinkerListener.ListenTo"/>
 public void ListenTo(IThinker subject)
 {
     subject.ThinkingInfo += ThinkingInfo;
 }
예제 #30
0
 public static void Add(IThinker toAdd)
 {
     _processQueue.Add(toAdd);
 }