داغاز: الحشد

الصورة الملايين منكم. نحن - الظلمة ، والظلام ، والظلام.
جربها ، حاربنا!
نعم ، السكيثيون - نحن! نعم ، الآسيويين - نحن ...

الكسندر بلوك " السكيثيون "

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


إذا كان أي شخص يتذكر ، كان الأمر يتعلق بلعبة " Abalon " ، التي طورها ميشيل لال ولوران ليفي في عام 1988. جوهرها هو دفع كرات العدو خارج الملعب. يمكن لكرتين دفع واحدة وثلاث كرات - زوج من الكرات بلون مختلف. يمكن للاعب تحريك الكرات الخاصة به على اللوحة ، واحدة في كل مرة ، أو في مجموعات ، كرتين أو ثلاث كرات (بالإضافة إلى ذلك ، يجب أن تشكل ثلاث كرات "صفًا"). ما الذي منعني من صنع هذه اللعبة في المرة الأخيرة؟

من الواضح أنها ليست حركة المجموعة نفسها. الحركة المتزامنة لعدة قطع ، في خطوة واحدة ، حتى في الشطرنج ( القلاع ). وتم بناء ألغاز " Sliding puzzles " لضمان حدوث مثل هذه الحركة بشكل متزامن وسلس. دعونا نلقي نظرة على لعبة واحدة طورها روبرت أبوت في عام 1975:


يبدو مثل أبالون. والفرق الوحيد هو أن "الصف" لا "يدفع" قطعة الخصم من مكانه ، ولكنه ببساطة يزيلها من اللوحة باستخدام التقاط "الشطرنج". يُمنح الفوز لأحد اللاعبين الذين تمكنوا من التعادل في الصف الأخير من لوحة قطعه أكثر مما تمكن خصمه من القيام به في نفس اللحظة. اللعبة بأكملها مبنية على تحريك "الصفوف". من غير المحتمل أن تنجح في الفوز بالقطاعات الانفرادية فقط. هذا ما تبدو عليه حركة الدفع البسيطة.

Zrf
(define push-1 ( $1 (verify friend?) (while friend? cascade $1 ) (verify not-friend?) add )) 

الأمر برمته يتعلق بالكلمة السحرية المتتالية - فهو يجبر المترجم على "تحرير" الرقم المتحرك إلى المجال الحالي ، مع أخذ شخصية أخرى "في اليد" (ليست مهمة بالنسبة له أو خصمه) ومواصلة التحرك ، بالفعل مع الشكل الجديد "في اليد". في خطوة واحدة ، يمكن إجراء مثل هذه العملية بشكل متكرر ، وبالتالي نقل عدد غير محدود من القطع في كل مرة. تم العثور على مثل هذه الحالات (والأكثر تعقيدًا قليلاً) في ألعاب أخرى - " Guns " و " Dameo " و " Leutwayite Game " و ...


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

Zrf
 (define push-2 ( $1 (verify friend?) (while friend? mark $1 (verify not-enemy?) to back cascade $1 ) $1 (verify not-friend?) add )) 

تعمل الكلمة الأساسية (وإقرانها من ) بالتزامن مع الشلال . هذا يعني أنه يجب وضع الرقم "خارج عن السيطرة" على السبورة الآن ، والشكل الجديد "يقبض على اليد" بعد ذلك بقليل ، بعد الانتقال إلى حقل آخر. بشكل عام ، "دفع" التحركات بسيط ، ولكن هناك نوع آخر من الحركة الجماعية لأبالون:


أسميها التحركات "المستعرضة". من وجهة نظر تشفير ZRF ، لا يوجد شيء معقد فيها. كانت المشكلة في واجهة المستخدم. كيفية "إخبار" البرنامج بأن اللاعب لا يرغب في تحريك كرة واحدة ، بل مجموعة ، إذا سمحت القواعد بالحركتين؟ أستخدم نفس "الومضة" ، التي كانت مفيدة جدًا لي في لعبة الداما ، لوضع علامة على الرقم "الحالي". الآن فقط هناك العديد من الأرقام "الحالية" في المجموعة.

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

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


في هذه اللعبة ، لا يُسمح إلا بالتحركات المتزامنة لمجموعات من ثلاث قطع (إذا كان هناك عدد أقل من القطع المتبقية ، فيجب على الجميع التحرك). تتحرك جميع الأشكال المختارة خطوة واحدة وفي نفس الاتجاه. القبض على الشطرنج ، تتداخل قطعه مع الحركة. للفوز ، يجب عليك تثبيت واحدة على الأقل من قطعك على السطر الأخير ، إلى معسكر العدو.

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

 (define step ( $1 add )) 

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

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

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


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

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

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

هذا ما يبدو عليه أذن البحر
 Dagaz.Model.closure = function(board, move, group) { var r = []; _.each(group, function(pos) { r.push(pos); }); for (var i = 0; i < r.length; i++) { var pos = r[i]; _.each(move.actions, function(a) { if ((a[0] !== null) && (a[1] !== null) && (a[0][0] == pos)) { var p = a[1][0]; var piece = board.getPiece(p); if ((piece !== null) && (piece.player == board.player) && (_.indexOf(r, p) < 0)) { r.push(p); } } }); } return r; } 

لكن التحركات "الدفعة" الطويلة مسموح بها في أوردو وهذه الخوارزمية لا تعمل! لا يهم - كل الوظائف المحددة في Dagaz. يمكن إعادة تعريف النموذج.

بهذه الطريقة
 Dagaz.Model.closure = function(board, move, group) { var design = board.game.design; var r = []; _.each(group, function(pos) { r.push(pos); }); for (var i = 0; i < r.length; i++) { var pos = r[i]; _.each(move.actions, function(a) { if ((a[0] !== null) && (a[1] !== null) && (a[0][0] == pos)) { var target = a[1][0]; var x = Dagaz.Model.getX(pos); var y = Dagaz.Model.getY(pos); var dx = sign(Dagaz.Model.getX(target) - x); var dy = sign(Dagaz.Model.getY(target) - y); var dir = design.findDirection(pos, pos + (dy * Dagaz.Model.WIDTH) + dx); if (dir !== null) { while ((pos !== null) && (pos != target)) { var piece = board.getPiece(pos); if ((piece === null) || (piece.player != board.player)) break; if (_.indexOf(r, pos) < 0) { r.push(pos); } pos = design.navigate(board.player, pos, dir); } } } }); } return r; } 

هذا التحميل الزائد أسهل بالنسبة لـ Takoka . نظرًا لعدم وجود تحركات "دفع" فيها (من الضروري دائمًا إبراز جميع القطع المضمنة في المجموعة بشكل واضح) ، يكفي حظر هذه الوظيفة ، أي ببساطة لا توسع المجموعة:

 Dagaz.Model.closure = function(board, move, group) { return group; } 

أعتذر عن اسم الوظيفة الذي لا يقول أي شيء لأي شخص. لم أستطع التوصل إلى اسم أفضل للعمل.


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

تحول GESS إلى كابوس حقيقي ، سواء من حيث " السحر " أو من حيث النموذج الأولي نفسه - الهيكل العظمي للعبة. يكفي القول أن اللوحة (20 × 20 ، مع مراعاة عدد من الحقول خارج اللوحة) تتكون من طبقتين. تمتلئ الطبقة العليا بالكامل بأشكال غير مرئية تتحكم في الحركة. إن حركة الأحجار التي تشكل "أنماط" اللاعبين هي مجرد آثار جانبية لهذه التحركات. لسوء الحظ ، لم أتمكن بعد من تطوير روبوت لهذه اللعبة.


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

انا ذاهب في اجازة ...

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


All Articles