Recent

Author Topic: [SOLVED] wildcard utilities list  (Read 643 times)

mas steindorff

  • Hero Member
  • *****
  • Posts: 593
[SOLVED] wildcard utilities list
« on: May 17, 2026, 12:22:21 am »
My latest self learning project is a poker card game. It's working well for standard deck of 52 cards where each card (in a hand or deck) is a pointer to a card info record I call TCard. I have a "hand" (specialize TFPGList<^card_info_rec>; Score generator that checks the hand.items[] for all of the poker sets (4 of a kind, full house, flush....
Now I'm adding wild cards. My current code simply replaces THE wild card with each posable card in the deck and after testing all 52 options, picks the option that generated the highest score for that hand.  so far so good but what if I have 2 or 3 wild cards?
I need to test 52 * 51 *50  card combos. I can work this out but then wondered if the pascal libs already had something.
does anyone know if there is a TryListItem(Item_to_be_swapped, list_of_items)?
it would be used something like
Code: Pascal  [Select][+][-]
  1. ...
  2. var Score_array :array of integer;
  3. Score_array := GenhandScore(hand, TryListItem(wildcard^, DeckOfCards))
  4.  
the "wildcard" I've found in pascal look more like a file find option to me.
Suggestion? and Thank you
MAS
 
« Last Edit: May 20, 2026, 08:22:04 am by mas steindorff »
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

mas steindorff

  • Hero Member
  • *****
  • Posts: 593
Re: wildcard utilities list
« Reply #1 on: May 17, 2026, 11:01:19 pm »
After some thinking, I figured the best approach is to just use a recursive function here. 
I do not see another .sort() type list property I can assign a "try with member of another list member" function to in the TFPGList critter.

Thanks for your time. MAS
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Thaddy

  • Hero Member
  • *****
  • Posts: 19273
  • Glad to be alive.
Re: wildcard utilities list
« Reply #2 on: May 18, 2026, 12:07:34 pm »
With wildcards you will still need a sorted collection. That will be faster.
objects are fine constructs. You can even initialize them with constructors.

Zvoni

  • Hero Member
  • *****
  • Posts: 3399
Re: wildcard utilities list
« Reply #3 on: May 18, 2026, 12:34:18 pm »
Now I'm adding wild cards. My current code simply replaces THE wild card with each posable card in the deck and after testing all 52 options, picks the option that generated the highest score for that hand. 
Why are you checking against the full deck?
Check against the cards on Hand (opt. incl. Flop)

In "Texas Hold-em" it would be max. 6 checks against the available values (e.g. King, Queen, Ace etc.), and max. 4 checks against face (Spades, Diamonds etc.)
on 3 turns (Flop, Turn, River).
EDIT: Actually... no idea how many checks it would involve (see below)

and the checks would have to be only against combinations providing greater winning-chances for what's already on Hand/Flop
e.g. with no wildcards, player has 3 of a kind (say after Flop)
Turn gives a Wildcard
You only have to check against combinations above 3 of a kind (e.g. do i get a FullHouse etc.)
« Last Edit: May 18, 2026, 02:16:38 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 19273
  • Glad to be alive.
Re: wildcard utilities list
« Reply #4 on: May 18, 2026, 12:47:15 pm »
Good idea. And you can sets for that + include/exclude. I can write you an example for that of you want,
objects are fine constructs. You can even initialize them with constructors.

Zvoni

  • Hero Member
  • *****
  • Posts: 3399
Re: wildcard utilities list
« Reply #5 on: May 18, 2026, 01:50:56 pm »
btw: And i would check Top-Down instead of Bottom-Up

in my example above (3 of kind on hand/Flop), the obvious one would be 4 of a kind, and there is only two above it: Straight Flush and Royal Flush.
So basically: 3 checks
1st for Royal Flush --> there might be "sub"-checks --> Royal Flush is a Straight from Ace down in the same face
2nd for Straight Flush --> there might be "sub"-checks --> Same as Royal Flush, but highest Card is NOT an Ace (HINT!!)
3rd 4 of a Kind
Done

Bottom-Up you would have way more checks (Straight, Flush, Full-House...)

To throw some spice into your scenario: What if player has 4 of a kind on Hand/Flop, and THEN comes a wildcard?
is "5 of a Kind" a valid combination?

Next: Think about a "strategy" for the subchecks
In my example above:
check for Royal Flush:
Check if highest Card is an Ace -->
If Yes, Check if all Cards are same face --> Here you would already have "Flush" -->
  If Yes, check if Values are consecutive down from Ace
  If No, you don't have to check for Straight Flush

Check for Straight Flush: If Highest Card not Ace (see above) continue here:
Check for same face -->
If yes, you already have flush --> Check for consecutive values down from highest Card
If no, Check for consecutive values down from highest Card --> If yes, you alreday have straight

checking for a "4 of a Kind" it doesn't make sense to check for face

checking for a "Full House" it doesn't make sense to check for face.
--> This check only makes sense, if you have 2 pairs. And 2 pairs implies at least two faces used (up to all 4)
with Subcheck "3 of a kind"-Values <> "pair"-Values, because otherwise you would have "4 of a kind" --> Last subcheck: Which one of the 2 pairs has the higher Value

checking for a "flush" it doesn't make sense to check for value --> can be skipped completely if Royal/Straight Flush failed Flush-criteria
checking for a "straight" it doesn't make sense to check for face --> just check consecutive values from highest card down. Can be skipped completely if Royal/Straight flush failed "straight"-criteria (though since it would satisfy "flush"-criteria, you wouldn't even reach here)
and so on

This is just out of my left sleeve. There might be mistakes in my logic, but i think you get the gist of it

Last EDIT (hopefully  :P):
You mentioned having a TCard-Record.
I take it you have a Field for "value" and a field for "face"
I would set the Values as follows:
"2" to "10" --> 2 to 10
Jack --> 11
Queen --> 12
King --> 13
Ace --> 14
There is no "Value" of 1.....
Have a guess why.....
« Last Edit: May 18, 2026, 03:20:10 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Warfley

  • Hero Member
  • *****
  • Posts: 2067
Re: wildcard utilities list
« Reply #6 on: May 18, 2026, 04:48:48 pm »
I do not know that much about poker, but if you check all possible cards, you will re-check basically the same result just differently. Like a flush is always a flush no matter which cards you have. Also in Poker you have hierachical points so you have Royal Flush > Straight Flush > ...

So the easiest way is to simply have a function like:
Code: Pascal  [Select][+][-]
  1. function CheckRoyalFlush(Hand: TCards; out WildCards: TCards): Boolean;
  2. var
  3.   RequiredCards: Set of TCardValue = [card10, cardJack, cardQueen, cardKing, cardAce];
  4.   card: TCard;
  5.   c: TCardValue;
  6.   CardSet: TCardSet;
  7. begin
  8.   Result := False;
  9.   for CardSet in TCardSet do
  10.   begin
  11.     for card in Hand do
  12.       if card.CardSet = CardSet then
  13.         RequiredCards := RequiredCards - card.Value;
  14.     // Create all the Wildcards required for
  15.     for c in RequiredCards do
  16.       WildCards := WildCards + [NewCard(CardSet, c)];
  17.   If Length(Hand) + Length(WildCards) <= MaxCards then Exit(True);
  18. end;
Then you can create something similar for all the other matches and have a function like this:
Code: Pascal  [Select][+][-]
  1. if CheckRoyalFlush(Hand, Wildcards) then
  2. begin
  3.   Points := RoyalFlushPoints;
  4.   Hand := Hand + WildCards;
  5. end
  6. else if StraightFlush(Hand, Wildcards) then
  7. ...
  8. else if CheckStraight(Hand, Wildcards) then
  9. ...
Until you end up with highest card

mas steindorff

  • Hero Member
  • *****
  • Posts: 593
Re: wildcard utilities list
« Reply #7 on: May 18, 2026, 08:35:41 pm »
Why are you checking against the full deck?
...
You only have to check against combinations above 3 of a kind (e.g. do i get a FullHouse etc.)
I have not created a hand_needs_cards() so I do not know if making the wild card a 3 of clubs fulfills a straight-flush or not until it is tested. So every card of every suite and then comparing score results is the simplest I could think of.
btw: And i would check Top-Down instead of Bottom-Up
...
1st for Royal Flush --> there might be "sub"-checks --> Royal Flush is a Straight from Ace down in the same face
2nd for Straight Flush --> there might be "sub"-checks --> Same as Royal Flush, but highest Card is NOT an Ace (HINT!!)
3rd 4 of a Kind
This is how I did it but skipping the Royal. it is the same as a Straight-Flush but with a higher top card.
This gives me 9 test that I run top down.
The score for each hand is a different equation. for all of them, a Base value is added so a full-house is allway > 3 of a kind but then I need to score 2 full-houses so the one with the higher triplet wins. so I add 14*highCardTrip(hand)  + highCardHighPair(hand).

Code: Pascal  [Select][+][-]
  1. function CheckRoyalFlush(Hand: TCards; out WildCards: TCards): Boolean;
  2. var
  3.   RequiredCards: Set of TCardValue = [card10, cardJack, cardQueen, cardKing, cardAce];
  4.   card: TCard;
  5. end;
...
I thought about using the pascal gem "in set" this but what to you do for a flush, full-house?  all cards qualify.

in the end, I use the .sort(by_rank) gem to simplify the most of the hand testing but this low level scoring does not know about wild card yet.  that may need to be changed: when two hands are the same, the one without the use of the wild card is the winner. somehow I need to generate a lower secondary score that accounts for the use of the wilds. (pending)
my approach to wild cards (trying every one for for each) works but it does take a few seconds with 3 wild.  I'll re-read the suggestion above to see if I missed something.
I'll also be adding a probability pass where the down cards are like the wilds, ran in a similar manor but without using any of the shown cards.  Not yet sure what I'll do with this, perhaps use it for a computer player.

FYI: the flush was the hardest to work with as far as scoring.  For two flushes, high card wins (unless it a draw) and then next highest and on and on... most of the the other hand I can just a the value of one or two of a select set of high cards. I had to bump the base_offsets between the flush and the full-house by 80,000 to account for the flushes need to include it's top 5 cards.
And thank you all for your thoughts. having some of the Greats (as I see you) suggest the same approaches as I came up with is  ;D
MAS   
 
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Zvoni

  • Hero Member
  • *****
  • Posts: 3399
Re: wildcard utilities list
« Reply #8 on: May 19, 2026, 08:29:28 am »
Quote
I have not created a hand_needs_cards() so I do not know if making the wild card a 3 of clubs fulfills a straight-flush or not until it is tested. So every card of every suite and then comparing score results is the simplest I could think of.
Nonsense.
If you have e.g. a 8 of Spades and a Queen of Diamonds on Hand, and the Flop show Jack of Diamonds, King of Diamonds and a Joker/Wildcard:
What sense does it make to check if the Joker returns a score if it's the 3 of clubs????

Remember: The Value/Face of the Joker can change later

Example above: No combinations. Best possible score is High Card King.
Do your Checks Top down as i described, and you'll reach the Bottom --> joker = King (any of the remaining faces) --> 1 Pair (with side-card Queen)

Now the Turn shows a 9 of Clubs
Do your Checks again, your checks stop at Straight, because Joker becomes a 10 (any of the faces)

Now the River shows 10 of Diamonds
Do your checks again, and you stop immediatly at Royal Flush, because the Joker becomes an Ace of Diamonds

The Joker/Wildcard changed value/face 3 times!
And never once you have to check for 3 of clubs

Quote
The score for each hand is a different equation. for all of them, a Base value is added so a full-house is allway > 3 of a kind but then I need to score 2 full-houses so the one with the higher triplet wins. so I add 14*highCardTrip(hand)  + highCardHighPair(hand).
This only makes sense if you have more than 1 Wildcard in a deck.

Whoever has the HighCardTriplet wins the Full House. 2 (or more) Players can never have the same HighCardTriplet if there is only one wildcard.
If there is two or more Wildcards, then it's a different story


EDIT: Forget what i said. Yes, with a Wildcard you have to check for HighPair

EDIT: reg. "BaseValue" --> I'd go for "higher" steps, and do addition instead of multiplication with 1 exception
Example:
1 Pair --> just add the Values of the 2 cards --> a pair of aces =Score 28 (2 x 14)

2 Pair -->
  The highest 2 pair is Pair of Aces and pair of Kings --> Total value = 54 (2 x 14 + 2 x 13), --> ADD with BaseValue of 100 = Score 154
  The lowest 2 pair is Pair of 2's and Pair of 3's --> total Value = 10, --> ADD with BaseValue of 100 = Score 110--> still higher than highest Pair

Triplet -->
  highest Triplet is 3 Aces --> total Value = 42, Add with BaseValue of 1000 --> Score 1042
  lowest Triplet is three 2's --> total Value = 6, Add with BaseValue of 1000 --> Score 1006 --> still higher than highest 2-Pairs

Straight --> just add the Values of the Cards, and add 10000 at the end --> higher Top-Card will always result in higher score if two players have a straight
(I'm implying a Value of 14 for an Ace, NOT 1).
e.g. Straight with Topcard King --> 13+12+11+10+9 = 55
Straight with Top-Card Ace = 14+13+12+11+10 = 60

Flush --> just add the Value of all 5 Cards, with multiplying TopCard with 100), adding 100,000 at the end (to get the distance to Straight)
e.g. Flush of Spades with Topcard Queen, 3, 7, 9, Jack = (12x100)+3+7+9+11 = 1230
Flush of Diamonds with Topcard Jack, 3, 7, 9, 10 = (11x100)+6+7+9+10 = 1132
btw: The lowest TopCard for a Flush is a 7 --> Have a guess why....

Full house --> Just apply "Triplet" plus "Pair" (from above), adding 1M at the end
and so on
« Last Edit: May 19, 2026, 09:57:25 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Warfley

  • Hero Member
  • *****
  • Posts: 2067
Re: wildcard utilities list
« Reply #9 on: May 19, 2026, 10:59:01 am »
The score for each hand is a different equation. for all of them, a Base value is added so a full-house is allway > 3 of a kind but then I need to score 2 full-houses so the one with the higher triplet wins. so I add 14*highCardTrip(hand)  + highCardHighPair(hand).
Well thats not an issue, instead of checking each possibility, you just generate the highest possible hand and then you know that all other hands cannot be higher.
For the full house, I'd do the following: If you have 3 wildcards, take the highest and second highest card in your hand assign two wild cards to the highest and the last one to the second highest. If you have 2 wildcards, you need at least one pair. Take the highest card, if it's part of the pair, complete it to a triple and take the second highest card and make it a pair, if not, just make the triple. If you have 1 wildcard, you need either two pairs or a triple. if you have two pairs, take the highest and turn it into a triple, if you have a triple take the highest card not part of that triple and make it a pair.

Thats the way to approach it, not to test every possible combination, but to only consider the highest possible value you can reach with your current hand

Zvoni

  • Hero Member
  • *****
  • Posts: 3399
Re: wildcard utilities list
« Reply #10 on: May 19, 2026, 11:53:34 am »
if you have a triple take the highest card not part of that triple and make it a pair.
Uh, no....
if you have a triple, take the 1 wildcard and make it a "4 of a kind" (higher score than FullHouse)
If you have 1 or 2 pair, and 2 wildcards, take the (higher) pair and apply both wildcards to make it a "4 of a kind" (higher score than FullHouse)
if you have 3 wildcards, any card becomes a "4 of a kind" (higher score than FullHouse)

Remember: A "Joker" doesn't care if a card is already in "use" by another player.
So there should be no checking against the deck, if e.g. the 10 of Diamonds is on the hand of your opponent
« Last Edit: May 19, 2026, 12:05:50 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Warfley

  • Hero Member
  • *****
  • Posts: 2067
Re: wildcard utilities list
« Reply #11 on: May 19, 2026, 12:13:58 pm »
Uh, no....
if you have a triple, take the 1 wildcard and make it a "4 of a kind" (higher score than FullHouse)
If you have 1 or 2 pair, and 2 wildcards, take the (higher) pair and apply both wildcards to make it a "4 of a kind" (higher score than FullHouse)
if you have 3 wildcards, any card becomes a "4 of a kind" (higher score than FullHouse)
You are right, if the approach is as I outlined in my first post, this check would never happen, as the 4 of a kind check would be performed before, succeed and therefore the full house check would never be performed.

I was just listing all the possibilities to make a full house. If some of those never happen, thats even better

Zvoni

  • Hero Member
  • *****
  • Posts: 3399
Re: wildcard utilities list
« Reply #12 on: May 19, 2026, 12:35:33 pm »
Uh, no....
if you have a triple, take the 1 wildcard and make it a "4 of a kind" (higher score than FullHouse)
If you have 1 or 2 pair, and 2 wildcards, take the (higher) pair and apply both wildcards to make it a "4 of a kind" (higher score than FullHouse)
if you have 3 wildcards, any card becomes a "4 of a kind" (higher score than FullHouse)
You are right, if the approach is as I outlined in my first post, this check would never happen, as the 4 of a kind check would be performed before, succeed and therefore the full house check would never be performed.

I was just listing all the possibilities to make a full house. If some of those never happen, thats even better
Correct. It's why i said to do the checks Top-Down.

And for a (or multiple) Joker to apply it needs only 1 non-Joker-Card
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

mas steindorff

  • Hero Member
  • *****
  • Posts: 593
Re: wildcard utilities list
« Reply #13 on: May 19, 2026, 11:30:25 pm »
With the wild cards, I did need to add  “5 of a Kind” (beats) “Royal flush”.
Nonsense.
If you have e.g. a 8 of Spades and a Queen of Diamonds on Hand, and the Flop show Jack of Diamonds, King of Diamonds and a Joker/Wildcard:
I can't visualize how to do this in code. if you have any guidance, that would help. Note that this code is for 5, 7, and 9 card hands.
My sub testing for straights and sets is simple. here is a snippet:
Code: Pascal  [Select][+][-]
  1. function QuadCard(hand:TCardList): Integer; // highest cards make up the 4 of a kind
  2. var i,vi :Integer;
  3. begin
  4.   result := 0;
  5.   if (hand.count < 4) then // 4 of a kind requires at least 4 cards
  6.      exit;
  7.   hand.Sort(@CompareCardRank);   // should be in sequence now
  8.   for i:= hand.Count-(1+3) downto 0 do begin // biggest to smallest
  9.     vi := CardRVal(hand.Items[i]);              
  10.     if ((vi = CardRVal(hand.Items[i+1])) and
  11.         (vi = CardRVal(hand.Items[i+2])) and
  12.         (vi = CardRVal(hand.Items[i+3]))) then // a four matching ranks
  13.         exit(vi);
  14.   end;
  15. end;    
  16.  

A simple rolling “if” statement that returns the value of the highest rank value of “4 of a kind”.
And a straight test:
Code: Pascal  [Select][+][-]
  1. function HighCardOf_Straigh(hand:TCardList):Integer;  // helper for scoring
  2. var i,v,c :integer;
  3.     h :TcardList;
  4. begin
  5.   result := 0;
  6.   if (hand.count < 5) then  // at lease 5 cards needed to qualify
  7.      exit;
  8.   h := TCardList.Create;
  9.   h.Assign(hand);        // create a temporary copy of the hand to work with
  10.   try
  11.     h.Sort(@CompareCardRank);       // are in sequence now but may have duplicates
  12.    // is there be a way to remove duplicates of the same rank here?
  13.    // i.e h.duplicates(@ByRank()) := false like other list "have"
  14.    // the hard way
  15.    c:= h.Count-1;
  16.    i := 0 ;
  17.    repeat
  18.        if (CardRVal(h[i]) = CardRVal(h[i+1])) then begin
  19.           h.Delete(i);
  20.           dec(c);
  21.           end;
  22.       inc(i);
  23.     until (i>=c);
  24.     if (h.count < 5) then  // still need at lease 5 cards needed to qualify
  25.        exit;
  26.     for i:= h.Count-(1+4) downto 0 do begin  // start with biggest card then go down
  27.       v := CardRVal( h[i] );
  28.       if (v+1 = CardRVal(h[i+1])) and
  29.          (v+2 = CardRVal(h[i+2])) and
  30.          (v+3 = CardRVal(h[i+3])) and
  31.          (v+4 = CardRVal(h[i+4])) then
  32.         exit(V+4); // is the highest card value in the straight
  33.      end;
  34.   finally
  35.     h.Free;  // temp hand
  36.   end;
  37. end;
Works because the .sort() groups the same ranking cards together and I only need to remove the duplicates (pairs… within the straight). Then I test 5 cards at a time until there is a match. I still need to add (Ace = 1) testing here. I figure I would do a h.addcard(AceRankedOne) just before the sequence test once I have things farther developed since a 2 card is ranked as 2.  I believe a ACE in a low straight is not considered the high card is this case.

Note: a TFPGList.removeDuplicates(@myTestFun) would make this function 9 lines shorter.  (one of my learn how to: task).

Adding the high card of a straight or “set of Kind” works but you can not use addition for scoring when there are 2 or more elements. For example for two pair for both players, it is the high pair that wins so 10 & 2 beats 9 & 8.  If you just add then (10+2) 12 !> 17 (9+8).  The high pair needs to take on a value higher than the lower 2 pair hand. If the high pair match then it comes down to the lower pair (and then the kicker if they match too but that is not shown in the score).  Same for full house as the higher triplet wins over a higher pair.
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

mas steindorff

  • Hero Member
  • *****
  • Posts: 593
Re: wildcard utilities list
« Reply #14 on: May 20, 2026, 12:45:36 am »
Flush --> just add the Value of all 5 Cards, with multiplying TopCard with 100), adding 100,000 at the end (to get the distance to Straight)
e.g. Flush of Spades with Topcard Queen, 3, 7, 9, Jack = (12x100)+3+7+9+11 = 1230
Flush of Diamonds with Topcard Jack, 3, 7, 9, 10 = (11x100)+6+7+9+10 = 1132
btw: The lowest TopCard for a Flush is a 7 --> Have a guess why....
if lowest topcard was a 6 then I would have a straight flush  ;)
It does look like your math for the flush only works when one of the flush has a higher top card.  if I'm doing this correctly, [K,9,4,3,2] =1318 should be > than [K,8,7,6,5] = 1326 (but it is not).
I think I need a scaler for each card.  so far, I found [10^4,9^3,9^2,9,1] is the lowest set of scalers for each flush card but [10^4,10^3,10^2,10,1] is not that much bigger.  For the 10s, I also subtract 75,432 (lowest hand value) to help reduce the range to 0...80887 before base is added.
PS: this is where AI fails too.  Gemini say [15^4,15^3...] not taking into account the 4 other cards of the hand (14 -4)^ = 10^ .
« Last Edit: May 20, 2026, 01:04:25 am by mas steindorff »
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

 

TinyPortal © 2005-2018