deck.cpp 6.7 KB

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