تاريخ المشاركة (والانتصار) في كأس منظمة العفو الدولية الروسية 2018 - CodeBall

كان يوم الأربعاء ، كان هناك اجتماع ممل عادي في العمل. خدش المصمم خلف أذنه ، ودفن الفاحص نفسه على الهاتف. بدأت إحدى السيارات خارج النافذة ، وتلقيت رسالة على الهاتف - بدأ كأس AI 2018 الروسي . لا أحد يشك في أي شيء ، وفي تلك اللحظة كنت أعرف بالضبط ما الذي سأفعله في الشهر ونصف الشهر المقبلين.

مرحباً بالجميع ، اسمي Andrey Tokarev وأود أن أشارك تجربتي في المشاركة في كأس روسيا 2018 AI .



ما هذا


كأس الذكاء الروسي هو مسابقة ذكاء اصطناعية سنوية تقام منذ عام 2012. هنا تحتاج إلى كتابة خوارزمية تتحكم في شخص ما أو شيء ما ، وهؤلاء الأشخاص أو شيء ما يتنافس مع بعضهم البعض. هذا العام كان من الضروري السيطرة على الروبوتات التي تلعب كرة القدم.

كان لدي بالفعل بعض الخبرة في اللعب في مثل هذه المسابقات. على وجه الخصوص ، شاركت في كأس AI الروسية لعام 2016 (بدون جائزة) وكأس Mini AI 2018 (المركز الثاني).

دعنا نذهب


بادئ ذي بدء ، قمت بإنشاء فصولي من عالم اللعبة ، والأشياء ، وأخذت متجهًا ثنائي الأبعاد وثلاثي الأبعاد من المسابقات السابقة وقمت بتحميله بالكامل إلى مستودع Git. بالطبع ، يمكنك استخدام كائنات من حزمة اللغة ، لكن لا توجد متجهات ، لا يمكن تعديلها ، بل إنه أكثر ملاءمة لاستخدام الفصول الدراسية الخاصة بك. ما لم أعد كتابته هو فئة الساحة ، لقد تناسبني كما هي ، ولم تكن هناك حاجة لتغييره.

المحاكاة


هنا لدينا عالم ألعاب ، وما الذي يمكننا فعله حيال ذلك؟

لكن لا يوجد أي شيء ، حتى يمكننا محاكاة عالم اللعبة ، ولا حتى تحديد ما إذا كانت الكرة تطير إلى شبكة فارغة. لذلك نحن شطب المحاكاة. لا يمثل رمز المحاكاة جزءًا من حزمة اللغة ، بل يتم توفيره بلغة لا أعرفها. لكن بناء جملة C متشابه ، لذلك نسخ + لصق تعريف الوظائف الضرورية ، وجهاز sim جاهز بنسبة 90٪. عندما كان من الضروري الحكم على يدي ، حاولت أن أفعل ذلك بعناية ، حيث أن الأخطاء هنا قد تكون مكلفة ولن يكون الإمساك بهم سهلاً. ما زلت أتمكن من ارتكاب بعض الأخطاء ، لكن الأمر كلفني القليل من الدماء.

أصبح من الواضح على الفور أنه إذا استخدمت محاكاة صادقة (100 علامة صغيرة) ، فإن هذا لا يكفي ، فمن المربح أكثر بكثير حساب 100 خيار باستخدام ميكروتيك واحد أكثر من خيار واحد مع 100 ميكروتيك. ما زلت غادر 2 microtics بحيث التناقض لم يكن كبيرا جدا.

أساسيات الاستراتيجية


وبالتالي لدينا عالم ألعاب ويمكننا محاكاة تغيره. إذن ماذا بعد؟
هناك طرق مختلفة. عندما يكون هناك عدد قليل من التحركات الممكنة والعمق ليس كبيرًا جدًا ، يمكنك القيام بذلك بقوة شديدة: يمكنك فرز جميع الحركات ، حتى حركات عودة الخصم ، لديهم تحركاتهم الخاصة مرة أخرى ... أي الحد الأدنى عندما يكون هناك العديد من التحركات ، يمكنك تقييدها بشكل مصطنع ، على سبيل المثال ، يمكنك اتخاذ اتجاهات بمضاعفات 15 درجة ، والانتقال إلى كل علامة عشر ، واستخدام الحد الأدنى نفسه. لكن يبدو لي أن هذا النهج مناسب عندما تكون النتيجة غير حساسة للتغيرات الطفيفة في الحركات ، وهنا ، فإن الانحراف بدرجة واحدة في اتجاه الروبوت سيؤدي إلى انحرافات كبيرة بعد الاصطدام.

الطرف الآخر ، عندما نتحرك دون بحث شامل ، هو نوع من مجريات الأمور. قد يكون هذا النهج قابلاً للتطبيق ، لكن إنشاء لاعب كرة قدم قوي ذو استدلال نقي أمر صعب للغاية.

لكن الجمع بين الطريقتين يبدو واعدًا: يمكنك أولاً التحرك في اتجاه عشوائي ، ثم إنهاء اللعبة بأسلوب ارشادي يمكن أن يصل إلى الكرة ويقفز في الوقت المناسب. يمكن استخدام نفس مجريات الأمور مجتمعة للتنبؤ بتحركات الخصم. في وقت سابق ، كنت قد استخدمت شيئًا مشابهًا في المسابقة ، ولم تثبت هذه الطريقة بشكل أو بآخر أنها سيئة.

وهكذا نكتب الاستدلال (في رجل ذكي رايك ovsky أو ​​ذكية فقط)!

منذ أن أردت رؤية النتيجة في أسرع وقت ممكن ، تمت كتابة smartgay على عجل واتضح أنها كانت غبية إلى حد ما (حتى الرمز مخجل). لقد قمت بحساب الوقت الذي يستطيع فيه الروبوت التقاط الكرة بناءً على السرعة الحالية للكرة والسرعة القصوى للروبوت ، وركضت إلى النقطة التي ستكون فيها الكرة في ذلك الوقت (لم تتم مراعاة التصادمات). لم يكن يعرف كيف يقفز ولم يأخذ في الحسبان ارتفاع الكرة ، ويمكنه بسهولة الركض تحت الكرة ، وإذا تحركت الكرة بسرعة كبيرة ، فقد ركض في الاتجاه المعاكس بشكل عام. بما أن الأذكياء لم يتمكنوا من القفز ، فقد جعلته أولاً يقفز على مسافة ثابتة من الكرة ، وبعد ذلك بقليل وقع اختيار لحظة القفز على أكتاف عشوائي كبير! تبين أن الافتقار إلى الاختيار العقلاني للقفز يمثل عائقًا كبيرًا ، ولكن أكثر من ذلك في وقت لاحق. ولكن بشكل عام ، لم تبدو النظافة الذكية سيئة ، وأحيانًا سجلت أهدافًا ، على الرغم من أهدافها الخاصة أيضًا.

بعد ذلك ، نحتاج إلى وظيفة تقييم (OF).

بدا الأمر الأول لـ OF كالتالي: (1000 - علامة) * هدف + ball.z + بعض وظائف الموضع النسبي للروبوت والكرة بحيث يتم تشغيلها حتى الكرة حتى لو لم تتمكن من الوصول إليها. هنا ، يمكن أن يكون الهدف -1،0،1 اعتمادًا على ما إذا كان هناك هدف ولمن ، والقراد هو علامة من بداية المحاكاة التي وقع فيها الهدف. آخر شيء هو أن الروبوت لا يؤجل الهدف باستمرار.

الآن نجعل الروبوت يعمل في اتجاه عشوائي عددًا عشوائيًا من القراد ، ثم ننقل التحكم إلى الشخص الذكي ، الذي يؤدي به إلى الكرة ، في لحظة عشوائية يقفز ويضرب الكرة . علاوة على ذلك ، من الأفضل عدم الركض إلى مركز الكرة ، ولكن مع تحول عشوائي بمسافة صغيرة ، بحيث يمكن أن يضرب الروبوت بزاوية.

استغرقت المحاكاة وقتًا ثابتًا قدره 2 ثانية ، وفي النهاية تم استدعاء OF. تم تكرار هذا السيناريو عدة مرات لكل روبوت وتم اختيار الأفضل على أساس التصنيف.

حتى الآن ، تحتوي هذه الاستراتيجية على عيب خطير: ليس لها ذاكرة - يتم حساب كل شيء من نقطة الصفر على كل علامة ، مما يعني أن الاستراتيجية يمكن أن ترى هدفًا في علامة واحدة ، ولن تجدها في المرحلة التالية. ليست هذه هي الحالة ، فأنت بحاجة إلى إصلاحها - فنحن نوفر الخيار الأفضل الموجود لكل روبوت ونعيد استخدامه في علامة التجزئة التالية. كما أن الروبوتات أصبحت الآن على دراية بشؤون بعضنا البعض ، على سبيل المثال ، إذا كانت الأولى ستضرب الكرة ، فإن الثانية لا تعمل بعد الكرة ، ولكنها تحاول التمريرة.

