Skip to content

Commit 84cb97a

Browse files
authored
Pokopia Cloud Island Reset (#1155)
* Pokopia Cloud Island Reset Adding basic stack for Pokopia and cloud island reset program * Add Stop Condition Stop resetting using reset counter or stop button * Auto Detect Palette Town Remove user defined setting and automatically detect location * Fix Edge Case Handling Re-shuffle position on unintential Pokemon dialog
1 parent 3d2526d commit 84cb97a

20 files changed

+2534
-0
lines changed

SerialPrograms/Source/PanelLists.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "PokemonRSE/PokemonRSE_Panels.h"
2424
#include "PokemonSV/PokemonSV_Panels.h"
2525
#include "PokemonLZA/PokemonLZA_Panels.h"
26+
#include "PokemonPokopia/PokemonPokopia_Panels.h"
2627
#include "ZeldaTotK/ZeldaTotK_Panels.h"
2728
#include "PanelLists.h"
2829

@@ -56,6 +57,7 @@ ProgramSelect::ProgramSelect(QWidget& parent, PanelHolder& holder)
5657

5758
add(std::make_unique<NintendoSwitch::PokemonLZA::PanelListFactory>());
5859
add(std::make_unique<NintendoSwitch::PokemonFRLG::PanelListFactory>());
60+
add(std::make_unique<NintendoSwitch::PokemonPokopia::PanelListFactory>());
5961
if (PreloadSettings::instance().DEVELOPER_MODE){
6062
add(std::make_unique<NintendoSwitch::PokemonRSE::PanelListFactory>());
6163
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/* Button Detector
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include <iostream>
8+
#include "Kernels/Waterfill/Kernels_Waterfill_Types.h"
9+
#include "CommonFramework/GlobalSettingsPanel.h"
10+
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
11+
#include "CommonTools/Images/WaterfillUtilities.h"
12+
#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h"
13+
#include "PokemonPokopia_ButtonDetector.h"
14+
15+
16+
17+
namespace PokemonAutomation{
18+
namespace NintendoSwitch{
19+
namespace PokemonPokopia{
20+
21+
22+
23+
class ButtonMatcher : public ImageMatch::WaterfillTemplateMatcher{
24+
public:
25+
// image template matcher for buttons
26+
// - min_width: candidate image min width if video stream is 1080p
27+
// - min_height: candidate image min height if video stream is 1080p
28+
ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd);
29+
static const ButtonMatcher& A(){
30+
static ButtonMatcher matcher(ButtonType::ButtonA, 40, 40, 70);
31+
return matcher;
32+
}
33+
static const ButtonMatcher& DpadLeft(){
34+
static ButtonMatcher matcher(ButtonType::ButtonDpadLeft, 30, 30, 120);
35+
return matcher;
36+
}
37+
static const ButtonMatcher& DpadRight(){
38+
static ButtonMatcher matcher(ButtonType::ButtonDpadRight, 30, 30, 120);
39+
return matcher;
40+
}
41+
42+
virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override{
43+
size_t min_width = m_min_width * input_resolution.width / 1920;
44+
size_t min_height = m_min_height * input_resolution.height / 1080;
45+
46+
if (PreloadSettings::debug().IMAGE_TEMPLATE_MATCHING){
47+
const double stddev_sum = image_stats(image).stddev.sum();
48+
std::cout << "???? ButtonMatcher::check_image() ???? min size " << min_width << " x " << min_height
49+
<< " got " << image.width() << " x " << image.height() << " stddev_sum: " << stddev_sum << std::endl;
50+
}
51+
return image.width() >= min_width && image.height() >= min_height;
52+
};
53+
54+
size_t m_min_width;
55+
size_t m_min_height;
56+
double m_max_rmsd;
57+
};
58+
59+
60+
const char* template_path(ButtonType type){
61+
switch (type){
62+
case ButtonType::ButtonA:
63+
return "PokemonPokopia/ButtonA.png";
64+
case ButtonType::ButtonDpadLeft:
65+
return "PokemonPokopia/ButtonDpadLeft.png";
66+
case ButtonType::ButtonDpadRight:
67+
return "PokemonPokopia/ButtonDpadRight.png";
68+
default:
69+
return "";
70+
}
71+
}
72+
73+
const ButtonMatcher& get_button_matcher(ButtonType type){
74+
switch (type){
75+
case ButtonType::ButtonA:
76+
return ButtonMatcher::A();
77+
case ButtonType::ButtonDpadLeft:
78+
return ButtonMatcher::DpadLeft();
79+
case ButtonType::ButtonDpadRight:
80+
return ButtonMatcher::DpadRight();
81+
default:
82+
throw std::runtime_error("No corresponding ButtonMatcher for ButtonType");
83+
}
84+
}
85+
86+
ButtonMatcher::ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd)
87+
: WaterfillTemplateMatcher(template_path(type), Color(0xffc0c0c0), Color(0xffffffff), 500)
88+
, m_min_width(min_width)
89+
, m_min_height(min_height)
90+
, m_max_rmsd(max_rmsd)
91+
{}
92+
93+
94+
95+
ButtonDetector::ButtonDetector(
96+
Color color,
97+
ButtonType button_type,
98+
const ImageFloatBox& box,
99+
VideoOverlay* overlay
100+
)
101+
: m_button_type(button_type)
102+
, m_color(color)
103+
, m_matcher(get_button_matcher(button_type))
104+
, m_box(box)
105+
, m_overlay(overlay)
106+
{
107+
108+
}
109+
void ButtonDetector::make_overlays(VideoOverlaySet& items) const{
110+
items.add(m_color, m_box);
111+
}
112+
bool ButtonDetector::detect(const ImageViewRGB32& screen){
113+
114+
double screen_rel_size = (screen.height() / 1080.0);
115+
double screen_rel_size_2 = screen_rel_size * screen_rel_size;
116+
117+
double min_area_1080p = 500;
118+
size_t min_area = size_t(screen_rel_size_2 * min_area_1080p);
119+
120+
const std::vector<std::pair<uint32_t, uint32_t>> FILTERS = {
121+
{0xffc0c0c0, 0xffffffff} // RGB(192, 192, 192), RGB(255, 255, 255)
122+
};
123+
124+
bool found = match_template_by_waterfill(
125+
screen.size(),
126+
extract_box_reference(screen, m_box),
127+
m_matcher,
128+
FILTERS,
129+
{min_area, SIZE_MAX},
130+
m_matcher.m_max_rmsd,
131+
[&](Kernels::Waterfill::WaterfillObject& object) -> bool {
132+
m_last_detected = translate_to_parent(screen, m_box, object);
133+
return true;
134+
}
135+
);
136+
137+
if (m_overlay){
138+
if (found){
139+
m_last_detected_box.emplace(*m_overlay, m_last_detected, COLOR_GREEN);
140+
}else{
141+
m_last_detected_box.reset();
142+
}
143+
}
144+
145+
return found;
146+
}
147+
148+
149+
150+
}
151+
}
152+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/* Button Detector
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_PokemonPokopia_ButtonDetector_H
8+
#define PokemonAutomation_PokemonPokopia_ButtonDetector_H
9+
10+
#include <optional>
11+
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
12+
#include "CommonTools/VisualDetector.h"
13+
#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h"
14+
15+
namespace PokemonAutomation{
16+
class Logger;
17+
namespace NintendoSwitch{
18+
namespace PokemonPokopia{
19+
20+
21+
enum class ButtonType{
22+
ButtonA,
23+
// ButtonB,
24+
// ButtonX,
25+
// ButtonY,
26+
// ButtonL,
27+
// ButtonR,
28+
// ButtonPlus,
29+
// ButtonMinus,
30+
// ButtonRight,
31+
// RightStickUpDown,
32+
ButtonDpadLeft,
33+
ButtonDpadRight
34+
// ButtonDpadUp,
35+
// ButtonDpadDown,
36+
// ButtonDpadUpInterior, // Used to create button detector that detects the black triangle inside the DPAD_UP button
37+
// ButtonDpadDownInterior, // Used to create button detector that detects the black triangle inside the DPAD_DOWN button
38+
};
39+
40+
class ButtonMatcher;
41+
42+
class ButtonDetector : public StaticScreenDetector{
43+
public:
44+
ButtonDetector(
45+
Color color,
46+
ButtonType button_type,
47+
const ImageFloatBox& box,
48+
VideoOverlay* overlay = nullptr
49+
);
50+
virtual void make_overlays(VideoOverlaySet& items) const override;
51+
virtual bool detect(const ImageViewRGB32& screen) override;
52+
53+
virtual void reset_state() override { m_last_detected_box.reset(); }
54+
55+
ButtonType button_type() const { return m_button_type; }
56+
57+
private:
58+
ButtonType m_button_type;
59+
Color m_color;
60+
const ButtonMatcher& m_matcher;
61+
ImageFloatBox m_box;
62+
VideoOverlay* m_overlay;
63+
64+
ImageFloatBox m_last_detected;
65+
std::optional<OverlayBoxScope> m_last_detected_box;
66+
};
67+
class ButtonWatcher : public DetectorToFinder<ButtonDetector>{
68+
public:
69+
ButtonWatcher(
70+
Color color,
71+
ButtonType button_type,
72+
const ImageFloatBox& box,
73+
VideoOverlay* overlay = nullptr,
74+
std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250)
75+
)
76+
: DetectorToFinder("ButtonWatcher", hold_duration, color, button_type, box, overlay)
77+
{}
78+
};
79+
class ButtonGoneWatcher : public DetectorToFinder<ButtonDetector>{
80+
public:
81+
ButtonGoneWatcher(
82+
Color color,
83+
ButtonType button_type,
84+
const ImageFloatBox& box,
85+
VideoOverlay* overlay = nullptr,
86+
std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250)
87+
)
88+
: DetectorToFinder("ButtonGoneWatcher", FinderType::GONE, hold_duration, color, button_type, box, overlay)
89+
{}
90+
};
91+
92+
93+
94+
95+
}
96+
}
97+
}
98+
#endif
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* Moves Detection
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "Common/Cpp/Exceptions.h"
8+
#include "Kernels/Waterfill/Kernels_Waterfill_Types.h"
9+
#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h"
10+
#include "CommonTools/Images/WaterfillUtilities.h"
11+
#include "PokemonPokopia_MovesDetection.h"
12+
13+
namespace PokemonAutomation{
14+
namespace NintendoSwitch{
15+
namespace PokemonPokopia{
16+
17+
18+
19+
OverworldDetector::OverworldDetector(
20+
Color color,
21+
VideoOverlay* overlay
22+
)
23+
: m_color(color)
24+
, m_overlay(overlay)
25+
{}
26+
void OverworldDetector::make_overlays(VideoOverlaySet& items) const{
27+
items.add(m_color, MOVES_LEFT_ARROW_BOX);
28+
items.add(m_color, MOVES_RIGHT_ARROW_BOX);
29+
}
30+
bool OverworldDetector::detect(const ImageViewRGB32& screen){
31+
ButtonDetector moves_left_detector(m_color, ButtonType::ButtonDpadLeft, MOVES_LEFT_ARROW_BOX, m_overlay);
32+
ButtonDetector moves_right_detector(m_color, ButtonType::ButtonDpadRight, MOVES_RIGHT_ARROW_BOX, m_overlay);
33+
34+
bool found = moves_left_detector.detect(screen) && moves_right_detector.detect(screen);
35+
36+
return found;
37+
}
38+
39+
40+
41+
}
42+
}
43+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* Moves Detection
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_PokemonPokopia_MovesDetection_H
8+
#define PokemonAutomation_PokemonPokopia_MovesDetection_H
9+
10+
#include <optional>
11+
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
12+
#include "CommonTools/VisualDetector.h"
13+
#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h"
14+
#include "PokemonPokopia/Inference/PokemonPokopia_ButtonDetector.h"
15+
16+
namespace PokemonAutomation{
17+
class Logger;
18+
namespace NintendoSwitch{
19+
namespace PokemonPokopia{
20+
21+
const ImageFloatBox MOVES_LEFT_ARROW_BOX{0.806500, 0.935000, 0.025000, 0.045000};
22+
const ImageFloatBox MOVES_RIGHT_ARROW_BOX{0.960600, 0.935000, 0.025000, 0.045000};
23+
24+
25+
class OverworldDetector : public StaticScreenDetector{
26+
public:
27+
OverworldDetector(
28+
Color color,
29+
VideoOverlay* overlay = nullptr
30+
);
31+
virtual void make_overlays(VideoOverlaySet& items) const override;
32+
virtual bool detect(const ImageViewRGB32& screen) override;
33+
34+
virtual void reset_state() override { m_last_detected_box.reset(); }
35+
36+
private:
37+
Color m_color;
38+
VideoOverlay* m_overlay;
39+
40+
ImageFloatBox m_last_detected;
41+
std::optional<OverlayBoxScope> m_last_detected_box;
42+
};
43+
class OverworldWatcher : public DetectorToFinder<OverworldDetector>{
44+
public:
45+
OverworldWatcher(
46+
Color color,
47+
VideoOverlay* overlay = nullptr,
48+
std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250)
49+
)
50+
: DetectorToFinder("OverworldWatcher", hold_duration, color, overlay)
51+
{}
52+
};
53+
class OverworldGoneWatcher : public DetectorToFinder<OverworldDetector>{
54+
public:
55+
OverworldGoneWatcher(
56+
Color color,
57+
VideoOverlay* overlay = nullptr,
58+
std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250)
59+
)
60+
: DetectorToFinder("OverworldGoneWatcher", FinderType::GONE, hold_duration, color, overlay)
61+
{}
62+
};
63+
64+
65+
66+
}
67+
}
68+
}
69+
#endif

0 commit comments

Comments
 (0)