summaryrefslogtreecommitdiff
path: root/Userland/Games/Spider/Game.h
blob: cea44a1961568c7b8d3ad439848a3726c976aa20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * Copyright (c) 2021, Jamie Mansfield <jmansfield@cadixdev.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Array.h>
#include <LibCards/CardStack.h>
#include <LibGUI/Frame.h>

using Cards::Card;
using Cards::CardStack;

namespace Spider {

enum class Mode : u8 {
    SingleSuit,
    TwoSuit,
    __Count
};

enum class GameOverReason {
    Victory,
    NewGame,
};

class Game final : public GUI::Frame {
    C_OBJECT(Game)
public:
    static constexpr int width = 10 + 10 * Card::width + 90 + 10;
    static constexpr int height = 480;

    ~Game() override;

    Mode mode() const { return m_mode; }
    void setup(Mode);

    Function<void(uint32_t)> on_score_update;
    Function<void()> on_game_start;
    Function<void(GameOverReason, uint32_t)> on_game_end;

private:
    Game();

    enum StackLocation {
        Completed,
        Stock,
        Pile1,
        Pile2,
        Pile3,
        Pile4,
        Pile5,
        Pile6,
        Pile7,
        Pile8,
        Pile9,
        Pile10,
        __Count
    };
    static constexpr Array piles = {
        Pile1, Pile2, Pile3, Pile4, Pile5,
        Pile6, Pile7, Pile8, Pile9, Pile10
    };

    void start_timer_if_necessary();
    void update_score(int delta);
    void draw_cards();
    void ensure_top_card_is_visible(NonnullRefPtr<CardStack> stack);
    void detect_full_stacks();
    void detect_victory();

    ALWAYS_INLINE CardStack& stack(StackLocation location)
    {
        return m_stacks[location];
    }

    void paint_event(GUI::PaintEvent&) override;
    void mousedown_event(GUI::MouseEvent&) override;
    void mouseup_event(GUI::MouseEvent&) override;
    void mousemove_event(GUI::MouseEvent&) override;
    void timer_event(Core::TimerEvent&) override;

    Mode m_mode { Mode::SingleSuit };

    NonnullRefPtrVector<Card> m_focused_cards;
    NonnullRefPtrVector<Card> m_new_deck;
    NonnullRefPtrVector<CardStack> m_stacks;
    CardStack* m_focused_stack { nullptr };
    Gfx::IntPoint m_mouse_down_location;

    bool m_mouse_down { false };

    bool m_waiting_for_new_game { true };
    bool m_new_game_animation { false };
    uint8_t m_new_game_animation_delay { 0 };
    uint8_t m_new_game_animation_pile { 0 };

    uint32_t m_score { 500 };
};

}