Skip to content

Instantly share code, notes, and snippets.

@misterspeedy
Created September 22, 2017 20:58
Show Gist options
  • Select an option

  • Save misterspeedy/09943b74e20b7ce3b34c177691465fe1 to your computer and use it in GitHub Desktop.

Select an option

Save misterspeedy/09943b74e20b7ce3b34c177691465fe1 to your computer and use it in GitHub Desktop.

Revisions

  1. misterspeedy created this gist Sep 22, 2017.
    172 changes: 172 additions & 0 deletions DiscriminatedUnions.fs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,172 @@
    #if COMPILED
    namespace CasualFSharp
    #endif

    module Monopoly =

    open System

    type Player =
    | Boot
    | Battleship
    | Iron
    // Etc.

    type Colour =
    | Brown
    | LightBlue
    | Magenta
    // Etc.

    type Development =
    | Empty
    | Houses of count:int
    | Hotel

    type Price = int

    type Location =
    | Street of
    name:string *
    cost:Price *
    colour:Colour *
    development:Development *
    rentals:Price[] *
    owner:Player option

    | Utility of
    name:string *
    cost:Price *
    owner:Player option

    | Station of
    name:string *
    cost:Price *
    owner:Player option

    | Tax of name:string * amount:Price

    | GotoJail
    | Go
    | CommunityChest
    | Chance
    | Jail
    | FreeParking

    let ownsLocation player location =
    match location with
    | Street(_, _, _, _, _, (Some(owner)))
    | Utility(_, _, (Some(owner)))
    | Station(_, _, (Some(owner))) ->
    player = owner
    | _ ->
    false

    let streetsOfColour colour board =
    board
    |> Seq.filter (fun l ->
    match l with
    | Street(_, _, c, _, _, _) ->
    colour = c
    | _ ->
    false)

    let ownsStreetSet player colour board =
    board
    |> streetsOfColour colour
    |> Seq.exists (fun loc ->
    not (ownsLocation player loc))
    |> not

    let charge (player : Player) (location : Location) board =
    match location with
    | Street(_, _, colour, development, rentals, owner) ->
    match owner with
    | None ->
    None
    | Some o when o <> player ->
    match development with
    | Empty ->
    let factor = if ownsStreetSet o colour board then 2 else 1
    rentals.[0] * factor |> Some
    | Houses c ->
    rentals.[c] |> Some
    | Hotel ->
    rentals.[5] |> Some
    | Some _ ->
    None
    | Utility(name, rentals, owner) ->
    raise <| NotImplementedException()
    | _ ->
    raise <| NotImplementedException()

    module Demo =

    open Monopoly

    let go = Go
    let oldKentRoad = Street("Old Kent Road", 60, Brown, Empty, [| 2; 10; 20; 90; 160; 250|], None)
    let communityChest = CommunityChest
    let whitechapelRoad = Street("Whitechapel Road", 60, Brown, Empty, [| 4; 20; 60; 180; 230; 450|], None)
    let incomeTax = Tax("Income Tax", 200)
    let kingsCross = Station("King's Cross", 200, None)
    let theAngelIslington = Street("The Angel Islington", 100, LightBlue, Empty, [| 6; 30; 90; 270; 400; 550|], None)

    let board = [
    go
    oldKentRoad
    communityChest
    whitechapelRoad
    incomeTax
    kingsCross
    theAngelIslington
    // Etc.
    ]

    charge Boot oldKentRoad board |> printfn "Charged: %A"

    let oldKentRoad' = Street("Old Kent Road", 60, Brown, Empty, [|2; 10; 20; 90; 160; 250|], Some Boot)

    let board' = [
    go
    oldKentRoad'
    communityChest
    whitechapelRoad
    incomeTax
    kingsCross
    theAngelIslington
    ]

    charge Boot oldKentRoad' board' |> printfn "Charged: %A"
    charge Battleship oldKentRoad' board' |> printfn "Charged: %A"

    let oldKentRoad'' = Street("Old Kent Road", 60, Brown, Houses 3, [|2; 10; 20; 90; 160; 250|], Some Boot)

    let board'' = [
    go
    oldKentRoad''
    communityChest
    whitechapelRoad
    incomeTax
    kingsCross
    theAngelIslington
    ]

    charge Boot oldKentRoad'' board'' |> printfn "Charged: %A"
    charge Battleship oldKentRoad'' board'' |> printfn "Charged: %A"

    let oldKentRoad''' = Street("Old Kent Road", 60, Brown, Empty, [|2; 10; 20; 90; 160; 250|], Some Battleship)
    let whitechapelRoad''' = Street("Whitechapel Road", 60, Brown, Empty, [| 4; 20; 60; 180; 230; 450|], Some Battleship)

    let board''' = [
    go
    oldKentRoad'''
    communityChest
    whitechapelRoad'''
    incomeTax
    kingsCross
    theAngelIslington
    ]

    charge Boot oldKentRoad''' board''' |> printfn "Charged: %A"