… | |
… | |
21 | |
21 | |
22 | $self->{set} = sub { }; |
22 | $self->{set} = sub { }; |
23 | $self->{format} = sub { "???" }; |
23 | $self->{format} = sub { "???" }; |
24 | } |
24 | } |
25 | |
25 | |
|
|
26 | sub FINALIZE_INSTANCE { |
|
|
27 | my $self = shift; |
|
|
28 | |
|
|
29 | $self->stop; |
|
|
30 | } |
|
|
31 | |
26 | sub configure { |
32 | sub configure { |
27 | my ($self, $timesys, $main, $interval, $count) = @_; |
33 | my ($self, $timesys, $main, $interval, $count) = @_; |
28 | |
34 | |
29 | if ($timesys == TIMESYS_ABSOLUTE) { |
35 | if ($timesys == TIMESYS_ABSOLUTE) { |
30 | $self->{set} = sub { $self->{time} = $_[0] }; |
36 | $self->{format} = sub { |
31 | $self->{format} = sub { util::format_time $_[0] }; |
37 | if ($_[0] <= 0) { |
|
|
38 | "TIMEOUT"; |
|
|
39 | } else { |
|
|
40 | util::format_time $_[0]; |
|
|
41 | } |
|
|
42 | }; |
32 | |
43 | |
33 | } elsif ($timesys == TIMESYS_BYO_YOMI) { |
44 | } elsif ($timesys == TIMESYS_BYO_YOMI) { |
34 | my $low = $interval * $count; |
45 | my $low = $interval * $count; |
35 | |
46 | |
36 | $self->{set} = sub { $self->{time} = $_[0] }; |
|
|
37 | |
|
|
38 | $self->{format} = sub { |
47 | $self->{format} = sub { |
|
|
48 | if ($_[0] <= 0) { |
|
|
49 | "TIMEOUT"; |
39 | if ($_[0] > $low) { |
50 | } elsif ($_[0] > $low) { |
40 | util::format_time $_[0] - $low; |
51 | util::format_time $_[0] - $low; |
41 | } else { |
52 | } else { |
42 | sprintf "%s (%d)", |
53 | sprintf "%s (%d)", |
43 | util::format_time int (($_[0] - 1) % $interval + 1), |
54 | util::format_time int (($_[0] - 1) % $interval + 1), |
44 | ($_[0] - 1) / $interval; |
55 | ($_[0] - 1) / $interval; |
45 | } |
56 | } |
46 | }; |
57 | }; |
47 | |
58 | |
48 | } elsif ($timesys == TIMESYS_CANADIAN) { |
59 | } elsif ($timesys == TIMESYS_CANADIAN) { |
49 | $self->{set} = sub { $self->{time} = $_[0]; $self->{moves} = $_[1] }; |
|
|
50 | |
|
|
51 | $self->{format} = sub { |
60 | $self->{format} = sub { |
|
|
61 | if ($_[0] <= 0) { |
|
|
62 | "TIMEOUT"; |
52 | if (!$self->{moves}) { |
63 | } elsif (!$self->{moves}) { |
53 | util::format_time $_[0] - $low; |
64 | util::format_time $_[0] - $low; |
54 | } else { |
65 | } else { |
55 | my $time = int (($_[0] - 1) % $interval + 1); |
66 | my $time = int (($_[0] - 1) % $interval + 1); |
56 | |
67 | |
57 | sprintf "%s/%d =%d", |
68 | sprintf "%s/%d =%d", |
… | |
… | |
63 | } |
74 | } |
64 | }; |
75 | }; |
65 | |
76 | |
66 | } else { |
77 | } else { |
67 | # none, or unknown |
78 | # none, or unknown |
68 | $self->{set} = sub { }; |
|
|
69 | $self->{format} = sub { "---" } |
79 | $self->{format} = sub { "-" } |
70 | } |
80 | } |
71 | } |
81 | } |
72 | |
82 | |
73 | sub refresh { |
83 | sub refresh { |
74 | my ($self, $timestamp) = @_; |
84 | my ($self, $timestamp) = @_; |
… | |
… | |
76 | |
86 | |
77 | # we round the timer value slightly... the protocol isn't exact anyways, |
87 | # we round the timer value slightly... the protocol isn't exact anyways, |
78 | # and this gives smoother timers ;) |
88 | # and this gives smoother timers ;) |
79 | my $timer2 = int $timer + 0.4; |
89 | my $timer2 = int $timer + 0.4; |
80 | |
90 | |
81 | if ($timer2 <= 0) { |
91 | $self->set_text ($self->{format}->($timer2)); |
82 | $timer2 = 0 if $timer2 < 0; |
92 | |
83 | $self->set_text ("TIME OUT"); |
93 | $timer - int $timer; |
|
|
94 | } |
|
|
95 | |
|
|
96 | sub set_time { |
|
|
97 | my ($self, $start, $time, $moves) = @_; |
|
|
98 | |
|
|
99 | $self->{time} = $time; |
|
|
100 | $self->{moves} = $moves; |
|
|
101 | |
|
|
102 | if ($start) { |
|
|
103 | $self->{start} = $start; |
|
|
104 | $self->start; |
84 | } else { |
105 | } else { |
85 | $self->set_text ($self->{format}->($timer2)); |
106 | $self->stop; |
86 | } |
|
|
87 | |
|
|
88 | $timer - int $timer; |
|
|
89 | } |
|
|
90 | |
|
|
91 | sub set_time { |
|
|
92 | my ($self, $time, $moves) = @_; |
|
|
93 | |
|
|
94 | # we ignore requests to re-set the time of a running clock. |
|
|
95 | # this is the easiest way to ensure that commentary etc. |
|
|
96 | # doesn't re-set the clock. yes, this is frickle design, |
|
|
97 | # but I think the protocol is to blame here, which gives |
|
|
98 | # very little time information. (cgoban2 also has had quite |
|
|
99 | # a lot of small time update problems...) |
|
|
100 | unless ($self->{timeout}) { |
|
|
101 | $self->{set}->($time, $moves); |
|
|
102 | $self->refresh ($self->{start}); |
107 | $self->refresh ($self->{start}); |
103 | } |
108 | } |
104 | } |
109 | } |
105 | |
110 | |
106 | sub start { |
111 | sub start { |
107 | my ($self, $when) = @_; |
112 | my ($self) = @_; |
108 | |
113 | |
109 | $self->stop; |
114 | $self->stop; |
110 | |
|
|
111 | $self->{start} = $when; |
|
|
112 | |
115 | |
113 | my $timeout; $timeout = sub { |
116 | my $timeout; $timeout = sub { |
114 | my $next = $self->refresh (Time::HiRes::time) * 1000; |
117 | my $next = $self->refresh (Time::HiRes::time) * 1000; |
115 | $next += 1000 if $next < 0; |
118 | $next += 1000 if $next < 0; |
116 | $self->{timeout} = add Glib::Timeout $next, $timeout; |
119 | $self->{timeout} = add Glib::Timeout $next, $timeout; |
… | |
… | |
180 | |
183 | |
181 | $self->{info}->set_text ("$captures pris."); |
184 | $self->{info}->set_text ("$captures pris."); |
182 | } |
185 | } |
183 | |
186 | |
184 | sub set_timer { |
187 | sub set_timer { |
185 | my ($self, $when, $time, $moves) = @_; |
188 | my ($self, $start, $time, $moves) = @_; |
186 | |
189 | |
187 | $self->{clock}->stop unless $when; |
|
|
188 | $self->{clock}->set_time ($time, $moves); |
190 | $self->{clock}->set_time ($start, $time, $moves); |
189 | $self->{clock}->start ($when) if $when; |
|
|
190 | } |
191 | } |
191 | |
192 | |
192 | package game; |
193 | package game; |
193 | |
194 | |
194 | use Scalar::Util qw(weaken); |
195 | use Scalar::Util qw(weaken); |
… | |
… | |
356 | |
357 | |
357 | delete $self->{board_click}; |
358 | delete $self->{board_click}; |
358 | |
359 | |
359 | if ($self->{teacher} eq $self->{app}{conn}) { |
360 | if ($self->{teacher} eq $self->{app}{conn}) { |
360 | #TODO# # teaching mode not implemented |
361 | #TODO# # teaching mode not implemented |
361 | $self->{button_pass}->set (label => "Pass", sensitive => 1, visible => 1); |
362 | $self->{button_pass}->set (label => "Pass", visible => 1, sensitive => 1); |
362 | $self->{button_undo}->hide; |
363 | $self->{button_undo}->hide; |
363 | $self->{button_resign}->hide; |
364 | $self->{button_resign}->hide; |
364 | $self->{board}->set (cursor => undef); |
365 | $self->{board}->set (cursor => undef); |
365 | |
366 | |
366 | } elsif ($running && $self->{colour} != COLOUR_NONE) { |
367 | } elsif ($running && $self->{colour} != COLOUR_NONE) { |
… | |
… | |
368 | $self->{button_undo}->show; |
369 | $self->{button_undo}->show; |
369 | $self->{button_resign}->show; |
370 | $self->{button_resign}->show; |
370 | |
371 | |
371 | if ($self->{cur_board}{score}) { |
372 | if ($self->{cur_board}{score}) { |
372 | # during scoring |
373 | # during scoring |
373 | $self->{button_pass}->set (label => "Done", sensitive => 1, visible => 1); |
374 | $self->{button_pass}->set (label => "Done", visible => 1, sensitive => 1); |
374 | $self->{board}->set (cursor => sub { |
375 | $self->{board}->set (cursor => sub { |
375 | $_[0] & (MARK_B | MARK_W) |
376 | $_[0] & (MARK_B | MARK_W) |
376 | ? $_[0] ^ MARK_GRAYED |
377 | ? $_[0] ^ MARK_GRAYED |
377 | : $_[0]; |
378 | : $_[0]; |
378 | }); |
379 | }); |
… | |
… | |
388 | dead => !($self->{cur_board}{board}[$_[0]][$_[1]] & MARK_GRAYED), |
389 | dead => !($self->{cur_board}{board}[$_[0]][$_[1]] & MARK_GRAYED), |
389 | ); |
390 | ); |
390 | } |
391 | } |
391 | }; |
392 | }; |
392 | |
393 | |
393 | } elsif (1 - $self->{colour} == $self->{cur_board}{last}) { |
394 | } elsif ($self->{colour} == $self->{whosemove}) { |
394 | # normal move |
395 | # normal move |
395 | $self->{button_pass}->set (label => "Pass", sensitive => 1, visible => 1); |
396 | $self->{button_pass}->set (label => "Pass", visible => 1, sensitive => 1); |
396 | $self->{board}->set (cursor => sub { |
397 | $self->{board}->set (cursor => sub { |
397 | # if is_valid_move oder so#TODO# |
398 | # if is_valid_move oder so#TODO# |
398 | $_[0] & (MARK_B | MARK_W) |
399 | $_[0] & (MARK_B | MARK_W) |
399 | ? $_[0] |
400 | ? $_[0] |
400 | : $_[0] | MARK_GRAYED | ($self->{colour} == COLOUR_WHITE ? MARK_W : MARK_B); |
401 | : $_[0] | MARK_GRAYED | ($self->{colour} == COLOUR_WHITE ? MARK_W : MARK_B); |
… | |
… | |
405 | delete $self->{board_click}; |
406 | delete $self->{board_click}; |
406 | $self->{button_pass}->sensitive (0); |
407 | $self->{button_pass}->sensitive (0); |
407 | }; |
408 | }; |
408 | } else { |
409 | } else { |
409 | $self->{button_pass}->set (label => "Pass", sensitive => 0, visible => 1); |
410 | $self->{button_pass}->set (label => "Pass", sensitive => 0, visible => 1); |
|
|
411 | $self->{board}->set (cursor => undef); |
410 | } |
412 | } |
411 | } else { |
413 | } else { |
412 | $self->{button_undo}->hide; |
414 | $self->{button_undo}->hide; |
413 | $self->{button_resign}->hide; |
415 | $self->{button_resign}->hide; |
414 | $self->{button_pass}->hide; |
416 | $self->{button_pass}->hide; |
… | |
… | |
423 | my $running = $self->{showmove} == @{$self->{path}} && !$self->{teacher}; |
425 | my $running = $self->{showmove} == @{$self->{path}} && !$self->{teacher}; |
424 | |
426 | |
425 | for my $colour (COLOUR_BLACK, COLOUR_WHITE) { |
427 | for my $colour (COLOUR_BLACK, COLOUR_WHITE) { |
426 | my $t = $timers->[$colour]; |
428 | my $t = $timers->[$colour]; |
427 | $self->{userpanel}[$colour]->set_timer ( |
429 | $self->{userpanel}[$colour]->set_timer ( |
428 | $running && $self->{lastmove_colour} == 1 - $colour && $t->[0], |
430 | $running && $colour == $self->{whosemove} && $t->[0], |
429 | $t->[1], $t->[2]); |
431 | $t->[1] || $self->{rules}{time} |
|
|
432 | + ($self->{rules}{timesys} == TIMESYS_BYO_YOMI |
|
|
433 | && $self->{rules}{interval} * $self->{rules}{count}), |
|
|
434 | $t->[2] || $self->{rules}{count}); |
430 | } |
435 | } |
431 | } |
436 | } |
432 | |
437 | |
433 | sub update_board { |
438 | sub update_board { |
434 | my ($self) = @_; |
439 | my ($self) = @_; |
… | |
… | |
439 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
444 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
440 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
445 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
441 | |
446 | |
442 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
447 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
443 | for COLOUR_WHITE, COLOUR_BLACK; |
448 | for COLOUR_WHITE, COLOUR_BLACK; |
|
|
449 | |
|
|
450 | if ($self->{rules}{ruleset} == RULESET_JAPANESE) { |
|
|
451 | if ($self->{curnode}{move} == 0) { |
|
|
452 | $self->{whosemove} = $self->{handicap} ? COLOUR_WHITE : COLOUR_BLACK; |
|
|
453 | } else { |
|
|
454 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
|
|
455 | } |
|
|
456 | } else { |
|
|
457 | # Chinese, Aga, NZ all have manual placement |
|
|
458 | if ($self->{curnode}{move} < $self->{handicap}) { |
|
|
459 | $self->{whosemove} = COLOUR_BLACK; |
|
|
460 | } elsif ($self->{curnode}{move} == $self->{handicap}) { |
|
|
461 | $self->{whosemove} = $self->{handicap} ? COLOUR_WHITE : COLOUR_BLACK; |
|
|
462 | } else { |
|
|
463 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
|
|
464 | } |
|
|
465 | } |
|
|
466 | |
|
|
467 | my $start_time = $self->{rules}{time}; |
444 | |
468 | |
445 | if ($self->{showmove} == @{$self->{path}}) { |
469 | if ($self->{showmove} == @{$self->{path}}) { |
446 | $self->{timers} = [ |
470 | $self->{timers} = [ |
447 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[0]}], |
471 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[0]}], |
448 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[1]}], |
472 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[1]}], |
… | |
… | |
455 | ]); |
479 | ]); |
456 | } |
480 | } |
457 | |
481 | |
458 | $self->{board}->set_board ($self->{cur_board}); |
482 | $self->{board}->set_board ($self->{cur_board}); |
459 | |
483 | |
|
|
484 | if ($self->{cur_board}{score}) { |
|
|
485 | $self->{score_inlay} ||= $self->{chat}->new_inlay; |
|
|
486 | $self->{score_inlay}->clear; |
|
|
487 | $self->{score_inlay}->append_text ("\n<header>Scoring</header>" |
|
|
488 | . "\n<score>" |
|
|
489 | . "White: $self->{cur_board}{score}[COLOUR_WHITE], " |
|
|
490 | . "Black: $self->{cur_board}{score}[COLOUR_BLACK]" |
|
|
491 | . "</score>"); |
|
|
492 | } elsif ($self->{score_inlay}) { |
|
|
493 | (delete $self->{score_inlay})->clear; |
|
|
494 | } |
|
|
495 | |
460 | $self->update_cursor; |
496 | $self->update_cursor; |
461 | } |
497 | } |
462 | |
498 | |
463 | sub event_update_tree { |
499 | sub event_update_tree { |
464 | my ($self) = @_; |
500 | my ($self) = @_; |
|
|
501 | |
|
|
502 | (delete $self->{undo_inlay})->clear |
|
|
503 | if $self->{undo_inlay}; |
465 | |
504 | |
466 | $self->{path} = $self->get_path; |
505 | $self->{path} = $self->get_path; |
467 | |
506 | |
468 | if ($self->{moveadj}) { |
507 | if ($self->{moveadj}) { |
469 | my $upper = $self->{moveadj}->upper; |
508 | my $upper = $self->{moveadj}->upper; |
… | |
… | |
532 | $self->destroy; |
571 | $self->destroy; |
533 | } |
572 | } |
534 | |
573 | |
535 | sub event_move { |
574 | sub event_move { |
536 | my ($self, $pass) = @_; |
575 | my ($self, $pass) = @_; |
|
|
576 | |
537 | sound::play 1, $pass ? "pass" : "move"; |
577 | sound::play 1, $pass ? "pass" : "move"; |
538 | |
|
|
539 | if ($self->{undo_inlay}) { |
|
|
540 | (delete $self->{undo_inlay})->clear; |
|
|
541 | } |
|
|
542 | } |
578 | } |
543 | |
579 | |
544 | sub event_update_game { |
580 | sub event_update_game { |
545 | my ($self) = @_; |
581 | my ($self) = @_; |
546 | |
582 | |
… | |
… | |
650 | $self->{userpanel}[$_]->configure ($self->{app}, $self->{user}[$_], $rules) |
686 | $self->{userpanel}[$_]->configure ($self->{app}, $self->{user}[$_], $rules) |
651 | for COLOUR_BLACK, COLOUR_WHITE; |
687 | for COLOUR_BLACK, COLOUR_WHITE; |
652 | } |
688 | } |
653 | |
689 | |
654 | sound::play 3, "gamestart"; |
690 | sound::play 3, "gamestart"; |
655 | |
|
|
656 | $self->{rules_inlay}->refresh; |
691 | $self->{rules_inlay}->refresh; |
657 | } |
692 | } |
658 | |
693 | |
659 | sub event_resign_game { |
694 | sub event_resign_game { |
660 | my ($self, $player) = @_; |
695 | my ($self, $player) = @_; |
… | |
… | |
678 | |
713 | |
679 | sub event_done { |
714 | sub event_done { |
680 | my ($self) = @_; |
715 | my ($self) = @_; |
681 | |
716 | |
682 | if ($self->{done}[1 - $self->{colour}] && !$self->{done}[$self->{colour}]) { |
717 | if ($self->{done}[1 - $self->{colour}] && !$self->{done}[$self->{colour}]) { |
|
|
718 | sound::play 2, "info" unless $inlay->{count}; |
683 | $self->{chat}->append_text ("\n<infoblock><header>Done</header>" |
719 | $self->{chat}->append_text ("\n<infoblock><header>Press Done</header>" |
684 | . "\nYour opponent pressed done."); |
720 | . "\nYour opponent pressed done. Now it's up to you."); |
685 | } |
721 | } |
|
|
722 | if ($self->{doneid} & 0x80000000) { |
|
|
723 | sound::play 2, "info" unless $inlay->{count}; |
|
|
724 | $self->{chat}->append_text ("\n<infoblock><header>Press Done Again</header>" |
|
|
725 | . "\nThe board has changed."); |
|
|
726 | } |
|
|
727 | |
|
|
728 | $self->{button_pass}->sensitive (!$self->{done}[$self->{colour}]); |
|
|
729 | |
|
|
730 | $self->{chat}->set_end; |
686 | } |
731 | } |
687 | |
732 | |
688 | sub inject_final_result { |
733 | sub inject_final_result { |
689 | my ($self, $msg) = @_; |
734 | my ($self, $msg) = @_; |
690 | |
735 | |
… | |
… | |
701 | $self->{timers} = [ |
746 | $self->{timers} = [ |
702 | [$msg->{NOW}, $msg->{black_time}, $msg->{black_moves}], |
747 | [$msg->{NOW}, $msg->{black_time}, $msg->{black_moves}], |
703 | [$msg->{NOW}, $msg->{white_time}, $msg->{white_moves}], |
748 | [$msg->{NOW}, $msg->{white_time}, $msg->{white_moves}], |
704 | ]; |
749 | ]; |
705 | |
750 | |
706 | print "SGT\n";#d# |
|
|
707 | $self->update_timers ($self->{timers}) |
751 | $self->update_timers ($self->{timers}) |
708 | if $self->{showmove} == @{$self->{path}}; |
752 | if $self->{showmove} == @{$self->{path}}; |
709 | } |
753 | } |
710 | |
754 | |
711 | sub inject_req_undo { |
755 | sub inject_req_undo { |
712 | my ($self, $msg) = @_; |
756 | my ($self, $msg) = @_; |
713 | |
757 | |
714 | my $inlay = $self->{undo_inlay} ||= $self->{chat}->new_inlay; |
758 | my $inlay = $self->{undo_inlay} ||= $self->{chat}->new_inlay; |
715 | return if $inlay->{ignore}; |
759 | return if $inlay->{ignore}; |
716 | |
760 | |
717 | sound::play 3, "warning" unless $inlay->{count}; |
761 | sound::play 2, "warning" unless $inlay->{count}; |
718 | $inlay->{count}++; |
762 | $inlay->{count}++; |
719 | |
763 | |
720 | $inlay->clear; |
764 | $inlay->clear; |
721 | $inlay->append_text ("\n<undo>Undo requested ($inlay->{count} times)</undo>\n"); |
765 | $inlay->append_text ("\n<undo>Undo requested ($inlay->{count} times)</undo>\n"); |
722 | $inlay->append_button ("Grant", sub { |
766 | $inlay->append_button ("Grant", sub { |
723 | $inlay->clear; |
767 | (delete $self->{undo_inlay})->clear; |
724 | $self->send (grant_undo => channel => $self->{channel}); |
768 | $self->send (grant_undo => channel => $self->{channel}); |
725 | }); |
769 | }); |
726 | $inlay->append_button ("Ignore", sub { |
770 | $inlay->append_button ("Ignore", sub { |
727 | $inlay->clear; |
771 | $inlay->clear; |
728 | $inlay->{ignore} = 1; |
772 | $inlay->{ignore} = 1; |
… | |
… | |
733 | } |
777 | } |
734 | |
778 | |
735 | sub inject_new_game { |
779 | sub inject_new_game { |
736 | my ($self, $msg) = @_; |
780 | my ($self, $msg) = @_; |
737 | |
781 | |
738 | $self->{chat}->append_text ("\n<header>ACK from server ($msg->{cid} == $self->{cid})</header>"); |
782 | if ($msg->{cid} != $self->{cid}) { |
|
|
783 | $self->part; |
|
|
784 | warn "ERROR: challenge id mismatch, PLEASE REPORT, especially the circumstances (many games open? etc..)\n";#d# |
|
|
785 | } |
|
|
786 | |
|
|
787 | $self->{chat}->append_text ("\n<header>Game successfully created on server.</header>"); |
739 | delete $self->{cid}; |
788 | delete $self->{cid}; |
740 | } |
789 | } |
741 | |
790 | |
742 | sub draw_challenge { |
791 | sub draw_challenge { |
743 | my ($self, $id) = @_; |
792 | my ($self, $id) = @_; |
… | |
… | |
747 | my $rules = $info->{rules}; |
796 | my $rules = $info->{rules}; |
748 | |
797 | |
749 | my $as_black = $info->{black}{name} eq $self->{conn}{name} ? 1 : 0;; |
798 | my $as_black = $info->{black}{name} eq $self->{conn}{name} ? 1 : 0;; |
750 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
799 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
751 | |
800 | |
752 | my ($size, $time, $interval, $count); |
801 | my ($size, $time, $interval, $count, $type); |
753 | |
802 | |
754 | if (!$self->{channel}) { |
803 | if (!$self->{channel}) { |
755 | $inlay->append_text ("\nNotes: "); |
804 | $inlay->append_text ("\nNotes: "); |
756 | $inlay->append_entry (\$info->{notes}, 20, ""); |
805 | $inlay->append_entry (\$info->{notes}, 20, ""); |
757 | $inlay->append_text ("\nGlobal Offer: "); |
806 | $inlay->append_text ("\nGlobal Offer: "); |
… | |
… | |
762 | } else { |
811 | } else { |
763 | $inlay->append_text ("\nNotes: " . util::toxml $info->{notes}); |
812 | $inlay->append_text ("\nNotes: " . util::toxml $info->{notes}); |
764 | } |
813 | } |
765 | |
814 | |
766 | $inlay->append_text ("\nType: "); |
815 | $inlay->append_text ("\nType: "); |
767 | $inlay->append_optionmenu ( |
816 | $type = $inlay->append_optionmenu ( |
768 | \$info->{gametype}, |
817 | \$info->{gametype}, |
769 | GAMETYPE_DEMONSTRATION , "Demonstration", |
818 | GAMETYPE_DEMONSTRATION , "Demonstration (not yet)", |
770 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P)", |
819 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P) (not yet)", |
771 | GAMETYPE_TEACHING , "Teaching", |
820 | GAMETYPE_TEACHING , "Teaching (not yet)", |
772 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P)", |
821 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P) (not yet)", |
773 | GAMETYPE_SIMUL , "Simul (not yet!)", |
822 | GAMETYPE_SIMUL , "Simul (not yet!)", |
774 | GAMETYPE_FREE , "Free", |
823 | GAMETYPE_FREE , "Free", |
775 | GAMETYPE_RATED , "Rated", |
824 | GAMETYPE_RATED , "Rated", |
776 | sub { |
825 | sub { |
777 | $size->set_history (2) if $_[0] eq GAMETYPE_RATED; |
826 | $size->set_history (2) if $_[0] eq GAMETYPE_RATED; |
… | |
… | |
801 | RULESET_NEW_ZEALAND, "New Zealand", |
850 | RULESET_NEW_ZEALAND, "New Zealand", |
802 | ); |
851 | ); |
803 | |
852 | |
804 | $inlay->append_text ("\nSize: "); |
853 | $inlay->append_text ("\nSize: "); |
805 | $size = $inlay->append_optionmenu ( |
854 | $size = $inlay->append_optionmenu ( |
|
|
855 | \$info->{rules}{size}, |
806 | \$info->{rules}{size}, 9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38 |
856 | (9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38), |
|
|
857 | sub { |
|
|
858 | $type->set_history (5) # reset to free |
|
|
859 | if $_[0] != 19 && $info->{gametype} == GAMETYPE_RATED; |
|
|
860 | }, |
807 | ); |
861 | ); |
808 | |
862 | |
809 | if ($self->{channel}) { |
863 | if ($self->{channel}) { |
810 | $inlay->append_text ("\nHandicap: "); |
864 | $inlay->append_text ("\nHandicap: "); |
811 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
865 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
… | |
… | |
912 | my $as_black = $info->{black}->{name} eq $self->{conn}{name}; |
966 | my $as_black = $info->{black}->{name} eq $self->{conn}{name}; |
913 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
967 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
914 | |
968 | |
915 | my $id = $opponent->{name}; |
969 | my $id = $opponent->{name}; |
916 | |
970 | |
|
|
971 | sound::play 2, "info"; |
|
|
972 | |
917 | $self->{challenge}{$id} = $info; |
973 | $self->{challenge}{$id} = $info; |
918 | $self->{challenge}{$id}{inlay} = $self->{chat}->new_switchable_inlay ( |
974 | $self->{challenge}{$id}{inlay} = $self->{chat}->new_switchable_inlay ( |
919 | exists $self->{challenge}{""} |
975 | exists $self->{challenge}{""} |
920 | ? "Challenge from $opponent->{name}" |
976 | ? "Challenge from " . $opponent->as_string |
921 | : "Challenge to $opponent->{name}", |
977 | : "Challenge to " . $opponent->as_string, |
922 | sub { |
978 | sub { |
923 | $self->{challenge}{$id}{inlay} = $_[0]; |
979 | $self->{challenge}{$id}{inlay} = $_[0]; |
924 | $self->draw_challenge ($id); |
980 | $self->draw_challenge ($id); |
925 | }, |
981 | }, |
926 | !exists $self->{challenge}{""} # only open when not offerer |
982 | !exists $self->{challenge}{""} # only open when not offerer |