Advertisement
Guest User

hello

a guest
Apr 26th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.72 KB | None | 0 0
  1. import java.util.HashMap;
  2. import java.util.Iterator;
  3. import java.util.Map;
  4. import java.util.Map.Entry;
  5.  
  6. public class IdkMate implements BotAPI {
  7.    
  8.     /*
  9.      * indicates progression of the game
  10.      */
  11.     private enum Stage {
  12.         contact,
  13.         opposedbearoff,
  14.         unopposedbearoff,
  15.         unopposedprebearoff;
  16.     }
  17.  
  18.     // The public API of Bot must not change
  19.     // This is ONLY class that you can edit in the program
  20.     // Rename Bot to the name of your team. Use camel case.
  21.     // Bot may not alter the state of the game objects
  22.     // It may only inspect the state of the board and the player objects
  23.  
  24.     private PlayerAPI me, opponent;
  25.     private BoardAPI board;
  26.     private CubeAPI cube;
  27.     private MatchAPI match;
  28.     private InfoPanelAPI info;
  29.  
  30.     IdkMate(PlayerAPI me, PlayerAPI opponent, BoardAPI board, CubeAPI cube, MatchAPI match, InfoPanelAPI info) {
  31.         this.me = me;
  32.         this.opponent = opponent;
  33.         this.board = board;
  34.         this.cube = cube;
  35.         this.match = match;
  36.         this.info = info;
  37.     }
  38.  
  39.     public String getName() {
  40.         return "IdkMate"; // must match the class name
  41.     }
  42.    
  43.     private class Duo {
  44.         int id;
  45.         Play play;
  46.        
  47.         Duo (int id, Play play) {
  48.             this.id = id;
  49.             this.play = play;
  50.         }
  51.     }
  52.  
  53.     public String getCommand(Plays possiblePlays) {
  54.        
  55.         String command = "1";
  56.         int counter = 0;
  57.  
  58.         Map <Duo, Double> thisMap = new HashMap<>();
  59.         for (Play play : possiblePlays) {
  60.             thisMap.put(new Duo(++counter,play), getWeight(play));
  61.         }
  62.        
  63.         //returns the Duo associated with the maximum values of the map
  64.         Duo res = thisMap.entrySet().stream().max((e1, e2) -> e1.getValue() > e2.getValue() ? 1 : -1).get().getKey();
  65.         command = Integer.toString(res.id);
  66.         System.out.println(thisMap.get(res));
  67.        
  68.         String dDecision = getDoubleDecision();
  69.        
  70.         if (dDecision == "double") {
  71.             if (match.canDouble((Player) me))
  72.                 command = "double";
  73.         }
  74.        
  75.         return command;
  76.    
  77.        
  78.     }
  79.    
  80.     private double getWeight(Play play) {
  81.         double weight = 0.0;
  82.        
  83.         //Hit Multiplier
  84.         double hitMult = 0.0;
  85.         if (doesHit(play) == 1)
  86.             hitMult = 0.05;
  87.         else if (doesHit(play) == 2)
  88.             hitMult = 0.1;
  89.         else if (doesHit(play) > 2)
  90.             hitMult = 0.15;
  91.            
  92.        
  93.         double blockMult = 0.0;
  94.         if (makesBlock(play))
  95.             blockMult = 0.1;
  96.        
  97.         double anchorMult = 0.0;
  98.         if (removesAnchor(play))
  99.             anchorMult = -0.1;
  100.        
  101.         double escapeMult = 0.0;
  102.         if (escapeTrappedChecker(play))
  103.             escapeMult = 0.1;
  104.        
  105.         double largeStackMult = 0.0;
  106.         if (flagLargeMoves(play))
  107.             largeStackMult = -0.1;
  108.        
  109.         double movesHBMult = 0.0;
  110.         if (movesHBCheckers(play))
  111.             movesHBMult = -0.1;
  112.        
  113.         double blotMult = 0.0;
  114.         if (makesBlot(play))
  115.             blotMult = -0.125;
  116.        
  117.         double primeMult = 0.0;
  118.         if(makesPrime(play))
  119.             primeMult = 0.2;
  120.        
  121.         //less important features are exponentiated
  122.        
  123.         if (getCurrentGameStatus(me).equals(Stage.unopposedbearoff)) {
  124.             weight = (numOfBearOffMoves(play)/10);  
  125.         } else if (getCurrentGameStatus(me).equals(Stage.opposedbearoff)) {
  126.             weight = (numOfBearOffMoves(play)/10)
  127.                     + hitMult
  128.                     + movesHBMult
  129.                     + Math.pow(blotMult,2)
  130.                     + Math.pow(largeStackMult,2);
  131.         } else {       
  132.             weight = (getDistanceTravelled(play) / 24)
  133.                     + hitMult
  134.                     + (blotMult*1.5)
  135.                     + Math.pow(anchorMult,2)
  136.                     + blockMult
  137.                     + escapeMult
  138.                     + largeStackMult
  139.                     + Math.pow(movesHBMult,3)
  140.                     + primeMult
  141.                     ;      
  142.         }
  143.        
  144.         return weight;
  145.     }
  146.    
  147.     /*
  148.      * Bot movement features
  149.      */
  150.    
  151.     //Returns true if there are already checkers on either side of a planned move.
  152.     private boolean makesPrime(Play play) {
  153.         Map<Integer, Integer> map = new HashMap<>();
  154.         for (Move move : play.moves) {
  155.             if (!map.containsKey(move.getToPip()))
  156.                 map.put(move.getToPip(), 1);
  157.             else
  158.                 map.replace(move.getToPip(), map.get(move.getToPip()) + 1);              
  159.         }
  160.        
  161.         Iterator<Entry<Integer, Integer>> it = map.entrySet().iterator();
  162.         while (it.hasNext()) {
  163.             Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
  164.             if (pair.getValue() == 2) {
  165.                 if (pair.getKey() - 1 > 0 && pair.getKey() + 1 < 25) {
  166.                     if (board.getNumCheckers(me.getId(), pair.getKey() - 1) > 1
  167.                             && board.getNumCheckers(me.getId(), pair.getKey() + 1) > 1)
  168.                         return true;
  169.                 }
  170.             }
  171.         }
  172.         return false;
  173.     }
  174.    
  175.     //returns the number of hits a given move will perform
  176.     private int doesHit(Play play) {
  177.         int numOfHits = 0;
  178.         for (Move move : play.moves) {
  179.             if (move.isHit())
  180.                 numOfHits++;
  181.         }
  182.        
  183.         return numOfHits;
  184.     }
  185.    
  186.     //returns true if a give move will place 2 checkers on an empty pip
  187.     private boolean makesBlock (Play play) {
  188.         Map<Integer, Integer> map = new HashMap<>();
  189.         for (Move move : play.moves) {
  190.             if (!map.containsKey(move.getToPip()))
  191.                 map.put(move.getToPip(), 1);
  192.             else
  193.                 map.replace(move.getToPip(), map.get(move.getToPip()) + 1);
  194.         }
  195.        
  196.         if (map.containsValue(2))
  197.             return true;
  198.         else
  199.             return false;          
  200.     }
  201.    
  202.     //returns true if a given move will remove an "anchor" (2 checkers in opponents home)
  203.     private boolean removesAnchor(Play play) {
  204.         Map<Integer, Integer> map = new HashMap<>();
  205.         for (Move move : play.moves) {
  206.             if (move.getFromPip() <= 24 && move.getFromPip() >= 19) {
  207.                 if (!map.containsKey(move.getFromPip()))
  208.                     map.put(move.getFromPip(), 1);
  209.                 else
  210.                     map.replace(move.getFromPip(), map.get(move.getFromPip()) + 1);
  211.             }
  212.         }
  213.        
  214.         if (map.containsValue(2))
  215.             return true;
  216.         else
  217.             return false;
  218.     }
  219.    
  220.     //returns the total pip difference for all moves of a given play
  221.     private double getDistanceTravelled(Play play) {
  222.         int distance = 0;
  223.         for (Move move : play.moves) {
  224.             distance += move.getPipDifference();
  225.         }
  226.        
  227.         return distance;
  228.     }
  229.    
  230.     //returns true if a give play will remove a "trapped" checker from the opponents Home board
  231.     private boolean escapeTrappedChecker(Play play) {
  232.         if (!board.lastCheckerInOpponentsInnerBoard((Player) opponent) &&
  233.                 board.lastCheckerInOpponentsInnerBoard((Player) me)) {
  234.             for (Move move : play.moves) {
  235.                 if (move.getFromPip() <= 24 && move.getFromPip() >= 19) {
  236.                     if (move.getToPip() < 19)
  237.                         return true;
  238.                 }                  
  239.             }
  240.         }
  241.        
  242.         return false;
  243.     }
  244.    
  245.     //returns true if a move will stack a large number of checkers onto 1 pip
  246.     private boolean flagLargeMoves (Play play) {
  247.         Map<Integer, Integer> map = new HashMap<>();
  248.         for (Move move : play.moves) {
  249.             if (!map.containsKey(move.getToPip()))
  250.                 map.put(move.getToPip(), 1);
  251.             else
  252.                 map.replace(move.getToPip(), map.get(move.getToPip()) + 1);
  253.         }
  254.        
  255.         if (map.containsValue(5))
  256.             return true;
  257.         else if (map.containsValue(6))
  258.             return true;
  259.         else if (map.containsValue(7))
  260.             return true;
  261.         else if (map.containsValue(8))
  262.             return true;
  263.         else if (map.containsValue(9))
  264.             return true;
  265.        
  266.         return false;
  267.     }
  268.    
  269.     //returns true if a given move only moves checkers forward in the players homeboard without a hit
  270.     private boolean movesHBCheckers (Play play) {
  271.         for (Move move : play.moves) {
  272.             if (move.getFromPip() <= 6) {
  273.                 if (move.getToPip() <= 5)
  274.                     if (!move.isHit())
  275.                         return true;
  276.             }
  277.         }
  278.        
  279.         return false;
  280.     }    
  281.    
  282.     //Returns the number of checkers moved to position 0 (bear off) for a given play
  283.     private double numOfBearOffMoves (Play play) {
  284.         int offCounter = 0;
  285.         for (Move move : play.moves) {
  286.             if (move.getToPip() == 0)
  287.                 offCounter++;
  288.         }
  289.        
  290.         return offCounter;
  291.     }
  292.    
  293.     //returns true if a given play creates a blot.
  294.     private boolean makesBlot(Play play) {
  295.         Map<Integer,Integer> map = new HashMap<>();
  296.         for (Move move : play.moves) {
  297.             if (!map.containsKey(move.getToPip()))
  298.                 map.put(move.getToPip(), 1);
  299.             else
  300.                 map.replace(move.getToPip(), map.get(move.getToPip()) + 1);
  301.         }
  302.        
  303.         if (map.containsValue(1))
  304.             return true;
  305.         else
  306.             return false;
  307.     }
  308.    
  309.     /*
  310.      * Bot doubling features
  311.      */
  312.  
  313.     public String getDoubleDecision() {
  314.        
  315.         String decision = "n";
  316.        
  317.        
  318.         /**
  319.          * Cube not owned
  320.          */
  321.         if (!cube.isOwned()) {
  322.             /* 1 point off, no double  */
  323.             if (me.getScore() + 1 == match.getLength())
  324.                 decision = "n";
  325.             /* 2 points off: */
  326.             else if (ifTwoOffWinning()) {
  327.                 if (getWinningProbability(me) < 0.50)
  328.                     decision = "n";            
  329.                 else if (getWinningProbability(me) < 0.75 && getWinningProbability(me) >= 0.47)
  330.                     decision = "double";
  331.                 else if (getWinningProbability(me) >= 0.75)
  332.                     decision = "double";
  333.             }
  334.            
  335.             /* Repeated below code in the next 2 big logic statements but it will be changed. */
  336.            
  337.             /* winning prob is good and gammon chance is good, no double */
  338.             else if (getWinningProbability(me) > 0.75 && getGammonChance(me) > 0.8)
  339.                 decision = "n";
  340.             /* winning prob is good and no gammon, double. */
  341.             else if (getWinningProbability(me) > 0.75 && getGammonChance(me) < 0.2)
  342.                 decision = "double";
  343.             /* winning prob is good and gammon chance is good, no double */
  344.             else if (getWinningProbability(me) > 0.66 && getGammonChance(me) >= 0.75)
  345.                 decision = "n";
  346.             /* winning prob is good and no gammon, double. */
  347.             else if (getWinningProbability(me) > 0.75 && getGammonChance(me) <= 0.66)
  348.                 decision = "double";
  349.             else if (getWinningProbability(me) > 0.85)
  350.                 decision = "double";
  351.         }
  352.        
  353.         /**
  354.          * Cube is owned
  355.          */
  356.         else {
  357.             /**
  358.              * Responding to a proposal
  359.              */
  360.             if (cube.getOwnerId() != me.getId()) {
  361.                 /* automatic lose, accept double. */
  362.                 if (opponent.getScore() + 1 == match.getLength())
  363.                     decision = "y";
  364.                 /* 2 points off: */
  365.                 else if (ifTwoOffWinning()) {
  366.                     if (getWinningProbability(opponent) < 0.50)
  367.                         decision = "y";
  368.                     else if (getWinningProbability(me) < 0.75 && getWinningProbability(me) >= 0.50)
  369.                         decision = "y";
  370.                     else if (getWinningProbability(opponent) >= 0.75)
  371.                         decision = "n";
  372.                 }
  373.                
  374.                 /* winning prob is good and gammon chance is good, no double */
  375.                 else if (getWinningProbability(opponent) > 0.75 && getGammonChance(opponent) > 0.8)
  376.                     decision = "n";
  377.                 /* winning prob is good and no gammon, double. */
  378.                 else if (getWinningProbability(opponent) > 0.75 && getGammonChance(opponent) < 0.2)
  379.                     decision = "n";
  380.                 /* winning prob is good and gammon chance is good, no double */
  381.                 else if (getWinningProbability(opponent) > 0.66 && getGammonChance(opponent) >= 0.75)
  382.                     decision = "y";
  383.                 /* winning prob is good and no gammon, double. */
  384.                 else if (getWinningProbability(opponent) > 0 && getGammonChance(opponent) <= 0.66)
  385.                     decision = "y";
  386.             }
  387.             /**
  388.              * Proposing a double
  389.              */
  390.             else {
  391.                 /* 1 point off, post crawford: double */
  392.                 if (me.getScore() + 1 == match.getLength())
  393.                     decision = "double";
  394.                 /* 2 points off: */
  395.                 else if (ifTwoOffWinning()) {
  396.                     if (getWinningProbability(me) < 0.50)
  397.                         decision = "n";
  398.                     else if (getWinningProbability(me) < 0.75 && getWinningProbability(me) >= 0.50)
  399.                         decision = "double";
  400.                     else if (getWinningProbability(me) >= 0.75)
  401.                         decision = "double";
  402.                 }
  403.                
  404.                 /* winning prob is good and gammon chance is good, no double */
  405.                 else if (getWinningProbability(me) > 0.75 && getGammonChance(me) > 0.8)
  406.                     decision = "n";
  407.                 /* winning prob is good and no gammon, double. */
  408.                 else if (getWinningProbability(me) > 0.75 && getGammonChance(me) < 0.2)
  409.                     decision = "double";
  410.                 /* winning prob is good and gammon chance is good, no double */
  411.                 else if (getWinningProbability(me) > 0.66 && getGammonChance(me) >= 0.75)
  412.                     decision = "double";
  413.                 /* winning prob is good and no gammon, double. */
  414.                 else if (getWinningProbability(me) > 0 && getGammonChance(me) <= 0.66)
  415.                     decision = "n";
  416.             }
  417.         }
  418.         return decision;
  419.     }
  420.    
  421.    
  422.    
  423.     //Based on the status of p's last checker compared to the opponents last checker,
  424.     //returns the stage of the game from Stage enum.
  425.     private Stage getCurrentGameStatus(PlayerAPI p) {
  426.         Stage returnThis = Stage.contact;
  427.         Player thisPlayer = (Player) p;
  428.         Player otherPlayer = (Player) ((thisPlayer.getId() == 0) ? opponent : me );
  429.        
  430.         if (board.lastCheckerInInnerBoard(thisPlayer) && board.lastCheckerInInnerBoard(otherPlayer))
  431.             returnThis = Stage.unopposedbearoff;
  432.         else if (board.lastCheckerInInnerBoard(thisPlayer) && board.lastCheckerInOpponentsInnerBoard(otherPlayer))
  433.             returnThis = Stage.opposedbearoff;
  434.         else if (board.lastCheckerInInnerBoard(otherPlayer) && !(board.lastCheckerInInnerBoard(thisPlayer)))
  435.             returnThis = Stage.unopposedprebearoff;
  436.        
  437.         return returnThis;      
  438.     }
  439.    
  440.     /* Based on certain aspects of the board, this method calculates the circumstancial
  441.      * probability of winning for a given player
  442.      */
  443.     private double getWinningProbability(PlayerAPI thisPlayer) {
  444.         double probability = 0.0;
  445.        
  446.         PlayerAPI otherPlayer = ((thisPlayer.getId() == 0)? opponent : me);
  447.        
  448.         double pcDiff = getPipCount(thisPlayer) - getPipCount(otherPlayer);
  449.         double hbCheckersDiff = getNumHBCheckers(otherPlayer) - getNumHBCheckers(thisPlayer);
  450.         double numBarredOpp = this.getNumOppBarredCheckers(thisPlayer);
  451.         double numBarredMe = board.getNumCheckers(thisPlayer.getId(), 25);
  452.         double numBearedOffDiff = this.getBearedOffDiff(thisPlayer);    
  453.        
  454.         int handicap = getHandicap(thisPlayer);
  455.         double handicapMod = 0;
  456.         if (handicap == 1)
  457.             handicapMod = -0.2;
  458.         else if (handicap == 2)
  459.             handicapMod = -0.1;    
  460.        
  461.         probability = Math.abs((1 - ( getPipCount(thisPlayer) / 167 )  )
  462.                 - ((pcDiff + 0.001) / (167 * 1.5)))
  463.                 + ((Math.pow(hbCheckersDiff,2) + 0.001) / 100)
  464.                 + handicapMod
  465.                 + (((Math.pow(numBearedOffDiff,2)) + 0.001) / 100)
  466.                 - (((Math.pow(numBarredMe, 2)) + 0.001) / 100)
  467.                 + (((Math.pow(numBarredOpp, 1.5)) + 0.001 ) / 100)
  468.                 ;
  469.        
  470.         if (probability >= 1)
  471.             probability = 0.98;
  472.        
  473.         return probability;
  474.     }
  475.    
  476.     /*
  477.      * Simple method which estimates the probability of a given player to
  478.      * win by a gammon.
  479.      */
  480.     private double getGammonChance(PlayerAPI thisPlayer) {
  481.         double chance = 0;
  482.        
  483.         PlayerAPI otherPlayer = (thisPlayer.getId() == 0) ? opponent : me;
  484.         final double PER_CHECKER = 0.02;
  485.         chance = board.getNumCheckers(thisPlayer.getId(), 0) * PER_CHECKER;    
  486.        
  487.         if (getNumHBCheckers(thisPlayer) == 15) {
  488.             if (board.getNumCheckers(otherPlayer.getId(), 25) == 1)
  489.                 chance += 0.05;
  490.             else if (board.getNumCheckers(otherPlayer.getId(), 25) == 2)
  491.                 chance += 0.40;
  492.             else if (board.getNumCheckers(otherPlayer.getId(), 25) == 3)
  493.                 chance += 0.75;
  494.         }
  495.        
  496.         return chance;
  497.     }
  498.      
  499.    
  500.     //num of checkers on pip * pip number
  501.     private double getPipCount(PlayerAPI p) {
  502.         double thisPlayerCount = 0;
  503.        
  504.         for (int i = 1; i < 25; i++)
  505.             thisPlayerCount += board.getNumCheckers(p.getId(), i) * i;
  506.        
  507.         return thisPlayerCount;
  508.     }    
  509.    
  510.    
  511.     //number of homeboard checkers + position 7 (imporant)
  512.     private double getNumHBCheckers(PlayerAPI thisPlayer) {
  513.         int number = 0;
  514.         for (int i = 1; i <= 7; i++)
  515.             number += board.getNumCheckers(thisPlayer.getId(), i);
  516.         return number;
  517.     }
  518.    
  519.     //weighed sum of the homeboard checkers + pos 7. The higher the number, the more checkers there
  520.     //are on important positions
  521.     private double getWeighedNumHBCheckers (PlayerAPI thisPlayer) {
  522.         double number = 0;
  523.         double multiplier = 1.0;
  524.         for (int i = 1; i <= 6; i++) {
  525.             if (i == 2) multiplier = 1.2;
  526.             else if (i == 3) multiplier = 1.3;
  527.             else if (i == 4) multiplier = 1.4;
  528.             else if (i == 5) multiplier = 1.6;
  529.             else if (i == 6) multiplier = 1.7;
  530.             else if (i == 7) multiplier = 1.5;
  531.                
  532.             number += board.getNumCheckers(thisPlayer.getId(), i) * multiplier;
  533.         }
  534.        
  535.         return number;
  536.     }
  537.    
  538.     /*
  539.      * Returns the number of checker the opposite player has on the bar
  540.      */
  541.     private double getNumOppBarredCheckers(PlayerAPI thisPlayer) {
  542.         PlayerAPI otherPlayer = (thisPlayer.getId() == 0) ? opponent : me;
  543.         return board.getNumCheckers(otherPlayer.getId(), 25);
  544.     }
  545.    
  546.     /*
  547.      * Returns the difference between the number of beared of checkers between
  548.      * the 2 players
  549.      */
  550.     private double getBearedOffDiff (PlayerAPI thisPlayer) {
  551.         PlayerAPI otherPlayer = (thisPlayer.getId() == 0) ? opponent : me;
  552.         return (board.getNumCheckers(otherPlayer.getId(), 0)) - (board.getNumCheckers(thisPlayer.getId(), 0));
  553.  
  554.     }
  555.    
  556.     /*
  557.      * Returns true if both of the current players are 2 points away from winning the match
  558.      */
  559.     private boolean ifTwoOffWinning() {
  560.         return ((me.getScore() + 2) == match.getLength() && (opponent.getScore() + 2) == match.getLength());
  561.     }
  562.    
  563.    
  564.     /*
  565.      * utility function which makes winning probability less biased
  566.      * towards the end stages of the game
  567.      */
  568.     private int getHandicap(PlayerAPI thisPlayer) {
  569.         PlayerAPI otherPlayer = (thisPlayer.getId() == 0) ? opponent : me;
  570.         int handicap = 0;
  571.        
  572.         if (board.lastCheckerInInnerBoard((Player) otherPlayer) &&
  573.                 !board.lastCheckerInInnerBoard((Player) thisPlayer))
  574.             handicap = 2;
  575.        
  576.         if (board.lastCheckerInInnerBoard((Player) otherPlayer) &&
  577.                 board.lastCheckerInOpponentsInnerBoard((Player) thisPlayer))
  578.             handicap = 1;
  579.        
  580.         return handicap;
  581.     }
  582. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement