diff options
-rw-r--r-- | play.js | 692 | ||||
-rw-r--r-- | rules.js | 2408 |
2 files changed, 1550 insertions, 1550 deletions
@@ -1,47 +1,47 @@ -"use strict"; +"use strict" -const CLEOPATRA = "Cleopatra"; -const DEAD = "Dead"; -const LEVY = "Levy"; -const ENEMY = { "Caesar": "Pompeius", "Pompeius": "Caesar" }; +const CLEOPATRA = "Cleopatra" +const DEAD = "Dead" +const LEVY = "Levy" +const ENEMY = { "Caesar": "Pompeius", "Pompeius": "Caesar" } -let label_style = window.localStorage['julius-caesar/label-style'] || 'columbia'; -let label_layout = window.localStorage['julius-caesar/label-layout'] || 'spread'; +let label_style = window.localStorage['julius-caesar/label-style'] || 'columbia' +let label_layout = window.localStorage['julius-caesar/label-layout'] || 'spread' function toggle_blocks() { - document.getElementById("blocks").classList.toggle("hide_blocks"); + document.getElementById("blocks").classList.toggle("hide_blocks") } function set_simple_labels() { - label_style = 'simple'; - document.getElementById("blocks").classList.remove("columbia-labels"); - document.getElementById("battle").classList.remove("columbia-labels"); - document.getElementById("blocks").classList.add("simple-labels"); - document.getElementById("battle").classList.add("simple-labels"); - window.localStorage['julius-caesar/label-style'] = label_style; - update_map(); + label_style = 'simple' + document.getElementById("blocks").classList.remove("columbia-labels") + document.getElementById("battle").classList.remove("columbia-labels") + document.getElementById("blocks").classList.add("simple-labels") + document.getElementById("battle").classList.add("simple-labels") + window.localStorage['julius-caesar/label-style'] = label_style + update_map() } function set_columbia_labels() { - label_style = 'columbia'; - document.getElementById("blocks").classList.remove("simple-labels"); - document.getElementById("battle").classList.remove("simple-labels"); - document.getElementById("blocks").classList.add("columbia-labels"); - document.getElementById("battle").classList.add("columbia-labels"); - window.localStorage['julius-caesar/label-style'] = label_style; - update_map(); + label_style = 'columbia' + document.getElementById("blocks").classList.remove("simple-labels") + document.getElementById("battle").classList.remove("simple-labels") + document.getElementById("blocks").classList.add("columbia-labels") + document.getElementById("battle").classList.add("columbia-labels") + window.localStorage['julius-caesar/label-style'] = label_style + update_map() } function set_spread_layout() { - label_layout = 'spread'; - window.localStorage['julius-caesar/label-layout'] = label_layout; - update_map(); + label_layout = 'spread' + window.localStorage['julius-caesar/label-layout'] = label_layout + update_map() } function set_stack_layout() { - label_layout = 'stack'; - window.localStorage['julius-caesar/label-layout'] = label_layout; - update_map(); + label_layout = 'stack' + window.localStorage['julius-caesar/label-layout'] = label_layout + update_map() } // Levy and hit animations for 'simple' blocks. @@ -49,12 +49,12 @@ const step_down_animation = [ { transform: 'translateY(0px)' }, { transform: 'translateY(10px)' }, { transform: 'translateY(0px)' }, -]; +] const step_up_animation = [ { transform: 'translateY(0px)' }, { transform: 'translateY(-10px)' }, { transform: 'translateY(0px)' }, -]; +] let ui = { cards: {}, @@ -66,654 +66,654 @@ let ui = { old_steps: null, old_location: null, present: new Set(), -}; +} function on_log(text) { - let p = document.createElement("div"); - text = text.replace(/&/g, "&"); - text = text.replace(/</g, "<"); - text = text.replace(/>/g, ">"); + let p = document.createElement("div") + text = text.replace(/&/g, "&") + text = text.replace(/</g, "<") + text = text.replace(/>/g, ">") - text = text.replace(/\u2192 /g, "\u2192\xa0"); - text = text.replace(/Mare /g, "Mare\xa0"); + text = text.replace(/\u2192 /g, "\u2192\xa0") + text = text.replace(/Mare /g, "Mare\xa0") - text = text.replace(/^([A-Z]):/, '<span class="$1"> $1 </span>'); + text = text.replace(/^([A-Z]):/, '<span class="$1"> $1 </span>') if (text.match(/^~ .* ~$/)) - p.className = 'br', text = text.substring(2, text.length-2); + p.className = 'br', text = text.substring(2, text.length-2) else if (text.match(/^Start Caesar/)) - p.className = 'C'; + p.className = 'C' else if (text.match(/^Start Pompeius/)) - p.className = 'P'; + p.className = 'P' else if (text.match(/^Start /)) - p.className = 'st', text = text.replace(/\.$/, ""); + p.className = 'st', text = text.replace(/\.$/, "") else if (text.match(/^Battle in/)) - p.className = 'bs'; + p.className = 'bs' if (text.match(/^Start /)) - text = text.substring(6); + text = text.substring(6) - p.innerHTML = text; - return p; + p.innerHTML = text + return p } function on_focus_space(evt) { - document.getElementById("status").textContent = evt.target.space; + document.getElementById("status").textContent = evt.target.space } function on_blur_space(evt) { - document.getElementById("status").textContent = ""; + document.getElementById("status").textContent = "" } function on_click_space(evt) { - send_action('space', evt.target.space); + send_action('space', evt.target.space) } -const STEPS = [ 0, "I", "II", "III", "IIII" ]; +const STEPS = [ 0, "I", "II", "III", "IIII" ] function block_description(b) { if (is_known_block(b)) { - let s = BLOCKS[b].steps; - let c = BLOCKS[b].initiative + BLOCKS[b].firepower; - let levy = BLOCKS[b].levy; + let s = BLOCKS[b].steps + let c = BLOCKS[b].initiative + BLOCKS[b].firepower + let levy = BLOCKS[b].levy if (levy) - return BLOCKS[b].name + " (" + levy + ") " + STEPS[s] + "-" + c; - return BLOCKS[b].name + " " + STEPS[s] + "-" + c; + return BLOCKS[b].name + " (" + levy + ") " + STEPS[s] + "-" + c + return BLOCKS[b].name + " " + STEPS[s] + "-" + c } - return block_owner(b); + return block_owner(b) } function block_owner(who) { if (who in view.owner) - return view.owner[who]; - return BLOCKS[who].owner; + return view.owner[who] + return BLOCKS[who].owner } function block_name(b) { - return BLOCKS[b].name; + return BLOCKS[b].name } function on_focus_map_block(evt) { - document.getElementById("status").textContent = block_description(evt.target.block); + document.getElementById("status").textContent = block_description(evt.target.block) } function on_blur_map_block(evt) { - document.getElementById("status").textContent = ""; + document.getElementById("status").textContent = "" } function on_focus_battle_block(evt) { - let b = evt.target.block; - let msg = block_name(b); + let b = evt.target.block + let msg = block_name(b) if (!evt.target.classList.contains("known")) - msg = "Reserves"; + msg = "Reserves" if (view.actions && view.actions.battle_fire && view.actions.battle_fire.includes(b)) - msg = "Fire with " + msg; + msg = "Fire with " + msg else if (view.actions && view.actions.battle_retreat && view.actions.battle_retreat.includes(b)) - msg = "Retreat with " + msg; + msg = "Retreat with " + msg else if (view.actions && view.actions.battle_hit && view.actions.battle_hit.includes(b)) - msg = "Take hit on " + msg; + msg = "Take hit on " + msg - document.getElementById("status").textContent = msg; + document.getElementById("status").textContent = msg } function on_blur_battle_block(evt) { - document.getElementById("status").textContent = ""; + document.getElementById("status").textContent = "" } function on_focus_battle_fire(evt) { document.getElementById("status").textContent = - "Fire with " + block_name(evt.target.block); + "Fire with " + block_name(evt.target.block) } function on_focus_battle_retreat(evt) { document.getElementById("status").textContent = - "Retreat with " + block_name(evt.target.block); + "Retreat with " + block_name(evt.target.block) } function on_focus_battle_pass(evt) { document.getElementById("status").textContent = - "Pass with " + block_name(evt.target.block); + "Pass with " + block_name(evt.target.block) } function on_focus_battle_hit(evt) { document.getElementById("status").textContent = - "Take hit on " + block_name(evt.target.block); + "Take hit on " + block_name(evt.target.block) } function on_blur_battle_button(evt) { - document.getElementById("status").textContent = ""; + document.getElementById("status").textContent = "" } -function on_click_battle_block(evt) { send_action('block', evt.target.block); } -function on_click_battle_hit(evt) { send_action('battle_hit', evt.target.block); } -function on_click_battle_fire(evt) { send_action('battle_fire', evt.target.block); } -function on_click_battle_retreat(evt) { send_action('battle_retreat', evt.target.block); } +function on_click_battle_block(evt) { send_action('block', evt.target.block) } +function on_click_battle_hit(evt) { send_action('battle_hit', evt.target.block) } +function on_click_battle_fire(evt) { send_action('battle_fire', evt.target.block) } +function on_click_battle_retreat(evt) { send_action('battle_retreat', evt.target.block) } function on_click_battle_pass(evt) { if (window.confirm("Are you sure that you want to PASS with " + block_name(evt.target.block) + "?")) - send_action('battle_pass', evt.target.block); + send_action('battle_pass', evt.target.block) } function on_click_map_block(evt) { - let b = evt.target.block; - let s = view.location[b]; + let b = evt.target.block + let s = view.location[b] if (view.actions && view.actions.secret && view.actions.secret.includes(s)) - send_action('secret', [s, BLOCKS[b].color]); + send_action('secret', [s, BLOCKS[b].color]) else if (!view.battle) - send_action('block', b); + send_action('block', b) } function build_map() { // These must match up with the sizes in play.html - const city_size = 60+10; - const sea_size = 70+10; + const city_size = 60+10 + const sea_size = 70+10 - ui.blocks_element = document.getElementById("blocks"); - ui.offmap_element = document.getElementById("offmap"); - ui.spaces_element = document.getElementById("spaces"); + ui.blocks_element = document.getElementById("blocks") + ui.offmap_element = document.getElementById("offmap") + ui.spaces_element = document.getElementById("spaces") for (let s in SPACES) { - let space = SPACES[s]; - let element = document.createElement("div"); - element.classList.add("space"); - let size = (space.type === 'sea') ? sea_size : city_size; + let space = SPACES[s] + let element = document.createElement("div") + element.classList.add("space") + let size = (space.type === 'sea') ? sea_size : city_size if (space.type === "sea") - element.classList.add("sea"); + element.classList.add("sea") else - element.classList.add("city"); - element.setAttribute("draggable", "false"); - element.addEventListener("mouseenter", on_focus_space); - element.addEventListener("mouseleave", on_blur_space); - element.addEventListener("click", on_click_space); - element.style.left = (space.x - size/2) + "px"; - element.style.top = (space.y - size/2) + "px"; + element.classList.add("city") + element.setAttribute("draggable", "false") + element.addEventListener("mouseenter", on_focus_space) + element.addEventListener("mouseleave", on_blur_space) + element.addEventListener("click", on_click_space) + element.style.left = (space.x - size/2) + "px" + element.style.top = (space.y - size/2) + "px" if (space.type !== 'pool') - document.getElementById("spaces").appendChild(element); - element.space = s; - ui.spaces[s] = element; + document.getElementById("spaces").appendChild(element) + element.space = s + ui.spaces[s] = element } function build_map_block(b, block) { - let element = document.createElement("div"); - element.classList.add("block"); - element.classList.add("known"); - element.classList.add(block.color); - element.classList.add("block_"+block.label); - element.addEventListener("mouseenter", on_focus_map_block); - element.addEventListener("mouseleave", on_blur_map_block); - element.addEventListener("click", on_click_map_block); - element.block = b; - ui.blocks[b] = element; + let element = document.createElement("div") + element.classList.add("block") + element.classList.add("known") + element.classList.add(block.color) + element.classList.add("block_"+block.label) + element.addEventListener("mouseenter", on_focus_map_block) + element.addEventListener("mouseleave", on_blur_map_block) + element.addEventListener("click", on_click_map_block) + element.block = b + ui.blocks[b] = element } function build_battle_button(menu, b, c, click, enter, img_src) { - let img = new Image(); - img.draggable = false; - img.classList.add("action"); - img.classList.add(c); - img.setAttribute("src", img_src); - img.addEventListener("click", click); - img.addEventListener("mouseenter", enter); - img.addEventListener("mouseleave", on_blur_battle_button); - img.block = b; - menu.appendChild(img); + let img = new Image() + img.draggable = false + img.classList.add("action") + img.classList.add(c) + img.setAttribute("src", img_src) + img.addEventListener("click", click) + img.addEventListener("mouseenter", enter) + img.addEventListener("mouseleave", on_blur_battle_button) + img.block = b + menu.appendChild(img) } function build_battle_block(b, block) { - let element = document.createElement("div"); - element.classList.add("block"); - element.classList.add(block.color); - element.classList.add("block_"+block.label); - element.addEventListener("mouseenter", on_focus_battle_block); - element.addEventListener("mouseleave", on_blur_battle_block); - element.addEventListener("click", on_click_battle_block); - element.block = b; - ui.battle_block[b] = element; - - let action_list = document.createElement("div"); - action_list.classList.add("battle_menu_list"); - action_list.appendChild(element); + let element = document.createElement("div") + element.classList.add("block") + element.classList.add(block.color) + element.classList.add("block_"+block.label) + element.addEventListener("mouseenter", on_focus_battle_block) + element.addEventListener("mouseleave", on_blur_battle_block) + element.addEventListener("click", on_click_battle_block) + element.block = b + ui.battle_block[b] = element + + let action_list = document.createElement("div") + action_list.classList.add("battle_menu_list") + action_list.appendChild(element) build_battle_button(action_list, b, "hit", on_click_battle_hit, on_focus_battle_hit, - "/images/cross-mark.svg"); + "/images/cross-mark.svg") build_battle_button(action_list, b, "fire", on_click_battle_fire, on_focus_battle_fire, - "/images/pointy-sword.svg"); + "/images/pointy-sword.svg") build_battle_button(action_list, b, "retreat", on_click_battle_retreat, on_focus_battle_retreat, - "/images/flying-flag.svg"); + "/images/flying-flag.svg") build_battle_button(action_list, b, "pass", on_click_battle_pass, on_focus_battle_pass, - "/images/sands-of-time.svg"); - - let menu = document.createElement("div"); - menu.classList.add("battle_menu"); - menu.appendChild(element); - menu.appendChild(action_list); - menu.block = b; - ui.battle_menu[b] = menu; + "/images/sands-of-time.svg") + + let menu = document.createElement("div") + menu.classList.add("battle_menu") + menu.appendChild(element) + menu.appendChild(action_list) + menu.block = b + ui.battle_menu[b] = menu } for (let b in BLOCKS) { - let block = BLOCKS[b]; - block.color = (block.name === "Cleopatra" ? "Cleopatra" : block.owner); - build_map_block(b, block); - build_battle_block(b, block); + let block = BLOCKS[b] + block.color = (block.name === "Cleopatra" ? "Cleopatra" : block.owner) + build_map_block(b, block) + build_battle_block(b, block) } for (let c = 1; c <= 27; ++c) - ui.cards[c] = document.getElementById("card+" + c); + ui.cards[c] = document.getElementById("card+" + c) for (let c = 1; c <= 6; ++c) - ui.card_backs[c] = document.getElementById("back+" + c); + ui.card_backs[c] = document.getElementById("back+" + c) } function update_steps(block, element, animate) { - let old_steps = ui.old_steps[block] || view.steps[block]; - let steps = view.steps[block]; + let old_steps = ui.old_steps[block] || view.steps[block] + let steps = view.steps[block] if (view.location[block] !== ui.old_location[block]) - animate = false; + animate = false if (label_style === 'simple' && steps !== old_steps && animate) { let options = { duration: 700, easing: 'ease', iterations: Math.abs(steps-old_steps) } if (steps < old_steps) - element.animate(step_down_animation, options); + element.animate(step_down_animation, options) if (steps > old_steps) - element.animate(step_up_animation, options); + element.animate(step_up_animation, options) } - element.classList.remove("r0"); - element.classList.remove("r1"); - element.classList.remove("r2"); - element.classList.remove("r3"); - element.classList.add("r"+(BLOCKS[block].steps - steps)); + element.classList.remove("r0") + element.classList.remove("r1") + element.classList.remove("r2") + element.classList.remove("r3") + element.classList.add("r"+(BLOCKS[block].steps - steps)) } function layout_blocks(location, north, south) { if (label_layout === 'spread' || (location === LEVY || location === DEAD)) - layout_blocks_spread(location, north, south); + layout_blocks_spread(location, north, south) else - layout_blocks_stacked(location, north, south); + layout_blocks_stacked(location, north, south) } function layout_blocks_spread(location, north, south) { - let wrap = SPACES[location].wrap; - let s = north.length; - let k = south.length; - let n = s + k; - let row, rows = []; - let i = 0; + let wrap = SPACES[location].wrap + let s = north.length + let k = south.length + let n = s + k + let row, rows = [] + let i = 0 function new_line() { - rows.push(row = []); - i = 0; + rows.push(row = []) + i = 0 } - new_line(); + new_line() while (north.length > 0) { if (i === wrap) - new_line(); - row.push(north.shift()); - ++i; + new_line() + row.push(north.shift()) + ++i } // Break early if north and south fit in exactly two rows and more than two blocks. if (s > 0 && s <= wrap && k > 0 && k <= wrap && n > 2) - new_line(); + new_line() while (south.length > 0) { if (i === wrap) - new_line(); - row.push(south.shift()); - ++i; + new_line() + row.push(south.shift()) + ++i } if (SPACES[location].layout_minor > 0.5) - rows.reverse(); + rows.reverse() for (let j = 0; j < rows.length; ++j) for (i = 0; i < rows[j].length; ++i) - position_block_spread(location, j, rows.length, i, rows[j].length, rows[j][i]); + position_block_spread(location, j, rows.length, i, rows[j].length, rows[j][i]) } function position_block_spread(location, row, n_rows, col, n_cols, element) { - let space = SPACES[location]; - let block_size = (label_style === 'columbia') ? 56+6 : 48+4; - let padding = (location === LEVY || location === DEAD) ? 6 : 3; - let offset = block_size + padding; - let row_size = (n_rows-1) * offset; - let col_size = (n_cols-1) * offset; - let x = space.x - block_size/2; - let y = space.y - block_size/2; + let space = SPACES[location] + let block_size = (label_style === 'columbia') ? 56+6 : 48+4 + let padding = (location === LEVY || location === DEAD) ? 6 : 3 + let offset = block_size + padding + let row_size = (n_rows-1) * offset + let col_size = (n_cols-1) * offset + let x = space.x - block_size/2 + let y = space.y - block_size/2 if (space.layout_axis === 'X') { - x -= col_size * space.layout_major; - y -= row_size * space.layout_minor; - x += col * offset; - y += row * offset; + x -= col_size * space.layout_major + y -= row_size * space.layout_minor + x += col * offset + y += row * offset } else { - y -= col_size * space.layout_major; - x -= row_size * space.layout_minor; - y += col * offset; - x += row * offset; + y -= col_size * space.layout_major + x -= row_size * space.layout_minor + y += col * offset + x += row * offset } - element.style.left = (x|0)+"px"; - element.style.top = (y|0)+"px"; + element.style.left = (x|0)+"px" + element.style.top = (y|0)+"px" } function layout_blocks_stacked(location, secret, known) { - let s = secret.length; - let k = known.length; - let both = secret.length > 0 && known.length > 0; - let i = 0; + let s = secret.length + let k = known.length + let both = secret.length > 0 && known.length > 0 + let i = 0 while (secret.length > 0) - position_block_stacked(location, i++, (s-1)/2, both ? 1 : 0, secret.shift()); - i = 0; + position_block_stacked(location, i++, (s-1)/2, both ? 1 : 0, secret.shift()) + i = 0 while (known.length > 0) - position_block_stacked(location, i++, (k-1)/2, 0, known.shift()); + position_block_stacked(location, i++, (k-1)/2, 0, known.shift()) } function position_block_stacked(location, i, c, k, element) { - let space = SPACES[location]; - let block_size = (label_style === 'columbia') ? 56+6 : 48+4; - let x = space.x + (i - c) * 16 + k * 12; - let y = space.y + (i - c) * 16 - k * 12; - element.style.left = ((x - block_size/2)|0)+"px"; - element.style.top = ((y - block_size/2)|0)+"px"; + let space = SPACES[location] + let block_size = (label_style === 'columbia') ? 56+6 : 48+4 + let x = space.x + (i - c) * 16 + k * 12 + let y = space.y + (i - c) * 16 - k * 12 + element.style.left = ((x - block_size/2)|0)+"px" + element.style.top = ((y - block_size/2)|0)+"px" } function show_block(element) { if (element.parentElement !== ui.blocks_element) - ui.blocks_element.appendChild(element); + ui.blocks_element.appendChild(element) } function hide_block(element) { if (element.parentElement !== ui.offmap_element) - ui.offmap_element.appendChild(element); + ui.offmap_element.appendChild(element) } function is_known_block(who) { if (view.game_over && player === 'Observer') - return true; + return true if (block_owner(who) === player) - return true; - let where = view.location[who]; + return true + let where = view.location[who] if (where === DEAD) - return true; - return false; + return true + return false } function is_visible_block(where, who) { if (view.game_over && player === 'Observer') - return true; + return true if (where === "Levy") - return block_owner(who) === player; - return true; + return block_owner(who) === player + return true } function update_map() { - let layout = {}; + let layout = {} for (let s in SPACES) - layout[s] = { north: [], south: [] }; + layout[s] = { north: [], south: [] } for (let b in view.location) { - let info = BLOCKS[b]; - let element = ui.blocks[b]; - let space = view.location[b]; + let info = BLOCKS[b] + let element = ui.blocks[b] + let space = view.location[b] if (is_visible_block(space, b)) { - let moved = view.moved[b] ? " moved" : ""; + let moved = view.moved[b] ? " moved" : "" if (space === DEAD && info.type !== 'leader') - moved = " moved"; + moved = " moved" if (is_known_block(b)) { - let image = " block_" + info.label; - let known = " known"; - let jupiter = ""; + let image = " block_" + info.label + let known = " known" + let jupiter = "" if (block_owner(b) !== BLOCKS[b].owner && view.game_over) - jupiter = " jupiter"; - element.classList = info.color + known + " block" + image + moved + jupiter; - update_steps(b, element, true); + jupiter = " jupiter" + element.classList = info.color + known + " block" + image + moved + jupiter + update_steps(b, element, true) } else { - let jupiter = ""; - let mars = ""; - let neptune = ""; + let jupiter = "" + let mars = "" + let neptune = "" if (block_owner(b) !== BLOCKS[b].owner) - jupiter = " jupiter"; + jupiter = " jupiter" if (block_owner(b) === view.mars && space === view.surprise) - mars = " mars"; + mars = " mars" if (block_owner(b) === view.neptune && space === view.surprise) - neptune = " neptune"; - element.classList = info.color + " block" + moved + jupiter + mars + neptune; + neptune = " neptune" + element.classList = info.color + " block" + moved + jupiter + mars + neptune } if (block_owner(b) === CAESAR) - layout[space].north.push(element); + layout[space].north.push(element) else - layout[space].south.push(element); - show_block(element); + layout[space].south.push(element) + show_block(element) } else { - hide_block(element); + hide_block(element) } } for (let space in SPACES) - layout_blocks(space, layout[space].north, layout[space].south); + layout_blocks(space, layout[space].north, layout[space].south) // Mark selections and highlights for (let where in SPACES) { if (ui.spaces[where]) { - ui.spaces[where].classList.remove('highlight'); - ui.spaces[where].classList.remove('where'); + ui.spaces[where].classList.remove('highlight') + ui.spaces[where].classList.remove('where') } } if (view.actions && view.actions.space) for (let where of view.actions.space) - ui.spaces[where].classList.add('highlight'); + ui.spaces[where].classList.add('highlight') for (let b in BLOCKS) { - ui.blocks[b].classList.remove('highlight'); - ui.blocks[b].classList.remove('selected'); + ui.blocks[b].classList.remove('highlight') + ui.blocks[b].classList.remove('selected') } if (!view.battle) { if (view.actions && view.actions.block) for (let b of view.actions.block) - ui.blocks[b].classList.add('highlight'); + ui.blocks[b].classList.add('highlight') if (view.who) - ui.blocks[view.who].classList.add('selected'); + ui.blocks[view.who].classList.add('selected') } for (let b in BLOCKS) { - let s = view.location[b]; + let s = view.location[b] if (view.actions && view.actions.secret && view.actions.secret.includes(s)) - ui.blocks[b].classList.add('highlight'); + ui.blocks[b].classList.add('highlight') } } function compare_blocks(a, b, ballista) { - let aa = BLOCKS[a].initiative; - let bb = BLOCKS[b].initiative; - if (aa === 'X') aa = ballista; - if (bb === 'X') bb = ballista; + let aa = BLOCKS[a].initiative + let bb = BLOCKS[b].initiative + if (aa === 'X') aa = ballista + if (bb === 'X') bb = ballista if (aa === bb) { - aa = BLOCKS[a].label; - bb = BLOCKS[b].label; + aa = BLOCKS[a].label + bb = BLOCKS[b].label } - return (aa < bb) ? -1 : (aa > bb) ? 1 : 0; + return (aa < bb) ? -1 : (aa > bb) ? 1 : 0 } function sort_battle_row(root, ballista) { - let swapped; - let children = root.children; + let swapped + let children = root.children do { - swapped = false; + swapped = false for (let i = 1; i < children.length; ++i) { if (compare_blocks(children[i-1].block, children[i].block, ballista) > 0) { - children[i].after(children[i-1]); - swapped = true; + children[i].after(children[i-1]) + swapped = true } } - } while (swapped); + } while (swapped) } function update_battle() { function fill_cell(name, list, reserve, ballista) { - let cell = window[name]; + let cell = window[name] - ui.present.clear(); + ui.present.clear() for (let block of list) { - ui.present.add(block); + ui.present.add(block) if (!cell.contains(ui.battle_menu[block])) - cell.appendChild(ui.battle_menu[block]); + cell.appendChild(ui.battle_menu[block]) if (block === view.who) - ui.battle_menu[block].classList.add("selected"); + ui.battle_menu[block].classList.add("selected") else - ui.battle_menu[block].classList.remove("selected"); + ui.battle_menu[block].classList.remove("selected") - ui.battle_block[block].classList.remove("highlight"); - ui.battle_menu[block].classList.remove('hit'); - ui.battle_menu[block].classList.remove('fire'); - ui.battle_menu[block].classList.remove('retreat'); - ui.battle_menu[block].classList.remove('pass'); + ui.battle_block[block].classList.remove("highlight") + ui.battle_menu[block].classList.remove('hit') + ui.battle_menu[block].classList.remove('fire') + ui.battle_menu[block].classList.remove('retreat') + ui.battle_menu[block].classList.remove('pass') if (view.actions && view.actions.block && view.actions.block.includes(block)) - ui.battle_block[block].classList.add("highlight"); + ui.battle_block[block].classList.add("highlight") if (view.actions && view.actions.battle_fire && view.actions.battle_fire.includes(block)) - ui.battle_menu[block].classList.add('fire'); + ui.battle_menu[block].classList.add('fire') if (view.actions && view.actions.battle_retreat && view.actions.battle_retreat.includes(block)) - ui.battle_menu[block].classList.add('retreat'); + ui.battle_menu[block].classList.add('retreat') if (view.actions && view.actions.battle_pass && view.actions.battle_pass.includes(block)) - ui.battle_menu[block].classList.add('pass'); + ui.battle_menu[block].classList.add('pass') if (view.actions && view.actions.battle_hit && view.actions.battle_hit.includes(block)) - ui.battle_menu[block].classList.add('hit'); + ui.battle_menu[block].classList.add('hit') - update_steps(block, ui.battle_block[block], true); + update_steps(block, ui.battle_block[block], true) if (reserve) - ui.battle_block[block].classList.add("secret"); + ui.battle_block[block].classList.add("secret") else - ui.battle_block[block].classList.remove("secret"); + ui.battle_block[block].classList.remove("secret") if (view.moved[block] || reserve) - ui.battle_block[block].classList.add("moved"); + ui.battle_block[block].classList.add("moved") else - ui.battle_block[block].classList.remove("moved"); + ui.battle_block[block].classList.remove("moved") if (reserve) - ui.battle_block[block].classList.remove("known"); + ui.battle_block[block].classList.remove("known") else - ui.battle_block[block].classList.add("known"); + ui.battle_block[block].classList.add("known") } for (let b in BLOCKS) { if (!ui.present.has(b)) { if (cell.contains(ui.battle_menu[b])) - cell.removeChild(ui.battle_menu[b]); + cell.removeChild(ui.battle_menu[b]) } } - sort_battle_row(cell, ballista); + sort_battle_row(cell, ballista) } if (player === CAESAR) { - fill_cell("FR", view.battle.CR, true, 'B'); - fill_cell("FF", view.battle.CF, false, view.battle.A === CAESAR ? 'D' : 'B'); - fill_cell("EF", view.battle.PF, false, view.battle.A === CAESAR ? 'B' : 'D'); - fill_cell("ER", view.battle.PR, true, 'B'); + fill_cell("FR", view.battle.CR, true, 'B') + fill_cell("FF", view.battle.CF, false, view.battle.A === CAESAR ? 'D' : 'B') + fill_cell("EF", view.battle.PF, false, view.battle.A === CAESAR ? 'B' : 'D') + fill_cell("ER", view.battle.PR, true, 'B') } else { - fill_cell("FR", view.battle.PR, true, 'B'); - fill_cell("FF", view.battle.PF, false, view.battle.A === POMPEIUS ? 'D' : 'B'); - fill_cell("EF", view.battle.CF, false, view.battle.A === POMPEIUS ? 'B' : 'D'); - fill_cell("ER", view.battle.CR, true, 'B'); + fill_cell("FR", view.battle.PR, true, 'B') + fill_cell("FF", view.battle.PF, false, view.battle.A === POMPEIUS ? 'D' : 'B') + fill_cell("EF", view.battle.CF, false, view.battle.A === POMPEIUS ? 'B' : 'D') + fill_cell("ER", view.battle.CR, true, 'B') } } function update_card_display(element, card, prior_card) { if (!card && !prior_card) { - element.className = "show card card_back"; + element.className = "show card card_back" } else if (prior_card) { - element.className = "show card prior card_" + CARDS[prior_card].image; + element.className = "show card prior card_" + CARDS[prior_card].image } else { - element.className = "show card card_" + CARDS[card].image; + element.className = "show card card_" + CARDS[card].image } } function update_cards() { - update_card_display(document.getElementById("caesar_card"), view.c_card, view.prior_c_card); - update_card_display(document.getElementById("pompeius_card"), view.p_card, view.prior_p_card); + update_card_display(document.getElementById("caesar_card"), view.c_card, view.prior_c_card) + update_card_display(document.getElementById("pompeius_card"), view.p_card, view.prior_p_card) for (let c = 1; c <= 27; ++c) { - let element = ui.cards[c]; + let element = ui.cards[c] if (view.hand.includes(c)) { - element.classList.add("show"); + element.classList.add("show") if (view.actions && view.actions.card) { if (view.actions.card.includes(c)) { - element.classList.add("enabled"); - element.classList.remove("disabled"); + element.classList.add("enabled") + element.classList.remove("disabled") } else { - element.classList.remove("enabled"); - element.classList.add("disabled"); + element.classList.remove("enabled") + element.classList.add("disabled") } } else { - element.classList.remove("enabled"); - element.classList.remove("disabled"); + element.classList.remove("enabled") + element.classList.remove("disabled") } } else { - element.classList.remove("show"); + element.classList.remove("show") } } - let n = view.hand.length; + let n = view.hand.length for (let c = 1; c <= 6; ++c) if (c <= n && player === 'Observer') - ui.card_backs[c].classList.add("show"); + ui.card_backs[c].classList.add("show") else - ui.card_backs[c].classList.remove("show"); + ui.card_backs[c].classList.remove("show") } function on_update() { if (!ui.old_steps) { - ui.old_steps = view.steps; - ui.old_location = view.location; + ui.old_steps = view.steps + ui.old_location = view.location } - document.getElementById("turn").className = "year_" + view.year; - document.getElementById("caesar_vp").textContent = view.c_vp + " VP"; - document.getElementById("pompeius_vp").textContent = view.p_vp + " VP"; + document.getElementById("turn").className = "year_" + view.year + document.getElementById("caesar_vp").textContent = view.c_vp + " VP" + document.getElementById("pompeius_vp").textContent = view.p_vp + " VP" if (view.turn < 1) - document.getElementById("turn_info").textContent = `Year ${view.year}`; + document.getElementById("turn_info").textContent = `Year ${view.year}` else - document.getElementById("turn_info").textContent = `Turn ${view.turn} of Year ${view.year}`; + document.getElementById("turn_info").textContent = `Turn ${view.turn} of Year ${view.year}` - action_button("surprise", "Surprise!"); - action_button("pass"); - action_button("undo", "Undo"); + action_button("surprise", "Surprise!") + action_button("pass") + action_button("undo", "Undo") - update_cards(); - update_map(); + update_cards() + update_map() if (view.battle) { - document.getElementById("battle_header").textContent = view.battle.title; - document.getElementById("battle_message").textContent = view.battle.flash; - document.getElementById("battle").classList.add("show"); - update_battle(); + document.getElementById("battle_header").textContent = view.battle.title + document.getElementById("battle_message").textContent = view.battle.flash + document.getElementById("battle").classList.add("show") + update_battle() } else { - document.getElementById("battle").classList.remove("show"); + document.getElementById("battle").classList.remove("show") } - ui.old_location = Object.assign({}, view.location); - ui.old_steps = Object.assign({}, view.steps); + ui.old_location = Object.assign({}, view.location) + ui.old_steps = Object.assign({}, view.steps) } function select_card(c) { - send_action('card', c); + send_action('card', c) } -build_map(); +build_map() -document.getElementById("blocks").classList.add(label_style+'-labels'); -document.getElementById("battle").classList.add(label_style+'-labels'); +document.getElementById("blocks").classList.add(label_style+'-labels') +document.getElementById("battle").classList.add(label_style+'-labels') -drag_element_with_mouse("#battle", "#battle_header"); -scroll_with_middle_mouse("main"); +drag_element_with_mouse("#battle", "#battle_header") +scroll_with_middle_mouse("main") @@ -1,171 +1,171 @@ -"use strict"; +"use strict" exports.scenarios = [ "Historical", "Free Deployment", // TODO: Avalon Digital scenarios? -]; +] exports.roles = [ "Caesar", "Pompeius", -]; - -const { CARDS, SPACES, EDGES, BLOCKS } = require('./data'); - -const APOLLO = 1; -const JUPITER = 2; -const MARS = 3; -const MERCURY = 4; -const NEPTUNE = 5; -const PLUTO = 6; -const VULCAN = 7; - -const OBSERVER = "Observer"; -const BOTH = "Both"; -const CAESAR = "Caesar"; -const POMPEIUS = "Pompeius"; -const CLEOPATRA = "Cleopatra"; -const OCTAVIAN = "Octavian"; -const BRUTUS = "Brutus"; -const ANTONIUS = "Antonius"; -const SCIPIO = "Scipio"; - -const ALEXANDRIA = "Alexandria"; -const ROMA = "Roma"; -const DEAD = "Dead"; -const LEVY = "Levy"; +] + +const { CARDS, SPACES, EDGES, BLOCKS } = require('./data') + +const APOLLO = 1 +const JUPITER = 2 +const MARS = 3 +const MERCURY = 4 +const NEPTUNE = 5 +const PLUTO = 6 +const VULCAN = 7 + +const OBSERVER = "Observer" +const BOTH = "Both" +const CAESAR = "Caesar" +const POMPEIUS = "Pompeius" +const CLEOPATRA = "Cleopatra" +const OCTAVIAN = "Octavian" +const BRUTUS = "Brutus" +const ANTONIUS = "Antonius" +const SCIPIO = "Scipio" + +const ALEXANDRIA = "Alexandria" +const ROMA = "Roma" +const DEAD = "Dead" +const LEVY = "Levy" // serif cirled numbers -const DIE_HIT = [ 0, '\u2776', '\u2777', '\u2778', '\u2779', '\u277A', '\u277B' ]; -const DIE_MISS = [ 0, '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465' ]; +const DIE_HIT = [ 0, '\u2776', '\u2777', '\u2778', '\u2779', '\u277A', '\u277B' ] +const DIE_MISS = [ 0, '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465' ] -const ATTACK_MARK = "*"; -const RESERVE_MARK = ""; +const ATTACK_MARK = "*" +const RESERVE_MARK = "" -let game = null; +let game = null function random(n) { - return Math.floor(((game.seed = game.seed * 48271 % 0x7fffffff) / 0x7fffffff) * n); + return Math.floor(((game.seed = game.seed * 48271 % 0x7fffffff) / 0x7fffffff) * n) } function logbr() { if (game.log.length > 0 && game.log[game.log.length-1] !== "") - game.log.push(""); + game.log.push("") } function log(...args) { - let s = Array.from(args).join(""); - game.log.push(s); + let s = Array.from(args).join("") + game.log.push(s) } function log_battle(s) { - game.log.push(game.active[0] + ": " + s); + game.log.push(game.active[0] + ": " + s) } function logp(s) { - game.log.push(game.active + " " + s); + game.log.push(game.active + " " + s) } function log_move_start(from, to, mark = false) { if (mark) - game.turn_buf = [ from, to + mark ]; + game.turn_buf = [ from, to + mark ] else - game.turn_buf = [ from, to ]; + game.turn_buf = [ from, to ] } function log_move_continue(to, mark = false) { if (mark) - game.turn_buf.push(to + mark); + game.turn_buf.push(to + mark) else - game.turn_buf.push(to); + game.turn_buf.push(to) } function log_move_end() { if (game.turn_buf) { - game.turn_log.push(game.turn_buf); - delete game.turn_buf; + game.turn_log.push(game.turn_buf) + delete game.turn_buf } } function log_levy(where) { - game.turn_log.push([where]); + game.turn_log.push([where]) } function print_turn_log_no_active(text) { function print_move(last) { - return "\n" + n + " " + last.join(" \u2192 "); + return "\n" + n + " " + last.join(" \u2192 ") } - game.turn_log.sort(); - let last = game.turn_log[0]; - let n = 0; + game.turn_log.sort() + let last = game.turn_log[0] + let n = 0 for (let entry of game.turn_log) { if (entry.toString() !== last.toString()) { - text += print_move(last); - n = 0; + text += print_move(last) + n = 0 } - ++n; - last = entry; + ++n + last = entry } if (n > 0) - text += print_move(last); + text += print_move(last) else - text += "\nnothing."; - log(text); - delete game.turn_log; + text += "\nnothing." + log(text) + delete game.turn_log } function print_turn_log(verb) { - print_turn_log_no_active(game.active + " " + verb + ":"); + print_turn_log_no_active(game.active + " " + verb + ":") } function is_inactive_player(current) { - return current === OBSERVER || (game.active !== current && game.active !== BOTH); + return current === OBSERVER || (game.active !== current && game.active !== BOTH) } function remove_from_array(array, item) { - let i = array.indexOf(item); + let i = array.indexOf(item) if (i >= 0) - array.splice(i, 1); + array.splice(i, 1) } function clear_undo() { if (game.undo) - game.undo.length = 0; + game.undo.length = 0 else - game.undo = []; + game.undo = [] } function push_undo() { game.undo.push(JSON.stringify(game, (k,v) => { - if (k === 'undo') return 0; - if (k === 'log') return v.length; - return v; - })); + if (k === 'undo') return 0 + if (k === 'log') return v.length + return v + })) } function pop_undo() { - let undo = game.undo; - let save_log = game.log; - game = JSON.parse(undo.pop()); - game.undo = undo; - save_log.length = game.log; - game.log = save_log; + let undo = game.undo + let save_log = game.log + game = JSON.parse(undo.pop()) + game.undo = undo + save_log.length = game.log + game.log = save_log } function gen_action_undo(view) { if (!view.actions) view.actions = {} if (game.undo && game.undo.length > 0) - view.actions.undo = 1; + view.actions.undo = 1 else - view.actions.undo = 0; + view.actions.undo = 0 } function gen_action_pass(view, text) { if (!view.actions) view.actions = {} - view.actions['pass'] = text; + view.actions['pass'] = text } function gen_action(view, action, argument) { @@ -173,282 +173,282 @@ function gen_action(view, action, argument) { view.actions = {} if (argument !== undefined) { if (!(action in view.actions)) - view.actions[action] = [ argument ]; + view.actions[action] = [ argument ] else - view.actions[action].push(argument); + view.actions[action].push(argument) } else { - view.actions[action] = 1; + view.actions[action] = 1 } } function edge_id(A, B) { if (A > B) - return B + "/" + A; - return A + "/" + B; + return B + "/" + A + return A + "/" + B } function roll_d6() { - return random(6) + 1; + return random(6) + 1 } function reset_deck() { - let deck = []; + let deck = [] for (let c = 1; c <= 27; ++c) if (!game.removed || !game.removed.includes(c)) - deck.push(c); - return deck; + deck.push(c) + return deck } function deal_cards(deck, n) { - let hand = []; - let events = 0; - let max_events = (game.max_2_events ? 2 : n); + let hand = [] + let events = 0 + let max_events = (game.max_2_events ? 2 : n) while (hand.length < n) { - let c = random(deck.length); + let c = random(deck.length) if (events < max_events || deck[c] > 7) { if (deck[c] <= 7) - ++events; - hand.push(deck[c]); - deck.splice(c, 1); + ++events + hand.push(deck[c]) + deck.splice(c, 1) } } - return hand; + return hand } function reset_road_limits() { - game.sea_moved = {}; - game.sea_retreated = false; - game.limits = {}; + game.sea_moved = {} + game.sea_retreated = false + game.limits = {} } function road_limit(e) { - return game.limits[e]|0; + return game.limits[e]|0 } function move_to(who, from, to) { - let e = edge_id(from, to); - game.location[who] = to; - game.last_from = from; - game.limits[e] = road_limit(e) + 1; + let e = edge_id(from, to) + game.location[who] = to + game.last_from = from + game.limits[e] = road_limit(e) + 1 if (is_contested_space(to)) - game.last_used[e] = game.active; + game.last_used[e] = game.active } function block_owner(who) { if (who in game.owner) - return game.owner[who]; - return BLOCKS[who].owner; + return game.owner[who] + return BLOCKS[who].owner } function block_name(who) { - return BLOCKS[who].name; + return BLOCKS[who].name } function block_type(who) { - return BLOCKS[who].type; + return BLOCKS[who].type } function block_initiative(who) { if (block_type(who) === 'ballista') - return is_defender(who) ? 'B' : 'D'; - return BLOCKS[who].initiative; + return is_defender(who) ? 'B' : 'D' + return BLOCKS[who].initiative } function block_fire_power(who) { - return BLOCKS[who].firepower; + return BLOCKS[who].firepower } function block_strength(who) { if (block_type(who) === 'elephant') - return game.steps[who] * 2; - return game.steps[who]; + return game.steps[who] * 2 + return game.steps[who] } function is_dead(b) { - return game.location[b] === DEAD; + return game.location[b] === DEAD } function eliminate_block(who) { if (who === CLEOPATRA) { - let new_owner = enemy(game.owner[who]); - game.flash = "Cleopatra was captured."; - log("Cleopatra joined " + new_owner + "!"); - game.owner[who] = new_owner; + let new_owner = enemy(game.owner[who]) + game.flash = "Cleopatra was captured." + log("Cleopatra joined " + new_owner + "!") + game.owner[who] = new_owner } else { - game.flash = block_name(who) + " was eliminated."; - log(block_name(who) + " was eliminated."); - game.location[who] = DEAD; - game.steps[who] = BLOCKS[who].steps; - delete game.owner[who]; + game.flash = block_name(who) + " was eliminated." + log(block_name(who) + " was eliminated.") + game.location[who] = DEAD + game.steps[who] = BLOCKS[who].steps + delete game.owner[who] } } function disband_block(who) { - game.location[who] = LEVY; - game.steps[who] = BLOCKS[who].steps; - delete game.owner[who]; + game.location[who] = LEVY + game.steps[who] = BLOCKS[who].steps + delete game.owner[who] } function reduce_block(who) { if (game.steps[who] === 1) { - eliminate_block(who); + eliminate_block(who) } else { - game.steps[who]--; + game.steps[who]-- } } /* Game state queries */ function enemy(p) { - return p === CAESAR ? POMPEIUS : CAESAR; + return p === CAESAR ? POMPEIUS : CAESAR } function enemy_player() { - return enemy(game.active); + return enemy(game.active) } function count_friendly(where) { - let count = 0; - let p = game.active; + let count = 0 + let p = game.active for (let b in BLOCKS) { if (game.location[b] === where && block_owner(b) === p) - ++count; + ++count } - return count; + return count } function count_enemy(where) { - let count = 0; - let p = enemy_player(); + let count = 0 + let p = enemy_player() for (let b in BLOCKS) { if (game.location[b] === where && block_owner(b) === p) - ++count; + ++count } - return count; + return count } function count_pinning(where) { - let count = 0; + let count = 0 if (game.active === game.p2) { - let p = enemy_player(); + let p = enemy_player() for (let b in BLOCKS) { if (game.location[b] === where && block_owner(b) === p) if (!game.reserves.includes(b)) - ++count; + ++count } } - return count; + return count } function count_pinned(where) { - let count = 0; + let count = 0 for (let b in BLOCKS) { if (game.location[b] === where && block_owner(b) === game.active) if (!game.reserves.includes(b)) - ++count; + ++count } - return count; + return count } function is_pinned(who) { if (game.active === game.p2) { - let where = game.location[who]; + let where = game.location[who] if (count_pinned(where) <= count_pinning(where)) - return true; + return true } - return false; + return false } function is_city(where) { - let t = SPACES[where].type; - return t === 'city' || t === 'major-port' || t === 'port'; + let t = SPACES[where].type + return t === 'city' || t === 'major-port' || t === 'port' } function is_port(where) { - let t = SPACES[where].type; - return t === 'major-port' || t === 'port'; + let t = SPACES[where].type + return t === 'major-port' || t === 'port' } function is_sea(where) { - return SPACES[where].type === 'sea'; + return SPACES[where].type === 'sea' } function is_map_space(where) { - return is_city(where) || is_sea(where); + return is_city(where) || is_sea(where) } function is_navis(b) { - return BLOCKS[b].type === 'navis'; + return BLOCKS[b].type === 'navis' } -function is_friendly_space(where) { return count_friendly(where) > 0 && count_enemy(where) === 0; } -function is_enemy_space(where) { return count_friendly(where) === 0 && count_enemy(where) > 0; } -function is_vacant_space(where) { return count_friendly(where) === 0 && count_enemy(where) === 0; } -function is_contested_space(where) { return count_friendly(where) > 0 && count_enemy(where) > 0; } +function is_friendly_space(where) { return count_friendly(where) > 0 && count_enemy(where) === 0 } +function is_enemy_space(where) { return count_friendly(where) === 0 && count_enemy(where) > 0 } +function is_vacant_space(where) { return count_friendly(where) === 0 && count_enemy(where) === 0 } +function is_contested_space(where) { return count_friendly(where) > 0 && count_enemy(where) > 0 } -function is_friendly_city(where) { return is_city(where) && is_friendly_space(where); } -function is_enemy_city(where) { return is_city(where) && is_enemy_space(where); } -function is_contested_city(where) { return is_city(where) && is_contested_space(where); } +function is_friendly_city(where) { return is_city(where) && is_friendly_space(where) } +function is_enemy_city(where) { return is_city(where) && is_enemy_space(where) } +function is_contested_city(where) { return is_city(where) && is_contested_space(where) } -function is_friendly_sea(where) { return is_sea(where) && is_friendly_space(where); } -function is_vacant_sea(where) { return is_sea(where) && is_vacant_space(where); } -function is_contested_sea(where) { return is_sea(where) && is_contested_space(where); } +function is_friendly_sea(where) { return is_sea(where) && is_friendly_space(where) } +function is_vacant_sea(where) { return is_sea(where) && is_vacant_space(where) } +function is_contested_sea(where) { return is_sea(where) && is_contested_space(where) } function have_contested_spaces() { for (let where in SPACES) if (is_map_space(where) && is_contested_space(where)) - return true; - return false; + return true + return false } function supply_limit(where) { if (SPACES[where].type === 'sea') - return 0; - return 3 + SPACES[where].value; + return 0 + return 3 + SPACES[where].value } function is_over_supply_limit(where) { - let count = 0; + let count = 0 for (let b in BLOCKS) { if (game.location[b] === where) - ++count; + ++count } - return count > supply_limit(where); + return count > supply_limit(where) } function count_vp() { - let old_active = game.active; - game.active = CAESAR; - game.c_vp = 0; - game.p_vp = 0; - game.active = CAESAR; + let old_active = game.active + game.active = CAESAR + game.c_vp = 0 + game.p_vp = 0 + game.active = CAESAR for (let s in SPACES) { if (is_friendly_city(s)) - game.c_vp += SPACES[s].value; + game.c_vp += SPACES[s].value if (is_enemy_city(s)) - game.p_vp += SPACES[s].value; + game.p_vp += SPACES[s].value } - if (is_dead(POMPEIUS)) game.c_vp += 1; - if (is_dead(SCIPIO)) game.c_vp += 1; - if (is_dead(BRUTUS)) game.c_vp += 1; - if (is_dead(CAESAR)) game.p_vp += 1; - if (is_dead(ANTONIUS)) game.p_vp += 1; - if (is_dead(OCTAVIAN)) game.p_vp += 1; - game.active = old_active; + if (is_dead(POMPEIUS)) game.c_vp += 1 + if (is_dead(SCIPIO)) game.c_vp += 1 + if (is_dead(BRUTUS)) game.c_vp += 1 + if (is_dead(CAESAR)) game.p_vp += 1 + if (is_dead(ANTONIUS)) game.p_vp += 1 + if (is_dead(OCTAVIAN)) game.p_vp += 1 + game.active = old_active } /* Game ability queries */ function can_amphibious_move_to(b, from, to) { - let e = edge_id(from, to); + let e = edge_id(from, to) if (EDGES[e] === 'sea') { if (is_city(to)) { if (is_friendly_space(to) || is_vacant_space(to)) { - return true; + return true } } else { if (is_friendly_space(to)) { - return true; + return true } } } @@ -457,321 +457,321 @@ function can_amphibious_move_to(b, from, to) { function can_amphibious_move(b) { if (block_owner(b) === game.active && !game.moved[b]) { if (BLOCKS[b].type === 'navis') - return false; + return false if (is_pinned(b)) - return false; - let from = game.location[b]; + return false + let from = game.location[b] for (let to of SPACES[from].exits) if (can_amphibious_move_to(b, from, to)) - return true; + return true } - return false; + return false } function can_regroup_to(b, from, to) { if (is_vacant_space(to) || is_friendly_space(to)) { - let e = edge_id(from, to); - let b_type = BLOCKS[b].type; - let e_type = EDGES[e]; + let e = edge_id(from, to) + let b_type = BLOCKS[b].type + let e_type = EDGES[e] if (b_type === 'navis') - return e_type === 'sea'; + return e_type === 'sea' if (e_type === 'major') - return road_limit(e) < 4; + return road_limit(e) < 4 if (e_type === 'minor') - return road_limit(e) < 2; + return road_limit(e) < 2 if (e_type === 'strait') - return road_limit(e) < 2; + return road_limit(e) < 2 } - return false; + return false } function can_block_use_road(b, from, to) { - let e = edge_id(from, to); - let b_type = BLOCKS[b].type; - let e_type = EDGES[e]; + let e = edge_id(from, to) + let b_type = BLOCKS[b].type + let e_type = EDGES[e] if (b_type === 'navis') { if (game.mars === game.active) - return false; + return false if (game.mercury === game.active) - return false; + return false if (game.pluto === game.active) - return false; - return e_type === 'sea'; + return false + return e_type === 'sea' } else { if (game.neptune === game.active) - return false; + return false } if (game.pluto === game.active) { if (is_enemy_space(to) || is_contested_space(to)) { if (e_type === 'major') - return road_limit(e) < 6; + return road_limit(e) < 6 if (e_type === 'minor') - return road_limit(e) < 3; + return road_limit(e) < 3 if (e_type === 'strait') - return road_limit(e) < 2; + return road_limit(e) < 2 } } if (e_type === 'major') - return road_limit(e) < 4; + return road_limit(e) < 4 if (e_type === 'minor') - return road_limit(e) < 2; + return road_limit(e) < 2 if (e_type === 'strait') { if (is_enemy_space(to) || is_contested_space(to)) - return road_limit(e) < 1; + return road_limit(e) < 1 else - return road_limit(e) < 2; + return road_limit(e) < 2 } - return false; + return false } function can_block_use_road_to_retreat(b, from, to) { - let e = edge_id(from, to); - let b_type = BLOCKS[b].type; - let e_type = EDGES[e]; + let e = edge_id(from, to) + let b_type = BLOCKS[b].type + let e_type = EDGES[e] if (b_type === 'navis') - return e_type === 'sea'; + return e_type === 'sea' if (e_type === 'major') - return road_limit(e) < 4; + return road_limit(e) < 4 if (e_type === 'minor') - return road_limit(e) < 2; + return road_limit(e) < 2 if (e_type === 'strait') - return road_limit(e) < 1; - return false; + return road_limit(e) < 1 + return false } function can_block_move_to(b, to) { - let from = game.location[b]; + let from = game.location[b] if (can_block_use_road(b, from, to)) { if (count_pinning(from) > 0) { - let e = edge_id(from, to); + let e = edge_id(from, to) if (game.last_used[e] === enemy_player()) - return false; + return false } - return true; + return true } - return false; + return false } function can_block_continue_to(b, to) { - let from = game.location[b]; + let from = game.location[b] if (is_friendly_space(to) || is_vacant_space(to)) if (can_block_use_road(b, from, to)) - return true; - return false; + return true + return false } function can_block_move(b) { if (block_owner(b) === game.active && !game.moved[b]) { - let from = game.location[b]; + let from = game.location[b] if (is_pinned(b)) - return false; + return false if (game.sea_moved[from] && count_friendly(from) <= 1) - return false; + return false for (let to of SPACES[from].exits) { if (can_block_move_to(b, to)) { - return true; + return true } } } - return false; + return false } function can_block_continue(b, last_from) { - let here = game.location[b]; + let here = game.location[b] if (is_enemy_space(here) || is_contested_space(here)) - return false; + return false for (let to of SPACES[here].exits) { if (to !== last_from && can_block_continue_to(b, to)) - return true; + return true } - return false; + return false } function can_sea_retreat(who, from, to) { if (game.sea_retreated) - return false; + return false if (BLOCKS[who].type === 'navis') - return false; + return false if (is_friendly_sea(to)) { for (let next of SPACES[to].exits) if (is_friendly_city(next)) - return true; + return true } - return false; + return false } function can_attacker_retreat_to(who, from, to) { - let e = edge_id(from, to); + let e = edge_id(from, to) if (can_sea_retreat(who, from, to)) - return true; + return true if (is_vacant_space(to)) if (can_block_use_road_to_retreat(who, from, to)) if (game.last_used[e] === game.active) - return true; + return true if (is_friendly_space(to)) if (can_block_use_road_to_retreat(who, from, to)) - return true; - return false; + return true + return false } function can_defender_retreat_to(who, from, to) { - let e = edge_id(from, to); + let e = edge_id(from, to) if (BLOCKS[who].type === 'navis') { // Navis can only retreat to vacant seas, not ports! if (is_vacant_sea(to)) { if (can_block_use_road_to_retreat(who, from, to)) if (game.last_used[e] !== enemy_player()) - return true; + return true } // Navis can retreat to any friendly sea or port, even ones used by the attacker! if (is_friendly_space(to)) { if (can_block_use_road_to_retreat(who, from, to)) - return true; + return true } } else { if (can_sea_retreat(who, from, to)) - return true; + return true if (is_vacant_space(to) || is_friendly_space(to)) { if (can_block_use_road_to_retreat(who, from, to)) if (game.last_used[e] !== enemy_player()) - return true; + return true } } - return false; + return false } function can_attacker_retreat(who) { - let from = game.location[who]; + let from = game.location[who] for (let to of SPACES[from].exits) if (can_attacker_retreat_to(who, from, to)) - return true; + return true } function can_defender_retreat(who) { - let from = game.location[who]; + let from = game.location[who] for (let to of SPACES[from].exits) if (can_defender_retreat_to(who, from, to)) - return true; + return true } function can_regroup(who) { - let from = game.location[who]; + let from = game.location[who] for (let to of SPACES[from].exits) if (can_regroup_to(who, from, to)) - return true; - return false; + return true + return false } function can_navis_move_to_port(who) { - let from = game.location[who]; + let from = game.location[who] for (let to of SPACES[from].exits) { if (is_friendly_city(to)) - return true; + return true } - return false; + return false } function can_levy_to(b, to) { if (is_friendly_city(to)) { if (BLOCKS[b].levy) - return BLOCKS[b].levy === to; + return BLOCKS[b].levy === to if (BLOCKS[b].type === 'navis') - return SPACES[to].type === 'major-port'; + return SPACES[to].type === 'major-port' if (b === OCTAVIAN) - return is_dead(CAESAR) || is_dead(ANTONIUS); + return is_dead(CAESAR) || is_dead(ANTONIUS) if (b === BRUTUS) - return is_dead(POMPEIUS) || is_dead(SCIPIO); - return true; + return is_dead(POMPEIUS) || is_dead(SCIPIO) + return true } - return false; + return false } function can_levy(b) { - let location = game.location[b]; + let location = game.location[b] if (block_owner(b) !== game.active) - return false; + return false if (location === LEVY) { for (let to in SPACES) if (can_levy_to(b, to)) - return true; - return false; + return true + return false } if (game.steps[b] === BLOCKS[b].steps) - return false; - return is_friendly_city(game.location[b]); + return false + return is_friendly_city(game.location[b]) } // === --- === --- === --- === --- === --- === // -let states = {}; +let states = {} function start_free_deployment() { - game.active = CAESAR; - game.setup_limit = {}; + game.active = CAESAR + game.setup_limit = {} for (let space in SPACES) { if (is_map_space(space)) { - let n = count_friendly(space) + count_enemy(space); + let n = count_friendly(space) + count_enemy(space) if (n > 0) - game.setup_limit[space] = n; + game.setup_limit[space] = n } } - validate_free_deployment(); - game.state = 'free_deployment'; - clear_undo(); + validate_free_deployment() + game.state = 'free_deployment' + clear_undo() } function validate_free_deployment() { - game.setup_error = []; + game.setup_error = [] for (let space in SPACES) { if (is_friendly_city(space)) { - let n = count_friendly(space); - let d = n - game.setup_limit[space]; + let n = count_friendly(space) + let d = n - game.setup_limit[space] if (d > 0) - game.setup_error.push(space + " +" + d); + game.setup_error.push(space + " +" + d) else if (d < 0) - game.setup_error.push(space + " " + d); + game.setup_error.push(space + " " + d) } } } function format_deployment_error(view) { - view.prompt = "Free Deployment: " + game.setup_error.join(", "); + view.prompt = "Free Deployment: " + game.setup_error.join(", ") } states.free_deployment = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to redeploy blocks..."; - gen_action_undo(view); + return view.prompt = "Waiting for " + game.active + " to redeploy blocks..." + gen_action_undo(view) if (game.setup_error.length === 0) { - view.prompt = "Free Deployment: You may rearrange blocks on the map."; - gen_action_pass(view, "End deployment"); + view.prompt = "Free Deployment: You may rearrange blocks on the map." + gen_action_pass(view, "End deployment") } else { - format_deployment_error(view); + format_deployment_error(view) } for (let b in BLOCKS) if (block_owner(b) === game.active && is_map_space(game.location[b])) - gen_action(view, 'block', b); + gen_action(view, 'block', b) }, block: function (who) { - push_undo(); - game.who = who; - game.state = 'free_deployment_to'; + push_undo() + game.who = who + game.state = 'free_deployment_to' }, pass: function () { if (game.active === CAESAR) { - clear_undo(); - game.moved = {}; - game.active = POMPEIUS; + clear_undo() + game.moved = {} + game.active = POMPEIUS } else { - game.moved = {}; - delete game.setup_limit; - delete game.setup_error; - start_year(); + game.moved = {} + delete game.setup_limit + delete game.setup_error + start_year() } }, undo: pop_undo @@ -780,462 +780,462 @@ states.free_deployment = { states.free_deployment_to = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to redeploy blocks..."; + return view.prompt = "Waiting for " + game.active + " to redeploy blocks..." if (game.setup_error.length === 0) { - view.prompt = "Free Deployment: You may rearrange blocks on the map."; + view.prompt = "Free Deployment: You may rearrange blocks on the map." } else { - format_deployment_error(view); + format_deployment_error(view) } - gen_action_undo(view); - gen_action(view, 'block', game.who); + gen_action_undo(view) + gen_action(view, 'block', game.who) for (let space in SPACES) { if (space in game.setup_limit && space !== game.location[game.who]) { if (!is_enemy_city(space)) { if (block_type(game.who) === 'navis') { if (is_port(space)) - gen_action(view, 'space', space); + gen_action(view, 'space', space) } else { - gen_action(view, 'space', space); + gen_action(view, 'space', space) } } } } }, space: function (where) { - game.location[game.who] = where; - game.moved[game.who] = 1; - validate_free_deployment(); - game.who = null; - game.state = 'free_deployment'; + game.location[game.who] = where + game.moved[game.who] = 1 + validate_free_deployment() + game.who = null + game.state = 'free_deployment' }, block: pop_undo, undo: pop_undo } function start_year() { - logbr(); - log("Start Year " + game.year); - game.turn = 1; - let deck = reset_deck(); - game.c_hand = deal_cards(deck, 6); - game.p_hand = deal_cards(deck, 6); - game.prior_c_card = 0; - game.prior_p_card = 0; - game.c_card = 0; - game.p_card = 0; - game.c_discard = 0; - game.p_discard = 0; - game.active = BOTH; - game.state = 'discard_and_play_card'; - game.show_cards = false; + logbr() + log("Start Year " + game.year) + game.turn = 1 + let deck = reset_deck() + game.c_hand = deal_cards(deck, 6) + game.p_hand = deal_cards(deck, 6) + game.prior_c_card = 0 + game.prior_p_card = 0 + game.c_card = 0 + game.p_card = 0 + game.c_discard = 0 + game.p_discard = 0 + game.active = BOTH + game.state = 'discard_and_play_card' + game.show_cards = false } function resume_discard_and_play_card() { if (game.c_card && game.p_card) - start_first_turn(); + start_first_turn() else if (game.c_card) - game.active = POMPEIUS; + game.active = POMPEIUS else if (game.p_card) - game.active = CAESAR; + game.active = CAESAR else - game.active = BOTH; + game.active = BOTH } states.discard_and_play_card = { prompt: function (view, current) { if (current === "Observer") - return view.prompt = "Waiting for players to discard one card and play one card."; + return view.prompt = "Waiting for players to discard one card and play one card." if (current === CAESAR) { if (!game.c_discard) { - view.prompt = "Discard a card."; + view.prompt = "Discard a card." for (let c of game.c_hand) - gen_action(view, 'card', c); + gen_action(view, 'card', c) } else if (!game.c_card) { - view.prompt = "Play a card."; + view.prompt = "Play a card." for (let c of game.c_hand) if (c !== APOLLO) - gen_action(view, 'card', c); - gen_action(view, 'undo'); + gen_action(view, 'card', c) + gen_action(view, 'undo') } else { - view.prompt = "Waiting for Pompeius..."; - gen_action(view, 'undo'); + view.prompt = "Waiting for Pompeius..." + gen_action(view, 'undo') } } else if (current === POMPEIUS) { if (!game.p_discard) { - view.prompt = "Discard a card."; + view.prompt = "Discard a card." for (let c of game.p_hand) - gen_action(view, 'card', c); + gen_action(view, 'card', c) } else if (!game.p_card) { - view.prompt = "Play a card."; + view.prompt = "Play a card." for (let c of game.p_hand) if (c !== APOLLO) - gen_action(view, 'card', c); - gen_action(view, 'undo'); + gen_action(view, 'card', c) + gen_action(view, 'undo') } else { - view.prompt = "Waiting for Caesar..."; - gen_action(view, 'undo'); + view.prompt = "Waiting for Caesar..." + gen_action(view, 'undo') } } }, card: function (c, current) { if (current === CAESAR) { if (!game.c_discard) - game.c_discard = c; + game.c_discard = c else - game.c_card = c; - remove_from_array(game.c_hand, c); + game.c_card = c + remove_from_array(game.c_hand, c) } if (current === POMPEIUS) { if (!game.p_discard) - game.p_discard = c; + game.p_discard = c else - game.p_card = c; - remove_from_array(game.p_hand, c); + game.p_card = c + remove_from_array(game.p_hand, c) } - resume_discard_and_play_card(); + resume_discard_and_play_card() }, undo: function (_, current) { if (current === CAESAR) { if (game.c_discard) { - game.c_hand.push(game.c_discard); - game.c_discard = 0; + game.c_hand.push(game.c_discard) + game.c_discard = 0 } if (game.c_card) { - game.c_hand.push(game.c_card); - game.c_card = 0; + game.c_hand.push(game.c_card) + game.c_card = 0 } } if (current === POMPEIUS) { if (game.p_discard) { - game.p_hand.push(game.p_discard); - game.p_discard = 0; + game.p_hand.push(game.p_discard) + game.p_discard = 0 } if (game.p_card) { - game.p_hand.push(game.p_card); - game.p_card = 0; + game.p_hand.push(game.p_card) + game.p_card = 0 } } - resume_discard_and_play_card(); + resume_discard_and_play_card() } } function start_first_turn() { - game.last_used = {}; - game.attacker = {}; - game.main_road = {}; - game.moved = {}; - game.reserves = []; - logbr(); - log("Start Turn " + game.turn + " of Year " + game.year); - reveal_cards(); + game.last_used = {} + game.attacker = {} + game.main_road = {} + game.moved = {} + game.reserves = [] + logbr() + log("Start Turn " + game.turn + " of Year " + game.year) + reveal_cards() } function start_turn() { - game.last_used = {}; - game.attacker = {}; - game.main_road = {}; - game.moved = {}; - game.reserves = []; - game.c_card = 0; - game.p_card = 0; - game.active = BOTH; - game.state = 'play_card'; - game.show_cards = false; - game.surprise = 0; - logbr(); - log("Start Turn " + game.turn + " of Year " + game.year); + game.last_used = {} + game.attacker = {} + game.main_road = {} + game.moved = {} + game.reserves = [] + game.c_card = 0 + game.p_card = 0 + game.active = BOTH + game.state = 'play_card' + game.show_cards = false + game.surprise = 0 + logbr() + log("Start Turn " + game.turn + " of Year " + game.year) } function resume_play_card() { if (game.c_card && game.p_card) - reveal_cards(); + reveal_cards() else if (game.c_card) - game.active = POMPEIUS; + game.active = POMPEIUS else if (game.p_card) - game.active = CAESAR; + game.active = CAESAR else - game.active = BOTH; + game.active = BOTH } states.play_card = { prompt: function (view, current) { if (current === "Observer") { - view.prior_c_card = game.prior_c_card; - view.prior_p_card = game.prior_p_card; - return view.prompt = "Waiting for players to play a card."; + view.prior_c_card = game.prior_c_card + view.prior_p_card = game.prior_p_card + return view.prompt = "Waiting for players to play a card." } if (current === CAESAR) { - view.prior_p_card = game.prior_p_card; + view.prior_p_card = game.prior_p_card if (game.c_card) { - view.prompt = "Waiting for Pompeius to play a card."; - gen_action(view, 'undo'); + view.prompt = "Waiting for Pompeius to play a card." + gen_action(view, 'undo') } else { - view.prior_c_card = game.prior_c_card; - view.prompt = "Play a card."; + view.prior_c_card = game.prior_c_card + view.prompt = "Play a card." for (let c of game.c_hand) - gen_action(view, 'card', c); + gen_action(view, 'card', c) } } if (current === POMPEIUS) { - view.prior_c_card = game.prior_c_card; + view.prior_c_card = game.prior_c_card if (game.p_card) { - view.prompt = "Waiting for Caesar to play a card."; - gen_action(view, 'undo'); + view.prompt = "Waiting for Caesar to play a card." + gen_action(view, 'undo') } else { - view.prior_p_card = game.prior_p_card; - view.prompt = "Play a card."; + view.prior_p_card = game.prior_p_card + view.prompt = "Play a card." for (let c of game.p_hand) - gen_action(view, 'card', c); + gen_action(view, 'card', c) } } }, card: function (card, current) { if (current === CAESAR) { - remove_from_array(game.c_hand, card); - game.c_card = card; + remove_from_array(game.c_hand, card) + game.c_card = card } if (current === POMPEIUS) { - remove_from_array(game.p_hand, card); - game.p_card = card; + remove_from_array(game.p_hand, card) + game.p_card = card } - resume_play_card(); + resume_play_card() }, undo: function (_, current) { if (current === CAESAR) { if (game.c_card) { - game.c_hand.push(game.c_card); - game.c_card = 0; + game.c_hand.push(game.c_card) + game.c_card = 0 } } if (current === POMPEIUS) { if (game.p_card) { - game.p_hand.push(game.p_card); - game.p_card = 0; + game.p_hand.push(game.p_card) + game.p_card = 0 } } - resume_play_card(); + resume_play_card() } } function reveal_cards() { - delete game.mars; - delete game.mercury; - delete game.neptune; - delete game.pluto; + delete game.mars + delete game.mercury + delete game.neptune + delete game.pluto - logbr(); - log("Caesar played " + CARDS[game.c_card].name + "."); - log("Pompeius played " + CARDS[game.p_card].name + "."); + logbr() + log("Caesar played " + CARDS[game.c_card].name + ".") + log("Pompeius played " + CARDS[game.p_card].name + ".") if (CARDS[game.c_card].event && CARDS[game.p_card].event) { - log("Events canceled each other."); - game.prior_c_card = game.c_card; - game.prior_p_card = game.p_card; - end_turn(); - return; + log("Events canceled each other.") + game.prior_c_card = game.c_card + game.prior_p_card = game.p_card + end_turn() + return } if (game.c_card === APOLLO) { - game.c_card = game.prior_p_card; - log("Apollo copied " + CARDS[game.c_card].name + "."); + game.c_card = game.prior_p_card + log("Apollo copied " + CARDS[game.c_card].name + ".") } if (game.p_card === APOLLO) { - game.p_card = game.prior_c_card; - log("Apollo copied " + CARDS[game.p_card].name + "."); + game.p_card = game.prior_c_card + log("Apollo copied " + CARDS[game.p_card].name + ".") } - game.prior_c_card = game.c_card; - game.prior_p_card = game.p_card; + game.prior_c_card = game.c_card + game.prior_p_card = game.p_card if (CARDS[game.c_card].event) { - game.p1 = CAESAR; - game.p2 = POMPEIUS; + game.p1 = CAESAR + game.p2 = POMPEIUS } else if (CARDS[game.p_card].event) { - game.p1 = POMPEIUS; - game.p2 = CAESAR; + game.p1 = POMPEIUS + game.p2 = CAESAR } else if (CARDS[game.p_card].move > CARDS[game.c_card].move) { - game.p1 = POMPEIUS; - game.p2 = CAESAR; + game.p1 = POMPEIUS + game.p2 = CAESAR } else { - game.p1 = CAESAR; - game.p2 = POMPEIUS; + game.p1 = CAESAR + game.p2 = POMPEIUS } // Tournament rule: Caesar always goes first on the first turn of the game. if (game.year === 705 && game.turn === 1 && game.tournament) { if (game.p1 !== CAESAR) { - game.p1 = CAESAR; - game.p2 = POMPEIUS; + game.p1 = CAESAR + game.p2 = POMPEIUS } } - game.show_cards = true; - game.active = game.p1; - start_player_turn(); + game.show_cards = true + game.active = game.p1 + start_player_turn() } function start_player_turn() { - logbr(); - log("Start " + game.active); - reset_road_limits(); - game.activated = []; + logbr() + log("Start " + game.active) + reset_road_limits() + game.activated = [] - let card = (game.active === CAESAR ? CARDS[game.c_card] : CARDS[game.p_card]); + let card = (game.active === CAESAR ? CARDS[game.c_card] : CARDS[game.p_card]) if (card.event) { switch (card.event) { // Apollo has already been handled in reveal_cards! case 'Jupiter': - game.state = 'jupiter'; - break; + game.state = 'jupiter' + break case 'Vulcan': - game.state = 'vulcan'; - break; + game.state = 'vulcan' + break case 'Mercury': - game.mercury = game.active; - game.moves = 1; - game.levies = 0; - game.amphibious_available = false; - game.state = 'move_who'; - game.turn_log = []; - break; + game.mercury = game.active + game.moves = 1 + game.levies = 0 + game.amphibious_available = false + game.state = 'move_who' + game.turn_log = [] + break case 'Pluto': - game.pluto = game.active; - game.moves = 1; - game.levies = 0; - game.amphibious_available = false; - game.state = 'move_who'; - game.turn_log = []; - break; + game.pluto = game.active + game.moves = 1 + game.levies = 0 + game.amphibious_available = false + game.state = 'move_who' + game.turn_log = [] + break case 'Mars': - game.mars = game.active; - game.moves = 1; - game.levies = 0; - game.amphibious_available = false; - game.state = 'move_who'; - game.turn_log = []; - break; + game.mars = game.active + game.moves = 1 + game.levies = 0 + game.amphibious_available = false + game.state = 'move_who' + game.turn_log = [] + break case 'Neptune': - game.neptune = game.active; - game.moves = 1; - game.levies = 0; - game.amphibious_available = false; - game.state = 'move_who'; - game.turn_log = []; - break; + game.neptune = game.active + game.moves = 1 + game.levies = 0 + game.amphibious_available = false + game.state = 'move_who' + game.turn_log = [] + break } } else { - game.moves = card.move; - game.levies = card.levy; - game.amphibious_available = true; - game.state = 'move_who'; - game.turn_log = []; + game.moves = card.move + game.levies = card.levy + game.amphibious_available = true + game.state = 'move_who' + game.turn_log = [] } - clear_undo(); + clear_undo() } function jupiter_block(b) { - let type = BLOCKS[b].type; + let type = BLOCKS[b].type if (type === 'navis' || type === 'leader') { - log("Jupiter reduced " + block_name(b) + "."); - reduce_block(b); - end_player_turn(); + log("Jupiter reduced " + block_name(b) + ".") + reduce_block(b) + end_player_turn() } else { - game.owner[b] = game.active; - game.who = b; - game.state = 'jupiter_to'; + game.owner[b] = game.active + game.who = b + game.state = 'jupiter_to' } } states.jupiter = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + "..."; - view.prompt = "Jupiter: Choose one enemy army adjacent to a friendly city."; + return view.prompt = "Waiting for " + game.active + "..." + view.prompt = "Jupiter: Choose one enemy army adjacent to a friendly city." for (let s in SPACES) { if (is_friendly_city(s)) { for (let to of SPACES[s].exits) if (is_enemy_city(to) || is_contested_city(to)) - gen_action(view, 'secret', to); + gen_action(view, 'secret', to) } } - gen_action_pass(view, "Pass"); + gen_action_pass(view, "Pass") }, space: function (where) { /* pick a random block */ - let list = []; + let list = [] for (let x in BLOCKS) if (game.location[x] === where) - list.push(x); - let i = random(list.length); - jupiter_block(list[i]); + list.push(x) + let i = random(list.length) + jupiter_block(list[i]) }, secret: function (args) { - let [where, owner] = args; + let [where, owner] = args /* pick a random block of the same color as the selected block */ if (owner === CLEOPATRA) { - jupiter_block(CLEOPATRA); + jupiter_block(CLEOPATRA) } else { - let list = []; + let list = [] for (let b in BLOCKS) if (game.location[b] === where && BLOCKS[b].owner === owner) - list.push(b); - let i = random(list.length); - jupiter_block(list[i]); + list.push(b) + let i = random(list.length) + jupiter_block(list[i]) } }, pass: function () { - end_player_turn(); + end_player_turn() }, } states.jupiter_to = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + "..."; - view.prompt = "Jupiter: Move " + block_name(game.who) + " to your city."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + "..." + view.prompt = "Jupiter: Move " + block_name(game.who) + " to your city." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (is_friendly_city(to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) }, space: function (to) { log(block_name(game.who) + " joined " + game.active + ":\n" + - game.location[game.who] + " \u2192 " + to + "."); - game.location[game.who] = to; - game.who = null; - end_player_turn(); + game.location[game.who] + " \u2192 " + to + ".") + game.location[game.who] = to + game.who = null + end_player_turn() }, } states.vulcan = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + "..."; - view.prompt = "Vulcan: Choose an enemy city to suffer a volcanic eruption."; + return view.prompt = "Waiting for " + game.active + "..." + view.prompt = "Vulcan: Choose an enemy city to suffer a volcanic eruption." for (let s in SPACES) if (is_enemy_city(s)) - gen_action(view, 'space', s); + gen_action(view, 'space', s) }, space: function (city) { - log("Vulcan struck " + city + "!"); + log("Vulcan struck " + city + "!") if (game.automatic_disruption) { for (let b in BLOCKS) if (game.location[b] === city) - reduce_block(b); + reduce_block(b) // uh-oh! cleopatra switched sides! if (is_contested_city(city)) - game.attacker[city] = game.active; - end_player_turn(); + game.attacker[city] = game.active + end_player_turn() } else { - game.where = city; - game.vulcan = []; + game.where = city + game.vulcan = [] for (let b in BLOCKS) if (game.location[b] === city) - game.vulcan.push(b); - game.active = enemy(game.active); - game.state = 'apply_vulcan'; + game.vulcan.push(b) + game.active = enemy(game.active) + game.state = 'apply_vulcan' } }, } @@ -1243,84 +1243,84 @@ states.vulcan = { states.apply_vulcan = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + "..."; - view.prompt = "Apply Vulcan hits in " + game.where + "."; + return view.prompt = "Waiting for " + game.active + "..." + view.prompt = "Apply Vulcan hits in " + game.where + "." for (let i = 0; i < game.vulcan.length; ++i) - gen_action(view, 'block', game.vulcan[i]); + gen_action(view, 'block', game.vulcan[i]) }, block: function (who) { - reduce_block(who); + reduce_block(who) // uh-oh! cleopatra switched sides! if (is_contested_city(game.where)) - game.attacker[game.where] = game.active; - remove_from_array(game.vulcan, who); + game.attacker[game.where] = game.active + remove_from_array(game.vulcan, who) if (game.vulcan.length === 0) { - delete game.vulcan; - game.where = null; - game.active = enemy(game.active); - end_player_turn(); + delete game.vulcan + game.where = null + game.active = enemy(game.active) + end_player_turn() } }, } function goto_mars_and_neptune() { - game.surprise_list = []; + game.surprise_list = [] for (let where in SPACES) if (is_map_space(where) && is_contested_space(where)) - game.surprise_list.push(where); + game.surprise_list.push(where) if (game.surprise_list.length === 0) { - delete game.surprise_list; - return end_player_turn(); + delete game.surprise_list + return end_player_turn() } if (game.surprise_list.length === 1) { - game.surprise = game.surprise_list[0]; - log("Surprise attack in " + game.surprise + "."); - delete game.surprise_list; - return end_player_turn(); + game.surprise = game.surprise_list[0] + log("Surprise attack in " + game.surprise + ".") + delete game.surprise_list + return end_player_turn() } - game.state = 'mars_and_neptune'; + game.state = 'mars_and_neptune' } states.mars_and_neptune = { prompt: function (view, current) { - let god = game.mars === game.active ? "Mars: " : "Neptune: "; + let god = game.mars === game.active ? "Mars: " : "Neptune: " if (is_inactive_player(current)) - return view.prompt = god + ": Waiting for " + game.active + "."; - view.prompt = god + "Select battle for surprise attack."; + return view.prompt = god + ": Waiting for " + game.active + "." + view.prompt = god + "Select battle for surprise attack." for (let space of game.surprise_list) - gen_action(view, 'space', space); + gen_action(view, 'space', space) }, space: function (where) { - game.surprise = where; - log("Surprise attack in " + game.surprise + "."); - delete game.surprise_list; - end_player_turn(); + game.surprise = where + log("Surprise attack in " + game.surprise + ".") + delete game.surprise_list + end_player_turn() }, } function is_amphibious_move(who, from, to) { if (BLOCKS[who].type === 'navis') - return false; - let e = edge_id(from, to); + return false + let e = edge_id(from, to) if (EDGES[e] === 'sea') - return true; - return false; + return true + return false } function move_or_attack(to) { - let from = game.location[game.who]; - move_to(game.who, from, to); + let from = game.location[game.who] + move_to(game.who, from, to) if (is_enemy_space(to) || is_contested_space(to)) { if (!game.attacker[to]) { - game.attacker[to] = game.active; - game.main_road[to] = from; - return ATTACK_MARK; + game.attacker[to] = game.active + game.main_road[to] = from + return ATTACK_MARK } else { if (game.attacker[to] !== game.active || game.main_road[to] !== from) { - game.reserves.push(game.who); - return RESERVE_MARK; + game.reserves.push(game.who) + return RESERVE_MARK } - return ATTACK_MARK; + return ATTACK_MARK } } return false; // not a combat move @@ -1329,56 +1329,56 @@ function move_or_attack(to) { states.move_who = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; + return view.prompt = "Waiting for " + game.active + " to move..." if (game.pluto === game.active) - view.prompt = "Pluto: Move one group. Road limits increase for attacks. No Navis movement."; + view.prompt = "Pluto: Move one group. Road limits increase for attacks. No Navis movement." else if (game.mars === game.active) - view.prompt = "Mars: Move one group. No Navis movement."; + view.prompt = "Mars: Move one group. No Navis movement." else if (game.neptune === game.active) - view.prompt = "Neptune: Move only the Navis in one group."; + view.prompt = "Neptune: Move only the Navis in one group." else if (game.mercury === game.active) - view.prompt = "Mercury: Move one group three cities, or two cities and attack. No Navis movement."; + view.prompt = "Mercury: Move one group three cities, or two cities and attack. No Navis movement." else if (game.amphibious_available) - view.prompt = "Choose an army to group or amphibious move. "+game.moves+"MP left."; + view.prompt = "Choose an army to group or amphibious move. "+game.moves+"MP left." else - view.prompt = "Choose an army to group move. "+game.moves+"MP left."; + view.prompt = "Choose an army to group move. "+game.moves+"MP left." if (game.moves === 0) { for (let b in BLOCKS) { - let from = game.location[b]; + let from = game.location[b] if (game.activated.includes(from)) if (can_block_move(b)) - gen_action(view, 'block', b); + gen_action(view, 'block', b) } } else { - let have_amphibious = false; + let have_amphibious = false for (let b in BLOCKS) { - let can_move = false; + let can_move = false if (game.amphibious_available && can_amphibious_move(b)) { - can_move = true; - have_amphibious = true; + can_move = true + have_amphibious = true } if (can_block_move(b)) - can_move = true; + can_move = true if (can_move) - gen_action(view, 'block', b); + gen_action(view, 'block', b) } if (!have_amphibious) - game.amphibious_available = false; + game.amphibious_available = false } - gen_action_pass(view, "End movement phase"); - gen_action_undo(view); + gen_action_pass(view, "End movement phase") + gen_action_undo(view) }, block: function (who) { - push_undo(); - game.who = who; + push_undo() + game.who = who if (game.mercury === game.active) - game.state = 'mercury_move_1'; + game.state = 'mercury_move_1' else - game.state = 'move_where'; + game.state = 'move_where' }, pass: function () { - push_undo(); - end_movement(); + push_undo() + end_movement() }, undo: pop_undo, } @@ -1386,54 +1386,54 @@ states.move_who = { states.move_where = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Move " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Move " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) { - let can_move_to = false; + let can_move_to = false if (game.amphibious_available && can_amphibious_move_to(game.who, from, to)) - can_move_to = true; + can_move_to = true if (can_block_move_to(game.who, to)) - can_move_to = true; + can_move_to = true if (can_move_to) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } gen_action(view, 'block', game.who); // for canceling move - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (is_amphibious_move(game.who, from, to)) { - game.moves --; - game.location[game.who] = to; - game.last_from = from; - log_move_start(from, to); - logp("amphibious moved."); + game.moves -- + game.location[game.who] = to + game.last_from = from + log_move_start(from, to) + logp("amphibious moved.") if (is_sea(to)) { - game.sea_moved[to] = true; - game.state = 'amphibious_move_to'; + game.sea_moved[to] = true + game.state = 'amphibious_move_to' } else { - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() } } else { if (!game.activated.includes(from)) { - logp("activated " + from + "."); - game.moves --; - game.activated.push(from); + logp("activated " + from + ".") + game.moves -- + game.activated.push(from) } - game.amphibious_available = false; - let mark = move_or_attack(to); - log_move_start(from, to, mark); + game.amphibious_available = false + let mark = move_or_attack(to) + log_move_start(from, to, mark) if (can_block_continue(game.who, game.last_from)) { - game.state = 'move_where_2'; + game.state = 'move_where_2' } else { - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() } } }, @@ -1444,25 +1444,25 @@ states.move_where = { states.move_where_2 = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Move " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Move " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (to !== game.last_from && can_block_continue_to(game.who, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) gen_action(view, 'space', from); // For ending move early. - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (to !== from) { - log_move_continue(to); - move_to(game.who, from, to); + log_move_continue(to) + move_to(game.who, from, to) } - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() }, undo: pop_undo, } @@ -1470,27 +1470,27 @@ states.move_where_2 = { states.amphibious_move_to = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Move " + block_name(game.who) + " to a friendly sea or port."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Move " + block_name(game.who) + " to a friendly sea or port." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (to !== game.last_from && can_amphibious_move_to(game.who, from, to)) - gen_action(view, 'space', to); - gen_action_undo(view); + gen_action(view, 'space', to) + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; - game.last_from = from; - game.location[game.who] = to; - log_move_continue(to); + let from = game.location[game.who] + game.last_from = from + game.location[game.who] = to + log_move_continue(to) if (is_sea(to)) { - game.sea_moved[to] = true; - game.state = 'amphibious_move_to'; + game.sea_moved[to] = true + game.state = 'amphibious_move_to' } else { - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() } }, undo: pop_undo, @@ -1499,29 +1499,29 @@ states.amphibious_move_to = { states.mercury_move_1 = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Mercury: Move " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Mercury: Move " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (can_block_move_to(game.who, to)) - gen_action(view, 'space', to); - gen_action_undo(view); + gen_action(view, 'space', to) + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (!game.activated.includes(from)) { - logp("activated " + from + "."); - game.moves --; - game.activated.push(from); + logp("activated " + from + ".") + game.moves -- + game.activated.push(from) } - let mark = move_or_attack(to); - log_move_start(from, to, mark); + let mark = move_or_attack(to) + log_move_start(from, to, mark) if (!is_contested_space(to) && can_block_move(game.who)) { - game.state = 'mercury_move_2'; + game.state = 'mercury_move_2' } else { - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.who = null + game.state = 'move_who' + log_move_end() } }, undo: pop_undo, @@ -1530,33 +1530,33 @@ states.mercury_move_1 = { states.mercury_move_2 = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Mercury: Move " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Mercury: Move " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (to !== game.last_from && can_block_move_to(game.who, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) gen_action(view, 'space', from); // For ending move early. - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (to !== from) { - let mark = move_or_attack(to); - log_move_continue(to, mark); + let mark = move_or_attack(to) + log_move_continue(to, mark) if (can_block_continue(game.who, game.last_from)) { - game.state = 'mercury_move_3'; + game.state = 'mercury_move_3' } else { - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() } } else { - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() } }, undo: pop_undo, @@ -1565,84 +1565,84 @@ states.mercury_move_2 = { states.mercury_move_3 = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move..."; - view.prompt = "Mercury: Move " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move..." + view.prompt = "Mercury: Move " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) if (to !== game.last_from && can_block_continue_to(game.who, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) gen_action(view, 'space', from); // For ending move early. - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (to !== from) { - log_move_continue(to); - move_to(game.who, from, to); + log_move_continue(to) + move_to(game.who, from, to) } - game.moved[game.who] = true; - game.who = null; - game.state = 'move_who'; - log_move_end(); + game.moved[game.who] = true + game.who = null + game.state = 'move_who' + log_move_end() }, undo: pop_undo, } function end_movement() { - print_turn_log("moved"); + print_turn_log("moved") if (game.mars === game.active || game.neptune === game.active) - return goto_mars_and_neptune(); + return goto_mars_and_neptune() if (game.pluto === game.active || game.mercury === game.active) - return end_player_turn(); + return end_player_turn() - game.who = null; - game.moves = 0; - game.state = 'levy'; - game.turn_log = []; + game.who = null + game.moves = 0 + game.state = 'levy' + game.turn_log = [] } states.levy = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to levy..."; - view.prompt = "Choose an army to levy. "+game.levies+"LP left."; - let is_levy_possible = false; + return view.prompt = "Waiting for " + game.active + " to levy..." + view.prompt = "Choose an army to levy. "+game.levies+"LP left." + let is_levy_possible = false if (game.levies > 0) { for (let b in BLOCKS) { if (can_levy(b)) { - gen_action(view, 'block', b); - is_levy_possible = true; + gen_action(view, 'block', b) + is_levy_possible = true } } } if (!is_levy_possible) - gen_action_pass(view, "End levy phase"); - gen_action_undo(view); + gen_action_pass(view, "End levy phase") + gen_action_undo(view) }, block: function (who) { - push_undo(); + push_undo() if (game.location[who] === LEVY) { if (BLOCKS[who].levy) { - let to = BLOCKS[who].levy; - log_levy(to); - game.levies --; - game.steps[who] = 1; - game.location[who] = to; + let to = BLOCKS[who].levy + log_levy(to) + game.levies -- + game.steps[who] = 1 + game.location[who] = to } else { - game.who = who; - game.state = 'levy_where'; + game.who = who + game.state = 'levy_where' } } else { - log_levy(game.location[who]); - game.levies --; - game.steps[who]++; - game.state = 'levy'; + log_levy(game.location[who]) + game.levies -- + game.steps[who]++ + game.state = 'levy' } }, pass: function () { - end_player_turn(); + end_player_turn() }, undo: pop_undo, } @@ -1650,164 +1650,164 @@ states.levy = { states.levy_where = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to levy..."; - view.prompt = "Choose a friendly city to levy " + block_name(game.who) + " in."; + return view.prompt = "Waiting for " + game.active + " to levy..." + view.prompt = "Choose a friendly city to levy " + block_name(game.who) + " in." for (let to in SPACES) if (can_levy_to(game.who, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) gen_action(view, 'block', game.who); // for canceling levy - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - log_levy(to); - game.levies --; - game.steps[game.who] = 1; - game.location[game.who] = to; - game.who = null; - game.state = 'levy'; + log_levy(to) + game.levies -- + game.steps[game.who] = 1 + game.location[game.who] = to + game.who = null + game.state = 'levy' }, block: pop_undo, undo: pop_undo, } function end_player_turn() { - clear_undo(); + clear_undo() if (game.turn_log) - print_turn_log("levied"); + print_turn_log("levied") if (game.active === game.p1) { - game.active = game.p2; - start_player_turn(); + game.active = game.p2 + start_player_turn() } else { - goto_pick_battle(); + goto_pick_battle() } } function goto_pick_battle() { - game.active = game.p1; + game.active = game.p1 if (have_contested_spaces()) - game.state = 'pick_battle'; + game.state = 'pick_battle' else - end_turn(); + end_turn() } states.pick_battle = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to pick a battle..."; - view.prompt = "Choose the next battle to fight!"; + return view.prompt = "Waiting for " + game.active + " to pick a battle..." + view.prompt = "Choose the next battle to fight!" for (let s in SPACES) if (is_contested_city(s) || is_contested_sea(s)) - gen_action(view, 'space', s); + gen_action(view, 'space', s) }, space: function (where) { - game.where = where; - start_battle(); + game.where = where + start_battle() }, } function is_attacker(b) { if (game.location[b] === game.where && block_owner(b) === game.attacker[game.where]) - return !game.reserves.includes(b); - return false; + return !game.reserves.includes(b) + return false } function is_defender(b) { if (game.location[b] === game.where && block_owner(b) !== game.attacker[game.where]) - return !game.reserves.includes(b); - return false; + return !game.reserves.includes(b) + return false } function count_attackers() { - let count = 0; + let count = 0 for (let b in BLOCKS) { if (is_attacker(b)) - ++count; + ++count } - return count; + return count } function count_defenders() { - let count = 0; + let count = 0 for (let b in BLOCKS) { if (is_defender(b)) - ++count; + ++count } - return count; + return count } function start_battle() { - game.battle_round = 0; - game.flash = ""; - logbr(); - log("Battle in " + game.where); + game.battle_round = 0 + game.flash = "" + logbr() + log("Battle in " + game.where) if (game.surprise === game.where) - log("Surprise attack."); - game.state = 'battle_round'; - start_battle_round(); + log("Surprise attack.") + game.state = 'battle_round' + start_battle_round() } function resume_battle() { - game.who = null; - game.state = 'battle_round'; - pump_battle_round(); + game.who = null + game.state = 'battle_round' + pump_battle_round() } function bring_on_reserves() { for (let b in BLOCKS) { if (game.location[b] === game.where) { - remove_from_array(game.reserves, b); + remove_from_array(game.reserves, b) } } } function goto_disrupt_reserves() { - game.flash = "Reserves were disrupted."; + game.flash = "Reserves were disrupted." if (game.automatic_disruption) { for (let b in BLOCKS) if (game.location[b] === game.where && block_owner(b) === game.attacker[game.where]) if (game.reserves.includes(b)) - reduce_block(b); - end_disrupt_reserves(); + reduce_block(b) + end_disrupt_reserves() } else { - game.disrupted = []; + game.disrupted = [] for (let b in BLOCKS) if (game.location[b] === game.where && block_owner(b) === game.attacker[game.where]) if (game.reserves.includes(b)) - game.disrupted.push(b); - game.active = game.attacker[game.where]; - game.state = 'disrupt_reserves'; + game.disrupted.push(b) + game.active = game.attacker[game.where] + game.state = 'disrupt_reserves' } } function disrupt_block(who) { - game.flash = "Reserves were disrupted."; - reduce_block(who); - remove_from_array(game.disrupted, who); + game.flash = "Reserves were disrupted." + reduce_block(who) + remove_from_array(game.disrupted, who) if (game.disrupted.length === 0) - end_disrupt_reserves(); + end_disrupt_reserves() } function end_disrupt_reserves() { game.state = 'battle_round' - game.flash = ""; - delete game.disrupted; - bring_on_reserves(); - log("~ Battle Round " + game.battle_round + " ~"); - pump_battle_round(); + game.flash = "" + delete game.disrupted + bring_on_reserves() + log("~ Battle Round " + game.battle_round + " ~") + pump_battle_round() } states.disrupt_reserves = { show_battle: true, prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to apply disruption hits..."; + return view.prompt = "Waiting for " + game.active + " to apply disruption hits..." view.prompt = "Apply disruption hits to reserves." for (let b of game.disrupted) { - gen_action(view, 'battle_hit', b); - gen_action(view, 'block', b); - gen_action(view, 'block', b); + gen_action(view, 'battle_hit', b) + gen_action(view, 'block', b) + gen_action(view, 'block', b) } }, block: disrupt_block, @@ -1817,144 +1817,144 @@ states.disrupt_reserves = { function start_battle_round() { if (++game.battle_round <= 4) { if (game.turn_log && game.turn_log.length > 0) - print_turn_log_no_active("Retreated from " + game.where + ":"); - game.turn_log = []; + print_turn_log_no_active("Retreated from " + game.where + ":") + game.turn_log = [] - reset_road_limits(); - game.moved = {}; + reset_road_limits() + game.moved = {} if (game.battle_round === 2) { if (game.surprise === game.where) - game.surprise = 0; + game.surprise = 0 if (count_defenders() === 0) { - log("Defending main force was eliminated."); - log("The attacker is now the defender."); - log("Reserves were disrupted."); - game.attacker[game.where] = enemy(game.attacker[game.where]); - return goto_disrupt_reserves(); + log("Defending main force was eliminated.") + log("The attacker is now the defender.") + log("Reserves were disrupted.") + game.attacker[game.where] = enemy(game.attacker[game.where]) + return goto_disrupt_reserves() } else if (count_attackers() === 0) { - log("Attacking main force was eliminated."); - log("Reserves were disrupted."); - return goto_disrupt_reserves(); + log("Attacking main force was eliminated.") + log("Reserves were disrupted.") + return goto_disrupt_reserves() } - bring_on_reserves(); + bring_on_reserves() } - log("~ Battle Round " + game.battle_round + " ~"); + log("~ Battle Round " + game.battle_round + " ~") - pump_battle_round(); + pump_battle_round() } else { - end_battle(); + end_battle() } } function pump_battle_round() { function filter_battle_blocks(ci, is_candidate) { - let output = null; + let output = null for (let b in BLOCKS) { if (is_candidate(b) && !game.moved[b]) { if (block_initiative(b) === ci) { if (!output) - output = []; - output.push(b); + output = [] + output.push(b) } } } - return output; + return output } function battle_step(active, initiative, candidate) { - game.battle_list = filter_battle_blocks(initiative, candidate); + game.battle_list = filter_battle_blocks(initiative, candidate) if (game.battle_list) { - game.active = active; - return true; + game.active = active + return true } - return false; + return false } if (is_friendly_space(game.where) || is_enemy_space(game.where)) { - end_battle(); + end_battle() } else if (count_attackers() === 0 || count_defenders() === 0) { - start_battle_round(); + start_battle_round() } else { - let attacker = game.attacker[game.where]; - let defender = enemy(attacker); + let attacker = game.attacker[game.where] + let defender = enemy(attacker) if (game.surprise === game.where) { - if (battle_step(attacker, 'A', is_attacker)) return; - if (battle_step(attacker, 'B', is_attacker)) return; - if (battle_step(attacker, 'C', is_attacker)) return; - if (battle_step(attacker, 'D', is_attacker)) return; - if (battle_step(defender, 'A', is_defender)) return; - if (battle_step(defender, 'B', is_defender)) return; - if (battle_step(defender, 'C', is_defender)) return; - if (battle_step(defender, 'D', is_defender)) return; + if (battle_step(attacker, 'A', is_attacker)) return + if (battle_step(attacker, 'B', is_attacker)) return + if (battle_step(attacker, 'C', is_attacker)) return + if (battle_step(attacker, 'D', is_attacker)) return + if (battle_step(defender, 'A', is_defender)) return + if (battle_step(defender, 'B', is_defender)) return + if (battle_step(defender, 'C', is_defender)) return + if (battle_step(defender, 'D', is_defender)) return } else { - if (battle_step(defender, 'A', is_defender)) return; - if (battle_step(attacker, 'A', is_attacker)) return; - if (battle_step(defender, 'B', is_defender)) return; - if (battle_step(attacker, 'B', is_attacker)) return; - if (battle_step(defender, 'C', is_defender)) return; - if (battle_step(attacker, 'C', is_attacker)) return; - if (battle_step(defender, 'D', is_defender)) return; - if (battle_step(attacker, 'D', is_attacker)) return; + if (battle_step(defender, 'A', is_defender)) return + if (battle_step(attacker, 'A', is_attacker)) return + if (battle_step(defender, 'B', is_defender)) return + if (battle_step(attacker, 'B', is_attacker)) return + if (battle_step(defender, 'C', is_defender)) return + if (battle_step(attacker, 'C', is_attacker)) return + if (battle_step(defender, 'D', is_defender)) return + if (battle_step(attacker, 'D', is_attacker)) return } - start_battle_round(); + start_battle_round() } } function end_battle() { if (game.turn_log && game.turn_log.length > 0) - print_turn_log_no_active("Retreated from " + game.where + ":"); + print_turn_log_no_active("Retreated from " + game.where + ":") if (game.surprise === game.where) - game.surprise = 0; - game.flash = ""; - game.battle_round = 0; - reset_road_limits(); - game.moved = {}; - goto_regroup(); + game.surprise = 0 + game.flash = "" + game.battle_round = 0 + reset_road_limits() + game.moved = {} + goto_regroup() } function can_fire_with_block(b) { if (is_attacker(b)) - return game.battle_round < 4; + return game.battle_round < 4 if (is_defender(b)) - return true; - return false; + return true + return false } function fire_with_block(b) { - game.moved[b] = true; - game.hits = 0; - let strength = block_strength(b); - let fire = block_fire_power(b); - let name = block_name(b) + " " + block_initiative(b) + fire; - let rolls = []; + game.moved[b] = true + game.hits = 0 + let strength = block_strength(b) + let fire = block_fire_power(b) + let name = block_name(b) + " " + block_initiative(b) + fire + let rolls = [] for (let i = 0; i < strength; ++i) { - let die = roll_d6(); + let die = roll_d6() if (die <= fire) { - rolls.push(DIE_HIT[die]); - ++game.hits; + rolls.push(DIE_HIT[die]) + ++game.hits } else { - rolls.push(DIE_MISS[die]); + rolls.push(DIE_MISS[die]) } } - game.flash = name + " fired " + rolls.join(" ") + " "; + game.flash = name + " fired " + rolls.join(" ") + " " if (game.hits === 0) - game.flash += "and missed."; + game.flash += "and missed." else if (game.hits === 1) - game.flash += "and scored 1 hit."; + game.flash += "and scored 1 hit." else - game.flash += "and scored " + game.hits + " hits."; + game.flash += "and scored " + game.hits + " hits." - log_battle(name + " fired " + rolls.join("") + "."); + log_battle(name + " fired " + rolls.join("") + ".") if (game.hits > 0) { - game.active = enemy(game.active); - goto_battle_hits(); + game.active = enemy(game.active) + goto_battle_hits() } else { - resume_battle(); + resume_battle() } } @@ -1962,126 +1962,126 @@ function can_retreat_with_block(who) { if (game.location[who] === game.where) { if (game.battle_round > 1) { if (block_owner(who) === game.attacker[game.where]) - return can_attacker_retreat(who); + return can_attacker_retreat(who) else - return can_defender_retreat(who); + return can_defender_retreat(who) } } - return false; + return false } function must_retreat_with_block(who) { if (game.location[who] === game.where) if (game.battle_round === 4) - return (block_owner(who) === game.attacker[game.where]); - return false; + return (block_owner(who) === game.attacker[game.where]) + return false } function retreat_with_block(who) { if (can_retreat_with_block(who)) { - game.who = who; - game.state = 'retreat'; + game.who = who + game.state = 'retreat' } else { - eliminate_block(who); - resume_battle(); + eliminate_block(who) + resume_battle() } } function pass_with_block(who) { - game.flash = block_name(who) + " passed."; - log_battle(block_name(who) + " passed."); - game.moved[who] = true; - resume_battle(); + game.flash = block_name(who) + " passed." + log_battle(block_name(who) + " passed.") + game.moved[who] = true + resume_battle() } states.battle_round = { show_battle: true, prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to choose a combat action..."; - let can_fire = false; - let can_retreat = false; - let must_retreat = false; - let can_pass = false; + return view.prompt = "Waiting for " + game.active + " to choose a combat action..." + let can_fire = false + let can_retreat = false + let must_retreat = false + let can_pass = false if (game.active === game.attacker[game.where]) { - if (game.battle_round < 4) can_fire = true; - if (game.battle_round > 1) can_retreat = true; - if (game.battle_round < 4) can_pass = true; - if (game.battle_round === 4) must_retreat = true; + if (game.battle_round < 4) can_fire = true + if (game.battle_round > 1) can_retreat = true + if (game.battle_round < 4) can_pass = true + if (game.battle_round === 4) must_retreat = true } else { - can_fire = true; - if (game.battle_round > 1) can_retreat = true; - can_pass = true; + can_fire = true + if (game.battle_round > 1) can_retreat = true + can_pass = true } if (can_fire && can_retreat) - view.prompt = "Fire, retreat, or pass with an army."; + view.prompt = "Fire, retreat, or pass with an army." else if (can_fire) - view.prompt = "Fire or pass with an army."; + view.prompt = "Fire or pass with an army." else - view.prompt = "Retreat with an army."; + view.prompt = "Retreat with an army." for (let b of game.battle_list) { - if (can_fire) gen_action(view, 'battle_fire', b); + if (can_fire) gen_action(view, 'battle_fire', b) if (must_retreat || (can_retreat && can_retreat_with_block(b))) - gen_action(view, 'battle_retreat', b); - if (can_pass) gen_action(view, 'battle_pass', b); - gen_action(view, 'block', b); + gen_action(view, 'battle_retreat', b) + if (can_pass) gen_action(view, 'battle_pass', b) + gen_action(view, 'block', b) } }, block: function (who) { if (can_fire_with_block(who)) - fire_with_block(who); + fire_with_block(who) else if (can_retreat_with_block(who)) - retreat_with_block(who); + retreat_with_block(who) else if (must_retreat_with_block(who)) - retreat_with_block(who); + retreat_with_block(who) else - pass_with_block(who); + pass_with_block(who) }, battle_fire: function (who) { - fire_with_block(who); + fire_with_block(who) }, battle_retreat: function (who) { - retreat_with_block(who); + retreat_with_block(who) }, battle_pass: function (who) { - pass_with_block(who); + pass_with_block(who) }, } function goto_battle_hits() { - game.battle_list = list_victims(game.active); + game.battle_list = list_victims(game.active) if (game.battle_list.length === 0) - resume_battle(); + resume_battle() else - game.state = 'battle_hits'; + game.state = 'battle_hits' } function list_victims(p) { - let is_candidate = (p === game.attacker[game.where]) ? is_attacker : is_defender; - let max = 0; + let is_candidate = (p === game.attacker[game.where]) ? is_attacker : is_defender + let max = 0 for (let b in BLOCKS) if (is_candidate(b) && block_strength(b) > max) - max = block_strength(b); - let list = []; + max = block_strength(b) + let list = [] for (let b in BLOCKS) if (is_candidate(b) && block_strength(b) === max) - list.push(b); - return list; + list.push(b) + return list } function apply_hit(who) { - game.flash = block_name(who) + " took a hit."; - log_battle(block_name(who) + " took a hit."); - reduce_block(who); - game.hits--; + game.flash = block_name(who) + " took a hit." + log_battle(block_name(who) + " took a hit.") + reduce_block(who) + game.hits-- if (game.hits === 0) - resume_battle(); + resume_battle() else { - game.battle_list = list_victims(game.active); + game.battle_list = list_victims(game.active) if (game.battle_list.length === 0) - resume_battle(); + resume_battle() else - game.flash += " " + game.hits + (game.hits === 1 ? " hit left." : " hits left."); + game.flash += " " + game.hits + (game.hits === 1 ? " hit left." : " hits left.") } } @@ -2089,18 +2089,18 @@ states.battle_hits = { show_battle: true, prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to apply hits..."; - view.prompt = "Assign " + game.hits + (game.hits !== 1 ? " hits" : " hit") + " to your armies."; + return view.prompt = "Waiting for " + game.active + " to apply hits..." + view.prompt = "Assign " + game.hits + (game.hits !== 1 ? " hits" : " hit") + " to your armies." for (let b of game.battle_list) { - gen_action(view, 'battle_hit', b); - gen_action(view, 'block', b); + gen_action(view, 'battle_hit', b) + gen_action(view, 'block', b) } }, block: function (who) { - apply_hit(who); + apply_hit(who) }, battle_hit: function (who) { - apply_hit(who); + apply_hit(who) }, } @@ -2108,42 +2108,42 @@ states.retreat = { show_battle: false, prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to retreat..."; - view.prompt = "Retreat " + block_name(game.who) + "."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to retreat..." + view.prompt = "Retreat " + block_name(game.who) + "." + let from = game.location[game.who] for (let to of SPACES[from].exits) { if (block_owner(game.who) === game.attacker[from]) { if (can_attacker_retreat_to(game.who, from, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } else { if (can_defender_retreat_to(game.who, from, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } } - gen_action(view, 'undo'); - gen_action(view, 'block', game.who); + gen_action(view, 'undo') + gen_action(view, 'block', game.who) }, space: function (to) { - let from = game.location[game.who]; + let from = game.location[game.who] if (is_sea(to) && !is_navis(game.who)) { - push_undo(); - move_to(game.who, from, to); - game.sea_retreated = true; - game.state = 'sea_retreat'; + push_undo() + move_to(game.who, from, to) + game.sea_retreated = true + game.state = 'sea_retreat' } else { - move_to(game.who, from, to); - game.flash = block_name(game.who) + " retreated."; - log_battle(game.flash); - game.turn_log.push([game.active, to]); - game.moved[game.who] = true; - resume_battle(); + move_to(game.who, from, to) + game.flash = block_name(game.who) + " retreated." + log_battle(game.flash) + game.turn_log.push([game.active, to]) + game.moved[game.who] = true + resume_battle() } }, block: function () { - resume_battle(); + resume_battle() }, undo: function () { - resume_battle(); + resume_battle() }, } @@ -2151,62 +2151,62 @@ states.sea_retreat = { show_battle: false, prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to retreat..."; - view.prompt = "Retreat " + block_name(game.who) + " to a friendly port."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to retreat..." + view.prompt = "Retreat " + block_name(game.who) + " to a friendly port." + let from = game.location[game.who] for (let to of SPACES[from].exits) { if (is_friendly_city(to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } - gen_action(view, 'undo'); + gen_action(view, 'undo') }, space: function (to) { - clear_undo(); - let from = game.location[game.who]; - game.flash = block_name(game.who) + " retreated."; - log_battle(game.flash); - game.turn_log.push([game.active, from, to]); - move_to(game.who, from, to); - game.moved[game.who] = true; - resume_battle(); + clear_undo() + let from = game.location[game.who] + game.flash = block_name(game.who) + " retreated." + log_battle(game.flash) + game.turn_log.push([game.active, from, to]) + move_to(game.who, from, to) + game.moved[game.who] = true + resume_battle() }, undo: pop_undo, } function goto_regroup() { - game.active = game.attacker[game.where]; + game.active = game.attacker[game.where] if (is_enemy_space(game.where)) - game.active = enemy(game.active); - log(game.active + " won the battle in " + game.where + "!"); - game.state = 'regroup'; - game.turn_log = []; - clear_undo(); + game.active = enemy(game.active) + log(game.active + " won the battle in " + game.where + "!") + game.state = 'regroup' + game.turn_log = [] + clear_undo() } states.regroup = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to regroup..."; - view.prompt = "Regroup: Choose an army to move."; + return view.prompt = "Waiting for " + game.active + " to regroup..." + view.prompt = "Regroup: Choose an army to move." for (let b in BLOCKS) { if (game.location[b] === game.where) { if (can_regroup(b)) - gen_action(view, 'block', b); + gen_action(view, 'block', b) } } - gen_action_pass(view, "End regroup"); - gen_action_undo(view); + gen_action_pass(view, "End regroup") + gen_action_undo(view) }, block: function (who) { - push_undo(); - game.who = who; - game.state = 'regroup_to'; + push_undo() + game.who = who + game.state = 'regroup_to' }, pass: function () { - print_turn_log("regrouped"); - clear_undo(); - game.where = null; - goto_pick_battle(); + print_turn_log("regrouped") + clear_undo() + game.where = null + goto_pick_battle() }, undo: pop_undo, } @@ -2214,145 +2214,145 @@ states.regroup = { states.regroup_to = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to regroup..."; - view.prompt = "Regroup: Move " + block_name(game.who) + " to a friendly or vacant location."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to regroup..." + view.prompt = "Regroup: Move " + block_name(game.who) + " to a friendly or vacant location." + let from = game.location[game.who] for (let to of SPACES[from].exits) { if (can_regroup_to(game.who, from, to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } gen_action(view, 'block', game.who); // for canceling move - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; - game.turn_log.push([from, to]); - move_to(game.who, from, to); - game.who = null; - game.state = 'regroup'; + let from = game.location[game.who] + game.turn_log.push([from, to]) + move_to(game.who, from, to) + game.who = null + game.state = 'regroup' }, block: pop_undo, undo: pop_undo, } function end_turn() { - game.moved = {}; + game.moved = {} if (game.turn === 5) { - cleopatra_goes_home(); - check_victory(); + cleopatra_goes_home() + check_victory() } else { - game.turn ++; - start_turn(); + game.turn ++ + start_turn() } } function cleopatra_goes_home() { - game.active = CAESAR; + game.active = CAESAR if (game.location[CLEOPATRA] !== ALEXANDRIA) - log("Cleopatra went home to Alexandria."); + log("Cleopatra went home to Alexandria.") if (is_friendly_space(ALEXANDRIA)) - game.owner[CLEOPATRA] = CAESAR; + game.owner[CLEOPATRA] = CAESAR else - game.owner[CLEOPATRA] = POMPEIUS; - game.location[CLEOPATRA] = ALEXANDRIA; + game.owner[CLEOPATRA] = POMPEIUS + game.location[CLEOPATRA] = ALEXANDRIA } function check_victory() { - count_vp(); + count_vp() if (game.c_vp >= 10) { - game.result = CAESAR; - game.active = null; - game.state = 'game_over'; - game.victory = "Caesar won an early victory."; - logbr(); - log(game.victory); + game.result = CAESAR + game.active = null + game.state = 'game_over' + game.victory = "Caesar won an early victory." + logbr() + log(game.victory) } else if (game.p_vp >= 10) { - game.victory = "Pompeius won an early victory."; - game.result = POMPEIUS; - game.active = null; - game.state = 'game_over'; - logbr(); - log(game.victory); + game.victory = "Pompeius won an early victory." + game.result = POMPEIUS + game.active = null + game.state = 'game_over' + logbr() + log(game.victory) } else { if (game.year === 709) { - end_game(); + end_game() } else { - logbr(); - log("Start Winter Turn of Year " + game.year); - logbr(); - start_navis_to_port(); + logbr() + log("Start Winter Turn of Year " + game.year) + logbr() + start_navis_to_port() } } } function count_navis_to_port() { - let count = 0; + let count = 0 for (let b in BLOCKS) { if (block_owner(b) === game.active && BLOCKS[b].type === 'navis') if (SPACES[game.location[b]].type === 'sea') if (can_navis_move_to_port(b)) - ++count; + ++count } - return count; + return count } function start_navis_to_port() { - game.active = CAESAR; - let count = count_navis_to_port(); + game.active = CAESAR + let count = count_navis_to_port() if (count > 0) { - game.state = 'navis_to_port'; - game.turn_log = []; - clear_undo(); + game.state = 'navis_to_port' + game.turn_log = [] + clear_undo() } else { - next_navis_to_port(); + next_navis_to_port() } } function next_navis_to_port() { if (game.active === CAESAR) { - game.active = POMPEIUS; - let count = count_navis_to_port(); + game.active = POMPEIUS + let count = count_navis_to_port() if (count > 0) { - game.state = 'navis_to_port'; - game.turn_log = []; - clear_undo(); - return; + game.state = 'navis_to_port' + game.turn_log = [] + clear_undo() + return } } - clear_undo(); - winter_supply(); + clear_undo() + winter_supply() } states.navis_to_port = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move navis to port..."; - view.prompt = "Move all Navis to a friendly port."; - let count = 0; + return view.prompt = "Waiting for " + game.active + " to move navis to port..." + view.prompt = "Move all Navis to a friendly port." + let count = 0 for (let b in BLOCKS) { if (block_owner(b) === game.active && BLOCKS[b].type === 'navis') { if (SPACES[game.location[b]].type === 'sea') { if (can_navis_move_to_port(b)) { - gen_action(view, 'block', b); - ++count; + gen_action(view, 'block', b) + ++count } } } } if (count > 0) - view.prompt += " " + count + " left."; + view.prompt += " " + count + " left." if (count === 0) - gen_action_pass(view, "End navis to port"); - gen_action_undo(view); + gen_action_pass(view, "End navis to port") + gen_action_undo(view) }, block: function (who) { - push_undo(); - game.who = who; - game.state = 'navis_to_port_where'; + push_undo() + game.who = who + game.state = 'navis_to_port_where' }, pass: function () { - print_turn_log("moved to port"); - next_navis_to_port(); + print_turn_log("moved to port") + next_navis_to_port() }, undo: pop_undo, } @@ -2360,126 +2360,126 @@ states.navis_to_port = { states.navis_to_port_where = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to move navis to port..."; - view.prompt = "Move " + block_name(game.who) + " to a friendly port."; - let from = game.location[game.who]; + return view.prompt = "Waiting for " + game.active + " to move navis to port..." + view.prompt = "Move " + block_name(game.who) + " to a friendly port." + let from = game.location[game.who] for (let to of SPACES[from].exits) { if (is_friendly_city(to)) - gen_action(view, 'space', to); + gen_action(view, 'space', to) } gen_action(view, 'block', game.who); // for canceling move - gen_action_undo(view); + gen_action_undo(view) }, space: function (to) { - let from = game.location[game.who]; - game.turn_log.push([from, to]); - game.location[game.who] = to; - game.who = null; - game.state = 'navis_to_port'; + let from = game.location[game.who] + game.turn_log.push([from, to]) + game.location[game.who] = to + game.who = null + game.state = 'navis_to_port' }, block: pop_undo, undo: pop_undo, } function winter_supply() { - game.active = CAESAR; - game.state = 'disband'; - game.turn_log = []; - clear_undo(); + game.active = CAESAR + game.state = 'disband' + game.turn_log = [] + clear_undo() } states.disband = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = "Waiting for " + game.active + " to disband..."; - let okay_to_end = true; + return view.prompt = "Waiting for " + game.active + " to disband..." + let okay_to_end = true for (let b in BLOCKS) { if (block_owner(b) === game.active && is_map_space(game.location[b]) && b !== CLEOPATRA) { if (is_over_supply_limit(game.location[b])) { - okay_to_end = false; - gen_action(view, 'block', b); + okay_to_end = false + gen_action(view, 'block', b) } } } if (!okay_to_end) { - view.prompt = "Disband armies in excess of supply."; + view.prompt = "Disband armies in excess of supply." } else { - view.prompt = "You may disband armies to your levy pool."; + view.prompt = "You may disband armies to your levy pool." for (let b in BLOCKS) { if (is_map_space(game.location[b])) if (block_owner(b) === game.active && b !== CLEOPATRA) - gen_action(view, 'block', b); + gen_action(view, 'block', b) } - gen_action_pass(view, "End disbanding"); + gen_action_pass(view, "End disbanding") } - gen_action_undo(view); + gen_action_undo(view) }, block: function (who) { - push_undo(); - game.turn_log.push([game.location[who]]); - disband_block(who); + push_undo() + game.turn_log.push([game.location[who]]) + disband_block(who) }, pass: function () { - print_turn_log("disbanded"); + print_turn_log("disbanded") if (game.active === CAESAR) { - game.turn_log = []; - game.active = POMPEIUS; - clear_undo(); + game.turn_log = [] + game.active = POMPEIUS + clear_undo() } else { - clear_undo(); - end_year(); + clear_undo() + end_year() } }, undo: pop_undo, } function end_year() { - game.year ++; + game.year ++ for (let b in BLOCKS) { if (game.location[b] === DEAD && BLOCKS[b].type !== 'leader') { - disband_block(b); + disband_block(b) } } - start_year(); + start_year() } function end_game() { - count_vp(); + count_vp() if (game.c_vp > game.p_vp) { - game.result = CAESAR; + game.result = CAESAR } else if (game.c_vp < game.p_vp) { - game.result = POMPEIUS; + game.result = POMPEIUS } else { - game.active = CAESAR; + game.active = CAESAR if (is_friendly_space(ROMA)) - game.result = CAESAR; + game.result = CAESAR else if (is_enemy_space(ROMA)) - game.result = POMPEIUS; + game.result = POMPEIUS else - game.result = null; + game.result = null } if (game.result === CAESAR) - game.victory = "Caesar won!"; + game.victory = "Caesar won!" else if (game.result === POMPEIUS) - game.victory = "Pompeius won!"; + game.victory = "Pompeius won!" else - game.victory = "The game ended in a draw."; - game.active = null; - game.state = 'game_over'; - logbr(); - log(game.victory); + game.victory = "The game ended in a draw." + game.active = null + game.state = 'game_over' + logbr() + log(game.victory) } states.game_over = { prompt: function (view) { - return view.prompt = game.victory; + return view.prompt = game.victory }, } exports.ready = function (scenario, options, players) { - return players.length === 2; + return players.length === 2 } exports.setup = function (seed, scenario, options) { @@ -2504,143 +2504,143 @@ exports.setup = function (seed, scenario, options) { main_road: {}, reserves: [], log: [], - }; + } if (options.tournament) { - log("Caesar goes first on the first turn regardless of the cards played."); - game.tournament = 1; + log("Tournament rule:\nCaesar is the first player on the very first turn of the game.") + game.tournament = 1 } if (options.max_2_events) { - log("At most 2 events per hand."); - game.max_2_events = 1; + log("At most 2 events per hand.") + game.max_2_events = 1 } - game.removed = []; + game.removed = [] if (options.remove_apollo || options.remove_all_events) { - log("Apollo removed from deck."); - game.removed.push(APOLLO); + log("Apollo removed from deck.") + game.removed.push(APOLLO) } if (options.remove_jupiter || options.remove_all_events) { - log("Jupiter removed from deck."); - game.removed.push(JUPITER); + log("Jupiter removed from deck.") + game.removed.push(JUPITER) } if (options.remove_mars || options.remove_all_events) { - log("Mars removed from deck."); - game.removed.push(MARS); + log("Mars removed from deck.") + game.removed.push(MARS) } if (options.remove_mercury || options.remove_all_events) { - log("Mercury removed from deck."); - game.removed.push(MERCURY); + log("Mercury removed from deck.") + game.removed.push(MERCURY) } if (options.remove_neptune || options.remove_all_events) { - log("Neptune removed from deck."); - game.removed.push(NEPTUNE); + log("Neptune removed from deck.") + game.removed.push(NEPTUNE) } if (options.remove_pluto || options.remove_all_events) { - log("Pluto removed from deck."); - game.removed.push(PLUTO); + log("Pluto removed from deck.") + game.removed.push(PLUTO) } if (options.remove_vulcan || options.remove_all_events) { - log("Vulcan removed from deck."); - game.removed.push(VULCAN); + log("Vulcan removed from deck.") + game.removed.push(VULCAN) } if (game.removed.length === 0) - delete game.removed; + delete game.removed - logbr(); + logbr() // Option for backwards compatible replays. if (options.automatic_disruption) - game.automatic_disruption = 1; + game.automatic_disruption = 1 - setup_historical_deployment(); + setup_historical_deployment() if (scenario === "Free Deployment") - start_free_deployment(); + start_free_deployment() else - start_year(); - return game; + start_year() + return game } function deploy_block(owner, location, name) { for (let b in BLOCKS) { if (BLOCKS[b].owner === owner && BLOCKS[b].name === name) { - game.steps[b] = BLOCKS[b].steps; - game.location[b] = location; - return; + game.steps[b] = BLOCKS[b].steps + game.location[b] = location + return } } } function setup_historical_deployment() { for (let b in BLOCKS) { - game.location[b] = LEVY; - game.steps[b] = BLOCKS[b].steps; - } - - deploy_block("Caesar", "Ravenna", "Caesar"); - deploy_block("Caesar", "Ravenna", "Legio 13"); - deploy_block("Caesar", "Ravenna", "Navis 2"); - deploy_block("Caesar", "Genua", "Antonius"); - deploy_block("Caesar", "Genua", "Legio 8"); - deploy_block("Caesar", "Genua", "Legio 12"); - deploy_block("Caesar", "Massilia", "Legio 11"); - deploy_block("Caesar", "Massilia", "Legio 14"); - deploy_block("Caesar", "Massilia", "Navis 1"); - deploy_block("Caesar", "Narbo", "Legio 7"); - deploy_block("Caesar", "Narbo", "Legio 9"); - deploy_block("Caesar", "Narbo", "Legio 10"); - deploy_block("Caesar", "Lugdunum", "Legio 16"); - deploy_block("Caesar", "Lugdunum", "Equitatus 1"); - - deploy_block("Pompeius", "Neapolis", "Pompeius"); - deploy_block("Pompeius", "Neapolis", "Legio 1"); - deploy_block("Pompeius", "Neapolis", "Navis 1"); - deploy_block("Pompeius", "Brundisium", "Legio 3"); - deploy_block("Pompeius", "Syracusae", "Legio 37"); - deploy_block("Pompeius", "Antiochia", "Scipio"); - deploy_block("Pompeius", "Antiochia", "Legio 34"); - deploy_block("Pompeius", "Alexandria", "Cleopatra"); - deploy_block("Pompeius", "Alexandria", "Navis 2"); - deploy_block("Pompeius", "Utica", "Legio 39"); - deploy_block("Pompeius", "Utica", "Navis 3"); - deploy_block("Pompeius", "Carthago Nova", "Legio 2"); - deploy_block("Pompeius", "Carthago Nova", "Legio 4"); - deploy_block("Pompeius", "Tarraco", "Legio 5"); - deploy_block("Pompeius", "Tarraco", "Legio 6"); - deploy_block("Pompeius", "Tarraco", "Equitatus 1"); + game.location[b] = LEVY + game.steps[b] = BLOCKS[b].steps + } + + deploy_block("Caesar", "Ravenna", "Caesar") + deploy_block("Caesar", "Ravenna", "Legio 13") + deploy_block("Caesar", "Ravenna", "Navis 2") + deploy_block("Caesar", "Genua", "Antonius") + deploy_block("Caesar", "Genua", "Legio 8") + deploy_block("Caesar", "Genua", "Legio 12") + deploy_block("Caesar", "Massilia", "Legio 11") + deploy_block("Caesar", "Massilia", "Legio 14") + deploy_block("Caesar", "Massilia", "Navis 1") + deploy_block("Caesar", "Narbo", "Legio 7") + deploy_block("Caesar", "Narbo", "Legio 9") + deploy_block("Caesar", "Narbo", "Legio 10") + deploy_block("Caesar", "Lugdunum", "Legio 16") + deploy_block("Caesar", "Lugdunum", "Equitatus 1") + + deploy_block("Pompeius", "Neapolis", "Pompeius") + deploy_block("Pompeius", "Neapolis", "Legio 1") + deploy_block("Pompeius", "Neapolis", "Navis 1") + deploy_block("Pompeius", "Brundisium", "Legio 3") + deploy_block("Pompeius", "Syracusae", "Legio 37") + deploy_block("Pompeius", "Antiochia", "Scipio") + deploy_block("Pompeius", "Antiochia", "Legio 34") + deploy_block("Pompeius", "Alexandria", "Cleopatra") + deploy_block("Pompeius", "Alexandria", "Navis 2") + deploy_block("Pompeius", "Utica", "Legio 39") + deploy_block("Pompeius", "Utica", "Navis 3") + deploy_block("Pompeius", "Carthago Nova", "Legio 2") + deploy_block("Pompeius", "Carthago Nova", "Legio 4") + deploy_block("Pompeius", "Tarraco", "Legio 5") + deploy_block("Pompeius", "Tarraco", "Legio 6") + deploy_block("Pompeius", "Tarraco", "Equitatus 1") } exports.action = function (state, current, action, arg) { - game = state; - let S = states[game.state]; + game = state + let S = states[game.state] if (action in S) - S[action](arg, current); + S[action](arg, current) else - throw new Error("Invalid action: " + action); - return game; + throw new Error("Invalid action: " + action) + return game } exports.resign = function (state, current) { - game = state; + game = state if (game.state !== 'game_over') { - logbr(); - log(current + " resigned."); - count_vp(); - game.active = null; - game.state = 'game_over'; - game.result = enemy(current); + logbr() + log(current + " resigned.") + count_vp() + game.active = null + game.state = 'game_over' + game.result = enemy(current) game.victory = current + " resigned." } - return game; + return game } function make_battle_view() { @@ -2649,49 +2649,49 @@ function make_battle_view() { CF: [], CR: [], PF: [], PR: [], flash: game.flash - }; + } - bv.title = game.attacker[game.where]; + bv.title = game.attacker[game.where] if (game.surprise === game.where) - bv.title += " surprise attacks "; + bv.title += " surprise attacks " else - bv.title += " attacks "; + bv.title += " attacks " bv.title += game.where - bv.title += " \u2014 round " + game.battle_round + " of 4"; + bv.title += " \u2014 round " + game.battle_round + " of 4" function is_battle_reserve(b) { - return game.battle_round === 1 && game.reserves.includes(b); + return game.battle_round === 1 && game.reserves.includes(b) } function fill_cell(name, p, fn) { for (let b in BLOCKS) { if (game.location[b] === game.where & block_owner(b) === p && fn(b)) { - bv[name].push(b); + bv[name].push(b) } } } - fill_cell("CR", CAESAR, b => is_battle_reserve(b)); - fill_cell("CF", CAESAR, b => !is_battle_reserve(b)); - fill_cell("PR", POMPEIUS, b => is_battle_reserve(b)); - fill_cell("PF", POMPEIUS, b => !is_battle_reserve(b)); + fill_cell("CR", CAESAR, b => is_battle_reserve(b)) + fill_cell("CF", CAESAR, b => !is_battle_reserve(b)) + fill_cell("PR", POMPEIUS, b => is_battle_reserve(b)) + fill_cell("PF", POMPEIUS, b => !is_battle_reserve(b)) - return bv; + return bv } function observer_hand() { - let hand = []; - hand.length = Math.max(game.c_hand.length, game.p_hand.length); - hand.fill(0); - return hand; + let hand = [] + hand.length = Math.max(game.c_hand.length, game.p_hand.length) + hand.fill(0) + return hand } -exports.is_checkpoint = (a, b) => a.turn !== b.turn; +exports.is_checkpoint = (a, b) => a.turn !== b.turn exports.view = function(state, current) { - game = state; + game = state - count_vp(); + count_vp() let view = { log: game.log, @@ -2711,21 +2711,21 @@ exports.view = function(state, current) { battle: null, prompt: null, actions: null, - }; + } - states[game.state].prompt(view, current); + states[game.state].prompt(view, current) if (states[game.state].show_battle) - view.battle = make_battle_view(); + view.battle = make_battle_view() if (game.mars && game.surprise) { - view.mars = game.p1; - view.surprise = game.surprise; + view.mars = game.p1 + view.surprise = game.surprise } if (game.neptune && game.surprise) { - view.neptune = game.p1; - view.surprise = game.surprise; + view.neptune = game.p1 + view.surprise = game.surprise } - return view; + return view } |