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;
|
||||
|
||||
@@ -7,11 +7,14 @@ import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.swing.Controller;
|
||||
import com.samskivert.swing.util.SwingUtil;
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
|
||||
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
|
||||
* to recompute its size based on the new tile layout.
|
||||
* Sets the tiles to be displayed by this board. Any previous tiles
|
||||
* 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.
|
||||
*/
|
||||
public void setTiles (DSet tiles)
|
||||
public void setTiles (DSet tset)
|
||||
{
|
||||
// grab the new tiles
|
||||
_tiles = tiles;
|
||||
// clear out our old tiles list
|
||||
_tiles.clear();
|
||||
|
||||
// update our display
|
||||
refreshTiles();
|
||||
// copy the tiles from the set into our local list
|
||||
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
|
||||
* occurred in the tiles set.
|
||||
* Sets the piecens to be placed on the appropriate tiles of the
|
||||
* 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
|
||||
// adjust to our changed size
|
||||
if (_tiles != null) {
|
||||
computeDimensions();
|
||||
// just iterate over the set placing each of the piecens in turn
|
||||
Iterator iter = piecens.elements();
|
||||
while (iter.hasNext()) {
|
||||
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
|
||||
revalidate();
|
||||
// add the tile
|
||||
_tiles.add(tile);
|
||||
|
||||
// we also have to repaint in case our dimensions didn't change
|
||||
repaint();
|
||||
// resort the list
|
||||
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) {
|
||||
updatePlacingInfo(true);
|
||||
}
|
||||
|
||||
// and repaint
|
||||
repaint();
|
||||
}
|
||||
@@ -135,12 +198,10 @@ public class VenisonBoard
|
||||
g.translate(_tx, _ty);
|
||||
|
||||
// iterate over our tiles, painting each of them
|
||||
if (_tiles != null) {
|
||||
Iterator iter = _tiles.elements();
|
||||
while (iter.hasNext()) {
|
||||
VenisonTile tile = (VenisonTile)iter.next();
|
||||
tile.paint(g2, _origX, _origY);
|
||||
}
|
||||
int tsize = _tiles.size();
|
||||
for (int i = 0; i < tsize; i++) {
|
||||
VenisonTile tile = (VenisonTile)_tiles.get(i);
|
||||
tile.paint(g2, _origX, _origY);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
g.translate(-_tx, -_ty);
|
||||
|
||||
g.setColor(Color.black);
|
||||
g2.draw(getBounds());
|
||||
}
|
||||
|
||||
/** Called by our adapter when the mouse moves. */
|
||||
@@ -166,11 +242,52 @@ public class VenisonBoard
|
||||
_mouseX = evt.getX() - _tx;
|
||||
_mouseY = evt.getY() - _ty;
|
||||
|
||||
// if we have a tile to be placed, update its coordinates
|
||||
if (_placingTile != null) {
|
||||
// if we have a tile to be placed, update its coordinates
|
||||
if (updatePlacingInfo(false)) {
|
||||
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;
|
||||
_placingTile = null;
|
||||
|
||||
// inherit claims on the placed tile
|
||||
TileUtil.inheritClaims(_tiles, _placedTile);
|
||||
|
||||
// post the action
|
||||
Controller.postAction(this, TILE_PLACED);
|
||||
|
||||
// and repaint
|
||||
repaint();
|
||||
// move into placing piecen mode
|
||||
_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
|
||||
// tile in this new position
|
||||
_validOrients = TileUtil.computeValidOrients(
|
||||
_tiles.elements(), _placingTile);
|
||||
_validOrients = TileUtil.computeValidOrients(_tiles, _placingTile);
|
||||
|
||||
// if we've changed positions, clear out our valid placement
|
||||
// flag
|
||||
@@ -290,7 +420,7 @@ public class VenisonBoard
|
||||
// documentation inherited
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
if (_tiles == null) {
|
||||
if (_tiles.size() == 0) {
|
||||
return new Dimension(100, 100);
|
||||
|
||||
} else {
|
||||
@@ -300,28 +430,33 @@ public class VenisonBoard
|
||||
|
||||
/**
|
||||
* 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 ()
|
||||
{
|
||||
int maxX = 0, maxY = 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
|
||||
if (_tiles != null) {
|
||||
Iterator iter = _tiles.elements();
|
||||
while (iter.hasNext()) {
|
||||
VenisonTile tile = (VenisonTile)iter.next();
|
||||
if (tile.x > maxX) {
|
||||
maxX = tile.x;
|
||||
} else if (tile.x < minX) {
|
||||
minX = tile.x;
|
||||
}
|
||||
if (tile.y > maxY) {
|
||||
maxY = tile.y;
|
||||
} else if (tile.y < minY) {
|
||||
minY = tile.y;
|
||||
}
|
||||
int tsize = _tiles.size();
|
||||
for (int i = 0; i < tsize; i++) {
|
||||
VenisonTile tile = (VenisonTile)_tiles.get(i);
|
||||
if (tile.x > maxX) {
|
||||
maxX = tile.x;
|
||||
} else if (tile.x < minX) {
|
||||
minX = tile.x;
|
||||
}
|
||||
if (tile.y > maxY) {
|
||||
maxY = tile.y;
|
||||
} else if (tile.y < minY) {
|
||||
minY = tile.y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,11 +464,25 @@ public class VenisonBoard
|
||||
minX -= 1; minY -= 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
|
||||
_origX = -minX;
|
||||
_origY = -minY;
|
||||
_width = maxX - minX + 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. */
|
||||
@@ -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(CURVED_ROAD, false, WEST, 0, 2));
|
||||
VenisonTile target =
|
||||
new VenisonTile(DISCONNECTED_CITY_TWO, false, NORTH, 0, 1);
|
||||
set.addTile(target);
|
||||
VenisonTile one = new VenisonTile(TWO_CITY_TWO, false, NORTH, 0, 1);
|
||||
set.addTile(one);
|
||||
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, 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);
|
||||
|
||||
VenisonTile placing = new VenisonTile(CITY_TWO, false, NORTH, 0, 0);
|
||||
board.setTileToBePlaced(placing);
|
||||
|
||||
// set a feature group to test propagation
|
||||
VenisonTile[] tiles = new VenisonTile[set.size()];
|
||||
Iterator iter = set.elements();
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
tiles[i] = (VenisonTile)iter.next();
|
||||
}
|
||||
Arrays.sort(tiles);
|
||||
TileUtil.setFeatureGroup(tiles, target, 0, 1, 0);
|
||||
List tiles = new ArrayList();
|
||||
CollectionUtil.addAll(tiles, set.elements());
|
||||
Collections.sort(tiles);
|
||||
|
||||
one.setPiecen(new Piecen(Piecen.BLUE, 0, 0, 0), tiles);
|
||||
two.setPiecen(new Piecen(Piecen.BLUE, 0, 0, 0), tiles);
|
||||
|
||||
frame.getContentPane().add(board, BorderLayout.CENTER);
|
||||
frame.pack();
|
||||
@@ -389,7 +537,7 @@ public class VenisonBoard
|
||||
}
|
||||
|
||||
/** A reference to our tile set. */
|
||||
protected DSet _tiles;
|
||||
protected ArrayList _tiles = new ArrayList();
|
||||
|
||||
/** The tile currently being placed by the user. */
|
||||
protected VenisonTile _placingTile;
|
||||
@@ -397,6 +545,9 @@ public class VenisonBoard
|
||||
/** The last tile being placed by the user. */
|
||||
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
|
||||
* tile is valid. */
|
||||
protected boolean _validPlacement = false;
|
||||
|
||||
@@ -7,7 +7,11 @@ import java.awt.event.ActionEvent;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
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.SetListener;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
@@ -23,7 +27,7 @@ import com.threerings.venison.Log;
|
||||
* the Venison game.
|
||||
*/
|
||||
public class VenisonController
|
||||
extends TurnGameController implements VenisonCodes
|
||||
extends TurnGameController implements VenisonCodes, SetListener
|
||||
{
|
||||
// documentation inherited
|
||||
protected void didInit ()
|
||||
@@ -48,6 +52,14 @@ public class VenisonController
|
||||
|
||||
// get a casted reference to our game object
|
||||
_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
|
||||
@@ -61,9 +73,6 @@ public class VenisonController
|
||||
Log.info("Setting tile to be placed: " + _venobj.currentTile);
|
||||
_panel.board.setTileToBePlaced(_venobj.currentTile);
|
||||
}
|
||||
|
||||
// and refresh the tiles
|
||||
_panel.board.refreshTiles();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -74,21 +83,74 @@ public class VenisonController
|
||||
// handle the setting of the board state
|
||||
if (event.getName().equals(VenisonObject.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
|
||||
public boolean handleAction (ActionEvent action)
|
||||
{
|
||||
if (action.getActionCommand().equals(TILE_PLACED)) {
|
||||
// the user placed the tile into a valid location. grab the
|
||||
// placed tile from the board and submit it to the server as
|
||||
// our move
|
||||
// placed tile from the board and submit it to the server
|
||||
Object[] args = new Object[] { _panel.board.getPlacedTile() };
|
||||
MessageEvent mevt = new MessageEvent(
|
||||
_venobj.getOid(), PLACE_TILE_REQUEST, args);
|
||||
_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 {
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
public VenisonBoard board;
|
||||
|
||||
/** A reference to our _noplace button. */
|
||||
public JButton noplace;
|
||||
|
||||
/**
|
||||
* Constructs a new Venison game display.
|
||||
*/
|
||||
@@ -49,6 +52,13 @@ public class VenisonPanel
|
||||
// add a turn indicator to the side panel
|
||||
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(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;
|
||||
|
||||
@@ -12,6 +12,14 @@ public interface VenisonCodes
|
||||
* the user places a tile into a valid position. */
|
||||
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
|
||||
* chosen where they wish to place their 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
|
||||
* chosen where they wish to place their 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;
|
||||
|
||||
@@ -17,6 +17,9 @@ public class VenisonObject extends TurnGameObject
|
||||
/** The field name of the <code>currentTile</code> field. */
|
||||
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
|
||||
* game. */
|
||||
public DSet tiles = new DSet(VenisonTile.class);
|
||||
@@ -25,6 +28,10 @@ public class VenisonObject extends TurnGameObject
|
||||
* only valid while it is someone's turn. */
|
||||
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
|
||||
* value.
|
||||
@@ -70,11 +77,48 @@ public class VenisonObject extends TurnGameObject
|
||||
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
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", tiles=").append(tiles);
|
||||
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;
|
||||
|
||||
@@ -7,16 +7,13 @@ import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.List;
|
||||
import com.samskivert.util.IntTuple;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
|
||||
@@ -50,11 +47,11 @@ public class VenisonTile
|
||||
public int[] claims;
|
||||
|
||||
/** 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
|
||||
* been placed on this tile. */
|
||||
// public Piecen piecen;
|
||||
public Piecen piecen;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* matched.
|
||||
*/
|
||||
public int getFeatureIndex (int featureMask)
|
||||
public int getFeatureIndex (int edgeMask)
|
||||
{
|
||||
// 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) {
|
||||
int fmask = features[i+1];
|
||||
if ((fmask & featureMask) != 0) {
|
||||
return i/2;
|
||||
// look for a feature with a matching edge mask
|
||||
for (int i = 0; i < features.length; i ++) {
|
||||
if ((features[i].edgeMask & edgeMask) != 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +110,32 @@ public class VenisonTile
|
||||
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
|
||||
* 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
|
||||
* 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];
|
||||
}
|
||||
|
||||
@@ -138,11 +161,67 @@ public class VenisonTile
|
||||
*/
|
||||
public void setFeatureGroup (int featureIndex, int claimGroup)
|
||||
{
|
||||
Log.info("Setting feature group [tile=" + this +
|
||||
", fidx=" + featureIndex + ", cgroup=" + claimGroup + "].");
|
||||
// Log.info("Setting feature group [tile=" + this +
|
||||
// ", fidx=" + featureIndex + ", cgroup=" + claimGroup + "].");
|
||||
|
||||
// update the claim group slot for this feature
|
||||
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;
|
||||
|
||||
// create our shapes if we haven't already
|
||||
if (_shapes[tidx][orientation] == null) {
|
||||
createShapes();
|
||||
}
|
||||
|
||||
// compute our screen coordinates
|
||||
int sx = (x + xoff) * TILE_WIDTH;
|
||||
int sy = (y + yoff) * TILE_HEIGHT;
|
||||
@@ -172,16 +246,16 @@ public class VenisonTile
|
||||
// translate to our screen coordinates
|
||||
g.translate(sx, sy);
|
||||
|
||||
// draw our shapes using the proper orientation
|
||||
GeneralPath[] paths = _shapes[tidx][orientation];
|
||||
IntTuple[] types = _types[tidx];
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
if (claims[types[i].right] != 0) {
|
||||
g.setColor(CLAIMED_COLOR_MAP[types[i].left]);
|
||||
} else {
|
||||
g.setColor(COLOR_MAP[types[i].left]);
|
||||
// render our features and piecen
|
||||
for (int i = 0; i < features.length; i++) {
|
||||
// paint the feature
|
||||
features[i].paint(g, orientation, claims[i]);
|
||||
|
||||
// if we have a piecen on this tile, render it as well
|
||||
if (piecen != null && piecen.featureIndex == i) {
|
||||
features[i].paintPiecen(
|
||||
g, orientation, piecen.color, piecen.claimGroup);
|
||||
}
|
||||
g.fill(paths[i]);
|
||||
}
|
||||
|
||||
// draw a rectangular outline
|
||||
@@ -205,9 +279,12 @@ public class VenisonTile
|
||||
*/
|
||||
public int compareTo (Object other)
|
||||
{
|
||||
// we will either be compared to another tile or to a coordinate
|
||||
// object
|
||||
if (other instanceof VenisonTile) {
|
||||
// we will either be compared to another tile, to a piecen or to a
|
||||
// coordinate object (int tuple)
|
||||
if (other == null) {
|
||||
return -1;
|
||||
|
||||
} else if (other instanceof VenisonTile) {
|
||||
VenisonTile tile = (VenisonTile)other;
|
||||
return (tile.x == x) ? y - tile.y : x - tile.x;
|
||||
|
||||
@@ -215,12 +292,22 @@ public class VenisonTile
|
||||
IntTuple coord = (IntTuple)other;
|
||||
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 {
|
||||
// who knows...
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
return (compareTo(other) == 0);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Object getKey ()
|
||||
{
|
||||
@@ -258,10 +345,10 @@ public class VenisonTile
|
||||
{
|
||||
if (type > 0) {
|
||||
// grab a reference to our feature information
|
||||
features = TileUtil.TILE_FEATURES[type-1];
|
||||
features = FeatureUtil.getTileFeatures(type);
|
||||
|
||||
// create our claims array
|
||||
claims = new int[features.length/2];
|
||||
claims = new int[features.length];
|
||||
|
||||
} else {
|
||||
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.
|
||||
*/
|
||||
@@ -359,30 +364,8 @@ public class VenisonTile
|
||||
{
|
||||
return "[type=" + type + ", shield=" + hasShield +
|
||||
", 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;
|
||||
|
||||
@@ -32,11 +32,11 @@ public interface TileCodes
|
||||
|
||||
/** A two-sided city tile with two separate city arcs adjacent to one
|
||||
* 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
|
||||
* 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. */
|
||||
public static final int CITY_ONE = 9;
|
||||
@@ -118,41 +118,4 @@ public interface TileCodes
|
||||
|
||||
/** A constant indicating a cloister. */
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -32,6 +33,8 @@ public class VenisonManager
|
||||
registerMessageHandler(PLACE_TILE_REQUEST, new PlaceTileHandler());
|
||||
registerMessageHandler(
|
||||
PLACE_PIECEN_REQUEST, new PlacePiecenHandler());
|
||||
registerMessageHandler(
|
||||
PLACE_NOTHING_REQUEST, new PlaceNothingHandler());
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -52,12 +55,19 @@ public class VenisonManager
|
||||
super.gameWillStart();
|
||||
|
||||
// generate a shuffled tile list
|
||||
_tiles = TileUtil.getStandardTileSet();
|
||||
Collections.shuffle(_tiles);
|
||||
_tilesInBox = TileUtil.getStandardTileSet();
|
||||
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.setPiecens(new DSet(Piecen.class));
|
||||
|
||||
// and add the starting tile
|
||||
_venobj.addToTiles(VenisonTile.STARTING_TILE);
|
||||
_tiles.add(VenisonTile.STARTING_TILE);
|
||||
}
|
||||
|
||||
protected void turnWillStart ()
|
||||
@@ -66,7 +76,7 @@ public class VenisonManager
|
||||
|
||||
// let the players know what the next tile is that should be
|
||||
// played
|
||||
VenisonTile tile = (VenisonTile)_tiles.remove(0);
|
||||
VenisonTile tile = (VenisonTile)_tilesInBox.remove(0);
|
||||
_venobj.setCurrentTile(tile);
|
||||
}
|
||||
|
||||
@@ -75,7 +85,7 @@ public class VenisonManager
|
||||
super.turnDidEnd();
|
||||
|
||||
// if there are no tiles left, we end the game
|
||||
if (_tiles.size() == 0) {
|
||||
if (_tilesInBox.size() == 0) {
|
||||
endGame();
|
||||
}
|
||||
}
|
||||
@@ -86,7 +96,7 @@ public class VenisonManager
|
||||
protected void setNextTurnHolder ()
|
||||
{
|
||||
// if we have tiles left, we move to the next player as normal
|
||||
if (_tiles.size() > 0) {
|
||||
if (_tilesInBox.size() > 0) {
|
||||
super.setNextTurnHolder();
|
||||
} else {
|
||||
// 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];
|
||||
|
||||
// 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
|
||||
_venobj.addToTiles(tile);
|
||||
|
||||
} else {
|
||||
Log.warning("Received invalid placement " + event + ".");
|
||||
}
|
||||
|
||||
// end the turn
|
||||
endTurn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +136,40 @@ public class VenisonManager
|
||||
{
|
||||
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
|
||||
* 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;
|
||||
|
||||
import java.awt.Polygon;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
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 and the current orientation of the target tile is ignored.
|
||||
*
|
||||
* @param tiles an iterator that will iterate over all of the tiles
|
||||
* currently placed on the board.
|
||||
* @param tiles a list of the tiles on the board.
|
||||
* @param target the tile whose valid orientations we wish to compute.
|
||||
*
|
||||
* @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}.
|
||||
*/
|
||||
public static boolean[] computeValidOrients (
|
||||
Iterator tiles, VenisonTile target)
|
||||
List tiles, VenisonTile target)
|
||||
{
|
||||
// this contains a count of tiles that match up with the candidate
|
||||
// tile in each of its four orientations
|
||||
int[] matches = new int[4];
|
||||
|
||||
while (tiles.hasNext()) {
|
||||
VenisonTile tile = (VenisonTile)tiles.next();
|
||||
int tsize = tiles.size();
|
||||
for (int i = 0; i < tsize; i++) {
|
||||
VenisonTile tile = (VenisonTile)tiles.get(i);
|
||||
|
||||
// figure out where this tile is in relation to the candidate
|
||||
int xdiff = tile.x - target.x;
|
||||
@@ -75,14 +75,14 @@ public class TileUtil implements TileCodes
|
||||
|
||||
// we iterate over the four possible orientations of the
|
||||
// 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
|
||||
// changes) with the edge of the target tile which is
|
||||
// adjusted based on the target tile's orientation
|
||||
if (getEdge(tile.type, tileEdge) ==
|
||||
getEdge(target.type, (targetEdge+(4-i)) % 4)) {
|
||||
getEdge(target.type, (targetEdge+(4-o)) % 4)) {
|
||||
// increment the edge matches
|
||||
matches[i]++;
|
||||
matches[o]++;
|
||||
|
||||
} else {
|
||||
// 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
|
||||
// of which of the other three tiles match in this
|
||||
// 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
|
||||
* legal given the placement of all of the existing tiles.
|
||||
*
|
||||
* @param tiles an iterator that enumerates all of the tile already on
|
||||
* the board.
|
||||
* @param tiles a list of the tiles already on the board.
|
||||
* @param target the tile whose validity we want to determine.
|
||||
*
|
||||
* @return true if the target tile is configured with a valid position
|
||||
* and orientation, false if it is not.
|
||||
*/
|
||||
public static boolean isValidPlacement (
|
||||
Iterator tiles, VenisonTile target)
|
||||
public static boolean isValidPlacement (List tiles, VenisonTile target)
|
||||
{
|
||||
boolean matchedAnEdge = false;
|
||||
|
||||
while (tiles.hasNext()) {
|
||||
VenisonTile tile = (VenisonTile)tiles.next();
|
||||
int tsize = tiles.size();
|
||||
for (int i = 0; i < tsize; i++) {
|
||||
VenisonTile tile = (VenisonTile)tiles.get(i);
|
||||
|
||||
// figure out where this tile is in relation to the candidate
|
||||
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
|
||||
* 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).
|
||||
* @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
|
||||
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
|
||||
// neighboring tile's matching feature is claimed
|
||||
for (int i = 0; i < tile.features.length; i += 2) {
|
||||
int ftype = tile.features[i];
|
||||
int fmask = tile.features[i+1];
|
||||
for (int i = 0; i < tile.features.length; i ++) {
|
||||
int ftype = tile.features[i].type;
|
||||
int fmask = tile.features[i].edgeMask;
|
||||
int cgroup = 0;
|
||||
|
||||
// iterate over all of the possible adjacency possibilities
|
||||
for (int c = 0; c < ADJADCENCY_MAP.length; c += 3) {
|
||||
int mask = ADJADCENCY_MAP[c];
|
||||
int dir = ADJADCENCY_MAP[c+1];
|
||||
int opp_mask = ADJADCENCY_MAP[c+2];
|
||||
// iterate over all of the possible adjacency possibilities,
|
||||
// first looking for a claim group to inherit
|
||||
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) {
|
||||
@@ -226,34 +226,84 @@ public class TileUtil implements TileCodes
|
||||
|
||||
// it looks like we have a match, so translate the target
|
||||
// stuff into our orientation
|
||||
mask = translateMask(mask, tile.orientation);
|
||||
opp_mask = translateMask(opp_mask, tile.orientation);
|
||||
mask = FeatureUtil.translateMask(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 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) {
|
||||
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);
|
||||
Log.info("Inherited claim [tile=" + tile +
|
||||
", fidx=" + i + ", cgroup=" + cgroup +
|
||||
", source=" + neighbors[dir] + "].");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// finally initialize the feature's claim group
|
||||
tile.claims[i/2] = cgroup;
|
||||
// if we didn't inherit a claim group, skip to the next
|
||||
// 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
|
||||
* 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
|
||||
* being set.
|
||||
* @param featureIndex the index of the feature.
|
||||
@@ -271,21 +321,21 @@ public class TileUtil implements TileCodes
|
||||
* propagating the group further).
|
||||
*/
|
||||
public static void setFeatureGroup (
|
||||
VenisonTile[] tiles, VenisonTile tile, int featureIndex,
|
||||
List tiles, VenisonTile tile, int featureIndex,
|
||||
int claimGroup, int entryEdgeMask)
|
||||
{
|
||||
// set the claim group for this feature on this tile
|
||||
tile.setFeatureGroup(featureIndex, claimGroup);
|
||||
|
||||
// now propagate this feature to connected features
|
||||
int ftype = tile.features[featureIndex*2];
|
||||
int fmask = tile.features[featureIndex*2+1];
|
||||
int ftype = tile.features[featureIndex].type;
|
||||
int fmask = tile.features[featureIndex].edgeMask;
|
||||
|
||||
// iterate over all of the possible adjacency possibilities
|
||||
for (int c = 0; c < ADJADCENCY_MAP.length; c += 3) {
|
||||
int mask = ADJADCENCY_MAP[c];
|
||||
int dir = ADJADCENCY_MAP[c+1];
|
||||
int opp_mask = ADJADCENCY_MAP[c+2];
|
||||
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];
|
||||
VenisonTile neighbor = null;
|
||||
|
||||
// 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
|
||||
// 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) {
|
||||
continue;
|
||||
}
|
||||
@@ -314,12 +364,16 @@ public class TileUtil implements TileCodes
|
||||
|
||||
// it looks like we have a match, so translate the target mask
|
||||
// into our orientation
|
||||
mask = translateMask(mask, tile.orientation);
|
||||
mask = FeatureUtil.translateMask(mask, tile.orientation);
|
||||
|
||||
// propagate, propagate, propagate
|
||||
int fidx = neighbor.getFeatureIndex(opp_mask);
|
||||
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 {
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
* 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);
|
||||
int tidx = Arrays.binarySearch(tiles, coord);
|
||||
return (tidx >= 0) ? tiles[tidx] : null;
|
||||
int tidx = Collections.binarySearch(tiles, coord);
|
||||
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)
|
||||
* 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).
|
||||
* Returns the next unused claim group value.
|
||||
*/
|
||||
public static Polygon roadSegmentToPolygon (
|
||||
int x1, int y1, int x2, int y2)
|
||||
public static int nextClaimGroup ()
|
||||
{
|
||||
// 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;
|
||||
|
||||
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;
|
||||
return ++_claimGroupCounter;
|
||||
}
|
||||
|
||||
/** Used to generate our standard tile set. */
|
||||
@@ -462,6 +431,9 @@ public class TileUtil implements TileCodes
|
||||
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
|
||||
* adjacent tiles. */
|
||||
protected static final int[] EDGE_MAP = new int[] {
|
||||
@@ -470,31 +442,6 @@ public class TileUtil implements TileCodes
|
||||
-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. */
|
||||
protected static final int[] TILE_EDGES = new int[] {
|
||||
-1, -1, -1, -1, // null tile
|
||||
@@ -504,8 +451,8 @@ public class TileUtil implements TileCodes
|
||||
CITY, GRASS, GRASS, CITY, // CITY_TWO
|
||||
CITY, ROAD, ROAD, CITY, // CITY_TWO_ROAD
|
||||
GRASS, CITY, GRASS, CITY, // CITY_TWO_ACROSS
|
||||
CITY, CITY, GRASS, GRASS, // DISCONNECTED_CITY_TWO
|
||||
GRASS, CITY, GRASS, CITY, // DISCONNECTED_CITY_TWO_ACROSS
|
||||
CITY, CITY, GRASS, GRASS, // TWO_CITY_TWO
|
||||
GRASS, CITY, GRASS, CITY, // TWO_CITY_TWO_ACROSS
|
||||
CITY, GRASS, GRASS, GRASS, // CITY_ONE
|
||||
CITY, ROAD, ROAD, GRASS, // CITY_ONE_ROAD_RIGHT
|
||||
CITY, GRASS, ROAD, ROAD, // CITY_ONE_ROAD_LEFT
|
||||
@@ -519,247 +466,6 @@ public class TileUtil implements TileCodes
|
||||
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. */
|
||||
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(2, TILE_SET, new VenisonTile(CITY_TWO_ACROSS, true));
|
||||
|
||||
addTiles(2, TILE_SET, new VenisonTile(DISCONNECTED_CITY_TWO, false));
|
||||
addTiles(3, TILE_SET,
|
||||
new VenisonTile(DISCONNECTED_CITY_TWO_ACROSS, false));
|
||||
addTiles(2, TILE_SET, new VenisonTile(TWO_CITY_TWO, false));
|
||||
addTiles(3, TILE_SET, new VenisonTile(TWO_CITY_TWO_ACROSS, false));
|
||||
|
||||
addTiles(5, TILE_SET, new VenisonTile(CITY_ONE, false));
|
||||
addTiles(3, TILE_SET, new VenisonTile(CITY_ONE_ROAD_RIGHT, false));
|
||||
|
||||
Reference in New Issue
Block a user