added quit
[svn42.git] / dart / Dart.pm
index 9f5fd3c..8ceee17 100644 (file)
@@ -2,6 +2,7 @@
 package Dart;
 use strict;
 use base 'Exporter';
+use Clone;
 # new Dart(player_names=>[ 'lala', 'popo' ]);
 ## Player, Rank, Active, 
 
@@ -12,28 +13,40 @@ sub new
   my (%params) =@_;
   my $self  = bless {}, $class;
   die "Missing player_names" if not ref $params{player_names} eq 'ARRAY';
-  die "Missing player_names" if @{$params{player_names}};
+  die "Missing player_names" if not @{$params{player_names}};
   $self->{player}=[];
-  $self->{current_player}=0;
-  my $player_counter=0;
   for my $player_name (@{$params{player_names}}) 
   {
-    $player_counter++;
     $self->add_player(&create_player(name=>$player_name,rank=>undef,active=>1));
   }
-  $self->{active_player_count}=$player_counter;
-  $self->{player_count}=$player_counter;
-  $self->{round}=1;
+  $self->{callbacks}=$params{callbacks};
+  $self->init();
+  return $self;
+}
+
+
+sub init
+{
+  my $self=shift;
+  $self->{round}=0;
   $self->{max_shoots_per_player}=3;
   $self->{current_shoot_count}=0;
-  
+  $self->{current_player}=0;
+  $self->{player_count}=@{$self->{player}};
+  $self->{active_player_count}=$self->{player_count};
   $self->callback('init');
-  return $self;
 }
 
 sub reset_game
 {
   my $self=shift;
+  my @sort_player = sort { $b->{rank} <=> $a->{rank} } @{$self->{player}};
+  $self->{player}=[];
+  for my $player (@sort_player)
+  {
+    $self->add_player(&create_player(name=>$player->{name},rank=>undef,active=>1));
+  }
+  $self->init();
 }
 
 sub callback
@@ -52,11 +65,15 @@ sub run
 {
   my $self=shift;
   my ($data_in_fh,$sound_out_fh)=@_;
+  my @history;
 #  $data_in_fh ||= STDIN;
 #  $sound_out_fh ||= STDOUT;
   $self->{sound_out_fh}=$sound_out_fh;
 
-  while ( my $shoot_data = <$data_in_fh>)
+  push @history, Clone::clone($self);
+  $self->callback('before_shoot');
+  #while ( my $shoot_data = <$data_in_fh>)
+  while ( my $shoot_data = <STDIN>)
   {
     #print STDERR $schuss;
     my ($mult,$number) = split /\s+/, $shoot_data;
@@ -67,7 +84,17 @@ sub run
       $self->shoot($mult,$number);
     } elsif ($mult eq 'btn') {
       $self->next_player();
+    } elsif ($mult eq 'undo' and $#history) {
+      pop @history;
+      $self= pop @history;
+      $self->callback('undo');
+    } elsif ($mult eq 'reset') {
+      $self->reset_game();
+    } elsif ($mult eq 'quit') {
+      return;
     }
+    push @history, Clone::clone($self);
+    $self->callback('before_shoot');
   }
 }
 
@@ -88,7 +115,10 @@ sub shoot
 sub shout_last_shoot
 {
   my $self=shift;
-  if ($self->{current_shoot}{mult} == 2) {
+  if ($self->{current_shoot}{mult} == 2 && $self->{current_shoot}{number} == 25) {
+    $self->shout("bullseye");
+    return;
+  } elsif ($self->{current_shoot}{mult} == 2 ) {
     $self->shout('double');
   } elsif ($self->{current_shoot}{mult} == 3) {
     $self->shout('triple');
@@ -102,7 +132,27 @@ sub shout
   my $self=shift;
   my ($what)=@_;
   my $fh = $self->{sound_out_fh};
-  print $fh "$what\n";
+  if ($what eq 25)
+  {
+    print "bull\n";
+  } else {
+    print "$what\n";
+  }
+#print $fh "$what\n";
+}
+
+sub get_current_player
+{
+  my $self=shift;
+  return $self->get_player($self->{current_player});
+}
+
+sub get_player
+{
+  my $self=shift;
+  my ($player_idx)=@_;
+  die "Illegal Player Index $player_idx" if $player_idx < 0 or $player_idx >= $self->{player_count};
+  return $self->{player}[$player_idx];
 }
 
 sub next_player
@@ -110,16 +160,18 @@ sub next_player
   my $self=shift;
   $self->callback('before_next_player');
   $self->{current_shoot_count}=0;
-  ($self->{current_player},my $new_round)=get_next_active_player($self->{current_player});
+  ($self->{current_player},my $new_round)=$self->get_next_active_player();
   $self->shout("player");
-  $self->shout($self->{player}[$self->{current_player}]{name});
+  $self->shout($self->get_current_player()->{name});
   $self->next_round() if $new_round;
   return $self->callback('next_player');
 }
 
 sub get_next_active_player
 {
-  my ($players_ref,$current_player)=@_;
+  my $self=shift;
+  my $players_ref = $self->{player};
+  my $current_player = $self->{current_player};
   my $num_players=@$players_ref;
   my $new_round=0;
   do
@@ -127,12 +179,12 @@ sub get_next_active_player
     $current_player++;
     if($current_player>=$num_players)
     {
-      die "Error no remaining active players" if $new_round;
+      $self->reset_game() if $new_round;
       $current_player=0;
       $new_round=1;
     }
   }
-  while (not $players_ref->[$current_player]{active});
+  while (not $self->{player}->[$current_player]{active});
   return ($current_player,$new_round);
 }
 
@@ -143,6 +195,30 @@ sub next_round
   return $self->callback('next_round');
 }
 
+sub win
+{
+  my $self=shift;
+  $self->shout('win');
+  $self->deactivate_current_player($self->{player_count}-$self->{active_player_count}+1);
+  if ($self->{active_player_count}==1)
+  {
+    $self->next_player();
+    $self->lose();
+  }
+}
+
+sub lose
+{
+  my $self=shift;
+  $self->shout('lose');
+  $self->deactivate_current_player($self->{active_player_count});
+  if ($self->{active_player_count}==1)
+  {
+    $self->next_player();
+    $self->win();
+  }
+}
+
 sub deactivate_current_player
 {
   my $self=shift;
@@ -157,6 +233,7 @@ sub deactivate_current_player
 sub end_game
 {
   my $self=shift;
+  $self->shout('end_game');
   return $self->callback('end_game');
 }
 
@@ -174,3 +251,5 @@ sub create_player
   #my $player = {%player_attributes};
   #return $player;
 }
+
+1;