mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-11 12:54:10 -07:00
Store allowedCounts by format
Took 15 minutes Took 6 seconds
This commit is contained in:
parent
0d33a79387
commit
b1f0026b6c
4 changed files with 94 additions and 43 deletions
|
|
@ -109,10 +109,26 @@ static QSharedPointer<FormatRules> parseFormat(QXmlStreamReader &xml)
|
||||||
rulesPtr->maxDeckSize = text.toInt();
|
rulesPtr->maxDeckSize = text.toInt();
|
||||||
} else if (xmlName == "maxSideboardSize") {
|
} else if (xmlName == "maxSideboardSize") {
|
||||||
rulesPtr->maxSideboardSize = xml.readElementText().toInt();
|
rulesPtr->maxSideboardSize = xml.readElementText().toInt();
|
||||||
} else if (xmlName == "maxCopies") {
|
} else if (xmlName == "allowedCounts") {
|
||||||
rulesPtr->maxCopies = xml.readElementText().toInt();
|
while (!xml.atEnd()) {
|
||||||
} else if (xmlName == "maxRestrictedCopies") {
|
token = xml.readNext();
|
||||||
rulesPtr->maxRestrictedCopies = xml.readElementText().toInt();
|
|
||||||
|
if (token == QXmlStreamReader::EndElement && xml.name().toString() == "allowedCounts") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token == QXmlStreamReader::StartElement && xml.name().toString() == "count") {
|
||||||
|
|
||||||
|
AllowedCount c;
|
||||||
|
|
||||||
|
QString maxAttr = xml.attributes().value("max").toString();
|
||||||
|
c.max = (maxAttr == "unlimited") ? -1 : maxAttr.toInt();
|
||||||
|
|
||||||
|
c.label = xml.readElementText().trimmed();
|
||||||
|
|
||||||
|
rulesPtr->allowedCounts.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (xmlName == "exceptions") {
|
} else if (xmlName == "exceptions") {
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
token = xml.readNext();
|
token = xml.readNext();
|
||||||
|
|
@ -387,8 +403,18 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const QSharedPointer<
|
||||||
xml.writeTextElement("minDeckSize", QString::number(rules.minDeckSize));
|
xml.writeTextElement("minDeckSize", QString::number(rules.minDeckSize));
|
||||||
xml.writeTextElement("maxDeckSize", rules.maxDeckSize >= 0 ? QString::number(rules.maxDeckSize) : "0");
|
xml.writeTextElement("maxDeckSize", rules.maxDeckSize >= 0 ? QString::number(rules.maxDeckSize) : "0");
|
||||||
xml.writeTextElement("maxSideboardSize", QString::number(rules.maxSideboardSize));
|
xml.writeTextElement("maxSideboardSize", QString::number(rules.maxSideboardSize));
|
||||||
xml.writeTextElement("maxCopies", QString::number(rules.maxCopies));
|
if (!rules.allowedCounts.isEmpty()) {
|
||||||
xml.writeTextElement("maxRestrictedCopies", QString::number(rules.maxRestrictedCopies));
|
xml.writeStartElement("allowedCounts");
|
||||||
|
|
||||||
|
for (const AllowedCount &c : rules.allowedCounts) {
|
||||||
|
xml.writeStartElement("count");
|
||||||
|
xml.writeAttribute("max", c.max == -1 ? "unlimited" : QString::number(c.max));
|
||||||
|
xml.writeCharacters(c.label);
|
||||||
|
xml.writeEndElement(); // count
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeEndElement(); // allowedCounts
|
||||||
|
}
|
||||||
|
|
||||||
if (!rules.exceptions.isEmpty()) {
|
if (!rules.exceptions.isEmpty()) {
|
||||||
xml.writeStartElement("exceptions");
|
xml.writeStartElement("exceptions");
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,12 @@ struct CardCondition
|
||||||
QString value; // e.g. "Basic Land"
|
QString value; // e.g. "Basic Land"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AllowedCount
|
||||||
|
{
|
||||||
|
int max = 0; // 4, 1, 0, or -1 for unlimited
|
||||||
|
QString label; // "legal", "restricted", "banned"
|
||||||
|
};
|
||||||
|
|
||||||
struct ExceptionRule
|
struct ExceptionRule
|
||||||
{
|
{
|
||||||
QList<CardCondition> conditions; // All must match
|
QList<CardCondition> conditions; // All must match
|
||||||
|
|
@ -28,8 +34,7 @@ struct FormatRules
|
||||||
int maxDeckSize = -1; // -1 = unlimited
|
int maxDeckSize = -1; // -1 = unlimited
|
||||||
int maxSideboardSize = 15;
|
int maxSideboardSize = 15;
|
||||||
|
|
||||||
int maxCopies = 4; // default constructed rule
|
QList<AllowedCount> allowedCounts;
|
||||||
int maxRestrictedCopies = 1; // Used for "restricted" legality tags
|
|
||||||
|
|
||||||
QList<ExceptionRule> exceptions; // Cards allowed to break maxCopies
|
QList<ExceptionRule> exceptions; // Cards allowed to break maxCopies
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -622,6 +622,17 @@ bool DeckListModel::isCardLegalForCurrentFormat(const CardInfoPtr cardInfo)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maxAllowedForLegality(const FormatRules &format, const QString &legality)
|
||||||
|
{
|
||||||
|
for (const AllowedCount &c : format.allowedCounts) {
|
||||||
|
if (c.label == legality) {
|
||||||
|
return c.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // unknown legality → treat as illegal
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DeckListModel::isCardQuantityLegalForCurrentFormat(const CardInfoPtr cardInfo, int quantity)
|
bool DeckListModel::isCardQuantityLegalForCurrentFormat(const CardInfoPtr cardInfo, int quantity)
|
||||||
{
|
{
|
||||||
auto formatRules = CardDatabaseManager::query()->getFormat(deckList->getGameFormat());
|
auto formatRules = CardDatabaseManager::query()->getFormat(deckList->getGameFormat());
|
||||||
|
|
@ -630,24 +641,29 @@ bool DeckListModel::isCardQuantityLegalForCurrentFormat(const CardInfoPtr cardIn
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cardHasAnyException(*cardInfo.data(), *formatRules.data())) {
|
// Exceptions always win
|
||||||
|
if (cardHasAnyException(*cardInfo, *formatRules)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cardInfo->getProperties().contains("format-" + deckList->getGameFormat())) {
|
const QString legalityProp = "format-" + deckList->getGameFormat();
|
||||||
QString formatLegality = cardInfo->getProperty("format-" + deckList->getGameFormat());
|
if (!cardInfo->getProperties().contains(legalityProp)) {
|
||||||
if (formatLegality == "legal") {
|
return false;
|
||||||
if (quantity <= formatRules->maxCopies) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (formatLegality == "restricted") {
|
|
||||||
if (quantity <= formatRules->maxRestrictedCopies) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
const QString legality = cardInfo->getProperty(legalityProp);
|
||||||
|
|
||||||
|
int maxAllowed = maxAllowedForLegality(*formatRules, legality);
|
||||||
|
|
||||||
|
if (maxAllowed == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxAllowed < 0) { // unlimited
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quantity <= maxAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeckListModel::refreshCardFormatLegalities()
|
void DeckListModel::refreshCardFormatLegalities()
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include <libcockatrice/card/database/parser/cockatrice_xml_4.h>
|
#include <libcockatrice/card/database/parser/cockatrice_xml_4.h>
|
||||||
#include <libcockatrice/card/relation/card_relation.h>
|
#include <libcockatrice/card/relation/card_relation.h>
|
||||||
|
|
||||||
|
static const QList<AllowedCount> kConstructedCounts = {{4, "legal"}, {1, "restricted"}, {0, "banned"}};
|
||||||
|
|
||||||
|
static const QList<AllowedCount> kSingletonCounts = {{1, "legal"}, {1, "restricted"}, {0, "banned"}};
|
||||||
|
|
||||||
SplitCardPart::SplitCardPart(const QString &_name,
|
SplitCardPart::SplitCardPart(const QString &_name,
|
||||||
const QString &_text,
|
const QString &_text,
|
||||||
const QVariantHash &_properties,
|
const QVariantHash &_properties,
|
||||||
|
|
@ -486,11 +490,11 @@ FormatRulesNameMap OracleImporter::createDefaultMagicFormats()
|
||||||
FormatRulesNameMap defaultFormatRulesNameMap;
|
FormatRulesNameMap defaultFormatRulesNameMap;
|
||||||
|
|
||||||
// ----------------- Helper lambda to create format -----------------
|
// ----------------- Helper lambda to create format -----------------
|
||||||
auto makeFormat = [&](const QString &name, int maxCopies = 4, int minDeck = 60, int maxDeck = -1,
|
auto makeFormat = [&](const QString &name, int minDeck = 60, int maxDeck = -1, int maxSideboardSize = 15,
|
||||||
int maxSideboardSize = 15) -> FormatRulesPtr {
|
const QList<AllowedCount> &allowedCounts = kConstructedCounts) -> FormatRulesPtr {
|
||||||
FormatRulesPtr f(new FormatRules);
|
FormatRulesPtr f(new FormatRules);
|
||||||
f->formatName = name;
|
f->formatName = name;
|
||||||
f->maxCopies = maxCopies;
|
f->allowedCounts = allowedCounts;
|
||||||
f->minDeckSize = minDeck;
|
f->minDeckSize = minDeck;
|
||||||
f->maxDeckSize = maxDeck;
|
f->maxDeckSize = maxDeck;
|
||||||
f->maxSideboardSize = maxSideboardSize;
|
f->maxSideboardSize = maxSideboardSize;
|
||||||
|
|
@ -501,27 +505,27 @@ FormatRulesNameMap OracleImporter::createDefaultMagicFormats()
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------- Standard formats -----------------
|
// ----------------- Standard formats -----------------
|
||||||
makeFormat("Alchemy", 4, 60);
|
|
||||||
makeFormat("Brawl", 1, 60, 60);
|
|
||||||
makeFormat("Commander", 1, 100, 100);
|
|
||||||
makeFormat("Duel", 1, 100, 100);
|
|
||||||
makeFormat("Future");
|
|
||||||
makeFormat("Gladiator", 4, 60, 60, 0);
|
|
||||||
makeFormat("Historic");
|
|
||||||
makeFormat("Legacy");
|
|
||||||
makeFormat("Modern");
|
|
||||||
makeFormat("Oathbreaker", 1, 60, 60);
|
|
||||||
makeFormat("OldSchool");
|
|
||||||
makeFormat("Pauper");
|
|
||||||
makeFormat("PauperCommander", 1, 100, 100);
|
|
||||||
makeFormat("Penny");
|
|
||||||
makeFormat("Pioneer");
|
|
||||||
makeFormat("Predh", 1, 100, 100);
|
|
||||||
makeFormat("Premodern");
|
|
||||||
makeFormat("Standard");
|
makeFormat("Standard");
|
||||||
makeFormat("StandardBrawl", 1, 60, 60);
|
makeFormat("Modern");
|
||||||
makeFormat("Timeless");
|
makeFormat("Legacy");
|
||||||
makeFormat("Vintage");
|
makeFormat("Vintage");
|
||||||
|
makeFormat("Pioneer");
|
||||||
|
makeFormat("Historic");
|
||||||
|
makeFormat("Timeless");
|
||||||
|
makeFormat("Future");
|
||||||
|
makeFormat("OldSchool");
|
||||||
|
makeFormat("Premodern");
|
||||||
|
makeFormat("Pauper");
|
||||||
|
makeFormat("Penny");
|
||||||
|
|
||||||
|
// ----------------- Singleton formats -----------------
|
||||||
|
makeFormat("Commander", 100, 100, 15, kSingletonCounts);
|
||||||
|
makeFormat("Duel", 100, 100, 15, kSingletonCounts);
|
||||||
|
makeFormat("Brawl", 60, 60, 15, kSingletonCounts);
|
||||||
|
makeFormat("StandardBrawl", 60, 60, 15, kSingletonCounts);
|
||||||
|
makeFormat("Oathbreaker", 60, 60, 15, kSingletonCounts);
|
||||||
|
makeFormat("PauperCommander", 100, 100, 15, kSingletonCounts);
|
||||||
|
makeFormat("Predh", 100, 100, 15, kSingletonCounts);
|
||||||
|
|
||||||
return defaultFormatRulesNameMap;
|
return defaultFormatRulesNameMap;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue