egonschiele / dominion Goto Github PK
View Code? Open in Web Editor NEWA Dominion simulator in Haskell
License: Other
A Dominion simulator in Haskell
License: Other
I noticed
dominion/src/Dominion/Internal.hs
Line 425 in 2f4ff82
libraryChoice :: [Card] -> [Card] -> Card -> Bool
libraryChoice cardsInHand cardsSetAside cardRevealed = -- choose whether to keep it
This isn't quite all the information available (eg, how many cards are left before my shuffle?), so maybe it needs to be lifted into State somehow, but I think it's close enough. If you agree, I think it's within my ability to make that change.
I don't really know how to run any of this code right now "in isolation" - things seem geared towards playing entire games with a specified strategy. But there are a number of effects that I think have issues, and I'd like a way to write a test like "Here is a player's hand. After he does XYZ, his hand should change as follows, and the supply/trash should change as follows." This would help me verify my understanding of how things are put together, so that I can properly direct my efforts at improving them.
One example is that I think you're discarding cards immediately after playing them, rather than putting them into the play area and then discarding post-turn, which would be quite bad. Additionally, some trash/discard effects are not judicious enough, and can affect other cards in hand unintentionally. I'd like to test a player holding Throne Room and three Feast cards, and throning one of them. It should be the case that the played Feast is trashed while the other two stay in hand, and the player gains two cards. But I suspect that instead two Feasts will be trashed and one will be discarded.
In expansion sets, there are a lot of cards that are more complicated than the things in Base: especially interesting are cards that "react" by interrupting a play in progress, doing something else, and then letting the play continue. Two interesting examples are Market Square and Haggler. Market Square can (optionally) fire any time it's in your hand when one of your cards is trashed, which might be during your turn or an opponent's turn. Haggler isn't technically a Reaction card, but when played it creates lasting effects with the "while this is in play, when you buy a card, gain a card costing less than it which is not a victory card" wording.
Cards like this aren't very easy to deal with in the current setup, where a lot of the engine logic directly manipulates [Card]
values representing decks, hands, and piles. How can a Market Square know to trigger if, eg, Moneylender just calls delete CA.copper hand
?
A solution that occurred to me tonight is to have these card effects be reified as values, and have a continuation associated with them: "trash a copper from my hand, and when you're done with that give me +3 coins" can be represented as Effect (Trash CA.copper) (\_ -> (AddCoins 3))
. This Effect
value gets passed to the engine, which processes any eligible on-trash effects and then calls the continuation to allow the Moneylender to continue its processing.
And I think you can wrap that plumbing up in a new monad (I don't think it's actually close to the Continuation monad, but I could be wrong), so that you can instead write something like:
resolve moneylender =
when (CA.copper `elem` hand) $ do
trash CA.copper
addCoins 3
I think this general approach even allows for crazy cards like Possession, which will be intercepting each Gain effect to change what player gains the card.
So how does this sound? I think it requires some pretty big changes to the existing code, so definitely requires careful consideration.
Would you be interested in me replacing _cards
in GameState
with a more efficient data structure? Perhaps with this library. I realize that it's not a huge deal since the number of cards in a game isn't massive, but I think it would be bennificial.
Citing from http://hydra.cryp.to/build/875727/log/raw:
running tests
Running 1 test suites...
Test suite test-dominion: RUNNING...
integration tests
player sherlock won 1000 times
player watson won 0 times
the stupid strategy of only buying provinces and golds should never win
player sherlock won 351 times
player watson won 649 times
bigMoney2 should win 1.4 times as often as bigMoney
player sherlock won 579 times
player watson won 421 times
bigMoneySmithy should win 1.4 times as often as bigMoney2 FAILED [1]
Failures:
1) integration tests bigMoneySmithy should win 1.4 times as often as bigMoney2
expected: True
but got: False
Randomized with seed 1337324813
Finished in 6.4645 seconds
3 examples, 1 failure
Test suite test-dominion: FAIL
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.