Commit b959a0c7 authored by nanahira's avatar nanahira

add lflist credit support

parent f8ce1246
......@@ -1932,18 +1932,42 @@ bool DeckBuilder::check_limit(code_pointer pointer) {
auto flit = filterList->content.find(limitcode);
if(flit != filterList->content.end())
limit = flit->second;
for (auto& card : deckManager.current_deck.main) {
if (card->first == limitcode || card->second.alias == limitcode)
auto remaining_credits = filterList->credit_limits;
auto limitcode_credit_it = filterList->credits.find(limitcode);
auto handle_card = [&](ygo::code_pointer& card) {
if (card->first == limitcode || card->second.alias == limitcode) {
limit--;
if(limit <= 0)
return false;
if(limitcode_credit_it != filterList->credits.end()) {
auto limitcode_credits = limitcode_credit_it->second;
for(auto& credit : limitcode_credits) {
auto key = credit.first;
auto remaining_credit_it = remaining_credits.find(key);
if(remaining_credit_it != remaining_credits.end()) {
auto value = credit.second;
auto remaining_credit = remaining_credit_it->second;
if(remaining_credit < value)
return false;
remaining_credits[key] -= value;
}
}
}
}
return true;
};
for (auto& card : deckManager.current_deck.main) {
if(!handle_card(card))
return false;
}
for (auto& card : deckManager.current_deck.extra) {
if (card->first == limitcode || card->second.alias == limitcode)
limit--;
if(!handle_card(card))
return false;
}
for (auto& card : deckManager.current_deck.side) {
if (card->first == limitcode || card->second.alias == limitcode)
limit--;
if(!handle_card(card))
return false;
}
return limit > 0;
return true;
}
}
......@@ -28,21 +28,68 @@ void DeckManager::LoadLFListFromLineProvider(const std::function<bool(char*, siz
cur = loadedLists.rbegin();
continue;
}
if (cur == loadedLists.rend())
if(cur == loadedLists.rend())
continue;
if(linebuf[0] == '$') {
char* keyPos = linebuf + 1;
keyPos += std::strspn(keyPos, " \t");
auto keyLen = std::strcspn(keyPos, " \t\r\n");
if(!keyLen)
continue;
char keybuf[256];
if(keyLen >= sizeof keybuf)
keyLen = sizeof keybuf - 1;
std::memcpy(keybuf, keyPos, keyLen);
keybuf[keyLen] = 0;
keyPos += keyLen;
keyPos += std::strspn(keyPos, " \t");
errno = 0;
char* valuePos = keyPos;
auto limitValue = std::strtoul(keyPos, &keyPos, 10);
if(errno || valuePos == keyPos)
continue;
BufferIO::DecodeUTF8(keybuf, strBuffer);
cur->credit_limits[strBuffer] = static_cast<uint32_t>(limitValue);
continue;
}
char* pos = linebuf;
errno = 0;
char* codePos = pos;
auto result = std::strtoul(pos, &pos, 10);
if (errno || result > UINT32_MAX)
if(errno || result > UINT32_MAX || codePos == pos)
continue;
if (pos == linebuf || *pos != ' ')
if(*pos != ' ' && *pos != '\t')
continue;
pos += std::strspn(pos, " \t");
uint32_t code = static_cast<uint32_t>(result);
if(*pos == '$') {
++pos;
pos += std::strspn(pos, " \t");
auto creditKeyLen = std::strcspn(pos, " \t\r\n");
if(!creditKeyLen)
continue;
char keybuf[256];
if(creditKeyLen >= sizeof keybuf)
creditKeyLen = sizeof keybuf - 1;
std::memcpy(keybuf, pos, creditKeyLen);
keybuf[creditKeyLen] = 0;
pos += creditKeyLen;
pos += std::strspn(pos, " \t");
errno = 0;
char* creditValuePos = pos;
auto creditValue = std::strtoul(pos, &pos, 10);
if(errno || creditValuePos == pos)
continue;
BufferIO::DecodeUTF8(keybuf, strBuffer);
cur->credits[code][strBuffer] = static_cast<uint32_t>(creditValue);
continue;
}
errno = 0;
char* countPos = pos;
int count = std::strtol(pos, &pos, 10);
if (errno)
if(errno || countPos == pos)
continue;
if (count < 0 || count > 2)
if(count < 0 || count > 2)
continue;
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
......@@ -135,6 +182,27 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
if (!lflist)
return 0;
auto& list = lflist->content;
std::unordered_map<std::wstring, uint32_t> credit_used;
auto spend_credit = [&](uint32_t code) {
auto code_credit_it = lflist->credits.find(code);
if(code_credit_it == lflist->credits.end())
return (uint32_t)0;
auto code_credit = code_credit_it->second;
for(auto& credit_it : code_credit) {
auto key = credit_it.first;
auto credit_limit_it = lflist->credit_limits.find(key);
if(credit_limit_it == lflist->credit_limits.end())
continue;
auto credit_limit = credit_limit_it->second;
if(credit_used.find(key) == credit_used.end())
credit_used[key] = 0;
auto credit_after = credit_used[key] + credit_it.second;
if(credit_after > credit_limit)
return (DECKERROR_LFLIST << 28) | code;
credit_used[key] = credit_after;
}
return (uint32_t)0;
};
const unsigned int rule_map[6] = { AVAIL_OCG, AVAIL_TCG, AVAIL_SC, AVAIL_CUSTOM, AVAIL_OCGTCG, 0 };
unsigned int avail = 0;
if (rule >= 0 && rule < (int)(sizeof rule_map / sizeof rule_map[0]))
......@@ -153,6 +221,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code);
if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
}
for (auto& cit : deck.extra) {
auto gameruleDeckError = checkAvail(cit->second.ot, avail);
......@@ -168,6 +239,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code);
if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
}
for (auto& cit : deck.side) {
auto gameruleDeckError = checkAvail(cit->second.ot, avail);
......@@ -183,6 +257,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code);
if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
}
return 0;
}
......
......@@ -44,6 +44,8 @@ struct LFList {
unsigned int hash{};
std::wstring listName;
std::unordered_map<uint32_t, int> content;
std::unordered_map<std::wstring, uint32_t> credit_limits;
std::unordered_map<uint32_t, std::unordered_map<std::wstring, uint32_t>> credits;
};
struct Deck {
std::vector<code_pointer> main;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment