Package com.jcloisterzone.ai.legacyplayer

Source Code of com.jcloisterzone.ai.legacyplayer.LegacyRanking$LegacyAiScoreAllCallback

package com.jcloisterzone.ai.legacyplayer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.google.common.collect.Iterables;
import com.jcloisterzone.Player;
import com.jcloisterzone.ai.AiPlayer;
import com.jcloisterzone.ai.GameRanking;
import com.jcloisterzone.board.EdgePattern;
import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.Rotation;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.feature.Castle;
import com.jcloisterzone.feature.City;
import com.jcloisterzone.feature.Cloister;
import com.jcloisterzone.feature.Completable;
import com.jcloisterzone.feature.Farm;
import com.jcloisterzone.feature.Feature;
import com.jcloisterzone.feature.Road;
import com.jcloisterzone.feature.score.ScoreAllCallback;
import com.jcloisterzone.feature.score.ScoreAllFeatureFinder;
import com.jcloisterzone.feature.visitor.score.CityScoreContext;
import com.jcloisterzone.feature.visitor.score.CompletableScoreContext;
import com.jcloisterzone.feature.visitor.score.FarmScoreContext;
import com.jcloisterzone.feature.visitor.score.MonasteryAbbotScoreContext;
import com.jcloisterzone.feature.visitor.score.RoadScoreContext;
import com.jcloisterzone.feature.visitor.score.ScoreContext;
import com.jcloisterzone.figure.Barn;
import com.jcloisterzone.figure.BigFollower;
import com.jcloisterzone.figure.Builder;
import com.jcloisterzone.figure.Follower;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.figure.SmallFollower;
import com.jcloisterzone.figure.predicate.MeeplePredicates;
import com.jcloisterzone.game.Game;
import com.jcloisterzone.game.capability.BuilderCapability;
import com.jcloisterzone.game.capability.BuilderCapability.BuilderState;
import com.jcloisterzone.game.capability.FairyCapability;
import com.jcloisterzone.game.capability.TowerCapability;
import com.jcloisterzone.game.phase.ScorePhase;


public class LegacyRanking implements GameRanking {

    private static final double TRAPPED_MY_FIGURE_POINTS = -12.0;
    private static final double TRAPPED_ENEMY_FIGURE_POINTS = 3.0;
    private static final double SELF_MERGE_PENALTY = 6.0;

    private static final double MIN_CHANCE = 0.4;

    protected int packSize, myTurnsLeft;
    protected int enemyPlayers;

    private static final int OPEN_COUNT_ROAD = 0;
    private static final int OPEN_COUNT_CITY = 1;
    private static final int OPEN_COUNT_FARM = 2;
    private static final int OPEN_COUNT_CLOITSTER = 3;

    private int[] openCount = new int[4]; //number of my open objects

    private final AiPlayer aiPlayer;


    public LegacyRanking(AiPlayer aiPlayer) {
        this.aiPlayer = aiPlayer;
    }

    protected boolean isMe(Player p) {
        return aiPlayer.getPlayer().equals(p);
    }

    protected void initVars(Game game) {
        packSize = game.getTilePack().totalSize();
        enemyPlayers = game.getAllPlayers().length - 1;
        myTurnsLeft = ((packSize-1) / (enemyPlayers+1)) + 1;
    }

    public double getPartialAfterTilePlacement(Game game, Tile tile) {
        Position pos = tile.getPosition();
        //return 0.001 * game.getBoard().getAdjacentAndDiagonalTiles(pos).size();
        return 0.001 * game.getBoard().getAdjacentTilesMap(pos).size(); //adjacent only is better
    }

    @Override
    public double getFinal(Game game) {
        double ranking = 0;
        initVars(game);

        //trigger score
        game.getPhase().next(ScorePhase.class);
        //skip scoring when no tile is places (eg. ranking pass in AbbeyPhase)
        if (game.getCurrentTile() != null) {
            game.getPhase().enter();
        }

        Arrays.fill(openCount, 0);

        ranking += meepleRating(game);
        ranking += pointRating(game);
        ranking += openObjectRating(game);
        ranking += rankPossibleFeatureConnections(game);

        ranking += rankFairy(game);

//        // --- dbg print --
//        Tile tile = game.getCurrentTile();
//        Feature meeplePlacement = Iterables.find(tile.getFeatures(), new Predicate<Feature>() {
//            @Override
//            public boolean apply(Feature f) {
//                return !f.getMeeples().isEmpty();
//            }
//        }, null);
//        Arrays.fill(openCount, 0);
//        System.err.println(
//                String.format("%8s (%4s) %10s %4s/%5s %8.3f = Mepl %.3f Poit %.3f Open %.3f Conn %.3f Covx %.3f Fair %.3f",
//                tile.getId(), tile.getRotation(), tile.getPosition(),
//                meeplePlacement == null ? "" : meeplePlacement.getClass().getSimpleName(),
//                meeplePlacement == null ? "" : meeplePlacement.getLocation(),
//                ranking, meepleRating(), pointRating(), openObjectRating(),
//                rankPossibleFeatureConnections(), rankConvexity(), rankFairy()));
//        // --- end of debug print

        //objectRatings.clear();

        return ranking;
    }

    protected double reducePoints(double points, Player p) {
        if (isMe(p)) return points;
        return -points/enemyPlayers;
    }

    protected double chanceToPlaceTile(Game game, Position pos) {
        EdgePattern pattern = game.getBoard().getAvailMoveEdgePattern(pos);
        if (pattern != null && pattern.wildcardSize() < 2) {
            int remains = game.getTilePack().getSizeForEdgePattern(pattern);
            if (remains == 0) return 0.0;
            if (remains < game.getAllPlayers().length) {
                if (remains == 0) return 0.0;
                return 1.0 - Math.pow(1.0 - 1.0 / (game.getAllPlayers().length), remains);
            }
        }
        return 1.0;
    }

    protected double meepleRating(Game game) {
        double rating = 0;

        for (Player p : game.getAllPlayers()) {
            double meeplePoints = 0;
            int limit = 0;
            for (Follower f : Iterables.filter(p.getFollowers(), MeeplePredicates.deployed())) {
                if (f instanceof SmallFollower) {
                    meeplePoints += 0.15;
                } else if (f instanceof BigFollower) {
                    meeplePoints += 0.25;
                }
                if (++limit == myTurnsLeft) break;
            }
            rating += reducePoints(meeplePoints, p);
        }
        return rating;
    }

    class LegacyAiScoreAllCallback implements ScoreAllCallback {

        private final Game game;
        private double rank = 0;

        private Set<Position> towerDanger = new HashSet<>();

        public LegacyAiScoreAllCallback(Game game) {
            this.game = game;
            TowerCapability towerCap = game.getCapability(TowerCapability.class);
            if (towerCap != null) {
                for (Position towerPos : towerCap.getTowers()) {
                    int dangerDistance = 1 + game.getBoard().get(towerPos).getTower().getHeight();
                    towerDanger.add(towerPos);
                    for (int i = 1; i < dangerDistance; i++) {
                        towerDanger.add(towerPos.add(new Position(i, 0)));
                        towerDanger.add(towerPos.add(new Position(-i, 0)));
                        towerDanger.add(towerPos.add(new Position(0, i)));
                        towerDanger.add(towerPos.add(new Position(0, -i)));
                    }
                }
            }
        }

        private boolean isInTowerDanger(ScoreContext ctx) {
            //not exact but it is easy heuristic at now
            if (!towerDanger.isEmpty()) {
                for (Follower f : ctx.getFollowers()) {
                    if (towerDanger.contains(f.getPosition())) {
                        return true;
                    }
                }
            }
            return false;
        }

        @Override
        public void scoreCastle(Meeple meeple, Castle castle) {
            throw new UnsupportedOperationException();
        }

        @Override
        public LegacyAiScoreContext getCompletableScoreContext(Completable completable) {
            //TODO uncomment after invalidate implemeted
//      AiScoreContext ctx = getScoreCache().get(completable);
//      if (ctx != null && ctx.isValid()) {
//        return (CompletableScoreContext) ctx;
//      }
            return new LegacyAiScoreContext(game, LegacyRanking.this, completable.getScoreContext()/*, getScoreCache()*/);
        }

        @Override
        public LegacyAiFarmScoreContext getFarmScoreContext(Farm farm) {
            //TODO uncomment after invalidate implemeted
//      AiScoreContext ctx = getScoreCache().get(farm);
//      if (ctx != null && ctx.isValid()) {
//        return (FarmScoreContext) ctx;
//      }
            return new LegacyAiFarmScoreContext(game/*, getScoreCache()*/);
        }

        @Override
        public void scoreFarm(FarmScoreContext ctx, Player player) {
            if (isInTowerDanger(ctx)) return;
            double points = getFarmPoints((Farm) ctx.getMasterFeature(), player, ctx);
            rank += reducePoints(points, player);
        }

        @Override
        public void scoreBarn(FarmScoreContext ctx, Barn meeple) {
            //prefer barn placement - magic constant
            rank += reducePoints(1.2 * ctx.getBarnPoints(), meeple.getPlayer());
        }

        @Override
        public void scoreCompletableFeature(CompletableScoreContext ctx) {
            if (ctx instanceof MonasteryAbbotScoreContext) {
                int points = ctx.getPoints();
                for (Player p : ctx.getMajorOwners()) {
                    rank += reducePoints(points, p);
                }
                return;
            }
            if (isInTowerDanger(ctx)) return;
            rank += rankUnfishedCompletable(ctx.getMasterFeature(), (LegacyAiScoreContext) ctx);
            rank += rankTrappedMeeples((LegacyAiScoreContext) ctx);
            rank += rankSpecialFigures(game, (LegacyAiScoreContext) ctx);
        }

        public double getRanking() {
            return rank;
        }

    }

    protected double pointRating(Game game) {
        double rating = 0;

        for (Player p : game.getAllPlayers()) {
            rating += reducePoints(p.getPoints(), p);
        }

        ScoreAllFeatureFinder scoreAll = new ScoreAllFeatureFinder();
        LegacyAiScoreAllCallback callback = new LegacyAiScoreAllCallback(game);
        scoreAll.scoreAll(game, callback);
        rating += callback.getRanking();

        return rating;
    }


    public static final double[][]  OPEN_PENALTY = {
        { 0.0, 1.0, 2.5, 4.5, 7.5, 10.5, 14.5, 19.0, 29.0 }, //road
        { 0.0, 0.5, 1.5, 3.0, 5.0, 8.0, 12.0, 17.0, 27.0 }, //city
        { 0.0, 5.0, 10.0, 19.0, 28.0, 37.0, 47.0, 57.0, 67.0 }, //farm
        { 0.0, 0.0, 0.4, 0.8, 1.2, 2.0, 4.0, 7.0, 11.0 } //cloister
    };

    protected double openObjectRating(Game game) {
        double rating = 0;

        for (int i = 0; i < OPEN_PENALTY.length; i++ ){
            double penalty;
            //fast fix for strange bug causes ArrayIndexOutOfBoundsException: 9
            if (openCount[i] >= OPEN_PENALTY[i].length) {
                penalty = OPEN_PENALTY[i][OPEN_PENALTY[i].length - 1];
            } else {
                penalty = OPEN_PENALTY[i][openCount[i]];
            }
            if (i == 2) {
                //Farm
                double modifier = (packSize - ((1+enemyPlayers) * 3)) / 20.0;
                if (modifier < 1.0) modifier = 1.0;
                rating -= modifier * penalty;
            } else {
                rating -= penalty;
            }
        }
        return rating;
    }

    private ScoreContext futureConnectionCreateScoreContext(Game game, Feature feature) {
        LegacyAiScoreAllCallback ctxHelper = new LegacyAiScoreAllCallback(game);
        ScoreContext ctx;
        if (feature instanceof Completable) {
            ctx = ctxHelper.getCompletableScoreContext((Completable) feature);
        } else {
            ctx = ctxHelper.getFarmScoreContext((Farm) feature);
            ((LegacyAiFarmScoreContext) ctx).setCityCache(new HashMap<City, CityScoreContext>());
        }
        feature.walk(ctx);
        return ctx;
    }

    private double futureConnectionGetFeaturePoints(Feature feature, ScoreContext featureCtx) {
        if (featureCtx instanceof CompletableScoreContext) {
            return getUnfinishedCompletablePoints((Completable) feature, (LegacyAiScoreContext) featureCtx);
        } else {
            return ((FarmScoreContext) featureCtx).getPoints(aiPlayer.getPlayer());
        }
    }

    private double futureConnectionRateConnection(Game game, Location toEmpty, Location toFeature, Position f2Pos, double chance) {
        Tile tile1 = game.getCurrentTile();
        Tile tile2 = game.getBoard().get(f2Pos);

        double rating = 0;

        Completable f1 = (Completable) tile1.getFeaturePartOf(toEmpty);
        Completable f2 = (Completable) tile2.getFeaturePartOf(toFeature.rev());

        if (f1 != null && f2 != null) {
            if (f1.getClass().equals(f2.getClass())) {
                //            System.err.println("    " + tile1.getPosition() + " <-->" + f2Pos + " / " + f1 + " " + f2);
                rating +=  futureConnectionRateFeatures(game, toEmpty, toFeature, chance, f1, f2);
            } else {
                rating +=  futureConnectionRateCrossing(game, toEmpty, toFeature, chance, f1, f2);
            }
        }

        if (toEmpty != toFeature) {
            boolean left = toEmpty.rotateCCW(Rotation.R90) == toFeature;
            Farm farm1 = (Farm) tile2.getFeaturePartOf(left ? toEmpty.getLeftFarm() : toEmpty.getRightFarm());
            Farm farm2 = (Farm) tile2.getFeaturePartOf(left ? toFeature.rev().getRightFarm() : toFeature.rev().getLeftFarm());

            if (farm1 != null && farm2 != null) {
//                System.err.println("    " + tile1.getPosition() + " <-->" + f2Pos + " / " + farm1 + " " + farm2);
                rating +=  futureConnectionRateFeatures(game, toEmpty, toFeature, chance, farm1, farm2);
            }
        }
        return rating;
    }

    private double futureConnectionRateCrossing(Game game, Location toEmpty, Location toFeature, double chance, Feature f1, Feature f2) {
        ScoreContext f1Ctx = futureConnectionCreateScoreContext(game, f1);
        ScoreContext f2Ctx = futureConnectionCreateScoreContext(game, f2);
        Map<Player, Integer> f1Powers = f1Ctx.getPowers();
        Map<Player, Integer> f2Powers = f2Ctx.getPowers();

        int[] powers = funtureConnectionSumPower(f2Powers, null);
        int myPower = powers[0];
        int bestEnemy = powers[1];

        if (f1Powers.size() == 0) {
            if (bestEnemy > myPower) {
                return 0.2;
            } else if (myPower > 0) {
                return -2.5;
            }
        } else {
            if (bestEnemy > myPower) {
                return -0.1;
            } else if (myPower > 0) {
                return -0.5;
            } else {
                return -0.5;
            }
        }
        return 0;
    }


    private double futureConnectionRateFeatures(Game game, Location toEmpty, Location toFeature, double chance, Feature f1, Feature f2) {
        ScoreContext f1Ctx = futureConnectionCreateScoreContext(game, f1);
        ScoreContext f2Ctx = futureConnectionCreateScoreContext(game, f2);
        Map<Player, Integer> f1Powers = f1Ctx.getPowers();
        Map<Player, Integer> f2Powers = f2Ctx.getPowers();

        if (f1Powers.size() == 0) {
            return 0;
        }

        if (f1Powers.size() == 1 && f2Powers.size() == 1 && f1Powers.containsKey(aiPlayer.getPlayer()) && f2Powers.containsKey(aiPlayer.getPlayer())) {
//            System.err.println("   !self merge");
//            System.err.println(f1Powers + " // " + f2Powers);
            return -SELF_MERGE_PENALTY;
        }

        double myPoints = futureConnectionGetFeaturePoints(f1, f1Ctx);
        double enemyPoints = futureConnectionGetFeaturePoints(f2, f2Ctx);

        if (enemyPoints < (toEmpty == toFeature ? 7.0 : 5.0)) {
//            System.err.println("too small penalty: " + enemyPoints);
            return  -0.05; //small penalty
        }

        int[] powers = funtureConnectionSumPower(f1Powers, f2Powers);
        int myPower = powers[0];
        int bestEnemy = powers[1];

        double coef = toEmpty != toFeature ? 0.7 : 0.4; //corner / straight connection

//        System.err.println("@@@ @@@ " + myPower + "/" + myPoints + " vs " + bestEnemy + "/" + enemyPoints);

        if (myPower == bestEnemy) {
            return coef * (enemyPoints - myPoints) * chance;
        }
        if (myPower > bestEnemy) {
            return coef * enemyPoints * chance;

        }
        return -myPoints * chance; //no coef here

    }

