diff options
author | Joël Simoneau <simoneaujoel@gmail.com> | 2024-12-29 11:15:08 -0500 |
---|---|---|
committer | Joël Simoneau <simoneaujoel@gmail.com> | 2024-12-29 11:15:08 -0500 |
commit | ea22a43c2f0507cdc25494c896f577475d6f0971 (patch) | |
tree | bfdd5f36c7e8aa82e9d3dfc14429b5cfd2a38c30 | |
parent | 74ecddba5a3c053b1dd57f0f4e330dca1dec0406 (diff) | |
download | vijayanagara-ea22a43c2f0507cdc25494c896f577475d6f0971.tar.gz |
attack wip
-rw-r--r-- | play.css | 2 | ||||
-rw-r--r-- | rules.js | 257 |
2 files changed, 230 insertions, 29 deletions
@@ -137,6 +137,8 @@ main { background-color: #777; } #log .italic { font-style: italic; } #log div { padding-left: 20px; text-indent: -12px; } #log div.indent { padding-left: 32px; text-indent: -12px; } +#log .h1 { border-bottom: 2px solid #444; border-top: 2px solid #444; } +#log .h2 { border-bottom: 1px solid #444; border-top: 1px solid #444; } #log .adice { font-size: 14px; @@ -342,6 +342,7 @@ function goto_eligible() { limited: 0, free: 0, spaces: [], + pieces: [], where: -1, pass: 1 } @@ -412,7 +413,7 @@ function goto_cavalry(n, next) { } function goto_compromising_gifts() { - if (game.inf[game.cmd.who] === 0) + if (game.inf[game.current] === 0) end_card() else game.state = "compromising_gifts" @@ -932,10 +933,12 @@ function can_attack_rebel_in_space(s, faction) { function goto_attack() { init_command("Attack") game.cmd.attacker = game.current + game.cmd.support_space = null game.state = "attack" } function goto_attack_select() { + game.cmd.selected = [] game.cmd.target = [0, 0, 0, 0] if (game.current === DS) { game.cmd.target[BK] += can_attack_rebel_in_space(game.cmd.where, BK) @@ -952,7 +955,7 @@ function goto_attack_select() { let n = game.cmd.target.reduce((a, c) => a + c, 0); if (n === 1) { game.cmd.target = game.cmd.target.indexOf(1) - game.state = "attack_space" + goto_attack_space() } else { game.state = "attack_select" } @@ -966,11 +969,6 @@ function roll_attack(faction_d) { game.dice[3] = 0 } -function goto_attack_cavalry() { - game.cmd.clog = false - game.state = "attack_cavalry" -} - function attack_use_cavalry(d) { use_cavalry(game.current) @@ -1008,20 +1006,25 @@ function screen_die(d) { states.attack = { prompt() { - if (game.current === DS) - view.prompt = "Attack: Select Spaces with Rebels or Mongol Invaders." - else - view.prompt = "Attack: Select Provinces with enemy pieces." - if (can_select_cmd_space(1) && can_attack()) { + if (game.current === DS) + view.prompt = "Attack: Select Spaces with Rebels or Mongol Invaders." + else + view.prompt = "Attack: Select Provinces with enemy pieces." + for (let s = first_space; s <= last_space; ++s) { if (!is_selected_cmd_space(s) && can_attack_in_space(s)) gen_action_space(s) } + } else { + view.prompt = "Attack: Done." } }, space(s) { + push_undo() game.cmd.where = s + select_cmd_space(game.cmd.where, 1) + set_add(game.cmd.spaces, game.cmd.where) log_space(game.cmd.where, "Attack") goto_attack_select() } @@ -1029,38 +1032,136 @@ states.attack = { states.attack_select = { prompt() { - view.prompt = "Attack: Choose a Faction to attack" + view.prompt = "Attack: Choose a Faction to attack." + for (let [f, t] of game.cmd.target.entries()) + if (t != 0) + gen_faction_in_space(game.cmd.where, f) + + }, + piece(p) { + let f = piece_faction(p) + game.cmd.target = f + goto_attack_space() + } +} + +function goto_attack_space() { + game.cmd.n_units = [0, 0] + + for_each_movable(game.cmd.target, p => { + if (piece_space(p) === game.cmd.where) { + set_add(game.cmd.selected, p) + set_add(game.cmd.pieces, p) + game.cmd.n_units[1] += 1 + if (game.cmd.target === BK || game.cmd.target === VE) + to_rebel(p) + } + }) + for_each_piece(game.cmd.target, DISC, p => { + if (piece_space(p) === game.cmd.where) + set_add(game.cmd.selected, p) + }) + for_each_movable(game.cmd.attacker, p => { + if (piece_space(p) === game.cmd.where) { + set_add(game.cmd.selected, p) + set_add(game.cmd.pieces, p) + game.cmd.n_units[0] += 1 + } + }) + game.cmd.n_adj = (game.current === VE) ? 1 : 2 + + if (has_valid_support_attackers(game.cmd.where, game.cmd.attacker)) + game.state = "attack_adjacent_support" + else + game.state = "attack_space" +} + +states.attack_adjacent_support = { + prompt() { + view.who = game.cmd.selected + + if (game.current === DS) + view.prompt = "Attack: Add up to two Units from adjacent Space with a Qasbah." + else if (game.current === BK) + view.prompt = "Attack: Add up to two Amirs from adjacent Province with a Fort." + else if (game.current === VE) + view.prompt = "Attack: Add up to one Raja from adjacent Province with a Temple." + + if (game.cmd.support_space == null) { + for (let s = first_space; s <= last_space; ++s) + if (can_support_from(s, game.cmd.attacker)) + gen_action_space(s) + } else { + if (game.cmd.n_adj > 0) + for_each_movable(game.cmd.attacker, p => { + if ( + piece_space(p) === game.cmd.support_space && + !set_has(game.cmd.selected, p) && + !set_has(game.cmd.pieces, p) + ) + gen_action_piece(p) + }) + } + + if (game.cmd.n_units[0] > 0) + view.actions.next = 1 + }, + space(s) { + game.cmd.support_space = s + }, + piece(p) { + set_add(game.cmd.selected, p) + set_add(game.cmd.pieces, p) + game.cmd.n_adj -= 1 + game.cmd.n_units[0] += 1 + + }, + next() { + game.state = "attack_space" } } states.attack_space = { prompt() { - view.prompt = "Attack: " + view.prompt = "Attack: Roll the die to attack." + view.who = game.cmd.selected view.actions.roll = 1 }, roll() { + // clear_undo() TODO: remove for prd roll_attack() log(">.ad " + game.dice.slice(0,4).map(d => AD[d]).join(" ")) log(">.dd " + game.dice.slice(4).map(d => DD[d]).join(" ")) log_br() + game.cmd.step = 0 goto_attack_cavalry() } } +function goto_attack_cavalry() { + if (game.cmd.step === 0) { + game.current = game.cmd.attacker + game.state = "attack_cavalry" + } else if (game.cmd.step === 1) { + game.current = game.cmd.target + game.state = "attack_cavalry" + } else { + game.cmd.a_hit = game.dice.slice(0,4).filter(d => d > 0 && d <= game.cmd.n_units[0]).length + game.cmd.d_hit = game.dice.slice(4).filter(d => d > 0 && d <= game.cmd.n_units[1]).length + game.cmd.victor = get_attack_victor() + log_br() + log(`${faction_name[game.cmd.attacker]} scores ${game.cmd.a_hit} hits.`) + log(`${faction_name[game.cmd.target]} scores ${game.cmd.d_hit} hits.`) + goto_attack_casualties("target") + } +} + states.attack_cavalry = { prompt() { view.prompt = "Attack: Use cavalry to..." - - // game.cmd.attacker - // game.cmd.target - // game.current - // - - // STEP ? - // step 1 - attacker cavalry - // step 2 - defender calvary + view.who = game.cmd.selected let curr_die = [0, 1, 2, 3, 4, 5] // TODO: restrict range for MI player @@ -1081,10 +1182,70 @@ states.attack_cavalry = { attack_use_cavalry(d) }, next() { + game.cmd.step += 1 + goto_attack_cavalry() + } +} + +function get_attack_victor() { + if (game.cmd.a_hit > game.cmd.d_hit) + return game.cmd.attacker + else if (game.cmd.a_hit < game.cmd.d_hit) + return game.cmd.target + else + return -1 +} +function goto_attack_casualties(step) { + if (step === "target") { + game.current = game.cmd.target + game.cmd.count = game.cmd.a_hit + game.state = "attack_casualties" + } else if (step === "attacker") { + game.current = game.cmd.attacker + game.cmd.count = game.cmd.d_hit + game.state = "attack_casualties" } } +states.attack_casualties = { + prompt() { + + if ( + game.cmd.count > 0 && + game.cmd.selected.filter(p => piece_faction(p) === game.current).length > 0 + ) { + view.prompt = `Attack: ${faction_name[game.current]} must remove ${game.cmd.count} pieces as casualties.` + + for (let p of game.cmd.selected) + if (piece_faction(p) === game.current) + gen_action_piece(p) + } else { + view.prompt = "Attack: No more casualties to remove." + view.actions.next = 1 + } + + }, + piece(p) { + remove_piece(p) + set_delete(game.cmd.selected, p) + game.cmd.count -= 1 + }, + next() { + if (game.current === game.cmd.target) + goto_attack_casualties("attacker") + else + goto_attack_resolution() + } +} + +function goto_attack_resolution() { + if (is_rebel_faction(game.cmd.target) && is_rebel_faction(game.cmd.attacker)) + console.log("Implement shift") + game.state = "attack" + +} + /* DELHI SULTANATE COMMANDS */ @@ -1956,6 +2117,16 @@ function is_faction_control(s, faction) { return game.control[faction] & (1 << s) } +function is_rebel_faction(faction) { + if (faction === BK || faction === VE) + return true + return false +} + +function is_rebel_faction_elite(p) { + return (piece_type(p) === ELITE && [BK, VE].includes(piece_faction(p))) +} + function remove_tributary(s) { game.tributary &= ~(1 << s) update_control() @@ -1978,9 +2149,11 @@ function is_rebel(p) { } function to_obedient(p) { - let faction = piece_faction(p) - let piece_index = p - first_piece[faction][ELITE] - game.rebel[faction] &= ~(1 << piece_index) + if (is_rebel_faction_elite(p)) { + let faction = piece_faction(p) + let piece_index = p - first_piece[faction][ELITE] + game.rebel[faction] &= ~(1 << piece_index) + } } function to_obedient_space(s) { @@ -2089,10 +2262,10 @@ function has_piece_faction(s, faction) { return count_faction_pieces(s, faction) > 0 } -function has_unmoved_piece(s, faction) { +function has_unmoved_piece(space, faction) { let unmoved = false for_each_movable(faction, p => { - if (piece_space(p) === s) + if (piece_space(p) === space) if (!game.cmd.pieces || game.cmd.pieces.length === 0) unmoved = true else if (!set_has(game.cmd.pieces, p)) @@ -2115,6 +2288,23 @@ function has_valid_attackers(s, faction) { return valid_attacker } +function can_support_from(s, faction) { + let valid_attacker = false + for_each_movable(faction, p => { + if (piece_space(p) === s && has_piece(s, faction, DISC)) + valid_attacker = true + }) + return valid_attacker +} + + +function has_valid_support_attackers(s, faction) { + for (let ss of SPACES[s].adjacent) + if (can_support_from(ss, faction)) + return true + return false +} + function gen_place_piece(faction, type) { for_each_piece(faction, type, p => { if (piece_space(p) === AVAILABLE) { @@ -2144,6 +2334,7 @@ function place_piece(p, s) { } function remove_piece(p) { + to_obedient(p) set_piece_space(p, AVAILABLE) update_control() } @@ -2855,6 +3046,15 @@ function gen_piece_in_space(space, faction, type) { }) } +function gen_faction_in_space(space, faction) { + if (faction === BK || faction === VE || faction === DS) { + gen_piece_in_space(space, faction, ELITE) + gen_piece_in_space(space, faction, DISC) + } + if (faction === DS || faction === MI) + gen_piece_in_space(space, faction, TROOPS) +} + function for_each_movable(faction, f) { if (faction === BK) for_each_piece(BK, ELITE, f) @@ -2863,7 +3063,6 @@ function for_each_movable(faction, f) { else if (faction === DS) { for_each_piece(DS, TROOPS, f) for_each_piece(DS, ELITE, f) - } } |