The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
package Volity::Bot::TicTacToe::Random;

# This is a bot that plays randomly.
# Challenge for the reader: write one that plays with some strategy.

use warnings;
use strict;

use base qw(Volity::Bot);

Volity::Bot::TicTacToe::Random->name("Tacky");
Volity::Bot::TicTacToe::Random->algorithm("http://volity.org/games/tictactoe/bot/random");

# Package variable of squares and the marks that fill them.
our %squares;

################
# RPC Handlers
################

# A handler for volity.start_game, an RPC defined by the core Volity
# protocol. (See http://www.volity.org/wiki/index.cgi?RPC_Requests)
# We react by resetting our idea of available squares.
sub volity_rpc_start_game {
    my $self = shift;
    $self->reset_board;
}

# A handler for volity.resume_game.
# There's a chance that one of the crafty humans has dragged me into a new
# seat, so I will make a state recovery request so I can get up to speed.
sub volity_rpc_resume_game {
    my $self = shift;
    $self->send_volity_rpc_to_referee("send_state");
}

# A handler for game.mark, an RPC defined by Tic Tac Toe's ruleset API.
# (See http://www.volity.org/games/tictactoe/)
# This means that a player has made a move.
sub game_rpc_mark {
    my $self = shift;
    my ($mark, $position) = @_;
    $self->mark_square($position, $mark);
}

# A handler for game.must_mark.
# This means that it's somebody's turn.
# If it's my turn, I will make a move.
sub game_rpc_must_mark {
    my $self = shift;
    my ($seat_id) = @_;
    if ($seat_id eq $self->seat_id) {
	# Whoops, it's my turn.
	$self->take_turn;
    }
}

#################
# Other methods
#################

# mark_square: Note that a given square (identified by number) has been
# marked.
sub mark_square {
    my $self = shift;
    my ($position, $mark) = @_;
    $squares{$position} = $mark;
}

# reset_board: Initialize our hash of squares to all blank.
sub reset_board {
    my $self = shift;
    foreach (0..8) {
	$squares{$_} = '';
    }
}

# mark_at_position: Returns the mark at the given board position,
# or the null string if there is no mark there.
sub mark_at_positon {
    my $self = shift;
    my ($position) = @_;
    return $squares{$position};
}

# take_turn: Take a turn, and send out an RPC.
# Becuase we're a dumb bot, we'll just pick a random unoccupied square.
# ( I note that one could try making a smarter bot by replacing this method. )
sub take_turn {
    my $self = shift;
    my @empty_squares = grep($squares{$_} eq '', keys(%squares));
    my $index = int(rand(@empty_squares));
    my $chosen_square = $empty_squares[$index];
    $self->send_game_rpc_to_referee("mark", $chosen_square);
}
	
    

1;

=head1 NAME

Volity::Bot::TicTacToe::Random - Tic tac toe bot module for Volity

=head1 DESCRIPTION

This is a subclass of C<Volity::Bot> that defines an automated Tic Tac
Toe player. It is not a very good Tic Tac Toe player, choosing a
random legal move to make every time its turn comes up.

More importantly, this module demonstrates how a simple Volty bot is
written in Perl. It is relatively short, and I have annotated its
source code in a way that I hope will be useful to people interested
in Volity game programming. Feel free to contact me with questions or
comments.

=head1 AUTHOR

Jason McIntosh <jmac@jmac.org>

=head1 COPYRIGHT

Copyright (c) 2006 by Jason McIntosh.

=head1 SEE ALSO

=over

=item * 

L<volityd>

=item * 

L<Volity::Bot>

=item *

L<Volity::Game::TicTacToe>

=item * 

http://volity.org

=back