soc.game
Class SOCScenario

java.lang.Object
  extended by soc.game.SOCVersionedItem
      extended by soc.game.SOCScenario
All Implemented Interfaces:
java.lang.Cloneable, java.lang.Comparable<java.lang.Object>

public class SOCScenario
extends SOCVersionedItem
implements java.lang.Cloneable, java.lang.Comparable<java.lang.Object>

Scenarios for game rules and options on the large sea board. Chooseable at game creation. This class holds the known scenarios, at the client or server, in a static dictionary of known scenarios; see getAllKnownScenarios() for the current list of all known scenarios.

For information about adding or changing game scenarios in a later version of JSettlers, please see initAllScenarios().

Scenarios use SOCGameOptions to change the game to the scenario's concept. Each scenario's scOpts field gives the scenario's option names and values. The game also knows its scenario by setting SOCGameOption "SC" = key.

Scenario name keys must start with a letter and contain only ASCII uppercase letters ('A' through 'Z'), underscore ('_'), and digits ('0' through '9'), in order to normalize handling and network message formats. This is enforced in constructors via SOCVersionedItem.isAlphanumericUpcaseAscii(String).

For the same reason, descriptions must not contain certain characters or span more than 1 line; this is checked by calling SOCMessage.isSingleLineAndSafe(String) within constructors and setters.

The "known scenarios" are initialized via initAllScenarios(). See that method's description for more details on adding or changing a scenario.

Version negotiation:
Game options were introduced in 1.1.07; check server, client versions against SOCNewGameWithOptions.VERSION_FOR_NEWGAMEWITHOPTIONS. Scenarios were introduced in 2.0.00, and negotiate the same way. Each scenario has version information, because scenarios can be added or changed with new versions of JSettlers. Since games run on the server, the server is authoritative about game scenarios and options: If the client is newer, it must defer to the server's older set of known scenarios and options. At client connect, the client compares its JSettlers version number to the server's, and asks for any changes if their versions differ.

I18N:
Game scenario names and descriptions are also stored as gamescen.*.n, .p in server/strings/toClient_*.properties to be sent to clients if needed. A scenario's text can be localized with setDesc(String, String).

Since:
2.0.00
Author:
Jeremy D. Monin <jeremy@nand.net>

Field Summary
private static java.util.Map<java.lang.String,SOCScenario> allScenarios
          Set of "known scenarios".
static java.lang.String K_SC_4ISL
          Scenario key SC_4ISL for The Four Islands.
static java.lang.String K_SC_CLVI
          Scenario key SC_CLVI for SOCScenarioPlayerEvent.CLOTH_TRADE_ESTABLISHED_VILLAGE: Cloth Trade with neutral villages.
static java.lang.String K_SC_FOG
          Scenario key SC_FOG for SOCScenarioGameEvent.SGE_FOG_HEX_REVEALED (The Fog Islands scenario).
static java.lang.String K_SC_FTRI
          Scenario key SC_FTRI for the Forgotten Tribe.
static java.lang.String K_SC_NSHO
          Scenario key SC_NSHO for New Shores.
static java.lang.String K_SC_PIRI
          Scenario key SC_PIRI for Pirate Islands and fortresses.
static java.lang.String K_SC_TTD
          Scenario key SC_TTD for Through The Desert.
static java.lang.String K_SC_WOND
          Scenario key SC_WOND for Wonders.
private  java.lang.String scLongDesc
          Detailed text for the scenario description and special rules, or null.
 java.lang.String scOpts
          Scenario's SOCGameOptions, as a formatted string from SOCGameOption.packOptionsToString(Map, boolean).
static int VERSION_FOR_SCENARIOS
          Version 2.0.00 (2000) introduced game scenarios.
 
Fields inherited from class soc.game.SOCVersionedItem
desc, isKnown, key, lastModVersion, minVersion
 
Constructor Summary
private SOCScenario(boolean isKnown, java.lang.String key, int minVers, int lastModVers, java.lang.String desc, java.lang.String longDesc, java.lang.String opts)
          Create a new game scenario - common constructor.
  SOCScenario(java.lang.String key)
          Create a new unknown scenario (isKnown false).
  SOCScenario(java.lang.String key, int minVers, int lastModVers, java.lang.String desc, java.lang.String longDesc, java.lang.String opts)
          Create a new known game scenario.
 
Method Summary
static boolean addKnownScenario(SOCScenario scNew)
          Add a new known scenario (received from a server having a newer or older version), or update the scenario's information.
static void addScenario(java.util.Map<java.lang.String,SOCScenario> newScens, java.lang.String scKey)
          If a set of scenarios doesn't already include this known scenario, clone and add it.
static java.lang.StringBuilder adjustScenariosToKnown(java.util.Map<java.lang.String,SOCScenario> newScens, java.util.Map<java.lang.String,SOCScenario> knownScenarios, boolean doServerPreadjust)
          Compare a set of scenarios with known-good values.
static java.util.Map<java.lang.String,SOCScenario> cloneScenarios(java.util.Map<java.lang.String,SOCScenario> scens)
          Clone this scenario map and its contents.
 int compareTo(java.lang.Object other)
          Compare two scenarios, for display purposes.
 boolean equals(java.lang.Object other)
          Test if this scenario equals another object.
static java.util.Set<java.lang.String> getAllKnownScenarioKeynames()
          Get the key names for all known scenarios.
static java.util.Map<java.lang.String,SOCScenario> getAllKnownScenarios()
          Get all known scenario objects, mapping from their key names (such as SC_4ISL).
 java.lang.String getLongDesc()
          Detailed text for the scenario description and special rules, or null.
static SOCScenario getScenario(java.lang.String key)
          Get the scenario information about this known scenario.
 int hashCode()
          Return this scenario's hashCode for comparison purposes, which is its key's String.hashCode().
private static java.util.Map<java.lang.String,SOCScenario> initAllScenarios()
          Create a set of the known scenarios.
static java.lang.String packKnownScenariosToString()
          Utility - build a string of known scenario key names from the known scenarios.
static java.lang.String packScenariosToString(java.util.Map<java.lang.String,SOCScenario> scMap)
          Utility - build a string of known scenario names.
static java.lang.String packScenariosToString(java.util.Map<java.lang.String,SOCScenario> scMap, int cliVers)
          Utility - build a string of known scenario names, adjusting for old clients if necessary.
static java.util.Map<java.lang.String,SOCScenario> parseScenariosToMap(java.lang.String scstr)
          Utility - build a map by parsing a list of scenario names.
static void removeUnknownScenario(java.lang.String scKey)
          Remove a scenario from known scenarios, based on info received from a server having an older or newer version.
 void setDesc(java.lang.String desc, java.lang.String longDesc)
          For i18n, update the scenario's description text fields: The name/short description (SOCVersionedItem.getDesc()) and optional long description (getLongDesc()).
 java.lang.String toString()
          Get this scenario's description, for use in user-facing displays and GUI elements.
 
Methods inherited from class soc.game.SOCVersionedItem
findUnknowns, getDesc, getMinVersion, implItemsVersionCheck, isAlphanumericUpcaseAscii, itemsForVersion, itemsMinimumVersion, itemsMinimumVersion, itemsNewerThanVersion, setDesc
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

VERSION_FOR_SCENARIOS

public static final int VERSION_FOR_SCENARIOS
Version 2.0.00 (2000) introduced game scenarios.

See Also:
Constant Field Values

allScenarios

private static java.util.Map<java.lang.String,SOCScenario> allScenarios
Set of "known scenarios". allScenarios must never be null, because other places assume it is filled. All scenarios here have their isKnown flag set true. To add or change a scenario, see initAllScenarios().


K_SC_NSHO

public static final java.lang.String K_SC_NSHO
Scenario key SC_NSHO for New Shores. Board layout is the standard 4- or 6-player board, or a smaller 3-player main island, plus small outlying islands. No main option or special rules, only the board layout and 2 SVP for reaching each island.

See Also:
Constant Field Values

K_SC_4ISL

public static final java.lang.String K_SC_4ISL
Scenario key SC_4ISL for The Four Islands. No main option or special rules, only a board layout and SVP.

See Also:
Constant Field Values

K_SC_FOG

public static final java.lang.String K_SC_FOG
Scenario key SC_FOG for SOCScenarioGameEvent.SGE_FOG_HEX_REVEALED (The Fog Islands scenario). Main option is SOCGameOption.K_SC_FOG.

See Also:
Constant Field Values

K_SC_TTD

public static final java.lang.String K_SC_TTD
Scenario key SC_TTD for Through The Desert. No main option or special rules, only a board layout and SVP.

See Also:
Constant Field Values

K_SC_CLVI

public static final java.lang.String K_SC_CLVI
Scenario key SC_CLVI for SOCScenarioPlayerEvent.CLOTH_TRADE_ESTABLISHED_VILLAGE: Cloth Trade with neutral villages. Main option is SOCGameOption.K_SC_CLVI.

See Also:
Constant Field Values

K_SC_PIRI

public static final java.lang.String K_SC_PIRI
Scenario key SC_PIRI for Pirate Islands and fortresses. Main option is SOCGameOption.K_SC_PIRI.

A pirate fleet circulates on a predefined path, stealing resources from weak players with adjacent settlements/cities until the player upgrades their ships to warships. To win, the player must build ships directly to the Fortress with their color, and defeat it several times using warships. Also, ship routes can't branch in different directions in this scenario, only extend from their ends.

See Also:
Constant Field Values

K_SC_FTRI

public static final java.lang.String K_SC_FTRI
Scenario key SC_FTRI for the Forgotten Tribe. Main option is "_SC_FTRI".

Far areas of the board have small habitations of a "forgotten tribe" of settlers. When players reach them (with a ship adjacent to various edge coordinates), they are greeted with "gifts" of a development card or Special Victory Point.

Trade ports at these far areas can be claimed by players and must be moved adjacent to one of their coastal settlements/cities, unless they have none that isn't at least separated 1 edge from an existing port. If that's the case, the claimed port is "set aside" for the player to place later when they have such a coastal settlement.

When a player reaches a Special Edge and is awarded a gift, the game clears that edge's special type, then fires a SOCScenarioPlayerEvent.DEV_CARD_REACHED_SPECIAL_EDGE or SOCScenarioPlayerEvent.SVP_REACHED_SPECIAL_EDGE event.

When a player reaches a "gift" trade port, either the port is added to their inventory as a SOCInventoryItem for later placement, or they must immediately place it: SOCGame.setPlacingItem(SOCInventoryItem) is called, state becomes SOCGame.PLACING_INV_ITEM.

See Also:
Constant Field Values

K_SC_WOND

public static final java.lang.String K_SC_WOND
Scenario key SC_WOND for Wonders. Main option is "_SC_WOND". The pirate ship is not used in this scenario.

Players must choose a unique Wonder and build all 4 of its levels. Each Wonder has its own requirements before they may start it, such as a harbor location or number of cities built.

When a player starts to build a wonder, it's added to their Special Items for visibility; see below.

To win, the player must complete their Wonder's 4 levels, or reach 10 VP and complete more levels than any other player.

Certain sets of nodes are special in this scenario's board layout. Node sets are retrieved from SOCBoardLarge.getAddedLayoutPart(String) by key:

This scenario also uses added layout part "AL" to specify that the nodes in N1, N2, and N3 become legal locations for settlements after initial placement.

The Wonders are stored as per-game Special Items: There are (1 + SOCGame.maxPlayers) wonders available, held in game Special Item indexes 1 - n, with type key SOCGameOption.K_SC_WOND, initialized in SOCGame.updateAtBoardLayout(). When a player starts to build a Wonder, a reference to its SOCSpecialItem is placed into index 0 of their Special Items: pl.setSpecialItem("_SC_WOND", 0, item).

The player's request to build must use player item index (pi) 0, game item index (gi) 1 to n.

See Also:
Constant Field Values

scOpts

public java.lang.String scOpts
Scenario's SOCGameOptions, as a formatted string from SOCGameOption.packOptionsToString(Map, boolean).


scLongDesc

private java.lang.String scLongDesc
Detailed text for the scenario description and special rules, or null. See getLongDesc() for more info and requirements.

Constructor Detail

SOCScenario

public SOCScenario(java.lang.String key)
            throws java.lang.IllegalArgumentException
Create a new unknown scenario (isKnown false). Minimum version will be Integer.MAX_VALUE. scDesc and scOpts will be an empty string.

Parameters:
key - Alphanumeric key name for this option; see SOCVersionedItem.isAlphanumericUpcaseAscii(String) for format.
Throws:
java.lang.IllegalArgumentException - if key length is > 8 or not alphanumeric

SOCScenario

public SOCScenario(java.lang.String key,
                   int minVers,
                   int lastModVers,
                   java.lang.String desc,
                   java.lang.String longDesc,
                   java.lang.String opts)
            throws java.lang.IllegalArgumentException
Create a new known game scenario.

Parameters:
key - Alphanumeric key name for this scenario; see SOCVersionedItem.isAlphanumericUpcaseAscii(String) for format.
minVers - Minimum client version supporting this scenario, or -1. Same format as Version.versionNumber(). If not -1, minVers must be at least 2000 (VERSION_FOR_SCENARIOS). To calculate the minimum version of a set of game options which might include a scenario, use SOCVersionedItem.itemsMinimumVersion(opts). That calculation won't be done automatically by this constructor.
lastModVers - Last-modified version for this scenario, or version which added it. This is the last change to the scenario itself as declared in getAllKnownScenarios(): Ignore changes to opts last-modified versions, because changed option info is sent separately and automatically when the client connects.
desc - Descriptive brief text, to appear in the scenarios dialog. Desc must not contain SOCMessage.sep_char or SOCMessage.sep2_char, and must evaluate true from SOCMessage.isSingleLineAndSafe(String).
longDesc - Longer descriptive text, or null; see getLongDesc() for requirements.
opts - Scenario's SOCGameOptions, as a formatted string from SOCGameOption.packOptionsToString(Map, boolean). Never "" or null.
Throws:
java.lang.IllegalArgumentException - if key length is > 8 or not alphanumeric, or if opts is null or the empty string "", or if desc contains SOCMessage.sep_char or SOCMessage.sep2_char or fail their described requirements, or if minVers or lastModVers is under 2000 but not -1

SOCScenario

private SOCScenario(boolean isKnown,
                    java.lang.String key,
                    int minVers,
                    int lastModVers,
                    java.lang.String desc,
                    java.lang.String longDesc,
                    java.lang.String opts)
             throws java.lang.IllegalArgumentException
Create a new game scenario - common constructor.

Parameters:
isKnown - True if scenario is known here (isKnown true)
key - Alphanumeric uppercase code for this scenario; see SOCVersionedItem.isAlphanumericUpcaseAscii(String) for format. Keys can be up to 8 characters long.
minVers - Minimum client version supporting this scenario, or -1. Same format as Version.versionNumber(). If not -1, minVers must be at least 2000 (VERSION_FOR_SCENARIOS). To calculate the minimum version of a set of game options which might include a scenario, use SOCVersionedItem.itemsMinimumVersion(opts). That calculation won't be done automatically by this constructor.
lastModVers - Last-modified version for this scenario, or version which added it. This is the last change to the scenario itself as declared in getAllKnownScenarios(): Ignore changes to opts last-modified versions, because changed option info is sent separately and automatically when the client connects.
desc - Descriptive brief text, to appear in the scenarios dialog. Desc must not contain SOCMessage.sep_char or SOCMessage.sep2_char, and must evaluate true from SOCMessage.isSingleLineAndSafe(String).
longDesc - Longer descriptive text, or null; see getLongDesc() for requirements.
opts - Scenario's SOCGameOptions, as a formatted string from SOCGameOption.packOptionsToString(Map, boolean). Never "" or null.
Throws:
java.lang.IllegalArgumentException - if key is not alphanumeric or length is > 8, or if desc contains SOCMessage.sep_char or SOCMessage.sep2_char, or if opts is null or the empty string "", or if minVers or lastModVers is under 2000 but not -1
Method Detail

initAllScenarios

private static java.util.Map<java.lang.String,SOCScenario> initAllScenarios()
Create a set of the known scenarios. This method creates and returns a Map, but does not set the static allScenarios field. See getAllKnownScenarios() for the current list of known scenarios.

If you want to add a game scenario:

If you want to change a scenario (in a later version):

Typical changes to a game scenario would be: Things you can't change about a scenario, because inconsistencies would occur: To make the change:

If you want to remove or obsolete a game scenario (in a later version):

Please think twice beforehand; users may be surprised when something is missing, so this shouldn't be done without a very good reason. That said, the server is authoritative on scenarios. If a scenario isn't in its known list (initAllScenarios()), the client won't be allowed to ask for it. Any obsolete scenario should be kept around as commented-out code. See SOCGameOption.initAllOptions() for things to think about when removing game options used only in the obsolete scenario.

Returns:
a fresh copy of the "known" scenarios, with their hardcoded default values

getAllKnownScenarios

public static java.util.Map<java.lang.String,SOCScenario> getAllKnownScenarios()
Get all known scenario objects, mapping from their key names (such as SC_4ISL).

Current Known Scenarios:

(See each scenario name field's javadoc for more details.)

Returns:
a deep copy of all known scenario objects
See Also:
getAllKnownScenarioKeynames(), addKnownScenario(SOCScenario)

getAllKnownScenarioKeynames

public static java.util.Set<java.lang.String> getAllKnownScenarioKeynames()
Get the key names for all known scenarios. This method avoids the copying overhead of getAllKnownScenarios().

Returns:
The set of all scenarios' key names, such as SC_4ISL. Please treat the returned set as read-only.
See Also:
getAllKnownScenarios()

addKnownScenario

public static boolean addKnownScenario(SOCScenario scNew)
Add a new known scenario (received from a server having a newer or older version), or update the scenario's information.

Parameters:
scNew - New scenario, or a changed version of one we already know.
Returns:
true if it's new, false if we already had that key and it was updated
See Also:
getAllKnownScenarios(), removeUnknownScenario(String)

removeUnknownScenario

public static void removeUnknownScenario(java.lang.String scKey)
Remove a scenario from known scenarios, based on info received from a server having an older or newer version. If scKey isn't a known scenario, does nothing.

Parameters:
scKey - Scenario key marked as unknown by the server
See Also:
getAllKnownScenarios(), addKnownScenario(SOCScenario)

cloneScenarios

public static java.util.Map<java.lang.String,SOCScenario> cloneScenarios(java.util.Map<java.lang.String,SOCScenario> scens)
Clone this scenario map and its contents.

Parameters:
scens - a map of SOCScenarios, or null
Returns:
a deep copy of all scenario objects within scens, or null if scens is null

getScenario

public static SOCScenario getScenario(java.lang.String key)
Get the scenario information about this known scenario.

Parameters:
key - Scenario key name, such as SC_4ISL, from getAllKnownScenarios()
Returns:
information about a known scenario, or null if none with that key

packKnownScenariosToString

public static java.lang.String packKnownScenariosToString()
Utility - build a string of known scenario key names from the known scenarios.

Returns:
string of key names, same format as packScenariosToString(Map); any scenarios with isKnown false will not be part of the string.
See Also:
parseScenariosToMap(String)

packScenariosToString

public static java.lang.String packScenariosToString(java.util.Map<java.lang.String,SOCScenario> scMap)
Utility - build a string of known scenario names. This can be unpacked with parseScenariosToMap(String).

Parameters:
scMap - Map of scenarios, or null
Returns:
string of scenario key names, or "-" for an empty or null scMap. Format: k1,k2,k3

packScenariosToString

public static java.lang.String packScenariosToString(java.util.Map<java.lang.String,SOCScenario> scMap,
                                                     int cliVers)
Utility - build a string of known scenario names, adjusting for old clients if necessary. This can be unpacked with parseScenariosToMap(String). See packScenariosToString(Map) javadoc for details.

Parameters:
scMap - Map of SOCScenarios, or null
cliVers - Client version; assumed >= 2000 (VERSION_FOR_SCENARIOS). If any game's scenarios can't be sent to an older client, skip them.
Returns:
string of scenario key names, or "-" for an empty or null scMap; see packScenariosToString(Map) javadoc for details.

parseScenariosToMap

public static java.util.Map<java.lang.String,SOCScenario> parseScenariosToMap(java.lang.String scstr)
Utility - build a map by parsing a list of scenario names.

Parameters:
scstr - string of key names, as created by packScenariosToString(Map). A leading comma is OK (possible artifact of StringTokenizer coming from over the network). If scstr=="-", the map will be null.
Returns:
map of SOCScenarios, or null if scstr==null or empty ("-") or if scstr is malformed. Any unrecognized scenarios will be in the map with isKnown false.

adjustScenariosToKnown

public static java.lang.StringBuilder adjustScenariosToKnown(java.util.Map<java.lang.String,SOCScenario> newScens,
                                                             java.util.Map<java.lang.String,SOCScenario> knownScenarios,
                                                             boolean doServerPreadjust)
Compare a set of scenarios with known-good values. If any are unknown, return a description. Will still check the known ones.

Parameters:
newScens - Set of SOCScenarios to check against knownScenarios; Must not be null.
knownScenarios - Set of known SOCScenarios to check against, or null to use the server's static copy
Returns:
null if all are known; or, a human-readable problem description if:

addScenario

public static void addScenario(java.util.Map<java.lang.String,SOCScenario> newScens,
                               java.lang.String scKey)
                        throws java.lang.NullPointerException
If a set of scenarios doesn't already include this known scenario, clone and add it.

Parameters:
newScens - Set to set scKey within
scKey - Key name for scenario to include
Throws:
java.lang.NullPointerException - if scKey isn't in newScens and doesn't exist in the set of known scenarios

getLongDesc

public java.lang.String getLongDesc()
Detailed text for the scenario description and special rules, or null. Shown as a reminder at start of a game. Must not contain network delimiter character SOCMessage.sep_char; SOCMessage.sep2_char is okay. Must pass SOCMessage.isSingleLineAndSafe(String, true). Don't include the description of any scenario game option, such as SOCGameOption.K_SC_SANY; those will be taken from SOCGameOption.desc and shown in the reminder message.

To update this field use setDesc(String, String).

Returns:
The long description, or null if none

setDesc

public void setDesc(java.lang.String desc,
                    java.lang.String longDesc)
             throws java.lang.IllegalArgumentException
For i18n, update the scenario's description text fields: The name/short description (SOCVersionedItem.getDesc()) and optional long description (getLongDesc()).

Parameters:
desc - Descriptive brief text, to appear in the scenarios dialog. Not null. Desc must not contain SOCMessage.sep_char or SOCMessage.sep2_char, and must evaluate true from SOCMessage.isSingleLineAndSafe(String).
longDesc - Longer descriptive text, or null; see getLongDesc() for requirements.
Throws:
java.lang.IllegalArgumentException - if desc contains SOCMessage.sep_char or SOCMessage.sep2_char, or desc or longDesc fails SOCMessage.isSingleLineAndSafe(String, boolean)
See Also:
SOCVersionedItem.setDesc(String)

toString

public java.lang.String toString()
Get this scenario's description, for use in user-facing displays and GUI elements. For a short unique identifier use SOCVersionedItem.key instead.

Overrides:
toString in class java.lang.Object
Returns:
desc

compareTo

public int compareTo(java.lang.Object other)
Compare two scenarios, for display purposes. (Comparable interface) Two game scenarios are considered equal if they have the same key. Greater/lesser is determined by getDesc().compareTo().

Specified by:
compareTo in interface java.lang.Comparable<java.lang.Object>
Parameters:
other - A SOCScenario to compare, or another object; if other isn't a scenario, the hashCode()s are compared.
See Also:
equals(Object)

equals

public boolean equals(java.lang.Object other)
Test if this scenario equals another object. Two game scenarios are considered equal if they have the same key.

Overrides:
equals in class java.lang.Object
Parameters:
other - A SOCScenario to compare, or another object; if other isn't a scenario, calls Object.equals(other).
See Also:
compareTo(Object), hashCode()

hashCode

public int hashCode()
Return this scenario's hashCode for comparison purposes, which is its key's String.hashCode().

Overrides:
hashCode in class java.lang.Object
See Also:
equals(Object)