حارس المرمى


نحن بحاجة إلى حارس مرمى كان حارس المرمى الخاص بي مختلفًا بشكل أساسي عن المهاجم لأنه كان ينشط عندما تقترب الكرة من مسافة معينة إلى الهدف ، وإلا فإنها ستعود ببساطة إلى نقطة قاعدتها.

ملخص


الآن لدينا استراتيجية أساسية جيدة يمكنها أن تفعل كل ما هو ضروري والتي يمكن البناء عليها في المستقبل.

ربما يبدو كل ما هو موصوف أعلاه بسيطًا ومنطقيًا ، ولكن بصراحة في بداية المسابقة ، لم تكن هناك صورة واضحة عن الاستراتيجية التي بدت أقرب إلى النهاية ، واستغرق الأمر أسبوعين لتنفيذ ذلك ، وهذا هو ثلث المسابقة.

قليلا عن الاختبار


بمرور الوقت ، ستحدث لعبة Grails التي تضاعف قوة اللعبة بشكل أقل وأقل ، وسيتعين علينا اختيار التغييرات التي تزيد + 10-20٪ من الأهداف. ثم اتضح أن هذه المكاسب الصغيرة ليس من السهل تحديدها. للحصول على نتيجة شاملة ، تحتاج إلى تسجيل مئات الأهداف ، ومع تكرار الهدف مرة واحدة في الدقيقة ، فإن هذا يستغرق عدة ساعات من وقت اللعب. لهذا السبب ، تقريبًا لم أختبر الاستراتيجيات على الخادم ، لكنني أجرت اختبارات محلية طويلة مقابل الإصدارات السابقة. لكن حتى اختبار أي تغيير محلي لمدة نصف يوم لن يكون مناسبًا للغاية. لذلك ، تقدمت بطلب قليل "خدعة" - اختبرت الاستراتيجيات المقطوعة. إذا ، على سبيل المثال ، في أحد الخوادم ، تجاوزت 50 خيارًا لكل روبوت ، ثم فقط 10 محليًا ، سمح لي ذلك بإجراء الاختبارات في وقت مقبول.

التحسينات


بعد ذلك ، سوف أصف التحسينات الرئيسية وتقييمها في النموذج التالي: بعدد المئة في المئة ، يسجل الإصدار الجديد أهدافًا أكثر مما يتلقاه من الإصدار القديم. أي على سبيل المثال ، إذا تفوق واحد جديد على القديم بنسبة 120: 100 فهو + 20 ٪ ، إذا كان يسجل مرتين أكثر ، فهو + 100 ٪.

- يجب أن يتغلب حارس المرمى على الأهداف. إذا لم ينجح ، فامنحه مزيدًا من الوقت ، وزد عدد الخيارات حتى 10. + 15 ٪

- في بعض الأحيان ، عندما يضرب حارس المرمى الكرة ، يذهب في رحلة مجانية ، وفي حين أن لديه الوقت للعودة إلى مكانه ، فإنهم يسجلون هدفًا بالفعل. بعد ضرب الكرة مباشرة ، نحاول إعادتها إلى مكانها وإضافة علامة إلى أنها تعود إلى التقييم بمعامل سلبي صغير. + 20 ٪

- ركلة إضافية على الكرة أمام هدف آخر تزيد من فرصة هدف ، وسنقدم مكافأة في OF لهذا. + 60 ٪

- تجربة مع نيترو! لم يتبق سوى بضعة أيام حتى الجولة الأولى ، لكنني قررت اختبار نيترو مقدمًا. حدسي ، بدا لي أن النيترو سيؤثر بشكل كبير على طريقة اللعب ، لأنه في إحدى الدبابات يمكنك القفز إلى السقف أو الطيران فوق الحقل بأكمله. بادئ ذي بدء ، قمت بتدريس كيفية استخدام nitro فقط للمهاجم ، وحتى بعد ذلك فقط في الهواء ، لكنني لم أحصل على الحزم بعد. تم استخدام Nitro أثناء الرحلة في الاتجاه ثلاثي الأبعاد الآن العشوائي. وكانت النتيجة ، بعبارة ملطفة ، ليست غاية ، لم أتمكن من الضغط على أكثر من + 20٪ ، ولم ينتج عن استخدام النيترو على الأرض أي نتائج. لذا تم وضع المشكلة مع nitro مؤقتًا ، على الرغم من أنني حاولت منذ هذه اللحظة إجراء اختبارات مع nitro قيد التشغيل.

- الكثير من العشوائية! Random أمر جيد ، بالطبع ، في بعض الأحيان يقدم حيلًا لا تفكر بها ، ولكن من ناحية أخرى ، عندما يكون هناك الكثير منها ، فإن احتمال تزامن كل شيء صغير جدًا. وكان لدي الكثير منه. قررت محاولة نقل لحظة القفزة إلى الأساس التحليلي. نظرًا لعدم وجود تسارع أفقي في الهواء (نسيان النيترو) ، فقد كان من السهل حساب اللحظة التي يلتقي فيها الروبوت والكرة (t1) ، وارتفاع الكرة في تلك اللحظة (h1). الآن نحسب الوقت (t2) الذي بعده سيكون الروبوت في ارتفاع h1 ، قفز الآن. هنا نحصل على معادلة من الدرجة الثانية ، إذا لم يكن لها حل أو t2 <t1 ، فقفز مبكراً ، وإلا فقفز.

أظهرت النتيجة صدمة لي قليلاً ، فقمت بالقفز الصحيح لكل من المهاجم وحارس المرمى ، وأظهرت الاختبارات + 200٪ ، أي فاز الإصدار الجديد القديم 3 مرات في الأهداف ، والكأس الحقيقي! في 17 كانون الثاني (يناير) ، بعد أن حملت الاستراتيجية على الخادم ، حصلت على تصنيف 200+ في سلسلة انتصارات من 20 مباراة وتصدرت صندوق الرمل لفترة.

- نحن نعلم حارس المرمى للعب. حتى تم تنشيط حارس المرمى الخاص بي ، وقف مثل العمود. من السهل المشي الجانب: س = ball.x / 4 أعطى زيادة طفيفة.

- يجب عدم توقع الخصم ، ولكن يفترض! أثناء النظر إلى الألعاب ، لاحظت أنني غالبًا ما أحصل على هدف بعد أن اصطدم حارس المرمى بالكرة مباشرة على الخصم وأحرز هدفًا لي أثناء الطيران. لضرب الكرة لتجاوز الخصم ، تحتاج أولاً إلى تحديد المكان الذي يمكن أن يكون فيه على القراد. بالطبع ، لن نأخذ بعين الاعتبار نيترو. لا يزال بإمكاني تحديد سرعة الروبوت بالتحليل ، ويبدو أن هناك تقاطع دائرتين. لكنه لم يستطع التعامل مع الأراضي التي يمكن الوصول إليها. حسنًا ، إلى الجحيم ، نحن مبرمجون (وليس عن طريق التعليم) ، فلندع الآلة تحسب لنا. قسّم الطائرة إلى اتجاهات n ، وانقل الروبوت في كل اتجاه ، وستكون نقاط النهاية هي رؤوس المضلع الذي يحدد مدى الوصول.

كيفية استخدامها؟ أضفت علامة حيث يمكن للخصم أن يمس الكرة لأول مرة ، مع معامل جيد في OF. بما أنه لم يعد هناك سيناريو محدد من الإجراءات ، ولكن تم اعتبار سحابة معينة من الوصول للخصم ، قمت بإزالة روبوتات العدو بمجرد اتصالهم بالأرض.

النتيجة + 40 ٪. بالإضافة إلى ذلك ، يتميز هذا الأسلوب بمميزتين سمينتين: إزالة روبوتات العدو في الأول تسرع المحاكاة ، وهذا بدوره يجعل من الممكن فرز خيارات أكثر ، وفي الثانية لا يتعين علينا أن نضايق مع سيطرة الخصم. الخلاصة: الربح!

- أخطاء غبية ، ولكن ماذا بدونها. هناك سطرين في المحاكي الرسمي:

if abs(ball.position.z) > arena.depth / 2 + ball.radius: goal_scored() 

لا أعرف من كيف ، لكن تركت وظيفة abs () كما هي ، لكن دون جدوى. يأخذ abs-line () (لا يجب الخلط بينه وبين std :: abs ()) قيمًا صحيحة ، مما يعني أن الكسور العشرية يتم اقتطاعها. في الممارسة العملية ، هذا يعني أنني سجلت الهدف فقط عندما كانت الكرة بالفعل متر كامل وراء خط المرمى. استبدال القيمة المطلقة () مع القوات المسلحة البوروندية ()! ليست هذه هي المرة الأولى التي خذلتني هذه القيمة المطلقة.

- نيترو مرة أخرى. كانت الجولة الثانية تقترب ولم يكن هناك مكان لتأجيل الاستخدام الطبيعي للنيترو. قام بتحسين استخدامها ، وراعى تعريف القفز ، وسمح باستخدام حارس المرمى ، وبدأ أيضًا في جمع الحزم عن طريق حارس المرمى.

- دعنا نعود إلى المحاكاة. لقد سبق أن قلت أن 100 خيار مع microtik واحد هي أكثر ربحية من خيار واحد مع 100 microtics. هذا صحيح ، لكن هذا لا يعني أنه مع وجود Mikrotik ، كل شيء على ما يرام ، وبدون تدابير إضافية ، كانت التناقضات خطيرة للغاية ، وهذا يمنع من لعب كرة القدم على مستوى احترافي. لتحسين دقة المحاكاة ، طبقت الطرق التالية:

  • خلال القفزة ، واثنين من Mikrotik إضافية.
  • عندما نجمع الكثير من microtics ، عند تحريكه ، من الأصح استخدام السرعة المتوسطة وليس الأخيرة.
  • باستخدام البحث الثنائي ، نجد علامة التجزئة التي يحدث فيها التصادم ، وننفذ تكتيكين فرعيين: أحدهما قبل التصادم والآخر بعده. (لم أكن آخذ في الاعتبار تصادم الكرة بسطح مستوٍ ، كان هناك تباين غير مهم بالنسبة لي.)
  • الركض على سطح منحنٍ ما زال يسبب اختلافات كبيرة وأحياناً غاب حارس المرمى عن هذا السبب. لذلك ، عندما كان حارس المرمى على سطح منحني ، استخدمت 10 ميكروتكس.

في المتوسط ​​، تم الحصول على حوالي 1.4 ميكروتك لكل علامة ، وكانت الدقة قريبة من المثالية. بالطبع ، أنا لم أكن برغي هذه التحسينات في وقت واحد ، ولكن تدريجيا. لا أعرف مقدار تأثيرهم على قوة اللعبة ، لكنني أعتقد أن هذا أمر مهم للغاية.

ماذا لدينا


بفضل عدد كبير من التحسينات المهمة ، نمت الإستراتيجية بشكل مطرد في الترتيب ، وقبل الجولة الثانية ، وصلت تقريبا إلى المعلم التاريخي - 5000 تصنيف Elo ، واكتسبت بثقة في المقام الأول.


في بعض الأحيان لا يمكنك حتى تصديق ما هي المجموعات التي تصدرها بشكل عشوائي. بفضل المجتمع الرقيقة المجهول للعثور.

الاسبوع الماضي


فيما يتعلق بهذا الهامش الجيد ، سمحت لنفسي بعدم ملاحقة التحسينات الصغيرة ، ولكن البحث عن شيء عالمي ، خاصة فيما يتعلق بالألعاب 3 × 3. ومع ذلك ، فشلت التجارب التي تهدف إلى المزيد من لعبة الفريق ، أو غرس لاعب ثالث في دور خاص ، أو لتعليم حارس المرمى على الخروج أثناء الفشل. لقد قضى الأسبوع بأكمله دون جدوى. رغم ذلك ، قبل يومين من النهائي ، كنت لا أزال في المقدمة.
والآن في اليوم الأخير قبل نهاية المباراة ، بدأت أخسر أمام واحد ، ثم آخر وحتى منافس ثالث. إذا لم تقم بإضافة ، يمكنك البقاء بدون جائزة. لم يحدث شيء طوال الأسبوع ، ماذا يمكنني أن أفعل في اليوم الأخير؟ كان المزاج - على الأقل يستسلم.

القيامة


