Package com.jcloisterzone.game.capability

Source Code of com.jcloisterzone.game.capability.TunnelCapability

package com.jcloisterzone.game.capability;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.jcloisterzone.Player;
import com.jcloisterzone.XmlUtils;
import com.jcloisterzone.action.PlayerAction;
import com.jcloisterzone.action.TunnelAction;
import com.jcloisterzone.board.Location;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.board.pointer.FeaturePointer;
import com.jcloisterzone.event.TunnelPiecePlacedEvent;
import com.jcloisterzone.feature.Feature;
import com.jcloisterzone.feature.Road;
import com.jcloisterzone.game.Capability;
import com.jcloisterzone.game.Game;


public final class TunnelCapability extends Capability {

    private Road placedTunnelCurrentTurn;

    private final Map<Player, Integer> tunnelTokensA = new HashMap<>();
    private final Map<Player, Integer> tunnelTokensB = new HashMap<>();

    private final List<Road> tunnels = new ArrayList<>();

    public TunnelCapability(Game game) {
        super(game);
    }

    @Override
    public Object backup() {
        return new Object[] {
            placedTunnelCurrentTurn,
            new HashMap<>(tunnelTokensA),
            new HashMap<>(tunnelTokensB)
        };
    }

    @SuppressWarnings("unchecked")
    @Override
    public void restore(Object data) {
        Object[] a = (Object[]) data;
        placedTunnelCurrentTurn = (Road) a[0];
        tunnelTokensA.clear();
        tunnelTokensA.putAll((Map<Player, Integer>)a[1]);
        tunnelTokensA.clear();
        tunnelTokensA.putAll((Map<Player, Integer>)a[2]);
    }

    @Override
    public void initPlayer(Player player) {
        tunnelTokensA.put(player, 2);
        tunnelTokensB.put(player, game.getAllPlayers().length <= 2 ? 2 : 0);
    }

    @Override
    public void initFeature(Tile tile, Feature feature, Element xml) {
        if (!(feature instanceof Road)) return;
        Road road = (Road) feature;
        if (road.isTunnelEnd()) {
            tunnels.add(road);
        }
    }

    public List<Road> getOpenTunnels() {
        List<Road> openTunnels = new ArrayList<>();
        for (Road road : tunnels) {
            if (road.getTile().getPosition() != null && road.isTunnelOpen()) {
                openTunnels.add(road);
            }
        }
        return openTunnels;
    }

    public int getTunnelTokens(Player player, boolean isB) {
        Map<Player, Integer> map = isB ? tunnelTokensB : tunnelTokensA;
        return map.get(player);
    }

    public void decreaseTunnelTokens(Player player, boolean isB) {
        Map<Player, Integer> map = isB ? tunnelTokensB : tunnelTokensA;
        int tokens = map.get(player);
        if (tokens == 0) throw new IllegalStateException("Player has no tunnel token");
        map.put(player, tokens-1);
    }

    @Override
    public void prepareActions(List<PlayerAction<?>> actions, Set<FeaturePointer> followerOptions) {
        if (isTunnelUsedThisTurn()) return;
        List<Road> openTunnels = getOpenTunnels();
        if (openTunnels.isEmpty()) return;

        List<TunnelAction> tunnelActions = new ArrayList<>(2);
        if (getTunnelTokens(game.getActivePlayer(), false) > 0) {
            tunnelActions.add(new TunnelAction(false));
        }
        if (getTunnelTokens(game.getActivePlayer(), true) > 0) {
            tunnelActions.add(new TunnelAction(true));
        }
        for (TunnelAction ta : tunnelActions) {
            for (Road tunnelEnd : openTunnels) {
                ta.add(new FeaturePointer(tunnelEnd.getTile().getPosition(), tunnelEnd.getLocation()));
            }
        }
        actions.addAll(tunnelActions);
    }

    public boolean isTunnelUsedThisTurn() {
        return placedTunnelCurrentTurn != null;
    }
    public Road getPlacedTunnel() {
        return placedTunnelCurrentTurn;
    }

    @Override
    public void turnCleanUp() {
        placedTunnelCurrentTurn = null;
    }

    private int getTunnelId(Player p, boolean isB) {
        return p.getIndex() + (isB ? 100 : 0);
    }

    public void placeTunnelPiece(Position p, Location loc, boolean isB) {
        Road road = (Road) getBoard().get(p).getFeature(loc);
        if (!road.isTunnelOpen()) {
            throw new IllegalStateException("No open tunnel here.");
        }
        placedTunnelCurrentTurn = road;
        Player player = game.getActivePlayer();
        placeTunnelPiece(road, player, p, loc, isB);
    }

    private void placeTunnelPiece(Road road, Player player, Position p, Location loc, boolean isB) {
        int connectionId = getTunnelId(player, isB);
        decreaseTunnelTokens(player, isB);
        for (Road r : tunnels) {
            if (r.getTunnelEnd() == connectionId) {
                r.setTunnelEdge(road);
                road.setTunnelEdge(r);
                break;
            }
        }
        road.setTunnelEnd(connectionId);
        game.post(new TunnelPiecePlacedEvent(player, p, loc, isB));
    }

    @Override
    public void saveToSnapshot(Document doc, Element node) {
        if (placedTunnelCurrentTurn != null) {
            Element el = doc.createElement("placed-tunnel");
            XmlUtils.injectPosition(el, placedTunnelCurrentTurn.getTile().getPosition());
            el.setAttribute("location", placedTunnelCurrentTurn.getLocation().toString());
            node.appendChild(el);
        }
        for (Road tunnel : tunnels) {
            if (tunnel.getTile().getPosition() != null && tunnel.getTunnelEnd() != Road.OPEN_TUNNEL) {
                Element el = doc.createElement("tunnel");
                node.appendChild(el);
                XmlUtils.injectPosition(el, tunnel.getTile().getPosition());
                el.setAttribute("location", tunnel.getLocation().toString());
                el.setAttribute("player", "" + (tunnel.getTunnelEnd() % 100));
                el.setAttribute("b", tunnel.getTunnelEnd() > 100 ? "yes" : "no");
            }
        }
    }

    @Override
    public void loadFromSnapshot(Document doc, Element node) {
        NodeList nl = node.getElementsByTagName("placed-tunnel");
        if (nl.getLength() > 0) {
            Element el = (Element) nl.item(0);
            placedTunnelCurrentTurn = (Road) getBoard().get(XmlUtils.extractPosition(el)).getFeature(Location.valueOf(el.getAttribute("location")));
        }
        nl = node.getElementsByTagName("tunnel");
        for (int i = 0; i < nl.getLength(); i++) {
            Element el = (Element) nl.item(i);
            Position pos = XmlUtils.extractPosition(el);
            Location loc = Location.valueOf(el.getAttribute("location"));
            Road road = (Road) getBoard().get(pos).getFeature(loc);
            if (!road.isTunnelEnd()) {
                logger.error("Tunnel end does not exist.");
                continue;
            }
            Player player = game.getPlayer(Integer.parseInt(el.getAttribute("player")));
            boolean isB = "yes".equals(el.getAttribute("b"));
            placeTunnelPiece(road, player, pos, loc, isB);
        }
    }

}
TOP

Related Classes of com.jcloisterzone.game.capability.TunnelCapability

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.