[gnome-games/glchess-vala] Get a chess clock working
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/glchess-vala] Get a chess clock working
- Date: Fri, 7 Jan 2011 04:20:37 +0000 (UTC)
commit 8dc0089e8682f083610f300f89a15935e71ca7e9
Author: Robert Ancell <robert ancell canonical com>
Date: Fri Jan 7 15:20:27 2011 +1100
Get a chess clock working
glchess/src/Makefile.am | 3 +-
glchess/src/chess-clock.vala | 156 +++++++++++++++++++++++++++++++-----------
glchess/src/chess-game.vala | 18 +++++-
glchess/src/glchess.vala | 38 ++++++++--
4 files changed, 166 insertions(+), 49 deletions(-)
---
diff --git a/glchess/src/Makefile.am b/glchess/src/Makefile.am
index 2d06d92..85640d8 100644
--- a/glchess/src/Makefile.am
+++ b/glchess/src/Makefile.am
@@ -7,12 +7,12 @@ glchess_SOURCES = \
glchess.vala \
ai-profile.vala \
chess-bitboard.vala \
+ chess-clock.vala \
chess-engine.vala \
chess-engine-cecp.vala \
chess-engine-uci.vala \
chess-game.vala \
chess-pgn.vala \
- chess-clock.vala \
chess-view.vala \
chess-view-2d.vala \
chess-view-3d.vala \
@@ -21,6 +21,7 @@ glchess_SOURCES = \
test_chess_game_SOURCES = \
chess-bitboard.vala \
+ chess-clock.vala \
chess-game.vala \
test-chess-game.vala
diff --git a/glchess/src/chess-clock.vala b/glchess/src/chess-clock.vala
index 4704eae..c1b8a98 100644
--- a/glchess/src/chess-clock.vala
+++ b/glchess/src/chess-clock.vala
@@ -1,77 +1,153 @@
public class ChessClock : Object
{
+ private uint _white_duration;
+ public uint white_duration
+ {
+ get { return _white_duration; }
+ }
+ private uint _black_duration;
+ public uint black_duration
+ {
+ get { return _black_duration; }
+ }
+
+ private uint _white_used;
+ public uint white_used
+ {
+ get
+ {
+ if (active_color == Color.WHITE)
+ return _white_used + (uint) (timer.elapsed () * 1000);
+ else
+ return _white_used;
+ }
+ }
+
+ public uint white_used_in_seconds
+ {
+ get { return (white_used + 500) / 1000; }
+ }
+
+ private uint _black_used;
+ public uint black_used
+ {
+ get
+ {
+ if (active_color == Color.WHITE)
+ return _black_used;
+ else
+ return _black_used + (uint) (timer.elapsed () * 1000);
+ }
+ }
+
+ public uint black_used_in_seconds
+ {
+ get { return (black_used + 500) / 1000; }
+ }
+
+ public Color _active_color = Color.WHITE;
+ public Color active_color
+ {
+ get { return _active_color; }
+ set
+ {
+ if (value == active_color)
+ return;
+
+ stop ();
+ _active_color = value;
+ start ();
+ }
+ }
+
private Timer timer;
- private uint white_duration;
- private uint black_duration;
- private uint white_used;
- private uint black_used;
- private Color active_color = Color.WHITE;
- private uint timeout = 0;
+ private uint expire_timeout = 0;
+ private uint tick_timeout = 0;
public signal void tick ();
public signal void expired ();
public ChessClock (uint white_duration, uint black_duration, uint white_used = 0, uint black_used = 0)
{
- this.white_duration = white_duration;
- this.black_duration = black_duration;
- this.white_used = white_used;
- this.black_used = black_used;
+ _white_duration = white_duration * 1000;
+ _black_duration = black_duration * 1000;
+ _white_used = white_used;
+ _black_used = black_used;
timer = new Timer ();
}
-
+
+ private bool is_started
+ {
+ get { return expire_timeout != 0; }
+ }
+
public void start ()
{
- if (timeout != 0)
+ if (is_started)
return;
- uint remaining;
+ /* Start stopwatch */
+ timer.start ();
+
+ /* Notify when this timer has expired */
if (active_color == Color.WHITE)
- {
- if (white_used > white_duration)
- white_used = white_duration;
- remaining = white_duration - white_used;
- }
+ expire_timeout = Timeout.add (white_duration - _white_used, timer_expired_cb);
else
- {
- if (black_used > black_duration)
- black_used = black_duration;
- remaining = black_duration - black_used;
- }
- timer.start ();
+ expire_timeout = Timeout.add (black_duration - _black_used, timer_expired_cb);
- timeout = Timeout.add (remaining, timer_expired_cb);
+ /* Wake up each second */
+ tick_cb ();
}
private bool timer_expired_cb ()
{
- timeout = 0;
+ stop ();
expired ();
return false;
}
- public void stop ()
+ private bool tick_cb ()
{
- if (timeout == 0)
- return;
- timer.stop ();
- Source.remove (timeout);
- timeout = 0;
+ if (tick_timeout != 0)
+ tick ();
- var elapsed = (uint) (timer.elapsed () * 1000000);
+ uint elapsed = (uint) (timer.elapsed () * 1000);
+ uint used;
if (active_color == Color.WHITE)
- white_used += elapsed;
+ used = _white_used + elapsed;
else
- black_used += elapsed;
+ used = _black_used + elapsed;
+ var next_tick_time = ((used / 1000) + 1) * 1000;
+ tick_timeout = Timeout.add (next_tick_time - used, tick_cb);
+
+ return false;
}
- public void set_color (Color color)
+ public void stop ()
{
- if (color == active_color)
+ if (!is_started)
return;
- active_color = color;
- stop ();
- start ();
+ timer.stop ();
+ Source.remove (expire_timeout);
+ expire_timeout = 0;
+ Source.remove (tick_timeout);
+ tick_timeout = 0;
+
+ var elapsed = (uint) (timer.elapsed () * 1000);
+ if (active_color == Color.WHITE)
+ {
+ _white_used += elapsed;
+ if (_white_used > white_duration)
+ _white_used = white_duration;
+ }
+ else
+ {
+ _black_used += elapsed;
+ if (_black_used > black_duration)
+ _black_used = black_duration;
+ }
+
+ timer.reset ();
}
}
diff --git a/glchess/src/chess-game.vala b/glchess/src/chess-game.vala
index ef5e418..0b475e0 100644
--- a/glchess/src/chess-game.vala
+++ b/glchess/src/chess-game.vala
@@ -787,6 +787,7 @@ public enum ChessRule
public class ChessGame
{
public bool is_started;
+ public ChessClock clock;
public ChessResult result;
public ChessRule rule;
public List<ChessState> move_stack;
@@ -811,6 +812,8 @@ public class ChessGame
public ChessGame (string fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
{
+ clock = new ChessClock (60, 60);
+
is_started = false;
move_stack.prepend (new ChessState (fen));
result = ChessResult.IN_PROGRESS;
@@ -866,6 +869,7 @@ public class ChessGame
state.last_move.moved_rook.moved ();
moved (state.last_move);
+ clock.active_color = current_player.color;
current_player.start_turn ();
turn_started (current_player);
@@ -905,11 +909,23 @@ public class ChessGame
reset ();
+ clock.expired.connect (clock_expired_cb);
+ clock.active_color = current_player.color;
+ clock.start ();
+
started ();
current_player.start_turn ();
turn_started (current_player);
}
-
+
+ private void clock_expired_cb (ChessClock clock)
+ {
+ if (current_player.color == Color.WHITE)
+ stop (ChessResult.BLACK_WON, ChessRule.TIMEOUT);
+ else
+ stop (ChessResult.WHITE_WON, ChessRule.TIMEOUT);
+ }
+
public void abandon ()
{
if (!is_started)
diff --git a/glchess/src/glchess.vala b/glchess/src/glchess.vala
index b9c0579..3d5c888 100644
--- a/glchess/src/glchess.vala
+++ b/glchess/src/glchess.vala
@@ -19,6 +19,9 @@ public class Application
private Gtk.Widget next_move_button;
private Gtk.Widget last_move_button;
private Gtk.ComboBox history_combo;
+ private Gtk.Widget white_time_label;
+ private Gtk.Widget black_time_label;
+
private Gtk.Dialog? preferences_dialog = null;
private Gtk.ComboBox duration_combo;
private Gtk.Adjustment duration_adjustment;
@@ -68,6 +71,8 @@ public class Application
next_move_button = (Gtk.Widget) builder.get_object ("next_move_button");
last_move_button = (Gtk.Widget) builder.get_object ("last_move_button");
history_combo = (Gtk.ComboBox) builder.get_object ("history_combo");
+ white_time_label = (Gtk.Widget) builder.get_object ("white_time_label");
+ black_time_label = (Gtk.Widget) builder.get_object ("black_time_label");
settings.bind ("show-toolbar", builder.get_object ("toolbar"), "visible", SettingsBindFlags.DEFAULT);
settings.bind ("show-history", builder.get_object ("navigation_box"), "visible", SettingsBindFlags.DEFAULT);
var view_box = (Gtk.VBox) builder.get_object ("view_box");
@@ -199,6 +204,7 @@ public class Application
game.turn_started.connect (game_turn_cb);
game.moved.connect (game_move_cb);
game.ended.connect (game_end_cb);
+ game.clock.tick.connect (game_clock_tick_cb);
var model = (Gtk.ListStore) history_combo.model;
model.clear ();
@@ -236,6 +242,9 @@ public class Application
break;
}
}
+
+ white_time_label.queue_draw ();
+ black_time_label.queue_draw ();
}
private ChessEngine? get_engine (string name)
@@ -321,6 +330,12 @@ public class Application
opponent_engine.start_game ();
}
+ private void game_clock_tick_cb (ChessClock clock)
+ {
+ white_time_label.queue_draw ();
+ black_time_label.queue_draw ();
+ }
+
private void game_turn_cb (ChessGame game, ChessPlayer player)
{
if (opponent_engine != null && player == opponent)
@@ -549,6 +564,9 @@ public class Application
info_title_label.set_markup ("<big><b>%s</b></big>".printf (title));
info_label.set_text (reason);
info_bar.show ();
+
+ white_time_label.queue_draw ();
+ black_time_label.queue_draw ();
}
public void show ()
@@ -606,30 +624,36 @@ public class Application
quit ();
}
- [CCode (cname = "G_MODULE_EXPORT black_time_draw_cb", instance_pos = -1)]
- public bool black_time_draw_cb (Gtk.Widget widget, Cairo.Context c)
+ [CCode (cname = "G_MODULE_EXPORT white_time_draw_cb", instance_pos = -1)]
+ public bool white_time_draw_cb (Gtk.Widget widget, Cairo.Context c)
{
double fg[3] = { 0.0, 0.0, 0.0 };
double bg[3] = { 1.0, 1.0, 1.0 };
- draw_time (widget, c, "â??", fg, bg);
+ draw_time (widget, c, (int) (game.clock.white_duration / 1000 - game.clock.white_used_in_seconds), fg, bg);
return false;
}
- [CCode (cname = "G_MODULE_EXPORT white_time_draw_cb", instance_pos = -1)]
- public bool white_time_draw_cb (Gtk.Widget widget, Cairo.Context c)
+ [CCode (cname = "G_MODULE_EXPORT black_time_draw_cb", instance_pos = -1)]
+ public bool black_time_draw_cb (Gtk.Widget widget, Cairo.Context c)
{
double fg[3] = { 1.0, 1.0, 1.0 };
double bg[3] = { 0.0, 0.0, 0.0 };
- draw_time (widget, c, "â??", fg, bg);
+ draw_time (widget, c, (int) (game.clock.black_duration / 1000 - game.clock.black_used_in_seconds), fg, bg);
return false;
}
- private void draw_time (Gtk.Widget widget, Cairo.Context c, string text, double[] fg, double[] bg)
+ private void draw_time (Gtk.Widget widget, Cairo.Context c, int used, double[] fg, double[] bg)
{
double alpha = 1.0;
+ string text = "â??";
+ if (used >= 60)
+ text = "%d:%02d".printf (used / 60, used % 60);
+ else if (used >= 0)
+ text = ":%02d".printf (used);
+
if (widget.get_state () == Gtk.StateType.INSENSITIVE)
alpha = 0.5;
c.set_source_rgba (bg[0], bg[1], bg[2], alpha);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]