Package com.barrybecker4.puzzle.tantrix.model

Source Code of com.barrybecker4.puzzle.tantrix.model.RandomTilePlacer

// Copyright by Barry G. Becker, 2012. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.puzzle.tantrix.model;

import com.barrybecker4.common.geometry.Location;
import com.barrybecker4.common.math.MathUtil;
import com.barrybecker4.puzzle.tantrix.model.fitting.PrimaryPathFitter;

import java.util.Collections;
import java.util.Map;

/**
* Generates random continuous primary color paths that do not necessarily match on secondary colors.
*
* @author Barry Becker
*/
public class RandomTilePlacer {

    private PathColor primaryColor;

    /**
     * Constructor
     */
    public RandomTilePlacer(PathColor primaryColor) {
        this.primaryColor = primaryColor;
    }

    /**
     * For each unplaced tile, find all valid placements given current configuration.
     * Valid placements must extend the primary path but not necessarily match secondary paths.
     * @return List of all valid tile placements for the current tantrix state.
     *  returns null of no placement is possible.
     */
    public TilePlacement generatePlacement(TantrixBoard board) {

        HexTileList unplacedTiles = (HexTileList) board.getUnplacedTiles().clone();
        Collections.shuffle(unplacedTiles, MathUtil.RANDOM);

        TilePlacement nextMove = null;
        int i=0;
        while (nextMove == null && i<unplacedTiles.size())   {
            HexTile tile = unplacedTiles.get(i++);
            boolean isLast = unplacedTiles.isEmpty();
            nextMove = findPrimaryPathPlacementForTile(board, tile, isLast);
        }
        /*
        if (nextMove == null) {
            throw new IllegalStateException("We could not find a placement on \n" + board
                    + "\nusing these unplaced tiles:"  + unplacedTiles + " primColor="+ board.getPrimaryColor());
        }*/
        return nextMove;
    }

    /**
     * A random placement for the specified tile which matches the primary path,
     * but not necessarily the secondary paths. The opposite end of the primary path can only
     * retouch the tantrix if it is the last tile to be placed in the random path.
     *
     * There are usually two ways to place a tile, but there are some rare cases where there can be four.
     * For example, given:
     * [tileNum=6 colors: [Y, R, B, Y, B, R] at (row=20, column=21) ANGLE_240]
     * [tileNum=2 colors: [B, Y, Y, B, R, R] at (row=20, column=20) ANGLE_60]
     * [tileNum=7 colors: [R, Y, R, Y, B, B] at (row=21, column=21) ANGLE_0]
     *
     * There are these 4 valid placements:
     *  [tileNum=4 colors: [B, Y, R, B, R, Y] at (row=21, column=22) ANGLE_0],
     *  [tileNum=4 colors: [B, Y, R, B, R, Y] at (row=21, column=22) ANGLE_60],
     *  [tileNum=4 colors: [B, Y, R, B, R, Y] at (row=21, column=22) ANGLE_240],
     *  [tileNum=4 colors: [B, Y, R, B, R, Y] at (row=21, column=22) ANGLE_300]]
     *  but all of them cause retouching to the main path.
     *
     * @return a valid primary pth placement.
     */
    private TilePlacement findPrimaryPathPlacementForTile(TantrixBoard board, HexTile tile, boolean isLast) {

        TilePlacement lastPlaced = board.getLastTile();
        PrimaryPathFitter fitter = new PrimaryPathFitter(board.getTantrix(), board.getPrimaryColor());

        Map<Integer, Location> outgoing = lastPlaced.getOutgoingPathLocations(primaryColor);
        Location nextLocation = null;
        for (int i : outgoing.keySet()) {
            if (board.getTilePlacement(outgoing.get(i)) == null) {
                nextLocation = outgoing.get(i);
            }
        }
        assert nextLocation != null;

        TilePlacementList validFits =
                fitter.getFittingPlacements(tile, nextLocation);

        if (validFits.isEmpty())  {
            return null;
        }

        return validFits.get(MathUtil.RANDOM.nextInt(validFits.size()));
    }

    /**
     * Avoid having the random extension to the path loop back and retouch the tantrix.
     * We remove those placements from consideration (unless it is the last one).
     *
    private void cullPlacementsThatRetouch(TantrixBoard board, TilePlacement lastPlaced, TilePlacementList validFits) {
        Iterator<TilePlacement> iter = validFits.iterator();
        while (iter.hasNext()) {
            TilePlacement fit = iter.next();
            Map<Integer, Location> outgoing = fit.getOutgoingPathLocations(primaryColor);
            boolean retouchesTantrix = false;

            for (int i : outgoing.keySet()) {
                TilePlacement p = board.getTilePlacement(outgoing.get(i));
                if (p != null && !p.equals(lastPlaced)) {
                    retouchesTantrix = true;
                }
            }
            if (retouchesTantrix) {
                iter.remove();
            }
        }
    } */
}
 
TOP

Related Classes of com.barrybecker4.puzzle.tantrix.model.RandomTilePlacer

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.