private void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            if (Client.IsRegistered && Client.Board == null || Client.CurrentPiece == null || Client.NextPiece == null)
            {
                return;
            }

            DateTime searchBestMoveStartTime = DateTime.Now;

            // Use specials
            List <SpecialAdvice> advices;

            SpecialStrategy.GetSpecialAdvices(Client.Board, Client.CurrentPiece, Client.NextPiece, Client.Inventory, Client.InventorySize, Client.Opponents.ToList(), out advices);
            foreach (SpecialAdvice advice in advices)
            {
                bool continueLoop = true;
                switch (advice.SpecialAdviceAction)
                {
                case SpecialAdvice.SpecialAdviceActions.Wait:
                    continueLoop = false;
                    break;

                case SpecialAdvice.SpecialAdviceActions.Discard:
                    Client.DiscardFirstSpecial();
                    continueLoop = true;
                    break;

                case SpecialAdvice.SpecialAdviceActions.UseSelf:
                    continueLoop = Client.UseFirstSpecial(Client.PlayerId);
                    break;

                case SpecialAdvice.SpecialAdviceActions.UseOpponent:
                    continueLoop = Client.UseFirstSpecial(advice.OpponentId);
                    break;
                }
                if (!continueLoop)
                {
                    break;
                }
                System.Threading.Thread.Sleep(10); // delay next special use
            }

            DateTime specialManaged = DateTime.Now;

            // Get best move
            int  bestRotationDelta;
            int  bestTranslationDelta;
            bool rotationBeforeTranslation;

            MoveStrategy.GetBestMove(Client.Board, Client.CurrentPiece, Client.NextPiece, out bestRotationDelta, out bestTranslationDelta, out rotationBeforeTranslation);

            DateTime searchBestModeEndTime = DateTime.Now;

            // Perform move
            if (rotationBeforeTranslation)
            {
                // Rotate
                Rotate(bestRotationDelta);
                // Translate
                Translate(bestTranslationDelta);
            }
            else
            {
                // Translate
                Translate(bestTranslationDelta);
                // Rotate
                Rotate(bestRotationDelta);
            }
            // Drop (delayed)
            TimeSpan timeSpan  = DateTime.Now - searchBestMoveStartTime;
            double   sleepTime = SleepTime - timeSpan.TotalMilliseconds;

            if (sleepTime <= 0)
            {
                sleepTime = 10;
            }
            System.Threading.Thread.Sleep((int)sleepTime);  // delay drop instead of animating
            Client.Drop();
            //
            Log.Default.WriteLine(LogLevels.Info, "BEST MOVE found in {0} ms and special in {1} ms", (searchBestModeEndTime - specialManaged).TotalMilliseconds, (specialManaged - searchBestMoveStartTime).TotalMilliseconds);
        }
Beispiel #2
0
        private void BotTask()
        {
            WaitHandle[] waitHandles =
            {
                _handleNextPieceEvent,
                _stopEvent
            };
            while (true)
            {
                int handle = WaitHandle.WaitAny(waitHandles, SleepTime);
                if (!_handleNextPieceEvent.WaitOne(0) && _client.IsPlaying && !_isConfusionActive)
                {
                    Log.Default.WriteLine(LogLevels.Warning, "!!!!!!!!!!! NextPieceEvent not raised  {0}  {1}", handle, _client.CurrentPiece?.Index ?? -1);
                }
                _handleNextPieceEvent.Reset();
                _stopEvent.Reset();

                if (handle == 1) // stop event
                {
                    break;
                }
                if (handle == 0 /*next piece event*/ && _client.IsPlaying && _client.Board != null && _client.CurrentPiece != null && _client.NextPiece != null)
                {
                    Log.Default.WriteLine(LogLevels.Debug, "NextPieceEvent was raised");

                    int currentPieceIndex = _client.CurrentPiece.Index;
                    //Log.Default.WriteLine(LogLevels.Debug, "Searching best move for Piece {0} {1}", _client.CurrentPiece.Value, _client.CurrentPiece.Index);

                    DateTime searchBestMoveStartTime = DateTime.Now;

                    // Use specials
                    if (SpecialStrategy != null)
                    {
                        List <SpecialAdvice> advices;
                        SpecialStrategy.GetSpecialAdvices(_client.Board, _client.CurrentPiece, _client.NextPiece, _client.Inventory, _client.InventorySize, _client.Opponents.ToList(), out advices);
                        foreach (SpecialAdvice advice in advices)
                        {
                            bool continueLoop = true;
                            switch (advice.SpecialAdviceAction)
                            {
                            case SpecialAdvice.SpecialAdviceActions.Wait:
                                continueLoop = false;
                                break;

                            case SpecialAdvice.SpecialAdviceActions.Discard:
                                _client.DiscardFirstSpecial();
                                continueLoop = true;
                                break;

                            case SpecialAdvice.SpecialAdviceActions.UseSelf:
                                continueLoop = _client.UseFirstSpecial(_client.PlayerId);
                                break;

                            case SpecialAdvice.SpecialAdviceActions.UseOpponent:
                                continueLoop = _client.UseFirstSpecial(advice.OpponentId);
                                break;
                            }
                            if (!continueLoop)
                            {
                                break;
                            }
                            Thread.Sleep(10); // delay next special use
                        }
                    }

                    DateTime specialManaged = DateTime.Now;

                    // No move evaluation if confusion is active
                    if (_isConfusionActive)
                    {
                        Log.Default.WriteLine(LogLevels.Info, "Confusion is active, no move evaluated");
                        continue;
                    }

                    // Get best move
                    if (MoveStrategy != null)
                    {
                        int  bestRotationDelta;
                        int  bestTranslationDelta;
                        bool rotationBeforeTranslation;
                        MoveStrategy.GetBestMove(_client.Board, _client.CurrentPiece, _client.NextPiece, out bestRotationDelta, out bestTranslationDelta, out rotationBeforeTranslation);

                        // TODO: could use an event linked to Client.OnRoundFinished
                        if (_client.CurrentPiece.Index != currentPieceIndex)
                        {
                            Log.Default.WriteLine(LogLevels.Warning, "BOT IS TOO SLOW COMPARED TO AUTOMATIC DROP, skipping to next piece {0} != {1}", _client.CurrentPiece.Index, currentPieceIndex);
                            continue;
                        }

                        DateTime searchBestModeEndTime = DateTime.Now;

                        //Log.Default.WriteLine(LogLevels.Debug, "Rotation: {0} Translation {1}  {2}", bestRotationDelta, bestTranslationDelta, rotationBeforeTranslation);

                        // Perform move

                        if (rotationBeforeTranslation)
                        {
                            // Rotate
                            Rotate(bestRotationDelta);
                            // Translate
                            Translate(bestTranslationDelta);
                        }
                        else
                        {
                            // Translate
                            Translate(bestTranslationDelta);
                            // Rotate
                            Rotate(bestRotationDelta);
                        }
                        // Drop (delayed)
                        TimeSpan timeSpan  = DateTime.Now - searchBestMoveStartTime;
                        double   sleepTime = SleepTime - timeSpan.TotalMilliseconds;
                        if (sleepTime < 10)
                        {
                            sleepTime = 10; // at least 10 ms
                        }
                        //Thread.Sleep((int)sleepTime); // delay drop instead of animating
                        bool stopped = _stopEvent.WaitOne((int)sleepTime);
                        if (stopped)
                        {
                            //Log.Default.WriteLine(LogLevels.Debug, "Stop bot received while sleeping before next move");
                            break;
                        }
                        // TODO: could use an event linked to Client.OnRoundFinished
                        if (_client.CurrentPiece.Index != currentPieceIndex)
                        {
                            Log.Default.WriteLine(LogLevels.Warning, "BOT IS TOO SLOW COMPARED TO AUTOMATIC DROP, skipping to next piece {0} != {1}", _client.CurrentPiece.Index, currentPieceIndex);
                            continue;
                        }
                        // Drop
                        Drop();
                    }
                    //
                    //Log.Default.WriteLine(LogLevels.Debug, "BEST MOVE found in {0} ms and special in {1} ms  {2} {3}", (searchBestModeEndTime - specialManaged).TotalMilliseconds, (specialManaged - searchBestMoveStartTime).TotalMilliseconds, _client.CurrentPiece.Value, _client.CurrentPiece.Index);
                }
            }
        }