    private int[] funtureConnectionSumPower(Map<Player, Integer> f1Powers, Map<Player, Integer> f2Powers) {
        Map<Player, Integer> sum = new HashMap<Player, Integer>(f1Powers);
        if (f2Powers != null) {
            for (Entry<Player, Integer> epower : f2Powers.entrySet()) {
                Integer val = sum.get(epower.getKey());
                sum.put(epower.getKey(), val == null ? epower.getValue() : val + epower.getValue());
            }
        }
        int myPower = 0;
        int bestEnemy = 0;
        for (Entry<Player, Integer> esum : sum.entrySet()) {
            int value = esum.getValue();
            if (esum.getKey().equals(aiPlayer.getPlayer())) {
                myPower = value;
            } else {
                if (value > bestEnemy) bestEnemy = value;
            }
        }
        return new int[] { myPower, bestEnemy };
    }

    private double rankPossibleFeatureConnections(Game game) {
        double rank = 0;

        Tile tile = game.getCurrentTile();
        Position placement = tile.getPosition();
        assert placement != null;

        for (Entry<Location, Position> eplace : Position.ADJACENT.entrySet()) {
            Position pos = placement.add(eplace.getValue());
            if (game.getBoard().get(pos) != null) continue;

            double chance = chanceToPlaceTile(game, pos);
            if (chance < MIN_CHANCE) continue;

            for (Entry<Location, Position> econn : Position.ADJACENT.entrySet()) {
                Position conn = pos.add(econn.getValue());
                if (conn.equals(placement)) continue;
                Tile connTile = game.getBoard().get(conn);
                if (connTile == null) continue;

                rank += futureConnectionRateConnection(game, eplace.getKey(), econn.getKey(), conn, chance);
            }
        }
        return rank;
    }

    protected double rankFairy(Game game) {
        if (!game.hasCapability(FairyCapability.class)) return 0;
        FairyCapability fc = game.getCapability(FairyCapability.class);
        Position fairyPos = fc.getFairyPosition();
        if (fairyPos == null) return 0;

        double rating = 0;

//    TODO more sophisticated rating
        for (Meeple meeple : game.getDeployedMeeples()) {
            if (!meeple.at(fairyPos)) continue;
            if (!(meeple instanceof Follower)) continue;
            if (meeple.getFeature() instanceof Castle) continue;

            rating += reducePoints(1.0, meeple.getPlayer());
        }

        return rating;

//     //OLD legacy impl
//    Set<PlacedFigure> onTile = gc.getPlacedFiguresForTile(board.get(fairyPos.x,fairyPos.y));
//    Set<Player> onePointPlayers = new HashSet<>();
//    for (PlacedFigure pfi : onTile) {
//      if (pfi != null && gi.get().equals(pfi.player)) {
//        onePointPlayers.add(pfi.player);
//      }
//      if (pfi.et == FeatureType.TOWER) continue;
//      LastPlaceInfo last = gc.getBoard().getLastPlacementInfo();
//      if (gc.getBoard().get(last.pos).getTrigger() == TileTrigger.DRAGON) {
//        int dist = last.pos.squareDistance(pfi.position);
//        if (dist == 1) {
//          //figurka hned vedle, heuristika
//          /*Tile lastTile = gc.getBoard().get(pfi.position);
//          if (pfi.et == ElementType.CLOISTER) {
//            //lastTile.getCloister().get ...
//          }*/
//          rating += reducePoints(4, pfi.player); //zatim proste odhadnem cenu figurky na 4 body
//        }
//      }
//    }
//    //kvuli brane a vice figurkam na jednom poli, aby kazdy hrac max +1 za kolo
//
//    for (Player player : onePointPlayers) {
//      rating += reducePoints(0.8, player);
//    }
    }

    protected double rankUnfishedCompletable(Completable completable, LegacyAiScoreContext ctx) {
        double rating = 0.0;
        double points = getUnfinishedCompletablePoints(completable, ctx);
        for (Player p : ctx.getMajorOwners()) {
            rating += reducePoints(points, p);
        }
        return rating;
    }

