… | |
… | |
55 | my $time = int (($_[0] - 1) % $interval + 1); |
55 | my $time = int (($_[0] - 1) % $interval + 1); |
56 | |
56 | |
57 | sprintf "%s/%d =%d", |
57 | sprintf "%s/%d =%d", |
58 | util::format_time $time, |
58 | util::format_time $time, |
59 | $self->{moves}, |
59 | $self->{moves}, |
|
|
60 | $self->{moves} > 1 |
60 | $time / ($self->{moves} || 1); |
61 | ? $time / $self->{moves} |
61 | |
62 | : $interval; |
62 | } |
63 | } |
63 | }; |
64 | }; |
64 | |
65 | |
65 | } else { |
66 | } else { |
66 | # none, or unknown |
67 | # none, or unknown |
… | |
… | |
145 | |
146 | |
146 | $self; |
147 | $self; |
147 | } |
148 | } |
148 | |
149 | |
149 | sub configure { |
150 | sub configure { |
150 | my ($self, $user, $rules) = @_; |
151 | my ($self, $app, $user, $rules) = @_; |
151 | |
152 | |
152 | if ($self->{name}->get_text ne $user->as_string) { |
153 | if ($self->{name}->get_text ne $user->as_string) { |
153 | $self->{name}->set_text ($user->as_string); |
154 | $self->{name}->set_text ($user->as_string); |
154 | |
155 | |
155 | $self->{imagebox}->remove ($_) for $self->{imagebox}->get_children; |
156 | $self->{imagebox}->remove ($_) for $self->{imagebox}->get_children; |
156 | $self->{imagebox}->add (gtk::image_from_data undef); |
157 | $self->{imagebox}->add (gtk::image_from_data undef); |
157 | $self->{imagebox}->show_all; |
158 | $self->{imagebox}->show_all; |
158 | |
159 | |
159 | if ($user->has_pic) { |
160 | if ($user->has_pic) { |
160 | # the big picture... |
161 | # the big picture... |
161 | appwin::userpic ($user->{name}, sub { |
162 | $app->userpic ($user->{name}, sub { |
162 | return unless $self->{imagebox}; |
163 | return unless $self->{imagebox}; |
|
|
164 | |
163 | if ($_[0]) { |
165 | if ($_[0]) { |
164 | $self->{imagebox}->remove ($_) for $self->{imagebox}->get_children; |
166 | $self->{imagebox}->remove ($_) for $self->{imagebox}->get_children; |
165 | $self->{imagebox}->add (gtk::image_from_data $_[0]); |
167 | $self->{imagebox}->add (gtk::image_from_data $_[0]); |
166 | $self->{imagebox}->show_all; |
168 | $self->{imagebox}->show_all; |
167 | } |
169 | } |
… | |
… | |
185 | package game; |
187 | package game; |
186 | |
188 | |
187 | use KGS::Constants; |
189 | use KGS::Constants; |
188 | use KGS::Game::Board; |
190 | use KGS::Game::Board; |
189 | |
191 | |
|
|
192 | use Gtk2::GoBoard; |
|
|
193 | |
190 | use base KGS::Listener::Game; |
194 | use base KGS::Listener::Game; |
191 | use base KGS::Game; |
195 | use base KGS::Game; |
192 | |
196 | |
193 | use base gtk::widget; |
197 | use base gtk::widget; |
194 | |
198 | |
… | |
… | |
259 | $sw->add(($self->{userlist} = new userlist)->widget); |
263 | $sw->add(($self->{userlist} = new userlist)->widget); |
260 | |
264 | |
261 | $self->{vpane}->add(my $vbox = new Gtk2::VBox); |
265 | $self->{vpane}->add(my $vbox = new Gtk2::VBox); |
262 | |
266 | |
263 | $vbox->pack_start((my $hbox = new Gtk2::HBox 1), 0, 1, 0); |
267 | $vbox->pack_start((my $hbox = new Gtk2::HBox 1), 0, 1, 0); |
264 | $hbox->add (($self->{userpanel}[WHITE] = new game::userpanel colour => WHITE)->widget); |
268 | $hbox->add (($self->{userpanel}[COLOUR_WHITE] = new game::userpanel colour => COLOUR_WHITE)->widget); |
265 | $hbox->add (($self->{userpanel}[BLACK] = new game::userpanel colour => BLACK)->widget); |
269 | $hbox->add (($self->{userpanel}[COLOUR_BLACK] = new game::userpanel colour => COLOUR_BLACK)->widget); |
266 | |
270 | |
267 | $vbox->pack_start(($self->{text} = new gtk::text)->widget, 1, 1, 0); |
271 | $vbox->pack_start(($self->{chat} = new chat), 1, 1, 0); |
268 | |
272 | |
269 | $vbox->pack_start(($self->{entry} = new Gtk2::Entry), 0, 1, 0); |
|
|
270 | $self->{entry}->signal_connect(activate => sub { |
273 | $self->{chat}->signal_connect(command => sub { |
271 | my $text = $self->{entry}->get_text; |
274 | my ($chat, $cmd, $arg) = @_; |
272 | $self->say($text) if $text =~ /\S/; |
275 | if ($cmd eq "rsave") { |
273 | $self->{entry}->set_text(""); |
276 | Storable::nstore { tree => $self->{tree}, curnode => $self->{curnode}, move => $self->{move} }, $arg;#d# |
|
|
277 | } else { |
|
|
278 | $self->{app}->do_command ($chat, $cmd, $arg, userlist => $self->{userlist}, game => $self); |
|
|
279 | } |
274 | }); |
280 | }); |
275 | |
281 | |
276 | $self->event_update_game; |
282 | $self->event_update_game; |
277 | $self; |
283 | $self; |
278 | } |
284 | } |
279 | |
285 | |
280 | sub event_update_users { |
286 | sub event_update_users { |
281 | my ($self, $add, $update, $remove) = @_; |
287 | my ($self, $add, $update, $remove) = @_; |
|
|
288 | |
|
|
289 | return unless $self->{userlist}; |
282 | |
290 | |
283 | $self->{userlist}->update ($add, $update, $remove); |
291 | $self->{userlist}->update ($add, $update, $remove); |
284 | |
292 | |
285 | my %important; |
293 | my %important; |
286 | $important{$self->{user1}{name}}++; |
294 | $important{$self->{user1}{name}}++; |
287 | $important{$self->{user2}{name}}++; |
295 | $important{$self->{user2}{name}}++; |
288 | $important{$self->{user3}{name}}++; |
296 | $important{$self->{user3}{name}}++; |
289 | |
297 | |
290 | if (my @users = grep $important{$_->{name}}, @$add) { |
298 | if (my @users = grep $important{$_->{name}}, @$add) { |
291 | $self->{text}->append_text ("\n<header>Joins:</header>"); |
299 | $self->{chat}->append_text ("\n<header>Joins:</header>"); |
292 | $self->{text}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
300 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
293 | } |
301 | } |
294 | if (my @users = grep $important{$_->{name}}, @$remove) { |
302 | if (my @users = grep $important{$_->{name}}, @$remove) { |
295 | $self->{text}->append_text ("\n<header>Parts:</header>"); |
303 | $self->{chat}->append_text ("\n<header>Parts:</header>"); |
296 | $self->{text}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
304 | $self->{chat}->append_text (" <user>" . $_->as_string . "</user>") for @users; |
297 | } |
305 | } |
298 | |
306 | |
299 | } |
307 | } |
300 | |
308 | |
301 | sub join { |
309 | sub join { |
… | |
… | |
325 | $self->{board_label}->set_text ("Move " . ($move - 1)); |
333 | $self->{board_label}->set_text ("Move " . ($move - 1)); |
326 | |
334 | |
327 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
335 | $self->{cur_board} = new KGS::Game::Board $self->{size}; |
328 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $move - 1]]); |
336 | $self->{cur_board}->interpret_path ([@{$self->{path}}[0 .. $move - 1]]); |
329 | |
337 | |
330 | for my $colour (WHITE, BLACK) { |
338 | for my $colour (COLOUR_WHITE, COLOUR_BLACK) { |
331 | $self->{userpanel}[$colour]->set_state ( |
339 | $self->{userpanel}[$colour]->set_state ( |
332 | $self->{cur_board}{captures}[$colour], |
340 | $self->{cur_board}{captures}[$colour], |
333 | $self->{cur_board}{timer}[$colour], |
341 | $self->{cur_board}{timer}[$colour], |
334 | ($running && $self->{lastmove_colour} == !$colour) |
342 | ($running && $self->{lastmove_colour} == !$colour) |
335 | ? $self->{lastmove_time} : 0 |
343 | ? $self->{lastmove_time} : 0 |
… | |
… | |
391 | }sgexi; |
399 | }sgexi; |
392 | |
400 | |
393 | $text .= $_; |
401 | $text .= $_; |
394 | } |
402 | } |
395 | |
403 | |
396 | $self->{text}->append_text ($text); |
404 | $self->{chat}->append_text ($text); |
397 | } |
405 | } |
398 | |
406 | |
399 | sub event_join { |
407 | sub event_join { |
400 | my ($self) = @_; |
408 | my ($self) = @_; |
401 | $self->SUPER::event_join; |
409 | $self->SUPER::event_join; |
… | |
… | |
413 | } |
421 | } |
414 | |
422 | |
415 | sub event_update_game { |
423 | sub event_update_game { |
416 | my ($self) = @_; |
424 | my ($self) = @_; |
417 | $self->SUPER::event_update_game; |
425 | $self->SUPER::event_update_game; |
|
|
426 | |
|
|
427 | return unless $self->{window}; |
418 | |
428 | |
419 | my $title = defined $self->{channel} |
429 | my $title = defined $self->{channel} |
420 | ? $self->owner->as_string . " " . $self->opponent_string |
430 | ? $self->owner->as_string . " " . $self->opponent_string |
421 | : "Game Window"; |
431 | : "Game Window"; |
422 | $self->{window}->set_title("KGS Game $title"); |
432 | $self->{window}->set_title("KGS Game $title"); |
423 | $self->{title}->set_text ($title); |
433 | $self->{title}->set_text ($title); |
424 | |
434 | |
425 | $self->{user}[BLACK] = $self->{user1}; |
435 | $self->{user}[COLOUR_BLACK] = $self->{user1}; |
426 | $self->{user}[WHITE] = $self->{user2}; |
436 | $self->{user}[COLOUR_WHITE] = $self->{user2}; |
427 | |
437 | |
428 | # show board |
438 | # show board |
429 | |
439 | |
430 | $self->{left}->remove ($_) for $self->{left}->get_children; |
|
|
431 | if ($self->is_valid) { |
440 | if ($self->is_valid) { |
|
|
441 | #D# TODO: check wether already inside, or already removed!!! |
432 | $self->{left}->add ($self->{boardbox}); |
442 | $self->{left}->add ($self->{boardbox}); |
433 | (delete $self->{challenge})->destroy if $self->{challenge}; |
443 | $self->{left}->remove ($self->{challenge}->widget) if $self->{challenge}; |
434 | } else { |
444 | } else { |
|
|
445 | #D# TODO: check wether already inside, or already removed!!! |
435 | $self->{left}->add ($self->{challenge}->widget); |
446 | $self->{left}->add ($self->{challenge}->widget); |
|
|
447 | $self->{left}->remove ($self->{boardbox}); |
436 | } |
448 | } |
437 | $self->{left}->show_all; |
449 | $self->{left}->show_all; |
438 | |
450 | |
439 | # view text |
451 | # view text |
440 | |
452 | |
… | |
… | |
473 | $text .= "</infoblock>"; |
485 | $text .= "</infoblock>"; |
474 | |
486 | |
475 | $self->{gatext} = \@ga; |
487 | $self->{gatext} = \@ga; |
476 | }; |
488 | }; |
477 | |
489 | |
478 | $self->{text}->append_text ($text); |
490 | $self->{chat}->append_text ($text); |
479 | } |
491 | } |
480 | |
492 | |
481 | sub event_update_rules { |
493 | sub event_update_rules { |
482 | my ($self, $rules) = @_; |
494 | my ($self, $rules) = @_; |
483 | |
495 | |
484 | $self->{userpanel}[$_]->configure ($self->{user}[$_], $rules) |
496 | $self->{userpanel}[$_]->configure ($self->{app}, $self->{user}[$_], $rules) |
485 | for BLACK, WHITE; |
497 | for COLOUR_BLACK, COLOUR_WHITE; |
486 | |
498 | |
487 | sound::play 3, "gamestart"; |
499 | sound::play 3, "gamestart"; |
488 | |
500 | |
489 | my $text = "\n<header>Game Rules</header>"; |
501 | my $text = "\n<header>Game Rules</header>"; |
490 | |
502 | |
… | |
… | |
503 | } elsif ($rules->{timesys} == TIMESYS_CANADIAN) { |
515 | } elsif ($rules->{timesys} == TIMESYS_CANADIAN) { |
504 | $text .= util::format_time $rules->{time}; |
516 | $text .= util::format_time $rules->{time}; |
505 | $text .= sprintf " + %s/%d CAN", util::format_time $rules->{interval}, $rules->{count}; |
517 | $text .= sprintf " + %s/%d CAN", util::format_time $rules->{interval}, $rules->{count}; |
506 | } |
518 | } |
507 | |
519 | |
508 | $self->{text}->append_text ("<infoblock>$text</infoblock>"); |
520 | $self->{chat}->append_text ("<infoblock>$text</infoblock>"); |
509 | } |
521 | } |
510 | |
522 | |
511 | sub inject_resign_game { |
523 | sub inject_resign_game { |
512 | my ($self, $msg) = @_; |
524 | my ($self, $msg) = @_; |
513 | |
525 | |
514 | sound::play 3, "resign"; |
526 | sound::play 3, "resign"; |
515 | |
527 | |
516 | $self->{text}->append_text ("\n<infoblock><header>Resign</header>" |
528 | $self->{chat}->append_text ("\n<infoblock><header>Resign</header>" |
517 | . "\n<user>" |
529 | . "\n<user>" |
518 | . (util::toxml $self->{user}[$msg->{player}]->as_string) |
530 | . (util::toxml $self->{user}[$msg->{player}]->as_string) |
519 | . "</user> resigned.</infoblock>"); |
531 | . "</user> resigned.</infoblock>"); |
520 | } |
532 | } |
521 | |
533 | |
522 | sub inject_final_result { |
534 | sub inject_final_result { |
523 | my ($self, $msg) = @_; |
535 | my ($self, $msg) = @_; |
524 | |
536 | |
525 | $self->{text}->append_text ("<infoblock>\n<header>Game Over</header>" |
537 | $self->{chat}->append_text ("<infoblock>\n<header>Game Over</header>" |
526 | . "\nWhite Score " . (util::toxml $msg->{whitescore}->as_string) |
538 | . "\nWhite Score " . (util::toxml $msg->{whitescore}->as_string) |
527 | . "\nBlack Score " . (util::toxml $msg->{blackscore}->as_string) |
539 | . "\nBlack Score " . (util::toxml $msg->{blackscore}->as_string) |
528 | . "</infoblock>" |
540 | . "</infoblock>" |
529 | ); |
541 | ); |
530 | } |
542 | } |
531 | |
543 | |
|
|
544 | sub event_challenge { |
|
|
545 | my ($self, $challenge) = @_; |
|
|
546 | |
|
|
547 | use KGS::Listener::Debug; |
|
|
548 | $self->{chat}->append_text ("\n".KGS::Listener::Debug::dumpval($challenge)); |
|
|
549 | } |
|
|
550 | |
532 | sub destroy { |
551 | sub destroy { |
533 | my ($self) = @_; |
552 | my ($self) = @_; |
|
|
553 | |
|
|
554 | delete $self->{app}{gamelist}{game}{$self->{channel}}; |
534 | $self->{userpanel}[$_] && (delete $self->{userpanel}[$_])->destroy |
555 | $self->{userpanel}[$_] && (delete $self->{userpanel}[$_])->destroy |
535 | for BLACK, WHITE; |
556 | for COLOUR_BLACK, COLOUR_WHITE; |
536 | $self->SUPER::destroy; |
557 | $self->SUPER::destroy; |
537 | delete $appwin::gamelist->{game}{$self->{channel}}; |
|
|
538 | } |
558 | } |
539 | |
559 | |
540 | 1; |
560 | 1; |
541 | |
561 | |