Giter VIP home page Giter VIP logo

kos's People

Contributors

a1270 avatar abenkovskii avatar alchemistch avatar bertcotton avatar chriswoerz avatar dunbaratu avatar ehrenmurdick avatar erendrake avatar firdacz avatar gisikw avatar hvacengi avatar jacktose avatar jwvanderbeck avatar kna27 avatar lucaelin avatar marianoapp avatar nivekk avatar palaslet avatar pgodd avatar piezpiedpy avatar rcrockford avatar sirdiazo avatar space-is-hard avatar tdw89 avatar thexa4 avatar tomekpiotrowski avatar tsholmes avatar wazwaz avatar yump avatar ziwkerman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kos's Issues

locking a var twice in interactive mode breaks kOS's dictionary from then on.

I discovered this when I was trying to print out a lot of stuff to test the problem I was having with a throttle of infinity (which used to work in old versions of kOS and just became a throttle of 1.0 effectively). When trying to diagnose that problem I ended up trying a lot of stuff at the interactive mode terminal that accidentally exposed this other problem:

Examine this output from the interactive terminal:

lock var to 0.5.
print var.
0.5
lock var to 0.4.
The given key was not present in the dictionary.
set var to 0.4.
The given key was not present in the dictionary.
set anotherVar to 5
The given key was not present in the dictionary.
copy testprog from 0.
The given key was not present in the dictionary.

This only happens in interactive mode. Once I try to "lock var to ..." a second time for a var that's been locked already, all statements parsed from then on seem to be broken, for all variables, even new ones, and any statement.

The same problem does not happen when doing it inside a program file. The following program runs just fine:

lock var to 0.5.
print var.
lock var to 0.4.
print var.
lock anotherLock to 5.0.
print anotherLock.
set anotherVar to 6.0.
print anotherVar.

Does this have something to do with the difference between how the parser behaves when it can see the upcoming future statements ahead of time (in a program file) versus when it can't (in interactive mode)?

Supplied parameter is not a number.

When I run the code shown below, I receive the error mentioned in the title. However, the parameter is a number because it is logged at a number in "debug."

As a side note, the "line zero errors" are frustrating because you have to guess where the error is coming from.

CLEARSCREEN.

set isLanded to 0.
set isFinal to 0.

set lastTime to TIME.
set dt to 1.

// Navigation constants
set threshW to latlng(-0.04022641,-74.71819).
set targW to latlng(-0.04059032,-74.67182).
set targElev to 67.
set threshE to latlng(-0.04179348,-74.49593).
set vor1 to latlng(-0.035,-76.5).
set glideslope to -8.
set glideslopevari to 1.

// Persistent private variables
set climbuUuerrSum to 0.
set climbuUulastErr to 0.
set climbuUulastInput to 0.

set speeduUuerrSum to 0.
set speeduUulastErr to 0.
set speeduUulastInput to 0.
set speeduUuSMOOTHuUuStm1 to 0.
set speeduUuSMOOTHuUuXtm1 to 0.

set pitchuUuerrSum to 0.
set pitchuUulastErr to 0.
set pitchuUulastInput to 0.
set pitchuUuSMOOTHuUuStm1 to 0.
set pitchuUuSMOOTHuUuXtm1 to 0.

UNTIL isLanded = 1 {
    set manageAlt to 0.
    set manageClimb to 0.
    set manageSpeed to 0.
    set managePitch to 0.

    // Intermediate variables
    set tClimb to 0.
    set tAlt to 0.
    set tSpeed to 0.
    set tPitch to 0. // Both an intermediate and final variable

    // Final variables
    set tThrust to 0.
    set tPitch to 0.    
    set tHeading to 0.


    // <main>

    if isFinal = 0 {

        set tAlt to 2500.
        set manageAlt to 1.

        set tSpeed to 150.
        set manageSpeed to 1.

        if (vor1:distance > 2500) {

            set tHeading to 90.


            set dr to vor1:distance - 30000. // Target arc: 30km
            set dH to dr*(90/5000).

            if dH < -90 {
                set dH to -90.              
            }.

            if dH > 90 {
                set dH to 90
            }.

            set dH to dH + 90.
            set tHeading to vor1:HEADING + dH.  
            if (vor1:HEADING > 45  AND vor1:HEADING < 135) {
                set tHeading to vor1:HEADING.
            }.
        }.


        if (vor1:distance <= 2500) {
            set tHeading to 90.
            if (vor1:HEADING > 45 AND vor1:HEADING < 135 AND tAlt > 2000 AND tAlt < 3000) {
                set isFinal to 1.
            }.
        }

    }.

    if isFinal = 1 {
        set tPitch to 5.
        set managePitch to 1.

        set hdist to ((altitude-targElev)^2+(targW:distance)^2)^0.5.    //because arctan is busted.
        set slope to (-1)*arccos(targW:distance/hdist).

        set baseClimb to tan(glideslope)*SURFACESPEED.
        set diff to (targW:bearing-threshE:bearing).

        if slope < (glideslope-glideslopevari) {
            // Too low
            set dS to (glideslope-glideslopevari) - slope.

            set tClimb to baseClimb + 3*dS.
            set manageClimb to 1.
        }.

        if slope > (glideslope+glideslopevari) {
            // Too high
            set dS to slope - (glideslope+glideslopevari).

            set tClimb to baseClimb - 3*dS.
            set manageClimb to 1.
        }.

        if slope < (glideslope+glideslopevari) AND slope > (glideslope-glideslopevari){

            set tClimb to baseClimb.
            set manageClimb to 1.

        }.

        if targW:bearing > 0.5 {
            // Too far left

            set tHeading to 90 + 2*abs(diff).
        }.

        if targW:bearing < -0.5 {
            // Too far right

            set tHeading to 90 - 2*abs(diff).
        }.


        if abs(targW:bearing) < 0.5 and abs(diff) < 0.25{
            set tHeading to 90.
        }.  

        if (ALTITUDE-targElev) < 50 {

            set tClimb to -5.
            set manageClimb to 1.

            set tHeading to 90.
        }.

        if (ALTITUDE-targElev) < 1.9 {

            set isLanded to 1.
        }.

    }.


    // </main>

    // Achieves tPitch using tSpeed
    if managePitch = 1 {

        set realPitch to tPitch.
        if manageClimb {
            set realPitch to (0.01 * error + 0.001 * climbuUuerrSum - 0.001 * dInput)/spdRatio. // Sloppy way of getting (close to) actual pitch
        }.

        set error to tPitch - realPitch.
        set pitchuUuerrSum to (error * dt) + pitchuUuerrSum.
        set dInput to (realPitch - pitchuUulastInput) / dt.
        set pitchuUulastErr to error.
        set pitchuUulastInput to realPitch.
        set tSpeed to  0.1 * error + 0 * pitchuUuerrSum - 0 * dInput.

        set smoothingFactor to 0.9.
        set invSmoothingFactor to 1 - smoothingFactor.

        set St to pitchuUuSMOOTHuUuXtm1 * smoothingFactor + invSmoothingFactor * pitchuUuSMOOTHuUuStm1.
        set pitchuUuSMOOTHuUuStm1 to St.
        set pitchuUuSMOOTHuUuXtm1 to tSpeed.

        set tSpeed to St.       

        if (tSpeed < 70) {

            set tSpeed to 70.
        }.

        if (tSpeed > 300) {

            set tSpeed to 300.
        }.

    }.


    // Achieves tAlt using tClimb
    if manageAlt = 1 {

        set spdRatio to SURFACESPEED/100.
        set maxClimb to spdRatio*100.
        set maxDescent to spdRatio*-100.

        set tClimb to (tAlt - ALTITUDE) * 5.

        if tClimb > maxClimb {

            set tClimb to maxClimb.
        }.

        if tClimb < maxDescent {

            set tClimb to maxDescent.
        }.

        set manageClimb to 1.
    }.

    // Achieves tClimb using tPitch
    if manageClimb = 1 {

        set spdRatio to SURFACESPEED/100.

        set error to tClimb + VERTICALSPEED.
        set climbuUuerrSum to (error * dt) + climbuUuerrSum.
        set dInput to (-1*VERTICALSPEED - climbuUulastInput) / dt.
        set climbuUulastErr to error.
        set climbuUulastInput to -1*VERTICALSPEED.

        set tPitch to (0.01 * error + 0.001 * climbuUuerrSum - 0.001 * dInput)/spdRatio.

    }.

    // Achieves tSpeed using tThrust
    if manageSpeed = 1 {

        set error to tSpeed - SURFACESPEED.
        set speeduUuerrSum to (error * dt) + speeduUuerrSum.
        set dInput to (SURFACESPEED - speeduUulastInput) / dt.
        set speeduUulastErr to error.
        set speeduUulastInput to SURFACESPEED.
        set tThrust to  0.1 * error + 0 * speeduUuerrSum - 0 * dInput.

        set smoothingFactor to 0.9.
        set invSmoothingFactor to 1 - smoothingFactor.

        set St to speeduUuSMOOTHuUuXtm1 * smoothingFactor + invSmoothingFactor * speeduUuSMOOTHuUuStm1.
        set speeduUuSMOOTHuUuStm1 to St.
        set speeduUuSMOOTHuUuXtm1 to tThrust.

        set tThrust to St.      

        if (tThrust < 0) {

            set tThrust to 0.
        }.

        if (tThrust > 1) {

            set tThrust to 1.
        }.
    }.


    if (tPitch > 45) {
        set tPitch to 45.
    }.

    if (tPitch < -45) {
        set tPitch to -45.
    }.

    //set tHeading to tHeading - 90.

    UNTIL tHeading <= 360 {
        set tHeading to tHeading - 360.
    }.

    UNTIL tHeading > 0 {
        set tHeading to tHeading + 360.
    }.

    // Set all of the values
    set aThrust to tThrust.
    set aHeading to tHeading.
    set aPitch to tPitch.

    print "Pitch: " + aPitch  + "                      " at (5,1).
    print "Heading: " + aHeading + 90  + "                      " at (5,2).
    print "Thrust: " + aThrust  + "                      " at (5,3).
    print "Steering: " + steering  + "                      " at (5,4).
    print "Vor1 heading: " + vor1:heading  + "                      " at (5,5).
    print "Prograde: " + prograde  + "                      " at (5,6).

    lock THROTTLE to aThrust.
    //lock STEERING to HEADING(aHeading, aPitch).

    set aCorrect to -90 + aPitch.

    LOG aCorrect to debug.

    lock steering to UP + R(tHeading,aCorrect,270).

    // Calculate the time loop
    set dt to TIME - lastTime.
    set lastTime to TIME.
}.

set THROTTLE to 0.
set STEERING to HEADING(90, 3).

BRAKES ON.

PR crashes game when paused

Hello,

The game seems to crash when paused and the kos console is running:

ArithmeticException: NAN
  at System.Math.Sign (Double value) [0x00000] in <filename unknown>:0 

  at kOS.Utilities.SteeringHelper.Sign (Vector3d vector) [0x00000] in <filename unknown>:0 

  at kOS.Utilities.SteeringHelper.GetEffectiveInertia (.Vessel vessel, Vector3d torque) [0x00000] in <filename unknown>:0 

  at kOS.Utilities.SteeringHelper.SteerShipToward (kOS.Suffixed.Direction targetDir, .FlightCtrlState c, .Vessel vessel) [0x00000] in <filename unknown>:0 

  at kOS.Binding.FlightControlManager+FlightCtrlParam.SteerByWire (.FlightCtrlState c) [0x00000] in <filename unknown>:0 

  at kOS.Binding.FlightControlManager+FlightCtrlParam.OnFlyByWire (.FlightCtrlState& c) [0x00000] in <filename unknown>:0 

  at kOS.Binding.FlightControlManager.OnFlyByWire (.FlightCtrlState c) [0x00000] in <filename unknown>:0 

  at (wrapper delegate-invoke) FlightInputCallback:invoke_void__this___FlightCtrlState (FlightCtrlState)

  at (wrapper delegate-invoke) FlightInputCallback:invoke_void__this___FlightCtrlState (FlightCtrlState)

  at Vessel.FeedInputFeed () [0x00000] in <filename unknown>:0 

  at FlightInputHandler.FixedUpdate () [0x00000] in <filename unknown>:0 

(Filename:  Line: -1)

Look rotation viewing vector is zero

(Filename:  Line: 62)

Look rotation viewing vector is zero

(Filename:  Line: 62)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

Invalid parameter because it was infinity or nan.

(Filename:  Line: 137)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\BoxShape.cpp Line: 126)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\SphereShape.cpp Line: 96)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\CapsuleShape.cpp Line: 133)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\CapsuleShape.cpp Line: 133)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\BoxShape.cpp Line: 126)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\SphereShape.cpp Line: 96)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\CapsuleShape.cpp Line: 133)

dest.radius>=0.0f

(Filename: ..\..\Core\Common\src\CapsuleShape.cpp Line: 133)

Look rotation viewing vector is zero

(Filename:  Line: 62)

Crash!!!

The Computer should do SHIP:CONTROL:NEUTRALIZE on program end

When using the LOCK STEERING style of control, when the program ends the system gives control back to the player again, even if "UNLOCK STEERING" was never explicitly called. This is very useful when programs crash or stop from an exception before reaching the intended endpoint where the UNLOCK command would be.

But when using the SET SHIP:CONTROL... style of control, it does not do this. When the program ends the player still cannot manually control the ship until issuing the "SET SHIP:CONTROL:NEUTRALIZE to True" command at the interactive terminal.

The control should probably be given back to the player automatically on exiting the (outermost nested) program just like it is for the LOCK STEERING technique.

integers do not work as boolean flags in UNTIL's (update: and maybe all other uses of Opcode LogicalNot).

Previously I had created issue #26 about integers not working as booleans. It was closed as un-reproducable.

But I just discovered how to re-produce it. The error only appears when using UNTIL statements, and does not appear in IF statements.

In other words:This works as expected:

set x to 0.
if x then { print "x is true". }.

But this does not.

set x to 0.
until x { print "X is still false.". }.

The error is in the implementation of UNTIL, not of IF.

The above until loop should do this:

X is still false.
X is still false.
X is still false.
X is still false.
[ continues like that forever until CTRL-C ]

But instead it just exits the loop immediately, as if 0 meant "true".

WARP does not distinguish between physics and rails mode

A KSP bug

When launching from Kerbin, the time warp mode sometimes remains stuck in physics mode even after leaving the atmosphere and cutting the throttle. I believe this is a bug in the stock game, however when flying manually it is easily worked around by clicking the 1x (normal speed) button manually, causing the game to switch to rails mode if it didn't do so automatically.

KOS script errors

However, KOS seems to be unable to trigger the switch from physics warp to rails warp. As a result, my auto-warping scripts tend to crash a lot with the message,

Array index is out of range.

Which occurs when a script tries to set WARP to a level higher than 3 while in physics mode. (WARP levels 4-7 are only valid when in rails mode.)

Failed scripting solutions

I have inserted gratuitous commands like

set WARP to 0.
WAIT 1.

into my scripts to try and force the game to switch to rails mode if available, but unlike manually clicking the 1x button, this doesn't seem to help when a script does it.

(Strangely, I think it may actually be the act of moving the mouse over the UI which causes the game to recheck if rails warp is available, rather than clicking on the 1x button, specifically.)

Possible KOS solutions

  1. Add settable WARP:MODE property. A setter would allow scripts to force KSP to switch between physics and rails as needed.
  2. Add a readable WARP:MODE property. This would allow scripts to adjust their behavior to avoid trying to set WARP >= 4 when in physics mode.
  3. Add a WARP:MAX property. In practice, this would mostly be used like the WARP:MODE option, but with physics mode indicated by a value of 3, and rails by a value of 7.
  4. Fix the KSP bug by convincing KSP to check if it should automatically switch to rails mode more often, as it should.

Any one of these changes would allow me to solve my current problem, but the most comprehensive solution on KOS' part would be to implement 1, 2, and 3 combined. I strongly suspect that 4 is possible to do in a plugin, but I understand that is outside of the scope of the KOS project.

(suggest) help for people making color syntax highlight defnitions

There's more than one IDE people made to handle kosscript, and some people have tried making syntax definition configurations for them, and other editors that support that type of thing (I maintained one for VIM but it's out of date now).

One shared problem I think all such people would have (I assume it's a shared problem) is that a lot of what you want to highlight has to be configured by reading the C# code here by eyeball, finding all the cases of things you want to highlight, and then manually coding those strings into the syntax def file. That makes keeping it updated a bit hard.

You can get the base syntax by reading the TinyPG configuration, but it only contains half of what you need to know. It tells you, for example, that a function call looks like:

something left-paren something right-paren

But it doesn't tell you that, for example, there is a built-in sqrt() function but not a built-in cuberoot() function. To get the list of all those terms you have to read through the code.
It doesn't tell you that BODY is a built-in special variable name but PLANET isn't.
It doesn't tell you that, for example, ":DELTAV" is a defined suffix for a NODE, but not for a BODY.

I was considering whether or not it would possible to put terms like that into some standardized form for people to pull out and use in syntax highlight configurations. It could just be as simple as having a bit of C# code that uses reflective methods to iterate over all the existing subclasses of the FunctionBase class, the BoundVariable class, and the SpecialVariable classes and prints out their configured strings. (Assuming the strings were written in a way that stuffs them into member variables instead of using string literals.)

discuss: List syntax for docking ports.

The previous version of kOS used:

list DOCKINGPORTS from VESSEL in x.

The new syntax:

LIST (IDENTIFIER (IN IDENTIFIER)?)? EOI;

Any ideas on what the best method for a dockingport command would be?

Parameters are passed in reverse order

The parameter list of a script is passed to it backwards. Example script test.txt:

declare parameter p0.
declare parameter p1.
declare parameter p2.
declare parameter p3.

print "0: " + p0.
print "1: " + p1.
print "2: " + p2.
print "3: " + p3.

Call it from the terminal as follows:

run test(0, 1, 2, 3).

The expected result would be:

0: 0
1: 1
2: 2
3: 3

But, the actual result is:

0: 3
1: 2
2: 1
3: 0

I believe this bug also effects some or all built-in functions (but not constructors):

print mod(21, 6).

According to the documentation, this command should return 3. However, it actually returns 6. But, it gives the expected answer if we flip the parameters:

print mod(6, 21).

Strange order of operations: "and" seems to evaluate before ">"

print 2 >= 1 and 2 > 1.
False.
print (2>=1) and (2 > 1).
True.

I suspect this is happening because the 'and' and 'or' operators aren't waiting for the <, <=, =, >=, and > operators to be evaluated first, leading the expression to end up trying to do things like this:
print ((2>=1) and 2) > 1.

which leads to asking if True is greater than 1.

Tertiary operator ("?") (with short-circuit logic) to protect against infinity in a single expression.

The change for #14 broke the ability to store infinity in a variable.

Now if there is going to be a chance that there might be a divide by zero anywhere in an expression, that has to be checked for ahead of time, rather than allowing it to return infinity. As soon as any math expression or sub-expression returns infinity, the script dies.

That means things like this:
set var to x / y.

If there's a chance Y might be zero, have to be turned into this instead:

set var to bigNum.
if y > 0 or y < 0 { 
  set var to x / y.
}.

(I'd use if/else instead for that if there was an 'else'.)

This makes writing lock expressions currently a bit of a pain because there's no mechanism currently to protect a lock expression with an "if" like you can with a 'set'. The value of a lock must be written out as a single expression, which you must assume could be executed at any random time not directly under your control (because flybywire might execute it even if you don't).

So what I'm talking about is the ability to do this:

lock var to x /y, unless y happens to be zero at this instant, in which case lock it to bigNum instead.

With a 'set' command, you can control when the check happens as shown above.

But since a lock has to all be one expression, the technique used for the set isn't quite right.

If something like C's trinary operator "?" was implemented, then you could protect lock expressions like this:

lock var to ( (y = 0) ? bigNum : x /y)

Obviously the syntax there isn't quite right for kosscript's terms. Perhaps something like:

lock var to CHECK y = 0 TRUEVAL bigNum FALSEVAL x/y .

might look a bit more 'kosscript'-like.

As it stands, the only way to protect the expression is to lie about the contents of 'y' and pretend it's something like 0.000001 whenever it's really 0.0, which if you're using it elsewhere besides this lock expression, could be messy.

That's what I'm doing for now in my script to deal with this new change. When the air pressure is really 0, I'm pretending it's 0.000001 just to keep the script from barfing out.

(enhancement) versatile loop akin to C's FOR loop

C's FOR loop is quite versatile. A lot of other languages have loops that sound nicer in English when read out ("for x from 1 to 10 step 2" for example), but what they gain in looks and legibility, they lose in versatility. They constrain the type of loop you can have. It must have exactly one loop counter variable, it must increment by a value known ahead of time, with an endpoint based upon a greater-than or less-than check which isn't appropriate for some algorithms where the counter isn't a number, and so on.

What I'm considering is a loop with the versatility of the C FOR loop , with the same 3 parts to it (do this when starting, check this to see when to stop, do this to increment), but done in a way more consistent with kosscript's "special" style of syntax.

I propose this syntax:
FROM init UNTIL end-check GOING incrimenter { โ€ฆ }.
Or the same thing by overloading the FOR syntax to also accept:
FOR init UNTIL end-check GOING incrimenter { โ€ฆ }.

(I'm not sure which I prefer. "FOR" is more traditional for programming, and also used by the list iterator loop already, but "FROM" flows better in the way it sounds in English and they way I've written it.)

examples:

FOR x=0 UNTIL x>10 GOING x=x+1
{
  print x.
}.

I wold propose that the expressions init, end-check, and incrimenter actually be designed to be any block of code, so they could include curly braced complex sections, like so:

// Iterate with x counting up while y counts down and they meet in the middle:
FOR {x=0. y=100.} UNTIL x >= y GOING {x=x+1. y=y-1}
{
  โ€ฆ stuff ...
}.

It should be instantly familiar to experienced programmers, while at the same time being easy to understand for first-timers because it describes the clauses and what they mean.

The implementation of parsing it is very simple, I think. It's just that you take anything of the form:
FOR A UNTIL B GOING C { body }.
And make it behave like so:
A.
UNTIL B {
body.
C.
}.
Most of the routines to do this are already there. It's just a matter of linking them together.

ELSE operator

The else statement extremely necessary.

Example syntax:

IF stmt {
 run foo.
}
ELSE {
 run bar.
}

IF stmt {
 run foo.
}
ELSE IF stmt2 {
 run baz.
}

Cannot "set" a variable that later will become a "lock".

print "starting.".
set var to "set value".
print "set var is: " + var.
lock var to "locked value".
print "locked var is: " + var.

Result:

starting.
Variable var* is not defined
Instruction 10

When going through and parsing the script ahead of time, kOS sets up conditions such that if var will at any point in the script be used in a lock command it cannot ever be used in a set command elsewhere in the script (even at an earlier point in the script).

(suggestion for fix: if it's going to be a lock such that it must be a function returning a value, then when the 'set' is encountered make kOS translate that kosscript code into this k-risc code:
step 1 - evaluate expression into a temp value.
step 2 - lock variable to that constant temp value.
This way the variable always is a 'lock' even when used as a 'set'. The 'lock' is locking to a value that was calculated just once instead of each time - so it behaves like a 'set'.)

print..at command does not use variables

Using version v12.0P3 the following code:

set tableCol to 2.
print ship:vesselname at (tableCol, 2).

results in a syntax error with the arrow pointing at the "t" in "tableCol".

Using
print ship:vesselname at (2,2).
works as expected.

And just cause I was confused before, this is the version on https://github.com/KSP-KOS/KOS/releases with the files in the zip file all dated April 7.

ETA:TRANSITION is broken

This stat seems like it should be really useful for predicting SOI changes, but as far as I can tell the number it returns is always too high - sometimes by quite a lot.

To demonstrate: manually set up an encounter with the Mun, then run the following command in the KOS terminal:

add node(time:seconds + ETA:transition, 0, 0, 0).

Go to map view and focus on the Mun. Compare the ETA reported by the stock UI for the encounter to that of the new maneuver node, and you will see that they do not match as they should.

When I tried this a second ago, the node was placed about 5 minutes after the actual transition; that is the closest I have seen it. Earlier tests averaged a separation of more like 20 minutes, but sometimes it is off by hours.

Cannot case from source to destination.

Hello,

I encounter this when running exenode. It seems to be a c# error.

// execute maneuver node
set nd to nextnode.
print "T+" + round(missiontime) + " Node in: " + round(nd:eta) + ", DeltaV: " + round(nd:deltav:mag).
print "T+" + round(missiontime) + " Node apoapsis: " + round(nd:orbit:apoapsis/1000) + "km, periapsis: " + round(nd:orbit:periapsis/1000) + "km".
set maxda to maxthrust/mass.
print "T+" + round(missiontime) + " Max DeltaA for engine: " + round(maxda).
set dob to nd:deltav:mag/maxda.     // incorrect: should use tsiolkovsky formula
print "T+" + round(missiontime) + " Duration of burn: " + round(dob).

print "T+" + round(missiontime) + " Warping to maneuver...".
run warp(nd:eta - dob/2 - 45).
// turn does not work during warp - so do now
print "T+" + round(missiontime) + " Turning ship to burn direction.".
sas off.
rcs on.
// workaround for steering:pitch not working with node assigned
lock np to R(0,0,0) * nd:deltav.
lock steering to np.
wait until abs(np:pitch - facing:pitch) < 0.1 and abs(np:yaw - facing:yaw) < 0.1.
rcs off.
run warp(nd:eta - dob/2).

wait 3.
wait until abs(np:pitch - facing:pitch) < 0.1 and abs(np:yaw - facing:yaw) < 0.1.
wait 2.

print "T+" + round(missiontime) + " Orbital burn start " + round(nd:eta) + "s before apoapsis.".
// lock steering to node:prograde which wanders off at small deltav
if nd:deltav:mag > 2*maxda {
    when nd:deltav:mag < 2*maxda then {
        print "T+" + round(missiontime) + " Reducing throttle, deltav " + round(nd:deltav:mag) + ", fuel:" + round(stage:liquidfuel).
        // continue to accelerate node:deltav
        set np to R(0,0,0) * nd:deltav.
    }
}
set tvar to 0.
lock throttle to tvar.
until nd:deltav:mag < 1 and stage:liquidfuel > 0 {
    set da to maxthrust*throttle/mass.
    set tset to nd:deltav:mag * mass / maxthrust.
    if nd:deltav:mag < 2*da and tset > 0.1 {
        set tvar to tset.
    }
    if nd:deltav:mag > 2*da {
        set tvar to 1.
    }
    print "Throttle: " + round(tset) at (0,29).
    print "DeltaA: " + round(da) at (20,29).
    print "Node DeltaV: " + round(nd:deltav:mag) at (0,30).
    print "Apoapis: " + round(apoapsis/1000) at (0,31).
    print "Periapis: " + round(periapsis/1000) at (20,31).
}
// compensate 1m/s due to "until" stopping short; nd:deltav:mag never gets to 0!
if stage:liquidfuel > 0 {
    wait 1/da.
}
lock throttle to 0.
unlock steering.
remove nextnode.
print "T+" + round(missiontime) + " Burn complete, apoapsis: " + round(apoapsis/1000) + "km, periapsis: " + round(periapsis/1000) + "km".
print "T+" + round(missiontime) + " Fuel after burn: " + round(stage:liquidfuel).

saving/reloading the game zeroes the files on the local drive.

Prior to saving, list the local drive and you see something like this:

list

Volume #1
Name                            Size
------------------------------------
prog1                            420
prog2                           1200
Free space remaining: 8380

Then, exit the game.
Then re-run the game, go to the Tracking Center, and switch back to the vessel again and take a look at the local drive again. Now you see this:

list

Volume #1
Name                            Size
------------------------------------
prog1                              0
prog2                              0
Free space remaining: 10000

The filenames are there, but with nothing in them.

It does not happen with the archive - only with local volumes. So I assume it has something to do with loading/saving the contents in the persistence file.

"locks" can't be read inside WHEN/THEN clauses.

If you set up a 'when' trigger designed to interrupt you in the future, and then lock a variable to an expression in the mainline code, then when the 'when' condition triggers, inside the 'when' clause the lock variable is treated as "undefined".

Here's a small example program demonstrating it:

set startTIme to time:seconds.
set done to 0.

// Set up a trigger to occur 5 seconds from now:
when time:seconds > startTime + 5 THEN {
  print "WHEN/THEN."
  print "in When/then body, elapsed time = " + secs.
  set done to 1.
}.

// Use the number of seconds elapsed as an example lock variable:
lock secs to (time:seconds - startTime).

print "Expect an interruption in 5 seconds...".

until done = 1{
  print "In mainline program, elapsed time = " + round(secs,0).
  wait 1.
}.

The expected result should be:

Expect an interruption in 5 seconds...
in mainline program, elapsed time = 0
in mainline program, elapsed time = 1
in mainline program, elapsed time = 2
in mainline program, elapsed time = 3
in mainline program, elapsed time = 4
WHEN/THEN.
In when/then body, elapsed time = 5

The actual result is this:

Expect an interruption in 5 seconds...
in mainline program, elapsed time = 0
in mainline program, elapsed time = 1
in mainline program, elapsed time = 2
in mainline program, elapsed time = 3
in mainline program, elapsed time = 4
WHEN/THEN.
Variable secs is undefined

No way to unset target from the script.

Once you do this:

set target to "some ship".

Then the only way to unset the target from then on is with manual user clicks.

You cannot set the target to a bogus ship name string, nor does "unset target" cause the target to be deselected.

Reminder: KOS_DOC has changes to go with the 0.12 release.

This is just a reminder to @erendrake that when 0.12 is released, there's some documentation updates to the MD files over in the KOS_DOC project that go along with it (like the list [] syntax). But they haven't been run through the doc generation process, and aren't public yet.

(On a side note, there's one thing over there that I don't know how to document because I don't actually know the answers myself. Can you have a look at this issue, @marianoapp, and see if you can help? It's this one: KSP-KOS/KOS_DOC#5 )

Expressions like 1.23*10^15 give the wrong number (tries to perform 10^15 as an integer that overflows).

print 1.23 * 10^35.
-2641404887.04

I looked at that and thought, "that can't be right". It's the wrong magnitude, wrong digits, and wrong sign.

After a bit of investigating, I think what it's doing is calculating 10^35 using entirely integer operations, thus getting an overflow result of the 32-bit minimum integer (-2147483648), and then multiplying that by 1.23.

As the example below shows, it doesn't matter if the value is inside variables in the expression or written as "raw" literals in the expression. Also, if the value is written with a ".0" suffix it forces the system to stop treating it as an integer and works as a temporary workaround:

set mantissa to 1.23.
set exponent to 35.
set exponentPointZero to 35.0.

print mantissa * 10 ^ exponent.
-2641404887.04

print mantissa * 10 ^ exponentPointZero
1.23E+35

The current way the parser is implemented, you can go up to 10^9 safely, but when you go to 10^10 or higher, this problem triggers unless you explicitly write one term with a decimal point, which isn't surprising because that's where the value exceeds signed integer32 max int.

I noticed that the divide operator (/) seems to be able to divide two integers without triggering integer-style truncation, i.e "print 1/2." returns 0.5, rather than 0, so maybe whatever was done for that can be done for the exponent operator (^) too.

can't use variables to index a list.

This works:

print someList#1.

This doesn't:

set idx to 1.
print someList#idx.

Is there a reason that you can only use literals with the "#" operator? Was that a deliberate decision? At the moment the only way to access the elements of a list is to iterate over them with the list's for loop. There seems to be an ':iterator' suffix but I don't think it's usable from within the script. You can't add or subtract or dereference the iterator so it's not useful in the way that iterators normally are.

transfer release notes for v12.0P1 to

I was about to build a release to share with everyone, then i realized i don't really know about all of the changes additions you made other than the major parser rewrite.

ill try to dig through the git log and find what i can

Surface retrograde

Is there a way to get the surface retrograde?
Very useful for lander scripts

Control-C doesn't interrupt at the interactive terminal.

set x to 1.
until x > 1000 { print x. set x to x + 1. }.
1
2
3
3
4
5
// (and so on......)

I can't hit Control-C to interrupt that printing. It goes all the way to the end of 1000. I think I used to be able to hit Control-C to stop execution.

immediate mode not allowing multiline syntax.

In previous versions of kOS you could write this in immediate mode at the terminal prompt and it would wait until you entered the final end brace ("}") before executing the "until" command:

set x to 1.
until x > 5 {
  print x.
  set x to x + 1.
}.
1
2
3
4
5

But in this new version it attempts to evaluate the "until" expression immediately as soon as you type the header line and hit 'enter', and thus gives a syntax error.

set x to 1.
until x > 5 {
syntax error at line 1
until x > 5 {
               ^

In the new version you'd have to type it all in in one line to make it work, like so:

until x > 5 {  print x.  set x to x + 1.}.

I noticed this because I was trying to test a few things out and therefore was typing syntax in at the terminal.

After 0.12 is out - should there be a goal for 0.13 ahead of time?

Obviously bugs should be fixed as solutions present themselves, but what really draws people in are new things to do.

Would it be a good idea to have a sort of brainstorming session of wishlist feedback from people, to help drive what 0.13 should focus on?

At any given moment there's always going to be more new features that people want than is reasonable to actually plan for just one release, but getting a feel for which things are most important to the user community might be a good idea to help prioritize which things to work on first.

But then again, when development is entirely on voluntary time, asking developers to work on a thing that the developers don't think is important, or is uninteresting to them, is a sure way to stall the project.

So to find a good compromise between those two competing factors of "give the users what they want" and "let developers work on what they want", I was contemplating this: First, potential developers here discuss what things they'd like to work on - ideas they have for future enhancements. Then second, a list of those things is presented on the forum for discussion. The intersection of "set of things developers want" and "set of things users want" becomes the basis for picking the next goals.

I'm just throwing a random idea out through bleary eyes too early in the morning. I don't know if I explained it well, but we'll see. What do people think of this?

Unable to view terminal window

Sometimes I will accidentally drag the kos window off of the screen. After this, I cannot access the kos window anymore.

I must reinstall the plugin to fix the problem; this is very annoying.

To reproduce, drag the kos window rapidly off the screen when not in fullscreen.

discuss: NULL and NaN check ability?

I think the ability to do the following would be useful:

if isNULL( expr ) { 
  // stuff
}
if isNaN( expr ) {
  // stuff
}

Only if every place in the kOS C# code that could potentially return NaN or NULL to the script manages to check for every case where that could happen and trap it and turn it into a different result would such functions be useless. (And even then I would argue that doing that trap is the wrong solution as it hides relevant data from the script programmer. There is a big difference between a valid number versus a NaN and a big difference between a valid object with zeroed-out data versus a NULL).

For example, you try to look at what your next encounter is. But there is no next encounter. NULL is the sensible way to report that, but currently returning a NULL to the script leaves the script programmer helpless to do anything to detect it and just means their code will crash when they try using the result.

There is also a difference between "your fuel tanks are empty" versus "you have no fuel tanks", so returning zero for cases where a resource is invalid and missing might not actually be the correct answer (see #5).

(suggest) Adding a syntax regression test script to the github code

Please let me know what you think of this idea, especially @marianoapp and @erendrake

When I implemented the ELSE operator (issue #6), it was my first attempt to alter the syntax definition, and I was nervous about breaking something so I checked it afterward with the following kosscript designed to try to cover every possible permutation of IFs and ELSEs that I could think of, including trying to regression-test for things that shouldn't have changed about it:

//KOS
//  A script with the purpose of testing that 'if' and 'else' work right:

set a to 10.
set b to 20.
set c to 40.

print "IF,  one line body, true check:".
print "is " + a + " = 10?".
if a = 10
  print "  yes.".
print "IF,  one line body, false check:".
print "is " + b + " = 10?".
if b = 10
  print "  yes.".

print "IF,  two line body requiring braces:".
print "is " + a + " = 10?".
if a = 10 {
  print "  yes.".
  set doNothing to 1. // just to make a reason for the braces.
}.

print "if/else, one-liners, true check:".
print "is " + a + " = 10?".
if a = 10
  print "  yes".
else
  print "  no".

print "if/else, one-liners, false check:".
print "is " + b + " = 10?".
if b = 10
  print "  yes".
else
  print "  no".

print "if/else, multi-line bodies, true check:".
print "is " + a + " = 10?".
if a = 10 {
  print "  yes".
  set doNothing to 1. // just to make the body longer than 1 stmt.
} else {
  print "  no".
  set doNothing to 1. // just to make the body longer than 1 stmt.
}.

print "if/else, multi-line bodies, false check:".
print "is " + b + " = 10?".
if b = 10 {
  print "  yes".
  set doNothing to 1. // just to make the body longer than 1 stmt.
} else {
  print "  no".
  set doNothing to 1. // just to make the body longer than 1 stmt.
}.

print "nested if/else, one-liners, hits first term:".
print "what is " + a + " ?".
if a < 15
  print "  less than 15".
else if a < 20
  print "  in the range [15,20)".
else if a < 30
  print "  in the range [20,30}".
else 
  print "  >= 30".

print "nested if/else, one-liners, hits third term:".
print "what is " + b + " ?".
if b < 15
  print "  less than 15".
else if b < 20
  print "  in the range [15,20)".
else if b < 30
  print "  in the range [20,30}".
else 
  print "  >= 30".

print "nested if/else, one-liners, hits final else:".
print "what is " + c + " ?".
if c < 15
  print "  less than 15".
else if c < 20
  print "  in the range [15,20)".
else if c < 30
  print "  in the range [20,30}".
else 
  print "  >= 30".

print "nested if/else, mix of one-line and braces, hits middle term:".
print "what is " + b + " ?".
if b < 10
  print "  less than 10.".
else if b < 30 {
  print "  in the range [10,30}".
  set doNothing to 1. // pointless line to force need for braces.
} else {
  print "  >= 30".
  set doNothing to 1. // pointless line to force need for braces.
}.

It occurs to me that expanding a thing like that into a very complex long script full of WHENs, LOCKs, FORs, UNTILs, Program calls, and so on might be a good idea for trying to exercise a bit of everything in the language, so that after a change you could run the test and compare the results to the results of a previous run, and look at the diff between them to make darn sure that any change you see is a change you meant to see.
Furthermore, when a new bit of syntax is added, you could update the regression test script to add checks for your new thing. Then when you diff it, you expect those changes for your new syntax, but are also making sure nothing previously working became broken.

If people think this is a good idea I would be happy to try to work out a starting version of it. The idea would be that it would be added to the github repository and using it to check any language feature update would be a standard practice people should get in the habit of. It would be a thing you could do as part of a check to see whether or not to accept a pull request.

Here's a few design bullet-points about how I picture it working:

  • To make a test run, you'd put the script in your archive volume, put a tiny do-nothing craft on the launchpad with just a battery and an SCS part and a command core on it, and open the terminal and run it.
  • Unlike in my example above, the script would need to print everything out to a log file, NOT to the screen. (it would be using LOG commands). This is so you'd have a file of the output on your computer that you can look at with an external diff tool.
  • It would be necessary that it be run from the archive because it might blow past the 10,000 byte limit, and because that way the LOG command ends up giving you a disk file, rather than a bunch of lines in a section of your persistence file.
  • In order to test the calling of subprograms, it would actually be more than one program, not a single script. Therefore it may as well be split up into logically consistent topics, one per script, that all get called from a master script. i.e. "this is the program that tests loops" "this is the program that tests when and on triggers", and so on.
  • The test would be incapable of finding problems in the steering or controlling or ship data interactions. It's just for testing the language features only. This is because you can test all language features from a craft sitting on the ground of the launchpad without needing to put it in a specific situation, but once you want to test things like throttle control or reading fuel levels, then you'd have to actually fly the craft into different situations and that's too ugly to deal with in an automated test that's only supposed to take a few seconds to give you your answer.

react to custom keystrokes

It would nice to have the possibility to define keys oder keycombinations that when hit trigger some action in my script
For example: a program that implement some sort of autopilot that should accept commands.

Issue with locking steering and throttle when out of RT2 range

My program is copied to a local volume and then executed while still in range. It waits untill 60 seconds before ETA:APOAPSIS before turning off SAS and locking steering to prograde. Then 30 seconds before ETA:APOAPSIS it turns SAS on and locks throttle to 1. For some reason neither of the lock commands seem to work while out of range. SAS is toggled just fine and a visual aspect of the program continues to work.

(suggestion) perhaps an ability to view if not edit code.

I can understand if the EDIT command is a pain to re-implement but it was once the only good way to read files on the local drive. If you did a LOG "MESSAGE" TO FILENAME command on the local drive, it gets stored in the persistence file and its hard to have to read it there instead of in the terminal window.

Also, if you want to check "is this the program that took 2 parameters or 3 again?" You can't currently look at it from the terminal to see.

Perhaps a primitive equivalent to the unix/dos 'more' program should be implemented so people can see what's in the files from the terminal window. It would be a lot simpler to implement than a full editor. It would just show a screenful of text and wait for "enter' to show the next screenful of text, and so on.

(discuss) Debug drawing arrows for vectors: Is this a good general purpose thing?

I intend to have this feature that I can use for myself because debugging math problems is a pain when you can't see the XYZ coordinate directions and can't tell what your vectors are really doing. If I implement it for myself, do you think it would be useful to put into the general project?

Read this:

http://forum.kerbalspaceprogram.com/threads/76005-I-want-to-draw-holographic-lines-in-space-to-aid-in-debugging-vectors

What I'm picturing is allowing users to issue a commands like so:

SET myRedArrow to DRAWARROW( Mun:Position , 1000000 , 1, 0, 0 ).
// argument 1 is any vector of any kind. In this case the mun's position relative to the craft.
// the 1,0,0 is the RGB color to draw the arrow.
// the '1000000' is the drawing scale i.e. at 1 million, a vector with magnitude 5 million woud be drawn as a 5-meter long line in space)

UNSET myRedArrow. // causes the arrow to disappear from the screen.

This allows users to actually SEE what the vectors are, and get a much better visual handle on what they're doing. The purpose is for helping them (and me) debug scripts.

An alternate and perhaps simpler syntax for the same idea would be to add suffix properties to kOS's Vector class, so that any Vector can have its drawing properties tweaked like so:

set myVec to V(1000,201,401.1).
set myVec:drawRed to 1.0.
set myVec:drawGreen to 0.0.
set myVec:drawBlue to 0.0.
set myVec:drawScale to 50.
set myVec:drawShow to true. // make it appear.
set myVec:drawShow to false. // make it disappear. All vectors start with drawShow set to false by default.

Add boolean "not" and a "not equal" operator.

(This is a repeat of an issue that was just raised on the old KOS project just before erendrake and marionoapp merged their work into this project.)

1: Add a boolean unary negation operator, as in:

If not x = 2 { ... }.

or

if ! x = 2 { ... }.

2: Also the "not equal" operator seems to be missing from the otherwise complete list of comparators:
Implement either like this:

if x <> 2 {...}.

or like this

if x != 2 {...}.

Cannot edit programs in the in-game terminal.

I have the latest release, titled "Better new parser!", when I execute the following in the in-game console nothing happens.

switch to archive.
edit asdf.

When pressing enter on edit asdf. the prompt simply moves to the next line like it does with many other commands. There is no error message.

If I edit files directly using Notepad the programs are visible and can be run in-game.

Large Exponents Issue

I had some scripts that used variable holding large constants in 0.11 that now no longer work in the 0.12.P3 pre-release.

SET const_g to 6.674 *10 ^ (-1 * 11). //now returns 0
SET body_mass TO 5.2915793 * 10^22. //now returns a large negative number

I found out that I can do

SET const_g TO 6.674E-11.
SET body_mass TO 5.2915793E+22.

I do also know there is now CONSTANT():G and the body list to get both of these numbers but this might still be an issue that should be looked at.

VELOCITY:SURFACE readings have 'mixed' vectors

Issue:
When looking at the readings from VELOCITY:SURFACE:Z, they seem to be somehow mixed with VELOCITY:SURFACE:X. Upwards velocity seems to induce an 'Eastward' bias in the Z vector, with downwards velocities giving a 'Westward' bias.

Example Program:

declare lastClear.
declare vel.
clearscreen.
set lastClear to time.
lock vel to velocity:surface.

until 0 {
   print "   vSped:" + round( VERTICALSPEED, 2 ) at (0,8).
   print "     V:X:" + round( vel:X, 2) at (0,9).
   print "     V:Y:" + round( vel:Y, 2) at (0,10).
   print "     V:Z:" + round( vel:Z, 2) at (0,11).

   //Clear Screen Errors
   if time-lastClear > 3 { clearscreen. set lastClear to time. }.
}.

Simple test probe will demonstrate issue on vertical launch.

More Detailed Example:


declare tAlt.
declare p.
declare i.
declare d.
declare error.
declare integError.
set integError to 0.
declare corY.
declare corZ.
declare vSpd.
declare sSpd.
declare vertMix.
declare velMag.

set tAlt to 1000.
set p to 0.06.
set i to 0.001.
set d to 0.25.


lock error to (tAlt - ALTITUDE).
lock vSpd to VERTICALSPEED.
set sSpd to SURFACESPEED.


clearscreen.
declare lastClear.
set lastClear to time.
lock vel to velocity:surface.
lock velMag to velocity:surface:mag.
LOCK THROTTLE TO p*error + i*integError + d*vel:x.

set corY to vel:Y/1.
set corZ to vel:Z/-1.
lock steering to up + R(corY,corZ,0).
until 0 {
   print "  pError:" + round( p*error*100, 2 ) at (0,1).
   print "  iError:" + round( i*integerror*100, 2 ) at (0,2).
   print "  dError:" + round( d*vel:x*100, 2 ) at (0,3).
   print " TrueErr:" + (tAlt - ALTITUDE) at (0,5).
   print "Throttle:" + round( throttle*100, 2 ) at (0,7).
   print "     V:X:" + round( vel:X, 2) at (0,9).
   print "     V:Y:" + round( vel:Y, 2) at (0,10).
   print "     V:Z:" + round( vel:Z, 2) at (0,11).
   print "  cos(Y):" + cos( vel:Y ) at (0,13).
   print "VelMag:" + velMag at (0,16).
   print "VertMix:" + vertMix at (0,17).



   set integError to (integError + error).
   set sSpd to max( SURFACESPEED, 1).

   // Bound Check
   if integError*i > 1 { set integError to 1/i.}.
   if integError*i < -1 { set integError to -1/i.}.

   set vertMix to min( abs( vSpd ), 10 ) / sSpd .

   // Bounds check and set steering vectors
   set corY to vel:Y/1.
   set corY to min( max( corY, -90 ), 90 ).
   set corZ to vel:Z/-1.
   set corZ to min( max( corZ, -90 ), 90 ).

   //Clear Screen Errors
   if time-lastClear > 3 { clearscreen. set lastClear to time. }.
}.

This controller seems to work fine in the 0.23 patch of the game, but shows the error documented above with the 0.23.5 'patch'.

It is interesting to note that the controller WILL settled to a zero horizontal speed eventually. This happens after the up-down oscillations stop (The PID controller is tuned for a critically dampened response for a very specific craft, most others will 'bob' for a while, then settle). During the final up-down motions, the craft will steer heavily east and west as it attempts to counter velocity that doesn't exist...

Sanitize values sent to KSP

Sometimes sending a double with a value of NaN or Inifinity to KSP causes the game to crash showing a black screen.
To avoid this we should sanitize all the values sent to KSP and raise an exception if we found either of this ones.

Syntax not supported: lock var to heading A by B

This syntax worked in previous versions of kOS:

LOCK someVar TO HEADING expr1 By expr2.
LOCK STEERING to someVar.

The expression "heading expr1 by expr2" doesn't seem to be recognized as valid syntax in this new version. What it used to do was create a Euler rotation pointing at compass heading expr1 pitched up expr2 degrees above the horizon.

SHIP:SOLIDFUEL can't be used to detect zero fuel - it bombs with error when fuel is zero.

The value of SHIP:SOLIDFUEL doesn't return zero when there's no solid fuel. Instead it says "suffix SOLIDFUEL not found on object" and bombs out.

I was trying to modify my ascent script, which used to only work if all the engines are liquid fueled, to handle working when there may or may not be solid boosters attached, but it's currently a mess to try to write the script because of this problem. If I try to query for whether or not solid fuel exists on the ship outside the current stage, the script bombs out while attempting the query.

Note, it does seem to work for STAGE:SOLIDFUEL. That does return zero. But SHIP:SOLIDFUEL, which seems to be taking its value from the KSP resource , is finding no such resource when querying for the SOLIDFUEL resource and thus producing that error.

Note that if you have solid boosters that have just run out and you haven't detached them yet, then SHIP:SOLIDFUEL does return zero. But the moment you decouple them, then SHIP:SOLIDFUEL will bomb out if you try to query it. It seems that as long as a part is attached to the ship that is capable of holding a resource but has run out, then querying for that resource will return zero. (i.e. empty fuel tanks or spent batteries) But the moment the part is no longer attached, then querying for that resource will error out.

i'm not sure how to fix this cleanly, since the KSP API itself seems to treat "this type of resource is currently not part of THIS ship" identically to "this type of resource cannot be part of ANY ship because I've never heard of it." Therefore if you change it to return zero when the resource is not found, then all misspelled resources would return zero as well and that's not desirable.

Rant: This is part of the reason I think it's important to expose some means for the script programmer to perform a boolean check against NULL and NaN conditions, and allow the script writer the means to handle these sorts of conditions instead of making them crash the script. Because there's no exception try/catch in the language, and I agree that implementing it would make the language too complex for entry level people, these conditions end up being impossible to work around.

If ship:solidfuel returned null, and there was a means to check isnull(ship:solidfuel) then I could handle the problem in my own script. Similarly with math functions that return NaN like taking the arccos of a number larger than 1. it's impossible to ever check for this condition currently. When a math function returns NaN you can't ever check for that case in kOSscript and instead you just have a variable that will cause a crash when you try using it.

All integer values treated as "false" when used as booleans.

This used to work in the old pre-kRISC version of kosscript:

set flag to 1.
if flag { print "flag is true". }.

But now any integer value of any kind, when interpreted as a boolean value, returns false, as opposed to the normal boolean meaning of zero=false, nonzero=true.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.