mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
801 lines
34 KiB
Plaintext
801 lines
34 KiB
Plaintext
############################################################## Localization
|
||
|
||
include file: language
|
||
|
||
############################################################## Sorting mana symbols
|
||
|
||
# correctly sort a mana symbol (no guild mana)
|
||
mana_sort := sort_text@(order: "XYZI[0123456789]DHSC(WUBRG)")
|
||
# correctly sort wedge mana
|
||
mana_sort_wedge := sort_text@(order: "XYZI[0123456789]DHSC(WBGUR)")
|
||
# correctly sort guild mana
|
||
mana_sort_guild := sort_text@(order: "[XYZI01234567890DHSCWUBRG/|]") +
|
||
replace@(
|
||
# No lookbehind :(
|
||
#match: "(?<!/)(./.|././.|./././.|.[|])(?!/)",
|
||
match: "./.|././.|./././.|.[|]",
|
||
in_context: "(^|[^/])<match>($|[^/])",
|
||
replace: {sort_text(order:"in_place((WUBRG)")}
|
||
)
|
||
mana_has_guild := match@(match: "[/|]") # Is there guild or half mana in the input?
|
||
mana_is_wedge := { contains(set.mana_cost_sorting, match: "wedge") and ( number_of_items(in: sort_text(order:"<WUBRG>", card.casting_cost), filter: "<WUBRG>") == 3 ) }
|
||
# A mana cost can contain both normal and guild mana
|
||
mana_filter := to_upper + {
|
||
if contains(set.mana_cost_sorting, match: "unsorted") then input
|
||
else if mana_has_guild() then mana_sort_guild()
|
||
else if mana_is_wedge() then mana_sort_wedge()
|
||
else mana_sort()
|
||
}
|
||
# Like mana filter, only also allow tap symbols:
|
||
tap_filter := sort_text@(order: "<TQ>")
|
||
mana_filter_t := replace@( # Remove [] used for forcing mana symbols
|
||
match: "[\\[\\]]",
|
||
replace: ""
|
||
) + { tap_filter() + mana_filter() }
|
||
|
||
|
||
############################################################## Determine card color
|
||
|
||
# Names of colors
|
||
color_name := {
|
||
if input == "W" then "white"
|
||
else if input == "U" then "blue"
|
||
else if input == "B" then "black"
|
||
else if input == "R" then "red"
|
||
else if input == "G" then "green"
|
||
else ""
|
||
}
|
||
color_names_1 := { color_name(colors.0) }
|
||
color_names_2 := { color_name(colors.0) + ", " + color_name(colors.1) }
|
||
color_names_3 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) }
|
||
color_names_4 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) }
|
||
color_names_5 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) + ", " + color_name(colors.4) }
|
||
# color based on mana cost, input = a mana cost
|
||
color_filter := sort_text@(order: "<WUBRG>")
|
||
color_filterH := sort_text@(order: "</>")
|
||
mana_to_color := {
|
||
count := number_of_items(in: colors)
|
||
if hybrid == "" and contains(type, match:"Artifact") then
|
||
# not a hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if set.set_info.use_gradient_multicolor == "no" then "artifact, multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", artifact, multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "artifact, multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", artifact, multicolor"
|
||
else if count == 4 then color_names_4() + ", artifact, multicolor"
|
||
else if count == 5 then color_names_5() + ", artifact, multicolor"
|
||
else "artifact, multicolor"
|
||
else if hybrid == "" then
|
||
# not a hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if set.set_info.use_gradient_multicolor == "no" then "multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", multicolor"
|
||
else if count == 4 then color_names_4() + ", multicolor"
|
||
else if count == 5 then color_names_5() + ", multicolor"
|
||
else "multicolor"
|
||
else if contains(type, match:"Artifact") then
|
||
# hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if count == 2 then color_names_2() + ", artifact"
|
||
else "artifact, multicolor"
|
||
else
|
||
# hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if count == 2 then color_names_2() + ", hybrid"
|
||
else "multicolor"
|
||
}
|
||
|
||
# color based on land text box, input = textbox contents
|
||
color_text_filter :=
|
||
# remove activation costs
|
||
replace@(
|
||
match: "<sym[^>]*>[^<]+</sym[^>]*>"
|
||
in_context: "(?ix) (\\n|^)[^:]*<match>(,|:) | (pays?|additional|costs?)[ ]<match>",
|
||
replace: ""
|
||
) +
|
||
# keep only mana
|
||
filter_text@(match: "<sym[^>]*>([^<]+)") + color_filter;
|
||
# get the land frame for a "WUBRG"-style input.
|
||
land_multicolor := {
|
||
count := number_of_items(in: colors)
|
||
if count == 0 then "land"
|
||
else if count == 1 then color_names_1() + ", land"
|
||
else if count == 2 then color_names_2() + ", land"
|
||
else "land, multicolor"
|
||
}
|
||
land_to_color := {
|
||
# Based on watermark
|
||
if watermark == "mana symbol white" then "white, land"
|
||
else if watermark == "mana symbol blue" then "blue, land"
|
||
else if watermark == "mana symbol black" then "black, land"
|
||
else if watermark == "mana symbol red" then "red, land"
|
||
else if watermark == "mana symbol green" then "green, land"
|
||
else land_multicolor(colors:color_text_filter(input: card.rule_text))
|
||
};
|
||
|
||
# Look for a CDA that defines colors
|
||
text_to_color := {
|
||
# Note: running filter_text is quite slow, do a quick 'contains' check first
|
||
if contains(match: card_name) then (
|
||
text := filter_text(match: "is (colorless|all colors|((blue|white|green|red|black)((,|,? and) (blue|white|green|red|black))*))", in_context: regex_escape(card_name)+"(</[-a-z]+>)* <match>\\.")
|
||
if text != "" then (
|
||
if contains(text, match: "all colors") then (
|
||
colors := "WUBRG"
|
||
if land == "land" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
) else (
|
||
colors := ""
|
||
if contains(text, match: "white") then colors := colors + "W"
|
||
if contains(text, match: "blue") then colors := colors + "U"
|
||
if contains(text, match: "black") then colors := colors + "B"
|
||
if contains(text, match: "red") then colors := colors + "R"
|
||
if contains(text, match: "green") then colors := colors + "G"
|
||
if land == "land" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
)
|
||
) else (
|
||
colors := ""
|
||
)
|
||
) else (
|
||
colors := ""
|
||
)
|
||
};
|
||
|
||
# The color of a card
|
||
is_creature := match@(match: "(?i)Creature")
|
||
is_tribal := match@(match: "(?i)Tribal")
|
||
is_artifact := match@(match: "(?i)Artifact")
|
||
is_land := match@(match: "(?i)Land")
|
||
is_enchantment := match@(match: "(?i)Enchantment")
|
||
is_spell := match@(match: "(?i)Instant|Sorcery")
|
||
card_color := {
|
||
# usually the color of mana
|
||
text_color := text_to_color(rules_text, land: is_land(type));
|
||
if text_color == "" then (
|
||
mana_color := mana_to_color(colors: color_filter(casting_cost), hybrid: color_filterH(casting_cost))
|
||
if mana_color == "colorless" and is_land (type) then land_to_color(watermark)
|
||
else if mana_color == "colorless" and is_artifact(type) then "artifact"
|
||
else if mana_color == "colorless" and contains(card.shape, match:"flip") then default
|
||
else mana_color
|
||
)
|
||
else text_color
|
||
};
|
||
|
||
# Number of colors in a card_color
|
||
card_color_color_count := count_chosen@(choices: "white,blue,black,red,green,artifact")
|
||
# Clean up color field
|
||
card_color_filter := {
|
||
colors := card_color_color_count()
|
||
if colors > 2 then
|
||
input := remove_choice(choice: "overlay")
|
||
if colors > 1 then (
|
||
input := require_choice(choices: "multicolor, hybrid, land, artifact")
|
||
input := exclusive_choice(choices: "multicolor, hybrid")
|
||
input := require_exclusive_choice(choices: "horizontal, vertical, radial, overlay")
|
||
) else
|
||
input := remove_choice(choices: "radial, horizontal, vertical, overlay, hybrid, reversed")
|
||
if chosen(choice:"overlay") then
|
||
input := remove_choice(choice: "reversed")
|
||
input
|
||
}
|
||
|
||
# needed by all style files anyway
|
||
include file: /magic-blends.mse-include/new-blends
|
||
|
||
|
||
############################################################## Card number
|
||
|
||
# Index for sorting, white cards are first, so white->A, blue->B, .. ,
|
||
# The code consists of 3 parts:
|
||
# color, shifted, split
|
||
sort_index := {
|
||
color_of_card() +
|
||
(if contains(card.shape, match:"shifted") then "S" else " ") + # planeshifted cards come after normal ones
|
||
(if contains(card.shape, match:"split") then "S" else " ") + # split cards come after normal ones
|
||
":"
|
||
}
|
||
# Process the name for sorting rules
|
||
sort_name :=
|
||
# Remove "The", "A", and "And" at the beginning
|
||
replace@(match: "^(The|An?) ", replace: "") +
|
||
# Remove commas and apostrophes
|
||
replace@(match: "(,|'|’)", replace: "") +
|
||
# Remove bold and italic tags
|
||
replace@(match: "(<b>|<i>|</b>|</i>)", replace: "") +
|
||
# Make lowercase
|
||
to_lower
|
||
|
||
is_multicolor := { chosen(choice: "multicolor") and input != "artifact, multicolor" }
|
||
is_null_cost := { input == "" or input == "0" }
|
||
is_hybrid_cost := { contains(card.casting_cost, match: "W/") or contains(card.casting_cost, match: "U/") or contains(card.casting_cost, match: "B/") or contains(card.casting_cost, match: "R/") or contains(card.casting_cost, match: "G/") }
|
||
basic_land_sort := {
|
||
if contains(card.name, match:"Plains") then "MB" # Plains
|
||
else if contains(card.name, match:"Island") then "MC" # Islands
|
||
else if contains(card.name, match:"Swamp") then "MD" # Swamps
|
||
else if contains(card.name, match:"Mountain") then "ME" # Mountains
|
||
else if contains(card.name, match:"Forest") then "MF" # Forests
|
||
else "MA" # other basic lands
|
||
}
|
||
hybrid_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if not set.sort_hybrid_in_pairs then "HK"
|
||
else if colors == "WU" then "HA"
|
||
else if colors == "UB" then "HB"
|
||
else if colors == "BR" then "HC"
|
||
else if colors == "RG" then "HD"
|
||
else if colors == "WG" then "HE"
|
||
else if colors == "WB" then "HF"
|
||
else if colors == "UR" then "HG"
|
||
else if colors == "BG" then "HH"
|
||
else if colors == "WR" then "HI"
|
||
else if colors == "UG" then "HJ"
|
||
else "HK"
|
||
}
|
||
multi_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if not set.sort_multicolor_in_pairs then "GK"
|
||
else if colors == "WU" then "GA"
|
||
else if colors == "UB" then "GB"
|
||
else if colors == "BR" then "GC"
|
||
else if colors == "RG" then "GD"
|
||
else if colors == "WG" then "GE"
|
||
else if colors == "WB" then "GF"
|
||
else if colors == "UR" then "GG"
|
||
else if colors == "BG" then "GH"
|
||
else if colors == "WR" then "GI"
|
||
else if colors == "UG" then "GJ"
|
||
else if contains(card.casting_cost, match:"/") then "GL"
|
||
else "GK"
|
||
}
|
||
# A code for the color of the card
|
||
color_of_card := {
|
||
card_color := card.card_color
|
||
casting_cost := card.casting_cost
|
||
type := card.super_type
|
||
if contains(card.shape, match: "split") and
|
||
card_color != card.card_color_2 then "I" # Diff Color Splits
|
||
else if chosen(choice: "land", card_color) then ( # Lands
|
||
if card.rarity != "basic land" then "L" # Nonbasic Land
|
||
else basic_land_sort() # Basic Land
|
||
) else if is_null_cost(casting_cost) then ( # Non-Land Cards with no or zero costs.
|
||
if chosen(choice: "colorless", card_color) then "A" # Clear Colorless
|
||
else if chosen(choice: "hybrid", card_color) then "HK" # Hybrids
|
||
else if is_multicolor(card_color) then "GK" # Multicolor
|
||
else if chosen(choice:"white", card_color) then "B" # White
|
||
else if chosen(choice:"blue", card_color) then "C" # Blue
|
||
else if chosen(choice:"black", card_color) then "D" # Black
|
||
else if chosen(choice:"red", card_color) then "E" # Red
|
||
else if chosen(choice:"green", card_color) then "F" # Green
|
||
else "J" # Artifact
|
||
) else (
|
||
# Cards with costs.
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if colors == "" and contains(type, match:"Artifact") then "J" # Artifact
|
||
else if colors == "" then "A" # Clear Colorless
|
||
else if colors == "W" then "B" # White
|
||
else if colors == "U" then "C" # Blue
|
||
else if colors == "B" then "D" # Black
|
||
else if colors == "R" then "E" # Red
|
||
else if colors == "G" then "F" # Green
|
||
else if is_hybrid_cost() then hybrid_color_pair_sort() # Hybrid (by pairs)
|
||
else if contains(casting_cost, match:"/") and contains(type, match:"Artifact") then "I" # Hybrid Artifacts
|
||
else multi_color_pair_sort() # Multicolor (by pairs)
|
||
)
|
||
}
|
||
|
||
rarity_sort := {
|
||
if card.shape == "token" then "T1"
|
||
else if card.shape == "emblem" then "T2"
|
||
else if card.shape == "rulestip" then "T3"
|
||
else if card.shape == "counter" then "T4"
|
||
else if card.shape == "checklist" then "T5"
|
||
else if is_masterpiece() then "T6"
|
||
else if set.sort_special_rarity == "with the rest" or card.rarity != "special" then " "
|
||
else "S"
|
||
}
|
||
set_filter := {
|
||
# TODO: what about rulestips?
|
||
if is_unsorted() then
|
||
{ is_unsorted() }
|
||
if card.shape == "token" or card.shape == "emblem" then
|
||
{ card.shape == "token" or card.shape == "emblem" }
|
||
else if card.shape == "rulestip" then
|
||
{ card.shape == "rulestip" }
|
||
else if card.shape == "counter" then
|
||
{ card.shape == "counter" }
|
||
else if card.shape == "checklist" then
|
||
{ card.shape == "checklist" }
|
||
else if is_masterpiece() and card.shape != "token" and card.shape != "emblem" then
|
||
{ is_masterpiece() and card.shape != "token" and card.shape != "emblem" }
|
||
else if set.sort_special_rarity != "separate numbering" then
|
||
{ not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist"}
|
||
else if card.rarity == "special" then
|
||
{ not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist" and card.rarity == "special" }
|
||
else
|
||
{ not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist" and card.rarity != "special" }
|
||
}
|
||
|
||
card_number := {
|
||
position (
|
||
of: card
|
||
in: set
|
||
order_by: { rarity_sort() + sort_index() + sort_name(card.name) }
|
||
filter: set_filter()
|
||
) + 1
|
||
}
|
||
card_count := {
|
||
number_of_items(in: set, filter: set_filter())
|
||
}
|
||
|
||
#Starting with M15, zero digits in card numbers should be shown up to three.
|
||
card_number_m15 := { (if card_number() < 100 then "0" else "") + (if card_number() < 10 then "0" else "") + card_number() }
|
||
card_count_m15 := { (if card_count() < 100 then "0" else "") + (if card_count() < 10 then "0" else "") + card_count() }
|
||
|
||
# used by pack scripts
|
||
is_token_card := { card.shape == "token" or card.shape == "rulestip" or card.shape == "counter" or card.shape == "checklist" or card.shape == "emblem"}
|
||
is_shifted_card := { contains(card.shape, match:"shifted") }
|
||
is_masterpiece := { card.rarity == "masterpiece" }
|
||
is_nightbreak := { card.shape == "nightbreak" }
|
||
|
||
|
||
############################################################## Utilities for keywords
|
||
|
||
comma_count := filter_text@(match:",")
|
||
# Replace spaces by a spacer
|
||
separate_words := remove_tags + trim + replace@(match:" ", replace: {spacer})
|
||
|
||
# replaces — correctly
|
||
add := "" # default is nothing
|
||
|
||
# If the 'input' parameter is a mana costs, then adds 'add'
|
||
for_mana_costs := format_cost := {
|
||
if input.separator_before == "—" and contains(input.param, match: " ") then (
|
||
if comma_count(input.param) == "," then (
|
||
if match(match: "^[DHSCTQXYZIWUBRG0-9/|]+,", input.param) then
|
||
"{add}<param-cost>{combined_cost(input.param)}</param-cost>"
|
||
else "<param-cost>{combined_cost(input.param)}</param-cost>"
|
||
) else if contains(input.param, match: ",") then (
|
||
if match(match: "^[DHSCTQXYZIWUBRG0-9/|]+,", input.param) then
|
||
"{add}<param-cost>{long_cost(input.param)}</param-cost>"
|
||
else "<param-cost>{long_nomana_cost(input.param)}</param-cost>"
|
||
) else
|
||
"<param-cost>{alternative_cost(input.param)}</param-cost>"
|
||
) else
|
||
"{add}<param-mana>{input.param}</param-mana>"
|
||
}
|
||
|
||
# Convert first character to lower case
|
||
alternative_cost := replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
# Convert extra costs
|
||
long_cost := replace@(match:", [A-Z]", replace: { to_lower() } )
|
||
long_nomana_cost := replace@(match:"[A-Z]", replace: { to_lower() })
|
||
#
|
||
combined_cost := replace@(match:", [A-Z]", replace: { to_lower() })+
|
||
replace@(match:",", replace:" and")+
|
||
replace@(match:"^[DHSCTQXYZIWUBRG0-9/|]+", in_context: "(^|[[:space:]])<match>(?![a-z])", replace: "<sym-auto>&</sym-auto>")+
|
||
replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
|
||
long_dash := replace@(match:"-", replace:"—")
|
||
|
||
# Utilities for keywords
|
||
|
||
has_cc := { card.casting_cost != "" }
|
||
|
||
has_pt := { card.power != "" or card.toughness != "" }
|
||
|
||
contains_target := match@(match:"(?i)([^a-z]|^)target([^a-z]|$)")
|
||
|
||
is_spell := { contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") }
|
||
|
||
is_targeted := { contains_target(card.rule_text) }
|
||
|
||
color_to_mana := replace@(match: "white", replace: "[W]")+
|
||
replace@(match: "blue", replace: "[U]")+
|
||
replace@(match: "black", replace: "[B]")+
|
||
replace@(match: "red", replace: "[R]")+
|
||
replace@(match: "green", replace: "[G]")
|
||
|
||
############################################################## The text box
|
||
|
||
# Filters for the text box
|
||
# context in which mana symbols are found
|
||
mana_context :=
|
||
"(?ix) # case insensitive, ignore whitespace
|
||
(^|[[:space:]\"(“']) # start of a word
|
||
( <match>: # G: something
|
||
| <match>, # G, tap: something
|
||
| or[ ]<match> # Add X, Y, or Z.
|
||
| <match>[ ]to # Add X, Y, or Z to your mana pool.
|
||
| <match>[ ]was[ ]spent # if G was spent to cast
|
||
| <match>[ ]can[ ]be[ ]pay
|
||
| (pays?|additional|costs?|the # pay X. creatures cost 1 less. pay an additional G.
|
||
|adds?|pay(ed)?[ ](with|using)
|
||
)
|
||
([ ]either)? # pay either X or Y
|
||
([ ](<sym[^>]*>)?[DHSCTQXYZIEWUBRG0-9/|]+(</sym[^>]*>)?,)* # pay X, Y or Z
|
||
([ ](<sym[^>]*>)?[DHSCTQXYZIEWUBRG0-9/|]+(</sym[^>]*>)?[ ](and|or|and/or))* # pay X or Y
|
||
[ ]<match>
|
||
([,.)]|$ # (end of word)
|
||
|[ ][^ .,]*$ # still typing...
|
||
|[ ]( or | and | in | less | more | to ) # or next word is ...
|
||
)
|
||
)
|
||
| <param-mana><match></param-mana> # keyword argument that is declared as mana
|
||
| <param-cost>[ ]*<match></param-cost> # keyword argument that is declared as cost
|
||
| <param-cost><match>, # keyword argument that is declared as cost
|
||
";
|
||
|
||
|
||
# truncates the name of legends
|
||
legend_filter := replace@(match:"(, | of | the ).*", replace: "" )
|
||
|
||
# these are considered a correct 'word' for spellchecking in the text box:
|
||
additional_text_words := match@(match:
|
||
"(?ix)^(?: # match whole word
|
||
<atom-[^>]*>.*?</atom-[^>]*> # cardnames and stuff
|
||
| [+-]?[0-9X]+ / [+-]?[0-9X]+ # '3/3', '+X/+X'
|
||
)$")
|
||
|
||
# the rule text filter
|
||
# - adds mana symbols
|
||
# - makes text in parentheses italic
|
||
text_filter :=
|
||
# step 1 : remove all automatic tags
|
||
remove_tag@(tag: "<sym-auto>") +
|
||
remove_tag@(tag: "<i-auto>") +
|
||
remove_tag@(tag: "<b-auto>") +
|
||
remove_tag@(tag: "<error-spelling") +
|
||
remove_tag@(tag: "<nospellcheck") +
|
||
# step 2 : reminder text for keywords
|
||
expand_keywords@(
|
||
condition: {
|
||
correct_case or (mode != "pseudo" and not used_placeholders)
|
||
}
|
||
default_expand: {
|
||
chosen(choice:if correct_case then mode else "lower case", set.automatic_reminder_text)
|
||
},
|
||
combine: {
|
||
keyword := "<nospellcheck>{keyword}</nospellcheck>"
|
||
reminder := process_english_hints(reminder)
|
||
if mode == "pseudo" then "<i-auto>{keyword}</i-auto>"
|
||
else keyword + if expand then "<atom-reminder-{mode}> ({reminder})</atom-reminder-{mode}>"
|
||
}) +
|
||
# step 2b : move action keywords' reminder text to the end of the line
|
||
replace@(
|
||
match: "(<atom-reminder-action>(?:(?!<kw-).)*</atom-reminder-action></kw[^>]*>)(((?!<atom-reminder| ?<kw-)[^\n(])+)",
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 2c : remove duplicate reminder text
|
||
replace@(
|
||
match: "(<atom-reminder-[^>]*>[^)]+[)]</atom-reminder-[^>]*>)([^\n]+)\\1"
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 3a : expand shortcut word CARDNAME
|
||
replace@(
|
||
match: "CARDNAME",
|
||
in_context: "(^|[[:space:]]|\\()<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-cardname></atom-cardname>"
|
||
) +
|
||
# step 3b : expand shortcut word LEGENDNAME
|
||
replace@(
|
||
match: "LEGENDNAME",
|
||
in_context: "(^|[[:space:]]|\\()<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-legname></atom-legname>"
|
||
) +
|
||
# step 3c : fill in atom fields
|
||
tag_contents@(
|
||
tag: "<atom-cardname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "CARDNAME" else card_name) + "</nospellcheck>" }
|
||
) +
|
||
tag_contents@(
|
||
tag: "<atom-legname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "LEGENDNAME" else legend_filter(card_name)) + "</nospellcheck>" }
|
||
) +
|
||
# step 4 : explict non mana symbols
|
||
replace@(
|
||
match: "\\][DHSCTQXYZIWUBRG0-9/|]+\\[",
|
||
replace: {"<nosym>" + mana_filter_t() + "</nosym>"} ) +
|
||
# step 5 : add mana & tap symbols
|
||
replace@(
|
||
match: "\\b[DHSCTQXYZIWUBRG0-9/|]+\\b",
|
||
in_context: mana_context,
|
||
replace: {"<sym-auto>" + mana_filter_t() + "</sym-auto>"} ) +
|
||
# step 5c : add explicit mana symbols
|
||
replace@(
|
||
match: "\\[[DHSCTQXYZIWUBRG0-9/|]+\\]",
|
||
replace: {"<sym>" + mana_filter_t() + "</sym>"} ) +
|
||
# step 6 : curly quotes
|
||
(if set.curly_quotes then curly_quotes) +
|
||
# step 7 : italicize text in parenthesis
|
||
replace@(
|
||
match: "[(]([^)\n]|[(][^)\n]*[)])*[)]?",
|
||
in_context: "(^|[[:space:]])<match>|<atom-keyword><match></",
|
||
replace: "<i-auto>&</i-auto>") +
|
||
# step 8 : automatic capitalization, but not after "("
|
||
replace@(
|
||
match: "([ ]*: |—| — )" # preceded by this
|
||
+ "([[:lower:]])" # match this
|
||
+ "(?![)])", # not followed by this
|
||
replace: { _1 + to_upper(_2) }) +
|
||
# step 9 : spellcheck
|
||
{ if set.mark_errors then
|
||
check_spelling(
|
||
language: language().spellcheck_code,
|
||
extra_dictionary: "/magic.mse-game/magic-words",
|
||
extra_match: additional_text_words
|
||
)
|
||
else input
|
||
}
|
||
|
||
|
||
############################################################## Other boxes
|
||
|
||
# the flavor text filter
|
||
# - makes all text italic
|
||
flavor_text_filter :=
|
||
# step 1 : remove italic tags
|
||
remove_tag@(tag: "<i-flavor>") +
|
||
# step 2 : surround by <i> tags
|
||
{ "<i-flavor>" + input + "</i-flavor>" } +
|
||
# curly quotes
|
||
(if set.curly_quotes then curly_quotes) +
|
||
# spellcheck
|
||
{ if set.mark_errors
|
||
then check_spelling(language:language().spellcheck_code)
|
||
else input
|
||
}
|
||
|
||
# Move the cursor past the separator in the p/t and type boxes
|
||
type_over_pt := replace@(match:"/$", replace:"")
|
||
type_over_type := replace@(match:" ?[-:]$", replace:"")
|
||
|
||
super_type_filter := {
|
||
input := remove_tag(tag: "<word-list-")
|
||
input := type_over_type()
|
||
tag := "word-list-type" # TODO: localize
|
||
"<{tag}>{input}</{tag}>"
|
||
}
|
||
|
||
break_subtypes := split_text@(match: " +|<atom-sep>[^<]*</atom-sep>", include_empty:false)
|
||
sub_type_filter := {
|
||
input := remove_tag(tag: "<word-list-")
|
||
input := remove_tag(tag: "<soft")
|
||
lang := language()
|
||
# What word list to use?
|
||
list_type_rest := if lang.is_creature(type) then "class"
|
||
else if lang.is_land(type) then "land"
|
||
else if lang.is_artifact(type) then "artifact"
|
||
else if lang.is_enchantment(type) then "enchantment"
|
||
else if lang.is_spell(type) then "spell"
|
||
else if lang.is_planeswalker(type) then "planeswalker"
|
||
else "";
|
||
if list_type_rest != "" then (
|
||
if lang.is_creature(type) or lang.is_tribal(type) then (
|
||
list_type_first := "race"
|
||
) else (
|
||
list_type_first := list_type_rest
|
||
);
|
||
# wrap wordlist tag around each part
|
||
parts := break_subtypes()
|
||
(for each i:part in parts do
|
||
if i == 0 then
|
||
"<word-list-{list_type_first}>{part}</word-list-{list_type_first}>"
|
||
else
|
||
lang.subtype_separator + "<word-list-{list_type_rest}>{part}</word-list-{list_type_rest}>"
|
||
) +
|
||
(if length(parts) > 0 then
|
||
# Add a new box at the end
|
||
"<soft>{lang.subtype_separator}</soft><word-list-{list_type_rest}></word-list-{list_type_rest}>"
|
||
else
|
||
"<word-list-{list_type_first}></word-list-{list_type_first}>"
|
||
)
|
||
) else input # do nothing
|
||
}
|
||
|
||
# all sub types, for word list
|
||
space_to_comma := replace@(match:" ", replace:",")
|
||
only_first := replace@(match:" .*", replace:"")
|
||
only_next := replace@(match:"^[^ ]* ?", replace:"")
|
||
all_sub_types := {
|
||
for each card in set do
|
||
if contains(card.super_type) then "," + space_to_comma(to_text(card.sub_type))
|
||
}
|
||
all_races := {
|
||
for each card in set do
|
||
if is_creature(card.super_type) or is_tribal(card.super_type) then
|
||
"," + only_first(to_text(card.sub_type))
|
||
}
|
||
all_classes := {
|
||
for each card in set do
|
||
if contains(card.super_type, match:"Creature") then
|
||
"," + space_to_comma(only_next(to_text(card.sub_type)))
|
||
}
|
||
|
||
# Determine a rarity code for M15 styles.
|
||
rarity_code := {
|
||
if is_promo() then "P"
|
||
else if is_masterpiece() then "S"
|
||
else if contains(card.shape, match:"token") then "T"
|
||
else if contains(card.shape, match:"emblem") then "E"
|
||
else if card.rarity == "common" then "C"
|
||
else if card.rarity == "uncommon" then "U"
|
||
else if card.rarity == "rare" then "R"
|
||
else if card.rarity == "mythic rare" then "M"
|
||
else if card.rarity == "special" then "S"
|
||
else if card.rarity == "basic land" then "L"
|
||
else ""
|
||
};
|
||
|
||
# Determine if the card is a promo card.
|
||
is_promo := { "false" }
|
||
|
||
# Determine if the card is a rare.
|
||
is_rare := { card.rarity == "rare" or card.rarity == "mythic rare" or card.rarity == "masterpiece" }
|
||
|
||
# Shape of cards, can be changed in style files
|
||
card_shape := { "normal" }
|
||
|
||
typesymbol_for :=
|
||
to_text +
|
||
replace@(match: "(Legendary|Basic|Snow|World| )", replace: "") +
|
||
{ if input == "Creature" then "creature"
|
||
else if input == "Sorcery" then "sorcery"
|
||
else if input == "Instant" then "instant"
|
||
else if input == "Artifact" then "artifact"
|
||
else if input == "Enchantment" then "enchantment"
|
||
else if input == "Land" then "land"
|
||
else if input == "Planeswalker" then "planeswalker"
|
||
else "multitype"
|
||
}
|
||
typesymbol_type := { typesymbol_for(type) }
|
||
|
||
#Script to make magic-mana-future compatible w/ other templates
|
||
colorless_color := {
|
||
if contains(card.card_color, match:"hybrid") or contains(card.card_color, match:"multicolor") then "c"
|
||
else if card.card_color=="white" then "w"
|
||
else if card.card_color=="blue" then "u"
|
||
else if card.card_color=="black" then "b"
|
||
else if card.card_color=="red" then "r"
|
||
else if card.card_color=="green" then "g"
|
||
else "c"
|
||
}
|
||
|
||
#Indicators never appear if the indicator would be colorless, colorless land, or colorless artifact.
|
||
#Indicators do appear if the chosen frame doesn't match the default.
|
||
#Indicators do appear if the chosen color for the indicator doesn't match the default.
|
||
|
||
has_identity := { ( ( card.card_color != card_color(casting_cost: card.casting_cost, rules_text: card.rule_text, type: card.super_type, watermark: card.watermark, card_name: card.name, default: "colorless") ) or ( card.indicator != card_color(casting_cost: card.casting_cost, rules_text: card.rule_text, type: card.super_type, watermark: card.watermark, card_name: card.name, default: "colorless") ) ) and card.indicator != "colorless" and card.indicator != "artifact" and card.indicator != "land"}
|
||
|
||
has_identity_2 := { ( ( card.card_color_2 != card_color(casting_cost: card.casting_cost_2, rules_text: card.rule_text_2, type: card.super_type_2, watermark: card.watermark_2, card_name: card.name_2, default: "colorless") ) or ( card.indicator_2 != card_color(casting_cost: card.casting_cost_2, rules_text: card.rule_text_2, type: card.super_type_2, watermark: card.watermark_2, card_name: card.name_2, default: "colorless") ) ) and card.indicator_2 != "colorless" and card.indicator_2 != "artifact" and card.indicator_2 != "land"}
|
||
|
||
############################################################## Statistics utilities
|
||
|
||
# Converted mana cost
|
||
is_half_mana := match@(match: "1/2|[|][WUBRGS]")
|
||
is_colored_mana := match@(match: "[WUBRG]")
|
||
only_numbers := filter_text@(match: "^[0123456789]+")
|
||
cmc_split := break_text@(match: "(?ix) 1/2 | [|][WUBRG] | [0-9]+(?!/[WUBRGDHSCTQ2]) | [WUBRGDHS0-9](/[WUBRGDHS])\{0,4} ")
|
||
cmc := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_half_mana(sym) then 0.5
|
||
else if numbers != "" then to_int(numbers)
|
||
else 1 # all other symbols are 1
|
||
))
|
||
}
|
||
|
||
colored_mana := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_colored_mana(sym) then
|
||
if is_half_mana(sym) then 0.5 else 1
|
||
else 0
|
||
))
|
||
}
|
||
|
||
primary_card_color := {
|
||
artifact := chosen(choice:"artifact") and not (chosen(choice:"white") or chosen(choice:"blue") or chosen(choice:"black") or chosen(choice:"red") or chosen(choice:"green"))
|
||
land := chosen(choice:"land")
|
||
multi := chosen(choice:"multicolor")
|
||
hybrid := chosen(choice:"hybrid")
|
||
white := chosen(choice:"white")
|
||
blue := chosen(choice:"blue")
|
||
black := chosen(choice:"black")
|
||
red := chosen(choice:"red")
|
||
green := chosen(choice:"green")
|
||
if land then "land"
|
||
else if multi then "multicolor"
|
||
else if hybrid then "hybrid"
|
||
else if artifact then "artifact"
|
||
else if white then "white"
|
||
else if blue then "blue"
|
||
else if black then "black"
|
||
else if red then "red"
|
||
else if green then "green"
|
||
else input
|
||
}
|
||
mainframe_stat_color := {
|
||
artifact := chosen(choice:"artifact") and not (chosen(choice:"white") or chosen(choice:"blue") or chosen(choice:"black") or chosen(choice:"red") or chosen(choice:"green"))
|
||
land := chosen(choice:"land")
|
||
multi := chosen(choice:"multicolor")
|
||
hybrid := chosen(choice:"hybrid")
|
||
white := chosen(choice:"white")
|
||
blue := chosen(choice:"blue")
|
||
black := chosen(choice:"black")
|
||
red := chosen(choice:"red")
|
||
green := chosen(choice:"green")
|
||
pink := chosen(choice:"pink")
|
||
purple := chosen(choice:"purple")
|
||
if land then "land"
|
||
else if multi then "multicolor"
|
||
else if hybrid then "hybrid"
|
||
else if artifact then "artifact"
|
||
else if white then "white"
|
||
else if blue then "blue"
|
||
else if black then "black"
|
||
else if red then "red"
|
||
else if green then "green"
|
||
else if pink then "pink"
|
||
else if purple then "purple"
|
||
else input
|
||
}
|
||
is_mainframe := { false }
|
||
is_walker := { contains(card.super_type, match:"Planeswalker") }
|
||
mainframe_power := { card.power }
|
||
mainframe_toughness := { card.toughness }
|
||
|
||
word_count := break_text@(match:"[^[:space:]]+") + length
|
||
line_count := split_text@(match:"\n+",include_empty:false) + length
|
||
|
||
#Remove supertypes or types to look at parts of the super_type field by themselves.
|
||
remove_supertype := replace@(match: "(Legendary|Basic|Snow|World|Tribal|Token)", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "^<match>", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "<match>$", replace: "")
|
||
remove_type := replace@(match: "(Artifact|Creature|Enchantment|Instant|Land|Planeswalker|Sorcery)", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "^<match>", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "<match>$", replace: "")
|
||
node_script := { if card.shape == "double faced" then "transform day" else "none" }
|
||
node_script_2 := {
|
||
if card.mainframe_node == "transform day" then "transform night"
|
||
else if card.mainframe_node == "transform night" then "transform day"
|
||
else if card.mainframe_node == "transform moon" then "transform eldrazi"
|
||
else if card.mainframe_node == "transform eldrazi" then "transform moon"
|
||
else if card.mainframe_node == "transform sparker" then "transform aetherprint"
|
||
else if card.mainframe_node == "transform aetherprint" then "transform sparker"
|
||
else "none"
|
||
}
|
||
card_new_color := {
|
||
if card.card_color == "white" then "w"
|
||
else if card.card_color == "blue" then "u"
|
||
else if card.card_color == "black" then "b"
|
||
else if card.card_color == "red" then "r"
|
||
else if card.card_color == "green" then "g"
|
||
else if contains(card.card_color, match:"artifact") then "a"
|
||
else if contains(card.card_color, match:"multi") or contains(card.card_color, match:"hybrid") then "m"
|
||
else "c"
|
||
}
|
||
spark_color := {
|
||
if card.card_color == "white" then "w"
|
||
else if card.card_color == "blue" then "u"
|
||
else if card.card_color == "black" then "b"
|
||
else if card.card_color == "red" then "r"
|
||
else if card.card_color == "green" then "g"
|
||
else if contains(card.card_color, match:"multi") or contains(card.card_color, match:"hybrid") then "m"
|
||
else ""
|
||
}
|
||
card_spotlight := { "/magic-mainframe-watermarks.mse-include/spotlight/" + card_new_color() + "spotlight.png" }
|
||
|
||
ancestral_mana := { card.pt != "" and card.pt == "" }
|
||
exporter_check := { "no" }
|
||
custom_watermark_1 := { if set.custom_watermark_1 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_1 else "/magic-watermarks.mse-include/aetherprint3.png" }
|
||
custom_watermark_2 := { if set.custom_watermark_2 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_2 else "/magic-watermarks.mse-include/aetherprint3.png" }
|
||
custom_watermark_3 := { if set.custom_watermark_3 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_3 else "/magic-watermarks.mse-include/aetherprint3.png" }
|
||
custom_watermark_4 := { if set.custom_watermark_4 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_4 else "/magic-watermarks.mse-include/aetherprint3.png" }
|
||
custom_watermark_5 := { if set.custom_watermark_5 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_5 else "/magic-watermarks.mse-include/aetherprint3.png" }
|
||
is_unsorted := {"false"} |