soc.game
Class SOCSpecialItem

java.lang.Object
  extended by soc.game.SOCSpecialItem
All Implemented Interfaces:
java.lang.Cloneable

public class SOCSpecialItem
extends java.lang.Object
implements java.lang.Cloneable

A special item for Settlers scenarios or expansions. During game play, players may be allowed to PICK (choose), SET, or CLEAR special items; the meaning of these actions is scenario-specific. See typeKey list below for usage and meaning. See playerPickItem(String, SOCGame, SOCPlayer, int, int) and playerSetItem(String, SOCGame, SOCPlayer, int, int, boolean) for API details.

Example use: The Wonders chosen by players in the _SC_WOND scenario.

Special Items are per-game and/or per-player. In SOCGame and SOCPlayer they're accessed by an item type key. For compatibility among scenarios and expansions, this key should be a SOCGameOption keyname; if an option has more than one special item type, typeKey should be optionName + "/" + a short alphanumeric key of your choosing. Please document the Special Item type(s) in the SOCGameOption's javadoc, including whether each is per-game, per-player, or both (for more convenient access).

In some scenarios, Special Items may have requirements for players to build or use them. See SOCSpecialItem.Requirement javadoc for more details. To check requirements, call checkRequirements(SOCPlayer, boolean).

Optional Fields:
Some typeKeys may use the getLevel() and getStringValue() fields; their meaning is type-specific.

Non-Networked Fields:
The cost and requirement fields are initialized at the server and at the client, not sent over the network. Because of their limited and known use, it's easier to set them up in a factory method here than to create, send, and parse messages with all details of the game's Special Items. If a new Special Item type is created for a new scenario or expansion, the client would most likely need new code to handle that scenario or expansion, so the new item type's field initialization can be added to the factory at that time. See makeKnownItem(String, int).

Locks: Field values are not synchronized here. If a specific item type or access pattern requires synchronization, do so outside this class and document the details. Some methods here require locking as described in their javadocs.

Special items must be Cloneable for use in copy constructors, see clone() for details.

Current scenarios and typeKeys:
_SC_WOND
In this scenario, the game has a list of unique "Wonders", indexed 1 to SOCGame.maxPlayers + 1. (The 6-player game includes another copy of the first two wonders.) To win the game, a player must take ownership of exactly one of these, and build 4 levels of it.

A reference to the player's SOCSpecialItem is kept in the game's Special Item list, and also placed at index 0 of the player's Special Item list.

This scenario uses the getStringValue() field to identify the wonder object with a localized name: "w1" is the Theater, "w5" is the Cathedral, etc. The 6-player game includes another copy of the first two wonders: 2 special items will have "w1", 2 will have "w2".

For more details see SOCScenario.K_SC_WOND.

Since:
2.0.00

Nested Class Summary
static class SOCSpecialItem.Requirement
          Data structure and parser for a special item's requirements.
 
Field Summary
protected  int coord
          Optional coordinates on the board for this item, or -1.
protected  SOCResourceSet cost
          Optional cost to buy, use, or build the next level, or null.
private static int[][] COST_SC_WOND
          Costs for the Wonders in the _SC_WOND scenario.
protected  int gameItemIndex
          Item's optional game item index, or -1, as used with SOCGame.getSpecialItem(String, int, int, int).
protected  int level
          Optional level of construction or strength, or 0.
protected  SOCPlayer player
          The player who owns this item, if any.
 java.util.List<SOCSpecialItem.Requirement> req
          Optional requirements to buy, use, or build the next level, or null.
private static java.lang.String[] REQ_SC_WOND
          Requirements for the Wonders in the _SC_WOND scenario.
static int SC_WOND_WIN_LEVEL
          To win the game in _SC_WOND, player can build this many levels (4) of their Wonder.
protected  java.lang.String sv
          Optional string value field, or null; this field's meaning is specific to the item's typeKey.
private static java.lang.String[] SV_SC_WOND
          sv for the Wonders in the _SC_WOND scenario.
 
Constructor Summary
SOCSpecialItem(SOCPlayer pl, int co, int lv, java.lang.String sv, SOCResourceSet cost, java.lang.String req)
          Make a new item, optionally owned by a player, with an optional level and string value.
SOCSpecialItem(SOCPlayer pl, int co, SOCResourceSet cost, java.lang.String req)
          Make a new item, optionally owned by a player.
 
Method Summary
 boolean checkCost(SOCPlayer pl)
          Does this player have resources for this special item's getCost(), if any?
 boolean checkRequirements(SOCPlayer pl, boolean checkCost)
          Does this player meet this special item's req requirements?
static boolean checkRequirements(SOCPlayer pl, java.util.List<SOCSpecialItem.Requirement> reqsList)
          Does this player meet a special item's requirements?
 SOCSpecialItem clone()
          For use in set copy constructors, create and return a clone of this SOCSpecialItem.
 boolean equals(java.lang.Object other)
          Compare this SOCSpecialItem to another SOCSpecialItem, or another object.
 int getCoordinates()
           
 SOCResourceSet getCost()
          Get the optional cost to buy, use, or build the next level.
 int getGameIndex()
          Get this item's optional game item index, or -1 if none, as used with SOCGame.getSpecialItem(String, int, int, int).
 int getLevel()
          Get the current construction level or strength of this item.
 SOCPlayer getPlayer()
          Get the player who owns this item, if any.
 java.lang.String getStringValue()
          Get the current string value, if any, of this special item.
static SOCSpecialItem makeKnownItem(java.lang.String typeKey, int idx)
          Create a scenario/expansion's special item if known.
static boolean playerPickItem(java.lang.String typeKey, SOCGame ga, SOCPlayer pl, int gi, int pi)
          Process a request from a player to PICK a known special item.
static boolean playerSetItem(java.lang.String typeKey, SOCGame ga, SOCPlayer pl, int gi, int pi, boolean isSet)
          Process a request from a player to SET or CLEAR a known special item.
 void setCoordinates(int co)
           
 void setCost(SOCResourceSet co)
          Set or clear the optional cost to buy, use, or build the next level.
 void setGameIndex(int gi)
          Set this item's {@link #getGameIndex().
 void setLevel(int lv)
          Set the current level of this special item.
 void setPlayer(SOCPlayer pl)
          Set or clear the player who owns this item.
 void setStringValue(java.lang.String sv)
          Set or clear the current string value of this special item.
 java.lang.String toString()
           
 
Methods inherited from class java.lang.Object
finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

SC_WOND_WIN_LEVEL

public static final int SC_WOND_WIN_LEVEL
To win the game in _SC_WOND, player can build this many levels (4) of their Wonder.

See Also:
Constant Field Values

REQ_SC_WOND

private static final java.lang.String[] REQ_SC_WOND
Requirements for the Wonders in the _SC_WOND scenario. Index 0 unused. The 6-player game includes another copy of the first two wonders. Used by makeKnownItem(String, int).


COST_SC_WOND

private static final int[][] COST_SC_WOND
Costs for the Wonders in the _SC_WOND scenario. Index 0 unused. The 6-player game includes another copy of the first two wonders. Each 5-element array is { clay, ore, sheep, wheat, wood }. Used by makeKnownItem(String, int).


SV_SC_WOND

private static final java.lang.String[] SV_SC_WOND
sv for the Wonders in the _SC_WOND scenario. sv is used in this scenario to identify the wonder with a localized name. Index 0 unused. The 6-player game includes another copy of the first two wonders. Used by makeKnownItem(String, int).


gameItemIndex

protected int gameItemIndex
Item's optional game item index, or -1, as used with SOCGame.getSpecialItem(String, int, int, int).


player

protected SOCPlayer player
The player who owns this item, if any. Will be null for certain items which belong to the game and not to players.


coord

protected int coord
Optional coordinates on the board for this item, or -1. An edge or a node, depending on item type.


level

protected int level
Optional level of construction or strength, or 0.


sv

protected java.lang.String sv
Optional string value field, or null; this field's meaning is specific to the item's typeKey.


cost

protected SOCResourceSet cost
Optional cost to buy, use, or build the next level, or null. Not sent over the network; see class javadoc.


req

public final java.util.List<SOCSpecialItem.Requirement> req
Optional requirements to buy, use, or build the next level, or null. Not sent over the network; see class javadoc.

Constructor Detail

SOCSpecialItem

public SOCSpecialItem(SOCPlayer pl,
                      int co,
                      SOCResourceSet cost,
                      java.lang.String req)
               throws java.lang.IllegalArgumentException
Make a new item, optionally owned by a player. Its optional Level will be 0, string value will be null.

Parameters:
pl - player who owns the item, or null
co - coordinates, or -1
cost - cost to buy, use, or build the next level, or null
req - requirements to buy, use, or build the next level, or null. If provided, this requirement specification string will be parsed by SOCSpecialItem.Requirement.parse(String).
Throws:
java.lang.IllegalArgumentException - if req != null but isn't a syntactically valid specification

SOCSpecialItem

public SOCSpecialItem(SOCPlayer pl,
                      int co,
                      int lv,
                      java.lang.String sv,
                      SOCResourceSet cost,
                      java.lang.String req)
               throws java.lang.IllegalArgumentException
Make a new item, optionally owned by a player, with an optional level and string value.

Parameters:
pl - player who owns the item, or null
co - coordinates, or -1
lv - current level of construction or strength, or 0
sv - current string value (optional), or null. Meaning is type-specific, see getStringValue(). If not null, must pass SOCMessage.isSingleLineAndSafe(String).
cost - cost to buy, use, or build the next level, or null
req - requirements to buy, use, or build the next level, or null. If provided, this requirement specification string will be parsed by SOCSpecialItem.Requirement.parse(String).
Throws:
java.lang.IllegalArgumentException - if req != null but isn't a syntactically valid specification, or if sv fails SOCMessage.isSingleLineAndSafe(String)
Method Detail

makeKnownItem

public static final SOCSpecialItem makeKnownItem(java.lang.String typeKey,
                                                 int idx)
Create a scenario/expansion's special item if known. This is a factory method for game setup convenience. The known item's requirements and cost will be filled from static data. Sets getGameIndex() to idx.

Currently known typeKeys:

If typeKey is unknown, the item will be created with null cost and requirements, equivalent to calling new SOCSpecialItem (null, -1, null, null).

Parameters:
typeKey - Special item type. Typically a SOCGameOption keyname; see class javadoc for details.
idx - Index within game's Special Item list
Returns:
A Special Item at no coordinate (-1) and unowned by any player, with cost/requirements if known, or null cost and requirements otherwise.

playerPickItem

public static boolean playerPickItem(java.lang.String typeKey,
                                     SOCGame ga,
                                     SOCPlayer pl,
                                     int gi,
                                     int pi)
                              throws java.lang.IllegalStateException
Process a request from a player to PICK a known special item. Implements scenario-specific rules and behavior for the item. Called at server, not at client.

In some scenarios, calls SOCGame.checkForWinner(); after calling this method, check SOCGame.getGameState() >= SOCGame.OVER.

When both gi and pi are specified, the item is retrieved by calling SOCGame.getSpecialItem(String, int, int, int) before making any changes. That object's getCost(), if any, is what was paid if this method returns true. If the caller needs to know the cost paid, call that method before this one.

Currently only _SC_WOND is recognized as a typeKey here. To see which scenario and option typeKeys use this method, and scenario-specific usage details, see the SOCSpecialItem class javadoc.

Locks: Call SOCGame.takeMonitor() before calling this method.

Parameters:
typeKey - Item's typeKey, as described in the SOCSpecialItem class javadoc
ga - Game containing pl and special items
pl - Requesting player; never null
gi - Pick this index within game's Special Item list, or -1
pi - Pick this index within pl's Special Item list, or -1
Returns:
true if the item's cost was deducted from pl's resources
Throws:
java.lang.IllegalStateException - if pl cannot set or clear this item right now (due to cost, requirements, game state, is not their turn, or anything else), or if typeKey is unknown here, or if this typeKey doesn't use PICK requests from client players.
See Also:
playerSetItem(String, SOCGame, SOCPlayer, int, int, boolean)

playerSetItem

public static boolean playerSetItem(java.lang.String typeKey,
                                    SOCGame ga,
                                    SOCPlayer pl,
                                    int gi,
                                    int pi,
                                    boolean isSet)
                             throws java.lang.IllegalStateException
Process a request from a player to SET or CLEAR a known special item. Implements scenario-specific rules and behavior for the item. Called at server, not at client.

In some scenarios, calls SOCGame.checkForWinner(); after calling this method, check SOCGame.getGameState() >= SOCGame.OVER.

To see which scenario and option typeKeys use this method, and scenario-specific usage details, see the SOCSpecialItem class javadoc.

Locks: Call SOCGame.takeMonitor() before calling this method.

Parameters:
typeKey - Item's typeKey, as described in the SOCSpecialItem class javadoc
ga - Game containing pl and special items
pl - Requesting player; never null
gi - Set or clear this index within game's Special Item list, or -1
pi - Set or clear this index within pl's Special Item list, or -1
isSet - True if player wants to set, false if player wants to clear, this item index
Returns:
true if the item's cost was deducted from pl's resources
Throws:
java.lang.IllegalStateException - if pl cannot set or clear this item right now (due to cost, requirements, game state, or anything else), or if typeKey is unknown here, or if this typeKey doesn't use SET or CLEAR requests from client players.
See Also:
playerPickItem(String, SOCGame, SOCPlayer, int, int)

