Skip to content

Instantly share code, notes, and snippets.

@asibahi
Created September 28, 2016 16:27
Show Gist options
  • Save asibahi/493bbe71205fb7cffad2f7b16b98c534 to your computer and use it in GitHub Desktop.
Save asibahi/493bbe71205fb7cffad2f7b16b98c534 to your computer and use it in GitHub Desktop.
Original baloot functions
// Types
type Team =
| Us
| Them
member this.Opp =
match this with
| Us -> Them
| Them -> Us
type Suit =
| Hearts
| Diamonds
| Clubs
| Spades
type Rank =
| Ace
| King
| Queen
| Jack
| Ten
| Nine
| Eight
| Seven
type Card =
{ Rank : Rank
Suit : Suit }
member this.SunValue =
match this.Rank with
| Ace -> 11
| Ten -> 10
| King -> 4
| Queen -> 3
| Jack -> 2
| _ -> 0
member this.TrumpValue trump =
match this.Rank, this.Suit = trump with
| Jack, true -> 20
| Nine, true -> 14
| _ -> this.SunValue
member this.IsPicture =
match this.Rank with
| Nine | Eight | Seven -> false
| _ -> true
member this.SortValue =
match this.Rank with
| Ace -> 0
| King -> 1
| Queen -> 2
| Jack -> 3
| Ten -> 4
| Nine -> 5
| Eight -> 6
| Seven -> 7
+ match this.Suit with
| Hearts -> 0
| Clubs -> 10
| Diamonds -> 20
| Spades -> 30
override this.ToString() = sprintf "%A of %A" this.Rank this.Suit
type Mode =
| Sun
| Trump of Suit
type Project =
| Sira
| Fifty
| Hundred
| FourHundred
| Baloot
type Round =
{ Mode : Mode
Captured : Card list
Projects : Project list
Ground : Team
Bettor : Team
Owner : Team }
// Trick Total Point Calculations
let capturedTrickPts round =
round.Captured
|> match round.Mode with
| Sun -> List.fold (fun acc card -> acc + (card.SunValue)) 0
| Trump(suit) -> List.fold (fun acc card -> acc + (card.TrumpValue suit)) 0
|> (+) (if round.Ground = round.Owner then 10
else 0)
// Captured Cards Point Calculations
let sunRoundPts pts =
match pts % 10 with
| 5 -> pts
| n when n < 5 -> pts - n
| n -> pts - n + 10
/ 5
let trumpRoundPts pts =
match pts % 10 with
| n when n <= 5 -> pts - n
| n -> pts - n + 10
/ 10
let capturedRoundPts round =
let pts = capturedTrickPts round
match round.Mode with
| Sun -> sunRoundPts pts
| Trump(_) ->
match pts % 10, round.Owner = round.Bettor with
| 6, true -> (trumpRoundPts pts) - 1
| _ -> trumpRoundPts pts
// Project Points Calculations
let sunProjectPts =
function
| Sira -> 4
| Fifty -> 10
| Hundred -> 20
| FourHundred -> 40
| _ -> 0
let trumpProjectPts =
function
| Sira | Baloot -> 2
| Fifty -> 5
| Hundred | FourHundred -> 10
let projectRoundPts (round : Round) =
let projectPts =
match round.Mode with
| Sun -> sunProjectPts
| Trump(_) -> trumpProjectPts
round.Projects |> List.fold (fun acc pro -> acc + (projectPts pro)) 0
// Total Point for Round
// TARGET FUNCTION
let roundPts round = (capturedRoundPts round) + (projectRoundPts round)
// Type Creations
let newRound (mode, captured, projects, ground, bettor, owner) =
{ Round.Mode = mode
Round.Captured = captured
Round.Projects = projects
Round.Ground = ground
Round.Bettor = bettor
Round.Owner = owner }
// The Other Team
open Microsoft.FSharp.Reflection
// Deck Creation and Shuffling
let fullDeck =
let suits = FSharpType.GetUnionCases typeof<Suit>
let ranks = FSharpType.GetUnionCases typeof<Rank>
[ for s in suits do
let suit = FSharpValue.MakeUnion(s, [||]) :?> Suit
for r in ranks do
let rank = FSharpValue.MakeUnion(r, [||]) :?> Rank
yield { Card.Rank = rank
Card.Suit = suit } ]
let globalRandom = System.Random()
let shuffleDeck = List.sortBy (fun _ -> globalRandom.Next())
let cutDeckRandomly = List.splitAt (globalRandom.Next(7) * 4)
// Randomized Round Creation for testing
let createTestRounds mode =
let rInt = globalRandom.Next(100)
let rBettor, rGround =
match rInt % 4 with
| 0 -> Us, Us
| 1 -> Us, Them
| 2 -> Them, Them
| _ -> Them, Us
let capped1, capped2 =
fullDeck
|> shuffleDeck
|> cutDeckRandomly
let round1 = newRound (mode, capped1, [], rGround, rBettor, Us)
let round2 = newRound (mode, capped2, [], rGround.Opp, rBettor.Opp, Them)
round1, round2
(* Project finder *)
// only works for lists of distinct integers
let hasIntSeqOf n =
List.sort
>> List.mapi (-) // subtract number from index. results in consecutive numbers having the same result.
>> List.groupBy id // Since consecutive numbers will have same results they can be grouped.
>> List.filter (snd // If any group has (>= n) members, the sequence exists
>> List.length
>> (<=) n)
>> List.map Some
let hasSeqOf n =
List.sortBy (fun (c : Card) -> c.SortValue) // To make sure the cards of the same suit are sorted correctly
>> List.mapi (fun i c -> (i - c.SortValue, c)) // tuple with the card and the invariant if there are consectuive cards
>> List.groupBy fst //group by the invariant
>> List.map snd // then strip it out
>> List.filter (List.length >> (<=) n)
>> List.map ((List.map snd) >> Some) // clean up
let hasFourOfAKind =
List.groupBy (fun c -> c.Rank)
>> List.map snd
>> List.tryFind (List.length >> (=) 4)
let hasOneSira =
hasSeqOf 3 >> function
| Some(cl) :: [] when 3 = List.length cl -> Some(cl)
| _ -> None
let hasTwoSira =
hasSeqOf 3 >> function
| Some(cl1) :: Some(cl2) :: _ when (List.length cl1) = (List.length cl2) -> Some(cl1 @ cl2)
| _ -> None
let hasFifty =
hasSeqOf 4 >> function // there can be only one (four in a row)
| Some(cl) :: _ when 4 = List.length cl -> Some(cl)
| _ -> None
let hasHundredOne =
hasSeqOf 5 >> function // there can be only one (five in a row)
| Some(cl) :: _ -> Some(cl)
| _ -> None
let hasHundredTwo =
hasFourOfAKind >> function
| Some(c :: tl) when c.IsPicture && c.Rank <> Ace -> Some(c :: tl)
| _ -> None
let hasFourHundred =
hasFourOfAKind >> function
| Some(c :: tl) when c.Rank = Ace -> Some(c :: tl)
| _ -> None
let hasBaloot mode cards =
match mode with
| Sun -> None
| Trump(t) ->
let king = List.tryFind (fun c -> c.Rank = King && c.Suit = t) cards
let queen = List.tryFind (fun c -> c.Rank = Queen && c.Suit = t) cards
match king, queen with
| Some(k), Some(q) -> Some([ k; q ])
| _ -> None
fullDeck
|> shuffleDeck
|> Seq.take 7
|> List.ofSeq
|> List.sortBy (fun (c : Card) -> c.SortValue)
|> hasHundredOne
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment