summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibCards/CardStack.cpp64
-rw-r--r--Userland/Libraries/LibCards/CardStack.h10
2 files changed, 67 insertions, 7 deletions
diff --git a/Userland/Libraries/LibCards/CardStack.cpp b/Userland/Libraries/LibCards/CardStack.cpp
index a06127fa45..dffbb41160 100644
--- a/Userland/Libraries/LibCards/CardStack.cpp
+++ b/Userland/Libraries/LibCards/CardStack.cpp
@@ -108,7 +108,7 @@ void CardStack::rebound_cards()
card.set_position(m_stack_positions.at(card_index++));
}
-void CardStack::add_all_grabbed_cards(const Gfx::IntPoint& click_location, NonnullRefPtrVector<Card>& grabbed)
+void CardStack::add_all_grabbed_cards(const Gfx::IntPoint& click_location, NonnullRefPtrVector<Card>& grabbed, MovementRule movement_rule)
{
VERIFY(grabbed.is_empty());
@@ -149,15 +149,56 @@ void CardStack::add_all_grabbed_cards(const Gfx::IntPoint& click_location, Nonnu
grabbed.append(*last_intersect);
last_intersect->set_moving(true);
}
+
+ // verify valid stack
+ bool valid_stack = true;
+ uint8_t last_value;
+ Color last_color;
+ for (size_t i = 0; i < grabbed.size(); i++) {
+ auto& card = grabbed.at(i);
+ if (i != 0) {
+ bool color_match;
+ switch (movement_rule) {
+ case Alternating:
+ color_match = card.color() != last_color;
+ break;
+ case Same:
+ color_match = card.color() == last_color;
+ break;
+ case Any:
+ color_match = true;
+ break;
+ }
+
+ if (!color_match || card.value() != last_value - 1) {
+ valid_stack = false;
+ break;
+ }
+ }
+ last_value = card.value();
+ last_color = card.color();
+ }
+
+ if (!valid_stack) {
+ for (auto& card : grabbed) {
+ card.set_moving(false);
+ }
+ grabbed.clear();
+ }
}
-bool CardStack::is_allowed_to_push(const Card& card, size_t stack_size) const
+bool CardStack::is_allowed_to_push(const Card& card, size_t stack_size, MovementRule movement_rule) const
{
if (m_type == Stock || m_type == Waste || m_type == Play)
return false;
- if (m_type == Normal && is_empty())
- return card.value() == 12;
+ if (m_type == Normal && is_empty()) {
+ // FIXME: proper solution for this
+ if (movement_rule == Alternating) {
+ return card.value() == 12;
+ }
+ return true;
+ }
if (m_type == Foundation && is_empty())
return card.value() == 0;
@@ -173,7 +214,20 @@ bool CardStack::is_allowed_to_push(const Card& card, size_t stack_size) const
return false;
return top_card.type() == card.type() && m_stack.size() == card.value();
} else if (m_type == Normal) {
- return top_card.color() != card.color() && top_card.value() == card.value() + 1;
+ bool color_match;
+ switch (movement_rule) {
+ case Alternating:
+ color_match = card.color() != top_card.color();
+ break;
+ case Same:
+ color_match = card.color() == top_card.color();
+ break;
+ case Any:
+ color_match = true;
+ break;
+ }
+
+ return color_match && top_card.value() == card.value() + 1;
}
VERIFY_NOT_REACHED();
diff --git a/Userland/Libraries/LibCards/CardStack.h b/Userland/Libraries/LibCards/CardStack.h
index 75259b57b2..e368d15da7 100644
--- a/Userland/Libraries/LibCards/CardStack.h
+++ b/Userland/Libraries/LibCards/CardStack.h
@@ -24,6 +24,12 @@ public:
Foundation
};
+ enum MovementRule {
+ Alternating,
+ Same,
+ Any,
+ };
+
CardStack();
CardStack(const Gfx::IntPoint& position, Type type);
CardStack(const Gfx::IntPoint& position, Type type, NonnullRefPtr<CardStack> associated_stack);
@@ -44,8 +50,8 @@ public:
void move_to_stack(CardStack&);
void rebound_cards();
- bool is_allowed_to_push(const Card&, size_t stack_size = 1) const;
- void add_all_grabbed_cards(const Gfx::IntPoint& click_location, NonnullRefPtrVector<Card>& grabbed);
+ bool is_allowed_to_push(const Card&, size_t stack_size = 1, MovementRule movement_rule = Alternating) const;
+ void add_all_grabbed_cards(const Gfx::IntPoint& click_location, NonnullRefPtrVector<Card>& grabbed, MovementRule movement_rule = Alternating);
void draw(GUI::Painter&, const Gfx::Color& background_color);
void clear();