Splix.io - भूमि का राजा


37

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

यदि आपने पहले से इसे आज़माया नहीं है, तो Splix.io पर जाएं और एक गेम आज़माएं। अपने आंदोलन को नियंत्रित करने के लिए तीर कुंजियों का उपयोग करें।

GIF

यहाँ छवि विवरण दर्ज करें

साभार: http://splix.io/

विशिष्ट तथ्य

सभी खिलाड़ी 200x200 बोर्ड में यादृच्छिक पदों पर शुरू करते हैं। (मैं इसे बदलने का अधिकार सुरक्षित रखता हूं :)। आपके पास सबसे अधिक संभव अंक प्राप्त करने के लिए कुछ निश्चित चालें होंगी। अंक इससे ऊँचे होते हैं:

  • आपके द्वारा मारे गए खिलाड़ियों की संख्या 300 है
  • दौर के अंत में आपके पास जितनी जमीन है

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

प्रत्येक दौर में खिलाड़ियों का एक यादृच्छिक रूप से चयनित समूह होता है (अधिकतम 5 अद्वितीय खिलाड़ी) (परिवर्तन के अधीन)। हर खिलाड़ी बराबर राउंड में भाग लेता है। आपके बॉट का अंतिम स्कोर उसके औसत प्रति गेम स्कोर से निर्धारित होता है। प्रत्येक गेम में 2000 मोड़ शामिल हैं (परिवर्तन के अधीन भी)। सभी बॉट एक ही समय में अपनी चाल बनाते हैं।

मौत के मामले

सिर बट

सिर बट

दोनों खिलाड़ी एक दूसरे के सिर पर हाथ फेरते हैं। यह तब भी सच है जब दोनों खिलाड़ी अपने स्थान के किनारे पर हों।

सिर बट

हालांकि, जब केवल एक खिलाड़ी अपनी भूमि में होता है, तो दूसरा खिलाड़ी मर जाता है।

यहाँ छवि विवरण दर्ज करें

रेखा पार

यहाँ छवि विवरण दर्ज करें

इस मामले में, केवल बैंगनी खिलाड़ी मर जाता है।

आप अपनी स्वयं की रेखा को पार नहीं कर सकते।

यहाँ छवि विवरण दर्ज करें

बोर्ड से बाहर निकलना

बोर्ड से बाहर जा रहा खिलाड़ी

यदि कोई खिलाड़ी बोर्ड से बाहर निकलने का प्रयास करता है, तो वह मर जाएगा और सभी बिंदुओं को खो देगा।

क्षेत्र पर कब्जा करना

एक खिलाड़ी उस क्षेत्र पर कब्जा करेगा जब उसके पास एक निशान होगा और वह फिर से अपनी जमीन में प्रवेश करेगा।

यहाँ छवि विवरण दर्ज करें

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

नियंत्रक का विवरण

नियंत्रक यहाँ है । यह मूल खेल से काफी मिलता-जुलता है, लेकिन इसमें कोठ के लिए बेहतर और तकनीकी कारणों से छोटे बदलाव किए गए हैं। यह @NathanMerrill के KotHComm लाइब्रेरी के साथ बनाया गया है , और साथ ही @NathanMerrill की पर्याप्त मदद के साथ बनाया गया है। कृपया मुझे चैट रूम में कंट्रोलर में किसी भी कीड़े के बारे में बताएं । KotHComm के अनुरूप होने के लिए, मैंने पूरे नियंत्रक में ग्रहण संग्रह का उपयोग किया है, लेकिन बॉट को केवल जावा संग्रह पुस्तकालय का उपयोग करके लिखा जा सकता है।

सब कुछ github रिलीज पृष्ठ पर एक uberjar में पैक किया गया है । इसका उपयोग करने के लिए, इसे डाउनलोड करें और इसे अपनी परियोजना में संलग्न करें ताकि आप इसे ऑटो-कम्पेट ( इंटेलीज , एक्लिप्स के लिए निर्देश ) के लिए उपयोग कर सकें । अपने सबमिशन को टेस्ट करने के लिए, आप जार को रन करें java -jar SplixKoTH-all.jar -d path\to\submissions\folder। सुनिश्चित करें कि path\to\submissions\folderएक सबफ़्लोर नाम दिया गया है java, और अपनी सभी फ़ाइलों को वहां रखने के लिए। अपने बॉट्स में पैकेज के नाम का उपयोग न करें (हालांकि यह कोटएचएचओएम के साथ संभव हो सकता है, यह थोड़ा अधिक परेशानी है)। सभी विकल्पों को देखने के लिए, उपयोग करें --help। सभी बॉट्स को लोड करने के लिए, उपयोग करें --question-id 126815

बॉट लिखना

बॉट लिखना शुरू करने के लिए, आपको विस्तार करना होगा SplixPlayer

  • Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board)
    • यह वह जगह है जहां आप तय करते हैं कि आप अपने बॉट को किस दिशा में ले जाना चाहते हैं। अशक्त नहीं लौटना चाहिए।
  • HiddenPlayer getThisHidden()
    • का HiddenPlayerसंस्करण प्राप्त करें this। बोर्ड को अपने बॉट की तुलना करने के लिए उपयोगी।

enum Direction

  • मान
    • East (x = 1; y = 0)
    • West (x = -1; y = 0)
    • North (x = 0; y = 1)
    • South (x = 0; y = -1)
  • Direction leftTurn()
    • जाओ Directionअगर तुम एक छोड़ दिया बारी बनाया आपको मिल जाएगा।
  • Direction RightTurn()
    • जाओ Directionयदि आप एक सही बारी बनाया आपको मिल जाएगा।

ReadOnlyBoard

यह वह वर्ग है जहां आप बोर्ड का उपयोग करते हैं। आप या तो बोर्ड के एक स्थानीय दृश्य (20x20) को दिखाए गए खिलाड़ी पदों के साथ, या एक वैश्विक दृश्य (संपूर्ण बोर्ड) प्राप्त कर सकते हैं, जिसके पास केवल यह जानकारी होती है कि कौन किसके पास है और बोर्ड पर पदों का दावा करता है। यह वह जगह भी है जहां आप अपना स्थान प्राप्त करते हैं।

  • SquareRegion getBounds()
    • बोर्ड के आकार को पुनः प्राप्त करें।
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal()
    • बोर्ड का वैश्विक मानचित्र प्राप्त करें।
  • MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView()
    • के रूप में भी getGlobal(), सिवाय इसके कि यह आपके खिलाड़ी के चारों ओर 20x20 क्षेत्र तक सीमित है, और यह खिलाड़ी के पदों को दर्शाता है।
  • Point2D getPosition(SplixPlayer me)
    • अपने खिलाड़ी की स्थिति प्राप्त करें। के रूप में उपयोग करें board.getPosition(this)
  • Point2D getSelfPosition(ReadOnlyBoard)
    • बोर्ड पर अपना स्थान प्राप्त करें। उपयोग:Point2D mypos = getSelfPosition(board)

ReadOnlyGame

ReadOnlyGameकेवल खेल के माध्यम से बचे हुए घुमावों की संख्या तक पहुँच प्रदान करता है int getRemainingIterations()

ReadOnlySplixPoint

  • HiddenPlayer getClaimer()
    • HiddenPlayerएक बिंदु का दावा करने वाले का संस्करण प्राप्त करें - दावा करने वाला = एक निशान।
  • HiddenPlayer getOwner()
    • जो एक बिंदु का मालिक हो जाओ।
  • HiddenPlayer getWhosOnSpot()
    • यदि खिलाड़ी को इस बिंदु पर तैनात किया गया है, तो इसके छिपे हुए संस्करण को लौटाएं। में ही काम करता है getLocal()

Point2D

यहां अन्य वर्गों के विपरीत, Point2Dकोटहोम लाइब्रेरी में निहित है।com.nmerrill.kothcomm.game.maps.Point2D

  • Point2D(int x, int y)
  • int getX()
  • int getY()
  • Point2D moveX(int x)
  • Point2D moveY(int y)
  • Point2D wrapX(int maxX)
    • xकी सीमा के भीतर होने के लिए मान लपेटें maxX
  • Point2D wrapY(int maxY)
    • yकी सीमा के भीतर होने के लिए मान लपेटें maxY
  • int cartesianDistance(Point2D other)
    • यह इस बात का अनुवाद करता है कि एक खिलाड़ी को बिंदु a से बिंदु b पर जाने के लिए कितने मोड़ लेने होंगे।

लौंग का सहारा

क्लोजर कंपाइलर के साथ बंडल किया गया है SplixKoTH-all.jar, इसलिए आप अपने बॉट के लिए क्लोझर का उपयोग कर सकते हैं! random_botइसका उपयोग करने के तरीके को देखने के लिए मेरा संदर्भ लें ।

एक बॉट डिबगिंग

नियंत्रक परीक्षण रणनीतियों की सहायता के लिए डिबगर के साथ आता है। इसे शुरू करने के लिए, --guiविकल्प के साथ जार चलाएं ।

डीबगर को अपने जार में संलग्न करने के लिए, IntelliJ के लिए इन निर्देशों का पालन करें , या ग्रहण के लिए इन निर्देशों (ग्रहण संस्करण अप्राप्त)।

यहाँ छवि विवरण दर्ज करें

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

यहाँ छवि विवरण दर्ज करें

अब, यह सब एक साथ करने के लिए:

चल बॉट्स

दूसरों के साथ अपने बॉट्स को चलाने के लिए, आपको रिलीज़ पृष्ठ पर जार को चलाने की आवश्यकता है। यहाँ झंडे की एक सूची है:

  • --iterations( -i) <= int(डिफ़ॉल्ट 500)
    • चलाने के लिए गेम की संख्या निर्दिष्ट करें।
  • --test-bot( -t) <=String
    • केवल उन खेलों को चलाएं जिनमें बॉट शामिल है।
  • --directory( -d) <= पथ
    • से प्रस्तुतियाँ चलाने के लिए निर्देशिका। अपने बॉट्स को चलाने के लिए इसका उपयोग करें। सुनिश्चित करें कि आपके बॉट्स नाम के पथ के सबफ़ोल्डर में हैं java
  • --question-id( -q) <= int(केवल उपयोग 126815)
    • डाउनलोड करें और साइट से अन्य प्रस्तुतियाँ संकलित करें।
  • --random-seed( -r) <= int(यादृच्छिक संख्या में चूक)
    • धावक को एक बीज दें ताकि बॉट्स जो यादृच्छिक का उपयोग करें, परिणाम पुन: उत्पन्न हो सकते हैं।
  • --gui( -g)
    • एक टूर्नामेंट चलाने के बजाय डिबगर उई चलाएं। के साथ सबसे अच्छा इस्तेमाल किया --test-bot
  • --multi-thread( -m) <= boolean(डिफ़ॉल्ट true)
    • मल्टी-थ्रेड मोड में एक टूर्नोमेंट चलाएँ। यदि आपके कंप्यूटर में एकाधिक कोर हैं, तो यह एक तेज़ परिणाम को सक्षम करता है।
  • --thread-count( -c) <= int(डिफ़ॉल्ट 4)
    • मल्टी-थ्रेड की अनुमति होने पर थ्रेड्स की संख्या।
  • --help( -h)
    • इसके समान एक सहायता संदेश प्रिंट करें।

इस पृष्ठ पर सभी प्रस्तुतियाँ चलाने के लिए, उपयोग करें java -jar SplixKoTH-all.jar -q 126815

अपनी पोस्ट का प्रारूपण

यह सुनिश्चित करने के लिए कि नियंत्रक सभी बॉट्स डाउनलोड कर सकता है, आपको इस प्रारूप का पालन करना चाहिए।

[BotName], Java                     // this is a header
                                    // any explanation you want
[BotName].java                      // filename, in the codeblock
[code]

इसके अलावा, पैकेज की घोषणा का उपयोग न करें।


स्कोरबोर्ड

+------+--------------+-----------+
| Rank | Name         |     Score |
+------+--------------+-----------+
|    1 | ImNotACoward | 8940444.0 |
|    2 | TrapBot      |  257328.0 |
|    3 | HunterBot    |  218382.0 |
+------+--------------+-----------+

कृपया मुझे बताएं कि क्या नियमों का कोई भी हिस्सा अस्पष्ट है, या यदि आपको चैट रूम में नियंत्रक में कोई त्रुटि मिलती है ।

मज़े करो!


अरे, यह आखिर पोस्ट हो गया! मैं सोच रहा था: D
MD XF

आप कितनी देर से प्रतीक्षा कर रहे हैं? ;) क्या आप जमा करने की योजना बनाते हैं?
J Atkin

मुझे नहीं पता कि मैं इस तरह की चुनौती को हल कर पाऊंगा या नहीं, क्योंकि मैं मुख्य रूप से एसोलंग में कार्यक्रम लिखता हूं। लेकिन मैंने इसे सैंडबॉक्स में देखा और यह एक बड़ी चुनौती की तरह लग रहा था!
एमडी एक्सएफ

@hyperneutrino मैंने संपादन देखा, क्या यह वास्तव में आपको परेशान करता है? राजनीतिक शुद्धता इस पद के दायरे में कहीं नहीं है, और यह पूरी तरह से सही अंग्रेजी व्याकरण है ...
जे एटकिन

2
0. छोटी सी दुनिया? मैं splix.io के डेवलपर को (के) जानता हूं। (यह @ उन्होंने ट्वीट किया)
CAD97

जवाबों:


2

ImNotACoward, जावा

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

ImNotACoward.java
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.MutableSet;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.Maps;
import org.eclipse.collections.impl.factory.Sets;

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;

public class ImNotACoward extends SplixPlayer {
    private static final MutableSet<Direction> DIRECTIONS = Sets.mutable.of(Direction.values());

    private static class Board {
        public MutableSet<Point2D> allPoints = null;
        private SquareRegion globalBounds = null;
        private SquareRegion viewBounds = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> global = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> view = null;

        public void update(ReadOnlyBoard readOnlyBoard) {
            if (this.allPoints == null) {
                this.allPoints = readOnlyBoard.getGlobal().keysView().toSet();
                this.globalBounds = readOnlyBoard.getBounds();
            }
            this.viewBounds = readOnlyBoard.viewingArea;
            this.global = readOnlyBoard.getGlobal();
            this.view = readOnlyBoard.getView();
        }

        public boolean inBounds(Point2D point) {
            return globalBounds.inBounds(point);
        }

        public boolean inView(Point2D point) {
            return viewBounds.inBounds(point);
        }

        public ReadOnlySplixPoint getSplixPoint(Point2D point) {
            return inView(point) ? view.get(point) : global.get(point);
        }

        public MutableSet<Point2D> getNeighbors(Point2D point) {
            return DIRECTIONS.collect(d -> point.move(d.vector.getX(), d.vector.getY())).select(this::inBounds);
        }

        public MutableSet<Point2D> getNeighbors(MutableSet<Point2D> points) {
            return points.flatCollect(this::getNeighbors);
        }

        public MutableSet<Point2D> getBorders(SquareRegion region) {
            return allPoints.select(p -> region.inBounds(p) &&
                    (p.getX() == region.getLeft() || p.getX() == region.getRight() ||
                    p.getY() == region.getTop() || p.getY() == region.getBottom() ||
                    p.getX() == globalBounds.getLeft() || p.getX() == globalBounds.getRight() ||
                    p.getY() == globalBounds.getTop() || p.getY() == globalBounds.getBottom()));
        }
    }

    private class Player {
        public final HiddenPlayer hiddenPlayer;
        public MutableSet<Point2D> owned = Sets.mutable.empty();
        private MutableSet<Point2D> unowned = null;
        private MutableSet<Point2D> oldClaimed = Sets.mutable.empty();
        public MutableSet<Point2D> claimed = Sets.mutable.empty();
        private MutableSet<Point2D> oldPos = Sets.mutable.empty();
        public MutableSet<Point2D> pos = Sets.mutable.empty();

        public Player(HiddenPlayer hiddenPlayer) {
            super();
            this.hiddenPlayer = hiddenPlayer;
        }

        public void nextMove() {
            owned.clear();
            unowned = null;
            oldClaimed = claimed;
            claimed = Sets.mutable.empty();
            oldPos = pos;
            pos = Sets.mutable.empty();
        }

        public MutableSet<Point2D> getUnowned() {
            if (unowned == null) {
                unowned = board.allPoints.difference(owned);
            }
            return unowned;
        }

        public void addOwned(Point2D point) {
            owned.add(point);
        }

        public void addClaimed(Point2D point) {
            claimed.add(point);
        }

        public void setPos(Point2D point) {
            pos.clear();
            pos.add(point);
        }

        public void calcPos() {
            if (pos.isEmpty()) {
                MutableSet<Point2D> claimedDiff = claimed.difference(oldClaimed);
                if (claimedDiff.size() == 1) {
                    pos = board.getNeighbors(claimedDiff).select(p -> !claimed.contains(p) && !board.inView(p));
                } else if (!oldPos.isEmpty()) {
                    pos = board.getNeighbors(oldPos).select(p -> owned.contains(p) && !board.inView(p));
                } else {
                    pos = owned.select(p -> !board.inView(p));
                }
            }
        }
    }

    private Board board = new Board();
    private Point2D myPos = null;
    private final Player nobody = new Player(new HiddenPlayer(null));
    private final Player me = new Player(new HiddenPlayer(this));
    private MutableMap<HiddenPlayer, Player> enemies = Maps.mutable.empty();
    private MutableMap<HiddenPlayer, Player> players = Maps.mutable.of(nobody.hiddenPlayer, nobody, me.hiddenPlayer, me);
    private MutableSet<Point2D> path = Sets.mutable.empty();

    private Player getPlayer(HiddenPlayer hiddenPlayer) {
        Player player = players.get(hiddenPlayer);
        if (player == null) {
            player = new Player(hiddenPlayer);
            players.put(player.hiddenPlayer, player);
            enemies.put(player.hiddenPlayer, player);
        }
        return player;
    }

    private Direction moveToOwned() {
        MutableSet<Point2D> targets = me.owned.difference(me.pos);
        if (targets.isEmpty()) {
            return moveTo(myPos);
        } else {
            return moveTo(targets.minBy(myPos::cartesianDistance));
        }
    }

    private Direction moveTo(Point2D target) {
        return DIRECTIONS.minBy(d -> {
            Point2D p = myPos.move(d.vector.getX(), d.vector.getY());
            return !board.inBounds(p) || me.claimed.contains(p) ? Integer.MAX_VALUE : target.cartesianDistance(p);
        });
    }

    @Override
    protected Direction makeMove(ReadOnlyGame readOnlyGame, ReadOnlyBoard readOnlyBoard) {
        board.update(readOnlyBoard);
        myPos = readOnlyBoard.getPosition(this);
        path.remove(myPos);

        for (Player e : players.valuesView()) {
            e.nextMove();
        }
        for (Point2D point : board.allPoints) {
            ReadOnlySplixPoint splixPoint = board.getSplixPoint(point);
            getPlayer(splixPoint.getOwner()).addOwned(point);
            getPlayer(splixPoint.getClaimer()).addClaimed(point);
            getPlayer(splixPoint.getWhosOnSpot()).setPos(point);
        }
        for (Player e : players.valuesView()) {
            e.calcPos();
        }

        if (me.owned.contains(myPos) && path.allSatisfy(p -> me.owned.contains(p))) {
            path.clear();
        }

        if (path.isEmpty()) {
            MutableSet<Point2D> enemyPositions = enemies.valuesView().flatCollect(e -> e.pos).toSet();
            int enemyDistance = enemyPositions.isEmpty() ? Integer.MAX_VALUE :
                    enemyPositions.minBy(myPos::cartesianDistance).cartesianDistance(myPos);

            if (enemyDistance < 20) {
                MutableSet<Point2D> enemyClaimed = enemies.valuesView().flatCollect(e -> e.claimed).toSet();
                if (!enemyClaimed.isEmpty()) {
                    Point2D closestClaimed = enemyClaimed.minBy(myPos::cartesianDistance);
                    if (closestClaimed.cartesianDistance(myPos) < enemyDistance) {
                        return moveTo(closestClaimed);
                    } else if (enemyDistance < 10) {
                        return moveToOwned();
                    }
                }
            }

            if (me.owned.contains(myPos)) {
                if (!me.getUnowned().isEmpty()) {
                    Point2D target = me.getUnowned().minBy(myPos::cartesianDistance);
                    if (target.cartesianDistance(myPos) > 2) {
                        return moveTo(target);
                    }
                }

                int safeSize = Math.max(1, Math.min(enemyDistance / 6, readOnlyGame.getRemainingIterations() / 4));
                SquareRegion region = Lists.mutable
                        .of(new SquareRegion(myPos, myPos.move(safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(safeSize, -safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, -safeSize)))
                        .maxBy(r -> me.getUnowned().count(p -> r.inBounds(p)));
                path = board.getBorders(region);
            } else {
                return moveToOwned();
            }
        }

        if (!path.isEmpty()) {
            return moveTo(path.minBy(myPos::cartesianDistance));
        }

        return moveToOwned();
    }
}

1

ट्रैपबॉट, जावा

TrapBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;
import javafx.util.Pair;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Lists;

import java.util.Comparator;

/**
 * Trap bot goes to the wall and traces the entirety around. Hopes that
 * the players in the middle die and that nobody challenges him. Nearly 
 * all turns are left turns.
 */
public class TrapBot extends SplixPlayer {

    /**
     * Mode when the bot is attempting to reach the wall from it's original spawn
     * location.
     */
    public static final int MODE_GOING_TO_WALL = 1;

    /**
     * Mode when we have reached the wall and are now going around the board.
     */
    public static final int MODE_FOLLOWING_WALL = 2;

    private int mode = MODE_GOING_TO_WALL;

    public static int WALL_EAST = 1;
    public static int WALL_NORTH = 2;
    public static int WALL_WEST = 3;
    public static int WALL_SOUTH = 4;


    /**
     * How long the bot would like to go before he turns around to go back home.
     */
    private static final int PREFERRED_LINE_DIST = 5;

    private int distToTravel = 0;

    private Direction lastMove = Direction.East;// could be anything that's not null
    private int lastTrailLength = 0;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Direction ret = null;
        MutableMap<Point2D, ReadOnlySplixPoint> view = board.getView();
        int trailLength = getTrailLength(board, view);

