Holy crap Batman! It's the beginnings of refactoring the basic puzzle
stuff into Narya. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2876 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// $Id: DropBoardUtil.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
import com.threerings.util.DirectionCodes;
|
||||
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
|
||||
public class DropBoardUtil
|
||||
implements DirectionCodes
|
||||
{
|
||||
/**
|
||||
* Returns the orientation resulting from rotating the block in the
|
||||
* given direction the specified number of times.
|
||||
*
|
||||
* @param orient the current orientation.
|
||||
* @param dir the direction to rotate in; one of <code>CW</code> or
|
||||
* <code>CCW</code>.
|
||||
* @param count the number of rotations to perform.
|
||||
*
|
||||
* @return the rotated orientation.
|
||||
*/
|
||||
public static int getRotatedOrientation (int orient, int dir, int count)
|
||||
{
|
||||
for (int ii = 0; ii < (count % 4); ii++) {
|
||||
orient = getRotatedOrientation(orient, dir);
|
||||
}
|
||||
return orient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation resulting from rotating the block in
|
||||
* the given direction.
|
||||
*
|
||||
* @param orient the current orientation.
|
||||
* @param dir the direction to rotate in; one of <code>CW</code> or
|
||||
* <code>CCW</code>.
|
||||
*
|
||||
* @return the rotated orientation.
|
||||
*/
|
||||
public static int getRotatedOrientation (int orient, int dir)
|
||||
{
|
||||
return (orient + ((dir == CW) ? 2 : 6)) % DIRECTION_COUNT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// $Id: DropGameUtil.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import com.threerings.util.KeyTranslatorImpl;
|
||||
|
||||
import com.threerings.puzzle.drop.client.DropControllerDelegate;
|
||||
import com.threerings.puzzle.util.PuzzleGameUtil;
|
||||
|
||||
/**
|
||||
* Drop puzzle game related utilities.
|
||||
*/
|
||||
public class DropGameUtil
|
||||
{
|
||||
/**
|
||||
* Returns a key translator configured with mappings suitable for a
|
||||
* drop puzzle game.
|
||||
*/
|
||||
public static KeyTranslatorImpl getKeyTranslator ()
|
||||
{
|
||||
// start with the standard puzzle key mappings
|
||||
KeyTranslatorImpl xlate = PuzzleGameUtil.getKeyTranslator();
|
||||
|
||||
// add all press key mappings
|
||||
xlate.addPressCommand(KeyEvent.VK_LEFT,
|
||||
DropControllerDelegate.MOVE_BLOCK_LEFT,
|
||||
MOVE_RATE, MOVE_DELAY);
|
||||
xlate.addPressCommand(KeyEvent.VK_RIGHT,
|
||||
DropControllerDelegate.MOVE_BLOCK_RIGHT,
|
||||
MOVE_RATE, MOVE_DELAY);
|
||||
xlate.addPressCommand(KeyEvent.VK_UP,
|
||||
DropControllerDelegate.ROTATE_BLOCK_CCW, 0);
|
||||
xlate.addPressCommand(KeyEvent.VK_DOWN,
|
||||
DropControllerDelegate.ROTATE_BLOCK_CW, 0);
|
||||
xlate.addPressCommand(KeyEvent.VK_SPACE,
|
||||
DropControllerDelegate.START_DROP_BLOCK, 0);
|
||||
|
||||
// add all release key mappings
|
||||
xlate.addReleaseCommand(KeyEvent.VK_SPACE,
|
||||
DropControllerDelegate.END_DROP_BLOCK);
|
||||
|
||||
return xlate;
|
||||
}
|
||||
|
||||
/** The move key repeat rate in moves per second. */
|
||||
protected static final int MOVE_RATE = 7;
|
||||
|
||||
/** The delay in milliseconds before the move keys begin to repeat. */
|
||||
protected static final long MOVE_DELAY = 300L;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// $Id: DropPieceProvider.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
/**
|
||||
* Does something extraordinary.
|
||||
*/
|
||||
public interface DropPieceProvider
|
||||
{
|
||||
/**
|
||||
* Get the next piece to add to the drop board.
|
||||
*/
|
||||
public int getNextPiece ()
|
||||
throws OutOfPiecesException;
|
||||
|
||||
/**
|
||||
* I lost my touch.
|
||||
*/
|
||||
public static class OutOfPiecesException extends Exception
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// $Id: PieceDestroyer.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
import com.threerings.puzzle.drop.data.DropBoard.PieceOperation;
|
||||
import com.threerings.puzzle.drop.data.DropPieceCodes;
|
||||
import com.threerings.puzzle.drop.data.SegmentInfo;
|
||||
|
||||
/**
|
||||
* Handles destroying contiguous piece segments in a drop board.
|
||||
*/
|
||||
public class PieceDestroyer
|
||||
implements DropPieceCodes
|
||||
{
|
||||
/**
|
||||
* An interface to be implemented by specific puzzles to detail the
|
||||
* parameters and methodology by which pieces are destroyed in the
|
||||
* puzzle board.
|
||||
*/
|
||||
public interface DestroyLogic
|
||||
{
|
||||
/**
|
||||
* Returns the minimum length of a contiguously piece segment that
|
||||
* should be destroyed.
|
||||
*/
|
||||
public int getMinimumLength ();
|
||||
|
||||
/**
|
||||
* Returns whether piece <code>a</code> is equivalent to piece
|
||||
* <code>b</code> for the purposes of including it in a contiguous
|
||||
* piece segment to be destroyed.
|
||||
*/
|
||||
public boolean isEquivalent (int a, int b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a piece destroyer that destroys pieces as specified by
|
||||
* the supplied destroy logic.
|
||||
*/
|
||||
public PieceDestroyer (DestroyLogic logic)
|
||||
{
|
||||
_logic = logic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all pieces in the given board that are in contiguous rows
|
||||
* or columns of pieces, returning a list of {@link SegmentInfo}
|
||||
* objects detailing the destroyed piece segments. Note that a single
|
||||
* list is used internally to gather the segment info, and so callers
|
||||
* that care to modify the list should create their own copy; also,
|
||||
* the pieces in the segments may overlap, i.e., two segments may
|
||||
* contain the same piece.
|
||||
*/
|
||||
public List destroyPieces (DropBoard board, PieceOperation destroyOp)
|
||||
{
|
||||
// find all horizontally-oriented destroyed segments
|
||||
int bwid = board.getWidth(), bhei = board.getHeight();
|
||||
_destroyed.clear();
|
||||
int end = bwid - _logic.getMinimumLength() + 1;
|
||||
for (int yy = (bhei - 1); yy >= 0; yy--) {
|
||||
int xx = 0;
|
||||
while (xx < end) {
|
||||
xx += findSegment(board, HORIZONTAL, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
// find all vertically-oriented destroyed segments
|
||||
end = _logic.getMinimumLength() - 2;
|
||||
for (int xx = 0; xx < bwid; xx++) {
|
||||
int yy = bhei - 1;
|
||||
while (yy > end) {
|
||||
yy -= findSegment(board, VERTICAL, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
// destroy the pieces
|
||||
int size = _destroyed.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
SegmentInfo si = (SegmentInfo)_destroyed.get(ii);
|
||||
board.applyOp(si.dir, si.x, si.y, si.len, destroyOp);
|
||||
}
|
||||
|
||||
return _destroyed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a contiguously colored piece segment with the
|
||||
* specified orientation and root coordinates in the supplied board
|
||||
* and returns the length of the segment traversed.
|
||||
*/
|
||||
protected int findSegment (DropBoard board, int dir, int x, int y)
|
||||
{
|
||||
_lengthOp.reset();
|
||||
board.applyOp(dir, x, y, _lengthOp);
|
||||
int len = _lengthOp.getLength();
|
||||
if (len >= _logic.getMinimumLength()) {
|
||||
_destroyed.add(new SegmentInfo(dir, x, y, len));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* A piece operation that calculates the length of the contiguous
|
||||
* piece segment to which it is applied.
|
||||
*/
|
||||
protected class SegmentLengthOperation
|
||||
implements PieceOperation
|
||||
{
|
||||
/**
|
||||
* Resets the operation for application to a new piece segment.
|
||||
*/
|
||||
public void reset ()
|
||||
{
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the contiguous piece segment.
|
||||
*/
|
||||
public int getLength ()
|
||||
{
|
||||
return _len;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean execute (DropBoard board, int col, int row)
|
||||
{
|
||||
int piece = board.getPiece(col, row);
|
||||
if (_len == 0) {
|
||||
_len = 1;
|
||||
_piece = piece;
|
||||
return (piece != PIECE_NONE);
|
||||
|
||||
} else if (_logic.isEquivalent(piece, _piece)) {
|
||||
_len++;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** The root segment piece. */
|
||||
protected int _piece;
|
||||
|
||||
/** The segment length in pieces. */
|
||||
protected int _len;
|
||||
}
|
||||
|
||||
/** The puzzle-specific destroy logic with which we do our business. */
|
||||
protected DestroyLogic _logic;
|
||||
|
||||
/** The piece operation used to determine segment length. */
|
||||
protected SegmentLengthOperation _lengthOp = new SegmentLengthOperation();
|
||||
|
||||
/** The list of destroyed piece segments. */
|
||||
protected ArrayList _destroyed = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// $Id: PieceDropLogic.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
import com.threerings.util.DirectionCodes;
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by games that would like to be able to
|
||||
* drop their pieces during game play.
|
||||
*/
|
||||
public interface PieceDropLogic
|
||||
{
|
||||
/**
|
||||
* Should the board always be filled?
|
||||
*
|
||||
* @return false for normal behavior.
|
||||
*/
|
||||
public boolean boardAlwaysFilled ();
|
||||
|
||||
/**
|
||||
* Returns whether the given piece is potentially droppable.
|
||||
*/
|
||||
public boolean isDroppablePiece (int piece);
|
||||
|
||||
/**
|
||||
* Returns whether the given piece has constraints upon it that
|
||||
* impact its droppability.
|
||||
*/
|
||||
public boolean isConstrainedPiece (int piece);
|
||||
|
||||
/**
|
||||
* Returns whether the given piece terminates a column climb when
|
||||
* determining the height of a piece column to be dropped.
|
||||
*
|
||||
* @param allowConst whether to allow dropping constrained pieces
|
||||
* (though only in the first encountered constrained block.)
|
||||
* @param piece the piece to consider.
|
||||
* @param pre whether the climbability check is being performed
|
||||
* before the height is incremented, or after.
|
||||
*/
|
||||
public boolean isClimbablePiece (
|
||||
boolean allowConst, int piece, boolean pre);
|
||||
|
||||
/**
|
||||
* Returns the x-axis coordinate of the specified edge of the
|
||||
* given constrained piece.
|
||||
*
|
||||
* <p> TODO: This should go away once the sword and sail games
|
||||
* have standardized on WEST/EAST or BLOCK_LEFT/BLOCK_RIGHT to
|
||||
* reference block edges.
|
||||
*
|
||||
* @param board the board to search.
|
||||
* @param col the column of the constrained piece.
|
||||
* @param row the row of the constrained piece.
|
||||
* @param dir the edge direction to find; one of {@link
|
||||
* DirectionCodes#LEFT} or {@link DirectionCodes#RIGHT}.
|
||||
*/
|
||||
public int getConstrainedEdge (DropBoard board, int col, int row, int dir);
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
//
|
||||
// $Id: PieceDropper.java,v 1.1 2003/11/26 01:42:34 mdb Exp $
|
||||
|
||||
package com.threerings.puzzle.drop.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.puzzle.Log;
|
||||
import com.threerings.puzzle.drop.data.DropBoard;
|
||||
import com.threerings.puzzle.drop.data.DropPieceCodes;
|
||||
|
||||
/**
|
||||
* Handles dropping pieces in a board.
|
||||
*/
|
||||
public class PieceDropper
|
||||
implements DropPieceCodes
|
||||
{
|
||||
/**
|
||||
* A class to hold information detailing the pieces to be dropped
|
||||
* in a particular column.
|
||||
*/
|
||||
public static class PieceDropInfo
|
||||
{
|
||||
/** The starting row of the bottom piece being dropped. */
|
||||
public int row;
|
||||
|
||||
/** The column number. */
|
||||
public int col;
|
||||
|
||||
/** The distance to drop the pieces. */
|
||||
public int dist;
|
||||
|
||||
/** The pieces to be dropped. */
|
||||
public int[] pieces;
|
||||
|
||||
/**
|
||||
* Constructs a piece drop info object.
|
||||
*/
|
||||
public PieceDropInfo (int col, int row, int dist)
|
||||
{
|
||||
this.col = col;
|
||||
this.row = row;
|
||||
this.dist = dist;
|
||||
}
|
||||
|
||||
/** Returns a string representation of this instance. */
|
||||
public String toString ()
|
||||
{
|
||||
return StringUtil.fieldsToString(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a piece dropper that uses the supplied piece drop logic
|
||||
* to specialise itself for a particular puzzle.
|
||||
*/
|
||||
public PieceDropper (PieceDropLogic logic)
|
||||
{
|
||||
_logic = logic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructively modifies the supplied board to contain pieces dropped
|
||||
* in the first of potentially multiple drop positions and returns a
|
||||
* list of {@link PieceDropInfo} objects detailing all column segments
|
||||
* to be dropped. Note that a single list is used internally to store
|
||||
* the drop info objects, and so callers that care to do anything
|
||||
* long-term with the drop info should create their own copy of the
|
||||
* list or somesuch.
|
||||
*
|
||||
* @param DropPieceProvider if the board should always be filled
|
||||
* (as specified by the PieceDropLogic) this will provide
|
||||
* information on the newly filled in pieces.
|
||||
*/
|
||||
public List dropPieces (DropBoard board, DropPieceProvider provider)
|
||||
{
|
||||
int bhei = board.getHeight(), bwid = board.getWidth();
|
||||
_drops.clear();
|
||||
for (int yy = bhei - 1; yy >= 0; yy--) {
|
||||
for (int xx = 0; xx < bwid; xx++) {
|
||||
// find all drops in this column
|
||||
getColumnDrops(board, _drops, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
if (_logic.boardAlwaysFilled()) {
|
||||
addFillingDrops(board, provider, _drops);
|
||||
}
|
||||
|
||||
return _drops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes but does not modify the supplied board and returns a list
|
||||
* of {@link PieceDropInfo} objects detailing all column segments to
|
||||
* be dropped. Note that a single list is used internally to store
|
||||
* the drop info objects, and so callers that care to do anything
|
||||
* long-term with the drop info should create their own copy of the
|
||||
* list or somesuch.
|
||||
*
|
||||
* @param DropPieceProvider if the board should always be filled
|
||||
* (as specified by the PieceDropLogic) this will provide
|
||||
* information on the newly filled in pieces.
|
||||
*/
|
||||
public List getDroppedPieces (DropBoard board, DropPieceProvider provider)
|
||||
{
|
||||
// grab a snapshot of the board within which we're dropping
|
||||
// pieces to avoid modifying the source board directly while we're
|
||||
// figuring out what to drop where
|
||||
if (_board == null) {
|
||||
_board = (DropBoard)board.clone();
|
||||
} else {
|
||||
board.copyInto(_board);
|
||||
}
|
||||
return dropPieces(_board, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the <code>drops</code> list with {@link PieceDropInfo}
|
||||
* objects detailing the column segments to be dropped per empty space
|
||||
* below. Destructively modifies the given board to reflect the final
|
||||
* positions of the column segments once dropped.
|
||||
*/
|
||||
protected void getColumnDrops (DropBoard board, List drops, int x, int y)
|
||||
{
|
||||
// skip empty or fixed pieces
|
||||
int piece = board.getPiece(x, y);
|
||||
if (!_logic.isDroppablePiece(piece)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_logic.isConstrainedPiece(piece)) {
|
||||
// get the distance to drop the block
|
||||
int dist = getBlockDropDistance(board, x, y);
|
||||
if (dist == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// scoot along the bottom edge of the block dropping each column
|
||||
int bwid = board.getWidth();
|
||||
int start = _logic.getConstrainedEdge(board, x, y, LEFT);
|
||||
int end = _logic.getConstrainedEdge(board, x, y, RIGHT);
|
||||
for (int xpos = start; xpos <= end; xpos++) {
|
||||
addDropInfo(board, drops, true, xpos, y, dist);
|
||||
}
|
||||
|
||||
} else {
|
||||
// get the distance to drop the pieces
|
||||
int dist = board.getDropDistance(x, y);
|
||||
if (dist == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add the column segment to the list of drops
|
||||
addDropInfo(board, drops, false, x, y, dist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link PieceDropInfo} object to the drop list detailing
|
||||
* dropping of the column segment at the specified location.
|
||||
*
|
||||
* @param board the working board.
|
||||
* @param allowConst whether to allow dropping constrained pieces in
|
||||
* the specified column segment.
|
||||
* @param x the column x-coordinate.
|
||||
* @param y the column segment bottom y-coordinate.
|
||||
* @param dist the distance to drop the pieces.
|
||||
*/
|
||||
protected void addDropInfo (DropBoard board, List drops,
|
||||
boolean allowConst, int x, int y, int dist)
|
||||
{
|
||||
// sanity check our column
|
||||
if (x < 0 || x >= board.getWidth()) {
|
||||
Log.warning("Requested to add bogus drop info [board=" + board +
|
||||
", drops=" + StringUtil.toString(drops) +
|
||||
", allowConst=" + allowConst +
|
||||
", x=" + x + ", y=" + y + ", dist=" + dist + "].");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
|
||||
// traverse up the column looking for an empty or block piece
|
||||
// that will terminate this column segment
|
||||
int height = getDropHeight(board, allowConst, x, y, dist);
|
||||
|
||||
// create the piece drop info object
|
||||
PieceDropInfo pdi = new PieceDropInfo(x, y, dist);
|
||||
|
||||
// copy in the relevant pieces
|
||||
pdi.pieces = new int[height];
|
||||
int idx = 0;
|
||||
for (int yy = y; yy > (y - height); yy--) {
|
||||
pdi.pieces[idx++] = board.getPiece(x, yy);
|
||||
}
|
||||
|
||||
// update the working copy of the board with the eventual
|
||||
// piece locations
|
||||
dropPieces(board, pdi);
|
||||
|
||||
// add the column segment to the pot
|
||||
drops.add(pdi);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we want to keep the board filled at all times,
|
||||
* this method will be called to create drop objects for the
|
||||
* newly-filled in pieces.
|
||||
*/
|
||||
protected void addFillingDrops (
|
||||
DropBoard board, DropPieceProvider provider, List drops)
|
||||
{
|
||||
boolean out = false;
|
||||
// drop in new pieces for empty spaces at the top
|
||||
for (int xx=0, bwid=board.getWidth(); xx < bwid; xx++) {
|
||||
// get the distance to drop the pieces
|
||||
int dist = board.getDropDistance(xx, -1);
|
||||
if (dist != 0) {
|
||||
PieceDropInfo pdi = new PieceDropInfo(xx, -1, dist);
|
||||
pdi.pieces = new int[dist];
|
||||
for (int ii=0; ii < dist; ii++) {
|
||||
try {
|
||||
pdi.pieces[ii] = provider.getNextPiece();
|
||||
} catch (DropPieceProvider.OutOfPiecesException oop) {
|
||||
// well, how far did we get?
|
||||
int[] something = new int[ii];
|
||||
System.arraycopy(pdi.pieces, 0, something, 0, ii);
|
||||
pdi.pieces = something;
|
||||
out = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dropPieces(board, pdi);
|
||||
drops.add(pdi);
|
||||
|
||||
// if we're outta pieces, bail.
|
||||
if (out) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the piece segment to be dropped at the
|
||||
* given coordinates.
|
||||
*/
|
||||
protected int getDropHeight (
|
||||
DropBoard board, boolean allowConst, int x, int y, int dist)
|
||||
{
|
||||
int height = 0;
|
||||
for (int yy = y; yy >= 0; yy--) {
|
||||
int curpiece = board.getPiece(x, yy);
|
||||
if (!_logic.isClimbablePiece(allowConst, curpiece, true)) {
|
||||
return height;
|
||||
}
|
||||
|
||||
height++;
|
||||
|
||||
if (!_logic.isClimbablePiece(allowConst, curpiece, false)) {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given board to reflect the eventual destination of the
|
||||
* given pieces.
|
||||
*/
|
||||
protected void dropPieces (DropBoard board, PieceDropInfo pdi)
|
||||
{
|
||||
// clear out the original piece positions
|
||||
if (!board.setSegment(
|
||||
VERTICAL, pdi.col, pdi.row, pdi.pieces.length, PIECE_NONE)) {
|
||||
Log.warning("Bogosity encountered when clearing pieces for drop " +
|
||||
"[bwid=" + board.getWidth() +
|
||||
", bhei=" + board.getHeight() + ", pdi=" + pdi + "].");
|
||||
}
|
||||
// place the pieces in their destination positions
|
||||
applyPieces(board, pdi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of spaces the block whose bottom edge
|
||||
* contains the specified coordinate can be dropped based on the
|
||||
* contents of the given board. The droppable distance for a
|
||||
* block is determined by finding the minimum drop distance across
|
||||
* all columns the block spans.
|
||||
*/
|
||||
protected int getBlockDropDistance (DropBoard board, int x, int y)
|
||||
{
|
||||
// get the smallest drop distance across all of the block columns
|
||||
int bwid = board.getWidth();
|
||||
int start = Math.max(_logic.getConstrainedEdge(board, x, y, LEFT), 0);
|
||||
int end = Math.min(
|
||||
_logic.getConstrainedEdge(board, x, y, RIGHT), bwid - 1);
|
||||
int dist = board.getHeight() - 1;
|
||||
|
||||
for (int xpos = start; xpos <= end; xpos++) {
|
||||
dist = Math.min(dist, board.getDropDistance(xpos, y));
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the pieces in the given piece drop info object to the given
|
||||
* board at their eventual destination positions.
|
||||
*/
|
||||
protected void applyPieces (DropBoard board, PieceDropInfo pdi)
|
||||
{
|
||||
int start = pdi.row, end = (pdi.row - pdi.pieces.length);
|
||||
int idx = 0;
|
||||
boolean error = false;
|
||||
for (int yy = (start + pdi.dist); yy > (end + pdi.dist); yy--) {
|
||||
error = !board.setPiece(pdi.col, yy, pdi.pieces[idx++]) || error;
|
||||
}
|
||||
if (error) {
|
||||
Log.warning("Bogosity encountered while applying dropped " +
|
||||
"pieces to board [bwid=" + board.getWidth() +
|
||||
", bhei=" + board.getHeight() + ", pdi=" + pdi + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/** The piece drop logic used to allow puzzle-specific piece dropping
|
||||
* hooks. */
|
||||
protected PieceDropLogic _logic;
|
||||
|
||||
/** The list of piece drop info objects detailing the piece drops
|
||||
* resulting from the last call to {@link #getDroppedPieces}. */
|
||||
protected ArrayList _drops = new ArrayList();
|
||||
|
||||
/** The board on which pieces are being dropped. */
|
||||
protected DropBoard _board;
|
||||
}
|
||||
Reference in New Issue
Block a user