diff --git a/projects/atlanti/.jde-project.el b/projects/atlanti/.jde-project.el
deleted file mode 100644
index ef6bdcac..00000000
--- a/projects/atlanti/.jde-project.el
+++ /dev/null
@@ -1,4 +0,0 @@
-(jde-set-variables
- '(jde-db-source-directories (quote ("/export/local/jdk1.4/src" "/home/mdb/projects/samskivert/src/java" "/home/mdb/work/narya/src/java" "/home/mdb/projects/atlanti/src/java")))
- '(jde-global-classpath (quote ("/home/mdb/projects/samskivert/dist/classes" "/home/mdb/work/narya/dist/classes" "/home/mdb/projects/atlanti/dist/classes")))
- )
diff --git a/projects/atlanti/bin/atlclient b/projects/atlanti/bin/atlclient
deleted file mode 100755
index 46143cbf..00000000
--- a/projects/atlanti/bin/atlclient
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-BINDIR=`dirname $0`
-JAVA_ARGS=""
-ARGS=""
-
-# grab the -Dinviter if it's specified
-while [ ! -z "$1" ] ; do
- case $1 in
- -D*)
- JAVA_ARGS="$JAVA_ARGS $1"
- shift
- ;;
- *)
- ARGS="$ARGS $1"
- shift
- ;;
- esac
-done
-
-$BINDIR/runjava $JAVA_ARGS com.threerings.micasa.client.MiCasaApp $ARGS
diff --git a/projects/atlanti/bin/atlserver b/projects/atlanti/bin/atlserver
deleted file mode 100755
index 5e43e32d..00000000
--- a/projects/atlanti/bin/atlserver
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-bindir=`dirname $0`
-$bindir/runjava com.threerings.micasa.server.MiCasaServer $*
diff --git a/projects/atlanti/bin/runjava b/projects/atlanti/bin/runjava
deleted file mode 100755
index 1d245060..00000000
--- a/projects/atlanti/bin/runjava
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/perl -w
-
-use Getopt::Std;
-
-my $usage = "Usage: $0 [-p pid_file] [-r root_directory] args\n";
-
-# locations of stuff
-chomp($location = `dirname $0`);
-
-# get the server root by popping the /bin off of our parent directory
-@parts = split(/\//, $location);
-pop(@parts);
-my $root = join("/", @parts);
-
-my $jhome = $ENV{"JAVA_HOME"};
-
-# make sure JAVA_HOME is set
-if (!defined $jhome) {
- warn "$0: Error: No JAVA_HOME specified!\n";
- warn "\n";
- warn "You must set your JAVA_HOME environment variable to the\n";
- warn "the absolute path of your JDK installation. For example:\n";
- warn "\n";
- warn " % JAVA_HOME=/usr/local/jdk1.2\n";
- warn " % export JAVA_HOME\n";
- die "\n";
-}
-
-# make sure it's set to a directory
-if (! -d $jhome) {
- die "$0: Can't find a java interpreter in '$jhome'.\n";
-}
-
-my $java = "$jhome/bin/java";
-my $jlib = "$jhome/lib/classes.zip";
-
-# put everything in our class path
-my $classpath = "-classpath $root/dist/classes";
-
-# add zip and jar files from our lib/ directory and the system lib/ directory
-my @dirs = ( "$root/lib" );
-foreach $dir (@dirs) {
- next unless (defined $dir);
- if (opendir(DIR, $dir)) {
- foreach $lib (grep { /.(zip|jar)/ && -f "$dir/$_" } readdir(DIR)) {
- $classpath .= ":$dir/$lib";
- }
- closedir DIR;
- }
-}
-
-# finally add the standard classes
-$classpath = "$classpath:$jlib";
-
-# specify our application root (the resource manager needs this)
-my $rootarg = "-Dresource_url=file:$root/rsrc";
-
-my $pid_file = undef;
-my $i = 0;
-
-# strip out the -p and -r args (we'd use getopt() but the damned thing
-# provides no way of escaping arguments so that we can pass args to
-# runjava that get passed down to the JVM)
-for ($i = 0; $i < @ARGV; $i++) {
- my $arg = $ARGV[$i];
-
- # stop when we see -- (and strip it out because Java don't dig --)
- if ($arg eq "--") {
- splice(@ARGV, $i, 1);
- last;
- }
-
- if ($arg eq "-p") {
- $pid_file = $ARGV[$i+1];
- splice(@ARGV, $i, 2);
- $i -= 1; # decrement i so that things stay in sync
-
- } elsif ($arg eq "-r") {
- $rootarg = "-DDapplication.root=" . $ARGV[$i+1];
- splice(@ARGV, $i, 2);
- $i -= 1; # decrement i so that things stay in sync
- }
-}
-
-# log the pid file if requested to do so
-print `echo $$ > $pid_file` if (defined $pid_file);
-
-my $cmd = "$java -mx256M $classpath $rootarg " . join(" ", @ARGV);
-# print "$cmd\n";
-exec($cmd);
diff --git a/projects/atlanti/build.xml b/projects/atlanti/build.xml
deleted file mode 100644
index 533b6bef..00000000
--- a/projects/atlanti/build.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
- * import com.samskivert.atlanti.Log;
- * // ...
- * Log.warning("All hell is breaking loose!");
- * // ...
- *
- *
- * @see com.samskivert.util.Log
- */
-public class Log
-{
- /** The static log instance configured for use by this package. */
- public static com.samskivert.util.Log log =
- new com.samskivert.util.Log("atlanti");
-
- /** Convenience function. */
- public static void debug (String message)
- {
- log.debug(message);
- }
-
- /** Convenience function. */
- public static void info (String message)
- {
- log.info(message);
- }
-
- /** Convenience function. */
- public static void warning (String message)
- {
- log.warning(message);
- }
-
- /** Convenience function. */
- public static void logStackTrace (Throwable t)
- {
- log.logStackTrace(com.samskivert.util.Log.WARNING, t);
- }
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/TileGeometryTest.java b/projects/atlanti/src/java/com/samskivert/atlanti/TileGeometryTest.java
deleted file mode 100644
index 2b372a3b..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/TileGeometryTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// $Id: TileGeometryTest.java,v 1.7 2003/03/23 02:22:51 mdb Exp $
-
-package com.samskivert.atlanti;
-
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-
-import com.samskivert.swing.util.SwingUtil;
-
-import com.threerings.media.image.ImageManager;
-import com.threerings.media.tile.TileManager;
-import com.threerings.resource.ResourceManager;
-
-import com.samskivert.atlanti.data.AtlantiTile;
-import com.samskivert.atlanti.data.TileCodes;
-import com.samskivert.atlanti.util.PiecenUtil;
-
-/**
- * A simple class for testing the tile geometry specifications by drawing
- * them.
- */
-public class TileGeometryTest extends JPanel
- implements TileCodes
-{
- public TileGeometryTest ()
- {
- for (int i = 0; i < TILE_TYPES; i++) {
- _tiles[i] = new AtlantiTile(i+1, true, NORTH, i % 5, i / 5);
- }
- }
-
- public void paintComponent (Graphics g)
- {
- super.paintComponent(g);
-
- // paint our tiles
- for (int i = 0; i < _tiles.length; i++) {
- _tiles[i].paint((Graphics2D)g, 0, 0);
- }
- }
-
- public Dimension getPreferredSize ()
- {
- // we want to be five tiles wide by four tiles tall
- return new Dimension(TILE_WIDTH * 5, TILE_HEIGHT * 4);
- }
-
- public static void main (String[] args)
- {
- JFrame frame = new JFrame("Tile geometry test");
-
- ResourceManager rmgr = new ResourceManager("rsrc");
- ImageManager imgr = new ImageManager(rmgr, frame);
- TileManager tmgr = new TileManager(imgr);
-
- AtlantiTile.setManagers(imgr, tmgr);
- AtlantiTile.piecenDebug = true;
- PiecenUtil.init(tmgr);
-
- // quit if we're closed
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- TileGeometryTest panel = new TileGeometryTest();
- frame.getContentPane().add(panel);
- frame.pack();
- SwingUtil.centerWindow(frame);
- frame.show();
- }
-
- protected AtlantiTile[] _tiles = new AtlantiTile[TILE_TYPES];
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiBoard.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiBoard.java
deleted file mode 100644
index b1d89c89..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiBoard.java
+++ /dev/null
@@ -1,693 +0,0 @@
-//
-// $Id: AtlantiBoard.java,v 1.19 2003/03/23 05:12:43 mdb Exp $
-
-package com.samskivert.atlanti.client;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-
-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;
-
-import com.samskivert.atlanti.Log;
-import com.samskivert.atlanti.data.AtlantiCodes;
-import com.samskivert.atlanti.data.AtlantiTile;
-import com.samskivert.atlanti.data.Piecen;
-import com.samskivert.atlanti.data.TileCodes;
-import com.samskivert.atlanti.util.TileUtil;
-
-/**
- * Displays the tiles that make up the board.
- */
-public class AtlantiBoard extends JPanel
- implements TileCodes, AtlantiCodes
-{
- /**
- * Constructs a board.
- */
- public AtlantiBoard ()
- {
- // create mouse adapters that will let us know when interesting
- // mouse events happen
- addMouseListener(new MouseAdapter() {
- public void mouseClicked (MouseEvent evt) {
- AtlantiBoard.this.mouseClicked(evt);
- }
- });
- addMouseMotionListener(new MouseMotionAdapter() {
- public void mouseMoved (MouseEvent evt) {
- AtlantiBoard.this.mouseMoved(evt);
- }
- });
- }
-
- /**
- * Sets the piecen color to use when creating new piecens.
- */
- public void setNewPiecenColor (int color)
- {
- _newPiecenColor = color;
- }
-
- /**
- * 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 tset the set of {@link AtlantiTile} objects to be displayed
- * by this board.
- */
- public void setTiles (DSet tset)
- {
- // clear out our old tiles list
- _tiles.clear();
-
- // copy the tiles from the set into our local list
- CollectionUtil.addAll(_tiles, tset.entries());
-
- // sort the list
- Collections.sort(_tiles);
-
- // recompute our desired dimensions and then have our parent
- // adjust to our changed size
- computeDimensions();
- }
-
- /**
- * 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 setPiecens (DSet piecens)
- {
- // just iterate over the set placing each of the piecens in turn
- Iterator iter = piecens.entries();
- 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 (AtlantiTile 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;
- }
-
- // add the tile
- _tiles.add(tile);
-
- // reference this as our most recently placed tile
- _lastPlacedTile = tile;
-
- // 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) {
- AtlantiTile tile = (AtlantiTile)_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
- repaintTile(tile);
-
- } else {
- Log.warning("Requested to place piecen for which we could " +
- "find no associated tile! [piecen=" + piecen + "].");
- }
- }
-
- /**
- * When a piecen is removed (after scoring it), this method should be
- * called to update the board display.
- */
- public void clearPiecen (Object key)
- {
- // locate the tile associated with this piecen key
- int tsize = _tiles.size();
- for (int i = 0; i < tsize; i++) {
- AtlantiTile tile = (AtlantiTile)_tiles.get(i);
- if (tile.getKey().equals(key)) {
- // clear the piecen out of the tile
- tile.clearPiecen();
- // and repaint
- repaintTile(tile);
- // and get on out
- return;
- }
- }
-
- Log.warning("Requested to clear piecen for which we could " +
- "find no associated tile! [key=" + key + "].");
- }
-
- /**
- * Turn off the ability to place a piecen on the most recently played
- * tile. This function assumes that the mouse will not be over a valid
- * piecen placement at the time this function is called (it expects
- * that it will be over a button of some sort that says something to
- * the effect of "skip placement for this turn").
- */
- public void cancelPiecenPlacement ()
- {
- _placingPiecen = false;
- }
-
- /**
- * If we freed up a placeable piecen that we didn't have when we
- * placed our tile, this can be called to reenable piecen placement.
- */
- public void enablePiecenPlacement ()
- {
- _placingPiecen = true;
- }
-
- /**
- * Sets the tile to be placed on the board. The tile will be displayed
- * in the square under the mouse cursor where it can be legally placed
- * and its orientation will be determined based on the pointer's
- * proximity to the edges of the target square. When the user clicks
- * the mouse while the tile is in a placeable position, a
- * TILE_PLACED command will be dispatched to the
- * controller in scope. The coordinates and orientation of the tile
- * will be available by fetching the tile back via {@link
- * #getPlacedTile}. The tile provided to this method will not be
- * modified.
- *
- * @param tile the new tile to be placed or null if no tile is to
- * currently be placed.
- */
- public void setTileToBePlaced (AtlantiTile tile)
- {
- Log.info("Setting tile to be placed [tile=" + tile + "].");
-
- // make a copy of this tile so that we can play with it
- _placingTile = (AtlantiTile)tile.clone();;
-
- // update our internal state based on this new placing tile
- if (_placingTile != null) {
- updatePlacingInfo(true);
- }
- }
-
- /**
- * Returns the last tile placed by the user.
- */
- public AtlantiTile getPlacedTile ()
- {
- return _placedTile;
- }
-
- // documentation inherited
- public void doLayout ()
- {
- super.doLayout();
-
- // compute our translation coordinates based on our size
- _tx = (getWidth() - TILE_WIDTH * _width)/2;
- _ty = (getHeight() - TILE_HEIGHT * _height)/2;
- }
-
- /**
- * Causes the supplied tile to be repainted.
- */
- public void repaintTile (AtlantiTile tile)
- {
- int offx = _tx + (tile.x + _origX) * TILE_WIDTH;
- int offy = _ty + (tile.y + _origY) * TILE_HEIGHT;
- repaint(offx, offy, TILE_WIDTH, TILE_HEIGHT);
- }
-
- // documentation inherited
- public void paintComponent (Graphics g)
- {
- super.paintComponent(g);
-
- Graphics2D g2 = (Graphics2D)g;
-
- // center the tile display if we are bigger than we need to be
- g.translate(_tx, _ty);
-
- // iterate over our tiles, painting each of them
- int tsize = _tiles.size();
- for (int i = 0; i < tsize; i++) {
- AtlantiTile tile = (AtlantiTile)_tiles.get(i);
- tile.paint(g2, _origX, _origY);
- }
-
- // if we have a placing tile, draw that one as well
- if (_placingTile != null && _validPlacement) {
- // if the current position is valid, draw the placing tile
- _placingTile.paint(g2, _origX, _origY);
-
- // draw a green rectangle around the placing tile
- g.setColor(Color.blue);
- int sx = (_placingTile.x + _origX) * TILE_WIDTH;
- int sy = (_placingTile.y + _origY) * TILE_HEIGHT;
- g.drawRect(sx, sy, TILE_WIDTH-1, TILE_HEIGHT-1);
- }
-
- // 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-1, TILE_HEIGHT-1);
- }
-
- // draw a white rectangle around the last placed
- if (_lastPlacedTile != null) {
- g.setColor(Color.white);
- int sx = (_lastPlacedTile.x + _origX) * TILE_WIDTH;
- int sy = (_lastPlacedTile.y + _origY) * TILE_HEIGHT;
- g.drawRect(sx, sy, TILE_WIDTH-1, TILE_HEIGHT-1);
- }
-
- // undo our translations
- g.translate(-_tx, -_ty);
- }
-
- /** Called by our adapter when the mouse moves. */
- protected void mouseMoved (MouseEvent evt)
- {
- // we always want to know about our last mouse coordinates
- _mouseX = evt.getX() - _tx;
- _mouseY = evt.getY() - _ty;
-
- if (_placingTile != null) {
- // if we have a tile to be placed, update its coordinates (it
- // will automatically be repainted)
- updatePlacingInfo(false);
-
- } 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(_newPiecenColor, 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) {
- repaintTile(_placedTile);
- }
- }
- }
-
- /** Called by our adapter when the mouse is clicked. */
- protected void mouseClicked (MouseEvent evt)
- {
- int modifiers = evt.getModifiers();
-
- // if this is a right button click, and we're in piecen placing
- // mode, generate a PLACE_NOTHING notification instead
- if (_placingPiecen && (modifiers & MouseEvent.BUTTON3_MASK) != 0) {
- // stop piecen placement
- _placingPiecen = false;
- // clear out any placed piecen because we're placing nothing
- if (_placedTile != null && _placedTile.piecen != null) {
- _placedTile.piecen = null;
- repaintTile(_placedTile);
- }
- // post the action
- Controller.postAction(this, PLACE_NOTHING);
-
- } else {
- // ignore non-button one presses other than cancel piecen
- // placement
- if ((modifiers & MouseEvent.BUTTON1_MASK) == 0) {
- return;
- }
- }
-
- // if we have a placing tile and it's in a valid position, we want
- // to dispatch an action letting the controller know that the user
- // placed it
- if (_placingTile != null && _validPlacement) {
- // move the placing tile to the placed tile
- _placedTile = _placingTile;
- _placingTile = null;
-
- // inherit claims on the placed tile
- TileUtil.inheritClaims(_tiles, _placedTile);
-
- // post the action
- Controller.postAction(this, TILE_PLACED);
-
- // move into placing piecen mode
- _placingPiecen = true;
-
- // recompute our dimensions (which will relayout or repaint)
- computeDimensions();
- }
-
- // if we're placing a piecen and the piecen is in a valid
- // position, we want to dispatch an action letting the controller
- // know that the user placed it
- if (_placingPiecen && _placedTile != null &&
- _placedTile.piecen != null) {
- // clear out placing piecen mode
- _placingPiecen = false;
-
- // post the action
- Controller.postAction(this, PIECEN_PLACED);
- }
- }
-
- /**
- * Updates the coordinates and orientation of the placing tile based
- * on the last known coordinates of the mouse and causes it to be
- * repainted.
- */
- protected void updatePlacingInfo (boolean force)
- {
- boolean updated = false;
-
- // convert mouse coordinates into tile coordinates and offset them
- // by the origin
- int x = divFloor(_mouseX, TILE_WIDTH) - _origX;
- int y = divFloor(_mouseY, TILE_HEIGHT) - _origY;
-
- // if these are different than the values currently in the placing
- // tile, update the tile coordinates
- if (_placingTile.x != x || _placingTile.y != y || force) {
- // if we have a valid orientation presently, and we're moving,
- // we need to clear out the old orientation
- if (_validPlacement) {
- repaintTile(_placingTile);
- }
-
- // update the coordinates of the tile
- _placingTile.x = x;
- _placingTile.y = y;
-
- // make a note that we moved
- updated = true;
-
- // we also need to recompute the valid orientations for the
- // tile in this new position
- _validOrients = TileUtil.computeValidOrients(_tiles, _placingTile);
-
- // if we've changed positions, clear out our valid placement
- // flag
- _validPlacement = false;
- }
-
- // determine if we should change the orientation based on the
- // position of the mouse within the tile boundaries
- int rx = _mouseX % TILE_WIDTH;
- int ry = _mouseY % TILE_HEIGHT;
- int orient = coordToOrient(rx, ry);
-
- // scan for a legal orientation that is closest to our desired
- // orientation
- for (int i = 0; i < 4; i++) {
- int candOrient = (orient+i)%4;
- if (_validOrients[candOrient]) {
- if (_placingTile.orientation != candOrient) {
- _placingTile.orientation = candOrient;
- // make a note that we moved
- updated = true;
- }
- _validPlacement = true;
- break;
- }
- }
-
- // if we now have a valid orientation and something was changed,
- // we want to repaint at the new tile location
- if (_validPlacement && updated) {
- repaintTile(_placingTile);
- }
- }
-
- /**
- * Converts mouse coordinates which are relative to a particular tile,
- * into an orientation based on the position within that tile. A tile
- * is divided up into four quadrants by lines connecting its four
- * corners. If the tile is in a quadrant closes to an edge, it is
- * converted to the orientation corresponding with that edge.
- *
- * @param rx the mouse coordinates modulo tile width.
- * @param ry the mouse coordinates modulo tile height.
- *
- * @return the orientation desired for the tile in which the mouse
- * resides.
- */
- protected int coordToOrient (int rx, int ry)
- {
- if (rx > ry) {
- if (rx > (TILE_HEIGHT - ry)) {
- return EAST;
- } else {
- return NORTH;
- }
- } else {
- if (rx > (TILE_HEIGHT - ry)) {
- return SOUTH;
- } else {
- return WEST;
- }
- }
- }
-
- /** Divides the two integers returning the floor of the divided value
- * rather than its truncation. */
- protected static int divFloor (int value, int divisor)
- {
- return (int)Math.floor((double)value/divisor);
- }
-
- // documentation inherited
- public Dimension getPreferredSize ()
- {
- if (_tiles.size() == 0) {
- return new Dimension(100, 100);
-
- } else {
- return new Dimension(TILE_WIDTH * _width, TILE_HEIGHT * _height);
- }
- }
-
- /**
- * Determines how big we want to be based on where the tiles have been
- * 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
- int tsize = _tiles.size();
- for (int i = 0; i < tsize; i++) {
- AtlantiTile tile = (AtlantiTile)_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;
- }
- }
-
- // spread our bounds out by one
- 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();
- }
-
- // always repaint because revalidation doesn't always seem to
- // result in a repaint
- repaint();
- }
-
- /** Test code. */
- public static void main (String[] args)
- {
- JFrame frame = new JFrame("Board test");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- AtlantiBoard board = new AtlantiBoard();
-
- TestDSet set = new TestDSet();
- set.addTile(new AtlantiTile(CITY_TWO, true, WEST, 0, 0));
- set.addTile(new AtlantiTile(CITY_TWO, false, WEST, -1, 1));
- set.addTile(new AtlantiTile(CITY_ONE, false, SOUTH, -1, -1));
- AtlantiTile zero = new AtlantiTile(CURVED_ROAD, false, WEST, 0, 2);
- set.addTile(zero);
- AtlantiTile one = new AtlantiTile(TWO_CITY_TWO, false, NORTH, 0, 1);
- set.addTile(one);
- set.addTile(new AtlantiTile(CITY_THREE, false, WEST, 1, 1));
- set.addTile(new AtlantiTile(CITY_THREE_ROAD, false, EAST, 1, 2));
- set.addTile(new AtlantiTile(CITY_THREE, false, NORTH, -1, 0));
- AtlantiTile two = new AtlantiTile(CITY_ONE, false, EAST, -2, 0);
- set.addTile(two);
- board.setTiles(set);
-
- AtlantiTile placing = new AtlantiTile(CITY_TWO, false, NORTH, 0, 0);
- board.setTileToBePlaced(placing);
-
- // set a feature group to test propagation
- List tiles = new ArrayList();
- CollectionUtil.addAll(tiles, set.entries());
- Collections.sort(tiles);
-
- zero.setPiecen(new Piecen(Piecen.GREEN, 0, 0, 2), tiles);
- one.setPiecen(new Piecen(Piecen.BLUE, 0, 0, 0), tiles);
- two.setPiecen(new Piecen(Piecen.RED, 0, 0, 1), tiles);
-
- Log.info("Incomplete road: " +
- TileUtil.computeFeatureScore(tiles, zero, 2));
-
- Log.info("Completed city: " +
- TileUtil.computeFeatureScore(tiles, two, 1));
-
- Log.info("Incomplete city: " +
- TileUtil.computeFeatureScore(tiles, one, 2));
-
- frame.getContentPane().add(board, BorderLayout.CENTER);
- frame.pack();
- SwingUtil.centerWindow(frame);
- frame.show();
- }
-
- protected static class TestDSet extends DSet
- {
- public void addTile (AtlantiTile tile)
- {
- add(tile);
- }
- }
-
- /** A reference to our tile set. */
- protected ArrayList _tiles = new ArrayList();
-
- /** The tile currently being placed by the user. */
- protected AtlantiTile _placingTile;
-
- /** The last tile being placed by the user. */
- protected AtlantiTile _placedTile;
-
- /** The last tile placed on the board via {@link #addTile}. */
- protected AtlantiTile _lastPlacedTile;
-
- /** 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;
-
- /** An array indicating which of the four directions are valid
- * placements based on the current position of the placing tile. */
- protected boolean[] _validOrients;
-
- /** The color to use when creating new piecens. */
- protected int _newPiecenColor = Piecen.BLUE;
-
- /** Our render offset in pixels. */
- protected int _tx, _ty;
-
- /** The offset in tile coordinates of the origin. */
- protected int _origX, _origY;
-
- /** The width and height of the board in tile coordinates. */
- protected int _width, _height;
-
- /** The last known position of the mouse. */
- protected int _mouseX, _mouseY;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiConfigurator.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiConfigurator.java
deleted file mode 100644
index 63de441b..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiConfigurator.java
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// $Id: AtlantiConfigurator.java,v 1.1 2002/12/12 05:51:53 mdb Exp $
-
-package com.samskivert.atlanti.client;
-
-import com.samskivert.swing.SimpleSlider;
-import com.samskivert.swing.VGroupLayout;
-
-import com.threerings.micasa.lobby.table.TableGameConfigurator;
-
-import com.samskivert.atlanti.data.AtlantiConfig;
-
-/**
- * Provides a user interface for configuring a game.
- */
-public class AtlantiConfigurator extends TableGameConfigurator
-{
- // documentation inherited
- protected void createConfigInterface ()
- {
- super.createConfigInterface();
-
-// _boardSize = new SimpleSlider("Board size:", 16, 48, 32);
-// add(_boardSize, VGroupLayout.FIXED);
-// _handSize = new SimpleSlider("Hand size:", 2, 5, 5);
-// add(_handSize, VGroupLayout.FIXED);
- }
-
- // documentation inherited
- protected void gotGameConfig ()
- {
- super.gotGameConfig();
- _vconfig = (AtlantiConfig)_config;
-
-// // configure our elements
-// _boardSize.setValue(_vconfig.boardWidth);
-// _handSize.setValue(_vconfig.handSize);
- }
-
- // documentation inherited
- protected void flushGameConfig ()
- {
- super.flushGameConfig();
-
-// // configure our elements
-// _vconfig.boardWidth = _boardSize.getValue();
-// _vconfig.boardHeight = _boardSize.getValue();
-// _vconfig.handSize = _handSize.getValue();
- }
-
- protected AtlantiConfig _vconfig;
-// protected SimpleSlider _boardSize;
-// protected SimpleSlider _handSize;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiController.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiController.java
deleted file mode 100644
index 4bf6e70e..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiController.java
+++ /dev/null
@@ -1,223 +0,0 @@
-//
-// $Id
-
-package com.samskivert.atlanti.client;
-
-import java.awt.event.ActionEvent;
-import com.samskivert.util.ListUtil;
-import com.threerings.util.Name;
-
-import com.threerings.presents.dobj.AttributeChangedEvent;
-import com.threerings.presents.dobj.DSet;
-import com.threerings.presents.dobj.EntryAddedEvent;
-import com.threerings.presents.dobj.EntryRemovedEvent;
-import com.threerings.presents.dobj.EntryUpdatedEvent;
-import com.threerings.presents.dobj.MessageEvent;
-import com.threerings.presents.dobj.SetListener;
-
-import com.threerings.crowd.data.BodyObject;
-import com.threerings.crowd.data.PlaceObject;
-import com.threerings.crowd.client.PlaceView;
-
-import com.threerings.parlor.game.GameController;
-import com.threerings.parlor.turn.TurnGameController;
-import com.threerings.parlor.turn.TurnGameControllerDelegate;
-import com.threerings.parlor.util.ParlorContext;
-
-import com.threerings.micasa.util.MiCasaContext;
-
-import com.samskivert.atlanti.Log;
-import com.samskivert.atlanti.data.AtlantiCodes;
-import com.samskivert.atlanti.data.AtlantiObject;
-import com.samskivert.atlanti.data.AtlantiTile;
-import com.samskivert.atlanti.data.Piecen;
-import com.samskivert.atlanti.util.TileUtil;
-
-/**
- * The main coordinator of user interface activities on the client-side of
- * the game.
- */
-public class AtlantiController extends GameController
- implements TurnGameController, AtlantiCodes, SetListener
-{
- /**
- * Creates our controller and prepares it for operation.
- */
- public AtlantiController ()
- {
- addDelegate(_delegate = new TurnGameControllerDelegate(this));
- }
-
- // documentation inherited
- protected void didInit ()
- {
- super.didInit();
-
- // get a handle on our body object
- _self = (BodyObject)_ctx.getClient().getClientObject();
- }
-
- // documentation inherited
- protected PlaceView createPlaceView ()
- {
- _panel = new AtlantiPanel((MiCasaContext)_ctx, this);
- return _panel;
- }
-
- // documentation inherited
- public void willEnterPlace (PlaceObject plobj)
- {
- super.willEnterPlace(plobj);
-
- // get a casted reference to our game object
- _venobj = (AtlantiObject)plobj;
-
- // find out what our index is and use that as our piecen color
- _selfIndex = ListUtil.indexOfEqual(_venobj.players, _self.username);
- if (_selfIndex != -1) {
- // use our player index as the piecen color directly
- _panel.board.setNewPiecenColor(_selfIndex);
- }
-
- // 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);
-
- // if it's our turn, set the tile to be placed
- if (_delegate.isOurTurn()) {
- _panel.board.setTileToBePlaced(_venobj.currentTile);
- }
- }
-
- // documentation inherited
- public void turnDidChange (Name turnHolder)
- {
- // if it's our turn, set the tile to be placed
- if (turnHolder.equals(_self.username)) {
- _panel.board.setTileToBePlaced(_venobj.currentTile);
- }
- }
-
- // documentation inherited
- public void attributeChanged (AttributeChangedEvent event)
- {
- super.attributeChanged(event);
-
- // handle the setting of the board state
- if (event.getName().equals(AtlantiObject.TILES)) {
- _panel.board.setTiles(_venobj.tiles);
-
- } else if (event.getName().equals(AtlantiObject.PIECENS)) {
- _panel.board.setPiecens(_venobj.piecens);
- }
- }
-
- // documentation inherited
- public void entryAdded (EntryAddedEvent event)
- {
- // we care about additions to TILES and PIECENS
- if (event.getName().equals(AtlantiObject.TILES)) {
- // a tile was added, add it to the board
- AtlantiTile tile = (AtlantiTile)event.getEntry();
- _panel.board.addTile(tile);
-
- } else if (event.getName().equals(AtlantiObject.PIECENS)) {
- // a piecen was added, place it on the board
- Piecen piecen = (Piecen)event.getEntry();
- _panel.board.placePiecen(piecen);
- }
- }
-
- // documentation inherited
- public void entryUpdated (EntryUpdatedEvent event)
- {
- }
-
- // documentation inherited
- public void entryRemoved (EntryRemovedEvent event)
- {
- if (event.getName().equals(AtlantiObject.PIECENS)) {
- // a piecen was removed, update the board
- _panel.board.clearPiecen(event.getKey());
- }
- }
-
- // documentation inherited
- public boolean handleAction (ActionEvent action)
- {
- if (action.getActionCommand().equals(TILE_PLACED)) {
- AtlantiTile tile = _panel.board.getPlacedTile();
-
- // the user placed the tile into a valid location. grab the
- // placed tile from the board and submit it to the server
- Object[] args = new Object[] { tile };
- MessageEvent mevt = new MessageEvent(
- _venobj.getOid(), PLACE_TILE_REQUEST, args);
- _ctx.getDObjectManager().postEvent(mevt);
-
- // if we have no piecens to place or if there are no unclaimed
- // features on the placed tile, we immediately disable piecen
- // placement in the board and expect that the server will end
- // our turn
- int pcount = TileUtil.countPiecens(_venobj.piecens, _selfIndex);
- if (pcount >= PIECENS_PER_PLAYER || !tile.hasUnclaimedFeature()) {
- _panel.board.cancelPiecenPlacement();
- _panel.noplace.setEnabled(false);
-
- } else {
- // otherwise, 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)) {
- // turn off piecen placement in the board
- _panel.board.cancelPiecenPlacement();
-
- // 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 if (action.getActionCommand().equals(BACK_TO_LOBBY)) {
- // bail on out
- _ctx.getLocationDirector().moveBack();
-
- } else {
- return super.handleAction(action);
- }
-
- return true;
- }
-
- /** Our turn game delegate. */
- protected TurnGameControllerDelegate _delegate;
-
- /** A reference to our game panel. */
- protected AtlantiPanel _panel;
-
- /** A reference to our game panel. */
- protected AtlantiObject _venobj;
-
- /** A reference to our body object. */
- protected BodyObject _self;
-
- /** Our player index or -1 if we're not a player. */
- protected int _selfIndex;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiPanel.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiPanel.java
deleted file mode 100644
index 081491c2..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/AtlantiPanel.java
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// $Id
-
-package com.samskivert.atlanti.client;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Frame;
-
-import javax.swing.*;
-import javax.swing.event.AncestorEvent;
-import javax.swing.event.AncestorListener;
-
-import com.samskivert.swing.Controller;
-import com.samskivert.swing.ControllerProvider;
-import com.samskivert.swing.HGroupLayout;
-import com.samskivert.swing.VGroupLayout;
-
-import com.threerings.media.image.ImageManager;
-import com.threerings.media.tile.TileManager;
-import com.threerings.resource.ResourceManager;
-
-import com.threerings.crowd.data.PlaceObject;
-import com.threerings.crowd.client.PlaceView;
-
-import com.threerings.micasa.client.ChatPanel;
-import com.threerings.micasa.util.MiCasaContext;
-
-import com.samskivert.atlanti.Log;
-import com.samskivert.atlanti.data.AtlantiCodes;
-import com.samskivert.atlanti.data.AtlantiTile;
-import com.samskivert.atlanti.util.PiecenUtil;
-
-/**
- * The top-level user interface component for the game display.
- */
-public class AtlantiPanel extends JPanel
- implements PlaceView, ControllerProvider, AtlantiCodes
-{
- /** A reference to the board that is accessible to the controller. */
- public AtlantiBoard board;
-
- /** A reference to our _noplace button. */
- public JButton noplace;
-
- /**
- * Constructs a new game display.
- */
- public AtlantiPanel (MiCasaContext ctx, AtlantiController controller)
- {
- // give ourselves a wee bit of a border
- setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
-
- HGroupLayout gl = new HGroupLayout(HGroupLayout.STRETCH);
- gl.setOffAxisPolicy(HGroupLayout.STRETCH);
- setLayout(gl);
-
- // create the board
- board = new AtlantiBoard();
-
- // create a scroll area to contain the board
- JScrollPane scrolly = new JScrollPane(board);
- add(scrolly);
-
- // create our side panel
- VGroupLayout sgl = new VGroupLayout(VGroupLayout.STRETCH);
- sgl.setOffAxisPolicy(VGroupLayout.STRETCH);
- sgl.setJustification(VGroupLayout.TOP);
- JPanel sidePanel = new JPanel(sgl);
-
- // add a big fat label because we love it!
- JLabel vlabel = new JLabel("Atlantissonne!");
- vlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
- vlabel.setForeground(Color.black);
- sidePanel.add(vlabel, VGroupLayout.FIXED);
-
- // add a player info view to the side panel
- sidePanel.add(new JLabel("Scores:"), VGroupLayout.FIXED);
- sidePanel.add(new PlayerInfoView(), VGroupLayout.FIXED);
-
- // add a turn indicator to the side panel
- sidePanel.add(new JLabel("Current turn:"), VGroupLayout.FIXED);
- sidePanel.add(new TurnIndicatorView(), VGroupLayout.FIXED);
-
- // add a "place nothing" button
- noplace = new JButton("Place nothing");
- noplace.setEnabled(false);
- noplace.setActionCommand(PLACE_NOTHING);
- noplace.addActionListener(Controller.DISPATCHER);
- sidePanel.add(noplace, VGroupLayout.FIXED);
-
- // add a chat box
- ChatPanel chat = new ChatPanel(ctx);
- chat.removeSendButton();
- sidePanel.add(chat);
-
- // add a "back" button
- JButton back = new JButton("Back to lobby");
- back.setActionCommand(BACK_TO_LOBBY);
- back.addActionListener(Controller.DISPATCHER);
- sidePanel.add(back, VGroupLayout.FIXED);
-
- // add our side panel to the main display
- add(sidePanel, HGroupLayout.FIXED);
-
- // we'll need this later to provide it
- _controller = controller;
- }
-
- // documentation inherited
- public void addNotify ()
- {
- super.addNotify();
-
- // we can't create our image manager until we have access to our
- // containing frame
- JRootPane rpane = getRootPane();
- ImageManager imgr = new ImageManager(_rmgr, rpane);
- TileManager tmgr = new TileManager(imgr);
- AtlantiTile.setManagers(imgr, tmgr);
- PiecenUtil.init(tmgr);
- }
-
- // documentation inherited
- public void willEnterPlace (PlaceObject plobj)
- {
- Log.info("Panel entered place.");
- }
-
- // documentation inherited
- public void didLeavePlace (PlaceObject plobj)
- {
- Log.info("Panel left place.");
- }
-
- // documentation inherited
- public Controller getController ()
- {
- return _controller;
- }
-
- /** A reference to our controller that we need to implement the {@link
- * ControllerProvider} interface. */
- protected AtlantiController _controller;
-
- // this stuff is all a bit of a hack right now. by all rights, the
- // MiCasa game app should set up the resource manager, because it
- // knows about that sort of stuff, and make it available via the
- // MiCasa context and we may have some better place for the tile
- // manager to live. but it's late and i want to get this working, so
- // fooey.
-
- /** Our resource manager. */
- protected static ResourceManager _rmgr = new ResourceManager("rsrc");
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/PlayerInfoView.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/PlayerInfoView.java
deleted file mode 100644
index 84250460..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/PlayerInfoView.java
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// $Id: PlayerInfoView.java,v 1.5 2002/12/12 05:51:54 mdb Exp $
-
-package com.samskivert.atlanti.client;
-
-import java.awt.Color;
-import java.awt.GridBagLayout;
-import java.awt.GridBagConstraints;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import com.threerings.util.Name;
-
-import com.threerings.presents.dobj.AttributeChangeListener;
-import com.threerings.presents.dobj.AttributeChangedEvent;
-import com.threerings.presents.dobj.SetListener;
-import com.threerings.presents.dobj.EntryAddedEvent;
-import com.threerings.presents.dobj.EntryUpdatedEvent;
-import com.threerings.presents.dobj.EntryRemovedEvent;
-
-import com.threerings.crowd.client.PlaceView;
-import com.threerings.crowd.data.PlaceObject;
-
-import com.samskivert.atlanti.data.AtlantiCodes;
-import com.samskivert.atlanti.data.AtlantiObject;
-import com.samskivert.atlanti.data.Feature;
-import com.samskivert.atlanti.util.TileUtil;
-
-/**
- * Displays each of the players in the game, their piece color and their
- * score.
- */
-public class PlayerInfoView
- extends JPanel
- implements PlaceView, AttributeChangeListener, SetListener
-{
- /**
- * Constructs a new player info panel, ready for insertion into the
- * game panel.
- */
- public PlayerInfoView ()
- {
- setLayout(new GridBagLayout());
-
- // we don't add our player info until we know how many players are
- // in the game (which we find out once we enter the game room)
- }
-
- // documentation inherited
- public void willEnterPlace (PlaceObject plobj)
- {
- // we want to grab a reference to the game object and add
- // ourselves as an attribute change listener
- _atlobj = (AtlantiObject)plobj;
- _atlobj.addListener(this);
-
- // we need score and piecen labels arrays so that we can keep
- // track of per player information
- _scoreLabels = new JLabel[_atlobj.players.length];
- _piecenLabels = new JLabel[_atlobj.players.length];
-
- // now that we're here, we can add an entry for every player
- for (int i = 0; i < _atlobj.players.length; i++) {
- addPlayer(i, _atlobj.players[i]);
- }
-
- // if we have scores, update them
- if (_atlobj.scores != null) {
- updateScores();
- // and the piecen count
- updatePiecenCount();
- }
- }
-
- /**
- * Adds a player to the display.
- */
- protected void addPlayer (int idx, Name username)
- {
- GridBagConstraints c = new GridBagConstraints();
-
- // create a label for their username
- c.fill = GridBagConstraints.HORIZONTAL;
- c.weightx = 1.0; // use up extra space on this label
- JLabel unlabel = new JLabel(username.toString());
- unlabel.setForeground(Feature.PIECEN_COLOR_MAP[idx]);
- add(unlabel, c);
-
- // create a label for their score
- c.weightx = 0.0; // size label to its preferred width
- c.ipadx = 5; // 5 pixels between this label and its neighbors
- c.fill = GridBagConstraints.NONE;
- _scoreLabels[idx] = new JLabel("0");
- _scoreLabels[idx].setForeground(Color.black);
- add(_scoreLabels[idx], c);
-
- // create a label for their piecen count
- c.gridwidth = GridBagConstraints.REMAINDER;
- c.ipadx = 0; // turn off padding
- _piecenLabels[idx] = new JLabel("(0)");
- _piecenLabels[idx].setForeground(Feature.PIECEN_COLOR_MAP[idx]);
- add(_piecenLabels[idx], c);
- }
-
- // documentation inherited
- public void didLeavePlace (PlaceObject plobj)
- {
- // remove our listening self
- _atlobj.removeListener(this);
- _atlobj = null;
- }
-
- // documentation inherited
- public void attributeChanged (AttributeChangedEvent event)
- {
- // we care about the scores (which change)
- if (event.getName().equals(AtlantiObject.SCORES)) {
- updateScores();
- }
- }
-
- // documentation inherited
- public void entryAdded (EntryAddedEvent event)
- {
- updatePiecenCount();
- }
-
- // documentation inherited
- public void entryUpdated (EntryUpdatedEvent event)
- {
- }
-
- // documentation inherited
- public void entryRemoved (EntryRemovedEvent event)
- {
- updatePiecenCount();
- }
-
- /**
- * Reads the scores from the game object and updates the view.
- */
- protected void updateScores ()
- {
- for (int i = 0; i < _atlobj.scores.length; i++) {
- _scoreLabels[i].setText(Integer.toString(_atlobj.scores[i]));
- }
- }
-
- /**
- * Updates the count of remaining piecens for all of the players.
- */
- protected void updatePiecenCount ()
- {
- for (int i = 0; i < _atlobj.scores.length; i++) {
- int pcount = TileUtil.countPiecens(_atlobj.piecens, i);
- int pleft = AtlantiCodes.PIECENS_PER_PLAYER - pcount;
- _piecenLabels[i].setText("(" + pleft + ")");
- }
- }
-
- /** A reference to the game object. */
- protected AtlantiObject _atlobj;
-
- /** References to our score label components. */
- protected JLabel[] _scoreLabels;
-
- /** References to our piecen label components. */
- protected JLabel[] _piecenLabels;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/TileLabel.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/TileLabel.java
deleted file mode 100644
index e87b4581..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/TileLabel.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// $Id: TileLabel.java,v 1.2 2002/12/12 05:51:54 mdb Exp $
-
-package com.samskivert.atlanti.client;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-
-import javax.swing.JComponent;
-
-import com.samskivert.atlanti.data.AtlantiTile;
-import com.samskivert.atlanti.data.TileCodes;
-
-/**
- * Displays a single tile in a Swing component.
- */
-public class TileLabel extends JComponent
- implements TileCodes
-{
- /**
- * Configures the component to display the specified tile.
- *
- * @param tile a reference to the tile to display or null if no tile
- * should be displayed.
- */
- public void setTile (AtlantiTile tile)
- {
- _tile = tile;
- repaint();
- }
-
- // documentation inherited
- public void paintComponent (Graphics g)
- {
- super.paintComponent(g);
-
- // simply paint the tile if we have one
- if (_tile != null) {
- _tile.paint((Graphics2D)g, 0, 0);
- }
- }
-
- // documentation inherited
- public Dimension getPreferredSize ()
- {
- return new Dimension(TILE_WIDTH, TILE_HEIGHT);
- }
-
- /** The tile we are displaying. */
- protected AtlantiTile _tile;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/client/TurnIndicatorView.java b/projects/atlanti/src/java/com/samskivert/atlanti/client/TurnIndicatorView.java
deleted file mode 100644
index 83cb71c1..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/client/TurnIndicatorView.java
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// $Id: TurnIndicatorView.java,v 1.5 2002/12/12 06:07:49 mdb Exp $
-
-package com.samskivert.atlanti.client;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import com.samskivert.swing.VGroupLayout;
-
-import com.threerings.presents.dobj.AttributeChangeListener;
-import com.threerings.presents.dobj.AttributeChangedEvent;
-
-import com.threerings.crowd.data.PlaceObject;
-import com.threerings.crowd.client.PlaceView;
-
-import com.samskivert.atlanti.data.AtlantiObject;
-
-/**
- * Displays who the current turn holder is as well as the tile they are
- * currently placing.
- */
-public class TurnIndicatorView extends JPanel
- implements PlaceView, AttributeChangeListener
-{
- /**
- * Creates a new turn indicator view which in turn creates its
- * subcomponents.
- */
- public TurnIndicatorView ()
- {
- setLayout(new VGroupLayout());
-
- // add our turn holder display
- _whoLabel = new JLabel();
- add(_whoLabel);
-
- // and add our tile display
- _tileLabel = new TileLabel();
- add(_tileLabel);
-
- // and add a tile's remaining label
- _countLabel = new JLabel();
- add(_countLabel);
- }
-
- // documentation inherited
- public void willEnterPlace (PlaceObject plobj)
- {
- // we want to grab a reference to the game object and add
- // ourselves as an attribute change listener
- _atlobj = (AtlantiObject)plobj;
- _atlobj.addListener(this);
-
- // update our displays
- updateCurrentTile();
- updateGameState();
- updateTurnHolder();
- updateRemainingTiles();
- }
-
- // documentation inherited
- public void didLeavePlace (PlaceObject plobj)
- {
- // remove our listening self
- _atlobj.removeListener(this);
- _atlobj = null;
- }
-
- // documentation inherited
- public void attributeChanged (AttributeChangedEvent event)
- {
- if (event.getName().equals(AtlantiObject.CURRENT_TILE)) {
- // update the current tile display
- updateCurrentTile();
-
- } else if (event.getName().equals(AtlantiObject.STATE)) {
- // update the game state display
- updateGameState();
- // update the tiles remaining
- updateRemainingTiles();
-
- } else if (event.getName().equals(AtlantiObject.TURN_HOLDER)) {
- // update the turn holder
- updateTurnHolder();
-
- // update the tiles remaining when the turn changes
- updateRemainingTiles();
- }
- }
-
- protected void updateGameState ()
- {
- switch (_atlobj.state) {
- case AtlantiObject.AWAITING_PLAYERS:
- _whoLabel.setText("Awaiting players...");
- _tileLabel.setTile(null);
- break;
- case AtlantiObject.GAME_OVER:
- _whoLabel.setText("Game over.");
- _tileLabel.setTile(null);
- break;
- case AtlantiObject.CANCELLED:
- _whoLabel.setText("Cancelled.");
- _tileLabel.setTile(null);
- break;
- }
- }
-
- protected void updateTurnHolder ()
- {
- if (_atlobj.state == AtlantiObject.IN_PLAY) {
- _whoLabel.setText(_atlobj.turnHolder.toString());
- }
- }
-
- protected void updateCurrentTile ()
- {
- // display the tile to be placed
- _tileLabel.setTile(_atlobj.currentTile);
- }
-
- protected void updateRemainingTiles ()
- {
- _countLabel.setText("Tiles remaining: " +
- Math.max(71-_atlobj.tiles.size(), 0));
- }
-
- /** The label displaying whose turn it is. */
- protected JLabel _whoLabel;
-
- /** The label displaying the tile to be placed. */
- protected TileLabel _tileLabel;
-
- /** The label displaying the number of tiles remaining. */
- protected JLabel _countLabel;
-
- /** A reference to the game object. */
- protected AtlantiObject _atlobj;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiCodes.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiCodes.java
deleted file mode 100644
index d4c733e8..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiCodes.java
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// $Id: AtlantiCodes.java,v 1.6 2002/12/12 05:51:54 mdb Exp $
-
-package com.samskivert.atlanti.data;
-
-/**
- * Constants used by the Atlanti game code.
- */
-public interface AtlantiCodes
-{
- /** The message bundle identifier for translation messages. */
- public static final String ATLANTI_MESSAGE_BUNDLE = "atlanti";
-
- /** The number of piecens provided to each player. */
- public static final int PIECENS_PER_PLAYER = 7;
-
- /** The name of the command posted by the {@link AtlantiBoard} when
- * 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 AtlantiBoard} 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";
-
- /** 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";
-
- /** The name of the command posted by the "Back to lobby" button in
- * the side bar. */
- public static final String BACK_TO_LOBBY = "back_to_lobby";
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiConfig.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiConfig.java
deleted file mode 100644
index 9db45c9b..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiConfig.java
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// $Id: AtlantiConfig.java,v 1.4 2002/12/12 05:51:54 mdb Exp $
-
-package com.samskivert.atlanti.data;
-
-import java.io.IOException;
-
-import com.threerings.io.ObjectInputStream;
-import com.threerings.io.ObjectOutputStream;
-
-import com.threerings.parlor.data.TableConfig;
-import com.threerings.parlor.game.GameConfig;
-
-import com.samskivert.atlanti.client.AtlantiConfigurator;
-import com.samskivert.atlanti.client.AtlantiController;
-
-/**
- * Describes the configuration parameters for the game.
- */
-public class AtlantiConfig extends GameConfig
- implements TableConfig
-{
- // documentation inherited
- public Class getControllerClass ()
- {
- return AtlantiController.class;
- }
-
- // documentation inherited from interface
- public Class getConfiguratorClass ()
- {
- return AtlantiConfigurator.class;
- }
-
- // documentation inherited
- public String getManagerClassName ()
- {
- return "com.samskivert.atlanti.server.AtlantiManager";
- }
-
- // documentation inherited
- public int getMinimumPlayers ()
- {
- return 2;
- }
-
- // documentation inherited
- public int getMaximumPlayers ()
- {
- return 5;
- }
-
- // documentation inherited
- public int getDesiredPlayers ()
- {
- return _desiredPlayers;
- }
-
- // documentation inherited
- public void setDesiredPlayers (int desiredPlayers)
- {
- _desiredPlayers = desiredPlayers;
- }
-
- // documentation inherited
- public void writeObject (ObjectOutputStream out)
- throws IOException
- {
- out.defaultWriteObject();
- out.writeInt(_desiredPlayers);
- }
-
- // documentation inherited
- public void readObject (ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- _desiredPlayers = in.readInt();
- }
-
- /** The desired number of players for this game or -1 if there is no
- * specific desired number of players. */
- protected int _desiredPlayers;
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.dobj b/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.dobj
deleted file mode 100644
index 106a2104..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.dobj
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// $Id: AtlantiObject.dobj,v 1.2 2002/12/12 05:51:54 mdb Exp $
-
-package com.samskivert.atlanti.data;
-
-import com.threerings.presents.dobj.DSet;
-import com.threerings.util.Name;
-
-import com.threerings.parlor.game.GameObject;
-import com.threerings.parlor.turn.TurnGameObject;
-
-/**
- * The distributed object used to maintain state for the game.
- */
-public class AtlantiObject extends GameObject
- implements TurnGameObject
-{
- /** The username of the current turn holder. */
- public Name turnHolder;
-
- /** A set containing all of the tiles that are in play in this
- * game. */
- public DSet tiles = new DSet();
-
- /** The tile being placed by the current turn holder. This value is
- * only valid while it is someone's turn. */
- public AtlantiTile currentTile = AtlantiTile.STARTING_TILE;
-
- /** A set containing all of the piecens that are placed on the
- * board. */
- public DSet piecens = new DSet();
-
- /** The scores for each player. */
- public int[] scores;
-
- // documentation inherited from interface
- public Name[] getPlayers ()
- {
- return players;
- }
-
- // documentation inherited from interface
- public String getTurnHolderFieldName ()
- {
- return TURN_HOLDER;
- }
-
- // documentation inherited from interface
- public Name getTurnHolder ()
- {
- return turnHolder;
- }
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.java
deleted file mode 100644
index eff24e14..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiObject.java
+++ /dev/null
@@ -1,216 +0,0 @@
-//
-// $Id: AtlantiObject.java,v 1.10 2003/03/23 02:22:51 mdb Exp $
-
-package com.samskivert.atlanti.data;
-
-import com.threerings.presents.dobj.DSet;
-import com.threerings.util.Name;
-
-import com.threerings.parlor.game.GameObject;
-import com.threerings.parlor.turn.TurnGameObject;
-
-/**
- * The distributed object used to maintain state for the game.
- */
-public class AtlantiObject extends GameObject
- implements TurnGameObject
-{
- /** The field name of the turnHolder field. */
- public static final String TURN_HOLDER = "turnHolder";
-
- /** The field name of the tiles field. */
- public static final String TILES = "tiles";
-
- /** The field name of the currentTile field. */
- public static final String CURRENT_TILE = "currentTile";
-
- /** The field name of the piecens field. */
- public static final String PIECENS = "piecens";
-
- /** The field name of the scores field. */
- public static final String SCORES = "scores";
-
- /** The username of the current turn holder. */
- public Name turnHolder;
-
- /** A set containing all of the tiles that are in play in this
- * game. */
- public DSet tiles = new DSet();
-
- /** The tile being placed by the current turn holder. This value is
- * only valid while it is someone's turn. */
- public AtlantiTile currentTile = AtlantiTile.STARTING_TILE;
-
- /** A set containing all of the piecens that are placed on the
- * board. */
- public DSet piecens = new DSet();
-
- /** The scores for each player. */
- public int[] scores;
-
- // documentation inherited from interface
- public Name[] getPlayers ()
- {
- return players;
- }
-
- // documentation inherited from interface
- public String getTurnHolderFieldName ()
- {
- return TURN_HOLDER;
- }
-
- // documentation inherited from interface
- public Name getTurnHolder ()
- {
- return turnHolder;
- }
-
- /**
- * Requests that the turnHolder field be set to the specified
- * value. The local value will be updated immediately and an event
- * will be propagated through the system to notify all listeners that
- * the attribute did change. Proxied copies of this object (on
- * clients) will apply the value change when they received the
- * attribute changed notification.
- */
- public void setTurnHolder (Name turnHolder)
- {
- requestAttributeChange(TURN_HOLDER, turnHolder);
- this.turnHolder = turnHolder;
- }
-
- /**
- * Requests that the specified entry be added to the
- * tiles set. The set will not change until the event is
- * actually propagated through the system.
- */
- public void addToTiles (DSet.Entry elem)
- {
- requestEntryAdd(TILES, elem);
- }
-
- /**
- * Requests that the entry matching the supplied key be removed from
- * the tiles set. The set will not change until the
- * event is actually propagated through the system.
- */
- public void removeFromTiles (Comparable key)
- {
- requestEntryRemove(TILES, key);
- }
-
- /**
- * Requests that the specified entry be updated in the
- * tiles set. The set will not change until the event is
- * actually propagated through the system.
- */
- public void updateTiles (DSet.Entry elem)
- {
- requestEntryUpdate(TILES, elem);
- }
-
- /**
- * Requests that the tiles field be set to the
- * specified value. Generally one only adds, updates and removes
- * entries of a distributed set, but certain situations call for a
- * complete replacement of the set value. The local value will be
- * updated immediately and an event will be propagated through the
- * system to notify all listeners that the attribute did
- * change. Proxied copies of this object (on clients) will apply the
- * value change when they received the attribute changed notification.
- */
- public void setTiles (DSet tiles)
- {
- requestAttributeChange(TILES, tiles);
- this.tiles = tiles;
- }
-
- /**
- * Requests that the currentTile field be set to the specified
- * value. The local value will be updated immediately and an event
- * will be propagated through the system to notify all listeners that
- * the attribute did change. Proxied copies of this object (on
- * clients) will apply the value change when they received the
- * attribute changed notification.
- */
- public void setCurrentTile (AtlantiTile currentTile)
- {
- requestAttributeChange(CURRENT_TILE, currentTile);
- this.currentTile = currentTile;
- }
-
- /**
- * Requests that the specified entry be added to the
- * piecens set. The set will not change until the event is
- * actually propagated through the system.
- */
- public void addToPiecens (DSet.Entry elem)
- {
- requestEntryAdd(PIECENS, elem);
- }
-
- /**
- * Requests that the entry matching the supplied key be removed from
- * the piecens set. The set will not change until the
- * event is actually propagated through the system.
- */
- public void removeFromPiecens (Comparable key)
- {
- requestEntryRemove(PIECENS, key);
- }
-
- /**
- * Requests that the specified entry be updated in the
- * piecens set. The set will not change until the event is
- * actually propagated through the system.
- */
- public void updatePiecens (DSet.Entry elem)
- {
- requestEntryUpdate(PIECENS, elem);
- }
-
- /**
- * Requests that the piecens field be set to the
- * specified value. Generally one only adds, updates and removes
- * entries of a distributed set, but certain situations call for a
- * complete replacement of the set value. The local value will be
- * updated immediately and an event will be propagated through the
- * system to notify all listeners that the attribute did
- * change. Proxied copies of this object (on clients) will apply the
- * value change when they received the attribute changed notification.
- */
- public void setPiecens (DSet piecens)
- {
- requestAttributeChange(PIECENS, piecens);
- this.piecens = piecens;
- }
-
- /**
- * Requests that the scores field be set to the specified
- * value. The local value will be updated immediately and an event
- * will be propagated through the system to notify all listeners that
- * the attribute did change. Proxied copies of this object (on
- * clients) will apply the value change when they received the
- * attribute changed notification.
- */
- public void setScores (int[] scores)
- {
- requestAttributeChange(SCORES, scores);
- this.scores = scores;
- }
-
- /**
- * Requests that the indexth element of
- * scores field be set to the specified value. The local
- * value will be updated immediately and an event will be propagated
- * through the system to notify all listeners that the attribute did
- * change. Proxied copies of this object (on clients) will apply the
- * value change when they received the attribute changed notification.
- */
- public void setScoresAt (int value, int index)
- {
- requestElementUpdate(SCORES, new Integer(value), index);
- this.scores[index] = value;
- }
-}
diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiTile.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiTile.java
deleted file mode 100644
index 4aa3412e..00000000
--- a/projects/atlanti/src/java/com/samskivert/atlanti/data/AtlantiTile.java
+++ /dev/null
@@ -1,536 +0,0 @@
-//
-// $Id: AtlantiTile.java,v 1.17 2003/03/23 02:22:51 mdb Exp $
-
-package com.samskivert.atlanti.data;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Polygon;
-
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-
-import java.io.IOException;
-
-import java.util.List;
-import com.samskivert.util.IntTuple;
-import com.samskivert.util.StringUtil;
-
-import com.threerings.media.image.ImageManager;
-import com.threerings.media.tile.Tile;
-import com.threerings.media.tile.TileManager;
-import com.threerings.media.tile.UniformTileSet;
-
-import com.threerings.io.ObjectInputStream;
-import com.threerings.presents.dobj.DSet;
-
-import com.samskivert.atlanti.Log;
-import com.samskivert.atlanti.util.FeatureUtil;
-import com.samskivert.atlanti.util.PiecenUtil;
-import com.samskivert.atlanti.util.TileUtil;
-
-/**
- * Represents a single tile in play on the game board.
- *
- * Note: this should really be split into a pure data class
- * and an associated visualization class in the
- * atlanti.client package.
- */
-public class AtlantiTile
- implements DSet.Entry, TileCodes, Cloneable, Comparable
-{
- /** The starting tile. */
- public static final AtlantiTile STARTING_TILE =
- new AtlantiTile(CITY_ONE_ROAD_STRAIGHT, false, NORTH, 0, 0);
-
- /** Activate this to render a piecen on every feature (useful for the
- * tile geometry test). */
- public static boolean piecenDebug = false;
-
- /** The tile type. */
- public int type;
-
- /** Whether this tile has a shield on it. */
- public boolean hasShield;
-
- /** The tile's orientation. */
- public int orientation;
-
- /** The tile's x and y coordinates. */
- public int x, y;
-
- /** An array of claim group values that correspond to the features of
- * this tile. If a piecen has claimed a feature on this tile or that
- * connects to this tile, it will be represented here by a non-zero
- * claim group in the array slot that corresponds to the claimed
- * feature. */
- public transient int[] claims;
-
- /** A reference to our static feature descriptions. */
- public transient Feature[] features;
-
- /** A reference to the piecen on this tile or null if no piecen has
- * been placed on this tile. */
- public transient Piecen piecen;
-
- /**
- * Constructs a tile with all of the supplied tile information.
- */
- public AtlantiTile (int type, boolean hasShield, int orientation,
- int x, int y)
- {
- this.type = type;
- this.hasShield = hasShield;
- this.orientation = orientation;
- this.x = x;
- this.y = y;
-
- // initialize our feature info
- initFeatures();
- }
-
- /**
- * Constructs a tile with the type information set, but in the default
- * NORTH orientation and with no position.
- */
- public AtlantiTile (int type, boolean hasShield)
- {
- this(type, hasShield, NORTH, 0, 0);
- }
-
- /**
- * Constructs a blank tile, suitable for unserialization.
- */
- public AtlantiTile ()
- {
- // nothing doing
- }
-
- /**
- * Returns true if this tile has at leats one unclaimed feature.
- */
- public boolean hasUnclaimedFeature ()
- {
- boolean unclaimed = false;
- for (int i = 0; i < claims.length; i++) {
- unclaimed = (unclaimed || (claims[i] == 0));
- }
- return unclaimed;
- }
-
- /**
- * Looks for a feature in this tile that matches the supplied feature
- * edge mask and returns the index of that feature in this tile's
- * {@link #claims} array.
- *
- * @return the index of the matching feature or -1 if no feature
- * matched.
- */
- public int getFeatureIndex (int edgeMask)
- {
- // translate the feature mask into our orientation
- edgeMask = FeatureUtil.translateMask(edgeMask, -orientation);
-
- // 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;
- }
- }
-
- // no match
- 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
- * (which may be zero).
- *
- * @return the claim group to which the feature that matches the
- * supplied mask belongs, or zero if no feature matched the supplied
- * mask.
- */
- public int getFeatureGroup (int edgeMask)
- {
- int fidx = getFeatureIndex(edgeMask);
- return fidx < 0 ? 0 : claims[fidx];
- }
-
- /**
- * Sets the claim group for the feature with the specified index. This
- * also updates the claim group for any piecen that was placed on that
- * feature as well.
- *
- * @param featureIndex the index of the feature to update.
- * @param claimGroup the claim group to associate with the feature.
- */
- public void setClaimGroup (int featureIndex, int claimGroup)
- {
- // update the claim group slot for this feature
- claims[featureIndex] = claimGroup;
-
- // 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.
- *
- *
Note that this will call {@link TileUtil#setClaimGroup} 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) - { - int claimGroup = 0; - - // if we're adding a piecen to a feature that's already claimed, - // we want to inherit the claim number (this could happen when we - // show up in an in progress game) - if (claims[piecen.featureIndex] != 0) { - Log.info("Requested to add a piecen to a feature " + - "that has already been claimed [tile=" + this + - ", piecen=" + piecen + "]. Inheriting."); - claimGroup = claims[piecen.featureIndex]; - - } else { - // otherwise we generate a new claim group - claimGroup = TileUtil.nextClaimGroup(); - Log.info("Creating claim group [cgroup=" + claimGroup + - ", tile=" + this + ", fidx=" + piecen.featureIndex + "]."); - } - - // 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) { - TileUtil.setClaimGroup( - tiles, this, piecen.featureIndex, claimGroup); - // update our piecen with the claim group as well - piecen.claimGroup = claimGroup; - } - } - - /** - * Clears out any piecen reference that was previously set (does not - * clear out its associated claim group, however). - */ - public void clearPiecen () - { - piecen = null; - } - - /** - * Paints this tile to the specified graphics context at its assigned - * location, accounting for the supplied x and y offsets of the - * origin. - * - * @param g the graphics context to use when painting the tile. - * @param xoff the offset (in tile units) of the origin in the x - * direction. - * @param yoff the offset (in tile units) of the origin in the y - * direction. - */ - public void paint (Graphics2D g, int xoff, int yoff) - { - int tidx = type-1; - - // obtain our tile image - if (_tileImage == null) { - _tileImage = getTileImage(type); - } - - // compute our screen coordinates - int sx = (x + xoff) * TILE_WIDTH; - int sy = (y + yoff) * TILE_HEIGHT; - - // translate to our screen coordinates - g.translate(sx, sy); - - // render our tile image - if (_tileImage != null) { - if (orientation > 0) { - g.drawImage(_tileImage, _xforms[orientation], null); - } else { - g.drawImage(_tileImage, 0, 0, null); - } - - } else { - Log.warning("No tile image!? [type=" + type + - ", img=" + _tileImage + "]."); - } - -// // render our features -// for (int i = 0; i < features.length; i++) { -// // paint the feature -// features[i].paint(g, orientation, claims[i]); -// } - - // if we have a shield, draw a square in the lower right - if (hasShield) { - Point2D sspot = FeatureUtil.getShieldSpot(orientation); - Image image = getShieldImage(); - - if (image != null) { - int iwidth = image.getWidth(null); - int iheight = image.getHeight(null); - Composite ocomp = g.getComposite(); - g.setComposite(ALPHA_PLACING); - g.drawImage(image, (int)(sspot.getX() - iwidth/2), - (int)(sspot.getY() - iheight/2), null); - g.setComposite(ocomp); - - } else { - g.setColor(Color.orange); - g.drawRect((int)(sspot.getX()-5), - (int)(sspot.getY()-5), 10, 10); - } - } - - // if we have a piecen on this tile, render it as well - if (piecen != null || piecenDebug) { - for (int i = 0; i < features.length; i++) { - if (piecenDebug) { - Image pimg = PiecenUtil.getPiecenImage(0); - features[i].paintPiecen(g, orientation, pimg, 0); - - } else if (piecen.featureIndex == i) { - Image pimg = PiecenUtil.getPiecenImage(piecen.owner); - features[i].paintPiecen( - g, orientation, pimg, piecen.claimGroup); - } - } - } - -// // draw a rectangular outline -// g.setColor(Color.black); -// g.drawRect(0, 0, TILE_WIDTH-1, TILE_HEIGHT-1); - - // translate back out - g.translate(-sx, -sy); - } - - /** - * Returns a copy of this tile object. - */ - public Object clone () - { - return new AtlantiTile(type, hasShield, orientation, x, y); - } - - /** - * Used to order tiles (which is done by board position). - */ - public int compareTo (Object other) - { - // 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 AtlantiTile) { - AtlantiTile tile = (AtlantiTile)other; - return (tile.x == x) ? y - tile.y : x - tile.x; - - } else if (other instanceof IntTuple) { - 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 Comparable getKey () - { - // our key is our coordinates conflated into one integer - return new Integer((x + 128) * 256 + y + 128); - } - - /** - * After we've been unserialized we have to initialize some derived - * fields. - */ - public void readObject (ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - initFeatures(); - } - - /** - * Initializes this tile's feature management data structures. - */ - protected void initFeatures () - { - if (type > 0) { - // grab a reference to our feature information - features = FeatureUtil.getTileFeatures(type); - - // create our claims array - claims = new int[features.length]; - - } else { - Log.warning("Requested to init features without valid type " + - this + "."); - Thread.dumpStack(); - } - } - - /** - * Generates a string representation of this tile instance. - */ - public String toString () - { - return "[type=" + type + ", shield=" + hasShield + - ", orient=" + ORIENT_NAMES[orientation] + - ", pos=" + x + "/" + y + - ", claims=" + StringUtil.toString(claims) + - ", piecen=" + piecen + "]"; - } - - /** - * Someone needs to configure this so that we can display tiles on - * screen. - */ - public static void setManagers (ImageManager imgr, TileManager tmgr) - { - _imgr = imgr; - _tmgr = tmgr; - } - - /** - * Fetches the image for the tile of the specified type. - */ - protected static Image getTileImage (int type) - { - // load up the tile set if we haven't already - if (_tset == null) { - _tset = _tmgr.loadTileSet(TILES_IMG_PATH, - TILE_WIDTH, TILE_HEIGHT); - } - - // fetch the tile - return _tset.getRawTileImage(type-1); - } - - /** - * Fetches the shield image. - */ - protected static Image getShieldImage () - { - // load up the tile set if we haven't already - if (_stset == null) { - _stset = _tmgr.loadTileSet(SHIELD_IMG_PATH, - SHIELD_SIZE, SHIELD_SIZE); - } - - // fetch the tile - return _stset.getRawTileImage(0); - } - - /** The tile image that we use to render this tile. */ - protected transient Image _tileImage; - - /** Our image manager. */ - protected static ImageManager _imgr; - - /** Our tile manager. */ - protected static TileManager _tmgr; - - /** Our tile image tileset. */ - protected static UniformTileSet _tset; - - /** Our shield image tileset. */ - protected static UniformTileSet _stset; - - /** The path to our tileset image. */ - protected static final String TILES_IMG_PATH = "media/tiles.png"; - - /** The path to our shield image. */ - protected static final String SHIELD_IMG_PATH = "media/shield.png"; - - /** The size of the shield image (width and height). */ - protected static final int SHIELD_SIZE = 17; - - /** Three affine transforms for rendering an image in three rotated - * orientations. */ - protected static AffineTransform[] _xforms; - - static { - // the first element will be left blank - _xforms = new AffineTransform[4]; - - // create our three orientation transforms - 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); - // and save it - _xforms[orient] = (AffineTransform)xform.clone(); - } - } - - /** For rendering shields with alpha. */ - protected static final Composite ALPHA_PLACING = - AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/Feature.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/Feature.java deleted file mode 100644 index 541c5c01..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/data/Feature.java +++ /dev/null @@ -1,375 +0,0 @@ -// -// $Id: Feature.java,v 1.6 2002/12/12 05:51:54 mdb Exp $ - -package com.samskivert.atlanti.data; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Image; -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; - -import com.samskivert.atlanti.Log; -import com.samskivert.atlanti.util.FeatureUtil; -import com.samskivert.atlanti.util.TileUtil; - -/** - * Represents all of the necessary information for a particular feature of - * a particular tile. - */ -public class Feature - implements TileCodes -{ - /** Maps piecen color codes to colors. */ - public static Color[] PIECEN_COLOR_MAP = { - new Color(0x0246B7), // BLUE - new Color(0x028A12), // GREEN - new Color(0xF47A02), // ORANGE - new Color(0xC20292), // MAGENTA - new Color(0xB90202), // RED - new Color(0xFECA11), // YELLOW - }; - - /** 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; - } - // oh, just a teeny hack for aesthetic shield placement - if (type == -1) { - px += 2; py += 2; - } - 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 image the piecen image 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, Image image, - int claimGroup) - { - Point2D point = piecenSpots[orientation]; - int iwidth = image.getWidth(null); - int iheight = image.getHeight(null); - - // render the piecen image slightly transparent - Composite ocomp = g.getComposite(); - g.setComposite(ALPHA_PLACING); - g.drawImage(image, (int)(point.getX() - iwidth/2), - (int)(point.getY() - iheight/2), null); - g.setComposite(ocomp); - -// // 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; - } - - /** - * Generates a string representation of this feature. - */ - public String toString () - { - return "[type=" + FeatureUtil.typeToString(type) + - ", edgeMask=" + FeatureUtil.edgeMaskToString(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 - }; - - /** For rendering piecens with alpha. */ - protected static final Composite ALPHA_PLACING = - AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/Piecen.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/Piecen.java deleted file mode 100644 index 66f4692d..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/data/Piecen.java +++ /dev/null @@ -1,133 +0,0 @@ -// -// $Id: Piecen.java,v 1.4 2002/12/12 05:51:54 mdb Exp $ - -package com.samskivert.atlanti.data; - -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.Entry -{ - /** 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 owner of this piecen. */ - public int owner; - - /** 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 owner, int x, int y, int featureIndex) - { - this.owner = owner; - this.x = x; - this.y = y; - this.featureIndex = featureIndex; - } - - /** - * Constructs a blank piecen, suitable for unserialization. - */ - public Piecen () - { - } - - // documentation inherited - public Comparable 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(owner); - out.writeInt(x); - out.writeInt(y); - out.writeInt(featureIndex); - } - - // documentation inherited - public void readFrom (DataInputStream in) - throws IOException - { - owner = 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 AtlantiTile) { - AtlantiTile tile = (AtlantiTile)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 "[owner=" + owner + ", pos=" + x + "/" + y + - ", feat=" + featureIndex + ", claim=" + claimGroup + "]"; - } -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/data/TileCodes.java b/projects/atlanti/src/java/com/samskivert/atlanti/data/TileCodes.java deleted file mode 100644 index c558a994..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/data/TileCodes.java +++ /dev/null @@ -1,127 +0,0 @@ -// -// $Id: TileCodes.java,v 1.10 2002/12/12 05:51:54 mdb Exp $ - -package com.samskivert.atlanti.data; - -/** - * A repository for constants related to the tiles that are used in the - * game of Atlantissonne. - */ -public interface TileCodes -{ - /** A four-sided city tile. */ - public static final int CITY_FOUR = 1; - - /** A three-sided city tile. */ - public static final int CITY_THREE = 2; - - /** A three-sided city tile with a road. */ - public static final int CITY_THREE_ROAD = 3; - - /** A two-sided city tile with city openings adjacent to one - * another. */ - public static final int CITY_TWO = 4; - - /** A two-sided city tile with city openings adjacent to one another - * and a road connecting the other two sides. */ - public static final int CITY_TWO_ROAD = 5; - - /** A two-sided city tile with city openings on opposite sides of the - * tile. */ - public static final int CITY_TWO_ACROSS = 6; - - /** A two-sided city tile with two separate city arcs adjacent to one - * another and not connected to each other. */ - 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 TWO_CITY_TWO_ACROSS = 8; - - /** A one-sided city tile. */ - public static final int CITY_ONE = 9; - - /** A one-sided city tile with a city arc on top and a right facing - * curved road segment beneath it. */ - public static final int CITY_ONE_ROAD_RIGHT = 10; - - /** A one-sided city tile with a city arc on top and a left facing - * curved road segment beneath it. */ - public static final int CITY_ONE_ROAD_LEFT = 11; - - /** A one-sided city tile with a city arc on top and a road tee - * beneath it. */ - public static final int CITY_ONE_ROAD_TEE = 12; - - /** A one-sided city tile with a city arc on top and straight road - * segment beneath it. */ - public static final int CITY_ONE_ROAD_STRAIGHT = 13; - - /** A cloister tile. */ - public static final int CLOISTER_PLAIN = 14; - - /** A cloister tile with a road extending from the cloister. */ - public static final int CLOISTER_ROAD = 15; - - /** A four-way road intersection. */ - public static final int FOUR_WAY_ROAD = 16; - - /** A three-way road intersection. */ - public static final int THREE_WAY_ROAD = 17; - - /** A straight road segment. */ - public static final int STRAIGHT_ROAD = 18; - - /** A curved road segment. */ - public static final int CURVED_ROAD = 19; - - /** The number of different tile types. */ - public static final int TILE_TYPES = 19; - - - /** A tile orientation constant indicating the tile is in its default - * orientation. */ - public static final int NORTH = 0; - - /** A tile orientation constant indicating the tile is rotated 90 - * degrees clockwise from its default orientation. */ - public static final int EAST = 1; - - /** A tile orientation constant indicating the tile is rotated 180 - * degrees clockwise from its default orientation. */ - public static final int SOUTH = 2; - - /** A tile orientation constant indicating the tile is rotated 270 - * degrees clockwise from its default orientation. */ - public static final int WEST = 3; - - /** A mapping from orientation codes to a string representation. */ - public static final String[] ORIENT_NAMES = { "N", "E", "S", "W" }; - - - /** The tile image width in pixels. */ - public static int TILE_WIDTH = 64; - - /** The tile image height in pixels. */ - public static int TILE_HEIGHT = 64; - - - /** A tile edge constant indicating a city edge. */ - public static final int CITY = 0; - - /** A tile edge constant indicating a grass edge. */ - public static final int GRASS = 1; - - /** A tile edge constant indicating a road edge. */ - public static final int ROAD = 2; - - /** A constant indicating a cloister. */ - public static final int CLOISTER = 3; - - /** Human readable names to go along with the feature constants. */ - public static final String[] FEATURE_NAMES = { - "island", "fishery", "boardwalk", "temple" }; - - /** A flag used to mark a tile as part of a completed city. */ - public static final int COMPLETED_CITY = 0x01; -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManager.java b/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManager.java deleted file mode 100644 index 1570427f..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManager.java +++ /dev/null @@ -1,763 +0,0 @@ -// -// $Id: AtlantiManager.java,v 1.26 2004/08/28 02:17:06 mdb Exp $ - -package com.samskivert.atlanti.server; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import com.samskivert.util.HashIntMap; -import com.samskivert.util.StringUtil; - -import com.threerings.presents.dobj.EntryAddedEvent; -import com.threerings.presents.dobj.EntryRemovedEvent; -import com.threerings.presents.dobj.EntryUpdatedEvent; -import com.threerings.presents.dobj.DSet; -import com.threerings.presents.dobj.SetListener; -import com.threerings.presents.dobj.MessageEvent; - -import com.threerings.presents.dobj.MessageEvent; - -import com.threerings.crowd.chat.server.SpeakProvider; -import com.threerings.crowd.data.PlaceObject; - -import com.threerings.crowd.data.PlaceConfig; -import com.threerings.crowd.server.PlaceManager; - -import com.threerings.parlor.game.GameManager; -import com.threerings.parlor.turn.TurnGameManager; - -import com.samskivert.atlanti.Log; -import com.samskivert.atlanti.data.AtlantiCodes; -import com.samskivert.atlanti.data.AtlantiObject; -import com.samskivert.atlanti.data.AtlantiTile; -import com.samskivert.atlanti.data.Feature; -import com.samskivert.atlanti.data.Piecen; -import com.samskivert.atlanti.data.TileCodes; -import com.samskivert.atlanti.util.FeatureUtil; -import com.samskivert.atlanti.util.TileUtil; - -/** - * The main coordinator of the Atlantissonne game on the server side. - */ -public class AtlantiManager extends GameManager - implements TurnGameManager, AtlantiCodes, SetListener -{ - public AtlantiManager () - { - addDelegate(_delegate = new AtlantiManagerDelegate(this)); - } - - // documentation inherited - protected Class getPlaceObjectClass () - { - return AtlantiObject.class; - } - - public int getTilesInBox () - { - return _tilesInBox.size(); - } - - // documentation inherited - public void didInit () - { - super.didInit(); - - // register our message handlers - registerMessageHandler(PLACE_TILE_REQUEST, new PlaceTileHandler()); - registerMessageHandler( - PLACE_PIECEN_REQUEST, new PlacePiecenHandler()); - registerMessageHandler( - PLACE_NOTHING_REQUEST, new PlaceNothingHandler()); - } - - // documentation inherited - public void didStartup () - { - super.didStartup(); - - // grab our own casted game object reference - _atlobj = (AtlantiObject)_gameobj; - } - - /** - * In preparation for starting the game, we clear out the tile set and - * put the starting tile into place. - */ - protected void gameWillStart () - { - super.gameWillStart(); - - // generate a shuffled tile list - _tilesInBox = TileUtil.getStandardTileSet(); - Collections.shuffle(_tilesInBox); - -// // shave off most of the tiles for the moment -// while (_tilesInBox.size() > 15) { -// _tilesInBox.remove(0); -// } - - // clear out our board tiles - _tiles.clear(); - - // create a claim group vector - _claimGroupVector = new int[getPlayerCount()]; - - // clear out the scores - _atlobj.setScores(new int[getPlayerCount()]); - - // clear out the tile and piecen set - _atlobj.setTiles(new DSet()); - _atlobj.setPiecens(new DSet()); - - // and add the starting tile - AtlantiTile start = TileUtil.getStartingTile(); - _atlobj.addToTiles(start); - _tiles.add(start); - } - - // documentation inherited - public void turnWillStart () - { - // let the players know what the next tile is that should be - // played - AtlantiTile tile = (AtlantiTile)_tilesInBox.remove(0); - _atlobj.setCurrentTile(tile); - } - - // documentation inherited - public void turnDidStart () - { - // nothing doing - } - - // documentation inherited - public void turnDidEnd () - { - // if there are no tiles left, we end the game - if (_tilesInBox.size() == 0) { - endGame(); - } - } - - /** - * At the end of the game, we need to compute the final scores. - */ - protected void gameDidEnd () - { - super.gameDidEnd(); - - // compute the final scores by iterating over each tile and - // scoring its features - Piecen[] piecens = getPiecens(); - Iterator iter = _atlobj.tiles.entries(); - while (iter.hasNext()) { - AtlantiTile tile = (AtlantiTile)iter.next(); - scoreFeatures(tile, piecens, true); - } - - // lastly, we have to score the farms (cue the ominous drums)... - scoreFarms(); - - // update the final scores - _atlobj.setScores(_atlobj.scores); - } - - /** - * Creates an array of piecens based on the contents of the piecens - * set in the game object, suitable for passing to {@link - * #scoreFeatures}. - */ - protected Piecen[] getPiecens () - { - // create a piecen array that we can manipulate while scoring - Piecen[] piecens = new Piecen[_atlobj.piecens.size()]; - Iterator iter = _atlobj.piecens.entries(); - for (int i = 0; iter.hasNext(); i++) { - piecens[i] = (Piecen)iter.next(); - } - return piecens; - } - - /** - * Scores the features on this tile. - * - * @param tile the tile whose features should be scored. - * @param piecens an array of the pieces on the board which we can - * manipulate directly without having to wait for entry removed - * events to be dispatched. - * @param finalTally during the final tally, we score differently and - * we don't remove piecens from the board as we score them. - */ - protected void scoreFeatures ( - AtlantiTile tile, Piecen[] piecens, boolean finalTally) - { - // potentially score all features on the tile - for (int i = 0; i < tile.features.length; i++) { - // we only need to worry about ROAD and CITY features because - // those are the only features on this tile that we might have - // completed - Feature f = tile.features[i]; - if (f.type != TileCodes.CITY && f.type != TileCodes.ROAD) { - continue; - } - - // see if any piecens are even on a feature in this group - int cgroup = tile.claims[i]; - int[] cgv = getClaimGroupVector(cgroup, piecens); - if (cgv == null) { - // if not, we don't have anything to score -// Log.info("Not scoring unclaimed feature " + -// "[ttype=" + tile.type + ", feat=" + f + -// ", cgroup=" + cgroup + "]."); - continue; - } - - // we do have something to score, so we compute the score for - // this feature - int score = TileUtil.computeFeatureScore(_tiles, tile, i); - - // if the score is positive, it's a completed feature and we - // score it regardless, we score incomplete features only - // during the final tally - if (score > 0 || finalTally) { - String qual = (score > 0) ? "Completed" : "Incomplete"; - - // convert the score into a positive value - score = Math.abs(score); - - // adjust and report the scores - StringBuffer names = new StringBuffer(); - for (int p = 0; p < cgv.length; p++) { - // adjust the score - _atlobj.scores[p] += (score * cgv[p]); - - // append the scorers name to the list - if (cgv[p] > 0) { - if (names.length() > 0) { - names.append(", "); - } - names.append(getPlayerName(p)); - } - } - - String message = qual + " " + TileCodes.FEATURE_NAMES[f.type] + - " scored " + score + " points for " + names + "."; - SpeakProvider.sendInfo( - _atlobj, ATLANTI_MESSAGE_BUNDLE, message); - - Log.info("New scores: " + StringUtil.toString(_atlobj.scores)); - - // broadcast the new scores if this isn't the final tally - if (!finalTally) { - _atlobj.setScores(_atlobj.scores); - } - - // and free up the scored piecens - removePiecens(cgroup, piecens, finalTally); - - } else { -// Log.info("Not scoring incomplete feature " + -// "[ttype=" + tile.type + ", feat=" + f + -// ", score=" + score + "]."); - } - } - - // we also may have completed a cloister, so we check that as well - for (int dx = -1; dx < 2; dx++) { - for (int dy = -1; dy < 2; dy++) { - // find our neighbor and make sure they exist - AtlantiTile neighbor = - TileUtil.findTile(_tiles, tile.x + dx, tile.y + dy); - if (neighbor == null) { - continue; - } - - // scan their features arrays for claimed cloisters - for (int i = 0; i < neighbor.features.length; i++) { - Feature f = neighbor.features[i]; - Piecen p = neighbor.piecen; - - // is a cloister - if (f.type != TileCodes.CLOISTER) { - continue; - } - - // tile has a piecen - if (p == null) { -// Log.info("Skipping non-piecen having " + -// "cloister tile [tile=" + neighbor + -// ", feat=" + f + "]."); - continue; - } - - // piecen is on cloister feature - if (neighbor.claims[i] != p.claimGroup) { -// Log.info("Skipping cloister tile with piecen on " + -// "non-cloister [tile=" + neighbor + -// ", feat=" + f + "]."); - continue; - } - - // score the cloister - int score = TileUtil.computeFeatureScore( - _tiles, neighbor, i); - - // if it's completed or if we're doing the final - // tally, we score it - if (score > 0 || finalTally) { - String qual = (score > 0) ? - "complete" : "incomplete"; - - // coerce the score into positive land - score = Math.abs(score); - - // deliver a chat notification to tell the - // players about the score - String message = getPlayerName(p.owner) + " scored " + - score + " points for " + qual + " temple."; - SpeakProvider.sendInfo( - _atlobj, ATLANTI_MESSAGE_BUNDLE, message); - - // add the score to the owning player - _atlobj.scores[p.owner] += score; - - // only broadcast the updated scores if this isn't - // the final tally - if (!finalTally) { - _atlobj.setScores(_atlobj.scores); - } - - // and clear out the piecen (only removing it from - // the piecen set if we're not in the final tally) - removePiecen(p, !finalTally); - } - } - } - } - } - - /** - * Scores the farms, which is the final act of scoring. - */ - protected void scoreFarms () - { - HashIntMap cities = new HashIntMap(); - int[] cityScores = new int[getPlayerCount()]; - - // clear out the claims for incompleted cities and claim unclaimed - // completed cities - TileUtil.prepCitiesForScoring(_tiles); - - // do the big process-ola - int tsize = _tiles.size(); - for (int i = 0; i < tsize; i++) { - AtlantiTile tile = (AtlantiTile)_tiles.get(i); - - // iterate over all of the city features in this tile - for (int f = 0; f < tile.features.length; f++) { - // get the claim group for this feature - int cityClaim = tile.claims[f]; - - // skip unclaimed and non-city features - if (tile.features[f].type != TileCodes.CITY || - cityClaim == 0) { - continue; - } - - // get the list associated with this claim group - int[] claims = (int[])cities.get(cityClaim); - if (claims == null) { - // create a claim vector if we've not got one. if a - // city had 35 separately claimed farms around it, all - // the piecens in the game would be in play and the - // city would not have been claimed which would be an - // extremely pathological case, but we love pathology - // (especially when we don't have a resizable int list - // class handy) - claims = new int[35]; - cities.put(cityClaim, claims); - } - - // iterate over all of the grass features that are - // connected to city features on this tile and add their - // claim groups the list for this city feature - int[] grasses = FeatureUtil.CITY_GRASS_MAP[tile.type-1]; - for (int g = 0; g < grasses.length; g++) { - int farmClaim = tile.claims[grasses[g]]; - - // only worry about claimed grass regions - if (farmClaim == 0) { - Log.info("Ignoring unclaimed farm group " + - "[tile=" + tile + - ", fidx=" + grasses[g] + "]."); - continue; - } - - // and the farm claim group to the list - for (int c = 0; c < claims.length; c++) { - // don't add the farm claim twice - if (claims[c] == farmClaim) { - break; - } else if (claims[c] == 0) { - claims[c] = farmClaim; - Log.info("Noting city/farm abuttal " + - "[tile=" + tile + - ", cityClaim=" + cityClaim + - ", farmClaim=" + farmClaim + "]."); - break; - } - } - } - } - } - - // now for each city, we look to see who has the most piecens that - // are connected to the city by farms - Iterator iter = cities.keys(); - while (iter.hasNext()) { - int cityClaim = ((Integer)iter.next()).intValue(); - int[] farmClaims = (int[])cities.get(cityClaim); - int[] pcount = new int[getPlayerCount()]; - int max = 0; - - Iterator piter = _atlobj.piecens.entries(); - while (piter.hasNext()) { - Piecen p = (Piecen)piter.next(); - // see if the piecen is on any of the farms - for (int c = 0; c < farmClaims.length; c++) { - if (p.claimGroup == farmClaims[c]) { - Log.info("Counting piecen [cityClaim=" + cityClaim + - ", farmClaim=" + farmClaims[c] + - ", piecen=" + p + "]."); - // increment their count and track the max - if (max < ++pcount[p.owner]) { - max = pcount[p.owner]; - } - } - } - } - - Log.info("Counted city [cityClaim=" + cityClaim + - ", counts=" + StringUtil.toString(pcount) + "]."); - - // ignore this city if no one has any farmers nearby - if (max == 0) { - continue; - } - - // now score four points for every player that has the max - for (int i = 0; i < pcount.length; i++) { - if (pcount[i] == max) { - Log.info("Scoring city for player [cgroup=" + cityClaim + - ", player=" + getPlayerName(i) + - ", pcount=" + pcount[i] + "]."); - cityScores[i] += 4; - } - } - } - - // now report the scoring and transfer the counts to the score - // array - for (int i = 0; i < getPlayerCount(); i++) { - if (cityScores[i] > 0) { - _atlobj.scores[i] += cityScores[i]; - String message = getPlayerName(i) + " scores " + - cityScores[i] + " points for fisheries."; - SpeakProvider.sendInfo( - _atlobj, ATLANTI_MESSAGE_BUNDLE, message); - } - } - } - - /** - * Returns an int array with zeros and ones in the appropriate places - * so that a score can be multiplied by a player's position in the - * vector to determine whether or not they receive any points for the - * scoring of a particular claim group. - * - *
Note that this function returns a static (to this instance) - * vector, so it cannot be called again without overwriting values - * returned previously. - * - * @param claimGroup the claim group that we're scoring. - * @param piecens an array to use when looking for matching piecens. - * - * @return an array for the specified claim group or null if no - * players have a piecen claiming the specified claim group. - */ - protected int[] getClaimGroupVector (int claimGroup, Piecen[] piecens) - { - // clear out the vector - Arrays.fill(_claimGroupVector, 0); - - // iterate over the piecens - int max = 0; - for (int i = 0; i < piecens.length; i++) { - Piecen piecen = piecens[i]; - if (piecen == null) { - continue; - } else if (piecen.claimGroup == claimGroup) { - // color == player index... somewhat sketchy - if (++_claimGroupVector[piecen.owner] > max) { - // keep track of the highest scorer - max = _claimGroupVector[piecen.owner]; - } - } - } - - // now cut out everyone with scores less than the highest score - for (int i = 0; i < _claimGroupVector.length; i++) { - _claimGroupVector[i] = (_claimGroupVector[i] < max) ? 0 : 1; - } - - return (max == 0) ? null : _claimGroupVector; - } - - /** - * Removes piecens either from the supplied array or from the game - * object piecen set if no array is supplied. - */ - protected void removePiecens (int claimGroup, Piecen[] piecens, - boolean finalTally) - { - // we always clear the piecens from the array - for (int i = 0; i < piecens.length; i++) { - if (piecens[i] == null) { - continue; - } else if (piecens[i].claimGroup == claimGroup) { - piecens[i] = null; - } - } - - // if this isn't the final tally, we also clear 'em from the board - if (!finalTally) { - Object[] pvec = _atlobj.piecens.toArray(null); - for (int ii = 0; ii < pvec.length; ii++) { - Piecen p = (Piecen)pvec[ii]; - if (p.claimGroup == claimGroup) { - removePiecen(p, true); - } - } - } - } - - /** - * Removes the piecen from the board and optionally removes it from - * the piecen set. - * - * @param piecen the piecen to be removed. - * @param removeFromPiecens if true, the piecen will also be removed - * from the piecens set in the game object. - */ - protected void removePiecen (Piecen piecen, boolean removeFromPiecens) - { - // locate the tile that contains this piecen - int tidx = _tiles.indexOf(piecen); - if (tidx == -1) { - Log.warning("Requested to remove piecen that is not " + - "associated with any tile [piecen=" + piecen + "]."); - } else { - AtlantiTile tile = (AtlantiTile)_tiles.get(tidx); - // and clear the piecen - tile.clearPiecen(); - } - - // also remove from the piecens dset if requested - if (removeFromPiecens) { - _atlobj.removeFromPiecens(piecen.getKey()); - } - } - - // documentation inherited - public void entryAdded (EntryAddedEvent event) - { - // we react to piecen additions by potentially scoring the placed - // piecen. we allow the piecen to be added to the piecens set - // before scoring so that the players can see the piecen pop up on - // their screen and then disappear with a scoring notice rather - // than never show up at all; plus it simplifies our code - if (event.getName().equals(AtlantiObject.PIECENS)) { - Piecen piecen = (Piecen)event.getEntry(); - - // make sure this is a valid placement - AtlantiTile tile = (AtlantiTile)_atlobj.tiles.get(piecen.getKey()); - if (tile == null) { - Log.warning("Can't find tile for piecen scoring " + - piecen + "."); - - } else { - // check to see if we added the piecen to a completed - // feature, in which case we score and remove it - scoreFeatures(tile, getPiecens(), false); - } - - // now that we've scored the piecen, we can end the turn - _delegate.endTurn(); - } - } - - // documentation inherited - public void entryUpdated (EntryUpdatedEvent event) - { - } - - // documentation inherited - public void entryRemoved (EntryRemovedEvent event) - { - } - - /** - * Called when the user requests to place a tile. - */ - protected void handlePlaceTileRequest (MessageEvent event) - { - AtlantiTile tile = (AtlantiTile)event.getArgs()[0]; - int pidx = _delegate.getTurnHolderIndex(); - - // make sure it's this player's turn - if (_playerOids[pidx] != event.getSourceOid()) { - Log.warning("Requested to place tile by non-turn holder " + - "[event=" + event + - ", turnHolder=" + _atlobj.turnHolder + "]."); - - // make sure this is a valid placement - } else if (TileUtil.isValidPlacement(_tiles, tile)) { - // add the tile to the list and resort it - _tiles.add(tile); - Collections.sort(_tiles); - - // inherit its claim groups - TileUtil.inheritClaims(_tiles, tile); - - // add the tile to the tiles set - _atlobj.addToTiles(tile); - - // placing a piece may have completed road or city - // features. if it did, we score them now - scoreFeatures(tile, getPiecens(), false); - - Log.info("Placed tile " + tile + "."); - - // if the player has no free piecens or if there are no - // unclaimed features on this tile, we end their turn - // straight away - int pcount = TileUtil.countPiecens(_atlobj.piecens, pidx); - if (pcount >= PIECENS_PER_PLAYER || - !tile.hasUnclaimedFeature()) { - _delegate.endTurn(); - } - - } else { - Log.warning("Received invalid placement " + event + "."); - } - } - - /** - * Called when the user requests to place a piecen. - */ - protected void handlePlacePiecenRequest (MessageEvent event) - { - Piecen piecen = (Piecen)event.getArgs()[0]; - AtlantiTile tile = (AtlantiTile)_atlobj.tiles.get(piecen.getKey()); - int pidx = _delegate.getTurnHolderIndex(); - int pcount = TileUtil.countPiecens(_atlobj.piecens, pidx); - - // make sure it's this player's turn - if (_playerOids[pidx] != event.getSourceOid()) { - Log.warning("Requested to place piecen by non-turn holder " + - "[event=" + event + - ", turnHolder=" + _atlobj.turnHolder + "]."); - - // do some checking before we place the piecen - } else if (pcount >= PIECENS_PER_PLAYER) { - Log.warning("Requested to place piecen for player that " + - "has all of their piecens in play " + - "[event=" + event + "]."); - - } else 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. when we receive - // the piecen added event, we'll score it and then end the - // turn - _atlobj.addToPiecens(piecen); - } - } - - /** - * Called when the user requests to forgo their piecen placement for - * this turn. - */ - protected void handlePlaceNothingRequest (MessageEvent event) - { - int pidx = _delegate.getTurnHolderIndex(); - if (_playerOids[pidx] != event.getSourceOid()) { - Log.warning("Requested to place nothing by non-turn holder " + - "[event=" + event + - ", turnHolder=" + _atlobj.turnHolder + "]."); - - } else { - // player doesn't want to place anything, so we just end - // the turn - _delegate.endTurn(); - } - } - - /** Handles place tile requests. */ - protected class PlaceTileHandler implements MessageHandler - { - public void handleEvent (MessageEvent event, PlaceManager pmgr) - { - handlePlaceTileRequest(event); - } - } - - /** Handles place piecen requests. */ - protected class PlacePiecenHandler implements MessageHandler - { - public void handleEvent (MessageEvent event, PlaceManager pmgr) - { - handlePlacePiecenRequest(event); - } - } - - /** Handles place nothing requests. */ - protected class PlaceNothingHandler implements MessageHandler - { - public void handleEvent (MessageEvent event, PlaceManager pmgr) - { - handlePlaceNothingRequest(event); - } - } - - /** Our turn game delegate. */ - protected AtlantiManagerDelegate _delegate; - - /** A casted reference to our Atlanti game object. */ - protected AtlantiObject _atlobj; - - /** The (shuffled) list of tiles remaining to be played in this - * game. */ - protected List _tilesInBox; - - /** A sorted list of the tiles that have been placed on the board. */ - protected List _tiles = new ArrayList(); - - /** Used to score features groups. */ - protected int[] _claimGroupVector; -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManagerDelegate.java b/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManagerDelegate.java deleted file mode 100644 index 75c436c5..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/server/AtlantiManagerDelegate.java +++ /dev/null @@ -1,42 +0,0 @@ -// -// $Id: AtlantiManagerDelegate.java,v 1.2 2002/12/12 05:51:54 mdb Exp $ - -package com.samskivert.atlanti.server; - -import com.threerings.parlor.turn.TurnGameManagerDelegate; - -import com.samskivert.atlanti.data.AtlantiCodes; - -/** - * Handles the turn-based gameplay. - */ -public class AtlantiManagerDelegate extends TurnGameManagerDelegate - implements AtlantiCodes -{ - /** - * Constructs the delegate and prepares it for operation. - */ - public AtlantiManagerDelegate (AtlantiManager vmgr) - { - super(vmgr); - _amgr = vmgr; - } - - /** - * Continue the game until we're out of tiles. - */ - protected void setNextTurnHolder () - { - // if we have tiles left, we move to the next player as normal - if (_amgr.getTilesInBox() > 0) { - super.setNextTurnHolder(); - } else { - // if we don't, we ensure that a new turn isn't started by - // setting _turnIdx to -1 - _turnIdx = -1; - } - } - - /** The manager for whom we're delegating. */ - protected AtlantiManager _amgr; -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/util/FeatureUtil.java b/projects/atlanti/src/java/com/samskivert/atlanti/util/FeatureUtil.java deleted file mode 100644 index a29ea464..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/util/FeatureUtil.java +++ /dev/null @@ -1,400 +0,0 @@ -// -// $Id: FeatureUtil.java,v 1.6 2002/12/12 05:51:54 mdb Exp $ - -package com.samskivert.atlanti.util; - -import java.awt.geom.Point2D; - -import com.samskivert.atlanti.data.Feature; -import com.samskivert.atlanti.data.TileCodes; - -/** - * 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, - }; - - /** A mapping for city tiles to the grass features that are adjacent - * to the city tiles. */ - public static final int[][] CITY_GRASS_MAP = new int[][] { - { }, - { 1 }, // CITY_THREE - { 1, 2 }, // CITY_THREE_ROAD - { 1 }, // CITY_TWO - { 1 }, // CITY_TWO_ROAD - { 1, 2 }, // CITY_TWO_ROAD_ACROSS - { 0 }, // TWO_CITY_TWO - { 0 }, // TWO_CITY_TWO_ACROSS - { 0 }, // CITY_ONE - { 0 }, // CITY_ONE_ROAD_RIGHT - { 0 }, // CITY_ONE_ROAD_LEFT - { 0 }, // CITY_ONE_ROAD_TEE - { 0 }, // CITY_ONE_ROAD_STRAIGHT - { }, - { }, - { }, - { }, - { }, - { }, - }; - - /** - * 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; - } - - /** - * Returns the position of the shield on a tile of the given - * orientation. - */ - public static Point2D getShieldSpot (int orientation) - { - return _shieldFeature.piecenSpots[orientation]; - } - - /** - * Returns a string describing the supplied type code. - */ - public static String typeToString (int type) - { - return TYPE_CODES[type]; - } - - /** - * Returns a string describing the supplied edge mask. - */ - public static String edgeMaskToString (int edgeMask) - { - StringBuffer buf = new StringBuffer(); - if ((edgeMask & NORTH_F) != 0) buf.append("NORTH_F|"); - if ((edgeMask & EAST_F) != 0) buf.append("EAST_F|"); - if ((edgeMask & SOUTH_F) != 0) buf.append("SOUTH_F|"); - if ((edgeMask & WEST_F) != 0) buf.append("WEST_F|"); - if ((edgeMask & NNW_F) != 0) buf.append("NNW_F|"); - if ((edgeMask & NNE_F) != 0) buf.append("NNE_F|"); - if ((edgeMask & SSW_F) != 0) buf.append("SSW_F|"); - if ((edgeMask & SSE_F) != 0) buf.append("SSE_F|"); - if ((edgeMask & WNW_F) != 0) buf.append("WNW_F|"); - if ((edgeMask & WSW_F) != 0) buf.append("WSW_F|"); - if ((edgeMask & ENE_F) != 0) buf.append("ENE_F|"); - if ((edgeMask & ESE_F) != 0) buf.append("ESE_F|"); - // strip off the trailing bar if there is one - if (buf.length() > 0) { - buf.deleteCharAt(buf.length()-1); - } - return buf.toString(); - } - - /** - * 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,2, 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 - -4,-4, 2,2, 4,2, 4,4, 2,4 }, - { GRASS, WSW_F|SSW_F, // SW_GRASS - -1,-4, 0,2, 2,2, 2,4, 0,4 }, - }; - - /** A feature that is used to obtain the position information for - * rendering shields on city tiles that use shields. */ - protected static final int[] SHIELD_FEATURE = new int[] - { -1, NORTH_F|WEST_F, -1,-1, 0,0, 4,0, 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, 1,-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,-4, 0,4, 4,0, 4,4 } }, - - { { NW_CITY }, // CITY_TWO_ROAD - { GRASS, ENE_F|SSW_F, -3,-2, 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 - -1,-3, 0,0, 4,0, 4,4, 0,4 }, - { CITY, NORTH_F, - 2,-1, 0,0, 2,1, 4,0 }, - { CITY, EAST_F, - -4,2, 4,0, 3,2, 4,4 } }, - - { { GRASS, NORTH_F|SOUTH_F, // TWO_CITY_TWO_ACROSS - 2,-4, 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,-3, 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 - -1,1, 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 - -1,1, 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, -4,-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, -4,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 }, - }; - - /** String representations of the feature type codes. */ - protected static final String[] TYPE_CODES = { - "CITY", "GRASS", "ROAD", "CLOISTER" }; - - /** A table of features that are used on more than one tile. */ - protected static Feature[] _reusedFeatures; - - /** The feature that provides the location information for shield - * rendering. */ - protected static Feature _shieldFeature; - - // 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]); - } - _shieldFeature = new Feature(SHIELD_FEATURE); - } -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/util/PiecenUtil.java b/projects/atlanti/src/java/com/samskivert/atlanti/util/PiecenUtil.java deleted file mode 100644 index b1a29f46..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/util/PiecenUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -// -// $Id: PiecenUtil.java,v 1.4 2003/03/23 02:22:51 mdb Exp $ - -package com.samskivert.atlanti.util; - -import java.awt.Image; - -import com.threerings.media.tile.Tile; -import com.threerings.media.tile.TileManager; -import com.threerings.media.tile.UniformTileSet; - -public class PiecenUtil -{ - /** - * Loads up the piecen images using the supplied tile manager. - */ - public static void init (TileManager tmgr) - { - UniformTileSet piecenSet = tmgr.loadTileSet( - PIECEN_IMG_PATH, PIECEN_WIDTH, PIECEN_HEIGHT); - _images = new Image[PIECEN_TYPES]; - for (int i = 0; i < PIECEN_TYPES; i++) { - _images[i] = piecenSet.getRawTileImage(i); - } - } - - /** - * Returns the piecen image for the specified piecen color. - */ - public static Image getPiecenImage (int color) - { - return _images[color]; - } - - /** Our piecen images. */ - protected static Image[] _images; - - /** The number of different colors of piecen. */ - protected static final int PIECEN_TYPES = 6; - - /** The width of the piecen image in pixels. */ - protected static final int PIECEN_WIDTH = 16; - - /** The height of the piecen image in pixels. */ - protected static final int PIECEN_HEIGHT = 16; - - /** The path to the piecen image (relative to the resource - * directory). */ - protected static final String PIECEN_IMG_PATH = "media/piecens.png"; -} diff --git a/projects/atlanti/src/java/com/samskivert/atlanti/util/TileUtil.java b/projects/atlanti/src/java/com/samskivert/atlanti/util/TileUtil.java deleted file mode 100644 index 40969af8..00000000 --- a/projects/atlanti/src/java/com/samskivert/atlanti/util/TileUtil.java +++ /dev/null @@ -1,734 +0,0 @@ -// -// $Id: TileUtil.java,v 1.17 2002/12/12 05:51:55 mdb Exp $ - -package com.samskivert.atlanti.util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import com.samskivert.util.IntTuple; - -import com.threerings.presents.dobj.DSet; - -import com.samskivert.atlanti.Log; -import com.samskivert.atlanti.data.AtlantiTile; -import com.samskivert.atlanti.data.Feature; -import com.samskivert.atlanti.data.Piecen; -import com.samskivert.atlanti.data.TileCodes; - -/** - * Utility functions relating to the Atlantissonne tiles. - */ -public class TileUtil implements TileCodes -{ - /** - * Returns an instance of the starting tile (properly cloned so that - * it can be messed with by the server). - */ - public static AtlantiTile getStartingTile () - { - return (AtlantiTile)AtlantiTile.STARTING_TILE.clone(); - } - - /** - * Returns a list containing the standard tile set for the - * Atlantissonne game. The list is a clone, so it can be bent, folded - * and modified by the caller. - */ - public static List getStandardTileSet () - { - // we need to deep copy the default tile set, so we can't just use - // clone - List tiles = new ArrayList(); - int tsize = TILE_SET.size(); - for (int i = 0; i < tsize; i++) { - tiles.add(((AtlantiTile)TILE_SET.get(i)).clone()); - } - return tiles; - } - - /** - * Scans the supplied tile set to determine which of the four - * orientations of the supplied target tile would result in a valid - * placement of that tile (valid placement meaning that all of its - * edges match up with neighboring tiles, it abuts at least one tile - * and it does not occupy the same space as any existing tile). The - * 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 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 - * tile can be placed in each of the cardinal directions (which match - * up with the direction constants specified in {@link TileCodes}. - */ - public static boolean[] computeValidOrients ( - List tiles, AtlantiTile 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]; - - int tsize = tiles.size(); - for (int i = 0; i < tsize; i++) { - AtlantiTile tile = (AtlantiTile)tiles.get(i); - - // figure out where this tile is in relation to the candidate - int xdiff = tile.x - target.x; - int ydiff = tile.y - target.y; - int sum = Math.abs(xdiff) + Math.abs(ydiff); - - if (sum == 0) { - // they overlap, nothing doing - return new boolean[4]; - - } else if (sum == 1) { - // they're neighbors, we may have a match - int targetEdge = EDGE_MAP[(ydiff+1)*3 + xdiff+1]; - - // we want the edge of the placed tile that matches up - // with the tile in the candidate location, but we also - // need to take into account the orientation of the placed - // tile - int tileEdge = (targetEdge+(4-tile.orientation)+2) % 4; - - // we iterate over the four possible orientations of the - // target tile - 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-o)) % 4)) { - // increment the edge matches - matches[o]++; - - } else { - // if we have a mismatch, we want to ensure that - // we screw this orientation up for good, so we - // deduct a large value from the array to ensure - // that it will remain less than zero regardless - // of which of the other three tiles match in this - // orientation - matches[o] -= 10; - } - } - } - } - - // for every orientation that we have a positive number of edge - // matches, we have a valid orientation - boolean[] orients = new boolean[4]; - for (int i = 0; i < matches.length; i++) { - orients[i] = (matches[i] > 0); - } - return orients; - } - - /** - * Returns true if the position and orientation of the target tile is - * legal given the placement of all of the existing tiles. - * - * @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 (List tiles, AtlantiTile target) - { - boolean matchedAnEdge = false; - - int tsize = tiles.size(); - for (int i = 0; i < tsize; i++) { - AtlantiTile tile = (AtlantiTile)tiles.get(i); - - // figure out where this tile is in relation to the candidate - int xdiff = tile.x - target.x; - int ydiff = tile.y - target.y; - int sum = Math.abs(xdiff) + Math.abs(ydiff); - - if (sum == 0) { - // they overlap, nothing doing - Log.warning("Tile overlaps another [candidate=" + target + - ", overlapped=" + tile + "]."); - return false; - - } else if (sum == 1) { - // they're neighbors, we may have a match - int targetEdge = EDGE_MAP[(ydiff+1)*3 + xdiff+1]; - - // we want the edge of the placed tile that matches up - // with the tile in the candidate location, but we also - // need to take into account the orientation of the placed - // tile - int tileEdge = (targetEdge+(4-tile.orientation)+2) % 4; - - // now rotate the target edge according to our orientation - targetEdge = ((targetEdge+(4-target.orientation)) % 4); - - // see if the edges match - if (getEdge(tile.type, tileEdge) == - getEdge(target.type, targetEdge)) { - // make a note that we matched at least one edge - matchedAnEdge = true; - - } else { - // the edges don't match, nothing doing - Log.warning("Edge mismatch [candidate=" + target + - ", tile=" + tile + - ", candidateEdge=" + targetEdge + - ", tileEdge=" + tileEdge + "]."); - return false; - } - } - } - - // if we got this far, we didn't have any mismatches, so we need - // only know that we matched at least one edge - return matchedAnEdge; - } - - /** - * When a tile is placed on the board, this method should be called on - * it to propagate existing claims to the appropriate features on this - * tile. It will determine if any city features are connected to - * cities that are already claimed, and if any road features are - * connected to roads that are already claimed and if any grassland is - * connected to grassland that is claimed. - * - *
If, in the process of initializing the claims for this tile, we - * discover that this tile connects two previously disconnected - * claims, those claims will be joined. The affected tiles and piecens - * will have their claim groups updated. - * - * @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 (List tiles, AtlantiTile tile) - { - List flist = new ArrayList(); - - // for each feature in the tile, load up its claim group and make - // sure all features in that group (which will include our new - // feature) now have the same claim number - for (int i = 0; i < tile.features.length; i ++) { - int claimGroup = 0; - - // clear out the tilefeatures list before enumerating - flist.clear(); - - // enumerate the claim group for this feature - enumerateGroup(tiles, tile, i, flist); - - // find the first non-zero claim number - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - int fcg = feat.tile.claims[feat.featureIndex]; - if (fcg != 0) { - claimGroup = fcg; - break; - } - } - - // if we found no non-zero claim number, we've nothing to - // inherit - if (claimGroup == 0) { - continue; - } - - // otherwise, assign our new claim number to all members of - // the group (potentially causing some to inherit the new - // claim number) - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - // set the claim group in the tile - feat.tile.claims[feat.featureIndex] = claimGroup; - // also set the claim group on the piecen if the tile has - // an associated piecen that is on this feature - Piecen p = feat.tile.piecen; - if (p != null && p.featureIndex == feat.featureIndex) { - p.claimGroup = claimGroup; - } - } - } - } - - /** - * Sets the claim group for the specified feature in this tile and - * propagates that claim group to all connected features. - * - * @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. - * @param claimGroup the claim group value to set. - */ - public static void setClaimGroup ( - List tiles, AtlantiTile tile, int featureIndex, int claimGroup) - { - // load up this feature group - List flist = new ArrayList(); - enumerateGroup(tiles, tile, featureIndex, flist); - - // and assign the claim number to all features in the group - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - feat.tile.claims[feat.featureIndex] = claimGroup; - } - } - - /** - * Computes the score for the specified feature and returns it. If the - * feature is complete (has no unconnected edges), the score will be - * positive. If it is incomplete, the score will be negative. - * - * @param tiles a sorted list of the tiles on the board. - * @param tile the tile that contains the feature whose score should - * be computed. - * @param featureIndex the index of the feature in the containing - * tile. - * - * @return a positive score for a completed feature group, a negative - * score for a partial feature group. - */ - public static int computeFeatureScore ( - List tiles, AtlantiTile tile, int featureIndex) - { - Feature feature = tile.features[featureIndex]; - - if (feature.type == CLOISTER) { - // cloister's score specially - return computeCloisterScore(tiles, tile); - - } else if (feature.type == GRASS) { - // grass doesn't score - return 0; - } - - // if we're here, it's a road or city feature, which we score by - // loading up the group and counting the number of tiles in it - List flist = new ArrayList(); - boolean complete = enumerateGroup(tiles, tile, featureIndex, flist); - - // we sort the group which will order the tile feature objects by - // their tiles, ensuring that features on the same tile are next - // to one another, so that we can only count them once - Collections.sort(flist); - - // now iterate over the list, counting only unique tiles - int score = 0; - AtlantiTile lastTile = null; - int fsize = flist.size(); - for (int i = 0; i < fsize; i++) { - TileFeature feat = (TileFeature)flist.get(i); - if (feat.tile != lastTile) { - score++; - lastTile = feat.tile; - } - } - - // for city groups, we need to add a bonus of one for every tile - // that contains a shield and mutiply by two if the city is - // complete and larger than two tiles - if (feature.type == CITY) { - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - if (feat.tile.hasShield) { - score++; - } - } - if (complete && score > 2) { - score *= 2; - } - } - - // incomplete scores are reported in the negative - return complete ? score : -score; - } - - /** - * A helper function for {@link - * #computeFeatureScore(List,AtlantiTile,int)}. - */ - protected static int computeCloisterScore (List tiles, AtlantiTile tile) - { - int score = 0; - - // all we need to know are how many neighbors this guy has (we - // count ourselves as well, just for code simplicity) - for (int dx = -1; dx < 2; dx++) { - for (int dy = -1; dy < 2; dy++) { - if (findTile(tiles, tile.x + dx, tile.y + dy) != null) { - score++; - } - } - } - - // incomplete cloisters return a negative score - return (score == 9) ? 9 : -score; - } - - /** - * Clears out the claim group information for incomplete cities so - * that we can ignore them during farm scoring. Assigns new claim - * group values to any completed cities that were unclaimed. - * - * @param tiles a sorted list of tiles on the board. - */ - public static void prepCitiesForScoring (List tiles) - { - List flist = new ArrayList(); - - // iterate over the tiles, marking every city completed or not - int tsize = tiles.size(); - for (int i = 0; i < tsize; i++) { - AtlantiTile tile = (AtlantiTile)tiles.get(i); - - // iterate over each feature on this tile - for (int f = 0; f < tile.features.length; f++) { - // skip non-city features - if (tile.features[f].type != TileCodes.CITY) { - continue; - } - - // clear out the feature group list before processing - flist.clear(); - - // enumerate the features in the group with this feature - if (enumerateGroup(tiles, tile, f, flist)) { - // if it's complete, we want to ensure that all of - // these features have a claim number - if (tile.claims[f] != 0) { - // it's complete and has a claim number. move on - continue; - } - - // assign the claim number to all features in the group - int claimGroup = nextClaimGroup(); - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - feat.tile.claims[feat.featureIndex] = claimGroup; - if (t == 0) { - Log.info("Claiming complete city " + - "[claim=" + feat.tile.claims[ - feat.featureIndex] + "]."); - } - } - - } else { - // it's incomplete, so we want to clear out the claim - // number from all tiles in the group - for (int t = 0; t < flist.size(); t++) { - TileFeature feat = (TileFeature)flist.get(t); - if (t == 0) { - Log.info("Clearing incomplete city " + - "[claim=" + feat.tile.claims[ - feat.featureIndex] + "]."); - } - feat.tile.claims[feat.featureIndex] = 0; - } - } - } - } - } - - /** - * Enumerates all of the features that are in the group of which the - * specified feature is a member. - * - * @param tiles a sorted list of the tiles on the board. - * @param tile the tile that contains the feature whose group is to be - * enumerated. - * @param featureIndex the index of the feature whose group is to be - * enumerated. - * @param group the list into which instances of {@link TileFeature} - * will be placed that represent the features that are members of the - * group. - * - * @return true if the group is complete (has no unconnected - * features), false if it is not. - */ - protected static boolean enumerateGroup ( - List tiles, AtlantiTile tile, int featureIndex, List group) - { - // create a tilefeature for this feature - TileFeature feat = new TileFeature(tile, featureIndex); - - // determine whether or not this feature is already in the group - if (group.contains(feat)) { - return true; - } - - // otherwise add this feature to the group and process this - // feature's neighbors - group.add(feat); - - boolean complete = true; - 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 < FeatureUtil.ADJACENCY_MAP.length; c += 3) { - int mask = FeatureUtil.ADJACENCY_MAP[c]; - int opp_mask = FeatureUtil.ADJACENCY_MAP[c+2]; - - // if this feature doesn't have this edge, skip it - if ((fmask & mask) == 0) { - continue; - } - - // look up our neighbor - AtlantiTile neighbor = null; - int dir = FeatureUtil.ADJACENCY_MAP[c+1]; - dir = (dir + tile.orientation) % 4; - switch (dir) { - case NORTH: neighbor = findTile(tiles, tile.x, tile.y-1); break; - case EAST: neighbor = findTile(tiles, tile.x+1, tile.y); break; - case SOUTH: neighbor = findTile(tiles, tile.x, tile.y+1); break; - case WEST: neighbor = findTile(tiles, tile.x-1, tile.y); break; - } - - // make sure we have a neighbor in this direction - if (neighbor == null) { - // if we don't have a neighbor in a direction that we - // need, we're an incomplete feature. alas - complete = false; - continue; - } - - // translate the target mask into our orientation - mask = FeatureUtil.translateMask(mask, tile.orientation); - opp_mask = FeatureUtil.translateMask(opp_mask, tile.orientation); - - // obtain the index of the feature on the opposing tile - int nFeatureIndex = neighbor.getFeatureIndex(opp_mask); - if (nFeatureIndex < 0) { - Log.warning("Tile mismatch while grouping [tile=" + tile + - "featIdx=" + featureIndex + - ", neighbor=" + neighbor + - ", nFeatIdx=" + nFeatureIndex + - ", srcEdge=" + mask + - ", destEdge=" + opp_mask + "]."); - continue; - } - - // add this feature and its neighbors to the group - if (!enumerateGroup(tiles, neighbor, nFeatureIndex, group)) { - // if our neighbor was incomplete, we become incomplete. - // as dr. evil might say, "you incomplete me." - complete = false; - } - } - - return complete; - } - - /** - * Locates and returns the tile with the specified coordinates. - * - * @param tiles a sorted list of tiles. - * - * @return the tile with the requested coordinates or null if no tile - * exists at those coordinates. - */ - public static AtlantiTile findTile (List tiles, int x, int y) - { - IntTuple coord = new IntTuple(x, y); - int tidx = Collections.binarySearch(tiles, coord); - return (tidx >= 0) ? (AtlantiTile)tiles.get(tidx) : null; - } - - /** - * Returns the number of piecens on the board owned the specified - * player. This can be used when we need to count piecens and the - * server potentially hasn't gotten around to processing piecen - * removal events quite yet. - * - * @param tiles a list of the tiles on the board. - * @param playerIndex the index of the player whose piecen count is - * desired. - */ - public static int countPiecens (List tiles, int playerIndex) - { - int count = 0; - for (int i = 0; i < tiles.size(); i++) { - AtlantiTile tile = (AtlantiTile)tiles.get(i); - if (tile.piecen != null && - tile.piecen.owner == playerIndex) { - count++; - } - } - return count; - } - - /** - * Returns the number of piecens on the board owned the specified - * player. - * - * @param piecens the piecens set from the game object. - * @param playerIndex the index of the player whose piecen count is - * desired. - */ - public static int countPiecens (DSet piecens, int playerIndex) - { - int count = 0; - Iterator iter = piecens.entries(); - while (iter.hasNext()) { - if (((Piecen)iter.next()).owner == playerIndex) { - count++; - } - } - return count; - } - - /** - * Returns the edge type for specified edge of the specified tile - * type. - * - * @param tileType the type of the tile in question. - * @param edge the direction constant indicating the edge in which we - * are interested. - * - * @return the edge constant for the edge in question. - */ - public static int getEdge (int tileType, int edge) - { - return TILE_EDGES[4*tileType + edge]; - } - - /** - * Returns the next unused claim group value. - */ - public static int nextClaimGroup () - { - return ++_claimGroupCounter; - } - - /** Used to generate our standard tile set. */ - protected static void addTiles (int count, List list, AtlantiTile tile) - { - for (int i = 0; i < count; i++) { - list.add(tile); - } - } - - /** Used to keep track of actual features on tiles. */ - protected static final class TileFeature implements Comparable - { - /** The tile that contains the feature. */ - public AtlantiTile tile; - - /** The index of the feature in the tile. */ - public int featureIndex; - - /** Constructs a new tile feature. */ - public TileFeature (AtlantiTile tile, int featureIndex) - { - this.tile = tile; - this.featureIndex = featureIndex; - } - - /** Properly implement equality. */ - public boolean equals (Object other) - { - if (other == null || - !(other instanceof TileFeature)) { - return false; - - } else { - TileFeature feat = (TileFeature)other; - return (feat.tile == tile && - feat.featureIndex == featureIndex); - } - } - - /** We sort based on our tiles. */ - public int compareTo (Object other) - { - return tile.compareTo(((TileFeature)other).tile); - } - - /** Generate a string representation. */ - public String toString () - { - return "[tile=" + tile + ", fidx=" + featureIndex + "]"; - } - } - - /** 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 = { - -1, NORTH, -1, - WEST, -1, EAST, - -1, SOUTH, -1 - }; - - /** A table indicating which tiles have which edges. */ - protected static final int[] TILE_EDGES = { - -1, -1, -1, -1, // null tile - CITY, CITY, CITY, CITY, // CITY_FOUR - CITY, CITY, GRASS, CITY, // CITY_THREE - CITY, CITY, ROAD, CITY, // CITY_THREE_ROAD - CITY, GRASS, GRASS, CITY, // CITY_TWO - CITY, ROAD, ROAD, CITY, // CITY_TWO_ROAD - GRASS, CITY, GRASS, CITY, // 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 - CITY, ROAD, ROAD, ROAD, // CITY_ONE_ROAD_TEE - CITY, ROAD, GRASS, ROAD, // CITY_ONE_ROAD_STRAIGHT - GRASS, GRASS, GRASS, GRASS, // CLOISTER_PLAIN - GRASS, GRASS, ROAD, GRASS, // CLOISTER_ROAD - ROAD, ROAD, ROAD, ROAD, // FOUR_WAY_ROAD - GRASS, ROAD, ROAD, ROAD, // THREE_WAY_ROAD - ROAD, GRASS, ROAD, GRASS, // STRAIGHT_ROAD - GRASS, GRASS, ROAD, ROAD, // CURVED_ROAD - }; - - /** The standard tile set for a game of Atlantissonne. */ - protected static ArrayList TILE_SET = new ArrayList(); - - // create our standard tile set - static { - addTiles(1, TILE_SET, new AtlantiTile(CITY_FOUR, true)); - - addTiles(3, TILE_SET, new AtlantiTile(CITY_THREE, false)); - addTiles(1, TILE_SET, new AtlantiTile(CITY_THREE, true)); - addTiles(1, TILE_SET, new AtlantiTile(CITY_THREE_ROAD, false)); - addTiles(2, TILE_SET, new AtlantiTile(CITY_THREE_ROAD, true)); - - addTiles(3, TILE_SET, new AtlantiTile(CITY_TWO, false)); - addTiles(2, TILE_SET, new AtlantiTile(CITY_TWO, true)); - addTiles(3, TILE_SET, new AtlantiTile(CITY_TWO_ROAD, false)); - addTiles(2, TILE_SET, new AtlantiTile(CITY_TWO_ROAD, true)); - addTiles(1, TILE_SET, new AtlantiTile(CITY_TWO_ACROSS, false)); - addTiles(2, TILE_SET, new AtlantiTile(CITY_TWO_ACROSS, true)); - - addTiles(2, TILE_SET, new AtlantiTile(TWO_CITY_TWO, false)); - addTiles(3, TILE_SET, new AtlantiTile(TWO_CITY_TWO_ACROSS, false)); - - addTiles(5, TILE_SET, new AtlantiTile(CITY_ONE, false)); - addTiles(3, TILE_SET, new AtlantiTile(CITY_ONE_ROAD_RIGHT, false)); - addTiles(3, TILE_SET, new AtlantiTile(CITY_ONE_ROAD_LEFT, false)); - addTiles(3, TILE_SET, new AtlantiTile(CITY_ONE_ROAD_TEE, false)); - addTiles(3, TILE_SET, new AtlantiTile(CITY_ONE_ROAD_STRAIGHT, false)); - - addTiles(4, TILE_SET, new AtlantiTile(CLOISTER_PLAIN, false)); - addTiles(2, TILE_SET, new AtlantiTile(CLOISTER_ROAD, false)); - - addTiles(1, TILE_SET, new AtlantiTile(FOUR_WAY_ROAD, false)); - addTiles(4, TILE_SET, new AtlantiTile(THREE_WAY_ROAD, false)); - addTiles(8, TILE_SET, new AtlantiTile(STRAIGHT_ROAD, false)); - addTiles(9, TILE_SET, new AtlantiTile(CURVED_ROAD, false)); - } -}