#include "scripts.h" #include #include "logging.h" ScriptTerror::ScriptTerror(Director &d) : Dispatch(d) { BUGZ_LOG(warning) << "ScriptTerror()"; init(); } ScriptTerror::~ScriptTerror() { BUGZ_LOG(warning) << "~ScriptTerror()"; } void ScriptTerror::init(void) { BUGZ_LOG(fatal) << "ScriptTerror::init()"; move = std::make_shared(director); md = static_cast(&(*move)); // setup notify functions for results/completion. md->setNotify([this]() { this->move_notify(); }); input = std::make_shared(director); id = static_cast(&(*input)); id->prompt = "Number of loops: "; id->max_length = 4; id->numeric = true; id->setNotify([this]() { this->input_notify(); }); trader = std::make_shared(director); td = static_cast(&(*trader)); td->setNotify([this]() { this->trade_notify(); }); BUGZ_LOG(fatal) << "ScriptTerror::init() completed."; } void ScriptTerror::activate(void) { BUGZ_LOG(warning) << "ScriptTerror::activate()"; // Need: InputDispatch, MoveDispatch, ScriptTrader // Save the trade_end_empty setting, and set to Y if (director.galaxy.config.contains("trade_end_empty")) { old_trade_end_empty = director.galaxy.config["trade_end_empty"]; } else { old_trade_end_empty = "Y"; } director.galaxy.config["trade_end_empty"] = "Y"; // Step 0: Get ship information / # of holds max_loops = loops = -1; to_server("I"); // Step 1: Get number of loops of terror // director.chain = input; // input->activate(); // Step 2: Look for closest trades, try ScriptTrade until none < some // level. Step 3: Move on, unless out of loops (or low on turns) // deactivate(); } void ScriptTerror::deactivate(void) { BUGZ_LOG(warning) << "ScriptTerror::deactivate()"; // restore the original value. director.galaxy.config["trade_end_empty"] = old_trade_end_empty; notify(); } void ScriptTerror::input_notify(void) { if (id->input.empty()) { deactivate(); return; } if (id->aborted) { deactivate(); return; } max_loops = sstoi(id->input, -1); if (max_loops == -1) { deactivate(); return; } id->input.clear(); BUGZ_LOG(warning) << "Loops of terror: " << max_loops; loops = max_loops; // find nearest int stop_percent; if (director.galaxy.config.contains("stop_percent")) { stop_percent = director.galaxy.config["stop_percent"].get(); } else { stop_percent = 25; director.galaxy.config["stop_percent"] = stop_percent; } ppt = director.galaxy.find_closest_trade(director.current_sector, 3, stop_percent); if (ppt.type == 0) { to_client("No trades found! You've burnt the galaxy!\n\r"); deactivate(); return; } // ok, step 2: move! // md->setNotify([this]() { this->proxy_deactivate(); }); if (director.current_sector != ppt.s1) { BUGZ_LOG(fatal) << "Moving to: " << ppt.s1; md->move_to = ppt.s1; director.chain = move; director.chain->activate(); return; } else { // We're already there! to_client("Ok! Get trading!\n\r"); td->port[0] = ppt.s1; td->port[1] = ppt.s2; td->trades = ppt.trades; td->type = ppt.type; director.chain = trader; director.chain->activate(); return; } } void ScriptTerror::move_notify(void) { BUGZ_LOG(fatal) << "move_notify()"; if (md->aborted) { to_client("Move cancel.\n\r"); deactivate(); return; } // Check for success, and start trading! if (md->success) { to_client("We're here, get trading!\n\r"); td->port[0] = ppt.s1; td->port[1] = ppt.s2; td->trades = ppt.trades; td->type = ppt.type; director.chain = trader; director.chain->activate(); return; } else { std::string message = "Move FAILED. " + md->why_failed + "\n\r"; // to_client("Move FAILED.\n\r"); to_client(message); deactivate(); } } void ScriptTerror::server_prompt(const std::string &prompt) { if ((loops == -1) && (max_loops == -1)) { if (at_command_prompt(prompt)) { // Step 1: Get number of loops of terror director.chain = input; input->activate(); return; } } } void ScriptTerror::trade_notify(void) { // Done trading -- maybe! :P if (td->aborted) { to_client("Trade cancel.\n\r"); deactivate(); return; } if (td->success) { // success! // find nearest int stop_percent; if (director.galaxy.config.contains("stop_percent")) { stop_percent = director.galaxy.config["stop_percent"].get(); } else { stop_percent = 25; director.galaxy.config["stop_percent"] = stop_percent; } ppt = director.galaxy.find_closest_trade(director.current_sector, 3, stop_percent); if (ppt.type == 0) { to_client("No trades found! You've burnt the galaxy!\n\r"); deactivate(); return; } if ((director.current_sector == ppt.s1) || (director.current_sector == ppt.s2)) { // We're still here... BUGZ_LOG(fatal) << "Trade it again, Sam."; to_client("Keep trading.\n\r"); td->port[0] = ppt.s1; td->port[1] = ppt.s2; td->trades = ppt.trades; td->type = ppt.type; director.chain = trader; director.chain->activate(); return; } // Ok, this isn't a local trade. if (loops == 0) { to_client("We're done terrorizing, for now...\n\r"); deactivate(); return; } --loops; // Move to our next target BUGZ_LOG(fatal) << "Moving to: " << ppt.s1; md->move_to = ppt.s1; director.chain = move; director.chain->activate(); return; } else { std::string message = "Trade done: " + td->why_failed + "\n\r"; to_client(message); } // to_client("Ok, trade is done.\n\r"); deactivate(); } ScriptVoyager::ScriptVoyager(Director &d) : Dispatch(d) { BUGZ_LOG(warning) << "ScriptVoyager()"; init(); } ScriptVoyager::~ScriptVoyager() { BUGZ_LOG(warning) << "~ScriptVoyager()"; } void ScriptVoyager::init(void) { move = std::make_shared(director); md = static_cast(&(*move)); md->setNotify([this]() { this->move_notify(); }); input = std::make_shared(director); id = static_cast(&(*input)); id->prompt = "Number of loops/tries: "; id->max_length = 5; id->numeric = true; id->setNotify([this]() { this->input_notify(); }); } void ScriptVoyager::activate(void) { director.chain = input; input->activate(); return; } void ScriptVoyager::deactivate(void) { BUGZ_LOG(warning) << "ScriptVoyager::deactivate()"; notify(); } void ScriptVoyager::move_notify(void) { if (md->aborted) { deactivate(); return; } if (md->success) { // Great! next(); return; } else { std::string message = "No safe moves. " + md->why_failed + "\n\r"; to_client(message); deactivate(); } } void ScriptVoyager::input_notify(void) { if (id->input.empty() || id->aborted) { to_client("Ok, maybe later then.\n\r"); deactivate(); return; } loops = sstoi(id->input, -1); if (loops == -1) { to_client("I'm sorry, WHAT?\n\r"); deactivate(); } id->input.clear(); BUGZ_LOG(warning) << "Voyager loops: " << loops; next(); } void ScriptVoyager::next(void) { if (loops == 0) { // ok, stop here. to_client("The voyage ends here, for now.\n\r"); deactivate(); return; } --loops; sector_type s = director.galaxy.find_nearest_unexplored(director.current_sector); if (s == 0) { to_client("I don't see anything else to explorer.\n\r"); BUGZ_LOG(warning) << "find_nearest_unexplored returned 0"; deactivate(); } BUGZ_LOG(warning) << "Next stop: " << s; md->move_to = s; director.chain = move; director.chain->activate(); } // SL: [###### DANGER! You have marked sector 740 to be avoided!] // SP: [Do you really want to warp there? (Y/N) ] void ScriptVoyager::server_prompt(const std::string &prompt) {} ScriptExplore::ScriptExplore(Director &d) : Dispatch(d) { BUGZ_LOG(warning) << "ScriptExplore()"; init(); } ScriptExplore::~ScriptExplore() { BUGZ_LOG(warning) << "~ScriptExplore()"; } void ScriptExplore::init() { move = std::make_shared(director); md = static_cast(&(*move)); md->setNotify([this]() { this->move_notify(); }); input = std::make_shared(director); id = static_cast(&(*input)); id->prompt = "Number of sectors to explore: "; id->max_length = 5; id->numeric = true; id->setNotify([this]() { this->input_notify(); }); state = 0; target = 0; if(!director.galaxy.config.contains("prefer_ports")) { director.galaxy.config["prefer_ports"] = "Y"; prefer_ports = true; } else { prefer_ports = json_str(director.galaxy.config["prefer_ports"]) == "Y"; } if(!director.galaxy.meta["help"].contains("prefer_ports")) { director.galaxy.meta["help"]["prefer_ports"] = "Explorer prefers to find ports."; } BUGZ_LOG(warning) << "Prefer Ports: " + prefer_ports; } void ScriptExplore::activate() { us = director.chain; state = 1; to_server("I"); /* director.chain = input; input->activate(); if(director.galaxy.meta["ship"]) { if(!director.galaxy.meta["ship"]["scanner"]) { to_client("\n\rIt appears your ship doesn't have a long range scanner.\n\r"); deactivate(); } } state = 1; return; */ } void ScriptExplore::deactivate() { BUGZ_LOG(warning) << "ScriptExplore::deactivate()"; us.reset(); notify(); } void ScriptExplore::move_notify() { director.chain = us; if (md->aborted) { deactivate(); return; } if (md->success) { to_server("SD"); state = 3; return; } else { if (unknown_warps.size() != 0) { BUGZ_LOG(warning) << "Seeking previous unexplored (Unsafe Dest.)"; state = 4; next(); target = unknown_warps.top(); unknown_warps.pop(); std::string message = "UNSAFE DESTINATION"; std::string indenter = " "; ANSIColor alert(COLOR::WHITE, COLOR::RED, ATTR::BOLD); to_client(indenter + alert() + message + reset() + "\n\r"); } else { std::string message = "Move failed: " + md->why_failed + "\n\r"; //to_client("No safe moves.\n\r"); BUGZ_LOG(warning) << message; to_client(message); deactivate(); } } } void ScriptExplore::input_notify() { director.chain = us; if (id->input.empty() || id->aborted) { to_client("Maybe next time.\n\r"); deactivate(); return; } loops = sstoi(id->input, -1); if (loops == -1) { to_client("I'm sorry, WHAT?\n\r"); deactivate(); return; } if (loops == 0) { infinite = true; } else { infinite = false; } id->input.clear(); if (!infinite) { BUGZ_LOG(warning) << "Explore loops: " << loops; } else { to_client("Infinite Mode!\n\r"); to_client("[ PRESS A KEY TO STOP ]\n\r"); BUGZ_LOG(warning) << "Explore loops: INFINITE"; } to_server("SD"); state = 3; } void ScriptExplore::next() { if (loops <= 0 && !infinite) { to_client("The exploration ends, for now.\n\r"); deactivate(); return; } if (!infinite) --loops; // Calculate next best sector to goto density_scan &ds = director.galaxy.dscan; density best_sector; <<<<<<< HEAD for (int x = 0; x < ds.pos; ++x) { BUGZ_LOG(warning) << "Comparing: " << ds.d[x].sector << " (" << ds.d[x].density << ", " << ds.d[x].known << ") to " << best_sector.sector << " (" << best_sector.density << ", " << best_sector.known << ")"; /* Is this sector prefered over others? * Warp Counts (Number of warps) * Density Check (Is this sector clear, does it contain a port) * NavHaz Check (Avoid sectors with navhaz above X%) */ if (!ds.d[x].known) { BUGZ_LOG(warning) << "Subject: " << ds.d[x].sector; // Compare, Warp counts if (best_sector.sector != 0) { if ((ds.d[x].warps >= best_sector.warps) || ((ds.d[x].density == 100 || ds.d[x].density == 101) && (best_sector.density != 100 || best_sector.density != 101))) { if (density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { if (best_sector.sector != 0) { BUGZ_LOG(warning) << "Storing previous best " << best_sector.sector; unknown_warps.push(best_sector.sector); ======= best_sector.sector = 0; if (target != 0) { BUGZ_LOG(info) << "Using: " << target; best_sector.sector = target; target = 0; } else { for (int x = 0; x < ds.pos; ++x) { if(best_sector.sector != 0) BUGZ_LOG(info) << "Comparing: " << ds.d[x].sector << " (" << ds.d[x].density << ", " << ds.d[x].known <<") to " << best_sector.sector << " (" << best_sector.density << ", " << best_sector.known << ")"; /* Is this sector prefered over others? * Warp Counts (Number of warps) * Density Check (Is this sector clear, does it contain a port) * NavHaz Check (Avoid sectors with navhaz above X%) */ if(!ds.d[x].known) { BUGZ_LOG(info) << "Subject: " << ds.d[x].sector; // Compare, Warp counts if (best_sector.sector != 0) { if(prefer_ports) { if((ds.d[x].density == 100 || ds.d[x].density == 101) || (ds.d[x].warps >= best_sector.warps)) { if(density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { if(best_sector.sector != 0) { BUGZ_LOG(info) << "Storing previous best " << best_sector.sector; unknown_warps.push(best_sector.sector); } best_sector = ds.d[x]; } } else { if(density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { BUGZ_LOG(info) << "Added " << ds.d[x].sector << " to unknown_warps (" << unknown_warps.size() << ")"; unknown_warps.push(ds.d[x].sector); } } } else { if((ds.d[x].warps >= best_sector.warps)) { if(density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { if(best_sector.sector != 0) { BUGZ_LOG(info) << "Storing previous best " << best_sector.sector; unknown_warps.push(best_sector.sector); } best_sector = ds.d[x]; } } else { if(density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { BUGZ_LOG(info) << "Added " << ds.d[x].sector << " to unknown_warps (" << unknown_warps.size() << ")"; unknown_warps.push(ds.d[x].sector); } >>>>>>> master } } } else { <<<<<<< HEAD if (density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) { BUGZ_LOG(warning) << "Added " << ds.d[x].sector << " to unknown_warps (" << unknown_warps.size() << ")"; unknown_warps.push(ds.d[x].sector); } ======= BUGZ_LOG(info) << "No-Op " << ds.d[x].sector << " is best."; best_sector = ds.d[x]; >>>>>>> master } // Check density for possible port } } } BUGZ_LOG(warning) << "Unknown Warps: " << unknown_warps.size(); if (best_sector.sector == 0) { if (unknown_warps.size() == 0) { to_client("No unknown warps."); deactivate(); return; } else { BUGZ_LOG(warning) << "Seeking previous unexplored"; best_sector.sector = unknown_warps.top(); unknown_warps.pop(); std::string message = "DEAD END"; std::string indenter = " "; ANSIColor alert(COLOR::WHITE, COLOR::RED, ATTR::BOLD); to_client(indenter + alert() + message + reset() + "\n\r"); } } BUGZ_LOG(warning) << "Targeting sector: " << best_sector.sector; if (director.current_sector != best_sector.sector) { md->move_to = best_sector.sector; director.chain = move; director.chain->activate(); } else { BUGZ_LOG(warning) << "Targeting current sector!"; state = 3; to_server("SD"); } } void ScriptExplore::server_prompt(const std::string &prompt) { <<<<<<< HEAD BUGZ_LOG(warning) << "Explorer State: SP " << state; // next(); if (state == 1) { if (at_command_prompt(prompt)) { if (director.galaxy.meta["ship"]) { if (!director.galaxy.meta["ship"]["scanner"]) { to_client( "\n\rIt appears your ship doesn't have a long range " "scanner.\n\r"); ======= BUGZ_LOG(info) << "Explorer State: SP " << state; //next(); if(state == 1) { if(at_command_prompt(prompt)) { if(director.galaxy.meta.contains("ship")) { if(!director.galaxy.meta["ship"].contains("scanner")) { to_client("\n\rIt appears your ship doesn't have a long range scanner.\n\r"); >>>>>>> master deactivate(); return; } } state = 2; BUGZ_LOG(info) << "state = 1, prompting for user input"; director.chain = input; input->activate(); return; } } if (state == 3) { if (at_command_prompt(prompt)) { state = 4; BUGZ_LOG(info) << "state = 3, calculating next sector"; next(); } } } ScriptPlanet::ScriptPlanet(Director &d) : Dispatch(d) { BUGZ_LOG(warning) << "ScriptPlanet()"; init(); } ScriptPlanet::~ScriptPlanet() { BUGZ_LOG(warning) << "~ScriptPlanet()"; } void ScriptPlanet::init() { move = std::make_shared(director); md = static_cast(&(*move)); md->setNotify([this]() { this->move_notify(); }); trader = std::make_shared(director); td = static_cast(&(*trader)); td->setNotify([this]() { this->trade_notify(); }); input = std::make_shared(director); id = static_cast(&(*input)); id->prompt = "Which planet would you like to upgrade => "; id->max_length = 3; id->numeric = true; id->setNotify([this]() { this->input_notify(); }); state = 0; } void ScriptPlanet::activate() { us = director.chain; // FUTURE: handle special case here, where we activate at planet/citadel // prompt state = 1; // clear out the planets list -- we're refreshing. director.galaxy.planets.clear(); // get planet lists to_server("TLQ"); } void ScriptPlanet::deactivate() { BUGZ_LOG(warning) << "ScriptPlanet::deactivate()"; us.reset(); notify(); } void ScriptPlanet::input_notify() { deactivate(); } void ScriptPlanet::move_notify() {} void ScriptPlanet::trade_notify() {} void ScriptPlanet::server_prompt(const std::string &prompt) { if (state == 1) { if (at_command_prompt(prompt)) { state = 2; to_server("CYQ"); } } else if (state == 2) { if (at_command_prompt(prompt)) { state = 3; if (director.galaxy.planets.empty()) { to_client("Sorry, I don't see that you have any planets!\n\r"); deactivate(); return; } for (auto const &planet : director.galaxy.planets) { std::string text = str(boost::format("%1$3d <%2$5d> Class %3% Level %4% Name %5%\n\r") % planet.first % planet.second.sector % planet.second.c % planet.second.level % planet.second.name); to_client(text); } director.chain = input; director.chain->activate(); return; } } } void ScriptPlanet::server_line(const std::string &line, const std::string &raw_line) {}