BSL:String comparison

From OniGalore
Revision as of 18:49, 17 May 2020 by Loser (talk | contribs) (Let's trample some hopes...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Summary of this page

Even though the topic is a bit convoluted, the general information is that BSL does not reliably support string comparison.
It is strongly advised to not rely on string comparison in BSL scripts.

Topic

As a lot of BSL scripters already know, BSL seemingly allows string comparison, meaning it looks like BSL should be capable of processing syntax similar to the following one:

func void some_ai_died(string ai_name){
  if (ai_name eq "A_t48") {
    dmsg("A_t48 died!");
  }
  else {
    dmsg("Some other AI died!");
  }
}

However, string comparison appears to be a bit unreliable - sometimes it looks like it works, sometimes it does not.
But why? The following research is an attempt to find the answer.

Test setup

A test was set in the 1st savepoint of the EnvWarehouse level.

The test comprized of:

  1. A test subject ("A_t48" ai2 character) and its slightly modified death function t48_dead(string ai_name).
  2. A global BSL string variable "BOB_string".
  3. A lot of wasted time while searching for all those damned addresses ^_^.


The test was set as follows:

  1. There is a global BSL variable "BOB_string".
    Init value of the variable is a BSL string literal "A_t48".
    The variable can be set via custom BSL functions to represent one of these BSL string literals: "A_t40", "A_t41", "A_t42"
  2. There is a BSL function t48_dead(string ai_name).
    The function is called by engine when the ai2 character "A_t48" dies.
  3. Inside the BSL function t48_dead(), there is an immediate comparison of ai_name and BOB_string.
  4. After cca 5 seconds, BOB_string is set to be the same as ai_name and another comparison attempt is made.

Test results

Please see the enclosed series of figures. Figures show a relevant selection of Oni application runtime memory data.

  1. Data regarding global BSL variable BOB_string.
    BSL-strcmp-01 gbStrVar-Ptr.png BSL-strcmp-02 gbStrVar-PointedMemory.png
  2. Data regarding local BSL variable ai_name.
    (relevant only during the execution of the t48_dead() BSL fnc)
    BSL-strcmp-03 ainame-Ptr.png BSL-strcmp-04 ainame-PointedMemory.png
  3. State of runtime memory data at the moment when BSL string 'comparison' got evaluated for the first time (evaluated 'false') and for the second time (evaluated 'true').
    BSL-strcmp-05 comparison-false.png BSL-strcmp 06 comparison-true.png


Conclusion

  1. BSL string data seems to be stored as a C-style string. No additional special characters, simply a stream of bytes till the first 0x00 byte (string terminator).
  2. If there are several various independent strings which by chance represent a same text (e.g. "A_t48"), then engine keeps separate instances of these strings (no string grouping or any similar techniques).
  3. For BSL strings, the 'string' BSL datatype does not seem to be a string itself, but it more probably represents a pointer to the given C-style string.
  4. When BSL string 'comparison' is attempted, it in fact most probably means that the values of pointers themselves are compared (meaning the addresses are compared), not strings themselves.
  5. Engine allocates local BSL variables and parameters of BSL functions "on demand" and utilizes a memory area which is not exclusive for BSL strings, but is generally used for various purposes.
    This point effectively means that address of a local BSL string (think ai_name) can differ based on what happened in the game prior to the string allocation request.