Talk:What is the 3rd Party HSI?

From OHRRPGCE-Wiki
Jump to: navigation, search

FyreWulff Ever since the OHRRPGCE has gone open-source, the Third Party HSI has been slowly replaced by actual in-engine code. I, or anyone else needs to audit the HSI and remove code replaced, or we can discuss the future of the HSI. Is there a point to it anymore? It seems TheMadCacti is intent on putting almost all the functions into the engine itself.

The Mad Cacti: I think it's still plenty useful. I've included either the 3rd Party HSI or my math.hsi (the math functions within this package) in the scripts of pretty much every game I've made (saying that, I would like to claim Pheoret as my only game though).

As more wrappers and low level functionality are added to the engine, the library could include more high level scripts. I think the number of scripts in it should increase with time.


FyreWulff As an aside, since you are one of the developers of the OHRRPGCE now, can we really call it the Third Party HSI anymore? (Just joking, I like the name, even though it technically doesn't fit anymore)

Moogle1: I was looking into this, hoping to find a sqrt function so I didn't have to write one myself. The included function is awful! Here's one I wrote in five minutes:

# Return the square root of n
script, sqrt, n, begin 
   variable(guess, last, i)
   guess := 2
   # Get a ballpark guess -- doesn't have to be very accurate
   if (n >> 99) then (guess := 10)
   if (n >> 399) then (guess := 20)
   if (n >> 799) then (guess := 40)
   if (n >> 3599) then (guess := 80)
   if (n >> 22499) then (guess := 150)
   if (n >> 62499) then (guess := 250)
   if (n >> 249999) then (guess := 500)
   if (n >> 999999) then (guess := 1000)
   
   while (last <> guess && i << 5) (
      last := guess
      guess = (guess + n/guess) / 2
      i += 1
   )
   return(guess)
end
Max of 5 iterations, accurate to one of the nearest integers. (Ex: For 600, you'll get 24 or 25, depending on what your max iteration is. The actual square root of 600 is 24.49...) I'm not sure this is being maintained anymore, but if it is, please replace the ugly add-and-check function currently in use.

The Mad Cacti: Yeah, I was 13-14 when I wrote the original version and didn't know about Newton-Raphson. It is pretty bad, but I wanted it to always return the correct rounded result.

You forgot that integers are truncated, not rounded, which decreases accuracy. Either way the result for sqrt(600) doesn't alternate between 24 and 25 (which is what I think you meant).

And 5 iterations is far from enough for all 31-bit integers.

I rewrote and optimised your function to calculate the correct result in just 4 faster iterations. It really took a while to calculate near-optimal guesses!

# Return the square root of n
script, sqrt, n, begin 
   variable(guess, i)
   
   #initial estimate: magic numbers!
   if (n <= 238629) then (
     if (n <= 3189) then (guess := 16) else (guess := 198)
   ) else (
     if (n <= 85812429) then (
       if (n <= 6093489) then (guess := 1202) else (guess := 5068)
     ) else (
       if (n <= 811651600) then (guess := 16930) else (guess := 30000)
     )
   }
   
   for (i, 1, 4) (
      guess := (guess + n/guess + 1) / 2
   )
   #Catch certain cases which return the wrong result otherwise
   if (guess * (guess -- 1) == n) then (return (guess -- 1)) else (return (guess))
end

Returns the correct result for all integers from 0 to 2^31-1 (I tested them all, and a good thing I did - I had to tweak the guesses slightly! However, I haven't actually tested the script, I used C)

There's probably a faster way to find an initial estimate though (as in, I'm aware I'm wasting my time).

Bob the Hamster: What if we just add a builtin to wrap FreeBasic's SQR function?

The Mad Cacti: Well, obviously. This was just an exercise in futility. Also, what about adding a floating point type to HamsterSpeak?

Bob the Hamster: I dunno. How would we make floating point types work? Should they be automatically cast to integers if you pass them to a command that expects an integer? Or will you have to manually round or truncate them? What would the syntax for a float be? 1.0 instead of 1? Maybe this calls for a Plan

The Mad Cacti: Yes, the decimal point would create a float literal, and any arithmetic involving floats causes casts to float.

I've seen some problems in GameMaker where there is no integer type and floats are used for everything. I've seen yes/no options in config files written out by games with values like 0.000005. I'm inclined to throw an error when a float is passed instead of an integer. But we could do this:

  • If a float occurs instead of an integer and is not within 0.01 of an integer, throw an error
  • Otherwise, decide to throw a warning/error or cast silently based on some preference, defaulting to the warning

Moogle1: I'm in favor of a less kludgy approach to data types. It would be REALLY nice if we could pass strings as parameters, if we could pass by reference and not just value, and a lot of other things. An idle thought is that we could handle variables in the way that Javascript and PHP do it -- everything is typeless and can be recast at runtime.

$myVar = 1;
$myVar = 'Now it's a string';
$myVar = 0.5;
$myVar['key'] = 'Now it's an array, but in PHP, all arrays are hashes!';

Okay, maybe we should just stick to normal arrays.

Bob the Hamster: Ah, yes, I have seen those float precision problems before too, like here.

And yes, real strings and real arrays are on the table for the future too, but floats seem like as good a place to start as any.

The Mad Cacti: Actually Moogle, I think you misunderstood. I was imagining this:

variable (myVar)
myVar := 1
myVar := "Now it's a string"
myVar := 0.5
myVar := hash()
myVar["key"] := "Now it's an associative array!"
myVar[781369172] := "(considering support for integers and strings as keys)"
myVar := array()
myVar[5] := "Now it's a dynamic array!"

I'd also like to support passing by reference, but that causes a lot of questions. Passing by reference is different from binding two variables to the same object, which is different from using a copy-on-write optimisation.

James, I'd like to implement everything at once by writing a new interpreter, in the near future, but designing one thing at a time might be sensible.

Bob the Hamster: Awesome. I like the plan above. Maybe you could flesh it out here? Plan for dynamically typed variables in HamsterSpeak

The Mad Cacti: Plan?! That wasn't a plan, it was a desperate cry for feedback! A plan should focus on implementation details, not vague goals (yes, the above is very vague).

I prefer keeping all of this together: Plan for dynamic types in HamsterSpeak

Bob the Hamster: Sorry. When I said "I like that plan", what I meant was I like that idea :) So my feedback is that I like the syntax you have proposed, and I agree that the functionality of dynamic types are definitely a desirable thing.

Bob the Hamster: I removed the old zip file of the thirdparty scripts. Links that pointed to it now redirect to What is the 3rd Party HSI?