#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["trade_end_empty"]) { old_trade_end_empty = director.galaxy.config["trade_end_empty"].as(); } 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["stop_percent"]) { stop_percent = director.galaxy.config["stop_percent"].as(); } 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["stop_percent"]) { stop_percent = director.galaxy.config["stop_percent"].as(); } 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()"; us.reset(); } 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; } 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()"; notify(); } void ScriptExplore::move_notify() { if (md->aborted) { deactivate(); return; } if (md->success) { to_server("SD"); state = 3; return; } else { to_client("No safe moves.\n\r"); deactivate(); } } void ScriptExplore::input_notify() { 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"; } director.chain = us; 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; 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 = ds.d[x]; } } else { 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); } } } else { best_sector = ds.d[x]; } // 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(); } } BUGZ_LOG(warning) << "Targeting sector: " << best_sector.sector; md->move_to = best_sector.sector; director.chain = move; director.chain->activate(); } void ScriptExplore::server_prompt(const std::string &prompt) { 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"); deactivate(); return; } } state = 2; BUGZ_LOG(fatal) << "state = 1, prompting for user input"; director.chain = input; input->activate(); return; } } if (state == 3) { if(at_command_prompt(prompt)) { state = 4; next(); } } }