summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2021-06-09 13:26:58 +0200
committerTor Andersson <tor@ccxvii.net>2023-02-18 12:12:42 +0100
commite1497ab0dacf979dd9bdb19db0eb860bbfc2361d (patch)
tree4e3293123b95ce8e6b725b0859db62dc5913923f
parente24c6f04917f0aa06dbbd2f0f41742a374ea7d79 (diff)
downloadshores-of-tripoli-e1497ab0dacf979dd9bdb19db0eb860bbfc2361d.tar.gz
tripoli: Land Battle events.
-rw-r--r--play.html7
-rw-r--r--rules.js469
2 files changed, 298 insertions, 178 deletions
diff --git a/play.html b/play.html
index dfb8d28..fdeb7fd 100644
--- a/play.html
+++ b/play.html
@@ -252,6 +252,13 @@
<div class="menu_item" onclick="window.open('info/us_cards.html', '_blank')">United States Cards</div>
<div class="menu_separator"></div>
<div class="menu_item" onclick="confirm_resign()">Resign</div>
+ <div class="menu_separator"></div>
+ <div class="menu_item" onclick="send_save()">Save</div>
+ <div class="menu_item" onclick="send_restore()">Restore</div>
+ <div class="menu_separator"></div>
+ <div class="menu_item" onclick="send_restart()">Restart</div>
+ <div class="menu_item" onclick="send_restart(1804)">Restart 1804</div>
+ <div class="menu_item" onclick="send_restart(1805)">Restart 1805</div>
</div>
</div>
diff --git a/rules.js b/rules.js
index 5b83ff4..8a4559c 100644
--- a/rules.js
+++ b/rules.js
@@ -1,38 +1,4 @@
"use strict";
-// Tribute Paid
-
-// RULES QUESTIONS:
-
-// A Show of Force -- can play with fewer than 3 available frigates?
-// Burn the Philadelphia and others -- damaged frigates in 1806, to supply or virtual 1807 box?
-// General Eaton Attacks Derne/Benghazi -- should American gunboats participate?
-// Bainbridge Supplies Intel -- can you play it to pick up itself in order to pass without spending cards?
-// Assault on Tripoli -- can you play if benghazi not captured and no send in the marines?
-
-// Battle Card timing:
-
-// us: before interception roll
-// tr: after interception roll
-// tr: before pirate raid
-// tr: after pirate raid
-
-// us: before naval battle
-// tr: before naval battle
-// us: before land battle
-// tr: before land battle
-
-// us: own reaction: burn the philadelphia
-// us: own reaction: launch the intrepid
-// us: own reaction: assault on tripoli
-// tr: own reaction: philadelphia runs aground
-
-// BATTLE CARDS HANDLED:
-// US: THE_DARING_STEPHEN_DECATUR
-// TR: UNCHARTED_WATERS
-// US: LIEUTENANT_STERETT_IN_PURSUIT
-// TR: US_SIGNAL_BOOKS_OVERBOARD
-// TR: HAPPY_HUNTING
-// TR: MERCHANT_SHIP_CONVERTED
const US = "United States";
const TR = "Tripolitania";
@@ -279,12 +245,6 @@ const REMOVE_AFTER_PLAY = [
LAUNCH_THE_INTREPID,
GENERAL_EATON_ATTACKS_DERNE,
GENERAL_EATON_ATTACKS_BENGHAZI,
- LIEUTENANT_STERETT_IN_PURSUIT,
- PREBLES_BOYS_TAKE_AIM,
- THE_DARING_STEPHEN_DECATUR,
- SEND_IN_THE_MARINES,
- LIEUTENANT_OBANNON_LEADS_THE_CHARGE,
- MARINE_SHARPSHOOTERS,
YUSUF_QARAMANLI,
MURAD_REIS_BREAKS_OUT,
CONSTANTINOPLE_SENDS_AID,
@@ -294,12 +254,6 @@ const REMOVE_AFTER_PLAY = [
ALGIERS_DECLARES_WAR,
MOROCCO_DECLARES_WAR,
TUNIS_DECLARES_WAR,
- US_SIGNAL_BOOKS_OVERBOARD,
- UNCHARTED_WATERS,
- MERCHANT_SHIP_CONVERTED,
- HAPPY_HUNTING,
- THE_GUNS_OF_TRIPOLI,
- MERCENARIES_DESERT,
];
const states = {};
@@ -404,7 +358,7 @@ function discard_random_card(hand, discard) {
return c;
}
-function is_card_unplayed(card) {
+function is_not_removed(card) {
return game.us.hand.includes(card) ||
game.us.deck.includes(card) ||
game.us.discard.includes(card) ||
@@ -467,37 +421,37 @@ function move_all_pieces(list, from, to) {
}
}
-function fire_3(what, n) {
+function fire_3(what, n, hit_on = 6) {
let hits = 0;
for (let i = 0; i < n; ++i) {
let a = roll_d6();
let b = roll_d6();
let c = roll_d6();
- if (a == 6) ++hits;
- if (b == 6) ++hits;
- if (c == 6) ++hits;
+ if (a >= hit_on) ++hits;
+ if (b >= hit_on) ++hits;
+ if (c >= hit_on) ++hits;
log(what + " fires " + a + ", " + b + ", " + c + ".");
}
return hits;
}
-function fire_2(what, n) {
+function fire_2(what, n, hit_on = 6) {
let hits = 0;
for (let i = 0; i < n; ++i) {
let a = roll_d6();
let b = roll_d6();
- if (a == 6) ++hits;
- if (b == 6) ++hits;
+ if (a >= hit_on) ++hits;
+ if (b >= hit_on) ++hits;
log(what + " fires " + a + ", " + b + ".");
}
return hits;
}
-function fire_1(what, n) {
+function fire_1(what, n, hit_on = 6) {
let hits = 0;
for (let i = 0; i < n; ++i) {
let roll = roll_d6();
- if (roll == 6) ++hits;
+ if (roll >= hit_on) ++hits;
log(what + " fires " + roll + ".");
}
return hits;
@@ -868,12 +822,10 @@ function take_gold(n) {
function goto_pirate_raid(harbor, patrol_zone) {
game.where = patrol_zone;
- if (count_american_frigates(patrol_zone) > 0) {
- if (is_card_unplayed(LIEUTENANT_STERETT_IN_PURSUIT)) {
- game.active = US;
- game.state = 'raid_before_intercept';
- return;
- }
+ if (can_play_lieutenant_sterett_in_pursuit()) {
+ game.active = US;
+ game.state = 'raid_before_intercept';
+ return;
}
goto_pirate_raid_intercept();
}
@@ -884,9 +836,8 @@ states.raid_before_intercept = {
if (is_inactive_player(current))
return view.prompt;
view.prompt += " You may play \"Lieutenant Sterett in Pursuit\".";
- if (game.us.hand.includes(LIEUTENANT_STERETT_IN_PURSUIT)) {
+ if (game.us.hand.includes(LIEUTENANT_STERETT_IN_PURSUIT))
gen_action(view, 'card_event', LIEUTENANT_STERETT_IN_PURSUIT);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -904,43 +855,31 @@ function goto_pirate_raid_intercept(us_dice) {
let patrol_zone = game.where;
let harbor = HARBOR[patrol_zone];
interception_roll(harbor, patrol_zone, us_dice);
- if (count_corsairs(harbor) > 0) {
- if (is_card_unplayed(HAPPY_HUNTING)) {
- game.state = 'raid_before_hunt';
- return;
- }
+ if (can_play_happy_hunting(harbor)) {
+ game.state = 'raid_before_hunt';
+ return;
}
- if (count_american_frigates(patrol_zone) > 0) {
- if (is_card_unplayed(US_SIGNAL_BOOKS_OVERBOARD)) {
- game.state = 'raid_before_hunt';
- return;
- }
+ if (can_play_us_signal_books_overboard(patrol_zone)) {
+ game.state = 'raid_before_hunt';
+ return;
}
goto_pirate_raid_hunt();
}
states.raid_before_hunt = {
prompt: function (view, current) {
- let patrol_zone = game.where;
- let harbor = HARBOR[patrol_zone];
view.prompt = "Pirate Raid in " + SPACES[game.where] + ".";
if (is_inactive_player(current))
return view.prompt;
- if (count_corsairs(harbor) > 0) {
- if (is_card_unplayed(HAPPY_HUNTING)) {
- view.prompt += " You may play \"Happy Hunting\".";
- if (game.tr.hand.includes(HAPPY_HUNTING)) {
- gen_action(view, 'card_event', HAPPY_HUNTING);
- }
- }
+ if (can_play_happy_hunting()) {
+ view.prompt += " You may play \"Happy Hunting\".";
+ if (game.tr.hand.includes(HAPPY_HUNTING))
+ gen_action(view, 'card_event', HAPPY_HUNTING);
}
- if (count_american_frigates(patrol_zone) > 0) {
- if (is_card_unplayed(US_SIGNAL_BOOKS_OVERBOARD)) {
- view.prompt += " You may play \"US Signal Books Overboard\".";
- if (game.tr.hand.includes(US_SIGNAL_BOOKS_OVERBOARD)) {
- gen_action(view, 'card_event', US_SIGNAL_BOOKS_OVERBOARD);
- }
- }
+ if (can_play_us_signal_books_overboard()) {
+ view.prompt += " You may play \"US Signal Books Overboard\".";
+ if (game.tr.hand.includes(US_SIGNAL_BOOKS_OVERBOARD))
+ gen_action(view, 'card_event', US_SIGNAL_BOOKS_OVERBOARD);
}
gen_action(view, 'next');
},
@@ -972,11 +911,9 @@ function goto_pirate_raid_hunt(happy_hunting) {
give_gold(merchants);
if (check_gold_victory())
return;
- if (merchants > 0 && count_tripolitan_corsairs(TRIPOLITAN_SUPPLY) > 0) {
- if (is_card_unplayed(MERCHANT_SHIP_CONVERTED)) {
- game.state = 'raid_after_hunt';
- return;
- }
+ if (can_play_merchant_ship_converted(merchants)) {
+ game.state = 'raid_after_hunt';
+ return;
}
end_pirate_raid();
}
@@ -987,9 +924,8 @@ states.raid_after_hunt = {
if (is_inactive_player(current))
return view.prompt;
view.prompt += " You may play \"Merchant Ship Converted\".";
- if (game.tr.hand.includes(MERCHANT_SHIP_CONVERTED)) {
+ if (game.tr.hand.includes(MERCHANT_SHIP_CONVERTED))
gen_action(view, 'card_event', MERCHANT_SHIP_CONVERTED);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -1092,7 +1028,7 @@ states.move_us_frigate_to = {
function goto_allocate_gunboats() {
if (count_american_gunboats(MALTA_HARBOR) == 0)
- return goto_select_combat();
+ return goto_select_battle();
game.where = MALTA_HARBOR;
game.state = 'allocate_gunboats';
}
@@ -1117,24 +1053,24 @@ states.allocate_gunboats = {
},
next: function () {
game.where = null;
- goto_select_combat();
+ goto_select_battle();
},
undo: pop_undo
}
-function goto_select_combat() {
+function goto_select_battle() {
clear_undo();
game.where = null;
game.active = US;
if (count_naval_battle_or_bombardment_locations() > 0)
- game.state = 'select_combat';
+ game.state = 'select_battle';
else
end_american_play();
}
-states.select_combat = {
+states.select_battle = {
prompt: function (view, current) {
- view.prompt = "United States: Pick the next naval combat or bombardment."
+ view.prompt = "United States: Pick the next naval battle or bombardment."
if (is_inactive_player(current))
return view.prompt;
for (let space of BATTLE_SPACES)
@@ -1153,7 +1089,6 @@ states.select_combat = {
function goto_naval_bombardment(space) {
game.where = space;
- log("Naval bombardment in " + SPACES[game.where] + ".");
naval_bombardment_round();
end_naval_bombardment();
}
@@ -1161,23 +1096,24 @@ function goto_naval_bombardment(space) {
function naval_bombardment_round() {
let n_frigates = count_american_frigates(game.where);
let n_gunboats = count_american_gunboats(game.where);
- let n_infantry = count_tripolitan_infantry(game.where);
-
- let n_hits = 0;
- n_hits += fire_2("American frigate", n_frigates);
- n_hits += fire_1("American gunboat", n_gunboats);
- if (n_hits > n_infantry)
- n_hits = n_infantry;
-
- log(n_hits + " Tripolitan infantry eliminated.");
- for (let i = 0; i < n_hits; ++i)
- move_one_piece(TR_INFANTRY, game.where, TRIPOLITAN_SUPPLY);
+ if (n_frigates + n_gunboats > 0) {
+ let n_infantry = count_tripolitan_infantry(game.where);
+ let n_hits = 0;
+ log("Naval Bombardment in " + SPACES[game.where] + ".");
+ n_hits += fire_2("American frigate", n_frigates);
+ n_hits += fire_1("American gunboat", n_gunboats);
+ if (n_hits > n_infantry)
+ n_hits = n_infantry;
+ log(n_hits + " Tripolitan infantry eliminated.");
+ for (let i = 0; i < n_hits; ++i)
+ move_one_piece(TR_INFANTRY, game.where, TRIPOLITAN_SUPPLY);
+ }
}
function end_naval_bombardment() {
move_all_pieces(US_FRIGATES, game.where, MALTA_HARBOR);
move_all_pieces(US_GUNBOATS, game.where, MALTA_HARBOR);
- goto_select_combat();
+ goto_select_battle();
}
// NAVAL BATTLE
@@ -1191,12 +1127,10 @@ function goto_naval_battle(space) {
function goto_naval_battle_american_card() {
game.prebles_boys_take_aim = false;
- if (BATTLE_SPACES.includes(game.where)) {
- if (is_card_unplayed(PREBLES_BOYS_TAKE_AIM)) {
- game.active = US;
- game.state = 'naval_battle_american_card';
- return;
- }
+ if (can_play_prebles_boys_take_aim()) {
+ game.active = US;
+ game.state = 'naval_battle_american_card';
+ return;
}
goto_naval_battle_tripolitan_card();
}
@@ -1207,9 +1141,8 @@ states.naval_battle_american_card = {
if (is_inactive_player(current))
return;
view.prompt += " You may play \"Preble's Boys Take Aim\".";
- if (game.us.hand.includes(PREBLES_BOYS_TAKE_AIM)) {
+ if (game.us.hand.includes(PREBLES_BOYS_TAKE_AIM))
gen_action(view, 'card_event', PREBLES_BOYS_TAKE_AIM);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -1224,13 +1157,10 @@ states.naval_battle_american_card = {
function goto_naval_battle_tripolitan_card() {
game.the_guns_of_tripoli = false;
- if (game.where == TRIPOLI_HARBOR) {
- if (is_card_unplayed(THE_GUNS_OF_TRIPOLI)) {
- game.save_active = game.active;
- game.active = TR;
- game.state = 'naval_battle_tripolitan_card';
- return;
- }
+ if (can_play_the_guns_of_tripoli()) {
+ game.active = TR;
+ game.state = 'naval_battle_tripolitan_card';
+ return;
}
goto_naval_battle_round();
}
@@ -1241,9 +1171,8 @@ states.naval_battle_tripolitan_card = {
if (is_inactive_player(current))
return;
view.prompt += " You may play \"The Guns of Tripoli\".";
- if (game.tr.hand.includes(THE_GUNS_OF_TRIPOLI)) {
+ if (game.tr.hand.includes(THE_GUNS_OF_TRIPOLI))
gen_action(view, 'card_event', THE_GUNS_OF_TRIPOLI);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -1461,14 +1390,14 @@ function end_naval_battle() {
end_tripolitan_play();
break;
default:
- goto_select_combat();
+ goto_select_battle();
break;
}
}
-// GROUND COMBAT
+// LAND BATTLE
-states.ground_combat_move_frigates = {
+states.land_battle_move_frigates = {
prompt: function (view, current) {
view.prompt = "United States: " + CARD_NAMES[game.active_card] + ".";
if (is_inactive_player(current))
@@ -1491,64 +1420,150 @@ states.ground_combat_move_frigates = {
next: function () {
let n = count_american_frigates(game.where);
log(n + " American frigates move to " + SPACES[game.where] + ".");
- goto_ground_combat_bombard();
+ goto_land_battle();
},
undo: pop_undo
}
-function goto_ground_combat_bombard() {
+function goto_land_battle() {
naval_bombardment_round();
- // TODO: play battle events
- goto_ground_combat_round();
+
+ log("Land Battle in " + SPACES[game.where] + ".");
+
+ goto_land_battle_american_card();
}
-function apply_tr_hits(n) {
- let max = count_tripolitan_infantry(game.where);
- if (n > max)
- n = max;
- log(n + " Tripolitan infantry eliminated.");
- for (let i = 0; i < n; ++i)
- move_one_piece(TR_INFANTRY, game.where, TRIPOLITAN_SUPPLY);
+function goto_land_battle_american_card() {
+ game.marine_sharpshooters = false;
+ game.lieutenant_obannon_leads_the_charge = false;
+ if (can_play_american_land_battle_card()) {
+ game.active = US;
+ game.state = 'land_battle_american_card';
+ } else {
+ goto_land_battle_tripolitan_card();
+ }
}
-function apply_us_hits(total) {
- // TODO: let the player choose victims?
+states.land_battle_american_card = {
+ prompt: function (view, current) {
+ view.prompt = "Land Battle in " + SPACES[game.where] + ".";
+ if (is_inactive_player(current))
+ return;
+ let options = [];
+ if (can_play_send_in_the_marines()) {
+ options.push("\"Send in the Marines\"");
+ if (game.us.hand.includes(SEND_IN_THE_MARINES))
+ gen_action(view, 'card_event', SEND_IN_THE_MARINES);
+ }
+ if (can_play_marine_sharpshooters()) {
+ options.push("\"Marine Sharpshooters\"");
+ if (game.us.hand.includes(MARINE_SHARPSHOOTERS))
+ gen_action(view, 'card_event', MARINE_SHARPSHOOTERS);
+ }
+ if (can_play_lieutenant_obannon_leads_the_charge()) {
+ options.push("\"Lieutenant O'Bannon Leads the Charge\"");
+ if (game.us.hand.includes(LIEUTENANT_OBANNON_LEADS_THE_CHARGE))
+ gen_action(view, 'card_event', LIEUTENANT_OBANNON_LEADS_THE_CHARGE);
+ }
+ view.prompt += " You may play " + options.join(", ") + ".";
+ gen_action(view, 'next');
+ },
+ card_event: function (card) {
+ play_battle_card(game.us, card);
+ switch (card) {
+ case SEND_IN_THE_MARINES:
+ move_one_piece(US_MARINES, UNITED_STATES_SUPPLY, TRIPOLI_HARBOR);
+ move_one_piece(US_MARINES, UNITED_STATES_SUPPLY, TRIPOLI_HARBOR);
+ move_one_piece(US_MARINES, UNITED_STATES_SUPPLY, TRIPOLI_HARBOR);
+ break;
+ case MARINE_SHARPSHOOTERS:
+ game.marine_sharpshooters = true;
+ break;
+ case LIEUTENANT_OBANNON_LEADS_THE_CHARGE:
+ game.lieutenant_obannon_leads_the_charge = true;
+ break;
+ }
+ if (!can_play_american_land_battle_card())
+ goto_land_battle_tripolitan_card();
+ },
+ next: function (card) {
+ goto_land_battle_tripolitan_card();
+ },
+}
- let n = total;
- let max_ar = count_arab_infantry(game.where);
- if (n > max_ar)
- n = max_ar;
- log(n + " Arab infantry eliminated.");
- for (let i = 0; i < n; ++i)
- move_one_piece(AR_INFANTRY, game.where, UNITED_STATES_SUPPLY);
+function goto_land_battle_tripolitan_card() {
+ if (can_play_mercenaries_desert()) {
+ game.active = TR;
+ game.state = 'land_battle_tripolitan_card';
+ } else {
+ goto_land_battle_round();
+ }
+}
- n = total - n;
- let max_us = count_american_marines(game.where);
- if (n > max_us)
- n = max_us;
- log(n + " American marines eliminated.");
- for (let i = 0; i < n; ++i)
- move_one_piece(US_MARINES, game.where, UNITED_STATES_SUPPLY);
+states.land_battle_tripolitan_card = {
+ prompt: function (view, current) {
+ view.prompt = "Land Battle in " + SPACES[game.where] + ".";
+ if (is_inactive_player(current))
+ return;
+ view.prompt += " You may play \"Mercenaries Desert\".";
+ if (game.tr.hand.includes(MERCENARIES_DESERT))
+ gen_action(view, 'card_event', MERCENARIES_DESERT);
+ gen_action(view, 'next');
+ },
+ card_event: function (card) {
+ play_battle_card(game.tr, MERCENARIES_DESERT);
+ let n = count_arab_infantry(game.where);
+ for (let i = 0; i < n; ++i) {
+ let roll = roll_d6();
+ log("Arab infantry rolls " + roll + ".");
+ if (roll == 6)
+ move_one_piece(AR_INFANTRY, game.where, UNITED_STATES_SUPPLY);
+ }
+ log("Deserters: " + (n - count_arab_infantry(game.where)) + ".");
+ goto_land_battle_round();
+ },
+ next: function (card) {
+ goto_land_battle_round();
+ },
}
-function goto_ground_combat_round() {
+function goto_land_battle_round() {
+ game.active = US;
for (;;) {
let n_us_mar = count_american_marines(game.where);
let n_ar_inf = count_arab_infantry(game.where);
let n_tr_inf = count_tripolitan_infantry(game.where);
- if (n_us_mar + n_ar_inf == 0)
+ if (n_us_mar + n_ar_inf == 0) {
+ delete game.marine_sharpshooters;
+ delete game.lieutenant_obannon_leads_the_charge;
return goto_game_over("Tripolitania wins by eliminating Hamet's army!");
+ }
if (n_tr_inf == 0) {
log("Americans have captured " + SPACES[game.where] + ".");
+ delete game.marine_sharpshooters;
+ delete game.lieutenant_obannon_leads_the_charge;
return end_american_play();
}
- log("Ground battle round.");
+ log("Land battle round.");
let n_tr_hits = 0;
- n_tr_hits += fire_1("American marine", n_us_mar);
+ if (game.lieutenant_obannon_leads_the_charge && n_us_mar > 0) {
+ if (game.marine_sharpshooters) {
+ n_tr_hits += fire_3("O'Bannon", 1, 5);
+ n_tr_hits += fire_1("American marine", n_us_mar - 1, 5);
+ } else {
+ n_tr_hits += fire_3("O'Bannon", 1, 6);
+ n_tr_hits += fire_1("American marine", n_us_mar - 1, 6);
+ }
+ } else {
+ if (game.marine_sharpshooters)
+ n_tr_hits += fire_1("American marine", n_us_mar, 5);
+ else
+ n_tr_hits += fire_1("American marine", n_us_mar, 6);
+ }
n_tr_hits += fire_1("Arab infantry", n_ar_inf);
let n_us_hits = fire_1("Tripolitan infantry", n_tr_inf);
@@ -1558,6 +1573,35 @@ function goto_ground_combat_round() {
}
}
+function apply_tr_hits(n) {
+ let max = count_tripolitan_infantry(game.where);
+ if (n > max)
+ n = max;
+ log(n + " Tripolitan infantry eliminated.");
+ for (let i = 0; i < n; ++i)
+ move_one_piece(TR_INFANTRY, game.where, TRIPOLITAN_SUPPLY);
+}
+
+function apply_us_hits(total) {
+ // TODO: let the player choose victims?
+
+ let n = total;
+ let max_ar = count_arab_infantry(game.where);
+ if (n > max_ar)
+ n = max_ar;
+ log(n + " Arab infantry eliminated.");
+ for (let i = 0; i < n; ++i)
+ move_one_piece(AR_INFANTRY, game.where, UNITED_STATES_SUPPLY);
+
+ n = total - n;
+ let max_us = count_american_marines(game.where);
+ if (n > max_us)
+ n = max_us;
+ log(n + " American marines eliminated.");
+ for (let i = 0; i < n; ++i)
+ move_one_piece(US_MARINES, game.where, UNITED_STATES_SUPPLY);
+}
+
// ASSAULT ON TRIPOLI
states.assault_on_tripoli = {
@@ -1645,6 +1689,7 @@ function play_yusuf_qaramanli() {
}
function resume_yusuf_qaramanli() {
+ game.where = null;
if (game.raids.length > 0)
game.state = 'yusuf_qaramanli';
else
@@ -1876,7 +1921,10 @@ function can_play_the_philadelphia_runs_aground() {
}
function play_the_philadelphia_runs_aground() {
- game.state = 'the_philadelphia_runs_aground';
+ if (can_play_uncharted_waters())
+ game.state = 'the_philadelphia_runs_aground';
+ else
+ end_the_philadelphia_runs_aground(false);
}
states.the_philadelphia_runs_aground = {
@@ -1885,9 +1933,8 @@ states.the_philadelphia_runs_aground = {
if (is_inactive_player(current))
return;
view.prompt += " You may play \"Uncharted Waters\".";
- if (game.tr.hand.includes(UNCHARTED_WATERS)) {
+ if (game.tr.hand.includes(UNCHARTED_WATERS))
gen_action(view, 'card_event', UNCHARTED_WATERS);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -2326,7 +2373,10 @@ function can_play_burn_the_philadelphia() {
}
function play_burn_the_philadelphia() {
- game.state = 'burn_the_philadelphia';
+ if (can_play_the_daring_stephen_decatur())
+ game.state = 'burn_the_philadelphia';
+ else
+ end_burn_the_philadelphia(false);
}
states.burn_the_philadelphia = {
@@ -2335,9 +2385,8 @@ states.burn_the_philadelphia = {
if (is_inactive_player(current))
return;
view.prompt += " You may play \"The Daring Stephen Decatur\".";
- if (game.us.hand.includes(THE_DARING_STEPHEN_DECATUR)) {
+ if (game.us.hand.includes(THE_DARING_STEPHEN_DECATUR))
gen_action(view, 'card_event', THE_DARING_STEPHEN_DECATUR);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -2384,7 +2433,10 @@ function can_play_launch_the_intrepid() {
}
function play_launch_the_intrepid() {
- game.state = 'launch_the_intrepid';
+ if (can_play_the_daring_stephen_decatur())
+ game.state = 'launch_the_intrepid';
+ else
+ end_launch_the_intrepid(false);
}
states.launch_the_intrepid = {
@@ -2393,9 +2445,8 @@ states.launch_the_intrepid = {
if (is_inactive_player(current))
return;
view.prompt += " You may play \"The Daring Stephen Decatur\".";
- if (game.us.hand.includes(THE_DARING_STEPHEN_DECATUR)) {
+ if (game.us.hand.includes(THE_DARING_STEPHEN_DECATUR))
gen_action(view, 'card_event', THE_DARING_STEPHEN_DECATUR);
- }
gen_action(view, 'next');
},
card_event: function (card) {
@@ -2458,7 +2509,7 @@ function play_general_eaton_attacks_derne() {
move_all_pieces(AR_INFANTRY, ALEXANDRIA_HARBOR, DERNE_HARBOR);
game.where = DERNE_HARBOR;
game.moves = 3;
- game.state = 'ground_combat_move_frigates';
+ game.state = 'land_battle_move_frigates';
}
function can_play_general_eaton_attacks_benghazi() {
@@ -2471,7 +2522,69 @@ function play_general_eaton_attacks_benghazi() {
move_all_pieces(AR_INFANTRY, DERNE_HARBOR, BENGHAZI_HARBOR);
game.where = BENGHAZI_HARBOR;
game.moves = 3;
- game.state = 'ground_combat_move_frigates';
+ game.state = 'land_battle_move_frigates';
+}
+
+// TRIPOLITAN BATTLE EVENTS
+
+function can_play_us_signal_books_overboard() {
+ let patrol_zone = game.where;
+ return (count_american_frigates(patrol_zone) > 0) && is_not_removed(US_SIGNAL_BOOKS_OVERBOARD);
+}
+
+function can_play_uncharted_waters() {
+ return is_not_removed(UNCHARTED_WATERS);
+}
+
+function can_play_merchant_ship_converted(merchants) {
+ return (merchants > 0) &&
+ (count_tripolitan_corsairs(TRIPOLITAN_SUPPLY) > 0) &&
+ is_not_removed(MERCHANT_SHIP_CONVERTED);
+}
+
+function can_play_happy_hunting() {
+ let harbor = HARBOR[game.where];
+ return (count_corsairs(harbor) > 0) && is_not_removed(HAPPY_HUNTING);
+}
+
+function can_play_the_guns_of_tripoli() {
+ return (game.where == TRIPOLI_HARBOR) && is_not_removed(THE_GUNS_OF_TRIPOLI);
+}
+
+function can_play_mercenaries_desert() {
+ return (count_arab_infantry(game.where) > 0) && is_not_removed(MERCENARIES_DESERT);
+}
+
+// AMERICAN BATTLE EVENTS
+
+function can_play_lieutenant_sterett_in_pursuit() {
+ return (count_american_frigates(game.where) > 0) && is_not_removed(LIEUTENANT_STERETT_IN_PURSUIT);
+}
+
+function can_play_prebles_boys_take_aim() {
+ return BATTLE_SPACES.includes(game.where) && is_not_removed(PREBLES_BOYS_TAKE_AIM);
+}
+
+function can_play_the_daring_stephen_decatur() {
+ return is_not_removed(THE_DARING_STEPHEN_DECATUR);
+}
+
+function can_play_send_in_the_marines() {
+ return game.active_card == ASSAULT_ON_TRIPOLI && is_not_removed(SEND_IN_THE_MARINES);
+}
+
+function can_play_lieutenant_obannon_leads_the_charge() {
+ return (count_american_marines(game.where) > 0) && is_not_removed(LIEUTENANT_OBANNON_LEADS_THE_CHARGE);
+}
+
+function can_play_marine_sharpshooters() {
+ return (count_american_marines(game.where) > 0) && is_not_removed(MARINE_SHARPSHOOTERS);
+}
+
+function can_play_american_land_battle_card() {
+ return can_play_send_in_the_marines() ||
+ can_play_marine_sharpshooters() ||
+ can_play_lieutenant_obannon_leads_the_charge();
}
// VICTORY