mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:57:44 +00:00
Solitaire: Add stack for the playable cards on top of the waste stack
While the waste stack and the playable card on top of the waste stack are collectively referred to as the "waste", it's programatically nice to separate them to enable 3-card-draw mode. In that mode, the playable stack will contain 3 cards with a slight x-axis shift, while the waste stack underneath will remain unshifted. So rather than introducing some ugly logic to CardStack to handle this, it's more convenient to have a separate stack on top of the waste stack.
This commit is contained in:
parent
d5ea04cdfb
commit
3a45bf5254
4 changed files with 56 additions and 8 deletions
|
@ -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<Card> 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 });
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
Stock,
|
||||
Normal,
|
||||
Waste,
|
||||
Play,
|
||||
Foundation
|
||||
};
|
||||
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
|
||||
void push(NonnullRefPtr<Card> card);
|
||||
NonnullRefPtr<Card> 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 {};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -84,6 +84,7 @@ private:
|
|||
enum StackLocation {
|
||||
Stock,
|
||||
Waste,
|
||||
Play,
|
||||
Foundation1,
|
||||
Foundation2,
|
||||
Foundation3,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue