Age | Commit message (Collapse) | Author |
|
|
|
|
|
I've added a dependency so if lib.macros isn't working, we can skip
all the tests in lib.functions. Therefore we can use lib.macros in
the test code.
|
|
|
|
|
|
Setup cantedraw/tests with a test-system record, as well as linking it
back to cantedraw so we can run test-system on cantedraw and run the
tests.
Using parachute, we can setup a suite of unit tests for each package.
For each package in src/ or lib/ we'll write a separate unit test
suite with tests for all the public exposing functionality.
I've setup a main suite in cantedraw/tests/main which will depend on
each of the unit test suites so we can run the tests all at once.
Currently we have one test for the --> macro.
|
|
|
|
|
|
Instead of an association list and a type contract, let's use a hash
table and a structure. This is: more explicit, encapsulates state
more effectively, generates much of the cruft (constructors,
destructors) for me.
A hash table is more efficient when considering large player bases.
In particular, we'll be generating unique player IDs to make it a bit
more difficult for a malicious agent to guess another player's ID and
make bad requests.
|
|
|
|
|
|
|
|
Clean up the implementation of player-pay and player-receive by:
- Single-clause early-error `if` for errors
- use `incf`/`decf` instead of `setf`.
|
|
Custom errors for malformed/nonexistent player IDs as well as a player
not having a high enough balance for the money requested.
This will allow me to encode more information in the errors, for
callers to use. I'm generally of the opinion that callers should be
checking error conditions before calling these functions, but per
Murphy's law it would be nice to have more information in the error
message.
|
|
This package defines a player data structure, collections of players,
and different interactions you can have with them:
- Extracting attributes (destructors)
- Checking if they're bankrupt or can bet
- Modifying a collection to adjust the balance of any one
player (including errors in case that isn't possible)
|
|
|
|
In case operators require use of a variable, we should let the caller
provide the symbol so we don't fall into weird package issues.
|
|
|
|
Found that I sometimes did a misinput which lead to losing a critical
card - implemented a function which asks for confirmation (with a
print out of the cards that will be redealt) before doing the redeal.
|
|
We've now got one of the major stages of the game down.
I think it's worth investing in some testing functions now - we've
reached just the level of complexity.
|
|
Like REPL stands for Read -> Evaluate -> Print -> Loop, here we
implement a similar loop which reads a set of indices for cards to
remove from the user, redeals those cards then loops back.
This keeps happening until either:
- the user does not want to redeal (empty input)
- there aren't enough cards for a redeal
|
|
Due to the way random works, we need to see it on each run of the
binary - thus need to make a new random state.
|
|
A player may:
- not redeal any cards
- redeal all their cards
Therefore the indices must be between 0,5 and there can be at most 5
inputs.
|
|
|
|
Currently can deal some hands and redeal some cards.
|
|
|
|
|
|
|
|
Gives a hand from a shuffled deck to the user, asks them to provide
indices for cards they wish to re-deal then does so.
|
|
|
|
This new version is terser while still expressing what I want.
|
|
`$` takes a list of forms and makes a unary function which applies
them via `->>`. Previous definition reversed the forms supplied
s.t. `$` was closer to the applicative operator in Haskell i.e. the
function (<$> f g) is f(g(x)). But this version fits closer with the
lower operator (->>) being used AND allows easier lifting from
`->>` (which produces a value) to `$` (which produces a function).
|
|
Joker constructor takes a rank for uniqueness - rank doesn't really
change anything in terms of the "power" of a joker but helps with
ensuring jokers are unique in a deck.
Deck constructor takes an optional argument for the number of decks.
A deck includes two jokers, so n decks include 2n jokers.
|
|
Because I assume n is modded already.
|
|
I can now use this package for a console application since we can
pretty print cards.
|
|
|
|
Generally, ACE is the best card in Cantedraw in a card-by-card basis
thus it should be the higher when comparing.
|
|
Given n in 0..51, certainly there exists r, s s.t. `n = 13s + r`
where r in 0..12 and s in 0..3. `r` is the rank, and `s` is the suit.
ranks are ordered Ace, 2, 3, ..., Queen, King and suits are ordered
Diamond, Club, Heart, Spade.
Therefore there is a 1-1 correspondence between 0..51 and any card in
the deck.
Jokers are a bit less straightforward; for now I'll define them as an
outlier which doesn't exist in the same bounds (which is why they're
the default return for suit in int->suit). Likely I'll go for -1
representing a Joker.
|
|
Time to do the fun non-yakshaving part. I'll start out by writing
some custom types for the objects of concern: ranks, suits, cards and
sets of cards.
|
|
Instead of exporting cantedraw.lib.macro._ and making anyone who wants
to use the --> macro _require_ importing that specific symbol, let's
just make it so the user has to supply a placeholder name before they
do anything. This means each package provides its own placeholder
symbol which lowers coupling.
|
|
This is mostly a sanity check in-case anyone else decides to load this
system for use in their own package - don't want to conflict with
their names.
|
|
|
|
|
|
|
|
|
|
Why name it something unique when this is what I'm going to be making
at the end of it all? Just makes it more confusing for the end user.
|
|
|
|
|
|
|
|
|