Commit graph

110 commits

Author SHA1 Message Date
ItsDrike a52681c0b3
Make automove return what changed
This allows us to optimize the emitted signals, as we will know what has
changed after an automove.
2024-12-12 20:45:39 +01:00
ItsDrike 1ecfd36598
Restart the timer on game restar 2024-12-12 20:02:12 +01:00
ItsDrike 6ecfc64a79
Remove duplicate unused QVariantMap attr in isWinnable 2024-12-10 13:27:42 +01:00
ItsDrike 47b80c4e25
Change winnable in to pre-won in 2024-12-10 00:06:55 +01:00
ItsDrike 55f2d520b7
Use a cards image for redeal button 2024-12-10 00:05:06 +01:00
ItsDrike 098b45a3ff
Adjust setupWinningDeck to make a bit harder deck 2024-12-09 23:41:13 +01:00
ItsDrike 5a2e7d5465
Improve preliminary win check 2024-12-09 23:27:05 +01:00
ItsDrike d68b2ecbcb
Show winnable in X status 2024-12-09 23:24:37 +01:00
ItsDrike a4a91e09f9
Add redeal button 2024-12-09 23:02:16 +01:00
ItsDrike 48d1bd0a89
Add win overlay 2024-12-09 21:02:43 +01:00
ItsDrike d21e9d1336
Fix SVG scaling in QML
For some reason, the default QML Image element doesn't scale SVGs like
it should. Essentially, it just reads the source size of the SVG and
scales it like it would a regular image (say PNG).

I'm fixing this by manually setting the source size of the image to the
current size. That said, this is in my opinion a hacky fix and it's
really weird that QML doesn't special-case SVGs and scale them as it
should.

Source:
https://stackoverflow.com/questions/69641034/qml-image-does-not-stretch-fit-svg
2024-12-09 20:57:51 +01:00
ItsDrike e56171f49c
Show game status in scorebar 2024-12-09 19:40:36 +01:00
ItsDrike b0630c2690
Store isWinnable as QVariant
QML doesn't natively support the complex type returned from isWinnable
property (`std::pair<std::optional<bool>, int>`), instead use
QVariantMap to implement custom attributes and return as QVariant.
2024-12-09 19:34:29 +01:00
ItsDrike c5e68601a4
Convert winnability check to property 2024-12-08 17:08:15 +01:00
ItsDrike 3254818410
Add preliminary win detection 2024-12-08 14:43:52 +01:00
ItsDrike e46d153604
Add game timer 2024-12-08 14:02:04 +01:00
ItsDrike 7ef0ade0b3
Keep track of move amount 2024-12-08 13:58:18 +01:00
ItsDrike fab342c71f
Remove no longer valid debug comment 2024-12-08 13:52:32 +01:00
ItsDrike 811900c75f
Use a saner default app dimensions (bigger height) 2024-12-08 13:14:44 +01:00
ItsDrike 57958ed853
Dynamically scale the cards & everything else
Currently, most things were scaled based on the card dimensions,
though some things were hard-coded. This commit moves away from all
hard-coded sizes in favor of everything relying on card heights.

Additionally, it makes the card height itself no longer hard-coded,
passing it as a property to most custom structures.

The card height itself is now calculated from Main.qml to make sure
everything fits within the screen and scales as the window is resized.
2024-12-08 13:09:15 +01:00
ItsDrike 511ca3744a
Improve rendering of empty cards in tableau columns 2024-12-08 00:18:33 +01:00
ItsDrike 70be6491a3
Improve foundation pile design when empty 2024-12-07 23:19:44 +01:00
ItsDrike 042720d10b
List items in qrc in alphabetical order 2024-12-07 23:17:34 +01:00
ItsDrike 459b23df2b
Add proper design for the draw pile 2024-12-07 23:17:30 +01:00
ItsDrike 190795fdf7
Add flip icon for empty draw pile 2024-12-07 22:16:37 +01:00
ItsDrike 88cdf28cfc
Use unique ptr for nicer memory freeing in win simulation func
This also switches from using `QQueue` here to `std::queue` as `QQueue`
doesn't seem to play well with holding unique pointers.
2024-12-07 21:26:28 +01:00
ItsDrike b209fbc94b
Use BFS approach for win simulation, not DFS
The original approach here was using depth-limited depth first search,
which was a hacky workaround to avoid exploring a single branch too
deeply. A much saner approach is to just explore in a breadth-first
manner.

This also completely negates the need for depth limitations and we can
instead let the algorithm run until it either finishes or hits the time
limit, as we always want to explore as much depth as we can, without it
slowing down the responsiveness of the UI.
2024-12-07 21:26:28 +01:00
ItsDrike 7cc52f272d
Add safe-guard against value underflow in column move check 2024-12-07 21:26:23 +01:00
ItsDrike bea2be5f63
bug: Fix state hash for empty piles
The current implementation of state hash doesn't represent empty columns
or foundations properly. This leads to a potential collision if there is
a full column next to an empty column, as it's indistinguishable which
column the data lies on. (In practice, this can't happen for
foundations, as they only hold cards of distinct types, so the collision
only occurs with columns.)

This commit fixes the issue and makes sure to represent empty piles
properly.
2024-12-07 20:48:41 +01:00
ItsDrike 985e99cf77
bug: fix moveColumnCardToColumn for multi-card moves 2024-12-07 20:44:10 +01:00
ItsDrike 36167edc78
Register parent QObjects properly 2024-12-07 13:30:02 +01:00
ItsDrike aa446e9c43
Enforce LF through gitattributes 2024-12-07 12:55:00 +01:00
ItsDrike 4426d83438
Add editorconfig file 2024-12-07 12:53:46 +01:00
ItsDrike 9be91f0942
Remove left over unneccessary clean-up logic 2024-12-07 12:49:28 +01:00
ItsDrike 3ab8cfb7dc
Clean up GameState constructor 2024-12-07 12:34:11 +01:00
ItsDrike fdc3405366
Limit runtime for win scenario calculations
Depth limit alone often does a poor job at ensuring the simulation
doesn't take too long, as the amount of branches may differ depending on
the game and in some cases, the function can take way too long.

This solution introduces another stop condition, based on the runtime
of the evaluation, ensuring we don't block the game for too long.

Note that the original depth limiting, while fairly effective is a hacky
solution, instead, it may be a good idea to change the simulation logic
from DFS to BFS based search.
2024-12-07 12:26:47 +01:00
ItsDrike 1eb72163b5
Fix win simulation unnecessarily drawing same card 2024-12-07 12:02:55 +01:00
ItsDrike 0bee5ddc12
bug: ignore correct column for moving multiple cards 2024-12-06 18:38:25 +01:00
ItsDrike b2cad5ac14
bug: Don't reverse throwaway pile on flipping 2024-12-06 18:37:44 +01:00
ItsDrike 2b44a39ee8
slight code clean up 2024-12-06 17:09:19 +01:00
ItsDrike 18891308bc
bug: fix manual cross-column movement logic
The original implementation didn't use references for the QList
instances, which meant they were getting copied, so the changes made
didn't mutate the actual values held by the class.
2024-12-06 17:08:34 +01:00
ItsDrike 5240949353
Significantly optimize the winnability simulation
The original approach for calculating winnability first checked for
inter-column movements, which isn't ideal, instead, the new logic now
first attempts to make foundation pile movements. Additionally, this
converts the function to return an option value, which will be null if
the winnability check fails to determine the result within given maximum
depth. This is a necessary check, as the original logic took really long
to finish, especially if ran at the beginning of the game, where it
could keep going for hundreds of moves.
2024-12-06 17:04:15 +01:00
ItsDrike 2ec6206e26
Improve hash state computing
The new logic avoids possible collisions that could previously occur.
2024-12-06 17:01:24 +01:00
ItsDrike 5da97d7c0e
Add a destructor 2024-12-06 16:59:54 +01:00
ItsDrike 135d16daae
Add winnability check 2024-12-06 05:08:58 +01:00
ItsDrike eec98ba110
Return bool (success status) from drawNextCard 2024-12-06 04:54:34 +01:00
ItsDrike 206ff25a1a
Make parent the first arg in PlayingCard constructor 2024-12-06 04:33:29 +01:00
ItsDrike 03e74a6c67
Const correctness for valid move checks 2024-12-06 03:49:25 +01:00
ItsDrike 4692ce356b
Return QVariantList objects instead of QList
QML doesn't have a proper type-safe generic list type, returning QList
instances does technically work, however, qmlls (LSP) complains about
using this as it isn't a proper QML type. Instead, return QVarianList
objects, that are meant for QML.
2024-12-06 03:40:23 +01:00
ItsDrike 84a8aa57d6
Don't use deprecated SIGNAL & SLOT macros 2024-12-06 03:39:34 +01:00