مسئلهای که باید حل میکردم
هستهٔ مشترک اگر شروع به دانستن حکم و پاسور کنه، هر بازی بعدی هزینهٔ بیشتری داره. من میخواستم مسئلهٔ اعتبار حرکت، برنده و امتیاز را جدا قابل تعریف کنم.
پیادهسازی در نسخهٔ فعلی
IGameRuleSet سه قرارداد ValidateCardPlay، EvaluateRoundWinner و CalculateScore داره. هر کدوم زمینه و نتیجهٔ مخصوص خودش را میگیرد؛ CoreRuleSystem مسیر اجرای این قراردادهاست.
تصمیم و هزینهٔ طراحی
قرارداد کوچک اجازه میدهد منطق عمومی دربارهٔ قانون بازی فرض نکند. با این حال، همهٔ جریانهای پیچیدهٔ بازی الزاماً داخل همین سه تابع جا نمیشوند و سرویس تخصصی هم لازم هست.
مرزهای فعلی
در مستندات، RuleSet حکم به صورت مثال توسعه آمده هست. وجود آن مثال را با کلاس نهاییِ متصل به صحنه یکی نمیگیرم؛ اجرای حکم از سرویسهای تخصصی خودش هم استفاده میکنه.
محاسبهٔ امتیاز پیش از اعمال اون
در یک بازی کارتی، پرسیدن اینکه این حرکت مجاز هست با پرسیدن اینکه چه کسی امتیاز میگیرد یک کار نیست. IGameRuleSet این دو تصمیم را با Context و Result جدا بیان میکنه و CoreRuleSystem فراخوانی را به پیادهسازی انتخابشده میسپارد. این واسطه خودش قوانین خال یا برتری رتبه را اضافه نمیکنه. فایدهٔ این مرز برای دلو آن هست که بتوان دربارهٔ ورودی هر تصمیم حرف زد؛ هزینهاش نیز روشن هست: اگر Context اطلاعات ضروری یک بازی را نداشته باشد، قرارداد عمومی بهتنهایی برای مدل کردن تمام مراحل آن کافی نخواهد بود.
ApplyScore در CoreRuleSystem نشان میدهد محاسبه و تغییر وضعیت میتوانند جدا بمانند. نتیجهٔ null یا بدون تغییر نادیده گرفته میشود؛ سپس ScoreChanges مرور میشود و مقدار هر تغییر به Score بازیکن مربوط اضافه میشود. ورودیای که Player نداره نیز رد نمیشود، بلکه از آن عبور میشود. این رفتار برای خوانندهٔ کد مهم هست، چون گزارش محاسبهشده الزاماً با خطای سخت متوقف نمیشود. مصرفکنندهای که اعمال کامل همهٔ تغییرات را لازم داره، باید اعتبار نتیجه را پیش از ورود به این حلقه بررسی کنه.
این حلقه شناسهٔ عملیات یا فهرست نتایج قبلاً اعمالشده نداره. بنابراین اعمال دوبارهٔ یک نتیجهٔ دارای تغییر میتواند همان امتیاز را دوباره اضافه کنه؛ وجود کلاس RuleSystem به معنای جلوگیری خودکار از ثبت تکراری نیست. برای همین در تحلیل معماری، قرارداد عمومی را از سرویسهای تخصصی حکم جدا میخوانم. مثال RuleSet در مستند هسته مسیر توسعه را توضیح میدهد، اما وجود آن مثال ثابت نمیکنه همان کلاس در صحنهٔ فعلی اجرا میشود. ادعای اتصال واقعی باید با ارجاع صحنه و مسیر ساخت سرویس پشتیبانی بشه، نه فقط یک قطعهٔ آموزشی.
چیزی که از این مرحله یاد گرفتم
این بخش برای من تمرین مرزبندی بود. هسته امکانات میدهد و بازی تصمیم میگیرد؛ افزودن بازی تازه قرار نیست با تبدیل هسته به مجموعهای از شرطهای نام بازی انجام بشه.
مثال عملی قرارداد قوانین بازی
اگر بخواهی قرارداد قوانین بازی را در یک پروژهٔ کوچک بررسی کنی، بهتر است از یک موقعیت محدود شروع کنی. حکم و جوکر از کارت و دست مشترک استفاده میکنند، ولی حرکت مجاز هرکدام متفاوت است. ورودی را ثابت نگه دار و نتیجهٔ مورد انتظار را پیش از اجرای نسخه بنویس. این کار کمک میکند تفاوت میان رفتار منطقی و چیزی که صرفاً روی صفحه دیده میشود روشن بماند. سناریوی این بخش آموزشی است و ادعای نتیجهٔ واقعی یک آزمایش روی کاربران دلو ندارد.
خطای رایج و علت آن
قرار دادن شرط همهٔ بازیها در یک کلاس بزرگ، افزودن بازی تازه را پرخطا میکند. این خطا معمولاً وقتی پنهان میماند که فقط مسیر موفق و ظاهر نهایی را ببینیم. برای پیدا کردن علت، آخرین وضعیت درست را از نخستین وضعیت نادرست جدا کن و ببین تغییر دقیقاً در کدام مرز رخ داده است. بازاستفادهٔ داده الزاماً به معنای یکی بودن قوانین و شرط پایان نیست. اگر این تفاوت در قرارداد مشخص نباشد، اصلاح یک نشانه ممکن است همان مسئله را در بخش دیگری دوباره ایجاد کند.
چطور نتیجه را بررسی کنیم؟
هر قانون را با ورودی معتبر، حرکت ممنوع و وضعیت پایان خودش بررسی کن. اجرای یکباره برای نتیجهگیری کافی نیست؛ یک بار مسیر معمول و بار دیگر همان موقعیت را با ورودی مرزی یا تکرار اقدام بررسی کن. اگر نتیجه فرق دارد، ورودی و شرایط اجرا را همراه خروجی نگه دار تا مقایسه قابل بازسازی باشد. جدول زیر خلاصهٔ مشخصات همین سناریو است و برای ثبت نتیجهٔ بررسی به کار میآید.
| بخش بررسی | آنچه باید ثبت شود |
|---|---|
| موقعیت آزمایشی | حکم و جوکر از کارت و دست مشترک استفاده میکنند، ولی حرکت مجاز هرکدام متفاوت است. |
| ریسک اصلی | قرار دادن شرط همهٔ بازیها در یک کلاس بزرگ، افزودن بازی تازه را پرخطا میکند. |
| روش بررسی | هر قانون را با ورودی معتبر، حرکت ممنوع و وضعیت پایان خودش بررسی کن. |
| مرز نتیجهگیری | بازاستفادهٔ داده الزاماً به معنای یکی بودن قوانین و شرط پایان نیست. |
پرسشهای کاربردی دربارهٔ قرارداد قوانین بازی
از کجا شروع کنم؟
از همان موقعیت محدود این مطلب شروع کن: حکم و جوکر از کارت و دست مشترک استفاده میکنند، ولی حرکت مجاز هرکدام متفاوت است. ابتدا نتیجهٔ مورد انتظار را مشخص کن و بعد سراغ پیادهسازی یا ابزار برو. وقتی مسیر پایه قابل توضیح و بررسی شد، میتوان حالتهای بیشتری اضافه کرد. ساخت همهٔ حالتها از ابتدا، فهم علت خطا را سختتر میکند.
چه زمانی میتوانم بگویم این بخش درست کار میکند؟
زمانی که رفتار در موقعیت تعریفشده با قرارداد سازگار باشد و محدودیتهای آن روشن بمانند. هر قانون را با ورودی معتبر، حرکت ممنوع و وضعیت پایان خودش بررسی کن. موفقیت در این آزمون دربارهٔ همان سناریو شاهد میدهد؛ از آن نمیتوان بدون بررسی دربارهٔ همهٔ دستگاهها، همهٔ قوانین محلی یا همهٔ حجمهای داده نتیجه گرفت. بازاستفادهٔ داده الزاماً به معنای یکی بودن قوانین و شرط پایان نیست.
برای ادامهٔ همین موضوع، هستهٔ مشترک دلو؛ یک میز برای چند بازی و بازی دلو را ببین. زمینهٔ ساخت این پروژهها و معرفی سازنده در صفحهٔ کیان پاک نعمت آمده است.




