summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-10-02 22:19:25 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-16 19:12:55 +0100
commite269954c8a936600f3d3d7fdba156b046e586df5 (patch)
tree7fb42e092e92ae4760f64b143e70d6c6c706135f
parent168b3f168bfb92336567a30c3e2a6fd961890abb (diff)
downloadrichard-iii-e269954c8a936600f3d3d7fdba156b046e586df5.tar.gz
Nobody and nowhere.
-rw-r--r--play.js31
-rw-r--r--rules.js141
2 files changed, 85 insertions, 87 deletions
diff --git a/play.js b/play.js
index d359eb9..ea429df 100644
--- a/play.js
+++ b/play.js
@@ -9,6 +9,9 @@ const POOL = "Pool";
const DEAD = "Dead";
const MINOR = "Minor";
+const NOBODY = -1
+const NOWHERE = 0
+
const KING_TEXT = "\u2756";
const PRETENDER_TEXT = "";
@@ -128,7 +131,7 @@ const STEP_TEXT = [ 0, "I", "II", "III", "IIII" ];
const HEIR_TEXT = [ 0, '\u00b9', '\u00b2', '\u00b3', '\u2074', '\u2075' ];
function block_name(who) {
- if (!who) return "Nobody";
+ if (who === NOBODY) return "Nobody";
let name = BLOCKS[who].name;
let long_name = LONG_NAME[name];
return long_name ? long_name : name;
@@ -136,9 +139,9 @@ function block_name(who) {
function block_owner(who) {
if (who === REBEL) {
- if (view.pretender)
+ if (view.pretender !== NOBODY)
return BLOCKS[view.pretender].owner;
- if (view.king)
+ if (view.king !== NOBODY)
return ENEMY[BLOCKS[view.king].owner];
return YORK;
}
@@ -454,7 +457,7 @@ function hide_block(element) {
}
function is_dead(who) {
- return view.location[who] === null;
+ return view.location[who] === NOWHERE;
}
function is_perma_dead(who) {
@@ -493,14 +496,14 @@ function update_map() {
let known = is_known_block(b);
// perma-dead nobles
- if (area === null && is_perma_dead(b)) {
+ if (area === NOWHERE && is_perma_dead(b)) {
area = DEAD;
moved = " moved";
known = 1;
steps = "";
}
- if (area !== null) {
+ if (area !== NOWHERE) {
if (known) {
element.classList = info.owner + " known block" + image + steps + moved;
} else {
@@ -528,16 +531,16 @@ function update_map() {
}
}
- for (let where in AREAS) {
- if (ui.areas[where]) {
- ui.areas[where].classList.remove('highlight');
- ui.areas[where].classList.remove('where');
+ for (let area in AREAS) {
+ if (ui.areas[area]) {
+ ui.areas[area].classList.remove('highlight');
+ ui.areas[area].classList.remove('where');
}
}
if (view.actions && view.actions.area)
- for (let where of view.actions.area)
- ui.areas[where].classList.add('highlight');
- if (view.where)
+ for (let area of view.actions.area)
+ ui.areas[area].classList.add('highlight');
+ if (view.where !== NOWHERE)
ui.areas[view.where].classList.add('where');
for (let b in BLOCKS) {
@@ -548,7 +551,7 @@ function update_map() {
if (view.actions && view.actions.block)
for (let b of view.actions.block)
ui.blocks[b].classList.add('highlight');
- if (view.who)
+ if (view.who !== NOBODY)
ui.blocks[view.who].classList.add('selected');
}
}
diff --git a/rules.js b/rules.js
index 11af1d3..bab505c 100644
--- a/rules.js
+++ b/rules.js
@@ -29,6 +29,9 @@ const BOTH = "Both"
const POOL = "Pool"
const MINOR = "Minor"
+const NOBODY = -1
+const NOWHERE = 0
+
// serif cirled numbers
const DIE_HIT = [ 0, '\u2776', '\u2777', '\u2778', '\u2779', '\u277A', '\u277B' ]
const DIE_MISS = [ 0, '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465' ]
@@ -195,8 +198,8 @@ function is_royal_heir(who) {
function is_dead(who) {
if (who in BLOCKS)
- return !game.location[who]
- return !game.location[who+"/L"] && !game.location[who+"/Y"]
+ return game.location[who] === NOWHERE
+ return game.location[who+"/L"] === NOWHERE && game.location[who+"/Y"] === NOWHERE
}
function is_shield_area_for(where, who, combat) {
@@ -261,7 +264,7 @@ function is_shield_area_for(where, who, combat) {
function is_at_home(who) {
let where = game.location[who]
- if (!where || where === MINOR || where === POOL)
+ if (where === NOWHERE || where === MINOR || where === POOL)
return true
if (is_pretender_heir(who))
return is_exile_area(where)
@@ -331,14 +334,13 @@ function go_home_if_possible(who) {
function is_on_map_not_in_exile_or_man(who) {
let where = game.location[who]
- return where && where !== MINOR &&
- where !== POOL &&
+ return where !== NOWHERE && where !== MINOR && where !== POOL &&
where !== "Isle of Man" &&
!is_exile_area(where)
}
function is_land_area(where) {
- return where && where !== MINOR && where !== POOL && !is_sea_area(where)
+ return where !== NOWHERE && where !== MINOR && where !== POOL && !is_sea_area(where)
}
function is_area_friendly_to(where, owner) {
@@ -391,9 +393,9 @@ function block_home(who) {
function block_owner(who) {
if (who === REBEL) {
- if (game.pretender)
+ if (game.pretender !== NOBODY)
return block_owner(game.pretender)
- else if (game.king)
+ else if (game.king !== NOBODY)
return ENEMY[block_owner(game.king)]
else
return YORK // whatever... they're both dead
@@ -460,7 +462,7 @@ function is_neville(who) {
}
function block_loyalty(source, target) {
- let source_name = source ? block_name(source) : "Event"
+ let source_name = source !== NOBODY ? block_name(source) : "Event"
if (source_name === "Warwick") {
let target_name = block_name(target)
if (target_name === "Kent" || target_name === "Salisbury")
@@ -481,11 +483,11 @@ function can_defect(source, target) {
function can_attempt_treason_event() {
if (game.treason === game.attacker[game.where]) {
for (let b of BLOCKLIST)
- if (is_defender(b) && can_defect(null, b))
+ if (is_defender(b) && can_defect(NOBODY, b))
return true
} else {
for (let b of BLOCKLIST)
- if (is_attacker(b) && can_defect(null, b))
+ if (is_attacker(b) && can_defect(NOBODY, b))
return true
}
return false
@@ -523,7 +525,7 @@ function can_activate(who) {
}
function is_area_on_map(location) {
- return location && location !== MINOR && location !== POOL
+ return location !== NOWHERE && location !== MINOR && location !== POOL
}
function is_block_on_map(b) {
@@ -726,7 +728,7 @@ function can_block_sea_move_to(who, from, to) {
function can_block_sea_move(who) {
if (can_activate(who)) {
let from = game.location[who]
- if (from) {
+ if (from !== NOWHERE) {
if (is_pinned(who, from))
return false
for (let to of AREAS[from].exits)
@@ -796,7 +798,7 @@ function can_block_land_move_to(who, from, to) {
function can_block_land_move(who) {
if (can_activate(who)) {
let from = game.location[who]
- if (from) {
+ if (from !== NOWHERE) {
if (is_pinned(who, from))
return false
for (let to of AREAS[from].exits)
@@ -909,7 +911,7 @@ function swap_blocks(a) {
let b = BLOCKS[a].enemy
game.location[b] = game.location[a]
game.steps[b] = game.steps[a]
- game.location[a] = null
+ game.location[a] = NOWHERE
game.steps[a] = block_max_steps(a)
return b
}
@@ -937,17 +939,17 @@ function eliminate_block(who) {
log(block_name(who) + " was eliminated.")
game.flash += " " + block_name(who) + " was eliminated."
if (who === "Exeter/Y") {
- game.location[who] = null
+ game.location[who] = NOWHERE
++game.killed_heirs[LANCASTER]
return check_instant_victory()
}
if (who === "Clarence/L") {
- game.location[who] = null
+ game.location[who] = NOWHERE
++game.killed_heirs[YORK]
return check_instant_victory()
}
if (is_heir(who)) {
- game.location[who] = null
+ game.location[who] = NOWHERE
++game.killed_heirs[block_owner(who)]
if (who === game.pretender)
game.pretender = find_senior_heir(block_owner(game.pretender))
@@ -955,7 +957,7 @@ function eliminate_block(who) {
return check_instant_victory()
}
if (is_rose_noble(who) || is_neville(who)) {
- game.location[who] = null
+ game.location[who] = NOWHERE
return
}
if (is_mercenary(who)) {
@@ -1099,7 +1101,7 @@ function deploy_york(name, where) {
function reset_blocks() {
for (let b of BLOCKLIST) {
- game.location[b] = null
+ game.location[b] = NOWHERE
game.steps[b] = block_max_steps(b)
}
}
@@ -1601,7 +1603,7 @@ states.muster_who = {
game.state = 'muster_move_1'
},
end_action_phase: function () {
- game.where = null
+ game.where = NOWHERE
clear_undo()
print_turn_log(game.active + " mustered:")
end_player_turn()
@@ -1630,7 +1632,7 @@ states.muster_move_1 = {
if (to === game.where) {
log_move_end()
set_add(game.moved, game.who)
- game.who = null
+ game.who = NOBODY
game.state = 'muster_who'
} else {
game.state = 'muster_move_2'
@@ -1653,7 +1655,7 @@ states.muster_move_2 = {
log_move_end()
move_block(game.who, game.location[game.who], to)
set_add(game.moved, game.who)
- game.who = null
+ game.who = NOBODY
game.state = 'muster_who'
},
undo: pop_undo,
@@ -1741,7 +1743,7 @@ states.action_phase = {
}
if (can_block_sea_move(b)) {
if (game.moves === 0) {
- if (game.move_port[game.location[b]])
+ if (game.move_port[game.location[b]] !== undefined)
gen_action(view, 'block', b)
} else {
gen_action(view, 'block', b)
@@ -1757,7 +1759,7 @@ states.action_phase = {
game.state = 'recruit_where'
} else {
game.distance = 0
- game.last_from = null
+ game.last_from = NOWHERE
game.state = 'move_to'
}
},
@@ -1932,15 +1934,15 @@ function end_move() {
}
set_add(game.moved, game.who)
}
- game.last_from = null
+ game.last_from = NOWHERE
end_action()
}
function end_action() {
free_henry_vi()
- game.who = null
+ game.who = NOBODY
game.distance = 0
- game.origin = null
+ game.origin = NOWHERE
game.state = 'action_phase'
}
@@ -1990,7 +1992,7 @@ function start_battle(where) {
function resume_battle() {
if (game.result)
return goto_game_over()
- game.who = null
+ game.who = NOBODY
game.state = 'battle_round'
pump_battle_round()
}
@@ -2017,12 +2019,12 @@ states.treason_event = {
gen_action(view, 'pass')
for (let b of BLOCKLIST) {
if (game.active === game.attacker[game.where]) {
- if (is_defender(b) && can_defect(null, b)) {
+ if (is_defender(b) && can_defect(NOBODY, b)) {
gen_action(view, 'battle_treachery', b)
gen_action(view, 'block', b)
}
} else {
- if (is_attacker(b) && can_defect(null, b)) {
+ if (is_attacker(b) && can_defect(NOBODY, b)) {
gen_action(view, 'battle_treachery', b)
gen_action(view, 'block', b)
}
@@ -2031,13 +2033,13 @@ states.treason_event = {
},
battle_treachery: function (target) {
delete game.treason
- attempt_treachery(null, target)
+ attempt_treachery(NOBODY, target)
game.state = 'battle_round'
start_battle_round()
},
block: function (target) {
delete game.treason
- attempt_treachery(null, target)
+ attempt_treachery(NOBODY, target)
game.state = 'battle_round'
start_battle_round()
},
@@ -2221,7 +2223,7 @@ function fire_with_block(b) {
}
function attempt_treachery(source, target) {
- if (source) {
+ if (source !== NOBODY) {
let once = treachery_tag(source)
set_add(game.treachery, once)
set_add(game.moved, source)
@@ -2238,7 +2240,7 @@ function attempt_treachery(source, target) {
rolls.push(DIE_HIT[die])
}
}
- if (source)
+ if (source !== NOBODY)
game.flash = block_name(source) + " treachery " + rolls.join(" ")
else
game.flash = "Treason event " + rolls.join(" ")
@@ -2282,40 +2284,40 @@ function can_block_fire(who) {
}
function find_minor_heir(owner) {
- let candidate = null
+ let candidate = NOBODY
for (let b of BLOCKLIST) {
if (block_owner(b) === owner && block_type(b) === 'heir' && game.location[b] === MINOR)
- if (!candidate || BLOCKS[b].heir < BLOCKS[candidate].heir)
+ if (candidate === NOBODY || BLOCKS[b].heir < BLOCKS[candidate].heir)
candidate = b
}
return candidate
}
function find_senior_heir(owner) {
- let candidate = null
+ let candidate = NOBODY
for (let b of BLOCKLIST)
if (block_owner(b) === owner && block_type(b) === 'heir' && !is_dead(b))
- if (!candidate || BLOCKS[b].heir < BLOCKS[candidate].heir)
+ if (candidate === NOBODY || BLOCKS[b].heir < BLOCKS[candidate].heir)
candidate = b
return candidate
}
function find_next_king(owner) {
- let candidate = null
+ let candidate = NOBODY
for (let b of BLOCKLIST)
- if (block_owner(b) === owner && block_type(b) === 'heir' && game.location[b])
- if (!candidate || BLOCKS[b].heir < BLOCKS[candidate].heir)
+ if (block_owner(b) === owner && block_type(b) === 'heir' && game.location[b] !== NOWHERE)
+ if (candidate === NOBODY || BLOCKS[b].heir < BLOCKS[candidate].heir)
candidate = b
return candidate
}
function find_senior_heir_in_area(owner, where) {
- let candidate = null
+ let candidate = NOBODY
for (let b of BLOCKLIST) {
if (block_owner(b) === owner && block_type(b) === 'heir' && game.location[b] === where) {
if (is_battle_reserve(b))
continue
- if (!candidate || BLOCKS[b].heir < BLOCKS[candidate].heir)
+ if (candidate === NOBODY || BLOCKS[b].heir < BLOCKS[candidate].heir)
candidate = b
}
}
@@ -2328,13 +2330,13 @@ function is_senior_royal_heir_in(who, where) {
function can_heir_charge() {
let heir = find_senior_heir_in_area(game.active, game.where)
- if (heir && !set_has(game.moved, heir)) {
+ if (heir !== NOBODY && !set_has(game.moved, heir)) {
if (is_attacker(heir))
- return game.battle_round < 4 ? heir : null
+ return game.battle_round < 4 ? heir : NOBODY
if (is_defender(heir))
return heir
}
- return null
+ return NOBODY
}
states.battle_round = {
@@ -2367,7 +2369,7 @@ states.battle_round = {
}
let heir = can_heir_charge()
- if (heir && set_has(game.battle_list, heir))
+ if (heir !== NOBODY && set_has(game.battle_list, heir))
gen_action(view, 'battle_charge', heir)
if (can_attempt_treachery(game.king))
gen_action(view, 'battle_treachery', game.king)
@@ -2647,7 +2649,7 @@ states.regroup = {
game.state = 'regroup_to'
},
end_regroup: function () {
- game.where = null
+ game.where = NOWHERE
clear_undo()
print_turn_log(game.active + " regrouped:")
goto_battle_phase()
@@ -2686,7 +2688,7 @@ states.regroup_to = {
} else {
game.turn_log.push([game.where, to])
move_block(game.who, game.where, to)
- game.who = null
+ game.who = NOBODY
game.state = 'regroup'
}
},
@@ -2709,7 +2711,7 @@ states.sea_regroup_to = {
log_move_continue(to)
log_move_end()
game.location[game.who] = to
- game.who = null
+ game.who = NOBODY
game.state = 'regroup'
},
undo: pop_undo,
@@ -2720,7 +2722,7 @@ states.sea_regroup_to = {
function goto_supply_phase() {
set_clear(game.moved)
- if (!game.location[game.king]) {
+ if (game.location[game.king] === NOWHERE) {
game.king = find_next_king(block_owner(game.king))
log("The King is dead; long live the king!")
if (game.location[game.king] === MINOR)
@@ -2753,13 +2755,13 @@ states.execute_clarence = {
execute_clarence: function () {
logp("executed Clarence.")
eliminate_block("Clarence/L")
- game.who = null
+ game.who = NOBODY
if (game.result)
return goto_game_over()
goto_execute_exeter()
},
pass: function () {
- game.who = null
+ game.who = NOBODY
goto_execute_exeter()
}
}
@@ -2785,13 +2787,13 @@ states.execute_exeter = {
execute_exeter: function () {
logp("executed Exeter.")
eliminate_block("Exeter/Y")
- game.who = null
+ game.who = NOBODY
if (game.result)
return goto_game_over()
goto_enter_pretender_heir()
},
pass: function () {
- game.who = null
+ game.who = NOBODY
goto_enter_pretender_heir()
}
}
@@ -2801,7 +2803,7 @@ states.execute_exeter = {
function goto_enter_pretender_heir() {
game.active = block_owner(game.pretender)
let n = game.killed_heirs[game.active]
- if (n > 0 && (game.who = find_minor_heir(game.active)))
+ if (n > 0 && (game.who = find_minor_heir(game.active)) !== NOBODY)
game.state = 'enter_pretender_heir'
else
goto_supply_limits_pretender()
@@ -2816,15 +2818,12 @@ states.enter_pretender_heir = {
if (is_pretender_exile_area(where))
gen_action(view, 'area', where)
},
- block: function () {
- game.who = null
- },
area: function (to) {
logbr()
log(block_name(game.who) + " came of age in " + to + ".")
--game.killed_heirs[game.active]
game.location[game.who] = to
- game.who = null
+ game.who = NOBODY
goto_enter_pretender_heir()
},
}
@@ -2878,7 +2877,7 @@ states.supply_limits_pretender = {
function goto_enter_royal_heir() {
game.active = block_owner(game.king)
let n = game.killed_heirs[game.active]
- if (n > 0 && (game.who = find_minor_heir(game.active)))
+ if (n > 0 && (game.who = find_minor_heir(game.active)) !== NOBODY)
game.state = 'enter_royal_heir'
else
goto_supply_limits_king()
@@ -2899,19 +2898,16 @@ states.enter_royal_heir = {
if (!can_enter)
gen_action(view, 'pass')
},
- block: function () {
- game.who = null
- },
area: function (to) {
logbr()
log(block_name(game.who) + " came of age in " + to + ".")
--game.killed_heirs[game.active]
game.location[game.who] = to
- game.who = null
+ game.who = NOBODY
goto_enter_royal_heir()
},
pass: function () {
- game.who = null
+ game.who = NOBODY
goto_supply_limits_king()
}
}
@@ -3142,7 +3138,7 @@ states.pretender_goes_home_to = {
game.turn_log.push([block_name(game.who), to]) // TODO: "Home"?
set_add(game.moved, game.who)
game.location[game.who] = to
- game.who = null
+ game.who = NOBODY
game.state = 'pretender_goes_home'
},
block: pop_undo,
@@ -3267,7 +3263,7 @@ states.king_goes_home_to = {
game.turn_log.push([block_name(game.who), to]) // TODO: "Home"?
set_add(game.moved, game.who)
game.location[game.who] = to
- game.who = null
+ game.who = NOBODY
game.state = 'king_goes_home'
},
block: pop_undo,
@@ -3371,8 +3367,8 @@ exports.setup = function (seed, scenario, options) {
active: null,
moves: 0,
- who: null,
- where: null,
+ who: NOBODY,
+ where: NOWHERE,
show_cards: false,
killed_heirs: { Lancaster: 0, York: 0 },
@@ -3451,14 +3447,13 @@ exports.view = function(state, current) {
l_card: (game.show_cards || current === LANCASTER) ? game.l_card : 0,
y_card: (game.show_cards || current === YORK) ? game.y_card : 0,
hand: (current === LANCASTER) ? game.l_hand : (current === YORK) ? game.y_hand : observer_hand(),
- who: (game.active === current) ? game.who : null,
+ who: (game.active === current) ? game.who : NOBODY,
where: game.where,
location: game.location,
steps: game.steps,
moved: game.moved,
battle: null,
prompt: null,
- actions: null,
}
states[game.state].prompt(view, current)