        if (trailLength == 0) {

            int closestWall = getClosestWall(board);
            Direction directionToWall = getDirectionToWall(closestWall);

            if (lastTrailLength != 0) {
                ret = lastMove.leftTurn();
                // move to the other half of 2 width line so we can start without shifting to the left
            }

            if (mode == MODE_GOING_TO_WALL && ret == null) {
                int distCanTravel = getDistCanTravel(
                        getSelfPosition(board), board.getBounds(), directionToWall);
                if (distCanTravel == 0) mode = MODE_FOLLOWING_WALL;
                else ret = directionToWall;
                distToTravel = distCanTravel;

            }

            if (mode == MODE_FOLLOWING_WALL && ret == null) {
                int distCanTravel = 0;
                ret = directionToWall;
                while (distCanTravel == 0) {// keep turning left until we can get somewhere
                    ret = ret.leftTurn();
                    distCanTravel = getDistCanTravel(
                            getSelfPosition(board), board.getBounds(), ret);
                }

                distToTravel = distCanTravel;
            }
        }

        // once we have started we are on auto pilot (can't run after the before block)
        else if (trailLength == distToTravel || trailLength == (distToTravel + 1))
            ret = lastMove.leftTurn();

        if (ret == null)// if we don't have a move otherwise, we must be on our trail. ret same as last time
            ret = lastMove;

        lastTrailLength = trailLength;
        lastMove = ret;
        return ret;
    }

    int getClosestWall(ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        return Lists.mutable.of(
                new Pair<>(WALL_NORTH, board.getBounds().getTop() - thisPos.getY()),
                new Pair<>(WALL_SOUTH, thisPos.getY()), 
                new Pair<>(WALL_EAST, board.getBounds().getRight() - thisPos.getX()),
                new Pair<>(WALL_WEST, thisPos.getX())
        ).min(Comparator.comparingInt(Pair::getValue)).getKey();
    }

    /**
     * This goes around some intended behavior in the controller to get the correct result. When a player goes outside
     * his territory the land under him is converted to a trail -- on the next step of the game. So a trail length may
     * be the count of the trail locations plus one. That is what this function calculates. Depends on the whole trail
     * being contained inside the view passed to it.
     * @return
     */
    int getTrailLength(ReadOnlyBoard board, MutableMap<Point2D, ReadOnlySplixPoint> view) {
        boolean isPlayerOutsideHome = !view.get(getSelfPosition(board)).getOwner().equals(getThisHidden());
        int trailLength = view.count(rop -> rop.getClaimer().equals(getThisHidden()));
        return trailLength + (isPlayerOutsideHome? 1 : 0);
    }

    /**
     * Calculate how far we can travel in the direction before we hit the wall.
     * @return
     */
    int getDistCanTravel(Point2D currPos, SquareRegion bounds, Direction direction) {
        for (int i = 1; i <= PREFERRED_LINE_DIST; i++) {
            if (!bounds.inBounds(currPos.move(direction.vector.getX()*i, direction.vector.getY()*i)))
                return i-1;
        }
        return PREFERRED_LINE_DIST;
    }

    /**
     * Get which direction needs to be traveled to reach the specified wall.
     * Requires that neither Direction nor the values of `WALL_...` change.
     * @param targetWall
     * @return
     */
    Direction getDirectionToWall(int targetWall) {
        return Direction.values()[targetWall-1];
    }
}

यह शायद सबसे सरल बॉट है। यह सब बोर्ड के किनारे का पता लगाता है, मारे जाने के जोखिम को कम करने के लिए खुद पर दोहरीकरण करता है।


आपको ग्रहण संग्रह देखने के लिए कूल। ईसी में एक पेयर इंटरफेस है। एक जोड़ी उदाहरण प्राप्त करने के लिए आप Tuples.pair () का उपयोग कर सकते हैं। एक PrimitiveTuples वर्ग भी है अगर या तो जोड़ी में दोनों मान प्राइमेटिव हैं।
डोनाल्ड रबाब

1

random_bot, क्लोजर

यह रैंडमबॉट है , लेकिन मुझे नामकरण सम्मेलनों से चिपके रहना था, और कुछ मुद्दे मुझे नाम में हाइफ़न का उपयोग करने से रोकते हैं, इसलिए अधोहस्ताक्षरी शासन करते हैं! make-moveFn पहला आइटम होने के साथ एक vec रिटर्न Directionआप में ले जाना चाहते हैं, और दूसरा जा रहा है राज्य आप चाहते हैं अगली बारी पर वापस आप के लिए पारित किया जाना है। किसी भी बाहरी परमाणु का उपयोग न करें, क्योंकि यह कोड समानांतर में कई गेम चला सकता है।

 random_bot.clj
 (ns random-bot
     (:import
      [com.jatkin.splixkoth.ppcg.game Direction]))

 (defn make-move [game board state]
       [(rand-nth [Direction/East
                   Direction/West
                   Direction/North
                   Direction/South])
        nil])

0

हंटरबॉट, जावा

HunterBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.impl.factory.Sets;

import java.util.Comparator;

/**
 * This bot looks for any trail points left behind by another player and sets that as his target. If the target ever
 * disappears, it will continue on in hopes that the player will return soon, or if another target appears, it will
 * go towards that one. Works best when the other player repeatedly goes in the same general direction.
 */
public class HunterBot extends SplixPlayer {

    private Point2D lastTarget;

    private Direction lastMove = Direction.East;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        MutableMap<Point2D, ReadOnlySplixPoint> global = board.getGlobal();
        MutableMap<Point2D, ReadOnlySplixPoint> targets = global.select((pt, rosp) ->
                !rosp.getClaimer().equals(getThisHidden()) 
                        && !rosp.getClaimer().equals(new HiddenPlayer(null)));

        if (targets.size() == 0 && lastTarget == null) {
            lastMove = lastMove.leftTurn();
            return lastMove;
        }

        Point2D target = null;
        if (targets.size() == 0) target = lastTarget;
        else target = targets.keysView().min(Comparator.comparingInt(thisPos::cartesianDistance));
        if (target.equals(thisPos)) {
            lastTarget = null;
            if (global.get(thisPos).getOwner().equals(getThisHidden())) {
                lastMove = lastMove.leftTurn();
                return lastMove;
            } else 
            // time to go home
            target = global.select((z_, x) -> getThisHidden().equals(x.getOwner())).keySet().iterator().next();

        }

        lastTarget = target;
        lastMove = makeSafeMove(target, global, board, thisPos);
        return lastMove;
    }

    private Direction makeSafeMove(Point2D targetLocation, MutableMap<Point2D, ReadOnlySplixPoint> map, ReadOnlyBoard board, Point2D currLoc) {
        Point2D dist = targetLocation.move(-currLoc.getX(), -currLoc.getY());
        ImmutableSet<Direction> possibleMoves = Sets.immutable.of(Direction.values())
                .select(x -> {
                    Point2D pos = currLoc.move(x.vector.getX(), x.vector.getY());
                    return !board.getBounds().outOfBounds(pos) && !getThisHidden().equals(map.get(pos).getClaimer());
                });
        Direction prefMove;
        if (Math.abs(dist.getX()) > Math.abs(dist.getY()))
            prefMove = getDirectionFroPoint(new Point2D(normalizeNum(dist.getX()), 0));
        else
            prefMove = getDirectionFroPoint(new Point2D(0, normalizeNum(dist.getY())));

        if (possibleMoves.contains(prefMove)) return prefMove;
        if (possibleMoves.contains(prefMove.leftTurn())) return prefMove.leftTurn();
        if (possibleMoves.contains(prefMove.rightTurn())) return prefMove.rightTurn();
        return prefMove.leftTurn().leftTurn();
    }

    private Direction getDirectionFroPoint(Point2D dir) {
        return Sets.immutable.of(Direction.values()).select(d -> d.vector.equals(dir)).getOnly();
    }

    private int normalizeNum(int n) { if (n < -1) return -1; if (n > 1) return 1; else return n;}

}

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

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