main.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #include "door.h"
  2. #include "space.h"
  3. #include <iostream>
  4. #include <random>
  5. #include <string>
  6. // The idea is that this would be defined elsewhere (maybe)
  7. int user_score = 0;
  8. // NOTE: When run as a door, we always detect CP437 (because that's what Enigma
  9. // is defaulting to)
  10. void adjust_score(int by) { user_score += by; }
  11. door::Panel make_timeout(int mx, int my) {
  12. door::ANSIColor yellowred =
  13. door::ANSIColor(door::COLOR::YELLOW, door::COLOR::RED, door::ATTR::BOLD);
  14. std::string line_text("Sorry, you've been inactive for too long.");
  15. int msgWidth = line_text.length() + (2 * 3); // + padding * 2
  16. door::Panel timeout((mx - (msgWidth)) / 2, my / 2 + 4, msgWidth);
  17. // place.setTitle(std::make_unique<door::Line>(title), 1);
  18. timeout.setStyle(door::BorderStyle::DOUBLE);
  19. timeout.setColor(yellowred);
  20. door::Line base(line_text);
  21. base.setColor(yellowred);
  22. std::string pad1(3, ' ');
  23. /*
  24. std::string pad1(3, '\xb0');
  25. if (door::unicode) {
  26. std::string unicode;
  27. door::cp437toUnicode(pad1.c_str(), unicode);
  28. pad1 = unicode;
  29. }
  30. */
  31. base.setPadding(pad1, yellowred);
  32. // base.setColor(door::ANSIColor(door::COLOR::GREEN, door::COLOR::BLACK));
  33. std::unique_ptr<door::Line> stuff = std::make_unique<door::Line>(base);
  34. timeout.addLine(std::make_unique<door::Line>(base));
  35. return timeout;
  36. }
  37. door::Menu make_main_menu(void) {
  38. door::Menu m(5, 5, 25);
  39. door::Line mtitle("Space-Ace Main Menu");
  40. door::ANSIColor border_color(door::COLOR::CYAN, door::COLOR::BLUE);
  41. door::ANSIColor title_color(door::COLOR::CYAN, door::COLOR::BLUE,
  42. door::ATTR::BOLD);
  43. m.setColor(border_color);
  44. mtitle.setColor(title_color);
  45. mtitle.setPadding(" ", title_color);
  46. m.setTitle(std::make_unique<door::Line>(mtitle), 1);
  47. // m.setColorizer(true,
  48. m.setRender(true, door::Menu::makeRender(
  49. door::ANSIColor(door::COLOR::CYAN, door::ATTR::BOLD),
  50. door::ANSIColor(door::COLOR::BLUE, door::ATTR::BOLD),
  51. door::ANSIColor(door::COLOR::CYAN, door::ATTR::BOLD),
  52. door::ANSIColor(door::COLOR::BLUE, door::ATTR::BOLD)));
  53. // m.setColorizer(false,
  54. m.setRender(false, door::Menu::makeRender(
  55. door::ANSIColor(door::COLOR::YELLOW, door::COLOR::BLUE,
  56. door::ATTR::BOLD),
  57. door::ANSIColor(door::COLOR::WHITE, door::COLOR::BLUE,
  58. door::ATTR::BOLD),
  59. door::ANSIColor(door::COLOR::YELLOW, door::COLOR::BLUE,
  60. door::ATTR::BOLD),
  61. door::ANSIColor(door::COLOR::CYAN, door::COLOR::BLUE,
  62. door::ATTR::BOLD)));
  63. m.addSelection('1', "Play Cards");
  64. m.addSelection('2', "View Scores");
  65. m.addSelection('3', "Drop to DOS");
  66. m.addSelection('4', "Chat with BUGZ");
  67. m.addSelection('H', "Help");
  68. m.addSelection('A', "About this game");
  69. m.addSelection('Q', "Quit");
  70. return m;
  71. }
  72. door::Panel make_about(void) {
  73. door::Panel about(2, 2, 60);
  74. about.setStyle(door::BorderStyle::DOUBLE_SINGLE);
  75. about.setColor(door::ANSIColor(door::COLOR::YELLOW, door::COLOR::BLUE,
  76. door::ATTR::BOLD));
  77. about.addLine(std::make_unique<door::Line>("About This Door", 60));
  78. /*
  79. 123456789012345678901234567890123456789012345678901234567890
  80. This door was written by Bugz.
  81. It is written in c++, only supports Linux, and replaces
  82. opendoors.
  83. It's written in c++, and replaces the outdated opendoors
  84. library.
  85. */
  86. about.addLine(
  87. std::make_unique<door::Line>("This door was written by Bugz.", 60));
  88. about.addLine(std::make_unique<door::Line>("", 60));
  89. about.addLine(std::make_unique<door::Line>(
  90. "It is written in c++, only support Linux, and replaces", 60));
  91. about.addLine(std::make_unique<door::Line>("opendoors.", 60));
  92. return about;
  93. }
  94. void display_starfield(int mx, int my, door::Door &door, std::mt19937 &rng) {
  95. door << door::reset << door::cls;
  96. // display starfield
  97. const char *stars[2];
  98. stars[0] = ".";
  99. if (door::unicode) {
  100. stars[1] = "\u2219"; // "\u00b7";
  101. } else {
  102. stars[1] = "\xf9"; // "\xfa";
  103. };
  104. {
  105. // Make uniform random distribution between 1 and MAX screen size X/Y
  106. std::uniform_int_distribution<int> uni_x(1, mx);
  107. std::uniform_int_distribution<int> uni_y(1, my);
  108. door::ANSIColor white(door::COLOR::WHITE);
  109. door::ANSIColor dark(door::COLOR::BLACK, door::ATTR::BRIGHT);
  110. for (int x = 0; x < (mx * my / 100); x++) {
  111. door::Goto star_at(uni_x(rng), uni_y(rng));
  112. door << star_at;
  113. if (x % 5 < 2)
  114. door << dark;
  115. else
  116. door << white;
  117. if (x % 2 == 0)
  118. door << stars[0];
  119. else
  120. door << stars[1];
  121. }
  122. }
  123. }
  124. void display_space_ace(int mx, int my, door::Door &door) {
  125. // space_ace is 72 chars wide, 6 high
  126. int sa_x = (mx - 72) / 2;
  127. int sa_y = (my - 6) / 2;
  128. // output the SpaceAce logo -- centered!
  129. for (const auto s : space) {
  130. door::Goto sa_at(sa_x, sa_y);
  131. door << sa_at;
  132. if (door::unicode) {
  133. std::string unicode;
  134. door::cp437toUnicode(s, unicode);
  135. door << unicode; // << door::nl;
  136. } else
  137. door << s; // << door::nl;
  138. sa_y++;
  139. }
  140. // pause 5 seconds so they can enjoy our awesome logo
  141. door.sleep_key(5);
  142. }
  143. void display_starfield_space_ace(int mx, int my, door::Door &door,
  144. std::mt19937 &rng) {
  145. display_starfield(mx, my, door, rng);
  146. display_space_ace(mx, my, door);
  147. door << door::reset;
  148. }
  149. int main(int argc, char *argv[]) {
  150. door::Door door("space-ace", argc, argv);
  151. // door << door::reset << door::cls << door::nl;
  152. door::ANSIColor ac(door::COLOR::YELLOW, door::ATTR::BOLD);
  153. // https://stackoverflow.com/questions/5008804/generating-random-integer-from-a-range
  154. std::random_device rd; // only used once to initialise (seed) engine
  155. std::mt19937 rng(
  156. rd()); // random-number engine used (Mersenne-Twister in this case)
  157. // std::uniform_int_distribution<int> uni(min, max); // guaranteed unbiased
  158. int mx, my; // Max screen width/height
  159. if (door.width == 0) {
  160. // screen detect failed, use sensible defaults
  161. mx = 80;
  162. my = 23;
  163. } else {
  164. mx = door.width;
  165. my = door.height;
  166. }
  167. // We assume here that the width and height are something crazy like 10x15. :P
  168. display_starfield_space_ace(mx, my, door, rng);
  169. // for testing inactivity timeout
  170. door.inactivity = 10;
  171. door::Panel timeout = make_timeout(mx, my);
  172. door::Menu m = make_main_menu();
  173. int r = m.choose(door);
  174. // need to reset the colors. (whoops!)
  175. door << door::reset;
  176. if (r == -1) {
  177. TIMEOUT:
  178. door.log("TIMEOUT");
  179. // mx, my
  180. door::ANSIColor yellowred = door::ANSIColor(
  181. door::COLOR::YELLOW, door::COLOR::RED, door::ATTR::BOLD);
  182. std::string line_text("Sorry, you've been inactive for too long.");
  183. int msgWidth = line_text.length() + (2 * 3); // + padding * 2
  184. door::Panel timeout((mx - (msgWidth)) / 2, my / 2 + 4, msgWidth);
  185. // place.setTitle(std::make_unique<door::Line>(title), 1);
  186. timeout.setStyle(door::BorderStyle::DOUBLE);
  187. timeout.setColor(yellowred);
  188. door::Line base(line_text);
  189. base.setColor(yellowred);
  190. std::string pad1(3, ' ');
  191. /*
  192. std::string pad1(3, '\xb0');
  193. if (door::unicode) {
  194. std::string unicode;
  195. door::cp437toUnicode(pad1.c_str(), unicode);
  196. pad1 = unicode;
  197. }
  198. */
  199. base.setPadding(pad1, yellowred);
  200. // base.setColor(door::ANSIColor(door::COLOR::GREEN, door::COLOR::BLACK));
  201. std::unique_ptr<door::Line> stuff = std::make_unique<door::Line>(base);
  202. timeout.addLine(std::make_unique<door::Line>(base));
  203. door << timeout << door::reset << door::nl << door::nl;
  204. return 0;
  205. }
  206. display_starfield(mx, my, door, rng);
  207. // WARNING: After starfield, cursor position is random!
  208. door << door::Goto(1, 9); // door::nl << door::nl; // door::cls;
  209. door << "Hello, " << door.username << ", you chose option " << r << "!"
  210. << door::nl;
  211. door << "Press a key...";
  212. r = door.sleep_key(door.inactivity);
  213. if (r == -1)
  214. goto TIMEOUT;
  215. door << door::nl;
  216. door::Panel about = make_about();
  217. about.set((mx - 60) / 2, (my - 5) / 2);
  218. door << about;
  219. door << door::reset << door::nl << "Press another key...";
  220. r = door.sleep_key(door.inactivity);
  221. if (r == -1)
  222. goto TIMEOUT;
  223. door << door::nl;
  224. // door << door::reset << door::cls;
  225. display_starfield(mx, my, door, rng);
  226. door << m << door::reset << door::nl << "This is what the menu looked liked!"
  227. << door::nl;
  228. // Normal DOOR exit goes here...
  229. door << door::nl << "Returning you to the BBS, please wait..." << door::nl;
  230. sleep(2);
  231. return 0;
  232. }