mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-10 20:13:24 -08:00
Honor finite deck copy limits across printings and deck zones [skip ci] (#7719)
This commit is contained in:
parent
18388d9994
commit
16455c9fd5
9 changed files with 440 additions and 48 deletions
|
|
@ -71,3 +71,52 @@ bool parseCipt(const QString &name, const QString &text)
|
|||
|
||||
return ciptPattern.match(text).hasMatch();
|
||||
}
|
||||
|
||||
std::optional<int> parseDeckCopyLimit(const QString &name, const QString &text)
|
||||
{
|
||||
// Require a complete, standalone allowance. Other effects that mention a
|
||||
// number of cards or a different card name must not change deck construction.
|
||||
static const QRegularExpression rule(
|
||||
R"(^A deck can have up to ([a-z]+(?:[ -][a-z]+)*|[0-9]+) cards? named ([^\r\n]+)\.\r?$)",
|
||||
QRegularExpression::MultilineOption);
|
||||
static const QStringList smallNumbers = {
|
||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
|
||||
static const QStringList tens = {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
|
||||
auto normalizedName = [](QString cardName) {
|
||||
return cardName.replace("Æ", "AE").replace("’", "'").normalized(QString::NormalizationForm_C);
|
||||
};
|
||||
const QString expectedName = normalizedName(name);
|
||||
if (expectedName.isEmpty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<int> limit;
|
||||
auto matches = rule.globalMatch(text);
|
||||
while (matches.hasNext()) {
|
||||
const auto match = matches.next();
|
||||
if (normalizedName(match.captured(2)) != expectedName) {
|
||||
continue;
|
||||
}
|
||||
const QString count = match.captured(1);
|
||||
bool numeric = false;
|
||||
int value = count.toInt(&numeric);
|
||||
if (!numeric) {
|
||||
// English words through ninety-nine; larger counts remain supported
|
||||
// as decimal numerals. Unknown wording is deliberately not guessed.
|
||||
const QStringList words = QString(count).replace('-', ' ').split(' ');
|
||||
value = words.size() == 1 ? smallNumbers.indexOf(words.first()) : -1;
|
||||
const int ten = tens.indexOf(words.first());
|
||||
if (ten >= 0 && words.size() <= 2) {
|
||||
const int unit = words.size() == 1 ? 0 : smallNumbers.indexOf(words.last());
|
||||
if (unit >= 0 && unit < 10 && (words.size() == 1 || unit > 0)) {
|
||||
value = (ten + 2) * 10 + unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value <= 0 || (limit && *limit != value)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
limit = value;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue