Skip to content

Instantly share code, notes, and snippets.

@makamaka
Created May 21, 2012 04:51
Show Gist options
  • Save makamaka/2760603 to your computer and use it in GitHub Desktop.
Save makamaka/2760603 to your computer and use it in GitHub Desktop.
やったー Yaircで○×ゲームできたよー
package Yairc::Plugin::OXGame;
=pod
○×ゲーム
3×3のマスに○と×を交互に置いて
タテ・ヨコ・ナナメ3連続になった方の勝ち
タグは #ox
まずはTAGSにoxを追加しておきましょう。
本文に join が含まれると参加
二人揃うとゲーム開始(一人で2回joinしてもok)
  a  b  c
 ┌─┬─┬─┐
1 │ │ │ │
 ├─┼─┼─┤
2 │ │ │ │
 ├─┼─┼─┤
3 │ │ │ │
 └─┴─┴─┘
a1 あるいは 1a と打てば左上隅に○(もしくは×)が置かれる
他のマスも同様。
view と打つと本人にのみ現在の盤面が表示される
help でコマンドリスト
quit でゲーム離脱
ex.
join #ox
view #ox
Let's enjoy!
=cut
use strict;
use warnings;
use utf8;
my $USER = {};
my $BOARD = [[0,0,0],[0,0,0],[0,0,0]];
my @TURN; # idx 0 is the user in turn.
my $TURN; # count
sub setup {
my ( $class, $sys ) = @_;
$sys->register_calling_tag( 'OX', sub {
my ( $sys, $socket, undef, $message_ref, $tags ) = @_;
my $user;
$socket->get('user_data', sub {
$user = $_[2];
});
return unless $user;
my $text = '';
my $game_is_over;
my $entried;
if ( $$message_ref =~ /join/ ) {
my $num = @TURN;
if ( $num == 2 ) {
$text .= "定員に達しています。\n";
}
else {
if ( $num == 1 and $TURN[0]->[0] == 2 ) {
$num = 0;
}
$USER->{ $user->{ token } } = [ $num + 1, $user ];
push @TURN, [ $num + 1, $user ];
$text .= $user->{ nickname } . "が参加しました。\n";
$text .= "(※ゲームセット時のみログに残ります)\n";
$entried = 1;
}
}
elsif ( $$message_ref =~ /help/ ) {
$text .= "join ... 参加\n";
$text .= "quit ... 離脱\n";
$text .= "view ... 閲覧\n";
}
elsif ( $$message_ref =~ /view/ ) {
$text .= board();
$socket->emit( 'user message', make_post( $sys, $text ) );
return;
}
elsif ( $$message_ref =~ /quit/ ) {
quit_player( $user );
}
elsif ( scalar( @TURN ) == 2 && exists $USER->{ $user->{ token } } ) {
my $turn = $USER->{ $user->{ token } };
if ( scalar( keys %$USER ) == 1 ) { # 一人プレイの場合
$turn = $TURN[0];
}
if ( $TURN[0]->[0] == $turn->[0] ) {
my ( $row ) = $$message_ref =~ /([123])/;
my ( $col ) = $$message_ref =~ /([abc])/;
$col = $col eq 'a' ? 1
: $col eq 'b' ? 2
: $col eq 'c' ? 3
: 0;
if ( $col and $row ) {
if ( $BOARD->[ $row - 1 ]->[ $col - 1 ] ) {
$text .= "そこは既に置かれています。\n";
}
else {
$TURN++;
$BOARD->[ $row - 1 ]->[ $col - 1 ] = $turn->[0];
if ( $game_is_over = is_game_over( $row - 1, $col - 1 ) ) {
$text .= "ゲームセット! " . $TURN[0]->[1]->{ nickname } . "の勝ち\n";
}
elsif ( $TURN == 9 ) {
$text = "ゲームセット! 引き分け\n" . $text;
$game_is_over = 1;
}
@TURN = @TURN[1,0];
}
}
}
else {
return;
}
}
else {
return;
}
$text .= board();
if ( $game_is_over ) {
%$USER = ();
@TURN = ();
$BOARD = [[0,0,0],[0,0,0],[0,0,0]];
$TURN = 0;
$sys->data_storage->add_post( make_post( $sys, $text ) );
}
$sys->send_post_to_tag_joined( make_post( $sys, $text ), 'OX' );
} );
$sys->register_hook( 'disconnected', sub {
my ( $sys, $socket ) = @_;
my $user;
$socket->get('user_data', sub {
$user = $_[2];
});
} );
}
sub quit_player {
my ( $user ) = @_;
return unless $user->{ token };
delete $USER->{ $user->{ token } };
@TURN = grep { $_->[1]->{ token } ne $user->{ token } } @TURN;
}
sub is_game_over {
my ( $row_num, $col_num ) = @_;
# yoko
my $d = $BOARD->[ $row_num ];
if ( $d->[0] == $d->[1] and $d->[0] == $d->[2] ) {
return 1;
}
# tate
if (
$BOARD->[ 0 ]->[ $col_num ] == $BOARD->[ 1 ]->[ $col_num ]
and $BOARD->[ 0 ]->[ $col_num ] == $BOARD->[ 2 ]->[ $col_num ]
)
{
return 1;
}
# naname
if ( ($row_num == 0 and $col_num == 0) or ($row_num == 1 and $col_num == 1)
or ($row_num == 2 and $col_num == 2) )
{
return 1 if ( $BOARD->[ 0 ]->[ 0 ] == $BOARD->[ 1 ]->[ 1 ]
and $BOARD->[ 0 ]->[ 0 ] == $BOARD->[ 2 ]->[ 2 ] );
}
if ( ($row_num == 0 and $col_num == 2) or ($row_num == 1 and $col_num == 1)
or ($row_num == 2 and $col_num == 0) )
{
return 1 if ( $BOARD->[ 0 ]->[ 2 ] == $BOARD->[ 1 ]->[ 1 ]
and $BOARD->[ 0 ]->[ 2 ] == $BOARD->[ 2 ]->[ 0 ] );
}
return 0;
}
sub board {
my $text = '';
for ( @TURN ) {
my ( $num, $user ) = @{$_};
$text .= $num == 1 ? '○' : '×';
$text .= ":" . $user->{ nickname } . "\n";
}
$text .= "  a  b  c\n ┌─┬─┬─┐\n";
my $i = 1;
for my $row ( @{ $BOARD } ) {
$text .= "$i │";
for my $col ( @$row ) {
if ( $col == 0 ) {
$text .= ' ';
}
elsif ( $col == 1 ) {
$text .= '○';
}
elsif ( $col == 2 ) {
$text .= '×';
}
$text .= '│';
}
$text .= "\n";
$text .= " ├─┼─┼─┤\n" if $i++ < 3;
}
$text .= " └─┴─┴─┘\n";
return $text;
}
sub make_post {
my ( $sys, $message ) = @_;
return {
id => '-1',
text => $message,
nickname => '○×ゲーム',
user_key => '+:ox',
tags => ['OX'],
created_at_ms => $sys->data_storage->_get_now_micro_sec,
is_message_log => JSON::false,
profile_image_url => '',
};
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment