git-svn-id: https://samskivert.googlecode.com/svn/trunk@363 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: AtlantiBoard.java,v 1.7 2001/10/16 09:31:46 mdb Exp $
|
// $Id: AtlantiBoard.java,v 1.8 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
@@ -7,11 +7,14 @@ import java.awt.*;
|
|||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.samskivert.swing.Controller;
|
import com.samskivert.swing.Controller;
|
||||||
import com.samskivert.swing.util.SwingUtil;
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
import com.samskivert.util.CollectionUtil;
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DSet;
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
@@ -45,38 +48,97 @@ public class VenisonBoard
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the tiles that are displayed by this board. Causes the board
|
* Sets the tiles to be displayed by this board. Any previous tiles
|
||||||
* to recompute its size based on the new tile layout.
|
* are forgotten and the new tiles are initialized according to their
|
||||||
|
* geometry to set up initial claim groups.
|
||||||
*
|
*
|
||||||
* @param tiles the set of {@link VenisonTile} objects to be displayed
|
* @param tset the set of {@link VenisonTile} objects to be displayed
|
||||||
* by this board.
|
* by this board.
|
||||||
*/
|
*/
|
||||||
public void setTiles (DSet tiles)
|
public void setTiles (DSet tset)
|
||||||
{
|
{
|
||||||
// grab the new tiles
|
// clear out our old tiles list
|
||||||
_tiles = tiles;
|
_tiles.clear();
|
||||||
|
|
||||||
// update our display
|
// copy the tiles from the set into our local list
|
||||||
refreshTiles();
|
CollectionUtil.addAll(_tiles, tset.elements());
|
||||||
|
|
||||||
|
// sort the list
|
||||||
|
Collections.sort(_tiles);
|
||||||
|
|
||||||
|
// recompute our desired dimensions and then have our parent
|
||||||
|
// adjust to our changed size
|
||||||
|
computeDimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs the board to refresh its display in case changes have
|
* Sets the piecens to be placed on the appropriate tiles of the
|
||||||
* occurred in the tiles set.
|
* board. This should only be done when first entering the game room
|
||||||
|
* and subsequent piecen placement should be done via {@link
|
||||||
|
* #placePiecen}.
|
||||||
*/
|
*/
|
||||||
public void refreshTiles ()
|
public void setPiecens (DSet piecens)
|
||||||
{
|
{
|
||||||
// recompute our desired dimensions and then have our parent
|
// just iterate over the set placing each of the piecens in turn
|
||||||
// adjust to our changed size
|
Iterator iter = piecens.elements();
|
||||||
if (_tiles != null) {
|
while (iter.hasNext()) {
|
||||||
computeDimensions();
|
placePiecen((Piecen)iter.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructs the board to add the specified tile to the display. The
|
||||||
|
* tile will have its claims inherited accordingly.
|
||||||
|
*/
|
||||||
|
public void addTile (VenisonTile tile)
|
||||||
|
{
|
||||||
|
Log.info("Adding tile to board " + tile + ".");
|
||||||
|
|
||||||
|
// if we add a tile that is the same as our most recently placed
|
||||||
|
// tile, leave the placed tile. otherwise clear it out
|
||||||
|
if (!tile.equals(_placedTile)) {
|
||||||
|
_placedTile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we may need to revalidate if our dimensions changed
|
// add the tile
|
||||||
revalidate();
|
_tiles.add(tile);
|
||||||
|
|
||||||
// we also have to repaint in case our dimensions didn't change
|
// resort the list
|
||||||
repaint();
|
Collections.sort(_tiles);
|
||||||
|
|
||||||
|
// have the new tile inherit its claim groups
|
||||||
|
TileUtil.inheritClaims(_tiles, tile);
|
||||||
|
|
||||||
|
// recompute our desired dimensions and then have our parent
|
||||||
|
// adjust to our changed size
|
||||||
|
computeDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places the specified piecen on the appropriate tile and updates
|
||||||
|
* claim groups as necessary.
|
||||||
|
*/
|
||||||
|
public void placePiecen (Piecen piecen)
|
||||||
|
{
|
||||||
|
// if we still have a placed tile, we get rid of it
|
||||||
|
_placedTile = null;
|
||||||
|
|
||||||
|
Log.info("Placing " + piecen + ".");
|
||||||
|
|
||||||
|
// locate the tile associated with this piecen
|
||||||
|
int tidx = _tiles.indexOf(piecen);
|
||||||
|
if (tidx != -1) {
|
||||||
|
VenisonTile tile = (VenisonTile)_tiles.get(tidx);
|
||||||
|
// set the piecen on the tile (supplying our tile list so that
|
||||||
|
// the necessary claim group adjustments can be made)
|
||||||
|
tile.setPiecen(piecen, _tiles);
|
||||||
|
// and repaint
|
||||||
|
repaint();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.warning("Requested to place piecen for which we could " +
|
||||||
|
"find no associated tile! [piecen=" + piecen + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,6 +165,7 @@ public class VenisonBoard
|
|||||||
if (_placingTile != null) {
|
if (_placingTile != null) {
|
||||||
updatePlacingInfo(true);
|
updatePlacingInfo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and repaint
|
// and repaint
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
@@ -135,12 +198,10 @@ public class VenisonBoard
|
|||||||
g.translate(_tx, _ty);
|
g.translate(_tx, _ty);
|
||||||
|
|
||||||
// iterate over our tiles, painting each of them
|
// iterate over our tiles, painting each of them
|
||||||
if (_tiles != null) {
|
int tsize = _tiles.size();
|
||||||
Iterator iter = _tiles.elements();
|
for (int i = 0; i < tsize; i++) {
|
||||||
while (iter.hasNext()) {
|
VenisonTile tile = (VenisonTile)_tiles.get(i);
|
||||||
VenisonTile tile = (VenisonTile)iter.next();
|
tile.paint(g2, _origX, _origY);
|
||||||
tile.paint(g2, _origX, _origY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have a placing tile, draw that one as well
|
// if we have a placing tile, draw that one as well
|
||||||
@@ -155,8 +216,23 @@ public class VenisonBoard
|
|||||||
g.drawRect(sx, sy, TILE_WIDTH, TILE_HEIGHT);
|
g.drawRect(sx, sy, TILE_WIDTH, TILE_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we have a recently placed tile, draw that one as well
|
||||||
|
if (_placedTile != null) {
|
||||||
|
// draw the tile
|
||||||
|
_placedTile.paint(g2, _origX, _origY);
|
||||||
|
|
||||||
|
// draw a white rectangle around the placed tile
|
||||||
|
g.setColor(Color.white);
|
||||||
|
int sx = (_placedTile.x + _origX) * TILE_WIDTH;
|
||||||
|
int sy = (_placedTile.y + _origY) * TILE_HEIGHT;
|
||||||
|
g.drawRect(sx, sy, TILE_WIDTH, TILE_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
// undo our translations
|
// undo our translations
|
||||||
g.translate(-_tx, -_ty);
|
g.translate(-_tx, -_ty);
|
||||||
|
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g2.draw(getBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called by our adapter when the mouse moves. */
|
/** Called by our adapter when the mouse moves. */
|
||||||
@@ -166,11 +242,52 @@ public class VenisonBoard
|
|||||||
_mouseX = evt.getX() - _tx;
|
_mouseX = evt.getX() - _tx;
|
||||||
_mouseY = evt.getY() - _ty;
|
_mouseY = evt.getY() - _ty;
|
||||||
|
|
||||||
// if we have a tile to be placed, update its coordinates
|
|
||||||
if (_placingTile != null) {
|
if (_placingTile != null) {
|
||||||
|
// if we have a tile to be placed, update its coordinates
|
||||||
if (updatePlacingInfo(false)) {
|
if (updatePlacingInfo(false)) {
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (_placedTile != null && _placingPiecen) {
|
||||||
|
// if we have a recently placed tile, we're doing piecen
|
||||||
|
// placement; first convert the mouse coords into tile coords
|
||||||
|
int mx = _mouseX - (_placedTile.x + _origX) * TILE_WIDTH;
|
||||||
|
int my = _mouseY - (_placedTile.y + _origY) * TILE_HEIGHT;
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
// now see if we're inside the placing tile
|
||||||
|
if (mx >= 0 && mx < TILE_WIDTH && my >= 0 && my < TILE_HEIGHT) {
|
||||||
|
int fidx = _placedTile.getFeatureIndex(mx, my);
|
||||||
|
|
||||||
|
// if the feature is not already claimed, we can put a
|
||||||
|
// piece there to indicate that it can be claimed
|
||||||
|
if (_placedTile.claims[fidx] == 0) {
|
||||||
|
if (_placedTile.piecen == null ||
|
||||||
|
_placedTile.piecen.featureIndex != fidx) {
|
||||||
|
Piecen p = new Piecen(Piecen.BLUE, 0, 0, fidx);
|
||||||
|
_placedTile.setPiecen(p, null);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// we may need to clear out a piecen since we've moved
|
||||||
|
if (_placedTile.piecen != null) {
|
||||||
|
_placedTile.clearPiecen();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// we may need to clear out a piecen since we've moved
|
||||||
|
if (_placedTile.piecen != null) {
|
||||||
|
_placedTile.clearPiecen();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,11 +302,25 @@ public class VenisonBoard
|
|||||||
_placedTile = _placingTile;
|
_placedTile = _placingTile;
|
||||||
_placingTile = null;
|
_placingTile = null;
|
||||||
|
|
||||||
|
// inherit claims on the placed tile
|
||||||
|
TileUtil.inheritClaims(_tiles, _placedTile);
|
||||||
|
|
||||||
// post the action
|
// post the action
|
||||||
Controller.postAction(this, TILE_PLACED);
|
Controller.postAction(this, TILE_PLACED);
|
||||||
|
|
||||||
// and repaint
|
// move into placing piecen mode
|
||||||
repaint();
|
_placingPiecen = true;
|
||||||
|
|
||||||
|
// recompute our dimensions (which will relayout or repaint)
|
||||||
|
computeDimensions();
|
||||||
|
|
||||||
|
} else if (_placingPiecen && _placedTile != null &&
|
||||||
|
_placedTile.piecen != null) {
|
||||||
|
// clear out placing piecen mode
|
||||||
|
_placingPiecen = false;
|
||||||
|
|
||||||
|
// post the action
|
||||||
|
Controller.postAction(this, PIECEN_PLACED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,8 +350,7 @@ public class VenisonBoard
|
|||||||
|
|
||||||
// we also need to recompute the valid orientations for the
|
// we also need to recompute the valid orientations for the
|
||||||
// tile in this new position
|
// tile in this new position
|
||||||
_validOrients = TileUtil.computeValidOrients(
|
_validOrients = TileUtil.computeValidOrients(_tiles, _placingTile);
|
||||||
_tiles.elements(), _placingTile);
|
|
||||||
|
|
||||||
// if we've changed positions, clear out our valid placement
|
// if we've changed positions, clear out our valid placement
|
||||||
// flag
|
// flag
|
||||||
@@ -290,7 +420,7 @@ public class VenisonBoard
|
|||||||
// documentation inherited
|
// documentation inherited
|
||||||
public Dimension getPreferredSize ()
|
public Dimension getPreferredSize ()
|
||||||
{
|
{
|
||||||
if (_tiles == null) {
|
if (_tiles.size() == 0) {
|
||||||
return new Dimension(100, 100);
|
return new Dimension(100, 100);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -300,28 +430,33 @@ public class VenisonBoard
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines how big we want to be based on where the tiles have been
|
* Determines how big we want to be based on where the tiles have been
|
||||||
* laid out.
|
* laid out. This will cause the component to be re-layed out if the
|
||||||
|
* dimensions change or repainted if not.
|
||||||
*/
|
*/
|
||||||
protected void computeDimensions ()
|
protected void computeDimensions ()
|
||||||
{
|
{
|
||||||
int maxX = 0, maxY = 0;
|
int maxX = 0, maxY = 0;
|
||||||
int minX = 0, minY = 0;
|
int minX = 0, minY = 0;
|
||||||
|
|
||||||
|
// if we have a recently placed tile, start with that one
|
||||||
|
if (_placedTile != null) {
|
||||||
|
minX = maxX = _placedTile.x;
|
||||||
|
minY = maxY = _placedTile.y;
|
||||||
|
}
|
||||||
|
|
||||||
// figure out what our boundaries are
|
// figure out what our boundaries are
|
||||||
if (_tiles != null) {
|
int tsize = _tiles.size();
|
||||||
Iterator iter = _tiles.elements();
|
for (int i = 0; i < tsize; i++) {
|
||||||
while (iter.hasNext()) {
|
VenisonTile tile = (VenisonTile)_tiles.get(i);
|
||||||
VenisonTile tile = (VenisonTile)iter.next();
|
if (tile.x > maxX) {
|
||||||
if (tile.x > maxX) {
|
maxX = tile.x;
|
||||||
maxX = tile.x;
|
} else if (tile.x < minX) {
|
||||||
} else if (tile.x < minX) {
|
minX = tile.x;
|
||||||
minX = tile.x;
|
}
|
||||||
}
|
if (tile.y > maxY) {
|
||||||
if (tile.y > maxY) {
|
maxY = tile.y;
|
||||||
maxY = tile.y;
|
} else if (tile.y < minY) {
|
||||||
} else if (tile.y < minY) {
|
minY = tile.y;
|
||||||
minY = tile.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,11 +464,25 @@ public class VenisonBoard
|
|||||||
minX -= 1; minY -= 1;
|
minX -= 1; minY -= 1;
|
||||||
maxX += 1; maxY += 1;
|
maxX += 1; maxY += 1;
|
||||||
|
|
||||||
|
// keep track of these to know if we've change dimensions
|
||||||
|
int oldOrigX = _origX, oldOrigY = _origY;
|
||||||
|
int oldWidth = _width, oldHeight = _height;
|
||||||
|
|
||||||
// now we can compute our width and the origin offset
|
// now we can compute our width and the origin offset
|
||||||
_origX = -minX;
|
_origX = -minX;
|
||||||
_origY = -minY;
|
_origY = -minY;
|
||||||
_width = maxX - minX + 1;
|
_width = maxX - minX + 1;
|
||||||
_height = maxY - minY + 1;
|
_height = maxY - minY + 1;
|
||||||
|
|
||||||
|
if (_origX != oldOrigX || _origY != oldOrigY ||
|
||||||
|
oldWidth != _width || oldHeight != _height) {
|
||||||
|
// if the dimensions changed, we need to relayout
|
||||||
|
revalidate();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise just repaint
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test code. */
|
/** Test code. */
|
||||||
@@ -348,26 +497,25 @@ public class VenisonBoard
|
|||||||
set.addTile(new VenisonTile(CITY_TWO, false, WEST, -1, 1));
|
set.addTile(new VenisonTile(CITY_TWO, false, WEST, -1, 1));
|
||||||
set.addTile(new VenisonTile(CITY_TWO, false, WEST, -1, -1));
|
set.addTile(new VenisonTile(CITY_TWO, false, WEST, -1, -1));
|
||||||
set.addTile(new VenisonTile(CURVED_ROAD, false, WEST, 0, 2));
|
set.addTile(new VenisonTile(CURVED_ROAD, false, WEST, 0, 2));
|
||||||
VenisonTile target =
|
VenisonTile one = new VenisonTile(TWO_CITY_TWO, false, NORTH, 0, 1);
|
||||||
new VenisonTile(DISCONNECTED_CITY_TWO, false, NORTH, 0, 1);
|
set.addTile(one);
|
||||||
set.addTile(target);
|
|
||||||
set.addTile(new VenisonTile(CITY_THREE, false, WEST, 1, 1));
|
set.addTile(new VenisonTile(CITY_THREE, false, WEST, 1, 1));
|
||||||
set.addTile(new VenisonTile(CITY_THREE_ROAD, false, EAST, 1, 2));
|
set.addTile(new VenisonTile(CITY_THREE_ROAD, false, EAST, 1, 2));
|
||||||
set.addTile(new VenisonTile(CITY_THREE, false, NORTH, -1, 0));
|
set.addTile(new VenisonTile(CITY_THREE, false, NORTH, -1, 0));
|
||||||
set.addTile(new VenisonTile(CITY_FOUR, false, NORTH, -2, 0));
|
VenisonTile two = new VenisonTile(CITY_FOUR, false, NORTH, -2, 0);
|
||||||
|
set.addTile(two);
|
||||||
board.setTiles(set);
|
board.setTiles(set);
|
||||||
|
|
||||||
VenisonTile placing = new VenisonTile(CITY_TWO, false, NORTH, 0, 0);
|
VenisonTile placing = new VenisonTile(CITY_TWO, false, NORTH, 0, 0);
|
||||||
board.setTileToBePlaced(placing);
|
board.setTileToBePlaced(placing);
|
||||||
|
|
||||||
// set a feature group to test propagation
|
// set a feature group to test propagation
|
||||||
VenisonTile[] tiles = new VenisonTile[set.size()];
|
List tiles = new ArrayList();
|
||||||
Iterator iter = set.elements();
|
CollectionUtil.addAll(tiles, set.elements());
|
||||||
for (int i = 0; iter.hasNext(); i++) {
|
Collections.sort(tiles);
|
||||||
tiles[i] = (VenisonTile)iter.next();
|
|
||||||
}
|
one.setPiecen(new Piecen(Piecen.BLUE, 0, 0, 0), tiles);
|
||||||
Arrays.sort(tiles);
|
two.setPiecen(new Piecen(Piecen.BLUE, 0, 0, 0), tiles);
|
||||||
TileUtil.setFeatureGroup(tiles, target, 0, 1, 0);
|
|
||||||
|
|
||||||
frame.getContentPane().add(board, BorderLayout.CENTER);
|
frame.getContentPane().add(board, BorderLayout.CENTER);
|
||||||
frame.pack();
|
frame.pack();
|
||||||
@@ -389,7 +537,7 @@ public class VenisonBoard
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A reference to our tile set. */
|
/** A reference to our tile set. */
|
||||||
protected DSet _tiles;
|
protected ArrayList _tiles = new ArrayList();
|
||||||
|
|
||||||
/** The tile currently being placed by the user. */
|
/** The tile currently being placed by the user. */
|
||||||
protected VenisonTile _placingTile;
|
protected VenisonTile _placingTile;
|
||||||
@@ -397,6 +545,9 @@ public class VenisonBoard
|
|||||||
/** The last tile being placed by the user. */
|
/** The last tile being placed by the user. */
|
||||||
protected VenisonTile _placedTile;
|
protected VenisonTile _placedTile;
|
||||||
|
|
||||||
|
/** A flag indicating whether or not we're placing a piecen. */
|
||||||
|
protected boolean _placingPiecen = false;
|
||||||
|
|
||||||
/** Whether or not the current position and orientation of the placing
|
/** Whether or not the current position and orientation of the placing
|
||||||
* tile is valid. */
|
* tile is valid. */
|
||||||
protected boolean _validPlacement = false;
|
protected boolean _validPlacement = false;
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import java.awt.event.ActionEvent;
|
|||||||
|
|
||||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||||
import com.threerings.presents.dobj.DSet;
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
import com.threerings.presents.dobj.ElementAddedEvent;
|
||||||
|
import com.threerings.presents.dobj.ElementRemovedEvent;
|
||||||
|
import com.threerings.presents.dobj.ElementUpdatedEvent;
|
||||||
import com.threerings.presents.dobj.MessageEvent;
|
import com.threerings.presents.dobj.MessageEvent;
|
||||||
|
import com.threerings.presents.dobj.SetListener;
|
||||||
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
import com.threerings.crowd.data.BodyObject;
|
||||||
import com.threerings.crowd.data.PlaceObject;
|
import com.threerings.crowd.data.PlaceObject;
|
||||||
@@ -23,7 +27,7 @@ import com.threerings.venison.Log;
|
|||||||
* the Venison game.
|
* the Venison game.
|
||||||
*/
|
*/
|
||||||
public class VenisonController
|
public class VenisonController
|
||||||
extends TurnGameController implements VenisonCodes
|
extends TurnGameController implements VenisonCodes, SetListener
|
||||||
{
|
{
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void didInit ()
|
protected void didInit ()
|
||||||
@@ -48,6 +52,14 @@ public class VenisonController
|
|||||||
|
|
||||||
// get a casted reference to our game object
|
// get a casted reference to our game object
|
||||||
_venobj = (VenisonObject)plobj;
|
_venobj = (VenisonObject)plobj;
|
||||||
|
|
||||||
|
// grab the tiles and piecens from the game object and configure
|
||||||
|
// the board with them
|
||||||
|
_panel.board.setTiles(_venobj.tiles);
|
||||||
|
_panel.board.setPiecens(_venobj.piecens);
|
||||||
|
|
||||||
|
// TBD: check to see if it's our turn and set things up
|
||||||
|
// accordingly
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -61,9 +73,6 @@ public class VenisonController
|
|||||||
Log.info("Setting tile to be placed: " + _venobj.currentTile);
|
Log.info("Setting tile to be placed: " + _venobj.currentTile);
|
||||||
_panel.board.setTileToBePlaced(_venobj.currentTile);
|
_panel.board.setTileToBePlaced(_venobj.currentTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and refresh the tiles
|
|
||||||
_panel.board.refreshTiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -74,21 +83,74 @@ public class VenisonController
|
|||||||
// handle the setting of the board state
|
// handle the setting of the board state
|
||||||
if (event.getName().equals(VenisonObject.TILES)) {
|
if (event.getName().equals(VenisonObject.TILES)) {
|
||||||
_panel.board.setTiles(_venobj.tiles);
|
_panel.board.setTiles(_venobj.tiles);
|
||||||
|
|
||||||
|
} else if (event.getName().equals(VenisonObject.PIECENS)) {
|
||||||
|
_panel.board.setPiecens(_venobj.piecens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void elementAdded (ElementAddedEvent event)
|
||||||
|
{
|
||||||
|
// we care about additions to TILES and PIECENS
|
||||||
|
if (event.getName().equals(VenisonObject.TILES)) {
|
||||||
|
// a tile was added, add it to the board
|
||||||
|
VenisonTile tile = (VenisonTile)event.getElement();
|
||||||
|
_panel.board.addTile(tile);
|
||||||
|
|
||||||
|
} else if (event.getName().equals(VenisonObject.PIECENS)) {
|
||||||
|
// a piecen was added, place it on the board
|
||||||
|
Piecen piecen = (Piecen)event.getElement();
|
||||||
|
_panel.board.placePiecen(piecen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void elementUpdated (ElementUpdatedEvent event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void elementRemoved (ElementRemovedEvent event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
public boolean handleAction (ActionEvent action)
|
public boolean handleAction (ActionEvent action)
|
||||||
{
|
{
|
||||||
if (action.getActionCommand().equals(TILE_PLACED)) {
|
if (action.getActionCommand().equals(TILE_PLACED)) {
|
||||||
// the user placed the tile into a valid location. grab the
|
// the user placed the tile into a valid location. grab the
|
||||||
// placed tile from the board and submit it to the server as
|
// placed tile from the board and submit it to the server
|
||||||
// our move
|
|
||||||
Object[] args = new Object[] { _panel.board.getPlacedTile() };
|
Object[] args = new Object[] { _panel.board.getPlacedTile() };
|
||||||
MessageEvent mevt = new MessageEvent(
|
MessageEvent mevt = new MessageEvent(
|
||||||
_venobj.getOid(), PLACE_TILE_REQUEST, args);
|
_venobj.getOid(), PLACE_TILE_REQUEST, args);
|
||||||
_ctx.getDObjectManager().postEvent(mevt);
|
_ctx.getDObjectManager().postEvent(mevt);
|
||||||
|
|
||||||
|
// enable the noplace button
|
||||||
|
_panel.noplace.setEnabled(true);
|
||||||
|
|
||||||
|
} else if (action.getActionCommand().equals(PIECEN_PLACED)) {
|
||||||
|
// the user placed a piecen on the tile. grab the piecen from
|
||||||
|
// the placed tile and submit it to the server
|
||||||
|
Object[] args = new Object[] {
|
||||||
|
_panel.board.getPlacedTile().piecen };
|
||||||
|
MessageEvent mevt = new MessageEvent(
|
||||||
|
_venobj.getOid(), PLACE_PIECEN_REQUEST, args);
|
||||||
|
_ctx.getDObjectManager().postEvent(mevt);
|
||||||
|
|
||||||
|
// disable the noplace button
|
||||||
|
_panel.noplace.setEnabled(false);
|
||||||
|
|
||||||
|
} else if (action.getActionCommand().equals(PLACE_NOTHING)) {
|
||||||
|
// the user doesn't want to place anything this turn. send a
|
||||||
|
// place nothing request to the server
|
||||||
|
MessageEvent mevt = new MessageEvent(
|
||||||
|
_venobj.getOid(), PLACE_NOTHING_REQUEST, null);
|
||||||
|
_ctx.getDObjectManager().postEvent(mevt);
|
||||||
|
|
||||||
|
// disable the noplace button
|
||||||
|
_panel.noplace.setEnabled(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return super.handleAction(action);
|
return super.handleAction(action);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,14 @@ import com.threerings.parlor.util.ParlorContext;
|
|||||||
* The top-level user interface component for the Venison game display.
|
* The top-level user interface component for the Venison game display.
|
||||||
*/
|
*/
|
||||||
public class VenisonPanel
|
public class VenisonPanel
|
||||||
extends JPanel implements PlaceView, ControllerProvider
|
extends JPanel implements PlaceView, ControllerProvider, VenisonCodes
|
||||||
{
|
{
|
||||||
/** A reference to the board that is accessible to the controller. */
|
/** A reference to the board that is accessible to the controller. */
|
||||||
public VenisonBoard board;
|
public VenisonBoard board;
|
||||||
|
|
||||||
|
/** A reference to our _noplace button. */
|
||||||
|
public JButton noplace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Venison game display.
|
* Constructs a new Venison game display.
|
||||||
*/
|
*/
|
||||||
@@ -49,6 +52,13 @@ public class VenisonPanel
|
|||||||
// add a turn indicator to the side panel
|
// add a turn indicator to the side panel
|
||||||
sidePanel.add(new TurnIndicatorView(), VGroupLayout.FIXED);
|
sidePanel.add(new TurnIndicatorView(), VGroupLayout.FIXED);
|
||||||
|
|
||||||
|
// add a "place nothing" button
|
||||||
|
noplace = new JButton("Place nothing");
|
||||||
|
noplace.setEnabled(false);
|
||||||
|
noplace.setActionCommand(PLACE_NOTHING);
|
||||||
|
noplace.addActionListener(Controller.DISPATCHER);
|
||||||
|
sidePanel.add(noplace, VGroupLayout.FIXED);
|
||||||
|
|
||||||
// add our side panel to the main display
|
// add our side panel to the main display
|
||||||
add(sidePanel, HGroupLayout.FIXED);
|
add(sidePanel, HGroupLayout.FIXED);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: AtlantiCodes.java,v 1.1 2001/10/12 20:34:13 mdb Exp $
|
// $Id: AtlantiCodes.java,v 1.2 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
@@ -12,6 +12,14 @@ public interface VenisonCodes
|
|||||||
* the user places a tile into a valid position. */
|
* the user places a tile into a valid position. */
|
||||||
public static final String TILE_PLACED = "tile_placed";
|
public static final String TILE_PLACED = "tile_placed";
|
||||||
|
|
||||||
|
/** The name of the command posted by the {@link VenisonBoard} when
|
||||||
|
* the user places a piecen onto an unclaimed feature. */
|
||||||
|
public static final String PIECEN_PLACED = "piecen_placed";
|
||||||
|
|
||||||
|
/** The name of the command posted by the "place nothing" button in
|
||||||
|
* the side bar. */
|
||||||
|
public static final String PLACE_NOTHING = "place_nothing";
|
||||||
|
|
||||||
/** The message submitted by the client to the server when they have
|
/** The message submitted by the client to the server when they have
|
||||||
* chosen where they wish to place their tile. */
|
* chosen where they wish to place their tile. */
|
||||||
public static final String PLACE_TILE_REQUEST = "place_tile";
|
public static final String PLACE_TILE_REQUEST = "place_tile";
|
||||||
@@ -19,4 +27,8 @@ public interface VenisonCodes
|
|||||||
/** The message submitted by the client to the server when they have
|
/** The message submitted by the client to the server when they have
|
||||||
* chosen where they wish to place their piecen. */
|
* chosen where they wish to place their piecen. */
|
||||||
public static final String PLACE_PIECEN_REQUEST = "place_piecen";
|
public static final String PLACE_PIECEN_REQUEST = "place_piecen";
|
||||||
|
|
||||||
|
/** The message submitted by the client to the server when they decide
|
||||||
|
* that they don't want to (or can't) place any piecen this turn. */
|
||||||
|
public static final String PLACE_NOTHING_REQUEST = "place_nothing";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: AtlantiObject.java,v 1.5 2001/10/16 17:11:58 mdb Exp $
|
// $Id: AtlantiObject.java,v 1.6 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
@@ -17,6 +17,9 @@ public class VenisonObject extends TurnGameObject
|
|||||||
/** The field name of the <code>currentTile</code> field. */
|
/** The field name of the <code>currentTile</code> field. */
|
||||||
public static final String CURRENT_TILE = "currentTile";
|
public static final String CURRENT_TILE = "currentTile";
|
||||||
|
|
||||||
|
/** The field name of the <code>piecens</code> field. */
|
||||||
|
public static final String PIECENS = "piecens";
|
||||||
|
|
||||||
/** A set containing all of the tiles that are in play in this
|
/** A set containing all of the tiles that are in play in this
|
||||||
* game. */
|
* game. */
|
||||||
public DSet tiles = new DSet(VenisonTile.class);
|
public DSet tiles = new DSet(VenisonTile.class);
|
||||||
@@ -25,6 +28,10 @@ public class VenisonObject extends TurnGameObject
|
|||||||
* only valid while it is someone's turn. */
|
* only valid while it is someone's turn. */
|
||||||
public VenisonTile currentTile = VenisonTile.STARTING_TILE;
|
public VenisonTile currentTile = VenisonTile.STARTING_TILE;
|
||||||
|
|
||||||
|
/** A set containing all of the piecens that are placed on the
|
||||||
|
* board. */
|
||||||
|
public DSet piecens = new DSet(Piecen.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests that the <code>tiles</code> field be set to the specified
|
* Requests that the <code>tiles</code> field be set to the specified
|
||||||
* value.
|
* value.
|
||||||
@@ -70,11 +77,48 @@ public class VenisonObject extends TurnGameObject
|
|||||||
requestAttributeChange(CURRENT_TILE, value);
|
requestAttributeChange(CURRENT_TILE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the <code>piecens</code> field be set to the specified
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
public void setPiecens (DSet value)
|
||||||
|
{
|
||||||
|
requestAttributeChange(PIECENS, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified element be added to the
|
||||||
|
* <code>piecens</code> set.
|
||||||
|
*/
|
||||||
|
public void addToPiecens (DSet.Element elem)
|
||||||
|
{
|
||||||
|
requestElementAdd(PIECENS, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the element matching the supplied key be removed from
|
||||||
|
* the <code>piecens</code> set.
|
||||||
|
*/
|
||||||
|
public void removeFromPiecens (Object key)
|
||||||
|
{
|
||||||
|
requestElementRemove(PIECENS, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified element be updated in the
|
||||||
|
* <code>piecens</code> set.
|
||||||
|
*/
|
||||||
|
public void updatePiecens (DSet.Element elem)
|
||||||
|
{
|
||||||
|
requestElementUpdate(PIECENS, elem);
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void toString (StringBuffer buf)
|
protected void toString (StringBuffer buf)
|
||||||
{
|
{
|
||||||
super.toString(buf);
|
super.toString(buf);
|
||||||
buf.append(", tiles=").append(tiles);
|
buf.append(", tiles=").append(tiles);
|
||||||
buf.append(", currentTile=").append(currentTile);
|
buf.append(", currentTile=").append(currentTile);
|
||||||
|
buf.append(", piecens=").append(piecens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: AtlantiTile.java,v 1.7 2001/10/16 17:12:32 mdb Exp $
|
// $Id: AtlantiTile.java,v 1.8 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
@@ -7,16 +7,13 @@ import java.awt.Color;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Polygon;
|
import java.awt.Polygon;
|
||||||
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.geom.GeneralPath;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
import com.samskivert.util.IntTuple;
|
import com.samskivert.util.IntTuple;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DSet;
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
@@ -50,11 +47,11 @@ public class VenisonTile
|
|||||||
public int[] claims;
|
public int[] claims;
|
||||||
|
|
||||||
/** A reference to our static feature descriptions. */
|
/** A reference to our static feature descriptions. */
|
||||||
public int[] features;
|
public Feature[] features;
|
||||||
|
|
||||||
/** A reference to the piecen on this tile or null if no piecen has
|
/** A reference to the piecen on this tile or null if no piecen has
|
||||||
* been placed on this tile. */
|
* been placed on this tile. */
|
||||||
// public Piecen piecen;
|
public Piecen piecen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a tile with all of the supplied tile information.
|
* Constructs a tile with all of the supplied tile information.
|
||||||
@@ -97,15 +94,15 @@ public class VenisonTile
|
|||||||
* @return the index of the matching feature or -1 if no feature
|
* @return the index of the matching feature or -1 if no feature
|
||||||
* matched.
|
* matched.
|
||||||
*/
|
*/
|
||||||
public int getFeatureIndex (int featureMask)
|
public int getFeatureIndex (int edgeMask)
|
||||||
{
|
{
|
||||||
// translate the feature mask into our orientation
|
// translate the feature mask into our orientation
|
||||||
featureMask = TileUtil.translateMask(featureMask, -orientation);
|
edgeMask = FeatureUtil.translateMask(edgeMask, -orientation);
|
||||||
|
|
||||||
for (int i = 0; i < features.length; i += 2) {
|
// look for a feature with a matching edge mask
|
||||||
int fmask = features[i+1];
|
for (int i = 0; i < features.length; i ++) {
|
||||||
if ((fmask & featureMask) != 0) {
|
if ((features[i].edgeMask & edgeMask) != 0) {
|
||||||
return i/2;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +110,32 @@ public class VenisonTile
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the feature that contains the supplied mouse
|
||||||
|
* coordinates (which will have been translated relative to the tile's
|
||||||
|
* origin).
|
||||||
|
*
|
||||||
|
* @return the index of the feature that contains the mouse
|
||||||
|
* coordinates. Some feature should always contain the mouse.
|
||||||
|
*/
|
||||||
|
public int getFeatureIndex (int mouseX, int mouseY)
|
||||||
|
{
|
||||||
|
// we search our features in reverse order because road features
|
||||||
|
// overlap grass features geometrically and are known to be
|
||||||
|
// specified after the grass features
|
||||||
|
for (int i = features.length-1; i >= 0; i--) {
|
||||||
|
if (features[i].contains(mouseX, mouseY, orientation)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// something is hosed; fake it
|
||||||
|
Log.warning("Didn't find matching feature for mouse coordinates!? " +
|
||||||
|
"[tile=" + this + ", mx=" + mouseX +
|
||||||
|
", my=" + mouseY + "].");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks for a feature in this tile that matches the supplied feature
|
* Looks for a feature in this tile that matches the supplied feature
|
||||||
* edge mask and returns the claim group to which that feature belongs
|
* edge mask and returns the claim group to which that feature belongs
|
||||||
@@ -122,9 +145,9 @@ public class VenisonTile
|
|||||||
* supplied mask belongs, or zero if no feature matched the supplied
|
* supplied mask belongs, or zero if no feature matched the supplied
|
||||||
* mask.
|
* mask.
|
||||||
*/
|
*/
|
||||||
public int getFeatureGroup (int featureMask)
|
public int getFeatureGroup (int edgeMask)
|
||||||
{
|
{
|
||||||
int fidx = getFeatureIndex(featureMask);
|
int fidx = getFeatureIndex(edgeMask);
|
||||||
return fidx < 0 ? 0 : claims[fidx];
|
return fidx < 0 ? 0 : claims[fidx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,11 +161,67 @@ public class VenisonTile
|
|||||||
*/
|
*/
|
||||||
public void setFeatureGroup (int featureIndex, int claimGroup)
|
public void setFeatureGroup (int featureIndex, int claimGroup)
|
||||||
{
|
{
|
||||||
Log.info("Setting feature group [tile=" + this +
|
// Log.info("Setting feature group [tile=" + this +
|
||||||
", fidx=" + featureIndex + ", cgroup=" + claimGroup + "].");
|
// ", fidx=" + featureIndex + ", cgroup=" + claimGroup + "].");
|
||||||
|
|
||||||
|
// update the claim group slot for this feature
|
||||||
claims[featureIndex] = claimGroup;
|
claims[featureIndex] = claimGroup;
|
||||||
|
|
||||||
// TBD: update the piecen
|
// if we have a piecen placed on the feature identified by this
|
||||||
|
// feature index, we need to update its claim group as well
|
||||||
|
if (piecen != null && piecen.featureIndex == featureIndex) {
|
||||||
|
piecen.claimGroup = claimGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places the specified piecen on this tile. The {@link
|
||||||
|
* Piecen#featureIndex} field is assumed to be initialized to the
|
||||||
|
* feature index of this tile on which the piecen is to be placed.
|
||||||
|
*
|
||||||
|
* <p> Note that this will call {@link TileUtil#setFeatureGroup} to
|
||||||
|
* propagate the claiming of this feature to all neighboring tiles if
|
||||||
|
* a non-null tiles array is supplied to the function.
|
||||||
|
*
|
||||||
|
* @param piecen the piecen to place on this tile (with an
|
||||||
|
* appropriately configured feature index).
|
||||||
|
* @param tiles a sorted list of all of the tiles on the board that
|
||||||
|
* we can use to propagate our new claim group to all features
|
||||||
|
* connected to this newly claimed feature or null if propagation of
|
||||||
|
* the claim group is not desired at this time.
|
||||||
|
*/
|
||||||
|
public void setPiecen (Piecen piecen, List tiles)
|
||||||
|
{
|
||||||
|
// are we sure about that?
|
||||||
|
if (claims[piecen.featureIndex] != 0) {
|
||||||
|
Log.warning("Aiya! Requested to add a piecen to a feature " +
|
||||||
|
"that has already been claimed [tile=" + this +
|
||||||
|
", piecen=" + piecen + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep a reference to this piecen and configure its position
|
||||||
|
this.piecen = piecen;
|
||||||
|
piecen.x = x;
|
||||||
|
piecen.y = y;
|
||||||
|
|
||||||
|
// assign a brand spanking new claim group to the feature and the
|
||||||
|
// piecen and propagate it to neighboring features
|
||||||
|
if (tiles != null) {
|
||||||
|
int claimGroup = TileUtil.nextClaimGroup();
|
||||||
|
Log.info("Creating claim group [cgroup=" + claimGroup +
|
||||||
|
", tile=" + this + ", fidx=" + piecen.featureIndex + "].");
|
||||||
|
TileUtil.setFeatureGroup(
|
||||||
|
tiles, this, piecen.featureIndex, claimGroup, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears out any piecen reference that was previously set (does not
|
||||||
|
* clear out its associated claim group, however).
|
||||||
|
*/
|
||||||
|
public void clearPiecen ()
|
||||||
|
{
|
||||||
|
piecen = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,11 +239,6 @@ public class VenisonTile
|
|||||||
{
|
{
|
||||||
int tidx = type-1;
|
int tidx = type-1;
|
||||||
|
|
||||||
// create our shapes if we haven't already
|
|
||||||
if (_shapes[tidx][orientation] == null) {
|
|
||||||
createShapes();
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute our screen coordinates
|
// compute our screen coordinates
|
||||||
int sx = (x + xoff) * TILE_WIDTH;
|
int sx = (x + xoff) * TILE_WIDTH;
|
||||||
int sy = (y + yoff) * TILE_HEIGHT;
|
int sy = (y + yoff) * TILE_HEIGHT;
|
||||||
@@ -172,16 +246,16 @@ public class VenisonTile
|
|||||||
// translate to our screen coordinates
|
// translate to our screen coordinates
|
||||||
g.translate(sx, sy);
|
g.translate(sx, sy);
|
||||||
|
|
||||||
// draw our shapes using the proper orientation
|
// render our features and piecen
|
||||||
GeneralPath[] paths = _shapes[tidx][orientation];
|
for (int i = 0; i < features.length; i++) {
|
||||||
IntTuple[] types = _types[tidx];
|
// paint the feature
|
||||||
for (int i = 0; i < paths.length; i++) {
|
features[i].paint(g, orientation, claims[i]);
|
||||||
if (claims[types[i].right] != 0) {
|
|
||||||
g.setColor(CLAIMED_COLOR_MAP[types[i].left]);
|
// if we have a piecen on this tile, render it as well
|
||||||
} else {
|
if (piecen != null && piecen.featureIndex == i) {
|
||||||
g.setColor(COLOR_MAP[types[i].left]);
|
features[i].paintPiecen(
|
||||||
|
g, orientation, piecen.color, piecen.claimGroup);
|
||||||
}
|
}
|
||||||
g.fill(paths[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw a rectangular outline
|
// draw a rectangular outline
|
||||||
@@ -205,9 +279,12 @@ public class VenisonTile
|
|||||||
*/
|
*/
|
||||||
public int compareTo (Object other)
|
public int compareTo (Object other)
|
||||||
{
|
{
|
||||||
// we will either be compared to another tile or to a coordinate
|
// we will either be compared to another tile, to a piecen or to a
|
||||||
// object
|
// coordinate object (int tuple)
|
||||||
if (other instanceof VenisonTile) {
|
if (other == null) {
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
} else if (other instanceof VenisonTile) {
|
||||||
VenisonTile tile = (VenisonTile)other;
|
VenisonTile tile = (VenisonTile)other;
|
||||||
return (tile.x == x) ? y - tile.y : x - tile.x;
|
return (tile.x == x) ? y - tile.y : x - tile.x;
|
||||||
|
|
||||||
@@ -215,12 +292,22 @@ public class VenisonTile
|
|||||||
IntTuple coord = (IntTuple)other;
|
IntTuple coord = (IntTuple)other;
|
||||||
return (coord.left == x) ? y - coord.right : x - coord.left;
|
return (coord.left == x) ? y - coord.right : x - coord.left;
|
||||||
|
|
||||||
|
} else if (other instanceof Piecen) {
|
||||||
|
Piecen piecen = (Piecen)other;
|
||||||
|
return (piecen.x == x) ? y - piecen.y : x - piecen.x;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// who knows...
|
// who knows...
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
return (compareTo(other) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
public Object getKey ()
|
public Object getKey ()
|
||||||
{
|
{
|
||||||
@@ -258,10 +345,10 @@ public class VenisonTile
|
|||||||
{
|
{
|
||||||
if (type > 0) {
|
if (type > 0) {
|
||||||
// grab a reference to our feature information
|
// grab a reference to our feature information
|
||||||
features = TileUtil.TILE_FEATURES[type-1];
|
features = FeatureUtil.getTileFeatures(type);
|
||||||
|
|
||||||
// create our claims array
|
// create our claims array
|
||||||
claims = new int[features.length/2];
|
claims = new int[features.length];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.warning("Requested to init features without valid type " +
|
Log.warning("Requested to init features without valid type " +
|
||||||
@@ -270,88 +357,6 @@ public class VenisonTile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the path objects that describe the shapes that make up this
|
|
||||||
* tile and sticks it into the appropriate slot in the shapes array.
|
|
||||||
*/
|
|
||||||
protected void createShapes ()
|
|
||||||
{
|
|
||||||
int tidx = type-1;
|
|
||||||
ArrayList polys = new ArrayList();
|
|
||||||
ArrayList types = new ArrayList();
|
|
||||||
|
|
||||||
// the first feature is the background color
|
|
||||||
Object[] features = (Object[])TileUtil.TILE_FEATURE_GEOMS[tidx];
|
|
||||||
IntTuple base = (IntTuple)features[0];
|
|
||||||
|
|
||||||
// add a polygon containing the whole tile
|
|
||||||
types.add(base);
|
|
||||||
Polygon poly = new Polygon();
|
|
||||||
poly.addPoint(0, 0);
|
|
||||||
poly.addPoint(TILE_WIDTH, 0);
|
|
||||||
poly.addPoint(TILE_WIDTH, TILE_HEIGHT);
|
|
||||||
poly.addPoint(0, TILE_HEIGHT);
|
|
||||||
polys.add(poly);
|
|
||||||
|
|
||||||
// the remainder are tuple/coordinate pairs
|
|
||||||
for (int f = 1; f < features.length; f += 2) {
|
|
||||||
IntTuple ftype = (IntTuple)features[f];
|
|
||||||
int[] coords = (int[])features[f+1];
|
|
||||||
|
|
||||||
// keep track of this shape's type
|
|
||||||
types.add(ftype);
|
|
||||||
|
|
||||||
// if this is a road segment, we need to create a special
|
|
||||||
// polygon
|
|
||||||
if (ftype.left == ROAD) {
|
|
||||||
poly = TileUtil.roadSegmentToPolygon(
|
|
||||||
coords[0], coords[1], coords[2], coords[3]);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// otherwise create the polygon directly from the coords
|
|
||||||
poly = new Polygon();
|
|
||||||
for (int c = 0; c < coords.length; c += 2) {
|
|
||||||
// scale the coords accordingly
|
|
||||||
int fx = (coords[c] * TILE_WIDTH) / 4;
|
|
||||||
int fy = (coords[c+1] * TILE_HEIGHT) / 4;
|
|
||||||
poly.addPoint(fx, fy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
polys.add(poly);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now create general paths from our polygons and convert
|
|
||||||
// everything into the appropriate arrays
|
|
||||||
GeneralPath[] paths = new GeneralPath[polys.size()];
|
|
||||||
for (int i = 0; i < polys.size(); i++) {
|
|
||||||
GeneralPath path = new GeneralPath();
|
|
||||||
path.append(((Polygon)polys.get(i)).getPathIterator(null), false);
|
|
||||||
path.closePath();
|
|
||||||
paths[i] = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep the first one around
|
|
||||||
_shapes[tidx][NORTH] = paths;
|
|
||||||
|
|
||||||
// and rotate it three times to get the other orientations
|
|
||||||
AffineTransform xform = new AffineTransform();
|
|
||||||
for (int o = 1; o < 4; o++) {
|
|
||||||
xform.translate(TILE_WIDTH, 0);
|
|
||||||
xform.rotate(Math.PI/2);
|
|
||||||
GeneralPath[] rpaths = new GeneralPath[paths.length];
|
|
||||||
for (int i = 0; i < paths.length; i++) {
|
|
||||||
rpaths[i] = (GeneralPath)paths[i].clone();
|
|
||||||
rpaths[i].transform(xform);
|
|
||||||
}
|
|
||||||
_shapes[tidx][o] = rpaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
// also fill in the feature type info
|
|
||||||
_types[tidx] = new IntTuple[types.size()];
|
|
||||||
types.toArray(_types[tidx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a string representation of this tile instance.
|
* Generates a string representation of this tile instance.
|
||||||
*/
|
*/
|
||||||
@@ -359,30 +364,8 @@ public class VenisonTile
|
|||||||
{
|
{
|
||||||
return "[type=" + type + ", shield=" + hasShield +
|
return "[type=" + type + ", shield=" + hasShield +
|
||||||
", orient=" + ORIENT_NAMES[orientation] +
|
", orient=" + ORIENT_NAMES[orientation] +
|
||||||
", pos=" + x + "/" + y + "]";
|
", pos=" + x + "/" + y +
|
||||||
|
", claims=" + StringUtil.toString(claims) +
|
||||||
|
", piecen=" + piecen + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Path objects that describe closed shapes which be used to render
|
|
||||||
* the tiles (one for each orientation of each tile type). */
|
|
||||||
protected static GeneralPath[][][] _shapes =
|
|
||||||
new GeneralPath[TILE_TYPES][4][];
|
|
||||||
|
|
||||||
/** The feature type of each shape in shapes array. */
|
|
||||||
protected static IntTuple[][] _types = new IntTuple[TILE_TYPES][];
|
|
||||||
|
|
||||||
/** Maps feature types to colors. */
|
|
||||||
protected static Color[] COLOR_MAP = {
|
|
||||||
Color.red, // CITY
|
|
||||||
Color.green, // GRASS
|
|
||||||
Color.black, // ROAD
|
|
||||||
Color.yellow // CLOISTER
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Maps feature types to colors for claimed features. */
|
|
||||||
protected static Color[] CLAIMED_COLOR_MAP = {
|
|
||||||
Color.red.darker(), // CITY
|
|
||||||
Color.green.darker(), // GRASS
|
|
||||||
Color.black.brighter(), // ROAD
|
|
||||||
Color.yellow.darker(), // CLOISTER
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,366 @@
|
|||||||
|
//
|
||||||
|
// $Id: Feature.java,v 1.1 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.venison;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Shape;
|
||||||
|
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.GeneralPath;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents all of the necessary information for a particular feature of
|
||||||
|
* a particular tile.
|
||||||
|
*/
|
||||||
|
public class Feature
|
||||||
|
implements TileCodes
|
||||||
|
{
|
||||||
|
/** The type of this feature. */
|
||||||
|
public int type;
|
||||||
|
|
||||||
|
/** The edge mask associated with this feature. */
|
||||||
|
public int edgeMask;
|
||||||
|
|
||||||
|
/** The location at which a piecen on this feature would be drawn (for
|
||||||
|
* each of the four tile orientations. */
|
||||||
|
public Point2D[] piecenSpots = new Point2D[4];
|
||||||
|
|
||||||
|
/** The polygons used to render and hit test this feature (one for
|
||||||
|
* each orientation). */
|
||||||
|
public GeneralPath[] polys = new GeneralPath[4];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a feature with a feature description array containing
|
||||||
|
* all of the necessary feature information.
|
||||||
|
*/
|
||||||
|
public Feature (int[] desc)
|
||||||
|
{
|
||||||
|
type = desc[0];
|
||||||
|
edgeMask = desc[1];
|
||||||
|
|
||||||
|
// fetch our natural piecen spot, scale it and adjust for half units
|
||||||
|
int px = (desc[2] * TILE_WIDTH) / 4;
|
||||||
|
if (px < 0) {
|
||||||
|
px *= -1;
|
||||||
|
px -= TILE_WIDTH/8;
|
||||||
|
}
|
||||||
|
int py = (desc[3] * TILE_HEIGHT) / 4;
|
||||||
|
if (py < 0) {
|
||||||
|
py *= -1;
|
||||||
|
py -= TILE_HEIGHT/8;
|
||||||
|
}
|
||||||
|
piecenSpots[NORTH] = new Point2D.Float(px, py);
|
||||||
|
|
||||||
|
// create our natural feature polygon
|
||||||
|
if (type == ROAD) {
|
||||||
|
// roads are handled specially; they are either one or two
|
||||||
|
// segment roads
|
||||||
|
if (desc.length == 8) {
|
||||||
|
polys[NORTH] = roadSegmentToPolygon(
|
||||||
|
desc[4], desc[5], desc[6], desc[7]);
|
||||||
|
|
||||||
|
} else if (desc.length == 10) {
|
||||||
|
polys[NORTH] = roadSegmentToPolygon(
|
||||||
|
desc[4], desc[5], desc[6], desc[7], desc[8], desc[9]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.warning("Feature constructed with bogus road geometry " +
|
||||||
|
"[desc=" + StringUtil.toString(desc) + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
GeneralPath poly = new GeneralPath();
|
||||||
|
for (int i = 4; i < desc.length; i += 2) {
|
||||||
|
// scale the coords accordingly
|
||||||
|
int fx = (desc[i] * TILE_WIDTH) / 4;
|
||||||
|
int fy = (desc[i+1] * TILE_HEIGHT) / 4;
|
||||||
|
if (i == 4) {
|
||||||
|
poly.moveTo(fx, fy);
|
||||||
|
} else {
|
||||||
|
poly.lineTo(fx, fy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poly.closePath();
|
||||||
|
polys[NORTH] = poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now create the three other orientations
|
||||||
|
AffineTransform xform = new AffineTransform();
|
||||||
|
for (int orient = 1; orient < 4; orient++) {
|
||||||
|
// rotate the xform into the next orientation
|
||||||
|
xform.translate(TILE_WIDTH, 0);
|
||||||
|
xform.rotate(Math.PI/2);
|
||||||
|
|
||||||
|
// transform the polygon
|
||||||
|
polys[orient] = (GeneralPath)polys[NORTH].clone();
|
||||||
|
polys[orient].transform(xform);
|
||||||
|
|
||||||
|
// transform the piecen spot
|
||||||
|
piecenSpots[orient] = new Point2D.Float();
|
||||||
|
xform.transform(piecenSpots[NORTH], piecenSpots[orient]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the feature contains the supplied mouse coordinates
|
||||||
|
* (which should be relative to the tile origin) given the supplied
|
||||||
|
* orientation information.
|
||||||
|
*/
|
||||||
|
public boolean contains (int mouseX, int mouseY, int orientation)
|
||||||
|
{
|
||||||
|
return polys[orientation].contains(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints this feature to the specified graphics context with the
|
||||||
|
* specified orientation, accounting for the supplied x and y offsets
|
||||||
|
* of the origin. The graphics context is assumed to be appropriately
|
||||||
|
* translated so that we may render this feature relative to the
|
||||||
|
* origin and have it painted in the proper place.
|
||||||
|
*
|
||||||
|
* @param g the graphics context to use when painting the feature.
|
||||||
|
* @param orientation the orientation at which to paint this feature.
|
||||||
|
* @param claimGroup the claim group to which this feature belongs (or
|
||||||
|
* zero if it belongs to no claim group).
|
||||||
|
*/
|
||||||
|
public void paint (Graphics2D g, int orientation, int claimGroup)
|
||||||
|
{
|
||||||
|
// set the color according to the claim group
|
||||||
|
g.setColor(claimGroup > 0 ? CLAIMED_COLOR_MAP[type] :
|
||||||
|
COLOR_MAP[type]);
|
||||||
|
|
||||||
|
// now render the appropriate polygon for this orientation
|
||||||
|
g.fill(polys[orientation]);
|
||||||
|
|
||||||
|
// // paint our features for debugging (they aren't rotated and thus
|
||||||
|
// // are only valid in the natural orientation)
|
||||||
|
// int w = TILE_WIDTH, hw = w/2, qw = hw/2, tqw = 3*qw;
|
||||||
|
// int h = TILE_HEIGHT, hh = h/2, qh = hh/2, tqh = 3*qh;
|
||||||
|
// g.setColor(Color.gray);
|
||||||
|
|
||||||
|
// if ((edgeMask & FeatureUtil.NORTH_F) != 0) {
|
||||||
|
// g.drawLine(hw, 0, hw, qh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.EAST_F) != 0) {
|
||||||
|
// g.drawLine(tqw, hh, w, hh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.SOUTH_F) != 0) {
|
||||||
|
// g.drawLine(hw, tqh, hw, h);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.WEST_F) != 0) {
|
||||||
|
// g.drawLine(0, hh, qw, hh);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ((edgeMask & FeatureUtil.NNE_F) != 0) {
|
||||||
|
// g.drawLine(tqw, 0, tqw, qh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.NNW_F) != 0) {
|
||||||
|
// g.drawLine(qw, 0, qw, qh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.SSE_F) != 0) {
|
||||||
|
// g.drawLine(tqw, tqh, tqw, h);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.SSW_F) != 0) {
|
||||||
|
// g.drawLine(qw, tqh, qw, h);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ((edgeMask & FeatureUtil.ENE_F) != 0) {
|
||||||
|
// g.drawLine(tqw, qh, w, qh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.ESE_F) != 0) {
|
||||||
|
// g.drawLine(tqw, tqh, w, tqh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.WNW_F) != 0) {
|
||||||
|
// g.drawLine(0, qh, qw, qh);
|
||||||
|
// }
|
||||||
|
// if ((edgeMask & FeatureUtil.WSW_F) != 0) {
|
||||||
|
// g.drawLine(0, tqh, qw, tqh);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints a piecen in a position indicating that it is placed on this
|
||||||
|
* feature. The graphics context is assumed to be appropriately
|
||||||
|
* translated so that we may render this feature relative to the
|
||||||
|
* origin and have it painted in the proper place.
|
||||||
|
*
|
||||||
|
* @param g the graphics context to use when painting the feature.
|
||||||
|
* @param orientation the orientation at which to paint this feature.
|
||||||
|
* @param color the piecen color to be painted.
|
||||||
|
* @param claimGroup the claim group to which this piecen belongs (or
|
||||||
|
* zero if it belongs to no claim group).
|
||||||
|
*/
|
||||||
|
public void paintPiecen (Graphics2D g, int orientation, int color,
|
||||||
|
int claimGroup)
|
||||||
|
{
|
||||||
|
// paint a colored circle around the proper piecen spot
|
||||||
|
Point2D point = piecenSpots[orientation];
|
||||||
|
double swidth = TILE_WIDTH/5;
|
||||||
|
double sheight = TILE_HEIGHT/5;
|
||||||
|
|
||||||
|
Shape spot = new RoundRectangle2D.Double(
|
||||||
|
point.getX()-swidth/2, point.getY()-sheight/2,
|
||||||
|
swidth, sheight, swidth/4, sheight/4);
|
||||||
|
g.setColor(PIECEN_COLOR_MAP[color]);
|
||||||
|
g.fill(spot);
|
||||||
|
|
||||||
|
// fucking ridiculous: draw()ing the same shape that was fill()ed
|
||||||
|
// doesn't generate the same shape. a draw()n shape is one pixel
|
||||||
|
// larger than a fill()ed shape (probably to account for some
|
||||||
|
// backwards compatible bad decision), so we have to create a
|
||||||
|
// whole new shape object to generate the outline. thanks sun
|
||||||
|
spot = new RoundRectangle2D.Double(
|
||||||
|
point.getX()-swidth/2, point.getY()-sheight/2,
|
||||||
|
swidth-1, sheight-1, swidth/4, sheight/4);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.draw(spot);
|
||||||
|
|
||||||
|
// for now, draw the claim group next to the piecen
|
||||||
|
g.drawString(Integer.toString(claimGroup),
|
||||||
|
(float)(point.getX() - swidth/2 + 2),
|
||||||
|
(float)(point.getY() - sheight/2 - 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Massages a road segment (specified in tile feature coordinates)
|
||||||
|
* into a polygon (in screen coordinates) that can be used to render
|
||||||
|
* or hit test the road. The coordinates must obey the following
|
||||||
|
* constraints: (x1 < x2 and y1 == y2) or (x1 == x2 and y1 < y2) or
|
||||||
|
* (x1 < x2 and y1 > y2).
|
||||||
|
*
|
||||||
|
* @return a polygon representing the road segment (with origin at 0,
|
||||||
|
* 0).
|
||||||
|
*/
|
||||||
|
protected static GeneralPath roadSegmentToPolygon (
|
||||||
|
int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
// first convert the coordinates into screen coordinates
|
||||||
|
x1 = (x1 * TILE_WIDTH) / 4;
|
||||||
|
y1 = (y1 * TILE_HEIGHT) / 4;
|
||||||
|
x2 = (x2 * TILE_WIDTH) / 4;
|
||||||
|
y2 = (y2 * TILE_HEIGHT) / 4;
|
||||||
|
|
||||||
|
GeneralPath poly = new GeneralPath();
|
||||||
|
int dx = 4, dy = 4;
|
||||||
|
|
||||||
|
// figure out what sort of line segment it is
|
||||||
|
if (x1 == x2) { // vertical
|
||||||
|
// make adjustments to ensure that we stay inside the tile
|
||||||
|
// bounds
|
||||||
|
if (y1 == 0) {
|
||||||
|
y1 += dy;
|
||||||
|
}
|
||||||
|
if (y2 == TILE_HEIGHT) {
|
||||||
|
y2 -= dy;
|
||||||
|
}
|
||||||
|
poly.moveTo(x1 - dx, y1 - dy);
|
||||||
|
poly.lineTo(x1 + dx, y1 - dy);
|
||||||
|
poly.lineTo(x2 + dx, y2 + dy);
|
||||||
|
poly.lineTo(x2 - dx, y2 + dy);
|
||||||
|
|
||||||
|
} else if (y1 == y2) { // horizontal
|
||||||
|
// make adjustments to ensure that we stay inside the tile
|
||||||
|
// bounds
|
||||||
|
if (x1 == 0) {
|
||||||
|
x1 += dx;
|
||||||
|
}
|
||||||
|
if (x2 == TILE_WIDTH) {
|
||||||
|
x2 -= dx;
|
||||||
|
}
|
||||||
|
poly.moveTo(x1 - dx, y1 - dy);
|
||||||
|
poly.lineTo(x1 - dx, y1 + dy);
|
||||||
|
poly.lineTo(x2 + dx, y2 + dy);
|
||||||
|
poly.lineTo(x2 + dx, y2 - dy);
|
||||||
|
|
||||||
|
} else { // diagonal
|
||||||
|
poly.moveTo(x1 - dx, y1);
|
||||||
|
poly.lineTo(x1 + dx, y1);
|
||||||
|
poly.lineTo(x2, y2 + dy);
|
||||||
|
poly.lineTo(x2, y2 - dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
poly.closePath();
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Massages a road segment (specified in tile feature coordinates)
|
||||||
|
* into a polygon (in screen coordinates) that can be used to render
|
||||||
|
* or hit test the road. The coordinates must obey the following
|
||||||
|
* constraints: (y1 == y2) and (y2 > y3) and (x2 == x3).
|
||||||
|
*
|
||||||
|
* @return a polygon representing the road segment (with origin at 0,
|
||||||
|
* 0).
|
||||||
|
*/
|
||||||
|
protected static GeneralPath roadSegmentToPolygon (
|
||||||
|
int x1, int y1, int x2, int y2, int x3, int y3)
|
||||||
|
{
|
||||||
|
// first convert the coordinates into screen coordinates
|
||||||
|
x1 = (x1 * TILE_WIDTH) / 4;
|
||||||
|
y1 = (y1 * TILE_HEIGHT) / 4;
|
||||||
|
x2 = (x2 * TILE_WIDTH) / 4;
|
||||||
|
y2 = (y2 * TILE_HEIGHT) / 4;
|
||||||
|
x3 = (x3 * TILE_WIDTH) / 4;
|
||||||
|
y3 = (y3 * TILE_HEIGHT) / 4;
|
||||||
|
|
||||||
|
GeneralPath poly = new GeneralPath();
|
||||||
|
int dx = 4, dy = 4;
|
||||||
|
|
||||||
|
// figure out what sort of road segment it is
|
||||||
|
if (x1 < x2) { // left turn
|
||||||
|
poly.moveTo(x1, y1-dy);
|
||||||
|
poly.lineTo(x2+dx, y2-dy);
|
||||||
|
poly.lineTo(x3+dx, y3);
|
||||||
|
poly.lineTo(x3-dx, y3);
|
||||||
|
poly.lineTo(x2-dx, y2+dy);
|
||||||
|
poly.lineTo(x1, y1+dy);
|
||||||
|
|
||||||
|
} else { // right turn
|
||||||
|
poly.moveTo(x1, y1-dy);
|
||||||
|
poly.lineTo(x2-dx, y2-dy);
|
||||||
|
poly.lineTo(x3-dx, y3);
|
||||||
|
poly.lineTo(x3+dx, y3);
|
||||||
|
poly.lineTo(x2+dx, y2+dy);
|
||||||
|
poly.lineTo(x1, y1+dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
poly.closePath();
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[type=" + type + ", edgeMask=" + edgeMask + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Maps feature types to colors. */
|
||||||
|
protected static Color[] COLOR_MAP = {
|
||||||
|
Color.red, // CITY
|
||||||
|
Color.green, // GRASS
|
||||||
|
Color.black, // ROAD
|
||||||
|
Color.yellow // CLOISTER
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Maps feature types to colors for claimed features. */
|
||||||
|
protected static Color[] CLAIMED_COLOR_MAP = {
|
||||||
|
Color.red.darker(), // CITY
|
||||||
|
Color.green.darker(), // GRASS
|
||||||
|
Color.darkGray, // ROAD
|
||||||
|
Color.yellow.darker(), // CLOISTER
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Maps piecen color codes to colors. */
|
||||||
|
protected static Color[] PIECEN_COLOR_MAP = {
|
||||||
|
Color.red, // RED
|
||||||
|
Color.darkGray, // BLACK
|
||||||
|
Color.blue, // BLUE
|
||||||
|
Color.yellow, // YELLOW
|
||||||
|
Color.green, // GREEN
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
//
|
||||||
|
// $Id: Piecen.java,v 1.1 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.venison;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A piecen is a person and a piece all rolled into one! Players can play
|
||||||
|
* a single piecen on a tile feature as a part of their turn and that
|
||||||
|
* piecen then claims that feature and all of the features that are
|
||||||
|
* connected to it forming a claim group. Once a group of features has
|
||||||
|
* been claimed, no further piecens can be placed on the group. Note,
|
||||||
|
* however, that two or more separately claimed feature groups can be
|
||||||
|
* joined by placing a tile that connects the previously disconnected
|
||||||
|
* groups together. In that case, the groups are merged into a single
|
||||||
|
* claim group and all the piecens that were part of the disparate groups
|
||||||
|
* become claimees in the new group. At scoring time, the player with the
|
||||||
|
* most piecens in a group gets the points for the group. If two or more
|
||||||
|
* players have equal numbers of piecens in a group, they each get the
|
||||||
|
* points for the group.
|
||||||
|
*/
|
||||||
|
public class Piecen
|
||||||
|
implements DSet.Element
|
||||||
|
{
|
||||||
|
/** A color constant. */
|
||||||
|
public static final int RED = 0;
|
||||||
|
|
||||||
|
/** A color constant. */
|
||||||
|
public static final int BLACK = 1;
|
||||||
|
|
||||||
|
/** A color constant. */
|
||||||
|
public static final int BLUE = 2;
|
||||||
|
|
||||||
|
/** A color constant. */
|
||||||
|
public static final int YELLOW = 3;
|
||||||
|
|
||||||
|
/** A color constant. */
|
||||||
|
public static final int GREEN = 4;
|
||||||
|
|
||||||
|
/** The color of this piecen. */
|
||||||
|
public int color;
|
||||||
|
|
||||||
|
/** The x and y coordinates of the tile on which this piecen is
|
||||||
|
* placed. */
|
||||||
|
public int x, y;
|
||||||
|
|
||||||
|
/** The index in the tile's feature array of the feature on which this
|
||||||
|
* piecen is placed. */
|
||||||
|
public int featureIndex;
|
||||||
|
|
||||||
|
/** The claim group to which this piecen belongs. */
|
||||||
|
public int claimGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construts a piecen with the specified configuration.
|
||||||
|
*/
|
||||||
|
public Piecen (int color, int x, int y, int featureIndex)
|
||||||
|
{
|
||||||
|
this.color = color;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.featureIndex = featureIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a blank piecen, suitable for unserialization.
|
||||||
|
*/
|
||||||
|
public Piecen ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Object getKey ()
|
||||||
|
{
|
||||||
|
// our key is our coordinates conflated into one integer
|
||||||
|
return new Integer((x + 128) * 256 + y + 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void writeTo (DataOutputStream out)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
out.writeInt(color);
|
||||||
|
out.writeInt(x);
|
||||||
|
out.writeInt(y);
|
||||||
|
out.writeInt(featureIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void readFrom (DataInputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
color = in.readInt();
|
||||||
|
x = in.readInt();
|
||||||
|
y = in.readInt();
|
||||||
|
featureIndex = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
// we will either be compared to a tile or to a piecen
|
||||||
|
if (other == null) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (other instanceof VenisonTile) {
|
||||||
|
VenisonTile tile = (VenisonTile)other;
|
||||||
|
return (tile.x == x) ? (y == tile.y) : false;
|
||||||
|
|
||||||
|
} else if (other instanceof Piecen) {
|
||||||
|
Piecen piecen = (Piecen)other;
|
||||||
|
return (piecen.x == x) ? (y == piecen.y) : false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// who knows...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a string representation of this piecen.
|
||||||
|
*/
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[color=" + color + ", pos=" + x + "/" + y +
|
||||||
|
", fidx=" + featureIndex + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: TileCodes.java,v 1.4 2001/10/16 09:31:46 mdb Exp $
|
// $Id: TileCodes.java,v 1.5 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
@@ -32,11 +32,11 @@ public interface TileCodes
|
|||||||
|
|
||||||
/** A two-sided city tile with two separate city arcs adjacent to one
|
/** A two-sided city tile with two separate city arcs adjacent to one
|
||||||
* another and not connected to each other. */
|
* another and not connected to each other. */
|
||||||
public static final int DISCONNECTED_CITY_TWO = 7;
|
public static final int TWO_CITY_TWO = 7;
|
||||||
|
|
||||||
/** A two-sided city tile with two separate city arcs on opposite
|
/** A two-sided city tile with two separate city arcs on opposite
|
||||||
* sides of the tile. */
|
* sides of the tile. */
|
||||||
public static final int DISCONNECTED_CITY_TWO_ACROSS = 8;
|
public static final int TWO_CITY_TWO_ACROSS = 8;
|
||||||
|
|
||||||
/** A one-sided city tile. */
|
/** A one-sided city tile. */
|
||||||
public static final int CITY_ONE = 9;
|
public static final int CITY_ONE = 9;
|
||||||
@@ -118,41 +118,4 @@ public interface TileCodes
|
|||||||
|
|
||||||
/** A constant indicating a cloister. */
|
/** A constant indicating a cloister. */
|
||||||
public static final int CLOISTER = 3;
|
public static final int CLOISTER = 3;
|
||||||
|
|
||||||
|
|
||||||
/** Bit mask for a north connecting feature. */
|
|
||||||
public static final int NORTH_F = 0x1 << 0;
|
|
||||||
|
|
||||||
/** Bit mask for an east connecting feature. */
|
|
||||||
public static final int EAST_F = 0x1 << 1;
|
|
||||||
|
|
||||||
/** Bit mask for a south connecting feature. */
|
|
||||||
public static final int SOUTH_F = 0x1 << 2;
|
|
||||||
|
|
||||||
/** Bit mask for a west connecting feature. */
|
|
||||||
public static final int WEST_F = 0x1 << 3;
|
|
||||||
|
|
||||||
/** Bit mask for a north by northeast connecting feature. */
|
|
||||||
public static final int NNE_F = 0x1 << 4;
|
|
||||||
|
|
||||||
/** Bit mask for an east by northeast connecting feature. */
|
|
||||||
public static final int ENE_F = 0x1 << 5;
|
|
||||||
|
|
||||||
/** Bit mask for an east by southeast connecting feature. */
|
|
||||||
public static final int ESE_F = 0x1 << 6;
|
|
||||||
|
|
||||||
/** Bit mask for a south by southeast connecting feature. */
|
|
||||||
public static final int SSE_F = 0x1 << 7;
|
|
||||||
|
|
||||||
/** Bit mask for a south by southwest connecting feature. */
|
|
||||||
public static final int SSW_F = 0x1 << 8;
|
|
||||||
|
|
||||||
/** Bit mask for a west by southwest connecting feature. */
|
|
||||||
public static final int WSW_F = 0x1 << 9;
|
|
||||||
|
|
||||||
/** Bit mask for a west by northwest connecting feature. */
|
|
||||||
public static final int WNW_F = 0x1 << 10;
|
|
||||||
|
|
||||||
/** Bit mask for a north by northwest connecting feature. */
|
|
||||||
public static final int NNW_F = 0x1 << 11;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
//
|
//
|
||||||
// $Id: AtlantiManager.java,v 1.7 2001/10/16 09:31:46 mdb Exp $
|
// $Id: AtlantiManager.java,v 1.8 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -32,6 +33,8 @@ public class VenisonManager
|
|||||||
registerMessageHandler(PLACE_TILE_REQUEST, new PlaceTileHandler());
|
registerMessageHandler(PLACE_TILE_REQUEST, new PlaceTileHandler());
|
||||||
registerMessageHandler(
|
registerMessageHandler(
|
||||||
PLACE_PIECEN_REQUEST, new PlacePiecenHandler());
|
PLACE_PIECEN_REQUEST, new PlacePiecenHandler());
|
||||||
|
registerMessageHandler(
|
||||||
|
PLACE_NOTHING_REQUEST, new PlaceNothingHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -52,12 +55,19 @@ public class VenisonManager
|
|||||||
super.gameWillStart();
|
super.gameWillStart();
|
||||||
|
|
||||||
// generate a shuffled tile list
|
// generate a shuffled tile list
|
||||||
_tiles = TileUtil.getStandardTileSet();
|
_tilesInBox = TileUtil.getStandardTileSet();
|
||||||
Collections.shuffle(_tiles);
|
Collections.shuffle(_tilesInBox);
|
||||||
|
|
||||||
// clear out the tile set
|
// clear out our board tiles
|
||||||
|
_tiles.clear();
|
||||||
|
|
||||||
|
// clear out the tile and piecen set
|
||||||
_venobj.setTiles(new DSet(VenisonTile.class));
|
_venobj.setTiles(new DSet(VenisonTile.class));
|
||||||
|
_venobj.setPiecens(new DSet(Piecen.class));
|
||||||
|
|
||||||
|
// and add the starting tile
|
||||||
_venobj.addToTiles(VenisonTile.STARTING_TILE);
|
_venobj.addToTiles(VenisonTile.STARTING_TILE);
|
||||||
|
_tiles.add(VenisonTile.STARTING_TILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void turnWillStart ()
|
protected void turnWillStart ()
|
||||||
@@ -66,7 +76,7 @@ public class VenisonManager
|
|||||||
|
|
||||||
// let the players know what the next tile is that should be
|
// let the players know what the next tile is that should be
|
||||||
// played
|
// played
|
||||||
VenisonTile tile = (VenisonTile)_tiles.remove(0);
|
VenisonTile tile = (VenisonTile)_tilesInBox.remove(0);
|
||||||
_venobj.setCurrentTile(tile);
|
_venobj.setCurrentTile(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +85,7 @@ public class VenisonManager
|
|||||||
super.turnDidEnd();
|
super.turnDidEnd();
|
||||||
|
|
||||||
// if there are no tiles left, we end the game
|
// if there are no tiles left, we end the game
|
||||||
if (_tiles.size() == 0) {
|
if (_tilesInBox.size() == 0) {
|
||||||
endGame();
|
endGame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +96,7 @@ public class VenisonManager
|
|||||||
protected void setNextTurnHolder ()
|
protected void setNextTurnHolder ()
|
||||||
{
|
{
|
||||||
// if we have tiles left, we move to the next player as normal
|
// if we have tiles left, we move to the next player as normal
|
||||||
if (_tiles.size() > 0) {
|
if (_tilesInBox.size() > 0) {
|
||||||
super.setNextTurnHolder();
|
super.setNextTurnHolder();
|
||||||
} else {
|
} else {
|
||||||
// if we don't, we ensure that a new turn isn't started by
|
// if we don't, we ensure that a new turn isn't started by
|
||||||
@@ -103,16 +113,21 @@ public class VenisonManager
|
|||||||
VenisonTile tile = (VenisonTile)event.getArgs()[0];
|
VenisonTile tile = (VenisonTile)event.getArgs()[0];
|
||||||
|
|
||||||
// make sure this is a valid placement
|
// make sure this is a valid placement
|
||||||
if (TileUtil.isValidPlacement(_venobj.tiles.elements(), tile)) {
|
if (TileUtil.isValidPlacement(_tiles, tile)) {
|
||||||
|
// add the tile to the lsit
|
||||||
|
_tiles.add(tile);
|
||||||
|
|
||||||
|
// inherit its claim groups
|
||||||
|
TileUtil.inheritClaims(_tiles, tile);
|
||||||
|
|
||||||
|
Log.info("Placed tile " + tile + ".");
|
||||||
|
|
||||||
// add the tile to the tiles set
|
// add the tile to the tiles set
|
||||||
_venobj.addToTiles(tile);
|
_venobj.addToTiles(tile);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.warning("Received invalid placement " + event + ".");
|
Log.warning("Received invalid placement " + event + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// end the turn
|
|
||||||
endTurn();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +136,40 @@ public class VenisonManager
|
|||||||
{
|
{
|
||||||
public void handleEvent (MessageEvent event)
|
public void handleEvent (MessageEvent event)
|
||||||
{
|
{
|
||||||
|
Piecen piecen = (Piecen)event.getArgs()[0];
|
||||||
|
|
||||||
|
// make sure this is a valid placement
|
||||||
|
VenisonTile tile = (VenisonTile)_venobj.tiles.get(piecen.getKey());
|
||||||
|
if (tile == null) {
|
||||||
|
Log.warning("Can't find tile for requested piecen " +
|
||||||
|
"placement " + piecen + ".");
|
||||||
|
|
||||||
|
} else if (tile.claims[piecen.featureIndex] != 0) {
|
||||||
|
Log.warning("Requested to place piecen on claimed feature " +
|
||||||
|
"[tile=" + tile + ", piecen=" + piecen + "].");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise stick the piece in the tile to update the
|
||||||
|
// claim groups
|
||||||
|
tile.setPiecen(piecen, _tiles);
|
||||||
|
|
||||||
|
// and add the piecen to the game object
|
||||||
|
_venobj.addToPiecens(piecen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end the turn
|
||||||
|
endTurn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles place nothing requests. */
|
||||||
|
protected class PlaceNothingHandler implements MessageHandler
|
||||||
|
{
|
||||||
|
public void handleEvent (MessageEvent event)
|
||||||
|
{
|
||||||
|
// player doesn't want to place anything, so we just end the
|
||||||
|
// turn
|
||||||
|
endTurn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,5 +178,8 @@ public class VenisonManager
|
|||||||
|
|
||||||
/** The (shuffled) list of tiles remaining to be played in this
|
/** The (shuffled) list of tiles remaining to be played in this
|
||||||
* game. */
|
* game. */
|
||||||
protected List _tiles;
|
protected List _tilesInBox;
|
||||||
|
|
||||||
|
/** A sorted list of the tiles that have been placed on the board. */
|
||||||
|
protected List _tiles = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
//
|
||||||
|
// $Id: FeatureUtil.java,v 1.1 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.venison;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feature related constants and utility functions.
|
||||||
|
*/
|
||||||
|
public class FeatureUtil implements TileCodes
|
||||||
|
{
|
||||||
|
/** Bit mask for a north connecting feature. */
|
||||||
|
public static final int NORTH_F = 0x1 << 0;
|
||||||
|
|
||||||
|
/** Bit mask for an east connecting feature. */
|
||||||
|
public static final int EAST_F = 0x1 << 1;
|
||||||
|
|
||||||
|
/** Bit mask for a south connecting feature. */
|
||||||
|
public static final int SOUTH_F = 0x1 << 2;
|
||||||
|
|
||||||
|
/** Bit mask for a west connecting feature. */
|
||||||
|
public static final int WEST_F = 0x1 << 3;
|
||||||
|
|
||||||
|
/** Bit mask for a north by northeast connecting feature. */
|
||||||
|
public static final int NNE_F = 0x1 << 4;
|
||||||
|
|
||||||
|
/** Bit mask for an east by northeast connecting feature. */
|
||||||
|
public static final int ENE_F = 0x1 << 5;
|
||||||
|
|
||||||
|
/** Bit mask for an east by southeast connecting feature. */
|
||||||
|
public static final int ESE_F = 0x1 << 6;
|
||||||
|
|
||||||
|
/** Bit mask for a south by southeast connecting feature. */
|
||||||
|
public static final int SSE_F = 0x1 << 7;
|
||||||
|
|
||||||
|
/** Bit mask for a south by southwest connecting feature. */
|
||||||
|
public static final int SSW_F = 0x1 << 8;
|
||||||
|
|
||||||
|
/** Bit mask for a west by southwest connecting feature. */
|
||||||
|
public static final int WSW_F = 0x1 << 9;
|
||||||
|
|
||||||
|
/** Bit mask for a west by northwest connecting feature. */
|
||||||
|
public static final int WNW_F = 0x1 << 10;
|
||||||
|
|
||||||
|
/** Bit mask for a north by northwest connecting feature. */
|
||||||
|
public static final int NNW_F = 0x1 << 11;
|
||||||
|
|
||||||
|
/** A mapping from feature edge masks to tile directions and
|
||||||
|
* corresponding feature edge masks. */
|
||||||
|
public static final int[] ADJACENCY_MAP = new int[] {
|
||||||
|
NORTH_F, NORTH, SOUTH_F,
|
||||||
|
EAST_F, EAST, WEST_F,
|
||||||
|
SOUTH_F, SOUTH, NORTH_F,
|
||||||
|
WEST_F, WEST, EAST_F,
|
||||||
|
NNW_F, NORTH, SSW_F,
|
||||||
|
NNE_F, NORTH, SSE_F,
|
||||||
|
ENE_F, EAST, WNW_F,
|
||||||
|
ESE_F, EAST, WSW_F,
|
||||||
|
SSE_F, SOUTH, NNE_F,
|
||||||
|
SSW_F, SOUTH, NNW_F,
|
||||||
|
WSW_F, WEST, ESE_F,
|
||||||
|
WNW_F, WEST, ENE_F,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the feature array for the tile of the specified type.
|
||||||
|
*/
|
||||||
|
public static Feature[] getTileFeatures (int type)
|
||||||
|
{
|
||||||
|
// create the features array
|
||||||
|
Feature[] features = new Feature[TILE_FEATURES[type-1].length];
|
||||||
|
|
||||||
|
// initialize it with features from the repeated feature table or
|
||||||
|
// with newly constructed features
|
||||||
|
for (int i = 0; i < features.length; i++) {
|
||||||
|
int[] desc = TILE_FEATURES[type-1][i];
|
||||||
|
// if the description is a length one array, it is the index
|
||||||
|
// into the reused feature table of the desired feature
|
||||||
|
if (desc.length == 1) {
|
||||||
|
features[i] = _reusedFeatures[desc[0]];
|
||||||
|
} else {
|
||||||
|
// otherwise it is the description of this unique feature
|
||||||
|
features[i] = new Feature(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates the feature edge mask into the orientation specified.
|
||||||
|
* For a forward translation, provide a positive valued orientation
|
||||||
|
* constant. For a backward translation, provide a negative valued
|
||||||
|
* orientation constant.
|
||||||
|
*
|
||||||
|
* @return the translated feature mask.
|
||||||
|
*/
|
||||||
|
public static int translateMask (int featureMask, int orientation)
|
||||||
|
{
|
||||||
|
int[] map = FEATURE_ORIENT_MAP[0];
|
||||||
|
if ((featureMask & (NNE_F|ESE_F|SSW_F|WNW_F)) != 0) {
|
||||||
|
map = FEATURE_ORIENT_MAP[1];
|
||||||
|
} else if ((featureMask & (ENE_F|SSE_F|WSW_F|NNW_F)) != 0) {
|
||||||
|
map = FEATURE_ORIENT_MAP[2];
|
||||||
|
}
|
||||||
|
return xlateMask(map, featureMask, orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@link #translateMask} helper function. */
|
||||||
|
protected static int xlateMask (
|
||||||
|
int[] map, int featureMask, int orientation)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < map.length; i++) {
|
||||||
|
if (map[i] == featureMask) {
|
||||||
|
return map[(i + 4 + orientation) % 4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return featureMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int NESW_CITY = 0;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int NEW_CITY = 1;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int EW_CITY = 2;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int NW_CITY = 3;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int N_CITY = 4;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int E_CITY = 5;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int W_CITY = 6;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int E_ROAD = 7;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int S_ROAD = 8;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int W_ROAD = 9;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int S_GRASS = 10;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int SE_GRASS = 11;
|
||||||
|
|
||||||
|
/** A reused feature identifier. */
|
||||||
|
protected static final int SW_GRASS = 12;
|
||||||
|
|
||||||
|
/** An array of features used more than once. */
|
||||||
|
protected static final int[][] FEATURES = new int[][] {
|
||||||
|
{ CITY, NORTH_F|EAST_F|SOUTH_F|WEST_F, // NESW_CITY
|
||||||
|
2,2, 0,0, 4,0, 4,4, 0,4 },
|
||||||
|
{ CITY, NORTH_F|EAST_F|WEST_F, // NEW_CITY
|
||||||
|
2,2, 0,0, 4,0, 4,4, 3,3, 1,3, 0,4 },
|
||||||
|
{ CITY, EAST_F|WEST_F, // EW_CITY
|
||||||
|
2,2, 0,0, 1,1, 3,1, 4,0, 4,4, 3,3, 1,3, 0,4 },
|
||||||
|
{ CITY, NORTH_F|WEST_F, // NW_CITY
|
||||||
|
1,1, 0,0, 4,0, 0,4 },
|
||||||
|
{ CITY, NORTH_F, // N_CITY
|
||||||
|
2,-1, 0,0, 1,1, 3,1, 4,0 },
|
||||||
|
{ CITY, EAST_F, // E_CITY
|
||||||
|
-4,2, 4,0, 3,1, 3,3, 4,4 },
|
||||||
|
{ CITY, WEST_F, // W_CITY
|
||||||
|
-1,2, 0,0, 1,1, 1,3, 0,4 },
|
||||||
|
{ ROAD, EAST_F, // E_ROAD
|
||||||
|
3,2, 2,2, 4,2 },
|
||||||
|
{ ROAD, SOUTH_F, // S_ROAD
|
||||||
|
2,3, 2,2, 2,4 },
|
||||||
|
{ ROAD, WEST_F, // W_ROAD
|
||||||
|
1,2, 0,2, 2,2 },
|
||||||
|
{ GRASS, SOUTH_F, // S_GRASS
|
||||||
|
2,-4, 0,4, 1,3, 3,3, 4,4 },
|
||||||
|
{ GRASS, ESE_F|SSE_F, // SE_GRASS
|
||||||
|
3,3, 2,2, 4,2, 4,4, 2,4 },
|
||||||
|
{ GRASS, WSW_F|SSW_F, // SW_GRASS
|
||||||
|
1,3, 0,2, 2,2, 2,4, 0,4 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A table describing the features of each tile. */
|
||||||
|
protected static final int[][][] TILE_FEATURES = new int[][][] {
|
||||||
|
// one must offset tile type by one when indexing into this array
|
||||||
|
|
||||||
|
{ { NESW_CITY } }, // CITY_FOUR
|
||||||
|
|
||||||
|
{ { NEW_CITY }, // CITY_THREE
|
||||||
|
{ S_GRASS } },
|
||||||
|
|
||||||
|
{ { NEW_CITY }, // CITY_THREE_ROAD
|
||||||
|
{ GRASS, SSW_F, -2,-4, 0,4, 1,3, 2,3, 2,4 },
|
||||||
|
{ GRASS, SSE_F, -3,-4, 2,4, 2,3, 3,3, 4,4 },
|
||||||
|
{ ROAD, SOUTH_F, 2,-4, 2,3, 2,4 } },
|
||||||
|
|
||||||
|
{ { NW_CITY }, // CITY_TWO
|
||||||
|
{ GRASS, EAST_F|SOUTH_F, 3,3, 0,4, 4,0, 4,4 } },
|
||||||
|
|
||||||
|
{ { NW_CITY }, // CITY_TWO_ROAD
|
||||||
|
{ GRASS, ENE_F|SSW_F, -3,-3, 0,4, 4,0, 4,2, 2,4 },
|
||||||
|
{ GRASS, ESE_F|SSE_F, -4,-4, 2,4, 4,2, 4,4 },
|
||||||
|
{ ROAD, EAST_F|SOUTH_F, 3,3, 2,4, 4,2 } },
|
||||||
|
|
||||||
|
{ { EW_CITY }, // CITY_TWO_ACROSS
|
||||||
|
{ GRASS, NORTH_F, 2,-1, 0,0, 1,1, 3,1, 4,0 },
|
||||||
|
{ S_GRASS } },
|
||||||
|
|
||||||
|
{ { GRASS, WEST_F|SOUTH_F, // TWO_CITY_TWO
|
||||||
|
2,2, 0,0, 1,1, 3,1, 3,3, 4,4, 0,4 },
|
||||||
|
{ N_CITY },
|
||||||
|
{ E_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, NORTH_F|SOUTH_F, // TWO_CITY_TWO_ACROSS
|
||||||
|
2,2, 0,0, 4,0, 3,1, 3,3, 4,4, 0,4, 1,3, 1,1 },
|
||||||
|
{ W_CITY },
|
||||||
|
{ E_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, EAST_F|SOUTH_F|WEST_F, // CITY_ONE
|
||||||
|
2,2, 0,0, 1,1, 3,1, 4,0, 4,4, 0,4 },
|
||||||
|
{ N_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, ENE_F|SSW_F|WEST_F, // CITY_ONE_ROAD_RIGHT
|
||||||
|
1,2, 0,0, 1,1, 3,1, 4,0, 4,2, 2,2, 2,4, 0,4 },
|
||||||
|
{ SE_GRASS },
|
||||||
|
{ ROAD, EAST_F|SOUTH_F, 3,2, 4,2, 2,2, 2,4 },
|
||||||
|
{ N_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, EAST_F|SSE_F|WNW_F, // CITY_ONE_ROAD_LEFT
|
||||||
|
3,2, 0,0, 1,1, 3,1, 4,0, 4,4, 2,4, 2,2, 0,2 },
|
||||||
|
{ SW_GRASS },
|
||||||
|
{ ROAD, SOUTH_F|WEST_F, 1,2, 0,2, 2,2, 2,4 },
|
||||||
|
{ N_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, ENE_F|WNW_F, // CITY_ONE_ROAD_TEE
|
||||||
|
2,-2, 0,0, 1,1, 3,1, 4,0, 4,2, 0,2 },
|
||||||
|
{ SE_GRASS },
|
||||||
|
{ SW_GRASS },
|
||||||
|
{ E_ROAD },
|
||||||
|
{ S_ROAD },
|
||||||
|
{ W_ROAD },
|
||||||
|
{ N_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, ENE_F|WNW_F, // CITY_ONE_ROAD_STRAIGHT
|
||||||
|
2,-2, 0,0, 1,1, 3,1, 4,0, 4,2, 0,2 },
|
||||||
|
{ GRASS, ESE_F|SOUTH_F|WSW_F, 2,3, 0,2, 4,2, 4,4, 0,4 },
|
||||||
|
{ ROAD, EAST_F|WEST_F, 2,2, 0,2, 4,2 },
|
||||||
|
{ N_CITY } },
|
||||||
|
|
||||||
|
{ { GRASS, NORTH_F|EAST_F|SOUTH_F|WEST_F, // CLOISTER_PLAIN
|
||||||
|
1,1, 0,0, 4,0, 4,4, 0,4 },
|
||||||
|
{ CLOISTER, 0, 2,2, 1,1, 3,1, 3,3, 1,3 } },
|
||||||
|
|
||||||
|
{ { GRASS, NORTH_F|EAST_F|WEST_F|SSE_F|SSW_F, // CLOISTER_ROAD
|
||||||
|
1,1, 0,0, 4,0, 4,4, 0,4 },
|
||||||
|
{ CLOISTER, 0, 2,2, 1,1, 3,1, 3,3, 1,3 },
|
||||||
|
{ ROAD, SOUTH_F, 2,-4, 2,3, 2,4 } },
|
||||||
|
|
||||||
|
{ { GRASS, WNW_F|NNW_F, // FOUR_WAY_ROAD
|
||||||
|
1,1, 0,0, 2,0, 2,2, 0,2 },
|
||||||
|
{ GRASS, NNE_F|ENE_F, 3,1, 2,0, 4,0, 4,2, 2,2 },
|
||||||
|
{ SE_GRASS },
|
||||||
|
{ SW_GRASS },
|
||||||
|
{ ROAD, NORTH_F, 2,1, 2,0, 2,2 },
|
||||||
|
{ E_ROAD },
|
||||||
|
{ S_ROAD },
|
||||||
|
{ W_ROAD } },
|
||||||
|
|
||||||
|
{ { GRASS, WNW_F|NORTH_F|ENE_F, // THREE_WAY_ROAD
|
||||||
|
2,1, 0,0, 4,0, 4,2, 0,2 },
|
||||||
|
{ SE_GRASS },
|
||||||
|
{ SW_GRASS },
|
||||||
|
{ E_ROAD },
|
||||||
|
{ S_ROAD },
|
||||||
|
{ W_ROAD } },
|
||||||
|
|
||||||
|
{ { GRASS, NNW_F|WEST_F|SSW_F, // STRAIGHT_ROAD
|
||||||
|
1,2, 0,0, 2,0, 2,4, 0,4 },
|
||||||
|
{ GRASS, SSE_F|EAST_F|NNE_F, 3,2, 2,0, 4,0, 4,4, 2,4 },
|
||||||
|
{ ROAD, NORTH_F|SOUTH_F, 2,2, 2,0, 2,4 } },
|
||||||
|
|
||||||
|
{ { GRASS, WNW_F|NORTH_F|EAST_F|SSE_F, // CURVED_ROAD
|
||||||
|
3,1, 0,0, 4,0, 4,4, 2,4, 2,2, 0,2 },
|
||||||
|
{ SW_GRASS },
|
||||||
|
{ ROAD, SOUTH_F|WEST_F, 1,2, 0,2, 2,2, 2,4 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Mapping table used to rotate feature facements. */
|
||||||
|
protected static final int[][] FEATURE_ORIENT_MAP = new int[][] {
|
||||||
|
// orientations rotate through one of three four-cycles
|
||||||
|
{ NORTH_F, EAST_F, SOUTH_F, WEST_F },
|
||||||
|
{ NNE_F, ESE_F, SSW_F, WNW_F },
|
||||||
|
{ ENE_F, SSE_F, WSW_F, NNW_F },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A table of features that are used on more than one tile. */
|
||||||
|
protected static Feature[] _reusedFeatures;
|
||||||
|
|
||||||
|
// create our reused features table
|
||||||
|
static {
|
||||||
|
_reusedFeatures = new Feature[FEATURES.length];
|
||||||
|
for (int i = 0; i < FEATURES.length; i++) {
|
||||||
|
_reusedFeatures[i] = new Feature(FEATURES[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
//
|
//
|
||||||
// $Id: TileUtil.java,v 1.6 2001/10/16 17:11:07 mdb Exp $
|
// $Id: TileUtil.java,v 1.7 2001/10/17 02:19:54 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.venison;
|
package com.threerings.venison;
|
||||||
|
|
||||||
import java.awt.Polygon;
|
import java.awt.Polygon;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.samskivert.util.IntTuple;
|
import com.samskivert.util.IntTuple;
|
||||||
|
|
||||||
@@ -36,8 +36,7 @@ public class TileUtil implements TileCodes
|
|||||||
* position of the target tile is assumed to be the desired placement
|
* position of the target tile is assumed to be the desired placement
|
||||||
* position and the current orientation of the target tile is ignored.
|
* position and the current orientation of the target tile is ignored.
|
||||||
*
|
*
|
||||||
* @param tiles an iterator that will iterate over all of the tiles
|
* @param tiles a list of the tiles on the board.
|
||||||
* currently placed on the board.
|
|
||||||
* @param target the tile whose valid orientations we wish to compute.
|
* @param target the tile whose valid orientations we wish to compute.
|
||||||
*
|
*
|
||||||
* @return an array of boolean values indicating whether or not the
|
* @return an array of boolean values indicating whether or not the
|
||||||
@@ -45,14 +44,15 @@ public class TileUtil implements TileCodes
|
|||||||
* up with the direction constants specified in {@link TileCodes}.
|
* up with the direction constants specified in {@link TileCodes}.
|
||||||
*/
|
*/
|
||||||
public static boolean[] computeValidOrients (
|
public static boolean[] computeValidOrients (
|
||||||
Iterator tiles, VenisonTile target)
|
List tiles, VenisonTile target)
|
||||||
{
|
{
|
||||||
// this contains a count of tiles that match up with the candidate
|
// this contains a count of tiles that match up with the candidate
|
||||||
// tile in each of its four orientations
|
// tile in each of its four orientations
|
||||||
int[] matches = new int[4];
|
int[] matches = new int[4];
|
||||||
|
|
||||||
while (tiles.hasNext()) {
|
int tsize = tiles.size();
|
||||||
VenisonTile tile = (VenisonTile)tiles.next();
|
for (int i = 0; i < tsize; i++) {
|
||||||
|
VenisonTile tile = (VenisonTile)tiles.get(i);
|
||||||
|
|
||||||
// figure out where this tile is in relation to the candidate
|
// figure out where this tile is in relation to the candidate
|
||||||
int xdiff = tile.x - target.x;
|
int xdiff = tile.x - target.x;
|
||||||
@@ -75,14 +75,14 @@ public class TileUtil implements TileCodes
|
|||||||
|
|
||||||
// we iterate over the four possible orientations of the
|
// we iterate over the four possible orientations of the
|
||||||
// target tile
|
// target tile
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int o = 0; o < 4; o++) {
|
||||||
// we compare the edge of the placed tile (which never
|
// we compare the edge of the placed tile (which never
|
||||||
// changes) with the edge of the target tile which is
|
// changes) with the edge of the target tile which is
|
||||||
// adjusted based on the target tile's orientation
|
// adjusted based on the target tile's orientation
|
||||||
if (getEdge(tile.type, tileEdge) ==
|
if (getEdge(tile.type, tileEdge) ==
|
||||||
getEdge(target.type, (targetEdge+(4-i)) % 4)) {
|
getEdge(target.type, (targetEdge+(4-o)) % 4)) {
|
||||||
// increment the edge matches
|
// increment the edge matches
|
||||||
matches[i]++;
|
matches[o]++;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if we have a mismatch, we want to ensure that
|
// if we have a mismatch, we want to ensure that
|
||||||
@@ -91,7 +91,7 @@ public class TileUtil implements TileCodes
|
|||||||
// that it will remain less than zero regardless
|
// that it will remain less than zero regardless
|
||||||
// of which of the other three tiles match in this
|
// of which of the other three tiles match in this
|
||||||
// orientation
|
// orientation
|
||||||
matches[i] -= 10;
|
matches[o] -= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,20 +110,19 @@ public class TileUtil implements TileCodes
|
|||||||
* Returns true if the position and orientation of the target tile is
|
* Returns true if the position and orientation of the target tile is
|
||||||
* legal given the placement of all of the existing tiles.
|
* legal given the placement of all of the existing tiles.
|
||||||
*
|
*
|
||||||
* @param tiles an iterator that enumerates all of the tile already on
|
* @param tiles a list of the tiles already on the board.
|
||||||
* the board.
|
|
||||||
* @param target the tile whose validity we want to determine.
|
* @param target the tile whose validity we want to determine.
|
||||||
*
|
*
|
||||||
* @return true if the target tile is configured with a valid position
|
* @return true if the target tile is configured with a valid position
|
||||||
* and orientation, false if it is not.
|
* and orientation, false if it is not.
|
||||||
*/
|
*/
|
||||||
public static boolean isValidPlacement (
|
public static boolean isValidPlacement (List tiles, VenisonTile target)
|
||||||
Iterator tiles, VenisonTile target)
|
|
||||||
{
|
{
|
||||||
boolean matchedAnEdge = false;
|
boolean matchedAnEdge = false;
|
||||||
|
|
||||||
while (tiles.hasNext()) {
|
int tsize = tiles.size();
|
||||||
VenisonTile tile = (VenisonTile)tiles.next();
|
for (int i = 0; i < tsize; i++) {
|
||||||
|
VenisonTile tile = (VenisonTile)tiles.get(i);
|
||||||
|
|
||||||
// figure out where this tile is in relation to the candidate
|
// figure out where this tile is in relation to the candidate
|
||||||
int xdiff = tile.x - target.x;
|
int xdiff = tile.x - target.x;
|
||||||
@@ -184,11 +183,11 @@ public class TileUtil implements TileCodes
|
|||||||
* claims, those claims will be joined. The affected tiles and piecens
|
* claims, those claims will be joined. The affected tiles and piecens
|
||||||
* will have their claim groups updated.
|
* will have their claim groups updated.
|
||||||
*
|
*
|
||||||
* @param tiles a sorted array of the tiles on the board (which need
|
* @param tiles a sorted list of the tiles on the board (which need
|
||||||
* not include the tile whose features are being configured).
|
* not include the tile whose features are being configured).
|
||||||
* @param tile the tile whose features should be configured.
|
* @param tile the tile whose features should be configured.
|
||||||
*/
|
*/
|
||||||
public static void inheritClaims (VenisonTile[] tiles, VenisonTile tile)
|
public static void inheritClaims (List tiles, VenisonTile tile)
|
||||||
{
|
{
|
||||||
// obtain our neighboring tiles
|
// obtain our neighboring tiles
|
||||||
VenisonTile[] neighbors = new VenisonTile[4];
|
VenisonTile[] neighbors = new VenisonTile[4];
|
||||||
@@ -199,16 +198,17 @@ public class TileUtil implements TileCodes
|
|||||||
|
|
||||||
// for each feature in the tile, determine whether or not the
|
// for each feature in the tile, determine whether or not the
|
||||||
// neighboring tile's matching feature is claimed
|
// neighboring tile's matching feature is claimed
|
||||||
for (int i = 0; i < tile.features.length; i += 2) {
|
for (int i = 0; i < tile.features.length; i ++) {
|
||||||
int ftype = tile.features[i];
|
int ftype = tile.features[i].type;
|
||||||
int fmask = tile.features[i+1];
|
int fmask = tile.features[i].edgeMask;
|
||||||
int cgroup = 0;
|
int cgroup = 0;
|
||||||
|
|
||||||
// iterate over all of the possible adjacency possibilities
|
// iterate over all of the possible adjacency possibilities,
|
||||||
for (int c = 0; c < ADJADCENCY_MAP.length; c += 3) {
|
// first looking for a claim group to inherit
|
||||||
int mask = ADJADCENCY_MAP[c];
|
for (int c = 0; c < FeatureUtil.ADJACENCY_MAP.length; c += 3) {
|
||||||
int dir = ADJADCENCY_MAP[c+1];
|
int mask = FeatureUtil.ADJACENCY_MAP[c];
|
||||||
int opp_mask = ADJADCENCY_MAP[c+2];
|
int dir = FeatureUtil.ADJACENCY_MAP[c+1];
|
||||||
|
int opp_mask = FeatureUtil.ADJACENCY_MAP[c+2];
|
||||||
|
|
||||||
// if this feature doesn't have this edge, skip it
|
// if this feature doesn't have this edge, skip it
|
||||||
if ((fmask & mask) == 0) {
|
if ((fmask & mask) == 0) {
|
||||||
@@ -226,34 +226,84 @@ public class TileUtil implements TileCodes
|
|||||||
|
|
||||||
// it looks like we have a match, so translate the target
|
// it looks like we have a match, so translate the target
|
||||||
// stuff into our orientation
|
// stuff into our orientation
|
||||||
mask = translateMask(mask, tile.orientation);
|
mask = FeatureUtil.translateMask(mask, tile.orientation);
|
||||||
opp_mask = translateMask(opp_mask, tile.orientation);
|
opp_mask = FeatureUtil.translateMask(
|
||||||
|
opp_mask, tile.orientation);
|
||||||
|
|
||||||
|
// inherit the group of the opposing feature
|
||||||
|
cgroup = neighbors[dir].getFeatureGroup(opp_mask);
|
||||||
|
|
||||||
|
// and bail as soon as we find a non-zero claim group
|
||||||
if (cgroup != 0) {
|
if (cgroup != 0) {
|
||||||
// if we've already been assigned to a group, we
|
Log.info("Inherited claim [tile=" + tile +
|
||||||
// propagate our group to the opposing feature
|
", fidx=" + i + ", cgroup=" + cgroup +
|
||||||
int fidx = neighbors[dir].getFeatureIndex(opp_mask);
|
", source=" + neighbors[dir] + "].");
|
||||||
if (fidx >= 0) {
|
break;
|
||||||
setFeatureGroup(tiles, neighbors[dir],
|
|
||||||
fidx, cgroup, mask);
|
|
||||||
} else {
|
|
||||||
Log.warning("Can't join-propagate feature " +
|
|
||||||
"[self=" + tile +
|
|
||||||
", target=" + neighbors[dir] +
|
|
||||||
", fidx=" + fidx + ", cgroup=" + cgroup +
|
|
||||||
", destEdge=" + opp_mask +
|
|
||||||
", srcEdge=" + mask + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// otherwise, we inherit the group of the opposing
|
|
||||||
// feature
|
|
||||||
cgroup = neighbors[dir].getFeatureGroup(opp_mask);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally initialize the feature's claim group
|
// if we didn't inherit a claim group, skip to the next
|
||||||
tile.claims[i/2] = cgroup;
|
// feature
|
||||||
|
if (cgroup == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the feature's claim group
|
||||||
|
tile.claims[i] = cgroup;
|
||||||
|
|
||||||
|
// otherwise, iterate over all of the possible adjacency
|
||||||
|
// possibilities, propagating our group to connected features
|
||||||
|
for (int c = 0; c < FeatureUtil.ADJACENCY_MAP.length; c += 3) {
|
||||||
|
int mask = FeatureUtil.ADJACENCY_MAP[c];
|
||||||
|
int dir = FeatureUtil.ADJACENCY_MAP[c+1];
|
||||||
|
int opp_mask = FeatureUtil.ADJACENCY_MAP[c+2];
|
||||||
|
|
||||||
|
// if this feature doesn't have this edge, skip it
|
||||||
|
if ((fmask & mask) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate the target direction accordingly
|
||||||
|
dir = (dir + tile.orientation) % 4;
|
||||||
|
|
||||||
|
// make sure we have a neighbor in the appropriate
|
||||||
|
// direction
|
||||||
|
if (neighbors[dir] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it looks like we have a match, so translate the target
|
||||||
|
// stuff into our orientation
|
||||||
|
mask = FeatureUtil.translateMask(mask, tile.orientation);
|
||||||
|
opp_mask = FeatureUtil.translateMask(
|
||||||
|
opp_mask, tile.orientation);
|
||||||
|
|
||||||
|
// make sure the neighbor in question isn't the one from
|
||||||
|
// which we inherited the group
|
||||||
|
int ogroup = neighbors[dir].getFeatureGroup(opp_mask);
|
||||||
|
if (ogroup == cgroup) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we've already been assigned to a group, we propagate
|
||||||
|
// our group to the opposing feature
|
||||||
|
int fidx = neighbors[dir].getFeatureIndex(opp_mask);
|
||||||
|
if (fidx >= 0) {
|
||||||
|
Log.info("Propagating group [fidx=" + i +
|
||||||
|
", cgroup=" + cgroup +
|
||||||
|
", dir=" + dir + "].");
|
||||||
|
setFeatureGroup(tiles, neighbors[dir],
|
||||||
|
fidx, cgroup, mask);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.warning("Can't join-propagate feature " +
|
||||||
|
"[self=" + tile +
|
||||||
|
", target=" + neighbors[dir] +
|
||||||
|
", fidx=" + fidx + ", cgroup=" + cgroup +
|
||||||
|
", destEdge=" + opp_mask +
|
||||||
|
", srcEdge=" + mask + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +311,7 @@ public class TileUtil implements TileCodes
|
|||||||
* Sets the claim group for the specified feature in this tile and
|
* Sets the claim group for the specified feature in this tile and
|
||||||
* propagates that claim group to all connected features.
|
* propagates that claim group to all connected features.
|
||||||
*
|
*
|
||||||
* @param tiles a sorted array of the tiles on the board.
|
* @param tiles a sorted list of the tiles on the board.
|
||||||
* @param tile the tile that contains the feature whose claim group is
|
* @param tile the tile that contains the feature whose claim group is
|
||||||
* being set.
|
* being set.
|
||||||
* @param featureIndex the index of the feature.
|
* @param featureIndex the index of the feature.
|
||||||
@@ -271,21 +321,21 @@ public class TileUtil implements TileCodes
|
|||||||
* propagating the group further).
|
* propagating the group further).
|
||||||
*/
|
*/
|
||||||
public static void setFeatureGroup (
|
public static void setFeatureGroup (
|
||||||
VenisonTile[] tiles, VenisonTile tile, int featureIndex,
|
List tiles, VenisonTile tile, int featureIndex,
|
||||||
int claimGroup, int entryEdgeMask)
|
int claimGroup, int entryEdgeMask)
|
||||||
{
|
{
|
||||||
// set the claim group for this feature on this tile
|
// set the claim group for this feature on this tile
|
||||||
tile.setFeatureGroup(featureIndex, claimGroup);
|
tile.setFeatureGroup(featureIndex, claimGroup);
|
||||||
|
|
||||||
// now propagate this feature to connected features
|
// now propagate this feature to connected features
|
||||||
int ftype = tile.features[featureIndex*2];
|
int ftype = tile.features[featureIndex].type;
|
||||||
int fmask = tile.features[featureIndex*2+1];
|
int fmask = tile.features[featureIndex].edgeMask;
|
||||||
|
|
||||||
// iterate over all of the possible adjacency possibilities
|
// iterate over all of the possible adjacency possibilities
|
||||||
for (int c = 0; c < ADJADCENCY_MAP.length; c += 3) {
|
for (int c = 0; c < FeatureUtil.ADJACENCY_MAP.length; c += 3) {
|
||||||
int mask = ADJADCENCY_MAP[c];
|
int mask = FeatureUtil.ADJACENCY_MAP[c];
|
||||||
int dir = ADJADCENCY_MAP[c+1];
|
int dir = FeatureUtil.ADJACENCY_MAP[c+1];
|
||||||
int opp_mask = ADJADCENCY_MAP[c+2];
|
int opp_mask = FeatureUtil.ADJACENCY_MAP[c+2];
|
||||||
VenisonTile neighbor = null;
|
VenisonTile neighbor = null;
|
||||||
|
|
||||||
// if this feature doesn't have this edge, skip it
|
// if this feature doesn't have this edge, skip it
|
||||||
@@ -295,7 +345,7 @@ public class TileUtil implements TileCodes
|
|||||||
|
|
||||||
// figure out if this would be the tile from which we
|
// figure out if this would be the tile from which we
|
||||||
// propagated into our current tile and skip it if so
|
// propagated into our current tile and skip it if so
|
||||||
opp_mask = translateMask(opp_mask, tile.orientation);
|
opp_mask = FeatureUtil.translateMask(opp_mask, tile.orientation);
|
||||||
if ((opp_mask & entryEdgeMask) != 0) {
|
if ((opp_mask & entryEdgeMask) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -314,12 +364,16 @@ public class TileUtil implements TileCodes
|
|||||||
|
|
||||||
// it looks like we have a match, so translate the target mask
|
// it looks like we have a match, so translate the target mask
|
||||||
// into our orientation
|
// into our orientation
|
||||||
mask = translateMask(mask, tile.orientation);
|
mask = FeatureUtil.translateMask(mask, tile.orientation);
|
||||||
|
|
||||||
// propagate, propagate, propagate
|
// propagate, propagate, propagate
|
||||||
int fidx = neighbor.getFeatureIndex(opp_mask);
|
int fidx = neighbor.getFeatureIndex(opp_mask);
|
||||||
if (fidx >= 0) {
|
if (fidx >= 0) {
|
||||||
setFeatureGroup(tiles, neighbor, fidx, claimGroup, mask);
|
// only set the feature in the neighbor if they aren't
|
||||||
|
// already set to the appropriate group (prevent loops)
|
||||||
|
if (neighbor.claims[fidx] != claimGroup) {
|
||||||
|
setFeatureGroup(tiles, neighbor, fidx, claimGroup, mask);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.warning("Can't propagate feature [self=" + tile +
|
Log.warning("Can't propagate feature [self=" + tile +
|
||||||
@@ -330,51 +384,19 @@ public class TileUtil implements TileCodes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the feature edge mask into the orientation specified.
|
|
||||||
* For a forward translation, provide a positive valued orientation
|
|
||||||
* constant. For a backward translation, provide a negative valued
|
|
||||||
* orientation constant.
|
|
||||||
*
|
|
||||||
* @return the translated feature mask.
|
|
||||||
*/
|
|
||||||
public static int translateMask (int featureMask, int orientation)
|
|
||||||
{
|
|
||||||
int[] map = FEATURE_ORIENT_MAP[0];
|
|
||||||
if ((featureMask & (NNE_F|ESE_F|SSW_F|WNW_F)) != 0) {
|
|
||||||
map = FEATURE_ORIENT_MAP[1];
|
|
||||||
} else if ((featureMask & (ENE_F|SSE_F|WSW_F|NNW_F)) != 0) {
|
|
||||||
map = FEATURE_ORIENT_MAP[2];
|
|
||||||
}
|
|
||||||
return xlateMask(map, featureMask, orientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@link #translateMask} helper function. */
|
|
||||||
protected static int xlateMask (
|
|
||||||
int[] map, int featureMask, int orientation)
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
for (int i = 0; i < map.length; i++) {
|
|
||||||
if (map[i] == featureMask) {
|
|
||||||
return map[(i + 4 + orientation) % 4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return featureMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates and returns the tile with the specified coordinates.
|
* Locates and returns the tile with the specified coordinates.
|
||||||
*
|
*
|
||||||
* @param tiles a sorted tiles array.
|
* @param tiles a sorted list of tiles.
|
||||||
*
|
*
|
||||||
* @return the tile with the requested coordinates or null if no tile
|
* @return the tile with the requested coordinates or null if no tile
|
||||||
* exists at those coordinates.
|
* exists at those coordinates.
|
||||||
*/
|
*/
|
||||||
protected static VenisonTile findTile (VenisonTile[] tiles, int x, int y)
|
protected static VenisonTile findTile (List tiles, int x, int y)
|
||||||
{
|
{
|
||||||
IntTuple coord = new IntTuple(x, y);
|
IntTuple coord = new IntTuple(x, y);
|
||||||
int tidx = Arrays.binarySearch(tiles, coord);
|
int tidx = Collections.binarySearch(tiles, coord);
|
||||||
return (tidx >= 0) ? tiles[tidx] : null;
|
return (tidx >= 0) ? (VenisonTile)tiles.get(tidx) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -393,64 +415,11 @@ public class TileUtil implements TileCodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Massages a road segment (specified in tile feature coordinates)
|
* Returns the next unused claim group value.
|
||||||
* into a polygon (in screen coordinates) that can be used to render
|
|
||||||
* or hit test the road. The coordinates must obey the following
|
|
||||||
* constraints: (x1 < x2 and y1 == y2) or (x1 == x2 and y1 < y2) or
|
|
||||||
* (x1 < x2 and y1 > y2).
|
|
||||||
*
|
|
||||||
* @return a polygon representing the road segment (with origin at 0,
|
|
||||||
* 0).
|
|
||||||
*/
|
*/
|
||||||
public static Polygon roadSegmentToPolygon (
|
public static int nextClaimGroup ()
|
||||||
int x1, int y1, int x2, int y2)
|
|
||||||
{
|
{
|
||||||
// first convert the coordinates into screen coordinates
|
return ++_claimGroupCounter;
|
||||||
x1 = (x1 * TILE_WIDTH) / 4;
|
|
||||||
y1 = (y1 * TILE_HEIGHT) / 4;
|
|
||||||
x2 = (x2 * TILE_WIDTH) / 4;
|
|
||||||
y2 = (y2 * TILE_HEIGHT) / 4;
|
|
||||||
|
|
||||||
Polygon poly = new Polygon();
|
|
||||||
int dx = 4, dy = 4;
|
|
||||||
|
|
||||||
// figure out what sort of line segment it is
|
|
||||||
if (x1 == x2) { // vertical
|
|
||||||
// make adjustments to ensure that we stay inside the tile
|
|
||||||
// bounds
|
|
||||||
if (y1 == 0) {
|
|
||||||
y1 += dy;
|
|
||||||
} else if (y2 == TILE_HEIGHT) {
|
|
||||||
y2 -= dy;
|
|
||||||
}
|
|
||||||
poly.addPoint(x1 - dx, y1 - dy);
|
|
||||||
poly.addPoint(x1 + dx, y1 - dy);
|
|
||||||
poly.addPoint(x2 + dx, y2 + dy);
|
|
||||||
poly.addPoint(x2 - dx, y2 + dy);
|
|
||||||
|
|
||||||
} else if (y1 == y2) { // horizontal
|
|
||||||
// make adjustments to ensure that we stay inside the tile
|
|
||||||
// bounds
|
|
||||||
if (x1 == 0) {
|
|
||||||
x1 += dx;
|
|
||||||
} else if (x2 == TILE_WIDTH) {
|
|
||||||
x2 -= dx;
|
|
||||||
}
|
|
||||||
poly.addPoint(x1 - dx, y1 - dy);
|
|
||||||
poly.addPoint(x1 - dx, y1 + dy);
|
|
||||||
poly.addPoint(x2 + dx, y2 + dy);
|
|
||||||
poly.addPoint(x2 + dx, y2 - dy);
|
|
||||||
|
|
||||||
} else { // diagonal
|
|
||||||
dx = 6; // widen these a bit so that the diagonal line appears
|
|
||||||
dy = 6; // to have the same weight as the straight ones
|
|
||||||
poly.addPoint(x1 - dx, y1);
|
|
||||||
poly.addPoint(x1 + dx, y1);
|
|
||||||
poly.addPoint(x2, y2 + dy);
|
|
||||||
poly.addPoint(x2, y2 - dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return poly;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to generate our standard tile set. */
|
/** Used to generate our standard tile set. */
|
||||||
@@ -462,6 +431,9 @@ public class TileUtil implements TileCodes
|
|||||||
list.add(tile);
|
list.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Used to generate claim group values. */
|
||||||
|
protected static int _claimGroupCounter;
|
||||||
|
|
||||||
/** Used to figure out which edges match up to which when comparing
|
/** Used to figure out which edges match up to which when comparing
|
||||||
* adjacent tiles. */
|
* adjacent tiles. */
|
||||||
protected static final int[] EDGE_MAP = new int[] {
|
protected static final int[] EDGE_MAP = new int[] {
|
||||||
@@ -470,31 +442,6 @@ public class TileUtil implements TileCodes
|
|||||||
-1, SOUTH, -1
|
-1, SOUTH, -1
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A mapping from feature edge masks to tile directions and
|
|
||||||
* corresponding feature edge masks. */
|
|
||||||
protected static final int[] ADJADCENCY_MAP = new int[] {
|
|
||||||
NORTH_F, NORTH, SOUTH_F,
|
|
||||||
EAST_F, EAST, WEST_F,
|
|
||||||
SOUTH_F, SOUTH, NORTH_F,
|
|
||||||
WEST_F, WEST, EAST_F,
|
|
||||||
NNW_F, NORTH, SSW_F,
|
|
||||||
NNE_F, NORTH, SSE_F,
|
|
||||||
ENE_F, EAST, WNW_F,
|
|
||||||
ESE_F, EAST, WSW_F,
|
|
||||||
SSE_F, SOUTH, NNE_F,
|
|
||||||
SSW_F, SOUTH, NNW_F,
|
|
||||||
WSW_F, WEST, ESE_F,
|
|
||||||
WNW_F, WEST, ENE_F,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Mapping table used to rotate feature facements. */
|
|
||||||
public static final int[][] FEATURE_ORIENT_MAP = new int[][] {
|
|
||||||
// orientations rotate through one of three four-cycles
|
|
||||||
{ NORTH_F, EAST_F, SOUTH_F, WEST_F },
|
|
||||||
{ NNE_F, ESE_F, SSW_F, WNW_F },
|
|
||||||
{ ENE_F, SSE_F, WSW_F, NNW_F },
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A table indicating which tiles have which edges. */
|
/** A table indicating which tiles have which edges. */
|
||||||
protected static final int[] TILE_EDGES = new int[] {
|
protected static final int[] TILE_EDGES = new int[] {
|
||||||
-1, -1, -1, -1, // null tile
|
-1, -1, -1, -1, // null tile
|
||||||
@@ -504,8 +451,8 @@ public class TileUtil implements TileCodes
|
|||||||
CITY, GRASS, GRASS, CITY, // CITY_TWO
|
CITY, GRASS, GRASS, CITY, // CITY_TWO
|
||||||
CITY, ROAD, ROAD, CITY, // CITY_TWO_ROAD
|
CITY, ROAD, ROAD, CITY, // CITY_TWO_ROAD
|
||||||
GRASS, CITY, GRASS, CITY, // CITY_TWO_ACROSS
|
GRASS, CITY, GRASS, CITY, // CITY_TWO_ACROSS
|
||||||
CITY, CITY, GRASS, GRASS, // DISCONNECTED_CITY_TWO
|
CITY, CITY, GRASS, GRASS, // TWO_CITY_TWO
|
||||||
GRASS, CITY, GRASS, CITY, // DISCONNECTED_CITY_TWO_ACROSS
|
GRASS, CITY, GRASS, CITY, // TWO_CITY_TWO_ACROSS
|
||||||
CITY, GRASS, GRASS, GRASS, // CITY_ONE
|
CITY, GRASS, GRASS, GRASS, // CITY_ONE
|
||||||
CITY, ROAD, ROAD, GRASS, // CITY_ONE_ROAD_RIGHT
|
CITY, ROAD, ROAD, GRASS, // CITY_ONE_ROAD_RIGHT
|
||||||
CITY, GRASS, ROAD, ROAD, // CITY_ONE_ROAD_LEFT
|
CITY, GRASS, ROAD, ROAD, // CITY_ONE_ROAD_LEFT
|
||||||
@@ -519,247 +466,6 @@ public class TileUtil implements TileCodes
|
|||||||
GRASS, GRASS, ROAD, ROAD, // CURVED_ROAD
|
GRASS, GRASS, ROAD, ROAD, // CURVED_ROAD
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A table describing the features of each tile and their edge
|
|
||||||
* connectedness. */
|
|
||||||
protected static final int[][] TILE_FEATURES = new int[][] {
|
|
||||||
// one must offset tile type by one when indexing into this array
|
|
||||||
|
|
||||||
{ CITY, NORTH_F|EAST_F|SOUTH_F|WEST_F }, // CITY_FOUR
|
|
||||||
|
|
||||||
{ CITY, NORTH_F|EAST_F|WEST_F, // CITY_THREE
|
|
||||||
GRASS, SOUTH_F },
|
|
||||||
|
|
||||||
{ CITY, NORTH_F|EAST_F|WEST_F, // CITY_THREE_ROAD
|
|
||||||
GRASS, SSW_F,
|
|
||||||
GRASS, SSE_F,
|
|
||||||
ROAD, SOUTH_F },
|
|
||||||
|
|
||||||
{ CITY, NORTH_F|WEST_F, // CITY_TWO
|
|
||||||
GRASS, EAST_F|SOUTH_F },
|
|
||||||
|
|
||||||
{ CITY, NORTH_F|WEST_F, // CITY_TWO_ROAD
|
|
||||||
GRASS, ENE_F|SSW_F,
|
|
||||||
GRASS, ESE_F|SSE_F,
|
|
||||||
ROAD, EAST_F|SOUTH_F },
|
|
||||||
|
|
||||||
{ CITY, WEST_F|EAST_F, // CITY_TWO_ACROSS
|
|
||||||
GRASS, NORTH_F,
|
|
||||||
GRASS, SOUTH_F },
|
|
||||||
|
|
||||||
{ GRASS, WEST_F|SOUTH_F, // DISCONNECTED_CITY_TWO
|
|
||||||
CITY, NORTH_F,
|
|
||||||
CITY, EAST_F },
|
|
||||||
|
|
||||||
{ GRASS, NORTH_F|SOUTH_F, // DISCONNECTED_CITY_TWO_ACROSS
|
|
||||||
CITY, WEST_F,
|
|
||||||
CITY, EAST_F },
|
|
||||||
|
|
||||||
{ GRASS, EAST_F|SOUTH_F|WEST_F, // CITY_ONE
|
|
||||||
CITY, NORTH_F },
|
|
||||||
|
|
||||||
{ GRASS, ENE_F|SSW_F|WEST_F, // CITY_ONE_ROAD_RIGHT
|
|
||||||
GRASS, ESE_F|SSE_F,
|
|
||||||
ROAD, EAST_F|SOUTH_F,
|
|
||||||
CITY, NORTH_F },
|
|
||||||
|
|
||||||
{ GRASS, EAST_F|SSE_F, WNW_F, // CITY_ONE_ROAD_LEFT
|
|
||||||
GRASS, SSW_F|WSW_F,
|
|
||||||
ROAD, SOUTH_F|WEST_F,
|
|
||||||
CITY, NORTH_F },
|
|
||||||
|
|
||||||
{ GRASS, ENE_F|WNW_F, // CITY_ONE_ROAD_TEE
|
|
||||||
GRASS, ESE_F|SSE_F,
|
|
||||||
GRASS, SSW_F|WSW_F,
|
|
||||||
ROAD, EAST_F,
|
|
||||||
ROAD, SOUTH_F,
|
|
||||||
ROAD, WEST_F,
|
|
||||||
CITY, NORTH_F },
|
|
||||||
|
|
||||||
{ GRASS, ENE_F|WNW_F, // CITY_ONE_ROAD_STRAIGHT
|
|
||||||
GRASS, ESE_F, SOUTH_F, WSW_F,
|
|
||||||
ROAD, EAST_F|WEST_F,
|
|
||||||
CITY, NORTH_F },
|
|
||||||
|
|
||||||
{ GRASS, NORTH_F|EAST_F|SOUTH_F|WEST_F, // CLOISTER_PLAIN
|
|
||||||
CLOISTER, 0},
|
|
||||||
|
|
||||||
{ GRASS, NORTH_F|EAST_F|WEST_F, // CLOISTER_ROAD
|
|
||||||
CLOISTER, 0,
|
|
||||||
ROAD, SOUTH_F },
|
|
||||||
|
|
||||||
{ GRASS, WNW_F|NNW_F, // FOUR_WAY_ROAD
|
|
||||||
GRASS, NNE_F|ENE_F,
|
|
||||||
GRASS, ESE_F|SSE_F,
|
|
||||||
GRASS, SSW_F|WSW_F,
|
|
||||||
ROAD, NORTH_F,
|
|
||||||
ROAD, EAST_F,
|
|
||||||
ROAD, SOUTH_F,
|
|
||||||
ROAD, WEST_F },
|
|
||||||
|
|
||||||
{ GRASS, WNW_F|NORTH_F|ENE_F, // THREE_WAY_ROAD
|
|
||||||
GRASS, ESE_F|SSE_F,
|
|
||||||
GRASS, SSW_F|WSW_F,
|
|
||||||
ROAD, EAST_F,
|
|
||||||
ROAD, SOUTH_F,
|
|
||||||
ROAD, WEST_F },
|
|
||||||
|
|
||||||
{ GRASS, NNE_F|EAST_F|SSE_F, // STRAIGHT_ROAD
|
|
||||||
GRASS, SSW_F|WEST_F|NNW_F,
|
|
||||||
ROAD, NORTH_F|SOUTH_F },
|
|
||||||
|
|
||||||
{ GRASS, WNW_F|NORTH_F|EAST_F|SSE_F, // CURVED_ROAD
|
|
||||||
GRASS, SSW_F|WSW_F,
|
|
||||||
ROAD, SOUTH_F|WEST_F },
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A table describing the geometry of the features (cities, roads,
|
|
||||||
* etc.) of each tile. */
|
|
||||||
protected static final Object[] TILE_FEATURE_GEOMS = new Object[] {
|
|
||||||
// one must offset tile type by one when indexing into this array
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), }, // CITY_FOUR
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), // CITY_THREE
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 4, 1, 3, 3, 3, 4, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), // CITY_THREE_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 4, 1, 3, 2, 3, 2, 4 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 2, 4, 2, 3, 3, 3, 4, 4 },
|
|
||||||
new IntTuple(ROAD, 3),
|
|
||||||
new int[] { 2, 3, 2, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), // CITY_TWO
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 4, 4, 0, 4, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), // CITY_TWO_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 4, 4, 0, 4, 2, 2, 4 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 2, 4, 4, 2, 4, 4 },
|
|
||||||
new IntTuple(ROAD, 3),
|
|
||||||
new int[] { 2, 4, 4, 2 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(CITY, 0), // CITY_TWO_ACROSS
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 0, 4, 1, 3, 3, 3, 4, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // DISCONNECTED_CITY_TWO
|
|
||||||
new IntTuple(CITY, 1),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 },
|
|
||||||
new IntTuple(CITY, 2),
|
|
||||||
new int[] { 4, 0, 3, 1, 3, 3, 4, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // DISCONNECTED_CITY_TWO_ACROSS
|
|
||||||
new IntTuple(CITY, 1),
|
|
||||||
new int[] { 0, 0, 1, 1, 1, 3, 0, 4 },
|
|
||||||
new IntTuple(CITY, 2),
|
|
||||||
new int[] { 4, 0, 3, 1, 3, 3, 4, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CITY_ONE
|
|
||||||
new IntTuple(CITY, 1),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CITY_ONE_ROAD_RIGHT
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 2, 2, 4, 2, 4, 4, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 2, 4, 2 },
|
|
||||||
new IntTuple(CITY, 3),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CITY_ONE_ROAD_LEFT
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 2, 2, 2, 2, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 0, 2, 2, 2 },
|
|
||||||
new IntTuple(CITY, 3),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CITY_ONE_ROAD_TEE
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 2, 2, 4, 2, 4, 4, 2, 4 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 0, 2, 2, 2, 2, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 3),
|
|
||||||
new int[] { 0, 2, 2, 2 },
|
|
||||||
new IntTuple(ROAD, 4),
|
|
||||||
new int[] { 2, 2, 4, 2 },
|
|
||||||
new IntTuple(ROAD, 5),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(CITY, 6),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CITY_ONE_ROAD_STRAIGHT
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 2, 4, 2, 4, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 0, 2, 4, 2 },
|
|
||||||
new IntTuple(CITY, 3),
|
|
||||||
new int[] { 0, 0, 1, 1, 3, 1, 4, 0 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CLOISTER_PLAIN
|
|
||||||
new IntTuple(CLOISTER, 1),
|
|
||||||
new int[] { 1, 1, 3, 1, 3, 3, 1, 3 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CLOISTER_ROAD
|
|
||||||
new IntTuple(CLOISTER, 1),
|
|
||||||
new int[] { 1, 1, 3, 1, 3, 3, 1, 3 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 3, 2, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // FOUR_WAY_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 2, 0, 4, 0, 4, 2, 2, 2 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 2, 2, 4, 2, 4, 4, 2, 4 },
|
|
||||||
new IntTuple(GRASS, 3),
|
|
||||||
new int[] { 0, 2, 2, 2, 2, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 4),
|
|
||||||
new int[] { 2, 0, 2, 2 },
|
|
||||||
new IntTuple(ROAD, 5),
|
|
||||||
new int[] { 2, 2, 4, 2 },
|
|
||||||
new IntTuple(ROAD, 6),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 7),
|
|
||||||
new int[] { 0, 2, 2, 2 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // THREE_WAY_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 2, 2, 4, 2, 4, 4, 2, 4 },
|
|
||||||
new IntTuple(GRASS, 2),
|
|
||||||
new int[] { 0, 2, 2, 2, 2, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 3),
|
|
||||||
new int[] { 2, 2, 4, 2 },
|
|
||||||
new IntTuple(ROAD, 4),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 5),
|
|
||||||
new int[] { 0, 2, 2, 2 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // STRAIGHT_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 2, 4, 2, 4, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 0, 2, 4 }},
|
|
||||||
|
|
||||||
new Object[] { new IntTuple(GRASS, 0), // CURVED_ROAD
|
|
||||||
new IntTuple(GRASS, 1),
|
|
||||||
new int[] { 0, 2, 2, 2, 2, 4, 0, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 2, 2, 2, 4 },
|
|
||||||
new IntTuple(ROAD, 2),
|
|
||||||
new int[] { 0, 2, 2, 2 }},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** The standard tile set for a game of Venison. */
|
/** The standard tile set for a game of Venison. */
|
||||||
protected static ArrayList TILE_SET = new ArrayList();
|
protected static ArrayList TILE_SET = new ArrayList();
|
||||||
|
|
||||||
@@ -779,9 +485,8 @@ public class TileUtil implements TileCodes
|
|||||||
addTiles(1, TILE_SET, new VenisonTile(CITY_TWO_ACROSS, false));
|
addTiles(1, TILE_SET, new VenisonTile(CITY_TWO_ACROSS, false));
|
||||||
addTiles(2, TILE_SET, new VenisonTile(CITY_TWO_ACROSS, true));
|
addTiles(2, TILE_SET, new VenisonTile(CITY_TWO_ACROSS, true));
|
||||||
|
|
||||||
addTiles(2, TILE_SET, new VenisonTile(DISCONNECTED_CITY_TWO, false));
|
addTiles(2, TILE_SET, new VenisonTile(TWO_CITY_TWO, false));
|
||||||
addTiles(3, TILE_SET,
|
addTiles(3, TILE_SET, new VenisonTile(TWO_CITY_TWO_ACROSS, false));
|
||||||
new VenisonTile(DISCONNECTED_CITY_TWO_ACROSS, false));
|
|
||||||
|
|
||||||
addTiles(5, TILE_SET, new VenisonTile(CITY_ONE, false));
|
addTiles(5, TILE_SET, new VenisonTile(CITY_ONE, false));
|
||||||
addTiles(3, TILE_SET, new VenisonTile(CITY_ONE_ROAD_RIGHT, false));
|
addTiles(3, TILE_SET, new VenisonTile(CITY_ONE_ROAD_RIGHT, false));
|
||||||
|
|||||||
Reference in New Issue
Block a user