getGameIndex

public int getGameIndex()
Get this item's optional game item index, or -1 if none, as used with SOCGame.getSpecialItem(String, int, int, int).

See Also:
getPlayer()

setGameIndex

public void setGameIndex(int gi)
Set this item's {@link #getGameIndex().


getPlayer

public SOCPlayer getPlayer()
Get the player who owns this item, if any.

Returns:
the owner of the item, or null
See Also:
getGameIndex()

setPlayer

public void setPlayer(SOCPlayer pl)
Set or clear the player who owns this item.

Parameters:
pl - the owner of this item, or null

getCoordinates

public int getCoordinates()
Returns:
the node or edge coordinate for this item, or -1 if none

setCoordinates

public void setCoordinates(int co)
Parameters:
co - the node or edge coordinate for this item, or -1 if none

getLevel

public int getLevel()
Get the current construction level or strength of this item.

Returns:
Current level

setLevel

public void setLevel(int lv)
Set the current level of this special item.

Parameters:
lv - New level

getStringValue

public java.lang.String getStringValue()
Get the current string value, if any, of this special item. This is an optional field whose meaning is specific to the item type (typeKey).

Returns:
Current string value, or null

setStringValue

public void setStringValue(java.lang.String sv)
Set or clear the current string value of this special item.

Parameters:
sv - New value, or null to clear

getCost

public SOCResourceSet getCost()
Get the optional cost to buy, use, or build the next level. Not sent over the network; see class javadoc.

Returns:
Cost, or null
See Also:
checkCost(SOCPlayer)

setCost

public void setCost(SOCResourceSet co)
Set or clear the optional cost to buy, use, or build the next level. Not sent over the network; see class javadoc.

Parameters:
co - New cost, or null to clear

checkCost

public final boolean checkCost(SOCPlayer pl)
Does this player have resources for this special item's getCost(), if any?

Parameters:
pl - Player to check
Returns:
True if cost is null or pl.getResources() contains the cost
See Also:
checkRequirements(SOCPlayer, boolean)

checkRequirements

public final boolean checkRequirements(SOCPlayer pl,
                                       boolean checkCost)
                                throws java.lang.IllegalArgumentException,
                                       java.lang.UnsupportedOperationException
Does this player meet this special item's req requirements?

Parameters:
pl - Player to check
checkCost - If true, also check the cost against player's current resources
Returns:
True if player meets the requirements, false otherwise; true if req is null or empty. If checkCost and getCost() != null, false unless player's resources contain cost.
Throws:
java.lang.IllegalArgumentException - if req has an unknown requirement type, or refers to an Added Layout Part "N1" through "N9" that isn't defined in the board layout
java.lang.UnsupportedOperationException - if requirement type S (Settlement) includes atPort location; this is not implemented
See Also:
checkRequirements(SOCPlayer, List), checkCost(SOCPlayer)

checkRequirements

public static boolean checkRequirements(SOCPlayer pl,
                                        java.util.List<SOCSpecialItem.Requirement> reqsList)
                                 throws java.lang.IllegalArgumentException,
                                        java.lang.UnsupportedOperationException
Does this player meet a special item's requirements?

Parameters:
pl - Player to check
reqsList - Requirements list; to parse from a string, use SOCSpecialItem.Requirement.parse(String)
Returns:
True if player meets the requirements, false otherwise; true if reqsList is null or empty
Throws:
java.lang.IllegalArgumentException - if reqsList has an unknown requirement type, or refers to an Added Layout Part "N1" through "N9" that isn't defined in the board layout
java.lang.UnsupportedOperationException - if requirement type S (Settlement) includes atPort location; this is not implemented
See Also:
checkRequirements(SOCPlayer, boolean)

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object
Returns:
a human readable form of this object

equals

public boolean equals(java.lang.Object other)
Compare this SOCSpecialItem to another SOCSpecialItem, or another object. Comparison method:

Overrides:
equals in class java.lang.Object
Parameters:
other - The object to compare with, or null

clone

public SOCSpecialItem clone()
                     throws java.lang.CloneNotSupportedException
For use in set copy constructors, create and return a clone of this SOCSpecialItem. The SOCSpecialItem implementation just calls super.clone(). If subclasses have any lists or structures, be sure to deeply copy them. Requirements aren't deep-copied, because they are final and won't change.

Overrides:
clone in class java.lang.Object
Returns:
a clone of this item
Throws:
java.lang.CloneNotSupportedException - Declared from super.clone(), should not occur since SOCSpecialItem implements Cloneable.