    protected double getUnfinishedCompletablePoints(Completable complatable, LegacyAiScoreContext ctx) {
        if (complatable instanceof City) {
            return getUnfinishedCityPoints((City) complatable, ctx);
        }
        if (complatable instanceof Road) {
            return getUnfinishedRoadPoints((Road) complatable, ctx);
        }
        if (complatable instanceof Cloister) {
            return getUnfinishedCloisterPoints((Cloister) complatable, ctx);
        }
        throw new IllegalArgumentException();
    }

    protected double getUnfinishedCityPoints(City city, LegacyAiScoreContext ctx) {
        double chanceToClose = ctx.getChanceToClose();

        if (chanceToClose > MIN_CHANCE && ctx.getMajorOwners().contains(aiPlayer.getPlayer())) {
            openCount[OPEN_COUNT_CITY]++;
        }

        //legacy heuristic
        CityScoreContext cityCtx = (CityScoreContext) ctx.getCompletableScoreContext();
        if (chanceToClose < MIN_CHANCE) {
            return cityCtx.getPoints(false) + 3.0*chanceToClose;
        } else {
            return cityCtx.getPoints(true) - 3.0*(1.0-chanceToClose);
        }
    }

    protected double getUnfinishedRoadPoints(Road road, LegacyAiScoreContext ctx) {
        double chanceToClose = ctx.getChanceToClose();;

        if (chanceToClose > MIN_CHANCE && ctx.getMajorOwners().contains(aiPlayer.getPlayer())) {
            openCount[OPEN_COUNT_ROAD]++;
        }

        //legacy heuristic
        RoadScoreContext roadCtx = (RoadScoreContext) ctx.getCompletableScoreContext();
        if (chanceToClose < MIN_CHANCE) {
            return roadCtx.getPoints(false) + 3.0*chanceToClose;
        } else {
            return roadCtx.getPoints(true) - 3.0*(1.0-chanceToClose);
        }

    }

    protected double getUnfinishedCloisterPoints(Cloister cloister, LegacyAiScoreContext ctx) {
        List<Meeple> followers = cloister.getMeeples();
        if (!followers.isEmpty() && isMe(followers.get(0).getPlayer())) {
            openCount[OPEN_COUNT_CLOITSTER]++;
        }
        double chanceToClose = ctx.getChanceToClose();
        int points = ctx.getPoints();
        return points + (9-points)*chanceToClose;
    }

    protected double getFarmPoints(Farm farm, Player p, FarmScoreContext ctx) {
        if (isMe(p)) {
            openCount[OPEN_COUNT_FARM]++;
        }
        return ctx.getPoints(p);
    }

    protected double rankSpecialFigures(Game game, LegacyAiScoreContext ctx) {
        double rating = 0.0;
        for (Meeple m : ctx.getSpecialMeeples()) {
            if (m instanceof Builder && isMe(m.getPlayer())) {
                rating += rankBuilder(game, (Builder) m, ctx);
            }
        }
        return rating;
    }

    protected double rankBuilder(Game game, Builder builder, LegacyAiScoreContext ctx) {
        if (!ctx.getMajorOwners().contains(aiPlayer.getPlayer())) {
            return -3.0; //builder in enemy object penalty
        }
        if (ctx.getChanceToClose() < 0.55) return 0.0;
        double rating = 0.0;
        //builder placed in object
        if (builder.getFeature() instanceof City) {
            rating += 1.5;
        } else {
            rating += 0.5;
        }

        BuilderCapability bc = game.getCapability(BuilderCapability.class);
        //builder used on object
        if (bc.getBuilderState() == BuilderState.ACTIVATED) {
            rating += 3.5;
        }
        return rating;
    }

    private double rankTrappedMeeples(LegacyAiScoreContext ctx) {
        //musi tu byt dolni mez - btw nestaci toto misto hodnoceni figurek, spis asi :)

        //TODO lepe
        if (myTurnsLeft < 8) return 0.0;

        if (ctx.getChanceToClose() > 0.4) return 0.0;

        double rating = 0.0;
        for (Meeple m : ctx.getMeeples()) {
            if (isMe(m.getPlayer())) {
                rating += TRAPPED_MY_FIGURE_POINTS;
            } else {
                rating += TRAPPED_ENEMY_FIGURE_POINTS;
            }
        }
        return (1.0 - ctx.getChanceToClose()) * rating; //no reduce
    }
}
TOP

Related Classes of com.jcloisterzone.ai.legacyplayer.LegacyRanking$LegacyAiScoreAllCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.