ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/kgsueme/bin/kgsueme
(Generate patch)

Comparing kgsueme/bin/kgsueme (file contents):
Revision 1.25 by pcg, Fri May 30 15:50:20 2003 UTC vs.
Revision 1.28 by pcg, Sat May 31 04:35:39 2003 UTC

15use List::Util; 15use List::Util;
16use Errno; 16use Errno;
17 17
18init Gtk; 18init Gtk;
19 19
20$HACK = 1; # do NEVER enable. ;) 20our $HACK = 1; # do NEVER enable. ;)
21our $DEBUG_EXPOSE = 1;
21 22
22if ($HACK) { 23if ($HACK) {
23 $KGS::debug = 1; 24 $KGS::debug = 1;
24} 25}
26
27our $VERSION = "0.1";
25 28
26our $config; 29our $config;
27our $LIBDIR = "."; 30our $LIBDIR = ".";
28our $IMGDIR = "$LIBDIR/images"; 31our $IMGDIR = "$LIBDIR/images";
29our $SNDDIR = "$LIBDIR/sounds"; 32our $SNDDIR = "$LIBDIR/sounds";
54{ 57{
55 #my $audioserver = new Audio::Play(0); 58 #my $audioserver = new Audio::Play(0);
56 my %sound; 59 my %sound;
57 $SIG{CHLD} = 'IGNORE'; 60 $SIG{CHLD} = 'IGNORE';
58 61
59 for (qw(alarm warning move)) { 62 for (qw(alarm warning move pass ring connect user_unknown)) {
60 local $/; 63 local $/;
61 open my $snd, "<", "$SNDDIR/$_" 64 open my $snd, "<", "$SNDDIR/$_"
62 or die "$SNDDIR: $!"; 65 or die "$SNDDIR/$_: $!";
63 binmode $snd; 66 binmode $snd;
64 67
65 $sound{$_} = new Audio::Data; 68 $sound{$_} = new Audio::Data;
66 $sound{$_}->Load($snd); 69 $sound{$_}->Load($snd);
67 } 70 }
68 71
69 sub play_sound { 72 sub play_sound {
73 my ($annoyancy, $sound) = @_;
74 # annoyany 1 => important, annoyance 2 => useful, annoyancy 3 => not useful
70 if (fork == 0) { 75 if (fork == 0) {
71 if (my $audioserver = new Audio::Play(1)) { 76 if (my $audioserver = new Audio::Play(1)) {
72 $audioserver->play ($sound{$_[0]}); 77 $audioserver->play ($sound{$sound});
73 } 78 }
74 Gtk->_exit(0); 79 Gtk->_exit(0);
75 } 80 }
76 } 81 }
77} 82}
85 my $state = -r $staterc ? Storable::retrieve($staterc) : {}; 90 my $state = -r $staterc ? Storable::retrieve($staterc) : {};
86 my @widgets; 91 my @widgets;
87 92
88 $config = $state->{config} ||= {}; 93 $config = $state->{config} ||= {};
89 94
90 $config{speed} = 1;#d# optimize for speed or memory? 95 $config{speed} = 0;#d# optimize for speed or memory?
91 $config{conserve_memory} = 0; 96 $config{conserve_memory} = 0;
92 97
93 # grr... more gtk+ brokenness 98 # grr... more gtk+ brokenness
94 my %get = ( 99 my %get = (
95 hpane_position => sub { ($_[0]->children)[0]->allocation->[2] }, 100 hpane_position => sub { ($_[0]->children)[0]->allocation->[2] },
187 192
188if (0) { 193if (0) {
189 use KGS::Constants; 194 use KGS::Constants;
190 195
191 for (19) { 196 for (19) {
192 my $board = new game size => $_; 197 my $board = new game %{Storable::retrieve "testboard.storable"};
198
199 if (0) {
193 $board->{board} = new KGS::Game::Board; 200 $board->{board} = new KGS::Game::Board;
194 $board->{board}{board}[0][0] = MARK_B; 201 $board->{board}{board}[0][0] = MARK_B;
195 $board->{board}{board}[1][1] = MARK_GRAY_B | MARK_SMALL_W; 202 $board->{board}{board}[1][1] = MARK_GRAY_B | MARK_SMALL_W;
196 $board->{board}{board}[2][2] = MARK_W | MARK_TRIANGLE; 203 $board->{board}{board}[2][2] = MARK_W | MARK_TRIANGLE;
197 $board->{board}{board}[1][2] = MARK_B | MARK_LABEL; 204 $board->{board}{board}[1][2] = MARK_B | MARK_LABEL;
198 $board->{board}{label}[1][2] = "198"; 205 $board->{board}{label}[1][2] = "198";
199 $board->{board}{board}[0][2] = MARK_W | MARK_LABEL; 206 $board->{board}{board}[0][2] = MARK_W | MARK_LABEL;
200 $board->{board}{label}[0][2] = "AWA"; 207 $board->{board}{label}[0][2] = "AWA";
208 }
201 $board->{window}->show_all; 209 $board->{window}->show_all;
202 } 210 }
203} 211}
204 212
205main Gtk; 213main Gtk;
289 } 297 }
290 $self->{conn}->feed_data($buf); 298 $self->{conn}->feed_data($buf);
291 }; 299 };
292 300
293 # now login 301 # now login
294 $self->{conn}->login($self->{login}->get_text, $self->{password}->get_text); 302 $self->{conn}->login("kgsueme $VERSION $^O", $self->{login}->get_text, $self->{password}->get_text);
295} 303}
296 304
297sub inject_login { 305sub inject_login {
298 my ($self, $msg) = @_; 306 my ($self, $msg) = @_;
299 307
302 310
303 if ($msg->{success}) { 311 if ($msg->{success}) {
304 for (keys %{$::config->{rooms}}) { 312 for (keys %{$::config->{rooms}}) {
305 $self->{roomlist}->join_room($_); 313 $self->{roomlist}->join_room($_);
306 } 314 }
315 ::play_sound 3, "connect";
316 } elsif ($msg->{result} eq "user unknown") {
317 ::play_sound 2, "user_unknown";
318 } else {
319 ::play_sound 2, "warning";
307 } 320 }
308} 321}
309 322
310sub event_disconnect { } 323sub event_disconnect { }
311 324
417 ::state $self->{gamelist}, "room::gamelist", $self->{name}, clist_column_widths => [20, 120, 120, 120]; 430 ::state $self->{gamelist}, "room::gamelist", $self->{name}, clist_column_widths => [20, 120, 120, 120];
418 431
419 $self->{gamelist}->signal_connect(select_row => sub { 432 $self->{gamelist}->signal_connect(select_row => sub {
420 my $game = $self->{gamelist}->get_row_data($_[1]) 433 my $game = $self->{gamelist}->get_row_data($_[1])
421 or return; 434 or return;
422 $self->{game}{$game->{channel}} ||= new game %$game, conn => $self->{conn}; 435 $self->{game}{$game->{channel}} ||= new game %$game, conn => $self->{conn}, room => $self;
423 $self->{game}{$game->{channel}}->join; 436 $self->{game}{$game->{channel}}->join;
424 $self->{gamelist}->unselect_all; 437 $self->{gamelist}->unselect_all;
425 }); 438 });
426 439
427 $vpane->add(my $vbox = new Gtk::VBox); 440 $vpane->add(my $vbox = new Gtk::VBox);
459 my ($self) = @_; 472 my ($self) = @_;
460 $self->SUPER::part; 473 $self->SUPER::part;
461 474
462 delete $::config->{rooms}{$self->{channel}}; 475 delete $::config->{rooms}{$self->{channel}};
463 $self->{window}->hide_all; 476 $self->{window}->hide_all;
464 $self->event_update_users;
465 $self->event_update_games;
466} 477}
467 478
468sub inject_msg_room { 479sub inject_msg_room {
469 my ($self, $msg) = @_; 480 my ($self, $msg) = @_;
470 481
574 585
575 $self->{moveadj}->signal_connect (value_changed => sub { 586 $self->{moveadj}->signal_connect (value_changed => sub {
576 $self->{board} = new KGS::Game::Board $self->{size}; 587 $self->{board} = new KGS::Game::Board $self->{size};
577 $self->{board}->interpret_path ([@{$self->{path}}[0 .. $self->{moveadj}->value - 1]]); 588 $self->{board}->interpret_path ([@{$self->{path}}[0 .. $self->{moveadj}->value - 1]]);
578 589
579 $self->repaint_board; 590 my $area = $self->repaint_board;
580 591
581 # force a redraw (not perfect(?)) 592 # force a redraw (not perfect(?))
582 expose_event($self->{canvas}, $self, { area => [0, 0, @{$self->{canvas}->allocation}[2,3]] }); 593 $self->expose ($area);
583 594
584 $self->{text}->backward_delete($self->{text}->get_length); 595 $self->{text}->backward_delete($self->{text}->get_length);
585 $self->{text}->insert(undef, undef, undef, KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment}); 596 $self->{text}->insert(undef, undef, undef, KGS::Listener::Debug::dumpval([$self->{board}{time},$self->{board}{captures}]). $self->{board}{comment});
586 }); 597 });
598
599 $self->{moveadj}->upper (scalar @{$self->{path}}) if $self->{path};
587 } 600 }
588 601
589 Gtk::Widget->push_visual (Gtk::Gdk::Rgb->get_visual); 602 Gtk::Widget->push_visual (Gtk::Gdk::Rgb->get_visual);
590 Gtk::Widget->push_colormap (Gtk::Gdk::Rgb->get_cmap); 603 Gtk::Widget->push_colormap (Gtk::Gdk::Rgb->get_cmap);
591 $vbox->pack_start(($self->{canvas} = new Gtk::DrawingArea), 1, 1, 0); 604 $vbox->pack_start(($self->{canvas} = new Gtk::DrawingArea), 1, 1, 0);
643} 656}
644 657
645sub configure_event { 658sub configure_event {
646 my ($widget, $self, $event) = @_; 659 my ($widget, $self, $event) = @_;
647 delete $self->{stack}; 660 delete $self->{stack};
661 delete $self->{pixbuf};
662 delete $self->{board_shown};
648 delete $self->{background}; 663 delete $self->{background};
649 $self->repaint_board; 664 $self->repaint_board;
650 1; 665 1;
651} 666}
652 667
684 699
685# create a stack of stones 700# create a stack of stones
686sub create_stack { 701sub create_stack {
687 my ($self, $mark, $size, $rand) = @_; 702 my ($self, $mark, $size, $rand) = @_;
688 703
689 my $shadow = $size * 0.06; 704 my $shadow = $size * 0.05;
690 705
691 my $c = \$self->{stack}{$mark}; 706 my $c = \$self->{stack}{$mark};
692 unless ($$c) { 707 unless ($$c) {
693 for my $stone ($mark & (MARK_W | MARK_GRAY_W) ? @::white_img : @::black_img) { 708 for my $stone ($mark & (MARK_W | MARK_GRAY_W) ? @::white_img : @::black_img) {
694 my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 1; 709 my $base = new_pixbuf $size + $shadow, $size + $shadow, 1, 1;
728 $::config{speed} ? INTERP_NEAREST : INTERP_HYPER, 192 743 $::config{speed} ? INTERP_NEAREST : INTERP_HYPER, 192
729 ); 744 );
730 } 745 }
731 } 746 }
732 747
733 # and lastly any markers (labels NYI) 748 # and lastly any markers
734 my $dark_bg = ! ! ($mark & (MARK_B | MARK_GRAY_B)); 749 my $dark_bg = ! ! ($mark & (MARK_B | MARK_GRAY_B));
735 750
736 for ([MARK_CIRCLE, $::circle_img[$dark_bg]], 751 for ([MARK_CIRCLE, $::circle_img[$dark_bg]],
737 [MARK_TRIANGLE, $::triangle_img[$dark_bg]], 752 [MARK_TRIANGLE, $::triangle_img[$dark_bg]],
738 [MARK_SQUARE, $::square_img[$dark_bg]]) { 753 [MARK_SQUARE, $::square_img[$dark_bg]]) {
793} 808}
794 809
795sub repaint_board { 810sub repaint_board {
796 my ($self) = @_; 811 my ($self) = @_;
797 my $canvas = $self->{canvas}; 812 my $canvas = $self->{canvas};
813 my $expose_area = undef;
798 814
799 return unless $self->{board}; 815 return $expose_area unless $self->{board};
800 816
801 my ($w, $h) = @{$canvas->allocation}[2,3]; 817 my ($w, $h) = @{$canvas->allocation}[2,3];
802 818
803 my $s = $w > $h ? $h : $w; 819 my $s = $w > $h ? $h : $w;
804 820
806 822
807 my $size = $self->{size}; 823 my $size = $self->{size};
808 824
809 my $border = int ($s / ($size + 3) * 0.5); 825 my $border = int ($s / ($size + 3) * 0.5);
810 my $s2 = $s - $border * 2; 826 my $s2 = $s - $border * 2;
811 my $edge = int ($s2 / ($size + 1) * 0.97); 827 my $edge = int ($s2 / ($size + 1) * 0.95);
812 my $ofs = int ($edge / 2); 828 my $ofs = int ($edge / 2);
813 829
814 my @k = map int ($s2 * $_ / ($size+1) + $border + 0.5), 0 .. $size; 830 my @k = map int ($s2 * $_ / ($size+1) + $border + 0.5), 0 .. $size;
815 831
816 my $pixbuf; 832 my $pixbuf;
817 833
834 my $oldboard;
835
818 if ($self->{background}) { 836 if ($self->{background}) {
837 if ($oldboard = $self->{board_shown}) {
838 $pixbuf = $self->{pixbuf};
839 } else {
819 $pixbuf = $self->{background}->copy; 840 $pixbuf = $self->{background}->copy;
841 $expose_area = [0, 0, $s, $s];
842 }
820 } else { 843 } else {
844 $expose_area = [0, 0, $s, $s];
845
821 my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); 846 my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height);
822 847
823 if ($s < $bw && $s < $bh) { 848 if ($s < $bw && $s < $bh) {
824 $pixbuf = new_pixbuf $s, $s, $::config{conserve_memory} ? 0 : 1, 0; 849 $pixbuf = new_pixbuf $s, $s, $::config{conserve_memory} ? 0 : 1, 0;
825 $::board_img->copy_area (0, 0, $s, $s, $pixbuf, 0, 0); 850 $::board_img->copy_area (0, 0, $s, $s, $pixbuf, 0, 0);
857 # hoshi-points(!)#d# 882 # hoshi-points(!)#d#
858 # caching of empty board gfx(!)#d# 883 # caching of empty board gfx(!)#d#
859 884
860 for my $x (1 .. $size) { 885 for my $x (1 .. $size) {
861 for my $y (1 .. $size) { 886 for my $y (1 .. $size) {
887 my ($dx, $dy) = ($k[$x] - $ofs, $k[$y] - $ofs);
862 my $mark = $self->{board}{board}[$x-1][$y-1]; 888 my $mark = $self->{board}{board}[$x-1][$y-1];
889 my $old = $oldboard ? $oldboard->{board}[$x-1][$y-1] : 0;
890
891 if ($oldboard && $old != $mark) {
892 my $shadow = $edge * 0.05;
893 my $new_expose = [$dx, $dy, $edge + $shadow, $edge + $shadow];
894 $self->{background}->copy_area (@$new_expose, $pixbuf, $dx, $dy);
895 $expose_area = $expose_area
896 ? Gtk::Gdk::Rectangle->union ($expose_area, $new_expose)
897 : $new_expose;
898 }
863 899
864 if ($mark) { 900 if ($mark) {
865 my ($dx, $dy) = ($k[$x] - $ofs, $k[$y] - $ofs);
866 my $pb = $self->create_stack($mark, $edge, $x * 17 + $y * 11 ); 901 my $pb = $self->create_stack($mark, $edge, $x * 17 + $y * 11 );
867 902
868 $pb->composite ($pixbuf, $dx, $dy, $pb->get_width, $pb->get_height, 903 $pb->composite ($pixbuf, $dx, $dy, $pb->get_width, $pb->get_height,
869 $dx, $dy, 1, 1, $::config{speed} ? INTERP_NEAREST : INTERP_NEAREST, 255); 904 $dx, $dy, 1, 1, $::config{speed} ? INTERP_NEAREST : INTERP_NEAREST, 255);
870 905
871 # labels are handled here because they are quite rare 906 # labels are handled here because they are quite rare
872 if ($mark & MARK_LABEL) { 907 if ($mark & MARK_LABEL) {
873 pixbuf_text $pixbuf, $mark & (MARK_W | MARK_GRAY_W) ? 0 : 1, 908 my $white = $mark & (MARK_W | MARK_GRAY_W) ? 0 : 1;
909
910 if ($white) {
911 pixbuf_text $pixbuf, 0,
912 $k[$x] + $ofs * 0.1, $k[$y] + $ofs * 0.1, $ofs * 0.7,
913 $self->{board}{label}[$x-1][$y-1];
914 }
915 pixbuf_text $pixbuf, $white,
874 $k[$x], $k[$y], $ofs * 0.7, 916 $k[$x], $k[$y], $ofs * 0.7,
875 $self->{board}{label}[$x-1][$y-1]; 917 $self->{board}{label}[$x-1][$y-1];
876 } 918 }
877 919
920 # old pixmap&mask-way. that was fast ;(
878 #my ($pm, $bm) = $self->create_stack($gc, $mark, $edge, $x * 17 + $y * 11 ); 921 #my ($pm, $bm) = $self->create_stack($gc, $mark, $edge, $x * 17 + $y * 11 );
879 922
880 #$gc->set_clip_mask ($bm); 923 #$gc->set_clip_mask ($bm);
881 #$gc->set_clip_origin ($dx, $dy); 924 #$gc->set_clip_origin ($dx, $dy);
882 #$pixmap->draw_pixmap ($gc, $pm, 0, 0, $dx, $dy, $edge, $edge); 925 #$pixmap->draw_pixmap ($gc, $pm, 0, 0, $dx, $dy, $edge, $edge);
883 } 926 }
884 } 927 }
885 } 928 }
886}
887 929
930 $self->{board_shown} = Storable::dclone $self->{board};
931 #d# save
932 #Storable::nstore { board => $self->{board}, size => $self->{size}, path => $self->{path}}, "testboard.storable";
933
934 $expose_area;
935}
936
888sub expose_event { 937sub expose {
889 my ($widget, $self, $event) = @_; 938 my ($self, $area) = @_;
890 939
891 $self->{pixbuf} or return; 940 if ($area && $self->{pixbuf}) {
892 941 my ($x, $y, $w, $h) = @$area;
893 my ($ox, $oy, $s) = @{$self->{offsets}}; 942 my ($ox, $oy, $s) = @{$self->{offsets}};
894 943
895 my ($x, $y, $w, $h) =
896 @{Gtk::Gdk::Rectangle->intersect(
897 $event->{area},
898 [$ox, $oy, $s, $s]
899 )};
900
901 if (defined $x) {
902 $self->{pixbuf}->render_to_drawable ($self->{canvas}->window, $self->{canvas}->style->white_gc, 944 $self->{pixbuf}->render_to_drawable ($self->{canvas}->window, $self->{canvas}->style->white_gc,
903 $x - $ox, $y - $oy, $x, $y, $w, $h); 945 $x, $y, $x + $ox, $y + $oy, $w, $h);
946 $self->{canvas}->window->draw_rectangle ($self->{canvas}->style->black_gc, 0,
947 $x + $ox - 1, $y + $oy - 1, $w + 2, $h + 2) if $::DEBUG_EXPOSE;
948
904 #$self->{canvas}->window->draw_pixmap ( 949 #$self->{canvas}->window->draw_pixmap (
905 # $self->{canvas}->style->white_gc, 950 # $self->{canvas}->style->white_gc,
906 # $self->{pixmap}, 951 # $self->{pixmap},
907 # $x - $ox, $y - $oy, $x, $y, $w, $h, 952 # $x - $ox, $y - $oy, $x, $y, $w, $h,
908 #); 953 #);
909 } 954 }
955}
956
957sub expose_event {
958 my ($widget, $self, $event) = @_;
959
960 $self->{pixbuf} or return;
961
962 my $area = $event->{area};
963 my ($ox, $oy, $s) = @{$self->{offsets}};
964
965 $self->expose (Gtk::Gdk::Rectangle->intersect (
966 [$area->[0] - $ox, $area->[1] - $oy, $area->[2], $area->[3]],
967 [0, 0, $s, $s],
968 ));
969
910 1; 970 1;
911} 971}
912 972
913sub event_update_tree { 973sub event_update_tree {
914 my ($self) = @_; 974 my ($self) = @_;
922 if ($self->{moveadj}->value >= $move - 1 || !$self->{moveadj}->value) { 982 if ($self->{moveadj}->value >= $move - 1 || !$self->{moveadj}->value) {
923 $self->{moveadj}->set_value ($move); 983 $self->{moveadj}->set_value ($move);
924 } 984 }
925} 985}
926 986
987sub event_part {
988 my ($self) = @_;
989 $self->SUPER::event_part;
990 (delete $self->{window})->destroy; # hmm.. why does this keep the object alive? puzzling.. ahh.. the callbacks ;)
991 delete $self->{room}{game}{$self->{channel}};
992}
993
927sub event_move { 994sub event_move {
928 ::play_sound "move"; 995 my ($self, $pass) = @_;
996 ::play_sound 1, $pass ? "pass" : "move";
997}
998
999sub DESTROY {#d#
1000 warn "DESTROY(@_)\n";#d#
929} 1001}
930 1002
9311; 10031;
932 1004
933 1005

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines