summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js94
1 files changed, 60 insertions, 34 deletions
diff --git a/rules.js b/rules.js
index 3438f70..9fbb6e8 100644
--- a/rules.js
+++ b/rules.js
@@ -9,6 +9,7 @@
// TODO: manual "pursuit" ?
// TODO: allow placing dice on full special formations?
+// TODO: fizzle when action says to take cards from other dice?
const data = require("./data.js")
@@ -83,6 +84,10 @@ exports.view = function (state, player) {
morale: game.morale,
front: game.front,
reserve: game.reserve,
+ selected: game.selected,
+ target: game.target,
+ hits: game.hits,
+ self: game.self,
}
if (game.state === "game_over") {
@@ -133,8 +138,6 @@ states.game_over = {
exports.setup = function (seed, scenario, options) {
// TODO: "Random"
- console.log("SETUP", scenario)
-
scenario = parseInt(scenario)
scenario = data.scenarios.findIndex(s => s.number === scenario)
if (scenario < 0)
@@ -163,12 +166,18 @@ exports.setup = function (seed, scenario, options) {
// cubes (map special formation -> count)
cubes: [],
- morale: [ info.players[0].morale, info.players[1].morale ],
+ morale: [ info.players[0].morale || -1, info.players[1].morale || -1 ],
front: [ [], [], ],
reserve: [ [], [] ],
// dice value placed on what card
placed: [],
+
+ // current action
+ selected: -1,
+ target: -1,
+ hits: 0,
+ self: 0,
}
function setup_formation(front, reserve, c) {
@@ -305,10 +314,10 @@ function set_dice_value(d, v) {
function is_card_in_play(c) {
return (
- set_has(game.players[0].front, c) ||
- set_has(game.players[1].front, c) ||
- set_has(game.players[0].reserve, c) ||
- set_has(game.players[1].reserve, c)
+ set_has(game.front[0], c) ||
+ set_has(game.front[1], c) ||
+ set_has(game.reserve[0], c) ||
+ set_has(game.reserve[1], c)
)
}
@@ -317,24 +326,25 @@ function is_card_attack_with_target_in_play(c) {
if (a.type === "Attack") {
for (let t of a.target_list)
if (is_card_in_play(c))
- return false
+ return true
}
}
+ return false
}
function check_impossible_to_attack_victory() {
let p = player_index()
- for (let c of game.players[p].front)
+ for (let c of game.front[p])
if (is_card_attack_with_target_in_play(c))
return false
- for (let c of game.players[p].reserve)
+ for (let c of game.reserve[p])
if (is_card_attack_with_target_in_play(c))
return false
return true
}
function check_morale_loss(p) {
- return game.players[0].morale === 0
+ return game.morale[0] === 0
}
// === ROLL PHASE ===
@@ -790,7 +800,7 @@ states.place = {
states.place_on_card = {
prompt() {
let card = data.cards[game.selected]
- view.selected = game.selected
+ // XXX view.selected = game.selected
view.prompt = "Place dice on " + card.name + "."
gen_place_dice_select_card()
@@ -811,8 +821,10 @@ states.place_on_card = {
die(d) {
push_undo()
place_dice_take[data.cards[game.selected].dice](game.selected, d)
- if (!can_place_dice(game.selected))
+ if (!can_place_dice(game.selected)) {
+ game.selected = -1
game.state = "place"
+ }
},
end_turn() {
end_roll_phase()
@@ -979,7 +991,7 @@ function can_take_any_action() {
function goto_action_phase() {
if (check_impossible_to_attack_victory()) {
- if (player === P1)
+ if (player_index() === 0)
goto_game_over(P2, P1 + " has no more attacks!")
else
goto_game_over(P1, P2 + " has no more attacks!")
@@ -1076,7 +1088,7 @@ function goto_take_action(c, ix) {
game.action = ix
switch (a.type) {
case "Attack":
- game.state = "attack"
+ goto_attack()
break
case "Bombard":
game.state = "bombard"
@@ -1125,9 +1137,8 @@ states.bombard = {
}
function format_attack_result() {
- let a = current_action()
- let hits = get_attack_hits(game.selected, a)
- let self = get_attack_self(game.selected, a)
+ let hits = game.hits
+ let self = game.self
if (hits !== 1 && self > 0)
return ` ${hits} hits. ${self} self.`
if (hits === 1 && self > 0)
@@ -1139,19 +1150,23 @@ function format_attack_result() {
return ""
}
+function goto_attack(c) {
+ let a = current_action()
+ game.state = "attack"
+ game.target = find_target_of_attack(a)
+ game.hits = get_attack_hits(game.selected, a)
+ game.self = get_attack_self(game.selected, a)
+}
+
states.attack = {
prompt() {
- let t = find_target_of_attack(current_action())
- view.prompt = "Attack " + card_name(t) + "." + format_attack_result()
- view.selected = game.selected
- gen_action_card(t)
+ view.prompt = "Attack " + card_name(game.target) + "." + format_attack_result()
+ // XXX view.selected = game.selected
+ gen_action_card(game.target)
+ view.actions.attack = 1
},
card(c) {
log(card_name(game.selected) + " attacked " + card_name(c) + ".")
- let a = current_action()
- game.target = c
- game.hits = get_attack_hits(game.selected, a)
- game.self = get_attack_self(game.selected, a)
if (can_opponent_react()) {
clear_undo()
set_opponent_active()
@@ -1165,8 +1180,11 @@ states.attack = {
function resume_attack() {
apply_hits(game.hits)
apply_self(game.self)
- game.hits = game.self = 0
pay_for_action(game.selected)
+
+ game.hits = game.self = 0
+ game.selected = -1
+ game.target = -1
end_action_phase()
}
@@ -1174,17 +1192,15 @@ states.command = {
prompt() {
let t = find_target_of_command(current_action())
view.prompt = "Bring " + card_name(t) + " out of reserve."
- view.selected = game.selected
+ // XXX view.selected = game.selected
gen_action_card(t)
},
card(c) {
log(card_name(game.selected) + " commanded " + card_name(c) + " out of reserve.")
- console.log("PRE COMMAND", JSON.stringify(game))
let p = player_index()
array_remove_item(game.reserve[p], c)
set_add(game.front[p], c)
pay_for_action(game.selected)
- console.log("POST COMMAND", JSON.stringify(game))
end_action_phase()
},
}
@@ -1256,8 +1272,8 @@ function can_take_reaction(c, a) {
states.react = {
prompt() {
view.prompt = card_name(game.selected) + " attacks " + card_name(game.target) + "! " + format_attack_result()
- view.selected = game.selected
- view.target = game.target
+ // XXX view.selected = game.selected
+ // XXX view.target = game.target
let voluntary = true
let p = player_index()
@@ -1320,9 +1336,19 @@ function goto_screen(c, a) {
log(card_name(c) + " screened.")
game.reacted = 1
pay_for_action(c)
+
+ switch (a.effect)
+ {
+ default:
+ throw new Error("invalid screen effect: " + a.effect)
+ case "":
+ game.hits = 0
+ game.self = 0
+ break
+ }
+
set_opponent_active()
- pay_for_action(game.selected)
- end_action_phase()
+ resume_attack()
}
function goto_absorb(c, a) {