diff options
-rw-r--r-- | data.js | 4 | ||||
-rw-r--r-- | play.html | 90 | ||||
-rw-r--r-- | rules.js | 131 | ||||
-rw-r--r-- | ui.js | 11 |
4 files changed, 185 insertions, 51 deletions
@@ -128,8 +128,9 @@ const TOWNS = { "Germania":{"x":140,"y":272}, "France":{"x":140,"y":573}, "England":{"x":140,"y":873}, + "Sea":{"x":320,"y":900}, "FP":{"x":50,"y":2150}, - "SP":{"x":50,"y":2150}, + "SP":{"x":125,"y":2150}, "Dead":{"x":50,"y":80}, }; @@ -266,6 +267,7 @@ const PORTS = []; town('Y', 0.0, 0.0, 30, "Pool", "FP", 0, "pool"); town('Y', 0.0, 0.0, 30, "Pool", "SP", 0, "pool"); town('Y', 1.0, 1.0, 30, "Pool", "Dead", 0, "pool"); + town('Y', 1.0, 1.0, 30, "Pool", "Sea", 0, "pool"); town('Y', 1.0, 0.5, 3, "Staging", "England", 3, "staging"); town('Y', 1.0, 0.5, 3, "Staging", "France", 3, "staging"); @@ -105,7 +105,7 @@ .map.tall { width: 1275px; height: 2475px; - background-image: url("map-v.jpg"); + background-color: #224467; } .map.wide { @@ -153,6 +153,14 @@ box-shadow: 0 0 0px 4px white; } +#sea { + fill: skyblue; + fill-opacity: 0.4; +} + +#sea { visibility: hidden; } +#sea.highlight { visibility: visible; cursor: pointer; } + /* BLOCKS */ body.shift .block.known:hover { @@ -185,8 +193,8 @@ body.shift .block.known:hover { .block.Franks.highlight { border-color: white; } .block.Saracens.highlight { border-color: lightgreen; } -.block.Franks.selected { border-color: gold; } -.block.Saracens.selected { border-color: gold; } +.block.Franks.selected { border-color: hotpink; } +.block.Saracens.selected { border-color: yellow; } .block.Assassins.selected { border-color: hotpink; } .block.Franks.highlight:not(.selected) { box-shadow: 0 0 4px 1px white; } @@ -478,6 +486,82 @@ X#FR { background-image: linear-gradient(182deg, tan 30%, olivedrab 35%); } <div class="mapwrap" id="mapwrap"> <div class="map" id="map"> +<svg id="svgmap" width="1275px" height="2475px" viewBox="0 0 1275 2475"> +<image href="map-v.jpg" x="0" y="0" width="1275" height="2475" /> +<g transform="translate(0.000000,2475.000000) scale(1.000000,-1.000000)"> + +<path id="sea" d="M29 1275 l0 -1171 3 0 c1 1 4 2 5 4 2 1 4 2 5 2 2 0 5 1 7 2 3 2 7 4 +11 6 3 1 7 4 8 5 1 2 3 3 4 3 2 0 49 24 57 29 4 3 10 6 13 7 2 1 7 4 9 6 2 2 +7 5 10 8 3 2 7 6 10 8 2 2 6 5 8 6 2 1 4 2 4 3 1 1 3 2 5 3 2 1 9 7 16 13 6 7 +14 15 17 18 3 2 6 6 7 8 1 2 9 10 17 19 8 8 15 16 15 17 0 0 1 2 3 2 2 1 4 4 +5 6 1 2 4 6 7 9 3 3 7 8 8 10 1 3 3 6 5 7 1 1 4 5 5 7 2 2 5 6 6 7 3 2 4 5 2 +4 -1 -1 0 0 1 1 1 1 2 2 2 4 0 2 1 5 2 6 1 2 2 3 2 4 0 1 0 1 1 1 1 -1 5 5 5 +7 -1 0 0 1 1 1 0 1 1 3 2 5 1 3 3 6 5 8 1 2 3 5 3 6 1 1 2 2 2 2 1 0 5 8 5 11 +0 1 1 3 1 4 1 1 4 6 6 11 2 4 5 9 6 10 1 1 2 3 2 4 0 0 1 3 3 5 2 3 3 6 3 11 +0 4 2 9 3 13 2 3 4 10 5 16 2 6 4 13 5 16 2 3 3 7 4 11 0 4 1 8 4 15 4 7 4 10 +6 20 0 6 1 14 0 18 0 6 0 8 1 10 1 2 2 5 2 7 0 3 1 5 2 6 0 1 1 4 1 7 0 10 1 +13 2 22 2 5 2 9 1 11 0 2 0 4 0 4 0 2 1 12 1 19 0 3 1 6 1 6 0 1 0 3 0 6 -1 3 +-1 8 -1 12 0 3 0 7 0 9 0 1 0 8 0 16 -1 7 -1 13 -1 14 0 0 0 3 0 5 1 4 1 5 0 +6 -1 1 -1 2 -1 3 2 2 2 13 1 15 -1 2 -2 8 -2 21 -1 9 -1 21 -2 25 -1 3 -1 9 +-1 12 0 2 -1 6 -2 8 -1 1 -2 4 -2 5 0 1 -1 2 -1 3 -1 1 -1 2 0 3 0 2 1 3 0 3 +0 1 -1 2 0 3 0 1 0 2 -1 3 -2 0 -2 1 -1 3 1 3 0 9 -2 13 -1 1 -2 3 -2 4 1 0 0 +1 -1 2 -1 1 -1 1 1 2 2 1 2 1 3 7 0 6 0 9 -2 13 -1 4 -2 9 -2 12 0 3 0 6 -2 +10 -4 7 -3 12 2 14 5 3 17 2 23 -1 5 -2 7 -3 9 0 1 1 3 2 5 3 4 2 12 9 16 16 +2 2 2 3 1 12 -1 12 -4 18 -9 16 -2 0 -3 0 -2 3 0 2 -1 4 -3 7 -2 4 -2 6 -3 13 +0 15 -1 31 -2 33 -1 1 -1 1 0 2 2 1 0 9 -3 12 -2 1 -2 2 -1 5 0 5 3 7 8 9 2 1 +4 2 4 3 1 1 2 1 3 1 1 0 3 1 4 5 1 2 3 5 3 5 1 1 1 2 1 3 -1 0 -1 2 0 3 1 0 1 +2 1 2 -1 2 0 2 3 2 2 0 4 1 6 3 3 3 3 4 3 8 -1 3 0 4 2 6 3 1 2 4 -1 15 -2 5 +-3 6 -6 8 -2 1 -6 2 -8 2 -5 0 -5 2 -1 2 6 2 7 2 8 5 0 1 1 5 2 8 0 2 1 5 2 6 +0 1 1 2 1 3 0 1 0 3 1 4 1 2 1 5 0 7 0 3 0 8 0 12 -1 3 -1 7 -1 8 -1 2 -1 3 1 +4 2 2 2 2 1 5 -1 3 -1 4 0 5 1 0 1 1 1 2 -1 0 0 1 1 3 1 2 1 2 0 3 -2 1 -1 2 +2 5 1 2 3 4 3 4 0 1 1 1 2 2 3 0 17 14 17 16 0 0 1 2 3 3 1 0 2 2 2 3 0 1 1 3 +2 4 3 3 5 9 3 10 -1 1 -1 2 0 4 0 2 0 3 -1 4 -2 0 -2 1 1 3 4 3 5 7 4 13 -1 2 +0 4 0 5 1 1 2 2 1 5 -1 2 -1 5 -1 6 0 1 -1 3 -1 3 -2 1 0 3 5 6 1 1 1 1 0 7 +-1 3 -2 6 -3 7 -1 1 -1 1 0 2 1 1 2 2 3 2 1 0 3 1 5 2 3 1 3 2 3 5 0 2 -1 5 +-2 6 -2 3 -3 6 -2 7 1 0 1 1 1 2 0 1 2 6 5 11 6 11 5 19 -2 33 -5 9 -7 12 -12 +14 -2 1 -5 2 -5 3 0 0 1 2 3 3 3 1 7 2 16 3 6 1 12 2 13 2 2 2 6 1 6 -1 0 -1 +0 -1 1 -1 1 0 6 4 7 6 1 1 3 2 4 4 6 6 7 8 7 10 0 2 6 14 8 15 0 1 1 1 1 2 0 +2 8 9 12 10 2 0 4 1 4 2 0 1 0 2 1 2 1 1 0 2 -2 4 -2 2 -4 3 -8 3 -2 0 -5 0 +-6 1 -1 1 -1 1 -1 1 0 0 0 2 0 3 -1 3 0 5 1 7 1 2 1 3 0 3 -1 1 -1 1 1 3 1 1 +2 2 1 3 0 1 0 4 0 8 0 5 0 7 -2 10 -2 1 -4 3 -4 3 -1 0 -2 1 -3 3 -1 2 -3 3 +-7 4 -3 0 -5 1 -5 0 -1 0 -1 2 -1 4 -1 2 -2 5 -3 6 0 1 -1 3 -1 4 0 1 -1 3 -2 +5 -1 4 0 6 3 8 2 1 3 2 3 3 0 2 1 3 1 4 1 1 1 1 0 3 -1 1 -1 3 -1 4 1 1 0 3 +-2 4 -2 2 -3 3 -2 5 0 1 -1 2 -2 3 -4 1 -4 3 1 7 4 3 4 4 3 6 -1 3 -1 5 0 5 1 +0 3 1 4 2 1 1 3 2 12 1 6 -1 9 2 11 8 1 4 0 6 -1 10 -1 3 -1 5 0 6 1 0 1 2 0 +3 0 3 0 3 3 4 1 1 4 1 7 2 2 0 5 1 6 2 1 1 2 2 3 2 1 0 3 1 4 3 1 1 3 2 4 2 0 +0 2 1 3 2 1 2 4 4 6 5 5 2 5 3 5 6 0 2 -1 3 -3 5 -2 1 -4 3 -4 4 -1 1 -2 2 -5 +2 -5 1 -3 3 3 3 6 0 11 1 23 6 4 2 8 4 11 4 0 0 1 1 1 1 0 3 5 5 10 4 3 0 4 0 +9 5 4 4 6 6 5 7 0 1 0 2 1 2 0 0 4 3 7 6 5 5 7 6 12 7 7 2 9 3 9 9 0 5 -1 7 +-4 14 -5 9 -14 19 -22 25 -2 1 -4 3 -4 3 0 1 -2 2 -4 4 -3 1 -5 3 -6 4 -1 0 +-4 2 -6 4 -3 1 -7 4 -9 6 -3 2 -6 5 -8 7 -7 4 -9 7 -13 14 -3 7 -4 8 -10 11 +-4 2 -8 4 -10 5 -1 0 -2 1 -3 2 -1 3 -14 13 -16 13 0 0 -1 0 -1 1 0 1 -1 2 -3 +2 -2 1 -3 2 -3 3 -1 1 -3 3 -6 5 -2 2 -4 5 -5 6 0 1 -1 2 -2 3 -1 1 -1 1 0 1 +1 0 1 2 0 2 -1 0 -2 1 -1 3 0 3 -3 10 -5 10 -1 0 -1 1 -1 3 0 2 0 3 -1 3 0 0 +-1 2 -2 3 -1 4 -1 4 4 9 2 2 4 5 4 6 0 1 -13 15 -15 15 -3 0 -4 3 -3 7 2 6 1 +7 -3 9 -2 1 -3 2 -3 2 0 3 3 9 5 9 2 1 4 5 3 7 -1 0 0 3 2 5 3 4 3 4 1 7 -2 4 +-1 6 6 9 3 2 6 4 7 6 l2 3 -7 6 c-3 3 -8 6 -9 7 -2 1 -4 2 -5 3 -1 2 -3 2 -11 +5 -7 4 -9 6 -9 12 -1 6 -1 7 -6 13 -2 3 -4 6 -4 8 0 1 -2 4 -5 8 -8 10 -9 12 +-8 16 0 3 0 3 -3 4 -1 1 -7 2 -12 3 -7 1 -12 2 -20 6 -11 4 -12 5 -22 5 -8 1 +-11 2 -14 3 -3 2 -7 3 -9 1 0 -1 -3 -1 -7 -2 -3 0 -7 -1 -10 -3 -5 -3 -9 -2 +-9 2 0 2 0 3 1 4 2 1 1 5 -1 7 -1 1 -5 2 -13 3 -14 2 -15 2 -13 6 2 4 0 5 -6 +2 -2 -1 -4 -2 -5 -2 0 1 4 4 11 8 5 2 7 3 7 5 0 1 1 2 3 3 2 0 2 1 2 3 -1 1 0 +2 1 3 0 1 1 3 1 4 0 3 -3 6 -10 8 -2 1 -4 2 -4 2 0 1 0 3 1 5 1 3 2 3 7 5 5 1 +6 2 7 4 0 2 1 3 1 3 1 0 1 1 2 3 1 1 2 3 4 5 3 2 4 6 5 11 0 1 0 3 1 4 1 0 2 +2 2 3 -1 3 -9 10 -17 15 -4 3 -9 7 -11 9 -2 2 -5 4 -6 4 -1 0 -3 1 -5 3 -1 1 +-3 2 -4 2 -1 0 -2 0 -2 1 0 1 8 2 15 2 2 0 7 1 10 2 6 2 7 3 8 5 1 1 2 2 2 2 +2 0 6 3 7 7 2 2 2 5 2 8 -1 4 -1 5 3 8 1 2 4 4 5 5 2 1 3 2 4 6 1 5 5 12 8 15 +1 1 2 3 2 4 0 1 0 1 1 1 1 -1 2 4 2 6 -1 1 2 5 3 4 1 0 1 0 1 1 0 1 0 1 1 1 0 +-1 2 0 3 1 1 1 1 2 0 2 0 0 -1 1 0 2 0 1 0 1 -1 1 0 -1 -1 -1 -1 0 0 0 -3 2 +-7 5 -3 2 -8 5 -10 8 -2 2 -5 4 -7 6 -2 1 -3 2 -3 2 0 2 -7 8 -11 10 -2 0 -8 +3 -13 6 -4 2 -10 4 -11 4 -3 0 -9 3 -12 6 -2 1 -4 2 -6 3 -1 0 -5 2 -8 4 -3 1 +-7 4 -9 4 -2 1 -6 3 -8 5 -3 1 -9 4 -13 6 -4 2 -7 4 -7 5 -1 1 -16 6 -32 11 +-8 2 -12 6 -12 10 0 2 1 4 5 8 4 3 6 6 7 9 l2 5 9 4 c5 3 10 5 11 6 0 2 1 4 1 +7 0 6 1 7 7 10 3 1 7 3 9 5 3 2 3 3 3 7 -1 4 -1 5 3 9 4 4 11 8 22 12 4 1 11 +4 16 7 8 4 9 5 10 9 0 3 2 6 5 8 4 5 6 6 13 7 4 1 6 2 8 6 2 3 3 5 4 9 l0 5 +-166 0 -166 0 0 -1171z"/> + +</g> +</svg> <div id="blocks" class="blocks"></div> <div id="offmap" class="offmap" style="visibility:hidden"></div> <div id="towns" class="towns"></div> @@ -23,6 +23,7 @@ const BOTH = "Both"; const DEAD = "Dead"; const F_POOL = "FP"; const S_POOL = "SP"; +const SEA = "Sea"; const ENGLAND = "England"; const FRANCE = "France"; const GERMANIA = "Germania"; @@ -70,6 +71,7 @@ const NO_MARK = ""; delete TOWNS[DEAD]; delete TOWNS[F_POOL]; delete TOWNS[S_POOL]; +delete TOWNS[SEA]; let states = {}; @@ -1536,9 +1538,10 @@ states.move_phase = { gen_action_undo(view); gen_action(view, 'end_move_phase'); if (game.moves > 0) { - gen_action(view, 'group_move'); - if (can_sea_move_anywhere()) - gen_action(view, 'sea_move'); + let sea_moves_allowed = (game.active != game.guide && game.active != game.jihad); + for (let b in BLOCKS) + if (can_block_land_move(b) || (sea_moves_allowed && can_block_sea_move(b))) + gen_action(view, 'block', b); if (can_muster_anywhere()) gen_action(view, 'muster'); if (game.winter_campaign == game.active) @@ -1550,31 +1553,88 @@ states.move_phase = { --game.moves; game.state = 'winter_campaign'; }, - group_move: function () { - push_undo(); - --game.moves; - game.state = 'group_move_first'; - game.summary = []; - }, - sea_move: function () { - push_undo(); - game.state = 'sea_move'; - }, muster: function () { push_undo(); --game.moves; game.state = 'muster'; }, + block: function (who) { + game.summary = []; + push_undo(); + game.who = who; + game.where = game.location[who]; + if (game.where == GERMANIA || game.where == FRANCE || game.where == ENGLAND) { + game.state = 'sea_move_to'; + } else { + game.state = 'move_phase_to'; + } + }, end_move_phase: end_move_phase, undo: pop_undo } +// Start new group move or sea move. +states.move_phase_to = { + prompt: function (view, current) { + if (is_inactive_player(current)) + return view.prompt = "Move Phase: Waiting for " + game.active + "."; + view.prompt = "Move Phase: Move " + block_name(game.who); + gen_action_undo(view); + gen_action(view, 'block', game.who); + let from = game.location[game.who]; + let can_group_move = false; + let can_sea_move = false; + for (let to of TOWNS[from].exits) { + if (can_block_land_move_to(game.who, from, to)) { + gen_action(view, 'town', to); + can_group_move = true; + } + } + if (can_block_sea_move(game.who)) { + gen_action(view, 'town', SEA); + can_sea_move = true; + } + if (can_group_move && can_sea_move) + view.prompt += " by road or by sea."; + else if (can_sea_move) + view.prompt += " by sea."; + else + view.prompt += " by road."; + }, + town: function (to) { + let from = game.location[game.who]; + if (to == SEA) { + log_move_start(from); + log_move_continue(to); + game.location[game.who] = SEA; + game.state = 'sea_move_to'; + return; + } + -- game.moves; + game.distance = 0; + log_move_start(from); + let mark = move_block(game.who, from, to); + if (mark) + log_move_continue(to + mark); + else + log_move_continue(to); + lift_siege(from); + game.last_from = from; + if (!can_block_continue(game.who, from, to)) + end_move(); + else { + game.state = 'group_move_to'; + } + }, + block: pop_undo, + undo: pop_undo +} + // GROUP MOVE -function group_move_phase(inactive = 0) { +function group_move_name(inactive = 0) { if (game.active == game.jihad) return "Jihad: "; if (game.active == game.guide) return "Guide: "; - if (inactive) return "Move Phase: "; return "Group Move: "; } @@ -1589,8 +1649,8 @@ function can_group_move_more() { states.group_move_first = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = group_move_phase(1) + "Waiting for " + game.active + "."; - view.prompt = group_move_phase(0) + "Choose a block to group move."; + return view.prompt = group_move_name(1) + "Waiting for " + game.active + "."; + view.prompt = group_move_name(0) + "Choose a block to group move."; gen_action_undo(view); if (game.active == game.guide || game.active == game.jihad) gen_action(view, 'end_move_phase'); @@ -1613,8 +1673,8 @@ states.group_move_first = { states.group_move_who = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = group_move_phase(1) + "Waiting for " + game.active + "."; - view.prompt = group_move_phase(0) + "Choose a block to group move."; + return view.prompt = group_move_name(1) + "Waiting for " + game.active + "."; + view.prompt = group_move_name(0) + "Move blocks from " + game.where + "."; gen_action_undo(view); if (game.active == game.guide || game.active == game.jihad) gen_action(view, 'end_move_phase'); @@ -1640,8 +1700,8 @@ states.group_move_who = { states.group_move_to = { prompt: function (view, current) { if (is_inactive_player(current)) - return view.prompt = group_move_phase(1) + "Waiting for " + game.active + "."; - view.prompt = group_move_phase(0) + "Move " + block_name(game.who) + "."; + return view.prompt = group_move_name(1) + "Waiting for " + game.active + "."; + view.prompt = group_move_name(0) + "Move " + block_name(game.who) + "."; gen_action_undo(view); if (game.distance == 0) gen_action(view, 'block', game.who); @@ -1706,32 +1766,14 @@ function end_group_move() { // SEA MOVE -states.sea_move = { - prompt: function (view, current) { - if (is_inactive_player(current)) - return view.prompt = "Move Phase: Waiting for " + game.active + "."; - view.prompt = "Sea Move: Choose a block to move."; - gen_action_undo(view); - for (let b in BLOCKS) - if (can_block_sea_move(b)) - gen_action(view, 'block', b); - }, - end_sea_move: function () { - game.state = 'move_phase'; - }, - block: function (who) { - game.who = who; - game.state = 'sea_move_to'; - }, - undo: pop_undo -} - states.sea_move_to = { prompt: function (view, current) { if (is_inactive_player(current)) return view.prompt = "Move Phase: Waiting for " + game.active + "."; if (is_english_crusader(game.who)) view.prompt = "Sea Move: Move " + block_name(game.who) + " to a port."; + else if (game.where == GERMANIA) + view.prompt = "Move Phase: Move " + block_name(game.who) + " to Aleppo, Antioch, or St. Simeon."; else view.prompt = "Sea Move: Move " + block_name(game.who) + " to a friendly port."; gen_action_undo(view); @@ -1744,7 +1786,7 @@ states.sea_move_to = { gen_action(view, 'town', ST_SIMEON); } else { for (let to of PORTS) - if (to != from && can_block_sea_move_to(game.who, to)) + if (to != game.where && can_block_sea_move_to(game.who, to)) gen_action(view, 'town', to); } }, @@ -1787,10 +1829,7 @@ states.sea_move_to = { game.who = null; game.state = 'move_phase'; }, - block: function () { - game.who = null; - game.state = 'sea_move'; - }, + block: pop_undo, undo: pop_undo, } @@ -375,7 +375,16 @@ function build_map() { for (let name in TOWNS) { let town = TOWNS[name]; - ui.towns[name] = build_town(name, town); + if (name == "Sea") { + element = document.getElementById("svgmap").getElementById("sea"); + element.town = "Sea"; + element.addEventListener("mouseenter", on_focus_town); + element.addEventListener("mouseleave", on_blur_town); + element.addEventListener("click", on_click_town); + ui.towns[name] = element; + } else { + ui.towns[name] = build_town(name, town); + } } for (let b in BLOCKS) { |