Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- open System
- open System.Collections.Generic
- // Pokemon Catch Simulator. Version 1.1
- // This program simulates how many Pokeballs it will take to catch a Pokemon.
- // In Pokemon, you are able to catch Pokemon you find in the wild and tame them.
- // In the game, you simply throw a Pokeball and hope for the best. The Pokemon will enter the ball, shake three times,
- // and will display a message saying the Pokemon was caught... if you're lucky.
- // The odds of catching a Pokemon increase if the Pokemon's health is low, if it is afflicted with a status condition
- // such as sleep, paralysis, burn, etc. The odds of catching a Pokemon also depend on that specific Pokemon's catch rate.
- // I am specifically using this calculation here:
- // https://bulbapedia.bulbagarden.net/wiki/Catch_rate#Capture_method_.28Generation_III-IV.29
- // ----------------------------------------------------------------------------
- // BEGIN CITATION: This following code was authored by Tomas Petricek. This code snippet implements the "break" and "continue" keywords in F#.
- // Retrieved from http://tomasp.net/blog/imperative-ii-break.aspx/
- type ImperativeResult<'T> =
- | ImpValue of 'T
- | ImpJump of int * bool
- | ImpNone
- type Imperative<'T> = unit -> ImperativeResult<'T>
- type ImperativeBuilder() =
- member x.Combine(a, b) = (fun () ->
- match a() with
- | ImpNone -> b()
- | res -> res)
- member x.Delay(f:unit -> Imperative<_>) = (fun () -> f()())
- member x.Return(v) : Imperative<_> = (fun () -> ImpValue(v))
- member x.Zero() = (fun () -> ImpNone)
- member x.Run<'T>(imp) =
- match imp() with
- | ImpValue(v) -> v
- | ImpJump _ -> failwith "Invalid use of break/continue!"
- | _ when typeof<'T> = typeof<unit> -> Unchecked.defaultof<'T>
- | _ -> failwith "No value has been returend!"
- // Add special Combine for loops and implement loops
- // Add Bind to enable using of break and continue
- type ImperativeBuilder with
- member x.CombineLoop(a, b) = (fun () ->
- match a() with
- | ImpValue(v) -> ImpValue(v)
- | ImpJump(0, false) -> ImpNone
- | ImpJump(0, true)
- | ImpNone -> b()
- | ImpJump(depth, b) -> ImpJump(depth - 1, b))
- member x.For(inp:seq<_>, f) =
- let rec loop(en:IEnumerator<_>) =
- if not(en.MoveNext()) then x.Zero() else
- x.CombineLoop(f(en.Current), x.Delay(fun () -> loop(en)))
- loop(inp.GetEnumerator())
- member x.While(gd, body) =
- let rec loop() =
- if not(gd()) then x.Zero() else
- x.CombineLoop(body, x.Delay(fun () -> loop()))
- loop()
- member x.Bind(v:Imperative<unit>, f : unit -> Imperative<_>) = (fun () ->
- match v() with
- | ImpJump(depth, kind) -> ImpJump(depth, kind)
- | _ -> f()() )
- let imperative = new ImperativeBuilder()
- let break = (fun () -> ImpJump(0, false))
- let continue = (fun () -> ImpJump(0, true))
- let breakn(n) = (fun () -> ImpJump(n, false))
- let continuen(n) = (fun () -> ImpJump(n, true))
- // END CITATION.
- // ----------------------------------------------------------------------------
- let HPcurrent = 20.0 // The current health of the Pokemon.
- let HPmax = 180.0 // The maximum health the Pokemon can have.
- let ball = 1.0 // The type of Pokeball to be used (1 = standard Pokeball, 1.5 = Great Ball, 2 = Ultra Ball)
- let status = 1.5 // Status affliction of the Pokemon (1 = no affliction, 1.5 = poisoned/burned/paralyzed, 2 = asleep/frozen)
- let rate = 3.0 // the catch rate of the Pokemon (a value between 1 and 255)
- // Do NOT mess with these:
- let mutable counter = 0 // this will be used to keep track of how many balls were used.
- let mutable caught = false // Boolean to keep track of whether or not the Pokemon is captured.
- let mutable a = (((3.0*HPmax - 2.0*HPcurrent) * rate * ball )/(3.0*HPmax)) * status // The calcuation of the modified catch rate given all the properties above.
- let b = Math.Floor (1048560.0 / sqrt (sqrt (16711680.0/a))) // Ball shake probability. It's actually supposed to floor every division and square root, but this will do.
- let mutable x = 0.0 // number that will be randomly generated
- // Display User-inputted information the program will run with.
- printfn "HP of Pokemon: %.0f/%.0f" HPcurrent HPmax
- if ball = 1.0 then printfn "Using Poke Ball."
- elif ball = 1.5 then printfn "Using Great Ball."
- elif ball = 2.0 then printfn "Using Ultra Ball."
- if status = 1.0 then printfn "Pokemon has no status affliction."
- elif status = 1.5 then printfn "Pokemon is paralyzed/burned/poisoned."
- elif status = 2.0 then printfn "Pokemon is asleep/frozen."
- printfn "Catch rate of Pokemon: %.0f" rate
- printfn "a = %.0f" a
- printfn "b = %.0f" b
- printfn "Press any key to begin..."
- Console.ReadKey() |> ignore
- let catch_the_monster() = imperative {
- if HPcurrent <> 0.0 || HPmax <> 0.0 || ball <> 0.0 || status <> 0.0 || rate <> 0.0 then
- if a < 1.0 then // if modified catch rate is less than 1, it is set to 1.
- a <- 1.0
- while not caught do
- let rand = Random() // initialize RNG
- for i in 0 .. 3 do //perform four shake checks
- x <- double (rand.Next(0,65535)) // pick a number between 1-65535
- printfn "Ball number %d / shake number %d / random number %.0f" counter i x
- if i = 0 && x >= b then // first shake check
- printfn "Oh no! The Pokemon broke free!"
- counter <- counter + 1
- do! break
- elif i = 1 && x >= b then // second shake check
- printfn "Aww! It appeared to be caught!"
- counter <- counter + 1
- do! break
- elif i = 2 && x >= b then // third shake check
- printfn "Aargh! Almost had it!"
- counter <- counter + 1
- do! break
- elif i = 3 && x >= b then // fails third shake check
- printfn "Shoot! It was so close, too!"
- counter <- counter + 1
- do! break
- elif i = 3 && x < b then // passes third shake check
- caught <- true
- printfn "Gotcha! The Pokemon was caught!"
- counter <- counter + 1
- printfn "It was caught after %d balls" counter
- else
- printfn "Something doesn't seem right. Check the properties of the Pokemon. Make sure nothing is set to zero." }
- catch_the_monster()
- Console.ReadKey() |> ignore
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement