scripts.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. #include "scripts.h"
  2. #include <boost/format.hpp>
  3. #include "logging.h"
  4. ScriptTerror::ScriptTerror(Director &d) : Dispatch(d) {
  5. BUGZ_LOG(warning) << "ScriptTerror()";
  6. init();
  7. }
  8. ScriptTerror::~ScriptTerror() { BUGZ_LOG(warning) << "~ScriptTerror()"; }
  9. void ScriptTerror::init(void) {
  10. BUGZ_LOG(fatal) << "ScriptTerror::init()";
  11. move = std::make_shared<MoveDispatch>(director);
  12. md = static_cast<MoveDispatch *>(&(*move));
  13. // setup notify functions for results/completion.
  14. md->setNotify([this]() { this->move_notify(); });
  15. input = std::make_shared<InputDispatch>(director);
  16. id = static_cast<InputDispatch *>(&(*input));
  17. id->prompt = "Number of loops: ";
  18. id->max_length = 4;
  19. id->numeric = true;
  20. id->setNotify([this]() { this->input_notify(); });
  21. trader = std::make_shared<TraderDispatch>(director);
  22. td = static_cast<TraderDispatch *>(&(*trader));
  23. td->setNotify([this]() { this->trade_notify(); });
  24. BUGZ_LOG(fatal) << "ScriptTerror::init() completed.";
  25. }
  26. void ScriptTerror::activate(void) {
  27. BUGZ_LOG(warning) << "ScriptTerror::activate()";
  28. // Need: InputDispatch, MoveDispatch, ScriptTrader
  29. // Save the trade_end_empty setting, and set to Y
  30. if (director.galaxy.config.contains("trade_end_empty")) {
  31. old_trade_end_empty = director.galaxy.config["trade_end_empty"];
  32. } else {
  33. old_trade_end_empty = "Y";
  34. }
  35. director.galaxy.config["trade_end_empty"] = "Y";
  36. // Step 0: Get ship information / # of holds
  37. max_loops = loops = -1;
  38. to_server("I");
  39. // Step 1: Get number of loops of terror
  40. // director.chain = input;
  41. // input->activate();
  42. // Step 2: Look for closest trades, try ScriptTrade until none < some
  43. // level. Step 3: Move on, unless out of loops (or low on turns)
  44. // deactivate();
  45. }
  46. void ScriptTerror::deactivate(void) {
  47. BUGZ_LOG(warning) << "ScriptTerror::deactivate()";
  48. // restore the original value.
  49. director.galaxy.config["trade_end_empty"] = old_trade_end_empty;
  50. notify();
  51. }
  52. void ScriptTerror::input_notify(void) {
  53. if (id->input.empty()) {
  54. deactivate();
  55. return;
  56. }
  57. if (id->aborted) {
  58. deactivate();
  59. return;
  60. }
  61. max_loops = sstoi(id->input, -1);
  62. if (max_loops == -1) {
  63. deactivate();
  64. return;
  65. }
  66. id->input.clear();
  67. BUGZ_LOG(warning) << "Loops of terror: " << max_loops;
  68. loops = max_loops;
  69. // find nearest
  70. int stop_percent;
  71. if (director.galaxy.config.contains("stop_percent")) {
  72. stop_percent = director.galaxy.config["stop_percent"].get<int>();
  73. } else {
  74. stop_percent = 25;
  75. director.galaxy.config["stop_percent"] = stop_percent;
  76. }
  77. ppt = director.galaxy.find_closest_trade(director.current_sector, 3,
  78. stop_percent);
  79. if (ppt.type == 0) {
  80. to_client("No trades found! You've burnt the galaxy!\n\r");
  81. deactivate();
  82. return;
  83. }
  84. // ok, step 2: move!
  85. // md->setNotify([this]() { this->proxy_deactivate(); });
  86. if (director.current_sector != ppt.s1) {
  87. BUGZ_LOG(fatal) << "Moving to: " << ppt.s1;
  88. md->move_to = ppt.s1;
  89. director.chain = move;
  90. director.chain->activate();
  91. return;
  92. } else {
  93. // We're already there!
  94. to_client("Ok! Get trading!\n\r");
  95. td->port[0] = ppt.s1;
  96. td->port[1] = ppt.s2;
  97. td->trades = ppt.trades;
  98. td->type = ppt.type;
  99. director.chain = trader;
  100. director.chain->activate();
  101. return;
  102. }
  103. }
  104. void ScriptTerror::move_notify(void) {
  105. BUGZ_LOG(fatal) << "move_notify()";
  106. if (md->aborted) {
  107. to_client("Move cancel.\n\r");
  108. deactivate();
  109. return;
  110. }
  111. // Check for success, and start trading!
  112. if (md->success) {
  113. to_client("We're here, get trading!\n\r");
  114. td->port[0] = ppt.s1;
  115. td->port[1] = ppt.s2;
  116. td->trades = ppt.trades;
  117. td->type = ppt.type;
  118. director.chain = trader;
  119. director.chain->activate();
  120. return;
  121. } else {
  122. std::string message = "Move FAILED. " + md->why_failed + "\n\r";
  123. // to_client("Move FAILED.\n\r");
  124. to_client(message);
  125. deactivate();
  126. }
  127. }
  128. void ScriptTerror::server_prompt(const std::string &prompt) {
  129. if ((loops == -1) && (max_loops == -1)) {
  130. if (at_command_prompt(prompt)) {
  131. // Step 1: Get number of loops of terror
  132. director.chain = input;
  133. input->activate();
  134. return;
  135. }
  136. }
  137. }
  138. void ScriptTerror::trade_notify(void) {
  139. // Done trading -- maybe! :P
  140. if (td->aborted) {
  141. to_client("Trade cancel.\n\r");
  142. deactivate();
  143. return;
  144. }
  145. if (td->success) {
  146. // success!
  147. // find nearest
  148. int stop_percent;
  149. if (director.galaxy.config.contains("stop_percent")) {
  150. stop_percent = director.galaxy.config["stop_percent"].get<int>();
  151. } else {
  152. stop_percent = 25;
  153. director.galaxy.config["stop_percent"] = stop_percent;
  154. }
  155. ppt = director.galaxy.find_closest_trade(director.current_sector, 3,
  156. stop_percent);
  157. if (ppt.type == 0) {
  158. to_client("No trades found! You've burnt the galaxy!\n\r");
  159. deactivate();
  160. return;
  161. }
  162. if ((director.current_sector == ppt.s1) ||
  163. (director.current_sector == ppt.s2)) {
  164. // We're still here...
  165. BUGZ_LOG(fatal) << "Trade it again, Sam.";
  166. to_client("Keep trading.\n\r");
  167. td->port[0] = ppt.s1;
  168. td->port[1] = ppt.s2;
  169. td->trades = ppt.trades;
  170. td->type = ppt.type;
  171. director.chain = trader;
  172. director.chain->activate();
  173. return;
  174. }
  175. // Ok, this isn't a local trade.
  176. if (loops == 0) {
  177. to_client("We're done terrorizing, for now...\n\r");
  178. deactivate();
  179. return;
  180. }
  181. --loops;
  182. // Move to our next target
  183. BUGZ_LOG(fatal) << "Moving to: " << ppt.s1;
  184. md->move_to = ppt.s1;
  185. director.chain = move;
  186. director.chain->activate();
  187. return;
  188. } else {
  189. std::string message = "Trade done: " + td->why_failed + "\n\r";
  190. to_client(message);
  191. }
  192. // to_client("Ok, trade is done.\n\r");
  193. deactivate();
  194. }
  195. ScriptVoyager::ScriptVoyager(Director &d) : Dispatch(d) {
  196. BUGZ_LOG(warning) << "ScriptVoyager()";
  197. init();
  198. }
  199. ScriptVoyager::~ScriptVoyager() { BUGZ_LOG(warning) << "~ScriptVoyager()"; }
  200. void ScriptVoyager::init(void) {
  201. move = std::make_shared<MoveDispatch>(director);
  202. md = static_cast<MoveDispatch *>(&(*move));
  203. md->setNotify([this]() { this->move_notify(); });
  204. input = std::make_shared<InputDispatch>(director);
  205. id = static_cast<InputDispatch *>(&(*input));
  206. id->prompt = "Number of loops/tries: ";
  207. id->max_length = 5;
  208. id->numeric = true;
  209. id->setNotify([this]() { this->input_notify(); });
  210. }
  211. void ScriptVoyager::activate(void) {
  212. director.chain = input;
  213. input->activate();
  214. return;
  215. }
  216. void ScriptVoyager::deactivate(void) {
  217. BUGZ_LOG(warning) << "ScriptVoyager::deactivate()";
  218. notify();
  219. }
  220. void ScriptVoyager::move_notify(void) {
  221. if (md->aborted) {
  222. deactivate();
  223. return;
  224. }
  225. if (md->success) {
  226. // Great!
  227. next();
  228. return;
  229. } else {
  230. std::string message = "No safe moves. " + md->why_failed + "\n\r";
  231. to_client(message);
  232. deactivate();
  233. }
  234. }
  235. void ScriptVoyager::input_notify(void) {
  236. if (id->input.empty() || id->aborted) {
  237. to_client("Ok, maybe later then.\n\r");
  238. deactivate();
  239. return;
  240. }
  241. loops = sstoi(id->input, -1);
  242. if (loops == -1) {
  243. to_client("I'm sorry, WHAT?\n\r");
  244. deactivate();
  245. }
  246. id->input.clear();
  247. BUGZ_LOG(warning) << "Voyager loops: " << loops;
  248. next();
  249. }
  250. void ScriptVoyager::next(void) {
  251. if (loops == 0) {
  252. // ok, stop here.
  253. to_client("The voyage ends here, for now.\n\r");
  254. deactivate();
  255. return;
  256. }
  257. --loops;
  258. sector_type s =
  259. director.galaxy.find_nearest_unexplored(director.current_sector);
  260. if (s == 0) {
  261. to_client("I don't see anything else to explorer.\n\r");
  262. BUGZ_LOG(warning) << "find_nearest_unexplored returned 0";
  263. deactivate();
  264. }
  265. BUGZ_LOG(warning) << "Next stop: " << s;
  266. md->move_to = s;
  267. director.chain = move;
  268. director.chain->activate();
  269. }
  270. // SL: [###### DANGER! You have marked sector 740 to be avoided!]
  271. // SP: [Do you really want to warp there? (Y/N) ]
  272. void ScriptVoyager::server_prompt(const std::string &prompt) {}
  273. ScriptExplore::ScriptExplore(Director &d) : Dispatch(d) {
  274. BUGZ_LOG(warning) << "ScriptExplore()";
  275. init();
  276. }
  277. ScriptExplore::~ScriptExplore() { BUGZ_LOG(warning) << "~ScriptExplore()"; }
  278. void ScriptExplore::init() {
  279. move = std::make_shared<MoveDispatch>(director);
  280. md = static_cast<MoveDispatch *>(&(*move));
  281. md->setNotify([this]() { this->move_notify(); });
  282. input = std::make_shared<InputDispatch>(director);
  283. id = static_cast<InputDispatch *>(&(*input));
  284. id->prompt = "Number of sectors to explore: ";
  285. id->max_length = 5;
  286. id->numeric = true;
  287. id->setNotify([this]() { this->input_notify(); });
  288. state = 0;
  289. }
  290. void ScriptExplore::activate() {
  291. us = director.chain;
  292. state = 1;
  293. to_server("I");
  294. /*
  295. director.chain = input;
  296. input->activate();
  297. if(director.galaxy.meta["ship"]) {
  298. if(!director.galaxy.meta["ship"]["scanner"]) {
  299. to_client("\n\rIt appears your ship doesn't have a long range
  300. scanner.\n\r"); deactivate();
  301. }
  302. }
  303. state = 1;
  304. return;
  305. */
  306. }
  307. void ScriptExplore::deactivate() {
  308. BUGZ_LOG(warning) << "ScriptExplore::deactivate()";
  309. us.reset();
  310. notify();
  311. }
  312. void ScriptExplore::move_notify() {
  313. director.chain = us;
  314. if (md->aborted) {
  315. deactivate();
  316. return;
  317. }
  318. if (md->success) {
  319. to_server("SD");
  320. state = 3;
  321. return;
  322. } else {
  323. to_client("No safe moves.\n\r");
  324. deactivate();
  325. }
  326. }
  327. void ScriptExplore::input_notify() {
  328. director.chain = us;
  329. if (id->input.empty() || id->aborted) {
  330. to_client("Maybe next time.\n\r");
  331. deactivate();
  332. return;
  333. }
  334. loops = sstoi(id->input, -1);
  335. if (loops == -1) {
  336. to_client("I'm sorry, WHAT?\n\r");
  337. deactivate();
  338. return;
  339. }
  340. if (loops == 0) {
  341. infinite = true;
  342. } else {
  343. infinite = false;
  344. }
  345. id->input.clear();
  346. if (!infinite) {
  347. BUGZ_LOG(warning) << "Explore loops: " << loops;
  348. } else {
  349. to_client("Infinite Mode!\n\r");
  350. to_client("[ PRESS A KEY TO STOP ]\n\r");
  351. BUGZ_LOG(warning) << "Explore loops: INFINITE";
  352. }
  353. to_server("SD");
  354. state = 3;
  355. }
  356. void ScriptExplore::next() {
  357. if (loops <= 0 && !infinite) {
  358. to_client("The exploration ends, for now.\n\r");
  359. deactivate();
  360. return;
  361. }
  362. if (!infinite) --loops;
  363. // Calculate next best sector to goto
  364. density_scan &ds = director.galaxy.dscan;
  365. density best_sector;
  366. for (int x = 0; x < ds.pos; ++x) {
  367. BUGZ_LOG(warning) << "Comparing: " << ds.d[x].sector << " ("
  368. << ds.d[x].density << ", " << ds.d[x].known << ") to "
  369. << best_sector.sector << " (" << best_sector.density
  370. << ", " << best_sector.known << ")";
  371. /* Is this sector prefered over others?
  372. * Warp Counts (Number of warps)
  373. * Density Check (Is this sector clear, does it contain a port)
  374. * NavHaz Check (Avoid sectors with navhaz above X%)
  375. */
  376. if (!ds.d[x].known) {
  377. BUGZ_LOG(warning) << "Subject: " << ds.d[x].sector;
  378. // Compare, Warp counts
  379. if (best_sector.sector != 0) {
  380. if ((ds.d[x].warps >= best_sector.warps) ||
  381. ((ds.d[x].density == 100 || ds.d[x].density == 101) &&
  382. (best_sector.density != 100 || best_sector.density != 101))) {
  383. if (density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) {
  384. if (best_sector.sector != 0) {
  385. BUGZ_LOG(warning)
  386. << "Storing previous best " << best_sector.sector;
  387. unknown_warps.push(best_sector.sector);
  388. }
  389. best_sector = ds.d[x];
  390. }
  391. } else {
  392. if (density_clear(ds.d[x].sector, ds.d[x].density, ds.d[x].navhaz)) {
  393. BUGZ_LOG(warning)
  394. << "Added " << ds.d[x].sector << " to unknown_warps ("
  395. << unknown_warps.size() << ")";
  396. unknown_warps.push(ds.d[x].sector);
  397. }
  398. }
  399. } else {
  400. best_sector = ds.d[x];
  401. }
  402. // Check density for possible port
  403. }
  404. }
  405. BUGZ_LOG(warning) << "Unknown Warps: " << unknown_warps.size();
  406. if (best_sector.sector == 0) {
  407. if (unknown_warps.size() == 0) {
  408. to_client("No unknown warps.");
  409. deactivate();
  410. return;
  411. } else {
  412. BUGZ_LOG(warning) << "Seeking previous unexplored";
  413. best_sector.sector = unknown_warps.top();
  414. unknown_warps.pop();
  415. }
  416. }
  417. BUGZ_LOG(warning) << "Targeting sector: " << best_sector.sector;
  418. md->move_to = best_sector.sector;
  419. director.chain = move;
  420. director.chain->activate();
  421. }
  422. void ScriptExplore::server_prompt(const std::string &prompt) {
  423. BUGZ_LOG(warning) << "Explorer State: SP " << state;
  424. // next();
  425. if (state == 1) {
  426. if (at_command_prompt(prompt)) {
  427. if (director.galaxy.meta["ship"]) {
  428. if (!director.galaxy.meta["ship"]["scanner"]) {
  429. to_client(
  430. "\n\rIt appears your ship doesn't have a long range "
  431. "scanner.\n\r");
  432. deactivate();
  433. return;
  434. }
  435. }
  436. state = 2;
  437. BUGZ_LOG(fatal) << "state = 1, prompting for user input";
  438. director.chain = input;
  439. input->activate();
  440. return;
  441. }
  442. }
  443. if (state == 3) {
  444. if (at_command_prompt(prompt)) {
  445. state = 4;
  446. next();
  447. }
  448. }
  449. }
  450. ScriptPlanet::ScriptPlanet(Director &d) : Dispatch(d) {
  451. BUGZ_LOG(warning) << "ScriptPlanet()";
  452. init();
  453. }
  454. ScriptPlanet::~ScriptPlanet() { BUGZ_LOG(warning) << "~ScriptPlanet()"; }
  455. void ScriptPlanet::init() {
  456. move = std::make_shared<MoveDispatch>(director);
  457. md = static_cast<MoveDispatch *>(&(*move));
  458. md->setNotify([this]() { this->move_notify(); });
  459. trader = std::make_shared<TraderDispatch>(director);
  460. td = static_cast<TraderDispatch *>(&(*trader));
  461. td->setNotify([this]() { this->trade_notify(); });
  462. input = std::make_shared<InputDispatch>(director);
  463. id = static_cast<InputDispatch *>(&(*input));
  464. id->prompt = "Which planet would you like to upgrade => ";
  465. id->max_length = 3;
  466. id->numeric = true;
  467. id->setNotify([this]() { this->input_notify(); });
  468. state = 0;
  469. }
  470. void ScriptPlanet::activate() {
  471. us = director.chain;
  472. // FUTURE: handle special case here, where we activate at planet/citadel
  473. // prompt
  474. state = 1;
  475. // clear out the planets list -- we're refreshing.
  476. director.galaxy.planets.clear();
  477. // get planet lists
  478. to_server("TLQ");
  479. }
  480. void ScriptPlanet::deactivate() {
  481. BUGZ_LOG(warning) << "ScriptPlanet::deactivate()";
  482. us.reset();
  483. notify();
  484. }
  485. void ScriptPlanet::input_notify() {
  486. deactivate();
  487. }
  488. void ScriptPlanet::move_notify() {}
  489. void ScriptPlanet::trade_notify() {}
  490. void ScriptPlanet::server_prompt(const std::string &prompt) {
  491. if (state == 1) {
  492. if (at_command_prompt(prompt)) {
  493. state = 2;
  494. to_server("CYQ");
  495. }
  496. } else if (state == 2) {
  497. if (at_command_prompt(prompt)) {
  498. state = 3;
  499. if (director.galaxy.planets.empty()) {
  500. to_client("Sorry, I don't see that you have any planets!\n\r");
  501. deactivate();
  502. return;
  503. }
  504. for (auto const &planet : director.galaxy.planets) {
  505. std::string text =
  506. str(boost::format("%1$3d <%2$5d> Class %3% Level %4% Name %5%\n\r") %
  507. planet.first % planet.second.sector % planet.second.c %
  508. planet.second.level % planet.second.name);
  509. to_client(text);
  510. }
  511. director.chain = input;
  512. director.chain->activate();
  513. return;
  514. }
  515. }
  516. }
  517. void ScriptPlanet::server_line(const std::string &line,
  518. const std::string &raw_line) {}