… | |
… | |
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 | }); |
379 | $self->{board_click} = sub { |
380 | $self->{board_click} = sub { |
380 | if ($_[0] == 255) { |
381 | if ($_[0] == 255) { |
381 | $self->{button_pass}->sensitive (0); |
382 | $self->{button_pass}->sensitive (0); |
|
|
383 | warn sprintf "SEND DONE @{$self->{done}} %x\n", $self->{doneid};#d# |
382 | $self->done; |
384 | $self->done; |
383 | } else { |
385 | } else { |
384 | $self->send (mark_dead => |
386 | $self->send (mark_dead => |
385 | channel => $self->{channel}, |
387 | channel => $self->{channel}, |
386 | x => $_[0], |
388 | x => $_[0], |
… | |
… | |
388 | dead => !($self->{cur_board}{board}[$_[0]][$_[1]] & MARK_GRAYED), |
390 | dead => !($self->{cur_board}{board}[$_[0]][$_[1]] & MARK_GRAYED), |
389 | ); |
391 | ); |
390 | } |
392 | } |
391 | }; |
393 | }; |
392 | |
394 | |
393 | } elsif (1 - $self->{colour} == $self->{cur_board}{last}) { |
395 | } elsif ($self->{colour} == $self->{whosemove}) { |
394 | # normal move |
396 | # normal move |
395 | $self->{button_pass}->set (label => "Pass", sensitive => 1, visible => 1); |
397 | $self->{button_pass}->set (label => "Pass", visible => 1, sensitive => 1); |
396 | $self->{board}->set (cursor => sub { |
398 | $self->{board}->set (cursor => sub { |
397 | # if is_valid_move oder so#TODO# |
399 | # if is_valid_move oder so#TODO# |
398 | $_[0] & (MARK_B | MARK_W) |
400 | $_[0] & (MARK_B | MARK_W) |
399 | ? $_[0] |
401 | ? $_[0] |
400 | : $_[0] | MARK_GRAYED | ($self->{colour} == COLOUR_WHITE ? MARK_W : MARK_B); |
402 | : $_[0] | MARK_GRAYED | ($self->{colour} == COLOUR_WHITE ? MARK_W : MARK_B); |
… | |
… | |
405 | delete $self->{board_click}; |
407 | delete $self->{board_click}; |
406 | $self->{button_pass}->sensitive (0); |
408 | $self->{button_pass}->sensitive (0); |
407 | }; |
409 | }; |
408 | } else { |
410 | } else { |
409 | $self->{button_pass}->set (label => "Pass", sensitive => 0, visible => 1); |
411 | $self->{button_pass}->set (label => "Pass", sensitive => 0, visible => 1); |
|
|
412 | $self->{board}->set (cursor => undef); |
410 | } |
413 | } |
411 | } else { |
414 | } else { |
412 | $self->{button_undo}->hide; |
415 | $self->{button_undo}->hide; |
413 | $self->{button_resign}->hide; |
416 | $self->{button_resign}->hide; |
414 | $self->{button_pass}->hide; |
417 | $self->{button_pass}->hide; |
… | |
… | |
423 | my $running = $self->{showmove} == @{$self->{path}} && !$self->{teacher}; |
426 | my $running = $self->{showmove} == @{$self->{path}} && !$self->{teacher}; |
424 | |
427 | |
425 | for my $colour (COLOUR_BLACK, COLOUR_WHITE) { |
428 | for my $colour (COLOUR_BLACK, COLOUR_WHITE) { |
426 | my $t = $timers->[$colour]; |
429 | my $t = $timers->[$colour]; |
427 | $self->{userpanel}[$colour]->set_timer ( |
430 | $self->{userpanel}[$colour]->set_timer ( |
428 | $running && $self->{lastmove_colour} == 1 - $colour && $t->[0], |
431 | $running && $colour == $self->{whosemove} && $t->[0], |
429 | $t->[1], $t->[2]); |
432 | $t->[1] || $self->{rules}{time} |
|
|
433 | + ($self->{rules}{timesys} == TIMESYS_BYO_YOMI |
|
|
434 | && $self->{rules}{interval} * $self->{rules}{count}), |
|
|
435 | $t->[2] || $self->{rules}{count}); |
430 | } |
436 | } |
431 | } |
437 | } |
432 | |
438 | |
433 | sub update_board { |
439 | sub update_board { |
434 | my ($self) = @_; |
440 | my ($self) = @_; |
… | |
… | |
439 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
445 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
440 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
446 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $self->{showmove} - 1]]); |
441 | |
447 | |
442 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
448 | $self->{userpanel}[$_]->set_captures ($self->{cur_board}{captures}[$_]) |
443 | for COLOUR_WHITE, COLOUR_BLACK; |
449 | for COLOUR_WHITE, COLOUR_BLACK; |
|
|
450 | |
|
|
451 | if ($self->{rules}{ruleset} == RULESET_JAPANESE) { |
|
|
452 | if ($self->{curnode}{move} == 0) { |
|
|
453 | $self->{whosemove} = $self->{handicap} ? COLOUR_WHITE : COLOUR_BLACK; |
|
|
454 | } else { |
|
|
455 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
|
|
456 | } |
|
|
457 | } else { |
|
|
458 | # Chinese, Aga, NZ all have manual placement |
|
|
459 | if ($self->{curnode}{move} < $self->{handicap}) { |
|
|
460 | $self->{whosemove} = COLOUR_BLACK; |
|
|
461 | } elsif ($self->{curnode}{move} == $self->{handicap}) { |
|
|
462 | $self->{whosemove} = COLOUR_WHITE; |
|
|
463 | } else { |
|
|
464 | $self->{whosemove} = 1 - $self->{cur_board}{last}; |
|
|
465 | } |
|
|
466 | } |
|
|
467 | |
|
|
468 | my $start_time = $self->{rules}{time}; |
444 | |
469 | |
445 | if ($self->{showmove} == @{$self->{path}}) { |
470 | if ($self->{showmove} == @{$self->{path}}) { |
446 | $self->{timers} = [ |
471 | $self->{timers} = [ |
447 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[0]}], |
472 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[0]}], |
448 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[1]}], |
473 | [$self->{lastmove_time}, @{$self->{cur_board}{timer}[1]}], |
… | |
… | |
455 | ]); |
480 | ]); |
456 | } |
481 | } |
457 | |
482 | |
458 | $self->{board}->set_board ($self->{cur_board}); |
483 | $self->{board}->set_board ($self->{cur_board}); |
459 | |
484 | |
|
|
485 | if ($self->{cur_board}{score}) { |
|
|
486 | $self->{score_inlay} ||= $self->{chat}->new_inlay; |
|
|
487 | $self->{score_inlay}->clear; |
|
|
488 | $self->{score_inlay}->append_text ("\n<header>Scoring</header>" |
|
|
489 | . "\n<score>" |
|
|
490 | . "White: $self->{cur_board}{score}[COLOUR_WHITE], " |
|
|
491 | . "Black: $self->{cur_board}{score}[COLOUR_BLACK]" |
|
|
492 | . "</score>"); |
|
|
493 | } elsif ($self->{score_inlay}) { |
|
|
494 | (delete $self->{score_inlay})->clear; |
|
|
495 | } |
|
|
496 | |
460 | $self->update_cursor; |
497 | $self->update_cursor; |
461 | } |
498 | } |
462 | |
499 | |
463 | sub event_update_tree { |
500 | sub event_update_tree { |
464 | my ($self) = @_; |
501 | my ($self) = @_; |
|
|
502 | |
|
|
503 | (delete $self->{undo_inlay})->clear |
|
|
504 | if $self->{undo_inlay}; |
465 | |
505 | |
466 | $self->{path} = $self->get_path; |
506 | $self->{path} = $self->get_path; |
467 | |
507 | |
468 | if ($self->{moveadj}) { |
508 | if ($self->{moveadj}) { |
469 | my $upper = $self->{moveadj}->upper; |
509 | my $upper = $self->{moveadj}->upper; |
… | |
… | |
532 | $self->destroy; |
572 | $self->destroy; |
533 | } |
573 | } |
534 | |
574 | |
535 | sub event_move { |
575 | sub event_move { |
536 | my ($self, $pass) = @_; |
576 | my ($self, $pass) = @_; |
|
|
577 | |
537 | sound::play 1, $pass ? "pass" : "move"; |
578 | sound::play 1, $pass ? "pass" : "move"; |
538 | |
|
|
539 | if ($self->{undo_inlay}) { |
|
|
540 | (delete $self->{undo_inlay})->clear; |
|
|
541 | } |
|
|
542 | } |
579 | } |
543 | |
580 | |
544 | sub event_update_game { |
581 | sub event_update_game { |
545 | my ($self) = @_; |
582 | my ($self) = @_; |
546 | |
583 | |
… | |
… | |
650 | $self->{userpanel}[$_]->configure ($self->{app}, $self->{user}[$_], $rules) |
687 | $self->{userpanel}[$_]->configure ($self->{app}, $self->{user}[$_], $rules) |
651 | for COLOUR_BLACK, COLOUR_WHITE; |
688 | for COLOUR_BLACK, COLOUR_WHITE; |
652 | } |
689 | } |
653 | |
690 | |
654 | sound::play 3, "gamestart"; |
691 | sound::play 3, "gamestart"; |
655 | |
|
|
656 | $self->{rules_inlay}->refresh; |
692 | $self->{rules_inlay}->refresh; |
657 | } |
693 | } |
658 | |
694 | |
659 | sub event_resign_game { |
695 | sub event_resign_game { |
660 | my ($self, $player) = @_; |
696 | my ($self, $player) = @_; |
… | |
… | |
677 | } |
713 | } |
678 | |
714 | |
679 | sub event_done { |
715 | sub event_done { |
680 | my ($self) = @_; |
716 | my ($self) = @_; |
681 | |
717 | |
|
|
718 | warn sprintf "EVENT DONE @{$self->{done}} %x\n", $self->{doneid};#d# |
|
|
719 | |
682 | if ($self->{done}[1 - $self->{colour}] && !$self->{done}[$self->{colour}]) { |
720 | if ($self->{done}[1 - $self->{colour}] && !$self->{done}[$self->{colour}]) { |
|
|
721 | sound::play 2, "ring" unless $inlay->{count}; |
683 | $self->{chat}->append_text ("\n<infoblock><header>Done</header>" |
722 | $self->{chat}->append_text ("\n<infoblock><header>Press Done</header>" |
684 | . "\nYour opponent pressed done."); |
723 | . "\nYour opponent pressed done. Now it's up to you."); |
685 | } |
724 | } |
|
|
725 | if ($self->{doneid} & 0x80000000) { |
|
|
726 | sound::play 2, "warning" unless $inlay->{count}; |
|
|
727 | $self->{chat}->append_text ("\n<infoblock><header>Press Done Again</header>" |
|
|
728 | . "\nYour opponent changed the board.."); |
|
|
729 | } |
|
|
730 | |
|
|
731 | $self->{button_pass}->sensitive (!$self->{done}[$self->{colour}]); |
|
|
732 | |
|
|
733 | $self->{chat}->set_end; |
686 | } |
734 | } |
687 | |
735 | |
688 | sub inject_final_result { |
736 | sub inject_final_result { |
689 | my ($self, $msg) = @_; |
737 | my ($self, $msg) = @_; |
690 | |
738 | |
… | |
… | |
701 | $self->{timers} = [ |
749 | $self->{timers} = [ |
702 | [$msg->{NOW}, $msg->{black_time}, $msg->{black_moves}], |
750 | [$msg->{NOW}, $msg->{black_time}, $msg->{black_moves}], |
703 | [$msg->{NOW}, $msg->{white_time}, $msg->{white_moves}], |
751 | [$msg->{NOW}, $msg->{white_time}, $msg->{white_moves}], |
704 | ]; |
752 | ]; |
705 | |
753 | |
706 | print "SGT\n";#d# |
|
|
707 | $self->update_timers ($self->{timers}) |
754 | $self->update_timers ($self->{timers}) |
708 | if $self->{showmove} == @{$self->{path}}; |
755 | if $self->{showmove} == @{$self->{path}}; |
709 | } |
756 | } |
710 | |
757 | |
711 | sub inject_req_undo { |
758 | sub inject_req_undo { |
712 | my ($self, $msg) = @_; |
759 | my ($self, $msg) = @_; |
713 | |
760 | |
714 | my $inlay = $self->{undo_inlay} ||= $self->{chat}->new_inlay; |
761 | my $inlay = $self->{undo_inlay} ||= $self->{chat}->new_inlay; |
715 | return if $inlay->{ignore}; |
762 | return if $inlay->{ignore}; |
716 | |
763 | |
717 | sound::play 3, "warning" unless $inlay->{count}; |
764 | sound::play 2, "warning" unless $inlay->{count}; |
718 | $inlay->{count}++; |
765 | $inlay->{count}++; |
719 | |
766 | |
720 | $inlay->clear; |
767 | $inlay->clear; |
721 | $inlay->append_text ("\n<undo>Undo requested ($inlay->{count} times)</undo>\n"); |
768 | $inlay->append_text ("\n<undo>Undo requested ($inlay->{count} times)</undo>\n"); |
722 | $inlay->append_button ("Grant", sub { |
769 | $inlay->append_button ("Grant", sub { |
723 | $inlay->clear; |
770 | (delete $self->{undo_inlay})->clear; |
724 | $self->send (grant_undo => channel => $self->{channel}); |
771 | $self->send (grant_undo => channel => $self->{channel}); |
725 | }); |
772 | }); |
726 | $inlay->append_button ("Ignore", sub { |
773 | $inlay->append_button ("Ignore", sub { |
727 | $inlay->clear; |
774 | $inlay->clear; |
728 | $inlay->{ignore} = 1; |
775 | $inlay->{ignore} = 1; |
… | |
… | |
733 | } |
780 | } |
734 | |
781 | |
735 | sub inject_new_game { |
782 | sub inject_new_game { |
736 | my ($self, $msg) = @_; |
783 | my ($self, $msg) = @_; |
737 | |
784 | |
738 | $self->{chat}->append_text ("\n<header>ACK from server ($msg->{cid} == $self->{cid})</header>"); |
785 | if ($msg->{cid} != $self->{cid}) { |
|
|
786 | $self->part; |
|
|
787 | warn "ERROR: challenge id mismatch, PLEASE REPORT, especially the circumstances (many games open? etc..)\n";#d# |
|
|
788 | } |
|
|
789 | |
|
|
790 | $self->{chat}->append_text ("\n<header>Game successfully created on server.</header>"); |
739 | delete $self->{cid}; |
791 | delete $self->{cid}; |
740 | } |
792 | } |
741 | |
793 | |
742 | sub draw_challenge { |
794 | sub draw_challenge { |
743 | my ($self, $id) = @_; |
795 | my ($self, $id) = @_; |
… | |
… | |
747 | my $rules = $info->{rules}; |
799 | my $rules = $info->{rules}; |
748 | |
800 | |
749 | my $as_black = $info->{black}{name} eq $self->{conn}{name} ? 1 : 0;; |
801 | my $as_black = $info->{black}{name} eq $self->{conn}{name} ? 1 : 0;; |
750 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
802 | my $opponent = $as_black ? $info->{white} : $info->{black}; |
751 | |
803 | |
752 | my ($size, $time, $interval, $count); |
804 | my ($size, $time, $interval, $count, $type); |
753 | |
805 | |
754 | if (!$self->{channel}) { |
806 | if (!$self->{channel}) { |
755 | $inlay->append_text ("\nNotes: "); |
807 | $inlay->append_text ("\nNotes: "); |
756 | $inlay->append_entry (\$info->{notes}, 20, ""); |
808 | $inlay->append_entry (\$info->{notes}, 20, ""); |
757 | $inlay->append_text ("\nGlobal Offer: "); |
809 | $inlay->append_text ("\nGlobal Offer: "); |
… | |
… | |
762 | } else { |
814 | } else { |
763 | $inlay->append_text ("\nNotes: " . util::toxml $info->{notes}); |
815 | $inlay->append_text ("\nNotes: " . util::toxml $info->{notes}); |
764 | } |
816 | } |
765 | |
817 | |
766 | $inlay->append_text ("\nType: "); |
818 | $inlay->append_text ("\nType: "); |
767 | $inlay->append_optionmenu ( |
819 | $type = $inlay->append_optionmenu ( |
768 | \$info->{gametype}, |
820 | \$info->{gametype}, |
769 | GAMETYPE_DEMONSTRATION , "Demonstration", |
821 | GAMETYPE_DEMONSTRATION , "Demonstration (not yet)", |
770 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P)", |
822 | GAMETYPE_DEMONSTRATION | GAMETYPE_PRIVATE, "Demonstration (P) (not yet)", |
771 | GAMETYPE_TEACHING , "Teaching", |
823 | GAMETYPE_TEACHING , "Teaching (not yet)", |
772 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P)", |
824 | GAMETYPE_TEACHING | GAMETYPE_PRIVATE, "Teaching (P) (not yet)", |
773 | GAMETYPE_SIMUL , "Simul (not yet!)", |
825 | GAMETYPE_SIMUL , "Simul (not yet!)", |
774 | GAMETYPE_FREE , "Free", |
826 | GAMETYPE_FREE , "Free", |
775 | GAMETYPE_RATED , "Rated", |
827 | GAMETYPE_RATED , "Rated", |
776 | sub { |
828 | sub { |
777 | $size->set_history (2) if $_[0] eq GAMETYPE_RATED; |
829 | $size->set_history (2) if $_[0] eq GAMETYPE_RATED; |
… | |
… | |
801 | RULESET_NEW_ZEALAND, "New Zealand", |
853 | RULESET_NEW_ZEALAND, "New Zealand", |
802 | ); |
854 | ); |
803 | |
855 | |
804 | $inlay->append_text ("\nSize: "); |
856 | $inlay->append_text ("\nSize: "); |
805 | $size = $inlay->append_optionmenu ( |
857 | $size = $inlay->append_optionmenu ( |
|
|
858 | \$info->{rules}{size}, |
806 | \$info->{rules}{size}, 9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38 |
859 | (9 => 9, 13 => 13, 19 => 19, map +($_, $_), 2..38), |
|
|
860 | sub { |
|
|
861 | $type->set_history (5) # reset to free |
|
|
862 | if $_[0] != 19 && $info->{gametype} == GAMETYPE_RATED; |
|
|
863 | }, |
807 | ); |
864 | ); |
808 | |
865 | |
809 | if ($self->{channel}) { |
866 | if ($self->{channel}) { |
810 | $inlay->append_text ("\nHandicap: "); |
867 | $inlay->append_text ("\nHandicap: "); |
811 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |
868 | $inlay->append_optionmenu (\$info->{rules}{handicap}, map +($_, $_), 0..9); |