KSP-KOS / KOS

Fully programmable autopilot mod for KSP. Originally By Nivekk
Other
691 stars 229 forks source link

Equality comparisons for ELEMENTS and :CREW are broken #3117

Open BobKermanIndustries opened 1 month ago

BobKermanIndustries commented 1 month ago

Elements is broken right now, for example, ship:elements = ship:elements returns False, same with ship:elements[0]:parts = ship:elements[0]:parts or core:element = core:element, and searches in lists of elements is impossible with ship:elements:find(ship:elements[0]) returning -1 and for elem in ship:elements{print ship:elements:indexof(elem).} returning -1. I do not know what is causing this. The same problem appears to be with the :crew suffix, ship:crew = ship:crew or ship:crew[0] = ship:crew[0] returning False, but ship:crew:name seems to be fine.

nuggreat commented 1 month ago

Nope that is things working as they should. Most data structures in kOS are not stored in vars by value and instead stored by reference and for most cases when you preform an equality check on references if they are not the same reference then you get false from the equality check. This is mostly because writing by value equality checks for all kOS structures is both an insane amount of work and because the vast majority of such checks will match exactly what you get from just checking reference equality. This is why comparing the :NAME of kerbals works as that is comparing strings which is something that while passed by reference does by value equality.

What you need to do is write your own by value equality check which compares something that you can get by value unique to the structure. For elements you would likely need to iterate the part list of both elements and check that the UID for all parts in one list is found on one part of the other list.

EDIT: something like this function for example should work through as difference instances of a given element list should be in the same order but I haven't checked that is actually the case.

FUNCTION are_elements_equal {
    PARAMETER elementA, elementB.
    LOCAL partsElementA TO elementA:PARTS.
    LOCAL partsElementB TO elementB:PARTS.
    LOCAL areEqual TO TRUE.
    IF partsElementA:LENGTH = partsElementB:LENGTH {
        FROM { LOCAL i IS partsElementA:LENGTH - 1. } UNTIL i < 0 STEP { SET i TO i - 1. } DO {
            IF partsElementA[i]:UID <> partsElementB[i]:UID {
                SET areEqual TO FALSE.
                BREAK.
            }
        }
    } ELSE {
        areEqual = FALSE.
    }
    RETURN areEqual.
}