Package com.jcloisterzone.game.phase

Source Code of com.jcloisterzone.game.phase.ScorePhase

package com.jcloisterzone.game.phase;

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.jcloisterzone.Player;
import com.jcloisterzone.PointCategory;
import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.event.FeatureCompletedEvent;
import com.jcloisterzone.event.ScoreEvent;
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.visitor.score.CityScoreContext;
import com.jcloisterzone.feature.visitor.score.CompletableScoreContext;
import com.jcloisterzone.feature.visitor.score.FarmScoreContext;
import com.jcloisterzone.figure.Barn;
import com.jcloisterzone.figure.Builder;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.figure.Wagon;
import com.jcloisterzone.game.Game;
import com.jcloisterzone.game.capability.BarnCapability;
import com.jcloisterzone.game.capability.BuilderCapability;
import com.jcloisterzone.game.capability.CastleCapability;
import com.jcloisterzone.game.capability.TunnelCapability;
import com.jcloisterzone.game.capability.WagonCapability;

public class ScorePhase extends Phase {

    private Set<Completable> alredyScored = new HashSet<>();

    private final BarnCapability barnCap;
    private final BuilderCapability builderCap;
    private final CastleCapability castleCap;
    private final TunnelCapability tunnelCap;
    private final WagonCapability wagonCap;

    public ScorePhase(Game game) {
        super(game);
        barnCap = game.getCapability(BarnCapability.class);
        builderCap = game.getCapability(BuilderCapability.class);
        tunnelCap = game.getCapability(TunnelCapability.class);
        castleCap = game.getCapability(CastleCapability.class);
        wagonCap = game.getCapability(WagonCapability.class);
    }

    private void scoreCompletedOnTile(Tile tile) {
        for (Feature feature : tile.getFeatures()) {
            if (feature instanceof Completable) {
                scoreCompleted((Completable) feature, true);
            }
        }
    }

    private void scoreCompletedNearAbbey(Position pos) {
        for (Entry<Location, Tile> e : getBoard().getAdjacentTilesMap(pos).entrySet()) {
            Tile tile = e.getValue();
            Feature feature = tile.getFeaturePartOf(e.getKey().rev());
            if (feature instanceof Completable) {
                scoreCompleted((Completable) feature, false);
            }
        }
    }

    private void scoreFollowersOnBarnFarm(Farm farm, Map<City, CityScoreContext> cityCache) {
        FarmScoreContext ctx = farm.getScoreContext();
        ctx.setCityCache(cityCache);
        farm.walk(ctx);

        boolean hasBarn = false;
        for (Meeple m : ctx.getSpecialMeeples()) {
            if (m instanceof Barn) {
                hasBarn = true;
                break;
            }
        }
        if (hasBarn) {
            for (Player p : ctx.getMajorOwners()) {
                int points = ctx.getPointsWhenBarnIsConnected(p);
                game.scoreFeature(points, ctx, p);
            }
            for (Meeple m : ctx.getMeeples()) {
                if (!(m instanceof Barn)) {
                    undeloyMeeple(m);
                }
            }
        }
    }

    @Override
    public void enter() {
        Position pos = getTile().getPosition();

        //TODO separate event here ??? and move this code to abbey and mayor game
        if (barnCap != null) {
            Map<City, CityScoreContext> cityCache = new HashMap<>();
            for (Feature feature : getTile().getFeatures()) {
                if (feature instanceof Farm) {
                    scoreFollowersOnBarnFarm((Farm) feature, cityCache);
                }
            }
        }

        scoreCompletedOnTile(getTile());
        if (getTile().isAbbeyTile()) {
            scoreCompletedNearAbbey(pos);
        }

        if (tunnelCap != null) {
            Road r = tunnelCap.getPlacedTunnel();
            if (r != null) {
                scoreCompleted(r, true);
            }
        }

        for (Tile neighbour : getBoard().getAdjacentAndDiagonalTiles(pos)) {
            Cloister cloister = neighbour.getCloister();
            if (cloister != null) {
                scoreCompleted(cloister, false);
            }
        }

        if (castleCap != null) {
            for (Entry<Castle, Integer> entry : castleCap.getCastleScore().entrySet()) {
                scoreCastle(entry.getKey(), entry.getValue());
            }
        }

        alredyScored.clear();
        next();
    }

    protected void undeployMeeples(CompletableScoreContext ctx) {
        for (Meeple m : ctx.getMeeples()) {
            undeloyMeeple(m);
        }
    }

    protected void undeloyMeeple(Meeple m) {
        Feature feature = m.getFeature();
        m.undeploy(false);
        if (m instanceof Wagon && wagonCap != null) {
            wagonCap.wagonScored((Wagon) m, feature);
        }
    }

    private void scoreCastle(Castle castle, int points) {
        List<Meeple> meeples = castle.getMeeples();
        if (meeples.isEmpty()) meeples = castle.getSecondFeature().getMeeples();
        Meeple m = meeples.get(0); //all meeples must share same owner
        m.getPlayer().addPoints(points, PointCategory.CASTLE);
        game.post(new ScoreEvent(m.getFeature(), points, PointCategory.CASTLE, m));
        undeloyMeeple(m);
    }

    private void scoreCompleted(Completable completable, boolean triggerBuilder) {
        CompletableScoreContext ctx = completable.getScoreContext();
        completable.walk(ctx);
        if (triggerBuilder && builderCap != null) {
            for (Meeple m : ctx.getSpecialMeeples()) {
                if (m instanceof Builder && m.getPlayer().equals(getActivePlayer())) {
                    if (!m.at(getTile().getPosition())) {
                        builderCap.useBuilder();
                    }
                    break;
                }
            }
        }
        if (ctx.isCompleted()) {
            Completable master = (Completable) ctx.getMasterFeature();
            if (!alredyScored.contains(master)) {
                alredyScored.add(master);
                game.scoreCompleted(ctx);
                game.scoreCompletableFeature(ctx);
                undeployMeeples(ctx);
                game.post(new FeatureCompletedEvent(getActivePlayer(), master, ctx));
            }
        }
    }

}
TOP

Related Classes of com.jcloisterzone.game.phase.ScorePhase

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.