Author Topic: Creating a list for an E:D command  (Read 3607 times)

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Creating a list for an E:D command
« on: January 09, 2021, 09:01:40 PM »
If you use EDDI, you might be familiar with the "Bodies to scan" event.  That's the one that says "Body A, Body B and Body C are worth mapping" after you complete your system scan.

I am trying to recreate this responder in VA's own system, in order to make it a little more interactive.  EDDI presents a number of variables as a result of the event that can be used, without the voice action part of the responder.

I haven't an issue with doing the incremental compare against these variables to determine how many bodies are worth mapping, but I can't quite wrap my head around how to create and add to a list of which bodies are worth it and then how to subtract from this list as I map them, if its even possible in VA's command structure.

I've read through the PDF at all the different variable/token options, but I'm just not sure of a good methodology.

Any suggestions or insight would be appreciated.

Thanks!

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #1 on: January 09, 2021, 10:48:43 PM »
There are currently no native lists, so you'd have to manually manage that functionality, or use an inline function that can split and parse them for you.


Some examples of the data you're getting from EDDI, and how you are looking to use that data (E.G. what you would add to the list, what you would subtract, and how you would trigger the latter), could help determine what the best approach may be.

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #2 on: January 10, 2021, 01:16:00 AM »
The EDDI plugin responds to the in-game event that bodies in the system have been "high level" scanned.  This in-game event triggers the EDDI plugin to take all the variables populated by the scan - atmosphere, gravity, terraformable, etc - and compare them against a list of criteria to generate a list of which bodies are worth a "detailed" scan.  As soon as the "high level" scan of the entire system is complete, it reads out this list of "detailed scan" candidates so that the player can locate each one in the nav panel and fly within range for the detailed scan. 

As a detailed scan of each in the list is complete, another in-game event is generated, which prompts the EDDI plugin to remove the now-scanned body from the list, and read off the remaining.

I'm trying to recreate this process so that I can add different response language, have VA respond to follow-up spoken commands to make the whole thing a little more "conversational", inform me that a given body is worth the closer look before the entire system scan is complete, respond if there are no bodies worth scanning, etc.

I was thinking I could maybe populate a TXT variable with each body name that meets the detailed scan criteria on each criteria compare loop, with an incremental in the variable name. Then, as each qualifying body is scanned, have VA compare its name against each of those name variables and remove the matching one.  But I don't see anything in the VA docs that I understand to indicate being able to generate a dynamic variable name.  And I can't realistically fill my loop with "Count = X so set variable {TXT:Worth_scanning_X} to [body name]."  Some systems may have only one body worth a closer look, some may have ten, some none at all.

Edit:  Or would that be a "nested token"?  The loop count is {INT:scan_count} so set {TXT:worthscan{INT:scan_count}}?  Is that a thing?

And then, how does one make tokens go away.  Not just be unset, but actually cease to be?

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #3 on: January 10, 2021, 01:31:06 AM »
I'll rephrase: Some verbatim samples of the data you're getting from EDDI


You can use tokens in variable names, however for a list that may not necessarily be the preferred option.



variable {TXT:Worth_scanning_X} to [body name]."
Edit:  Or would that be a "nested token"?  The loop count is {INT:scan_count} so set {TXT:worthscan{INT:scan_count}}?  Is that a thing?

And then, how does one make tokens go away.  Not just be unset, but actually cease to be?
Do you understand the distinction between a token and a variable name?

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #4 on: January 10, 2021, 03:08:44 AM »
I guess I can give a more concrete example.  I apologize, but it may be a bit long.  Hopefully it makes for better understanding.

So in E:D, you have the Full Spectrum Scanner and the Detailed Surface Scanner.  The FSS gives a "high level" scan of a system.  When you jump into the system, you activate the FSS and give it a "honk," which then identifies all the stars/planets/moons in the system.  You then proceed to "zoom in" on each of the planets/moons, each in turn. As you zoom in, all sorts of details about that body are revealed.

You can see all the details revealed and variables passed to VA at https://github.com/EDCD/EDDI/wiki/Body-scanned-event

So, in this example, let's say I jump into the system known as Methuselah 934, and give that initial "honk."  This reveals that there are eight bodies in the system - a main star and seven planets/moons.  They are identified as Methuselah 934 A through F, with Methuselah 934 C having a moon, which is identified as Methuselah 934 C 1.  So I "zoom in" on each one.

Methuselah 934 A is a rocky planet, no atmosphere, and is tidal-locked to the main star.  Not a candidate for detailed scans.
Methuselah 934 B is a hot rocky planet, dense sulfur atmosphere.  Not a candidate.
Methuselah 934 C is a terraformable water world with an ammonia atmosphere.  Definite candidate.
Methuselah 934 C 1, its moon, is icy with no atmosphere.  Not a candidate.
Methuselah 934 D is a fully Earth-like world!  Definitely scan that.
Methuselah 934 E and F are Class III gas giants.  Meh.

So after all that, EDDI performs a voice action saying "Methuselah 934 C and Methuselah 934 D are good candidates for mapping" (detailed scanning).  That is what it says.  In this scenario let's say 934 D is closer, so I fly within range of the detailed scanner and "map" it.  When I'm done, EDDI will do another voice action saying that only "Methuselah 934 C is a good candidate for mapping." 

So I fly to it, and do a detailed scan.  When that is done, EDDI will perform another voice action saying "You have mapped all interesting bodies in the system."  So I call up the galaxy map, set my next system target and jump out.

I'd like to get all that into VA's own system so that perhaps instead of just being told that 934 C and D are good candidates, it could go something like this:

[FSS scan complete]
Me:  Is there anything worth scanning here?
VA:  There are a couple of candidates
Me:  Which ones?
VA:  Methuselah 934 C and Methuselah 934 D
[Scan of 934 D complete]
Me:  What was/were the other body/bodies to scan?
VA:  Methuselah 934 C

Or, as soon as I do the "zoom in" on 934 C, VA says "You might consider mapping this one" instead of waiting until the whole thing is FSS scanned and giving me the list.

And if the question needed to be asked, I guess I don't really know the difference between a token and variable.  Reading through the docs, to me {TIME} (a "token") is a just a variable that is set by the system and is changed every nanosecond or whatever by the system, but I can call it via a command, and {MYVARIABLE} is one generated and set by a command I wrote and I can modify at any time.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #5 on: January 10, 2021, 03:36:29 AM »
to me {TIME} (a "token") is a just a variable that is set by the system and is changed every nanosecond or whatever by the system, but I can call it via a command, and {MYVARIABLE} is one generated and set by a command I wrote and I can modify at any time.
Quote from: https://forum.voiceattack.com/smf/index.php?topic=3500.0
Onto tokens: One important thing to keep in mind, is that tokens are not variables; Variables store information, tokens either retrieve information, or process information, but they do not store it.
Understanding the difference is very important for the correct use of these features.



Apparently "verbatim samples" is not clear: Provide the exact data that you will be putting in these lists (I.E. literally that values of the variables you are using, as in the output that EDDI provides you), and in what way that data needs to be manipulated in order to achieve the result you are looking for.

There does not appear to be a data value that literally states whether a scan is worthwhile or not. The closest I can see would be "estimatedvalue", but that would require a threshold value to check against.

Either way, I need to know what the input is, and what the output should be, in order to make a recommendation on what may be a good method of achieving that.


I interpreted the original post as specifically asking for a method to create and use lists, but it seems that is not all. Do you have the other steps figured out, or not?



A very basic example of a list system would be something like
Code: [Select]
//The list must be initialized to be blank for fist-time use, otherwise appending it will result in "Not set" getting prepended
Set text [list] to ''
Write [Blue] 'List contents: "{TXT:list}"' to log

//Add a list item
Set text [list] to '{TXT:list};Item 1;'
Write [Blue] 'List contents: "{TXT:list}"' to log

//And some more
Set text [list] to '{TXT:list};Item 2;;item 3;;item 4;'
Write [Blue] 'List contents: "{TXT:list}"' to log

//Remove a list item
Set text [list] to [list] (Replace ';Item 1;' with '')
Write [Blue] 'List contents: "{TXT:list}"' to log

//Count the items in a list
Write [Blue] 'List item count: {EXP: {TXTOCCURRENCES:";":list} / 2}' to log

However, whether this can be applied to this scenario depends on what data it needs to store, and which operations you need to be able to perform on the list itself.

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #6 on: January 10, 2021, 01:02:37 PM »
Okay, I can't give verbatim examples, because I don't know how to pull the data out of the game.  And the data is used in the background or only as a voice statement. But, using their variable names, it would seem to be that after a body is scanned:

if {TXT:EDDI body scanned planettype} = "Ammonia world" or "water world" or "Earth-like world"

and/or

if {TXT:EDDI body scanned terraformstate}= "Candidate for terraforming"

and {DEC:EDDI body scanned estimatedvalue} >= 80000

then add {bodyname} to {bodies to map}

else skip it

I have several incremental loops in my profile, but I'm not sure how to achieve the {bodies to map} if it has more than one body, because it would require a list.  If I could do a dynamic incremental variable name, I could do something like this at the beginning:

set {bodies to map count} = 0

and then after a body is scanned that meets the criteria above:

set {INT:bodies to map count}={INT:bodies to map count}+1
set {TXT:bodies to map{INT:bodies to map count}}

Then if I say "Is there anything worth mapping?

VA would read back all existing {TXT:bodies to map{INT:bodies to map count}} variables.

And then, after mapping one of them, VA would compare {TXT:EDDI body mapped bodyname} to the {TXT:bodies to map{INT:bodies to map count}} and eliminate the matching one.

But that would be the part I can't quite figure out, as it would need to compare against a changing total of variables, and I may eliminate the third of five.  Or the first. Or I may decide to leave the Full Spectrum Scanner and immediately do the detailed scan on the one body, then go back to the Full Spectrum Scan to find others.

And all of this would need to reset to zero after each jump.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #7 on: January 10, 2021, 02:51:14 PM »
I'm not sure how to achieve the {bodies to map} if it has more than one body, because it would require a list.
Have you looked at the example in my previous post?

If you understand what tokens are, you can see how something like
Code: [Select]
Set text [list] to '{TXT:list};{TXT:bodyName};'can be used to add an item to a "list"

This also allows removing items anywhere in the list, without having numbering issues.

Iterating through the list is a little more involved, but certainly doable:
Code: [Select]
//Iterate through the items in a list
Set integer [itemCount] value to the converted value of {EXP: {TXTOCCURRENCES:";":list} / 2}
Set integer [itemEnd] value to 0
Start Loop : Repeat [itemCount] Times
    Set integer [itemStart] value to the converted value of {EXP: {TXTPOS:";":list:itemEnd} + 1}
    Set integer [itemEnd] value to the converted value of {TXTPOS:";":list:itemStart}
    Write [Blue] '{TXTSUBSTR:list:itemStart:{EXP: {INT:itemEnd} - {INT:itemStart}}}' to log
    Set integer [itemEnd] to [itemEnd] plus 1
End Loop

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #8 on: January 10, 2021, 06:22:41 PM »
Okay, so to make sure I'm understanding your example correctly ...

Code: [Select]
//Add a list item
Set text [list] to '{TXT:list};Item 1;'
Write [Blue] 'List contents: "{TXT:list}"' to log

So in the VA gui, this would be

Other -> Advanced -> Set a text value

Put "List" in the variable name, and set its text value to the literal text value of {TXT:list};{TXT:EDDI body scanned bodyname}; as opposed to setting it to another variable that is named that?  I tried another variable and it barked about not using semicolons.

Then choose Other -> Advanced -> Write a value to the Event log

and put {TXT:list} in the field, and a color.

Correct?

And then I guess I would just repeat that line for each instance, as there isn't a variable for each body, but the event resets all those "body scanned event" variables to their new values each time a body is scanned, so that it appends the new value of {TXT:EDDI body scanned bodyname} to the "list".

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #9 on: January 10, 2021, 06:40:48 PM »
The features used in these examples are designated "Advanced", and do require a certain level of understanding of the logic involved, in order to utilize them successfully


If you want to use some of these tokens in fields that don't accept semicolons, you are free to choose a different separator character, as long as you make sure it does not occur in the data you are storing, and that it is not a reserved character within VoiceAttack. The character is otherwise arbitrary.
There is nothing special about the text variable or the text stored within it either (to VoiceAttack itself, at least); only the manner in which the data is used by other actions allows it to function as a list.


If the intent is to add all eligible names to the list, you would use whichever series of actions you have devised to determine which bodies are eligible, and then, if a body meets all the criteria, append its name to the list.

The "Write a Value to the Event Log" action is merely used to show the example working. It is not required for the list to function.

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #10 on: January 11, 2021, 11:34:56 AM »
I think it has clicked in my head how this works.

Code: [Select]
Set text [list] to '{TXT:list};Item 1;'
Is conceptually similar to an incremental loop for an integer:

Code: [Select]
[number]=[number]+1
        only you are setting the text variable {list} to be a semicolon-delimited value and the statement you provided essentially makes it {list}={list}+{appended text}, with the appendant represented by "Item 1"

        For counting the items in the list, you said

Code: [Select]
{EXP: {TXTOCCURRENCES:";":list} / 2}'
Would that be "count of delimiters divided by 2"?  Because I understand it is counting the number of delimiter characters, but I was thinking it would be "+1" since three delimiters would mean four items, four delimiters would be five items, etc.

And I guess I would use something based on this for reading back the contents of the list via TTS in order to identify which item is the last in the list in order to replace the final delimiter with an "and" in the spoken sequence. Or maybe copy the {list} contents to a new variable using TXTREGEXREPLACE to replace the final delimiter with "and" that VA then reads back with TTS.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #11 on: January 11, 2021, 12:01:57 PM »
It's similar in a sense, but when incrementing an integer, the value itself is changed (E.G. 1 becomes 2), whereas with text the values are concatenated ("1" becomes "12") because you're dealing with characters of text, not mathematical numbers


The semicolon is placed both before and after each item, so there should always be two of them for each item in the list (and as such, getting the total amount and dividing by two equals the amount of items in the list).

This also prevents issues with items that are partially identical. E.G. if you want to remove an item named "item 1", but you also have an item named "other item 1", you can't just replace "item 1;", as that would lob off the end of "other item 1" as well, thus by instead replacing ";item 1;", you can be assured it's the correct item.


If you want to get the entire contents of the list for TTS, you can do
Code: [Select]
//Get all items in the list, separated by ", "
Write [Blue] '{TXTREPLACEVAR:"{TXTREPLACEVAR:list:";;":", "}":";":""}' to log

The first token replaces all double occurrences with ", ", and the output of that is then passed into the second token, which removes the semicolon at the beginning and end of the list (another advantage of wrapping rather than using a single separator).

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #12 on: January 11, 2021, 03:39:49 PM »
I don't know how up on regex you are, but I made some inquiries with some computery folks I know.  After using the sequence you provided to replace the ";" delimiters with single commas, would this work for making a TXT variable of the list that could be spoken, replacing the final delimiter with an "and"?

Code: [Select]
set [final delimiter replace] = [/\.(?!.*\,)]
and then

Code: [Select]
set [list spoken]={TXTREGEXREPLACE:list:final delimiter replace:and}
So that if I run your delimiter replacement, a {list} containing ";bob;;carol;;ted;;alice;" would become "bob, carol, ted, alice" and then copied to the {list spoken} as "bob, carol, ted and alice" or just "bob, carol" becomes "bob and carol".

Edit:  And then its a use of the number of items in the {list} for proper use is "is" vs "are" using what you previously provided me.

I think I have it.  Thanks a bunch!
« Last Edit: January 11, 2021, 04:30:54 PM by jcdick1 »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #13 on: January 11, 2021, 04:30:53 PM »
That is possible, yes...if you use the correct regular expression, which "[/\.(?!.*\,)]" is not. Where did you get that from?

Code: [Select]
//Get all items in the list, separated by ", ", with the last items separated by "and"
Set text [~input] to '{TXTREPLACEVAR:"{TXTREPLACEVAR:list:";;":", "}":";":""}'
Set text [~regex] to ',(?=[^,]*$)'
Set text [~replaceWith] to ' and'
Write [Blue] '{TXTREGEXREPLACE:~input:~regex:~replaceWith}' to log

jcdick1

  • Jr. Member
  • **
  • Posts: 55
Re: Creating a list for an E:D command
« Reply #14 on: January 11, 2021, 06:41:33 PM »
Quote
Where did you get that from?

I asked a programming acquaintance of mine.  His entire response was "const regex = /\,(?!.*\,}/gim" but I figured the "/gim" part wasn't really part of the generic regex statement.  But I'm glad I asked, because that is well past the "gobbledy****" border for me, and I'd have never understood why it wouldn't work.

I will assume this regex replace won't do anything if there's only one item in the list following all the delimiter processing.

Also, could I use a regex replace statement to remove a given item from the list?  For example, if

Code: [Select]
[list]=;item1;;item2;;item3;
and I do a detailed scan of Item 2 first, I'd need to do a search and replace for the the Item2 name and replace it with '', yes?  So that now

Code: [Select]
[list]=;item1;;item3;
I was thinking

Code: [Select]
set [body mapped blank] = ''
set [body mapped regex]=',(?=[^{TXT:bodyname}]*$)'  <- I hope I'm replacing the correct comma in modifying the previous regex.
set [list] = {TXTREGEXREPLACE:list:body mapped regex:body mapped blank}

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4759
  • RTFM
Re: Creating a list for an E:D command
« Reply #15 on: January 11, 2021, 07:04:42 PM »
There is already a built-in replace option in the "Set a Text Value" action that can be used for that, as noted in the examples...

Regex would at best achieve the same result, at the cost of more resource usage, and being much less readable when editing.


And no, you cannot randomly replace a character in a regular expression and expect it to work. If you want to use regular expressions, you'll need to learn their syntax, or at least look up examples that achieve the result you need. Sites like RegExr can also be useful.

"/\,(?!.*\,}/gim" is not a valid expression, and does not match the expression you mentioned previously...


Either way, you should now have a basic system to work with. For further developments you'll want to read up on how to use VoiceAttack's advanced features.
Press F1 while VoiceAttack has focus to open VoiceAttackHelp.pdf in your default PDF viewer, which contains information on those features.