diff --git a/Userland/Games/Solitaire/CardStack.cpp b/Userland/Games/Solitaire/CardStack.cpp index a9ecfa1435..d7694b90bc 100644 --- a/Userland/Games/Solitaire/CardStack.cpp +++ b/Userland/Games/Solitaire/CardStack.cpp @@ -52,6 +52,8 @@ void CardStack::draw(GUI::Painter& painter, const Gfx::Color& background_color) } break; case Waste: + break; + case Play: if (is_empty() || (m_stack.size() == 1 && peek().is_moving())) painter.draw_rect(m_base, background_color.darkened(0.5)); break; @@ -131,7 +133,7 @@ void CardStack::add_all_grabbed_cards(const Gfx::IntPoint& click_location, Nonnu bool CardStack::is_allowed_to_push(const Card& card) const { - if (m_type == Stock || m_type == Waste) + if (m_type == Stock || m_type == Waste || m_type == Play) return false; if (m_type == Normal && is_empty()) @@ -191,6 +193,17 @@ NonnullRefPtr CardStack::pop() return card; } +void CardStack::move_to_stack(CardStack& stack) +{ + while (!m_stack.is_empty()) { + auto card = m_stack.take_first(); + m_stack_positions.take_first(); + stack.push(move(card)); + } + + calculate_bounding_box(); +} + void CardStack::calculate_bounding_box() { m_bounding_box = Gfx::IntRect(m_position, { Card::width, Card::height }); diff --git a/Userland/Games/Solitaire/CardStack.h b/Userland/Games/Solitaire/CardStack.h index 5521b54194..5acd22d473 100644 --- a/Userland/Games/Solitaire/CardStack.h +++ b/Userland/Games/Solitaire/CardStack.h @@ -18,6 +18,7 @@ public: Stock, Normal, Waste, + Play, Foundation }; @@ -36,6 +37,7 @@ public: void push(NonnullRefPtr card); NonnullRefPtr pop(); + void move_to_stack(CardStack&); void rebound_cards(); bool is_allowed_to_push(const Card&) const; @@ -59,8 +61,11 @@ private: case Normal: return { 0, 20, 1, 3 }; case Stock: - case Waste: return { 2, 1, 8, 1 }; + case Waste: + return { 0, 0, 1, 0 }; + case Play: + return { 20, 0, 1, 0 }; default: return {}; } diff --git a/Userland/Games/Solitaire/Game.cpp b/Userland/Games/Solitaire/Game.cpp index 6e1f29d5a6..1b041ef16a 100644 --- a/Userland/Games/Solitaire/Game.cpp +++ b/Userland/Games/Solitaire/Game.cpp @@ -22,6 +22,7 @@ Game::Game() m_stacks[Stock] = CardStack({ 10, 10 }, CardStack::Type::Stock); m_stacks[Waste] = CardStack({ 10 + Card::width + 10, 10 }, CardStack::Type::Waste); + m_stacks[Play] = CardStack({ 10 + Card::width + 10, 10 }, CardStack::Type::Play); m_stacks[Foundation4] = CardStack({ Game::width - Card::width - 10, 10 }, CardStack::Type::Foundation); m_stacks[Foundation3] = CardStack({ Game::width - 2 * Card::width - 20, 10 }, CardStack::Type::Foundation); m_stacks[Foundation2] = CardStack({ Game::width - 3 * Card::width - 30, 10 }, CardStack::Type::Foundation); @@ -148,16 +149,26 @@ void Game::mousedown_event(GUI::MouseEvent& event) auto click_location = event.position(); for (auto& to_check : m_stacks) { + if (to_check.type() == CardStack::Type::Waste) + continue; + if (to_check.bounding_box().contains(click_location)) { if (to_check.type() == CardStack::Type::Stock) { auto& waste = stack(Waste); auto& stock = stack(Stock); + auto& play = stack(Play); if (stock.is_empty()) { - if (waste.is_empty()) + if (waste.is_empty() && play.is_empty()) return; update(waste.bounding_box()); + update(play.bounding_box()); + + while (!play.is_empty()) { + auto card = play.pop(); + stock.push(card); + } while (!waste.is_empty()) { auto card = waste.pop(); @@ -167,9 +178,9 @@ void Game::mousedown_event(GUI::MouseEvent& event) update_score(-100); update(stock.bounding_box()); } else { - move_card(stock, waste); + play.move_to_stack(waste); + move_card(stock, play); } - } else if (!to_check.is_empty()) { auto& top_card = to_check.peek(); @@ -213,12 +224,21 @@ void Game::mouseup_event(GUI::MouseEvent& event) m_focused_stack->pop(); } + if (m_focused_stack->type() == CardStack::Type::Play) { + auto& waste = this->stack(Waste); + if (m_focused_stack->is_empty() && !waste.is_empty()) { + auto card = waste.pop(); + m_focused_cards.append(card); + m_focused_stack->push(move(card)); + } + } + update(m_focused_stack->bounding_box()); update(stack.bounding_box()); - if (m_focused_stack->type() == CardStack::Type::Waste && stack.type() == CardStack::Type::Normal) { + if (m_focused_stack->type() == CardStack::Type::Play && stack.type() == CardStack::Type::Normal) { update_score(5); - } else if (m_focused_stack->type() == CardStack::Type::Waste && stack.type() == CardStack::Type::Foundation) { + } else if (m_focused_stack->type() == CardStack::Type::Play && stack.type() == CardStack::Type::Foundation) { update_score(10); } else if (m_focused_stack->type() == CardStack::Type::Normal && stack.type() == CardStack::Type::Foundation) { update_score(10); @@ -279,7 +299,7 @@ void Game::doubleclick_event(GUI::MouseEvent& event) auto click_location = event.position(); for (auto& to_check : m_stacks) { - if (to_check.type() == CardStack::Type::Foundation || to_check.type() == CardStack::Type::Stock) + if (to_check.type() == CardStack::Type::Foundation || to_check.type() == CardStack::Type::Stock || to_check.type() == CardStack::Type::Waste) continue; if (to_check.bounding_box().contains(click_location) && !to_check.is_empty()) { @@ -296,6 +316,15 @@ void Game::doubleclick_event(GUI::MouseEvent& event) else break; + if (to_check.type() == CardStack::Type::Play) { + auto& waste = this->stack(Waste); + if (to_check.is_empty() && !waste.is_empty()) { + auto card = waste.pop(); + m_focused_cards.append(card); + to_check.push(move(card)); + } + } + update_score(10); } break; diff --git a/Userland/Games/Solitaire/Game.h b/Userland/Games/Solitaire/Game.h index 0a4902154f..9fa44b1a6e 100644 --- a/Userland/Games/Solitaire/Game.h +++ b/Userland/Games/Solitaire/Game.h @@ -84,6 +84,7 @@ private: enum StackLocation { Stock, Waste, + Play, Foundation1, Foundation2, Foundation3,