diff options
author | Mischa Untaga <99098079+MischaU8@users.noreply.github.com> | 2023-11-13 16:49:25 +0100 |
---|---|---|
committer | Mischa Untaga <99098079+MischaU8@users.noreply.github.com> | 2023-11-13 16:49:25 +0100 |
commit | e8a1a9911cc9c063e9e4b87ac607dfebe7ffd30f (patch) | |
tree | 839cdccf9a7909376cddd014b31a58b77a1784b8 | |
parent | 6226c3f330eb7b29440d782966d433c5265ec45e (diff) | |
download | votes-for-women-e8a1a9911cc9c063e9e4b87ac607dfebe7ffd30f.tar.gz |
cubes WIP
-rw-r--r-- | play.js | 140 | ||||
-rw-r--r-- | rules.js | 114 |
2 files changed, 251 insertions, 3 deletions
@@ -24,6 +24,13 @@ const REGION_NAMES = [ "Northeast" ] +const PURPLE = 1 +const YELLOW = 2 +const PURPLE_OR_YELLOW = 3 +const RED = 4 +const GREEN_CHECK = 5 +const RED_X = 6 + const region_count = 6 const us_states_count = region_count * 8 const card_count = 128 @@ -40,6 +47,7 @@ let ui = { pieces: document.getElementById("pieces"), support_campaigner: [], opposition_campaigner: [], + cubes: [], cards: [ null ], us_states: [ null ], regions: [ null ], @@ -106,6 +114,57 @@ const LAYOUT = { const US_STATES_LAYOUT = [ null ] const REGIONS_LAYOUT = [ null ] +// bits + +// RED cubes (6 bits), YELLOW cubes (7 bits), PURPLE cubes (7 bits), RED_X (1 bit), GREEN_CHECK (1 bit), +const GREEN_CHECK_SHIFT = 0 +const GREEN_CHECK_MASK = 1 << GREEN_CHECK_SHIFT + +const RED_X_SHIFT = 1 +const RED_X_MASK = 1 << RED_X_SHIFT + +const PURPLE_SHIFT = 2 +const PURPLE_MASK = 127 << PURPLE_SHIFT + +const YELLOW_SHIFT = 9 +const YELLOW_MASK = 127 << YELLOW_SHIFT + +const RED_SHIFT = 16 +const RED_MASK = 63 << RED_SHIFT + +function is_green_check(u) { + return (view.us_states[u] & GREEN_CHECK_MASK) === GREEN_CHECK_MASK +} + +function is_red_x(u) { + return (view.us_states[u] & RED_X_MASK) === RED_X_MASK +} + +function purple_cubes(u) { + return (view.us_states[u] & PURPLE_MASK) >> PURPLE_SHIFT +} + +function yellow_cubes(u) { + return (view.us_states[u] & YELLOW_MASK) >> YELLOW_SHIFT +} + +function red_cubes(u) { + return (view.us_states[u] & RED_MASK) >> RED_SHIFT +} + +function support_cubes(u) { + return purple_cubes(u) + yellow_cubes(u) +} + +function color_cubes(cube, u) { + if (cube === PURPLE) + return purple_cubes(u) + else if (cube === YELLOW) + return yellow_cubes(u) + else + return red_cubes(u) +} + // CARD MENU var card_action_menu = Array.from(document.getElementById("popup").querySelectorAll("li[data-action]")).map(e => e.dataset.action) @@ -368,6 +427,16 @@ function build_user_interface() { create_campaigner('red1', 1), create_campaigner('red2', 2), ] + + for (let i = 0; i < 190; ++i) { + // XXX do we need to set the color here? + // let color = (i < 65) ? "purple" : (i < 130) ? "yellow" : "red" + elt = ui.cubes[i] = create("div", { + className: `piece cube`, + onmousedown: on_click_cube, + }) + document.getElementById("pieces").appendChild(elt) + } } function on_focus_card_tip(card_number) { // eslint-disable-line no-unused-vars @@ -433,6 +502,27 @@ function opposition_info() { return `${pluralize(view.opposition_buttons, 'button')}, ${pluralize(view.opposition_hand, 'card')} in hand` } +function layout_cubes(list, xorig, yorig) { + const dx = 12 + const dy = 8 + if (list.length > 0) { + let ncol = Math.round(Math.sqrt(list.length)) + let nrow = Math.ceil(list.length / ncol) + function place_cube(row, col, e, z) { + let x = xorig - (row * dx - col * dx) - 10 + (nrow-ncol) * 6 + let y = yorig - (row * dy + col * dy) - 13 + (nrow-1) * 8 + e.style.left = x + "px" + e.style.top = y + "px" + e.style.zIndex = z + } + let z = 50 + let i = 0 + for (let row = 0; row < nrow; ++row) + for (let col = 0; col < ncol && i < list.length; ++col) + place_cube(row, col, list[list.length-(++i)], z--) + } +} + function on_update() { // eslint-disable-line no-unused-vars console.log("VIEW", view) @@ -485,6 +575,7 @@ function on_update() { // eslint-disable-line no-unused-vars for (let c of view.out_of_play) document.getElementById("out_of_play").appendChild(ui.cards[c]) + // TODO Replace with stacked cards for (let id of ['persistent_turn', 'persistent_game', 'persistent_ballot']) { document.getElementById(id).replaceChildren() for (let c of view[id] || []) { @@ -523,7 +614,6 @@ function on_update() { // eslint-disable-line no-unused-vars } for (let i = 0; i < ui.opposition_campaigner.length; ++i) { // TODO Cleanup - ui.opposition_campaigner[i].classList.toggle("hide", !view.opposition_campaigner[i]) let campaigner_region = view.opposition_campaigner[i] if (campaigner_region) { ui.pieces.appendChild(ui.opposition_campaigner[i]) @@ -535,6 +625,54 @@ function on_update() { // eslint-disable-line no-unused-vars } } + let ci = 0 + for (let i = 1; i < ui.us_states.length; ++i) { + // TODO Cleanup + if (view.us_states[i]) { + let state_cubes = [] + let cube = null + console.log("US_STATE", i, purple_cubes(i), yellow_cubes(i), red_cubes(i), is_green_check(i), is_red_x(i)) + for (let c = 0; c < purple_cubes(i); ++c) { + cube = ui.cubes[ci++] + // TODO track both state and color + cube.my_us_state = i + cube.my_cube = PURPLE + cube.classList.add("purple") + cube.classList.remove("yellow", "red") + state_cubes.push(cube) + ui.pieces.appendChild(cube) + console.log("add purple", cube) + } + for (let c = 0; c < yellow_cubes(i); ++c) { + cube = ui.cubes[ci++] + cube.my_us_state = i + cube.my_cube = YELLOW + cube.classList.add("yellow") + cube.classList.remove("purple", "red") + state_cubes.push(cube) + ui.pieces.appendChild(cube) + console.log("add yellow", cube) + } + for (let c = 0; c < red_cubes(i); ++c) { + cube = ui.cubes[ci++] + cube.my_us_state = i + cube.my_cube = RED + cube.classList.add("red") + cube.classList.remove("purple", "yellow") + state_cubes.push(cube) + ui.pieces.appendChild(cube) + console.log("add red", cube) + } + let [x, y] = US_STATES_LAYOUT[i] + layout_cubes(state_cubes, x, y) + } + } + + // remove remaining unused cubes from DOM + for (let i = ci; i < ui.cubes.length; ++i) { + ui.cubes[i].remove() + } + action_button("commit_1_button", "+1 Button") action_button("defer", "Defer") @@ -202,8 +202,114 @@ function add_campaigner(campaigner_color, region) { log(`Placed ${COLOR_CODE[campaigner_color]}R in R${region}`) } +// RED cubes (6 bits), YELLOW cubes (7 bits), PURPLE cubes (7 bits), RED_X (1 bit), GREEN_CHECK (1 bit), +const GREEN_CHECK_SHIFT = 0 +const GREEN_CHECK_MASK = 1 << GREEN_CHECK_SHIFT + +const RED_X_SHIFT = 1 +const RED_X_MASK = 1 << RED_X_SHIFT + +const PURPLE_SHIFT = 2 +const PURPLE_MASK = 127 << PURPLE_SHIFT + +const YELLOW_SHIFT = 9 +const YELLOW_MASK = 127 << YELLOW_SHIFT + +const RED_SHIFT = 16 +const RED_MASK = 63 << RED_SHIFT + +function is_green_check(u) { + return (game.us_states[u] & GREEN_CHECK_MASK) === GREEN_CHECK_MASK +} + +function set_green_check(u) { + game.us_states[u] |= GREEN_CHECK_MASK +} + +function clear_green_check(u) { + game.us_states[u] &= ~GREEN_CHECK_MASK +} + +function is_red_x(u) { + return (game.us_states[u] & RED_X_MASK) === RED_X_MASK +} + +function set_red_x(u) { + game.us_states[u] |= RED_X_MASK +} + +function clear_red_x(u) { + game.us_states[u] &= ~RED_X_MASK +} + +function purple_cubes(u) { + return (game.us_states[u] & PURPLE_MASK) >> PURPLE_SHIFT +} + +function set_purple_cubes(u, x) { + game.us_states[u] = (game.us_states[u] & ~PURPLE_MASK) | (x << PURPLE_SHIFT) +} + +function yellow_cubes(u) { + return (game.us_states[u] & YELLOW_MASK) >> YELLOW_SHIFT +} + +function set_yellow_cubes(u, x) { + game.us_states[u] = (game.us_states[u] & ~YELLOW_MASK) | (x << YELLOW_SHIFT) +} + +function red_cubes(u) { + return (game.us_states[u] & RED_MASK) >> RED_SHIFT +} + +function set_red_cubes(u, x) { + game.us_states[u] = (game.us_states[u] & ~RED_MASK) | (x << RED_SHIFT) +} + +function support_cubes(u) { + return purple_cubes(u) + yellow_cubes(u) +} + +function color_cubes(cube, u) { + if (cube === PURPLE) + return purple_cubes(u) + else if (cube === YELLOW) + return yellow_cubes(u) + else + return red_cubes(u) +} + +function set_color_cubes(cube, u, x) { + if (cube === PURPLE) + set_purple_cubes(u, x) + else if (cube === YELLOW) + set_yellow_cubes(u, x) + else + set_red_cubes(u, x) +} + function add_cube(cube, us_state) { log(`Added ${COLOR_CODE[cube]}C in S${us_state}`) + + if ((cube === RED && support_cubes(us_state) > 0) || (cube !== RED && red_cubes(us_state) > 0)) + throw new Error("Can't add cube when opponent still has cubes there") + + if (is_green_check(us_state) || is_red_x(us_state)) + throw new Error("Can't add cube with green_check / red_x") + + set_color_cubes(cube, us_state, color_cubes(cube, us_state) + 1) +} + +function remove_cube(cube, us_state) { + log(`Removed ${COLOR_CODE[cube]}C from S${us_state}`) + + if ((cube === PURPLE && !purple_cubes(us_state)) || (cube === YELLOW && !yellow_cubes(us_state)) || (cube === RED && !red_cubes(us_state))) + throw new Error("Can't remove cube that aint there") + + if (is_green_check(us_state) || is_red_x(us_state)) + throw new Error("Can't remove cube in us_state with green_check / red_x") + + set_color_cubes(cube, us_state, color_cubes(cube, us_state) - 1) } // #endregion @@ -285,6 +391,7 @@ exports.setup = function (seed, _scenario, _options) { round: 0, congress: 0, us_states: new Array(us_states_count).fill(0), + nineteenth_amendment: 0, strategy_deck: [], strategy_draw: [], @@ -379,7 +486,8 @@ exports.view = function(state, player) { turn: game.turn, round: game.round, congress: game.congress, - states: game.states, + us_states: game.us_states, + nineteenth_amendment: game.nineteenth_amendment, strategy_deck: game.strategy_deck.length, strategy_draw: game.strategy_draw, @@ -460,7 +568,7 @@ function goto_planning_phase() { states.planning_phase = { inactive: "do Planning.", prompt() { - view.prompt = "Planning." + view.prompt = "Planning. Draw cards." gen_action("draw") }, draw() { @@ -1380,6 +1488,7 @@ states.vm_add_cubes = { gen_action("yellow") } + // TODO remove cube if opponent has any cubes here if (game.vm.cube_color) { for (let s of game.vm.us_states) gen_action_us_state(s) @@ -1393,6 +1502,7 @@ states.vm_add_cubes = { }, us_state(s) { push_undo() + // TODO remove cube if opponent has any cubes here add_cube(game.vm.cube_color, s) map_incr(game.vm.added, s, 1) |