Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3d9bf94
Pokemon navigation: story steps, one table vocabulary for FRLG and BDSP
dayfine Nov 1, 2026
c8a6554
Merge nav/story-steps (3d9bf943d: shared story steps) into bdsp/story…
dayfine Nov 1, 2026
474c2a0
Pokemon navigation: one retry policy for every story segment
dayfine Nov 1, 2026
d2b814b
Merge nav/story-steps (474c2a013: one retry policy) into bdsp/story-s…
dayfine Nov 1, 2026
c0859dd
BDSP AutoStory: 00.04b as story steps, and the shared retry options
dayfine Nov 1, 2026
f140830
Pokemon navigation: story executors hear of each attempt (begin_attempt)
dayfine Nov 1, 2026
9ddcc67
Merge nav/story-steps (f1408301a: begin_attempt) into bdsp/story-steps
dayfine Nov 1, 2026
d700381
Merge bdsp/mvp-v3 (b08c41884: 00.04b/c/d) into bdsp/story-steps
dayfine Nov 1, 2026
5da607b
BDSP AutoStory: segments 00 and 01 as one story-step table, run end t…
dayfine Nov 1, 2026
79cc161
BDSP AutoStory: initialize AutoStoryOptions::policy for its positiona…
dayfine Nov 1, 2026
03298de
Pokemon navigation: a shared checks level for story steps (Thorough o…
dayfine Nov 1, 2026
ef5a12b
Merge nav/story-steps (03298de07: checks level) into bdsp/story-steps
dayfine Nov 1, 2026
c1e9a37
BDSP AutoStory: hand the shared checks option to the story executor
dayfine Nov 1, 2026
daf7b8f
Pokemon navigation: story steps take the game's language, and never n…
dayfine Nov 1, 2026
c7a2136
Pokemon navigation: the route log lines, shared by the games' walkers
dayfine Nov 1, 2026
9268fe9
Merge nav/story-steps (daf7b8faf: game language) into bdsp/story-steps
dayfine Nov 1, 2026
7ac4356
BDSP AutoStory: no story step needs the game's language
dayfine Nov 1, 2026
716bb5a
Pokemon navigation: route log tests as small tables, for the function…
dayfine Nov 1, 2026
abd0fac
Merge nav/shared (716bb5ae0, #114) into bdsp/story-steps
dayfine Nov 1, 2026
a13d5fb
BDSP AutoStory: log routes through the shared route log lines
dayfine Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@



UnitTestDatabase make_UNIT_TESTS_ALL(){

Check warning on line 53 in SerialPrograms/Source/ComputerPrograms/ComputerPrograms_UnitTestRunner.cpp

View workflow job for this annotation

GitHub Actions / code-health

Code health (advisory)

PokemonAutomation::ComputerPrograms::make_UNIT_TESTS_ALL(): function_lines=37 (advisory above 25, limit 50)
UnitTestDatabase ret;

add_tests_QtEventThreadPool(ret, GlobalThreadPools::computation_normal());
Expand All @@ -67,8 +67,10 @@
Kernels::add_tests(ret);
Pokemon::add_tests_LegPlanner(ret);
Pokemon::add_tests_MapData(ret);
Pokemon::add_tests_RouteLog(ret);
Pokemon::add_tests_StoryEvents(ret);
Pokemon::add_tests_StorySegments(ret);
Pokemon::add_tests_StorySteps(ret);
NintendoSwitch::add_tests_CheckOnlineDetector(ret);
NintendoSwitch::add_tests_FailedToConnectDetector(ret);
NintendoSwitch::add_tests_UpdatePopupDetector(ret);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ namespace Pokemon{

void add_tests_LegPlanner(UnitTestDatabase& database);
void add_tests_MapData(UnitTestDatabase& database);
void add_tests_RouteLog(UnitTestDatabase& database);
void add_tests_StoryEvents(UnitTestDatabase& database);
void add_tests_StorySegments(UnitTestDatabase& database);
void add_tests_StorySteps(UnitTestDatabase& database);

// (name, JSON text) of each map in Pokemon/Navigation/TestMaps/, built into
// the program by pa_embed_text_files() (cmake/EmbedTextFiles.cmake).
Expand Down
98 changes: 98 additions & 0 deletions SerialPrograms/Source/Pokemon/Navigation/Pokemon_RouteLog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* Route Log
*
* From: https://github.com/PokemonAutomation/
*
*/

#include <format>
#include "Pokemon_RouteLog.h"

namespace PokemonAutomation{
namespace Pokemon{


std::string to_string(const RouteTile& tile){
return tile.map + " " + to_string(tile.pos);
}

std::string describe(const std::vector<RouteTile>& tiles){
if (tiles.empty()){
return "an unknown tile";
}
std::string out;
for (const RouteTile& tile : tiles){
out += (out.empty() ? "" : ", ") + to_string(tile);
}
return out;
}

std::string to_string(const RouteLogLeg& leg){
const std::string direction = direction_name(leg.direction);
switch (leg.action){
case RouteLegAction::SURF:
return "surf " + direction;
case RouteLegAction::FACE:
return "face " + direction;
case RouteLegAction::WALK:
break;
}
const char* end = leg.end == RouteLegEnd::WALL ? " (to wall)" : leg.end == RouteLegEnd::WARP ? " (warp)" : " (open)";
return direction + " " + std::to_string(leg.tiles) + end;
}

const char* basis_name(EndBasis basis){
switch (basis){
case EndBasis::WALKED:
return "walked";
case EndBasis::ASSUMED:
return "assumed";
case EndBasis::UNKNOWN:
return "unknown";
}
return "?";
}


std::string route_plan_line(const std::string& label, const std::vector<RouteTile>& from, const std::vector<PlannedRouteLeg>& legs){
std::string text = label + ": plan from " + describe(from) + ":";
for (const PlannedRouteLeg& leg : legs){
text += "\n " + to_string(leg.leg) + " to " + describe(leg.after);
}
return text;
}

std::string route_leg_line(size_t number, size_t count, const PlannedRouteLeg& leg){
return std::format("Leg {}/{}: {} to {}", number, count, to_string(leg.leg), describe(leg.after));
}

std::string route_leg_end_line(
const std::string& label, const RouteLogLeg& leg,
const std::vector<RouteTile>& at, EndBasis basis, const std::string& why
){
const std::string how = why.empty() ? basis_name(basis) : std::string(basis_name(basis)) + ": " + why;
return std::format("{}: {}: ended at {} ({}).", label, to_string(leg), describe(at), how);
}

std::string route_replan_line(
const std::string& label, const RouteLogLeg& leg,
const std::string& what, const std::vector<RouteTile>& at
){
return std::format("{}: {}: {}, at {}; planning again.", label, to_string(leg), what, describe(at));
}

std::string route_found_line(const std::string& label, const std::vector<RouteTile>& at, size_t holds){
return std::format("{}: found again at {}, after {} hold(s).", label, describe(at), holds);
}

std::string route_trainer_line(const std::string& label, const std::string& who, const std::vector<RouteTile>& at){
return label + ": " + who + " stopped us about " + describe(at) + ".";
}

std::string route_arrived_line(const std::string& label, const std::vector<RouteTile>& at){
return label + ": arrived at " + describe(at) + ".";
}



}
}
120 changes: 120 additions & 0 deletions SerialPrograms/Source/Pokemon/Navigation/Pokemon_RouteLog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* Route Log
*
* From: https://github.com/PokemonAutomation/
*
* The log lines a route walk writes, shared by the games' walkers so that
* every game's log reads the same and devtools/maps can draw any run's
* routes from it. These are BDSP AutoStory's route lines, lifted from
* PokemonBDSP_AutoStory_RouteWalk.cpp, with what the other games need:
*
* [Route] To the grass: plan from Route 202 (15, 25), Route 202 (16, 25):
* east 15 (to wall) to Route 202 (23, 25), Route 202 (30, 26)
* north 5 (to wall) to Route 202 (23, 24)
* [Route] Leg 1/2: east 15 (to wall) to Route 202 (23, 25), Route 202 (30, 26)
* [Route] To the grass: east 15 (to wall): ended at Route 202 (23, 25) (walked).
* [Route] To the grass: north 5 (to wall): stopped early after about 2 tiles, at Route 202 (23, 23); planning again.
* [Route] To the grass: found again at Route 202 (22, 24), after 2 holds.
* [Route] To the grass: arrived at Route 202 (23, 24).
*
* A position is a set of tiles: BDSP plans from every tile the player may
* be on, FRLG from the one it is on. A leg's end says how it is known:
* walked (as planned, or seen), assumed (taken to have ended as planned
* after something interrupted it), or unknown.
*
* The functions return a line without the "[Route] " tag, which
* ROUTE_LOG_TAG holds; the caller logs it.
*
*/

#ifndef PokemonAutomation_Pokemon_RouteLog_H
#define PokemonAutomation_Pokemon_RouteLog_H

#include <cstddef>
#include <string>
#include <vector>
#include "Pokemon_Grid.h"

namespace PokemonAutomation{
namespace Pokemon{


inline constexpr const char* ROUTE_LOG_TAG = "[Route] ";

// A tile of a named map.
struct RouteTile{
std::string map;
TilePos pos;
};
// "Route 202 (23, 25)".
std::string to_string(const RouteTile& tile);
// The tiles, comma-separated; "an unknown tile" for none.
std::string describe(const std::vector<RouteTile>& tiles);


enum class RouteLegAction{
WALK,
SURF,
FACE,
};

// How a leg ends: at a wall, on a warp, or where it is timed to.
enum class RouteLegEnd{
OPEN,
WALL,
WARP,
};

struct RouteLogLeg{
RouteLegAction action = RouteLegAction::WALK;
Direction direction = Direction::NORTH;
size_t tiles = 0;
RouteLegEnd end = RouteLegEnd::OPEN;
};
// "east 15 (to wall)", "south 4 (open)", "north 1 (warp)", "surf east",
// "face west".
std::string to_string(const RouteLogLeg& leg);

// A planned leg and the tiles it may end on.
struct PlannedRouteLeg{
RouteLogLeg leg;
std::vector<RouteTile> after;
};

// How the end of a walked leg is known.
enum class EndBasis{
WALKED, // walked as planned, or seen
ASSUMED, // taken to have ended as planned after an interrupt
UNKNOWN, // stopped somewhere on the way
};
const char* basis_name(EndBasis basis);


// "<label>: plan from <tiles>:", then a line per leg.
std::string route_plan_line(const std::string& label, const std::vector<RouteTile>& from, const std::vector<PlannedRouteLeg>& legs);
// "Leg <number>/<count>: <leg> to <tiles>", as the leg starts.
std::string route_leg_line(size_t number, size_t count, const PlannedRouteLeg& leg);
// "<label>: <leg>: ended at <tiles> (<basis>).", or "(<basis>: <why>)".
std::string route_leg_end_line(
const std::string& label, const RouteLogLeg& leg,
const std::vector<RouteTile>& at, EndBasis basis, const std::string& why
);
// "<label>: <leg>: <what>, at <tiles>; planning again.": the leg stopped
// short, where the player was seen to be, and the route is planned again
// from there.
std::string route_replan_line(
const std::string& label, const RouteLogLeg& leg,
const std::string& what, const std::vector<RouteTile>& at
);
// "<label>: found again at <tiles>, after <holds> hold(s).": after a stop
// where the player wasn't seen, holds to walls found them.
std::string route_found_line(const std::string& label, const std::vector<RouteTile>& at, size_t holds);
// "<label>: <who> stopped us about <tiles>."
std::string route_trainer_line(const std::string& label, const std::string& who, const std::vector<RouteTile>& at);
// "<label>: arrived at <tiles>."
std::string route_arrived_line(const std::string& label, const std::vector<RouteTile>& at);



}
}
#endif
Loading
Loading