deck.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #include "deck.h"
  2. #include <algorithm>
  3. #include <sstream>
  4. Deck::Deck(int size) {
  5. cardback = door::ANSIColor(door::COLOR::RED);
  6. card_height = size;
  7. init();
  8. }
  9. Deck::Deck(door::ANSIColor backcolor, int size) : cardback{backcolor} {
  10. card_height = size;
  11. init();
  12. }
  13. void Deck::init(void) {
  14. if (card_height != 3) {
  15. if (card_height != 5) {
  16. card_height = 3;
  17. }
  18. }
  19. for (int i = 0; i < 52; ++i) {
  20. cards.push_back(card_of(i));
  21. }
  22. // 0 = BLANK, 1-4 levels
  23. for (int i = 0; i < 5; ++i) {
  24. backs.push_back(back_of(i));
  25. }
  26. }
  27. Deck::~Deck() {
  28. for (auto c : cards) {
  29. delete c;
  30. }
  31. cards.clear();
  32. for (auto b : backs) {
  33. delete b;
  34. }
  35. backs.clear();
  36. }
  37. int Deck::is_deck(int c) { return c / 52; }
  38. int Deck::is_suit(int c) { return (c % 52) / 13; }
  39. int Deck::is_rank(int c) { return (c % 52) % 13; }
  40. char Deck::rank_symbol(int c) {
  41. const char symbols[] = "A23456789TJQK";
  42. return symbols[c];
  43. }
  44. std::string Deck::suit_symbol(int c) {
  45. // unicode
  46. if (door::unicode) {
  47. switch (c) {
  48. case 0:
  49. return std::string("\u2665");
  50. case 1:
  51. return std::string("\u2666");
  52. case 2:
  53. return std::string("\u2663");
  54. case 3:
  55. return std::string("\u2660");
  56. }
  57. } else {
  58. switch (c) {
  59. case 0:
  60. return std::string(1, '\x03');
  61. case 1:
  62. return std::string(1, '\x04');
  63. case 2:
  64. return std::string(1, '\x05');
  65. case 3:
  66. return std::string(1, '\x06');
  67. }
  68. }
  69. return std::string("!", 1);
  70. }
  71. door::Panel *Deck::card_of(int c) {
  72. int suit = is_suit(c);
  73. int rank = is_rank(c);
  74. bool is_red = (suit < 2);
  75. door::ANSIColor color;
  76. if (is_red) {
  77. color = door::ANSIColor(door::COLOR::RED, door::COLOR::WHITE);
  78. } else {
  79. color = door::ANSIColor(door::COLOR::BLACK, door::COLOR::WHITE);
  80. }
  81. door::Panel *p = new door::Panel(0, 0, 5);
  82. // setColor sets border_color. NOT WHAT I WANT.
  83. // p->setColor(color);
  84. char r = rank_symbol(rank);
  85. std::string s = suit_symbol(suit);
  86. // build lines
  87. std::ostringstream oss;
  88. oss << r << s << " ";
  89. std::string str = oss.str();
  90. p->addLine(std::make_unique<door::Line>(str, 5, color));
  91. oss.str(std::string());
  92. oss.clear();
  93. if (card_height == 5)
  94. p->addLine(std::make_unique<door::Line>(" ", 5, color));
  95. oss << " " << s << " ";
  96. str = oss.str();
  97. p->addLine(std::make_unique<door::Line>(str, 5, color));
  98. oss.str(std::string());
  99. oss.clear();
  100. if (card_height == 5)
  101. p->addLine(std::make_unique<door::Line>(" ", 5, color));
  102. oss << " " << s << r;
  103. str = oss.str();
  104. p->addLine(std::make_unique<door::Line>(str, 5, color));
  105. oss.str(std::string());
  106. oss.clear();
  107. return p;
  108. }
  109. std::string Deck::back_char(int level) {
  110. std::string c;
  111. if (level == 0) {
  112. c = ' ';
  113. return c;
  114. }
  115. if (door::unicode) {
  116. switch (level) {
  117. case 1:
  118. c = "\u2591";
  119. break;
  120. case 2:
  121. c = "\u2592";
  122. break;
  123. case 3:
  124. c = "\u2593";
  125. break;
  126. case 4:
  127. c = "\u2588";
  128. break;
  129. }
  130. } else {
  131. switch (level) {
  132. case 1:
  133. c = "\xb0";
  134. break;
  135. case 2:
  136. c = "\xb1";
  137. break;
  138. case 3:
  139. c = "\xb2";
  140. break;
  141. case 4:
  142. c = "\xdb";
  143. break;
  144. }
  145. }
  146. return c;
  147. }
  148. door::Panel *Deck::back_of(int level) {
  149. // using: \xb0, 0xb1, 0xb2, 0xdb
  150. // OR: \u2591, \u2592, \u2593, \u2588
  151. // door::ANSIColor color(door::COLOR::RED, door::COLOR::BLACK);
  152. door::Panel *p = new door::Panel(0, 0, 5);
  153. std::string c = back_char(level);
  154. std::string l = c + c + c + c + c;
  155. for (int x = 0; x < card_height; ++x) {
  156. p->addLine(std::make_unique<door::Line>(l, 5, cardback));
  157. };
  158. // p->addLine(std::make_unique<door::Line>(l, 5, cardback));
  159. // p->addLine(std::make_unique<door::Line>(l, 5, cardback));
  160. return p;
  161. }
  162. void Deck::part(int x, int y, door::Door &d, int level, bool left) {
  163. // Render part of the back of a card.
  164. y += 2;
  165. if (!left) {
  166. x += 2;
  167. }
  168. std::string c = back_char(level);
  169. std::string l = c + c + c;
  170. door::Goto g(x, y);
  171. d << g << cardback << l;
  172. }
  173. door::Panel *Deck::card(int c) { return cards[c]; }
  174. door::Panel *Deck::back(int level) { return backs[level]; }
  175. const std::array<std::pair<int, int>, 18> Deck::blocks = {
  176. make_pair(3, 4), make_pair(5, 6), make_pair(7, 8), // end row 1
  177. make_pair(9, 10), make_pair(10, 11), make_pair(12, 13),
  178. make_pair(13, 14), make_pair(15, 16), make_pair(16, 17),
  179. make_pair(18, 19), // end row 2
  180. make_pair(19, 20), make_pair(20, 21), make_pair(21, 22),
  181. make_pair(22, 23), make_pair(23, 24), make_pair(24, 25),
  182. make_pair(25, 26), make_pair(26, 27) // 27
  183. };
  184. /**
  185. * @brief Which card (if any) is unblocked by this card
  186. *
  187. * @param c
  188. * @return * int
  189. */
  190. int Deck::unblocks(int c) {
  191. for (size_t i = 0; i < blocks.size(); ++i) {
  192. if ((blocks.at(i).first == c) || (blocks.at(i).second == c)) {
  193. return i;
  194. }
  195. }
  196. return -1;
  197. }
  198. /*
  199. Layout spacing 1:
  200. 1 2 3 4 5 6
  201. 123456789012345678901234567890123456789012345678901234567890
  202. ░░░░░ ░░░░░ ░░░░░
  203. ░░░░░ ░░░░░ ░░░░░
  204. ▒▒▒▒▒░▒▒▒▒▒ #####░##### #####░#####
  205. ▒▒▒▒▒ ▒▒▒▒▒ ##### ##### ##### #####
  206. ▓▓▓▓▓▒▓▓▓▓▓▒▓▓▓▓▓ #####=#####=##### #####=#####=#####
  207. ▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓ ##### ##### ##### ##### ##### #####
  208. █████▓█████▓█████▓#####=#####=#####=#####=#####=#####=#####
  209. █████ █████ █████ ##### ##### ##### ##### ##### ##### #####
  210. █████ █████ █████ ##### ##### ##### ##### ##### ##### #####
  211. width = 5 * 10 + (1*9) = 59 OK!
  212. Layout with spacing = 2:
  213. EEEEE
  214. ZZZZZ
  215. yyyyyZZZyyyyy
  216. yyyyy yyyyy
  217. XXXXXyyyXXXXXyyyXXXXX
  218. XXXXX XXXXX XXXXX
  219. width = 5 * 10 + (2 * 9) = 50+18 = 68 ! I could do that!
  220. */
  221. void cardgo(int pos, int space, int h, int &x, int &y, int &level) {
  222. const int CARD_WIDTH = 5;
  223. int HALF_WIDTH = 3;
  224. // space = 1 or 3
  225. // int space = 1;
  226. // space = 3;
  227. HALF_WIDTH += space / 2;
  228. /*
  229. int levels[4] = {3, 6, 9, 10};
  230. for (level = 0; level < 4; ++level) {
  231. if (pos < levels[level]) {
  232. level++;
  233. // we're here
  234. y = (level -1) * 2 + 1;
  235. } else {
  236. pos -= levels[level];
  237. }
  238. }
  239. */
  240. int between = CARD_WIDTH + space;
  241. if (pos < 3) {
  242. // top
  243. level = 1;
  244. y = (level - 1) * (h - 1) + 1;
  245. x = pos * (between * 3) + between + HALF_WIDTH + space; // 10
  246. return;
  247. } else {
  248. pos -= 3;
  249. }
  250. if (pos < 6) {
  251. level = 2;
  252. y = (level - 1) * (h - 1) + 1;
  253. int group = (pos) / 2;
  254. x = pos * between + (group * between) + CARD_WIDTH + space * 2;
  255. return;
  256. } else {
  257. pos -= 6;
  258. }
  259. if (pos < 9) {
  260. level = 3;
  261. y = (level - 1) * (h - 1) + 1;
  262. x = pos * between + HALF_WIDTH + space;
  263. return;
  264. } else {
  265. pos -= 9;
  266. }
  267. if (pos < 10) {
  268. level = 4;
  269. y = (level - 1) * (h - 1) + 1;
  270. x = (pos)*between + space;
  271. return;
  272. } else {
  273. // something is wrong.
  274. y = -1;
  275. x = -1;
  276. level = -1;
  277. }
  278. }
  279. cards card_shuffle(std::seed_seq &seed, int decks) {
  280. std::mt19937 gen;
  281. // build deck of cards
  282. int size = decks * 52;
  283. std::vector<int> deck;
  284. deck.reserve(size);
  285. for (int x = 0; x < size; ++x) {
  286. deck.push_back(x);
  287. }
  288. // repeatable, but random
  289. gen.seed(seed);
  290. std::shuffle(deck.begin(), deck.end(), gen);
  291. return deck;
  292. }
  293. cards card_states(int decks) {
  294. // auto states = std::unique_ptr<std::vector<int>>(); // (decks * 52, 0)>;
  295. std::vector<int> states;
  296. states.assign(decks * 52, 0);
  297. return states;
  298. }