Search in sources :

Example 1 with SOCGameOption

use of soc.game.SOCGameOption in project JSettlers2 by jdmonin.

the class SOCBoardAtServer method makeNewBoard.

// //////////////////////////////////////////
// 
// Make New Board
// 
// To add a new board layout, see the class javadoc.
// 
/**
 * Shuffle the hex tiles and layout a board.
 * Sets up land hex types, water, ports, dice numbers, Land Areas' contents, starting Land Area if any,
 * and the legal/potential node sets ({@link SOCBoardLarge#getLegalSettlements()}).
 * Sets up any Added Layout Parts such as {@code "PP", "CE", "VE", "N1"}, etc.
 *<P>
 * This is called at server, but not at client;
 * client instead calls methods such as {@link #setLandHexLayout(int[])}
 * and {@link #setLegalSettlements(Collection, int, HashSet[])},
 * see {@link SOCBoardLarge} class javadoc.
 * @param opts {@link SOCGameOption Game options}, which may affect
 *          tile placement on board, or null.  <tt>opts</tt> must be
 *          the same as passed to constructor, and thus give the same size and layout
 *          (same {@link #getBoardEncodingFormat()}).
 */
@SuppressWarnings("unchecked")
@Override
public void makeNewBoard(final Map<String, SOCGameOption> opts) {
    final SOCGameOption opt_breakClumps = (opts != null ? opts.get("BC") : null);
    SOCGameOption opt = (opts != null ? opts.get(SOCGameOption.K_SC_FOG) : null);
    final boolean hasScenarioFog = (opt != null) && opt.getBoolValue();
    // scenario key, such as SOCScenario.K_SC_4ISL, or empty string
    final String scen;
    {
        final SOCGameOption optSC = (opts != null ? opts.get("SC") : null);
        if (optSC != null) {
            final String ostr = optSC.getStringValue();
            scen = (ostr != null) ? ostr : "";
        } else {
            scen = "";
        }
    }
    /**
     * _SC_4ISL doesn't require startingLandArea, it remains 0; all other scenarios require it.
     */
    final boolean hasScenario4ISL = scen.equals(SOCScenario.K_SC_4ISL);
    // For scenario boards, use 3-player or 4-player or 6-player layout?
    // Always test maxPl for ==6 or < 4 ; actual value may be 6, 4, 3, or 2.
    // Same maxPl initialization as in getBoardShift(opts) and getBoardSize(..).
    final int maxPl;
    if (maxPlayers == 6) {
        maxPl = 6;
    } else {
        opt = (opts != null ? opts.get("PL") : null);
        if (opt == null)
            maxPl = 4;
        else if (opt.getIntValue() > 4)
            maxPl = 6;
        else
            maxPl = opt.getIntValue();
    }
    // unless hasScenario4ISL. Set that field now, in case a board-setup method wants it.
    if (!hasScenario4ISL)
        startingLandArea = 1;
    // shuffle and place the land hexes, numbers, and robber:
    // sets robberHex, contents of hexLayout[] and numberLayout[].
    // Adds to landHexLayout and nodesOnLand.
    // Clears cachedGetlandHexCoords.
    // Also checks vs game option BC: Break up clumps of # or more same-type hexes/ports
    // port types, or null if none
    final int[] PORTS_TYPES_MAINLAND, PORTS_TYPES_ISLANDS;
    // port edge locations and facings
    final int[] PORT_LOC_FACING_MAINLAND, PORT_LOC_FACING_ISLANDS;
    if (hasScenario4ISL) {
        if (maxPl < 4) {
            landAreasLegalNodes = new HashSet[5];
            makeNewBoard_placeHexes(FOUR_ISL_LANDHEX_TYPE_3PL, FOUR_ISL_LANDHEX_COORD_3PL, FOUR_ISL_DICENUM_3PL, true, true, FOUR_ISL_LANDHEX_LANDAREA_RANGES_3PL, false, maxPl, opt_breakClumps, scen);
            PORTS_TYPES_MAINLAND = FOUR_ISL_PORT_TYPE_3PL;
            PORT_LOC_FACING_MAINLAND = FOUR_ISL_PORT_EDGE_FACING_3PL;
            pirateHex = FOUR_ISL_PIRATE_HEX[0];
        } else if (maxPl != 6) {
            landAreasLegalNodes = new HashSet[5];
            makeNewBoard_placeHexes(FOUR_ISL_LANDHEX_TYPE_4PL, FOUR_ISL_LANDHEX_COORD_4PL, FOUR_ISL_DICENUM_4PL, true, true, FOUR_ISL_LANDHEX_LANDAREA_RANGES_4PL, false, maxPl, opt_breakClumps, scen);
            PORTS_TYPES_MAINLAND = FOUR_ISL_PORT_TYPE_4PL;
            PORT_LOC_FACING_MAINLAND = FOUR_ISL_PORT_EDGE_FACING_4PL;
            pirateHex = FOUR_ISL_PIRATE_HEX[1];
        } else {
            // Six Islands
            landAreasLegalNodes = new HashSet[7];
            makeNewBoard_placeHexes(FOUR_ISL_LANDHEX_TYPE_6PL, FOUR_ISL_LANDHEX_COORD_6PL, FOUR_ISL_DICENUM_6PL, true, true, FOUR_ISL_LANDHEX_LANDAREA_RANGES_6PL, false, maxPl, opt_breakClumps, scen);
            PORTS_TYPES_MAINLAND = FOUR_ISL_PORT_TYPE_6PL;
            PORT_LOC_FACING_MAINLAND = FOUR_ISL_PORT_EDGE_FACING_6PL;
            pirateHex = FOUR_ISL_PIRATE_HEX[2];
        }
        PORT_LOC_FACING_ISLANDS = null;
        PORTS_TYPES_ISLANDS = null;
    } else if (scen.equals(SOCScenario.K_SC_TTD)) {
        // Through The Desert
        // 6-player, 4, or 3-player board
        final int idx = (maxPl > 4) ? 2 : (maxPl > 3) ? 1 : 0;
        // Land Area count varies by number of players;
        // 2 + number of small islands.  Array length has + 1 for unused landAreasLegalNodes[0].
        landAreasLegalNodes = new HashSet[1 + 2 + (TTDESERT_LANDHEX_RANGES_SMALL[idx].length / 2)];
        // - Desert strip (not part of any landarea)
        {
            final int[] desertLandHexCoords = TTDESERT_LANDHEX_COORD_DESERT[idx];
            // all 0
            final int[] desertDiceNum = new int[desertLandHexCoords.length];
            final int[] desertLandhexType = new int[desertLandHexCoords.length];
            Arrays.fill(desertLandhexType, DESERT_HEX);
            makeNewBoard_placeHexes(desertLandhexType, desertLandHexCoords, desertDiceNum, false, false, 0, false, maxPl, null, scen);
        }
        // - Main island (landarea 1 and 2)
        makeNewBoard_placeHexes(TTDESERT_LANDHEX_TYPE_MAIN[idx], TTDESERT_LANDHEX_COORD_MAIN[idx], TTDESERT_DICENUM_MAIN[idx], true, true, TTDESERT_LANDHEX_RANGES_MAIN[idx], false, maxPl, opt_breakClumps, scen);
        // - Small islands (LA 3 to n)
        makeNewBoard_placeHexes(TTDESERT_LANDHEX_TYPE_SMALL[idx], TTDESERT_LANDHEX_COORD_SMALL[idx], TTDESERT_DICENUM_SMALL[idx], true, true, TTDESERT_LANDHEX_RANGES_SMALL[idx], false, maxPl, null, scen);
        pirateHex = TTDESERT_PIRATE_HEX[idx];
        PORTS_TYPES_MAINLAND = TTDESERT_PORT_TYPE[idx];
        PORTS_TYPES_ISLANDS = null;
        PORT_LOC_FACING_MAINLAND = TTDESERT_PORT_EDGE_FACING[idx];
        PORT_LOC_FACING_ISLANDS = null;
    } else if (scen.equals(SOCScenario.K_SC_PIRI)) {
        // Pirate Islands
        landAreasLegalNodes = new HashSet[2];
        // 4-player or 6-player board
        final int idx = (maxPl > 4) ? 1 : 0;
        // - Large starting island
        makeNewBoard_placeHexes(PIR_ISL_LANDHEX_TYPE_MAIN[idx], PIR_ISL_LANDHEX_COORD_MAIN[idx], PIR_ISL_DICENUM_MAIN[idx], false, false, 1, false, maxPl, opt_breakClumps, scen);
        // - Pirate islands
        // (LA # 0: Player can't place there except at their Lone Settlement coordinate within "LS".)
        makeNewBoard_placeHexes(PIR_ISL_LANDHEX_TYPE_PIRI[idx], PIR_ISL_LANDHEX_COORD_PIRI[idx], PIR_ISL_DICENUM_PIRI[idx], false, false, 0, false, maxPl, opt_breakClumps, scen);
        pirateHex = PIR_ISL_PIRATE_HEX[idx];
        PORTS_TYPES_MAINLAND = PIR_ISL_PORT_TYPE[idx];
        PORTS_TYPES_ISLANDS = null;
        PORT_LOC_FACING_MAINLAND = PIR_ISL_PORT_EDGE_FACING[idx];
        PORT_LOC_FACING_ISLANDS = null;
        setAddedLayoutPart("PP", PIR_ISL_PPATH[idx]);
    } else if (scen.equals(SOCScenario.K_SC_FTRI)) {
        // Forgotten Tribe
        landAreasLegalNodes = new HashSet[2];
        // 4-player or 6-player board
        final int idx = (maxPl > 4) ? 1 : 0;
        // - Larger main island
        makeNewBoard_placeHexes(FOR_TRI_LANDHEX_TYPE_MAIN[idx], FOR_TRI_LANDHEX_COORD_MAIN[idx], FOR_TRI_DICENUM_MAIN[idx], true, true, 1, false, maxPl, opt_breakClumps, scen);
        // - Small outlying islands for tribe
        // (LA # 0; Player can't place there)
        makeNewBoard_placeHexes(FOR_TRI_LANDHEX_TYPE_ISL[idx], FOR_TRI_LANDHEX_COORD_ISL[idx], null, false, false, 0, false, maxPl, null, scen);
        pirateHex = FOR_TRI_PIRATE_HEX[idx];
        // The 4-player board doesn't have enough 3-for-1 ports for that to work.
        if (maxPl > 4) {
            // PORTS_TYPES_MAINLAND breaks clumps
            PORTS_TYPES_MAINLAND = FOR_TRI_PORT_TYPE[idx];
            PORTS_TYPES_ISLANDS = null;
            PORT_LOC_FACING_MAINLAND = FOR_TRI_PORT_EDGE_FACING[idx];
            PORT_LOC_FACING_ISLANDS = null;
        } else {
            PORTS_TYPES_MAINLAND = null;
            // PORTS_TYPES_ISLAND doesn't break clumps
            PORTS_TYPES_ISLANDS = FOR_TRI_PORT_TYPE[idx];
            PORT_LOC_FACING_MAINLAND = null;
            PORT_LOC_FACING_ISLANDS = FOR_TRI_PORT_EDGE_FACING[idx];
        }
        setAddedLayoutPart("CE", FOR_TRI_DEV_CARD_EDGES[idx]);
        setAddedLayoutPart("VE", FOR_TRI_SVP_EDGES[idx]);
    // startGame_putInitPieces will set aside dev cards for players to reach "CE" special edges.
    } else if (scen.equals(SOCScenario.K_SC_CLVI)) {
        // Cloth Villages
        landAreasLegalNodes = new HashSet[2];
        // 4-player or 6-player board
        final int idx = (maxPl > 4) ? 1 : 0;
        // - Larger main islands
        makeNewBoard_placeHexes(CLVI_LANDHEX_TYPE_MAIN[idx], CLVI_LANDHEX_COORD_MAIN[idx], CLVI_DICENUM_MAIN[idx], true, true, 1, false, maxPl, opt_breakClumps, scen);
        // - Small middle islands for villages
        // (LA # 0; Players can't place there)
        makeNewBoard_placeHexes(CLVI_LANDHEX_TYPE_ISL[idx], CLVI_LANDHEX_COORD_ISL[idx], null, false, false, 0, false, maxPl, null, scen);
        pirateHex = CLVI_PIRATE_HEX[idx];
        // The 4-player board doesn't have enough 3-for-1 ports for that to work.
        if (maxPl > 4) {
            // PORTS_TYPES_MAINLAND breaks clumps
            PORTS_TYPES_MAINLAND = CLVI_PORT_TYPE[idx];
            PORTS_TYPES_ISLANDS = null;
            PORT_LOC_FACING_MAINLAND = CLVI_PORT_EDGE_FACING[idx];
            PORT_LOC_FACING_ISLANDS = null;
        } else {
            PORTS_TYPES_MAINLAND = null;
            // PORTS_TYPES_ISLAND doesn't break clumps
            PORTS_TYPES_ISLANDS = CLVI_PORT_TYPE[idx];
            PORT_LOC_FACING_MAINLAND = null;
            PORT_LOC_FACING_ISLANDS = CLVI_PORT_EDGE_FACING[idx];
        }
        final int[] cl = CLVI_CLOTH_VILLAGE_AMOUNTS_NODES_DICE[idx];
        // also sets board's "general supply"
        setVillageAndClothLayout(cl);
        setAddedLayoutPart("CV", cl);
    } else if (scen.equals(SOCScenario.K_SC_WOND)) {
        // Wonders
        landAreasLegalNodes = new HashSet[3];
        // 4-player or 6-player board
        final int idx = (maxPl > 4) ? 1 : 0;
        // - Large main island
        makeNewBoard_placeHexes(WOND_LANDHEX_TYPE_MAIN[idx], WOND_LANDHEX_COORD_MAIN[idx], WOND_DICENUM_MAIN[idx], true, true, 1, false, maxPl, opt_breakClumps, scen);
        // - Desert on main island (not shuffled with other hexes)
        int[] desert = new int[WOND_LANDHEX_COORD_DESERT[idx].length];
        Arrays.fill(desert, DESERT_HEX);
        makeNewBoard_placeHexes(desert, WOND_LANDHEX_COORD_DESERT[idx], null, false, false, 1, true, maxPl, null, scen);
        // - Small outlying islands (LA #2)
        makeNewBoard_placeHexes(WOND_LANDHEX_TYPE_ISL[idx], WOND_LANDHEX_COORD_ISL[idx], WOND_DICENUM_ISL[idx], false, false, 2, false, maxPl, null, scen);
        pirateHex = 0;
        // ports
        // PORTS_TYPES_MAINLAND breaks clumps
        PORTS_TYPES_MAINLAND = WOND_PORT_TYPE[idx];
        PORTS_TYPES_ISLANDS = null;
        PORT_LOC_FACING_MAINLAND = WOND_PORT_EDGE_FACING[idx];
        PORT_LOC_FACING_ISLANDS = null;
        // Will have to re-add after initial placement, via addLegalNodes from SOCGame.updateAtGameFirstTurn().
        for (int i = 0; i <= 2; ++i) makeNewBoard_removeLegalNodes(WOND_SPECIAL_NODES[idx][i], startingLandArea, i + 1, (i == 2));
    } else if (// _SC_FOG
    hasScenarioFog) {
        // for pirate: 3, 4, or 6-player board
        final int idx;
        landAreasLegalNodes = new HashSet[((maxPl == 6) ? 4 : 3)];
        if (maxPl < 4) {
            // - East and West islands:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_MAIN_3PL, FOG_ISL_LANDHEX_COORD_MAIN_3PL, FOG_ISL_DICENUM_MAIN_3PL, true, true, 1, false, maxPl, opt_breakClumps, scen);
            // - "Fog Island" in the middle:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_FOG, FOG_ISL_LANDHEX_COORD_FOG_3PL, FOG_ISL_DICENUM_FOG_3PL, true, true, 2, false, maxPl, null, scen);
            PORTS_TYPES_MAINLAND = FOG_ISL_PORT_TYPE_3PL;
            PORT_LOC_FACING_MAINLAND = FOG_ISL_PORT_EDGE_FACING_3PL;
            idx = 0;
        } else if (maxPl == 4) {
            // - East and West islands:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_MAIN_4PL, FOG_ISL_LANDHEX_COORD_MAIN_4PL, FOG_ISL_DICENUM_MAIN_4PL, true, true, 1, false, maxPl, opt_breakClumps, scen);
            // - "Fog Island" in the middle:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_FOG, FOG_ISL_LANDHEX_COORD_FOG_4PL, FOG_ISL_DICENUM_FOG_4PL, true, true, 2, false, maxPl, null, scen);
            PORTS_TYPES_MAINLAND = FOG_ISL_PORT_TYPE_4PL;
            PORT_LOC_FACING_MAINLAND = FOG_ISL_PORT_EDGE_FACING_4PL;
            idx = 1;
        } else // maxPl == 6
        {
            // - Northern main island:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_MAIN_6PL, FOG_ISL_LANDHEX_COORD_MAIN_6PL, FOG_ISL_DICENUM_MAIN_6PL, true, true, 1, false, maxPl, opt_breakClumps, scen);
            // - "Fog Island" in an arc from southwest to southeast:
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_FOG_6PL, FOG_ISL_LANDHEX_COORD_FOG_6PL, FOG_ISL_DICENUM_FOG_6PL, true, true, 2, false, maxPl, opt_breakClumps, scen);
            // - Gold Corners in southwest, southeast
            makeNewBoard_placeHexes(FOG_ISL_LANDHEX_TYPE_GC, FOG_ISL_LANDHEX_COORD_GC, FOG_ISL_DICENUM_GC, false, false, 3, false, maxPl, null, scen);
            PORTS_TYPES_MAINLAND = FOG_ISL_PORT_TYPE_6PL;
            PORT_LOC_FACING_MAINLAND = FOG_ISL_PORT_EDGE_FACING_6PL;
            idx = 2;
        }
        // no ports inside fog island's random layout
        PORTS_TYPES_ISLANDS = null;
        PORT_LOC_FACING_ISLANDS = null;
        pirateHex = FOG_ISL_PIRATE_HEX[idx];
    // Fog hex hiding is done below after some other steps; search for hasScenarioFog
    } else if (scen.equals(SOCScenario.K_SC_NSHO)) {
        // New Shores: Uses original 4- or 6-player board like fallback layout does, + outlying islands.
        // 3pl has 4 LAs, 4pl has 4, 6pl has 7
        landAreasLegalNodes = new HashSet[(maxPl == 6) ? 8 : 5];
        // 3-player, 4-player, or 6-player board
        final int idx = (maxPl == 6) ? 2 : (maxPl == 4) ? 1 : 0;
        // - Main island:
        makeNewBoard_placeHexes(NSHO_LANDHEX_TYPE_MAIN[idx], NSHO_LANDHEX_COORD_MAIN[idx], NSHO_DICENUM_MAIN[idx], (maxPl < 4), true, 1, false, maxPl, opt_breakClumps, scen);
        // - Outlying islands:
        makeNewBoard_placeHexes(NSHO_LANDHEX_TYPE_ISL[idx], NSHO_LANDHEX_COORD_ISL[idx], NSHO_DICENUM_ISL[idx], true, true, NSHO_LANDHEX_LANDAREA_RANGES[idx], false, maxPl, null, scen);
        pirateHex = NSHO_PIRATE_HEX[idx];
        // ports
        PORTS_TYPES_MAINLAND = NSHO_PORT_TYPE[idx];
        PORTS_TYPES_ISLANDS = null;
        PORT_LOC_FACING_MAINLAND = NSHO_PORT_EDGE_FACING[idx];
        PORT_LOC_FACING_ISLANDS = null;
    } else {
        // This is the fallback layout, the large sea board used when no scenario is chosen.
        // Size is BOARDHEIGHT_LARGE by BOARDWIDTH_LARGE for 4 players.
        // For 6 players, there's an extra row of hexes: BOARDHEIGHT_LARGE + 3.
        // hardcoded max number of land areas
        landAreasLegalNodes = new HashSet[5];
        // - Mainland:
        makeNewBoard_placeHexes((maxPl > 4) ? SOCBoard6p.makeNewBoard_landHexTypes_v2 : SOCBoard4p.makeNewBoard_landHexTypes_v1, (maxPl > 4) ? LANDHEX_DICEPATH_MAINLAND_6PL : LANDHEX_DICEPATH_MAINLAND_4PL, (maxPl > 4) ? SOCBoard6p.makeNewBoard_diceNums_v2 : SOCBoard4p.makeNewBoard_diceNums_v1, false, true, 1, false, maxPl, opt_breakClumps, scen);
        // - Outlying islands:
        makeNewBoard_placeHexes((maxPl > 4) ? LANDHEX_TYPE_ISLANDS_6PL : LANDHEX_TYPE_ISLANDS_4PL, (maxPl > 4) ? LANDHEX_COORD_ISLANDS_ALL_6PL : LANDHEX_COORD_ISLANDS_ALL_4PL, (maxPl > 4) ? LANDHEX_DICENUM_ISLANDS_6PL : LANDHEX_DICENUM_ISLANDS_4PL, true, true, (maxPl > 4) ? LANDHEX_LANDAREA_RANGES_ISLANDS_6PL : LANDHEX_LANDAREA_RANGES_ISLANDS_4PL, false, maxPl, null, scen);
        PORTS_TYPES_MAINLAND = (maxPl > 4) ? SOCBoard6p.PORTS_TYPE_V2 : SOCBoard4p.PORTS_TYPE_V1;
        PORTS_TYPES_ISLANDS = (maxPl > 4) ? PORT_TYPE_ISLANDS_6PL : PORT_TYPE_ISLANDS_4PL;
        PORT_LOC_FACING_MAINLAND = (maxPl > 4) ? PORT_EDGE_FACING_MAINLAND_6PL : PORT_EDGE_FACING_MAINLAND_4PL;
        PORT_LOC_FACING_ISLANDS = (maxPl > 4) ? PORT_EDGE_FACING_ISLANDS_6PL : PORT_EDGE_FACING_ISLANDS_4PL;
    }
    // Set up legalRoadEdges:
    initLegalRoadsFromLandNodes();
    initLegalShipEdges();
    // consistency-check land areas
    if (landAreasLegalNodes != null) {
        for (int i = 1; i < landAreasLegalNodes.length; ++i) if (landAreasLegalNodes[i] == null)
            throw new IllegalStateException("inconsistent landAreasLegalNodes: null idx " + i);
    }
    // Hide some land hexes behind fog, if the scenario does that
    if (hasScenarioFog) {
        final int[] FOGHEXES = (maxPl == 6) ? FOG_ISL_LANDHEX_COORD_FOG_6PL : ((maxPl < 4) ? FOG_ISL_LANDHEX_COORD_FOG_3PL : FOG_ISL_LANDHEX_COORD_FOG_4PL);
        makeNewBoard_hideHexesInFog(FOGHEXES);
    } else if (null != System.getProperty(PROP_JSETTLERS_DEBUG_BOARD_FOG)) {
        // Select n random hexes (20% of landHexLayout):
        // Knuth, "The Art of Computer Programming" Vol 2 Seminumerical Algorithms, Algorithm 3.4.2 S
        int d = landHexLayout.size();
        int n = (int) (d * .20f);
        if (n == 0)
            // round up
            n = 1;
        final int[] hideCoord = new int[n];
        for (int hexcoord : landHexLayout) {
            if (rand.nextFloat() <= (n / (float) d)) {
                hideCoord[hideCoord.length - n] = hexcoord;
                n -= 1;
                if (n == 0)
                    break;
            }
            d -= 1;
        }
        makeNewBoard_hideHexesInFog(hideCoord);
    }
    if ((PORTS_TYPES_MAINLAND == null) && (PORTS_TYPES_ISLANDS == null)) {
        // <--- Early return: No ports to place ---
        return;
    }
    // check port locations & facings, make sure no overlap with land hexes
    if (PORTS_TYPES_MAINLAND != null)
        makeNewBoard_checkPortLocationsConsistent(PORT_LOC_FACING_MAINLAND);
    if (PORT_LOC_FACING_ISLANDS != null)
        makeNewBoard_checkPortLocationsConsistent(PORT_LOC_FACING_ISLANDS);
    // copy and shuffle the ports, and check vs game option BC
    int[] portTypes_main;
    int[] portTypes_islands;
    if (PORTS_TYPES_MAINLAND != null) {
        final int ptL = PORTS_TYPES_MAINLAND.length, plfL = PORT_LOC_FACING_MAINLAND.length;
        if ((2 * ptL) != plfL)
            throw new IllegalArgumentException("Mismatched port-array lengths: PORT_LOC_FACING_MAINLAND (" + plfL + ") should be 2 x PORTS_TYPES_MAINLAND (" + ptL + ")");
        portTypes_main = new int[ptL];
        System.arraycopy(PORTS_TYPES_MAINLAND, 0, portTypes_main, 0, ptL);
        if ((maxPl == 6) || !hasScenarioFog)
            makeNewBoard_shufflePorts(portTypes_main, opt_breakClumps);
    } else {
        portTypes_main = null;
    }
    if (PORTS_TYPES_ISLANDS != null) {
        final int ptL = PORTS_TYPES_ISLANDS.length, plfL = PORT_LOC_FACING_ISLANDS.length;
        if ((2 * ptL) != plfL)
            throw new IllegalArgumentException("Mismatched port-array lengths: PORT_LOC_FACING_ISLANDS (" + plfL + ") should be 2 x PORTS_TYPES_ISLANDS (" + ptL + ")");
        portTypes_islands = new int[ptL];
        System.arraycopy(PORTS_TYPES_ISLANDS, 0, portTypes_islands, 0, ptL);
        makeNewBoard_shufflePorts(portTypes_islands, null);
    } else {
        portTypes_islands = null;
    }
    // copy port types to beginning of portsLayout[]
    final int pcountMain = (PORTS_TYPES_MAINLAND != null) ? portTypes_main.length : 0;
    portsCount = pcountMain;
    if (PORTS_TYPES_ISLANDS != null)
        portsCount += PORTS_TYPES_ISLANDS.length;
    if ((portsLayout == null) || (portsLayout.length != (3 * portsCount)))
        portsLayout = new int[3 * portsCount];
    if (PORTS_TYPES_MAINLAND != null)
        System.arraycopy(portTypes_main, 0, portsLayout, 0, pcountMain);
    if (PORTS_TYPES_ISLANDS != null)
        System.arraycopy(portTypes_islands, 0, portsLayout, pcountMain, portTypes_islands.length);
    // place the ports (hex numbers and facing) within portsLayout[] and nodeIDtoPortType.
    // fill out the ports[] vectors with node coordinates where a trade port can be placed.
    nodeIDtoPortType = new HashMap<Integer, Integer>();
    // - main island(s):
    // i == port type array index
    // j == port edge & facing array index
    final int L = (portTypes_main != null) ? portTypes_main.length : 0;
    if (L > 0) {
        for (int i = 0, j = 0; i < L; ++i) {
            // also == portsLayout[i]
            final int ptype = portTypes_main[i];
            final int edge = PORT_LOC_FACING_MAINLAND[j];
            ++j;
            final int facing = PORT_LOC_FACING_MAINLAND[j];
            ++j;
            final int[] nodes = getAdjacentNodesToEdge_arr(edge);
            placePort(ptype, -1, facing, nodes[0], nodes[1]);
            // portsLayout[i] is set already, from portTypes_main[i]
            portsLayout[i + portsCount] = edge;
            portsLayout[i + (2 * portsCount)] = facing;
        }
    }
    // j == port edge & facing array index
    if (PORTS_TYPES_ISLANDS != null) {
        for (int i = 0, j = 0; i < PORTS_TYPES_ISLANDS.length; ++i) {
            // also == portsLayout[i+L]
            final int ptype = portTypes_islands[i];
            final int edge = PORT_LOC_FACING_ISLANDS[j];
            ++j;
            final int facing = PORT_LOC_FACING_ISLANDS[j];
            ++j;
            final int[] nodes = getAdjacentNodesToEdge_arr(edge);
            placePort(ptype, -1, facing, nodes[0], nodes[1]);
            // portsLayout[L+i] is set already, from portTypes_islands[i]
            portsLayout[L + i + portsCount] = edge;
            portsLayout[L + i + (2 * portsCount)] = facing;
        }
    }
}
Also used : SOCGameOption(soc.game.SOCGameOption) HashSet(java.util.HashSet)

Example 2 with SOCGameOption

use of soc.game.SOCGameOption in project JSettlers2 by jdmonin.

the class NewGameOptionsFrame method clickScenarioInfo.

/**
 * The "Scenario Info" button was clicked.
 * Reads the current scenario, if any, from {@link #scenDropdown}.
 * Calls {@link #showScenarioInfoDialog(SOCScenario, Map, int, SOCPlayerClient.GameAwtDisplay, Frame)}.
 * @since 2.0.00
 */
private void clickScenarioInfo() {
    if (scenDropdown == null)
        // should not happen, scenDropdown is created before scenInfo
        return;
    final Object scObj = scenDropdown.getSelectedItem();
    if ((scObj == null) || !(scObj instanceof SOCScenario))
        // "(none)" item is a String, not a scenario
        return;
    final SOCScenario scen = (SOCScenario) scObj;
    // find game's vp_winner
    int vpWinner = SOCGame.VP_WINNER_STANDARD;
    boolean vpKnown = false;
    if (opts != null) {
        SOCGameOption vp = opts.get("VP");
        if (vp.getBoolValue()) {
            vpWinner = vp.getIntValue();
            vpKnown = true;
        }
    }
    if (forNewGame && (!vpKnown) && scen.scOpts.contains("VP=")) {
        final Map<String, SOCGameOption> scenOpts = SOCGameOption.parseOptionsToMap(scen.scOpts);
        final SOCGameOption scOptVP = (scenOpts != null) ? scenOpts.get("VP") : null;
        if (scOptVP != null)
            vpWinner = scOptVP.getIntValue();
    }
    showScenarioInfoDialog(scen, null, vpWinner, gameDisplay, this);
}
Also used : SOCGameOption(soc.game.SOCGameOption) SOCScenario(soc.game.SOCScenario)

Example 3 with SOCGameOption

use of soc.game.SOCGameOption in project JSettlers2 by jdmonin.

the class NewGameOptionsFrame method itemStateChanged.

/**
 * Called when a Choice or Checkbox value changes (ItemListener).
 * Used for these things:
 *<UL>
 * <LI>
 * Set {@link SOCGameOption#userChanged}
 * <LI>
 * Check Choices or Checkboxes to see if their game option has a {@link SOCGameOption.ChangeListener ChangeListener}.
 * <LI>
 * Set the checkbox when the popup-menu Choice value is changed for a
 * {@link SOCGameOption#OTYPE_INTBOOL} or {@link SOCGameOption#OTYPE_ENUMBOOL}.
 * <LI>
 * Update game option {@code "SC"} and the {@link #scenInfo} button when a scenario is picked
 * from {@link #scenDropdown}. Other scenario-related updates are handled by this method calling
 * {@link SOCGameOption.ChangeListener#valueChanged(SOCGameOption, Object, Object, Map)}.
 *</UL>
 * @param e itemevent from a Choice or Checkbox in {@link #controlsOpts}
 */
public void itemStateChanged(ItemEvent e) {
    final Object ctrl = e.getSource();
    SOCGameOption opt = controlsOpts.get(ctrl);
    if (opt == null)
        return;
    boolean wasCBEvent = false, choiceSetCB = false;
    Checkbox cb = boolOptCheckboxes.get(opt.key);
    if ((cb != null) && (cb != ctrl)) {
        // If the user picked a choice, also set the checkbox
        // any item sets it
        boolean wantsSet = true;
        if (wantsSet != cb.getState()) {
            cb.setState(wantsSet);
            choiceSetCB = true;
        }
    } else if (ctrl instanceof Checkbox) {
        wasCBEvent = true;
        choiceSetCB = (e.getStateChange() == ItemEvent.SELECTED);
    }
    fireUserChangedOptListeners(opt, ctrl, choiceSetCB, wasCBEvent);
}
Also used : Checkbox(java.awt.Checkbox) SOCGameOption(soc.game.SOCGameOption)

