godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.22k stars 21.04k forks source link

Itertools like class in gdscript - to aid procedural generation #9264

Closed blurymind closed 6 years ago

blurymind commented 7 years ago

Basically I stumbled on an issue that requires me to return an array that holds all possible combinations of a sequence. I filed it as a question here: https://godotengine.org/qa/15813/function-that-returns-all-possible-combinations-sequence

Class1 = [1,2,3,4] Class2 = [1,2,3,4] Class3 = [1,2,3,4]

Now what I would like to do is return all possible combinations of these three classes.

Example:

1 1 1 2 1 1 3 1 1 4 1 1 1 2 1 2 2 1 3 2 1 4 2 1 ...

That functionality is available in python - as a module called itertools. Trying to write a function that does what I want in gdscript is proving to be dificult without the product itertools module.

Doing that in python would be as simple as:

import itertools
iterables = [ [1,2,3,4], [88,99], ['a','b'] ]

for t in itertools.product(*iterables):
     print t

That module would be incredibly useful when you want to automatically generate enemies with different types of armor for example - as it can create an array with all possible combinations of boots + helmets + chest for example

In my case, I am very close to writing a tool for godot that can aid artists and my tool needs that functionality. But I can see this being useful for games too

blurymind commented 7 years ago

Looking at itertools, this is how the product function there looks like: https://docs.python.org/3/library/itertools.html#itertools.product

def product(*args, repeat=1):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)
blurymind commented 7 years ago

For the record, I came up with a solution to this in godot, but it is kind of ugly. It generates a custom script with nested for loops and runs it.

Another users suggested a better solution, but it is still quite a long function. Here is what we have so far: https://godotengine.org/qa/15813/function-that-returns-all-possible-combinations-sequence

In any case, it would be awesome if somebody implements this in c++ as a built in function in godot. :)

I hope that these code snipets help

hubbyist commented 7 years ago

Another solution:

extends SceneTree

func _init():
    var a = ['a1','a2','a3']
    var b = ['b1','b2']
    var c = ['c1','c2','c3']
    var d = ['d1','d2','d3']
    var arrays = [a,b,c,d]
    print(arrays)
    for combination in array_combinations(arrays):
        print(combination)
    quit()

func array_combinations(arrays):
    var combinations = []
    var first = arrays.front()
    arrays.pop_front()
    for item in first:
        combinations.push_back([item])
    for array in arrays:
        var sequences = [];
        for item in array:
            for combination in combinations:
                var sequence = combination + [item]
                sequences.push_back(sequence)
        combinations = sequences;
    return combinations
blurymind commented 7 years ago

Woudnt it be great to have a built in function- to help with procedural generation :D

Thank you for sharing these great examples btw. I came up with a solution last week, but ended up with using one of the suggested ones instead of mine, because the code was slightly cleaner

On 28 Jun 2017 10:08, "hubbyist" notifications@github.com wrote:

Another option:

extends SceneTree

func _init(): var a = ['a1','a2','a3'] var b = ['b1','b2'] var c = ['c1','c2','c3'] var d = ['d1','d2','d3'] var arrays = [a,b,c,d] print(arrays) for combination in array_combinations(arrays): print(combination) quit()

func array_combinations(arrays): var combinations = [] var first = arrays.front() arrays.pop_front() for item in first: combinations.push_back([item]) for array in arrays: var products = []; for item in array: for combination in combinations: var product = combination + [item] products.push_back(product) combinations = products; return combinations

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot/issues/9264#issuecomment-311601979, or mute the thread https://github.com/notifications/unsubscribe-auth/AGMbVa7MNTfQoic8FAZwuuv6mYbZVPC3ks5sIhf0gaJpZM4N9-rX .

kubecz3k commented 6 years ago

First of all thank you for your report and sorry for the delay.

We released Godot 3.0 in January 2018 after 18 months of work, fixing many old issues either directly, or by obsoleting/replacing the features they were referring to.

We still have hundreds of issues whose relevance/reproducibility needs to be checked against the current stable version, and that's where you can help us. Could you check if the issue that you described initially is still relevant/reproducible in Godot 3.0 or any newer version, and comment about its current status here?

For bug reports, please also make sure that the issue contains detailed steps to reproduce the bug and, if possible, a zipped project that can be used to reproduce it right away. This greatly speeds up debugging and bugfixing tasks for our contributors.

Our Bugsquad will review this issue more in-depth in 15 days, and potentially close it if its relevance could not be confirmed.

Thanks in advance.

Note: This message is being copy-pasted to many "stale" issues (90+ days without activity). It might happen that it is not meaningful for this specific issue or appears oblivious of the issue's context, if so please comment to notify the Bugsquad about it.

akien-mga commented 6 years ago

Our Bugsquad will review this issue more in-depth in 15 days, and potentially close it if its relevance could not be confirmed.

As there was no update since the previous post, we close this issue.

If it is still relevant in the way it was described and discussed above, please comment to ask for it to be reevaluated. If it is only partly relevant, or if the original issue has changed, it would be better to open a new issue (potentially referring to this one) focused on the current state.

Zireael07 commented 6 years ago

I believe this is still relevant, reopen?

akien-mga commented 6 years ago

This proposal was discussed a lot a few months ago, as it had slipped into our ideas list for the Google Summer of Code.

After much discussion, we could not really see a lot of use cases that would warrant integrating it directly in GDScript, so we removed it from our ideas list. We try to keep GDScript as simple as possible, which means cutting on "sometimes useful" features to focus on what is really needed.

Since this can't satisfy everyone of course, the best approach would be to implement such features as a GDScript or GDNative plugin, and usage will speak for itself. If many users use such plugin extensively in their games, then it might be considered to be included in the core for convenience.

frojo commented 5 years ago

Is it possible that a class with custom iterators would work for this usecase?

(I know this issue is closed, this is mostly for people in the future looking for iterator-related solutions)

tanjunior commented 4 years ago

Is it possible that a class with custom iterators would work for this usecase?

(I know this issue is closed, this is mostly for people in the future looking for iterator-related solutions)

curious about this too, anyway to use custom iterators to do number permutations

Davo00 commented 1 year ago

This proposal was discussed a lot a few months ago, as it had slipped into our ideas list for the Google Summer of Code.

After much discussion, we could not really see a lot of use cases that would warrant integrating it directly in GDScript, so we removed it from our ideas list. We try to keep GDScript as simple as possible, which means cutting on "sometimes useful" features to focus on what is really needed.

Since this can't satisfy everyone of course, the best approach would be to implement such features as a GDScript or GDNative plugin, and usage will speak for itself. If many users use such plugin extensively in their games, then it might be considered to be included in the core for convenience.

Or I'll just use a decent programming language with a broad range of libraries ;)

akien-mga commented 1 year ago

Please don't comment on old issues if you don't have anything constructive to add.