mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-16 23:50:12 +01:00
Started deck builder function, added base structure and prompt for selecting commander
This commit is contained in:
parent
ff2b1e9932
commit
aee44190a9
4 changed files with 166 additions and 3 deletions
|
|
@ -5,7 +5,6 @@ import pandas as pd # type: ignore
|
||||||
|
|
||||||
from fuzzywuzzy import fuzz, process # type: ignore
|
from fuzzywuzzy import fuzz, process # type: ignore
|
||||||
from IPython.display import display
|
from IPython.display import display
|
||||||
from tabulate import tabulate
|
|
||||||
|
|
||||||
pd.set_option('display.max_colwidth', None)
|
pd.set_option('display.max_colwidth', None)
|
||||||
pd.set_option('display.expand_frame_repr', True)
|
pd.set_option('display.expand_frame_repr', True)
|
||||||
|
|
|
||||||
131
deck_builder.py
Normal file
131
deck_builder.py
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import inquirer.prompt # type: ignore
|
||||||
|
import pandas as pd # type: ignore
|
||||||
|
import pprint # type: ignore
|
||||||
|
|
||||||
|
from fuzzywuzzy import fuzz, process # type: ignore
|
||||||
|
from IPython.display import display
|
||||||
|
|
||||||
|
# Basic deck builder, initial plan will just be for kindred support.
|
||||||
|
# Would like to add logic for other themes, as well as automatically go
|
||||||
|
# through the commander and find suitable themes.
|
||||||
|
|
||||||
|
# Will have it ask questions to determine number of creatures, lands,
|
||||||
|
# interaction, ramp, etc... then adjust from there.
|
||||||
|
# Land spread will ideally be handled based on pips and some adjustment
|
||||||
|
# is planned based on mana curve and ramp added
|
||||||
|
|
||||||
|
# Later plans to have card price taken into account will be added. Lands
|
||||||
|
|
||||||
|
class DeckBuilder:
|
||||||
|
def __init__(self):
|
||||||
|
# Commander
|
||||||
|
self.commander = ''
|
||||||
|
self.commander_info = {}
|
||||||
|
|
||||||
|
# Library (99 cards total)
|
||||||
|
self.library = []
|
||||||
|
|
||||||
|
# Number of cards that do/are what
|
||||||
|
self.land_count = 0
|
||||||
|
self.creature_count = 0
|
||||||
|
self.removal = 0
|
||||||
|
self.wipes = 0
|
||||||
|
self.card_advantage = 0
|
||||||
|
self.ramp = 0
|
||||||
|
self.protection = 0
|
||||||
|
|
||||||
|
# Ideal number of cards that do/are what
|
||||||
|
self.ideal_land_count = 0
|
||||||
|
self.ideal_creature_count = 0
|
||||||
|
self.ideal_removal = 0
|
||||||
|
self.ideal_wipes = 0
|
||||||
|
self.ideal_card_advantage = 0
|
||||||
|
self.ideal_ramp = 0
|
||||||
|
self.ideal_protection = 0
|
||||||
|
|
||||||
|
# Cards that are what type
|
||||||
|
# Lands
|
||||||
|
self.land_cards = []
|
||||||
|
self.lands = len(self.land_cards)
|
||||||
|
# Creatures
|
||||||
|
self.creature_cards = []
|
||||||
|
self.creatures = len(self.creature_cards)
|
||||||
|
|
||||||
|
# Instants
|
||||||
|
self.instant_cards = []
|
||||||
|
self.instants = len(self.creature_cards)
|
||||||
|
|
||||||
|
# Sorceries
|
||||||
|
self.sorcery_cards = []
|
||||||
|
self.sorceries = len(self.sorcery_cards)
|
||||||
|
|
||||||
|
# Artifacts
|
||||||
|
self.artifact_cards = []
|
||||||
|
self.artifacts = len(self.artifact_cards)
|
||||||
|
|
||||||
|
# Enchantments
|
||||||
|
self.enchantment_cards = []
|
||||||
|
self.enchantments = len(self.enchantment_cards)
|
||||||
|
|
||||||
|
# Planeswalkers
|
||||||
|
self.planeswalker_cards = []
|
||||||
|
self.planeswalkers = len(self.planeswalker_cards)
|
||||||
|
|
||||||
|
# Battles
|
||||||
|
self.battle_cards = []
|
||||||
|
self.battles = len(self.battle_cards)
|
||||||
|
|
||||||
|
def determine_commander(self):
|
||||||
|
# Determine the commander of the deck
|
||||||
|
commander_chosen = False
|
||||||
|
while not commander_chosen:
|
||||||
|
print('Enter a card name to be your commander, note that at this time only cards that have the \'Creature\' type may be chosen')
|
||||||
|
question = [
|
||||||
|
inquirer.Text(
|
||||||
|
'card_prompt',
|
||||||
|
message=''
|
||||||
|
)
|
||||||
|
]
|
||||||
|
answer = inquirer.prompt(question)
|
||||||
|
card_choice = answer['card_prompt']
|
||||||
|
|
||||||
|
# Logic to find the card in the legendary_cards csv, then display it's information
|
||||||
|
df = pd.read_csv('csv_files/legendary_cards.csv', low_memory=False)
|
||||||
|
fuzzy_card_choice = process.extractOne(card_choice, df['name'], scorer=fuzz.ratio)
|
||||||
|
fuzzy_card_choice = fuzzy_card_choice[0]
|
||||||
|
filtered_df = df[df['name'] == fuzzy_card_choice]
|
||||||
|
columns_to_keep = ['name', 'colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'power', 'toughness', 'text']
|
||||||
|
filtered_df = filtered_df[columns_to_keep]
|
||||||
|
df_dict = filtered_df.to_dict('list')
|
||||||
|
print('Is this the card you chose?')
|
||||||
|
pprint.pprint(df_dict, sort_dicts=False)
|
||||||
|
|
||||||
|
# Confirm if card entered was correct
|
||||||
|
correct_commander = [
|
||||||
|
inquirer.Confirm(
|
||||||
|
'commander',
|
||||||
|
)
|
||||||
|
]
|
||||||
|
confirm_commander = inquirer.prompt(correct_commander)
|
||||||
|
commander_confirmed = confirm_commander['commander']
|
||||||
|
# If correct, set it as the commander
|
||||||
|
if commander_confirmed:
|
||||||
|
commander_chosen = True
|
||||||
|
self.commander_info = df_dict
|
||||||
|
first_key = list(self.commander_info.keys())[0]
|
||||||
|
self.commander = str(self.commander_info[first_key])
|
||||||
|
#print(self.commander)
|
||||||
|
else:
|
||||||
|
commander_chosen = False
|
||||||
|
|
||||||
|
def determine_ideals(self):
|
||||||
|
# Determine ideal land count
|
||||||
|
question = [
|
||||||
|
inquirer.Text
|
||||||
|
]
|
||||||
|
|
||||||
|
build_deck = DeckBuilder()
|
||||||
|
build_deck.determine_commander()
|
||||||
|
print(build_deck.commander)
|
||||||
37
setup.py
37
setup.py
|
|
@ -43,6 +43,26 @@ def filter_by_color(df, column_name, value, new_csv_name):
|
||||||
filtered_df = filtered_df[columns_to_keep]
|
filtered_df = filtered_df[columns_to_keep]
|
||||||
filtered_df.sort_values(by='name', key=lambda col: col.str.lower(), inplace=True)
|
filtered_df.sort_values(by='name', key=lambda col: col.str.lower(), inplace=True)
|
||||||
filtered_df.to_csv(new_csv_name, index=False)
|
filtered_df.to_csv(new_csv_name, index=False)
|
||||||
|
|
||||||
|
def determine_legendary():
|
||||||
|
# Filter dataframe
|
||||||
|
df = pd.read_csv('csv_files/cards.csv', low_memory=False)
|
||||||
|
legendary_options = ['Legendary Creature', 'Legendary Artifact Creature', 'Legendary Enchantment Creature']
|
||||||
|
filtered_df = df[df['type'].str.contains('|'.join(legendary_options))]
|
||||||
|
"""
|
||||||
|
Save the filtered dataframe to a new csv file, and narrow down/rearranges the columns it
|
||||||
|
keeps to increase readability/trim some extra data.
|
||||||
|
Additionally attempts to remove as many duplicates (including cards with reversible prints,
|
||||||
|
as well as taking out Arena-only cards.
|
||||||
|
"""
|
||||||
|
filtered_df.sort_values('name')
|
||||||
|
filtered_df = filtered_df[filtered_df['layout'].str.contains('reversible_card') == False]
|
||||||
|
filtered_df = filtered_df[filtered_df['availability'].str.contains('arena') == False]
|
||||||
|
filtered_df.drop_duplicates(subset='name', keep='first', inplace=True)
|
||||||
|
columns_to_keep = ['name', 'edhrecRank','colorIdentity', 'colors', 'manaCost', 'manaValue', 'type', 'keywords', 'text', 'power', 'toughness']
|
||||||
|
filtered_df = filtered_df[columns_to_keep]
|
||||||
|
filtered_df.sort_values(by='name', key=lambda col: col.str.lower(), inplace=True)
|
||||||
|
filtered_df.to_csv('csv_files/legendary_cards.csv', index=False)
|
||||||
|
|
||||||
def initial_setup():
|
def initial_setup():
|
||||||
# Check if the overall cards.csv file exists
|
# Check if the overall cards.csv file exists
|
||||||
|
|
@ -281,6 +301,15 @@ def initial_setup():
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print('jeskai_cards.csv not found, creating it.')
|
print('jeskai_cards.csv not found, creating it.')
|
||||||
filter_by_color(df, 'colorIdentity', 'R, U, W', 'csv_files/jeskai_cards.csv')
|
filter_by_color(df, 'colorIdentity', 'R, U, W', 'csv_files/jeskai_cards.csv')
|
||||||
|
print('Checking for mardu_cards.csv.')
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
with open('csv_files/mardu_cards.csv', 'r', encoding='utf-8'):
|
||||||
|
print('mardu_cards.csv exists.\n')
|
||||||
|
break
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('mardu_cards.csv not found, creating it.')
|
||||||
|
filter_by_color(df, 'colorIdentity', 'B, R, W', 'csv_files/mardu_cards.csv')
|
||||||
print('Checking for sultai_cards.csv.')
|
print('Checking for sultai_cards.csv.')
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|
@ -612,12 +641,16 @@ def generate_staple_lists():
|
||||||
df = df[columns_to_keep]
|
df = df[columns_to_keep]
|
||||||
df.sort_values(by='edhrecRank', key=lambda col: col, inplace=True)
|
df.sort_values(by='edhrecRank', key=lambda col: col, inplace=True)
|
||||||
i = 1
|
i = 1
|
||||||
while len(staples) < 20:
|
y = 0
|
||||||
|
while len(staples) < 20 and y < len(df):
|
||||||
for index, row in df.iterrows():
|
for index, row in df.iterrows():
|
||||||
if row['edhrecRank'] == i:
|
if row['edhrecRank'] == i:
|
||||||
if 'Land' not in row['type'] and row['name'] not in banned_cards:
|
if 'Land' not in row['type'] and row['name'] not in banned_cards:
|
||||||
staples.append(row['name'])
|
staples.append(row['name'])
|
||||||
i += 1
|
i += 1
|
||||||
|
y += 1
|
||||||
with open(f'staples/{color}.txt', 'w') as f:
|
with open(f'staples/{color}.txt', 'w') as f:
|
||||||
for items in staples:
|
for items in staples:
|
||||||
f.write('%s\n' %items)
|
f.write('%s\n' %items)
|
||||||
|
|
||||||
|
determine_legendary()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue