summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2021-06-24 14:01:24 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-16 19:19:38 +0100
commita6f5d220f496829911ac3011cdbbcc045f057b63 (patch)
tree0e34ba679ac16718652f1b9571be94b0e66f344c
parentcbc1f4048a69dfe12ef16a63195d5a6088720495 (diff)
downloadcrusader-rex-a6f5d220f496829911ac3011cdbbcc045f057b63.tar.gz
crusader: Many fixes.
-rw-r--r--badges/Cross_of_the_Knights_Templar.svg1
-rw-r--r--badges/Star_and_Crescent.svg1
-rw-r--r--badges/camping-tent.svg1
-rw-r--r--badges/stone-tower.svg1
-rw-r--r--badges/trebuchet.svg1
-rw-r--r--besieged.svg1
-rw-r--r--besieging.svg1
-rw-r--r--jihad-christian.svg1
-rw-r--r--jihad-muslim.svg1
-rw-r--r--play.html36
-rw-r--r--rules.js180
-rw-r--r--ui.js18
12 files changed, 149 insertions, 94 deletions
diff --git a/badges/Cross_of_the_Knights_Templar.svg b/badges/Cross_of_the_Knights_Templar.svg
new file mode 100644
index 0000000..d96e204
--- /dev/null
+++ b/badges/Cross_of_the_Knights_Templar.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600"><g opacity=".3"><path d="M0 300h600" fill="none" stroke="#000" stroke-width="72"/><path d="M0 216l60 84-60 84zM216 0h168l-84 60z"/><path d="M300 600V0" fill="none" stroke="#000" stroke-width="72"/><path d="M216 600h168l-84-60zm324-300l60 84V216z"/></g></svg> \ No newline at end of file
diff --git a/badges/Star_and_Crescent.svg b/badges/Star_and_Crescent.svg
new file mode 100644
index 0000000..e2d7cb9
--- /dev/null
+++ b/badges/Star_and_Crescent.svg
@@ -0,0 +1 @@
+<svg width="248.87" height="215.85" viewBox="0 0 65.847 57.11" xmlns="http://www.w3.org/2000/svg"><g opacity=".3"><path d="M28.02.53C12.797.82.534 13.264.534 28.553c0 15.47 12.56 28.029 28.03 28.029a27.924 27.924 0 0018.801-7.251 23.821 23.821 0 01-11.906 3.166c-13.21 0-23.928-10.718-23.928-23.928S22.25 4.64 35.46 4.64a23.82 23.82 0 0111.99 3.217A27.922 27.922 0 0028.563.53c-.181 0-.365-.003-.546 0z"/><path d="M65.32 28.57L41.2 36.408l14.906-20.516v25.36L41.201 20.733z"/></g></svg> \ No newline at end of file
diff --git a/badges/camping-tent.svg b/badges/camping-tent.svg
new file mode 100644
index 0000000..832d8b8
--- /dev/null
+++ b/badges/camping-tent.svg
@@ -0,0 +1 @@
+<svg style="height:512px;width:512px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M361.155 91.245l-18 .193.42 38.98c-45.773 13.285-108.533 19.738-166.474 23.573 35.097 96.284 99.357 173.77 157.845 257.13 20.718-19.655 51.11-31.983 83.46-36.01-20.8-18.109-36.634-27.966-58.833-70.438 31.27 37.085 52.579 48.467 77.623 62.006 3.263-13.094 8.938-24.638 18.721-32.674 8.667-7.12 20.026-10.654 33.53-10.344-46.874-59.763-101.67-117.054-127.83-189.435l-.462-42.98zM163.25 102.92l-17.998.244s.25 18.34.56 36.97c.156 9.316.325 18.703.489 25.929.06 2.636.117 4.58.174 6.542-34.378 83.733-69.154 160.993-123.92 233.442 33.635-1.387 66.326-1.203 98.552-.041C143.37 343.389 144.453 271.151 156.734 204c11.417 68.562 10.566 139.445 33.483 205.83 42.962 3.082 85.69 7.198 129.35 10.926-55.67-79.151-118.213-155.037-155.118-249.365-.05-1.782-.1-3.396-.152-5.737-.162-7.156-.333-16.523-.488-25.82-.31-18.594-.559-36.914-.559-36.914z" opacity=".3"/></svg> \ No newline at end of file
diff --git a/badges/stone-tower.svg b/badges/stone-tower.svg
new file mode 100644
index 0000000..7885d8d
--- /dev/null
+++ b/badges/stone-tower.svg
@@ -0,0 +1 @@
+<svg style="height:512px;width:512px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M71 22.406v102.53h202.25v18.69h-73.22v36.968h-18.686v-36.97H79.156l43.375 53.782h180.44v18.688H180.905v36.97H162.22v-36.97h-39.407v163.562h58.53v-44.75H157.47V316.22h74.155v-33.66H193.72v-18.687h97.218v18.688h-40.625v33.656h73.28v18.686h-32.437v44.75h26.313v18.688h-63.69l-2.686 74.03-18.688-.687 2.656-73.343H93.032V398h-.22l-28.687 92.844h79.844l9.81-70.688 18.5 2.563-9.468 68.124H453.25L424.562 398h-30.03V197.78l51.812-64.25V22.407h-64.406v52.438h-39.22V22.406h-65.124v52.438h-38.53V22.406h-65.126v52.438h-38.5V22.406H71zm129.03 312.5v44.75h72.44v-44.75h-72.44z" fill-opacity=".3"/></svg> \ No newline at end of file
diff --git a/badges/trebuchet.svg b/badges/trebuchet.svg
new file mode 100644
index 0000000..aff8da2
--- /dev/null
+++ b/badges/trebuchet.svg
@@ -0,0 +1 @@
+<svg style="height:512px;width:512px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M51.984 50.486l-7.968 16.14 11.396 5.626H55V237.85l.977-1.93 7.957-15.647 8.06 15.594c.342.66.667 1.317 1.006 1.977V80.934l216.248 106.742a31.87 31.87 0 00-.248 3.896c0 17.228 13.773 31 31 31 8.558 0 16.26-3.4 21.85-8.93l83.277 41.106-26.832 32.133L454.508 416H480V304l-35.002-41.918 6.986-14.152-101.597-50.15c.4-2.003.613-4.078.613-6.208 0-17.227-13.773-31.002-31-31.002-9.404 0-17.772 4.11-23.44 10.64L51.985 50.487zM282.78 223.34L249.73 279H224v18h15.04L132.386 476.615l-100.375-.11-.02 18 122.53.134 4.376.005L479.99 495l.02-18-18.576-.02L352.99 227.722c-8.722 7.97-20.312 12.847-32.99 12.847-3.074 0-6.08-.3-9-.847V279h-24.05l23.392-39.396c-10.927-2.207-20.56-8.08-27.56-16.264zM329 252.793L340.402 279H329v-26.207zm-265.016 7.172C53.41 280.85 42.212 301.81 27.3 320.367c13.75 18.88 26.382 26.917 36.938 26.996 10.568.08 22.95-7.66 36.49-26.86-15.842-19.27-26.55-40.147-36.744-60.538zM276.26 297H311v179.813l-141.422-.157L276.26 297zm52.74 0h19.232L384 379.21V416h16.006l26.514 60.94-97.52-.106V297z" fill-opacity=".3"/></svg> \ No newline at end of file
diff --git a/besieged.svg b/besieged.svg
deleted file mode 100644
index 9328f94..0000000
--- a/besieged.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M71 22.406v102.53h202.25v18.69h-73.22v36.968h-18.686v-36.97H79.156l43.375 53.782h180.44v18.688H180.905v36.97H162.22v-36.97h-39.407v163.562h58.53v-44.75H157.47V316.22h74.155V282.56H193.72v-18.687h97.218v18.688h-40.625v33.656h73.28v18.686h-32.437v44.75h26.313v18.688h-63.69l-2.686 74.03-18.688-.687 2.656-73.343H93.032V398h-.22l-28.687 92.844h79.844l9.81-70.688 18.5 2.563-9.468 68.124H453.25L424.562 398h-30.03V197.78l51.812-64.25V22.407h-64.406v52.438h-39.22V22.406h-65.124v52.438h-38.53V22.406h-65.126v52.438h-38.5V22.406H71zm129.03 312.5v44.75h72.44v-44.75h-72.44z" fill="#000" fill-opacity="0.3"></path></g></svg>
diff --git a/besieging.svg b/besieging.svg
deleted file mode 100644
index 57bb874..0000000
--- a/besieging.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M51.984 50.486l-7.968 16.14 11.396 5.626H55V237.85l.977-1.93 7.957-15.647 8.06 15.594c.342.66.667 1.317 1.006 1.977V80.934l216.248 106.742c-.157 1.276-.248 2.575-.248 3.896 0 17.228 13.773 31 31 31 8.558 0 16.26-3.4 21.85-8.93l83.277 41.106-26.832 32.133L454.508 416H480V304l-35.002-41.918 6.986-14.152-101.597-50.15c.4-2.003.613-4.078.613-6.208 0-17.227-13.773-31.002-31-31.002-9.404 0-17.772 4.11-23.44 10.64L51.985 50.487zM282.78 223.34L249.73 279H224v18h15.04L132.386 476.615l-100.375-.11-.02 18 122.53.134 4.376.005L479.99 495l.02-18-18.576-.02L352.99 227.722c-8.722 7.97-20.312 12.847-32.99 12.847-3.074 0-6.08-.3-9-.847V279h-24.05l23.392-39.396c-10.927-2.207-20.56-8.08-27.56-16.264zM329 252.793L340.402 279H329v-26.207zm-265.016 7.172C53.41 280.85 42.212 301.81 27.3 320.367c13.75 18.88 26.382 26.917 36.938 26.996 10.568.08 22.95-7.66 36.49-26.86-15.842-19.27-26.55-40.147-36.744-60.538zM276.26 297H311v179.813l-141.422-.157L276.26 297zm52.74 0h19.232L384 379.21V416h16.006l26.514 60.94-97.52-.106V297z" fill="#000" fill-opacity="0.3"></path></g></svg>
diff --git a/jihad-christian.svg b/jihad-christian.svg
deleted file mode 100644
index 196101e..0000000
--- a/jihad-christian.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600"><g opacity="0.3"><path d="M0 300h600" fill="none" stroke="#000" stroke-width="72"/><path fill="#000" d="M0 216l60 84-60 84zM216 0h168l-84 60z"/><path d="M300 600V0" fill="none" stroke="#000" stroke-width="72"/><path fill="#000" d="M216 600h168l-84-60zM540 300l60 84V216z"/></g></svg>
diff --git a/jihad-muslim.svg b/jihad-muslim.svg
deleted file mode 100644
index a1538be..0000000
--- a/jihad-muslim.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="248.87" height="215.85" viewBox="0 0 65.847 57.11" xmlns="http://www.w3.org/2000/svg"><g fill="#000" opacity="0.3"><path d="M28.02.53C12.797.82.534 13.264.534 28.553c0 15.47 12.56 28.029 28.03 28.029a27.924 27.924 0 0018.801-7.251 23.821 23.821 0 01-11.906 3.166c-13.21 0-23.928-10.718-23.928-23.928S22.25 4.64 35.46 4.64a23.82 23.82 0 0111.99 3.217A27.922 27.922 0 0028.563.53c-.181 0-.365-.003-.546 0z"/><path d="M65.32 28.57L41.2 36.408l14.906-20.516v25.36L41.201 20.733z"/></g></svg>
diff --git a/play.html b/play.html
index b374274..3fd6f1d 100644
--- a/play.html
+++ b/play.html
@@ -188,35 +188,52 @@ body.shift .block.known:hover {
.block.Franks.selected { border-color: gold; }
.block.Saracens.selected { border-color: gold; }
.block.Assassins.selected { border-color: hotpink; }
+.block.Franks.highlight:not(.selected) { box-shadow: 0 0 3px white; }
.block.highlight { cursor: pointer; }
.block.moved { filter: brightness(80%) grayscale(40%); }
.block.highlight.moved { filter: brightness(95%) grayscale(40%); }
+
.map .block.castle.known { filter: grayscale(50%); }
.map.stack_layout .block.castle { filter: grayscale(90%); }
-.map .block.castle:not(.known) {
- background-image: url("/crusader-rex/besieged.svg");
+.block.castle:not(.known) {
+ background-image: url("badges/stone-tower.svg");
background-size: 60%;
background-position: center;
}
-.map .block.besieging:not(.known) {
- background-image: url("/crusader-rex/besieging.svg");
+.block.besieging:not(.known) {
+ background-image: url("badges/trebuchet.svg");
+ background-size: 60%;
+ background-position: center;
+}
+.block.winter_campaign:not(.known) {
+ background-image: url("badges/camping-tent.svg");
background-size: 60%;
background-position: center;
}
-
.block.Franks.jihad {
- background-image: url("/crusader-rex/jihad-christian.svg");
+ background-image: url("badges/Cross_of_the_Knights_Templar.svg");
background-size: 60%;
background-position: center;
}
.block.Saracen.jihad {
- background-image: url("/crusader-rex/jihad-muslim.svg");
+ background-image: url("badges/Star_and_Crescent.svg");
background-size: 60%;
background-position: center;
}
+.block.besieging.Franks.jihad:not(.known) {
+ background-image: url("badges/trebuchet.svg"), url("badges/Cross_of_the_Knights_Templar.svg");
+ background-size: 60%, 40%;
+ background-position: 30% 80%, 85% 15%;
+}
+.block.besieging.Saracens.jihad:not(.known) {
+ background-image: url("badges/trebuchet.svg"), url("badges/Star_and_Crescent.svg");
+ background-size: 60%, 40%;
+ background-position: 30% 80%, 85% 15%;
+}
+
.block.r0 { transform: rotate(0deg); }
.block.r1 { transform: rotate(-90deg); }
.block.r2 { transform: rotate(-180deg); }
@@ -398,10 +415,11 @@ body.shift .block.known:hover {
<div id="prompt" class="prompt">$PROMPT</div>
<button id="eliminate_button" class="hide" onclick="on_button_eliminate()">Eliminate</button>
- <button id="group_move_button" class="hide" onclick="on_button_group_move()">Group move</button>
- <button id="end_group_move_button" class="hide" onclick="on_button_end_group_move()">End group move</button>
+ <button id="winter_campaign_button" class="hide" onclick="on_button_winter_campaign()">Winter campaign</button>
<button id="sea_move_button" class="hide" onclick="on_button_sea_move()">Sea move</button>
<button id="end_sea_move_button" class="hide" onclick="on_button_end_sea_move()">End sea move</button>
+ <button id="group_move_button" class="hide" onclick="on_button_group_move()">Group move</button>
+ <button id="end_group_move_button" class="hide" onclick="on_button_end_group_move()">End group move</button>
<button id="muster_button" class="hide" onclick="on_button_muster()">Muster</button>
<button id="end_muster_button" class="hide" onclick="on_button_end_muster()">End muster</button>
<button id="end_retreat_button" class="hide" onclick="on_button_end_retreat()">End retreat</button>
diff --git a/rules.js b/rules.js
index 9659602..19d0a42 100644
--- a/rules.js
+++ b/rules.js
@@ -3,9 +3,10 @@
// TODO: optional rule - iron bridge
// TODO: optional rule - force marches
-// TODO: can sea move into fortified port that is under attack but not yet besieged?
-// TODO: pause after battle ends to show final result/action
+// TODO: can sea move into fortified port that is under attack but not yet besieged? no...
+// TODO: pause after battle ends to show final result/action?
// TODO: optional retreat after combat round 3 if storming
+// TODO: new combat deployment in round 2/3 if defenders are wiped out? maybe...
exports.scenarios = [
"Third Crusade"
@@ -256,9 +257,14 @@ function list_seats(who) {
if (is_saladin_family(who))
who = SALADIN;
switch (block_type(who)) {
- case 'nomads': return [ block_home(who) ];
- case 'turcopoles': who = "Turcopoles"; break;
- case 'military_orders': who = BLOCKS[who].name; break;
+ case 'nomads':
+ return [ block_home(who) ];
+ case 'turcopoles':
+ who = "Turcopoles";
+ break;
+ case 'military_orders':
+ who = BLOCKS[who].name;
+ break;
}
let list = [];
for (let town in SHIELDS)
@@ -271,9 +277,14 @@ function is_home_seat(where, who) {
if (is_saladin_family(who))
who = SALADIN;
switch (block_type(who)) {
- case 'nomads': return [ block_home(who) ];
- case 'turcopoles': who = "Turcopoles"; break;
- case 'military_orders': who = BLOCKS[who].name; break;
+ case 'nomads':
+ return where == block_home(who);
+ case 'turcopoles':
+ who = "Turcopoles";
+ break;
+ case 'military_orders':
+ who = BLOCKS[who].name;
+ break;
}
for (let town in SHIELDS)
if (SHIELDS[town].includes(who))
@@ -482,6 +493,9 @@ function is_friendly_or_vacant_town(where) {
function is_contested_or_enemy_town(where) {
return is_contested_town(where) || is_enemy_town(where);
}
+function is_enemy_occupied_town(where) {
+ return count_enemy(where) > 0;
+}
/* Field queries exclude castles. */
function is_friendly_field(where) {
@@ -675,8 +689,8 @@ function can_block_land_move(who) {
function can_use_richards_sea_legs(who, to) {
// English Crusaders may attack by sea.
// If combined with another attack, the English must be the Main Attacker.
- if (is_contested_or_enemy_town(to)) {
- if (is_english_crusader(who)) {
+ if (is_english_crusader(who)) {
+ if (is_enemy_field(to)) {
if (!game.attacker[to])
return true;
if (game.attacker[to] == FRANKS)
@@ -787,7 +801,7 @@ function can_block_retreat(who) {
function can_block_regroup_to(who, to) {
// regroup during winter campaign
- if (is_winter() && is_contested_or_enemy_town(to))
+ if (is_winter() && is_enemy_occupied_town(to))
return false;
if (is_friendly_field(to) || is_vacant_town(to)) {
let from = game.location[who];
@@ -1028,7 +1042,7 @@ states.saracen_deployment = {
start_year();
},
pass: function () {
- game.who = SALADIN;
+ game.who = null;
start_year();
}
}
@@ -1477,6 +1491,11 @@ function end_move_phase() {
game.who = null;
game.where = null;
game.moves = 0;
+
+ // declined to use winter campaign
+ if (game.winter_campaign == game.active)
+ delete game.winter_campaign;
+
if (game.active == game.jihad)
goto_select_jihad();
else
@@ -1484,18 +1503,18 @@ function end_move_phase() {
}
function format_moves(phase, prompt) {
- if (game.moves == 0)
- return phase + "No moves left.";
- if (game.moves == 1)
- return phase + prompt + " \u2014 1 move left.";
- return phase + prompt + " \u2014 " + game.moves + " moves left.";
}
states.move_phase = {
prompt: function (view, current) {
if (is_inactive_player(current))
return view.prompt = "Move Phase: Waiting for " + game.active + ".";
- view.prompt = format_moves("Move Phase: ", "Group Move, Sea Move, or Muster");
+ if (game.moves == 0)
+ view.prompt = "Move Phase: No moves left.";
+ else if (game.moves == 1)
+ view.prompt = "Move Phase: 1 move left.";
+ else
+ view.prompt = "Move Phase: " + game.moves + " moves left.";
gen_action_undo(view);
gen_action(view, 'end_move_phase');
if (game.moves > 0) {
@@ -1504,8 +1523,15 @@ states.move_phase = {
gen_action(view, 'sea_move');
if (can_muster_anywhere())
gen_action(view, 'muster');
+ if (game.winter_campaign == game.active)
+ gen_action(view, 'winter_campaign');
}
},
+ winter_campaign: function () {
+ push_undo();
+ --game.moves;
+ game.state = 'winter_campaign';
+ },
group_move: function () {
push_undo();
--game.moves;
@@ -1604,13 +1630,13 @@ states.group_move_to = {
let from = game.location[game.who];
if (game.distance > 0) {
// cannot start or reinforce battles in winter
- if (!(is_winter() && is_contested_or_enemy_town(from)))
+ if (!(is_winter() && is_enemy_occupied_town(from)))
gen_action(view, 'town', from);
}
for (let to of TOWNS[from].exits) {
if (to != game.last_from && can_block_land_move_to(game.who, from, to)) {
// cannot start or reinforce battles in winter
- if (is_winter() && is_contested_or_enemy_town(to)) {
+ if (is_winter() && is_enemy_occupied_town(to)) {
// but can move through friendly sieges
if (!is_friendly_field(to))
continue;
@@ -1666,7 +1692,7 @@ states.sea_move = {
prompt: function (view, current) {
if (is_inactive_player(current))
return view.prompt = "Move Phase: Waiting for " + game.active + ".";
- view.prompt = format_moves("Sea Move: ", "Choose a block to sea move");
+ view.prompt = "Sea Move: Choose a block to move.";
gen_action_undo(view);
for (let b in BLOCKS)
if (can_block_sea_move(b))
@@ -1756,7 +1782,7 @@ states.muster = {
prompt: function (view, current) {
if (is_inactive_player(current))
return view.prompt = "Move Phase: Waiting for " + game.active + ".";
- view.prompt = "Muster: Choose one friendly or vacant muster town.";
+ view.prompt = "Muster: Choose a friendly muster town.";
gen_action_undo(view);
for (let where in TOWNS) {
// cannot start or reinforce battles in winter
@@ -1918,6 +1944,26 @@ function end_muster_move() {
game.state = 'muster_who';
}
+// WINTER CAMPAIGN
+
+states.winter_campaign = {
+ prompt: function (view, current) {
+ if (is_inactive_player(current))
+ return view.prompt = "Move Phase: Waiting for " + game.active + ".";
+ view.prompt = "Winter Campaign: Select a siege to maintain over the winter.";
+ gen_action_undo(view);
+ for (let town in TOWNS)
+ if (is_friendly_field(town) && is_under_siege(town))
+ gen_action(view, 'town', town);
+ },
+ town: function (where) {
+ log(game.active + " winter campaign in " + where + ".");
+ game.winter_campaign = where;
+ game.state = 'move_phase';
+ },
+ undo: pop_undo
+}
+
// COMBAT PHASE
function goto_combat_phase() {
@@ -2094,7 +2140,7 @@ states.regroup = {
clear_undo();
print_summary(game.active + " regroup:");
if (is_winter())
- end_winter_campaign();
+ goto_winter_2();
else if (is_contested_town(game.where))
next_combat_round();
else
@@ -3008,10 +3054,10 @@ states.draw_phase = {
town: function (where) {
let type = block_type(game.who);
- log(game.active + " arrive in " + where + ".");
+ log(game.active + " draw to " + where + ".");
game.location[game.who] = where;
- if ((type == 'outremers' || type == 'emirs' || type == 'nomads') && is_home_seat(where, game.who));
+ if ((type == 'outremers' || type == 'emirs' || type == 'nomads') && is_home_seat(where, game.who))
game.steps[game.who] = 1;
else
game.steps[game.who] = block_max_steps(game.who);
@@ -3035,7 +3081,7 @@ function end_draw_phase() {
function end_game_turn() {
if (is_winter()) {
- goto_winter_campaign();
+ goto_winter_1();
} else {
if (check_sudden_death())
return;
@@ -3044,64 +3090,45 @@ function end_game_turn() {
}
}
-// WINTER CAMPAIGN
+// WINTER SUPPLY
-function goto_winter_campaign() {
+function goto_winter_1() {
log("");
- if (game.winter_campaign) {
- log("Start Winter Campaign.");
- game.active = game.winter_campaign;
- game.state = 'winter_campaign';
- } else {
- log("Start Winter.");
- end_winter_campaign();
- }
+ log("Start Winter of " + game.year + ".");
+ if (game.winter_campaign)
+ winter_siege_attrition();
+ else
+ goto_winter_2();
}
-states.winter_campaign = {
- prompt: function (view, current) {
- if (is_inactive_player(current))
- return view.prompt = "Winter Campaign: Waiting for " + game.active + ".";
- view.prompt = "Winter Campaign: Select a siege to maintain over the winter.";
- gen_action(view, 'pass');
- for (let town in TOWNS)
- if (is_friendly_field(town) && is_under_siege(town))
- gen_action(view, 'town', town);
- },
- town: function (where) {
- log(game.active + " maintain siege of " + where + ".");
- game.winter_campaign = where;
- game.where = where;
+function winter_siege_attrition() {
+ log(game.active + " winter campaign in " + game.winter_campaign + ".");
+ game.where = game.winter_campaign;
- let target = (game.where == TYRE || game.where == TRIPOLI) ? 2 : 4;
- for (let b in BLOCKS) {
- if (is_block_in_castle_in(b, game.where)) {
- let die = roll_d6();
- if (die <= target) {
- log("Attrition roll " + DIE_HIT[die] + ".");
- reduce_block(b);
- } else {
- log("Attrition roll " + DIE_MISS[die] + ".");
- }
+ let target = (game.where == TYRE || game.where == TRIPOLI) ? 2 : 4;
+ for (let b in BLOCKS) {
+ if (is_block_in_castle_in(b, game.where)) {
+ let die = roll_d6();
+ if (die <= target) {
+ log("Attrition roll " + DIE_HIT[die] + ".");
+ reduce_block(b);
+ } else {
+ log("Attrition roll " + DIE_MISS[die] + ".");
}
}
+ }
- if (!is_under_siege(game.where)) {
- log(game.where + " falls to siege attrition.");
- goto_regroup();
- } else {
- log("Siege continues.");
- end_winter_campaign();
- }
- },
- pass: function () {
- log(game.active + " decline to winter campaign.");
- game.winter_campaign = null;
- end_winter_campaign();
- },
+ if (!is_under_siege(game.where)) {
+ log(game.where + " falls to siege attrition.");
+ goto_regroup();
+ } else {
+ log("Siege continues.");
+ game.where = null;
+ goto_winter_2();
+ }
}
-function end_winter_campaign() {
+function goto_winter_2() {
eliminate_besieging_blocks(FRANKS);
eliminate_besieging_blocks(SARACENS);
lift_all_sieges();
@@ -3128,8 +3155,6 @@ function eliminate_besieging_blocks(owner) {
game.summary = null;
}
-// WINTER SUPPLY
-
function need_winter_supply_check() {
for (let town in TOWNS) {
if (town == game.winter_campaign)
@@ -3468,6 +3493,7 @@ exports.view = function(state, current) {
year: game.year,
turn: game.turn,
active: game.active,
+ p1: game.p1,
f_vp: game.f_vp,
s_vp: game.s_vp,
f_card: (game.show_cards || current == FRANKS) ? game.f_card : 0,
@@ -3487,6 +3513,8 @@ exports.view = function(state, current) {
if (game.jihad && game.jihad != game.p1)
view.jihad = game.jihad;
+ if (game.winter_campaign && game.winter_campaign != game.p1 && game.winter_campaign != game.p2)
+ view.winter_campaign = game.winter_campaign;
states[game.state].prompt(view, current);
diff --git a/ui.js b/ui.js
index 6c99613..4930ce7 100644
--- a/ui.js
+++ b/ui.js
@@ -226,6 +226,7 @@ function on_click_card(evt) {
function on_button_next(evt) { send_action('next'); }
function on_button_pass(evt) { send_action('pass'); }
function on_button_undo(evt) { send_action('undo'); }
+function on_button_winter_campaign(evt) { send_action('winter_campaign'); }
function on_button_group_move(evt) { send_action('group_move'); }
function on_button_end_group_move(evt) { send_action('end_group_move'); }
function on_button_sea_move(evt) { send_action('sea_move'); }
@@ -590,8 +591,16 @@ function update_map() {
known = "";
element.classList = info.owner + known + " block" + image + steps + moved;
} else {
- let besieging = (game.sieges[town] == info.owner) ? " besieging" : "";
- let jihad = (game.jihad == town) ? " jihad" : "";
+ let besieging = "";
+ if (game.sieges[town] == info.owner) {
+ if (game.winter_campaign == town)
+ besieging = " winter_campaign";
+ else
+ besieging = " besieging";
+ }
+ let jihad = "";
+ if (game.jihad == town && info.owner == game.p1)
+ jihad = " jihad";
element.classList = info.owner + " block" + moved + besieging + jihad;
}
if (info.owner == FRANKS)
@@ -626,10 +635,8 @@ function update_map() {
if (game.who)
ui.blocks[game.who].classList.add('selected');
}
- for (let b of game.castle) {
+ for (let b of game.castle)
ui.blocks[b].classList.add('castle');
- ui.battle_block[b].classList.add('castle');
- }
}
function update_card_display(element, card, prior_card) {
@@ -790,6 +797,7 @@ function on_update() {
show_action_button("#next_button", "next");
show_action_button("#pass_button", "pass");
show_action_button("#undo_button", "undo");
+ show_action_button("#winter_campaign_button", "winter_campaign");
show_action_button("#group_move_button", "group_move");
show_action_button("#end_group_move_button", "end_group_move");
show_action_button("#sea_move_button", "sea_move");