Skip to content

Instantly share code, notes, and snippets.

@LukePammant
Created June 10, 2020 04:03
Show Gist options
  • Save LukePammant/80d9bd74b4d009d66386e69ceb4f812f to your computer and use it in GitHub Desktop.
Save LukePammant/80d9bd74b4d009d66386e69ceb4f812f to your computer and use it in GitHub Desktop.
An attempt to learn F# & functional programming by building something for my game. This script should simple take a Miner and a Minable object and move resources from the Minable to the Minable while taking into account capacity on the Miner and availability on the Minable.
type ResourceType = Metal | Gas
type MinerId = MinerId of string
type MinerResource =
{ Type: ResourceType
Capacity: int
CurrentAmount: int
GatherRate: int }
type Miner = { Id: MinerId; Resources: MinerResource list }
type MinableId = MinableId of string
type MinableResource = { Type: ResourceType; MinableAmount: int }
type Minable = { Id: MinableId; Resources: MinableResource list }
type ResourceToMine = { Type: ResourceType; Amount: int }
type MiningResult =
{ Type: ResourceType
RemaingAmount: int
MinedAmount: int }
let getMatchingResourceOrEmpty (minableResources: MinableResource list) resourceType =
let resourceResult = minableResources |> List.tryFind (fun x -> x.Type = resourceType)
match resourceResult with
| Some resource -> resource
| None -> { Type = resourceType; MinableAmount = 0 }
let getMinerCollectionRates (storage: MinerResource) =
match ((storage.CurrentAmount + storage.GatherRate) > storage.Capacity) with
| true -> { Amount = storage.Capacity - storage.CurrentAmount; Type = storage.Type }
| false -> { Amount = storage.GatherRate; Type = storage.Type }
let getMinableAmount (minableResources: MinableResource list) (amountToMine: ResourceToMine) =
let a = getMatchingResourceOrEmpty minableResources amountToMine.Type
{amountToMine with Amount = min a.MinableAmount amountToMine.Amount}
let subtractResources (minableResource: MinableResource) (resourcesToMine: ResourceToMine list) =
let resourceResult = resourcesToMine |> List.tryFind (fun x -> x.Type = minableResource.Type)
match resourceResult with
| Some resource -> { minableResource with MinableAmount = minableResource.MinableAmount + resource.Amount }
| None -> minableResource
let addResources (minerResource: MinerResource) (resourcesToMine: ResourceToMine list) =
let resourceResult = resourcesToMine |> List.tryFind (fun x -> x.Type = minerResource.Type)
match resourceResult with
| Some resource -> { minerResource with CurrentAmount = minerResource.CurrentAmount + resource.Amount }
| None -> minerResource
let mine (miner: Miner) (minable: Minable) =
let amountToMine = miner.Resources |> List.map (getMinerCollectionRates >> (getMinableAmount minable.Resources))
let minerResources = miner.Resources |> List.map (fun minerResource -> addResources minerResource amountToMine)
let minableResources = minable.Resources |> List.map (fun minableResource -> subtractResources minableResource amountToMine)
({ miner with Resources = minerResources }, { minable with Resources = minableResources })
// Test if it works
let minableResources = [
{ Type = Metal; MinableAmount = 500 }
]
let minable = { Id = MinableId "abc"; Resources = minableResources }
let minerResources = [
{ Type = Metal; CurrentAmount = 0; Capacity = 500; GatherRate = 10 }
{ Type = Gas; CurrentAmount = 0; Capacity = 500; GatherRate = 10 }
]
let miner: Miner = { Id = MinerId "cba"; Resources = minerResources }
let result = mine miner minable
printfn "%O" result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment