simon816 / Command-Block-Assembly

Compile high-level code into Minecraft commands
https://www.simon816.com/minecraft/assembler
MIT License
272 stars 29 forks source link

Customs entities scoreboard id : #4

Closed Loumardes closed 5 years ago

Loumardes commented 5 years ago

Allow to target entities with scoreboard id equal to a changing scoreboard value at in game tics

Why : It is a basic contraption useful for more complex ones For example I use it for modular moving platforms through selecting them by _idobjective and running on them relative clone and tp It can have many other purposes We could add new instructions rather than the function example

Hi everyone maybe I should introduce myself a litle bit ? so I am a minecraft player experienced in commands I used to write functions files for some complex contraptions for last 2 years Hand writing is time-consuming, that is why I am interested in your assembly and I have a lot to learn I have some ideas and I could help to improve it, even if my Github account is not updated

In minecraft commands : Running a function on selected entities id looks like this :

_scoreboard players operation @s computed_objective = @s id_objectivename
scoreboard players operation @s computed_objective -= @a[tag=memory_entity] id_cible
execute as @s[scores={computed_objective=0..0}] at @s run function functionpath__

maybe it is already possible to do that with assembly instructions ? I do not know them enough I also do not understand why "It is not possible to dynamically reference scoreboard objectives"

chorman0773 commented 5 years ago

"It is not possible to dynamically reference scoreboard objectives", means that it is impossible as minecraft is now, to dynamically compute the scoreboard objective name (dynamically meaning at runtime). the scores argument of the target selector should be {computed_object=0}, it means the same thing, but is more concise. There is not presently an easy way to do the above, due to the presence of the @a. Otherwise, you could just use a global with the name you want, and use a local variable, and test the local variable.

@simon816 could add a few compiler intrinsics, then it would look something like this (assuming the intrinsics work the way I figure in my head:

int sum = <global>;
for(EntitySelectorIterator es = __selector_iterate("@a[tag=\"memory_entity\"]");es!=__selector_end();es=__selector_next(es))
sum -= __scoreboard_objective(__selector_get(es),"id_cible");
if(sum==0)
<function>;
chorman0773 commented 5 years ago

As for the original point, I assume you mean the ability to get the value of a scoreboard objective from any entity. I would implement __scoreboard_objective as taking either a string literal, or the result of __selector_get which is the entity that it applies to, and a string literal that names the objective, and it returns an lvalue of type int (an lvalue so that you can assign it, as well as read it), but you cannot take its address or bind it to a reference (If and when C++ support exists). The lvalue names the score with that objective for the given entity. Basically, with this extension, you would simply use __scoreboard_objective to read the value of an entities score in any objective (provided the entity and the objective are known at compile time), and you could also assign the result to write that value to the objective.

Loumardes commented 5 years ago

Thanks you for your fast answer

It show that I don't know much about C and your assembly For instance i just learn python and I am mainly good in the design part of programmation

if I well understand : selector_get() take a selector as argument and output an entity id dest and address are entity id

I dont understand what does the selector instructions

also I dont see the point to use intvalues for address since you can add tags to entity you want to keep in memory to run subroutines/functions on it

I read the README but it is not enough for me Is there special instructions running in functions json file or mcmeta ? Is there a place to learn how works your assembly and how to use it ?

chorman0773 commented 5 years ago

I'm not the developer of this project, but I have done some work for it, and also have provided a few suggestions. The way that the proposed intrinsics would work in theory is: __selector_iterate takes a string literal which represents a target selector, and returns an iterator over it. __selector_next advances a target selector iterator. __selector_get takes either a string that represents a target selector or a iterator over it. It would just be easier to use the commands directly, though you would need to figure out variable names (and probably put some volatile in there). The README is probably the best for the Assembly as it stands. I also recommend that @simon816 includes some more comprehensive documentation on the Assembly and the C implementation. Presently neither the Assembly nor the C implementation actually explicitly supports what your trying to do, my code would hopefully be vectorized down to the commands you had. (C++ would make it look nicer).

simon816 commented 5 years ago

Regarding selectors, I added several selector opcodes (see the EXEC* series in the readme) @chorman0773 is right that I need to create more documentation since it is not clear how some of the C compiler features can be used. I utilize selectors in this more advance example: https://github.com/simon816/Command-Block-Assembly/blob/master/examples/carpet_on_stairs.c

I have created several intrinsic selector functions, they can be seen here: https://github.com/simon816/Command-Block-Assembly/blob/609c23baf190d077f45791690dde30a50ace0fb1/compiler/compiler.py#L934-L945

@chorman0773 is over-complicating the way in which selectors can be used. It is not possible to have C++ style iteration because there is no data structure for selector results.

If you look through the carpet_on_stairs.c example, you'll see select_entities and select_players. These correspond to @e and @a. Within the body of the select statement, the current entity is @s. I created a special "type" called entity_local, seen here it's value is local to each entity - and only makes sense to query its value when in an @s context. entity_local acts just like a mapping of entity -> intval.

With these intrinsics, it should be possible to perform an equivalent calculation. Something like this (untested):

int computed_objective = ...;
entity_local id_cible;
select_players(sel_match(tag, memory_entity)) {
    computed_objective -= id_cible;
}
if (!computed_objective) {
    ...
}

Of course this is possible with the assembly language directly but most the time I'm working on the C compiler as it's easier to represent the program that way.

Loumardes commented 5 years ago

Thanks you I deeper understand the assembly language

But your example do not seem to do the same thing than mine

if I well understand : You run the if statement if the player with _memoryentity tag have _computedobjective same than _idcible. But it works with a single player

My fault if there is a misunderstanding : I wanted to run function (your if instructions) as all entity wich have _idobjectivename same than _idcible

My commands are executed in a function file as _@e[tag=potentialtarget]. So there is always a couple of entities with the right _scoreboardid to run as themselves the new function. _computedobjective is just for storing _id_objectivename -= idcible value without changing _idobjectivename. So it works for multiples entity

Thanks to you 2 I am close to do it with assembly language

simon816 commented 5 years ago

OK if I understand what you're doing, you want to execute a function for each entity that matches some condition.

The select_players/select_entities will do that; it runs the body for each matching entity.

For example:

select_players(sel_match(tag, memory_entity)) {
    some_function();
}

will run some_function for each player that has the tag memory_entity Roughly equal to execute as @a[tag=memory_entity] run some_function you can also do:

select_entities(sel_variable(some_var == 0)) { ... }

To run a function for every entity that has the some_var value of 0.

Loumardes commented 5 years ago

Yes, but I want _somevar == condition to check a dynamic scoreboard value, for example _changingvar, instead of a fixed value When you have _some_var == changingvar you also have _some_var -= changingvar == 0

So you achieve this with : _computedobjective taking value of : _some_var -= changingvar Tracking if _computedobjective == 0

To conclude, it is possible to do that in Minecraft, and it prevent the use of giant lookup tables. _computedobjective is only needed to perform the check And maybe the assembly provides the tools to avoid _computedobjective

Loumardes commented 5 years ago

much easier with 1.13 syntax outdated