-
شما باید کد هوش مصنوعی خود را در توابع
move
وget_starting_node
که با کامنت# write your code here
مشخص شدهاند پیادهسازی کنید. دقت کنید که نام این توابع در کلاینتها ممکن است کمی فرق بکند. -
شما میتوانید کد کلاینت داده شده را تغییر دهید، به آن فایل اضافه کنید یا از آن فایل حذف کنید، به شرط آنکه تغییرات داده شده در کامپایل و اجرای کلاینت و ارتباط آن با سرور اختلالی ایجاد نکند. در مورد هر کلاینت نکاتی ذکر شده که به آنها نیز باید توجه شود. همچنین باید تغییرات احتمالی فایلهای دیگر کلاینت، یعنی فایلهایی غیر از فایلی که در آن کد میزنید را در نظر بگیرید.
-
شما میتوانید برای به روز بودن کلاینتها یا سرور خود به آخرین نسخه منتشر شده در repository مسابقه مراجعه کنید.
-
نکتهی قابل توجه در مورد کلاینت، این است که برای هر کدام از نیروها، چه دزدها و چه پلیسها، یک بار به طور جداگانه کد کلاینت اجرا میشود. در نتیجه نیروها حافظهی مشترکی با یکدیگر ندارند و تنها راه ارتباطی آنها از طریق چت باکس میباشد (توضیحات چتباکس را در مستند بازی بخوانید).
کلاینتهای جاوا، برای اجرا توسط سرور، باید به فایل jar تبدیل شوند. برای ساخت فایل jar کلاینت جاوا، باید از Intellij استفاده کنید.
- در Intellij، زمانی که کلاینت را به عنوان پروژه maven باز میکنید، مانند تصویر زیر از قسمت
maven -> Lifecycle
گزینهcompile
را انتخاب کنید تا کدهای ارتباط با سرور تولید شوند. اجرای این دستور برای بار اول نیاز به اینترنت دارد و کمی طول میکشد.
- حال از قسمت
project -> target -> generated-sources -> protobuf
بر روی دو پوشهgrpc-java
وjava
کلیک راست کنید و گزینهMark Directory as -> Generated Source Root
را انتخاب کنید. دقت کنید که برای هر دو این پوشهها این کار را انجام دهید.
- در آخر از قسمت
maven -> Lifecycle
گزینهpackage
را انتخاب کنید تا فایل.jar
شما در پوشهtarget
ایجاد شود.
هر بار که تغییری در کد کلاینت داده شد، برای اجرا باید یک فایل jar تازه ساختهشود.
با استفاده از داکر بدون نیاز به نصب دیپندنسیها بر روی سیستم عامل خودتان، میتوانید با دستور زیر کلاینت جاوا را بیلد کنید. دقت کنید که وقتی اولین بار این دستور اجرا میشود یک ایمیج 300 مگی دانلود میکند.
docker run --rm -v <path to your source code>:/src -it parsa2820/aic22-client-java-build
توجه:به جای <path to source code>
آدرس کد خودتان (پوشهای که فایل pom.xml
در آن قرار دارد) را قرار دهید.
برای ارسال کد کلاینت جاوا، ابتدا آن را مطابق آموزش بالا تبدیل به jar کنید، سپس فایل jar را zip کرده و از قسمت ارسال کد بفرستید.
برای اجرای کلاینتهای پایتون، باید کدها و تمامی dependency ها در یک پکیج تجمیع شود (Binary). این کار با ابزار Pyinstaller به راحتی امکانپذیر است. برای نصب این پکیج، میتوانید از دستور pip install pyinstaller استفاده کنید. اگر pip را نصب ندارید، طریقهی نصب آن روی سیستمعاملهای مختلف، از لینکهای زیر مشاهده کنید:
پس از نصب pip و سپس pyinstaller، باید کد زیر را با آدرس درست Client.py اجرا کنید.
pyinstaller --onefile /path/to/Client.py
پس از آن، دو فولدر dist و build و یک فایل Client.spec در محل کامند، ساخته خواهد شد. شما باید آدرس dist/Client را که یک فایل باینری قابل اجراست، به سرور بدهید.
دقت کنید که پس از هر بار تغییر در کد، پوشه های build و dist را پاک کنید و مجددا با PyInstaller بیلد بگیرید.
در کلاینت پایتون، شما میتوانید از کتابخانههای زیر استفاده کنید:
numpy==1.23.0
pandas==1.4.3
scikit-learn==1.1.1
scipy==1.8.1
torch==1.12.0
توجه کنید که اگر کتابخانهی دیگیری را استفاده کرده باشید، بازی شما دچار مشکل میشود.
با استفاده از داکر بدون نیاز به نصب دیپندنسیها بر روی سیستم عامل خودتان، میتوانید با دستور زیر کلاینت پایتون را بیلد کنید. دقت کنید که وقتی اولین بار این دستور اجرا میشود یک ایمیج ۱ گیگی دانلود میکند.
docker run --rm -v <path to your source code>:/src -it parsa2820/aic22-client-python-build
توجه:به جای <path to source code>
آدرس کد خودتان (پوشهای که فایل requirments.txt
در آن قرار دارد) را قرار دهید.
برای ارسال کد پایتون خود، دایرکتوری پروژه را zip کنید و در قسمت ارسال کد آپلود کنید. به صورتی که زمانی که وارد پوشهی آنزیپ شده میشویم، فولدر src در آنجا باشد.
توجه:راه پیشنهادی تیم فنی برای بیلد کلاینت سیپیپی استفاده از داکر است.
برای دریافت و اجرای کلاینت، دستورات زیر را اجرا کنید.
cd path/to/working/directory
git clone --depth=1 https://github.com/SharifAIChallenge/AIC22-Client-Cpp
cd AIC21-Client-Cpp
./build.sh
البته بیلد کردن کلاینت سیپیپی نیاز به نصب دیپندنسیهایی دارد که دستورات نصب آنها در ریپو کلاینت سیپیپی موجود است.
برای اجرای بیلد کردن کلاینت روی سیستمعامل ویندوز، باید از wsl استفاده کنید. برای نصب wsl از داکیومنت رسمی ماکروسافت استفاده کنید. با نصب این ابزار شما امکان استفاده از ترمینال لینوکس در ویندوز خود را پیدا میکنید و میتوانید بقیه مراحل را مطابق بیلد لینوکس پیش بروید.
بعد از هر تغییر در فایلها، فقط باید دستور make را بزنید. اگر یک فایل جدید به پروژه اضافه یا فایلی را از پروژه حذف کردید، ابتدا دستور cmake ..
و سپس دستور make
را اجرا کنید.
با استفاده از داکر بدون نیاز به نصب دیپندنسیها بر روی سیستم عامل خودتان، میتوانید با دستور زیر کلاینت سیپیپی را بیلد کنید. دقت کنید که وقتی اولین بار این دستور اجرا میشود یک ایمیج ۱ گیگی دانلود میکند.
docker run --rm -v <path to your source code>:/src -it parsa2820/aic22-client-cpp-build
توجه:به جای <path to source code>
آدرس کد خودتان (پوشهای که فایل build.sh
در آن قرار دارد) را قرار دهید.
برای ارسال کد، کل پوشهی پروژهی خود را zip و از قسمت ارسال کد، آپلود کنید.
برای اجرای سرور، باید از java 16 به بالا استفاده کنید.
سرور برای اجرا شدن نیاز به فایل map.yml دارد. این فایل شامل اطلاعات agentها و دیگر تنظیمات بازی شامل نقشه بازی به صورت گراف، turnها و ... است. شما به عنوان شرکتکننده نیاز ندارید محتوای این فایل را بفهمید یا تغییر دهید.
ابتدا آخرین نسخه ریلیز سرور را از اینجا دانلود کنید (فایل hideandseek-x.x.x.jar).
فایل map.yml را از ریپوی گیم دریافت کنید در کنار سرور در پوشه resources قرار دهید.
سپس سرور را به این شکل اجرا کنید:
java -jar server.jar --first-team="<path to first team code>" --second-team="<path to second team code>" "<path to map.yml file>"
دقت کنید اگر میخواهید بعدا لاگ تولید شده را در محیط گرافیکی مشاهده کنید، باید پارامتر دیگری که مسیر فایل map.json است را نیز به دستور اجرای سرور اضافه کنید. این فایل نیز در همان مخزن بازی موجود است. به عبارت دیگر دستور اجرای سرور به صورت زیر میشود.
java -jar server.jar --first-team="<path to first team code>" --second-team="<path to second team code>" "<path to map.yml file>" "<path to map.json file>"
این بخش interface ای هست که بین تمام کلاینت ها و سرور یکسان هست. در این بخش تمام کلاسها و متد هایی که برای ارتباط با سرور وجود دارد نوشته شده است. Message ها همون کلاسهایی هستن که به صورت ابجکت بین سرور و کلاینت رد و بدل میشود به عنوان مثال
message MoveCommand{
string token = 1;
int32 toNodeId = 2;
}
این message درواقع مانند کلاسی هست که دو فیلد token از تایپ string و toNodeId از تایپ int هست اعدادی که جلوی این فیلدها نوشته شده است اهمیت خاصی ندارد و بیشتر مربوط به ارتباط بین این فیلد ها در سرور و کلاینت ها است بنابراین نیازی به توضیح ندارد.
در اینجا Enum که مانند enum در زبانهای برنامه نویسی است و صرفاً یک داده ثابت است Service که مانند اینترفیس فقط متد ها به همراه ورودی و خروجی آنها است که این متد ها درواقع راه ارتباطی سرور و کلاینت میباشد.
در این proto چهار متد وجود دارد DeclareReadiness , Watch , Move و SendMessage که متد Move برای حرکت کردن متد DeclareReadiness برای جوین شدن به بازی و SendMessage برای فرستادن پیام استفاده میشود و در آخر متد Watch که درواقع با استفاده از این متد کلاینت استریمی از اتفاقاتی که در سرور رخ میده را دریافت میکند و میتواند نسبت به آنها واکنشی نشون دهد.
این متدهای بالا ورودی ها و خروجی هایی از جنس message دارند که در همون فایل proto قرار دارد در اینجا مهمترین message را توضیح میدهیم به اسم gameview این message درواقع خروجی متد watch است که تمام بازی را لحظهای نشان میدهد.
message GameView {
GameStatus status = 1;
GameResult result = 2;
Turn turn = 3;
GameConfig config = 4;
Agent viewer = 5;
double balance = 6;
repeated Agent visible_agents = 7;
repeated Chat chatBox = 8;
}
- فیلد GameStatus: اینامی هست که وضعیت بازی را مشخص میکند که شامل Pending یعنی هنوز بازی شروع نشده ONGOING که در حال اجرای بازی و FINISHED که پایان بازی است را نشان میدهد
- فیلد Result: اینامی است که وضعیت برد و باخت بازی را مشخص میکند
- فیلد Turn: مسجی است که نوع turn را در هر لحظه مشخص میکند یعنی (نوبت پلیس یا دزد) و شماره ی Turn را مشخص میکند.
- فیلد config: درواقع اطلاعات شرایط و قوانین بازی را نشان میدهد مانند حداکثر تعداد turn ها و … و config تماماً ثابت است و در طول بازی تغییری نمیکند.
- فیلد View: که در واقعاً خود کلاینت را نشان میدهد و شامل id, team ,type , node_id , is_dead است که type میتواند دزد یا پلیس باشد، team که میتواند تیم ۱ یا ۲ باشد ، node_id که شماره خانهای است که در آن قرار دارد و در آخر is_dead که نشان میدهد آیا هنوز زنده است یا دستگیر شده است.
- فیلد Balance: پولی است که کلاینت در هر لحظه دارد و visible_agent ارایه ای از agent ها یا بازیکنانی است که در هر لحظه از بازی برای این کلاینت خاص قابل دیدن است و در نهایت chatBox که ارایه ای از chat های قابل خواندن برای این کلاینت خاص در هر لحظه است.
این بخش شامل یک فایل yml به است application.yml است که کانفیگ کلاینت قرار دارد در این بخش اول آدرس و پورت سرور برای کانکت شدن به آن نیاز است دوم token کلاینت است که با استفاده از این token خودش را به سرور معرفی میکند و درصورتی که token در سرور وجود داشته باشد سرور اجازه ی بازی به این کلاینت میدهد.
این بخش که مربوط به شرکت کنندگان بازی میشود و شامل ۳ بخش اصلی میباشد اولین آن phone است که یک ابجکتی است که دارای یک متد به اسم sendMessage است این متد وظیفه ی فرستادن پیام را دارد و شرکت کنندگان میتوانند با استفاده از این ابجکت هر جایی که خواستند پیام خودشان را ارسال کنند.
بخش دوم آن متد Move است که دو متد وجود دارد یکی برای دزدها یکی برای پلیس ها ورودی این متد یک GameView است که در بالا درباره ی آن صحبت کردیم. این GameView شامل تمام دیتای بازی تا آن لحظه میباشد و در این متد باید با توجه به view آمده از سمت سرور یک int برگرداند شود که این int درواقع id خانهای است که میخواهیم به آن رویم.
بخش سوم متد getStartingNode است که این متد برای پلیس ها استفادهای ندارد و اگر هم وجود داشته باشد خروجی این متد برای پلیس در نظر گرفته نمیشود. اما برای دزد ها در این متد با استفاده از view اول در ابتدای بازی دزد ها نسبت به اطلاعات بازی و مپ بازی باید تصمیم بگیرند که از کدام خانه شروع به حرکت کنند. ورودی و خروجی این متدهم عیناً مانند متد Move است. پر کردن بدنه ی این متد ها بر عهده ی شرکت کنندگان است.
در این بخش درواقع Main برنامه میشود و متد اصلی آن ClientHandler میباشد که در این متد ابتدا به سرور وصل شده و از طریق message Watch از سرور GameView ها را دریافت میکنیم و بسته به این view ها یکی از متد هایی که شرکت کنندگان نوشتهاند را صدا میزنیم به عنوان مثال در turn اول با فرستادن declearReadiness به سرور خودمون رو معرفی میکنیم و در turn های بعدی move را صدا میزنیم.
تماشای بازیها به صورت گرافیکی نیز امکانپذیر است. بعد از اجرای سرور که پیشتر مراحل آن توضیح داده شد، میتوانید با اجرای رابط گرافیکی بازی و ایمپورت کردن فایل log.json که سرور بعد از اجرای بازی آنرا تولید میکند، اتفاقات بازی را به صورت گرافیکی مشاهده کنید.
پس از unzip کردن فایل گرافیک با توجه به سیستمعاملتان، با کلیک کردن بر روی فایل AIC_Graphic_Linux.x86_64 یا AIC22-Graphic.exe ی برنامه گرافیک بازی را باز کنید و با کلیک روی دکمهی Choose Game File، فایل server.log تولید شده توسط سرور را به آن بدهید.
پس از آن میتوانید بازی را به صورت گرافیکی مشاهده کنید.
توجه کنید که روی سیستمعاملهای unix based، ابتدا باید با اجرای دستورchmod +x /path/to/graphic/file
آن را قابل اجرا کنید.
در بالای رابط گرافیکی، نواریست که امکانات و همچنین اطلاعاتی از بازی در اختیار شما قرار میدهد. این اطلاعات و امکانات به شرح زیراند:
- کلید های جهت راست و چپ: رفتن به نوبت بعدی و قبلی
- کلید Space: شروع و توقف پخش خودکار
- کلید N: پخش حرکت بعدی
با استفاده از ماوس میتوان نقشه را جابهجا کرد. همچنین امکان zoom in و zoom out روی نقشه نیز وجود دارد.
مشکلات و ایرادات پیش آمده در گرافیک بازی را از طریق سایت با ارسال تیکت در قالب زیر، با ما در میان بگذارید:
- شرح مشکل پیشآمده
- تصویر یا تصاویری از مشکل پیشآمده
- لینک فایل server.log که در گرافیک در حال اجرای آن بوده(میتوانید برای مثال از گوگل درایو استفاده کنید)