স্ক্রিপ্টবট ওয়ার্জ!


14

স্ক্রিপ্টবট ওয়ার্জ!


ফলাফলগুলি রয়েছে এবং আসসিন আমাদের চ্যাম্পিয়ন, 3 ম্যাচের 2 টি জিতেছে! যারা তাদের স্ক্রিপ্টবট জমা দিয়েছেন তাদের সবাইকে ধন্যবাদ! BestOpportunityBot এর জন্য শিংগুলির জন্য বিশেষ ধন্যবাদ যা চমৎকার পথ প্রদর্শন করেছে এবং সমস্ত ক্রিয়াকলাপের বিকল্প ব্যবহার করে।

মানচিত্র 1

প্রথম দিকে বেস্টঅপার্টিউটিবোটকে বের করে দিয়েছিল আসসিন, এবং ম্যাচের বাকি অংশটি বেশ বিরক্তিকর ছিল। এখানে প্লে-বাই-প্লে বিস্তারিত।

  1. অ্যাসাসিন: 10 এইচপি, 10 ড্যামেজ ডিল্ট, 3 ক্ষয়ক্ষতি নেওয়া হয়েছে
  2. অ্যাভয়েডার ভি 3: 10 এইচপি, 0 ক্ষতির ডিল্ট, 0 ক্ষতি নেওয়া হয়েছে
  3. সমাপ্ত খাবার খাওয়াতে হবে: 10 এইচপি, 0 ক্ষতির ডিল্ট, 0 ক্ষতি নেওয়া হয়েছে
  4. বেস্টঅরপোর্টনিউবট: 0 এইচপি, 3 ড্যামেজ ডিল্ট, 10 ড্যামেজ নেওয়া হয়েছে

মানচিত্র 2

এই ম্যাচের সেরা কাজ বেস্টঅপার্পটিটিউবট করেছেন তবে শেষ পর্যন্ত তাকে বের করে নিতে সক্ষম হন আসসিন। এখানে প্লে-বাই-প্লে বিস্তারিত।

  1. হত্যাকারী: 2 এইচপি, 10 ক্ষতির ডিল্ট, 9 টি ক্ষতি হয়েছে
  2. বেস্টঅরপোর্টনিউবট: 0 এইচপি, 32 ড্যামেজ ডিল্ট, 10 ড্যামেজ নেওয়া হয়েছে
  3. অ্যাভয়েডার ভি 3: 0 এইচপি, 0 ড্যামেজ ডিল্ট, 12 ড্যামেজ নেওয়া হয়েছে
  4. সমাপ্ত খাবার খাওয়াতে হবে: 0 এইচপি, 0 ড্যামেজ ডিল্ট, 11 ড্যামেজ নেওয়া হয়েছে

মানচিত্র 3

সেরা ম্যাচটি এই ম্যাচে সবাইকে ফাঁদে ফেলে দিয়েছে Best খুব ঠান্ডা. এখানে প্লে-বাই-প্লে বিস্তারিত।

  1. বেস্টঅরপোর্টনিউবট: 10 এইচপি, 30 ড্যামেজ ডিল্ট, 0 ক্ষয়ক্ষতি নেওয়া হয়েছে
  2. হত্যাকারী: 0 এইচপি, 0 ক্ষতির ডিল্ট, 0 ক্ষতি নেওয়া হয়েছে
  3. সমাপ্ত খাবার খাওয়াতে হবে: 0 এইচপি, 0 ক্ষতির ডিল্ট, 0 ক্ষতি নেওয়া হয়েছে
  4. অ্যাভয়েডার ভি 3: 0 এইচপি, 0 ক্ষতির ডিল্ট, 0 ক্ষতি নেওয়া হয়েছে

আপনার উত্তরের জন্য ধন্যবাদ! যেহেতু এখানে মাত্র 4 স্ক্রিপ্টবট রয়েছে, তাই আমরা তিনটি ফ্রি-ফর ম্যাচের জন্য টুর্নামেন্টের পরিকল্পনাগুলি ত্যাগ করছি, নীচের প্রতিটি মানচিত্রে একটি করে। সর্বাধিক জয়ের রেকর্ডের সাথে স্ক্রিপ্টবট জিতেছে। টাই হওয়ার সময়, আমরা হঠাৎ মৃত্যুতে প্রবেশ করব যেখানে স্ক্রিপ্টবট যিনি টাইকে প্রথমে বিরতি দেয়।


আপনার কাজটি, যদি আপনি এটি গ্রহণ করা পছন্দ করেন তবে হ'ল একটি স্ক্রিপ্টবোট কোড করা যা একটি ASCII মানচিত্রটি অতিক্রম করতে এবং এর বিরোধীদের ধ্বংস করতে পারে। প্রতিটি যুদ্ধ একটি র্যান্ডম-স্টার্টিং-অর্ডার টার্ন-বেসড গেমের রূপ নেবে যেখানে প্রতিটি স্ক্রিপ্টবটকে পদক্ষেপ নিতে তাদের শক্তি পয়েন্টগুলি (ইপি) ব্যয় করার সুযোগ রয়েছে has গেমমাস্টার স্ক্রিপ্ট প্রতিটি স্ক্রিপ্টবট থেকে ইনপুট ফিড করবে এবং ব্যাখ্যা করবে।

পরিবেশ

প্রতিটি Scriptbot নিজস্ব ডিরেক্টরির মধ্যে অন্তর্ভুক্ত করা হয় যেখানে এটি থেকে পড়তে পারেন mapএবং stats/ ফাইল এবং লেখার পড়া dataফাইল। dataফাইলটি কোন ক্রমাগত তথ্য আপনি পক্ষে উপযোগী হতে পারে সঞ্চয় করতে ব্যবহার করা যাবে।

পরিসংখ্যান ফাইল

statsফাইল আপনার বিরোধীদের সম্পর্কে তথ্য রয়েছে এবং নিম্নরূপ ফর্ম্যাট করা হয়েছে। প্রতিটি খেলোয়াড় একটি পৃথক সারিতে প্রতিনিধিত্ব করা হয়। প্রথম কলামটি প্লেয়ার আইডি ( @মানে আপনি)। দ্বিতীয় কলামটি সেই খেলোয়াড়ের স্বাস্থ্য।

1,9HP
@,10HP
3,9HP
4,2HP

মানচিত্র ফাইল

mapফাইল ভালো কিছু চেহারা হতে পারে ...

####################
#   #          #   #
# 1 #          # 2 #
#                  #
###              ###
#                  #
#      #           #
#       #     !    #
#        #         #
#       !####      #
#      ####!       #
#         #        #
#    !     #       #
#           #      #
#                  #
###              ###
#                  #
# 3 #          # @ #
#   #          #   #
####################

... অথবা এটা...

######################################
#       # 1        #   @             #
#       #          #          #!     #
#       #          #          ####   #
#  #    #  #       #         !#!     #
#  #    #  #       #      #####      #
#  ###     #    ####    #         #  #
#          #    #!      ###       #  #
#  ######  #    #       #     #####  #
#  #!      #    ######  #        !#  #
#  ###     #            #         #  #
#  #    2  #            #   4     #  #
######################################

... অথবা এটা...

###################
###!!!!!!#!!!!!!###
##!             !##
#! 1     !     2 !#
#!       !       !#
#!               !#
#!               !#
#!      !!!      !#
## !!   !!!   !! ##
#!      !!!      !#
#!               !#
#!               !#
#!       !       !#
#! 3     !     @ !#
##!             !##
###!!!!!!#!!!!!!###
###################

... অথবা এটি সম্পূর্ণ আলাদা দেখায়। যেভাবেই হোক না কেন, ব্যবহৃত অক্ষরগুলি এবং তাদের অর্থ একই থাকবে:

  • # একটি প্রাচীর, দুর্গম এবং দুর্ভেদ্য।
  • 1, 2, 3... একটি নম্বর শত্রু খেলোয়াড় উপস্থাপন করে। এই সংখ্যাগুলি statsফাইলের প্লেয়ার আইডির সাথে মিলে যায় ।
  • !একটি ফাঁদ. স্ক্রিপ্টবটগুলি যারা এই অবস্থানগুলিতে চলে যায় অবিলম্বে মারা যাবে।
  • @ আপনার স্ক্রিপ্টবটের অবস্থান।
  • উন্মুক্ত স্থান যা আপনি চলাচল করতে মুক্ত।

গেমপ্লের

গেমমাস্টার স্ক্রিপ্ট স্ক্রিপ্টবটগুলিতে এলোমেলোভাবে অর্ডার দেবে। স্ক্রিপ্টবটগুলি তখনও জীবিত থাকাকালীন এই ক্রমে অনুরোধ করা হয়। স্ক্রিপ্টবটগুলিতে 10 টি হেলথ পয়েন্টস (এইচপি) রয়েছে এবং প্রতিটি পালা 10 এনার্জি পয়েন্টস (ইপি) দিয়ে শুরু হয়, যা তারা স্থানান্তর বা আক্রমণ করতে ব্যবহার করতে পারে। প্রতিটি পালা শুরু করার সময়, একটি স্ক্রিপ্টবট একটি এইচপির জন্য নিরাময় করবে, বা যদি ইতিমধ্যে 10 এইচপি-তে থাকে তবে একটি অতিরিক্ত ইসি দেওয়া হবে (এইভাবে চলমান সময়ে কার্যকর व्यवहार হতে পারে)।

যুদ্ধের শেষ হয় যখন কেবলমাত্র একটি স্ক্রিপ্টবট বেঁচে থাকে বা যখন 100 টি টার্নস পেরিয়ে যায়। যুদ্ধের শেষে যদি একাধিক স্ক্রিপ্টবট বেঁচে থাকে তবে নিম্নলিখিত স্থানের ভিত্তিতে তাদের স্থান নির্ধারণ করা হবে:

  1. বেশিরভাগ স্বাস্থ্য।
  2. সর্বাধিক ক্ষয়ক্ষতি
  3. সর্বাধিক ক্ষতি নেওয়া হয়েছে।

স্ক্রিপ্টবট ইনপুট

গেমমাস্টার যুদ্ধের মানচিত্রটি এমন কোনও ফাইলটিতে মুদ্রণ করবে mapযা স্ক্রিপ্টবোট থেকে পড়ার অ্যাক্সেস থাকবে। মানচিত্রটি যে কোনও রূপ নিতে পারে, তাই স্ক্রিপ্টবট এটি ব্যাখ্যা করতে সক্ষম হওয়া গুরুত্বপূর্ণ। আপনার স্ক্রিপ্টবট ইপি ইঙ্গিত করে এমন একটি পরামিতি সহ আহ্বান করা হবে। উদাহরণ স্বরূপ...

:> example_scriptbot.py 3

