Package com.jcloisterzone.game.capability

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

package com.jcloisterzone.game.capability;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.action.BridgeAction;
import com.jcloisterzone.action.PlayerAction;
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.BridgeDeployedEvent;
import com.jcloisterzone.game.Capability;
import com.jcloisterzone.game.Game;

public class BridgeCapability extends Capability {

    private boolean bridgeUsed;
    private final Map<Player, Integer> bridges = new HashMap<>();

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

    @Override
    public Object backup() {
        return new Object[] {
            bridgeUsed,
            new HashMap<>(bridges)
        };
    }

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


    @Override
    public void initPlayer(Player player) {
        int players = game.getAllPlayers().length;
        if (players < 5) {
            bridges.put(player, 3);
        } else {
            bridges.put(player, 2);
        }
    }

    @Override
    public void turnPartCleanUp() {
        bridgeUsed = false;
    }

    @Override
    public void prepareActions(List<PlayerAction<?>> actions, Set<FeaturePointer> followerOptions) {
        if (!bridgeUsed && getPlayerBridges(game.getPhase().getActivePlayer()) > 0) {
            BridgeAction action = prepareBridgeAction();
            if (action != null) {
                actions.add(action);
            }
        }
    }

    public BridgeAction prepareMandatoryBridgeAction() {
        Tile tile = game.getCurrentTile();
        for (Entry<Location, Tile> entry : getBoard().getAdjacentTilesMap(tile.getPosition()).entrySet()) {
            Tile adjacent = entry.getValue();
            Location rel = entry.getKey();

            char adjacentSide = adjacent.getEdge(rel.rev());
            char tileSide = tile.getEdge(rel);
            if (tileSide != adjacentSide) {
                Location bridgeLoc = getBridgeLocationForAdjacent(rel);
                BridgeAction action = prepareTileBridgeAction(tile, null, bridgeLoc);
                if (action != null) return action;
                return prepareTileBridgeAction(adjacent, null, bridgeLoc);
            }
        }
        throw new IllegalStateException();
    }

    private Location getBridgeLocationForAdjacent(Location rel) {
        if (rel == Location.N || rel == Location.S) {
            return Location.NS;
        } else {
            return Location.WE;
        }
    }

    private BridgeAction prepareBridgeAction() {
        BridgeAction action = null;
        Tile tile = game.getCurrentTile();
        action = prepareTileBridgeAction(tile, action, Location.NS);
        action = prepareTileBridgeAction(tile, action, Location.WE);
        for (Entry<Location, Tile> entry : getBoard().getAdjacentTilesMap(tile.getPosition()).entrySet()) {
            Tile adjacent = entry.getValue();
            Location rel = entry.getKey();
            action = prepareTileBridgeAction(adjacent, action, getBridgeLocationForAdjacent(rel));
        }
        return action;
    }

    private BridgeAction prepareTileBridgeAction(Tile tile, BridgeAction action, Location bridgeLoc) {
        if (isBridgePlacementAllowed(tile, tile.getPosition(), bridgeLoc)) {
            if (action == null) action = new BridgeAction();
            action.add(new FeaturePointer(tile.getPosition(), bridgeLoc));
        }
        return action;
    }

    private boolean isBridgePlacementAllowed(Tile tile, Position p, Location bridgeLoc) {
        if (!tile.isBridgeAllowed(bridgeLoc)) return false;
        for (Entry<Location, Tile> e : getBoard().getAdjacentTilesMap(p).entrySet()) {
            Location rel = e.getKey();
            if (rel.intersect(bridgeLoc) != null) {
                Tile adjacent = e.getValue();
                char adjacentSide = adjacent.getEdge(rel.rev());
                if (adjacentSide != 'R') return false;
            }
        }
        return true;
    }

    public boolean isTilePlacementWithBridgePossible(Tile tile, Position p) {
        if (getPlayerBridges(game.getActivePlayer()) > 0) {
            if (isTilePlacementWithBridgeAllowed(tile, p, Location.NS)) return true;
            if (isTilePlacementWithBridgeAllowed(tile, p, Location.WE)) return true;
            if (isTilePlacementWithOneAdjacentBridgeAllowed(tile, p)) return true;
        }
        return false;
    }

    private boolean isTilePlacementWithBridgeAllowed(Tile tile, Position p, Location bridgeLoc) {
        if (!tile.isBridgeAllowed(bridgeLoc)) return false;

        for (Entry<Location, Tile> e : getBoard().getAdjacentTilesMap(p).entrySet()) {
            Tile adjacent = e.getValue();
            Location rel = e.getKey();

            char adjacentSide = adjacent.getEdge(rel.rev());
            char tileSide = tile.getEdge(rel);
            if (rel.intersect(bridgeLoc) != null) {
                if (adjacentSide != 'R') return false;
            } else {
                if (adjacentSide != tileSide) return false;
            }
        }
        return true;
    }

    private boolean isTilePlacementWithOneAdjacentBridgeAllowed(Tile tile, Position p) {
        boolean bridgeUsed = false;
        for (Entry<Location, Tile> e : getBoard().getAdjacentTilesMap(p).entrySet()) {
            Tile adjacent = e.getValue();
            Location rel = e.getKey();

            char tileSide = tile.getEdge(rel);
            char adjacentSide = adjacent.getEdge(rel.rev());

            if (tileSide != adjacentSide) {
                if (bridgeUsed) return false;
                if (tileSide != 'R') return false;

                Location bridgeLoc = getBridgeLocationForAdjacent(rel);
                if (!isBridgePlacementAllowed(adjacent, adjacent.getPosition(), bridgeLoc)) return false;
                bridgeUsed = true;
            }
        }
        return bridgeUsed; //ok if exactly one bridge is used
    }

    public int getPlayerBridges(Player pl) {
        return bridges.get(pl);
    }

    public void decreaseBridges(Player player) {
        int n = getPlayerBridges(player);
        if (n == 0) throw new IllegalStateException("Player has no bridges");
        bridges.put(player, n-1);
    }

    public void deployBridge(Position pos, Location loc) {
        Tile tile = getBoard().get(pos);
        if (!tile.isBridgeAllowed(loc)) {
            throw new IllegalArgumentException("Cannot deploy " + loc + " bridge on " + pos);
        }
        bridgeUsed = true;
        tile.placeBridge(loc);
        game.post(new BridgeDeployedEvent(game.getActivePlayer(), pos, loc));
    }



    @Override
    public void saveTileToSnapshot(Tile tile, Document doc, Element tileNode) {
        if (tile.getBridge() != null) {
            Location realLoc = tile.getBridge().getRawLocation();
            tileNode.setAttribute("bridge", realLoc.toString());
        }
    }

    @Override
    public void loadTileFromSnapshot(Tile tile, Element tileNode) {
        if (tileNode.hasAttribute("bridge")) {
            Location loc =  Location.valueOf(tileNode.getAttribute("bridge"));
            tile.placeBridge(loc);
        }
    }

    @Override
    public void saveToSnapshot(Document doc, Element node) {
        node.setAttribute("bridgeUsed", bridgeUsed + "");
        for (Player player: game.getAllPlayers()) {
            Element el = doc.createElement("player");
            node.appendChild(el);
            el.setAttribute("index", "" + player.getIndex());
            el.setAttribute("bridges", "" + getPlayerBridges(player));
        }
    }

    @Override
    public void loadFromSnapshot(Document doc, Element node) {
        bridgeUsed = Boolean.parseBoolean(node.getAttribute("bridgeUsed"));
        NodeList nl = node.getElementsByTagName("player");
        for (int i = 0; i < nl.getLength(); i++) {
            Element playerEl = (Element) nl.item(i);
            Player player = game.getPlayer(Integer.parseInt(playerEl.getAttribute("index")));
            bridges.put(player, Integer.parseInt(playerEl.getAttribute("bridges")));
        }
    }


}
TOP

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

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.