NAME

Game::Fanorona::Bot - a player for fanorona, at a strength you choose

VERSION

Version 0.03

SYNOPSIS

use Game::Fanorona;
use Game::Fanorona::Bot;

my $game = Game::Fanorona->new;
until ($game->over) {
    Game::Fanorona::Bot->play($game, level => 10_000, seed => 'a seed');
}
print $game->result->how, "\n";

DESCRIPTION

A player. It has no state: every method is a class method that is handed the game.

A level is a number of positions

A level is how many positions the player may look at before it moves. It is a count and not a time, so a level plays the same on a fast machine as on a slow one, and the same position, level and seed always give the same move.

Level 0 does not look ahead at all. It makes the capture that takes most, goes on taking while it can, and otherwise moves a stone at random.

levels lists the levels this distribution has measured against each other. Any other number is a level too.

What it is and is not good at

It counts stones, likes its stones to have room to move and to stand towards the middle of the board, and looks ahead. Where there is a capture to be found within its reach it finds it, and it does not leave stones to be taken.

It has no plan for an ending. With a few stones against fewer, it will often not find the way to finish, and the game will be drawn when sixty moves have passed with nothing taken.

CLASS METHODS

play

my $thought = Game::Fanorona::Bot->play($game, level => 10_000, seed => $seed);

Makes the player's move on the game: every step of it, and the stop if one is needed. From the middle of a move it finishes that move. Returns what think returns, or undef if the game is over.

think

my $thought = Game::Fanorona::Bot->think($game, level => 10_000, seed => $seed);

What the player would do, without doing it:

{
    move  => 'b2-c2A-c3A',   # '' when the thing to do is stop
    steps => [ ... ],        # the same, a step at a time, as $game->steps gives them
    level => 10000,
    depth => 4,              # whole moves looked ahead
    nodes => '9984',         # positions looked at
    score => 100,            # for the side to move; undef at level 0
}

level is the strongest of levels unless given. seed may be any string of bytes; it settles the choice among moves the player thinks equal, and at level 0 the choice among captures of the same size. A seed holding a character above 255 croaks. depth limits the looking ahead to that many whole moves.

choose

The move as a string, and nothing else.

hint

think at the strongest level, whatever level is asked for.

answer_draw

my $answer = Game::Fanorona::Bot->answer_draw($game);

accept or decline, for the side a standing offer was made to; undef when there is no offer or the game is over. It accepts when it is behind in stones, and when it is level and half the quiet limit has already passed with nothing taken.

levels

The measured levels, weakest first.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)