Age | Commit message (Collapse) | Author |
|
Scoring is designed to mimic Microsoft's implementation - starting at
500, decreasing by 1 every move, and increasing by 100 for every full
stack.
Fixes GH-5319.
|
|
The crash happens very rarely and is hard to reproduce so it is
hard to know for certain, but I am confident this fixes it.
I previously delayed the start of the game-over animation by one
frame, but neglected to check m_start_game_over_animation_next_frame
wasn't set. This means multiple calls to start_game_over_animation()
on the same frame (or rather, before the first timer_event) would
each call Object::start_timer(). Now that we do check the flag,
that should no longer be possible.
Fixes #8122.
|
|
"High score" should be two words, and this matches other games in the
system.
|
|
Previously, the high score was only in-memory, so only persisted for as
long as the FlappyBug window was open.
|
|
|
|
The PR for this pre-dates the concept of components, so it was forgotten
to add one.
|
|
We now have a nice sunset sky and some random cloud graphics.
The obstacles will get graphics at some point too :)
|
|
This adds some actual graphics to the game, and tweaks the obstacle and
sky colors. Eventually there will be graphics for those elements too.
|
|
This makes sure the player doesn't accidentally start a new game after
they bump into an obstacle.
|
|
Better information is now shown to the player. Instructions are shown
when first loading the program, and any available scores are shown on
the game over screen.
|
|
Previously obstacles were respawning fully on-screen which caused a
discontinuous look. Now they smoothly move into view from off-screen.
|
|
The position of the gap in the obstacle is now randomly generated each
time it spawns. The game is more fun to play now :)
|
|
This introduces a Flappy Bug game. It's pretty simple currently, but is
playable.
|
|
This adds component declarations so that users can select to not build
certain parts of the OS.
|
|
This fixes #7792.
The visual glitches with card corners, and the screen-clear when
opening a menu, were both caused by the widgets having
`fill_with_background_color` set. We need that set most of the time,
so we just disable it for the duration of the game-over animation.
Also resove a FIXME that no longer applies. :^)
|
|
Previously, the timer started if you clicked within the game area,
whether that was on a card or not. Now, we only start when you click
on a card or otherwise attempt a move.
As a bonus, we now immediately update the status bar time indicator
on game start, instead of having to wait until 1 second has elapsed.
|
|
|
|
Previously, if a tab-move moved all the remaining cards to the
foundations, the game would not notice until you moved a card
away and then back again.
I had to add a 1-frame delay to starting the animation, so that it
would have time to re-paint the foundation in that case.
|
|
Whether or not tiles moved used to be determined by comparing new_tiles
with m_tiles. This is no longer possible since the slide is done
in-place.
This fix makes the game look through the m_sliding_tiles, which contains
previous and current position for each tile on the board, to determine
whether any tile moved at all. If not, the move is deemed unsuccessful.
Fixes #8008.
|
|
|
|
This change brings all the board twiddling code into the Board proper to
enable sliding animations further down the line.
|
|
|
|
|
|
|
|
Keeping this as a separate commit as I'm not certain whether this
is a good change or not. The repeated if-else for each Foundation
stack bothered me a bit, though more so before I reduced the code
in the {}. But maybe the ifs are clearer than the loop?
Doing that also meant I could inline the move_card() code instead
of needing to make it a lambda. Again, maybe it would be better as
a lambda? I'm still figuring out the style Serenity uses, and I
know Andreas is big on expressiveness, and move_card() is more
expressive than just having the code in the loop.
|
|
Previously, pressing <tab> to auto-move cards would render all but
the last one that moved invisible. Now they all render correctly.
:^)
|
|
The two paths did the same thing, in two different ways. Now they
are the same. :^)
Can't quite put all of the logic into
attempt_to_move_card_to_foundations() because the double-click has
to check that you clicked on the top card.
|
|
Solitaire: Correct default arg definition location
|
|
|
|
|
|
Previously, AK::Function would accept _any_ callable type, and try to
call it when called, first with the given set of arguments, then with
zero arguments, and if all of those failed, it would simply not call the
function and **return a value-constructed Out type**.
This lead to many, many, many hard to debug situations when someone
forgot a `const` in their lambda argument types, and many cases of
people taking zero arguments in their lambdas to ignore them.
This commit reworks the Function interface to not include any such
surprising behaviour, if your function instance is not callable with
the declared argument set of the Function, it can simply not be
assigned to that Function instance, end of story.
|
|
|
|
Now that the cards have rounded corners, draw the stack box behind the
cards with rounded corners as well. This way, the corner of the stack
box doesn't peek out from behind the cards.
The caveat here is that the "play" card stack now needs to hold a
reference to the "waste" stack beneath it so it knows when not to draw
its background on top of the waste stack. To faciliate that, the array
of card stacks is now a NonnullRefPtrVector so the play stack can store
a smart pointer to the waste stack (instead of a raw pointer or
reference).
|
|
|
|
Also shifts logic of starting game length timer into function
`start_timer_if_necessary`, so it can be called from original
mouse event handler and new `auto_move_eligible_cards_to_stacks`
|
|
|
|
|
|
|
|
Previously the function did not sort the hand at all which means we
wouldn't necessarily pick the card with the highest value.
|
|
Previously we'd prefer to pass high points cards. Instead we should
prefer to pass high value cards first.
|
|
When we don't have a matching card for the lead card rather than
always preferring to play hearts we should try to get rid of our
high value cards first if no other player has hearts cards higher
than what we have.
|
|
When building Hearts with HEARTS_DEBUG we highlight the card the AI
would have picked. This makes comparing AI and human decisions easier.
|
|
When we're the third player in a trick and we don't have a lower value
card we would previously pick a slightly higher value card. Instead
we should pick the highest value card unless there are points in the
current trick or the lead card is spades and the higher value card
we would've picked is higher than the queen and another player still
has the queen.
The rationale is that we have to take the trick anyway so we might as
well get rid of our highest value card. If the trailing player has a
lower value card of the same type we take the trick but don't gain
any points. If they don't have a card of the same type it doesn't
matter whether we play a high value or low value card.
|
|
Previously the AI would prefer playing a lead card for which no other
player had a card with a higher value even though it also had a card
for which a higher value card was still in play.
|
|
Starts the game timer when the first card is clicked or moved instead of
when a new game is started.
Fixes #7489
|
|
This briefly inverts the selected card when the user attempts to make
an invalid play.
|
|
With different scoring rules for one-card vs. three-card draw mode, it
makes more sense to separately track their high scores.
|
|
The exact formula used for bonus points seems to vary by implementation.
This uses Klondike Solitaire's formula:
https://en.wikipedia.org/wiki/Klondike_(solitaire)#Scoring
|
|
Currently, the player loses 100 points each time the waste stack is
recycled. In three-card draw mode, it's standard to only lose 20 points
after the third recycle event.
|
|
This invocation will exit immediately. There's also no reason to invoke
stop_game_over_animation here because that's the first thing that will
happen in the call to setup.
|