mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-09-22 04:50:46 +02:00
chore(release): v2.2.3 - fixed bug causing basic lands to not be added; updated removal tagging logic causing non-removal cards to be tagged due to wording
This commit is contained in:
parent
a0a12baa9b
commit
fe9aabbce9
9 changed files with 48 additions and 16 deletions
|
@ -12,6 +12,13 @@ This format follows Keep a Changelog principles and aims for Semantic Versioning
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.2.3] - 2025-09-01
|
||||
### Fixes
|
||||
- Bug causing basic lands to no longer be added due to combined dataframe not including basics
|
||||
|
||||
### Changed
|
||||
- Logic for removal tagging causing self-targetting cards (e.g. Conjurer's Closet) to be tagged as removal
|
||||
|
||||
## [2.2.2] - 2025-09-01
|
||||
### Fixed
|
||||
- Ensure default config files are available when running with bind-mounted config directories:
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
- Existing completed pairs are counted toward the target; only missing partners are added.
|
||||
- No changes to CLI inputs for this feature in this release.
|
||||
- Headless: `tag_mode` supported from JSON/env and exported in interactive run-config JSON.
|
||||
- Logic for removal tagging causing self-targetting cards (e.g. Conjurer's Closet) to be tagged as removal (2.2.3)
|
||||
|
||||
## Fixes
|
||||
- Fixed an issue with the Docker Hub image not having the config files for combos/synergies/default deck json example
|
||||
- Fixed an issue with the Docker Hub image not having the config files for combos/synergies/default deck json example
|
||||
- Bug causing basic lands to no longer be added due to combined dataframe not including basics (2.2.3)
|
|
@ -1030,15 +1030,25 @@ class DeckBuilder(
|
|||
# Allow the commander to bypass this check.
|
||||
try:
|
||||
if not is_commander:
|
||||
df_src = self._full_cards_df if self._full_cards_df is not None else self._combined_cards_df
|
||||
if df_src is not None and not df_src.empty and 'name' in df_src.columns:
|
||||
if df_src[df_src['name'].astype(str).str.lower() == str(card_name).lower()].empty:
|
||||
# Not in the legal pool (likely off-color or unavailable)
|
||||
try:
|
||||
self.output_func(f"Skipped illegal/off-pool card: {card_name}")
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
# Permit basic lands even if they aren't present in the current CSV pool.
|
||||
# Some distributions may omit basics from the per-color card CSVs, but they are
|
||||
# always legal within color identity. We therefore bypass pool filtering for
|
||||
# basic/snow basic lands and Wastes.
|
||||
try:
|
||||
basic_names = bu.basic_land_names()
|
||||
except Exception:
|
||||
basic_names = set()
|
||||
|
||||
if str(card_name) not in basic_names:
|
||||
df_src = self._full_cards_df if self._full_cards_df is not None else self._combined_cards_df
|
||||
if df_src is not None and not df_src.empty and 'name' in df_src.columns:
|
||||
if df_src[df_src['name'].astype(str).str.lower() == str(card_name).lower()].empty:
|
||||
# Not in the legal pool (likely off-color or unavailable)
|
||||
try:
|
||||
self.output_func(f"Skipped illegal/off-pool card: {card_name}")
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
except Exception:
|
||||
# If any unexpected error occurs, fall through (do not block legitimate adds)
|
||||
pass
|
||||
|
|
|
@ -496,7 +496,18 @@ REMOVAL_TEXT_PATTERNS: List[str] = [
|
|||
|
||||
REMOVAL_SPECIFIC_CARDS: List[str] = ['from.*graveyard.*hand']
|
||||
|
||||
REMOVAL_EXCLUSION_PATTERNS: List[str] = []
|
||||
REMOVAL_EXCLUSION_PATTERNS: List[str] = [
|
||||
# Ignore self-targeting effects so they aren't tagged as spot removal
|
||||
# Exile self
|
||||
r'exile target.*you control',
|
||||
r'exiles target.*you control',
|
||||
# Destroy self
|
||||
r'destroy target.*you control',
|
||||
r'destroys target.*you control',
|
||||
# Bounce self to hand
|
||||
r'return target.*you control.*to.*hand',
|
||||
r'returns target.*you control.*to.*hand',
|
||||
]
|
||||
|
||||
REMOVAL_KEYWORDS: List[str] = []
|
||||
|
||||
|
|
|
@ -6775,9 +6775,10 @@ def tag_for_removal(df: pd.DataFrame, color: str) -> None:
|
|||
|
||||
# Create masks for different removal patterns
|
||||
text_mask = create_removal_text_mask(df)
|
||||
exclude_mask = create_removal_exclusion_mask(df)
|
||||
|
||||
# Combine masks
|
||||
final_mask = text_mask
|
||||
# Combine masks (and exclude self-targeting effects like 'target permanent you control')
|
||||
final_mask = text_mask & (~exclude_mask)
|
||||
|
||||
# Apply tags via rules engine
|
||||
tag_utils.apply_rules(df, rules=[
|
||||
|
|
1
config/card_lists/combo.json
Symbolic link
1
config/card_lists/combo.json
Symbolic link
|
@ -0,0 +1 @@
|
|||
combos.json
|
|
@ -47,7 +47,7 @@ services:
|
|||
# Enable virtualization + lazy image tweaks in Step 5
|
||||
WEB_VIRTUALIZE: "1"
|
||||
# Version label (optional; shown in footer/diagnostics)
|
||||
APP_VERSION: "v2.2.2"
|
||||
APP_VERSION: "v2.2.3"
|
||||
volumes:
|
||||
- ${PWD}/deck_files:/app/deck_files
|
||||
- ${PWD}/logs:/app/logs
|
||||
|
|
|
@ -21,7 +21,7 @@ services:
|
|||
# Note: THEME still applies as the default even if selector is hidden
|
||||
|
||||
# Version label (optional; shown in footer/diagnostics)
|
||||
APP_VERSION: "v2.2.2"
|
||||
APP_VERSION: "v2.2.3"
|
||||
|
||||
volumes:
|
||||
# Persist app data locally; ensure these directories exist next to this compose file
|
||||
|
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "mtg-deckbuilder"
|
||||
version = "2.2.2"
|
||||
version = "2.2.3"
|
||||
description = "A command-line tool for building and analyzing Magic: The Gathering decks"
|
||||
readme = "README.md"
|
||||
license = {file = "LICENSE"}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue