Commit da3931dc authored by Arnaud B.'s avatar Arnaud B. 😎

Use uint8.

parent c10e3c41
......@@ -27,7 +27,7 @@ private class FourInARow : Gtk.Application
/* Translators: application name, as used in the window manager, the window title, the about dialog... */
private const string PROGRAM_NAME = _("Four-in-a-row");
private const int SIZE_VSTR = 53;
private const uint8 SIZE_VSTR = 53;
private const int SPEED_BLINK = 150;
private const int SPEED_MOVE = 35;
private const int SPEED_DROP = 20;
......@@ -50,13 +50,13 @@ private class FourInARow : Gtk.Application
private PlayerID last_first_player = PlayerID.NOBODY;
private Board game_board = new Board ();
private bool one_player_game;
private int ai_level;
private uint8 ai_level;
/**
* score:
*
* The scores for the current instance (Player 1, Player 2, Draw)
*/
private int [] score = { 0, 0, 0 };
private uint [] score = { 0, 0, 0 };
private bool reset_score = true;
private uint playgame_timeout = 0;
......@@ -69,19 +69,19 @@ private class FourInARow : Gtk.Application
private MenuButton history_button_2;
// game state
private char vstr [53];
private int moves;
private int column;
private int column_moveto;
private int row;
private int row_dropto;
private char vstr [/* SIZE_VSTR */ 53];
private uint8 moves;
private uint8 column;
private uint8 column_moveto;
private uint8 row;
private uint8 row_dropto;
// animation
private static AnimID anim = AnimID.NONE;
private int [,] blink_lines = {{}};
private uint8 [,] blink_lines = {{}};
private uint8 blink_line = 0; // index of currenly blinking line in blink_lines
private int blink_t = 0;
private int blink_n = 0;
private Tile blink_t = Tile.PLAYER1; // garbage
private uint8 blink_n = 0;
private bool blink_on = false;
private uint timeout = 0;
......@@ -90,7 +90,7 @@ private class FourInARow : Gtk.Application
[CCode (notify = false)] internal int keypress_right { private get; internal set; }
[CCode (notify = false)] internal int keypress_left { private get; internal set; }
[CCode (notify = false)] internal bool sound_on { private get; internal set; }
[CCode (notify = false)] private int theme_id { private get; private set; }
private uint8 theme_id;
private const GLib.ActionEntry app_entries [] = // see also add_actions()
{
......@@ -195,10 +195,10 @@ private class FourInARow : Gtk.Application
settings.bind ("theme-id", scorebox, "theme-id", SettingsBindFlags.GET | SettingsBindFlags.NO_SENSITIVITY);
settings.changed ["theme-id"].connect (() => {
scorebox.update (score, one_player_game);
theme_id = settings.get_int ("theme-id");
theme_id = (uint8) settings.get_int ("theme-id");
prompt_player ();
});
theme_id = settings.get_int ("theme-id");
theme_id = (uint8) settings.get_int ("theme-id");
add_actions ();
......@@ -313,7 +313,7 @@ private class FourInARow : Gtk.Application
{
player = settings.get_string ("first-player") == "computer" ? PlayerID.PLAYER2 : PlayerID.PLAYER1;
settings.set_string ("first-player", player == PlayerID.PLAYER1 ? "computer" : "human");
ai_level = settings.get_int ("opponent");
ai_level = (uint8) settings.get_int ("opponent");
}
else
{
......@@ -344,19 +344,25 @@ private class FourInARow : Gtk.Application
{
vstr [0] = vlevel [ai_level];
playgame_timeout = Timeout.add (COMPUTER_INITIAL_DELAY, () => {
process_move (playgame ((string) vstr) - 1);
int c = playgame ((string) vstr) - 1;
if (c > 6)
assert_not_reached ();
if (c < 0)
return Source.REMOVE;
process_move ((uint8) c);
playgame_timeout = 0;
return Source.REMOVE;
});
}
}
private void blink_winner (int n) /* blink the winner's line(s) n times */
private void blink_winner (uint8 n) /* blink the winner's line(s) n times */
// requires (n < 128)
{
if (winner == NOBODY)
return;
blink_t = winner;
blink_t = (Tile) winner; // FIXME converting a PlayerID in Tile, bad
if (game_board.is_line_at ((Tile) winner, row, column, out blink_lines))
{
......@@ -371,32 +377,31 @@ private class FourInARow : Gtk.Application
}
}
private inline void draw_line (int r1, int c1, int r2, int c2, int tile)
private inline void draw_line (uint8 _r1, uint8 _c1, uint8 _r2, uint8 _c2, int tile)
{
/* draw a line of 'tile' from r1,c1 to r2,c2 */
bool done = false;
int d_row;
int d_col;
int8 d_row;
int8 d_col;
if (r1 < r2)
d_row = 1;
else if (r1 > r2)
d_row = -1;
else
d_row = 0;
int8 r1 = (int8) _r1;
int8 c1 = (int8) _c1;
int8 r2 = (int8) _r2;
int8 c2 = (int8) _c2;
if (c1 < c2)
d_col = 1;
else if (c1 > c2)
d_col = -1;
else
d_col = 0;
if (r1 < r2) d_row = 1;
else if (r1 > r2) d_row = -1;
else d_row = 0;
if (c1 < c2) d_col = 1;
else if (c1 > c2) d_col = -1;
else d_col = 0;
do
{
done = (r1 == r2 && c1 == c2);
game_board[r1, c1] = (Tile) tile;
game_board [r1, c1] = (Tile) tile;
game_board_view.draw_tile (r1, c1);
if (r1 != r2)
r1 += d_row;
......@@ -413,7 +418,7 @@ private class FourInARow : Gtk.Application
window.allow_hint (human && !gameover);
if (one_player_game)
window.allow_undo ((human && moves >1) || (!human && gameover));
window.allow_undo ((human && moves > 1) || (!human && gameover));
else
window.allow_undo (moves > 0);
......@@ -469,7 +474,7 @@ private class FourInARow : Gtk.Application
prompt_player ();
}
private void process_move3 (int c)
private void process_move3 (uint8 c)
{
play_sound (SoundID.DROP);
......@@ -493,10 +498,12 @@ private class FourInARow : Gtk.Application
{
playgame_timeout = Timeout.add (COMPUTER_MOVE_DELAY, () => {
vstr [0] = vlevel [ai_level];
c = playgame ((string) vstr) - 1;
if (c < 0)
int col = playgame ((string) vstr) - 1;
if (col < 0)
gameover = true;
var nm = new NextMove (c, this);
else if (col > 6)
assert_not_reached ();
var nm = new NextMove ((uint8) col, this);
Timeout.add (SPEED_DROP, nm.exec);
playgame_timeout = 0;
return Source.REMOVE;
......@@ -532,10 +539,10 @@ private class FourInARow : Gtk.Application
return true;
}
private void process_move2 (int c)
private void process_move2 (uint8 c)
{
int r = game_board.first_empty_row (c);
if (r > 0)
uint8 r = game_board.first_empty_row (c);
if (r != 0)
{
row = 0;
row_dropto = r;
......@@ -547,7 +554,7 @@ private class FourInARow : Gtk.Application
play_sound (SoundID.COLUMN_FULL);
}
private void process_move (int c)
private void process_move (uint8 c)
{
if (timeout != 0)
{
......@@ -574,7 +581,7 @@ private class FourInARow : Gtk.Application
game_board_view.draw_tile (row, column);
}
private inline void move (int c)
private inline void move (uint8 c)
{
game_board [0, column] = Tile.CLEAR;
game_board_view.draw_tile (0, column);
......@@ -585,7 +592,7 @@ private class FourInARow : Gtk.Application
game_board_view.draw_tile (0, c);
}
private void move_cursor (int c)
private void move_cursor (uint8 c)
{
move (c);
column = column_moveto = c;
......@@ -599,10 +606,10 @@ private class FourInARow : Gtk.Application
private class NextMove
{
int c;
FourInARow application;
private uint8 c;
private FourInARow application;
internal NextMove (int c, FourInARow application)
internal NextMove (uint8 c, FourInARow application)
{
this.c = c;
this.application = application;
......@@ -628,7 +635,7 @@ private class FourInARow : Gtk.Application
{
game_board.clear ();
for (var i = 0; i < SIZE_VSTR; i++)
for (uint8 i = 0; i < SIZE_VSTR; i++)
vstr [i] = '\0';
vstr [0] = vlevel [/* weak */ 1];
......@@ -636,13 +643,13 @@ private class FourInARow : Gtk.Application
moves = 0;
}
private inline void blink_tile (int row, int col, int t, int n)
private inline void blink_tile (uint8 row, uint8 col, Tile tile, uint8 n)
{
if (timeout != 0)
return;
blink_lines = {{ row, col, row, col }};
blink_line = 0;
blink_t = t;
blink_t = tile;
blink_n = n;
blink_on = false;
anim = AnimID.BLINK;
......@@ -652,10 +659,11 @@ private class FourInARow : Gtk.Application
private class Animate
{
private int c;
private uint8 c;
private FourInARow application;
private int blink_n_times;
internal Animate (int c, FourInARow application, int blink_n_times = 0)
private uint8 blink_n_times;
internal Animate (uint8 c, FourInARow application, uint8 blink_n_times = 0)
{
this.c = c;
this.application = application;
......@@ -708,7 +716,7 @@ private class FourInARow : Gtk.Application
/* col 2 */ application.blink_lines [application.blink_line, 3],
/* tile */ application.blink_on ? application.blink_t : Tile.CLEAR);
application.blink_n--;
if (application.blink_n <= 0 && application.blink_on)
if (application.blink_n == 0 && application.blink_on)
{
if (application.blink_line >= application.blink_lines.length [0] - 1)
{
......@@ -743,7 +751,7 @@ private class FourInARow : Gtk.Application
private inline void on_game_hint ()
{
string s;
int c;
uint8 c;
if (timeout != 0)
return;
......@@ -757,7 +765,10 @@ private class FourInARow : Gtk.Application
set_status_message (_("I’m Thinking…"));
vstr [0] = vlevel [/* strong */ 3];
c = playgame ((string) vstr) - 1;
int _c = playgame ((string) vstr) - 1;
if (_c < 0 || _c > 6)
assert_not_reached ();
c = (uint8) _c;
column_moveto = c;
while (timeout != 0)
......@@ -783,8 +794,8 @@ private class FourInARow : Gtk.Application
if (timeout != 0)
return;
int c = vstr [moves] - '0' - 1;
int r = game_board.first_empty_row (c) + 1;
uint8 c = vstr [moves] - '0' - 1;
uint8 r = game_board.first_empty_row (c) + 1;
vstr [moves] = '0';
vstr [moves + 1] = '\0';
moves--;
......@@ -897,7 +908,7 @@ private class FourInARow : Gtk.Application
if (key == "Left" || event.keyval == keypress_left)
{
if (column <= 0)
if (column == 0)
return false;
column_moveto--;
move_cursor (column_moveto);
......@@ -912,12 +923,12 @@ private class FourInARow : Gtk.Application
else if (key == "space" || key == "Return" || key == "KP_Enter" || key == "Down" || event.keyval == keypress_drop)
process_move (column);
else if (key == "1" || key == "2" || key == "3" || key == "4" || key == "5" || key == "6" || key == "7")
process_move (int.parse (key) - 1);
process_move ((uint8) int.parse (key) - 1);
return true;
}
private inline bool column_clicked_cb (int column)
private inline bool column_clicked_cb (uint8 column)
{
if (gameover && timeout == 0)
blink_winner (2);
......@@ -1093,12 +1104,14 @@ private class FourInARow : Gtk.Application
}
}
// WARNING PlayerID and Tile should be synced
private enum PlayerID {
PLAYER1 = 0,
PLAYER2,
NOBODY;
}
// WARNING PlayerID and Tile should be synced
private enum Tile {
PLAYER1 = 0,
PLAYER2,
......
......@@ -273,7 +273,7 @@ private class GameBoardView : Gtk.DrawingArea
*
* Which column was clicked on
*/
internal signal bool column_clicked (int column);
internal signal bool column_clicked (uint8 column);
protected override bool button_press_event (Gdk.EventButton e)
{
......@@ -284,18 +284,22 @@ private class GameBoardView : Gtk.DrawingArea
assert_not_reached ();
((!) window).get_device_position (e.device, out x, out y, null);
int col;
uint8 col;
if (get_column (x, y, out col))
return column_clicked (col);
else
return false;
}
private inline bool get_column (int x, int y, out int col)
private inline bool get_column (int x, int y, out uint8 col)
{
col = (x - board_x) / tile_size;
if (x < board_x || y < board_y || col < 0 || col > 6)
int _col = (x - board_x) / tile_size;
if (x < board_x || y < board_y || _col < 0 || _col > 6)
{
col = 0;
return false;
}
col = (uint8) _col;
int row = (y - board_y) / tile_size;
if (row < 0 || row > 6)
......
......@@ -18,45 +18,50 @@
with GNOME Four-in-a-row. If not, see <https://www.gnu.org/licenses/>.
*/
private class Board : Object {
private static Tile[,] gboard;
private const int BOARD_SIZE = 7;
private class Board : Object
{
private static Tile [,] gboard;
private const uint8 BOARD_SIZE = 7;
internal Board() {
gboard = new Tile[BOARD_SIZE, BOARD_SIZE];
internal Board ()
{
gboard = new Tile [BOARD_SIZE, BOARD_SIZE];
}
internal new void @set(int x, int y, Tile tile) {
gboard[x, y] = tile;
internal new void @set (uint8 x, uint8 y, Tile tile)
{
gboard [x, y] = tile;
}
internal new Tile @get(int x, int y) {
return gboard[x, y];
internal new Tile @get (uint8 x, uint8 y)
{
return gboard [x, y];
}
internal void clear() {
for (int r = 0; r < BOARD_SIZE; r++) {
for (int c = 0; c < BOARD_SIZE; c++) {
gboard[r, c] = Tile.CLEAR;
}
}
internal void clear ()
{
for (uint8 row = 0; row < BOARD_SIZE; row++)
for (uint8 col = 0; col < BOARD_SIZE; col++)
gboard [row, col] = Tile.CLEAR;
}
internal int first_empty_row(int c) {
int r = 1;
internal uint8 first_empty_row (uint8 col)
{
uint8 row = 1;
while (r < BOARD_SIZE && gboard[r, c] == Tile.CLEAR)
r++;
return r - 1;
while (row < BOARD_SIZE && gboard [row, col] == Tile.CLEAR)
row++;
return row - 1;
}
/*\
* * check if there is a line passing by a given point
\*/
internal bool is_line_at(Tile tile, int row, int col, out int [,] lines = null) {
internal bool is_line_at (Tile tile, uint8 row, uint8 col, out uint8 [,] lines = null)
{
uint8 n_lines = 0;
int [,] lines_tmp = new int [4, 4];
uint8 [,] lines_tmp = new uint8 [4, 4];
if (is_hline_at (tile, row, col, out lines_tmp [0, 0],
out lines_tmp [0, 1],
......@@ -79,84 +84,86 @@ private class Board : Object {
out lines_tmp [n_lines, 3]))
n_lines++;
lines = new int [n_lines, 4];
for (int x = 0; x < n_lines; x++)
for (int y = 0; y < 4; y++)
lines = new uint8 [n_lines, 4];
for (uint8 x = 0; x < n_lines; x++)
for (uint8 y = 0; y < 4; y++)
lines [x, y] = lines_tmp [x, y];
return n_lines != 0;
}
private inline 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;
}
private inline 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)
private inline bool is_hline_at (Tile tile, uint8 row, uint8 col,
out uint8 row_1, out uint8 col_1,
out uint8 row_2, out uint8 col_2)
{
row_1 = row;
row_2 = row;
col_1 = col;
col_2 = col;
while (col_1 > 0 && gboard [row, col_1 - 1] == tile)
col_1 = col_1 - 1;
while (col_2 < 6 && gboard [row, col_2 + 1] == tile)
col_2 = col_2 + 1;
if (col_2 - col_1 >= 3)
return true;
return false;
}
private inline bool is_dline1_at(Tile p, int r, int c,
out int r1, out int c1,
out int r2, out int c2) {
private inline bool is_vline_at (Tile tile, uint8 row, uint8 col,
out uint8 row_1, out uint8 col_1,
out uint8 row_2, out uint8 col_2)
{
row_1 = row;
row_2 = row;
col_1 = col;
col_2 = col;
while (row_1 > 1 && gboard [row_1 - 1, col] == tile)
row_1 = row_1 - 1;
while (row_2 < 6 && gboard [row_2 + 1, col] == tile)
row_2 = row_2 + 1;
return row_2 - row_1 >= 3;
}
private inline bool is_dline1_at (Tile tile, uint8 row, uint8 col,
out uint8 row_1, out uint8 col_1,
out uint8 row_2, out uint8 col_2)
{
/* 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;
}
private inline bool is_dline2_at(Tile p, int r, int c,
out int r1, out int c1,
out int r2, out int c2) {
row_1 = row;
row_2 = row;
col_1 = col;
col_2 = col;
while (col_1 > 0 && row_1 > 1 && gboard [row_1 - 1, col_1 - 1] == tile)
{
row_1 = row_1 - 1;
col_1 = col_1 - 1;
}
while (col_2 < 6 && row_2 < 6 && gboard [row_2 + 1, col_2 + 1] == tile)
{
row_2 = row_2 + 1;
col_2 = col_2 + 1;
}
return row_2 - row_1 >= 3;
}
private inline bool is_dline2_at (Tile tile, uint8 row, uint8 col,
out uint8 row_1, out uint8 col_1,
out uint8 row_2, out uint8 col_2)
{
/* 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;
row_1 = row;
row_2 = row;
col_1 = col;
col_2 = col;
while (col_1 < 6 && row_1 > 1 && gboard [row_1 - 1, col_1 + 1] == tile)
{
row_1 = row_1 - 1;
col_1 = col_1 + 1;
}
while (col_2 > 0 && row_2 < 6 && gboard [row_2 + 1, col_2 - 1] == tile)
{
row_2 = row_2 + 1;
col_2 = col_2 - 1;
}
return row_2 - row_1 >= 3;
}
}
......@@ -93,7 +93,7 @@ private class Scorebox : Dialog {
*
* updates the scorebox with the latest scores
*/
internal void update(int[] scores, bool one_player_game) {
internal void update(uint[] scores, bool one_player_game) {
if (one_player_game) {
if (scores[PlayerID.PLAYER1] >= scores[PlayerID.PLAYER2]) {
/* Translators: in the Scores dialog, label of the line where is indicated the number of games won by the human player */
......@@ -115,8 +115,8 @@ private class Scorebox : Dialog {
label_score[1].label = scores[0].to_string();
}
} else {
label_name[0].label = theme_get_player(PlayerID.PLAYER1, theme_id); // FIXME missing ":" at end
label_name[1].label = theme_get_player(PlayerID.PLAYER2, theme_id); // idem
label_name[0].label = theme_get_player(PlayerID.PLAYER1, (uint8) theme_id); // FIXME missing ":" at end
label_name[1].label = theme_get_player(PlayerID.PLAYER2, (uint8) theme_id); // idem
label_score[PlayerID.PLAYER1].label = scores[PlayerID.PLAYER1].to_string();
label_score[PlayerID.PLAYER2].label = scores[PlayerID.PLAYER2].to_string();
......
......@@ -39,29 +39,32 @@ private struct Theme
*/
private const string theme_gettext_package = GETTEXT_PACKAGE;
private static string theme_get_title (int id)
private static string theme_get_title (uint8 id)
{
return _(theme [id].title); // FIXME this gettext call feels horrible
}
private static string theme_get_player_turn (PlayerID who, int theme_id)
private static string theme_get_player_turn (PlayerID who, uint8 theme_id)
{
if (who == PlayerID.PLAYER1)
return theme [theme_id].player1_turn;
else
return theme [theme_id].player2_turn;
}
private static string theme_get_player_win (PlayerID who, int theme_id)
private static string theme_get_player_win (PlayerID who, uint8 theme_id)
{
if (who == PlayerID.PLAYER1)
return theme [theme_id].player1_win;
else
return theme [theme_id].player2_win;