Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// $Id: PieceDropper.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user