/*
* $Id$
*
* Copyright (c) 2004 by Rodney Kinney
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.build.module.map;
import java.util.ArrayList;
import java.util.Arrays;
import VASSAL.counters.Deck;
import VASSAL.counters.GamePiece;
import VASSAL.counters.Properties;
import VASSAL.counters.Stack;
/**
* Base class for PieceCollection implementation that organize
* pieces into distinct layers. The layers are drawn in order of their index, i.e.
* layer 0 is on the bottom.
*/
public abstract class CompoundPieceCollection implements PieceCollection {
protected SimplePieceCollection[] layers;
protected int bottomLayer = 0;
protected boolean[] enabled;
protected CompoundPieceCollection(int layerCount) {
initLayers(layerCount);
}
protected void initLayers(int layerCount) {
layers = new SimplePieceCollection[layerCount];
enabled = new boolean[layerCount];
for (int i=0;i<layers.length;++i) {
layers[i] = new SimplePieceCollection();
enabled[i] = true;
}
}
public int getLayerForPiece(GamePiece p) {
return 0;
}
public String getLayerNameForPiece(GamePiece p) {
return "";
}
public int getLayerForName(String layerName) {
return -1;
}
protected PieceCollection getCollectionForPiece(GamePiece p) {
return layers[getLayerForPiece(p)];
}
public void add(GamePiece p) {
getCollectionForPiece(p).add(p);
}
public void clear() {
for (int i=0;i<layers.length;++i) {
layers[i].clear();
}
}
/*
* Return pieces in layer order from the bottom up. Take into account
* layer rotation and enabled state.
*/
public GamePiece[] getPieces() {
return getPieces(false);
}
protected GamePiece[] getPieces(boolean includeDisabled) {
ArrayList<GamePiece> l = new ArrayList<GamePiece>();
int layer = bottomLayer;
for (int i = 0; i < layers.length; ++i) {
if (includeDisabled || (!includeDisabled && enabled[layer])) {
l.addAll(Arrays.asList(layers[layer].getPieces()));
}
layer++;
if (layer >= layers.length) {
layer = 0;
}
}
return l.toArray(new GamePiece[l.size()]);
}
public GamePiece[] getAllPieces() {
return getPieces(true);
}
public int indexOf(GamePiece p) {
int layer = getLayerForPiece(p);
int index = layers[layer].indexOf(p);
if (index >= 0) {
for (int i=0;i<layer-1;++i) {
index += layers[i].getPieces().length;
}
}
return index;
}
public void remove(GamePiece p) {
getCollectionForPiece(p).remove(p);
}
public void moveToBack(GamePiece p) {
getCollectionForPiece(p).moveToBack(p);
}
public void moveToFront(GamePiece p) {
getCollectionForPiece(p).moveToFront(p);
}
public boolean canMerge(GamePiece p1, GamePiece p2) {
boolean canMerge = false;
if (p1 instanceof Deck
|| p2 instanceof Deck) {
canMerge = true;
}
else if (p1 instanceof Stack) {
if (p2 instanceof Stack) {
canMerge = canStacksMerge((Stack) p1, (Stack) p2);
}
else {
canMerge = canStackAndPieceMerge((Stack) p1, p2);
}
}
else if (p2 instanceof Stack) {
canMerge = canStackAndPieceMerge((Stack) p2, p1);
}
else {
canMerge = canPiecesMerge(p1, p2);
}
return canMerge;
}
protected boolean canStacksMerge(Stack s1, Stack s2) {
return canPiecesMerge(s1.topPiece(), s2.topPiece());
}
protected boolean canStackAndPieceMerge(Stack s, GamePiece p) {
boolean canMerge = false;
GamePiece top = s.topPiece();
if (top != null) {
canMerge = canPiecesMerge(top, p);
}
return canMerge;
}
protected boolean canPiecesMerge(GamePiece p1, GamePiece p2) {
boolean canMerge = false;
if (p1 != null
&& p2 != null) {
canMerge = !Boolean.TRUE.equals(p1.getProperty(Properties.NO_STACK))
&& !Boolean.TRUE.equals(p2.getProperty(Properties.NO_STACK))
&& !Boolean.TRUE.equals(p1.getProperty(Properties.INVISIBLE_TO_ME))
&& !Boolean.TRUE.equals(p2.getProperty(Properties.INVISIBLE_TO_ME));
}
return canMerge;
}
public int getLayerCount() {
return layers.length;
}
/*
* Set a new bottom layer. Take care of wrapping around ends of layer list.
*/
public void setBottomLayer(int layer) {
bottomLayer = layer;
if (bottomLayer < 0) bottomLayer = getLayerCount() - 1;
if (bottomLayer >= getLayerCount()) bottomLayer = 0;
}
public int getBottomLayer() {
return bottomLayer;
}
public int getTopLayer() {
int layer = bottomLayer - 1;
if (layer < 0) {
layer = getLayerCount() - 1;
}
return layer;
}
/*
* Rotate layers up or down, optionally skipping top layers not containing
* counters.
*/
public void rotate(boolean rotateUp, boolean skipNullLayers) {
if (skipNullLayers) {
for (int i = 0; i < layers.length; i++) {
rotate(rotateUp);
if (layers[getTopLayer()].getPieces().length > 0) {
return;
}
}
}
else {
rotate(rotateUp);
}
}
/*
* Rotate Layers up or down by 1 layer
*/
public void rotate(boolean rotateUp) {
if (rotateUp) {
setBottomLayer(bottomLayer-1);
}
else {
setBottomLayer(bottomLayer + 1);
}
}
/*
* Enable/Disable layers
*/
public void setLayerEnabled(int layer, boolean b) {
if (layer >= 0 && layer < layers.length) {
enabled[layer] = b;
}
}
public void toggleLayerEnabled(int layer) {
if (layer >= 0 && layer < layers.length) {
enabled[layer] = !enabled[layer];
}
}
public void setLayerEnabled(String layer, boolean b) {
setLayerEnabled(getLayerForName(layer), b);
}
public void toggleLayerEnabled(String layer) {
toggleLayerEnabled(getLayerForName(layer));
}
/*
* Reset Layers to original state
*/
public void reset() {
setBottomLayer(0);
for (int i = 0; i < layers.length; i++) {
enabled[i] = true;
}
}
}