Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

All discussions & material related to Command's Lua interface

Moderators: RoryAndersonCDT, michaelm75au, angster, MOD_Command

Post Reply
Rory Noonan
Posts: 2418
Joined: Thu Dec 18, 2014 1:53 am
Location: Brooklyn, NY

Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by Rory Noonan »

To reduce double handling, I recommend you read this tutorial first.

This tutorial will step you through the process of randomly selecting a course by creating a table of possible courses and randomly assigning one of them to a unit.

OK here we go;

Open a new blank scenario file.

Create a side, 'Side A' is the name I'll be using in the example code.

Add a ship to your new side, type isn't really important. You can name it whatever you like, but in the example below it's named 'Ship 1'.

Q: Based on the presence of the quotation marks and type of data inside them, what kind of value are the ship and side names?
A: The ship and side names are strings.


Plot out a course for your ship in the usual manner (press F3, click to plot, press Esc when you're done).

Click back on your ship and press Ctrl+C. This copies the unit name and GUID in a dictionary table to the clipboard, ready to be used for Lua scriting.

Now open the Lua console; Editor > Lua Script Console.

Use the dropdown function list to find the ScenEdit_GetUnit() function and insert it into the console (or you can just type it in). Now click between the two brackets (if using the insert function drop down, select the word 'table') and press Ctrl+V. Your console input area should look something like this:
ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})
The GUID will be different, and the name may be different depending on what you named your ship.

Remember from the previous tutorial that we can run this and not much will happen, because the output that is generated by the function we used is actually not being used for anything. Let's change that.

Make the necessary input to your console so it looks like this:
Ship_1 = ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})
print (Ship_1.course)

Click 'Run' and you should get an output similar to this (the latitude and longitude values will obviously be different unless you happened to pick the exact co-ordinates I did)
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.850046518263, latitude = -33.5171769441731 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } }

So here we can see that we've retrieved the plotted course from the ship. It's formatted into an array of nested dictionaries. Remember when I said that tables can be really powerful in the last tutorial? We're about to brush up ever so lightly against the power of tables.

Now, we're going to make a script where we have three different possible courses for a ship which are randomly chosen. Using the technique above, create two additional ships (for a total of three), create courses for those ships--these will be the alternate choices--and assign each ship to a variable (i.e. Ship_2 and Ship_3 in addition to Ship_1 above). Note that the actual position of the ship doesn't matter, we're just working with the courses here.

Your console should look something like this:
Ship_1 = ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})
print (Ship_1.course)

Ship_2 = ScenEdit_GetUnit({name='Ship 2', guid='b4060416-5dbe-474a-9a94-de18ea047d4e'})
print (Ship_2.course)

Ship_3 = ScenEdit_GetUnit( {name='Ship 3', guid='fad3dddf-a534-4a15-9c51-978c5db36c85'})
print (Ship_3.course)
Now that we've got the course data, there's a myriad of ways we could use it to implement the functionality we desire. I'm choosing a method that is simple and easy to explain. There are other ways to do this with less keystrokes, but they require a deeper understanding--and the end result is the same.

First we're going to clear the output area of the Lua console. Select all the previous output (i.e. the uppermost field in the Lua console), and press delete or backspace to clear it. This functionality will make your life a lot easier when you're working with long pieces of code in the future. Next, clear the 'Echo input script on result text' checkbox. With that box unchecked, we will just see the pure output without any of the input displayed.

Now, click run and something similar to this should appear.
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.850046518263, latitude = -33.5171769441731 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } }
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } }
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } }
Ok that looks quite intimidating. Lets break it down. What we have here is three seperate tables, none of which are assigned to a variable. Each table is an array of dictionaries, meaning it is a numbered list of seperate lists of keys and values. In the above example there's 3 seperate lists of keys and values in each table. Sound confusing? Let's look at it a different way.

Thankfully, Lua allows us to format code to make it easier for humans to understand. Below is the same code formatted in a style that makes it easier to comprehend:
{
[1] = {
TypeOf = 'ManualPlottedCourseWaypoint',
longitude = 155.850046518263,
latitude = -33.5171769441731
},
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 }
}

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 }
}

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 }
}

See how the use of seperate lines and indentation makes it easier to understand what's going on? The above code functions exactly the same as the first example, but is much easier to read. I've broken down the first value in the first table onto seperate lines to aid visualisation. You can do this for each value, but for the sake of space I've only done it for one here.

So we have three tables that are each pretty much the same, except for differing values in their nested dictionaries. As you have probably guessed, these are the coordinates of the courses we plotted just moments ago.

Now, we are going to put these three seperate tables into (yet another) table. So it will be a table of tables of tables. You can nest tables in Lua to your hearts content. There may be technical limits on it but they are well beyond anything you would reasonably need to use. To put these tables into our table, we're going to add a curly brace at either end of our pasted output, and then we're going to assign the whole thing a variable so we don't need to keep typing out all those characters over and over.

Add curly braces encapsulating the course tables as described above, and assign your newly created table (of tables of tables) to the variable Courses. Because we're now making these three tables into values in an array, we need to seperate them by commas. After each curly brace closing a table, add a comma. Your code should look like this (It's a good habit to put a comma after every closing curly brace, they don't cause errors if they're not necessary but if you need one and it's not there you'll get an error every time):
Courses = {
{
[1] = {
TypeOf = 'ManualPlottedCourseWaypoint',
longitude = 155.850046518263,
latitude = -33.5171769441731
},
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 }
},

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 }
},

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 }
},
}

Now to make use of our Courses table, we're going to use the math.randomseed, os.time and math.random native functions as we did in the last tutorial, but this time we're going to add in a special operator that returns a table's length.

Q: In the above example how would you print the latitude of the first waypoint in the first possible course?
A: print (Courses[1][1].latitude)
Q: In the above example how would you print the longitude of the second waypoint in the third possible course?
A: print (Courses[3][2].longitude)


Enter the following into your console:
Courses = {
{
[1] = {
TypeOf = 'ManualPlottedCourseWaypoint',
longitude = 155.850046518263,
latitude = -33.5171769441731
},
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 }
},

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 }
},

{
[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 },
[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 },
[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 }
},
}

math.randomseed(os.time())
randomCourse = Courses[math.random(1,#Courses)]
ScenEdit_SetUnit({guid=Ship_1.guid,course=randomCourse})
Click run and observe that the course of Ship 1 changes randomly between the three possible courses we plotted earlier.

But how does it work? We've already covered how our table of tables of tables works so I'll spare you from a repeat of that, but lets go through what the other three lines of code do.
math.randomseed(os.time())
First we set the random seed to the current operating system time. See the first tutorial for an explanation of why this is important.
randomCourse = Courses[math.random(1,#Courses)]
Now we define a new variable (randomCourse) with one of the arrays of the table Courses. Remember from the first tutorial that arrays are referenced with square brackets, and that the math.random function returns a random number between your chosen floor (1 in this case) and ceiling (#Courses). But #Courses isn't a number, you say! #Courses returns the number of items in an array, so it is actually treated as a number. We could have put the number 3 in and it would work, but using the # operator gives us the flexibility to add as many (or remove as many) items from the array in the future as we like, and the code will adapt and work regardless.

Q: For the array Example={'A','B','C','D','E'} what would #Example return?
A: 5
Q: How could we print the second item in that array?
A: print (Example[2])
Q: How could we print the last item in that array?
A: print (Example[#Example])

ScenEdit_SetUnit({guid=Ship_1.guid,course=randomCourse})
Now we've randomly chosen a value from our table (i.e. one of the tables describing a course), we use the ScenEdit_SetUnit function to assign it to our example ship. Because we assigned the randomly chosen table to the variable randomCourse we can simply put randomCourse in the course field (value is the proper term, but field makes more sense in this context) of the SetUnit function.

Congratulations, you just wrote a script that randomly chooses a pre-plotted course and assigns it to a unit.
Image
rmunie0613
Posts: 202
Joined: Tue Jan 02, 2018 7:41 pm

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by rmunie0613 »

love this!
HaughtKarl
Posts: 128
Joined: Wed Jan 28, 2015 4:13 am

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by HaughtKarl »


[/quote]
Now, click run and something similar to this should appear.

At this step mine comes out differently.
{ [1] = { longitude = 129.095475452519, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.3223893312447 }, [2] = { longitude = 129.609731071856, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.2636421487373 }, [3] = { longitude = 129.591676603146, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.0430498047744 } }
{ [1] = { longitude = 129.225406064969, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.4707737030459 }, [2] = { longitude = 129.482777536457, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.5766030646704 }, [3] = { longitude = 129.615161882619, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.4640453151941 } }
{ [1] = { longitude = 128.730800886859, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.4181118579756 }, [2] = { longitude = 128.800709844119, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.2250738936112 }, [3] = { longitude = 128.646823449038, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.0798593853367 } }
{ [1] = { longitude = 129.344399389574, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.9038721289695 }, [2] = { longitude = 129.100626420491, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 39.9280777999365 }, [3] = { longitude = 129.575855848895, TypeOf = 'ManualPlottedCourseWaypoint', latitude = 40.0135772675672 } }

See how my first line begins with " longitude = 129.095475452519" while yours begins with "TypeOf = 'ManualPlottedCourseWaypoint"? Why is mine different?
Betty_YueTu
Posts: 4
Joined: Fri Apr 13, 2018 12:54 am

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by Betty_YueTu »

There are no differences~~
User avatar
NimrodX
Posts: 82
Joined: Sat May 12, 2018 8:34 pm
Contact:

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by NimrodX »

I know this is old but I figured I'd explain in case anyone was still wondering.

Arrays are ordered, but dictionaries are unordered. Basically you can sort an array for example and the sort order will be "remembered" (stored, retained, whatever) but dictionaries don't have an order so can't be sorted. In a dictionary the idea is that you have keys to identify each item in the dictionary, therefore the order shouldn't matter. In an array, there is no key to identify each value so the only way to attribute meaning to the values is by the ordering. Thus ordering has to be maintained for arrays. (I mean imagine if your waypoints were randomly shuffled.... you'd end up with a much different course.)

So when you do something like print a dictionary, the order that it gets printed in is "nondeterministic" meaning that it's essentially random. (It's not really purely random, but what order its stored in internally is "implementation dependent" and undefined. In other words the order isn't guaranteed to be anything in particular that you can depend on so it's best to just treat the order as though it's random. Even if you could guess the order most of the time, it might change at some point for no apparent reason, etc.)

This is worthwhile to keep in mind because it applies equally to many other languages, such as Python and JavaScript, that also have arrays and dictionaries (though they might use different terminology).
miller7219
Posts: 223
Joined: Sat Apr 07, 2007 8:59 am

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by miller7219 »

Excellent stuff. Just beginning to learn Lua. While researching random ship placement I came across a script that will one can use to randomly place a random number of platforms within a defined area. I've made some modifications to the code and when run will drop 20-30 ships into the Yellow Sea area. Questions:

1. They won't assign to the "Vladivostok" ferry mission. Message Log indicates ships can't be assigned to Ferry Missions. I want the ships to auto set a course to Vladivostok how would I set that command in Lua?

2. What if instead of assigning the ships to a mission, I wanted them to be assigned a random course and speed? How would I add that to this script?
Attachments
RandomShipPacement.zip
(4.7 KiB) Downloaded 27 times
miller7219
Posts: 223
Joined: Sat Apr 07, 2007 8:59 am

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by miller7219 »

{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.850046518263, latitude = -33.5171769441731 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } }
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } }
{ [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } }

Mine looks like this:
{ [1] = { latitude = 38.9143481774981, TypeOf = 'ManualPlottedCourseWaypoint', longitude = 123.801182868273 } }
{ [1] = { latitude = 37.7138790465018, TypeOf = 'ManualPlottedCourseWaypoint', longitude = 124.248910918897 } }
{ [1] = { latitude = 35.304212744822, TypeOf = 'ManualPlottedCourseWaypoint', longitude = 124.867936684342 } }

Lat/Long will obviously be different than yours, but the output layout is different. Expected it to be the same.
TyphoonFr
Posts: 153
Joined: Thu Nov 23, 2017 4:27 pm
Location: FRA

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by TyphoonFr »


If you copy the coordinates of the pointer position with Ctrl-x, and you paste with Ctrl-v in the Lua console, the format is
latitude='38.2645033235011',longitude ='132.511598769527'

So it will be easier and faster to use the format:
{[1] = {TypeOf='ManualPlottedCourseWaypoint',latitude ='38.2645033235011',longitude='132.511598769527'}}
ORIGINAL: miller7219

Excellent stuff. Just beginning to learn Lua. While researching random ship placement I came across a script that will one can use to randomly place a random number of platforms within a defined area. I've made some modifications to the code and when run will drop 20-30 ships into the Yellow Sea area. Questions:

1. They won't assign to the "Vladivostok" ferry mission. Message Log indicates ships can't be assigned to Ferry Missions. I want the ships to auto set a course to Vladivostok how would I set that command in Lua?

2. What if instead of assigning the ships to a mission, I wanted them to be assigned a random course and speed? How would I add that to this script?
Your code works well,but mission ferry does not work with ships.
Replace it with a support mission with an RP at the location of 'VLADIVOSTOK'.
If you create multiple RPs that represent multiple ports, your ships will go back and forth between each.


You can assign your ships to a port (base='Vladivostok'), and tell them to go back to base (RTB=true), if you add the line:

ScenEdit_SetUnit({side='Merchant',unitname=new_merch.name,base='Vladivostok',RTB=true})

Christophe

To all English teachers of the forum, sorry if English is not my mother language.
miller7219
Posts: 223
Joined: Sat Apr 07, 2007 8:59 am

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by miller7219 »

[/quote]
Your code works well,but mission ferry does not work with ships.
Replace it with a support mission with an RP at the location of 'VLADIVOSTOK'.
If you create multiple RPs that represent multiple ports, your ships will go back and forth between each.


You can assign your ships to a port (base='Vladivostok'), and tell them to go back to base (RTB=true), if you add the line:

ScenEdit_SetUnit({side='Merchant',unitname=new_merch.name,base='Vladivostok',RTB=true})

Thanks! Added both suggestions to the script. A reference point with a patrol mission or assigning merchants to the a base and ordering them to RTB, both methods work. Updated script attached.

Still not sure how to order a random course.

Still tinkering with this random waypoint script Apache85 outlines. Maybe I'll figure it out!
Attachments
RandomShi.._Script.zip
(5.01 KiB) Downloaded 22 times
TyphoonFr
Posts: 153
Joined: Thu Nov 23, 2017 4:27 pm
Location: FRA

RE: Absolute Beginner's Intro to Lua Part 2: Randomly Assign a Course

Post by TyphoonFr »

Try this, in the script n ° 1, I add a list of 6 ports with random choice.
Ships will RTB to one of the 6 ports. You can change the location of ports, as well as the quantity and the name, by modifying well on the list of ports in the script:

PortTable ={"Port A","Port B","Port C","Port D","Port E","Port F"} --list of Port

In the script n ° 2, I added the random waypoints script of Apache85. For simplicity, I chose the ports like waypoints. The ships have the choice between 3 courses:
Course #1: "Port A", "Port B", then "Port C"
Course #2: "Port D", "Port E", then "Port F"
Course #3: "Port C", "Port A", then "Port F":

Courses = {
-- Course n°1 (Port A-Port B-Port C):
{
[1] = {TypeOf = 'ManualPlottedCourseWaypoint',latitude=37.2681434320673, longitude=122.59455932607}, -- Direction Port A
[2] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=31.2704422605587, longitude=122.014721160601}, -- Direction Port B
[3] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=35.5104815834653, longitude=126.293384175094} -- Direction Port C
},
-- Course n°2 (Port D-Port E-Port F):
{
[1] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=35.5486485738367, longitude=132.88663277135}, -- Direction Port D
[2] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=37.4361334445333, longitude=136.808678667868}, -- Direction Port E
[3] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=42.8284933260854, longitude=132.556812432586} -- Direction Port F
},
-- Course n°3 (Port C-Port A-Port F):
{
[1] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=35.5104815834653, longitude=126.293384175094}, -- Direction Port C
[2] = {TypeOf = 'ManualPlottedCourseWaypoint',latitude=37.2681434320673, longitude=122.59455932607}, -- Direction Port A
[3] = {TypeOf = 'ManualPlottedCourseWaypoint', latitude=42.8284933260854, longitude=132.556812432586} -- Direction Port F
}
}


Regarding the speed, despite several attempts, the ships persist in using the Cruise Trottle.
Attachments
Random Ship Test.zip
(7.46 KiB) Downloaded 34 times
Christophe

To all English teachers of the forum, sorry if English is not my mother language.
Post Reply

Return to “Lua Legion”