@@ -254,69 +254,115 @@ std::set<std::string> BattleMenuReader::read_opponent(
254254 return result;
255255}
256256std::set<std::string> BattleMenuReader::read_opponent_in_summary (Logger& logger, const ImageViewRGB32& screen) const {
257- ImageViewRGB32 name = extract_box_reference (screen, m_summary_opponent_name);
258-
259- // We can use a weaker threshold here since we are cross-checking with the type.
260- std::set<std::string> slugs = read_pokemon_name (logger, m_language, name, -1.0 );
261-
262- ImageViewRGB32 types = extract_box_reference (screen, m_summary_opponent_types);
263- std::multimap<double , std::pair<PokemonType, ImagePixelBox>> candidates = find_symbols (types, 0.2 );
257+ // Start by reading the types.
258+ PokemonType type0, type1;
259+ {
260+ ImageViewRGB32 types = extract_box_reference (screen, m_summary_opponent_types);
261+ std::multimap<double , std::pair<PokemonType, ImagePixelBox>> candidates = find_symbols (types, 0.2 );
264262
265- std::string type_str = " Type Read Result:\n " ;
266- for (const auto & item : candidates){
267- type_str += " " + get_type_slug (item.second .first ) + " : " + tostr_default (item.first ) + " \n " ;
263+ std::string type_str = " Type Read Result:\n " ;
264+ for (const auto & item : candidates){
265+ type_str += " " + get_type_slug (item.second .first ) + " : " + tostr_default (item.first ) + " \n " ;
266+ }
267+ logger.log (type_str);
268+
269+ type0 = PokemonType::NONE;
270+ type1 = PokemonType::NONE;
271+ {
272+ auto iter = candidates.begin ();
273+ if (iter != candidates.end ()){
274+ type0 = iter->second .first ;
275+ ++iter;
276+ }
277+ if (iter != candidates.end ()){
278+ type1 = iter->second .first ;
279+ ++iter;
280+ }
281+ }
268282 }
269- logger.log (type_str);
270283
271- PokemonType type0 = PokemonType::NONE;
272- PokemonType type1 = PokemonType::NONE;
273- {
274- auto iter = candidates.begin ();
275- if (iter != candidates.end ()){
276- type0 = iter->second .first ;
277- ++iter;
284+ // Compile a list of all possible mons that match the type.
285+ std::set<std::string> allowed_slugs;
286+ for (const auto & item : maxlair_slugs ()){
287+ const MaxLairMon& mon = get_maxlair_mon (item.first );
288+ if ((type0 == mon.type [0 ] && type1 == mon.type [1 ]) ||
289+ (type0 == mon.type [1 ] && type1 == mon.type [0 ])
290+ ){
291+ allowed_slugs.insert (item.first );
278292 }
279- if (iter != candidates.end ()){
280- type1 = iter->second .first ;
281- ++iter;
293+ }
294+
295+ // Special case for stunfisk-galar which changes types.
296+ if (type1 == PokemonType::NONE){
297+ switch (type0){
298+ case PokemonType::ELECTRIC:
299+ case PokemonType::GRASS:
300+ case PokemonType::FAIRY:
301+ case PokemonType::PSYCHIC:
302+ allowed_slugs.insert (" stunfisk-galar" );
303+ break ;
304+ default :;
282305 }
283306 }
284307
285- // cout << get_type_slug(type0) << endl;
286- // cout << get_type_slug(type1) << endl;
308+ if (allowed_slugs.size () == 1 ){
309+ return allowed_slugs;
310+ }
311+
312+
313+ // Now we read the name.
314+ std::set<std::string> name_slugs;
315+ {
316+ ImageViewRGB32 name = extract_box_reference (screen, m_summary_opponent_name);
287317
288- for (auto iter = slugs.begin (); iter != slugs.end ();){
289- const MaxLairMon& mon = get_maxlair_mon (*iter);
290- // cout << mon.species << endl;
291- // cout << get_type_slug(mon.type[0]) << endl;
292- // cout << get_type_slug(mon.type[1]) << endl;
293- if ((type0 == mon.type [0 ] && type1 == mon.type [1 ]) || (type0 == mon.type [1 ] && type1 == mon.type [0 ])){
294- ++iter;
295- }else {
296- iter = slugs.erase (iter);
318+ // We can use a weaker threshold here since we are cross-checking with the type.
319+ name_slugs = read_pokemon_name (logger, m_language, name, -1.0 );
320+ }
321+
322+ // See if there's anything in common between the slugs that match the type
323+ // and the slugs that match the OCR'ed name.
324+ std::set<std::string> common_slugs;
325+ for (const std::string& slug : name_slugs){
326+ if (allowed_slugs.find (slug) != allowed_slugs.end ()){
327+ common_slugs.insert (slug);
297328 }
298329 }
299330
300- if (slugs.size () == 1 ){
301- logger.log (" Disambiguation succeeded: " + *slugs.begin (), COLOR_BLUE);
302- return slugs;
331+ // for (const auto& slug : allowed_slugs){
332+ // cout << "allowed_slugs = " << slug << endl;
333+ // }
334+ // for (const auto& slug : name_slugs){
335+ // cout << "name_slugs = " << slug << endl;
336+ // }
337+
338+ if (common_slugs.size () == 1 ){
339+ logger.log (" Disambiguation succeeded: " + *common_slugs.begin (), COLOR_BLUE);
340+ return common_slugs;
303341 }
304342
305- if (slugs.empty ()){
306- logger.log (" Disambiguation failed. No results." , COLOR_RED);
307- }else {
308- logger.log (" Disambiguation failed. Still have multiple results: " + set_to_str (slugs), COLOR_RED);
343+
344+ // Special case: Korean Clefairy
345+ // Reason: Korean OCR cannot read the character: 삐
346+ if (m_language == Language::Korean &&
347+ name_slugs.empty () &&
348+ type0 == PokemonType::FAIRY &&
349+ type1 == PokemonType::NONE
350+ ){
351+ logger.log (" Known case that cannot be read: Korean Clefairy" , COLOR_RED);
352+ return {" clefairy" };
309353 }
310354
355+
356+
311357 static std::set<std::string> KNOWN_BAD_SLUGS{
312358 " basculin-blue-striped" ,
313359 " basculin-red-striped" ,
314360 " lycanroc-midday" ,
315361 " lycanroc-midnight" ,
316- " stunfisk-galar" , // After using terrain pulse.
362+ // "stunfisk-galar", // After using terrain pulse.
317363 };
318364 bool error = true ;
319- for (const std::string& slug : slugs ){
365+ for (const std::string& slug : common_slugs ){
320366 auto iter = KNOWN_BAD_SLUGS.find (slug);
321367 if (iter != KNOWN_BAD_SLUGS.end ()){
322368 error = false ;
@@ -325,23 +371,12 @@ std::set<std::string> BattleMenuReader::read_opponent_in_summary(Logger& logger,
325371 }
326372 }
327373
328- // Special case: Korean Clefairy.
329- // Reason: Korean OCR cannot read the character: 삐
330- if (m_language == Language::Korean &&
331- slugs.empty () &&
332- type0 == PokemonType::FAIRY &&
333- type1 == PokemonType::NONE
334- ){
335- logger.log (" Known case that cannot be read: Korean Clefairy" , COLOR_RED);
336- return {" clefairy" };
337- }
338-
339374 // At this point we're out of options.
340375 if (error){
341376 dump_image (logger, MODULE_NAME, " DisambiguateBoss" , screen);
342377 }
343378
344- return slugs ;
379+ return common_slugs ;
345380}
346381std::string BattleMenuReader::read_own_mon (Logger& logger, const ImageViewRGB32& screen) const {
347382 return read_pokemon_name_sprite (
0 commit comments