Skip to content

Instantly share code, notes, and snippets.

@GeeLaw
Last active April 9, 2024 12:12
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GeeLaw/9bbd838ad561ed2b938f92a128730c2b to your computer and use it in GitHub Desktop.
Save GeeLaw/9bbd838ad561ed2b938f92a128730c2b to your computer and use it in GitHub Desktop.
通过攻击抗性决定敌方宝可梦的属性组合 / determining type combo of an unknown enemy pokémon from type-based prompts against attacks
/*
Copyright 2024 by Ji Luo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
----------------------------------------
chcp 65001 && cls && cl.exe /permissive- /EHsc /std:c++20 /O2 /Oi /Oy /source-charset:utf-8 /execution-charset:utf-8 pokemon.cpp
pokemon.exe > results-all.txt
pokemon.exe known > results-known.txt
pokemon.exe gen 2 > results-gen2.txt
pokemon.exe gen 1 > results-gen1.txt
见 https://www.bilibili.com/video/BV1Rt421L7TV/
最新的优化是加入了滚动数组,见 https://gist.github.com/wellcoming/9330eea23477aedae447435d8e04e5a5
手还是生了呀!
*/
// 属性
char const * const TypeNames[] = { "普", "格", "飞", "毒", "地", "岩", "虫", "鬼", "钢", "火", "水", "草", "电", "超", "冰", "龙", "恶", "妖" };
constexpr int const TypeCount = sizeof TypeNames / sizeof TypeNames[0];
// 属性组合
char const * const TypeComboNames[] =
{
"普", "格", "飞", "毒", "地", "岩", "虫", "鬼", "钢", "火", "水", "草", "电", "超", "冰", "龙", "恶", "妖",
"普+格", "普+飞", "普+毒", "普+地", "普+岩", "普+虫", "普+鬼", "普+钢", "普+火", "普+水", "普+草", "普+电", "普+超", "普+冰", "普+龙", "普+恶", "普+妖",
"格+飞", "格+毒", "格+地", "格+岩", "格+虫", "格+鬼", "格+钢", "格+火", "格+水", "格+草", "格+电", "格+超", "格+冰", "格+龙", "格+恶", "格+妖",
"飞+毒", "飞+地", "飞+岩", "飞+虫", "飞+鬼", "飞+钢", "飞+火", "飞+水", "飞+草", "飞+电", "飞+超", "飞+冰", "飞+龙", "飞+恶", "飞+妖",
"毒+地", "毒+岩", "毒+虫", "毒+鬼", "毒+钢", "毒+火", "毒+水", "毒+草", "毒+电", "毒+超", "毒+冰", "毒+龙", "毒+恶", "毒+妖",
"地+岩", "地+虫", "地+鬼", "地+钢", "地+火", "地+水", "地+草", "地+电", "地+超", "地+冰", "地+龙", "地+恶", "地+妖",
"岩+虫", "岩+鬼", "岩+钢", "岩+火", "岩+水", "岩+草", "岩+电", "岩+超", "岩+冰", "岩+龙", "岩+恶", "岩+妖",
"虫+鬼", "虫+钢", "虫+火", "虫+水", "虫+草", "虫+电", "虫+超", "虫+冰", "虫+龙", "虫+恶", "虫+妖",
"鬼+钢", "鬼+火", "鬼+水", "鬼+草", "鬼+电", "鬼+超", "鬼+冰", "鬼+龙", "鬼+恶", "鬼+妖",
"钢+火", "钢+水", "钢+草", "钢+电", "钢+超", "钢+冰", "钢+龙", "钢+恶", "钢+妖",
"火+水", "火+草", "火+电", "火+超", "火+冰", "火+龙", "火+恶", "火+妖",
"水+草", "水+电", "水+超", "水+冰", "水+龙", "水+恶", "水+妖",
"草+电", "草+超", "草+冰", "草+龙", "草+恶", "草+妖",
"电+超", "电+冰", "电+龙", "电+恶", "电+妖",
"超+冰", "超+龙", "超+恶", "超+妖",
"冰+龙", "冰+恶", "冰+妖",
"龙+恶", "龙+妖",
"恶+妖",
"无" // 第四世代羽栖先制的回合
};
constexpr int const TypeComboCount = sizeof TypeComboNames / sizeof TypeComboNames[0];
static_assert(TypeComboCount == TypeCount * (TypeCount - 1) / 2 + TypeCount + 1, "属性和属性组合数不一致。");
// 攻击的提示文字
// 无意义 = -1, 其他依本数组下标.
char const * const PromptTexts[] = { "无效", "很小", "普通", "拔群" };
constexpr int const PromptCount = sizeof PromptTexts / sizeof PromptTexts[0];
// 属性相克表
// table[attack][defense]: 无意义 = -1, 无效 = 0, 减半 = 1, 正常 = 2, 加倍 = 4.
typedef int MultiplierTable[TypeCount][TypeCount];
struct TypeComboSet;
// 一次攻击观察到提示文字后,剩余可能的防守属性组合集
// table[attack][prompt] = { defense combo | attack 的效果是 prompt }.
typedef TypeComboSet RemainingTable[TypeCount][PromptCount];
#include<exception>
// 计算提示文字
constexpr int GetPrompt(int multiplier1, int multiplier2) noexcept
{
if (multiplier1 < 0 || multiplier2 < 0)
std::terminate();
int multiplier = multiplier1 * multiplier2;
if (multiplier > 4)
return 3;
if (multiplier == 4)
return 2;
if (multiplier > 0)
return 1;
return 0;
}
constexpr int GetPrompt(int multiplier) noexcept
{
if (multiplier < 0)
std::terminate();
return multiplier > 2 ? 3 : multiplier;
}
#include<cstdint>
constexpr std::uint32_t const OneU32 = 1;
// 属性集
struct TypeSet
{
static_assert((TypeCount + 31) / 32 == 1, "属性数不恰当。");
std::uint32_t Bitset;
constexpr TypeSet AfterRemoving(int element) const noexcept
{
return { Bitset & ~(element >= 0 && element < TypeCount ? OneU32 << element : 0) };
}
constexpr bool Has(int element) const noexcept
{
if (element < 0 || element >= TypeCount)
std::terminate();
return Bitset & (OneU32 << element);
}
};
// 属性组合集
struct TypeComboSet
{
static_assert((TypeComboCount + 31) / 32 == 6, "属性组合数不恰当。");
std::uint32_t BitSubsets[6];
constexpr bool IsEmpty() const noexcept { return !(BitSubsets[0] | BitSubsets[1] | BitSubsets[2] | BitSubsets[3] | BitSubsets[4] | BitSubsets[5]); }
constexpr bool IsSingleton() const noexcept
{
if (!BitSubsets[0] + !BitSubsets[1] + !BitSubsets[2] + !BitSubsets[3] + !BitSubsets[4] + !BitSubsets[5] != 5)
return false;
std::uint32_t const subsets = (BitSubsets[0] | BitSubsets[1] | BitSubsets[2] | BitSubsets[3] | BitSubsets[4] | BitSubsets[5]);
return (subsets & (-subsets)) == subsets;
}
void Add(int element) noexcept
{
if (element < 0 || element >= TypeComboCount)
std::terminate();
BitSubsets[element / 32] |= (OneU32 << (element % 32));
}
constexpr bool Has(int element) const noexcept
{
if (element < 0 || element >= TypeComboCount)
std::terminate();
return BitSubsets[element / 32] & (OneU32 << (element % 32));
}
constexpr int GetElementFromSingleton() const noexcept
{
for (int group = 0; group != 6; ++group)
{
std::uint32_t singleton = BitSubsets[group];
if (singleton)
{
int element = 32 * group;
while (singleton)
{
singleton >>= 1;
++element;
}
return --element;
}
}
std::terminate();
}
friend constexpr TypeComboSet operator &(TypeComboSet const &a, TypeComboSet const &b) noexcept
{
return
{
{
a.BitSubsets[0] & b.BitSubsets[0],
a.BitSubsets[1] & b.BitSubsets[1],
a.BitSubsets[2] & b.BitSubsets[2],
a.BitSubsets[3] & b.BitSubsets[3],
a.BitSubsets[4] & b.BitSubsets[4],
a.BitSubsets[5] & b.BitSubsets[5]
}
};
}
friend constexpr bool operator ==(TypeComboSet const &a, TypeComboSet const &b) noexcept
{
return a.BitSubsets[0] == b.BitSubsets[0]
&& a.BitSubsets[1] == b.BitSubsets[1]
&& a.BitSubsets[2] == b.BitSubsets[2]
&& a.BitSubsets[3] == b.BitSubsets[3]
&& a.BitSubsets[4] == b.BitSubsets[4]
&& a.BitSubsets[5] == b.BitSubsets[5];
}
};
namespace std
{
template <>
struct hash<TypeComboSet>
{
std::size_t operator ()(TypeComboSet const &tcs) const noexcept
{
static_assert(sizeof(std::size_t) >= 8, "必须用 64 位寻址空间。");
return ((((((((((((static_cast<std::size_t>(0xCBF29CE484222325u)
* 0x100000001B3u) ^ tcs.BitSubsets[0])
* 0x100000001B3u) ^ tcs.BitSubsets[1])
* 0x100000001B3u) ^ tcs.BitSubsets[2])
* 0x100000001B3u) ^ tcs.BitSubsets[3])
* 0x100000001B3u) ^ tcs.BitSubsets[4])
* 0x100000001B3u) ^ tcs.BitSubsets[5]);
}
};
}
// 决策树
struct DecisionTree
{
// 即使把所有攻击属性都尝试一次也无法完全区分每个防守属性组合.
static constexpr int const Undecidable = 0;
// 需要尝试另一攻击属性, AttackOrDefense = 要尝试的攻击属性.
static constexpr int const AnotherAttack = 1;
// 已经得出答案, AttackOrDefense = 防守属性组合答案.
static constexpr int const Determined = 2;
// 不存在这种情况, 例如: 火属性攻击无效.
static constexpr int const Unreachable = 3;
// 是哪种类型?
int Kind;
// 最多还要尝试多少次?
int Depth;
// 见上面.
int AttackOrDefense;
// Children[prompt] 为本次攻击后得到 prompt 的决策树.
DecisionTree const *Children[PromptCount];
// 节约内存
static DecisionTree const UndecidableTree;
static DecisionTree const UnreachableTree;
};
constexpr DecisionTree const DecisionTree::UndecidableTree = { DecisionTree::Undecidable, TypeCount + 1, 0, {} };
constexpr DecisionTree const DecisionTree::UnreachableTree = { DecisionTree::Unreachable, 0, 0, {} };
#include<unordered_map>
struct FindBestTree
{
FindBestTree(TypeSet const attacks, TypeComboSet const &defenseCombos, MultiplierTable const &multipliers)
: AttackUniverse{ attacks }, DefenseComboUniverse{ defenseCombos },
After{ ComputeRemainingTable(attacks, defenseCombos, multipliers) }, Memo{}
{
}
operator DecisionTree const *() noexcept
{
return Compute(DefenseComboUniverse);
}
private:
TypeSet const AttackUniverse;
TypeComboSet const DefenseComboUniverse;
RemainingTable const &After;
// 两种看法:
// 1. 问题建模为 F(A, D), 其中 A 是 剩余攻击, D 是 剩余防守组合,
// 但对于 F(AU, DU) 有意义的 F(A, D) 都等于 F(AU, D),
// 其中 AU, DU 是全集, 因此可以采用原地滚动数组 ("松弛") 的优化.
// 2. 问题可以直接建模为 F(D), 状态里不需要 A,
// 此时状态转移方程需要选择不导致递归的 a in AU.
std::unordered_map<TypeComboSet, DecisionTree const *> Memo;
DecisionTree const *Compute(TypeComboSet const &defenseCombos)
{
// 令 found 析构
{
auto found = Memo.find(defenseCombos);
if (found != Memo.end())
return found->second;
}
if (defenseCombos.IsEmpty())
return Memo[defenseCombos] = &DecisionTree::UnreachableTree;
if (defenseCombos.IsSingleton())
return Memo[defenseCombos] = new DecisionTree{ DecisionTree::Determined, 0, defenseCombos.GetElementFromSingleton(), {} };
// 这里采用 F(A, D) + 滚动数组 ("松弛") 的看法,
// 此时必须先设备忘答案为 不可判定 (监视哨), 防止无穷递归.
// 在 https://gist.github.com/wellcoming/9330eea23477aedae447435d8e04e5a5
// 里似乎采用的是 F(D) 的看法, 于是稍后递归进入 Compute 前需要先确认 D 缩小.
// 从实际效果来看是一样的, 这里进入 Compute(未缩小的 D) 会立刻返回 不可判定.
Memo[defenseCombos] = &DecisionTree::UndecidableTree;
DecisionTree best = DecisionTree::UndecidableTree;
for (int attack = 0; attack != TypeCount; ++attack)
{
if (!AttackUniverse.Has(attack))
continue;
DecisionTree const *children[PromptCount];
int depth = -1;
for (int prompt = 0; prompt != PromptCount; ++prompt)
{
DecisionTree const *child = Compute(defenseCombos & After[attack][prompt]);
if ((children[prompt] = child)->Depth > depth && (depth = child->Depth) >= best.Depth - 1)
goto break2;
}
best.Kind = DecisionTree::AnotherAttack;
best.Depth = ++depth;
best.AttackOrDefense = attack;
for (int prompt = 0; prompt != PromptCount; ++prompt)
best.Children[prompt] = children[prompt];
break2:
;
}
return Memo[defenseCombos] = (best.Kind == DecisionTree::Undecidable
? &DecisionTree::UndecidableTree
: new DecisionTree{ best });
}
static RemainingTable const &ComputeRemainingTable(TypeSet const attacks, TypeComboSet const &defenseCombos, MultiplierTable const &multipliers)
{
RemainingTable &table = *new RemainingTable[1]{};
for (int attack = 0; attack != TypeCount; ++attack)
{
if (!attacks.Has(attack))
continue;
int defenseCombo = 0;
for (int defense = 0; defense != TypeCount; ++defense, ++defenseCombo)
if (defenseCombos.Has(defenseCombo))
table[attack][GetPrompt(multipliers[attack][defense])].Add(defenseCombo);
for (int defense1 = 0; defense1 != TypeCount; ++defense1)
for (int defense2 = defense1 + 1; defense2 != TypeCount; ++defense2, ++defenseCombo)
if (defenseCombos.Has(defenseCombo))
table[attack][GetPrompt(multipliers[attack][defense1], multipliers[attack][defense2])].Add(defenseCombo);
// defenseCombo: 无
if (defenseCombos.Has(defenseCombo))
// 普通效果
table[attack][2].Add(defenseCombo);
}
return table;
}
};
namespace Data
{
constexpr TypeSet const Gen6TypeSet = { 0x3FFFFu };
constexpr TypeSet const Gen2TypeSet = { 0x1FFFFu };
constexpr TypeSet const Gen1TypeSet = { 0x0FEFFu };
// 属性相克表 https://wiki.52poke.com/zh-hans/%E5%B1%9E%E6%80%A7%E7%9B%B8%E5%85%8B%E8%A1%A8
constexpr MultiplierTable const Gen6MultiplierTable =
{
{ 2, 2, 2, 2, 2, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 4, 2, 1, 1, 2, 4, 1, 0, 4, 2, 2, 2, 2, 1, 4, 2, 4, 1 },
{ 2, 4, 2, 2, 2, 1, 4, 2, 1, 2, 2, 4, 1, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 1, 1, 1, 2, 1, 0, 2, 2, 4, 2, 2, 2, 2, 2, 4 },
{ 2, 2, 0, 4, 2, 4, 1, 2, 4, 4, 2, 1, 4, 2, 2, 2, 2, 2 },
{ 2, 1, 4, 2, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 4, 2, 2, 2 },
{ 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 4, 2, 4, 2, 2, 4, 1 },
{ 0, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 1, 2 },
{ 2, 2, 2, 2, 2, 4, 2, 2, 1, 1, 1, 2, 1, 2, 4, 2, 2, 4 },
{ 2, 2, 2, 2, 2, 1, 4, 2, 4, 1, 1, 4, 2, 2, 4, 1, 2, 2 },
{ 2, 2, 2, 2, 4, 4, 2, 2, 2, 4, 1, 1, 2, 2, 2, 1, 2, 2 },
{ 2, 2, 1, 1, 4, 4, 1, 2, 1, 1, 4, 1, 2, 2, 2, 1, 2, 2 },
{ 2, 2, 4, 2, 0, 2, 2, 2, 2, 2, 4, 1, 1, 2, 2, 1, 2, 2 },
{ 2, 4, 2, 4, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 0, 2 },
{ 2, 2, 4, 2, 4, 2, 2, 2, 1, 1, 1, 4, 2, 2, 1, 4, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 4, 2, 0 },
{ 2, 1, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 1, 1 },
{ 2, 4, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 4, 4, 2 }
};
constexpr MultiplierTable const Gen2MultiplierTable =
{
{ 2, 2, 2, 2, 2, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, -1 },
{ 4, 2, 1, 1, 2, 4, 1, 0, 4, 2, 2, 2, 2, 1, 4, 2, 4, -1 },
{ 2, 4, 2, 2, 2, 1, 4, 2, 1, 2, 2, 4, 1, 2, 2, 2, 2, -1 },
{ 2, 2, 2, 1, 1, 1, 2, 1, 0, 2, 2, 4, 2, 2, 2, 2, 2, -1 },
{ 2, 2, 0, 4, 2, 4, 1, 2, 4, 4, 2, 1, 4, 2, 2, 2, 2, -1 },
{ 2, 1, 4, 2, 1, 2, 4, 2, 1, 4, 2, 2, 2, 2, 4, 2, 2, -1 },
{ 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 4, 2, 4, 2, 2, 4, -1 },
{ 0, 2, 2, 2, 2, 2, 2, 4, 1, 2, 2, 2, 2, 4, 2, 2, 1, -1 },
{ 2, 2, 2, 2, 2, 4, 2, 2, 1, 1, 1, 2, 1, 2, 4, 2, 2, -1 },
{ 2, 2, 2, 2, 2, 1, 4, 2, 4, 1, 1, 4, 2, 2, 4, 1, 2, -1 },
{ 2, 2, 2, 2, 4, 4, 2, 2, 2, 4, 1, 1, 2, 2, 2, 1, 2, -1 },
{ 2, 2, 1, 1, 4, 4, 1, 2, 1, 1, 4, 1, 2, 2, 2, 1, 2, -1 },
{ 2, 2, 4, 2, 0, 2, 2, 2, 2, 2, 4, 1, 1, 2, 2, 1, 2, -1 },
{ 2, 4, 2, 4, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 0, -1 },
{ 2, 2, 4, 2, 4, 2, 2, 2, 1, 1, 1, 4, 2, 2, 1, 4, 2, -1 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 4, 2, -1 },
{ 2, 1, 2, 2, 2, 2, 2, 4, 1, 2, 2, 2, 2, 4, 2, 2, 1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
};
constexpr MultiplierTable const Gen1MultiplierTable =
{
{ 2, 2, 2, 2, 2, 1, 2, 0, -1, 2, 2, 2, 2, 2, 2, 2, -1, -1 },
{ 4, 2, 1, 1, 2, 4, 1, 0, -1, 2, 2, 2, 2, 1, 4, 2, -1, -1 },
{ 2, 4, 2, 2, 2, 1, 4, 2, -1, 2, 2, 4, 1, 2, 2, 2, -1, -1 },
{ 2, 2, 2, 1, 1, 1, 4, 1, -1, 2, 2, 4, 2, 2, 2, 2, -1, -1 },
{ 2, 2, 0, 4, 2, 4, 1, 2, -1, 4, 2, 1, 4, 2, 2, 2, -1, -1 },
{ 2, 1, 4, 2, 1, 2, 4, 2, -1, 4, 2, 2, 2, 2, 4, 2, -1, -1 },
{ 2, 1, 1, 4, 2, 2, 2, 1, -1, 1, 2, 4, 2, 4, 2, 2, -1, -1 },
{ 0, 2, 2, 2, 2, 2, 2, 4, -1, 2, 2, 2, 2, 0, 2, 2, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ 2, 2, 2, 2, 2, 1, 4, 2, -1, 1, 1, 4, 2, 2, 4, 1, -1, -1 },
{ 2, 2, 2, 2, 4, 4, 2, 2, -1, 4, 1, 1, 2, 2, 2, 1, -1, -1 },
{ 2, 2, 1, 1, 4, 4, 1, 2, -1, 1, 4, 1, 2, 2, 2, 1, -1, -1 },
{ 2, 2, 4, 2, 0, 2, 2, 2, -1, 2, 4, 1, 1, 2, 2, 1, -1, -1 },
{ 2, 4, 2, 4, 2, 2, 2, 2, -1, 2, 2, 2, 2, 1, 2, 2, -1, -1 },
{ 2, 2, 4, 2, 4, 2, 2, 2, -1, 2, 1, 4, 2, 2, 1, 4, -1, -1 },
{ 2, 2, 2, 2, 2, 2, 2, 2, -1, 2, 2, 2, 2, 2, 2, 4, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
};
constexpr TypeComboSet const AllPossibleTypeCombosExceptNone = { { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x7FFu } };
constexpr TypeComboSet const AllPossibleTypeCombos = { { 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFu } };
// 2024 年 2 月不存在的属性如下 https://wiki.52poke.com/wiki/%E5%B1%9E%E6%80%A7
// 普+岩, 普+虫, 普+钢, 普+冰, 毒+冰, 地+妖, 岩+鬼, 虫+龙, 火+妖
constexpr TypeComboSet const TypeCombos202402 = { { 0x7D3FFFFFu, 0xFFFFFFFFu, 0xAFFFEFFFu, 0xFFFDFFFFu, 0xFFFFBFFFu, 0x7FFu } };
// 第二世代属性表 https://bulbapedia.bulbagarden.net/wiki/List_of_Pok%C3%A9mon_by_index_number_(Generation_II)
constexpr TypeComboSet const Gen2TypeCombos = { { 0x4009BEFBu, 0xFF780880u, 0x22290335u, 0x00002483u, 0x008F2002u, 0x042u } };
// 第一世代属性表 https://bulbapedia.bulbagarden.net/wiki/List_of_Pok%C3%A9mon_by_index_number_(Generation_I)
constexpr TypeComboSet const Gen1TypeCombos = { { 0x0008BE5Bu, 0xD6680800u, 0x00010334u, 0x00002002u, 0x00860000u, 0x002u } };
}
#include<cstdio>
void PrintTree(DecisionTree const *tree, int prompt, int indent)
{
for (int i = 0; i != indent; ++i)
{
std::putchar(' ');
std::putchar(' ');
}
if (prompt >= 0)
std::printf("%s: ", PromptTexts[prompt]);
switch (tree->Kind)
{
case DecisionTree::Undecidable:
std::puts("不可判定.");
return;
case DecisionTree::AnotherAttack:
std::printf("尝试 %s.\n", TypeNames[tree->AttackOrDefense]);
++indent;
for (prompt = 0; prompt != PromptCount; ++prompt)
PrintTree(tree->Children[prompt], prompt, indent);
return;
case DecisionTree::Determined:
std::printf("答案 = %s.\n", TypeComboNames[tree->AttackOrDefense]);
return;
case DecisionTree::Unreachable:
std::puts("无此情况.");
return;
}
std::terminate();
}
#include<ctime>
void AllPossible()
{
std::clock_t start = std::clock();
// 会使用 5.5 MB 以内的内存, 用 1024 进制换算的.
DecisionTree const *best = FindBestTree(
Data::Gen6TypeSet,
Data::AllPossibleTypeCombosExceptNone,
Data::Gen6MultiplierTable
);
std::printf("全部理论可能: %.3f 秒, ",
(std::clock() - start) / (double)CLOCKS_PER_SEC);
std::printf("深度 = %d.\n\n", best->Depth);
PrintTree(best, -1, 0);
}
void Only202402()
{
clock_t start = std::clock();
// 会使用 4.72 MB 以内的内存, 用 1024 进制换算的.
DecisionTree const *best = FindBestTree(
Data::Gen6TypeSet,
Data::TypeCombos202402,
Data::Gen6MultiplierTable
);
std::printf("当前存在组合: %.3f 秒, ",
(std::clock() - start) / (double)CLOCKS_PER_SEC);
std::printf("深度 = %d.\n\n", best->Depth);
PrintTree(best, -1, 0);
}
void Gen2()
{
clock_t start = std::clock();
// 会使用 0.99 MB 以内的内存, 用 1024 进制换算的.
DecisionTree const *best = FindBestTree(
Data::Gen2TypeSet,
Data::Gen2TypeCombos,
Data::Gen2MultiplierTable
);
std::printf("第二世代: %.3f 秒, ",
(std::clock() - start) / (double)CLOCKS_PER_SEC);
std::printf("深度 = %d.\n\n", best->Depth);
PrintTree(best, -1, 0);
}
void Gen1()
{
clock_t start = std::clock();
// 会使用 0.61 MB 以内的内存, 用 1024 进制换算的.
DecisionTree const *best = FindBestTree(
Data::Gen1TypeSet,
Data::Gen1TypeCombos,
Data::Gen1MultiplierTable
);
std::printf("第一世代: %.3f 秒, ",
(std::clock() - start) / (double)CLOCKS_PER_SEC);
std::printf("深度 = %d.\n\n", best->Depth);
PrintTree(best, -1, 0);
}
int main(int argc, char **argv)
{
if (argc == 1)
// 无参数: 计算全部理论可能.
AllPossible();
else if (argc == 2)
// 参数是 known: 计算当前存在组合.
Only202402();
else if (argc == 3 && argv[2][0] == '1')
// 参数是 gen 1: 计算第一世代.
Gen1();
else if (argc == 3 && argv[2][0] == '2')
// 参数是 gen 2: 计算第二世代.
Gen2();
// 一次性程序, 操作系统会回收内存.
return 0;
}
全部理论可能: 2.193 秒, 深度 = 6.
尝试 普.
无效: 尝试 鬼.
无效: 答案 = 普+鬼.
很小: 无此情况.
普通: 答案 = 鬼+恶.
拔群: 尝试 草.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+鬼.
很小: 尝试 毒.
无效: 无此情况.
很小: 答案 = 虫+鬼.
普通: 答案 = 鬼+草.
拔群: 无此情况.
普通: 答案 = 鬼+龙.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 鬼+钢.
普通: 答案 = 毒+鬼.
拔群: 答案 = 鬼+火.
普通: 尝试 钢.
无效: 无此情况.
很小: 答案 = 鬼+电.
普通: 尝试 超.
无效: 无此情况.
很小: 答案 = 鬼+超.
普通: 答案 = 鬼.
拔群: 答案 = 格+鬼.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 鬼+冰.
普通: 答案 = 鬼+妖.
拔群: 无此情况.
拔群: 尝试 钢.
无效: 无此情况.
很小: 答案 = 鬼+水.
普通: 答案 = 地+鬼.
拔群: 答案 = 岩+鬼.
很小: 尝试 岩.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 尝试 电.
无效: 答案 = 地+钢.
很小: 尝试 飞.
无效: 无此情况.
很小: 尝试 火.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 钢+龙.
拔群: 答案 = 钢+电.
普通: 答案 = 钢+草.
拔群: 无此情况.
普通: 尝试 超.
无效: 答案 = 钢+恶.
很小: 尝试 鬼.
无效: 答案 = 普+钢.
很小: 无此情况.
普通: 答案 = 钢.
拔群: 答案 = 钢+超.
普通: 尝试 格.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 毒+钢.
拔群: 答案 = 格+钢.
拔群: 无此情况.
拔群: 答案 = 钢+水.
普通: 尝试 格.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 钢+妖.
拔群: 答案 = 岩+钢.
拔群: 尝试 飞.
无效: 无此情况.
很小: 答案 = 地+岩.
普通: 答案 = 格+岩.
拔群: 无此情况.
普通: 尝试 虫.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+钢.
很小: 无此情况.
普通: 答案 = 虫+钢.
拔群: 答案 = 钢+火.
普通: 答案 = 钢+冰.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+岩.
普通: 答案 = 岩+妖.
拔群: 无此情况.
普通: 尝试 电.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 岩+电.
拔群: 答案 = 岩+龙.
普通: 尝试 鬼.
无效: 答案 = 普+岩.
很小: 无此情况.
普通: 答案 = 岩.
拔群: 无此情况.
拔群: 答案 = 岩+水.
拔群: 尝试 鬼.
无效: 无此情况.
很小: 答案 = 岩+恶.
普通: 答案 = 岩+草.
拔群: 答案 = 岩+超.
拔群: 尝试 格.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 飞.
无效: 无此情况.
很小: 答案 = 飞+岩.
普通: 答案 = 岩+虫.
拔群: 无此情况.
拔群: 尝试 虫.
无效: 无此情况.
很小: 答案 = 岩+火.
普通: 答案 = 岩+冰.
拔群: 无此情况.
普通: 尝试 格.
无效: 无此情况.
很小: 尝试 电.
无效: 尝试 毒.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+地.
很小: 答案 = 地+虫.
普通: 答案 = 地+超.
拔群: 答案 = 毒+地.
普通: 答案 = 地+妖.
拔群: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+电.
普通: 答案 = 电+超.
拔群: 答案 = 电+妖.
普通: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+龙.
普通: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 超+龙.
拔群: 答案 = 虫+电.
拔群: 答案 = 龙+妖.
拔群: 尝试 毒.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 地.
无效: 无此情况.
很小: 答案 = 虫+龙.
普通: 答案 = 毒+草.
拔群: 无此情况.
拔群: 尝试 恶.
无效: 无此情况.
很小: 答案 = 草+妖.
普通: 答案 = 虫+草.
拔群: 答案 = 草+超.
普通: 尝试 毒.
无效: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 答案 = 格+毒.
普通: 尝试 虫.
无效: 无此情况.
很小: 答案 = 毒.
普通: 答案 = 毒+超.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 毒+火.
拔群: 答案 = 毒+虫.
普通: 尝试 地.
无效: 尝试 飞.
无效: 无此情况.
很小: 答案 = 飞+电.
普通: 答案 = 飞+龙.
拔群: 无此情况.
很小: 尝试 虫.
无效: 无此情况.
很小: 答案 = 格+虫.
普通: 答案 = 虫.
拔群: 答案 = 虫+超.
普通: 尝试 岩.
无效: 无此情况.
很小: 答案 = 格+超.
普通: 答案 = 超.
拔群: 答案 = 虫+火.
拔群: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 毒+妖.
拔群: 答案 = 火+超.
拔群: 尝试 地.
无效: 答案 = 飞+草.
很小: 答案 = 虫+妖.
普通: 尝试 超.
无效: 无此情况.
很小: 答案 = 超+妖.
普通: 答案 = 妖.
拔群: 答案 = 格+妖.
拔群: 答案 = 火+妖.
拔群: 尝试 钢.
无效: 无此情况.
很小: 尝试 地.
无效: 尝试 水.
无效: 无此情况.
很小: 答案 = 飞+水.
普通: 无此情况.
拔群: 答案 = 飞+火.
很小: 答案 = 虫+水.
普通: 答案 = 水+超.
拔群: 答案 = 毒+水.
普通: 尝试 超.
无效: 无此情况.
很小: 答案 = 飞+超.
普通: 尝试 火.
无效: 无此情况.
很小: 答案 = 水+妖.
普通: 答案 = 飞.
拔群: 答案 = 飞+虫.
拔群: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 飞+毒.
拔群: 答案 = 格+飞.
拔群: 答案 = 飞+妖.
普通: 尝试 毒.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 地+电.
普通: 尝试 火.
无效: 无此情况.
很小: 尝试 妖.
无效: 无此情况.
很小: 答案 = 地+火.
普通: 答案 = 地+水.
拔群: 答案 = 地+龙.
普通: 尝试 鬼.
无效: 答案 = 普+毒.
很小: 答案 = 毒+恶.
普通: 答案 = 地.
拔群: 无此情况.
拔群: 答案 = 毒+冰.
拔群: 答案 = 格+地.
普通: 尝试 冰.
无效: 无此情况.
很小: 尝试 水.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 水+电.
普通: 答案 = 水.
拔群: 答案 = 格+水.
普通: 尝试 地.
无效: 无此情况.
很小: 答案 = 虫+冰.
普通: 答案 = 超+冰.
拔群: 答案 = 火+水.
拔群: 尝试 飞.
无效: 无此情况.
很小: 答案 = 火+电.
普通: 答案 = 火.
拔群: 答案 = 格+火.
普通: 尝试 地.
无效: 答案 = 飞+冰.
很小: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 普+虫.
拔群: 答案 = 虫+恶.
普通: 尝试 超.
无效: 答案 = 超+恶.
很小: 答案 = 普+超.
普通: 答案 = 水+龙.
拔群: 答案 = 格.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 格+电.
普通: 答案 = 电.
拔群: 答案 = 火+龙.
拔群: 尝试 飞.
无效: 无此情况.
很小: 答案 = 电+龙.
普通: 尝试 鬼.
无效: 答案 = 普+飞.
很小: 答案 = 飞+恶.
普通: 答案 = 龙.
拔群: 无此情况.
拔群: 尝试 地.
无效: 无此情况.
很小: 答案 = 地+草.
普通: 答案 = 格+龙.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+妖.
普通: 答案 = 恶+妖.
拔群: 答案 = 草+电.
拔群: 答案 = 冰+妖.
拔群: 尝试 火.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 妖.
无效: 无此情况.
很小: 答案 = 火+草.
普通: 答案 = 水+草.
拔群: 答案 = 草+龙.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 格+草.
普通: 答案 = 草.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 尝试 鬼.
无效: 答案 = 普+电.
很小: 答案 = 电+恶.
普通: 答案 = 电+冰.
拔群: 无此情况.
普通: 尝试 鬼.
无效: 尝试 冰.
无效: 无此情况.
很小: 尝试 水.
无效: 无此情况.
很小: 答案 = 普+水.
普通: 答案 = 普+冰.
拔群: 答案 = 普+火.
普通: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 普.
拔群: 答案 = 普+恶.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 普+地.
普通: 答案 = 普+龙.
拔群: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 答案 = 地+恶.
普通: 尝试 草.
无效: 无此情况.
很小: 答案 = 龙+恶.
普通: 答案 = 恶.
拔群: 答案 = 水+恶.
拔群: 尝试 地.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 冰+恶.
拔群: 答案 = 火+恶.
普通: 尝试 地.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 电.
无效: 答案 = 地+冰.
很小: 答案 = 冰+龙.
普通: 答案 = 冰.
拔群: 答案 = 水+冰.
拔群: 答案 = 火+冰.
拔群: 无此情况.
拔群: 尝试 毒.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 鬼.
无效: 答案 = 普+格.
很小: 答案 = 格+恶.
普通: 答案 = 格+冰.
拔群: 无此情况.
拔群: 尝试 鬼.
无效: 答案 = 普+草.
很小: 答案 = 草+恶.
普通: 答案 = 草+冰.
拔群: 无此情况.
拔群: 无此情况.
第一世代: 0.012 秒, 深度 = 4.
尝试 格.
无效: 答案 = 毒+鬼.
很小: 尝试 地.
无效: 尝试 水.
无效: 无此情况.
很小: 尝试 草.
无效: 无此情况.
很小: 答案 = 飞+龙.
普通: 答案 = 飞+水.
拔群: 无此情况.
普通: 尝试 飞.
无效: 无此情况.
很小: 答案 = 飞+电.
普通: 答案 = 飞+毒.
拔群: 答案 = 飞+虫.
拔群: 答案 = 飞+火.
很小: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 草+超.
拔群: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 虫.
拔群: 答案 = 虫+草.
普通: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 火.
无效: 无此情况.
很小: 答案 = 水+超.
普通: 答案 = 超.
拔群: 无此情况.
拔群: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 毒+草.
拔群: 答案 = 毒+虫.
拔群: 尝试 水.
无效: 无此情况.
很小: 答案 = 毒+水.
普通: 答案 = 毒.
拔群: 答案 = 毒+地.
普通: 尝试 飞.
无效: 无此情况.
很小: 尝试 普.
无效: 无此情况.
很小: 答案 = 飞+岩.
普通: 答案 = 电.
拔群: 无此情况.
普通: 尝试 地.
无效: 尝试 鬼.
无效: 答案 = 普+飞.
很小: 无此情况.
普通: 答案 = 飞+冰.
拔群: 无此情况.
很小: 无此情况.
普通: 尝试 电.
无效: 答案 = 地.
很小: 答案 = 龙.
普通: 答案 = 超+冰.
拔群: 答案 = 水.
拔群: 答案 = 火.
拔群: 尝试 火.
无效: 无此情况.
很小: 答案 = 格+水.
普通: 答案 = 格.
拔群: 答案 = 草.
拔群: 尝试 普.
无效: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 答案 = 地+岩.
普通: 答案 = 岩+水.
拔群: 无此情况.
普通: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 普.
拔群: 答案 = 水+冰.
拔群: 无此情况.
第二世代: 0.107 秒, 深度 = 4.
尝试 格.
无效: 尝试 地.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 鬼.
拔群: 答案 = 毒+鬼.
很小: 尝试 火.
无效: 无此情况.
很小: 尝试 草.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 答案 = 飞+火.
普通: 答案 = 飞+龙.
拔群: 无此情况.
普通: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+水.
普通: 答案 = 飞+水.
拔群: 无此情况.
拔群: 答案 = 水+超.
普通: 尝试 岩.
无效: 无此情况.
很小: 答案 = 毒+地.
普通: 尝试 地.
无效: 答案 = 飞+地.
很小: 无此情况.
普通: 答案 = 超.
拔群: 答案 = 毒.
拔群: 尝试 超.
无效: 无此情况.
很小: 答案 = 飞+超.
普通: 答案 = 飞+电.
拔群: 答案 = 飞+毒.
拔群: 尝试 虫.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+虫.
很小: 答案 = 格+虫.
普通: 答案 = 毒+虫.
拔群: 无此情况.
普通: 尝试 地.
无效: 答案 = 飞+草.
很小: 答案 = 虫.
普通: 答案 = 毒+草.
拔群: 无此情况.
拔群: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 草+超.
拔群: 答案 = 虫+草.
普通: 尝试 火.
无效: 无此情况.
很小: 尝试 电.
无效: 答案 = 地+水.
很小: 答案 = 龙.
普通: 尝试 草.
无效: 无此情况.
很小: 答案 = 火.
普通: 答案 = 水+龙.
拔群: 答案 = 水+电.
拔群: 尝试 飞.
无效: 无此情况.
很小: 答案 = 飞+岩.
普通: 答案 = 水.
拔群: 答案 = 格+水.
普通: 尝试 岩.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 地.
拔群: 答案 = 格.
普通: 尝试 飞.
无效: 无此情况.
很小: 答案 = 电.
普通: 答案 = 普+超.
拔群: 无此情况.
拔群: 尝试 鬼.
无效: 答案 = 普+飞.
很小: 答案 = 飞+恶.
普通: 答案 = 岩+虫.
拔群: 无此情况.
拔群: 尝试 普.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 飞+钢.
普通: 答案 = 虫+钢.
拔群: 无此情况.
普通: 尝试 地.
无效: 答案 = 飞+冰.
很小: 答案 = 草.
普通: 答案 = 超+冰.
拔群: 无此情况.
拔群: 无此情况.
拔群: 尝试 普.
无效: 无此情况.
很小: 尝试 虫.
无效: 无此情况.
很小: 尝试 电.
无效: 答案 = 地+钢.
很小: 答案 = 钢+电.
普通: 答案 = 岩+火.
拔群: 无此情况.
普通: 尝试 电.
无效: 答案 = 地+岩.
很小: 无此情况.
普通: 答案 = 岩.
拔群: 答案 = 岩+水.
拔群: 答案 = 岩+恶.
普通: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 鬼.
无效: 答案 = 普.
很小: 答案 = 恶.
普通: 答案 = 地+冰.
拔群: 无此情况.
拔群: 尝试 钢.
无效: 无此情况.
很小: 答案 = 火+恶.
普通: 答案 = 水+冰.
拔群: 答案 = 冰+恶.
拔群: 无此情况.
当前存在组合: 1.522 秒, 深度 = 5.
尝试 格.
无效: 尝试 鬼.
无效: 答案 = 普+鬼.
很小: 无此情况.
普通: 答案 = 鬼+恶.
拔群: 尝试 草.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+鬼.
很小: 尝试 毒.
无效: 无此情况.
很小: 答案 = 虫+鬼.
普通: 答案 = 鬼+草.
拔群: 无此情况.
普通: 答案 = 鬼+龙.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 鬼+钢.
普通: 答案 = 毒+鬼.
拔群: 答案 = 鬼+火.
普通: 尝试 钢.
无效: 无此情况.
很小: 答案 = 鬼+电.
普通: 尝试 超.
无效: 无此情况.
很小: 答案 = 鬼+超.
普通: 答案 = 鬼.
拔群: 答案 = 格+鬼.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 鬼+冰.
普通: 答案 = 鬼+妖.
拔群: 无此情况.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 地+鬼.
普通: 答案 = 鬼+水.
拔群: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 地.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 地+超.
拔群: 答案 = 毒+地.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 格+毒.
普通: 答案 = 格+超.
拔群: 答案 = 格+妖.
普通: 尝试 电.
无效: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 飞+地.
拔群: 答案 = 地+虫.
很小: 尝试 飞.
无效: 无此情况.
很小: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+电.
普通: 答案 = 电+超.
拔群: 答案 = 电+妖.
普通: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+龙.
普通: 答案 = 超+龙.
拔群: 答案 = 龙+妖.
拔群: 尝试 超.
无效: 无此情况.
很小: 答案 = 草+超.
普通: 答案 = 草+妖.
拔群: 答案 = 毒+草.
普通: 尝试 毒.
无效: 无此情况.
很小: 尝试 虫.
无效: 无此情况.
很小: 答案 = 毒.
普通: 答案 = 毒+超.
拔群: 无此情况.
普通: 尝试 地.
无效: 无此情况.
很小: 答案 = 格+虫.
普通: 答案 = 超.
拔群: 答案 = 毒+妖.
拔群: 尝试 虫.
无效: 无此情况.
很小: 答案 = 妖.
普通: 答案 = 超+妖.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+水.
普通: 答案 = 水+超.
拔群: 答案 = 水+妖.
拔群: 答案 = 格+飞.
拔群: 尝试 火.
无效: 无此情况.
很小: 尝试 地.
无效: 尝试 妖.
无效: 无此情况.
很小: 答案 = 飞+火.
普通: 答案 = 飞+水.
拔群: 答案 = 飞+龙.
很小: 无此情况.
普通: 无此情况.
拔群: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+火.
普通: 答案 = 火+超.
拔群: 无此情况.
普通: 尝试 钢.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+电.
很小: 答案 = 虫+水.
普通: 答案 = 虫+火.
拔群: 无此情况.
普通: 尝试 超.
无效: 无此情况.
很小: 答案 = 飞+超.
普通: 答案 = 飞.
拔群: 答案 = 飞+毒.
拔群: 答案 = 飞+妖.
拔群: 尝试 虫.
无效: 无此情况.
很小: 尝试 毒.
无效: 无此情况.
很小: 答案 = 毒+虫.
普通: 答案 = 飞+虫.
拔群: 答案 = 虫+妖.
普通: 尝试 地.
无效: 答案 = 飞+草.
很小: 答案 = 虫.
普通: 答案 = 虫+电.
拔群: 无此情况.
拔群: 尝试 毒.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 虫+超.
拔群: 答案 = 虫+草.
普通: 尝试 火.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 尝试 草.
无效: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 电+龙.
拔群: 答案 = 火+电.
普通: 尝试 地.
无效: 答案 = 飞+岩.
很小: 无此情况.
普通: 无此情况.
拔群: 答案 = 毒+岩.
拔群: 尝试 虫.
无效: 无此情况.
很小: 答案 = 岩+妖.
普通: 答案 = 水+电.
拔群: 答案 = 岩+超.
普通: 尝试 岩.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 答案 = 地+水.
普通: 答案 = 地+龙.
拔群: 无此情况.
普通: 尝试 电.
无效: 答案 = 地+火.
很小: 答案 = 龙.
普通: 答案 = 水+龙.
拔群: 答案 = 水.
拔群: 尝试 电.
无效: 无此情况.
很小: 答案 = 火+龙.
普通: 答案 = 火.
拔群: 答案 = 火+水.
拔群: 尝试 电.
无效: 无此情况.
很小: 答案 = 格+龙.
普通: 答案 = 格+火.
拔群: 答案 = 格+水.
普通: 尝试 毒.
无效: 无此情况.
很小: 尝试 岩.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 地+电.
普通: 答案 = 地.
拔群: 答案 = 格+地.
普通: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+毒.
普通: 答案 = 毒+恶.
拔群: 无此情况.
拔群: 答案 = 岩+虫.
普通: 尝试 地.
无效: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+飞.
普通: 答案 = 飞+恶.
拔群: 无此情况.
很小: 无此情况.
普通: 尝试 超.
无效: 答案 = 超+恶.
很小: 答案 = 普+超.
普通: 无此情况.
拔群: 答案 = 格.
拔群: 尝试 飞.
无效: 无此情况.
很小: 答案 = 电.
普通: 答案 = 格+电.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+妖.
普通: 答案 = 恶+妖.
拔群: 无此情况.
拔群: 尝试 妖.
无效: 无此情况.
很小: 答案 = 火+草.
普通: 答案 = 水+草.
拔群: 答案 = 草+龙.
拔群: 尝试 飞.
无效: 无此情况.
很小: 尝试 地.
无效: 答案 = 飞+钢.
很小: 无此情况.
普通: 无此情况.
拔群: 尝试 恶.
无效: 无此情况.
很小: 答案 = 钢+妖.
普通: 答案 = 毒+钢.
拔群: 答案 = 钢+超.
普通: 尝试 毒.
无效: 答案 = 虫+钢.
很小: 无此情况.
普通: 尝试 地.
无效: 答案 = 飞+冰.
很小: 无此情况.
普通: 答案 = 超+冰.
拔群: 无此情况.
拔群: 尝试 岩.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 草+电.
拔群: 答案 = 冰+妖.
拔群: 尝试 毒.
无效: 无此情况.
很小: 无此情况.
普通: 尝试 冰.
无效: 无此情况.
很小: 答案 = 虫+冰.
普通: 答案 = 虫+恶.
拔群: 答案 = 地+草.
拔群: 尝试 岩.
无效: 无此情况.
很小: 答案 = 格+草.
普通: 答案 = 草.
拔群: 无此情况.
拔群: 尝试 岩.
无效: 无此情况.
很小: 尝试 火.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 地+岩.
普通: 答案 = 格+岩.
拔群: 无此情况.
普通: 尝试 飞.
无效: 无此情况.
很小: 尝试 电.
无效: 无此情况.
很小: 答案 = 钢+龙.
普通: 答案 = 岩+钢.
拔群: 答案 = 钢+水.
普通: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 普+地.
拔群: 答案 = 地+恶.
拔群: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+格.
普通: 答案 = 格+恶.
拔群: 无此情况.
拔群: 尝试 电.
无效: 答案 = 地+钢.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 钢+电.
普通: 答案 = 钢+草.
拔群: 无此情况.
普通: 尝试 超.
无效: 答案 = 钢+恶.
很小: 答案 = 钢.
普通: 答案 = 格+钢.
拔群: 无此情况.
拔群: 无此情况.
普通: 尝试 鬼.
无效: 尝试 电.
无效: 无此情况.
很小: 尝试 飞.
无效: 无此情况.
很小: 答案 = 普+电.
普通: 答案 = 普+龙.
拔群: 答案 = 普+草.
普通: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 普.
拔群: 答案 = 普+恶.
拔群: 答案 = 普+水.
很小: 尝试 飞.
无效: 无此情况.
很小: 尝试 普.
无效: 无此情况.
很小: 答案 = 岩+恶.
普通: 答案 = 电+恶.
拔群: 无此情况.
普通: 尝试 草.
无效: 无此情况.
很小: 答案 = 龙+恶.
普通: 答案 = 恶.
拔群: 答案 = 水+恶.
拔群: 答案 = 草+恶.
普通: 尝试 草.
无效: 无此情况.
很小: 尝试 钢.
无效: 无此情况.
很小: 答案 = 钢+火.
普通: 答案 = 钢+冰.
拔群: 无此情况.
普通: 尝试 飞.
无效: 无此情况.
很小: 答案 = 岩+龙.
普通: 答案 = 岩+草.
拔群: 答案 = 格+冰.
拔群: 尝试 电.
无效: 答案 = 地+冰.
很小: 答案 = 岩+电.
普通: 答案 = 岩.
拔群: 答案 = 岩+水.
拔群: 无此情况.
拔群: 尝试 飞.
无效: 无此情况.
很小: 尝试 火.
无效: 无此情况.
很小: 答案 = 岩+火.
普通: 答案 = 岩+冰.
拔群: 答案 = 电+冰.
普通: 尝试 火.
无效: 无此情况.
很小: 尝试 虫.
无效: 无此情况.
很小: 答案 = 普+火.
普通: 答案 = 火+恶.
拔群: 无此情况.
普通: 尝试 电.
无效: 无此情况.
很小: 答案 = 冰+龙.
普通: 答案 = 火+冰.
拔群: 答案 = 水+冰.
拔群: 尝试 虫.
无效: 无此情况.
很小: 无此情况.
普通: 答案 = 冰.
拔群: 答案 = 冰+恶.
拔群: 答案 = 草+冰.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment