[four-in-a-row/KaKnife/four-in-a-row-vala: 27/65] begin transition to OOP
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [four-in-a-row/KaKnife/four-in-a-row-vala: 27/65] begin transition to OOP
- Date: Sun, 16 Dec 2018 03:22:15 +0000 (UTC)
commit 17a345989c6d62e8dd44fb07290790b2c92808af
Author: Jacob Humphrey <jacob ryan humphrey gmail com>
Date: Sun Dec 9 21:37:40 2018 -0600
begin transition to OOP
src/Makefile.am | 2 +
src/game_board.vala | 133 +++++
src/gfx.vala | 127 ++++-
src/main.vala | 1472 +++++++++++++++++++++------------------------------
src/prefs.vala | 114 ++--
src/scorebox.vala | 92 ++++
6 files changed, 1001 insertions(+), 939 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index f03e842..162e120 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,8 @@ four_in_a_row_SOURCES = \
prefs.vala \
gfx.vala \
theme.vala \
+ scorebox.vala \
+ game_board.vala \
config.vapi
four_in_a_row_CPPFLAGS = \
diff --git a/src/game_board.vala b/src/game_board.vala
new file mode 100644
index 0000000..03bf4e9
--- /dev/null
+++ b/src/game_board.vala
@@ -0,0 +1,133 @@
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* game_board.vala
+ *
+ * Copyright © 2018 Jacob Humphrey
+ *
+ * This file is part of GNOME Four-in-a-row.
+ *
+ * GNOME Four-in-a-row is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME Four-in-a-row is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME Four-in-a-row. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+class Board : Object {
+ static Tile[,] gboard;
+ const int BOARD_SIZE = 7;
+ static Once<Board> _instance;
+ public static Board instance {
+ get {
+ return _instance.once(() => {return new Board();});
+ }
+ }
+
+ public Board() {
+ gboard = new Tile[BOARD_SIZE, BOARD_SIZE];
+ }
+
+ public void @set(int x, int y, Tile tile) {
+ gboard[x,y] = tile;
+ }
+
+ public Tile @get(int x, int y) {
+ return gboard[x, y];
+ }
+
+ public void clear() {
+ for (var r = 0; r < BOARD_SIZE; r++) {
+ for (var c = 0; c < BOARD_SIZE; c++) {
+ gboard[r, c] = Tile.CLEAR;
+ }
+ }
+ }
+
+ public int first_empty_row(int c) {
+ int r = 1;
+
+ while (r < BOARD_SIZE && gboard[r, c] == Tile.CLEAR)
+ r++;
+ return r - 1;
+ }
+
+ bool is_hline_at(Tile p, int r, int c, out int r1, out int c1, out int r2, out int c2) {
+ r1 = r;
+ r2 = r;
+ c1 = c;
+ c2 = c;
+ while (c1 > 0 && gboard[r, c1 - 1] == p)
+ c1 = c1 - 1;
+ while (c2 < 6 && gboard[r, c2 + 1] == p)
+ c2 = c2 + 1;
+ if (c2 - c1 >= 3)
+ return true;
+ return false;
+ }
+
+ public bool is_line_at(Tile p, int r, int c, out int r1 = null,
+ out int c1 = null, out int r2 = null, out int c2 = null) {
+ return is_hline_at(p, r, c, out r1, out c1, out r2, out c2) ||
+ is_vline_at(p, r, c, out r1, out c1, out r2, out c2) ||
+ is_dline1_at(p, r, c, out r1, out c1, out r2, out c2) ||
+ is_dline2_at(p, r, c, out r1, out c1, out r2, out c2);
+ }
+
+ bool is_vline_at(Tile p, int r, int c, out int r1 , out int c1, out int r2, out int c2) {
+ r1 = r;
+ r2 = r;
+ c1 = c;
+ c2 = c;
+ while (r1 > 1 && get(r1 - 1, c) == p)
+ r1 = r1 - 1;
+ while (r2 < 6 && get(r2 + 1, c) == p)
+ r2 = r2 + 1;
+ if (r2 - r1 >= 3)
+ return true;
+ return false;
+ }
+
+ bool is_dline1_at(Tile p, int r, int c, out int r1, out int c1, out int r2, out int c2) {
+ /* upper left to lower right */
+ r1 = r;
+ r2 = r;
+ c1 = c;
+ c2 = c;
+ while (c1 > 0 && r1 > 1 && get(r1 - 1, c1 - 1) == p) {
+ r1 = r1 - 1;
+ c1 = c1 - 1;
+ }
+ while (c2 < 6 && r2 < 6 && get(r2 + 1, c2 + 1) == p) {
+ r2 = r2 + 1;
+ c2 = c2 + 1;
+ }
+ if (r2 - r1 >= 3)
+ return true;
+ return false;
+ }
+
+ bool is_dline2_at(Tile p, int r, int c, out int r1, out int c1, out int r2, out int c2) {
+ /* upper right to lower left */
+ r1 = r;
+ r2 = r;
+ c1 = c;
+ c2 = c;
+ while (c1 < 6 && r1 > 1 && get(r1 - 1, c1 + 1) == p) {
+ r1 = r1 - 1;
+ c1 = c1 + 1;
+ }
+ while (c2 > 0 && r2 < 6 && get(r2 + 1, c2 - 1) == p) {
+ r2 = r2 + 1;
+ c2 = c2 - 1;
+ }
+ if (r2 - r1 >= 3)
+ return true;
+ return false;
+ }
+}
diff --git a/src/gfx.vala b/src/gfx.vala
index 18c8a14..de53a02 100644
--- a/src/gfx.vala
+++ b/src/gfx.vala
@@ -19,22 +19,44 @@
* along with GNOME Four-in-a-row. If not, see <http://www.gnu.org/licenses/>.
*/
-Gtk.Widget drawarea;
-int[,] gboard;
+
int boardsize = 0;
int tilesize = 0;
int offset[6];
-namespace Gfx {
+class GameBoardView : Gtk.DrawingArea {
/* unscaled pixbufs */
Gdk.Pixbuf pb_tileset_raw;
Gdk.Pixbuf pb_bground_raw;
-
/* scaled pixbufs */
Gdk.Pixbuf pb_tileset;
Gdk.Pixbuf pb_bground;
+ //public Gtk.DrawingArea drawarea;
+
+ static Once<GameBoardView> _instance;
+ public static GameBoardView instance {
+ get {
+ return _instance.once(() => {return new GameBoardView();});
+ }
+ }
- int get_column(int xpos) {
+ public GameBoardView() {
+ Object();
+ /* set a min size to avoid pathological behavior of gtk when scaling down */
+ set_size_request(350, 350);
+ halign = Gtk.Align.FILL;
+ valign = Gtk.Align.FILL;
+
+ events = Gdk.EventMask.EXPOSURE_MASK |
+ Gdk.EventMask.BUTTON_PRESS_MASK |
+ Gdk.EventMask.BUTTON_RELEASE_MASK;
+ configure_event.connect(resize);
+ draw.connect(expose);
+ //button_press_event.connect(button_press_event);
+ key_press_event.connect(this.on_key_press);
+ }
+
+ public int get_column(int xpos) {
/* Derive column from pixel position */
int c = xpos / tilesize;
if (c > 6)
@@ -45,28 +67,19 @@ namespace Gfx {
return c;
}
- void draw_tile(int r, int c) {
- drawarea.queue_draw_area(c*tilesize, r*tilesize, tilesize, tilesize);
+ public void draw_tile(int r, int c) {
+ queue_draw_area(c*tilesize, r*tilesize, tilesize, tilesize);
}
- void draw_all() {
- drawarea.queue_draw_area(0, 0, boardsize, boardsize);
- }
-
- bool change_theme() {
- if (!Gfx.load_pixmaps())
- return false;
-
- Gfx.refresh_pixmaps();
- draw_all();
- return true;
+ public void draw_all() {
+ queue_draw_area(0, 0, boardsize, boardsize);
}
- void resize(Gtk.Widget w) {
+ public bool resize(Gdk.EventConfigure e) {
int width, height;
- width = w.get_allocated_width();
- height = w.get_allocated_height();
+ width = get_allocated_width();
+ height = get_allocated_height();
boardsize = int.min(width, height);
tilesize = boardsize / 7;
@@ -78,11 +91,21 @@ namespace Gfx {
offset[Tile.PLAYER1_CURSOR] = tilesize * 4;
offset[Tile.PLAYER2_CURSOR] = tilesize * 5;
- Gfx.refresh_pixmaps();
+ refresh_pixmaps();
draw_all();
+ return true;
+ }
+
+ public bool change_theme() {
+ if (!load_pixmaps())
+ return false;
+
+ refresh_pixmaps();
+ GameBoardView.instance.draw_all();
+ return true;
}
- void expose(Cairo.Context cr) {
+ public bool expose(Cairo.Context cr) {
int r, c;
/* draw the background */
@@ -94,11 +117,12 @@ namespace Gfx {
for (r = 0; r < 7; r++) {
for (c = 0; c < 7; c++) {
- Gfx.paint_tile(cr, r, c);
+ paint_tile(cr, r, c);
}
}
draw_grid(cr);
+ return false;
}
void draw_grid(Cairo.Context cr) {
@@ -145,7 +169,7 @@ namespace Gfx {
void paint_tile(Cairo.Context cr, int r, int c) {
int x = c * tilesize;
int y = r * tilesize;
- int tile = gboard[r,c];
+ int tile = Board.instance.get(r, c);
int os = 0;
if (tile == Tile.CLEAR && r != 0)
@@ -181,13 +205,13 @@ namespace Gfx {
cr.restore();
}
- void refresh_pixmaps() {
+ public void refresh_pixmaps() {
/* scale the pixbufs */
pb_tileset = pb_tileset_raw.scale_simple(tilesize * 6, tilesize, Gdk.InterpType.BILINEAR);
pb_bground = pb_bground_raw.scale_simple(boardsize, boardsize, Gdk.InterpType.BILINEAR);
}
- bool load_pixmaps() {
+ public bool load_pixmaps() {
string fname;
Gdk.Pixbuf pb_tileset_tmp;
Gdk.Pixbuf pb_bground_tmp = null;
@@ -202,7 +226,7 @@ namespace Gfx {
p.theme_id = 0;
continue;
} else {
- Gfx.load_error(fname);
+ load_error(fname);
return false;
}
}
@@ -216,7 +240,7 @@ namespace Gfx {
try {
pb_bground_tmp = new Gdk.Pixbuf.from_file(fname);
} catch (Error e) {
- Gfx.load_error(fname);
+ load_error(fname);
return false;
}
}
@@ -250,4 +274,49 @@ namespace Gfx {
return true;
}
+
+ protected override bool button_press_event(Gdk.EventButton e) {
+ int x, y;
+ if (application.player_active) {
+ return false;
+ }
+
+ if (application.gameover && timeout == 0) {
+ application.blink_winner(2);
+ } else if (application.is_player_human() && timeout == 0) {
+ get_window().get_device_position(e.device, out x, out y, null);
+ application.game_process_move(GameBoardView.instance.get_column(x));
+ }
+
+ return true;
+ }
+
+ bool on_key_press(Gtk.Widget w, Gdk.EventKey e) {
+ if ((application.player_active) || timeout != 0 ||
+ (e.keyval != p.keypress[Move.LEFT] &&
+ e.keyval != p.keypress[Move.RIGHT] &&
+ e.keyval != p.keypress[Move.DROP])) {
+ return false;
+ }
+
+ if (application.gameover) {
+ application.blink_winner(2);
+ return true;
+ }
+
+ if (e.keyval == p.keypress[Move.LEFT] && column != 0) {
+ column_moveto--;
+ application.move_cursor(column_moveto);
+ } else if (e.keyval == p.keypress[Move.RIGHT] && column < 6) {
+ column_moveto++;
+ application.move_cursor(column_moveto);
+ } else if (e.keyval == p.keypress[Move.DROP]) {
+ application.game_process_move(column);
+ }
+ return true;
+ }
+
+
}
+
+
diff --git a/src/main.vala b/src/main.vala
index d774acb..facace6 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -19,6 +19,15 @@
* along with GNOME Four-in-a-row. If not, see <http://www.gnu.org/licenses/>.
*/
+const string APPNAME_LONG = N_("Four-in-a-row");
+const int SIZE_VSTR = 53;
+const int SPEED_BLINK = 150;
+const int SPEED_MOVE = 35;
+const int SPEED_DROP = 20;
+const char vlevel[] = {'0','a','b','c','\0'};
+const int DEFAULT_WIDTH = 495;
+const int DEFAULT_HEIGHT = 435;
+
public enum AnimID {
NONE,
MOVE,
@@ -28,7 +37,7 @@ public enum AnimID {
}
public enum PlayerID {
- PLAYER1,
+ PLAYER1 = 0,
PLAYER2,
NOBODY
}
@@ -41,7 +50,7 @@ public enum Level {
}
public enum Tile {
- PLAYER1,
+ PLAYER1 = 0,
PLAYER2,
CLEAR,
CLEAR_CURSOR,
@@ -64,1010 +73,757 @@ public enum SoundID {
COLUMN_FULL
}
-SimpleAction hint_action;
-SimpleAction undo_action;
-SimpleAction new_game_action;
-
-const string APPNAME_LONG = N_("Four-in-a-row");
-const int SIZE_VSTR = 53;
-
-Gtk.Application? application;
-Gtk.Window window;
-Gtk.Dialog? scorebox = null;
-Gtk.Label label_name[3];
-Gtk.Label label_score[3];
-bool gameover;
-bool player_active;
-PlayerID player;
-PlayerID winner;
-PlayerID who_starts;
-int score[3];
-AnimID anim;
-char vstr[53];
-const char vlevel[] = {'0','a','b','c','\0'};
-int moves;
-const int SPEED_BLINK = 150;
-const int SPEED_MOVE = 35;
-const int SPEED_DROP = 20;
-int column;
-int column_moveto;
-int row;
-int row_dropto;
-Gtk.HeaderBar headerbar;
-
-const int DEFAULT_WIDTH = 495;
-const int DEFAULT_HEIGHT = 435;
-
-int blink_r1 = 0;
-int blink_c1 = 0;
-int blink_r2 = 0;
-int blink_c2 = 0;
-int blink_t = 0;
-int blink_n = 0;
-bool blink_on = false;
-uint timeout = 0;
+class FourInARow : Gtk.Application {
+ public bool gameover;
+ public bool player_active;
-void on_game_new(SimpleAction a, Variant? v) {
- stop_anim();
- game_reset();
-}
+ const ActionEntry app_entries[] = {
+ {"scores", on_game_scores},
+ {"quit", on_game_exit},
+ {"preferences", on_settings_preferences},
+ {"help", on_help_contents},
+ {"about", on_help_about}
+ };
-void draw_line(int r1, int c1, int r2, int c2, int tile) {
- /* draw a line of 'tile' from r1,c1 to r2,c2 */
-
- bool done = false;
- int d_row = 0;
- int d_col = 0;
-
- if (r1 < r2)
- d_row = 1;
- else if (r1 > r2)
- d_row = -1;
-
- if (c1 < c2)
- d_col = 1;
- else if (c1 > c2)
- d_col = -1;
-
- do {
- done = (r1 == r2 && c1 == c2);
- gboard[r1, c1] = tile;
- Gfx.draw_tile(r1, c1);
- if (r1 != r2)
- r1 += d_row;
- if (c1 != c2)
- c1 += d_col;
- } while (!done);
-}
+ public void game_reset() {
+ stop_anim();
-public int main(string[] argv) {
- gboard = new int[7,7];
- Intl.setlocale();
+ undo_action.set_enabled(false);
+ hint_action.set_enabled(false);
- application = new Gtk.Application("org.gnome.four-in-a-row", 0);
+ who_starts = (who_starts == PlayerID.PLAYER1)
+ ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
+ player = who_starts;
- Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
- Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "UTF-8");
- Intl.textdomain(Config.GETTEXT_PACKAGE);
+ gameover = true;
+ player_active = false;
+ winner = NOBODY;
+ column = 3;
+ column_moveto = 3;
+ row = 0;
+ row_dropto = 0;
- application.startup.connect(create_app);
- application.activate.connect(activate);
+ clear_board();
+ set_status_message(null);
+ GameBoardView.instance.draw_all();
- var context = new OptionContext();
- context.add_group(Gtk.get_option_group(true));
- try {
- context.parse(ref argv);
- } catch (Error error) {
- print("%s", error.message);
- return 1;
+ move_cursor(column);
+ gameover = false;
+ prompt_player();
+ if (!is_player_human()) {
+ vstr[0] = player == PLAYER1 ? vlevel[p.level[PlayerID.PLAYER1]]
+ : vlevel[p.level[PlayerID.PLAYER2]];
+ game_process_move(playgame((string)vstr) - 1);
+ }
}
- settings = new GLib.Settings("org.gnome.four-in-a-row");
+ public void blink_winner(int n) {
+ /* blink the winner's line(s) n times */
- Environment.set_application_name(_(Config.APPNAME_LONG));
+ if (winner == NOBODY)
+ return;
- prefs_init();
- game_init();
+ blink_t = winner;
+
+ if (Board.instance.is_line_at((Tile)winner, row, column, out blink_r1,
+ out blink_c1, out blink_r2, out blink_c2)) {
+ anim = AnimID.BLINK;
+ blink_on = false;
+ blink_n = n;
+ var temp = new Animate(0);
+ timeout = Timeout.add(SPEED_BLINK, temp.exec);
+ while (timeout!=0)
+ Gtk.main_iteration();
+ }
- if (!Gfx.load_pixmaps())
- return 1;
+ }
- var app_retval = application.run(argv);
+ public void add_actions() {
+ new_game_action = new SimpleAction("new-game", null);
+ new_game_action.activate.connect(this.on_game_new);
+ add_action(new_game_action);
- return app_retval;
-}
+ hint_action = new SimpleAction("hint", null);
+ hint_action.activate.connect(this.on_game_hint);
+ add_action(hint_action);
-public void activate() {
- if (!window.is_visible()) {
- window.show_all();
- Gfx.refresh_pixmaps();
- Gfx.draw_all();
- scorebox_update(); /* update visible player descriptions */
- prompt_player();
- game_reset();
- }
-}
+ undo_action = new SimpleAction("undo-move", null);
+ undo_action.activate.connect(on_game_undo);
+ add_action(undo_action);
-class NextMove {
- int c;
+ set_accels_for_action("app.new-game", {"<Primary>n"});
+ set_accels_for_action("app.hint", {"<Primary>h"});
+ set_accels_for_action("app.undo-move", {"<Primary>z"});
+ set_accels_for_action("app.quit", {"<Primary>q"});
+ set_accels_for_action("app.contents", {"F1"});
- public NextMove(int c) {
- this.c = c;
+ add_action_entries(app_entries, this);
}
- public bool exec() {
- return next_move(c);
+ void on_game_new(Variant? v) {
+ stop_anim();
+ game_reset();
}
-}
-public bool next_move(int c) {
- process_move(c);
- return false;
-}
+ public void draw_line(int r1, int c1, int r2, int c2, int tile) {
+ /* draw a line of 'tile' from r1,c1 to r2,c2 */
-public void game_process_move(int c) {
- process_move(c);
-}
+ bool done = false;
+ int d_row = 0;
+ int d_col = 0;
-public void game_init() {
- anim = AnimID.NONE;
- gameover = true;
- player_active = false;
- player = PlayerID.PLAYER1;
- winner = PlayerID.NOBODY;
- score[PlayerID.PLAYER1] = 0;
- score[PlayerID.PLAYER2] = 0;
- score[PlayerID.NOBODY] = 0;
+ if (r1 < r2)
+ d_row = 1;
+ else if (r1 > r2)
+ d_row = -1;
- who_starts = PlayerID.PLAYER2; /* This gets reversed immediately. */
-
- clear_board();
-}
+ if (c1 < c2)
+ d_col = 1;
+ else if (c1 > c2)
+ d_col = -1;
-void clear_board() {
- int r, c, i;
+ do {
+ done = (r1 == r2 && c1 == c2);
+ Board.instance.set(r1, c1, (Tile) tile);
+ GameBoardView.instance.draw_tile(r1, c1);
+ if (r1 != r2)
+ r1 += d_row;
+ if (c1 != c2)
+ c1 += d_col;
+ } while (!done);
+ }
- for (r = 0; r < 7; r++) {
- for (c = 0; c < 7; c++) {
- gboard[r, c] = Tile.CLEAR;
+ public FourInARow() {
+ Object(application_id: "org.gnome.four-in-a-row",
+ flags: ApplicationFlags.FLAGS_NONE);
+ anim = AnimID.NONE;
+ gameover = true;
+ player_active = false;
+ player = PlayerID.PLAYER1;
+ winner = PlayerID.NOBODY;
+ score[PlayerID.PLAYER1] = 0;
+ score[PlayerID.PLAYER2] = 0;
+ score[PlayerID.NOBODY] = 0;
+
+ who_starts = PlayerID.PLAYER2; /* This gets reversed immediately. */
+
+ clear_board();
+ }
+
+ protected override void activate() {
+ if (!window.is_visible()) {
+ window.show_all();
+ GameBoardView.instance.refresh_pixmaps();
+ GameBoardView.instance.draw_all();
+ scorebox.update(); /* update visible player descriptions */
+ prompt_player();
+ game_reset();
}
}
- for (i = 0; i < SIZE_VSTR; i++)
- vstr[i] = '\0';
-
- vstr[0] = vlevel[Level.WEAK];
- vstr[1] = '0';
- moves = 0;
-}
-
-int first_empty_row(int c) {
- int r = 1;
+ // protected override void startup() {
+ // create_app(this);
+ // }
- while (r < 7 && gboard[r, c] == Tile.CLEAR)
- r++;
- return r - 1;
-}
-
-int get_n_human_players() {
- if (p.level[PlayerID.PLAYER1] != Level.HUMAN && p.level[PlayerID.PLAYER2] != Level.HUMAN)
- return 0;
- if (p.level[PlayerID.PLAYER1] != Level.HUMAN || p.level[PlayerID.PLAYER2] != Level.HUMAN)
- return 1;
- return 2;
-}
-
-bool is_player_human() {
- return player == PLAYER1 ? p.level[PlayerID.PLAYER1] == Level.HUMAN
- : p.level[PlayerID.PLAYER2] == Level.HUMAN;
-}
+ public void prompt_player() {
+ int players = p.get_n_human_players();
+ bool human = is_player_human();
+ string who;
+ string str;
-static void drop_marble(int r, int c) {
- int tile;
- tile = player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+ hint_action.set_enabled(human && !gameover);
- gboard[r, c] = tile;
- Gfx.draw_tile(r, c);
+ switch (players) {
+ case 0:
+ undo_action.set_enabled(false);
+ break;
+ case 1:
+ undo_action.set_enabled((human && moves >1) || (!human && gameover));
+ break;
+ case 2:
+ undo_action.set_enabled(moves > 0);
+ break;
+ }
- column = column_moveto = c;
- row = row_dropto = r;
-}
+ if (gameover && winner == PlayerID.NOBODY) {
+ if (score[PlayerID.NOBODY] == 0)
+ set_status_message(null);
+ else
+ set_status_message(_("It’s a draw!"));
+ return;
+ }
-void drop() {
- Tile tile = player == PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+ switch (players) {
+ case 1:
+ if (human) {
+ if (gameover)
+ set_status_message(_("You win!"));
+ else
+ set_status_message(_("Your Turn"));
+ } else {
+ if (gameover)
+ set_status_message(_("I win!"));
+ else
+ set_status_message(_("I’m Thinking…"));
+ }
+ break;
+ case 2:
+ case 0:
- gboard[row, column] = Tile.CLEAR;
- Gfx.draw_tile(row, column);
+ if (gameover) {
+ who = player == PLAYER1 ? theme_get_player_win(PlayerID.PLAYER1)
+ : theme_get_player_win(PlayerID.PLAYER2);
+ str = _(who);
+ } else if (player_active) {
+ set_status_message(_("Your Turn"));
+ return;
+ } else {
+ who = player == PLAYER1 ? theme_get_player_turn(PlayerID.PLAYER1)
+ : theme_get_player_turn(PlayerID.PLAYER2);
+ str = _(who);
+ }
- row++;
- gboard[row, column] = tile;
- Gfx.draw_tile(row, column);
-}
+ set_status_message(str);
+ break;
+ }
+ }
-void move(int c) {
- gboard[0, column] = Tile.CLEAR;
- Gfx.draw_tile(0, column);
+ public void swap_player() {
+ player = (player == PlayerID.PLAYER1) ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
+ move_cursor(3);
+ prompt_player();
+ }
- column = c;
- gboard[0, c] = player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
+ public void game_process_move(int c) {
+ process_move(c);
+ }
- Gfx.draw_tile(0, c);
-}
+ public void play_sound(SoundID id) {
+ string name;
-static void move_cursor(int c) {
- move(c);
- column = column_moveto = c;
- row = row_dropto = 0;
-}
+ if (!p.do_sound)
+ return;
-void swap_player() {
- player = (player == PlayerID.PLAYER1) ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
- move_cursor(3);
- prompt_player();
-}
+ switch (id) {
+ case SoundID.DROP:
+ name = "slide";
+ break;
+ case SoundID.I_WIN:
+ name = "reverse";
+ break;
+ case SoundID.YOU_WIN:
+ name = "bonus";
+ break;
+ case SoundID.PLAYER_WIN:
+ name = "bonus";
+ break;
+ case SoundID.DRAWN_GAME:
+ name = "reverse";
+ break;
+ case SoundID.COLUMN_FULL:
+ name = "bad";
+ break;
+ default:
+ return;
+ }
-void set_status_message(string? message) {
- headerbar.set_title(message);
-}
+ string filename, path;
-static void blink_tile(int r, int c, int t, int n) {
- if (timeout != 0)
- return;
- blink_r1 = r;
- blink_c1 = c;
- blink_r2 = r;
- blink_c2 = c;
- blink_t = t;
- blink_n = n;
- blink_on = false;
- anim = AnimID.BLINK;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_BLINK, temp.exec);
-}
+ filename = name + ".ogg";
+ path = Path.build_filename(Config.SOUND_DIRECTORY, filename);
-void stop_anim() {
- if (timeout == 0)
- return;
- anim = AnimID.NONE;
- Source.remove(timeout);
- timeout = 0;
-}
+ CanberraGtk.context_get().play(
+ id,
+ Canberra.PROP_MEDIA_NAME, name,
+ Canberra.PROP_MEDIA_FILENAME, path);
-bool on_drawarea_resize(Gtk.Widget w, Gdk.EventConfigure e) {
- Gfx.resize(w);
- return true;
-}
+ }
-bool on_drawarea_draw(Gtk.Widget w, Cairo.Context cr) {
- Gfx.expose(cr);
- return false;
-}
+ public void process_move3(int c) {
+ play_sound(SoundID.DROP);
-void on_game_undo(SimpleAction action, Variant? parameter) {
- int r, c;
+ vstr[++moves] = '1' + (char)c;
+ vstr[moves + 1] = '0';
- if (timeout != 0)
- return;
- c = vstr[moves] - '0' - 1;
- r = first_empty_row(c) + 1;
- vstr[moves] = '0';
- vstr[moves + 1] = '\0';
- moves--;
+ check_game_state();
- if (gameover) {
- score[winner]--;
- scorebox_update();
- gameover = false;
- prompt_player();
- } else {
- swap_player();
- }
- move_cursor(c);
-
- gboard[r, c] = Tile.CLEAR;
- Gfx.draw_tile(r, c);
-
- if (get_n_human_players() == 1 && !is_player_human()) {
- if (moves > 0) {
- c = vstr[moves] - '0' - 1;
- r = first_empty_row(c) + 1;
- vstr[moves] = '0';
- vstr[moves + 1] = '\0';
- moves--;
+ if (gameover) {
+ score[winner]++;
+ scorebox.update();
+ prompt_player();
+ } else {
swap_player();
- move_cursor(c);
- gboard[r, c] = Tile.CLEAR;
- Gfx.draw_tile(r, c);
+ if (!is_player_human()) {
+ vstr[0] = player == PlayerID.PLAYER1 ? vlevel[p.level[PlayerID.PLAYER1]]
+ : vlevel[p.level[PlayerID.PLAYER2]];
+ c = playgame((string)vstr) - 1;
+ if (c < 0)
+ gameover = true;
+ var nm = new NextMove(c);
+ Timeout.add(SPEED_DROP, nm.exec);
+ }
}
}
-}
-void on_game_scores(SimpleAction action, Variant? parameter) {
- Gtk.Grid grid, grid2;
- Gtk.Widget icon;
- if (scorebox != null) {
- scorebox.present();
- return;
- }
+ public void game_init() {
+ anim = AnimID.NONE;
+ gameover = true;
+ player_active = false;
+ player = PlayerID.PLAYER1;
+ winner = PlayerID.NOBODY;
+ score[PlayerID.PLAYER1] = 0;
+ score[PlayerID.PLAYER2] = 0;
+ score[PlayerID.NOBODY] = 0;
- scorebox = new Gtk.Dialog.with_buttons(_("Scores"), window,
- Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.USE_HEADER_BAR);
+ who_starts = PlayerID.PLAYER2; /* This gets reversed immediately. */
- scorebox.set_resizable(false);
- scorebox.set_border_width(5);
- scorebox.get_content_area().set_spacing(2);
+ clear_board();
+ }
- grid = new Gtk.Grid();
- grid.set_halign(Gtk.Align.CENTER);
- grid.set_row_spacing(6);
- grid.set_orientation(Gtk.Orientation.VERTICAL);
- grid.set_border_width(5);
+ public bool is_player_human() {
+ return player == PLAYER1 ? p.level[PlayerID.PLAYER1] == Level.HUMAN
+ : p.level[PlayerID.PLAYER2] == Level.HUMAN;
+ }
- scorebox.get_content_area().pack_start(grid);
+ public void process_move2(int c) {
+ int r = Board.instance.first_empty_row(c);
+ if (r > 0) {
+ row = 0;
+ row_dropto = r;
+ anim = AnimID.DROP;
+ var temp = new Animate(c);
+ timeout = Timeout.add(SPEED_DROP, temp.exec);
+ } else {
+ application.play_sound(SoundID.COLUMN_FULL);
+ }
+ }
- grid2 = new Gtk.Grid();
- grid.add(grid2);
- grid2.set_column_spacing(6);
+ public void process_move(int c) {
+ if (timeout != 0) {
+ var temp = new Animate(c);
+ Timeout.add(SPEED_DROP, temp.exec);
+ return;
+ }
- label_name[PlayerID.PLAYER1] = new Gtk.Label(null);
- grid2.attach(label_name[PlayerID.PLAYER1], 0, 0, 1, 1);
- label_name[PlayerID.PLAYER1].set_xalign(0);
- label_name[PlayerID.PLAYER1].set_yalign(0.5f);
+ column_moveto = c;
+ anim = AnimID.MOVE;
+ var temp = new Animate(c);
+ timeout = Timeout.add(SPEED_DROP, temp.exec);
+ }
- label_score[PlayerID.PLAYER1] = new Gtk.Label(null);
- grid2.attach(label_score[PlayerID.PLAYER1], 1, 0, 1, 1);
- label_score[PlayerID.PLAYER1].set_xalign(0);
- label_score[PlayerID.PLAYER1].set_yalign(0.5f);
+ void drop_marble(int r, int c) {
+ Tile tile = player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
- label_name[PlayerID.PLAYER2] = new Gtk.Label(null);
- grid2.attach(label_name[PlayerID.PLAYER2], 0, 1, 1, 1);
- label_name[PlayerID.PLAYER2].set_xalign(0);
- label_name[PlayerID.PLAYER2].set_yalign(0.5f);
+ Board.instance.set(r, c, tile);
+ GameBoardView.instance.draw_tile(r, c);
- label_score[PlayerID.PLAYER2] = new Gtk.Label(null);
- grid2.attach(label_score[PlayerID.PLAYER2], 1, 0, 1, 1);
- label_score[PlayerID.PLAYER2].set_xalign(0);
- label_score[PlayerID.PLAYER2].set_yalign(0.5f);
+ column = column_moveto = c;
+ row = row_dropto = r;
+ }
- label_name[PlayerID.NOBODY] = new Gtk.Label(_("Drawn:"));
- grid2.attach(label_name[PlayerID.NOBODY], 0, 2, 1, 1);
- label_name[PlayerID.NOBODY].set_xalign(0);
- label_name[PlayerID.NOBODY].set_yalign(0.5f);
+ public void drop() {
+ Tile tile = player == PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2;
- label_score[PlayerID.NOBODY] = new Gtk.Label(null);
- grid2.attach(label_score[PlayerID.NOBODY], 1, 0, 1, 1);
- label_score[PlayerID.NOBODY].set_xalign(0);
- label_score[PlayerID.NOBODY].set_yalign(0.5f);
+ Board.instance.set(row, column, Tile.CLEAR);
+ GameBoardView.instance.draw_tile(row, column);
- scorebox.show_all();
+ row++;
+ Board.instance.set(row, column, tile);
+ GameBoardView.instance.draw_tile(row, column);
+ }
- scorebox_update();
-}
+ public void move(int c) {
+ Board.instance.set(0, column, Tile.CLEAR);
+ GameBoardView.instance.draw_tile(0, column);
-void on_game_exit(SimpleAction action, Variant? parameter) {
- stop_anim();
- application.quit();
-}
+ column = c;
+ Board.instance.set(0, c, player == PlayerID.PLAYER1 ? Tile.PLAYER1 : Tile.PLAYER2);
-void process_move2(int c) {
- int r = first_empty_row(c);
- if (r > 0) {
- row = 0;
- row_dropto = r;
- anim = AnimID.DROP;
- var temp = new Animate(c);
- timeout = Timeout.add(SPEED_DROP, temp.exec);
- } else {
- play_sound(SoundID.COLUMN_FULL);
+ GameBoardView.instance.draw_tile(0, c);
}
-}
-bool is_vline_at(PlayerID p, int r, int c, int * r1, int * c1, int * r2, int * c2) {
- *r1 = *r2 = r;
- *c1 = *c2 = c;
- while (*r1 > 1 && gboard[*r1 - 1, c] == p)
- *r1 = *r1 - 1;
- while (*r2 < 6 && gboard[*r2 + 1, c] == p)
- *r2 = *r2 + 1;
- if (*r2 - *r1 >= 3)
- return true;
- return false;
-}
-
-bool is_dline1_at(PlayerID p, int r, int c, int * r1, int * c1, int * r2, int * c2) {
- /* upper left to lower right */
- *r1 = *r2 = r;
- *c1 = *c2 = c;
- while (*c1 > 0 && *r1 > 1 && gboard[*r1 - 1, *c1 - 1] == p) {
- *r1 = *r1 - 1;
- *c1 = *c1 - 1;
- }
- while (*c2 < 6 && *r2 < 6 && gboard[*r2 + 1, *c2 + 1] == p) {
- *r2 = *r2 + 1;
- *c2 = *c2 + 1;
+ public void move_cursor(int c) {
+ move(c);
+ column = column_moveto = c;
+ row = row_dropto = 0;
}
- if (*r2 - *r1 >= 3)
- return true;
- return false;
-}
-
-bool is_line_at(PlayerID p, int r, int c) {
- int r1, r2, c1, c2;
-
- return is_hline_at(p, r, c, &r1, &c1, &r2, &c2) ||
- is_vline_at(p, r, c, &r1, &c1, &r2, &c2) ||
- is_dline1_at(p, r, c, &r1, &c1, &r2, &c2) ||
- is_dline2_at(p, r, c, &r1, &c1, &r2, &c2);
-}
-bool is_dline2_at(PlayerID p, int r, int c, int * r1, int * c1, int * r2, int * c2) {
- /* upper right to lower left */
- *r1 = *r2 = r;
- *c1 = *c2 = c;
- while (*c1 < 6 && *r1 > 1 && gboard[*r1 - 1, *c1 + 1] == p) {
- *r1 = *r1 - 1;
- *c1 = *c1 + 1;
- }
- while (*c2 > 0 && *r2 < 6 && gboard[*r2 + 1, *c2 - 1] == p) {
- *r2 = *r2 + 1;
- *c2 = *c2 - 1;
+ void set_status_message(string? message) {
+ headerbar.set_title(message);
}
- if (*r2 - *r1 >= 3)
- return true;
- return false;
-}
-bool is_hline_at(PlayerID p, int r, int c, int * r1, int * c1, int * r2, int * c2) {
- *r1 = *r2 = r;
- *c1 = *c2 = c;
- while (*c1 > 0 && gboard[r, *c1 - 1] == p)
- *c1 = *c1 - 1;
- while (*c2 < 6 && gboard[r, *c2 + 1] == p)
- *c2 = *c2 + 1;
- if (*c2 - *c1 >= 3)
- return true;
- return false;
-}
+ class NextMove {
+ int c;
-void scorebox_reset() {
- score[PlayerID.PLAYER1] = 0;
- score[PlayerID.PLAYER2] = 0;
- score[PlayerID.NOBODY] = 0;
- scorebox_update();
-}
+ public NextMove(int c) {
+ this.c = c;
+ }
-void process_move(int c) {
- if (timeout != 0) {
- var temp = new Animate(c);
- Timeout.add(SPEED_DROP, temp.exec);
- return;
+ public bool exec() {
+ application.process_move(c);
+ return false;
+ }
}
- column_moveto = c;
- anim = AnimID.MOVE;
- var temp = new Animate(c);
- timeout = Timeout.add(SPEED_DROP, temp.exec);
-}
+ void stop_anim() {
+ if (timeout == 0)
+ return;
+ anim = AnimID.NONE;
+ Source.remove(timeout);
+ timeout = 0;
+ }
-void on_help_about(SimpleAction action, Variant? parameter) {
- const string authors[] = {"Tim Musson <trmusson ihug co nz>",
- "David Neary <bolsh gimp org>",
- "Nikhar Agrawal <nikharagrawal2006 gmail com>",
- "Jacob Humphrey <jacob ryan humphrey gmail com"
- };
+ void clear_board() {
+ Board.instance.clear();
- const string artists[] = { "Alan Horkan",
- "Anatol Drlicek",
- "Based on the Faenza icon theme by Matthieu James"
- };
+ for (var i = 0; i < SIZE_VSTR; i++)
+ vstr[i] = '\0';
- const string documenters[] = {"Timothy Musson"};
-
- Gtk.show_about_dialog(window,
- name: _(Config.APPNAME_LONG),
- version: Config.VERSION,
- copyright: "Copyright © 1999–2008 Tim Musson and David Neary\nCopyright © 2014 Michael
Catanzaro\nCopyright © 2018 Jacob Humphrey",
- license_type: Gtk.License.GPL_2_0,
- comments: _("Connect four in a row to win"),
- authors: authors,
- documenters: documenters,
- artists: artists,
- translator_credits: _("translator-credits"),
- logo_icon_name: "four-in-a-row",
- website: "https://wiki.gnome.org/Apps/Four-in-a-row");
-}
-
-void check_game_state() {
- if (is_line_at(player, row, column)) {
- gameover = true;
- winner = player;
- switch (get_n_human_players()) {
- case 1:
- play_sound(is_player_human() ? SoundID.YOU_WIN : SoundID.I_WIN);
- break;
- case 0:
- case 2:
- play_sound(SoundID.PLAYER_WIN);
- break;
- }
- blink_winner(6);
- } else if (moves == 42) {
- gameover = true;
- winner = NOBODY;
- play_sound(SoundID.DRAWN_GAME);
+ vstr[0] = vlevel[Level.WEAK];
+ vstr[1] = '0';
+ moves = 0;
}
-}
-void on_help_contents(SimpleAction action, Variant? parameter) {
- try {
- Gtk.show_uri(window.get_screen(),
- "help:four-in-a-row",
- Gtk.get_current_event_time());
- } catch(Error error) {
- warning("Failed to show help: %s", error.message);
+ void blink_tile(int r, int c, int t, int n) {
+ if (timeout != 0)
+ return;
+ blink_r1 = r;
+ blink_c1 = c;
+ blink_r2 = r;
+ blink_c2 = c;
+ blink_t = t;
+ blink_n = n;
+ blink_on = false;
+ anim = AnimID.BLINK;
+ var temp = new Animate(0);
+ timeout = Timeout.add(SPEED_BLINK, temp.exec);
}
-}
-void process_move3(int c) {
- play_sound(SoundID.DROP);
+ void on_game_hint(SimpleAction action, Variant? parameter) {
+ string s;
+ int c;
- vstr[++moves] = '1' + (char)c;
- vstr[moves + 1] = '0';
+ if (timeout != 0)
+ return;
+ if (gameover)
+ return;
- check_game_state();
+ hint_action.set_enabled(false);
+ undo_action.set_enabled(false);
- if (gameover) {
- score[winner]++;
- scorebox_update();
- prompt_player();
- } else {
- swap_player();
- if (!is_player_human()) {
- vstr[0] = player == PlayerID.PLAYER1 ? vlevel[p.level[PlayerID.PLAYER1]]
- : vlevel[p.level[PlayerID.PLAYER2]];
- c = playgame((string)vstr) - 1;
- if (c < 0)
- gameover = true;
- var nm = new NextMove(c);
- Timeout.add(SPEED_DROP, nm.exec);
- }
- }
-}
+ application.set_status_message(_("I’m Thinking…"));
-void game_reset() {
- stop_anim();
-
- undo_action.set_enabled(false);
- hint_action.set_enabled(false);
-
- who_starts = (who_starts == PlayerID.PLAYER1)
- ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
- player = who_starts;
-
- gameover = true;
- player_active = false;
- winner = NOBODY;
- column = 3;
- column_moveto = 3;
- row = 0;
- row_dropto = 0;
-
- clear_board();
- set_status_message(null);
- Gfx.draw_all();
-
- move_cursor(column);
- gameover = false;
- prompt_player();
- if (!is_player_human()) {
- vstr[0] = player == PLAYER1 ? vlevel[p.level[PlayerID.PLAYER1]]
- : vlevel[p.level[PlayerID.PLAYER2]];
- game_process_move(playgame((string)vstr) - 1);
- }
-}
+ vstr[0] = vlevel[Level.STRONG];
+ c = playgame((string)vstr) - 1;
-void play_sound(SoundID id) {
- string name;
-
- if (!p.do_sound)
- return;
-
- switch (id) {
- case SoundID.DROP:
- name = "slide";
- break;
- case SoundID.I_WIN:
- name = "reverse";
- break;
- case SoundID.YOU_WIN:
- name = "bonus";
- break;
- case SoundID.PLAYER_WIN:
- name = "bonus";
- break;
- case SoundID.DRAWN_GAME:
- name = "reverse";
- break;
- case SoundID.COLUMN_FULL:
- name = "bad";
- break;
- default:
- return;
- }
+ column_moveto = c;
+ while (timeout != 0)
+ Gtk.main_iteration();
+ anim = AnimID.HINT;
+ var temp = new Animate(0);
+ timeout = Timeout.add(SPEED_MOVE, temp.exec);
- string filename, path;
+ application.blink_tile(0, c, Board.instance.get(0, c), 6);
- filename = name + ".ogg";
- path = Path.build_filename(Config.SOUND_DIRECTORY, filename);
+ s = _("Hint: Column ")+ (c + 1).to_string();
+ application.set_status_message(s);
- CanberraGtk.context_get().play(
- id,
- Canberra.PROP_MEDIA_NAME, name,
- Canberra.PROP_MEDIA_FILENAME, path);
+ if (moves <= 0 || (moves == 1 && application.is_player_human()))
+ undo_action.set_enabled(false);
+ else
+ undo_action.set_enabled(true);
+ }
-}
+ void on_game_scores(SimpleAction action, Variant? parameter) {
+ if (scorebox != null) {
+ scorebox.present();
+ return;
+ }
-class Animate {
- int c;
- public Animate(int c) {
- this.c = c;
+ scorebox = new Scorebox();
+ scorebox.show_all();
+ scorebox.update();
}
- public bool exec() {
- return on_animate(c);
+ void on_game_exit(SimpleAction action, Variant? parameter) {
+ stop_anim();
+ quit();
}
-}
-bool on_animate(int c = 0) {
- if (anim == AnimID.NONE)
- return false;
-
- switch (anim) {
- case AnimID.NONE:
- break;
- case AnimID.HINT:
- case AnimID.MOVE:
- if (column < column_moveto) {
- move(column + 1);
- } else if (column > column_moveto) {
- move(column - 1);
- } else {
- timeout = 0;
- if (anim == AnimID.MOVE) {
- anim = AnimID.NONE;
- process_move2(c);
- } else {
- anim = AnimID.NONE;
- }
- return false;
+ class Animate {
+ int c;
+ public Animate(int c) {
+ this.c = c;
}
- break;
- case AnimID.DROP:
- if (row < row_dropto) {
- drop();
- } else {
- anim = AnimID.NONE;
- timeout = 0;
- process_move3(c);
- return false;
- }
- break;
- case AnimID.BLINK:
- draw_line(blink_r1, blink_c1, blink_r2, blink_c2, blink_on ? blink_t
- : Tile.CLEAR);
- blink_n--;
- if (blink_n <= 0 && blink_on) {
- anim = AnimID.NONE;
- timeout = 0;
+
+ public bool exec() {
+ if (anim == AnimID.NONE)
return false;
+
+ switch (anim) {
+ case AnimID.NONE:
+ break;
+ case AnimID.HINT:
+ case AnimID.MOVE:
+ if (column < column_moveto) {
+ application.move(column + 1);
+ } else if (column > column_moveto) {
+ application.move(column - 1);
+ } else {
+ timeout = 0;
+ if (anim == AnimID.MOVE) {
+ anim = AnimID.NONE;
+ application.process_move2(c);
+ } else {
+ anim = AnimID.NONE;
+ }
+ return false;
+ }
+ break;
+ case AnimID.DROP:
+ if (row < row_dropto) {
+ application.drop();
+ } else {
+ anim = AnimID.NONE;
+ timeout = 0;
+ application.process_move3(c);
+ return false;
+ }
+ break;
+ case AnimID.BLINK:
+ application.draw_line(blink_r1, blink_c1, blink_r2, blink_c2, blink_on ? blink_t
+ : Tile.CLEAR);
+ blink_n--;
+ if (blink_n <= 0 && blink_on) {
+ anim = AnimID.NONE;
+ timeout = 0;
+ return false;
+ }
+ blink_on = !blink_on;
+ break;
+ }
+ return true;
}
- blink_on = !blink_on;
- break;
}
- return true;
-}
-bool on_key_press(Gtk.Widget w, Gdk.EventKey e) {
- if ((player_active) || timeout != 0 ||
- (e.keyval != p.keypress[Move.LEFT] &&
- e.keyval != p.keypress[Move.RIGHT] &&
- e.keyval != p.keypress[Move.DROP])) {
- return false;
- }
+ void on_game_undo(SimpleAction action, Variant? parameter) {
+ int r, c;
- if (gameover) {
- blink_winner(2);
- return true;
- }
+ if (timeout != 0)
+ return;
+ c = vstr[moves] - '0' - 1;
+ r = Board.instance.first_empty_row(c) + 1;
+ vstr[moves] = '0';
+ vstr[moves + 1] = '\0';
+ moves--;
- if (e.keyval == p.keypress[Move.LEFT] && column != 0) {
- column_moveto--;
- move_cursor(column_moveto);
- } else if (e.keyval == p.keypress[Move.RIGHT] && column < 6) {
- column_moveto++;
- move_cursor(column_moveto);
- } else if (e.keyval == p.keypress[Move.DROP]) {
- game_process_move(column);
+ if (gameover) {
+ score[winner]--;
+ scorebox.update();
+ gameover = false;
+ prompt_player();
+ } else {
+ swap_player();
+ }
+ move_cursor(c);
+
+ Board.instance.set(r, c, Tile.CLEAR);
+ GameBoardView.instance.draw_tile(r, c);
+
+ if (p.get_n_human_players() == 1 && !application.is_player_human()) {
+ if (moves > 0) {
+ c = vstr[moves] - '0' - 1;
+ r = Board.instance.first_empty_row(c) + 1;
+ vstr[moves] = '0';
+ vstr[moves + 1] = '\0';
+ moves--;
+ swap_player();
+ move_cursor(c);
+ Board.instance.set(r, c, Tile.CLEAR);
+ GameBoardView.instance.draw_tile(r, c);
+ }
+ }
}
- return true;
-}
-
-void blink_winner(int n) {
- /* blink the winner's line(s) n times */
- if (winner == NOBODY)
- return;
- blink_t = winner;
- if (is_hline_at(winner, row, column, &blink_r1, &blink_c1, &blink_r2, &blink_c2)) {
- anim = AnimID.BLINK;
- blink_on = false;
- blink_n = n;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_BLINK, temp.exec);
- while (timeout!=0)
- Gtk.main_iteration();
+ void on_settings_preferences(SimpleAction action, Variant? parameter) {
+ prefsbox_open();
}
- if (is_vline_at(winner, row, column, &blink_r1, &blink_c1, &blink_r2, &blink_c2)) {
- anim = AnimID.BLINK;
- blink_on = false;
- blink_n = n;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_BLINK, temp.exec);
- while (timeout!=0)
- Gtk.main_iteration();
- }
+ void on_help_about(SimpleAction action, Variant? parameter) {
+ const string authors[] = {"Tim Musson <trmusson ihug co nz>",
+ "David Neary <bolsh gimp org>",
+ "Nikhar Agrawal <nikharagrawal2006 gmail com>",
+ "Jacob Humphrey <jacob ryan humphrey gmail com"
+ };
- if (is_dline1_at(winner, row, column, &blink_r1, &blink_c1, &blink_r2, &blink_c2)) {
- anim = AnimID.BLINK;
- blink_on = false;
- blink_n = n;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_BLINK, temp.exec);
- while (timeout!=0)
- Gtk.main_iteration();
- }
+ const string artists[] = { "Alan Horkan",
+ "Anatol Drlicek",
+ "Based on the Faenza icon theme by Matthieu James"
+ };
- if (is_dline2_at(winner, row, column, &blink_r1, &blink_c1, &blink_r2, &blink_c2)) {
- anim = AnimID.BLINK;
- blink_on = false;
- blink_n = n;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_BLINK, temp.exec);
- while (timeout!=0)
- Gtk.main_iteration();
+ const string documenters[] = {"Timothy Musson"};
+
+ Gtk.show_about_dialog(window,
+ name: _(Config.APPNAME_LONG),
+ version: Config.VERSION,
+ copyright: "Copyright © 1999–2008 Tim Musson and David Neary" +
+ "Copyright © 2014 Michael Catanzaro\nCopyright © 2018 Jacob Humphrey",
+ license_type: Gtk.License.GPL_2_0,
+ comments: _("Connect four in a row to win"),
+ authors: authors,
+ documenters: documenters,
+ artists: artists,
+ translator_credits: _("translator-credits"),
+ logo_icon_name: "four-in-a-row",
+ website: "https://wiki.gnome.org/Apps/Four-in-a-row");
}
-}
-bool on_button_press(Gtk.Widget w, Gdk.EventButton e) {
- int x, y;
- if (player_active) {
- return false;
+ void on_help_contents(SimpleAction action, Variant? parameter) {
+ try {
+ Gtk.show_uri_on_window(window,
+ "help:four-in-a-row",
+ Gtk.get_current_event_time());
+ } catch(Error error) {
+ warning("Failed to show help: %s", error.message);
+ }
}
- if (gameover && timeout == 0) {
- blink_winner(2);
- } else if (is_player_human() && timeout == 0) {
- w.get_window().get_device_position(e.device, out x, out y, null);
- game_process_move(Gfx.get_column(x));
+ void check_game_state() {
+ if (Board.instance.is_line_at((Tile)player, row, column)) {
+ gameover = true;
+ winner = player;
+ switch (p.get_n_human_players()) {
+ case 1:
+ play_sound(is_player_human() ? SoundID.YOU_WIN : SoundID.I_WIN);
+ break;
+ case 0:
+ case 2:
+ play_sound(SoundID.PLAYER_WIN);
+ break;
+ }
+ blink_winner(6);
+ } else if (moves == 42) {
+ gameover = true;
+ winner = NOBODY;
+ play_sound(SoundID.DRAWN_GAME);
+ }
}
- return true;
-}
+ protected override void startup() {
+ base.startup();
+ Gtk.AspectFrame frame;
+ GLib.Menu app_menu, section;
-void scorebox_update() {
- string s;
+ Gtk.Builder builder;
+ Gtk.CssProvider css_provider;
- if (scorebox == null)
- return;
+ Gtk.Window.set_default_icon_name("four-in-a-row");
- if (get_n_human_players() == 1) {
- if (p.level[PlayerID.PLAYER1] == Level.HUMAN) {
- label_score[PlayerID.PLAYER1].set_text(_("You:"));
- label_score[PlayerID.PLAYER2].set_text(_("Me:"));
- } else {
- label_score[PlayerID.PLAYER2].set_text(_("You:"));
- label_score[PlayerID.PLAYER1].set_text(_("Me:"));
+ css_provider = new Gtk.CssProvider();
+ try {
+ css_provider.load_from_data("GtkButtonBox {-GtkButtonBox-child-internal-pad-x:0;}\0");
+ } catch (Error error) {
+ stderr.printf("Could not load UI: %s\n", error.message);
+ return;
}
- } else {
- label_name[PlayerID.PLAYER1].set_text(theme_get_player(PlayerID.PLAYER1));
- label_name[PlayerID.PLAYER2].set_text(theme_get_player(PlayerID.PLAYER2));
- }
+ Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
+ css_provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
- label_score[PlayerID.PLAYER1].set_text((string)score[PlayerID.PLAYER1]);
- label_score[PlayerID.PLAYER2].set_text((string)score[PlayerID.PLAYER2]);
- label_score[PlayerID.NOBODY].set_text((string)score[PlayerID.NOBODY]);
+ builder = new Gtk.Builder.from_file(Config.DATA_DIRECTORY + "/four-in-a-row.ui");
-}
+ window = builder.get_object("fiar-window") as Gtk.ApplicationWindow;
+ window.application = this;
+ window.set_default_size(DEFAULT_WIDTH, DEFAULT_HEIGHT); /* TODO save size & state */
-void on_settings_preferences(SimpleAction action, Variant? parameter) {
- prefsbox_open();
-}
+ headerbar = builder.get_object("headerbar") as Gtk.HeaderBar;
-void on_game_hint(SimpleAction action, Variant? parameter) {
- string s;
- int c;
+ add_actions();
- if (timeout != 0)
- return;
- if (gameover)
- return;
+ app_menu = new GLib.Menu();
+ section = new GLib.Menu();
+ app_menu.append_section(null, section);
+ section.append(_("_Scores"), "app.scores");
+ section.append(_("_Preferences"), "app.preferences");
+ section = new GLib.Menu();
+ app_menu.append_section(null, section);
+ section.append(_("_Help"), "app.help");
+ section.append(_("_About"), "app.about");
+ section.append(_("_Quit"), "app.quit");
- hint_action.set_enabled(false);
- undo_action.set_enabled(false);
+ app_menu = app_menu;
- set_status_message(_("I’m Thinking…"));
+ frame = builder.get_object("frame") as Gtk.AspectFrame;
- vstr[0] = vlevel[Level.STRONG];
- c = playgame((string)vstr) - 1;
+ frame.add(GameBoardView.instance);
- column_moveto = c;
- while (timeout != 0)
- Gtk.main_iteration();
- anim = AnimID.HINT;
- var temp = new Animate(0);
- timeout = Timeout.add(SPEED_MOVE, temp.exec);
+ hint_action.set_enabled(false);
+ undo_action.set_enabled(false);
+ }
- blink_tile(0, c, gboard[0, c], 6);
+ Gtk.HeaderBar headerbar;
+}
- s = _("Hint: Column ")+ (c + 1).to_string();
- set_status_message(s);
- g_free(s);
+SimpleAction hint_action;
+SimpleAction undo_action;
+SimpleAction new_game_action;
- if (moves <= 0 || (moves == 1 && is_player_human()))
- undo_action.set_enabled(false);
- else
- undo_action.set_enabled(true);
-}
+FourInARow? application;
+Gtk.ApplicationWindow window;
+Scorebox? scorebox = null;
-const GLib.ActionEntry app_entries[] = {
- {"new-game", on_game_new, null, null, null},
- {"undo-move", on_game_undo, null, null, null},
- {"hint", on_game_hint, null, null, null},
- {"scores", on_game_scores, null, null, null},
- {"quit", on_game_exit, null, null, null},
- {"preferences", on_settings_preferences, null, null, null},
- {"help", on_help_contents, null, null, null},
- {"about", on_help_about, null, null, null}
-};
+PlayerID player;
+PlayerID winner;
+PlayerID who_starts;
+int score[3];
+AnimID anim;
+char vstr[53];
+int moves;
+int column;
+int column_moveto;
+int row;
+int row_dropto;
+int blink_r1 = 0;
+int blink_c1 = 0;
+int blink_r2 = 0;
+int blink_c2 = 0;
+int blink_t = 0;
+int blink_n = 0;
+bool blink_on = false;
+uint timeout = 0;
-void create_app(GLib.Application app) {
- Gtk.AspectFrame frame;
- GLib.Menu app_menu, section;
+public int main(string[] argv) {
+ Intl.setlocale();
- Gtk.Builder builder;
- Gtk.CssProvider css_provider;
+ application = new FourInARow();
- Gtk.Window.set_default_icon_name("four-in-a-row");
+ Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
+ Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "UTF-8");
+ Intl.textdomain(Config.GETTEXT_PACKAGE);
- css_provider = new Gtk.CssProvider();
+ var context = new OptionContext();
+ context.add_group(Gtk.get_option_group(true));
try {
- css_provider.load_from_data("GtkButtonBox{-GtkButtonBox-child-internal-pad-x:0;}\0");
+ context.parse(ref argv);
} catch (Error error) {
- stderr.printf("Could not load UI: %s\n", error.message);
- return;
+ print("%s", error.message);
+ return 1;
}
- Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
- css_provider,
- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- builder = new Gtk.Builder.from_file(Config.DATA_DIRECTORY + "/four-in-a-row.ui");
-
- window = (Gtk.Window) builder.get_object("fiar-window");
- window.application = application;
- window.set_default_size(DEFAULT_WIDTH, DEFAULT_HEIGHT); /* TODO save size & state */
-
- headerbar = (Gtk.HeaderBar) builder.get_object("headerbar");
-
- application.add_action_entries(app_entries, application);
- application.add_accelerator("<Primary>n", "app.new-game", null);
- application.add_accelerator("<Primary>h", "app.hint", null);
- application.add_accelerator("<Primary>z", "app.undo-move", null);
- application.add_accelerator("<Primary>q", "app.quit", null);
- application.add_accelerator("F1", "app.contents", null);
-
- app_menu = new GLib.Menu();
- section = new GLib.Menu();
- app_menu.append_section(null, section);
- section.append(_("_Scores"), "app.scores");
- section.append(_("_Preferences"), "app.preferences");
- section = new GLib.Menu();
- app_menu.append_section(null, section);
- section.append(_("_Help"), "app.help");
- section.append(_("_About"), "app.about");
- section.append(_("_Quit"), "app.quit");
-
- new_game_action = (GLib.SimpleAction) application.lookup_action("new-game");
- undo_action = (GLib.SimpleAction) application.lookup_action("undo-move");
- hint_action = (GLib.SimpleAction) application.lookup_action("hint");
-
- application.app_menu = app_menu;
-
- frame = (Gtk.AspectFrame) builder.get_object("frame");
-
- drawarea = new Gtk.DrawingArea();
- /* set a min size to avoid pathological behavior of gtk when scaling down */
- drawarea.set_size_request(350, 350);
- drawarea.halign = Gtk.Align.FILL;
- drawarea.valign = Gtk.Align.FILL;
- frame.add(drawarea);
-
- drawarea.events = Gdk.EventMask.EXPOSURE_MASK |
- Gdk.EventMask.BUTTON_PRESS_MASK |
- Gdk.EventMask.BUTTON_RELEASE_MASK;
- drawarea.configure_event.connect(on_drawarea_resize);
- drawarea.draw.connect(on_drawarea_draw);
- drawarea.button_press_event.connect(on_button_press);
- drawarea.key_press_event.connect(on_key_press);
-
- hint_action.set_enabled(false);
- undo_action.set_enabled(false);
-}
-void on_dialog_close(Gtk.Widget w, int response_id) {
- w.hide();
-}
+ settings = new GLib.Settings("org.gnome.four-in-a-row");
-void prompt_player() {
- int players = get_n_human_players();
- bool human = is_player_human();
- string who;
- string str;
+ Environment.set_application_name(_(Config.APPNAME_LONG));
- hint_action.set_enabled(human && !gameover);
+ p = new Prefs();
+ application.game_init();
- switch (players) {
- case 0:
- undo_action.set_enabled(false);
- break;
- case 1:
- undo_action.set_enabled((human && moves >1) || (!human && gameover));
- break;
- case 2:
- undo_action.set_enabled(moves > 0);
- break;
- }
+ if (!GameBoardView.instance.load_pixmaps())
+ return 1;
- if (gameover && winner == PlayerID.NOBODY) {
- if (score[PlayerID.NOBODY] == 0)
- set_status_message(null);
- else
- set_status_message(_("It’s a draw!"));
- return;
- }
+ var app_retval = application.run(argv);
- switch (players) {
- case 1:
- if (human) {
- if (gameover)
- set_status_message(_("You win!"));
- else
- set_status_message(_("Your Turn"));
- } else {
- if (gameover)
- set_status_message(_("I win!"));
- else
- set_status_message(_("I’m Thinking…"));
- }
- break;
- case 2:
- case 0:
+ return app_retval;
+}
- if (gameover) {
- who = player == PLAYER1 ? theme_get_player_win(PlayerID.PLAYER1)
- : theme_get_player_win(PlayerID.PLAYER2);
- str = _(who);
- } else if (player_active) {
- set_status_message(_("Your Turn"));
- return;
- } else {
- who = player == PLAYER1 ? theme_get_player_turn(PlayerID.PLAYER1)
- : theme_get_player_turn(PlayerID.PLAYER2);
- str = _(who);
- }
- set_status_message(str);
- break;
- }
-}
diff --git a/src/prefs.vala b/src/prefs.vala
index 567d99b..37df47d 100644
--- a/src/prefs.vala
+++ b/src/prefs.vala
@@ -19,11 +19,65 @@
* along with GNOME Four-in-a-row. If not, see <http://www.gnu.org/licenses/>.
*/
-struct Prefs {
- bool do_sound;
- int theme_id;
- Level level[2];
- int keypress[3];
+class Prefs {
+ public bool do_sound;
+ public int theme_id;
+ public Level level[2];
+ public int keypress[3];
+
+ public Prefs() {
+ do_sound = settings.get_boolean("sound");
+ level[PlayerID.PLAYER1] = Level.HUMAN; /* Human. Always human. */
+ level[PlayerID.PLAYER2] = (Level) settings.get_int("opponent");
+ keypress[Move.LEFT] = settings.get_int("key-left");
+ keypress[Move.RIGHT] = settings.get_int("key-right");
+ keypress[Move.DROP] = settings.get_int("key-drop");
+ theme_id = settings.get_int("theme-id");
+
+ settings.changed.connect(settings_changed_cb);
+
+ level[PlayerID.PLAYER1] = sane_player_level(level[PlayerID.PLAYER1]);
+ level[PlayerID.PLAYER2] = sane_player_level(level[PlayerID.PLAYER2]);
+ theme_id = sane_theme_id(theme_id);
+ }
+
+ int sane_theme_id(int val) {
+ if (val < 0 || val >= theme.length)
+ return DEFAULT_THEME_ID;
+ return val;
+ }
+
+ public void settings_changed_cb(string key) {
+ if (key == "sound") {
+ p.do_sound = settings.get_boolean("sound");
+ ((Gtk.ToggleButton)checkbutton_sound).set_active(p.do_sound);
+ } else if (key == "key-left") {
+ p.keypress[Move.LEFT] = settings.get_int("key-left");
+ } else if (key == "key-right") {
+ p.keypress[Move.RIGHT] = settings.get_int("key-right");
+ } else if (key == "key-drop") {
+ p.keypress[Move.DROP] = settings.get_int("key-drop");
+ } else if (key == "theme-id") {
+ int val = sane_theme_id(settings.get_int("theme-id"));
+ if (val != p.theme_id) {
+ p.theme_id = val;
+ if (!GameBoardView.instance.change_theme())
+ return;
+ if (prefsbox == null)
+ return;
+ combobox_theme.set_active(p.theme_id);
+ }
+ }
+ }
+
+ public int get_n_human_players() {
+ if (level[PlayerID.PLAYER1] != Level.HUMAN && level[PlayerID.PLAYER2] != Level.HUMAN)
+ return 0;
+ if (level[PlayerID.PLAYER1] != Level.HUMAN || level[PlayerID.PLAYER2] != Level.HUMAN)
+ return 1;
+ return 2;
+ }
+
}
Settings settings;
@@ -43,13 +97,8 @@ const uint DEFAULT_KEY_RIGHT = Gdk.Key.Right;
const uint DEFAULT_KEY_DROP = Gdk.Key.Down;
const int DEFAULT_THEME_ID = 0;
-static int sane_theme_id(int val) {
- if (val < 0 || val >= theme.length)
- return DEFAULT_THEME_ID;
- return val;
-}
-public int sane_player_level(int val) {
+public Level sane_player_level(Level val) {
if (val < Level.HUMAN)
return Level.HUMAN;
if (val > Level.STRONG)
@@ -67,45 +116,6 @@ public void on_toggle_sound(Gtk.ToggleButton t) {
settings.set_boolean("sound", t.get_active());
}
-void prefs_init() {
- p.do_sound = settings.get_boolean("sound");
- p.level[PlayerID.PLAYER1] = Level.HUMAN; /* Human. Always human. */
- p.level[PlayerID.PLAYER2] = (Level) settings.get_int("opponent");
- p.keypress[Move.LEFT] = settings.get_int("key-left");
- p.keypress[Move.RIGHT] = settings.get_int("key-right");
- p.keypress[Move.DROP] = settings.get_int("key-drop");
- p.theme_id = settings.get_int("theme-id");
-
- settings.changed.connect(settings_changed_cb);
-
- p.level[PlayerID.PLAYER1] = (Level) sane_player_level(p.level[PlayerID.PLAYER1]);
- p.level[PlayerID.PLAYER2] = (Level) sane_player_level(p.level[PlayerID.PLAYER2]);
- p.theme_id = sane_theme_id(p.theme_id);
-}
-
-public void settings_changed_cb(string key) {
- if (key == "sound") {
- p.do_sound = settings.get_boolean("sound");
- ((Gtk.ToggleButton)checkbutton_sound).set_active(p.do_sound);
- } else if (key == "key-left") {
- p.keypress[Move.LEFT] = settings.get_int("key-left");
- } else if (key == "key-right") {
- p.keypress[Move.RIGHT] = settings.get_int("key-right");
- } else if (key == "key-drop") {
- p.keypress[Move.DROP] = settings.get_int("key-drop");
- } else if (key == "theme-id") {
- int val = sane_theme_id(settings.get_int("theme-id"));
- if (val != p.theme_id) {
- p.theme_id = val;
- if (!Gfx.change_theme())
- return;
- if (prefsbox == null)
- return;
- combobox_theme.set_active(p.theme_id);
- }
- }
-}
-
public void on_select_opponent(Gtk.ComboBox w) {
Gtk.TreeIter iter;
int value;
@@ -115,9 +125,9 @@ public void on_select_opponent(Gtk.ComboBox w) {
p.level[PlayerID.PLAYER2] = (Level)value;
settings.set_int("opponent", value);
- scorebox_reset();
+ scorebox.reset();
who_starts = PlayerID.PLAYER2; /* This gets reversed in game_reset. */
- game_reset();
+ application.game_reset();
}
public void prefsbox_open() {
diff --git a/src/scorebox.vala b/src/scorebox.vala
new file mode 100644
index 0000000..9ac7b8d
--- /dev/null
+++ b/src/scorebox.vala
@@ -0,0 +1,92 @@
+
+/*
+ * Needed to force vala to include headers in the correct order.
+ * See https://gitlab.gnome.org/GNOME/vala/issues/98
+ */
+const string scorebox_gettext_package = Config.GETTEXT_PACKAGE;
+
+class Scorebox : Gtk.Dialog {
+ Gtk.Label label_name[3];
+ Gtk.Label label_score[3];
+
+ public Scorebox() {
+ Object(title: _("Scores"),
+ parent: window,
+ use_header_bar: 1,
+ destroy_with_parent: true,
+ resizable: false,
+ border_width: 5);
+ get_content_area().spacing = 2;
+
+ Gtk.Grid grid, grid2;
+
+ grid = new Gtk.Grid();
+ grid.halign = Gtk.Align.CENTER;
+ grid.row_spacing = 6;
+ grid.orientation = Gtk.Orientation.VERTICAL;
+ grid.border_width = 5;
+
+ get_content_area().pack_start(grid);
+
+ grid2 = new Gtk.Grid();
+ grid.add(grid2);
+ grid2.column_spacing = 6;
+
+ label_name[PlayerID.PLAYER1] = new Gtk.Label(null);
+ grid2.attach(label_name[PlayerID.PLAYER1], 0, 0, 1, 1);
+ label_name[PlayerID.PLAYER1].xalign = 0;
+ label_name[PlayerID.PLAYER1].yalign = 0.5f;
+
+ label_score[PlayerID.PLAYER1] = new Gtk.Label(null);
+ grid2.attach(label_score[PlayerID.PLAYER1], 1, 0, 1, 1);
+ label_score[PlayerID.PLAYER1].xalign = 0;
+ label_score[PlayerID.PLAYER1].yalign = 0.5f;
+
+ label_name[PlayerID.PLAYER2] = new Gtk.Label(null);
+ grid2.attach(label_name[PlayerID.PLAYER2], 0, 1, 1, 1);
+ label_name[PlayerID.PLAYER2].xalign = 0;
+ label_name[PlayerID.PLAYER2].yalign = 0.5f;
+
+ label_score[PlayerID.PLAYER2] = new Gtk.Label(null);
+ grid2.attach(label_score[PlayerID.PLAYER2], 1, 0, 1, 1);
+ label_score[PlayerID.PLAYER2].set_xalign(0);
+ label_score[PlayerID.PLAYER2].set_yalign(0.5f);
+
+ label_name[PlayerID.NOBODY] = new Gtk.Label(_("Drawn:"));
+ grid2.attach(label_name[PlayerID.NOBODY], 0, 2, 1, 1);
+ label_name[PlayerID.NOBODY].set_xalign(0);
+ label_name[PlayerID.NOBODY].set_yalign(0.5f);
+
+ label_score[PlayerID.NOBODY] = new Gtk.Label(null);
+ grid2.attach(label_score[PlayerID.NOBODY], 1, 0, 1, 1);
+ label_score[PlayerID.NOBODY].set_xalign(0);
+ label_score[PlayerID.NOBODY].set_yalign(0.5f);
+ }
+
+ public void update() {
+ if (p.get_n_human_players() == 1) {
+ if (p.level[PlayerID.PLAYER1] == Level.HUMAN) {
+ label_score[PlayerID.PLAYER1].label = _("You:");
+ label_score[PlayerID.PLAYER2].label = _("Me:");
+ } else {
+ label_score[PlayerID.PLAYER2].label = _("You:");
+ label_score[PlayerID.PLAYER1].label = _("Me:");
+ }
+ } else {
+ label_name[PlayerID.PLAYER1].label = theme_get_player(PlayerID.PLAYER1);
+ label_name[PlayerID.PLAYER2].label = theme_get_player(PlayerID.PLAYER2);
+ }
+
+ label_score[PlayerID.PLAYER1].label = (string)score[PlayerID.PLAYER1];
+ label_score[PlayerID.PLAYER2].label = (string)score[PlayerID.PLAYER2];
+ label_score[PlayerID.NOBODY].label = (string)score[PlayerID.NOBODY];
+
+ }
+
+ public void reset() {
+ score[PlayerID.PLAYER1] = 0;
+ score[PlayerID.PLAYER2] = 0;
+ score[PlayerID.NOBODY] = 0;
+ update();
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]