summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-05-25 13:09:01 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-16 19:19:39 +0100
commit4ac1a15288a36ca0651984080af74454e1531d3e (patch)
tree80c159ad2513e0765cede5124b2f739aef2deeea
parenta5056f8f5d3b9db6998758e11fc6886af711dbb5 (diff)
downloadcrusader-rex-4ac1a15288a36ca0651984080af74454e1531d3e.tar.gz
Past tense.
-rw-r--r--data.js42
-rw-r--r--play.js4
-rw-r--r--rules.js199
3 files changed, 95 insertions, 150 deletions
diff --git a/data.js b/data.js
index 56a1d85..ad35be3 100644
--- a/data.js
+++ b/data.js
@@ -7,27 +7,27 @@ const CARDS = {
4: { name: "Jihad", event: "jihad", image: "card_jihad" },
5: { name: "Manna", event: "manna", image: "card_manna" },
6: { name: "Winter Campaign", moves: 1, image: "card_winter_campaign" },
- 7: { name: "3", moves: 3, image: "card_3" },
- 8: { name: "3", moves: 3, image: "card_3" },
- 9: { name: "3", moves: 3, image: "card_3" },
- 10: { name: "3", moves: 3, image: "card_3" },
- 11: { name: "3", moves: 3, image: "card_3" },
- 12: { name: "3", moves: 3, image: "card_3" },
- 13: { name: "2", moves: 2, image: "card_2" },
- 14: { name: "2", moves: 2, image: "card_2" },
- 15: { name: "2", moves: 2, image: "card_2" },
- 16: { name: "2", moves: 2, image: "card_2" },
- 17: { name: "2", moves: 2, image: "card_2" },
- 18: { name: "2", moves: 2, image: "card_2" },
- 19: { name: "2", moves: 2, image: "card_2" },
- 20: { name: "2", moves: 2, image: "card_2" },
- 21: { name: "2", moves: 2, image: "card_2" },
- 22: { name: "1", moves: 1, image: "card_1" },
- 23: { name: "1", moves: 1, image: "card_1" },
- 24: { name: "1", moves: 1, image: "card_1" },
- 25: { name: "1", moves: 1, image: "card_1" },
- 26: { name: "1", moves: 1, image: "card_1" },
- 27: { name: "1", moves: 1, image: "card_1" },
+ 7: { name: "a 3", moves: 3, image: "card_3" },
+ 8: { name: "a 3", moves: 3, image: "card_3" },
+ 9: { name: "a 3", moves: 3, image: "card_3" },
+ 10: { name: "a 3", moves: 3, image: "card_3" },
+ 11: { name: "a 3", moves: 3, image: "card_3" },
+ 12: { name: "a 3", moves: 3, image: "card_3" },
+ 13: { name: "a 2", moves: 2, image: "card_2" },
+ 14: { name: "a 2", moves: 2, image: "card_2" },
+ 15: { name: "a 2", moves: 2, image: "card_2" },
+ 16: { name: "a 2", moves: 2, image: "card_2" },
+ 17: { name: "a 2", moves: 2, image: "card_2" },
+ 18: { name: "a 2", moves: 2, image: "card_2" },
+ 19: { name: "a 2", moves: 2, image: "card_2" },
+ 20: { name: "a 2", moves: 2, image: "card_2" },
+ 21: { name: "a 2", moves: 2, image: "card_2" },
+ 22: { name: "a 1", moves: 1, image: "card_1" },
+ 23: { name: "a 1", moves: 1, image: "card_1" },
+ 24: { name: "a 1", moves: 1, image: "card_1" },
+ 25: { name: "a 1", moves: 1, image: "card_1" },
+ 26: { name: "a 1", moves: 1, image: "card_1" },
+ 27: { name: "a 1", moves: 1, image: "card_1" },
};
const BLOCKS = {};
diff --git a/play.js b/play.js
index 586feea..216bbb3 100644
--- a/play.js
+++ b/play.js
@@ -63,9 +63,9 @@ function on_log(text) {
if (text.match(/^~ .* ~$/))
p.className = 'br', text = text.substring(2, text.length-2);
- else if (text.match(/^Start Frank turn/))
+ else if (text.match(/^Start Franks/))
p.className = 'F';
- else if (text.match(/^Start Saracen turn/))
+ else if (text.match(/^Start Saracens/))
p.className = 'S';
else if (text.match(/^Start /))
p.className = 'st', text = text.replace(/\.$/, "");
diff --git a/rules.js b/rules.js
index cf1b276..faaedd9 100644
--- a/rules.js
+++ b/rules.js
@@ -1,6 +1,5 @@
"use strict";
-// TODO: optional rule - iron bridge
// TODO: optional rule - force marches
// TODO: 6.2 - In Sieges, the attacker /may/ retreat or stay on siege.
@@ -86,8 +85,7 @@ function random(n) {
return Math.floor(((game.seed = game.seed * 48271 % 0x7fffffff) / 0x7fffffff) * n);
}
-function log(...args) {
- let s = Array.from(args).join("");
+function log(s) {
game.log.push(s);
}
@@ -250,10 +248,6 @@ function select_random_enemy_block(where) {
return list[random(list.length)];
}
-function block_plural(who) {
- return BLOCKS[who].plural;
-}
-
function block_name(who) {
if (BLOCKS[who].type === 'nomads')
return BLOCKS[who].name;
@@ -985,10 +979,7 @@ function eliminate_block(who) {
remove_from_array(game.castle, who);
if (game.sallying) remove_from_array(game.sallying, who);
if (game.storming) remove_from_array(game.storming, who);
- if (block_plural(who))
- log(block_name(who) + " are eliminated.");
- else
- log(block_name(who) + " is eliminated.");
+ log(block_name(who) + " was eliminated.");
if (is_saladin_family(who) || block_type(who) === 'crusaders' || block_type(who) === 'military_orders')
game.location[who] = null; // permanently eliminated
else
@@ -1073,7 +1064,7 @@ states.frank_deployment_to = {
function goto_saracen_deployment() {
for (let i = 0; i < 4; ++i) {
let nomad = select_random_block(S_POOL);
- log(BLOCKS[nomad].name + " arrive in " + block_home(nomad) + ".");
+ log(BLOCKS[nomad].name + " arrived in " + block_home(nomad) + ".");
deploy(nomad, block_home(nomad));
}
game.active = SARACENS;
@@ -1135,7 +1126,7 @@ function check_sudden_death() {
if (count_victory_points(FRANKS) === 7) {
game.state = 'game_over';
game.result = FRANKS;
- game.victory = "Franks control all seven victory cities."
+ game.victory = "Franks controlled all seven victory cities."
log("");
log(game.victory);
return true;
@@ -1143,7 +1134,7 @@ function check_sudden_death() {
if (count_victory_points(SARACENS) === 7) {
game.state = 'game_over';
game.result = SARACENS;
- game.victory = "Saracens control all seven victory cities."
+ game.victory = "Saracens controlled all seven victory cities."
log("");
log(game.victory);
return true;
@@ -1152,7 +1143,7 @@ function check_sudden_death() {
function start_year() {
log("");
- log("Start Year " + game.year + ".");
+ log("Start Year " + game.year);
game.turn = 1;
@@ -1167,7 +1158,7 @@ function start_year() {
function start_game_turn() {
log("");
- log("Start Turn ", game.turn, " of Year ", game.year, ".");
+ log("Start Turn " + game.turn + " of Year " + game.year);
game.guide = null;
game.jihad = null;
@@ -1264,12 +1255,12 @@ states.play_card = {
function reveal_cards() {
log("");
- log("Franks play " + CARDS[game.f_card].name + ".");
- log("Saracens play " + CARDS[game.s_card].name + ".");
+ log("Franks played " + CARDS[game.f_card].name + ".");
+ log("Saracens played " + CARDS[game.s_card].name + ".");
game.show_cards = true;
if (CARDS[game.f_card].event && CARDS[game.s_card].event) {
- log("Game Turn is cancelled.");
+ log("Game Turn cancelled.");
game.prior_f_card = game.f_card;
game.prior_s_card = game.s_card;
end_game_turn();
@@ -1278,11 +1269,11 @@ function reveal_cards() {
if (game.f_card === INTRIGUE) {
game.f_card = game.prior_s_card;
- log("Intrigue copies " + CARDS[game.f_card].name + ".");
+ log("Intrigue copied " + CARDS[game.f_card].name + ".");
}
if (game.s_card === INTRIGUE) {
game.s_card = game.prior_f_card;
- log("Intrigue copies " + CARDS[game.s_card].name + ".");
+ log("Intrigue copied " + CARDS[game.s_card].name + ".");
}
delete game.winter_campaign;
@@ -1322,7 +1313,7 @@ function reveal_cards() {
function start_player_turn() {
log("");
- log("Start " + active_adjective() + " turn.");
+ log("Start " + game.active);
reset_road_limits();
game.main_road = {};
let card = CARDS[game.active === FRANKS ? game.f_card : game.s_card];
@@ -1516,7 +1507,7 @@ states.manna = {
},
next: function () {
clear_undo();
- print_summary(game.active + " use Manna:");
+ print_summary(game.active + " used Manna:");
game.moved = {};
end_player_turn();
},
@@ -1618,9 +1609,9 @@ states.confirm_end_move_phase = {
},
end_move_phase: function () {
if (game.moves === 1)
- log(game.active + " do nothing with " + game.moves + " move.");
+ log(game.active + " did nothing with " + game.moves + " move.");
else
- log(game.active + " do nothing with " + game.moves + " moves.");
+ log(game.active + " did nothing with " + game.moves + " moves.");
game.moves = 0;
end_move_phase();
},
@@ -1864,7 +1855,7 @@ function end_move() {
}
function end_group_move() {
- print_summary(game.active + " activate " + game.where + ":");
+ print_summary(game.active + " activated " + game.where + ":");
game.state = 'move_phase';
}
@@ -1889,9 +1880,9 @@ states.german_move_to = {
game.distance = 0;
let mark = move_block(game.who, from, to);
if (mark)
- log(game.active + " move:\n Germania \u2192 " + to + mark + ".");
+ log(game.active + " moved:\n Germania \u2192 " + to + mark + ".");
else
- log(game.active + " move:\n Germania \u2192 " + to + ".");
+ log(game.active + " moved:\n Germania \u2192 " + to + ".");
game.who = null;
game.state = 'move_phase';
},
@@ -1934,17 +1925,17 @@ states.sea_move_to = {
if (besieged_player(to) === game.active && is_more_room_in_castle(to)) {
// Move into besieged fortified port
game.castle.push(game.who);
- log(game.active + " sea move:\n" + from + " \u2192 " + to + " castle.");
+ log(game.active + " sea moved:\n" + from + " \u2192 " + to + " castle.");
} else if (!is_friendly_port(to)) {
// English Crusaders attack!
game.attacker[to] = FRANKS;
game.main_road[to] = "England";
- log(game.active + " sea move:\n" + from + " \u2192 " + to + ATTACK_MARK + ".");
+ log(game.active + " sea moved:\n" + from + " \u2192 " + to + ATTACK_MARK + ".");
} else {
// Normal move.
- log(game.active + " sea move:\n" + from + " \u2192 " + to + ".");
+ log(game.active + " sea moved:\n" + from + " \u2192 " + to + ".");
}
game.who = null;
@@ -2002,7 +1993,7 @@ states.muster_who = {
game.state = 'muster_move_1';
},
end_muster: function () {
- print_summary(game.active + " muster to " + game.where + ":");
+ print_summary(game.active + " mustered to " + game.where + ":");
game.where = null;
game.state = 'move_phase';
},
@@ -2134,7 +2125,7 @@ states.winter_campaign = {
gen_action(view, 'town', town);
},
town: function (where) {
- log(game.active + " winter campaign in " + where + ".");
+ log(game.active + " winter campaigned in " + where + ".");
game.winter_campaign = where;
game.state = 'move_phase';
},
@@ -2186,7 +2177,7 @@ states.combat_phase = {
function start_combat() {
game.flash = "";
log("");
- log("Battle in " + game.where + ".");
+ log("Battle in " + game.where);
game.combat_round = 0;
game.halfhit = null;
game.storming = [];
@@ -2206,7 +2197,7 @@ function start_combat() {
game.castle_owner = besieged_player(game.where);
if (!game.attacker[game.where])
game.attacker[game.where] = enemy(game.castle_owner);
- log("Existing siege continues.");
+ log("Existing siege continued.");
game.is_existing_siege = 1;
next_combat_round();
}
@@ -2274,9 +2265,9 @@ states.combat_deployment = {
clear_undo();
let n = count_blocks_in_castle(game.where);
if (n === 1)
- log(game.active + " withdraw 1 block.");
+ log(game.active + " withdrew 1 block.");
else
- log(game.active + " withdraw " + n + " blocks.");
+ log(game.active + " withdrew " + n + " blocks.");
game.active = game.attacker[game.where];
if (count_enemy_in_field_and_reserve(game.where) === 0) {
return goto_regroup();
@@ -2290,7 +2281,7 @@ states.combat_deployment = {
function print_retreat_summary() {
if (game.summary && game.summary.length > 0)
- print_summary("Retreats from " + game.where + ":");
+ print_summary("Retreated from " + game.where + ":");
}
function goto_regroup() {
@@ -2324,7 +2315,7 @@ states.regroup = {
},
end_regroup: function () {
clear_undo();
- print_summary(game.active + " regroup:", true);
+ print_summary(game.active + " regrouped:", true);
if (is_winter())
goto_winter_2();
else if (is_contested_town(game.where))
@@ -2390,9 +2381,9 @@ function bring_on_reserves(reserves) {
}
}
if (f > 0)
- log(f + " Frank " + (f === 1 ? "reserve arrives." : "reserves arrive."));
+ log(f + " Frank " + (f === 1 ? "reserve arrived." : "reserves arrived."));
if (s > 0)
- log(s + " Saracen " + (s === 1 ? "reserve arrives." : "reserves arrive."));
+ log(s + " Saracen " + (s === 1 ? "reserve arrived." : "reserves arrived."));
}
function clear_reserves(where) {
@@ -2438,7 +2429,7 @@ function goto_combat_round(new_combat_round) {
if (is_contested_battle_field()) {
if (is_under_siege(game.where)) {
if (!was_contested) {
- log("Relief forces arrive!");
+ log("Relief forces arrived!");
if (game.storming.length > 0) {
log("Storming canceled by arriving relief force.");
game.halfhit = null;
@@ -2502,10 +2493,10 @@ states.declare_storm = {
clear_undo();
let n = game.storming.length;
if (n === 0) {
- game.flash = game.active + " decline to storm.";
+ game.flash = game.active + " declined to storm.";
if (game.jihad === game.where)
game.jihad = null;
- log(game.active + " decline to storm.");
+ log(game.active + " declined to storm.");
goto_declare_sally();
} else {
goto_siege_battle();
@@ -2518,13 +2509,10 @@ function storm_with_block(who) {
push_undo();
game.storming.push(who);
if (game.storming.length > 1)
- game.flash = game.active + " storm with " + game.storming.length + " blocks.";
+ game.flash = game.active + " stormed with " + game.storming.length + " blocks.";
else
- game.flash = game.active + " storm with 1 block.";
- if (block_plural(who))
- log(game.active[0] + ": " + block_name(who) + " storm.");
- else
- log(game.active[0] + ": " + block_name(who) + " storms.");
+ game.flash = game.active + " stormed with 1 block.";
+ log(game.active[0] + ": " + block_name(who) + " stormed.");
}
// DECLARE SALLY
@@ -2562,8 +2550,8 @@ states.declare_sally = {
clear_undo();
let n = game.sallying.length;
if (n === 0) {
- game.flash = game.active + " decline to sally.";
- log(game.active + " decline to sally.");
+ game.flash = game.active + " declined to sally.";
+ log(game.active + " declined to sally.");
}
if (is_contested_battle_field()) {
if (!game.was_contested) {
@@ -2585,13 +2573,10 @@ function sally_with_block(who) {
remove_from_array(game.castle, who);
game.sallying.push(who);
if (game.sallying.length > 1)
- game.flash = game.active + " sally with " + game.sallying.length + " blocks.";
- else
- game.flash = game.active + " sally with 1 block.";
- if (block_plural(who))
- log(game.active[0] + ": " + block_name(who) + " sally.");
+ game.flash = game.active + " sallied with " + game.sallying.length + " blocks.";
else
- log(game.active[0] + ": " + block_name(who) + " sallies.");
+ game.flash = game.active + " sallied with 1 block.";
+ log(game.active[0] + ": " + block_name(who) + " sallied.");
}
// RETREAT AFTER COMBAT
@@ -2643,7 +2628,7 @@ states.retreat = {
for (let b in BLOCKS)
if (game.location[b] === game.where && !is_block_in_castle(b) && block_owner(b) === game.active)
eliminate_block(b);
- print_summary(game.active + " retreat:");
+ print_summary(game.active + " retreated:");
game.active = enemy(game.active);
goto_regroup();
},
@@ -2705,10 +2690,10 @@ function resume_siege_attrition() {
delete game.attrition_list;
if (!is_under_siege(game.where)) {
game.active = enemy(game.active);
- log(game.where + " falls to siege attrition.");
+ log(game.where + " fell to siege attrition.");
goto_regroup();
} else {
- log("Siege continues.");
+ log("Siege continued.");
end_combat();
}
}
@@ -2979,10 +2964,7 @@ states.field_battle_hits = {
function apply_field_battle_hit_to(who, flash) {
let msg;
- if (block_plural(who))
- msg = block_name(who) + " take a hit.";
- else
- msg = block_name(who) + " takes a hit.";
+ msg = block_name(who) + " took a hit.";
log(game.active[0] + ": " + msg);
if (flash)
game.flash = msg;
@@ -3044,11 +3026,7 @@ states.siege_battle_hits = {
}
function apply_siege_battle_hit_to(who, flash) {
- let msg;
- if (block_plural(who))
- msg = block_name(who) + " take a ";
- else
- msg = block_name(who) + " takes a ";
+ let msg = block_name(who) + " took a ";
if (game.halfhit === who) {
msg += "hit.";
log(game.active[0] + ": " + msg);
@@ -3109,21 +3087,12 @@ function roll_attack(active, b, verb, is_charge) {
}
game.flash = name + " " + verb + " " + rolls.join(" ") + " ";
- if (block_plural(b)) {
- if (game.hits === 0)
- game.flash += "and miss.";
- else if (game.hits === 1)
- game.flash += "and score 1 hit.";
- else
- game.flash += "and score " + game.hits + " hits.";
- } else {
- if (game.hits === 0)
- game.flash += "and misses.";
- else if (game.hits === 1)
- game.flash += "and scores 1 hit.";
- else
- game.flash += "and scores " + game.hits + " hits.";
- }
+ if (game.hits === 0)
+ game.flash += "and missed.";
+ else if (game.hits === 1)
+ game.flash += "and scored 1 hit.";
+ else
+ game.flash += "and scored " + game.hits + " hits.";
if (self > 0) {
if (self === 1)
@@ -3140,10 +3109,7 @@ function roll_attack(active, b, verb, is_charge) {
function field_fire_with_block(b) {
game.moved[b] = 1;
- if (block_plural(b))
- roll_attack(game.active, b, "fire", 0);
- else
- roll_attack(game.active, b, "fires", 0);
+ roll_attack(game.active, b, "fired", 0);
if (game.hits > 0) {
goto_field_battle_hits();
} else {
@@ -3153,10 +3119,7 @@ function field_fire_with_block(b) {
function siege_fire_with_block(b) {
game.moved[b] = 1;
- if (block_plural(b))
- roll_attack(game.active, b, "fire", 0);
- else
- roll_attack(game.active, b, "fires", 0);
+ roll_attack(game.active, b, "fired", 0);
if (game.hits > 0) {
goto_siege_battle_hits();
} else {
@@ -3166,10 +3129,7 @@ function siege_fire_with_block(b) {
function charge_with_block(b) {
game.moved[b] = 1;
- if (block_plural(b))
- roll_attack(game.active, b, "charge", 1);
- else
- roll_attack(game.active, b, "charges", 1);
+ roll_attack(game.active, b, "charged", 1);
if (game.hits > 0) {
goto_field_battle_hits();
} else {
@@ -3178,10 +3138,7 @@ function charge_with_block(b) {
}
function field_withdraw_with_block(b) {
- if (block_plural(b))
- game.flash = b + " withdraw.";
- else
- game.flash = b + " withdraws.";
+ game.flash = b + " withdrew.";
log(game.active[0] + ": " + game.flash);
game.moved[b] = 1;
remove_from_array(game.sallying, b);
@@ -3190,10 +3147,7 @@ function field_withdraw_with_block(b) {
}
function siege_withdraw_with_block(b) {
- if (block_plural(b))
- game.flash = b + " withdraw.";
- else
- game.flash = b + " withdraws.";
+ game.flash = b + " withdrew.";
log(game.active[0] + ": " + game.flash);
game.moved[b] = 1;
remove_from_array(game.storming, b);
@@ -3203,10 +3157,7 @@ function siege_withdraw_with_block(b) {
function harry_with_block(b) {
game.harry = game.active; // remember to retreat after hits have been applied
game.who = b;
- if (block_plural(b))
- roll_attack(game.active, b, "harry", 0);
- else
- roll_attack(game.active, b, "harries", 0);
+ roll_attack(game.active, b, "harried", 0);
if (game.hits > 0) {
goto_field_battle_hits();
} else {
@@ -3224,10 +3175,7 @@ states.harry = {
gen_action(view, 'town', to);
},
town: function (to) {
- if (block_plural(game.who))
- game.flash += " " + block_name(game.who) + " retreat.";
- else
- game.flash += " " + block_name(game.who) + " retreats.";
+ game.flash += " " + block_name(game.who) + " retreated.";
game.summary.push([game.active, to]);
game.location[game.who] = to;
move_block(game.who, game.where, to);
@@ -3253,10 +3201,7 @@ states.retreat_in_battle = {
gen_action(view, 'town', to);
},
town: function (to) {
- if (block_plural(game.who))
- game.flash = block_name(game.who) + " retreat.";
- else
- game.flash = block_name(game.who) + " retreats.";
+ game.flash = block_name(game.who) + " retreated.";
log(game.active[0] + ": " + game.flash);
game.summary.push([game.active, to]);
game.location[game.who] = to;
@@ -3343,7 +3288,7 @@ states.draw_phase = {
town: function (where) {
let type = block_type(game.who);
- log(game.active + " place drawn block in " + where + ".");
+ log(game.active + " placed drawn block in " + where + ".");
game.location[game.who] = where;
if (type === 'turcopoles' || type === 'outremers' || type === 'emirs' || type === 'nomads') {
@@ -3389,7 +3334,7 @@ function end_game_turn() {
function goto_winter_1() {
log("");
- log("Start Winter of " + game.year + ".");
+ log("Start Winter of " + game.year);
log("");
if (game.winter_campaign)
goto_winter_siege_attrition();
@@ -3398,7 +3343,7 @@ function goto_winter_1() {
}
function goto_winter_siege_attrition() {
- log(game.active + " winter campaign in " + game.winter_campaign + ".");
+ log(game.active + " winter campaigned in " + game.winter_campaign + ".");
game.where = game.winter_campaign;
game.active = besieged_player(game.where);
@@ -3414,10 +3359,10 @@ function resume_winter_siege_attrition() {
delete game.attrition_list;
if (!is_under_siege(game.where)) {
game.active = enemy(game.active);
- log(game.where + " falls to siege attrition.");
+ log(game.where + " fell to siege attrition.");
goto_regroup();
} else {
- log("Siege continues.");
+ log("Siege continued.");
goto_winter_2();
}
}
@@ -3470,7 +3415,7 @@ function eliminate_besieging_blocks(owner) {
}
}
if (game.summary.length > 0)
- print_summary(owner + " disband sieges:");
+ print_summary(owner + " disbanded sieges:");
else
game.summary = null;
}
@@ -3535,7 +3480,7 @@ states.winter_supply = {
next: function () {
clear_undo();
if (game.summary.length > 0)
- print_summary(game.active + " disband:");
+ print_summary(game.active + " disbanded:");
if (game.active === FRANKS) {
game.active = SARACENS;
game.summary = [];
@@ -3627,12 +3572,12 @@ function goto_year_end() {
let s_vp = count_victory_points(SARACENS);
if (f_vp > s_vp) {
game.result = FRANKS;
- game.victory = "Franks win!";
+ game.victory = "Franks won!";
} else if (f_vp < s_vp) {
- game.victory = "Saracens win!";
+ game.victory = "Saracens won!";
game.result = SARACENS;
} else {
- game.victory = "The game is a draw.";
+ game.victory = "The game ended in a draw.";
game.result = null;
}
log("");