… | |
… | |
295 | for @$remove; |
295 | for @$remove; |
296 | |
296 | |
297 | $self->{users_inlay}->refresh; |
297 | $self->{users_inlay}->refresh; |
298 | |
298 | |
299 | my %important; |
299 | my %important; |
|
|
300 | $important{$self->{black}{name}}++; |
|
|
301 | $important{$self->{white}{name}}++; |
300 | $important{$self->{user1}{name}}++; |
302 | $important{$self->{owner}{name}}++; |
301 | $important{$self->{user2}{name}}++; |
|
|
302 | $important{$self->{user3}{name}}++; |
|
|
303 | |
303 | |
304 | if (my @users = grep $important{$_->{name}}, @$add) { |
304 | if (my @users = grep $important{$_->{name}}, @$add) { |
305 | $self->{chat}->append_text ("\n<header>Joins:</header>"); |
305 | $self->{chat}->append_text ("\n<header>Joins:</header>"); |
306 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
306 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
307 | } |
307 | } |
… | |
… | |
331 | warn !($self->{playing} && $running); |
331 | warn !($self->{playing} && $running); |
332 | warn $self->{teacher} ne $self->{app}{conn}; |
332 | warn $self->{teacher} ne $self->{app}{conn}; |
333 | if (!($self->{playing} && $running) && $self->{teacher} ne $self->{app}{conn}) { |
333 | if (!($self->{playing} && $running) && $self->{teacher} ne $self->{app}{conn}) { |
334 | warn "A\n"; |
334 | warn "A\n"; |
335 | $self->{board}->set (cursor_mask => 0, cursor_value => 0); |
335 | $self->{board}->set (cursor_mask => 0, cursor_value => 0); |
336 | } elsif ($self->{user1}{name} eq $self->{conn}{name}) { |
336 | } elsif ($self->{black}{name} eq $self->{conn}{name}) { |
337 | warn "B\n"; |
337 | warn "B\n"; |
338 | $self->{board}->set (cursor_mask => MARK_B | MARK_W, cursor_value => MARK_B | MARK_GRAYED); |
338 | $self->{board}->set (cursor_mask => MARK_B | MARK_W, cursor_value => MARK_B | MARK_GRAYED); |
339 | $cb = sub { |
339 | $cb = sub { |
340 | $self->send (upd_tree => |
340 | $self->send (upd_tree => |
341 | channel => $self->{channel}, |
341 | channel => $self->{channel}, |
342 | tree => $self->gen_move_tree (COLOUR_BLACK, $_[0], $_[1]), |
342 | tree => $self->gen_move_tree (COLOUR_BLACK, $_[0], $_[1]), |
343 | ); |
343 | ); |
344 | }; |
344 | }; |
345 | } elsif ($self->{user2}{name} eq $self->{conn}{name}) { |
345 | } elsif ($self->{white}{name} eq $self->{conn}{name}) { |
346 | warn "C\n"; |
346 | warn "C\n"; |
347 | $self->{board}->set (cursor_mask => MARK_B | MARK_W, cursor_value => MARK_W | MARK_GRAYED); |
347 | $self->{board}->set (cursor_mask => MARK_B | MARK_W, cursor_value => MARK_W | MARK_GRAYED); |
348 | $cb = sub { |
348 | $cb = sub { |
349 | $self->send (upd_tree => |
349 | $self->send (upd_tree => |
350 | channel => $self->{channel}, |
350 | channel => $self->{channel}, |
… | |
… | |
458 | } |
458 | } |
459 | |
459 | |
460 | sub event_move { |
460 | sub event_move { |
461 | my ($self, $pass) = @_; |
461 | my ($self, $pass) = @_; |
462 | sound::play 1, $pass ? "pass" : "move"; |
462 | sound::play 1, $pass ? "pass" : "move"; |
|
|
463 | |
|
|
464 | if ($self->{undo_inlay}) { |
|
|
465 | (delete $self->{undo_inlay})->clear; |
|
|
466 | } |
463 | } |
467 | } |
464 | |
468 | |
465 | sub event_update_game { |
469 | sub event_update_game { |
466 | my ($self) = @_; |
470 | my ($self) = @_; |
467 | |
471 | |
… | |
… | |
476 | ? $self->owner->as_string . " " . $self->opponent_string |
480 | ? $self->owner->as_string . " " . $self->opponent_string |
477 | : "Game Window"; |
481 | : "Game Window"; |
478 | $self->set_title("KGS Game $title"); |
482 | $self->set_title("KGS Game $title"); |
479 | $self->{title}->set_text ($title); |
483 | $self->{title}->set_text ($title); |
480 | |
484 | |
481 | $self->{user}[COLOUR_BLACK] = $self->{user1}; |
485 | $self->{user}[COLOUR_BLACK] = $self->{black}; |
482 | $self->{user}[COLOUR_WHITE] = $self->{user2}; |
486 | $self->{user}[COLOUR_WHITE] = $self->{white}; |
483 | |
487 | |
484 | # show board |
488 | # show board |
485 | if ($self->is_inprogress) { |
489 | if ($self->is_inprogress) { |
486 | if (!$self->{boardbox}->parent) { |
490 | if (!$self->{boardbox}->parent) { |
487 | $self->{boardbox}->add ($self->{board} = new Gtk2::GoBoard size => $self->{size}); |
491 | $self->{boardbox}->add ($self->{board} = new Gtk2::GoBoard size => $self->{size}); |
… | |
… | |
492 | $self->{board_click}->($_[2], $_[3]) if $self->{board_click}; |
496 | $self->{board_click}->($_[2], $_[3]) if $self->{board_click}; |
493 | } |
497 | } |
494 | }); |
498 | }); |
495 | } |
499 | } |
496 | if (my $ch = delete $self->{challenge}) { |
500 | if (my $ch = delete $self->{challenge}) { |
497 | (delete $_->{inlay})->destroy for values %$ch; |
501 | $_->{inlay}->destroy for values %$ch; |
498 | } |
502 | } |
499 | $self->update_cursor; |
503 | $self->update_cursor; |
500 | } |
504 | } |
501 | |
505 | |
502 | $self->{left}->show_all; |
506 | $self->{left}->show_all; |
… | |
… | |
515 | my $text = ""; |
519 | my $text = ""; |
516 | |
520 | |
517 | $text .= "\nTeacher: <user>" . (util::toxml $self->{teacher}) . "</user>" |
521 | $text .= "\nTeacher: <user>" . (util::toxml $self->{teacher}) . "</user>" |
518 | if $self->{teacher}; |
522 | if $self->{teacher}; |
519 | |
523 | |
520 | $text .= "\nOwner: <user>" . (util::toxml $self->{user3}->as_string) . "</user>" |
524 | $text .= "\nOwner: <user>" . (util::toxml $self->{owner}->as_string) . "</user>" |
521 | if $self->{user3}->is_valid; |
525 | if $self->{owner}->is_valid; |
522 | |
526 | |
523 | if ($self->is_inprogress) { |
527 | if ($self->is_inprogress) { |
524 | $text .= "\nPlayers: <user>" . (util::toxml $self->{user2}->as_string) . "</user>" |
528 | $text .= "\nPlayers: <user>" . (util::toxml $self->{white}->as_string) . "</user>" |
525 | . " vs. <user>" . (util::toxml $self->{user1}->as_string) . "</user>"; |
529 | . " vs. <user>" . (util::toxml $self->{black}->as_string) . "</user>"; |
526 | } |
530 | } |
527 | $text .= "\nType: " . util::toxml $gametype{$self->type}; |
531 | $text .= "\nType: " . util::toxml $gametype{$self->type}; |
528 | |
532 | |
529 | $text .= "\nRuleset: " . $ruleset{$rules->{ruleset}}; |
533 | $text .= "\nRuleset: " . $ruleset{$rules->{ruleset}}; |
530 | |
534 | |
… | |
… | |
598 | . "\nBlack Score " . (util::toxml $msg->{blackscore}->as_string) |
602 | . "\nBlack Score " . (util::toxml $msg->{blackscore}->as_string) |
599 | . "</infoblock>" |
603 | . "</infoblock>" |
600 | ); |
604 | ); |
601 | } |
605 | } |
602 | |
606 | |
|
|
607 | sub inject_req_undo { |
|
|
608 | my ($self, $msg) = @_; |
|
|
609 | |
|
|
610 | my $inlay = $self->{undo_inlay} ||= $self->{chat}->new_inlay; |
|
|
611 | return if $inlay->{ignore}; |
|
|
612 | |
|
|
613 | $inlay->{count}++; |
|
|
614 | $inlay->clear; |
|
|
615 | $inlay->append_text ("\n<undo>Undo requested ($inlay->{count} times)</undo>\n"); |
|
|
616 | $inlay->append_button ("Grant", sub { |
|
|
617 | $inlay->clear; |
|
|
618 | $self->send (grant_undo => channel => $self->{channel}); |
|
|
619 | }); |
|
|
620 | $inlay->append_button ("Ignore", sub { |
|
|
621 | $inlay->clear; |
|
|
622 | $inlay->{ignore} = 1; |
|
|
623 | # but leave inlay, so further undo requests get counted |
|
|
624 | }); |
|
|
625 | |
|
|
626 | } |
|
|
627 | |
603 | sub inject_new_game { |
628 | sub inject_new_game { |
604 | my ($self, $msg) = @_; |
629 | my ($self, $msg) = @_; |
605 | |
630 | |
606 | $self->{chat}->append_text ("\n<header>ACK from server ($msg->{cid} == $self->{cid})</header>"); |
631 | $self->{chat}->append_text ("\n<header>ACK from server ($msg->{cid} == $self->{cid})</header>"); |
607 | delete $self->{cid}; |
632 | delete $self->{cid}; |
608 | } |
633 | } |
609 | |
634 | |
610 | sub draw_challenge { |
635 | sub draw_challenge { |
611 | my ($self, $id) = @_; |
636 | my ($self, $id) = @_; |
612 | |
637 | |
613 | my $challenge = $self->{challenge}{$id}; |
638 | my $info = $self->{challenge}{$id}; |
614 | |
|
|
615 | my $inlay = $challenge->{inlay}; |
639 | my $inlay = $info->{inlay}; |
616 | my $rules = $challenge->{rules}; |
640 | my $rules = $info->{rules}; |
|
|
641 | warn "drawchal $id\n";#d# |
|
|
642 | # use PApp::Util; warn PApp::Util::dumpval $challenge;#d# |
617 | |
643 | |
618 | my $as_black = $challenge->{user1}{name} eq $self->{conn}{name} ? 1 : 0;; |
644 | my $as_black = $info->{black}{name} eq $self->{conn}{name} ? 1 : 0;; |
619 | my $opponent = $as_black ? $challenge->{user2} : $challenge->{user1}; |
645 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
620 | |
646 | |
621 | my ($size, $time, $interval, $count); |
647 | my ($size, $time, $interval, $count); |
622 | |
648 | |
623 | if (!$self->{channel}) { |
649 | if (!$self->{channel}) { |
624 | $inlay->append_text ("\nNotes: "); |
650 | $inlay->append_text ("\nNotes: "); |
625 | $inlay->append_entry (\$channel->{notes}, 20, ""); |
651 | $inlay->append_entry (\$info->{notes}, 20, ""); |
626 | $inlay->append_text ("\nGlobal Offer: "); |
652 | $inlay->append_text ("\nGlobal Offer: "); |
627 | $inlay->append_optionmenu (\$challenge->{flags}, |
653 | $inlay->append_optionmenu (\$info->{flags}, |
628 | 0 => "No", |
654 | 0 => "No", |
629 | 2 => "Yes", |
655 | 2 => "Yes", |
630 | ); |
656 | ); |
631 | } else { |
657 | } else { |
632 | $inlay->append_text ("\nNotes: " . util::toxml $channel->{notes}); |
658 | $inlay->append_text ("\nNotes: " . util::toxml $info->{notes}); |
633 | } |
659 | } |
634 | |
660 | |
635 | $inlay->append_text ("\nType: "); |
661 | $inlay->append_text ("\nType: "); |
636 | $inlay->append_optionmenu ( |
662 | $inlay->append_optionmenu ( |
637 | \$challenge->{type}, |
663 | \$info->{gametype}, |
638 | GAMETYPE_DEMONSTRATION , "Demonstration", |
664 | GAMETYPE_DEMONSTRATION , "Demonstration", |
639 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P)", |
665 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P)", |
640 | GAMETYPE_TEACHING , "Teaching", |
666 | GAMETYPE_TEACHING , "Teaching", |
641 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P)", |
667 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P)", |
642 | GAMETYPE_SIMUL , "Simul (not yet!)", |
668 | GAMETYPE_SIMUL , "Simul (not yet!)", |
… | |
… | |
652 | $inlay->append_optionmenu ( |
678 | $inlay->append_optionmenu ( |
653 | \$as_black, |
679 | \$as_black, |
654 | 0 => "White", |
680 | 0 => "White", |
655 | 1 => "Black", |
681 | 1 => "Black", |
656 | sub { |
682 | sub { |
657 | if ($challenge->{$_[0] ? "user1" : "user2"}{name} ne $self->{conn}{name}) { |
683 | if ($info->{$_[0] ? "black" : "white"}{name} ne $self->{conn}{name}) { |
658 | ($challenge->{user1}, $challenge->{user2}) = ($challenge->{user2}, $challenge->{user1}); |
684 | ($info->{black}, $info->{white}) = ($info->{white}, $info->{black}); |
659 | } |
685 | } |
660 | } |
686 | } |
661 | ); |
687 | ); |
662 | } |
688 | } |
663 | |
689 | |
664 | $inlay->append_text ("\nRuleset: "); |
690 | $inlay->append_text ("\nRuleset: "); |
665 | $inlay->append_optionmenu ( |
691 | $inlay->append_optionmenu ( |
666 | \$challenge->{rules}{ruleset}, |
692 | \$info->{rules}{ruleset}, |
667 | RULESET_JAPANESE , "Japanese", |
693 | RULESET_JAPANESE , "Japanese", |
668 | RULESET_CHINESE , "Chinese", |
694 | RULESET_CHINESE , "Chinese", |
669 | RULESET_AGA , "AGA", |
695 | RULESET_AGA , "AGA", |
670 | RULESET_NEW_ZEALAND, "New Zealand", |
696 | RULESET_NEW_ZEALAND, "New Zealand", |
671 | ); |
697 | ); |
672 | |
698 | |
673 | $inlay->append_text ("\nSize: "); |
699 | $inlay->append_text ("\nSize: "); |
674 | $size = $inlay->append_optionmenu ( |
700 | $size = $inlay->append_optionmenu ( |
675 | \$challenge->{rules}{size}, 9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38 |
701 | \$info->{rules}{size}, 9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38 |
676 | ); |
702 | ); |
677 | |
703 | |
678 | if ($self->{channel}) { |
704 | if ($self->{channel}) { |
679 | $inlay->append_text ("\nHandicap: "); |
705 | $inlay->append_text ("\nHandicap: "); |
680 | $inlay->append_optionmenu (\$challenge->{rules}{handicap}, map +($_, $_), 0..9); |
706 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
681 | |
707 | |
682 | $inlay->append_text ("\nKomi: "); |
708 | $inlay->append_text ("\nKomi: "); |
683 | $inlay->append_entry (\$challenge->{rules}{komi}, 5); |
709 | $inlay->append_entry (\$info->{rules}{komi}, 5); |
684 | } |
710 | } |
685 | |
711 | |
686 | $inlay->append_text ("\nTimesys: "); |
712 | $inlay->append_text ("\nTimesys: "); |
687 | $inlay->append_optionmenu ( |
713 | $inlay->append_optionmenu ( |
688 | \$challenge->{rules}{timesys}, |
714 | \$info->{rules}{timesys}, |
689 | &TIMESYS_NONE => "None", |
715 | &TIMESYS_NONE => "None", |
690 | &TIMESYS_ABSOLUTE => "Absolute", |
716 | &TIMESYS_ABSOLUTE => "Absolute", |
691 | &TIMESYS_BYO_YOMI => "Byo Yomi", |
717 | &TIMESYS_BYO_YOMI => "Byo Yomi", |
692 | &TIMESYS_CANADIAN => "Canadian", |
718 | &TIMESYS_CANADIAN => "Canadian", |
693 | sub { |
719 | sub { |
… | |
… | |
717 | } |
743 | } |
718 | } |
744 | } |
719 | ); |
745 | ); |
720 | |
746 | |
721 | $inlay->append_text ("\nMain Time: "); |
747 | $inlay->append_text ("\nMain Time: "); |
722 | $time = $inlay->append_entry (\$challenge->{rules}{time}, 5); |
748 | $time = $inlay->append_entry (\$info->{rules}{time}, 5); |
723 | $inlay->append_text ("\nInterval: "); |
749 | $inlay->append_text ("\nInterval: "); |
724 | $interval = $inlay->append_entry (\$challenge->{rules}{interval}, 3); |
750 | $interval = $inlay->append_entry (\$info->{rules}{interval}, 3); |
725 | $inlay->append_text ("\nPeriods/Stones: "); |
751 | $inlay->append_text ("\nPeriods/Stones: "); |
726 | $count = $inlay->append_entry (\$challenge->{rules}{count}, 2); |
752 | $count = $inlay->append_entry (\$info->{rules}{count}, 2); |
727 | |
753 | |
728 | $inlay->append_text ("\n"); |
754 | $inlay->append_text ("\n"); |
729 | |
755 | |
730 | if (!$self->{channel}) { |
756 | if (!$self->{channel}) { |
731 | $inlay->append_button ("Create Challenge", sub { |
757 | $inlay->append_button ("Create Challenge", sub { |
732 | $inlay->clear; |
758 | $inlay->clear; |
733 | $self->{cid} = $self->{conn}->alloc_clientid; |
759 | $self->{cid} = $self->{conn}->alloc_clientid; |
734 | $self->send (new_game => |
760 | $self->send (new_game => |
735 | channel => delete $self->{roomid}, |
761 | channel => delete $self->{roomid}, |
|
|
762 | gametype => $info->{gametype}, |
736 | cid => $self->{cid}, |
763 | cid => $self->{cid}, |
737 | type => $challenge->{type}, |
|
|
738 | flags => $challenge->{flags}, |
764 | flags => $info->{flags}, |
739 | rules => $challenge->{rules}, |
765 | rules => $info->{rules}, |
740 | notes => $challenge->{notes}, |
766 | notes => $info->{notes}, |
741 | ); |
767 | ); |
742 | }); |
768 | }); |
743 | } else { |
769 | } else { |
744 | $inlay->append_button ("OK", sub { |
770 | $inlay->append_button ("OK", sub { |
745 | $inlay->clear; |
771 | $inlay->clear; |
746 | $self->send (challenge => |
772 | $self->send (challenge => |
747 | channel => $self->{channel}, |
773 | channel => $self->{channel}, |
748 | challenge => $challenge, |
774 | black => $info->{black}, |
|
|
775 | white => $info->{white}, |
|
|
776 | gametype => $info->{gametype}, |
|
|
777 | cid => $info->{cid}, |
|
|
778 | rules => $info->{rules}, |
749 | ); |
779 | ); |
750 | }); |
780 | }); |
751 | if (exists $self->{challenge}{""}) { |
781 | if (exists $self->{challenge}{""}) { |
752 | $inlay->append_button ("Reject", sub { |
782 | $inlay->append_button ("Reject", sub { |
753 | $inlay->clear; |
783 | $inlay->clear; |
754 | $self->send (reject_challenge => |
784 | $self->send (reject_challenge => |
755 | channel => $self->{channel}, |
785 | channel => $self->{channel}, |
756 | name => $opponent->{name}, |
786 | name => $opponent->{name}, |
|
|
787 | gametype => $info->{gametype}, |
|
|
788 | cid => $info->{cid}, |
|
|
789 | rules => $info->{rules}, |
757 | ); |
790 | ); |
758 | }); |
791 | }); |
759 | } |
792 | } |
760 | } |
793 | } |
761 | } |
794 | } |
… | |
… | |
767 | $inlay->append_text (" <user>" . $self->{users}{$_}->as_string . "</user>"); |
800 | $inlay->append_text (" <user>" . $self->{users}{$_}->as_string . "</user>"); |
768 | } |
801 | } |
769 | } |
802 | } |
770 | |
803 | |
771 | sub event_challenge { |
804 | sub event_challenge { |
772 | my ($self, $challenge) = @_; |
805 | my ($self, $info) = @_; |
773 | |
806 | |
774 | my $as_black = $challenge->{user1}{name} eq $self->{conn}{name}; |
807 | my $as_black = $info->{black}->{name} eq $self->{conn}{name}; |
775 | my $opponent = $as_black ? $challenge->{user2} : $challenge->{user1}; |
808 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
776 | |
809 | |
777 | my $id = $opponent->{name}; |
810 | my $id = $opponent->{name}; |
778 | |
811 | |
|
|
812 | warn "challenge from $opponent->{name}\n";#d# |
|
|
813 | |
779 | $self->{challenge}{$id} = $challenge; |
814 | $self->{challenge}{$id} = $info; |
780 | $self->{chat}->new_switchable_inlay ( |
815 | $self->{challenge}{$id}{inlay} = $self->{chat}->new_switchable_inlay ( |
781 | exists $self->{challenge}{""} ? "Challenge from $opponent->{name}" : "Challenge to $opponent->{name}", |
816 | exists $self->{challenge}{""} |
|
|
817 | ? "Challenge from $opponent->{name}" |
|
|
818 | : "Challenge to $opponent->{name}", |
782 | sub { |
819 | sub { |
783 | $self->{challenge}{$id}{inlay} = $_[0]; |
820 | $self->{challenge}{$id}{inlay} = $_[0]; |
784 | $self->draw_challenge ($id); |
821 | $self->draw_challenge ($id); |
785 | }, |
822 | }, |
786 | !exists $self->{challenge}{""} # only open when not offerer |
823 | 1 || !exists $self->{challenge}{""} # only open when not offerer |
787 | ); |
824 | ); |
788 | } |
825 | } |
789 | |
826 | |
790 | 1; |
827 | 1; |
791 | |
828 | |