TeamDman / SuperFactoryManager

Mozilla Public License 2.0
44 stars 18 forks source link

FeatureRequest: Functions #146

Open RotzRohr opened 1 month ago

RotzRohr commented 1 month ago

Why do we need functions? Bc that would help players make the code more readable

Here is how i would implement functions

For normal players Functions can only be called in a main function

So it would look like this

name "SimpleFunction"
EVERY 20 TICKS DO
    RUN FUNCTION A
END

FUNCTION A
    -- do something
END

So calling a Function in a function would not be possible

Why? Bc otherwise players could create loops which crash the server

Lets say a player knows what he does Then he can create Advanced Functions which can be called in loops how often the player wants Maybe also make a gamerule to disallow that (For servers)

This would look like this

name "AdvancedFunction"
EVERY 20 TICKS DO
    RUN FUNCTION A
END

AFUNCTION A
    -- do something
    RUN FUNCTION B
END

AFUNCTION B
    -- do something
END

Obviously whis would also allow this

name "MixedFunction"
EVERY 20 TICKS DO
    RUN FUNCTION A
END

FUNCTION A
    -- do something
    RUN FUNCTION B
END

AFUNCTION B
    -- do something
END
Burkino commented 1 month ago

But what would the actual use of functions be? SFM doesn't have variables or return values, pretty sure it can't do math so there's no (good) way to limit recursion.

TeamDman commented 1 month ago

I could limit recursion without giving the language math capabilities, but yeah I'm not sure what the use case is

RotzRohr commented 1 month ago

The use case: given this code

name "Worker"
EVERY 100 TICKS DO

    FORGET
    INPUT FROM ItemInput_SaltDust
    OUTPUT TO EACH Electrolyzer_Chlorine TOP SIDE

    FORGET
    INPUT FROM Electrolyzer_Chlorine BOTTOM SIDE
    OUTPUT TO EACH ItemBuffer_SD

    FORGET
    INPUT fluid:: FROM Electrolyzer_Chlorine BOTTOM SIDE
    OUTPUT fluid:: TO EACH FluidBuffer_Chlorine

    FORGET
    INPUT FROM ItemInput_NickelOre
    OUTPUT TO EACH MaceleratorFrom_NickelOre_To_RawNickel TOP SIDE

    FORGET
    INPUT FROM MaceleratorFrom_NickelOre_To_RawNickel BOTTOM SIDE
    OUTPUT TO ItemBuffer_RawNickel

    FORGET
    INPUT FROM ItemBuffer_RawNickel
    OUTPUT TO MaceleratorFrom_RawNickel_To_NickelDust TOP SIDE

    FORGET
    INPUT FROM MaceleratorFrom_RawNickel_To_NickelDust BOTTOM SIDE
    OUTPUT TO ItemBuffer_NickelDust

    FORGET
    INPUT FROM ItemInput_RawIron
    OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE

    FORGET
    INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
    OUTPUT iron_dust TO ItemBuffer_IronDust
    OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust

    FORGET
    INPUT FROM ItemBuffer_ManganeseCrushedDust
    OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE

    FORGET
    INPUT fluid:: FROM FluidBuffer_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE

    FORGET
    INPUT fluid:: FROM FluidInput_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE

    FORGET
    INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_MSS

    FORGET
    INPUT fluid:: FROM FluidBuffer_MSS
    OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE

    FORGET
    INPUT FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT TO ItemBuffer_MTD

    FORGET
    INPUT fluid:: FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_SulfuricAcid

    FORGET
    INPUT FROM ItemBuffer_MTD
    OUTPUT To Packager_MD TOP SIDE

    FORGET
    INPUT FROM ItemBuffer_CTD
    OUTPUT To Packager_CD TOP SIDE

    FORGET
    INPUT FROM Packager_MD BOTTOM SIDE
    OUTPUT TO ItemBuffer_MD
    FORGET
    INPUT FROM Packager_CD BOTTOM SIDE
    OUTPUT TO ItemBuffer_CD

    FORGET
    INPUT FROM ItemBuffer_CCD
    OUTPUT TO ChemicalReactor_CHS
    FORGET
    INPUT fluid:: FROM FluidBuffer_HA
    OUTPUT fluid:: TO ChemicalReactor_CHS

    FORGET
    INPUT fluid:: FROM ChemicalReactor_CHS BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_CHS

    FORGET
    INPUT fluid:: FROM FluidBuffer_CHS BOTTOM SIDE
    OUTPUT fluid:: TO Electrolyzer_CTD TOP SIDE

    FORGET
    INPUT FROM Electrolyzer_CTD BOTTOM SIDE
    OUTPUT TO ItemBuffer_CTD

    FORGET
    INPUT fluid:: FROM Electrolyzer_CTD
    OUTPUT fluid::hydrogen TO FluidBuffer_Hydrogen
    OUTPUT fluid::chlorine TO FluidBuffer_Chlorine

    FORGET
    INPUT FROM ItemInput_Redstone
    OUTPUT TO EACH Centrifuge_RD TOP SIDE

    FORGET
    INPUT FROM Centrifuge_RD BOTTOM SIDE
    OUTPUT ruby_dust TO ItemBuffer_RD
    OUTPUT iron_dust TO ItemBuffer_IronDust
    OUTPUT quartz_dust TO ItemBuffer_QD
    OUTPUT neodymium_tiny_dust TO ItemBuffer_NTD

    FORGET
    INPUT FROM ItemBuffer_RD
    OUTPUT TO EACH Centrifuge_CCD TOP SIDE

    FORGET
    INPUT FROM Centrifuge_CCD BOTTOM SIDE
    OUTPUT chromium_crushed_dust TO ItemBuffer_CCD
    OUTPUT aluminum_dust TO ItemBuffer_AD

    FORGET
    INPUT fluid:: FROM FluidBuffer_Hydrogen
    OUTPUT fluid:: TO ChemicalReactor_HA
    FORGET
    INPUT fluid:: FROM FluidInput_Hydrogen
    OUTPUT fluid:: TO ChemicalReactor_HA

    FORGET
    INPUT fluid:: FROM FluidBuffer_Chlorine
    OUTPUT fluid:: TO ChemicalReactor_HA

    FORGET
    INPUT fluid:: FROM ChemicalReactor_HA
    OUTPUT fluid:: TO FluidBuffer_HA

END

EVERY 400 TICKS DO

    INPUT FROM ItemBuffer_NickelDust
    OUTPUT TO MixerMain TOP SIDE

    FORGET
    INPUT FROM ItemBuffer_IronDust
    OUTPUT TO MixerMain TOP SIDE

    FORGET
    INPUT FROM ItemBuffer_MD
    OUTPUT TO MixerMain TOP SIDE

    FORGET
    INPUT FROM ItemBuffer_CD
    OUTPUT TO MixerMain TOP SIDE

END

EVERY 100 TICKS DO
    INPUT FROM MixerMain BOTTOM SIDE
    OUTPUT TO ItemOutput_SSD
END

EVERY 10 TICKS DO
    INPUT forge_energy:: FROM Energy SOUTH SIDE
    OUTPUT forge_energy:: TO EACH NeedsEnergy TOP SIDE
END

As we can see it has no structure at all

Even if i would have them orderd like the functions this code would not look much better

This is how the improved version would look like (I used ChatGPT bc i even cant get through that even more (so expect parts to be wrong or from an alternate universe))

name "Worker"
EVERY 100 TICKS DO
    RUN ProcessSalt
    RUN ProcessChlorine
    RUN ProcessNickelOre
    RUN ProcessRawIron
    RUN ProcessChemicals
END
EVERY 400 TICKS DO
    RUN ProcessMixerOutput
END

EVERY 100 TICKS DO
    INPUT FROM MixerMain BOTTOM SIDE
    OUTPUT TO ItemOutput_SSD
END

EVERY 10 TICKS DO
    INPUT forge_energy:: FROM Energy SOUTH SIDE
    OUTPUT forge_energy:: TO EACH NeedsEnergy TOP SIDE
END

FUNCTION ProcessMixerInputs
    FORGET
    INPUT FROM ItemBuffer_NickelDust
    OUTPUT TO MixerMain TOP SIDE
    FORGET
    INPUT FROM ItemBuffer_IronDust
    OUTPUT TO MixerMain TOP SIDE
    FORGET
    INPUT FROM ItemBuffer_MD
    OUTPUT TO MixerMain TOP SIDE
    FORGET
    INPUT FROM ItemBuffer_CD
    OUTPUT TO MixerMain TOP SIDE
END

FUNCTION ProcessSalt
    FORGET
    INPUT FROM ItemInput_SaltDust
    OUTPUT TO EACH Electrolyzer_Chlorine TOP SIDE
END

FUNCTION ProcessChlorine
    FORGET
    INPUT FROM Electrolyzer_Chlorine BOTTOM SIDE
    OUTPUT TO EACH ItemBuffer_SD
    FORGET
    INPUT fluid:: FROM Electrolyzer_Chlorine BOTTOM SIDE
    OUTPUT fluid:: TO EACH FluidBuffer_Chlorine
END

FUNCTION ProcessNickelOre
    FORGET
    INPUT FROM ItemInput_NickelOre
    OUTPUT TO EACH MaceleratorFrom_NickelOre_To_RawNickel TOP SIDE
    FORGET
    INPUT FROM MaceleratorFrom_NickelOre_To_RawNickel BOTTOM SIDE
    OUTPUT TO ItemBuffer_RawNickel
    FORGET
    INPUT FROM ItemBuffer_RawNickel
    OUTPUT TO MaceleratorFrom_RawNickel_To_NickelDust TOP SIDE
    FORGET
    INPUT FROM MaceleratorFrom_RawNickel_To_NickelDust BOTTOM SIDE
    OUTPUT TO ItemBuffer_NickelDust
END

FUNCTION ProcessRawIron
    FORGET
    INPUT FROM ItemInput_RawIron
    OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE
    FORGET
    INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
    OUTPUT iron_dust TO ItemBuffer_IronDust
    OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust
END

FUNCTION ProcessChemicals
    FORGET
    INPUT FROM ItemBuffer_ManganeseCrushedDust
    OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM FluidBuffer_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM FluidInput_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_MSS
    FORGET
    INPUT fluid:: FROM FluidBuffer_MSS
    OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE
    FORGET
    INPUT FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT TO ItemBuffer_MTD
    FORGET
    INPUT fluid:: FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_SulfuricAcid
END
END
TeamDman commented 1 month ago

I don't see how this is different from using code comments tho

-- Process chemicals
EVERY 20 TICKS DO
    INPUT FROM ItemBuffer_ManganeseCrushedDust
    OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM FluidBuffer_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM FluidInput_SulfuricAcid
    OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
    FORGET
    INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_MSS
    FORGET
    INPUT fluid:: FROM FluidBuffer_MSS
    OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE
    FORGET
    INPUT FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT TO ItemBuffer_MTD
    FORGET
    INPUT fluid:: FROM Electrolyzer_MTD  BOTTOM SIDE
    OUTPUT fluid:: TO FluidBuffer_SulfuricAcid
END

-- process raw iron
EVERY 20 TICKS DO
    INPUT FROM ItemInput_RawIron
    OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE
    FORGET
    INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
    OUTPUT iron_dust TO ItemBuffer_IronDust
    OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust
END
RotzRohr commented 1 month ago

Sure comments can also do the Job

But i think functions would do the job much better (or a combo of both) (my opinion)

And when functions would be implemented you could also directly also implement return types (int boolean and void)

Which would def step up the sfm game

And now you might say but there is no way to store informations like int`s You could just count items in a chest and use the container as a int

Example

name "Worker"
EVERY 100 TICKS DO
    RUN FUNCTION DoSomething
END

AFUNCTION VOID IncreaseIntA
    -- code
END

AFUNCTION VOID DecreaseIntA
    -- code
END

AFUNCTION VOID EmptyIntA
    -- code
END

AFUNCTION INT GetIntA
    -- code
END

AFUNCTION VOID DoSomething
    IF RUN FUNCTION GetIntA >= 10 THEN
        RUN FUNCTION EmptyIntA
    END
    ELSE
        RUN FUNCTION DoSomething
    END
END
Burkino commented 1 month ago

You can use the ChatGPT'd output and replace the functions with EVERY 100 TICKS DO and get pretty much the same result.

Zachary-collins7 commented 1 month ago

An advantage I see is that it would give each program a sort of "main" or "entry" function. Reading the first loop with the function example I could generally see what the program is supposed to do - as opposed to finding a comment at the start of every loop. I think this feature would be especially nice if there was a quick way to scroll to the function declaration line.

name "Worker"
EVERY 100 TICKS DO
    RUN ProcessSalt
    RUN ProcessChlorine
    RUN ProcessNickelOre
    RUN ProcessRawIron
    RUN ProcessChemicals
END
TeamDman commented 1 month ago

perhaps code folding would meet the need until variables and functions are introduced

something like

EVERY TICK DO ▶ -- move energy 
EVERY 20 TICKS DO ▶ -- process salt
EVERY 40 TICKS DO ▶ -- move nickel
RotzRohr commented 1 month ago

When you want to do before you do the function it would be need to also have this

REGION START "Desc"
    -- code
REGION END

and then you can also fold these.

Obv it should also then allow this

REGION START "Desc1"
    REGION START "Desc2"
        -- code
    REGION END
REGION END

(When the functions are implemented they should also be foldable)

Burkino commented 1 month ago

It would be easier to implicitly fold on IF/ELSE/END and DO/END. Or it could be comment style with --#region to explicitly fold.

RotzRohr commented 1 month ago

It would be easier to implicitly fold on IF/ELSE/END and DO/END. Or it could be comment style with --#region to explicitly fold.

Yes it should also automatically fold on IF/ELSE/END and DO/END But in addtion

REGION START "Desc"
    -- code
REGION END

this would be pretty nice

Burkino commented 1 month ago

Comment style for explicit marking would be better since it doesn't actually matter to the program. It's something only for the editor.

RotzRohr commented 1 month ago

Comment style for explicit marking would be better since it doesn't actually matter to the program. It's something only for the editor.

But the avarage player learned that he has a start and a END so either it would be

REGION START "Desc"
    -- code
REGION END

or

--#region-start"Desc"
    -- code
--#region-end

if the comment is not including start and end this would not be possible

REGION START "Desc1"
    REGION START "Desc2"
        -- code
    REGION END
REGION END
TeamDman commented 1 month ago

Could just let people use

Every 20 ticks do
Do -- thing1
Input from chest
Output to chest2
Forget
End
Do -- thing2
Input fluid:: from tank1
Output fluid:: to tank2
End
End
RotzRohr commented 1 month ago

Could just let people use

Every 20 ticks do
Do -- thing1
Input from chest
Output to chest2
Forget
End
Do -- thing2
Input fluid:: from tank1
Output fluid:: to tank2
End
End

Still does not allow for reuse of code but its a start with code folding i could actually see this being usefull

Alternativly you could do it like this

name "Worker"
Every 20 ticks do
    RUN moveitems
    RUN movefluids
End

Do "moveitems"
    Input from chest
    Output to chest2
End

Do "movefluids"
    Input fluid:: from tank1
    Output fluid:: to tank2
End