com.threerings.puzzle.drop.util.PieceDropper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vilya Show documentation
Show all versions of vilya Show documentation
Facilities for making networked multiplayer games.
//
// $Id: PieceDropper.java 1046 2011-01-01 05:04:14Z dhoover $
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2011 Three Rings Design, Inc., All Rights Reserved
// http://code.google.com/p/vilya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.puzzle.drop.util;
import com.samskivert.util.StringUtil;
import com.threerings.puzzle.drop.data.DropBoard;
import com.threerings.puzzle.drop.data.DropPieceCodes;
import static com.threerings.puzzle.Log.log;
/**
* 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;
}
@Override
public String toString () {
return StringUtil.fieldsToString(this);
}
}
/**
* Called to inform a drop observer that a piece has been dropped.
*/
public static interface DropObserver
{
/** Indicates that the specified piece was dropped. */
public void pieceDropped (int piece, int sx, int sy, int dx, int dy);
}
/**
* Constructs a piece dropper that uses the supplied piece drop logic to specialize itself for
* a particular puzzle.
*/
public PieceDropper (PieceDropLogic logic)
{
_logic = logic;
}
/**
* Effects any drops possible on the supplied board (modifying the board in the progress) and
* notifying the supplied drop observer of those drops.
*
* @return the number of pieces dropped.
*/
public int dropPieces (DropBoard board, DropObserver drobs)
{
int dropped = 0, bhei = board.getHeight(), bwid = board.getWidth();
for (int yy = bhei - 1; yy >= 0; yy--) {
for (int xx = 0; xx < bwid; xx++) {
dropped += dropPieces(board, xx, yy, drobs);
}
}
// if the board wants pieces to be dropped in to fill the gaps, do that now
if (_logic.boardAlwaysFilled()) {
dropped += fillBoard(board, drobs);
}
return dropped;
}
/**
* Drops new pieces onto the board to fill the gaps.
*
* @return the number of pieces dropped.
*/
public int fillBoard (DropBoard board, DropObserver drobs)
{
int dropped = 0;
int bwid = board.getWidth();
for (int xx = 0; xx < bwid; xx++) {
int dist = board.getDropDistance(xx, -1);
for (int ii = 0; ii < dist; ii++) {
int yy = (-1 - ii);
int piece = board.getNextPiece();
if (piece != PIECE_NONE) {
drop(board, piece, xx, yy, yy + dist, drobs);
dropped++;
}
}
}
return dropped;
}
/**
* Computes and effects the drop for the specified piece and any associated attached pieces.
* The supplied observer is notified of all drops.
*/
protected int dropPieces (DropBoard board, int xx, int yy, DropObserver drobs)
{
// skip empty or fixed pieces
int piece = board.getPiece(xx, yy);
if (!_logic.isDroppablePiece(piece)) {
return 0;
}
int dropped = 0;
if (_logic.isConstrainedPiece(piece)) {
// find out where this constrained block starts and ends
int start = _logic.getConstrainedEdge(board, xx, yy, LEFT);
int end = _logic.getConstrainedEdge(board, xx, yy, RIGHT);
int bwid = board.getWidth();
if (start < 0 || end >= bwid) {
log.warning("Board reported bogus constrained edge",
"x", xx, "y", yy, "start", start, "end", end);
board.dump();
start = Math.max(start, 0);
end = Math.min(end, bwid);
}
// get the smallest drop distance across all of the block columns
int dist = board.getHeight() - 1;
for (int xpos = start; xpos <= end; xpos++) {
dist = Math.min(dist, board.getDropDistance(xpos, yy));
}
if (dist == 0) {
return 0;
}
// scoot along the bottom edge of the block, noting the drop for each column
for (int xpos = start; xpos <= end; xpos++) {
piece = board.getPiece(xpos, yy);
drop(board, piece, xpos, yy, yy + dist, drobs);
dropped++;
}
} else {
// get the distance to drop the pieces
int dist = board.getDropDistance(xx, yy);
if (dist == 0) {
return 0;
}
drop(board, piece, xx, yy, yy + dist, drobs);
dropped++;
}
return dropped;
}
/** Helpy helper function. */
protected final void drop (
DropBoard board, int piece, int xx, int yy, int ty, DropObserver drobs)
{
// don't try to clear things out if we're filling in from off-board
if (yy >= 0) {
board.setPiece(xx, yy, PIECE_NONE);
}
board.setPiece(xx, ty, piece);
if (drobs != null) {
drobs.pieceDropped(piece, xx, yy, xx, ty);
}
}
/** Allows puzzle-specific customizations. */
protected PieceDropLogic _logic;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy