diff --git a/client/public/assets/gfx/tiles-jungle.png b/client/public/assets/gfx/tiles-jungle.png new file mode 100755 index 0000000..3752abc Binary files /dev/null and b/client/public/assets/gfx/tiles-jungle.png differ diff --git a/client/src/Board.js b/client/src/Board.js index 1edbd99..ece2c23 100644 --- a/client/src/Board.js +++ b/client/src/Board.js @@ -47,11 +47,13 @@ const Board = () => { const [ turn, setTurn ] = useState({}); const [ state, setState ] = useState(""); const [ color, setColor ] = useState(""); + const [ rules, setRules ] = useState({}); const [ longestRoadLength, setLongestRoadLength ] = useState(0); const fields = useMemo(() => [ 'signature', 'robber', 'robberName', 'pips', 'pipOrder', 'borders', 'borderOrder', 'tiles', 'tileOrder', - 'placements', 'turn', 'state', 'color', 'longestRoadLength' + 'placements', 'turn', 'state', 'color', 'longestRoadLength', + 'rules' ], []); console.log(`board - ws`, ws); @@ -68,7 +70,8 @@ const Board = () => { setRobber(data.update.robber); } - if ('robberName' in data.update && data.update.robberName !== robberName) { + if ('robberName' in data.update + && data.update.robberName !== robberName) { setRobberName(data.update.robberName); } @@ -76,6 +79,11 @@ const Board = () => { setState(data.update.state); } + if ('rules' in data.update + && !equal(data.update.rules, rules)) { + setRules(data.update.rules); + } + if ('color' in data.update && data.update.color !== color) { setColor(data.update.color); } @@ -485,8 +493,15 @@ const Board = () => { const tile = Object.assign({}, tiles[order], { index: index++, left: x, top: y}); + if ('tiles-start-facing-down' in rules + && rules[`tiles-start-facing-down`].enabled + && state !== 'normal' + && state !== 'winner') { + tile.type = 'jungle'; + tile.card = 0; + } let div = ; if (++rowCount === rows[row]) { @@ -550,7 +565,7 @@ const Board = () => { }, [ signature, generated, pips, pipOrder, borders, borderOrder, tiles, tileOrder, - ws + ws, state, rules ]); /* Re-render turn info after every render */ diff --git a/client/src/HouseRules.js b/client/src/HouseRules.js index 8f914e3..da005c5 100644 --- a/client/src/HouseRules.js +++ b/client/src/HouseRules.js @@ -9,32 +9,32 @@ import "./HouseRules.css"; import { GlobalContext } from "./GlobalContext.js"; -const VictoryPoints = ({ ws, houseRules, field }) => { +const VictoryPoints = ({ ws, rules, field }) => { const minVP = 10; - const [points, setPoints] = useState(houseRules[field].points || minVP); - console.log(`house-rules - ${field} - `, houseRules[field]); + const [points, setPoints] = useState(rules[field].points || minVP); + console.log(`house-rules - ${field} - `, rules[field]); - if (!(field in houseRules)) { - houseRules[field] = { + if (!(field in rules)) { + rules[field] = { points: minVP } }; - if (houseRules[field].points && houseRules[field].points !== points) { - setPoints(houseRules[field].points); + if (rules[field].points && rules[field].points !== points) { + setPoints(rules[field].points); } const update = (value) => { - let points = (houseRules[field].points || minVP) + value; + let points = (rules[field].points || minVP) + value; if (points < minVP) { return; } - if (points !== houseRules[field].points) { + if (points !== rules[field].points) { setPoints(points); - houseRules[field].points = points; + rules[field].points = points; ws.send(JSON.stringify({ type: 'rules', - houseRules + rules: rules })); } }; @@ -52,9 +52,8 @@ const NotImplemented = () => { const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { const { ws } = useContext(GlobalContext); - const [houseRules, setHouseRules] = useState(undefined); + const [rules, setRules] = useState(undefined); const [state, setState] = useState(undefined); - const [rules, setRules] = useState([]); const [ruleElements, setRuleElements] = useState([]); const fields = useMemo(() => [ 'state', 'rules' @@ -67,10 +66,11 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { if ('state' in data.update && data.update.state !== state) { setState(data.update.state); } - if ('rules' in data.update && !equal(data.update.rules, houseRules)) { + if ('rules' in data.update + && !equal(data.update.rules, rules)) { console.log(`house-rules - setting house rules to `, data.update.rules); - setHouseRules(data.update.rules); + setRules(data.update.rules); } break; default: @@ -104,45 +104,43 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { }*/ }, [setHouseRulesActive]);//ws, HouseRulesDismissed, setHouseRulesDismissed]); - console.log(`house-rules - render - `, { houseRules }); + console.log(`house-rules - render - `, { rules }); const setRule = useCallback((event, key) => { - const rules = houseRules ? Object.assign({}, houseRules) : {}; if (!(key in rules)) { rules[key] = { enabled: false }; } rules[key].enabled = !rules[key].enabled; console.log(`house-rules - set ${key} - ${rules[key].enabled}`); - setHouseRules(rules); + setRules(Object.assign({}, rules)); ws.send(JSON.stringify({ type: 'rules', - houseRules: rules + rules })); - }, [ws, houseRules]); + }, [ws, rules]); useEffect(() => { - const _rules = [ { + setRuleElements([ { title: `More victory points`, key: `victory-points`, - description: `Customize how many Victory Points are required to win. ` + - `The minimum number of Victory Points is 10.`, - element: , implemented: true }, { title: `Tiles start facing down`, key: `tiles-start-facing-down`, - description: `Flip resource tiles upside - down while placing starting settlements.`, - element: , + description: `Resource tiles start upside-down while placing starting settlements.`, + element:
Once all players have placed their initial settlements + and roads, the tiles are flipped and you discover what the + resources are.
, + implemented: true }, { title: `Bribery`, key: `bribery`, description: `Dissuade enemies from robbing you by offering resources voluntarily.`, element: , }, { @@ -150,7 +148,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `king-of-the-hill`, description: `Keep your lead for one full turn after you reach max victory points.`, element: , }, { @@ -158,7 +156,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `everyone-gets-one-reroll`, description: `Each player gets one chance re - roll at any point.`, element: , }, { @@ -166,7 +164,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `the-bridge`, description: `Build a super-bridge across one resource tile.`, element: , }, { @@ -174,7 +172,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `discard-desert`, description: `Scrap the desert in favour of an additional resource tile.`, element: , }, { @@ -182,7 +180,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `roll-double-roll-again`, description: `Roll again if you roll two of the same number.`, element: , }, { @@ -196,7 +194,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `crime-and-punishment`, description: `Change how the robber works to make Catan more or less competitive.`, element: , }, { @@ -204,7 +202,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { key: `credit`, description: `Trade with resources you don't have.`, element: , } ] @@ -220,24 +218,20 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { return +1; } return A.title.localeCompare(); - }); - - setRules(_rules); - - setRuleElements(_rules + }) .map(item => { const disabled = (state !== 'lobby' || !item.implemented), - defaultChecked = houseRules - && (item.key in houseRules) - ? houseRules[item.key].enabled + defaultChecked = rules + && (item.key in rules) + ? rules[item.key].enabled : false; console.log(`house-rules - ${item.key} - `, - { houseRules, defaultChecked, disabled }); + { rules, defaultChecked, disabled }); return
@@ -254,7 +248,7 @@ const HouseRules = ({ houseRulesActive, setHouseRulesActive }) => { { defaultChecked && item.element }
})); - }, [houseRules, setRules, setRule ]); + }, [rules, setRules, setRuleElements, state, ws ]); if (!houseRulesActive) { return <>; diff --git a/server/routes/games.js b/server/routes/games.js index f75de8a..7b0dc87 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -292,8 +292,8 @@ const distributeResources = (game, roll) => { if (!tile.robber) { receives[active.color][resource.type] += count; } else { - if (`robin-hood-robber` in game.houseRules - && game.houseRules[`robin-hood-robber`].enabled + if (`robin-hood-robber` in game.rules + && game.rules[`robin-hood-robber`].enabled && game.players[active.color].points <= 2) { addChatMessage(game, null, `Robber does not steal ${count} ${resource.type} from ${game.players[active.color].name} ` + @@ -2568,43 +2568,51 @@ const placeRoad = (game, session, index) => { const getVictoryPointRule = (game) => { const minVP = 10; - if (!('victory-points' in game.houseRules) - || !game.houseRules['victory-points'].enabled) { + if (!('victory-points' in game.rules) + || !game.rules['victory-points'].enabled) { return minVP; } - return game.houseRules['victory-pionts'].points; + return game.rules['victory-pionts'].points; } -const setHouseRules = (game, session, houseRules) => { +const setRules = (game, session, rules) => { if (game.state !== 'lobby') { return `You can not modify House Rules once the game has started.`; } - for (let rule in houseRules) { - if (equal(game.houseRules[rule], houseRules[rule])) { + for (let rule in rules) { + if (equal(game.rules[rule], rules[rule])) { continue; } switch (rule) { case 'victory-points': - if (!('points' in houseRules[rule])) { + if (!('points' in rules[rule])) { return `No points specified for victory-points`; } - if (!houseRules[rule].enabled) { + if (!rules[rule].enabled) { addChatMessage(game, null, `${getName(session)} has disabled the Victory Point ` + `house rule.`); } else { addChatMessage(game, null, `${getName(session)} set the minimum Victory Points to ` + - `${houseRules[rule].points}`); + `${rules[rule].points}`); } - game.houseRules[rule] = houseRules[rule]; + game.rules[rule] = rules[rule]; + break; + case 'tiles-start-facing-down': + addChatMessage(game, null, + `${getName(session)} has ${rules[rule].enabled ? 'en' : 'dis'}abled the Tiles Start Facing Down house rule.`); + if (rules[rule].enabled) { + shuffle(game, session); + } + game.rules[rule] = rules[rule]; break; case 'robin-hood-robber': addChatMessage(game, null, - `${getName(session)} has ${houseRules[rule].enabled ? 'en' : 'dis'}abled the Robin Hood Robber house rule.`); - game.houseRules[rule] = houseRules[rule]; + `${getName(session)} has ${rules[rule].enabled ? 'en' : 'dis'}abled the Robin Hood Robber house rule.`); + game.rules[rule] = rules[rule]; break; default: return `Rule ${rule} not recognized.`; @@ -2612,7 +2620,7 @@ const setHouseRules = (game, session, houseRules) => { } sendUpdateToPlayers(game, { - rules: game.houseRules, + rules: game.rules, chat: game.chat }); }; @@ -3725,7 +3733,7 @@ router.ws("/ws/:id", async (ws, req) => { update[field] = game[field]; break; case 'rules': - update[field] = game.houseRules ? game.houseRules : {}; + update[field] = game.rules ? game.rules : {}; break; case 'name': update.name = session.name; @@ -3949,8 +3957,8 @@ router.ws("/ws/:id", async (ws, req) => { break; case 'rules': console.log(`${short} - <- rules:${getName(session)} - `, - data.houseRules); - warning = setHouseRules(game, session, data.houseRules); + data.rules); + warning = setRules(game, session, data.rules); if (warning) { sendWarning(session, warning); } @@ -4303,7 +4311,7 @@ const createGame = (id) => { sessions: {}, unselected: [], active: 0, - houseRules: { + rules: { 'victory-points': { points: 10 }