summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js588
1 files changed, 317 insertions, 271 deletions
diff --git a/rules.js b/rules.js
index 691461e..0430252 100644
--- a/rules.js
+++ b/rules.js
@@ -1,5 +1,7 @@
"use strict"
+// TODO: search_path with actual unit speed
+
// TODO: partial moves during regroup (to allow deciding entry hex-side)
// TODO: first_friendly_unit / for_each_friendly_unit
@@ -10,6 +12,46 @@
// unit state: location (8 bits), supply source (3 bits), steps (2 bits), disrupted (1 bit)
+// SEQUENCE
+// --------
+// Supply check
+// Turn option
+// Movement
+// declare moves
+// normal moves
+// rout
+// retreats
+// declare full/partial retreats
+// probe combat
+// pursuit fire
+// withdraw
+// rout
+// pursuit fire
+// withdraw
+// forced marches
+// rout
+// pursuit fire
+// withdraw
+// refuse battle
+// pursuit fire
+// withdraw
+// rout
+// pursuit fire
+// withdraw
+// Combat
+// declare active
+// declare assault
+// resolve
+// defensive fire
+// rout
+// offensive fire
+// rout
+// Blitz Movement
+// Blitz Combat
+// Final supply check
+// rout
+// Reveal supply cards -> next player
+
const max = Math.max
const min = Math.min
const abs = Math.abs
@@ -449,6 +491,12 @@ function has_undisrupted_enemy_unit(x) {
return has_undisrupted_allied_unit(x)
}
+function is_new_battle_hex(a) {
+ if (is_battle_hex(a))
+ return !set_has(game.axis_hexes, a) && !set_has(game.allied_hexes, a)
+ return false
+}
+
function claim_hexside_control(side) {
if (game.active === AXIS) {
set_add(game.axis_sides, side)
@@ -472,12 +520,6 @@ function release_hex_control(a) {
})
}
-function is_new_battle_hex(a) {
- if (is_battle_hex(a))
- return !set_has(game.axis_hexes, a) && !set_has(game.allied_hexes, a)
- return false
-}
-
function claim_hex_control_for_defender(a) {
// a new battle hex: claim hex and hexsides for defender
@@ -595,6 +637,15 @@ function count_hp_in_battle() {
return hp
}
+function count_hp_in_battle_of_class(tc) {
+ let hp = 0
+ for_each_undisrupted_enemy_unit_in_hex(game.battle, u => {
+ if (unit_class(u) === tc)
+ hp += unit_hp(u)
+ })
+ return hp
+}
+
function count_normal_steps_in_pursuit() {
let steps = 0
for_each_undisrupted_enemy_unit_in_hex(game.pursuit, u => {
@@ -898,6 +949,15 @@ const path_cost = [ new Array(hexcount), new Array(hexcount), new Array(hexcount
const path_valid = new Array(hexcount)
const path_enemy = new Array(hexcount)
+function print_path(who, from, to, road) {
+ let p = [ hex_name[to] ]
+ while (to && to !== from) {
+ to = path_from[road][to]
+ p.unshift(hex_name[to])
+ }
+ log(unit_name(who) + " moved " + p.join(", ") + ".")
+}
+
function search_move(start, start_cost, start_road) {
// recon=4, forced march=+1, rommel bonus=+1
let limit = 6
@@ -1084,6 +1144,8 @@ function search_withdraw_bfs(from, cost, start, road, max_cost, sline, sdist) {
}
}
+// TODO: search_retreat where first hexside exit is restricted to friendly
+
function can_move_to(to, road, speed) {
// TODO: engagement & hexside limit
if (road >= 4 && path_cost[4][to] <= speed + 4)
@@ -1152,13 +1214,13 @@ function adjacent_hex_has_undisrupted_friendly_unit(here) {
}
function max_speed_of_undisrupted_friendly_unit_in_hex(from) {
- let max = 0
+ let max_speed = 0
for_each_undisrupted_friendly_unit_in_hex(from, u => {
let s = unit_speed(u)
- if (s > max)
- max = s
+ if (s > max_speed)
+ max_speed = s
})
- return max
+ return max_speed
}
function find_valid_regroup_destinations(from, rommel) {
@@ -1179,50 +1241,18 @@ function set_active_player() {
}
function set_passive_player() {
- if (game.phasing === AXIS)
+ if (game.active === AXIS)
game.active = ALLIED
else
game.active = AXIS
}
-// Supply check
-// Turn option
-
-// Movement
-// declare moves
-// normal moves
-// rout
-// retreats
-// declare full/partial retreats
-// probe combat
-// pursuit fire
-// withdraw
-// rout
-// pursuit fire
-// withdraw
-// forced marches
-// rout
-// pursuit fire
-// withdraw
-// refuse battle
-// pursuit fire
-// withdraw
-// rout
-// pursuit fire
-// withdraw
-// Combat
-// declare active
-// declare assault
-// resolve
-// defensive fire
-// rout
-// offensive fire
-// rout
-// Blitz Movement
-// Blitz Combat
-// Final supply check
-// rout
-// Reveal supply cards -> next player
+function set_enemy_player() {
+ if (game.active === AXIS)
+ game.active = ALLIED
+ else
+ game.active = AXIS
+}
function end_player_turn() {
// TODO: end when both pass
@@ -1235,6 +1265,8 @@ function end_player_turn() {
}
function goto_player_turn() {
+ log_h2(game.phasing)
+
// paranoid resetting of state
game.side_limit = {}
game.rommel = 0
@@ -1254,7 +1286,7 @@ function goto_initial_supply_check() {
if (snet[x]) {
set_unit_supply(u, ssrc)
if (is_unit_disrupted(u) && set_has(game.recover, u) && !is_battle_hex(x)) {
- log(`${unit_name(u)} recovered at ${hex_name[x]}`)
+ log(`%${u} recovered at #${x}`)
set_delete(game.recover, u)
clear_unit_disrupted(u)
}
@@ -1464,25 +1496,25 @@ states.regroup_move_destination = {
function goto_move_who() {
if (game.rommel === 1) {
if (game.from1 && game.to1)
- log(`Regroup move from ${game.from1} to ${game.to1} (Rommel).`)
+ log(`Regroup move from #${game.from1} to #${game.to1} (Rommel).`)
else if (game.from1)
- log(`Group move from ${game.from1} (Rommel).`)
+ log(`Group move from #${game.from1} (Rommel).`)
} else {
if (game.from1 && game.to1)
- log(`Regroup move from ${game.from1} to ${game.to1}.`)
+ log(`Regroup move from #${game.from1} to #${game.to1}.`)
else if (game.from1)
- log(`Group move from ${game.from1}.`)
+ log(`Group move from #${game.from1}.`)
}
if (game.rommel === 2) {
if (game.from2 && game.to2)
- log(`Regroup move from ${game.from2} to ${game.to2} (Rommel).`)
+ log(`Regroup move from #${game.from2} to #${game.to2} (Rommel).`)
else if (game.from2)
- log(`Group move from ${game.from2} (Rommel).`)
+ log(`Group move from #${game.from2} (Rommel).`)
} else {
if (game.from2 && game.to2)
- log(`Regroup move from ${game.from2} to ${game.to2}.`)
+ log(`Regroup move from #${game.from2} to #${game.to2}.`)
else if (game.from2)
- log(`Group move from ${game.from2}.`)
+ log(`Group move from #${game.from2}.`)
}
game.state = 'move_who'
}
@@ -1555,25 +1587,6 @@ function end_move_phase() {
goto_refuse_battle()
}
-function print_path(who, from, to, road) {
- let p = [ hex_name[to] ]
- while (to && to !== from) {
- to = path_from[road][to]
- p.unshift(hex_name[to])
- }
- log(unit_name(who) + " moved " + p.join(", ") + ".")
-}
-
-function print_pathX(who, start, to, road) {
- let from = path_from[road][to]
- log(`M ${hex_name[from]} to ${hex_name[to]}`)
- while (from && from !== start) {
- to = from
- from = path_from[road][from]
- log(`M ${hex_name[from]} to ${hex_name[to]}`)
- }
-}
-
function apply_move(move, who, from, to) {
let speed = unit_speed(who) + (move === game.rommel ? 1 : 0)
let road = pick_path(to, game.move_road, speed)
@@ -1869,7 +1882,7 @@ states.retreat_select_who = {
})
game.retreat_units = game.selected
game.selected = []
- goto_pursuit_fire(game.retreat)
+ goto_retreat_pursuit_fire(game.retreat)
},
partial_retreat() {
clear_undo()
@@ -1898,7 +1911,7 @@ states.provoke_probe_combat = {
if (shielded)
goto_retreat_who()
else
- goto_pursuit_fire(game.retreat)
+ goto_retreat_pursuit_fire(game.retreat)
},
}
@@ -1938,13 +1951,30 @@ states.retreat_to = {
prompt() {
view.prompt = `Retreat: Select destination.`
let who = game.selected[0]
+
gen_action_unit(who)
- //if (game.turn_option === 'pass') {
- {
+
+ if (game.turn_option === 'pass') {
search_withdraw(game.retreat, true)
- // TODO: regroup
- gen_withdraw_group_move(who, game.retreat)
+ } else {
+ search_retreat(game.retreat)
}
+
+ if (from === game.from1 && !game.to1)
+ for (let to of all_hexes)
+ if (to != from && can_move_group_1(who, from, to))
+ gen_action_hex(to)
+
+ if (from === game.from2 && !game.to2)
+ for (let to of all_hexes)
+ if (to != from && can_move_group_2(who, from, to))
+ gen_action_hex(to)
+
+ if (can_move_regroup_1(who, from, game.to1))
+ gen_action_hex(game.to1)
+
+ if (can_move_regroup_2(who, from, game.to2))
+ gen_action_hex(game.to2)
},
unit(who) {
pop_undo()
@@ -1989,7 +2019,7 @@ states.refuse_battle = {
hex(x) {
push_undo()
set_delete(game.active_battles, x)
- goto_pursuit_fire(x)
+ goto_refuse_pursuit_fire(x)
},
next() {
goto_combat_phase()
@@ -2144,213 +2174,203 @@ function end_combat_phase() {
// === BATTLES ===
+// Normal Battle:
+// passive fire
+// active hits
+// active fire
+// passive hits
+
+function roll_fire(who, fp, tc) {
+ let roll = random(6) + 1
+ log(`${who} fired ${firepower_name[fp]} ${roll} at ${class_name[tc]}`)
+ if (roll >= fp)
+ return 1
+ return 0
+}
+
function goto_battle(x) {
clear_undo()
game.battle = x
- goto_defensive_fire()
-}
+ game.fired = []
-function goto_defensive_fire() {
+ // goto defensive fire
set_passive_player()
- game.fired = []
+ game.state = 'battle_fire'
game.hits = [ 0, 0, 0, 0 ]
- game.state = 'defensive_fire'
}
-function goto_offensive_fire() {
- set_active_player()
- game.fired = []
- game.hits = [ 0, 0, 0, 0 ]
- game.state = 'offensive_fire'
-}
+function apply_battle_fire(tc) {
+ let firing = game.selected[0]
+ game.selected.length = 0
-const xxx_fire = {
- prompt() {
- view.prompt = `Fire!`
+ let fp = FIREPOWER_MATRIX[unit_class(firing)][tc]
+ let cv = unit_cv(firing)
- let arty = false
- for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
- if (is_artillery_unit(u)) {
- if (!is_unit_fired(u)) {
- gen_action_unit(u)
- arty = true
- }
- }
- })
+ set_unit_fired(firing)
- if (!arty) {
- for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
- if (!is_unit_fired(u))
- gen_action_unit(u)
- })
+ for (let i = 0; i < cv; ++i)
+ game.hits[tc] += roll_fire(firing, fp, tc)
+
+ // clamp to available hit points
+ game.hits[tc] = min(game.hits[tc], count_hp_in_battle_of_class(tc))
+
+ // end firing when all done
+ let done = true
+ for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
+ if (!is_unit_fired(u))
+ done = false
+ })
+ if (done) {
+ set_enemy_player()
+ game.state = 'battle_hits'
+ }
+}
+
+function gen_battle_fire() {
+ let arty = false
+ for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
+ if (is_artillery_unit(u)) {
+ if (!is_unit_fired(u)) {
+ gen_action_unit(u)
+ arty = true
+ }
}
- },
- unit(who) {
- game.selected = [ who ]
- game.state = game.state + '_target'
- },
+ })
+ if (!arty) {
+ for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
+ if (!is_unit_fired(u))
+ gen_action_unit(u)
+ })
+ }
}
-const xxx_fire_target = {
- prompt() {
- view.prompt = `Select a target class.`
+function gen_battle_target() {
+ let hp = count_hp_in_battle()
+ for (let i = 0; i < 4; ++i)
+ hp[i] -= game.hits[i]
- let hp = count_hp_in_battle()
- for (let i = 0; i < 4; ++i)
- hp[i] -= game.hits[i]
+ let who = game.selected[0]
+ let fc = unit_class(who)
- let who = game.selected[0]
- let fc = unit_class(who)
+ gen_action_unit(who) // deselect
- gen_action_unit(who) // deselect
+ // armor must target armor if possible
+ if (fc === ARMOR && hp[ARMOR] > 0) {
+ gen_action('armor')
+ return
+ }
- // armor must target armor if possible
- if (fc === ARMOR && hp[ARMOR] > 0) {
- gen_action('armor')
- return
- }
+ // infantry must target infantry if possible
+ if (fc === INFANTRY && hp[INFANTRY] > 0) {
+ gen_action('infantry')
+ return
+ }
- // infantry must target infantry if possible
- if (fc === INFANTRY && hp[INFANTRY] > 0) {
- gen_action('infantry')
- return
+ if (hp[ARMOR] > 0)
+ gen_action('armor')
+ if (hp[INFANTRY] > 0)
+ gen_action('infantry')
+ if (hp[ANTITANK] > 0)
+ gen_action('antitank')
+
+ // only artillery may target artillery if other units are alive
+ if (hp[ARTILLERY] > 0) {
+ if (fc === ARTILLERY ||
+ (hp[ARTILLERY] <= 0 && hp[INFANTRY] <= 0 && hp[ANTITANK] <= 0))
+ gen_action('artillery')
+ }
+}
+
+function gen_battle_hits() {
+ let normal_steps = count_normal_steps_in_battle()
+ let elite_steps = count_elite_steps_in_battle()
+
+ let done = true
+ for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
+ let c = unit_class(u)
+ if (is_unit_elite(u)) {
+ if (game.hits[c] >= 2) {
+ gen_action_unit(u)
+ done = false
+ }
+ } else {
+ if (game.hits[c] >= 1) {
+ // If mixed elite and non-elite: must assign ALL damage.
+ if (elite_steps[c] > 0 && normal_steps[c] === 1 && (game.hits[c] & 1) === 0) {
+ // Eliminating the last non-elite must not leave an odd
+ // number of hits remaining.
+ } else {
+ gen_action_unit(u)
+ done = false
+ }
+ }
}
+ })
+ if (done)
+ gen_action_next()
+}
+
+function apply_battle_hit(who) {
+ game.hits[unit_class(who)] -= reduce_unit(who)
+}
- if (hp[ARMOR] > 0)
- gen_action('armor')
- if (hp[INFANTRY] > 0)
- gen_action('infantry')
- if (hp[ANTITANK] > 0)
- gen_action('antitank')
-
- // only artillery may target artillery if other units are alive
- if (hp[ARTILLERY] > 0) {
- if (fc === ARTILLERY ||
- (hp[ARTILLERY] <= 0 && hp[INFANTRY] <= 0 && hp[ANTITANK] <= 0))
- gen_action('artillery')
+states.battle_fire = {
+ prompt() {
+ if (game.active === game.phasing)
+ view.prompt = `Offensive Fire!`
+ else
+ view.prompt = `Defensive Fire!`
+ if (game.selected.length > 0) {
+ gen_battle_target()
+ } else {
+ gen_battle_fire()
}
},
- unit(u) {
- game.selected = []
- resume_fire()
+ unit(who) {
+ if (game.selected.length > 0)
+ game.selected.length = 0
+ else
+ game.selected.push(who)
},
armor() {
- let who = game.selected[0]
- game.selected = []
- fire_at(who, ARMOR)
+ apply_battle_fire(ARMOR)
},
infantry() {
- let who = game.selected[0]
- game.selected = []
- fire_at(who, INFANTRY)
+ apply_battle_fire(INFANTRY)
},
antitank() {
- let who = game.selected[0]
- game.selected = []
- fire_at(who, ANTITANK)
+ apply_battle_fire(ANTITANK)
},
artillery() {
- let who = game.selected[0]
- game.selected = []
- fire_at(who, ARTILLERY)
+ apply_battle_fire(ARTILLERY)
},
}
-const xxx_fire_hits = {
+states.battle_hits = {
prompt() {
+ if (game.active === game.phasing)
+ view.prompt = `Apply hits from Defensive Fire.`
+ else
+ view.prompt = `Apply hits from Offensive Fire.`
view.prompt = `Apply hits.`
-
- let normal_steps = count_normal_steps_in_battle()
- let elite_steps = count_elite_steps_in_battle()
-
- let done = true
- for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
- let c = unit_class(u)
- if (is_unit_elite(u)) {
- if (game.hits[c] >= 2) {
- gen_action_unit(u)
- done = false
- }
- } else {
- if (game.hits[c] >= 1) {
- // If mixed elite and non-elite: must assign ALL damage.
- if (elite_steps[c] > 0 && normal_steps[c] === 1 && (game.hits[c] & 1) === 0) {
- // Eliminating the last non-elite must not leave an odd
- // number of hits remaining.
- } else {
- gen_action_unit(u)
- done = false
- }
- }
- }
- })
- if (done)
- gen_action_next()
+ gen_battle_hits()
},
unit(who) {
push_undo()
- let c = unit_class(who)
- game.hits[c] -= reduce_unit(who)
+ apply_battle_hit(who)
},
next() {
clear_undo()
- if (game.state === 'defensive_fire_hits') {
- goto_offensive_fire()
+ if (game.active === game.phasing) {
+ // goto offensive fire
+ game.state = 'battle_fire'
+ game.hits = [ 0, 0, 0, 0 ]
} else {
end_battle()
}
},
}
-function roll_fire(who, fp, tc) {
- let roll = random(6) + 1
- log(`${who} fired ${firepower_name[fp]} ${roll} at ${class_name[tc]}`)
- if (roll >= fp)
- return 1
- return 0
-}
-
-function fire_at(firing, tc) {
- let fp = FIREPOWER_MATRIX[unit_class(firing)][tc]
- let cv = unit_cv(firing)
-
- set_unit_fired(firing)
-
- for (let i = 0; i < cv; ++i)
- game.hits[tc] += roll_fire(firing, fp, tc)
-
- resume_fire()
-}
-
-function resume_fire() {
- game.state = game.state.replace("_target", "")
- let done = true
- for_each_undisrupted_friendly_unit_in_hex(game.battle, u => {
- if (!is_unit_fired(u))
- done = false
- })
- if (done)
- goto_fire_hits()
-}
-
-function goto_fire_hits() {
- // clamp number of hits to available hp
- let hp = [ 0, 0, 0, 0 ]
- for (let u = 0; u < units.length; ++u)
- if (is_enemy_unit(u) && unit_hex(u) === game.battle)
- hp[unit_class(u)] += unit_hp(u)
- for (let i = 0; i < 4; ++i)
- game.hits[i] = min(game.hits[i], hp[i])
-
- if (game.state === 'defensive_fire') {
- set_active_player()
- game.state = 'defensive_fire_hits'
- } else {
- set_passive_player()
- game.state = 'offensive_fire_hits'
- }
-}
-
function end_battle() {
clear_undo()
set_active_player()
@@ -2363,37 +2383,47 @@ function end_battle() {
end_combat_phase()
}
-states.defensive_fire = xxx_fire
-states.offensive_fire = xxx_fire
-states.defensive_fire_target = xxx_fire_target
-states.offensive_fire_target = xxx_fire_target
-states.defensive_fire_hits = xxx_fire_hits
-states.offensive_fire_hits = xxx_fire_hits
+function end_probe() {
+ game.battle = 0
+ resume_retreat()
+}
// === PURSUIT FIRE ===
-function goto_retreat_fire(where) {
+function goto_retreat_pursuit_fire(where) {
clear_undo()
set_passive_player()
game.hits = 0
game.pursuit = where
if (can_pursuit_fire())
- game.state = 'pursuit_fire'
+ game.state = 'retreat_pursuit_fire'
else
goto_pursuit_hits()
}
-function goto_pursuit_fire(where) {
+function goto_refuse_pursuit_fire(where) {
clear_undo()
set_active_player()
game.hits = 0
game.pursuit = where
if (can_pursuit_fire())
- game.state = 'pursuit_fire'
+ game.state = 'refuse_pursuit_fire'
else
goto_pursuit_hits()
}
+function goto_pursuit_hits() {
+ if (game.hits > 0) {
+ set_passive_player()
+ let hp = count_hp_in_pursuit()
+ if (game.hits > hp)
+ game.hits = hp
+ game.state = 'pursuit_hits'
+ } else {
+ end_pursuit_fire()
+ }
+}
+
function slowest_undisrupted_enemy_unit_speed(where) {
let r = 4
for_each_undisrupted_enemy_unit_in_hex(where, u => {
@@ -2433,7 +2463,7 @@ function roll_pursuit_fire(n) {
}
}
-states.pursuit_fire = {
+const xxx_pursuit_fire = {
inactive: "pursuit fire (fire)",
prompt() {
view.prompt = `Pursuit Fire.`
@@ -2457,19 +2487,7 @@ states.pursuit_fire = {
}
}
-function goto_pursuit_hits() {
- if (game.hits > 0) {
- set_passive_player()
- let hp = count_hp_in_pursuit()
- if (game.hits > hp)
- game.hits = hp
- game.state = 'pursuit_hits'
- } else {
- end_pursuit_fire()
- }
-}
-
-states.pursuit_hits = {
+const xxx_pursuit_hits = {
inactive: "pursuit fire (hits)",
prompt() {
view.prompt = `Pursuit Fire: Apply ${game.hits} hits.`
@@ -2569,6 +2587,7 @@ states.free_deployment = {
},
hex(x) {
push_undo()
+ log(`Deployed ${game.selected.length} at #${x}.`)
for (let i = 0; i < game.selected.length; ++i) {
let u = game.selected[i]
set_unit_hex(u, x)
@@ -2577,10 +2596,12 @@ states.free_deployment = {
},
next() {
clear_undo()
- if (game.active === AXIS)
+ if (game.active === AXIS) {
game.active = ALLIED
- else
+ log_h2("Allied Deployment")
+ } else {
end_free_deployment()
+ }
}
}
@@ -2594,6 +2615,10 @@ function end_free_deployment() {
// TODO: mulligan
+ log_br()
+ log_h1(`Month ${game.month}`)
+ log_br()
+
// No buildup first month
// No initiative first month
goto_player_turn()
@@ -3026,12 +3051,15 @@ function setup(name) {
let scenario = SCENARIOS[name]
game.month = scenario.start
+ log_h1(name)
+
SETUP[name](-scenario.start)
game.bardia = setup_fortress(scenario, BARDIA)
game.benghazi = setup_fortress(scenario, BENGHAZI)
game.tobruk = setup_fortress(scenario, TOBRUK)
+ log_h2("Axis Deployment")
game.active = 'Axis'
game.state = 'free_deployment'
game.selected = []
@@ -3296,7 +3324,7 @@ function clear_undo() {
game.undo = []
}
-function logbr() {
+function log_br() {
if (game.log.length > 0 && game.log[game.log.length-1] !== "")
game.log.push("")
}
@@ -3305,6 +3333,24 @@ function log(msg) {
game.log.push(msg)
}
+function log_h1(msg) {
+ log_br()
+ log(".h1 " + msg)
+ log_br()
+}
+
+function log_h2(msg) {
+ log_br()
+ log(".h2 " + msg)
+ log_br()
+}
+
+function log_h3(msg) {
+ log_br()
+ log(".h3 " + msg)
+ log_br()
+}
+
function gen_action(action, argument) {
if (argument !== undefined) {
if (!(action in view.actions)) {
@@ -3323,7 +3369,7 @@ function goto_game_over(result, victory) {
game.active = "None"
game.result = result
game.victory = victory
- logbr()
+ log_br()
log(game.victory)
}