Lonami / pyndustric

A Python compiler for Mindustry's logic processors assembly language
MIT License
49 stars 9 forks source link

Supporting radar functions? #28

Closed TelosTelos closed 3 years ago

TelosTelos commented 3 years ago

Mlog has two sorts of radar functions to return found units: uradar sees things in range of the currently bound unit, whereas radar instead (I think) sees things in range of a specified building. (Strangely both of these seem to include a buiding slot in the text version of mlog, even though the unit version's mindustry interface offers no way to alter this???)

I'd be inclined to syntactically implement these in Pyndustric as methods of Unit, and of various building objects, respectively, e.g. Unit.radar(....) and ripple1.radar(...)

Each of these accepts up to three criteria that must be jointly satisfied by any returned result. In python, it would be natural to use some form of default argument for optional criteria. In addition, these accept two other arguments, an order boolean which defaults to 1 (which I think would have been more natural to present as a reversed defaulting to 0 but it might be confusing for us to impose that), and a sorting criterion, which in Python would usually be called a "key". I would be tempted to make these keyword arguments as well (since they occur in mlog after optional arguments, and since key arguments in Python are often specified with key = ...). That would make us end up with something like the following:

foundunit = Unit.radar( criterion1, criterion2=any, criterion2=any, order=True, key=distance) foundunit = ripple1.radar( criterion1, criterion2=any, criterion2=any, order=True, key=distance)

Another tricky issue with these is how we want to have users pass the criteria and sorting key. If we take them as strings, then linters won't provide any auto-completion help to indicate which criteria could be used. If we take them as ordinary expressions (like flying and enemy), there will be potential collisions with other uses for those expressions (the current criteria are any enemy ally player attacker boss flying ground and the sorting keys are distance health maxHealth shield armor) which may confuse the linter and human coders, but wouldn't be ambiguous to the compiler. The main other option I see is to somehow make these attributes of some class/object, e.g. criterion.flying and criterion.enemy though I don't like how wordy that is.

A part of me is also inclined to phrase this closer to the way I'd actually write such a search in Python, e.g.

foundunit = min( (unit for unit in ripple1.visible_units if is_enemy(unit) and is_flying(unit)), key = distance )

However, that format wouldn't necessarily come naturally to Python novices (or even Python intermediates!), and it could easily invite coders to write more complicated logical tests that mlog can't actually support. So probably better not to go that route...

TelosTelos commented 3 years ago

I guess I'd also be tempted to allow order=min and order=max since that's much more intuitive than order = 0,1,True or False, as is evidenced by the fact that even now I can't remember which of these means min/closest!

TelosTelos commented 3 years ago

I went ahead and implemented this in my version. It accepts commands like the following:

        u1 = Unit.radar( enemy, flying, order = max, key = distance)
        u2 = ripple1.radar( ally, key = health )
Lonami commented 3 years ago

Nice, if you make a commit and push your changes with just that I'll likely be able to cherry-pick it later today. I really would appreciate if your commits are as small as possible, it helps me out.

Not sure if you've noticed but I've been updating this repository with your code and added a CONTRIBUTING.md guide too.

TelosTelos commented 3 years ago

This is fairly entangled with my mostly-completed complex-expression handler, so it may be a bit hard to cherry pick if you decide you just want radar without complex expression handling. I think I'll get that cleaned up a bit more, and likely fully working, before committing, probly couple hours, depending on family interference.

Lonami commented 3 years ago

I've already pulled the changes regarding better conditionals and instructions as well as the initial separation for expressions, but I'm not sure how much more you've done offline. I'll be waiting then.

TelosTelos commented 3 years ago

Ok this is all pushed to my fork now. I imagine it's frustrating for you to keep recalibrating two sets of files, with my stubborn self not making things very easy for you - sorry!

On the bright side though, I think we're now through one of the thickest snarls I was planning to work on, with vectorized operations being the main other snarl that will involve a bunch of interrelated stuff tangled together. Otherwise, I'd mostly just like to get unit control working, and to object-orient building control to match, but those should be much more self contained. After that I think Pyndustric will be in pretty good shape to be usable as a (much more user-friendly!) full replacement for the in-game editor. So at that point, I may go back to see how much I can break the game with AI-controlled units. (Plus my vacation's gonna end in not that long anyway, alas...)

Lonami commented 3 years ago

I think this is implemented by https://github.com/Lonami/pyndustric/commit/f12e33534b35550fb4137b074a2e0dfafdb70a52 and https://github.com/Lonami/pyndustric/commit/873d5af1e3d16e6b66a44bdc4d96a82a7a42faf5.