Example 4 with SOCGameOption

use of soc.game.SOCGameOption in project JSettlers2 by jdmonin.

the class NewGameOptionsFrame method initInterface_Options.

/**
 * Interface setup: {@link SOCGameOption}s, user's client preferences, per-game local preferences.
 * One row per option, except for 3-letter options which group with 2-letter ones.
 * Boolean checkboxes go on the left edge; text and int/enum values are to right of checkboxes.
 *<P>
 * When showing options to create a new game, option keys starting with '_' are hidden
 * unless the player nickname is "debug".  This prevents unwanted changes to those options,
 * which are set at the server during game creation.  When the options are shown read-only
 * during a game, these options are shown and not hidden.
 *<P>
 * Options which have {@link SOCGameOption#FLAG_INTERNAL_GAME_PROPERTY} are always hidden.
 * If not {@link #readOnly}, they're removed from opts.  Unknown opts are always removed.
 *<P>
 * This is called from constructor, so this is a new NGOF being shown.
 * If not read-only, clear {@link SOCGameOption#userChanged} flag for
 * each option in {@link #opts}.
 *<P>
 * If options are null, put a label with "This server version does not support game options" (localized).
 *<P>
 * Sets up local preferences for the client by calling
 * {@link #initInterface_UserPrefs(JPanel, GridBagLayout, GridBagConstraints)}.
 */
private void initInterface_Options(JPanel bp, GridBagLayout gbl, GridBagConstraints gbc) {
    final boolean hideUnderscoreOpts = (!readOnly) && (!gameDisplay.nick.getText().equalsIgnoreCase("debug"));
    Label L;
    if (opts == null) {
        // "This server version does not support game options."
        L = new Label(strings.get("game.options.not"));
        L.setForeground(LABEL_TXT_COLOR);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbl.setConstraints(L, gbc);
        bp.add(L);
        initInterface_UserPrefs(bp, gbl, gbc);
        // <---- Early return: no options ----
        return;
    } else if (!readOnly) {
        for (SOCGameOption opt : opts.values()) // clear flag from any previously shown NGOF
        opt.userChanged = false;
    }
    if (opts.containsKey("SC"))
        allSc = SOCScenario.getAllKnownScenarios();
    gbc.anchor = GridBagConstraints.WEST;
    // Look for options that should be on the same
    // line as other options (based on key length)
    // instead of at the start of a line.
    // TODO: for now these are on subsequent lines
    // instead of sharing the same line.
    // key=on-same-line opt, value=opt to start line
    HashMap<String, String> sameLineOpts = new HashMap<String, String>();
    for (final String kf3 : opts.keySet()) {
        if (kf3.length() <= 2)
            continue;
        final String kf2 = kf3.substring(0, 2);
        if (opts.containsKey(kf2))
            sameLineOpts.put(kf3, kf2);
    }
    // Sort and lay out options; remove unknowns and internal-onlys from opts.
    // TreeSet sorts game options by description, using gameopt.compareTo.
    // The array lets us remove from opts without disrupting an iterator.
    SOCGameOption[] optArr = new TreeSet<SOCGameOption>(opts.values()).toArray(new SOCGameOption[0]);
    for (int i = 0; i < optArr.length; ++i) {
        SOCGameOption op = optArr[i];
        if (op.optType == SOCGameOption.OTYPE_UNKNOWN) {
            opts.remove(op.key);
            // <-- Removed, Go to next entry --
            continue;
        }
        if (op.hasFlag(SOCGameOption.FLAG_INTERNAL_GAME_PROPERTY)) {
            if (!readOnly)
                // ignore internal-property options when requesting new game from client
                opts.remove(op.key);
            // <-- Don't show internal-property options
            continue;
        }
        if (op.key.charAt(0) == '_') {
            if (hideUnderscoreOpts)
                // <-- Don't show options starting with '_'
                continue;
            if ((allSc != null) && allSc.containsKey(op.key.substring(1)))
                // <-- Don't show options which are scenario names (use SC dropdown to pick at most one)
                continue;
        }
        if (sameLineOpts.containsKey(op.key))
            // <-- Shares a line, Go to next entry --
            continue;
        final boolean sharesLine = sameLineOpts.containsValue(op.key);
        initInterface_OptLine(op, bp, gbl, gbc);
        if (sharesLine) {
            // TODO group on same line, not following lines, if there's only 1.
            for (final String kf3 : sameLineOpts.keySet()) {
                final String kf2 = sameLineOpts.get(kf3);
                if ((kf2 == null) || !kf2.equals(op.key))
                    // <-- Goes with a a different option --
                    continue;
                final SOCGameOption op3 = opts.get(kf3);
                if (op3 != null)
                    initInterface_OptLine(op3, bp, gbl, gbc);
            }
        }
    }
    // for(opts)
    initInterface_UserPrefs(bp, gbl, gbc);
}
Also used : HashMap(java.util.HashMap) SOCGameOption(soc.game.SOCGameOption) Label(java.awt.Label)

Example 5 with SOCGameOption

use of soc.game.SOCGameOption in project JSettlers2 by jdmonin.

the class NewGameOptionsFrame method mouseClicked.

/**
 * when an option with a boolValue's label is clicked, toggle its checkbox
 */
public void mouseClicked(MouseEvent e) {
    SOCGameOption opt = controlsOpts.get(e.getSource());
    if (opt == null)
        return;
    Checkbox cb = boolOptCheckboxes.get(opt.key);
    if (cb == null)
        return;
    final boolean becameChecked = !cb.getState();
    cb.setState(becameChecked);
    opt.setBoolValue(becameChecked);
    if (!opt.userChanged)
        opt.userChanged = true;
    SOCGameOption.ChangeListener cl = opt.getChangeListener();
    if (cl == null)
        return;
    final Boolean newValue = (becameChecked) ? Boolean.TRUE : Boolean.FALSE;
    final Boolean oldValue = (becameChecked) ? Boolean.FALSE : Boolean.TRUE;
    fireOptionChangeListener(cl, opt, oldValue, newValue);
}
Also used : Checkbox(java.awt.Checkbox) SOCGameOption(soc.game.SOCGameOption)

Aggregations

SOCGameOption (soc.game.SOCGameOption)20 Checkbox (java.awt.Checkbox)5 TextField (java.awt.TextField)3 MissingResourceException (java.util.MissingResourceException)3 TreeSet (java.util.TreeSet)3 SOCScenario (soc.game.SOCScenario)3 Choice (java.awt.Choice)2 Component (java.awt.Component)2 Label (java.awt.Label)2 ArrayList (java.util.ArrayList)2 Test (org.junit.Test)2 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 SQLException (java.sql.SQLException)1 Timestamp (java.sql.Timestamp)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 PropertyResourceBundle (java.util.PropertyResourceBundle)1 StringTokenizer (java.util.StringTokenizer)1 SOCGame (soc.game.SOCGame)1