TableauColumn.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include "TableauColumn.h"
  2. #include "utils/RenderBuffer.h"
  3. #define max(a, b) a>b?a:b
  4. void TableauColumn::Reset() {
  5. cards->clear();
  6. }
  7. void TableauColumn::AddCard(Card *c) {
  8. check_pointer(c);
  9. cards->add(c);
  10. }
  11. void TableauColumn::AddRange(List<Card> *hand) {
  12. check_pointer(hand);
  13. for (auto *item: *hand) {
  14. check_pointer(item);
  15. cards->add(item);
  16. }
  17. }
  18. void TableauColumn::Render(uint8_t x, uint8_t y, bool selected, uint8_t selection_from_end, RenderBuffer *buffer) {
  19. // If the hand is empty
  20. if (cards->count == 0) {
  21. Card::RenderEmptyCard(x, y, buffer);
  22. if (selected)
  23. buffer->draw_rbox(x+1, y+1, x + 16, y + 22, Flip);
  24. return;
  25. }
  26. uint8_t selection = cards->count - selection_from_end;
  27. if (selected) selection--;
  28. uint8_t loop_end = cards->count;
  29. uint8_t loop_start = max(loop_end - 4, 0);
  30. uint8_t position = 0;
  31. uint8_t first_non_flipped = FirstNonFlipped();
  32. bool had_top = false;
  33. check_pointer(cards);
  34. // Draw the first flipped and non-flipped card with adjusted visibility
  35. if (first_non_flipped <= loop_start && selection != first_non_flipped) {
  36. // Draw a card back if it is not the first card
  37. if (first_non_flipped > 0) {
  38. Card::RenderBack(x, y + position, false, buffer, 5);
  39. // Increment loop start index and position
  40. position += 4;
  41. loop_start++;
  42. had_top = true;
  43. }
  44. // Draw the front side of the first non-flipped card
  45. check_pointer((*cards)[first_non_flipped]);
  46. (*cards)[first_non_flipped]->Render(x, y + position, false, buffer,
  47. cards->count == 1 ? 22 : 9);
  48. position += 8;
  49. loop_start++; // Increment loop start index
  50. }
  51. // Draw the selected card with adjusted visibility
  52. if (loop_start > selection) {
  53. if (!had_top && first_non_flipped > 0) {
  54. Card::RenderBack(x, y + position, false, buffer, 5);
  55. position += 4;
  56. loop_start++;
  57. }
  58. check_pointer((*cards)[selection]);
  59. // Draw the front side of the selected card
  60. (*cards)[selection]->Render(x, y + position, true, buffer, 9);
  61. position += 8;
  62. loop_start++; // Increment loop start index
  63. }
  64. //Draw the rest
  65. for (uint8_t i = loop_start; i < loop_end; i++, position += 4) {
  66. int height = 5;
  67. if((i + 1) == loop_end) height = 22;
  68. else if(i == selection || i == first_non_flipped) height = 9;
  69. check_pointer((*cards)[i]);
  70. if((*cards)[i]) {
  71. (*cards)[i]->Render(x, y + position, i == selection, buffer, height);
  72. if (i == selection || i == first_non_flipped) position += 4;
  73. }
  74. }
  75. }
  76. int8_t TableauColumn::FirstNonFlipped() {
  77. int8_t index = -1;
  78. if (cards->count > 0) {
  79. for (auto *card: *cards) {
  80. index++;
  81. if (card && card->exposed) {
  82. break;
  83. }
  84. }
  85. }
  86. return index;
  87. }
  88. TableauColumn::TableauColumn() {
  89. cards = new List<Card>();
  90. }
  91. TableauColumn::~TableauColumn() {
  92. delete cards;
  93. }
  94. void TableauColumn::Merge(TableauColumn *other) {
  95. Card *prev = nullptr;
  96. for (auto *item: *(other->cards)) {
  97. if(prev == item) {
  98. FURI_LOG_E("PLACE", "Possible circular dependency!");
  99. break;
  100. }
  101. FURI_LOG_D("PLACE", "ADDING %i %i", item->suit, item->value);
  102. if(!item){
  103. FURI_LOG_E("PLACE", "nullptr in merge!");
  104. break;
  105. }
  106. cards->add(item);
  107. }
  108. FURI_LOG_D("PLACE", "clear");
  109. other->cards->soft_clear();
  110. }
  111. Card *TableauColumn::TopCard() {
  112. return (*cards)[0];
  113. }
  114. uint8_t TableauColumn::Count() {
  115. return cards->count;
  116. }
  117. Card *TableauColumn::Pop() {
  118. return cards->pop();
  119. }
  120. void TableauColumn::Reveal() {
  121. (*cards)[cards->count - 1]->exposed = true;
  122. }
  123. Card *TableauColumn::LastCard() {
  124. if (cards->count > 0) {
  125. return (*cards)[cards->count - 1];
  126. }
  127. return nullptr;
  128. }
  129. void TableauColumn::Clear() {
  130. cards->soft_clear();
  131. }
  132. bool TableauColumn::CanPlace(TableauColumn *other) {
  133. if (cards->count == 0) {
  134. if(other->TopCard()->value == 11) FURI_LOG_D("TBLC", "placing first");
  135. return other->TopCard()->value == 11;
  136. }
  137. Card *last = LastCard();
  138. Card *top = other->TopCard();
  139. int current_suit = last->suit / 2;
  140. int other_suit = top->suit / 2;
  141. if((current_suit + 1) % 2 == other_suit && (last->value + 1) % 13 == (top->value + 2) % 13) FURI_LOG_D("TBLC", "Adding at end");
  142. else
  143. FURI_LOG_D("TBLC", "CANT ADD, suit check %i, label check %i", (current_suit + 1) % 2 == other_suit, (last->value + 1) % 13 == (top->value + 2) % 13);
  144. return (current_suit + 1) % 2 == other_suit && (last->value + 1) % 13 == (top->value + 2) % 13;
  145. }
  146. List<Card> *TableauColumn::splice(uint32_t selection) {
  147. FURI_LOG_D("TBLC", "%li, %li", cards->count-selection, selection);
  148. return cards->splice(cards->count-selection-1, selection+1);
  149. }