স্ক্রিপ্টবটটি তার সমস্ত ইপি বা সর্বোচ্চ 10 বার ব্যয় না করা পর্যন্ত ডাকা হবে । প্রতিটি অনুরোধের আগে মানচিত্র এবং পরিসংখ্যান ফাইল আপডেট করা হয়।

স্ক্রিপ্টবট আউটপুট

স্ক্রিপ্টবটগুলি তাদের ক্রিয়াগুলিকে স্টাউটে আউটপুট করে। সম্ভাব্য ক্রিয়াগুলির একটি তালিকা নিম্নরূপ:

  • MOVE <DIRECTION> <DISTANCE>

    প্রতি 1 ইসি খরচ হয় DISTANCEMOVEকমান্ড মানচিত্র চারপাশে আপনার Scriptbot চলে আসে। যদি কোনও প্রাচীর বা অন্য স্ক্রিপ্টবোটের মতো কিছু থাকে তবে গেমমাস্টার আপনার স্ক্রিপ্টবটকে যথাসম্ভব সরিয়ে ফেলবে। যদি DISTANCEস্ক্রিপ্টবোটের অবশিষ্ট ইপি বেশি দেওয়া হয়, গেমমাস্টার এর ইপি শেষ না হওয়া অবধি স্ক্রিপ্টবট সরিয়ে ফেলবে। DIRECTIONকোন কম্পাস দিক হতে পারে N, E, S, অথবা W

  • PUSH <DIRECTION> <DISTANCE>

    প্রতি 1 ইসি খরচ হয় DISTANCEPUSHকমান্ড অন্য Scriptbot সরাতে একটি Scriptbot দেয়। কমান্ড জারি করা স্ক্রিপ্টবটটি সরাসরি স্ক্রিপ্টবটকে ধাক্কা দেওয়ার সাথে পাশেই থাকতে হবে। উভয় স্ক্রিপ্টবটগুলি নির্দেশিত দিকটিতে সরে যাবে যদি স্ক্রিপ্টবটকে ধাক্কা দিয়ে কোনও জিনিস আটকাচ্ছে না। DIRECTIONএবং কমান্ড DISTANCEহিসাবে একই MOVE

  • ATTACK <DIRECTION>

    একটি ইপি খরচ করে। ATTACKকমান্ডের Scriptbot প্রয়োজন এবং দিক নিদিষ্ট কোনো Scriptbot 1 ক্ষতি পুলিশ সরাসরি পরবর্তী। কমান্ড DIRECTIONহিসাবে একই MOVE

  • PASS

    আপনার পালা শেষ।

সমর্থিত ভাষা

এটি আমার পক্ষে যুক্তিযুক্ত রাখার জন্য, আমি নিম্নলিখিত ভাষাগুলি গ্রহণ করব:

  • জাভা
  • node.js
  • পাইথন
  • পিএইচপি

আপনি সাধারণত লাইব্রেরিগুলিতে সীমাবদ্ধ যা আপনার ভাষাগুলির বাইরে সাধারণত বাক্সের বাইরে প্যাক করা হয়। আপনার কোডটি কাজ করতে আমাকে অস্পষ্ট লাইব্রেরিগুলি সনাক্ত করতে দয়া করে না।

জমা দেওয়া এবং বিচারক

নীচে আপনার স্ক্রিপ্টবোট উত্স কোড পোস্ট করুন এবং এটি একটি দুর্দান্ত নাম দিন! আপনার ব্যবহৃত ভাষার সংস্করণটিও তালিকাভুক্ত করুন। সমস্ত স্ক্রিপ্টবটগুলি টমফুলারির জন্য পর্যালোচনা করা হবে তাই দয়া করে ভাল মন্তব্য করুন এবং আপনার কোডটি অবলম্বন করবেন না।

আপনি একাধিক এন্ট্রি জমা দিতে পারেন, তবে দয়া করে এগুলিকে সম্পূর্ণ অনন্য এন্ট্রি করুন এবং একই প্রবেশের সংস্করণ নয়। উদাহরণস্বরূপ, আপনি একটি জের্গ রাশ বট এবং একটি গরিলা ওয়ারফেয়ার বট কোড করতে পারেন। সেটা ঠিক আছে. জের্গ রাশ ভি 1, জের্গ রাশ ভি 2 ইত্যাদি পোস্ট করবেন না

7th ই নভেম্বর আমি সমস্ত উত্তর সংগ্রহ করব এবং যা প্রাথমিক পর্যালোচনা পাস করেছে তাদের একটি টুর্নামেন্ট বন্ধনীতে যুক্ত করা হবে। চ্যাম্পিয়ন গৃহীত উত্তর পায়। আদর্শ বন্ধনী নীচে দেখানো হয়েছে। যেহেতু সম্ভবত সঠিকভাবে 16 টি এন্ট্রি থাকবে না, কিছু বন্ধনী কেবল তিন বা এমনকি দুটি বট হতে পারে। আমি যতটা সম্ভব বন্ধনী বন্ধ করার চেষ্টা করব। যে কোনও প্রয়োজনীয় পক্ষপাতিত্ব (উদাহরণস্বরূপ, একটি বাই সপ্তাহের প্রয়োজন হলে ইভেন্ট) প্রথমে জমা দেওয়া বটগুলিতে দেওয়া হবে।

BOT01_
BOT02_|
BOT03_|____
BOT04_|    |
           |
BOT05_     |
BOT06_|___ |
BOT07_|  | |
BOT08_|  | |_BOT ?_
         |___BOT ?_|
BOT09_    ___BOT ?_|___CHAMPION!
BOT10_|  |  _BOT ?_|
BOT11_|__| |
BOT12_|    |
           |
BOT13_     |
BOT14_|____|
BOT15_|
BOT16_|

Q & A-

আমি নিশ্চিত যে আমি কিছু বিবরণ মিস করেছি, তাই নির্দ্বিধায় প্রশ্ন জিজ্ঞাসা করুন!

আমরা কি বিশ্বাস করতে পারি যে কোনও মানচিত্রের ফাইল সর্বদা # চিহ্ন দ্বারা বেষ্টিত থাকে? যদি তা না হয় তবে ঘটনাটি কী ঘটে যখন বট মানচিত্রটি চালিয়ে যাওয়ার চেষ্টা করে? - ব্রেইন স্টিল

হ্যাঁ মানচিত্রটি সর্বদা # দ্বারা সীমাবদ্ধ থাকবে এবং আপনার স্ক্রিপ্টবট এই সীমার অভ্যন্তরে শুরু হবে।

যদি পুশ কমান্ডে উল্লিখিত দিকটিতে কোনও বট উপস্থিত না থাকে, কমান্ডটি কীভাবে কাজ করবে? - ব্রেইন স্টিল

গেমমাস্টার কিছুই করবে না, শূন্য ইপি ব্যয় করবে এবং স্ক্রিপ্টবট আবার কল হবে।

অব্যবহৃত ইপি জমে? - মলমূত্র

নং। প্রতিটি স্ক্রিপ্টবট 10 ইপি দিয়ে গোল / পালা শুরু করবে। যে কোনও ইপি ব্যয় করা হয়নি তা নষ্ট হয়ে যাবে।

আমি মনে করি এটি পেয়েছি, তবে কেবল স্পষ্ট করে বলার জন্য: বট A এবং B সহ, ইভেন্টগুলির ক্রম হ'ল A @ 10EP-> MOVE MAP_UPDATE B @ 10EP-> পুশ এমএপ_আপডিকে একটি @ 9EP-> আক্রমণ ম্যাপ_আপডেট বি @ 9EP-> আক্রমণ ... অন্য কথায়, সমস্ত ক্রিয়াকলাপ কি একটি নিয়ামক-বট ক্যোয়ারী লুপ পারমাণবিক? যদি তাই হয় তবে লুপ কেন? সমস্ত ক্রিয়া সম্পন্ন করার সাথে একটি ফাইল কেন ফেরত দেবে না? অন্যথায় বটগুলি মাল্টি-অ্যাকশন সিকোয়েন্সগুলি ট্র্যাক রাখতে তাদের নিজস্ব রাষ্ট্র ফাইলগুলি লিখতে হবে। মানচিত্র / পরিসংখ্যান ফাইলটি প্রথম ক্রিয়া করার আগে কেবল বৈধ হবে। - কোটো

আপনার দ্বিতীয় উদাহরণটি নিকটে, তবে একেবারেই সঠিক নয়। একটি পালা চলাকালীন, স্ক্রিটবটটি বার বার তাদের ইপি ব্যয় না করা বা সর্বোচ্চ 11 বার বার বার ডাকা হবে। প্রতিটি অনুরোধের আগে মানচিত্র এবং পরিসংখ্যান ফাইল আপডেট করা হয়। কোনও বটটি অবৈধ আউটপুট দেয় ইভেন্টে লুপটি কার্যকর। গেমমাস্টার অবৈধ আউটপুট নিয়ে কাজ করবে এবং বটকে আবার যুক্ত করবে, বটকে তার ভুলটির জন্য সংশোধন করার সুযোগ দেবে।

আপনি পরীক্ষার জন্য গেমমাস্টার স্ক্রিপ্টটি প্রকাশ করবেন? - আইচবিনকিনবাউম

গেমমাস্টার স্ক্রিপ্টটি প্রকাশিত হবে না। আমি আপনার বটের আচরণ পরীক্ষা করার জন্য একটি মানচিত্র এবং পরিসংখ্যান ফাইল তৈরি করতে উত্সাহিত করব।

রোবটা যদি রোবটবিকে ফাঁদে ফেলে, তবে রোবোটাকে কি "ড্যামেজ ডিল" পয়েন্ট দেওয়া হয় তা রোবটবির বর্তমান স্বাস্থ্যের সমান? - মাইক সুইনি

হ্যাঁ, এটি একটি ভাল ধারণা। কোনও বট যে ফাঁদে ফেলে দেয় তার স্বাস্থ্যের সমান ক্ষতি পয়েন্ট দেওয়া হবে।


আমরা কি বিশ্বাস করতে পারি যে কোনও mapফাইল সর্বদা #প্রতীক দ্বারা বেষ্টিত থাকে ? যদি তা না হয় তবে ঘটনাটি কী ঘটে যখন বট মানচিত্রটি চালিয়ে যাওয়ার চেষ্টা করে?
ব্রেনস্টিল

@ ব্রেনস্টিল হ্যাঁ মানচিত্রটি সর্বদা সীমাবদ্ধ #থাকবে এবং আপনার স্ক্রিপ্টবট এই সীমার অভ্যন্তরে শুরু হবে।
রিপ লীব

3
আপনি যদি নিশ্চিত হন যে আপনি কিছু মিস করেছেন তবে এটি স্যান্ডবক্সে পোস্ট করবেন না কেন ?
মার্টিন ইন্ডার

