Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC new position rep #7

Merged
merged 2 commits into from
Oct 17, 2021
Merged

POC new position rep #7

merged 2 commits into from
Oct 17, 2021

Conversation

santiweight
Copy link
Owner

What do you think of this design. Biggest issue is obviously having to pass around the NumPlayers (I prefer TableSize in hindsight). We could do something like (I think I'm making a mistake or two here, but you'll probably get the picture):

data TableSize = HeadsUp | ThreeMax | FourMax | SixMax ...

instance KnownNat HeadsUp where
  natSing = 2

data Position (n :: TableSize) where
  Position :: forall (n :: TableSize). Word8 -> Position n

mkPosition :: TableSize -> Word8 -> Position
mkPosition HeadsUp pos = {- check bounds -} Position @HeadsUp pos

Although I'd be worried about having to require everyone to use an existential Position (we could hide the singletons):

data SomePosition where
  SomePosition :: STableSize -> Word8 -> SomePosition 

@tonyday567
Copy link
Collaborator

I know I criticised Position yesterday, but then I saw that it comes out from histories just like that, and thought ok, I get it.

Can we have both? I was especially thinking that it makes it much easier to write histories. It's like a naming scheme for the players at a table, ie once the table size has been locked in then you are called UTG2 or whatever for the duration.

I think KnownNat type-level tracking might be a bit restrictive. Strategy analysis probably varies more according to SecondToAct on the Turn or whatnot and this type of labelling changes as player actions occur.

@santiweight
Copy link
Owner Author

santiweight commented Oct 6, 2021

I don't get the second issue you raised about the type-level tracking being restrictive - wouldn't figuring out second-to-act still require passing around the number of players either way? I think the type-level approach is better with the only caveats being simplicity (for a non-expert) and runtime representation only. The only thing carried around at the type level would be how many players started the hand, which afaik never changes and would be useful throughout a hand.

"Can we have both?". I was wondering about that too... I wonder if we could have both via pattern synonyms? But that would probably still require some type-level trickery... It might be a good idea for me to test poker-histories on this new representation and see whether it causes any issues (I suspect not).

We should also check other libraries maybe? How do you normally do Position?

@tonyday567
Copy link
Collaborator

Position

The way you're doing it in the PR is close to mine.

Like, in my mind, position is very different. I'm in the HJ seat and BU is a wimp, gunna steal some chips here. (LJ = LowJack, btw?).

But I think representation-wise, using sum types here can lead you astray. Something like:

tableSize = 9
players = [0,1,2,3,4,5,6,7,8] (index into a list, say)
button = 8
preFlopActFirst = 1
postFlopActFirst = 9

And then you just (mod) increment a nextToAct cursor. It's partly just the way my mind works - that I see these calculations as mod integer arithmetic and the sum-type names just add confusion. But I can't see where you may need to have an unordered [Position] and then need to sort it.

With mod arithmetic there is also no confusion in heads-up.

Restrictions of type-level programming:

So if I want to calculate the expected payoff of AKo in CO for table size 2 to 9, I'll have to type-level code a list?

@santiweight
Copy link
Owner Author

LJ = lowjack yeah. I've seen it spelled Lojack mostly though - maybe I'm imagining that though?

I think about Position in the same way - so I think I agree with everything you've said. You might be right about never needing to sort an unordered [Position] - just rotate it until you get where you want to be... We should definitely code it like that when we get there. The branch I wrote is just easy-first. I'm happy to sift through the muck before mergning.

Restrictions of type-level programming:
So if I want to calculate the expected payoff of AKo in CO for table size 2 to 9, I'll have to type-level code a list?

I don't think so? I don't think I quite grasp the question you're asking, maybe could you write the type signature you want and I could try to come up with what the tagged Position version would look like?

Either way - we should stay away from the type level thing until everything is stable and then we can revisit I think - but I agree with your apprehension - I too would be surprised if it didn't introduce a lot of complexity. Let's just defer the type-safe Position for now and go with something like what I wrote. You're welcome to hijack this branch if you'd like. If not I'll take another stab at this tomorrow with a little less hackiness and then we can try get a review through a PR.

Copy link
Collaborator

@tonyday567 tonyday567 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a quick glance, it looks great, but I don't have the time right now to dig in to it.

Ship it!

@santiweight santiweight merged commit e7f09a5 into main Oct 17, 2021
@santiweight santiweight mentioned this pull request Oct 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants