2025-08-19 14:15:23 -07:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import List, Optional
|
|
|
|
|
2025-08-18 11:58:25 -07:00
|
|
|
from deck_builder.builder import DeckBuilder
|
|
|
|
|
2025-08-19 10:18:53 -07:00
|
|
|
"""Non-interactive harness.
|
|
|
|
|
|
|
|
Features:
|
|
|
|
- Script commander selection.
|
|
|
|
- Script primary / optional secondary / tertiary tags.
|
|
|
|
- Apply bracket & accept default ideal counts.
|
|
|
|
- Invoke multi-theme creature addition if available (fallback to primary-only).
|
|
|
|
|
|
|
|
Use run(..., secondary_choice=2, tertiary_choice=3, use_multi_theme=True) to exercise multi-theme logic.
|
|
|
|
Indices correspond to the numbered tag list presented during interaction.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def run(
|
2025-08-20 10:46:23 -07:00
|
|
|
command_name: str = "Pantlaza",
|
2025-08-19 10:18:53 -07:00
|
|
|
add_creatures: bool = True,
|
2025-08-19 14:15:23 -07:00
|
|
|
add_non_creature_spells: bool = True,
|
|
|
|
# Fine-grained toggles (used only if add_non_creature_spells is False)
|
|
|
|
add_ramp: bool = True,
|
|
|
|
add_removal: bool = True,
|
|
|
|
add_wipes: bool = True,
|
|
|
|
add_card_advantage: bool = True,
|
|
|
|
add_protection: bool = True,
|
2025-08-19 10:18:53 -07:00
|
|
|
use_multi_theme: bool = True,
|
2025-08-20 10:46:23 -07:00
|
|
|
primary_choice: int = 2,
|
|
|
|
secondary_choice: Optional[int] = 2,
|
|
|
|
tertiary_choice: Optional[int] = 2,
|
2025-08-19 10:18:53 -07:00
|
|
|
add_lands: bool = True,
|
2025-08-19 14:15:23 -07:00
|
|
|
fetch_count: Optional[int] = 3,
|
|
|
|
dual_count: Optional[int] = None,
|
|
|
|
triple_count: Optional[int] = None,
|
|
|
|
utility_count: Optional[int] = None,
|
2025-08-19 15:00:28 -07:00
|
|
|
seed: Optional[int] = None,
|
2025-08-19 14:15:23 -07:00
|
|
|
) -> DeckBuilder:
|
|
|
|
"""Run a scripted non-interactive deck build and return the DeckBuilder instance.
|
|
|
|
|
|
|
|
Integer parameters (primary_choice, secondary_choice, tertiary_choice) correspond to the
|
|
|
|
numeric indices shown during interactive tag selection. Pass None to omit secondary/tertiary.
|
|
|
|
Optional counts (fetch_count, dual_count, triple_count, utility_count) constrain land steps.
|
2025-08-19 15:00:28 -07:00
|
|
|
seed: optional deterministic RNG seed for reproducible builds.
|
2025-08-19 14:15:23 -07:00
|
|
|
"""
|
|
|
|
scripted_inputs: List[str] = []
|
2025-08-19 10:18:53 -07:00
|
|
|
# Commander query & selection
|
|
|
|
scripted_inputs.append(command_name) # initial query
|
|
|
|
scripted_inputs.append("1") # choose first search match to inspect
|
|
|
|
scripted_inputs.append("y") # confirm commander
|
|
|
|
# Primary tag selection
|
|
|
|
scripted_inputs.append(str(primary_choice))
|
|
|
|
# Secondary tag selection or stop (0)
|
|
|
|
if secondary_choice is not None:
|
|
|
|
scripted_inputs.append(str(secondary_choice))
|
|
|
|
# Tertiary tag selection or stop (0)
|
|
|
|
if tertiary_choice is not None:
|
|
|
|
scripted_inputs.append(str(tertiary_choice))
|
|
|
|
else:
|
|
|
|
scripted_inputs.append("0")
|
|
|
|
else:
|
|
|
|
scripted_inputs.append("0") # stop at primary
|
|
|
|
# Bracket (meta power / style) selection; keeping existing scripted value
|
2025-08-20 10:46:23 -07:00
|
|
|
scripted_inputs.append("3")
|
2025-08-19 10:18:53 -07:00
|
|
|
# Ideal count prompts (press Enter for defaults)
|
2025-08-18 11:58:25 -07:00
|
|
|
for _ in range(8):
|
|
|
|
scripted_inputs.append("")
|
|
|
|
|
|
|
|
def scripted_input(prompt: str) -> str:
|
|
|
|
if scripted_inputs:
|
|
|
|
return scripted_inputs.pop(0)
|
|
|
|
raise RuntimeError("Ran out of scripted inputs for prompt: " + prompt)
|
|
|
|
|
2025-08-19 15:00:28 -07:00
|
|
|
builder = DeckBuilder(input_func=scripted_input, seed=seed)
|
2025-08-19 10:18:53 -07:00
|
|
|
builder.run_initial_setup()
|
|
|
|
builder.run_deck_build_step1()
|
|
|
|
builder.run_deck_build_step2()
|
|
|
|
|
|
|
|
# Land sequence (optional)
|
|
|
|
if add_lands:
|
|
|
|
if hasattr(builder, 'run_land_step1'):
|
|
|
|
builder.run_land_step1() # Basics / initial
|
|
|
|
if hasattr(builder, 'run_land_step2'):
|
|
|
|
builder.run_land_step2() # Utility basics / rebalancing
|
|
|
|
if hasattr(builder, 'run_land_step3'):
|
|
|
|
builder.run_land_step3() # Kindred lands if applicable
|
|
|
|
if hasattr(builder, 'run_land_step4'):
|
|
|
|
builder.run_land_step4(requested_count=fetch_count)
|
|
|
|
if hasattr(builder, 'run_land_step5'):
|
|
|
|
builder.run_land_step5(requested_count=dual_count)
|
|
|
|
if hasattr(builder, 'run_land_step6'):
|
|
|
|
builder.run_land_step6(requested_count=triple_count)
|
|
|
|
if hasattr(builder, 'run_land_step7'):
|
2025-08-19 14:15:23 -07:00
|
|
|
|
2025-08-19 10:18:53 -07:00
|
|
|
builder.run_land_step7(requested_count=utility_count)
|
|
|
|
if hasattr(builder, 'run_land_step8'):
|
|
|
|
builder.run_land_step8()
|
|
|
|
|
|
|
|
if add_creatures:
|
|
|
|
builder.add_creatures()
|
2025-08-19 14:15:23 -07:00
|
|
|
# Non-creature spell categories (ramp / removal / wipes / draw / protection)
|
|
|
|
if add_non_creature_spells and hasattr(builder, 'add_non_creature_spells'):
|
|
|
|
builder.add_non_creature_spells()
|
|
|
|
else:
|
|
|
|
# Allow selective invocation if orchestrator not desired
|
|
|
|
if add_ramp and hasattr(builder, 'add_ramp'):
|
|
|
|
builder.add_ramp()
|
|
|
|
if add_removal and hasattr(builder, 'add_removal'):
|
|
|
|
builder.add_removal()
|
|
|
|
if add_wipes and hasattr(builder, 'add_board_wipes'):
|
|
|
|
builder.add_board_wipes()
|
|
|
|
if add_card_advantage and hasattr(builder, 'add_card_advantage'):
|
|
|
|
builder.add_card_advantage()
|
|
|
|
if add_protection and hasattr(builder, 'add_protection'):
|
|
|
|
builder.add_protection()
|
2025-08-19 10:18:53 -07:00
|
|
|
|
|
|
|
|
2025-08-19 14:15:23 -07:00
|
|
|
# Suppress verbose library print in non-interactive run since CSV export is produced.
|
|
|
|
# builder.print_card_library()
|
2025-08-19 10:18:53 -07:00
|
|
|
builder.post_spell_land_adjust()
|
2025-08-19 14:15:23 -07:00
|
|
|
# Export decklist CSV (commander first word + date)
|
|
|
|
if hasattr(builder, 'export_decklist_csv'):
|
|
|
|
builder.export_decklist_csv()
|
2025-08-19 10:18:53 -07:00
|
|
|
return builder
|
2025-08-18 11:58:25 -07:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
run()
|