2
@ মার্টিনবাটনার আমি এটি পুরোপুরিভাবে ভেবে দেখেছি। আমি কেবল বন্ধুত্বপূর্ণ হওয়ার চেষ্টা করেছিলাম এবং পরিষ্কার করে দিয়েছিলাম যে প্রশ্নগুলি স্বাগত।
রিপ লীব

1
রোবটা যদি রোবটবিকে ফাঁদে ফেলে, তবে রোবোটাকে কি "ড্যামেজ ডিল" পয়েন্ট দেওয়া হয় তা রোবটবির বর্তমান স্বাস্থ্যের সমান?
লজিক নাইট

উত্তর:


1

হত্যাকারী (জাভা 1.7)

যখনই সম্ভব শত্রুদের হত্যা করার চেষ্টা করে, অন্যথায় একটি ক্ষেত্র সরিয়ে দেয়। শত্রুর পথ খুঁজে পাওয়া এটি বেশ ভাল, তবে অন্যান্য বট থেকে লুকানোর জন্য কিছুই করেন না।

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Assassin {
    private final Path dataPath = Paths.get("data");
    private final Path mapPath = Paths.get("map");
    private final Path statsPath = Paths.get("stats");
    private final List<Player> players = new ArrayList<>();
    private final int energy;
    private Map map = null;

    public Assassin(int energy) {
        this.energy = energy;
    }

    private void doSomething() {
        if (dataFileEmpty()) {
            calculateTurn();
        }
        printStoredOutput();
    }

    private boolean dataFileEmpty() {
        try {
            return !Files.exists(dataPath) || Files.size(dataPath)  == 0;
        } catch (IOException e) {
            return true;
        }
    }

    private void printStoredOutput() {
        try {
            List<String> lines = Files.readAllLines(dataPath, StandardCharsets.UTF_8);
            //print first line
            System.out.println(lines.get(0));           
            //delete first line
            lines.remove(0);
            Files.write(dataPath, lines, StandardCharsets.UTF_8);
        } catch (IOException e) {
            System.out.println("PASS");
        }
    }

    private void calculateTurn() {
        try {
            readStats();
            readMap();
            if (!tryKill())  {
                sneakCloser();
            }
        } catch (IOException e) {}
    }

    private void readStats() throws IOException{
        List<String> stats = Files.readAllLines(statsPath, StandardCharsets.UTF_8);
        for (String stat : stats) {
            String[] infos = stat.split(",");
            int hp = Integer.parseInt(infos[1].replace("HP", ""));
            players.add(new Player(stat.charAt(0), hp));
        }
    }

    private void readMap() throws IOException{
        List<String> lines = Files.readAllLines(mapPath, StandardCharsets.UTF_8);
        Field[][] fields = new Field[lines.size()][lines.get(0).length()];
        for (int row = 0; row < lines.size(); row++) {
            String line = lines.get(row);
            for (int col = 0; col < line.length(); col++) {
                fields[row][col] = new Field(line.charAt(col), row, col);
            }
        }
        map = new Map(fields);
    }

    private boolean tryKill() {     
        Field me = map.getMyField();
        for (Field field : map.getEnemyFields()) {
            for (Field surrField : map.surroundingFields(field)) { 
                List<Direction> dirs = map.path(me, surrField);
                if (dirs != null) {
                    for (Player player : players) {
                        //can kill this player
                        int remainderEnergy = energy - dirs.size() - player.hp;
                        if (player.id == field.content && remainderEnergy >= 0) {
                            //save future moves
                            List<String> commands = new ArrayList<>();
                            for (Direction dir : dirs) {
                                commands.add("MOVE " + dir + " 1");
                            }
                            //attacking direction
                            Direction attDir = surrField.dirsTo(field).get(0);
                            for (int i = 0; i < player.hp; i++) {
                                commands.add("ATTACK " + attDir);                               
                            }
                            if (remainderEnergy > 0) {
                                commands.add("PASS");
                            }
                            try {
                                Files.write(dataPath, commands, StandardCharsets.UTF_8);
                            } catch (IOException e) {}
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private void sneakCloser() {        
        Field me = map.getMyField();
        for (Direction dir : Direction.values()) {
            if (!map.move(me, dir).blocked()) {
                List<String> commands = new ArrayList<>();
                commands.add("MOVE " + dir + " 1");
                commands.add("PASS");
                try {
                    Files.write(dataPath, commands, StandardCharsets.UTF_8);
                } catch (IOException e) {}
                return;
            }
        }
    }

    public static void main(String[] args) {
        try {
            new Assassin(Integer.parseInt(args[0])).doSomething();
        } catch (Exception e) {
            System.out.println("PASS");
        }
    }

    class Map {
        private Field[][] fields;

        public Map(Field[][] fields) {
            this.fields = fields;
        }

        public Field getMyField() {
            for (Field[] rows : fields) {
                for (Field field : rows) {
                    if (field.isMyPos()) {
                        return field;
                    }
                }
            }
            return null; //should never happen
        }   

        public List<Field> getEnemyFields() {
            List<Field> enemyFields = new ArrayList<>();
            for (Field[] rows : fields) {
                for (Field field : rows) {
                    if (field.hasEnemy()) {
                        enemyFields.add(field);
                    }
                }
            }
            return enemyFields;
        }

        public List<Field> surroundingFields(Field field) {
            List<Field> surrFields = new ArrayList<>();
            for (Direction dir : Direction.values()) {
                surrFields.add(move(field, dir));
            }
            return surrFields;
        }

        public Field move(Field field, Direction dir) {
            return fields[field.row + dir.rowOffset][field.col + dir.colOffset];
        }

        public List<Direction> path(Field from, Field to) {
            List<Direction> dirs = new ArrayList<>();
            Field lastField = from;
            boolean changed = false;

            for (int i = 0; i < energy && lastField != to; i++) {
                List<Direction> possibleDirs = lastField.dirsTo(to);
                changed = false;
                for (Direction dir : possibleDirs) {
                    Field nextField = move(lastField, dir);
                    if (!nextField.blocked()) {
                        lastField = nextField;
                        changed = true;
                        dirs.add(dir);
                        break;
                    }
                }
                if (!changed) {
                    return null; //not possible
                }
            }
            if (lastField != to) {
                return null; //not enough energy
            }           
            return dirs;
        }
    }

    class Field {
        private char content;
        private int row;
        private int col;

        public Field(char content, int row, int col) {
            this.content = content;
            this.row = row;
            this.col = col;
        }

        public boolean hasEnemy() {
            return content == '1' || content == '2' || content == '3' || content == '4';
        }

        public List<Direction> dirsTo(Field field) {
            List<Direction> dirs = new ArrayList<>();
            int distance = Math.abs(row - field.row) + Math.abs(col - field.col);

            for (Direction dir : Direction.values()) {
                int dirDistance = Math.abs(row - field.row + dir.rowOffset) + 
                        Math.abs(col - field.col + dir.colOffset);
                if (dirDistance < distance) {
                    dirs.add(dir);
                }
            }
            if (dirs.size() == 1) { //add near directions
                for (Direction dir : dirs.get(0).nearDirections()) {
                    dirs.add(dir);
                }
            }
            return dirs;
        }

        public boolean isMyPos() {
            return content == '@';
        }

        public boolean blocked() {
            return content != ' ';
        }
    }

    class Player {
        private char id;
        private int hp;

        public Player(char id, int hp) {
            this.id = id;
            this.hp = hp;
        }
    }

    enum Direction {
        N(-1, 0),S(1, 0),E(0, 1),W(0, -1);

        private final int rowOffset;
        private final int colOffset;

        Direction(int rowOffset, int colOffset) {
            this.rowOffset = rowOffset;
            this.colOffset = colOffset;
        }

        public Direction[] nearDirections() {
            Direction[] dirs = new Direction[2];
            for (int i = 0; i < Direction.values().length; i++) {
                Direction currentDir = Direction.values()[i];
                if (Math.abs(currentDir.rowOffset) != Math.abs(this.rowOffset)) {
                    dirs[i%2] = currentDir;
                }
            }
            return dirs;
        }
    }
}

জাভা এর কোন সংস্করণে এটি লেখা হয়েছিল?
রিপ লীব

@ নাট আমি ব্যবহার করেছি 1.7।
কমনগ্যুই

3

অ্যাভয়েডার ভি 3

একটি সাধারণ মনের বট। এটি অন্যান্য রোবট এবং ফাঁদগুলির ভয় পায়। এটি আক্রমণ করবে না। এটি পরিসংখ্যানের ফাইলটিকে উপেক্ষা করে এবং সামনে চিন্তা করে না।

এটি নিয়মগুলি কীভাবে কাজ করবে তা দেখার জন্য এবং অন্যান্য প্রতিযোগীদের কাছে বোবা প্রতিপক্ষ হিসাবে এটি মূলত একটি পরীক্ষা।

সম্পাদনা করুন: যখন কোনও রূপান্তর ভাল হয় না এখন পাস করুন।

সম্পাদনা 2: রোবটগুলি '123' এর পরিবর্তে '1234' হতে পারে

পাইথন কোড:

import sys
maxmoves = int(sys.argv[1])

ORTH = [(-1,0), (1,0), (0,-1), (0,1)]
def orth(p):
    return [(p[0]+dx, p[1]+dy) for dx,dy in ORTH]

mapfile = open('map').readlines()[::-1]
arena = dict( ((x,y),ch) 
    for y,row in enumerate(mapfile)
    for x,ch in enumerate(row.strip()) )
loc = [loc for loc,ch in arena.items() if ch == '@'][0]

options = []
for direc in ORTH:
    for dist in range(maxmoves+1):
        newloc = (loc[0]+direc[0]*dist, loc[1]+direc[1]*dist)
        if arena.get(newloc) in '#!1234':
            break
        penalty = dist * 10  # try not to use moves too fast
        if newloc == loc:
            penalty += 32   # incentive to move
        for nextto in orth(newloc):
            ch = arena.get(nextto)
            if ch == '#':
                penalty += 17  # don't get caught againt a wall
            elif ch in '1234':
                penalty += 26  # we are afraid of other robots
            elif ch == '!':
                penalty += 38  # we are very afraid of deadly traps
        options.append( [penalty, dist, direc] )

penalty, dist, direc = min(options)
if dist > 0:
    print 'MOVE', 'WESN'[ORTH.index(direc)], dist
else:
    print 'PASS'  # stay still?

elif ch in '123':আপনি কমপক্ষে 1234 সন্ধান করতে চান you আপনি যদি বট 3 হন তবে প্রতিপক্ষের তালিকাটি 124 হবে
রিপ লিব

1
@ নেট ধন্যবাদ আমি বট পরিবর্তন করেছি। আপনি বিধিগুলিতে এটি পরিষ্কার করতে চাইতে পারেন। আমি কেবল এটিই হতে পারি না যে এটির ভুল বোঝে।
লজিক নাইট

3

BestOpportunityBot

এটি আমার ইচ্ছা থেকে কিছুটা দীর্ঘ হয়ে গেছে ... এবং আমি নিশ্চিত না যে আমি মোড় ঘুরিয়ে দেওয়ার নিয়মগুলি পুরোপুরি বুঝতে পেরেছি কিনা, সুতরাং আমরা কীভাবে এটি করব তা দেখব।

from sys import argv
from enum import IntEnum

with open("map") as map_file:
    map_lines = map_file.read().splitlines()

with open("stats") as stats_file:
    stats_data = stats_file.read().splitlines()

ep = argv[1]

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(lhs, rhs):
        if (type(rhs) == tuple or type(rhs) == list):
            return Point(lhs.x + rhs[0], lhs.y + rhs[1])
        return Point(lhs.x + rhs.x, lhs.y + rhs.y)

    def __sub__(lhs, rhs):
        if (type(rhs) == tuple or type(rhs) == list):
            return Point(lhs.x - rhs[0], lhs.y - rhs[1])
        return Point(lhs.x - rhs.x, lhs.y - rhs.y)

    def __mul__(lhs, rhs):
        return Point(lhs.x * rhs, lhs.y * rhs)

    def __str__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __repr__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __eq__(lhs, rhs):
        return lhs.x == rhs.x and lhs.y == rhs.y

    def __hash__(self):
        return hash(self.x) * 2**32 + hash(self.y)

    def reverse(self):
        return Point(self.y, self.x)

dirs = (Point(0, 1), Point(1, 0), Point(0, -1), Point(-1, 0))

class Bot:
    def __init__(self, pos, ch, hp):
        self.pos = pos
        self.ch = ch
        self.hp = hp

    def __str__(self):
        return str(self.pos) + " " + str(self.ch) + " " + str(self.hp)

    def __repr__(self):
        return str(self.pos) + " " + str(self.ch) + " " + str(self.hp)

class MyBot(Bot):
    def __init__(self, pos, ch, hp, ep):
        self.ep = ep
        super().__init__(pos, ch, hp)

    def __str__(self):
        return super().__str__() + " " + self.ep

    def __repr__(self):
        return super().__repr__() + " " + self.ep

class Arena:
    def __init__(self, orig_map):
        self._map = list(zip(*orig_map[::-1]))
        self.bots = []
        self.me = None

    def __getitem__(self, indexes):
        if (type(indexes) == Point):
            return self._map[indexes.x][indexes.y]
        return self._map[indexes[0]][indexes[1]]

    def __str__(self):
        output = ""
        for i in range(len(self._map[0]) - 1, -1, -1):
            for j in range(len(self._map)):
                output += self._map[j][i]
            output += "\n"
        output = output[:-1]
        return output

    def set_bot_loc(self, bot):
        for x in range(len(self._map)):
            for y in range(len(self._map[x])):
                if self._map[x][y] == bot.ch:
                    bot.pos = Point(x, y)

    def set_bots_locs(self):
        self.set_bot_loc(self.me)
        for bot in self.bots:
            self.set_bot_loc(bot)

    def adjacent_bots(self, pos=None):
        if type(pos) == None:
            pos = self.me.pos
        output = []
        for bot in self.bots:
            for d in dirs:
                if bot.pos == pos + d:
                    output.append(bot)
                    break
        return output

    def adjacent_bots_and_dirs(self):
        output = {}
        for bot in self.bots:
            for d in dirs:
                if bot.pos == self.me.pos + d:
                    yield bot, d
                    break
        return output

    def look(self, position, direction, distance, ignore='', stopchars='#1234'):
        current = position + direction
        output = []
        for i in range(distance):
            if (0 <= current.x < len(self._map) and
                0 <= current.y < len(self._map[current.x]) and
                (self[current] not in stopchars or self[current] in ignore)):
                output += self[current]
                current = current + direction
            else:
                break
        return output

    def moveable(self, position, direction, distance):
        current = position + direction
        output = []
        for i in range(distance):
            if (0 <= current.x < len(self._map) and
                0 <= current.y < len(self._map[current.x]) and
                self[current] == ' '):
                output += self[current]
            else:
                break
        return output


    def danger(self, pos, ignore=None): # damage that can be inflicted on me
        output = 0
        adjacents = self.adjacent_bots(pos)
        hps = [bot.hp for bot in adjacents if bot != ignore]
        if len(hps) == 0:
            return output

        while max(hps) > 0:
            if 0 in hps:
                hps.remove(0)

            for i in range(len(hps)):
                if hps[i] == min(hps):
                    hps[i] -= 1
                output += 1
        return output

    def path(self, pos): # Dijkstra's algorithm adapted from https://gist.github.com/econchick/4666413
        visited = {pos: 0}
        path = {}

        nodes = set()

        for i in range(len(self._map)):
            for j in range(len(self._map[0])):
                nodes.add(Point(i, j))

        while nodes:
            min_node = None
            for node in nodes:
                if node in visited:
                    if min_node is None:
                        min_node = node
                    elif visited[node] < visited[min_node]:
                        min_node = node

            if min_node is None:
                break

            nodes.remove(min_node)
            current_weight = visited[min_node]

            for _dir in dirs:
                new_node = min_node + _dir
                if self[new_node] in ' 1234':
                    weight = current_weight + 1
                    if new_node not in visited or weight < visited[new_node]:
                        visited[new_node] = weight
                        path[new_node] = min_node

        return visited, path

class MoveEnum(IntEnum):
    Null = 0
    Pass = 1
    Attack = 2
    Move = 3
    Push = 4

class Move:
    def __init__(self, move=MoveEnum.Null, direction=Point(0, 0), distance=0):
        self.move = move
        self.dir = direction
        self.dis = distance

    def __repr__(self):
        if self.move == MoveEnum.Null:
            return "NULL"
        elif self.move == MoveEnum.Pass:
            return "PASS"
        elif self.move == MoveEnum.Attack:
            return "ATTACK " + "NESW"[dirs.index(self.dir)]
        elif self.move == MoveEnum.Move:
            return "MOVE " + "NESW"[dirs.index(self.dir)] + " " + str(self.dis)
        elif self.move == MoveEnum.Push:
            return "PUSH " + "NESW"[dirs.index(self.dir)] + " " + str(self.dis)

arena = Arena(map_lines)
arena.me = MyBot(Point(0, 0), '@', 0, ep)

for line in stats_data:
    if line[0] == '@':
        arena.me.hp = int(line[2:-2])
    else:
        arena.bots.append(Bot(Point(0, 0), line[0], int(line[2:-2])))

arena.set_bots_locs()

current_danger = arena.danger(arena.me.pos)

moves = [] # format (move, damage done, danger, energy)

if arena.me.ep == 0:
    print(Move(MoveEnum.Pass))
    exit()

for bot, direction in arena.adjacent_bots_and_dirs():
    # Push to damage
    pushable_to = arena.look(arena.me.pos, direction,
                             arena.me.ep + 1, ignore=bot.ch)
    if '!' in pushable_to:
        distance = pushable_to.index('!')
        danger = arena.danger(arena.me.pos + (direction * distance), bot)
        danger -= current_danger
        moves.append((Move(MoveEnum.Push, direction, distance),
                      bot.hp, danger, distance))

    # Push to escape
    pushable_to = arena.look(arena.me.pos, direction,
                             arena.me.ep + 1, ignore=bot.ch, stopchars='#1234!')
    for distance in range(1, len(pushable_to)):
        danger = arena.danger(arena.me.pos + (direction * distance), bot)
        danger += bot.hp
        danger -= current_danger
        moves.append((Move(MoveEnum.Push, direction, distance),
                      0, danger, distance))

    # Attack
    bot.hp -= 1
    danger = arena.danger(arena.me.pos) - current_danger
    moves.append((Move(MoveEnum.Attack, direction), 1, danger, 1))
    bot.hp += 1

culled_moves = []

for move in moves: # Cull out attacks and pushes that result in certain death
    if current_danger + move[2] < arena.me.hp:
        culled_moves.append(move)

if len(culled_moves) == 1:
    print(culled_moves[0][0])
    exit()
elif len(culled_moves) > 1:
    best_move = culled_moves[0]

    for move in culled_moves:
        if move[1] - move[2] > best_move[1] - best_move[2]:
            best_move = move
        if move[1] - move[2] == best_move[1] - best_move[2] and move[3] < best_move[3]:
            best_move = move

    print (best_move[0])
    exit()

# Can't attack or push without dying, time to move

moves = []

if current_danger > 0: # Try to escape
    for direction in dirs:
        moveable_to = arena.moveable(arena.me.pos, direction, ep)

        i = 1

        for space in moveable_to:
            danger = arena.danger(arena.me.pos + (direction * i))
            danger -= current_danger
            moves.append((Move(MoveEnum.Move, direction, i), 0, danger, i))
            i += 1

    if len(moves) == 0: # Trapped and in mortal danger, attack biggest guy
        adjacents = arena.adjacent_bots()
        biggest = adjacents[0]
        for bot in adjacents:
            if biggest.hp < bot.hp:
                biggest = bot
        print (Move(MoveEnum.Attack, biggest.pos - arena.me.pos))
        exit()

    best_move = moves[0]
    for move in moves:
        if ((move[2] < best_move[2] and best_move[2] >= arena.me.hp) or
            (move[2] == best_move[2] and move[3] < best_move[3])):
            best_move = move

    print(best_move[0])
    exit()

else: # Seek out closest target with lower health
    distances, path = arena.path(arena.me.pos)

    bot_dists = list((bot, distances[bot.pos]) for bot in arena.bots)

    bot_dists.sort(key=lambda x: x[1])

    target = bot_dists[0]

    for i in range(len(bot_dists)):
        if bot_dists[i][0].hp <= arena.me.hp:
            target = bot_dists[i]
            break

    pos = target[0].pos
    for i in range(target[1] - 1):
        pos = path[pos]

    print (Move(MoveEnum.Move, pos - arena.me.pos, 1))
    exit()

# Shouldn't get here, but I might as well do something
print (Move(MoveEnum.Pass))

অজগরটির কোন সংস্করণ আপনি এটি লিখেছেন?
রিপ লিব

উইন

এটি একটি @ হর্নস জমা দেওয়ার জন্য ধন্যবাদ। দেখতে সত্যিই মজা লাগছিল!
রিপ লীব

1

খাওয়া দাওয়া শেষ

পাইথন:

import sys
print 'PASS'

1
আমি এটা করতে চাই - এবং কেন import sys?
টমসডিং

1
@ টমসডিং ওয়েল আমাকে কিছু জিনিস কপি করতে হয়েছিল। এবং আমি ভেবেছিলাম যে আমার যদি কখনও কিছু আরগগুলি পড়ার প্রয়োজন হয় :) যখন আমি খাওয়া শেষ করি অবশ্যই।
টিমটেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.