#!/usr/local/bin/perl # # $Id: seeheaven.pl,v 4.9 2002/07/21 06:49:49 kono Exp $ package TempCardPile; use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK ); require Exporter; require AutoLoader; @ISA = qw(Exporter AutoLoader CardPlay::CardPile); @EXPORT = qw( ); $VERSION = "0.2"; use Tk; use CardPlay::Card; use CardPlay::CardPile; use CardPlay::CardBoard; sub new { my $type = shift; my $self = CardPlay::CardPile->new(@_); $self->{'-mergeable'}=1; $self->{'-splitable'}=1; # $self->{'-deltay'}=20; bless $self; } sub can_merge { my ($self,$cardpile) = @_; my ($card) = $cardpile->first(); my ($last) = $self->last(); if (defined($self->{'-max'}) && $self->count()+$cardpile->count() >$self->{'-max'}) { return $self->intelligent($cardpile); } if (!defined($card)) { return 0; } if ($self eq $cardpile->{'-prevSplit'}) { # any better place? return $self->intelligent($cardpile); } if (!defined($last)) { if (defined($self->{'-max'})) { return 1; } else { if ($card->{'-number'} == 13) { return 1; } else { return $self->intelligent($cardpile); } } } if ($last->{'-state'} eq 'hide') { return $self->intelligent($cardpile); } if ($card->{'-number'}==$last->{'-number'}-1 && $card->{'-suit'} eq $last->{'-suit'} ) { return 1; } return $self->intelligent($cardpile); } sub intelligent { # intelligent? Ha! my ($self,$cardpile) = @_; # remember this is called from can_merge. # use do_merge for undo logging etc. my ($suit) = $cardpile->first()->{'-suit'}; my ($number) = $cardpile->first()->{'-number'}; my ($board) = $self->{'-board'}; my ($last); my ($i); foreach $i ( @{$self->{'-tempPiles'}} ) { next if ($i eq $self); $last = $i->last(); next if (! defined($last)); next if ($last->{'-suit'} ne $suit); next if ($last->{'-number'} != $number+1); $i->do_merge($cardpile); return 2; } foreach $i ( @{$self->{'-tempPiles'}} ) { next if ($i eq $self); $last = $i->last(); next if (defined($last)); next if (!defined($self->{'-max'}) && $number != 13); next if (defined($self->{'-max'}) && $cardpile->count > $self->{'-max'}); $i->do_merge($cardpile); return 2; } return 0 if ($cardpile->count != 1); foreach $i ( @{$self->{'-bufPiles'}} ) { next if ($i eq $self); $last = $i->last(); next if (defined($last)); $i->do_merge($cardpile); return 2; } return 0; } sub can_split { my ($self,$i) = @_; my (@contents) = @{$self->{'-contents'}}; return 0 if (!defined($contents[$i])); return 0 if ($contents[$i]->{'-state'} eq 'hide'); my $suit = $contents[$i]->{'-suit'}; my $number = $contents[$i]->{'-number'}; my $vacancy = $self->{'-board'}->buf_vacancy(); return 0 if ($vacancy < $#contents+1-$i); for(;$i<=$#contents;$i++) { return 0 if (!defined($contents[$i])); return 0 if ($contents[$i]->{'-suit'} ne $suit); return 0 if ($contents[$i]->{'-number'} != $number); $number--; } return 1; } # package FinishCardPile; use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK ); require Exporter; require AutoLoader; @ISA = qw(Exporter AutoLoader CardPlay::CardPile); @EXPORT = qw( ); $VERSION = "0.2"; use Tk; use Carp; use CardPlay::Card; use CardPlay::CardPile; use CardPlay::CardBoard; sub new { my $type = shift; my $self = CardPlay::CardPile->new(@_); $self->{'-mergeable'}=1; $self->{'-deltay'}=0; bless $self; } sub can_merge { my ($self,$cardpile) = @_; my (@contents) = @{$cardpile->{'-contents'}}; return 0 if ($cardpile->empty()); my $suit = $contents[0]->{'-suit'}; my $number = ($self->empty())?1:1+$self->count(); for(my $i=0;$i<=$#contents;$i++) { return 0 if (!defined($contents[$i])); return 0 if ($contents[$i]->{'-suit'} ne $suit); return 0 if ($contents[$i]->{'-number'} != $number); $number++; } return 1; } # end package SeeHeavenBoard; use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK @count ); require Exporter; require AutoLoader; @ISA = qw(Exporter AutoLoader CardPlay::CardBoard); @EXPORT = qw( ); $VERSION = "0.2"; use Tk; use Carp; use CardPlay::Card; use CardPlay::CardPile; use CardPlay::CardBoard; sub new { my $type = shift; my $self = CardPlay::CardBoard->new(@_); $self->{'-auto_play'} = 1; bless $self; } sub new_cards { my $self = shift; my $card = []; my ($i,$suit); my ($c) = $self->{'-canvas'}; foreach $suit ( 's','h','c','d') { for($i=1;$i<14;$i++) { push(@{$card},CardPlay::Card->new( -state=>'open', -canvas=>$c,-board=>$self,-suit=>$suit,-number=>$i)); } } $self->{'-cards'} = $card; $self; } sub buf_vacancy { my ($self) = @_; my ($i) = 1; foreach my $j ( @{$self->{'-bufPiles'}} ) { $i++ if ($j->empty); } return $i; } sub auto_play { my ($self) = @_; my ($done) = 1; my ($cardpile); my ($finish); my ($card); my ($dest); # my ($c) = $self->{'-tempPiles'}->[0]->{'-canvas'}; my ($c) = $self->{'-canvas'}; my @list = (@{$self->{'-tempPiles'}},@{$self->{'-bufPiles'}}) ; retry: while ($done) { $done = 0; foreach $cardpile ( @list ) { $card = $cardpile->last(); next if (! defined($card)); foreach $finish ( @{$self->{'-finishPiles'}} ) { if ($finish->empty()) { if ($card->{'-number'}==1) { $finish->do_merge($cardpile->do_split(-1)); $done=1; $c->update; next retry; } } else { $dest = $finish->last(); if ($card->{'-number'}==$dest->{'-number'}+1 && $card->{'-suit'} eq $dest->{'-suit'}) { $finish->do_merge($cardpile->do_split(-1)); $done=1; $c->update; next retry; } } } } } } #sub enable_undo { # my ($self) = @_; # $self->{'-undoButton'}->configure(-state=>'normal'); # $self->{'-redoButton'}->configure(-state=>'normal'); # $self->{'-canvas'}->update; #} #sub disable_undo { # my ($self) = @_; # $self->{'-undoButton'}->configure(-state=>'disabled'); # $self->{'-redoButton'}->configure(-state=>'disabled'); # $self->{'-canvas'}->update; #} @count = (6,6,5,5,5,5,5,5,5,5); sub display { my $self = shift; $self->SUPER::display( -title=>'SeeHeaven'); my $c = $self->{'-canvas'}; my $x = $CardPlay::Card::cx+10; my $y = 20; my @finish; my @cp; my @buff; my $i; $self->{'-mainWindow'}->geometry( sprintf("%dx%d", ($CardPlay::Card::cx+10)*10, ($CardPlay::Card::cy)*7 )); $self->new_cards; for($i=0;$i<4;$i++) { $finish[$i] = FinishCardPile->new(-canvas=>$c,-base=>1,-board=>$self); $finish[$i]->display('-x'=>$x,'-y'=>$y); $x += $CardPlay::Card::cx+5; } $self->{'-finishPiles'} = \@finish; $self->add_piles(@finish); $x = $x+10; for($i=0;$i<4;$i++) { $buff[$i] = TempCardPile->new(-canvas=>$c,-base=>1, -tempPiles=>\@cp, -board=>$self,-max=>1 ); $buff[$i]->display('-x'=>$x,'-y'=>$y); $x += $CardPlay::Card::cx+5; } $self->{'-bufPiles'} = \@buff; $self->add_piles(@buff); $x = 5; $y = 20; my $dl = CardPlay::CardPile->new(); $self->{'-dealPile'}=$dl; $self->add_piles($dl); $x = 5; $y += $CardPlay::Card::cy+10; for($i=0;$i<=$#count;$i++) { $cp[$i] = TempCardPile->new( -canvas=>$c,-auto_open=>1,-board=>$self, -tempPiles=>\@cp,-bufPiles=>\@buff); $cp[$i]->display('-x'=>$x,'-y'=>$y,-base=>1); $x += $CardPlay::Card::cx+5; } $self->{'-tempPiles'} = \@cp; $self->add_piles(@cp); $self; } sub setup { my $self = shift; my ($dl) = $self->{'-dealPile'}; my ($cp) = $self->{'-tempPiles'}; my ($buff) = $self->{'-bufPiles'}; my ($fi) = $self->{'-finishPiles'}; my ($i,$j); # remove all CardPile $self->clear; # make new board by saved card array @{$dl->{'-contents'}} = @{$self->{'-cards'}}; # copy for($i=0;$i<=$#count;$i++) { $cp->[$i]->merge($dl->split(- $count[$i])); } $self; } # end package main; use strict; use CardPlay::CardBoard; my $board = SeeHeavenBoard->new(); $board->game(); 1; # end