summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2021-07-02 20:48:01 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-16 19:19:39 +0100
commit88eabb2b84ff90377630a722a0f593189c6704ad (patch)
tree1b6b581d5df7ae40de7078922dad186dc22804c3
parent7e1f01c2b85f4c2773484bfa30023e552355b387 (diff)
downloadcrusader-rex-88eabb2b84ff90377630a722a0f593189c6704ad.tar.gz
crusader: Merge move phases and make sea moves by sea.
-rw-r--r--data.js4
-rw-r--r--play.html90
-rw-r--r--rules.js131
-rw-r--r--ui.js11
4 files changed, 185 insertions, 51 deletions
diff --git a/data.js b/data.js
index 0af45a8..0255d5a 100644
--- a/data.js
+++ b/data.js
@@ -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");
diff --git a/play.html b/play.html
index 0128af5..ac6ab2b 100644
--- a/play.html
+++ b/play.html
@@ -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>
diff --git a/rules.js b/rules.js
index f368858..df581e5 100644
--- a/rules.js
+++ b/rules.js
@@ -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,
}
diff --git a/ui.js b/ui.js
index 90c8ac0..1460612 100644
--- a/ui.js
+++ b/ui.js
@@ -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) {