फैलोशिप की लड़ाई कोटह


45

इस चुनौती में, आप लड़ाई में अन्य सभी फैलोशिप को हराने के लक्ष्य के साथ एक फैलोशिप बनाने जा रहे हैं ।

फेलोशिप (टीम) में 3 वर्ण होते हैं । प्रत्येक चरित्र अपनी टीम के बाकी हिस्सों से स्वतंत्र रूप से आगे बढ़ता है, लेकिन उन्हें अपने दुश्मन से लड़ते समय एक साथ काम करने की आवश्यकता होगी। टीमें एक दूसरे के आमने-सामने घूमती हुई तरीके से आमने सामने होंगी। जीत 3 अंक के बराबर होती है, संबंध 1 अंक के होते हैं, और नुकसान 0 अंक के होते हैं।

चरित्रों में क्षमताएँ होती हैं। आपके पात्र में क्या योग्यता है, इसका चुनाव इस कोठ में सबसे महत्वपूर्ण (और मजेदार) भागों में से एक है । वे सभी मजबूत हैं, और अपने दुश्मन का सफाया करने की क्षमता रखते हैं।

वर्ण में स्वास्थ्य अंक (HP) होते हैं, और जब उनका HP हिट होता है (या नीचे जाता है) 0, तो वे मर जाते हैं । यदि आपके प्रतिद्वंद्वी की टीम के सभी अक्षर मर जाते हैं, तो आप जीत जाते हैं!

चरित्रों में मन है। अधिकांश क्रियाओं के लिए मन को प्रदर्शन की आवश्यकता होती है , और यदि आपके पास पर्याप्त नहीं है, तो वह क्रिया आपके लिए उपलब्ध नहीं है।

वर्णों में एक मोड़ विलंब होता है । यह प्रत्येक मोड़ के बीच टिक्स की संख्या निर्धारित करता है (100 पर शुरू होता है)। नीचा बेहतर है।

चरित्रों में विशेषताएँ होती हैं । प्रत्येक विशेषता में प्रत्येक वर्ण का आधार 5 है, और आपको विभाजित करने के लिए 20 अतिरिक्त विशेषता बिंदु दिए गए हैं। विशेषता बिंदु निर्दिष्ट करने के बाद, आपकी प्राथमिक विशेषता को आपकी उच्चतम विशेषता के रूप में सेट किया जाता है।

उपलब्ध विशेषताएँ हैं:

  • ताकत: प्रति अधिकतम 10 एचपी और .5 एचपी देता है
  • खुफिया: 7 अधिकतम मान और .1 मान प्रति मोड़ देता है
  • चपलता: 1 से टर्न डिले को कम करता है

आंदोलन, दृष्टि, रेंज
रेंज इस प्रकार हैं (0 के आसपास केंद्रित)। कुछ श्रेणियां कार्डिनल हैं , जिसका अर्थ है कि वे केवल सीधे ऊपर, बाएं, दाएं या नीचे जा सकते हैं।

    444
   43334
  4322234
 432111234
 432101234
 432111234
  4322234
   43334
    444

वर्णों की एक प्रारंभिक दृष्टि है। एक ही फेलोशिप के खिलाड़ियों के बीच विजन साझा किया जाता है।

कैसे खेलें

निर्माण
खिलाड़ी अपनी संगति का निर्माण करेंगे। आपको निम्न चरण करने की आवश्यकता है :

  1. प्रत्येक वर्ण विशेषता अंक दें । प्रत्येक चरित्र प्रत्येक स्टेट में 5 के साथ शुरू होता है, 3 के बीच वितरित करने के लिए 20 अतिरिक्त।

  2. प्रत्येक वर्ण क्षमता दें । प्रत्येक चरित्र 4 क्षमता स्लॉट्स के साथ शुरू होता है, और क्षमताएं डिफ़ॉल्ट रूप से 1 स्लॉट लेती हैं। कुछ क्षमताएं दोहराई जा सकती हैं, और कई बार एक चरित्र को दी जा सकती हैं। मालिक की अनुमति के बिना किसी अन्य सबमिशन की क्षमता सेट का उपयोग करने की अनुमति नहीं है।

  3. अपने बॉट्स के लिए कुछ कोड लिखें । कोड जावा में होना चाहिए, और इसका इस्तेमाल जूझने के लिए किया जाएगा (अगला चरण)

क्रिया

सभी वर्ण 3 मानक क्रियाओं से शुरू होते हैं:

  1. चरण : 1 के कार्डिनल रेंज में अपने चरित्र को स्थानांतरित करें
  2. स्लाइस : 1 के कार्डिनल रेंज में प्राइमरी एट्रिब्यूट के लिए दुश्मन पर हमला करें
  3. मुस्कान : कुछ मत करो

एक वर्ण के मोड़ पर, फिर प्रदर्शन करने के लिए एक क्रिया चुननी चाहिए। क्रियाओं में एक मन लागत हो सकती है, और एक Cooldown हो सकता है, जो कि उन क्रियाओं को परिभाषित करता है जिन्हें आपको फिर से कार्रवाई करने से पहले इंतजार करना पड़ता है।

क्षमताओं
हर चरित्र में 4 क्षमता स्लॉट हैं। यदि एक क्षमता इटैलिक में है, तो यह एक क्रिया है।

क्षमताओं

नाम विवरण मन कोल्डाउन 
                                                     गतिशीलता                                                     

ब्लिंक         एक वर्ग में ले जाएँ,          लक्ष्य 5 5 टेलपोर्ट के साथ 4 2 2 
 स्वैप स्वैप स्थानों को 
      20 5 कहीं भी स्थानांतरित करें

डैश चरण 1 की सीमा बढ़ाएँ। दोहराए जाने योग्य                                               
मोबाइल स्टेप 8 दिशाओं में से किसी में भी जा सकता है                                                  
                                                    हमला                                                    

त्वरित         स्लाइस दो बार 3 0 
 बुनें         सभी दिखाई देने वाले दुश्मनों को 15 10 पर एक बार बुनें

प्रत्येक स्लाइस को अपने लक्ष्य की प्राथमिक विशेषता को चुरा लेता है। 20 मोड़ तक रहता है                    
क्लीव प्रत्येक स्लाइस निकटवर्ती दुश्मनों को 1/2 नुकसान पहुंचाता है                                           
क्रिटिटल 200% क्षति से निपटने के लिए स्लाइस के लिए 30% मौका जोड़ता है। repeatable                               
पर्व प्रत्येक स्लाइस आपके HP को 3. दोहराता है                                             
लचीली कैन 8 दिशाओं में से किसी में भी स्लाइस कर सकती है                                                      
मैना चोरी स्लाइस 2 मैना चोरी। repeatable                                                           
0 3 फिसलने पर रिफ्लेक्टिव स्लाइस 
रेंजेड स्लाइस की रेंज 1 से जोड़ता है                                                              
एक ही लक्ष्य पर प्रत्येक लगातार स्लाइस स्वाइप करें पिछले की तुलना में 3 अधिक नुकसान               
                                                    वे स्थितियां                                                     

Dispel        एक टारगेट से सभी स्टेटस को हटाता है। सीमा 2. 20 10 
 द्वंद्वयुद्ध          आपको और आपके लक्ष्य को तब तक मुक्त करता है जब तक कि आपकी मृत्यु नहीं हो जाती। श्रेणी 1 25 0 
 नॉकआउट      आप और लक्ष्य अगले 1000 टिक्स 10 10 
 उल्का के        लिए स्तब्ध हैं सभी दुश्मन अगले 100 टिक्स के लिए दंग रह गए हैं 25 10 
 पट्टा         लक्ष्य उनके 2 अगले 4 से 4 जहर        जहर के लिए जमे हुए है 
 1 5 के लिए 1 एचपी के लिए दुश्मन जहर ५ ० 
 मौन      लक्ष्य 5 टर्न के लिए खामोश है 5 7 
 धीमा          टारगेट 40 टिक्स से धीमा हो जाता है उनके अगले 3 टर्न के लिए 10 5 
 स्टन          टारगेट अगले 300 टिक्स 10 10 के लिए स्तब्ध है

2 श्रेणी के भीतर सभी अन्य वर्ण 10 टिक से धीमा होते हैं                                
प्रतिरक्षा आपके लिए कोई स्थिति लागू नहीं की जा सकती                                                           
                                                    बचाव                                                    

फोर्स फील्ड   ब्लॉक नुकसान के अगले 5 स्रोतों।         एक मोड़ के लिए 15 5 भूत को स्टैक नहीं करता है 
 , सभी क्षति          20 एचपी के लिए 10 10 
 हील हील को ठीक करती है 10 3 3 
 पुनर्स्थापित करें       सभी इकाइयों को पूर्ण स्वास्थ्य पर वापस बहाल किया जाता है 20 40 
 शील्ड        आप अपने अगले मोड़ 3 0 तक कटा नहीं जा सकता

एक स्लाइस के लिए आप को हिट न करने के लिए 25% मौका। repeatable                                         
पिलर को केवल एक बार मोड़ने के बाद खिसकाया जा सकता है                                                            
पुनर्जीवित जब मारा गया, पूर्ण एचपी के साथ जीवन में वापस आओ (और कोई स्थिति नहीं) 0 40 
स्पाइक्स जब क्षति से निपटते हैं, तो नुकसान का आधा हिस्सा वापस लेते हैं                                           
                                                     विजन                                                      

क्लॉक         टीम 5 मुड़ने के लिए अदृश्य हो जाती है 20 20 
 छिपाएं          आप 5 बारी के लिए अदृश्य हैं 4 7 
 चरण         1 मोड़ के लिए अदृश्य बनें 0 3 
 ट्रैक         लक्ष्य अदृश्य नहीं हो सकते हैं, और 10% अधिक नुकसान पहुंचाते हैं। 10 मोड़ तक रहता है। ५ ५

अंधेरा शत्रु दृष्टि सीमा में 1. कमी आई, लेकिन 1 से नीचे नहीं जा सकता।                                 
दूर दृष्टि दृष्टि सीमा 2. की वृद्धि हुई                                                    
अदृश्य आप अदृश्य हैं यदि आप दुश्मन की दृष्टि से अपनी बारी शुरू करते हैं                               
सच्ची दृष्टि बारी शुरू में सीमा 2 के भीतर सभी छिपी हुई इकाइयों को प्रकट करती है                                     
                                                     क्षति                                                      

ड्रेन         सौदे को 5 नुकसान पहुंचाता है और 5 एचपी के लिए स्वयं को ठीक करता है जबकि वे 1 रेंज में रहते हैं 5 5 
 लाइटनिंग     डील 15 सभी दुश्मनों को नुकसान 20 20 
 के / ओ           मारता है यदि लक्ष्य 20% से कम है तो एचपी 20 0 
 ट्रैप          एक अदृश्य जाल रखें। ट्रैप के 15 कदम होने पर नुकसान होता है। ढेर। 10 2 
 जैप           डील 30 5 को निशाना बनाने के लिए 30 नुकसान

स्टेटिक डील 1 रेंज के भीतर सभी दुश्मनों को 5 नुकसान पहुंचाती है। repeatable                       
                                                      आँकड़े                                                      

वेयरवोल्फ      5 के लिए 10 सभी आँकड़े जोड़ें 30 25 बदल जाता है

बफ़ डबल अपने एचपी पूल। repeatable                                                           
चतुर क्रियाओं में 20% कम कोल्डाउन होता है। repeatable                                             
ध्यान केंद्रित Int / 10 द्वारा अपने मन प्रतिगमन दर बढ़ जाती है। repeatable                                  
पुनर्जनन शक्ति / 2 द्वारा आपके प्रतिगमन दर को बढ़ाता है। repeatable                                 
स्मार्ट क्रियाओं की कीमत 2 कम मान है। repeatable                                                      
मजबूत आप 10 विशेषता अंक प्राप्त करते हैं। repeatable                                                  
कमजोर आप 15 विशेषता अंक खो देते हैं। आप 2 क्षमता स्लॉट हासिल करते हैं (यह उनमें से एक लेता है)                  
                                                      अन्य                                                      

भालू          एक भालू को बुलवा सकता है जिसके पास प्रत्येक स्टेट 8 में 10 10 
 क्लोन         क्लोन है। दो क्षमता वाले स्लॉट लेता है। 100 100 
 चोरी         अंतिम कार्रवाई दुश्मन लक्ष्य के साथ इस कार्रवाई को बदलें। लास्ट 10 बदल जाता है 5 0 
 दीवार          लक्षित खाली वर्ग पर एक अगम्य दीवार बनाएं, रेंज 6 10 10 

अवस्थाएँ:

  • स्टन आपके चरित्र को केवल स्माइल एक्शन करने की अनुमति देता है, और एक्स टिक टिकता है
  • फ्रीज आपके चरित्र को बढ़ने से रोकता है, और एक्स बदल जाता है।
  • मौन आपके चरित्र को स्माइल, स्टेप या स्लाइस के अलावा कुछ भी करने से रोकता है, और एक्स बदल जाता है।
  • ज के वाई नुकसान के लिए ज़हर आपके चरित्र को नुकसान पहुंचाता है। यदि आप एक और जहर लागू करते हैं, तो नुकसान एक साथ जोड़ता है, और अवधि ताज़ा होती है।
  • स्लो एक्स को आपके टर्न के बीच टिक की संख्या में जोड़ता है। यह आपके आगामी मोड़ को प्रभावित नहीं करता है , केवल बाद में बदल जाता है।
  • अदृश्य बनाता है ताकि आप अपने प्रतिद्वंद्वी द्वारा देखे या क्षतिग्रस्त न हो सकें। यदि आप स्टेप या स्माइल के अलावा कोई एक्शन करते हैं, तो उसे हटा दिया जाता है। यदि आपके प्रतिद्वंद्वी में एक क्षमता है जो उन्हें आपके बारे में दृष्टि देता है, तो अदृश्यता को हटा दिया जाता है।

सभी स्थितियाँ (ज़हर को छोड़कर) एक दूसरे से स्वतंत्र रूप से कार्य करती हैं।

साइड नोट्स:

  • यदि प्राथमिक विशेषता के लिए कोई टाई है, तो इसे STR> AGI> INT के रूप में हल किया जाता है।
  • आप 10x10 ग्रिड पर खेलते हैं। टीमों को विपरीत दिशा में रखा जाएगा।
  • क्लीवर को छोड़कर, गुणक स्टैक गुणक रूप से होता है।

प्रस्तुत करने का नियम

आपको 2 कार्यों को लागू करने की आवश्यकता है:

// Create *exactly* 3 Character templates.  You must return the same templates every time
public List<CharacterTemplate> createCharacters();

// Choose an action for a character.  If the action requires a target or location, it must be set.
public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character);

आपके पास तीन चर (सदस्य चर) तक पहुंच भी होगी:

Set<ReadonlyCharacter> team;
Set<EnemyCharacter> enemies;
Map<Point2D, EnemyCharacter> visibleEnemies;

बस। नीचे आप वर्णमाला क्रम में एक पूर्ण एपीआई पा सकते हैं:

class Ability and ReadonlyAbility
    int getNumSlots() returns the number of slots it takes up
    boolean repeatable() returns true if the ability can be repeated
    String name()
class Action and ReadonlyAction
    Set<Point2D> availableLocations()
    Set<ReadonlyCharacter> availableTargets()
    boolean basicAction() returns true if the action is Smile, Step, or Slice
    boolean breaksInvisibiliby()      
    int getCooldown() returns the cooldown cost (not the cooldown remaining)
    int getManaCost()
    String getName()
    int getRemainingCooldown()
    boolean isAvailable() returns true if the action can be performed
    boolean movementAction() returns true if the action is prevented when Frozen
    boolean needsLocation()
    boolean needsTarget()
    void setTarget(ReadonlyCharacter target)
    void setLocation(Point2D location)
class CharacterTemplate
    void addAbility(Ability)
    boolean canAddAbility(Ability)
    List<Ability> currentAbilities()
    Map<Stat, Integer> currentAttributes()
    int getRemainingPoints() returns the total number of ability points you have left to assign
    int getRemainingSlots() returns the total number of slots you have to assign
    int getStat(Stat stat)
    boolean isValid() returns true if your character template is complete and valid
class Point2D
    getX()
    getY()
class Range
    boolean isCardinal() returns true if the range only extends in the 4 cardinal directions
    int getRange() returns the distance of the range
class ReadonlyCharacter and EnemyCharacter
    Class characterClass()
    int cleverness()
    List<ReadonlyAbility> getAbilities()
    Point2D getLocation()   Not on EnemyCharacter
    double getHealth()
    double getMana()
    int getMaxHealth()
    int getMaxMana()
    Range getSightRange()
    Range getSliceRange()
    int getStat(Stat stat)
    Range getStepRange()
    ReadonlyAction getLastAction()
    boolean isFrozen()
    boolean isStunned()
    boolean isPoisoned()
    int getPoisonAmount()
    boolean isSilenced()
    boolean isInvisible()
    boolean isDead()
    Stat primaryStat()
    int smartness()
enum Stat
    INT, STR, AGI

उपरोक्त सभी कार्य हैं जिन्हें आप संभवतः अपने सबमिशन के लिए कर सकते हैं। परावर्तन की अनुमति नहीं है। यदि किसी कारण से कोई जमा अमान्य है, तो कृपया इसे हटा दें या शीर्ष लेख में "अमान्य" जोड़ें। आपके सबमिशन में पैकेज की घोषणा नहीं होनी चाहिए । आपका सबमिशन पहले मल्टी-लाइन कोड ब्लॉक में समाहित होना चाहिए, और पहली लाइन में फ़ाइल का नाम होना चाहिए।

परियोजना कैसे चलाएं:

कई तरीके हैं:

  1. JAR फ़ाइल डाउनलोड करें , और चलाएँ java -jar Fellowship.jar। यदि आप अन्य सबमिशन डाउनलोड करना चाहते हैं, तो पास करें -q 99744। JDK java को इंगित करना चाहिए , JRE को नहीं।
  2. गैटो रेपो को क्लोन करें , और चलाएं gradle run। आपको ग्रेडेल स्थापित करने की आवश्यकता है, और यदि आप तर्क पारित करना चाहते हैं, तो उपयोग करें-PappArgs="['arg1', 'args2']"
  3. गिट रेपो को क्लोन करें , और इसे स्वयं संकलित करें। आप निम्नलिखित पुस्तकालयों की आवश्यकता होगी: org.eclipse.collections:eclipse-collections-api:8.0.0, org.eclipse.collections:eclipse-collections:8.0.0, com.beust:jcommander:1.48, com.google.code.gson:gson:2.7,org.jsoup:jsoup:1.9.2

यदि आप क्लोन करते हैं तो आपको --recursiveध्वज का उपयोग करना चाहिए , और जब आप अपडेट खींचते हैं,--recurse-submodules तो उपरोक्त में से किसी एक के लिए, आपकी कक्षा को submissions/javaफ़ोल्डर में जाने की आवश्यकता है । यदि आप ग्रेडेल का उपयोग कर रहे हैं, या इसे स्वयं संकलित कर रहे हैं, तो आप प्रोजेक्ट में ही क्लास लगा सकते हैं। आपको मुख्य फ़ंक्शन में कुछ पंक्तियों को अनसुना करना होगा, और उन्हें अपनी कक्षा में इंगित करने के लिए अपडेट करना होगा।

स्कोरबोर्ड:

+------+-------------------+-------+
| Rank | Name              | Score |
+------+-------------------+-------+
|    1 | TheWalkingDead    | 738.0 |
|    2 | RogueSquad        | 686.0 |
|    3 | Spiky             | 641.0 |
|    4 | Invulnerables     | 609.0 |
|    5 | Noob              | 581.0 |
|    6 | Railbender        | 561.0 |
|    7 | Vampire           | 524.0 |
|    8 | LongSword         | 508.0 |
|    9 | SniperSquad       | 456.0 |
|   10 | BearCavalry       | 430.0 |
|   11 | StaticCloud       | 429.0 |
|   12 | PlayerWerewolf    | 388.0 |
|   13 | LongSwordv2       | 347.0 |
|   14 | Derailer          | 304.0 |
|   15 | Sorcerer          | 266.0 |
|   16 | CowardlySniperMk2 | 262.0 |
|   17 | TemplatePlayer    |  59.0 |
+------+-------------------+-------+

यदि आपके कोई प्रश्न हैं, या मदद चाहिए, तो नीचे टिप्पणी करें, या चैट रूम में शामिल हों ! गुड लक और मजा करें


1
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
डेनिस

बिजली के रूप में सूचीबद्ध है Deal 15 damage to all enemies, लेकिन अदृश्य दुश्मन बिजली से अप्रभावित हैं। क्या यह एक बग है? अन्यथा, अदृश्यता मुझे बहुत मजबूत लगती है ...
कॉमनग्यूई

1
यह चुनौती पिछली ऐसी चुनौतियों की तुलना में असाधारण रूप से अधिक जटिल है। काश, यहां एक प्रारूप होता, जो दीर्घावधि में इस तरह के और अधिक प्रतिस्पर्धी बनाता।
स्पर्म

2
हां, पता है कि क्या -g विकल्प है, हालांकि जब मैं अपना बॉट विकसित कर रहा था तो मेरे पास यह अभी तक उपयोग करने योग्य स्थिति में नहीं था इसलिए मैंने एक विकल्प बनाना शुरू कर दिया। यह इस समय बहुत ही अल्पविकसित है लेकिन इसमें दृश्य त्रिज्या दिखाई देती है। यहाँ भालू कैवलरी बनाम टेम्पलेट खिलाड़ी का कब्जा है! कब्जा करना
मोगी

1
क्या आप नए पात्रों का परीक्षण कर सकते हैं और स्कोर को अपडेट कर सकते हैं?
विध्वंसक नींबू

जवाबों:


10

StaticCloud

एक बढ़ता हुआ बादल जो किसी के करीब आने पर स्थैतिक क्षति करता है। यह मिश्रण है:

  • 1/3 अदृश्य हिस्सा
    • एसटीआर: 5; AGI: 5; INT: 25
    • क्लोन , अदृश्य , स्टेटिक
  • 2/3 दृश्यमान भाग
    • एसटीआर: 5; AGI: 5; INT: 25
    • क्लोन , स्टेटिक , स्टेटिक

आप अपनी टीम में यहां से एकल वर्णों का पुन: उपयोग कर सकते हैं, जब तक आप कम से कम एक और चरित्र जोड़ते हैं जो यहां मौजूद नहीं है।

StaticCloud.java
import java.util.Arrays;
import java.util.List;

import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.impl.factory.Sets;

import com.nmerrill.kothcomm.game.maps.Point2D;

import fellowship.abilities.ActionAbility;
import fellowship.abilities.damage.Static;
import fellowship.abilities.vision.Invisible;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.other.Clone;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class StaticCloud extends SleafarPlayer {
    private CharacterTemplate invisibleTemplate() {
        return new CharacterTemplate(0, 0, 20,
                new ActionAbility(Clone::new), new Invisible(), new Static());
    }

    private CharacterTemplate visibleTemplate() {
        return new CharacterTemplate(0, 0, 20,
                new ActionAbility(Clone::new), new Static(), new Static());
    }

    @Override
    public List<CharacterTemplate> createCharacters() {
        return Arrays.asList(visibleTemplate(), invisibleTemplate(), visibleTemplate());
    }

    private class InvisibleCloud extends Character {
        protected InvisibleCloud(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction clone = getAction(Clone.class);
            if (clone != null && (isVisible() || !isInEnemySightRange())) {
                int invisibleCount = countCharacters(InvisibleCloud.class);
                if (invisibleCount > 8 && setClosestSafeLocation(clone, getStaticLocations())) {
                    return clone;
                } else if (setCloneLocation(clone, invisibleCount < 3 ? 3 : 1)) {
                    return clone;
                }
            }
            if (step != null && isVisible() && isInEnemySliceRange() &&
                    setClosestSafeLocation(step, getStaticLocations())) {
                return step;
            }
            if (slice != null && isVisible() && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null) {
                ImmutableSet<Point2D> avoidLocations = !isVisible() || isInEnemySliceRange() ?
                        Sets.immutable.empty() : getEnemySliceLocations();
                if ((isVisible() || clone != null) && !getEnemyHiddenLocations().isEmpty() &&
                        setClosestLocation(step, avoidLocations, getEnemyHiddenLocations())) {
                    return step;
                }
                if (!getStaticLocations().contains(getLocation()) &&
                        setClosestLocation(step, avoidLocations, getStaticLocations())) {
                    return step;
                }
            }
            return smile;
        }
    }

    private class VisibleCloud extends Character {
        protected VisibleCloud(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction clone = getAction(Clone.class);
            if (clone != null) {
                int visibleCount = countCharacters(VisibleCloud.class);
                if (visibleCount > 5 && setClosestSafeLocation(clone, getStaticLocations())) {
                    return clone;
                } else if (setCloneLocation(clone, visibleCount < 3 ? 2 : 1)) {
                    return clone;
                }
            }
            if (step != null && isInEnemySliceRange() && setClosestSafeLocation(step, getStaticLocations())) {
                return step;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null && !getStaticLocations().contains(getLocation())) {
                if (isInEnemySliceRange() ? setClosestLocation(step, getStaticLocations()) :
                        setClosestSafeLocation(step, getStaticLocations())) {
                    return step;
                }
            }
            return smile;
        }
    }

    @Override
    protected Character createCharacter(ReadonlyCharacter delegate) {
        if (hasAbility(delegate, Invisible.class)) {
            return new InvisibleCloud(delegate);
        } else {
            return new VisibleCloud(delegate);
        }
    }
}

3
यह एक दिलचस्प है क्योंकि स्टेटिक अदृश्यता को नहीं तोड़ता है।
ड्रेको

7

टेम्पलेट प्लेयर

उपयोग लेकर , लचीला , जैप , और KO । यदि आप चाहें तो आपको इस क्षमता सेट का उपयोग करने की अनुमति है।

इस बॉट को अपने स्वयं के निर्माण के लिए एक टेम्पलेट के रूप में उपयोग करने के लिए स्वतंत्र महसूस करें।

याद रखें कि आपको पहली पंक्ति में फ़ाइल नाम बदलने की आवश्यकता है, साथ ही साथ अपनी क्षमता सेट का चयन करना होगा।

TemplatePlayer.java
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Flexible;
import fellowship.abilities.attacking.Ranged;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.damage.KO;
import fellowship.actions.damage.Zap;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.Player;
import org.eclipse.collections.api.set.MutableSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class TemplatePlayer extends Player{
    private final double CRITICAL_HEALTH = 20;
    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(10, 5, 5,
                    new Ranged(),
                    new Flexible(),
                    new ActionAbility(KO::new),
                    new ActionAbility(Zap::new)));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        int minPriority = Integer.MAX_VALUE;
        ReadonlyAction chosen = null;
        for (ReadonlyAction action: actions){
            int priority = getPriorityFor(action, character);
            if (priority < minPriority){
                chosen = action;
                minPriority = priority;
            }
        }
        if (chosen == null){
            throw new RuntimeException("No valid actions");
        }
        if (chosen.needsLocation()){
            chosen.setLocation(chooseLocationFor(chosen, character));
        } else if (chosen.needsTarget()){
            chosen.setTarget(chooseTargetFor(chosen));
        }
        return chosen;
    }

    private Point2D chooseLocationFor(ReadonlyAction action, ReadonlyCharacter character){
        if (action.movementAction()){
            if (character.getHealth() < CRITICAL_HEALTH){
                return fromEnemy(action.availableLocations());
            } else {
                return toEnemy(action.availableLocations());
            }
        }
        return toTeam(action.availableLocations());
    }

    private Point2D toEnemy(MutableSet<Point2D> availableLocations){
        if (visibleEnemies.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.minBy(p1 ->
                p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))
        );
    }

    private Point2D fromEnemy(MutableSet<Point2D> availableLocations){
        if (visibleEnemies.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.maxBy(p1 ->
                p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))
        );
    }

    private Point2D toTeam(MutableSet<Point2D> availableLocations){
        if (team.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.minBy(p1 ->
                p1.cartesianDistance(team.collect(ReadonlyCharacter::getLocation).minBy(p1::cartesianDistance))
        );
    }

    private ReadonlyCharacter chooseTargetFor(ReadonlyAction action){
        return action.availableTargets().minBy(ReadonlyCharacter::getHealth);
    }

    private int getPriorityFor(ReadonlyAction action, ReadonlyCharacter character){
        if (character.isInvisible() && action.breaksInvisibility()){
            return 1000;
        }
        if (action.getName().equals("Smile")){
            return 999;
        }
        if (action.movementAction()){
            if (character.getHealth() < 20){
                return 0;
            }
            return 998;
        }
        if (action.needsTarget()) {
            return ((int) action.availableTargets().minBy(ReadonlyCharacter::getHealth).getHealth());
        }
        return 997;
    }
}

7

CowardlySniperMk2

Zap , FarSight * 2, और Hide का उपयोग करता है ।

यह बॉट एक कायर है। इसकी सर्वोच्च प्राथमिकता लक्षित होना नहीं है। उस छोर तक वह अपनी श्रेष्ठ दृष्टि का उपयोग यह देखने के लिए करता है कि दुश्मन कहाँ हैं। यह इस ज्ञान का उपयोग करता है ताकि दुश्मन को नज़र रखने के साथ नज़र रखने / पीछा करने से बचा जा सके। यदि यह देखा जाता है, या अगली बारी में देखा जा सकता है, तो बॉट एक समय के लिए अदृश्य हो जाएगा।

ट्रैकिंग मोड में, और पर्याप्त मैना और कोल्डाउन रीसेट है, फिर सबसे कमजोर दिखाई देने वाले दुश्मन को 'जैप' करेगा।

एक बार जब मन 10% से कम हो जाता है, तब तक दुश्मनों से दूर हो जाएगा जब तक कि मन बहाल नहीं हो जाता। इस तरह, यह ट्रैक किए गए दुश्मन पर जितनी जल्दी हो सके झपकी ले सकता है। उम्मीद है कि दुश्मन के पास मौजूद किसी भी एचपी को नकार दिया जाए।

ध्यान दें कि 'जैप' अनंत सीमा है, टीम के सदस्य ज़पिंग के दौरान एक ही बॉट को निशाना बनाएंगे।

मेरे पास इस मूल विचार के अन्य संस्करण हैं जिन्हें मैं उत्तर के रूप में जोड़ सकता हूं: इन सभी के अलग-अलग लाभ / निरोध हैं जिनका उपयोग मौजूद विरोधियों के आधार पर किया जाता है।

CowardlySniperMk2.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.vision.FarSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.damage.Zap;
import fellowship.actions.vision.Hide;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import fellowship.*;

public class CowardlySniperMk2 extends Player{

    private final static boolean DEBUG=false; 
    private static Point2D lastAttackedEnemyLocation = null;
    private static HashMap<ReadonlyCharacter, Boolean> rechargingManaMap = new HashMap<>();
    private final double STANDARD_VISION_MOVEMENT_BUFFER = 3;
    private final double MIN_VISION_DISTANCE = 2;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(8, 8, 4,
                    new ActionAbility(Zap::new),
                    new FarSight(),
                    new FarSight(),
                    new ActionAbility(Hide::new)));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {

        // get last flag for recharging mana
        Boolean rechargingMana = rechargingManaMap.get(character);
        if (rechargingMana == null || rechargingMana)
        {
            rechargingMana = !(character.getMana()>0.90*character.getMaxMana());
        }
        else
        {
            rechargingMana = character.getMana()<0.10*character.getMaxMana();
        }

        rechargingManaMap.put(character,rechargingMana);

        HashMap<Integer, ReadonlyAction> validActions = new HashMap<>();
        HashMap<Integer, String> actionString = new HashMap<>();

        // see if we have arrived at the last attack location of the enemy
        if (character.getLocation().equals(lastAttackedEnemyLocation))
        {
            lastAttackedEnemyLocation = null;
        }

        double closestEnemyVisionDistance = Double.MAX_VALUE;
        for ( Point2D enemyLocation : visibleEnemies.keySet())
        {
            final int enemyVisibiltyRange = visibleEnemies.get(enemyLocation).getSightRange().getRange();
            double visionDistanceDiff = character.getLocation().diagonalDistance(enemyLocation)-enemyVisibiltyRange;
            if (visionDistanceDiff< closestEnemyVisionDistance)
            {
                closestEnemyVisionDistance = visionDistanceDiff;
            }
        }

        for (ReadonlyAction action: actions){

            int priority=-1;
            String message = "";
            switch (action.getName())
            {
                case "Hide":
                    // are we, or will we be within sight range of an enemy
                    if (closestEnemyVisionDistance < STANDARD_VISION_MOVEMENT_BUFFER )
                    {
                        if (!character.isInvisible())
                        {
                            message = ""+closestEnemyVisionDistance;
                            priority = 1000;
                        }
                    }
                    break;

                case "Step":

                    Point2D chosenLocation = null;

                    // are we within sight range of an enemy or are we recharging mana?
                    if (closestEnemyVisionDistance < MIN_VISION_DISTANCE || rechargingMana)
                    {
                        message = "Fleeing (Seen) "+ closestEnemyVisionDistance;
                        priority = 800;

                        if (character.isInvisible())
                        {
                            message = "Fleeing (UnSeen) "+ closestEnemyVisionDistance;
                            priority = 500;
                        }

                        // simple enemy avoidance... chose location that is farthest away from closest enemy
                        double furthestDistance = 0;

                        for ( Point2D enemyLocation : visibleEnemies.keySet())
                        {
                            for (Point2D location : action.availableLocations())
                            {
                                if (location.diagonalDistance(enemyLocation) > furthestDistance)
                                {
                                    furthestDistance = location.diagonalDistance(enemyLocation);
                                    chosenLocation = location;
                                }
                            }
                        }

                        if (chosenLocation == null)
                        {
                            // no moves are better than staying in current location
                            priority = -1;
                            break;
                        }
                    }
                    // are we "tracking" an enemy?
                    else if (lastAttackedEnemyLocation !=null)
                    {
                        priority = 20;
                        message = "Tracking "+ closestEnemyVisionDistance;

                        // head toward last attacked enemy location
                        double distance = Integer.MAX_VALUE;
                        for (Point2D location : action.availableLocations())
                        {
                            if (location.diagonalDistance(lastAttackedEnemyLocation) < distance)
                            {
                                distance = location.diagonalDistance(lastAttackedEnemyLocation);
                                chosenLocation = location;
                            }
                        }
                    }
                    // are we outside the sight range of all enemies?
                    else if (closestEnemyVisionDistance > STANDARD_VISION_MOVEMENT_BUFFER)
                    {
                        // scout for an enemy

                        priority = 10;
                        message = "Scouting "+ closestEnemyVisionDistance;

                        // dumb random location selection... not optimal but is sufficent.
                        int index = getRandom().nextInt(action.availableLocations().size());
                        for (Point2D location : action.availableLocations())
                        {
                            chosenLocation= location;
                            if (--index == 0)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        // we are in the sweet zone... just out of enemy sight range but within our sight range
                        break;
                    }

                    action.setLocation(chosenLocation);
                    break;

                case "Zap":
                    message = ""+closestEnemyVisionDistance;
                    ReadonlyCharacter chosenTarget = null;
                    double chosenTargetHealth = Double.MAX_VALUE;

                    // target the weakest enemy
                    for (ReadonlyCharacter target : action.availableTargets())
                    {
                        if (target.getHealth() < chosenTargetHealth)
                        {
                            chosenTargetHealth = target.getHealth();
                            chosenTarget = target;
                        }
                    }

                    if (chosenTarget != null)
                    {
                        priority = 100;
                        action.setTarget(chosenTarget);
                        lastAttackedEnemyLocation = chosenTarget.getLocation();
                    }
                    else
                    {
                        // nothing to target
                    }

                    break;

                case "Smile":
                    priority = 0;
                    break;
            }

            // add the action to the collection of valid actions to perform
            if (priority >-1)
            {
                validActions.put(priority, action);
                actionString.put(priority, message);
            }

        }


        int highestPriority = -1;
        ReadonlyAction chosen = null;

        // choose the highest priority action
        for (Integer priority : validActions.keySet())
        {
            if (priority > highestPriority)
            {
                highestPriority = priority;
                chosen = validActions.get(priority);
            }
        }
        String message = actionString.get(highestPriority);

        if (chosen == null){
            throw new RuntimeException("No valid actions");
        }

        if (DEBUG) System.out.println(this+"("+System.identityHashCode(character)+"): "+chosen.getName()+ (rechargingMana?" Mana_charge":" Mana_usable")+" H: "+character.getHealth()+" M: "+character.getMana() +(character.isInvisible()?" InVis":" Vis") +" x: "+character.getLocation().getX()+" y: "+character.getLocation().getY()+" "+message);
        return chosen;
    }
}

फ़ाइल नाम CowardlySniperMk2 होना चाहिए :)
नाथन मेरिल

oops: पी कट और पेस्ट मुझे एक मूर्ख की तरह दिखता है!
Moogie


@KritiiLithos स्पलैटून के बांसबाज 14 Mk II की याद दिलाता है। ;)
टीएनटी

7

द वाकिंग डेड

लाश, हर कोई उन्हें जानता है। वे तब तक समूह में रहते हैं जब तक कोई कुछ नहीं दिखाता। उन्हें मारना कठिन है, और चाहे आप कितने भी मार लें, हमेशा अधिक होते हैं। और वे आमतौर पर आपकी पीठ के पीछे कहीं से बाहर दिखाई देते हैं।

  • 1 एक्स ज़ोंबी # 1 (सबसे मजबूत, और इसलिए अल्फा ज़ोंबी)
    • एसटीआर: 25; AGI: 5; INT: 15
    • क्लोन , पुनरुत्थान , मजबूत
  • 2 एक्स ज़ोंबी # 2 (कोई भी बंद क्रेडिट में ज़ोंबी # 3 नहीं बनना चाहता था, इसलिए दोनों को एक ही नंबर मिला)
    • एसटीआर: 15; AGI: 5; INT: 15
    • क्लोन , पुनरुत्थान , अवशोषण

आप अपनी टीम में यहां से एकल वर्णों का पुन: उपयोग कर सकते हैं, जब तक आप कम से कम एक और चरित्र जोड़ते हैं जो यहां मौजूद नहीं है।

TheWalkingDead.java
import java.util.Arrays;
import java.util.List;

import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Absorb;
import fellowship.abilities.defensive.Resurrect;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.other.Clone;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class TheWalkingDead extends SleafarPlayer {
    private CharacterTemplate zombie1Template() {
        return new CharacterTemplate(20, 0, 10, new ActionAbility(Clone::new), new Resurrect(), new Strong());
    }

    private CharacterTemplate zombie2Template() {
        return new CharacterTemplate(10, 0, 10, new ActionAbility(Clone::new), new Resurrect(), new Absorb());
    }

    @Override
    public List<CharacterTemplate> createCharacters() {
        return Arrays.asList(zombie1Template(), zombie2Template(), zombie2Template());
    }

    private class Zombie extends Character {
        private int resurrectCountdown = 0;
        private double oldHealth;

        protected Zombie(ReadonlyCharacter delegate) {
            super(delegate);
            this.oldHealth = getHealth();
        }

        @Override
        protected ReadonlyAction choose() {
            if (getHealth() > oldHealth + getHealthRegen() + 0.1) {
                resurrectCountdown = 40;
            }
            if (resurrectCountdown > 0) {
                --resurrectCountdown;
            }
            oldHealth = getHealth();

            ReadonlyAction clone = getAction(Clone.class);
            if (resurrectCountdown > 0) {
                if (step != null && isInEnemySliceRange() && setAvoidEnemiesLocation(step)) {
                    return step;
                }
                if (clone != null && !getSliceLocations().isEmpty() && setClosestLocation(clone, getSliceLocations())) {
                    return clone;
                }
                if (clone != null && setCloneLocation(clone, 1)) {
                    return clone;
                }
                if (slice != null && setSliceTarget(slice, 0.01)) {
                    return slice;
                }
                if (step != null && setAvoidEnemiesLocation(step)) {
                    return step;
                }
            } else {
                if (clone != null && !getSliceLocations().isEmpty() && setClosestLocation(clone, getSliceLocations())) {
                    return clone;
                }
                if (clone != null && setCloneLocation(clone, 1)) {
                    return clone;
                }
                if (slice != null && setSliceTarget(slice, 0.01)) {
                    return slice;
                }
                if (step != null && !getSliceLocations().isEmpty() && setClosestLocation(step, getSliceLocations())) {
                    return step;
                }
            }
            return smile;
        }
    }

    @Override
    protected Character createCharacter(ReadonlyCharacter delegate) {
        return new Zombie(delegate);
    }
}

मैं आपके बॉट्स को काम नहीं करवा सकता ... स्लिफ़र बेस क्लास एक फेलोशिप.चैचरर्स.चैचररइंटरफेस आयात करता है जो नवीनतम मास्टर शाखा में नहीं लगता ...
Moogie


7

The Invulnerables

हार्डी योद्धाओं की एक टीम जो लगभग हर चीज से बच सकती है। यह बहुत सारे टाइमआउट की ओर जाता है, जो दुर्भाग्य से मैं अक्सर नहीं जीत पाता। हालाँकि, मैंने जो भी मैचअप देखा है वह अपरिहार्य है, और जब टीम हार जाती है, तो यह अक्सर पात्रों के साथ रहता है।

इस टीम के सबसे कठिन मैचअप भालू कैवेलरी के खिलाफ हैं (वे सचमुच इस टीम को पोंछने में असमर्थ हैं, लेकिन आम तौर पर अपने सरासर संख्या के कारण टाईब्रेक पर जीत जाते हैं); दुष्ट दस्ते (टीम जहर के लिए कुछ कमजोर है); और वैम्पायर (मुझे पूरी तरह से यकीन नहीं है कि अभी तक क्यों)।

सिमुलेशन में, टीम लगभग हमेशा पहले या दूसरे नंबर पर आती है। इसका स्कोर बहुत स्थिर है; विजेता सामान्य रूप से इस बात पर निर्भर करता है कि दुष्ट स्क्वाड अन्य प्रतिस्पर्धियों के खिलाफ कितना अच्छा करता है (इसका प्लेसमेंट इनवॉल्वेंबल्स की तुलना में बहुत अधिक यादृच्छिक है)।

द मॉज इन द नॉक्सियस स्फीयर

  • एसटीआर : 5; AGI : 5; INT : 25

पिलर और फोर्स फील्ड के कॉम्बो का उपयोग करके द मैज खुद को बचाता है ; किया जा रहा केंद्रित और एक उच्च खुफिया होने, हर बार cooldown पर डाली फोर्स फील्ड करने के लिए पर्याप्त माना पुन: बनाता है। यह मानते हुए कि विरोधियों में चुस्ती-फुर्ती नहीं है, वे इस तरह से इसे हर पांच मोड़ पर अधिकतम पांच स्लाइस के साथ मार सकते हैं, और पांच क्षति स्रोतों को उस समय अवधि में अवरुद्ध कर दिया जाएगा। दूसरे शब्दों में, दाना को हार के लिए मंत्र की आवश्यकता होती है; Slicing अपने आप से काम नहीं करता है चाहे आप कितने भी अच्छे क्यों न हों।

द एमज एक आपात स्थिति में 25 के लिए स्लाइसिंग के माध्यम से हमला कर सकता है, लेकिन ज्यादातर बार ज़हर को बार-बार फेंक देता है, जो कि एक एमपी उत्थान के साथ बहुत अधिक है। क्योंकि पॉइज़न में एक अनंत सीमा होती है, जो केवल टीम की दृष्टि से सीमित होती है, मैज वह तरीका है जिससे यह टीम बहुत एचपी-भारी या पुनर्योजी दुश्मनों को हरा देती है; टीम के बाकी सदस्य उन पर दृष्टि बनाए रखते हैं, जबकि माजे चौपायों को नुकसान पहुंचाता है। जहर अनिवार्य रूप से अपने एचपी उत्थान को अंततः समाप्त कर देता है, और मुझे इस प्रक्रिया में स्पाइक्स जैसे स्थिर क्षति के बारे में चिंता करने की ज़रूरत नहीं है।

विशालकाय क्लिफ्टफॉप फाल्कनर

  • एसटीआर : 35; AGI : 5; INT : 5

फाल्कनर का मुख्य काम बाकी टीम के लक्ष्यों को प्राप्त करना है, ताकि उन पर हमला किया जा सके, ताकि वे बाज़ की आँखों से नक्शा निकाल सकें। सुदूर दृष्टि पर्याप्त दृष्टि देती है कि दुश्मन जो छिपने या भागने की कोशिश करते हैं, वे आमतौर पर मानचित्र के कोने में दृष्टि सीमा से फंस सकते हैं; फाल्कनर को रनवे देना बहुत आसान नहीं है। ट्रू साइट , अदृश्य दुश्मनों के खिलाफ इस टीम का मुख्य सहारा है, जो अन्यथा नुकसान पहुंचाना असंभव होगा। बड़े होने के नाते, और इस तरह मजबूत , फाल्कन को नुकसान के लिए बहुत प्रतिरोधी बनाता है, और जब आवश्यक हो तो भारी स्लाइस में सक्षम होता है। अंत में, बाज़ नीचे दुश्मन की भीड़ पर अपने बाज़ को जारी कर सकता है, उन्हें दुश्मन के बीच बुनने का आदेश दे सकता है और बड़े पैमाने पर (35) क्षेत्र को नुकसान पहुंचा सकता है।

फाल्कनर की नौकरी के अलावा, दुश्मनों का शिकार करना, और दुश्मनों की दृष्टि बनाए रखना ताकि मैज उन्हें जहर देते रहें, 35 के लिए कभी-कभी बुनाई की क्षमता दुश्मन झुंड टीमों से निपटने के लिए महत्वपूर्ण है; इस तरह से बहुत सारे दुश्मनों को मारना संभव है, और बाकी टीम को समाप्त करने के लिए उन्हें कम छोड़ दें (आदर्श रूप से एक और बुनाई के साथ)। झुंड इन नियमों के तहत बहुत अधिक रणनीति है, और बुनाई कुछ असली काउंटरों में से एक है। फिर भी, यह वास्तव में अपने आप में बहुत अच्छा नहीं है।

ट्रोलबोन खोपड़ी

  • एसटीआर : 25; AGI : 5; INT : 5

ट्रोलबोन का काम दुश्मन की भीड़ को दबाए रखना है जबकि अन्य इकाइयां अपना काम कर सकती हैं। बस दाना की तरह, Trollbone में एक अनंत दूरी जादू है नॉकआउट । यह कॉम्बो मैज के ज़हर के साथ बहुत अच्छी तरह से; यदि कभी भी दुश्मन का एक-एक करके सामना करना संभव है (और कई टीमों के खिलाफ, यह है), फाल्कनर दृष्टि प्राप्त करेगा, ट्रोलबोन उन्हें अचेत कर देगा, फिर दाना उन पर जहर ढेर कर देगा, और वे अंत में मर जाएंगे कुछ भी करने की क्षमता के बिना (नॉकआउट लक्ष्य पर 1000 टिक करता है और ट्रोलबोन ने इसके लिए कोल्डाउन को फिर से बढ़ा दिया है)। यह एकल मजबूत दुश्मनों के खिलाफ ट्रोलबोन की रक्षा करने में भी बहुत अच्छा है; अगर वे होश में नहीं हैं तो वे उसके लिए कुछ नहीं कर सकते। बेशक, एक दुश्मन के साथ खोपड़ी मुंहतोड़ जवाब देने के लिए उत्तरदायी है दोनों,अचेत करना और जहर (और अन्य स्थितियों का एक गुच्छा कोई भी परवाह नहीं करता है)। एक जादू-केंद्रित चरित्र के रूप में, जो फिर भी बहुत जादुई रूप से इच्छुक नहीं है, ट्रोलबोन जादू को बुद्धि के माध्यम से नहीं, बल्कि अपने दुश्मनों के खून पीने के माध्यम से, हर हिट के साथ मन चोरी कर रहा है ; यह एमपी उत्थान की एक बहुत अच्छी दर देता है (और स्तब्ध दुश्मन एमपी से चोरी करने के लिए आसान लक्ष्य बनाते हैं)। अंत में, ट्रोलबोन कभी-कभी एक क्रोध पर चला जाता है और दुश्मन रैंकों के माध्यम से बुनाई करेगा, जबकि अपने सिर को अंदर धकेल देगा और उनका खून पीएगा । दुश्मनों के पर्याप्त बड़े झुंड के खिलाफ, यह वास्तव में मैना को फिर से हासिल करता है, और यह एक झुंड को खत्म कर सकता है जो फाल्कनर कमजोर हो गया (25 + 35 60 है, इसलिए यह काम करता है, भले ही दुश्मनों के बीच कुछ हद तक पुनर्जीवित हो)।

रणनीति

कई टीमों के विपरीत, मैंने एआई में बहुत अधिक ध्यान केंद्रित किया, न कि केवल टीम बनाने के लिए। एक मौलिक नियम यह है कि टीम हमेशा समूह बनाने की कोशिश करेगी यदि वे कुछ और करने में व्यस्त नहीं हैं, जिससे उन्हें घेरना और एक दूसरे का बचाव करने में सक्षम होना मुश्किल हो जाता है। यदि वे झुंड में आ रहे हैं, तो वे एक कोने में छिपने की कोशिश करेंगे। दूसरी ओर, यदि दुश्मन भागने या भागने की कोशिश करता है, तो वे नक्शे को उठाते हैं, यादृच्छिक कोनों या केंद्र तक ले जाते हैं और रास्ते में आते हैं; यह कमोबेश इस बात की गारंटी है कि फाल्कनर अंततः एक लक्ष्य प्राप्त करेगा। आंदोलन को दुश्मन को कभी भी संभव नहीं होने देने के लिए तैयार किया गया है; दुश्मन को स्लाइस रेंज में चलना होगा। दाना हमेशा रहेगाफोर्स फील्ड के लिए सांसद को छोड़ दें, एमपी थकावट के नुकसान को रोकना (यह एकमात्र तरीका विफल हो सकता है, एब्सॉर्ब के साथ है, जो नुकसान नहीं होने पर भी फोर्स फील्ड के माध्यम से प्राप्त कर सकता है)। यह आमतौर पर एक समस्या नहीं है; आमतौर पर दाना बिना किसी मुद्दे के हर मोड़ पर ज़हर को स्पैम कर सकता है। अगर साथ नहीं दिया जाता है, तो टीम एक समय में दुश्मनों का पीछा करना पसंद करती है, जब वे दृष्टि में आते हैं, तो उन्हें तेजस्वी बनाते हैं, फिर उन्हें तब तक जहर देते हैं जब तक कि वे मर नहीं जाते। चारों ओर अन्य दुश्मनों के साथ, यदि संभव हो तो टीम उन्हें पतंग करने की कोशिश करेगी, हलकों में चारों ओर चल रही है और अधिकांश दुश्मनों का पीछा करने के लिए मजबूर कर रही है, जबकि आश्चर्यजनक और उनमें से एक को जहर दे रही है। मुख्य समस्या स्वार्स के साथ है, यही वजह है कि यहां बहुत बुनाई होती है, लेकिन फिर भी वास्तव में रणनीति को हरा पाना कठिन लगता है।

Invulnerables.java
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.*;
import fellowship.abilities.attacking.*;
import fellowship.abilities.defensive.*;
import fellowship.abilities.vision.*;
import fellowship.abilities.stats.*;
import fellowship.abilities.statuses.*;
import fellowship.actions.*;
import fellowship.actions.attacking.*;
import fellowship.actions.damage.*;
import fellowship.actions.defensive.*;
import fellowship.actions.statuses.*;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.characters.EnemyCharacter;
import fellowship.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class Invulnerables extends Player {
  @Override
  public List<CharacterTemplate> createCharacters() {
    List<CharacterTemplate> templates = new ArrayList<>();

    templates.add(new CharacterTemplate(0, 0, 20,
                                        new ActionAbility(Poison::new),
                                        new ActionAbility(ForceField::new),
                                        new Focused(),
                                        new Pillar()));

    templates.add(new CharacterTemplate(30, 0, 0,
                                        new ActionAbility(Weave::new),
                                        new Strong(),
                                        new FarSight(),
                                        new TrueSight()));

    templates.add(new CharacterTemplate(20, 0, 0,
                                        new ActionAbility(Weave::new),
                                        new ActionAbility(Knockout::new),
                                        new ManaSteal(),
                                        new Immune()));

    return templates;
  }

  private String lastIdentifier(String s) {
    String[] split = s.split("\\W");
    return split[split.length - 1];
  }

  private boolean hasAbility(ReadonlyCharacter character, String abilityName) {
    for (ReadonlyAbility ability : character.getAbilities()) {
      if (lastIdentifier(ability.name()).equals(abilityName))
        return true;
    }
    return false;
  }

  private boolean hasAbility(EnemyCharacter character, String abilityName) {
    for (ReadonlyAbility ability : character.getAbilities()) {
      if (lastIdentifier(ability.name()).equals(abilityName))
        return true;
    }
    return false;
  }

  private int getSquareDanger(ReadonlyCharacter character, Point2D square) {
    /* A square's danger is basically equal to the number of hits we'd
       expect to take when standing there. Each hit is worth 1; a hit of
       25 damage or more is worth 2. */
    int sliceDanger = 0;
    int otherDanger = 0;
    int cx = square.getX();
    int cy = square.getY();
    for (Point2D enemyLocation : visibleEnemies.keysView()) {
      EnemyCharacter enemy = visibleEnemies.get(enemyLocation);
      if (enemy.isStunned())
        continue; /* approaching stunned enemies is a good thing */
      int dx = enemyLocation.getX() - cx;
      int dy = enemyLocation.getY() - cy;
      if (dx < 0)
        dx = -dx;
      if (dy < 0)
        dy = -dy;
      if (dx + dy <= 1) {
        /* We're in Static range. */
        if (hasAbility(enemy, "Static"))
          otherDanger++;
      }
      if (dx + dy <= enemy.getSliceRange().getRange() &&
          (dx * dy == 0 || !enemy.getSliceRange().isCardinal())) {
        int sliceMultiplier = 1;
        if (hasAbility(enemy, "Quick") && !hasAbility(character, "Pillar"))
          sliceMultiplier *= 2;
        if (enemy.getStat(enemy.primaryStat()) >= 25)
          sliceMultiplier *= 2;
        if (hasAbility(character, "Pillar")) {
          if (sliceDanger >= sliceMultiplier)
            continue;
          sliceDanger = 0;
        }
        sliceDanger += sliceMultiplier;
      }
    }
    return sliceDanger + otherDanger;
  }

  private ReadonlyAction[] forceFieldAction = new ReadonlyAction[3];
  private int goalX = 5;
  private int goalY = 5;

  @Override
  public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {

    /* Which character are we? */
    int characterNumber;
    if (hasAbility(character, "Focused"))
      characterNumber = 0;
    else if (hasAbility(character, "Immune"))
      characterNumber = 1;
    else if (hasAbility(character, "TrueSight"))
      characterNumber = 2;
    else
      throw new RuntimeException("Unrecognised character!");

    /* If we're at the goal square, pick a new one. */
    if (goalX == character.getLocation().getX() &&
        goalY == character.getLocation().getY()) {
      int i = getRandom().nextInt(5);
      goalX = i < 2 ? 1 : i > 2 ? 9 : 5;
      goalY = i == 2 ? 5 : (i % 2) == 1 ? 1 : 9;
    }

    /* If there are a lot of visible enemies, try to group up in a corner in order
       to prevent being surrounded. */
    if (visibleEnemies.size() > 3) {
      int xVotes = 0;
      int yVotes = 0;
      for (ReadonlyCharacter ally : team) {
        xVotes += ally.getLocation().getX() >= 5 ? 1 : -1;
        yVotes += ally.getLocation().getY() >= 5 ? 1 : -1;
      }
      goalX = xVotes > 0 ? 9 : 0;
      goalY = yVotes > 0 ? 9 : 0;
    }

    /* We need to know our Force Field cooldowns even between turns, so store the
       actions in a private field for later use (they aren't visible via the API) */
    for (ReadonlyAction action : actions) {
      if (action.getName().equals("ForceField"))
        forceFieldAction[characterNumber] = action;
    }

    /* If we know Force Field, ensure we always hang on to enough mana to cast it, and
       never allow our mana to dip low enough that it wouldn't regenerate in time. */
    double mpFloor = 0.0;
    if (forceFieldAction[characterNumber] != null) {
      double mpRegen = character.getStat(Stat.INT) / 10.0;
      if (hasAbility(character, "Focused"))
        mpRegen *= 2;
      mpFloor = forceFieldAction[characterNumber].getManaCost();
      mpFloor -= forceFieldAction[characterNumber].getRemainingCooldown() * mpRegen;
    }
    if (mpFloor > character.getMana())
      mpFloor = character.getMana();

    /* We use a priority rule for actions. */
    int bestPriority = -2;
    ReadonlyAction bestAction = null;
    for (ReadonlyAction action : actions) {
      int priority = 0;
      if (lastIdentifier(action.getName()).equals("ForceField"))
        priority = 20; /* top priority */
      else if (character.getMana() - action.getManaCost() < mpFloor) {
        continue; /* never spend mana if it'd block a force field */
      } else if (lastIdentifier(action.getName()).equals("Quick") ||
                 lastIdentifier(action.getName()).equals("Slice")) {
        int damagePotential =
          lastIdentifier(action.getName()).equals("Quick") ? 50 : 25;
        /* We use these abilities with very high priority to /kill/ an enemy
           who's weak enough to die from the damage. If they wouldn't die,
           we're much more wary about attacking; we do it only if we have
           nothing better to do and it's safe. */
        ReadonlyCharacter chosenTarget = null;
        for (ReadonlyCharacter target : action.availableTargets()) {
          if (!isEnemy(target))
            continue;
          if (target.getHealth() <= damagePotential) {
            chosenTarget = target;
            priority = (damagePotential == 25 ? 19 : 18);
            break; /* can't do beter than this */
          }
          if (hasAbility(target, "Spikes") ||
              hasAbility(target, "Reflexive"))
            /*  (target.getLastAction() != null &&
                target.getLastAction().getName().equals("Ghost")) */
            continue; /* veto the target */
          priority = (damagePotential == 25 ? 3 : 4);
          chosenTarget = target;
        }
        if (chosenTarget == null)
          continue;
        action.setTarget(chosenTarget);
      } else if (lastIdentifier(action.getName()).equals("Weave")) {
        priority = visibleEnemies.size() >= 3 ? 14 :
          visibleEnemies.size() >= 1 ? 6 : -1;
      } else if (lastIdentifier(action.getName()).equals("Smile")) {
        /* If there's a stunned or poisoned enemy in view, we favour Smile
           as the idle action, rather than exploring, so that we don't
           move it out of view. Exception: if they're the only enemy;
           in that case, hunt them down. Another exception: if we're
           running into a corner. */
        for (EnemyCharacter enemy : visibleEnemies) {
          if (enemy.isStunned() || enemy.isPoisoned())
            if (visibleEnemies.size() > 1 && visibleEnemies.size() < 4)
              priority = 2;
        }
        /* otherwise we leave it as 0, and Smile only as a last resort */
      } else if (lastIdentifier(action.getName()).equals("Knockout")) {
        /* Use this only on targets who have more than 50 HP. It doesn't
           matter where they are: if we can see them now, knocking them
           out will guarantee we can continue to see them. Of course, if
           they're already knocked out, don't use it (although this case
           should never come up). If there's only one enemy target in
           view, knocking it out has slightly higher priority, because
           we don't need to fear enemy attacks if all the enemies are
           knocked out.

           Mildly favour stunning poisoned enemies; this reduces the
           chance that they'll run out of sight and reset the poison. */
        ReadonlyCharacter chosenTarget = null;
        for (ReadonlyCharacter target : action.availableTargets())
          if ((target.getHealth() > 50 || target.isPoisoned()) &&
              !target.isStunned() && isEnemy(target)) {
            chosenTarget = target;
            if (target.isPoisoned())
              break;
          }
        if (chosenTarget == null)
          continue;
        action.setTarget(chosenTarget);
        priority = visibleEnemies.size() == 1 ? 17 : 15;
      } else if (lastIdentifier(action.getName()).equals("Poison")) {
        /* Use this preferentially on stronger enemies, and preferentially
           on enemies who are more poisoned. We're willing to poison
           almost anyone, although weak enemies who aren't poisoned
           are faster to kill via slicing. The cutoff is at 49, not 50,
           so that in the case of evasive enemies who we can't hit any
           other way, we can wear them one at a time using poison. */
        ReadonlyCharacter chosenTarget = null;
        int chosenTargetPoisonLevel = -1;
        for (ReadonlyCharacter target : action.availableTargets()) {
          int poisonLevel = 0;

          if (!isEnemy(target))
            continue;
          if (target.isPoisoned())
            poisonLevel = target.getPoisonAmount() + 1;
          if (poisonLevel < chosenTargetPoisonLevel)
            continue;
          if (poisonLevel == 0 && target.getHealth() <= 49)
            continue; /* prefer stronger targets */
          if (poisonLevel == 0 && target.getHealth() == 50 &&
              chosenTarget != null)
            continue; /* we poison at 50, but not with other options */
          chosenTarget = target;
          chosenTargetPoisonLevel = poisonLevel;
          priority = 12;
        }
        if (chosenTarget == null)
          continue;
        action.setTarget(chosenTarget);
      } else if (action.movementAction()) {
        /* A move to a significantly safer square is worth 16.
           A move to a mildly safer square is worth 8.
           Otherwise, move to group, either with the enemy,
           the team, or the goal, at priority 1, if we
           safely can; that's our "idle" action. */
        int currentSquareDanger =
          getSquareDanger(character, character.getLocation());
        int bestSquareDanger = currentSquareDanger;
        int bestGroupiness = 0;
        Point2D bestLocation = null;
        priority = 1;
        for (Point2D location :
               action.availableLocations().toList().shuffleThis(getRandom())) {
          int danger = getSquareDanger(character, location);
          if (danger > bestSquareDanger)
            continue;
          else if (danger < bestSquareDanger) {
            priority = (currentSquareDanger - danger > 2)
              ? 16 : 8;
            bestSquareDanger = danger;
            bestLocation = location;
            bestGroupiness = 0; /* reset the tiebreak */
          }

          int cx = character.getLocation().getX();
          int xDelta = location.getX() - cx;
          int cy = character.getLocation().getY();
          int yDelta = location.getY() - cy;
          int groupiness = 0;
          /* Always hunt down a visible enemy when they're the only
             remaining enemy and doing so is safe. Otherwise, still
             favour hunting them down, but in that situation also
             consider factors like grouping and exploration. */
          for (Point2D enemyLocation : visibleEnemies.keysView())
            if (xDelta * (enemyLocation.getX() - cx) > 0 ||
                yDelta * (enemyLocation.getY() - cy) > 0)
              groupiness += (visibleEnemies.size() == 1 ? 99 : 5);
          /* If there are 4 or more visible enemies, then grouping is
             vitally important (so as to not get surrounded).
             Otherwise, it's more minor. */
          for (ReadonlyCharacter ally : team)
            if (xDelta * (ally.getLocation().getX() - cx) > 0 ||
                yDelta * (ally.getLocation().getY() - cy) > 0)
              groupiness += (visibleEnemies.size() > 3 ? 99 : 3);
          /* When exploring, we bias towards random map locations,
             changing location when we reach them. This helps us beat
             enemies that hide in the corners. When there are a lot
             of visible enemies, this changes to a bias to hide in a
             corner. */
          if (xDelta * (goalX - cx) > 0 ||
              yDelta * (goalY - cy) > 0)
            groupiness += (visibleEnemies.size() > 3 ? 99 : 4);
          if (groupiness >= bestGroupiness) {
            bestLocation = location;
            bestGroupiness = groupiness;
            /* leave priority, safety untouched */
          }
        }
        if (bestLocation == null)
          continue;
        action.setLocation(bestLocation);
      } else
        throw new RuntimeException("unknown action" + action.getName());

      if (priority > bestPriority) {
        bestPriority = priority;
        bestAction = action;
      }
    }
    if (bestAction == null)
      throw new RuntimeException("no action?");

    return bestAction;
  }
}

बहुत प्रभावी :) तेजस्वी एक प्रभावी रणनीति की तरह लग रहा है!
मोगी

ForceField के साथ आपके चरित्र को मेरे Noobs द्वारा नहीं हराया जा सकता है, भले ही इसका केवल 50 स्वास्थ्य हो!
कृति लिथोस २६'१६

एक बग तय किया जो @Sleafar ने बताया।

मुझे लगता है कि आप अपने फल्कोनर और trollbone पर कुछ भी कई skillpoints कर रहे हैं
Eumel

निश्चित भी। यह विवरण में सिर्फ एक टाइपो था, कोड सही था।

7

RogueSquad

एक बदमाश दस्ते में शामिल हैं:

  • 1 स्काउट (नक्शे की खोज करते समय छाया में रहता है)
    • एसटीआर: 5; AGI: 5; INT: 25
    • क्लोन , अदृश्य , दूर दृष्टि
  • 2 हत्यारे (घातक जहर के साथ दुश्मन पर हमला)
    • एसटीआर: 5; AGI: 5; INT: 25
    • क्लोन , पॉइज़न , फोकस्ड

दोनों अब तक की सबसे बड़ी शक्ति का उपयोग कर सकते हैं, उन्हें समर्थन देने के लिए दस्ते के अतिरिक्त सदस्यों को बुलाना है।

आप अपनी टीम में यहां से एकल वर्णों का पुन: उपयोग कर सकते हैं, जब तक आप कम से कम एक और चरित्र जोड़ते हैं जो यहां मौजूद नहीं है।

RogueSquad.java
import java.util.Arrays;
import java.util.List;

import fellowship.abilities.ActionAbility;
import fellowship.abilities.stats.Focused;
import fellowship.abilities.vision.FarSight;
import fellowship.abilities.vision.Invisible;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.other.Clone;
import fellowship.actions.statuses.Poison;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class RogueSquad extends SleafarPlayer {
    private CharacterTemplate scoutTemplate() {
        return new CharacterTemplate(0, 0, 20,
                new ActionAbility(Clone::new), new Invisible(), new FarSight());
    }

    private CharacterTemplate assasinTemplate() {
        return new CharacterTemplate(0, 0, 20,
                new ActionAbility(Clone::new), new ActionAbility(Poison::new), new Focused());
    }

    @Override
    public List<CharacterTemplate> createCharacters() {
        return Arrays.asList(assasinTemplate(), scoutTemplate(), assasinTemplate());
    }

    private class Scout extends Character {
        protected Scout(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction clone = getAction(Clone.class);
            if (clone != null && (isVisible() || !isInEnemySightRange()) && setCloneLocation(clone, 3)) {
                return clone;
            }
            if (step != null && isVisible() && isInEnemySliceRange() && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (slice != null && isVisible() && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null && isVisible() && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (step != null && !isVisible() && setExploreLocation(step)) {
                return step;
            }
            return smile;
        }
    }

    private class Assasin extends Character {
        protected Assasin(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction clone = getAction(Clone.class);
            ReadonlyAction poison = getAction(Poison.class);
            if (clone != null && setCloneLocation(clone, 1)) {
                return clone;
            }
            if (step != null && isInEnemySliceRange() && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (poison != null && setPoisonTarget(poison)) {
                return poison;
            }
            if (step != null && setAvoidEnemiesLocation(step)) {
                return step;
            }
            return smile;
        }
    }

    @Override
    protected Character createCharacter(ReadonlyCharacter delegate) {
        if (hasAbility(delegate, Invisible.class)) {
            return new Scout(delegate);
        } else if (hasAbility(delegate, Poison.class)) {
            return new Assasin(delegate);
        } else {
            throw new IllegalArgumentException();
        }
    }
}

मेरे सभी बॉट्स के लिए बेस क्लास

SleafarPlayer.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.api.set.MutableSet;
import org.eclipse.collections.api.tuple.Pair;
import org.eclipse.collections.impl.factory.Maps;
import org.eclipse.collections.impl.factory.Sets;
import org.eclipse.collections.impl.list.primitive.IntInterval;
import org.eclipse.collections.impl.tuple.Tuples;

import com.nmerrill.kothcomm.game.maps.Point2D;

import fellowship.Player;
import fellowship.Range;
import fellowship.abilities.ReadonlyAbility;
import fellowship.abilities.attacking.Critical;
import fellowship.abilities.attacking.Reflexive;
import fellowship.abilities.defensive.Spikes;
import fellowship.abilities.statuses.Immune;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.actions.attacking.Slice;
import fellowship.actions.mobility.Step;
import fellowship.actions.other.Smile;
import fellowship.characters.CharacterInterface;
import fellowship.characters.EnemyCharacter;
import fellowship.characters.ReadonlyCharacter;

public abstract class SleafarPlayer extends Player {
    private static final ImmutableSet<Point2D> MAP_LOCATIONS = IntInterval.fromTo(0, 9)
            .collect(x -> IntInterval.fromTo(0, 9).collect(y -> new Point2D(x, y))).flatCollect(t -> t).toSet()
            .toImmutable();
    protected static final Comparator<CharacterInterface> HEALTH_COMPARATOR = (o1, o2) ->
            Double.compare(o1.getHealth(), o2.getHealth());
    private static final Range BLOCKING_RANGE = new Range(1, true);
    private static final Range STATIC_RANGE = new Range(1);

    protected static boolean hasAbility(CharacterInterface character, Class<?> ability) {
        return character.getAbilities().anySatisfy(a -> a.abilityClass().equals(ability));
    }

    protected static boolean isBear(CharacterInterface character) {
        return character.getAbilities().isEmpty();
    }

    protected static double calcSliceDamage(CharacterInterface character) {
        return character.getStat(character.primaryStat()) * (hasAbility(character, Quick.class) ? 2.0 : 1.0);
    }

    protected static boolean setLocation(ReadonlyAction action, Point2D location) {
        if (location != null) {
            action.setLocation(location);
        }
        return location != null;
    }

    protected static boolean setTarget(ReadonlyAction action, ReadonlyCharacter target) {
        if (target != null) {
            action.setTarget(target);
        }
        return target != null;
    }

    protected abstract class Character {
        protected final ReadonlyCharacter delegate;

        protected Character(ReadonlyCharacter delegate) {
            super();
            this.delegate = delegate;
        }

        protected abstract ReadonlyAction choose();

        protected double getHealth() {
            return delegate.getHealth();
        }

        protected double getHealthRegen() {
            return delegate.getHealthRegen();
        }

        protected double getMana() {
            return delegate.getMana();
        }

        protected double getManaRegen() {
            return delegate.getManaRegen();
        }

        protected Point2D getLocation() {
            return delegate.getLocation();
        }

        protected boolean isVisible() {
            return !delegate.isInvisible();
        }

        protected double getSliceDamage() {
            return delegate.getStat(delegate.primaryStat());
        }

        protected boolean isInEnemySliceRange() {
            return getEnemySliceLocations().contains(delegate.getLocation());
        }

        protected boolean isInEnemySightRange() {
            return getEnemySightLocations().contains(delegate.getLocation());
        }

        protected boolean isInEnemyStepSightRange() {
            return getEnemyStepSightLocations().contains(delegate.getLocation());
        }

        protected double calcSliceRetaliationDamage(CharacterInterface character) {
            double result = 0.0;
            double ownDamage = getSliceDamage();
            for (ReadonlyAbility ability : character.getAbilities()) {
                if (ability.abilityClass().equals(Critical.class)) {
                    ownDamage = ownDamage * 2;
                }
            }
            for (ReadonlyAbility ability : character.getAbilities()) {
                if (ability.abilityClass().equals(Spikes.class)) {
                    result += ownDamage / 2.0;
                } else if (ability.abilityClass().equals(Reflexive.class)) {
                    result += character.getStat(character.primaryStat());
                }
            }
            return result;
        }

        protected double calcSpellRetaliationDamage(CharacterInterface character, double ownDamage) {
            double result = 0.0;
            for (ReadonlyAbility ability : character.getAbilities()) {
                if (ability.abilityClass().equals(Spikes.class)) {
                    result += ownDamage / 2.0;
                }
            }
            return result;
        }

        protected boolean setRandomLocation(ReadonlyAction action) {
            return setLocation(action, chooseRandom(action.availableLocations()));
        }

        protected boolean setRandomLocation(ReadonlyAction action, ImmutableSet<Point2D> avoidLocations) {
            return setLocation(action, chooseRandom(action.availableLocations().difference(avoidLocations)));
        }

        protected boolean setClosestLocation(ReadonlyAction action, ImmutableSet<Point2D> targetLocations) {
            return setLocation(action, chooseClosest(action.availableLocations(), targetLocations));
        }

        protected boolean setClosestLocation(ReadonlyAction action, ImmutableSet<Point2D> avoidLocations,
                ImmutableSet<Point2D> targetLocations) {
            return setLocation(action, chooseClosest(action.availableLocations().difference(avoidLocations),
                    targetLocations));
        }

        protected boolean setClosestHiddenLocation(ReadonlyAction action, ImmutableSet<Point2D> preferredLocations) {
            return setClosestLocation(action, getEnemySightLocations(), preferredLocations);
        }

        protected boolean setClosestSafeLocation(ReadonlyAction action, ImmutableSet<Point2D> preferredLocations) {
            return setClosestLocation(action, getEnemySliceLocations(), preferredLocations);
        }

        protected boolean setFarthestLocation(ReadonlyAction action, ImmutableSet<Point2D> targetLocations) {
            return setLocation(action, chooseFarthest(action.availableLocations(), targetLocations));
        }

        protected boolean setFarthestLocation(ReadonlyAction action, ImmutableSet<Point2D> avoidLocations,
                ImmutableSet<Point2D> targetLocations) {
            return setLocation(action, chooseFarthest(action.availableLocations().difference(avoidLocations),
                    targetLocations));
        }

        public boolean setCloneLocation(ReadonlyAction action, int distance) {
            ImmutableSet<Point2D> cloneLocations = distance < 2 ? team.collect(t -> t.getLocation()).toImmutable() :
                team.flatCollect(t -> t.rangeAround(new Range(distance))).difference(
                team.flatCollect(t -> t.rangeAround(new Range(distance - 1)))).toImmutable();
            if (cloneLocations.isEmpty()) {
                return setRandomLocation(action, getEnemySightLocations()) ||
                        setRandomLocation(action, getEnemySliceLocations()) ||
                        setRandomLocation(action);
            } else {
                return setClosestLocation(action, getEnemySightLocations(), cloneLocations) ||
                        setClosestLocation(action, getEnemySliceLocations(), cloneLocations) ||
                        setClosestLocation(action, cloneLocations);
            }
        }

        protected boolean setAvoidEnemiesLocation(ReadonlyAction action) {
            Point2D location = chooseFarthest(Sets.mutable.ofAll(action.availableLocations())
                    .with(delegate.getLocation()).difference(getEnemySliceLocations()), getEnemyLocations());
            if (location == null || location.equals(delegate.getLocation())) {
                return false;
            } else {
                return setLocation(action, location);
            }
        }

        protected boolean setBlockEnemiesLocation(ReadonlyAction action) {
            return setLocation(action, chooseRandom(action.availableLocations().intersect(getEnemyBlockingLocations())));
        }

        protected boolean setExploreLocation(ReadonlyAction action) {
            return visibleEnemies.size() < enemies.size() && getTeamHiddenLocations().notEmpty() &&
                    setClosestLocation(action, getEnemyStepSightLocations(), getTeamHiddenLocations());
        }

        protected boolean setSliceTarget(ReadonlyAction action, double minHealthReserve) {
            MutableSet<Pair<ReadonlyCharacter, Double>> pairs = action.availableTargets()
                    .collect(t -> Tuples.pair(t, calcSliceRetaliationDamage(t)));
            Pair<ReadonlyCharacter, Double> smallest = chooseSmallest(pairs, (o1, o2) -> {
                int c = Double.compare(o1.getTwo(), o2.getTwo());
                return c == 0 ? Double.compare(o1.getOne().getHealth(), o2.getOne().getHealth()) : c;
            });
            if (smallest == null || smallest.getTwo() > delegate.getHealth() - minHealthReserve) {
                return false;
            } else {
                return setTarget(action, smallest.getOne());
            }
        }

        protected boolean setPoisonTarget(ReadonlyAction action) {
            return setTarget(action, chooseSmallest(action.availableTargets().reject(c -> hasAbility(c, Immune.class)),
                    HEALTH_COMPARATOR));
        }

        protected final ImmutableSet<Point2D> getEnemyLocations() {
            if (enemyLocations == null) {
                enemyLocations = visibleEnemies.keysView().toSet().toImmutable();
            }
            return enemyLocations;
        }

        protected final ImmutableSet<Point2D> getEnemySliceLocations() {
            if (enemySliceLocations == null) {
                enemySliceLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> c.getTwo().rangeAround(c.getTwo().getSliceRange(), c.getOne())).toSet()
                        .toImmutable();
            }
            return enemySliceLocations;
        }

        protected final ImmutableSet<Point2D> getEnemySightLocations() {
            if (enemySightLocations == null) {
                enemySightLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> c.getTwo().rangeAround(c.getTwo().getSightRange(), c.getOne())).toSet()
                        .toImmutable();
            }
            return enemySightLocations;
        }

        protected final ImmutableSet<Point2D> getEnemyStepSightLocations() {
            if (enemyStepSightLocations == null) {
                enemyStepSightLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> Sets.mutable.ofAll(c.getTwo().rangeAround(c.getTwo().getStepRange(), c.getOne()))
                                .with(c.getOne()).flatCollect(r -> c.getTwo().rangeAround(c.getTwo().getSightRange(), r)))
                        .toSet().toImmutable();
            }
            return enemyStepSightLocations;
        }

        protected final ImmutableSet<Point2D> getEnemyHiddenLocations() {
            if (enemyHiddenLocations == null) {
                enemyHiddenLocations = MAP_LOCATIONS.difference(getEnemySightLocations());
            }
            return enemyHiddenLocations;
        }

        protected final ImmutableSet<Point2D> getEnemyBlockingLocations() {
            if (enemyBlockingLocations == null) {
                enemyBlockingLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> c.getTwo().rangeAround(BLOCKING_RANGE, c.getOne())).toSet().toImmutable();
            }
            return enemyBlockingLocations;
        }

        protected final ImmutableSet<Point2D> getTeamHiddenLocations() {
            if (teamHiddenLocations == null) {
                teamHiddenLocations = MAP_LOCATIONS.difference(team.flatCollect(c -> c.rangeAround(c.getSightRange())));
            }
            return teamHiddenLocations;
        }

        protected final ImmutableSet<Point2D> getTeamBlockingLocations() {
            if (teamBlockingLocations == null) {
                teamBlockingLocations = team.flatCollect(c -> c.rangeAround(BLOCKING_RANGE)).toImmutable();
            }
            return teamBlockingLocations;
        }

        protected final ImmutableSet<Point2D> getSliceLocations() {
            if (sliceLocations == null) {
                sliceLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> c.getTwo().rangeAround(delegate.getSliceRange(), c.getOne())).toSet().toImmutable();
            }
            return sliceLocations;
        }

        protected final ImmutableSet<Point2D> getStaticLocations() {
            if (staticLocations == null) {
                staticLocations = visibleEnemies.keyValuesView()
                        .flatCollect(c -> c.getTwo().rangeAround(STATIC_RANGE, c.getOne())).toSet().toImmutable();
            }
            return staticLocations;
        }

        protected final ImmutableMap<Point2D, Double> getEnemySliceDamage() {
            if (enemySliceDamage == null) {
                MutableMap<Point2D, Double> tmp = MAP_LOCATIONS.toMap(l -> l, l -> 0.0);
                for (Pair<Point2D, EnemyCharacter> p : visibleEnemies.keyValuesView()) {
                    double damage = calcSliceDamage(p.getTwo());
                    for (Point2D l : p.getTwo().rangeAround(p.getTwo().getSliceRange(), p.getOne())) {
                        tmp.put(l, tmp.get(l) + damage);
                    }
                }
                enemySliceDamage = tmp.toImmutable();
            }
            return enemySliceDamage;
        }
    }

    protected ImmutableMap<ReadonlyCharacter, Character> characters = Maps.immutable.empty();

    private ImmutableMap<Class<?>, ReadonlyAction> actions = null;
    protected ReadonlyAction step = null;
    protected ReadonlyAction slice = null;
    protected ReadonlyAction smile = null;

    private ImmutableSet<Point2D> enemyLocations = null;
    private ImmutableSet<Point2D> enemySliceLocations = null;
    private ImmutableSet<Point2D> enemySightLocations = null;
    private ImmutableSet<Point2D> enemyStepSightLocations = null;
    private ImmutableSet<Point2D> enemyHiddenLocations = null;
    private ImmutableSet<Point2D> enemyBlockingLocations = null;
    private ImmutableSet<Point2D> teamHiddenLocations = null;
    private ImmutableSet<Point2D> teamBlockingLocations = null;
    private ImmutableSet<Point2D> sliceLocations = null;
    private ImmutableSet<Point2D> staticLocations = null;
    private ImmutableMap<Point2D, Double> enemySliceDamage = null;

    protected final <T> T chooseRandom(Collection<T> collection) {
        if (!collection.isEmpty()) {
            int i = getRandom().nextInt(collection.size());
            for (T t : collection) {
                if (i == 0) {
                    return t;
                }
                --i;
            }
        }
        return null;
    }

    protected final <T> T chooseSmallest(Collection<T> collection, Comparator<? super T> comparator) {
        if (!collection.isEmpty()) {
            List<T> list = new ArrayList<>();
            for (T t : collection) {
                if (list.isEmpty()) {
                    list.add(t);
                } else {
                    int c = comparator.compare(t, list.get(0));
                    if (c < 0) {
                        list.clear();
                    }
                    if (c <= 0) {
                        list.add(t);
                    }
                }
            }
            return list.get(getRandom().nextInt(list.size()));
        }
        return null;
    }

    protected final Point2D chooseClosest(Collection<Point2D> available, RichIterable<Point2D> targets) {
        if (targets.isEmpty()) {
            return chooseRandom(available);
        } else {
            Map<Point2D, Integer> map = new HashMap<>();
            for (Point2D a : available) {
                map.put(a, targets.collect(t -> t.cartesianDistance(a)).min());
            }
            return chooseSmallest(available, (o1, o2) -> Integer.compare(map.get(o1), map.get(o2)));
        }
    }

    protected final Point2D chooseFarthest(Collection<Point2D> available, RichIterable<Point2D> targets) {
        if (targets.isEmpty()) {
            return chooseRandom(available);
        } else {
            Map<Point2D, Integer> map = new HashMap<>();
            for (Point2D a : available) {
                map.put(a, targets.collect(t -> t.cartesianDistance(a)).min());
            }
            return chooseSmallest(available, (o1, o2) -> Integer.compare(map.get(o2), map.get(o1)));
        }
    }

    protected int countCharacters(Class<?> clazz) {
        return characters.count(c -> c.getClass().equals(clazz));
    }

    protected ReadonlyAction getAction(Class<?> clazz) {
        return actions.get(clazz);
    }

    protected abstract Character createCharacter(ReadonlyCharacter delegate);

    @Override
    public final ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        characters = team.collect(c -> characters.getIfAbsentWith(c, this::createCharacter, c))
                .groupByUniqueKey(c -> c.delegate).toImmutable();

        this.actions = Sets.immutable.ofAll(actions).groupByUniqueKey(ReadonlyAction::actionClass);
        step = getAction(Step.class);
        slice = getAction(Slice.class);
        smile = getAction(Smile.class);

        enemyLocations = null;
        enemySliceLocations = null;
        enemySightLocations = null;
        enemyStepSightLocations = null;
        enemyHiddenLocations = null;
        enemyBlockingLocations = null;
        teamHiddenLocations = null;
        teamBlockingLocations = null;
        sliceLocations = null;
        staticLocations = null;
        enemySliceDamage = null;

        return characters.get(character).choose();
    }
}

अच्छी तरह से किया। हरा करने के लिए एक कठिन टीम ... चुनौती स्वीकार की गई: P
Moogie

6

पिशाच

मैं इसके लिए नया हूं और मुझे यकीन नहीं है कि मुझे पता है कि मैं क्या कर रहा हूं, लेकिन मुझे लगा कि यह दिलचस्प लग रहा है, इसलिए यहां मेरा प्रयास है।

पिशाच दुश्मनों को खोजते हैं और सबसे कमजोर लोगों को निशाना बनाते हैं, उनसे जीवन को सूखा देते हैं, जबकि मजबूत होते हुए और अपने स्वयं के स्वास्थ्य को पुनः प्राप्त करते हुए, अपने अगले शिकार पर जाने के लिए तैयार होते हैं। क्या उन्हें महत्वपूर्ण रूप से घायल होना चाहिए, वे तब तक दूर जाने का प्रयास करेंगे जब तक कि उनकी प्राकृतिक पुनर्जनन स्थिति से लड़ने की स्थिति में उन्हें पुनर्स्थापित नहीं किया जाता।

का उपयोग करते हुए को सोखना , पर्व , पुनः उत्पन्न , मजबूत में सब कुछ के साथ एसटीआर

Vampire.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Absorb;
import fellowship.abilities.attacking.Feast;
import fellowship.abilities.stats.Strong;
import fellowship.abilities.stats.Regenerate;
import fellowship.actions.ReadonlyAction;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.Player;
import org.eclipse.collections.api.set.MutableSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class Vampire extends Player{
    private final double CRITICAL_HEALTH = 5;
    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(30, 0, 0,
                    new Absorb(),
                    new Feast(),
                    new Regenerate(),
                    new Strong()));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        int minPriority = Integer.MAX_VALUE;
        ReadonlyAction chosen = null;
        for (ReadonlyAction action: actions){
            int priority = getPriorityFor(action, character);
            if (priority < minPriority){
                chosen = action;
                minPriority = priority;
            }
        }
        if (chosen == null){
            throw new RuntimeException("No valid actions");
        }
        if (chosen.needsLocation()){
            chosen.setLocation(chooseLocationFor(chosen, character));
        } else if (chosen.needsTarget()){
            chosen.setTarget(chooseTargetFor(chosen));
        }
        return chosen;
    }

    private Point2D chooseLocationFor(ReadonlyAction action, ReadonlyCharacter character){
        if (action.movementAction()){
            if (character.getHealth() <= CRITICAL_HEALTH){
                return fromEnemy(action.availableLocations());
            } else {
                return toEnemy(action.availableLocations());
            }
        }
        return toTeam(action.availableLocations());
    }

    private Point2D toEnemy(MutableSet<Point2D> availableLocations){
        if (visibleEnemies.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.minBy(p1 ->
                p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))
        );
    }

    private Point2D fromEnemy(MutableSet<Point2D> availableLocations){
        if (visibleEnemies.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.maxBy(p1 ->
                p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))
        );
    }

    private Point2D toTeam(MutableSet<Point2D> availableLocations){
        if (team.isEmpty()){
            return availableLocations.iterator().next();
        }
        return availableLocations.minBy(p1 ->
                p1.cartesianDistance(team.collect(ReadonlyCharacter::getLocation).minBy(p1::cartesianDistance))
        );
    }

    private ReadonlyCharacter chooseTargetFor(ReadonlyAction action){
        return action.availableTargets().minBy(ReadonlyCharacter::getHealth);
    }

    private int getPriorityFor(ReadonlyAction action, ReadonlyCharacter character){
        if (action.getName().equals("Smile")){
            return 1000;
        }
        if (action.movementAction()){
            if (character.getHealth() <= CRITICAL_HEALTH){
                return 0;
            }
            return 999;
        }
        if (action.needsTarget()) {
            return ((int) action.availableTargets().minBy(ReadonlyCharacter::getHealth).getHealth());
        }
        return 998;
    }
}

मुझे सभी निष्क्रिय कार्यों का उपयोग पसंद है! अच्छा है।
मोगी

6

भालू कैवलरी

अवशोषक , क्लोन का उपयोग करता है और भालू का ; आँकड़े (+9, +0, +11) हैं

पहली बारी में, हर कोई खुद का एक क्लोन बनाता है, ताकि टीम के पास मैदान पर 6 अक्षर हों। फिर वे दुश्मन को चार्ज करते हैं, जब भी वे कर सकते हैं, स्पैमिंग करते हैं, और स्टेट-अवशोषित हमलों के साथ अपने दुश्मनों को कमजोर करते हैं।

कोड एक गड़बड़ है, लेकिन यह काम करने लगता है। मैंने इसका हिस्सा टेम्पलेट प्लेयर से कॉपी किया है।

आप किसी भी तरह से इस टीम के पात्रों का उपयोग कर सकते हैं।

BearCavalry.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Absorb;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.other.Clone;
import fellowship.actions.other.Bear;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.Player;
import org.eclipse.collections.api.set.MutableSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class BearCavalry extends Player{
    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(9, 0, 11,
                        new Absorb(),
                        new ActionAbility(Clone::new),
                        new ActionAbility(Bear::new)));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
    for(ReadonlyAction action: actions){
        if (action.getName().equals("Clone") && action.isAvailable()){
        action.setLocation(toTeam(action.availableLocations(), character));
        return action;
        }
    }
    for(ReadonlyAction action: actions){
        if (action.getName().equals("Bear") && action.isAvailable()){
        action.setLocation(toEnemy(action.availableLocations(), character));
        return action;
        }
    }
    for(ReadonlyAction action: actions){
        if (action.getName().equals("Slice") && action.isAvailable()){
        action.setTarget(action.availableTargets().minBy(ReadonlyCharacter::getHealth));
        return action;
        }
    }
    for(ReadonlyAction action: actions){
        if (action.getName().equals("Step") && action.isAvailable()){
        action.setLocation(toEnemy(action.availableLocations(), character));
        return action;
        }
    }
    for(ReadonlyAction action: actions){
        if (action.getName().equals("Smile")){
        return action;
        }
    }
    return null;
    }

    private Point2D toTeam(MutableSet<Point2D> availableLocations, ReadonlyCharacter character){
        if (team.isEmpty()){
            return availableLocations.minBy(p1 ->
                        p1.diagonalDistance(character.getLocation())
                        );
        }
        return availableLocations.minBy(p1 ->
                    p1.diagonalDistance(team.collect(ReadonlyCharacter::getLocation).minBy(p1::cartesianDistance))
                    );
    }

    private Point2D toEnemy(MutableSet<Point2D> availableLocations, ReadonlyCharacter character){
        if (visibleEnemies.isEmpty()){
            return toTeam(availableLocations, character);
        }
        return availableLocations.minBy(p1 ->
                    p1.diagonalDistance(visibleEnemies.keyValuesView().minBy(p -> p.getTwo().getHealth()).getOne())
                    );
    }
}

आपके भालू मेरे कायर स्नाइपर के खिलाफ एक प्रभावी रणनीति हैं :) मेरे बॉट के लिए बहुत से लक्ष्य जप शुरू करने के लिए एक स्टैंड-ऑफ स्थिति में आने के लिए हैं! अच्छी तरह से किया
Moogie

5

काँटेदार

स्पाइकी, जैसा कि उनके नाम का तात्पर्य है, आँख बंद करके हमला नहीं करना। वह टैंकी है, एचपी की एक पूरी बहुत कुछ पुनर्जीवित कर सकता है, और एक ट्रक की तरह हिट कर सकता है। वह नक्शे के केंद्र में मंडराएगा, किसी के करीब आने का इंतजार करेगा।

का उपयोग करते हुए मजबूत (एसटीआर +10) x2, पुनः जेनरेट , स्पाइक और पूर्ण एसटीआर (+40, 0, 0) जा रहा है।

Spiky.java

import fellowship.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

import com.nmerrill.kothcomm.game.maps.Point2D;

import fellowship.abilities.defensive.Spikes;
import fellowship.abilities.stats.Regenerate;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class Spiky extends Player {

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(40, 0, 0,
                    new Strong(),
                    new Strong(),
                    new Regenerate(),
                    new Spikes()));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {

        ReadonlyAction chosen = null;
        Boolean canSlice = false;
        for (ReadonlyAction action: actions) {
            if (action.getName().equals("Slice")) {
                canSlice = true;
            }
        }

        for (ReadonlyAction action: actions) {
             if (action.getName().equals("Slice")) {
                 chosen = action;
                 chosen.setTarget(action.availableTargets().minBy(ReadonlyCharacter::getHealth));
             }
             if (!canSlice && action.getName().equals("Step")){
                 int x = ThreadLocalRandom.current().nextInt(3, 6 + 1);
                 int y = ThreadLocalRandom.current().nextInt(3, 6 + 1);
                 chosen = action;
                 Point2D destination = null;
                 if (visibleEnemies.isEmpty()){
                     destination = action.availableLocations().minBy(p1 -> p1.cartesianDistance(new Point2D(x, y)));
                 } else {
                     destination = action.availableLocations().minBy(p1 -> p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance)));
                 }
                 chosen.setLocation(destination);
             }
        }
        if (chosen == null){
            for (ReadonlyAction action: actions){
                if (action.getName().equals("Smile")){
                    chosen = action;
                }
            }
        }

        return chosen;
    }

}

> आपके सबमिशन में पैकेज की घोषणा नहीं होनी चाहिए। आपका सबमिशन पहले मल्टी-लाइन कोड ब्लॉक में समाहित होना चाहिए, और पहली लाइन में फ़ाइल का नाम होना चाहिए।
क्रिकटी लिथोस

मैंने अभी कहा था कि पोस्ट में क्या कहा गया था।
३ith पर क्रिक्टी लिथोस

@KritiiLithos अनुमान है कि मैंने सही किया है। धन्यवाद।
थ्रक्स

अच्छा बॉट! स्पाइकी ने मेरे बॉट्स को सर्वश्रेष्ठ हराया।
क्रिति लिथोस 12

आप बदल सकते हैं ThreadLocalRandom.current()करने के लिए getRandom()? यह खेल को नियतात्मक होने की अनुमति देता है।
नाथन मेरिल

5

जादूगर

वेव के साथ जितना संभव हो सके सभी दुश्मनों को तत्काल नुकसान से निपटने के लिए क्लोन करें (यह पहले से बिजली था, लेकिन वीव अधिक नुकसान करता है और कम मान लागत होती है।

Sorcerer.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.Player;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.vision.TrueSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Slice;
import fellowship.actions.attacking.Weave;
import fellowship.actions.mobility.Step;
import fellowship.actions.other.Clone;
import fellowship.actions.other.Smile;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.collections.api.set.MutableSet;

public class Sorcerer extends Player {

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(0, 0, 20,
                    new ActionAbility(Clone::new),
                    new TrueSight(),
                    new ActionAbility(Weave::new)));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        ReadonlyAction chosen = getBestAction(actions, character);
        if (chosen == null){
            throw new RuntimeException("No valid actions");
        }
        if (chosen.needsLocation()){
            chosen.setLocation(toEnemy(chosen.availableLocations()));
        } else if (chosen.needsTarget()){
            chosen.setTarget(chooseTargetFor(chosen));
        }
        return chosen;
    }

    private Point2D toEnemy(MutableSet<Point2D> availableLocations){
        if (visibleEnemies.isEmpty()){
            return availableLocations.minBy(p1 ->
                    p1.cartesianDistance(team.minBy(x -> p1.cartesianDistance(x.getLocation())).getLocation())
            );
        }

        return availableLocations.maxBy(p1 ->
                p1.cartesianDistance(visibleEnemies.keysView().maxBy(p1::cartesianDistance))
        );
    }

    private ReadonlyCharacter chooseTargetFor(ReadonlyAction action){
        return action.availableTargets().minBy(ReadonlyCharacter::getHealth);
    }

    private ReadonlyAction getBestAction(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        Map<Class<?>, ReadonlyAction> actionMap = new HashMap<>();
        for (ReadonlyAction action : actions) {
            actionMap.put(action.actionClass(), action);
        }

        ReadonlyAction clone = actionMap.get(Clone.class);
        if (clone != null && clone.isAvailable() && !clone.availableLocations().isEmpty()) {
            return clone;
        }

        ReadonlyAction weave = actionMap.get(Weave.class);
        if (weave != null && weave.isAvailable() && (clone == null || clone.getRemainingCooldown() > 0)) {
            return weave;
        }

        ReadonlyAction slice = actionMap.get(Slice.class);
        if (slice != null && slice.isAvailable() && !slice.availableLocations().isEmpty() && !character.isInvisible()) {
            return slice;
        }

        ReadonlyAction step = actionMap.get(Step.class);
        if (step != null && step.isAvailable()) {
            return step;
        }

        return actionMap.get(Smile.class);        
    }
}

क्लोनिंग बॉट्स के लिए एक लोकप्रिय विकल्प लगता है ... मुझे आपके बॉट को प्रेरणा के रूप में उपयोग करना चाहिए।
मोगी

4

longsword

उपयोग लेकर (स्लाइस की श्रृंखला के लिए जोड़ता है 1), लचीले (Can स्लाइस 8 दिशाओं में से किसी में), त्वरित (: 3, Cooldown: स्लाइस दो बार, मन 0), मजबूत (आप 10 और विशेषता अंक हासिल)

आँकड़े

शुरुआती 5 अंक आधार है

  • एसटीआर: 5 + 20 + 10
  • AGI: 5 + 0
  • INT: 5 + 0

सबसे पहले, मुझे वास्तव में इस बॉट को बनाने में बहुत मज़ा आया, और मुझे वास्तव में यह KotH पसंद है (यह KotH चुनौती के लिए मेरा पहला सबमिशन है!)। (मैं अधिक बॉट पोस्ट कर सकता हूं)

बॉट

यह बॉट अपने विरोधियों को पछाड़ने के लिए हमले की क्षमताओं पर निर्भर करता है। जहां तक ​​मैंने परीक्षण किया है, यह बॉट अपेक्षाकृत कम स्वास्थ्य के साथ बॉट के खिलाफ वास्तव में अच्छा है। इसके अलावा, इसकी एक बड़ी हमला रेंज है, और इसकी दृष्टि में आसानी से सबसे (या आधे) दुश्मनों को लक्षित कर सकते हैं।

एक nethack भूमिका के साथ इस बोट की तुलना करने के लिए, मैं कहूंगा कि यह करने के लिए मिलता-जुलता Valkyrie "longsword" और औसत स्वास्थ्य की अवधारणा की वजह से।

नाम

इस बॉट में सामान्य बॉट्स की तुलना में थोड़ी लंबी रेंज है और यह किसी भी दिशा में हमला कर सकती है। इसने मुझे नेटहैक में सबसे लंबे समय तक तलवार की याद दिलाई, इसलिए मैंने अपने बॉट को इस तरह नामित किया।

व्यवहार

यदि चरित्र दुश्मन के चरित्र को नहीं देख सकता है, तो यह दुश्मन के पात्रों को खोजने के लिए क्षेत्र के विपरीत दिशा (दुश्मन के स्पॉन क्षेत्र / दुश्मन के "आधार") पर जाएगा। यदि यह दुश्मनों को ढूंढता है, तो यह उन पर क्विक, स्लाइस (प्राथमिकता में कमी) के साथ हमला करेगा। यदि यह दुश्मनों को निशाना नहीं बना सकता है, तो बॉट उन्हें नष्ट करने के लिए दुश्मन के पात्रों की ओर जाएगा।

यदि चरित्र दुश्मन के चरित्र को नहीं देख सकता है और कम स्वास्थ्य है, तो वह "आधार" / स्पॉन क्षेत्र की ओर पीछे हट जाएगा।

नोट: बॉट लड़ाई के बीच में कभी पीछे नहीं हटेगा। यह बॉट कभी स्माइल नहीं करेगा।

मैंने निम्नलिखित रेगेक्स का उपयोग किया अपने जावा कोड को एक स्वरूपित कोड ब्लॉक में बदलने के लिए regexr.com पर ।

नीचे दिए गए कोड पर टिप्पणी की गई है, इसलिए इसे समझना आसान होना चाहिए। यदि आपके पास कोई प्रश्न या स्पष्टीकरण है कि यह कैसे काम करता है, तो मुझे बेझिझक फ़ेलोशिप चैट रूम की लड़ाई में पिंग करें !

संपादित करें: मैंने बॉट के आंदोलन (आगे की ओर पीछे की ओर) को अनुकूलित करने के लिए अपने कार्यक्रम में एक छोटी सी गलती तय की है, जहां यह शुरू हुआ था। मैं यह करना भूल गया, इसलिए मैंने इसे अब संपादित किया।

LongSword.java

import fellowship.*;
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Flexible;
import fellowship.abilities.attacking.Ranged;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class LongSword/*Closest NetHack Role: Valkyrie*/ extends Player{

    //debugging
    private boolean debug = false;
    private void println(String text) {
        if(debug)
            System.out.println(text);
    }

    //variables use to hold the start Y coordinate of the bot
    private boolean started = false;
    private int startY = 5;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(30, 0, 0,
                    new Ranged(), //Adds 1 to the range of Slice
                    new Flexible(), //Can Slice in any of the 8 directions
                    new ActionAbility(Quick::new), //Slice twice, Mana: 3, Cooldown: 0
                    new Strong())); //You gain 10 attribute points
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        if(!started) {
            startY = character.getLocation().getY(); //giving startY the value of the bot's starting y-value
            started = true; //do this only once, that's why there is the if statement
        }

        ReadonlyAction current = null;

        //choosing action depending on priority
        int priority = Integer.MAX_VALUE;
        for(ReadonlyAction action:actions) {
            int priorityLocal = getPriority(action, character);
            if(priorityLocal < priority) {
                current = action;
                priority = priorityLocal;
            }
        }

        if (current == null){
            throw new RuntimeException("No valid actions");
        }

        println(current.getName());

        if(current.needsLocation()) {
            if(visibleEnemies.isEmpty()) {
                if (character.getHealth() < 100) {
                    //if has low health, go backwards towards "base"
                    //println("lowHealth");
                    current.setLocation(move(current, character, "backward"));
                } else {
                    //else go forwards to enemy's "base"
                    current.setLocation(move(current, character, "forward"));
                }
            }else{
                //go towards closest enemy
                current.setLocation(current.availableLocations().minBy(p1->p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))));
            }
        }
        if(current.needsTarget()) {
            //get closest target
            current.setTarget(current.availableTargets().minBy(p1 -> 0));
        }

        return current;
    }

    //move backwards or forwards
    private Point2D move(ReadonlyAction readonlyAction, ReadonlyCharacter character, String direction) {
        Point2D location = null;

        //move direction depending on Y coordinate of point
        for(Point2D point2D:readonlyAction.availableLocations()) {
            switch (direction) {
                case "forward":
                    if(startY > 5) { //bot started at bottom
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }else{ //bot started at top
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }
                    break;
                case "backward":
                    if(startY > 5) { //bot started at bottom
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }else{ //bot started at top
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }
                    break;
            }

        }

        //if no available locations, just choose the first available location
        if(location == null) {
            location = readonlyAction.availableLocations().iterator().next();
        }

        println(location.getY()+","+character.getLocation().getY());

        return location;
    }

    private int getPriority(ReadonlyAction action, ReadonlyCharacter character) {
        if(visibleEnemies.isEmpty()) {
            //if there are no visible enemies, Step. In the choose function, this becomes move forward or backward depending on health
            if(action.getName().equals("Step")) {
                return 100;
            }
        }else {
            /*
             * PRIORITIES:
             *  1. Quick (Slice twice)
             *  2. Slice
             *  3. Step (when enemy is not in range --> move towards enemy)
             */
            if (action.getName().equals("Quick")) {
                return 1;
            }else if(action.getName().equals("Slice")) {
                return 10;
            }else if(action.getName().equals("Step")) {
                return 50;
            }
        }
        //Kids, don't Smile, instead Step or Slice
        return 1000;
    }
}

2
मेरी कायरता को लज्जित करता है। अच्छा काम
Moogie

4

Derailer

इसे दो बार हटाना थामुझे पड़ा क्योंकि मेरे पास तर्क त्रुटियों का एक समूह था। : पी

यह निश्चित रूप से आपकी योजनाओं को पटरी से उतार सकता है। ;)

दल:

  • साथ 1 चरित्र गंभीर , बफ , मजबूत , और क्विक के दुश्मनों को हराने के लिए बहुत मुश्किल है। +25 एसटीआर, +2 एजीआई, +3 इंटे
  • चतुर , चतुर , पुनर्स्थापना , और के साथ 1 चरित्र जैप के । समर्थन के रूप में पीछे रहता है और एचपी पर कम चलने वाले किसी भी साथियों के स्वास्थ्य को पुनर्स्थापित करता है, और आवश्यक रूप से हमला कर सकता है और बचाव कर सकता है। +14 एसटीआर, +3 एजीआई, +3 इंट
  • साथ 1 चरित्र TrueSight , स्पाइक , गोलमाल , और Weave । हिट करने के लिए इतना आसान नहीं है, और यदि आप करते हैं, या यदि आप बहुत करीब आते हैं, तो यह आपको देखेगा और हड़ताल करेगा। +13 एसटीआर, +3 एजीआई, +4 इंट
Derailer.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.Player;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.ReadonlyAbility;
import fellowship.abilities.attacking.Critical;
import fellowship.abilities.defensive.Evasive;
import fellowship.abilities.defensive.Spikes;
import fellowship.abilities.stats.Buff;
import fellowship.abilities.stats.Clever;
import fellowship.abilities.stats.Strong;
import fellowship.abilities.vision.TrueSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.actions.attacking.Weave;
import fellowship.actions.damage.Zap;
import fellowship.actions.defensive.Restore;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

public class Derailer extends Player {
    private static final double CRITICAL_HEALTH_PCT = .175;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> list = new ArrayList<>();

        list.add(new CharacterTemplate(14, 3, 3,
                                       new Clever(),
                                       new Clever(),
                                       new ActionAbility(Restore::new),
                                       new ActionAbility(Zap::new)));

        list.add(new CharacterTemplate(25, 2, 3,
                                       new Critical(),
                                       new Buff(),
                                       new ActionAbility(Quick::new),
                                       new Strong()));

        list.add(new CharacterTemplate(13, 3, 4,
                                       new TrueSight(),
                                       new Spikes(),
                                       new Evasive(),
                                       new ActionAbility(Weave::new)));
        return list;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        List<ReadonlyAbility> abilities = character.getAbilities();
        ReadonlyAction action = null;

        for (ReadonlyAbility a : abilities) {
            String s = a.name();
            int i = s.lastIndexOf(".");
            if (i == -1)
                continue;
            s = s.substring(i+1, s.length());
            if (s.equals("Clever")) {
                action = getActionForChar1(character, actions);
                break;
            }
            else if (s.equals("Buff")) {
                action = getActionForChar2(character, actions);
                break;
            }
            else if (s.equals("Evasive")) {
                action = getActionForChar3(character, actions);
                break;
            }
        }

        return action;
    }

    private ReadonlyAction getActionForChar1(ReadonlyCharacter character, Set<ReadonlyAction> actions) {
        int members = (int) team.stream().filter(c -> !c.isDead()).count();

        List<ReadonlyAction> list = actions.stream()
                                           .sorted(Comparator.comparingInt(this::getPriority))
                                           .collect(Collectors.toList());

        for (ReadonlyAction a : list) {
            String name = a.getName();
            if (name.equals("Restore")) {
                for (ReadonlyCharacter teammate : team) {
                    if (teammate.getHealth() / teammate.getMaxHealth() < CRITICAL_HEALTH_PCT * (4 - members))
                        return a;
                }
            }
            else if (name.equals("Zap") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets()
                             .stream()
                             .reduce(
                                 BinaryOperator.minBy(
                                     Comparator.<ReadonlyCharacter>comparingDouble(e -> e.getHealth())
                                 )
                             )
                             .get()
                );
                return a;
            }
            else if (name.equals("Slice") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().iterator().next());
                return a;
            }
            else if (name.equals("Smile"))
                return a;
        }
        throw new RuntimeException("No available actions");
    }

    private ReadonlyAction getActionForChar2(ReadonlyCharacter character, Set<ReadonlyAction> actions) {
        List<ReadonlyAction> list = actions.stream()
                                           .sorted(Comparator.comparingInt(this::getPriority))
                                           .collect(Collectors.toList());

        for (ReadonlyAction a : list) {
            String name = a.getName();
            if (name.equals("Quick") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().minBy(ReadonlyCharacter::getHealth));
                return a;
            }
            else if (name.equals("Slice") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().minBy(ReadonlyCharacter::getHealth));
                return a;
            }
            else if (name.equals("Step") && !a.availableLocations().isEmpty()) {
                Point2D e = getClosestEnemyPoint(character);
                if (e == null) {
                    Point2D p = character.getLocation();
                    if (p.getY() > 5) {
                        a.setLocation(a.availableLocations()
                                       .stream()
                                       .filter(x -> x.getY() < p.getY())
                                       .findFirst()
                                       .orElse(a.availableLocations().iterator().next()));
                    }
                    else if (p.getY() < 4) {
                        a.setLocation(a.availableLocations()
                                       .stream()
                                       .filter(x -> x.getY() > p.getY())
                                       .findFirst()
                                       .orElse(a.availableLocations().iterator().next()));
                    }
                    else
                        a.setLocation(randomLocation(new ArrayList<>(a.availableLocations())));
                }
                else {
                    int currentDistance = character.getLocation().cartesianDistance(e);
                    a.setLocation(a.availableLocations()
                                   .stream()
                                   .filter(x -> x.cartesianDistance(e) < currentDistance)
                                   .findFirst()
                                   .orElse(randomLocation(new ArrayList<>(a.availableLocations()))));
                }
                return a;
            }
            else if (name.equals("Smile"))
                return a;
        }
        throw new RuntimeException("No available actions");
    }

    private ReadonlyAction getActionForChar3(ReadonlyCharacter character, Set<ReadonlyAction> actions) {
        List<ReadonlyAction> list = actions.stream()
                                           .sorted(Comparator.comparingInt(this::getPriority))
                                           .collect(Collectors.toList());

        for (ReadonlyAction a : list) {
            String name = a.getName();
            if (name.equals("Weave") && visibleEnemies.keySet().size() > 1)
                return a;
            else if (name.equals("Slice") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().iterator().next());
                return a;
            }
            else if (name.equals("Smile"))
                return a;
            else if (name.equals("Step")) {
                Point2D p = character.getLocation();
                if (!visibleEnemies.keySet().isEmpty()) {
                    Point2D e = getClosestEnemyPoint(character);
                    int currentDistance = character.getLocation().cartesianDistance(e);
                    a.setLocation(a.availableLocations()
                                   .stream()
                                   .filter(x -> x.cartesianDistance(e) < currentDistance)
                                   .findAny()
                                   .orElse(randomLocation(new ArrayList<>(a.availableLocations()))));
                }
                else if (p.getY() > 5) {
                    a.setLocation(a.availableLocations()
                                   .stream()
                                   .filter(x -> x.getY() < p.getY())
                                   .findFirst()
                                   .orElse(randomLocation(new ArrayList<>(a.availableLocations()))));
                }
                else if (p.getY() < 4) {
                    a.setLocation(a.availableLocations()
                                   .stream()
                                   .filter(x -> x.getY() > p.getY())
                                   .findFirst()
                                   .orElse(randomLocation(new ArrayList<>(a.availableLocations()))));
                }
                else
                    a.setLocation(randomLocation(new ArrayList<>(a.availableLocations())));
                return a;
            }
        }
        throw new RuntimeException("No available actions");
    }

    private Point2D getClosestEnemyPoint(ReadonlyCharacter c) {
        return visibleEnemies.keySet()
                             .stream()
                             .reduce(
                                 BinaryOperator.minBy(
                                     Comparator.comparingInt(x -> x.cartesianDistance(c.getLocation()))
                                 )
                             )
                             .orElse(null);
    }

    private int getPriority(ReadonlyAction action) {
        switch (action.getName()) {
            case "Quick":
            case "Restore":
            case "Weave":
                return 1;
            case "Zap": return 2;
            case "Slice": return 3;
            case "Step": return 4;
            case "Smile": return 5;
        }
        throw new IllegalArgumentException(String.valueOf(action));
    }

    private Point2D randomLocation(List<Point2D> l) {
        return l.get((int) (Math.random() * l.size()));
    }
}

दिलचस्प टीम की गतिशीलता! मुझे कुछ और उन्नत टीम एक्शन के लिए प्रयास करना चाहता है :)
Moogie

धन्यवाद। मैंने टीम के भीतर तालमेल को शामिल करने की कोशिश की, लेकिन तीसरा चरित्र थोड़ा हटकर है। शायद मैं भविष्य की बॉट में इस रणनीति पर सुधार करूंगा।
टीएनटी

दिलचस्प है, पहले की एक प्रति के साथ तीसरे चरित्र को प्रतिस्थापित करने के परिणामस्वरूप बहुत बेहतर परिणाम मिले।
टीएनटी

4

SniperSquad

एक स्नाइपर दस्ते में शामिल हैं:

  • 1 स्पॉटर (उपलब्ध सर्वोत्तम स्पॉटिंग गियर से लैस, जिससे लगभग पूरे मानचित्र का अवलोकन होता है)
    • एसटीआर: 25; AGI: 5; INT: 5
    • दूर दृष्टि , दूर दृष्टि , दूर दृष्टि , दूर दृष्टि
  • 2 निशानेबाज (नवीनतम मल्टी टारगेट स्नाइपर राइफल्स से लैस, एकमात्र दोष धीमी आग दर है)
    • एसटीआर: 25; AGI: 5; INT: 5
    • बुनें , क्रिटिकल , क्रिटिकल , क्रिटिकल

आप अपनी टीम में यहां से एकल वर्णों का पुन: उपयोग कर सकते हैं, जब तक आप कम से कम एक और चरित्र जोड़ते हैं जो यहां मौजूद नहीं है।

SniperSquad.java
import java.util.Arrays;
import java.util.List;

import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Critical;
import fellowship.abilities.vision.FarSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Weave;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class SniperSquad extends SleafarPlayer {
    private static CharacterTemplate spotterTemplate() {
        return new CharacterTemplate(20, 0, 0,
                new FarSight(), new FarSight(), new FarSight(), new FarSight());
    }

    private static CharacterTemplate shooterTemplate() {
        return new CharacterTemplate(20, 0, 0,
                new ActionAbility(Weave::new), new Critical(), new Critical(), new Critical());
    }

    @Override
    public List<CharacterTemplate> createCharacters() {
        return Arrays.asList(shooterTemplate(), spotterTemplate(), shooterTemplate());
    }

    private class Spotter extends Character {
        protected Spotter(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            if (slice != null && setSliceTarget(slice, 100.0)) {
                return slice;
            }
            if (step != null && isInEnemyStepSightRange() && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null && setExploreLocation(step)) {
                return step;
            }
            return smile;
        }
    }

    private class Shooter extends Character {
        protected Shooter(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction weave = getAction(Weave.class);
            if (weave != null && !visibleEnemies.isEmpty() &&
                    visibleEnemies.collectDouble(e -> calcSliceRetaliationDamage(e)).sum() < getHealth()) {
                return weave;
            }
            if (slice != null && setSliceTarget(slice, 100.0)) {
                return slice;
            }
            if (step != null && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            return smile;
        }
    }

    @Override
    protected Character createCharacter(ReadonlyCharacter delegate) {
        if (hasAbility(delegate, FarSight.class)) {
            return new Spotter(delegate);
        } else if (hasAbility(delegate, Weave.class)) {
            return new Shooter(delegate);
        } else {
            throw new IllegalArgumentException();
        }
    }
}

Hehe, आपके स्निपर्स ने मेरे कायर स्निपर्स को निकाल दिया :) अच्छा काम
Moogie

3

werewolves

मैं AI पसंद चयन लिखने में सबसे बड़ा नहीं हूं , विशेष रूप से एक जटिल नियम के लिए यह एक के रूप में। एक गेमस्टैट को देखने और निर्णय लेने वाले अभिनेताओं का अवलोकन करने की कम क्षमता के साथ संयुक्त (और रन के बीच परिणाम थोड़ा अलग है, एआई तर्क को बेहतर बनाने के लिए थोड़े से बदलाव की सफलता मार्जिन की गणना करने की क्षमता बहुत कम है), लेकिन मैं बनाने में सक्षम था एक बेहतर क्षमता / विशेषता चयन जो मौजूदा बॉट सेट पर हावी है।

उपयोग लेकर , स्वाइप , मजबूत , और वेयरवोल्फ और अन्यथा रूप में एक ही ऐ तर्क का उपयोग करता longsword , हालांकि थोड़ा बदल दिया।

सबसे आदर्श मूल्यों को चुनने के लिए कठिन है, क्योंकि कभी-कभी कोई बदलाव "सर्वोत्तम" से "सबसे खराब" होने का परिणाम नहीं हो सकता है। हेल्थ-रिट्रीट-थ्रेशोल्ड यहां 50 है, लेकिन ऐसा लगता है कि समान परिणामों में 10 और 70 परिणामों के बीच कोई भी मूल्य (कोई अन्य बॉट जो प्रदर्शन के सटीक शिखर को भेद करने के लिए एक उच्च पर्याप्त चुनौती प्रदान करता है)।

PlayerWerewolf.java

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.nmerrill.kothcomm.game.maps.Point2D;

import fellowship.Player;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Ranged;
import fellowship.abilities.attacking.Swipe;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.stats.Werewolf;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.characters.EnemyCharacter;

public class PlayerWerewolf extends Player {
    //variables use to hold the start Y coordinate of the bot
    private boolean started = false;
    private int startY = 5;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(30, 0, 0,
                    new Ranged(), //Adds 1 to the range of Slice
                    new Swipe(), //Deal increasing damage
                    new ActionAbility(Werewolf::new), //Turn into a werewolf for 5 turns
                    new Strong())); //You gain 10 attribute points
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        if(!started) {
            startY = character.getLocation().getY(); //giving startY the value of the bot's starting y-value
            started = true; //do this only once, that's why there is the if statement
        }

        ReadonlyAction current = null;

        //choosing action depending on priority
        int priority = Integer.MAX_VALUE;
        for(ReadonlyAction action:actions) {
            int priorityLocal = getPriority(action, character);
            if(priorityLocal < priority) {
                current = action;
                priority = priorityLocal;
            }
        }

        if (current == null){
            throw new RuntimeException("No valid actions");
        }

        if(current.needsLocation()) {
            if(visibleEnemies.isEmpty()) {
                if (character.getHealth() < 50) {
                    //if has low health, go backwards towards "base"
                    //println("lowHealth");
                    current.setLocation(move(current, character, "backward"));
                } else {
                    //else go forwards to enemy's "base"
                    current.setLocation(move(current, character, "forward"));
                }
            }else{
                //go towards closest enemy
                current.setLocation(current.availableLocations().minBy(p1->p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))));
            }
        }
        if(current.needsTarget()) {
            //get closest target
            current.setTarget(current.availableTargets().minBy(p1 -> 0));
        }

        return current;
    }

    //move backwards or forwards
    private Point2D move(ReadonlyAction readonlyAction, ReadonlyCharacter character, String direction) {
        Point2D location = null;

        //move direction depending on Y coordinate of point
        for(Point2D point2D:readonlyAction.availableLocations()) {
            switch (direction) {
            case "forward":
                if(startY > 5) { //bot started at bottom
                    if (point2D.getY() < character.getLocation().getY())
                        location = point2D;
                }else{ //bot started at top
                    if (point2D.getY() > character.getLocation().getY())
                        location = point2D;
                }
                break;
            case "backward":
                if(startY > 5) { //bot started at bottom
                    if (point2D.getY() > character.getLocation().getY())
                        location = point2D;
                }else{ //bot started at top
                    if (point2D.getY() < character.getLocation().getY())
                        location = point2D;
                }
                break;
            }

        }

        //if no available locations, just choose the first available location
        if(location == null) {
            location = readonlyAction.availableLocations().iterator().next();
        }

        return location;
    }

    private int getPriority(ReadonlyAction action, ReadonlyCharacter character) {
        if(visibleEnemies.isEmpty()) {
            //if there are no visible enemies, Step. In the choose function, this becomes move forward or backward depending on health
            if(action.getName().equals("Step")) {
                return 100;
            }
        }else {
            /*
             * PRIORITIES:
             *  1. If near an enemy, and not a werewolf, turn into a werewolf
             *  2. Slice
             *  3. Step (when enemy is not in range --> move towards enemy)
             */
            if (action.getName().equals("Werewolf") && action.isAvailable()) {
                EnemyWrapper wrap = getNearestEnemy(character);
                //don't turn into a werewolf unless we're close to an enemy
                if(wrap.location.diagonalDistance(character.getLocation()) < 3) {
                    return 1;
                }
            }else if(action.getName().equals("Slice")) {
                return 10;
            }else if(action.getName().equals("Step")) {
                return 50;
            }
        }
        //Kids, don't Smile, instead Step or Slice
        return 1000;
    }

    private EnemyWrapper getNearestEnemy(ReadonlyCharacter character) {
        double closestEnemyDistance = Double.MAX_VALUE;
        Point2D closestEnemy = null;
        for ( Point2D enemyLocation : visibleEnemies.keySet()) {
            double visionDistanceDiff = character.getLocation().diagonalDistance(enemyLocation);
            if (visionDistanceDiff< closestEnemyDistance)
            {
                closestEnemyDistance = visionDistanceDiff;
                closestEnemy = enemyLocation;
            }
        }
        return new EnemyWrapper(visibleEnemies.get(closestEnemy), closestEnemy);
    }
    private static class EnemyWrapper {
        public final EnemyCharacter enemy;
        public final Point2D location;

        EnemyWrapper(EnemyCharacter e, Point2D l) {
            enemy = e;
            location = l;
        }
    }
}

कुछ मुद्दे थे (एक पैकेज की घोषणा, साथ ही पहली पंक्ति में फ़ाइल नाम नहीं डालना), और मैंने उन्हें तय किया। उस ने कहा, मैं अपने कंपाइलर को पाने के लिए स्टैटिक क्लास नहीं ले सकता ... इसे देख रहा हूं।
नाथन मेरिल

मुझे यह समझ में आया: आप एक आयात याद कर रहे थे:import fellowship.characters.EnemyCharacter;
नाथन मेरिल

@NathanMerrill मैंने ग्रहण के बाहर द्वितीयक वर्ग को एक आंतरिक वर्ग में संयोजित करने का प्रयास किया, शायद यही वह था।
ड्रैक 18s

अच्छा! आपने LongSword से अपने स्वयं के आंदोलन कार्यों का उपयोग किया!
कृतिका लिथोस

@KritiiLithos हां, मुझे चीजों के "एआई" भाग को लिखने में परेशानी हो रही थी, इसलिए मैंने एक को लिया जो एक शुरुआती बिंदु होने के लिए सरल था और यह वास्तव में अच्छी तरह से काम करता था। मैं उनके साथ यह देखने की कोशिश कर रहा हूं कि क्या मैं इसे बेहतर बना सकता हूं, क्योंकि वे सिर्फ आगे बढ़ते रहेंगे यदि वे किसी को नहीं देख सकते हैं, भले ही उनका प्रतिद्वंद्वी उनके पीछे हो, लेकिन बहुत कुछ नहीं किया है अंतर। ज्यादातर इसलिए क्योंकि न तो भेड़ियों और न ही लंबे तलवारबाजों के पास वैसे भी अदृश्यता का मुकाबला करने के लिए है।
ड्रेको

2

Railbender

यह बॉट डेरेलर का एक संस्करण है जिसमें पहले की एक प्रति के साथ इसकी तीसरी विशेषता थी। यह Derailer की तुलना में बहुत बेहतर परिणाम देता है।

डेरेलर को बनाते समय, मैं प्रत्येक चरित्र क्षमताओं को देना चाहता था जो एक दूसरे के साथ अच्छी तरह से तालमेल करेंगे। उच्च एचपी और हमले की शक्ति के साथ एक चरित्र होने और पुनर्स्थापना कार्रवाई के साथ एक और चरित्र अच्छी तरह से एक साथ काम किया। हालाँकि, ऐसा नहीं लगता था कि तीसरा किरदार बहुत अच्छी तरह से फिट होगा। शायद यही मुख्य कारण था कि डेरेलर ने अच्छे परिणाम नहीं दिए। इसलिए मुझे लगा कि एक तीसरा चरित्र है जो दूसरों के साथ अच्छा काम कर सकता है और लाभान्वित होगा।

Railbender.java

import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.Player;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.ReadonlyAbility;
import fellowship.abilities.attacking.Critical;
import fellowship.abilities.stats.Buff;
import fellowship.abilities.stats.Clever;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.actions.damage.Zap;
import fellowship.actions.defensive.Restore;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

public class Railbender extends Player {
    private static final double CRITICAL_HEALTH_PCT = .175;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> list = new ArrayList<>();

        list.add(new CharacterTemplate(14, 3, 3,
                                       new Clever(),
                                       new Clever(),
                                       new ActionAbility(Restore::new),
                                       new ActionAbility(Zap::new)));

        for (int k = 0; k < 2; k++) {
            list.add(new CharacterTemplate(25, 2, 3,
                                           new Critical(),
                                           new Buff(),
                                           new ActionAbility(Quick::new),
                                           new Strong()));
        }
        return list;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        List<ReadonlyAbility> abilities = character.getAbilities();
        ReadonlyAction action = null;

        for (ReadonlyAbility a : abilities) {
            String s = a.name();
            int i = s.lastIndexOf(".");
            if (i == -1)
                continue;
            s = s.substring(i+1, s.length());
            if (s.equals("Clever")) {
                action = getActionForChar1(character, actions);
                break;
            }
            else if (s.equals("Buff")) {
                action = getActionForChar2(character, actions);
                break;
            }
        }

        return action;
    }

    private ReadonlyAction getActionForChar1(ReadonlyCharacter character, Set<ReadonlyAction> actions) {
        int members = (int) team.stream().filter(c -> !c.isDead()).count();

        List<ReadonlyAction> list = actions.stream()
                                           .sorted(Comparator.comparingInt(this::getPriority))
                                           .collect(Collectors.toList());

        Point2D closestEnemy = getClosestEnemyPoint(character);

        for (ReadonlyAction a : list) {
            String name = a.getName();
            if (name.equals("Restore")) {
                for (ReadonlyCharacter teammate : team) {
                    if (teammate.getHealth() / teammate.getMaxHealth() < CRITICAL_HEALTH_PCT * (4 - members))
                        return a;
                }
            }
            else if (name.equals("Zap") && !a.availableTargets().isEmpty() && closestEnemy != null &&
                     character.getLocation().cartesianDistance(closestEnemy) <= 4) {
                a.setTarget(a.availableTargets()
                             .stream()
                             .reduce(
                                 BinaryOperator.minBy(
                                     Comparator.<ReadonlyCharacter>comparingDouble(e -> e.getHealth())
                                 )
                             )
                             .get()
                );
                return a;
            }
            else if (name.equals("Slice") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().iterator().next());
                return a;
            }
            else if (name.equals("Smile"))
                return a;
        }
        throw new RuntimeException("No available actions");
    }

    private ReadonlyAction getActionForChar2(ReadonlyCharacter character, Set<ReadonlyAction> actions) {
        List<ReadonlyAction> list = actions.stream()
                                           .sorted(Comparator.comparingInt(this::getPriority))
                                           .collect(Collectors.toList());

        for (ReadonlyAction a : list) {
            String name = a.getName();
            if (name.equals("Quick") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().minBy(ReadonlyCharacter::getHealth));
                return a;
            }
            else if (name.equals("Slice") && !a.availableTargets().isEmpty()) {
                a.setTarget(a.availableTargets().minBy(ReadonlyCharacter::getHealth));
                return a;
            }
            else if (name.equals("Step") && !a.availableLocations().isEmpty()) {
                Point2D e = getClosestEnemyPoint(character);
                if (e == null) {
                    Point2D p = character.getLocation();
                    if (p.getY() > 5) {
                        a.setLocation(a.availableLocations()
                                       .stream()
                                       .filter(x -> x.getY() < p.getY())
                                       .findFirst()
                                       .orElse(a.availableLocations().iterator().next()));
                    }
                    else if (p.getY() < 4) {
                        a.setLocation(a.availableLocations()
                                       .stream()
                                       .filter(x -> x.getY() > p.getY())
                                       .findFirst()
                                       .orElse(a.availableLocations().iterator().next()));
                    }
                    else
                        a.setLocation(randomLocation(new ArrayList<>(a.availableLocations())));
                }
                else {
                    int currentDistance = character.getLocation().cartesianDistance(e);
                    a.setLocation(a.availableLocations()
                                   .stream()
                                   .filter(x -> x.cartesianDistance(e) < currentDistance)
                                   .findFirst()
                                   .orElse(randomLocation(new ArrayList<>(a.availableLocations()))));
                }
                return a;
            }
            else if (name.equals("Smile"))
                return a;
        }
        throw new RuntimeException("No available actions");
    }

    private Point2D getClosestEnemyPoint(ReadonlyCharacter c) {
        return visibleEnemies.keySet()
                             .stream()
                             .reduce(
                                 BinaryOperator.minBy(
                                     Comparator.comparingInt(x -> x.cartesianDistance(c.getLocation()))
                                 )
                             )
                             .orElse(null);
    }

    private int getPriority(ReadonlyAction action) {
        switch (action.getName()) {
            case "Quick":
            case "Restore":
                return 1;
            case "Zap": return 2;
            case "Slice": return 3;
            case "Step": return 4;
            case "Smile": return 5;
        }
        throw new IllegalArgumentException(String.valueOf(action));
    }

    private Point2D randomLocation(List<Point2D> l) {
        return l.get((int) (Math.random() * l.size()));
    }
}

गजब का! यह डेरेलर की तुलना में अधिक कठिन है
क्रिक्टी लिथोस

2

Noob/*Destroyer*/

का उपयोग करता है मजबूत * 2, पुनः उत्पन्न , और स्टन (अगले 300 टिक के लिए stuns लक्ष्य)

आँकड़े

  • एसटीआर : 5 + 40
  • AGI : 5 + 0
  • INT : 5 + 0

Noob का अधिकांश कोड मेरे LongSword से लिया गया है।

रणनीति

जब चरित्र पहली बार किसी दुश्मन के चरित्र को देखता है, तो प्राथमिकता पहले दुश्मन को तेजस्वी को दे रही है, और फिर दुश्मन को घूरते हुए जब वे स्तब्ध हैं। और अपने उच्च स्वास्थ्य और उत्थान के साथ, नोब तब तक जीवित रहने में सक्षम होना चाहिए जब तक कि वह फिर से स्टन का उपयोग करने में सक्षम न हो।

Noob.java
import fellowship.*;
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.Stat;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.stats.Regenerate;
import fellowship.abilities.stats.Strong;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.defensive.Shield;
import fellowship.actions.statuses.Silence;
import fellowship.actions.statuses.Stun;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.Player;
import org.eclipse.collections.api.set.MutableSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class Noob/*Destroyer*/ extends Player {

    private boolean debug = false;
    private void println(String text) {
        if(debug)
            System.out.println(text);
    }

    private boolean started = false;
    private int startY = 5;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(40, 0, 0,
                    new Regenerate(),
                    new ActionAbility(Stun::new),
                    new Strong(),
                    new Strong()));
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        if(!started) {
            startY = character.getLocation().getY();
            started = true;
        }

        ReadonlyAction readonlyAction = null;

        //get priority of action
        int priority = Integer.MAX_VALUE;

        for(ReadonlyAction action:actions) {
            int priorityLocal = getPriority(action, character);
            if(priorityLocal < priority) {
                readonlyAction = action;
                priority = priorityLocal;
            }
        }

        if (readonlyAction == null){
            println("NULL!");
            throw new RuntimeException("No valid actions");
        }

        //movement
        if(readonlyAction.needsLocation()) {
            if(visibleEnemies.isEmpty()) {
                if (character.getHealth() < 100) {
                    readonlyAction.setLocation(move(readonlyAction, character, "backward"));
                } else {
                    readonlyAction.setLocation(move(readonlyAction, character, "forward")); //enemy base is "forward"
                }
            }else{
                readonlyAction.setLocation(readonlyAction.availableLocations().minBy(p1->p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))));
            }
        }

        if(readonlyAction.needsTarget()) {
            readonlyAction.setTarget(readonlyAction.availableTargets().minBy(p1 -> 0));
        }

        return readonlyAction;
    }

    private Point2D move(ReadonlyAction readonlyAction, ReadonlyCharacter character, String direction) {
        Point2D location = null;

        for(Point2D point2D:readonlyAction.availableLocations()) {
            switch (direction) {
                case "forward":
                    if(startY > 5) { //bot starts at bottom
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }else{ //bot starts at top
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }
                    break;
                case "backward":
                    if(startY > 5) { //bot starts at bottom
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }else{ //bot starts at top
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }
                    break;
            }

        }

        if(location == null) {
            location = readonlyAction.availableLocations().iterator().next();
        }
        return location;
    }

    private int getPriority(ReadonlyAction action, ReadonlyCharacter character) {
        if(visibleEnemies.isEmpty()) {
            if(action.getName().equals("Step")) {
                return 100;
            }
        }else {
            if (action.getName().equals("Slice")) {
                return 10;
            }else if(action.getName().equals("Step")) {
                return 50;
            }else if(action.getName().equals("Stun") && !action.availableTargets().minBy(p1->0).isStunned()) {
                //if target is not stunned, stun 'em
                return 1;
            }
        }
        return 1000;
    }
}

2

लिविंग वॉल

जीवित लकड़ी की एक दीवार जो युद्ध के मैदान के साथ चल सकती है, जो किसी भी दुश्मन पर मजबूत हिट उतरती है, और उसके अधिकतम स्वास्थ्य को बढ़ाने के लिए उनमें से सैप को सूखा देती है। इसकी जड़ प्रणाली कंपन का पता लगा सकती है, जिससे यह अदृश्य दुश्मनों पर भी चाबुक चला सकता है। यह मिश्रण है:

  • 2 शाखाएँ : एसटीआर 35, एजीआई 5, इन्ट 5, स्ट्रॉन्ग , बफ , बफ , एब्सॉर्ब
  • 1 रूट : एसटीआर 25, एजीआई , 5, इन्ट , 5, ट्रू साइट , बफ , बफ , एब्सॉर्ब

एआई अविश्वसनीय रूप से सरल है: टीम के निकटतम दुश्मन को ढूंढें, फिर पूरी दीवार उस एकल दुश्मन पर केंद्रित है। केवल छोटी-मोटी जटिलताएँ हैं: यदि कोई दुश्मन दृष्टि में नहीं है, और / या नक्शे के केंद्र के यादृच्छिक कोनों की ओर चलें (इस प्रकार अंततः दुश्मनों को शिकार कर रहे हैं जो छिप रहे हैं); यदि कोई दुश्मन पहुंच के भीतर है, तो भी उस पर हमला करें, भले ही वह दुश्मन हो जिसे हम निशाना बना रहे हैं (लेकिन हम जिस दुश्मन को निशाना बना रहे हैं, उस पर ध्यान केंद्रित करना पसंद करते हैं, और इससे भी ज्यादा दुश्मन हम ओएचकेओ कर सकते हैं)।

टीम अविश्वसनीय रूप से अच्छा करती है; सिमुलेशन में, एकमात्र टीम (जो लेखन के समय मौजूद होती है) जो इसे हरा सकती है, वह है RogueSquad, और फिर भी हमेशा नहीं (कभी-कभी RogueSquad भी दीवार की ताकत से मर जाता है)। कभी-कभी एक ड्रॉ का परिमार्जन करने के लिए इनवैलेंबल्स का प्रबंधन होता है।

टीम की सफलता का मूल कारण बफ़ × 2 और अबॉर्ब के कॉम्बो के कारण है; इसका मतलब यह है कि हर बार जब हम एसटीआर-प्राइमरी दुश्मन से टकराते हैं, तो हम प्रभावी रूप से शॉर्ट टर्म में 40 एचपी प्राप्त कर रहे हैं (केवल 10 एचपी लंबी अवधि में चोरी हुए एसटीआर से वृद्धि के कारण, लेकिन तब तक लड़ाई खत्म हो जानी चाहिए। और हमारे प्राकृतिक उत्थान को हम पर हावी होना चाहिए), और उसके ऊपर 12.5 या 17.5 की प्राकृतिक पुनर्जनन दर को देखते हुए, मूल रूप से उत्थान के साथ तालमेल बनाए रखने के लिए तेजी से नुकसान पहुंचाना असंभव है (एक एजीआई टीम संभावित रूप से हिट का उपयोग कर सकती है- और चलाने की रणनीति, लेकिन किसी ने अभी तक उनमें से एक का निर्माण नहीं किया है)। { अपडेट करें : जाहिर तौर पर यह कॉम्बो वास्तव में काम नहीं करता है (केवल 10 एचपी को अवशोषित करता है), लेकिन टीम किसी भी तरह से जीतती है।} इस बीच, अगर दुश्मन। नहीं है।एसटीआर-प्राइमरी, वे बार-बार 25- या 35-क्षति हिट लेना पसंद नहीं करेंगे (और वास्तव में संभवतः उनके एक मोड़ के नीचे ध्यान केंद्रित किया जा सकता है); और अगर दुश्मन INT-Primary है और खुद का बचाव करने के लिए मंत्र का इस्तेमाल कर रहा है (हाय इनवुलेनरेबल्स!), अबशोर्ब अंततः अपने सांसद को उस बिंदु तक ले जाएगा जहां वे अब मंत्रों को डालने का जोखिम नहीं उठा सकते हैं। (इसके अतिरिक्त, हमारे पास मूल रूप से अधिकांश मंत्रों से डरने के लिए कुछ भी नहीं है; उनके कोऑनडाउन हमारे उत्थान को नुकसान पहुंचाने के लिए बहुत लंबे हैं। मुख्य अपवाद ट्रैप हैं, जो अभी तक कोई भी नहीं चल रहा है, और ज़हर, जो 1000 या 1400 के माध्यम से पहनने के लिए उम्र लेता है। एचपी, लेकिन काम करता है अगर दीवार पहले ढलाईकार को नहीं हराती है।) सही दृष्टि अभी भी अदृश्य दुश्मनों को हराने के लिए व्यावहारिक रूप से सक्षम एकमात्र क्षमता है (ट्रैक डन ')

LivingWall.java
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.*;
import fellowship.abilities.attacking.*;
import fellowship.abilities.defensive.*;
import fellowship.abilities.vision.*;
import fellowship.abilities.stats.*;
import fellowship.abilities.statuses.*;
import fellowship.actions.*;
import fellowship.actions.attacking.*;
import fellowship.actions.damage.*;
import fellowship.actions.defensive.*;
import fellowship.actions.statuses.*;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;
import fellowship.characters.EnemyCharacter;
import fellowship.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class LivingWall extends Player {
  @Override
  public List<CharacterTemplate> createCharacters() {
    List<CharacterTemplate> templates = new ArrayList<>();

    for (int i = 0; i < 2; i++)
      templates.add(new CharacterTemplate(30, 0, 0,
                                          new Absorb(),
                                          new Strong(),
                                          new Buff(),
                                          new Buff()));
    templates.add(new CharacterTemplate(20, 0, 0,
                                        new Absorb(),
                                        new TrueSight(),
                                        new Buff(),
                                        new Buff()));

    return templates;
  }

  private String lastIdentifier(String s) {
    String[] split = s.split("\\W");
    return split[split.length - 1];
  }

  private boolean hasAbility(ReadonlyCharacter character, String abilityName) {
    for (ReadonlyAbility ability : character.getAbilities()) {
      if (lastIdentifier(ability.name()).equals(abilityName))
        return true;
    }
    return false;
  }

  private boolean hasAbility(EnemyCharacter character, String abilityName) {
    for (ReadonlyAbility ability : character.getAbilities()) {
      if (lastIdentifier(ability.name()).equals(abilityName))
        return true;
    }
    return false;
  }

  private int goalX = 5;
  private int goalY = 5;

  @Override
  public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {

    /* If we're at the goal square, pick a new one. */
    if (goalX == character.getLocation().getX() &&
        goalY == character.getLocation().getY()) {
      int i = getRandom().nextInt(5);
      goalX = i < 2 ? 1 : i > 2 ? 9 : 5;
      goalY = i == 2 ? 5 : (i % 2) == 1 ? 1 : 9;
    }

    {
      int bestDistance = 99999;
      /* If there are visible enemies, place the goal square under the closest enemy to
         the team. */
      for (Point2D enemyLocation : visibleEnemies.keysView()) {
        int distance = 0;
        for (ReadonlyCharacter ally : team) {
          Point2D allyLocation = ally.getLocation();
          distance +=
            (allyLocation.getX() - enemyLocation.getX()) *
            (allyLocation.getX() - enemyLocation.getX()) +
            (allyLocation.getY() - enemyLocation.getY()) *
            (allyLocation.getY() - enemyLocation.getY());
        }
        if (distance < bestDistance) {
          goalX = enemyLocation.getX();
          goalY = enemyLocation.getY();
          bestDistance = distance;
        }
      }
    }

    /* We use a priority rule for actions. */
    int bestPriority = -2;
    ReadonlyAction bestAction = null;
    for (ReadonlyAction action : actions) {
      int priority = 0;
      if (lastIdentifier(action.getName()).equals("Slice")) {
        int damagePotential = 35;
        /* We use these abilities with very high priority to /kill/ an enemy
           who's weak enough to die from the damage. If they wouldn't die,
           we still want to attack them, but we might prefer to attack
           other enemies instead. The enemy on the goal square (if any)
           is a slightly preferred target, to encourage the team to focus
           on a single enemy. */
        ReadonlyCharacter chosenTarget = null;
        for (ReadonlyCharacter target : action.availableTargets()) {
          if (!isEnemy(target))
            continue;
          chosenTarget = target;
          if (target.getHealth() <= damagePotential) {
            priority = 18;
          } else
            priority = 14;
          if (target.getLocation().getX() == goalX &&
              target.getLocation().getY() == goalY)
            priority++;
        }
        if (chosenTarget == null)
          continue;
        action.setTarget(chosenTarget);
      } else if (lastIdentifier(action.getName()).equals("Smile")) {
        priority = 0;
      } else if (action.movementAction()) {
        /* Move towards the goal location. */
        int bestDistance = 99999;
        Point2D bestLocation = null;
        priority = 1;
        for (Point2D location :
               action.availableLocations().toList().shuffleThis(getRandom())) {
          int distance =
            (location.getX() - goalX) * (location.getX() - goalX) +
            (location.getY() - goalY) * (location.getY() - goalY);
          if (distance < bestDistance) {
            bestDistance = distance;
            bestLocation = location;
          }
        }
        if (bestLocation == null)
          continue;
        action.setLocation(bestLocation);
      } else
        throw new RuntimeException("unknown action" + action.getName());

      if (priority > bestPriority) {
        bestPriority = priority;
        bestAction = action;
      }
    }
    if (bestAction == null)
      throw new RuntimeException("no action?");

    return bestAction;
  }
}

2

DarkAbsorbers

द डार्क एब्सोर्सर्स 2 भाई हैं, जो अपने पीड़ितों की जीवन शक्ति को अवशोषित करते हैं:

  • Oracle अवशोषक (अदृश्य दुश्मनों को देख सकते हैं)
    • एसटीआर: 25; AGI: 5; INT: 5
    • TrueSight , लचीला , लेकर , सोखना
  • त्वरित अवशोषक (अपने भाई से भी जल्दी अवशोषित कर सकता है)
    • एसटीआर: 25; AGI: 5; INT: 5
    • क्विक , फ्लेक्सिबल , रेंजेड , एब्सॉर्ब

वे हमेशा बढ़ते डार्कनेस क्लाउड के साथ होते हैं। एक बार जब यह एक महत्वपूर्ण द्रव्यमान तक पहुंच जाता है तो यह दुश्मनों को मारना शुरू कर देता है।

  • अंधेरा बादल
    • एसटीआर: 5; AGI: 5; INT: 25
    • क्लोन , जैप , डार्कनेस

आप अपनी टीम में यहां से एकल वर्णों का पुन: उपयोग कर सकते हैं, जब तक आप कम से कम एक और चरित्र जोड़ते हैं जो यहां मौजूद नहीं है।

DarkAbsorbers.java
import java.util.Arrays;
import java.util.List;

import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.set.ImmutableSet;

import com.nmerrill.kothcomm.game.maps.Point2D;

import fellowship.abilities.ActionAbility;
import fellowship.abilities.ReadonlyAbility;
import fellowship.abilities.attacking.Absorb;
import fellowship.abilities.attacking.Flexible;
import fellowship.abilities.attacking.Ranged;
import fellowship.abilities.vision.Darkness;
import fellowship.abilities.vision.TrueSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.actions.damage.Zap;
import fellowship.actions.defensive.ForceField;
import fellowship.actions.other.Clone;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

public class DarkAbsorbers extends SleafarPlayer {
    private ReadonlyCharacter zapTarget = null;

    private CharacterTemplate oracleAbsorberTemplate() {
        return new CharacterTemplate(20, 0, 0,
                new TrueSight(), new Flexible(), new Ranged(), new Absorb());
    }

    private CharacterTemplate quickAbsorberTemplate() {
        return new CharacterTemplate(20, 0, 0,
                new ActionAbility(Quick::new), new Flexible(), new Ranged(), new Absorb());
    }

    private CharacterTemplate darknessCloudTemplate() {
        return new CharacterTemplate(0, 0, 20,
                new ActionAbility(Clone::new), new ActionAbility(Zap::new), new Darkness());
    }

    @Override
    public List<CharacterTemplate> createCharacters() {
        return Arrays.asList(oracleAbsorberTemplate(), quickAbsorberTemplate(), darknessCloudTemplate());
    }

    private class Absorber extends Character {
        protected Absorber(ReadonlyCharacter delegate) {
            super(delegate);
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction quick = getAction(Quick.class);

            if (quick != null && setSliceTarget(quick, 100.0)) {
                return quick;
            }
            if (slice != null && setSliceTarget(slice, 100.0)) {
                return slice;
            }

            ImmutableMap<Point2D, Double> damage = getEnemySliceDamage();
            ImmutableSet<Point2D> above5Damage = damage.select((k, v) -> v > 5.0).keysView().toSet().toImmutable();

            if (step != null && (above5Damage.contains(getLocation()) ||
                    (getHealth() <= 5.0 && isInEnemySliceRange())) && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (quick != null && setSliceTarget(quick, 0.01)) {
                return quick;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null && getSliceLocations().notEmpty() && setClosestLocation(step, getSliceLocations())) {
                return step;
            }
            if (step != null && setExploreLocation(step)) {
                return step;
            }
            return smile;
        }
    }

    private class DarknessCloud extends Character {
        private int zapCooldown = 0;
        private boolean zapNow = false;
        private boolean zapLater = false;

        protected DarknessCloud(ReadonlyCharacter delegate) {
            super(delegate);
        }

        private void updateZapFlags(double mana) {
            zapNow = zapCooldown == 0 && mana >= 15.0;
            zapLater = mana + 5 * getManaRegen() >= (zapNow ? 30.0 : 15.0);
        }

        private boolean isZappable(ReadonlyCharacter c, int zapNowCount, int zapLaterCount) {
            int forceFieldNow = 0;
            int forceFieldLater = 0;
            for (ReadonlyAbility a : c.getAbilities()) {
                if (a.abilityClass().equals(ForceField.class)) {
                    forceFieldNow = a.getRemaining();
                    forceFieldLater = 5;
                }
            }
            return c.getHealth() + c.getHealthRegen() <= (zapNowCount - forceFieldNow) * 30.0 ||
                    c.getHealth() + c.getHealthRegen() * 6 <= (zapNowCount + zapLaterCount - forceFieldNow - forceFieldLater) * 30.0;
        }

        @Override
        protected ReadonlyAction choose() {
            ReadonlyAction clone = getAction(Clone.class);
            ReadonlyAction zap = getAction(Zap.class);

            zapCooldown = zapCooldown > 0 ? zapCooldown - 1 : 0;
            updateZapFlags(getMana());
            int zapNowCount = characters.count(c -> c instanceof DarknessCloud && ((DarknessCloud) c).zapNow);
            int zapLaterCount = characters.count(c -> c instanceof DarknessCloud && ((DarknessCloud) c).zapLater);

            if (zap != null) {
                if (zapTarget != null && (!zap.availableTargets().contains(zapTarget) || zapTarget.isDead() ||
                        !isZappable(zapTarget, zapNowCount, zapLaterCount))) {
                    zapTarget = null;
                }
                if (zapTarget == null) {
                    zapTarget = chooseSmallest(zap.availableTargets().reject(c ->
                            isBear(c) || !isZappable(c, zapNowCount, zapLaterCount)), HEALTH_COMPARATOR);
                }
                if (zapTarget != null) {
                    zapCooldown = 5;
                    zapNow = false;
                    zap.setTarget(zapTarget);
                    return zap;
                }
            }

            ImmutableMap<Point2D, Double> damage = getEnemySliceDamage();
            ImmutableSet<Point2D> above5Damage = damage.select((k, v) -> v > 5.0).keysView().toSet().toImmutable();

            if (clone != null) {
                if (visibleEnemies.isEmpty()) {
                    if (setFarthestLocation(clone, getTeamHiddenLocations())) {
                        updateZapFlags(getMana() - 100.0);
                        return clone;
                    }
                } else {
                    if (setFarthestLocation(clone, above5Damage, getEnemyLocations()) ||
                            setLocation(clone, chooseSmallest(clone.availableLocations(),
                            (o1, o2) -> Double.compare(damage.get(o1), damage.get(o2))))) {
                        updateZapFlags(getMana() - 100.0);
                        return clone;
                    }
                }

                return clone;
            }
            if (step != null && (above5Damage.contains(getLocation()) ||
                    (getHealth() <= 5.0 && isInEnemySliceRange())) && setAvoidEnemiesLocation(step)) {
                return step;
            }
            if (slice != null && setSliceTarget(slice, 0.01)) {
                return slice;
            }
            if (step != null && !visibleEnemies.isEmpty() &&
                    setFarthestLocation(step, getEnemySliceLocations(), getEnemyLocations())) {
                return step;
            }
            return smile;
        }
    }

    @Override
    protected Character createCharacter(ReadonlyCharacter delegate) {
        if (hasAbility(delegate, Absorb.class)) {
            return new Absorber(delegate);
        } else if (hasAbility(delegate, Darkness.class)) {
            return new DarknessCloud(delegate);
        } else {
            throw new IllegalArgumentException();
        }
    }
}

0

LongSwordv2

"आप चला सकते हैं, लेकिन आप छिपा नहीं सकते ..." - LongSwordv2

उपयोग लेकर , लचीला , त्वरित , TrueSight

यह बॉट बिल्कुल है LongSwordv2 जैसा है, सिवाय इसके कि यह स्ट्रॉन्ग की जगह ट्रूसाइट का इस्तेमाल करता है।

अदृश्य बॉट्स में वृद्धि को देखते हुए, मैंने एक बॉट बनाने का फैसला किया, जो उन्हें कई बॉट्स द्वारा undetectable होने के बाद से बाहर निकालने में केंद्रित है। अपनी लंबी दूरी और लचीली स्लाइस रेंज और डबल स्लाइस एक्शनएबिलिटी के साथ, लॉन्गसवर्ड 2 को स्लीक रेंज में दुश्मन के पात्रों के आने से पहले भारी क्षति पहुंचाने में सक्षम होना चाहिए। और इसके परीक्षण चरणों में, मैं कहूंगा कि यह उन टीमों के खिलाफ जीतता है जो ज्यादातर समय अदृश्य पात्रों के आसपास केंद्रित होती हैं।

LongSwordv2.java
import fellowship.*;
import com.nmerrill.kothcomm.game.maps.Point2D;
import fellowship.abilities.ActionAbility;
import fellowship.abilities.attacking.Flexible;
import fellowship.abilities.attacking.Ranged;
import fellowship.abilities.stats.Strong;
import fellowship.abilities.vision.Darkness;
import fellowship.abilities.vision.TrueSight;
import fellowship.actions.ReadonlyAction;
import fellowship.actions.attacking.Quick;
import fellowship.characters.CharacterTemplate;
import fellowship.characters.ReadonlyCharacter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class LongSwordv2 extends Player{
    //debugging
    private boolean debug = false;
    private void println(String text) {
        if(debug)
            System.out.println(text);
    }

    //variables use to hold the start Y coordinate of the bot
    private boolean started = false;
    private int startY = 5;

    private boolean together = false;

    @Override
    public List<CharacterTemplate> createCharacters() {
        List<CharacterTemplate> templates = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            templates.add(new CharacterTemplate(20, 0, 0,
                    new Ranged(), //Adds 1 to the range of Slice
                    new Flexible(), //Can Slice in any of the 8 directions
                    new ActionAbility(Quick::new), //Slice twice, Mana: 3, Cooldown: 0
                    new TrueSight())); //Reveals all hidden units within range 2 at turn start
        }
        return templates;
    }

    @Override
    public ReadonlyAction choose(Set<ReadonlyAction> actions, ReadonlyCharacter character) {
        if(!started) {
            startY = character.getLocation().getY(); //giving startY the value of the bot's starting y-value
            started = true; //do this only once, that's why there is the if statement
        }

        ReadonlyAction current = null;

        //choosing action depending on priority
        int priority = Integer.MAX_VALUE;
        for(ReadonlyAction action:actions) {
            int priorityLocal = getPriority(action, character);
            if(priorityLocal < priority) {
                current = action;
                priority = priorityLocal;
            }
        }

        if (current == null){
            throw new RuntimeException("No valid actions");
        }

        println(current.getName());

        if(current.needsLocation()) {
            if(visibleEnemies.isEmpty()) {
                if (character.getHealth() < 100) {
                    //if has low health, go backwards towards "base"
                    //println("lowHealth");
                    current.setLocation(move(current, character, "backward"));
                } else {
                    //else go forwards to enemy's "base"
                    current.setLocation(move(current, character, "forward"));
                }
            }else{
                //go towards closest enemy
                current.setLocation(current.availableLocations().minBy(p1->p1.cartesianDistance(visibleEnemies.keysView().minBy(p1::cartesianDistance))));
            }
        }
        if(current.needsTarget()) {
            //get closest target
            current.setTarget(current.availableTargets().minBy(p1 -> 0));
        }

        Iterator<ReadonlyCharacter> iterator = current.availableTargets().iterator();

        while(iterator.hasNext()) {
            Point2D loc = iterator.next().getLocation();
            println(loc.getX()+","+loc.getY());
        }

        return current;
    }

    //move backwards or forwards
    private Point2D move(ReadonlyAction readonlyAction, ReadonlyCharacter character, String direction) {
        Point2D location = null;

        //move direction depending on Y coordinate of point
        for(Point2D point2D:readonlyAction.availableLocations()) {
            switch (direction) {
                case "forward":
                    if(startY > 5) { //bot started at bottom
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }else{ //bot started at top
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }
                    break;
                case "backward":
                    if(startY > 5) { //bot started at bottom
                        if (point2D.getY() > character.getLocation().getY())
                            location = point2D;
                    }else{ //bot started at top
                        if (point2D.getY() < character.getLocation().getY())
                            location = point2D;
                    }
                    break;
            }

        }

        //if no available locations, just choose the first available location
        if(location == null) {
            location = readonlyAction.availableLocations().iterator().next();
        }

        println(location.getY()+","+character.getLocation().getY());

        return location;
    }

    private int getPriority(ReadonlyAction action, ReadonlyCharacter character) {
        if(visibleEnemies.isEmpty()) {
            //if there are no visible enemies, Step. In the choose function, this becomes move forward or backward depending on health
            if(action.getName().equals("Step")) {
                return 100;
            }
        }else {
            /*
             * PRIORITIES:
             *  1. Quick (Slice twice)
             *  2. Slice
             *  3. Step (when enemy is not in range --> move towards enemy)
             */
            if (action.getName().equals("Quick")) {
                return 1;
            }else if(action.getName().equals("Slice")) {
                return 10;
            }else if(action.getName().equals("Step")) {
                return 50;
            }
        }
        //Kids, don't Smile, instead Step or Slice
        return 1000;
    }
}

इस बॉट को डाउनलोड करना विफल हो जाता है, क्योंकि हेडर गायब है।
स्लेफ़र

@Sleafar वहाँ हम ... इसे जोड़ा!
कृति लिथोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.