بعد مشاهدة مباراتين خاسرتين ، لاحظت أن الجميع يقفز مثل الماعز في نيترو ويمرر الكرة في الهواء ، لكنني لا أستطيع الحصول عليها. جربت أبسط شيء يمكن أن يؤدي إلى هذا السلوك - لقد أضفت ارتفاع الكرة في وقت التأثير مع معامل قوي في OF. النتيجة + 50 ٪ ، واو! مستوحاة من النتيجة ، بدأت في تحريف المعلمات بشكل مكثف (الذي أهملته خلال المسابقة بأكملها) ، وأضفت خيارات بحث جديدة ، وأضفت مزيدًا من التحكم في الوقت في النهاية ، مما سمح لي باستخدام الوقت إلى أقصى حد دون المخاطرة بحياتي. بحلول نهاية اليوم ، تحولت النسبة إلى 150-200٪ ، أي النسخة الجديدة تغلبت على الهدف السابق ثلاث مرات تقريبًا في الأهداف! نعم ، نعم ، لقد احتل المركز الأول قبل ما يقرب من أسبوع على المركز الأول ووصل إلى تصنيف غير مسبوق بلغ 5000+ في تاريخ البطولة. على الخادم ، تم اختبار الاستراتيجية بنجاح قبل ساعتين من النهائي. بعد ذلك ، قمت بإعداده للإطلاق النهائي: التأكيدات المعطلة ، إضافة تدقيقات القسم إلى الصفر ، وتحميله إلى الخادم مرة أخرى ، وتحويل نفسي إلى وضع الاستعداد.

الجزء الأخير


استغرق الجزء الأول من النهائيات مكان في الليل. تابعت النتائج حتى غفيت ، استيقظت في الصباح الباكر. لقد لعبت ثلاث موجات (في موجة واحدة يلعب كل منها مع كل منهما) ، خسرت مباراة واحدة فقط ضد توني ، وبما أن أنتون ما زال يخسر أحيانًا أمام لاعبين آخرين ، فقد كنت في المقدمة بفارق 7 نقاط (نقطتان للفوز). فجوة خطيرة جدا لمدة 3 موجات ، ولكن ليس بما فيه الكفاية للاسترخاء.

في اليوم الأخير ، بالطبع ، لم أكن أنوي فعل أي شيء جاد ، فالمعلمات الملتوية بشكل أساسي. تم إجراء العديد من التغييرات ، ولكن نظرًا لأن كل شيء تم اختباره على عجل ، لم أكن متأكدًا تمامًا من أن التأثير كان إيجابيًا. بشكل عام ، كانت الزيادة 0-20 ٪. لكن انطون أضاف بشكل كبير وبدأ على الأقل اللعب ليس أسوأ مني.

لم يكن هناك شيء لأفعله ، كان علي إرسال ما هو ، والأمل في الحظ وتزويدك بالنقاط.

الجزء الثاني


لحسن الحظ ، تم فرز الألعاب بحيث لعب القادة في البداية فيما بينهم ، لذلك لم يكن هناك داع للقلق ، وكانت المباراة الأولى ضد TonyK. الحظ كان في صفحتي ، لقد فزت في المعركة الأولى ، بالإضافة إلى جميع المباريات الأخرى في هذه الموجة ، بينما خسر TonyK نقطة أخرى. يكاد يكون من المستحيل اللعب فجوة قدرها 10 نقاط لاثنين من الأمواج ، والآن أصبح من الممكن الاسترخاء.

النتيجة النهائية: 352 فوزًا وخسارة 2 (كلاهما من أنطون) ، المركز الأول بهامش 12 نقطة.

شكرا وغيرها من القمامة


بشكل عام ، لقد أحببت حقًا مهمة هذا العام ، فقد كانت "بالنسبة لي" (المحاكاة هي لي ، وثلاثية الأبعاد لا تخيفني) وكانت المباريات مذهلة ، وأعتقد أنه كان من المثير للاهتمام أن أشاهد ليس فقط المشاركين.

أود أن أشكر المنظمين على المنافسة الرائعة.

أود أيضًا أن أشكر جميع المشاركين ، خاصةً أنطون كوزلوفسكي ( TonyK ) على المنافسة في النهائيات ، إيفان Tyamgin ( tyamgin ) للمنافسة في صندوق الرمل وأليكسي ديتشوفسكي ( كوماندوز ) على الامتناع عن المشاركة وبالتالي زادت فرصي في الفوز.

حظا سعيدا للجميع في RAIK القادم!

Source: https://habr.com/ru/post/ar440398/


All Articles