33f55d5a8d
creating new source files. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@209 c613c5cb-e716-0410-b11b-feb51c14d237
204 lines
6.1 KiB
Java
204 lines
6.1 KiB
Java
//
|
|
// $Id$
|
|
//
|
|
// Vilya library - tools for developing networked games
|
|
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
|
// http://www.threerings.net/code/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 java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 specialise 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()) {
|
|
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;
|
|
}
|