Package com.barrybecker4.game.twoplayer.blockade.board.move.wall

Source Code of com.barrybecker4.game.twoplayer.blockade.board.move.wall.WallPlacementValidator

// Copyright by Barry G. Becker, 2012. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.game.twoplayer.blockade.board.move.wall;

import com.barrybecker4.common.geometry.Location;
import com.barrybecker4.game.common.GameContext;
import com.barrybecker4.game.twoplayer.blockade.board.BlockadeBoard;
import com.barrybecker4.game.twoplayer.blockade.board.BlockadeBoardPosition;
import com.barrybecker4.game.twoplayer.blockade.board.Homes;
import com.barrybecker4.game.twoplayer.blockade.board.analysis.BoardAnalyzer;
import com.barrybecker4.game.twoplayer.blockade.board.path.PathList;

import java.util.HashMap;
import java.util.Map;

/**
* Checks for legal wall placements.
*
* @author Barry Becker
*/
public class WallPlacementValidator {

    private BlockadeBoard board;

    /**
     * Constructor.
     */
    public WallPlacementValidator(BlockadeBoard board) {
        this.board = board;
    }

    /*
     * It is illegal to place a wall at a position that overlaps
     * or intersects another wall, or if the wall prevents one of the pawns from reaching an
     * opponent home.
     * @param wall to place. has not been placed yet.
     * @param location where the wall is to be placed.
     * @return an error string if the wall is not a legal placement on the board.
     */
    public String checkLegalWallPlacement(BlockadeWall wall, Location location, BoardAnalyzer analyzer) {
        String sError = null;
        assert (wall != null);

        Map<BlockadeBoardPosition, BlockadeWall> oldWalls = getOldWalls(wall);

        if (hasWallOverlap(wall)) {
            sError = GameContext.getLabel("CANT_OVERLAP_WALLS");
        }

        BlockadeBoardPosition pos = board.getPosition(location);
        if (sError == null && hasWallIntersection(wall)) {
             sError = GameContext.getLabel("CANT_INTERSECT_WALLS");
        }
        else if (sError == null && pos == null) {
            sError = GameContext.getLabel("INVALID_WALL_PLACEMENT");
        }
        else if (sError == null && missingPath(analyzer)) {
            sError = GameContext.getLabel("MUST_HAVE_ONE_PATH");
        }

       // now restore the original walls
       for (BlockadeBoardPosition wallPos: wall.getPositions())  {
            BlockadeWall origWall = oldWalls.get(wallPos);
            if (wall.isVertical())
                wallPos.setEastWall(origWall);
            else
                wallPos.setSouthWall(origWall);
        }
        return sError;
    }


    private Map<BlockadeBoardPosition, BlockadeWall> getOldWalls(BlockadeWall wall) {

        Map<BlockadeBoardPosition, BlockadeWall> oldWalls = new HashMap<BlockadeBoardPosition, BlockadeWall>();
        boolean vertical = wall.isVertical();

        for (BlockadeBoardPosition pos: wall.getPositions())  {

            BlockadeWall origWall = vertical ? pos.getEastWall() : pos.getSouthWall() ;

            // save the old wall, and temporarily set the candidate wall
            oldWalls.put(pos, origWall);

        }
        return oldWalls;
    }

    private boolean hasWallOverlap(BlockadeWall wall) {
        // iterate over the 2 positions covered by the wall.
        boolean vertical = wall.isVertical();
        for (BlockadeBoardPosition pos: wall.getPositions())  {
            BlockadeWall origWall = vertical? pos.getEastWall() : pos.getSouthWall() ;

            if ((vertical && pos.isEastBlocked()) || (!vertical && pos.isSouthBlocked())) {
                return true;
            }

            if (vertical) {
                pos.setEastWall(wall);
            }
            else  {
                pos.setSouthWall(wall);
            }
        }
        return false;
    }

    /**
     * @return error message if the new wall intersects an old one.
     */
    private boolean hasWallIntersection(BlockadeWall wall) {
         boolean vertical = wall.isVertical();
         // you cannot intersect one wall with another
         BlockadeBoardPosition pos = wall.getFirstPosition();

         BlockadeBoardPosition secondPos =
                    (vertical? board.getPosition(pos.getRow(), pos.getCol()+1) :
                               board.getPosition(pos.getRow()+1, pos.getCol()));
        return (vertical && pos.isSouthBlocked() && secondPos.isSouthBlocked())
                || (!vertical && pos.isEastBlocked()) && secondPos.isEastBlocked();
    }

    /**
     * @return error message if no path exists from this position to an opponent home.
     */
    private boolean missingPath(BoardAnalyzer analyzer) {
        PathList paths1 = analyzer.findAllOpponentShortestPaths(true);
        PathList paths2 = analyzer.findAllOpponentShortestPaths(false);
        GameContext.log(2, "paths1.magnitude="+paths1.size()+" paths2.magnitude ="+paths2.size() );

        int expectedNumPaths = getExpectedNumPaths();
        return  (paths1.size() < expectedNumPaths || paths2.size() <expectedNumPaths );
    }

    private int getExpectedNumPaths() {
        return Homes.NUM_HOMES * Homes.NUM_HOMES;
    }
}
TOP

Related Classes of com.barrybecker4.game.twoplayer.blockade.board.move.wall.WallPlacementValidator

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.