Ludeme / LudiiExampleAI

Project with examples for the implementation of third-party AI algorithms / agents for the Ludii general game system.
MIT License
26 stars 15 forks source link

New playout function #3

Open n-ai-up8-edu opened 4 years ago

n-ai-up8-edu commented 4 years ago

Hi,

ExampleUCT.java of LudiiExampleAI/src/mcts/ shows us how to call a build-in method to make a playout.

Is it possible to override the playout method of the Game class to define a new playout function ? Is Ludii an open source project ?

DennisSoemers commented 4 years ago

No, it's not possible to directly override that method. Of course, if you're implementing an AI, you could just implement your own version of a playout method (outside of the Game class), and call that one. However, I'd only recommend doing so if you really need to -- for instance if you want playout policies that do not select moves uniformly at random.

Such a method would require different implementations for different cases though -- in particular, alternating-move vs. simultaneous-move games require quite different implementations. The simplest case for an alternating-move game would look something like this:

public Trial playout(final Context context)
{
    final Game game = context.game();
    final Trial trial = context.trial();

    while (!trial.over())
    {
        final int mover = context.state().mover();
        final Moves legal = game.moves(context);

    if (legal.moves().size() == 0)
    {
        // No legal moves: automatic pass
        game.apply(context, Game.createPassMove(context));
        continue;
    }

        final int r = random.nextInt(legal.moves().size());
        final Move move = legal.moves().get(r);
        game.apply(context, move);
    }

    return trial;
}

Where presumably you'd want to make changes to get non-random (or at least non-uniformly random) behaviour.

If you do in fact want uniformly random move selection during your playouts, I'd recommend just using the Game.playout() implementation that we provide. That implementation already handles different cases for you (like alternating-move vs. simultaneous-move). Additionally, our Game compiler is able to detect some common cases where playouts with uniformly-random action selection can be implemented in significantly more efficient ways than the "standard" implementation shown above, and our Game.playout() implementation will be able to make use of these optimisations.

n-ai-up8-edu commented 4 years ago

Thx for this basic playout that corresponds to my question. But the compiler is not able to find the Moves class. ... error: cannot find symbol final Moves legal = game.moves(context); ...

Is there a doc of all existing classes (with their attributes and methods) of Ludii.jar ?

DennisSoemers commented 4 years ago

The import should look like this:

import game.rules.play.moves.Moves;

Doesn't your IDE automatically find that though? There should probably be only one class with that name, so it should be able to infer which one you want and import automatically?

I don't have full javadoc for the 0.9.3 public release available (our development version has already changed quite a bit since then). Hopefully we will also make javadoc available from the next version onwards though.

n-ai-up8-edu commented 4 years ago

IDE ? using emacs... :-)

Ok, I saw it with the following command : jar tvf Ludii.jar | grep "Moves.class" But did not want to program by trial and error on declaring one class or another.

New error about the variable move that is not declared.

error: cannot find symbol move = legal.moves().get(r); ^

The javadoc is a real need. Even a previous version of public release would be very helpful.

DennisSoemers commented 4 years ago

Oh oops yeah of course that was a mistake in my example code, just edited to fix that line. The type to import there would be import util.Move;

n-ai-up8-edu commented 4 years ago

No no, import was ever done. Ok that it : move is a Move instance --> final Move move = legal.moves().get(r);

One last : random is ThreadLocalRandom.current() --> final int r = ThreadLocalRandom.current().nextInt(legal.moves().size());

And the UCT player with its own playout works :-) Thx again.