diff options
author | Tor Andersson <tor@ccxvii.net> | 2023-12-11 14:39:55 +0100 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2023-12-11 20:26:07 +0100 |
commit | f3aa1d4862a6f85a201ce51c24c2e4f1b1dbdbdc (patch) | |
tree | 4e3cb4ce519d9fe448df46d708e1e1a251098cdc | |
parent | 6da83fe13cc580770a4a556bac9d53447da404b5 (diff) | |
download | votes-for-women-f3aa1d4862a6f85a201ce51c24c2e4f1b1dbdbdc.tar.gz |
Add temporary "drawn" and "deck" panel displays.
Use this to show drawn cards while choosing cards for events that
draw X cards, play one, and put the rest on top / bottom.
Use stack of "draw" arrays in VM to handle nested events.
NOTE: This is not necessary now, but will be if we change the Winning Moves
event to play its event immediately.
-rw-r--r-- | play.css | 21 | ||||
-rw-r--r-- | play.html | 12 | ||||
-rw-r--r-- | play.js | 32 | ||||
-rw-r--r-- | rules.js | 197 |
4 files changed, 190 insertions, 72 deletions
@@ -181,9 +181,10 @@ body.Opposition header.your_turn { background-color: var(--opp-75); } body.Suffragist #hand_header { background-color: var(--suf-75); } body.Opposition #hand_header { background-color: var(--opp-75); } - -body.Suffragist #set_aside_header { background-color: var(--suf-85); } -body.Opposition #set_aside_header { background-color: var(--opp-85); } +body.Suffragist #drawn_header { background-color: var(--suf-85); } +body.Opposition #drawn_header { background-color: var(--opp-85); } +body.Suffragist #deck_header { background-color: var(--suf-85); } +body.Opposition #deck_header { background-color: var(--opp-85); } section { margin-top: 24px; @@ -194,7 +195,7 @@ section { .panel { padding: 3px; - font-family: TiffanyGothicCC; + font-family: TiffanyGothicCC, "Source Sans"; background-color: hsl(43, 52%, 88%); box-shadow: 1px 2px 4px #0004; width: fit-content; @@ -222,6 +223,8 @@ section { } #hand { grid-template-columns: repeat(4, 250px); grid-template-rows: repeat(2, 350px); } +#deck { grid-template-columns: repeat(4, 250px) } +#drawn { grid-template-columns: repeat(4, 250px) } #set_aside { grid-template-columns: repeat(4, 250px) } #support_claimed { grid-template-columns: repeat(3, 250px) } #opposition_claimed { grid-template-columns: repeat(3, 250px) } @@ -235,11 +238,13 @@ section { #opposition_claimed_panel { margin-left: 0; grid-column: span 1; } } -@media (min-width: 1590px) { #set_aside { grid-template-columns: repeat(5, 250px) } } -@media (min-width: 1840px) { #set_aside { grid-template-columns: repeat(6, 250px) } } +@media (min-width: 1590px) { #deck, #drawn, #set_aside { grid-template-columns: repeat(5, 250px) } } +@media (min-width: 1840px) { #deck, #drawn, #set_aside { grid-template-columns: repeat(6, 250px) } } @media (min-width: 2120px) { #hand { grid-template-columns: repeat(7, 250px); grid-template-rows: repeat(1, 350px); } + #deck { grid-template-columns: repeat(7, 250px); } + #drawn { grid-template-columns: repeat(7, 250px); } #set_aside { grid-template-columns: repeat(7, 250px); } #support_claimed { grid-template-columns: repeat(3, 250px) } #opposition_claimed { grid-template-columns: repeat(3, 250px) } @@ -571,6 +576,8 @@ div.button_box .button { .card_support_back{background-image:url(cards.1x/support_01.jpg)} .card_opposition_back{background-image:url(cards.1x/opposition_01.jpg)} +.card_strategy_back{background-image:url(cards.1x/strategy_01.jpg)} +.card_states_back{background-image:url(cards.1x/states_01.jpg)} .card_1{background-image:url(cards.1x/support_02.jpg)} .card_2{background-image:url(cards.1x/support_03.jpg)} .card_3{background-image:url(cards.1x/support_04.jpg)} @@ -703,6 +710,8 @@ div.button_box .button { @media (min-resolution: 97dpi) { .card_support_back{background-image:url(cards.2x/support_01.jpg)} .card_opposition_back{background-image:url(cards.2x/opposition_01.jpg)} +.card_strategy_back{background-image:url(cards.2x/strategy_01.jpg)} +.card_states_back{background-image:url(cards.2x/states_01.jpg)} .card_1{background-image:url(cards.2x/support_02.jpg)} .card_2{background-image:url(cards.2x/support_03.jpg)} .card_3{background-image:url(cards.2x/support_04.jpg)} @@ -609,6 +609,18 @@ c5 3 13 7 17 8 8 2 9 3 11 12 1 5 5 12 8 16 5 8 5 8 3 22 l-3 14 -30 -1 c-35 </div> </div> + <div id="drawn_panel" class="panel hide"> + <div id="drawn_header" class="panel_header">Drawn Cards</div> + <div id="drawn" class="panel_body"></div> + </div> + </div> + + <div id="deck_panel" class="panel hide"> + <div id="deck_header" class="panel_header">Top ◀ Draw Deck ▶ Bottom</div> + <div id="deck" class="panel_body"></div> + </div> + </div> + <div id="set_aside_panel" class="panel hide"> <div id="set_aside_header" class="panel_header">Set-aside Cards</div> <div id="set_aside" class="panel_body"></div> @@ -72,10 +72,15 @@ const US_STATES = [ const region_count = 6 const us_states_count = region_count * 8 -const card_count = 128 +const last_card = 128 const green_check_count = 36 const red_x_count = 13 +const SUF_CARD_BACK = last_card + 1 +const OPP_CARD_BACK = last_card + 2 +const STRATEGY_CARD_BACK = last_card + 3 +const STATE_CARD_BACK = last_card + 4 + let ui = { favicon: document.getElementById("favicon"), status: document.getElementById("status"), @@ -454,7 +459,7 @@ function build_user_interface() { }) } - for (let c = 1; c <= card_count; ++c) { + for (let c = 1; c <= last_card; ++c) { elt = ui.cards[c] = create("div", { className: `card card_${c} ${CARDS[c].type}`, my_card: c, @@ -463,6 +468,11 @@ function build_user_interface() { elt.addEventListener("click", on_click_card) } + ui.cards[SUF_CARD_BACK] = create("div", { className: "card card_support_back" }) + ui.cards[OPP_CARD_BACK] = create("div", { className: "card card_opposition_back" }) + ui.cards[STRATEGY_CARD_BACK] = create("div", { className: "card card_strategy_back" }) + ui.cards[STATE_CARD_BACK] = create("div", { className: "card card_states_back" }) + for (let r = 1; r <= region_count; ++r) { let region_name_css = REGION_NAMES[r].replaceAll(' & ', '') elt = ui.regions[r] = document.querySelector(`#map #${region_name_css}`) @@ -718,6 +728,8 @@ function on_update() { // eslint-disable-line no-unused-vars } document.getElementById("hand").replaceChildren() + document.getElementById("deck").replaceChildren() + document.getElementById("drawn").replaceChildren() document.getElementById("set_aside").replaceChildren() document.getElementById("support_claimed").replaceChildren() document.getElementById("opposition_claimed").replaceChildren() @@ -732,6 +744,22 @@ function on_update() { // eslint-disable-line no-unused-vars document.getElementById("hand_panel").classList.add("hide") } + if (view.drawn) { + document.getElementById("drawn_panel").classList.remove("hide") + for (let c of view.drawn) + document.getElementById("drawn").appendChild(ui.cards[c]) + } else { + document.getElementById("drawn_panel").classList.add("hide") + } + + if (view.deck) { + document.getElementById("deck_panel").classList.remove("hide") + for (let c of view.deck) + document.getElementById("deck").appendChild(ui.cards[c]) + } else { + document.getElementById("deck_panel").classList.add("hide") + } + if (view.set_aside.length) { document.getElementById("set_aside_panel").classList.remove("hide") for (let c of view.set_aside) @@ -17,6 +17,7 @@ const first_strategy_card = 105 const last_strategy_card = 116 const first_states_card = 117 const last_states_card = 128 +const last_card = last_states_card const MAX_SUPPORT_BUTTONS = 12 const MAX_OPPOSITION_BUTTONS = 6 @@ -24,6 +25,11 @@ const MAX_OPPOSITION_BUTTONS = 6 const GREEN_CHECK_VICTORY = 36 const RED_X_VICTORY = 13 +const SUF_CARD_BACK = last_card + 1 +const OPP_CARD_BACK = last_card + 2 +const STRATEGY_CARD_BACK = last_card + 3 +const STATE_CARD_BACK = last_card + 4 + const WEST = 1 const PLAINS = 2 const SOUTH = 3 @@ -782,6 +788,9 @@ exports.view = function(state, player) { view.red_xs = count_red_xs() } + if (player === game.active && game.vm && game.vm.draw) + view.drawn = game.vm.draw + if (player === SUF) { view.hand = game.support_hand view.set_aside = game.support_set_aside @@ -2373,14 +2382,33 @@ function vm_counter_strat() { game.state = "vm_counter_strat" } +function start_vm_draw() { + if (game.vm.draw) { + if (!game.vm.save_draw) + game.vm.save_draw = [] + game.vm.save_draw.push(game.vm.draw) + } + game.vm.draw = [] +} + +function end_vm_draw() { + if (game.vm.save_draw) { + game.vm.draw = game.vm.save_draw.pop() + if (game.vm.save_draw.length === 0) + delete game.vm.save_draw + } else { + delete game.vm.draw + } +} + function vm_draw_2_play_1_event() { vm_assert_argcount(0) clear_undo() - game.vm.draw = [] + + start_vm_draw() for (let i = 0; i < 2; ++i) { let card = draw_card(player_deck()) game.vm.draw.push(card) - player_hand().push(card) } log(`${game.active} drew 2 cards.`) @@ -3034,104 +3062,145 @@ states.vm_draw_2_play_1_event = { card(c) { push_undo() end_play_card(game.played_card) + let other = game.vm.draw.find(x => x !== c) - discard_card_from_hand(other) log(`Discarded C${other}.`) - delete game.vm.draw + + end_vm_draw() + + // move to hand to play + player_hand().push(c) play_card_event(c) }, skip() { log("None of the cards could be played for their event.") - for (let c of game.vm.draw) { - discard_card_from_hand(c) - } - delete game.vm.draw + for (let c of game.vm.draw) + log(`Discarded C${c}.`) + end_vm_draw() vm_next() } } function goto_vm_place_any_on_top_of_draw() { clear_undo() - game.vm.draw = [] - game.selected_cards = [] + start_vm_draw() + game.vm.on_top = [] + game.vm.on_bottom = [] let draw_count = Math.min(player_deck().length, 6) for (let i = 0; i < draw_count; ++i) { let card = draw_card(player_deck()) game.vm.draw.push(card) - player_hand().push(card) } log(`${game.active} drew ${draw_count} cards.`) - game.state = "vm_place_any_on_top_of_draw" + if (game.vm.play_one < 0) + game.state = "vm_place_any_on_top_of_draw_play" + else + game.state = "vm_place_any_on_top_of_draw" } -states.vm_place_any_on_top_of_draw = { - inactive: "choose which cards to put on top of their Draw Deck.", +states.vm_place_any_on_top_of_draw_play = { + inactive: "choose which card to play for its event.", prompt() { let can_play = false - if (game.vm.play_one && !game.selected_cards.length) { - event_prompt("Select which card to play as Event.") - for (let c of game.vm.draw) { - if (can_play_event(c)) { - gen_action_card(c) - can_play = true - } - } - } else { - event_prompt("Select which cards to put on top of your Draw Deck. The rest go to the bottom.") - if (game.vm.play_one) { - let event_card_name = CARDS[game.selected_cards[0]].name - view.prompt += ` Will play "${event_card_name}" for its event.` - } - for (let c of game.vm.draw) { - if (!game.selected_cards.includes(c)) - gen_action_card(c) + event_prompt("Select which card to play as Event.") + for (let c of game.vm.draw) { + if (can_play_event(c)) { + gen_action_card(c) + can_play = true } } - - - if (!game.vm.play_one || game.selected_cards.length) { - gen_action("done") - } else if (!can_play) { + if (!can_play) { gen_action("skip") } }, card(c) { push_undo() - game.selected_cards.push(c) + array_remove_item(game.vm.draw, c) + player_hand().push(c) + game.vm.play_one = c + game.state = "vm_place_any_on_top_of_draw" }, skip() { log("None of the drawn cards could be played for their Event.") - delete game.vm.play_one + game.vm.play_one = -1 + game.state = "vm_place_any_on_top_of_draw" + }, +} + +states.vm_place_any_on_top_of_draw = { + inactive: "choose which cards to place on top of their Draw Deck.", + prompt() { + event_prompt("Select which cards to place on TOP of your Draw Deck.") + if (game.vm.play_one >= 0) + view.prompt += ` Will play "${CARDS[game.vm.play_one].name}" for its event.` + + // show cards going on top + if (game.active === OPP) + view.deck = [ ...game.vm.on_top, OPP_CARD_BACK ] + else + view.deck = [ ...game.vm.on_top, SUF_CARD_BACK ] + + for (let c of game.vm.draw) + gen_action_card(c) + + gen_action("next") + }, + card(c) { + push_undo() + array_remove_item(game.vm.draw, c) + game.vm.on_top.unshift(c) + }, + next() { + if (game.vm.draw.length > 0) + game.state = "vm_place_any_on_bottom_of_draw" + else + end_vm_place_any_on_top_of_draw() + }, +} + +states.vm_place_any_on_bottom_of_draw = { + inactive: "choose which cards to place at the bottom of their Draw Deck.", + prompt() { + event_prompt("Place the remaining cards at the BOTTOM of your Draw Deck.") + if (game.vm.play_one >= 0) + view.prompt += ` Will play "${CARDS[game.vm.play_one].name}" for its event.` + + // show cards going at the bottom + if (game.active === OPP) + view.deck = [ ...game.vm.on_top, OPP_CARD_BACK, ...game.vm.on_bottom ] + else + view.deck = [ ...game.vm.on_top, SUF_CARD_BACK, ...game.vm.on_bottom ] + + for (let c of game.vm.draw) + gen_action_card(c) + + if (game.vm.draw.length === 0) + gen_action("done") + }, + card(c) { + push_undo() + array_remove_item(game.vm.draw, c) + game.vm.on_bottom.push(c) }, done() { - // first selected card is the to be played event card - if (game.vm.play_one) - game.vm.play_one = game.selected_cards.shift() - log(`${game.active} selected ${pluralize(game.selected_cards.length, 'card')} to put on top of their Draw Deck.`) - - // first selected card goes on top. - for (let c of game.selected_cards.reverse()) { - player_deck().push(c) - array_remove_item(game.vm.draw, c) - array_remove_item(player_hand(), c) - } - // rest goes to the bottom, except for the to be played event card - for (let c of game.vm.draw) { - if (c !== game.vm.play_one) { - player_deck().unshift(c) - array_remove_item(player_hand(), c) - } - } + end_vm_place_any_on_top_of_draw() + }, +} - delete game.vm.draw - game.selected_cards = [] - if (game.vm.play_one) { - end_play_card(game.played_card) - play_card_event(game.vm.play_one) - } else { - vm_next() - } +function end_vm_place_any_on_top_of_draw() { + log(`${game.active} placed ${pluralize(game.vm.on_top.length, 'card')} on top and ${pluralize(game.vm.on_bottom.length, 'card')} at the bottom of their Draw Deck.`) + while (game.vm.on_top.length > 0) + player_deck().push(game.vm.on_top.pop()) + for (let c of game.vm.on_bottom) + player_deck().unshift(c) + end_vm_draw() + + if (game.vm.play_one >= 0) { + end_play_card(game.played_card) + play_card_event(game.vm.play_one) + } else { + vm_next() } } |