Hi!
This (fairly big) patch adds a cdebconf-gtk-tetris package to the
debian-installer. As the name suggest, this will allow you to play
Tetris within d-i.
The implementation is based on Gnometris, porting from C++ and stripping
it from most of its fancy features.
If you want to see what it looks like, you can use one of the available
mini.iso [1,2], start in expert mode and use the "Play Tetris" option in
main-menu.
[1] http://people.debian.org/~lunar/g-i+tetris-mini.iso (i386)
[2] http://people.debian.org/~lunar/g-i+tetris-mini-amd64.iso
I wonder if this patch should be integrated as is. Maybe it would be
better to be able to start the Tetris during any progress bar. Or while
base-installer/pkgsel are running... Another option is just to
integrate it as the entropy plugin for the graphical frontend.
I am also unsure about the required Depends for the udeb. Comments are
really welcome on that matter, as my original dependencies made me
report #437323.
Note: This patch depends on the integration of the fe_gtk branch, but I
won't spam the mailling-list with another huge patch to review, as there
is no significant modification from what is already in the subversion
repository.
---
packages/cdebconf-tetris/Makefile.in | 84 +++++
packages/cdebconf-tetris/block_ops.c | 297 +++++++++++++++
packages/cdebconf-tetris/block_ops.h | 64 ++++
packages/cdebconf-tetris/blocks.c | 308 +++++++++++++++
packages/cdebconf-tetris/blocks.h | 45 +++
packages/cdebconf-tetris/configure.ac | 16 +
.../debian/cdebconf-gtk-tetris.install | 1 +
.../debian/cdebconf-gtk-tetris.postinst | 8 +
.../debian/cdebconf-gtk-tetris.templates | 43 +++
packages/cdebconf-tetris/debian/changelog | 5 +
packages/cdebconf-tetris/debian/compat | 1 +
packages/cdebconf-tetris/debian/control | 17 +
packages/cdebconf-tetris/debian/copyright | 30 ++
packages/cdebconf-tetris/debian/po/POTFILES.in | 1 +
packages/cdebconf-tetris/debian/rules | 71 ++++
packages/cdebconf-tetris/field.c | 286 ++++++++++++++
packages/cdebconf-tetris/field.h | 52 +++
packages/cdebconf-tetris/gtk-plugin-tetris.c | 395 ++++++++++++++++++++
packages/cdebconf-tetris/linker-script | 6 +
packages/cdebconf-tetris/preview.c | 166 ++++++++
packages/cdebconf-tetris/preview.h | 42 ++
packages/cdebconf-tetris/score.c | 182 +++++++++
packages/cdebconf-tetris/score.h | 45 +++
packages/cdebconf-tetris/tetris.h | 77 ++++
24 files changed, 2242 insertions(+), 0 deletions(-)
create mode 100644 packages/cdebconf-tetris/Makefile.in
create mode 100644 packages/cdebconf-tetris/block_ops.c
create mode 100644 packages/cdebconf-tetris/block_ops.h
create mode 100644 packages/cdebconf-tetris/blocks.c
create mode 100644 packages/cdebconf-tetris/blocks.h
create mode 100644 packages/cdebconf-tetris/configure.ac
create mode 100644 packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.install
create mode 100644 packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.postinst
create mode 100644 packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.templates
create mode 100644 packages/cdebconf-tetris/debian/changelog
create mode 100644 packages/cdebconf-tetris/debian/compat
create mode 100644 packages/cdebconf-tetris/debian/control
create mode 100644 packages/cdebconf-tetris/debian/copyright
create mode 100644 packages/cdebconf-tetris/debian/po/POTFILES.in
create mode 100755 packages/cdebconf-tetris/debian/rules
create mode 100644 packages/cdebconf-tetris/field.c
create mode 100644 packages/cdebconf-tetris/field.h
create mode 100644 packages/cdebconf-tetris/gtk-plugin-tetris.c
create mode 100644 packages/cdebconf-tetris/linker-script
create mode 100644 packages/cdebconf-tetris/preview.c
create mode 100644 packages/cdebconf-tetris/preview.h
create mode 100644 packages/cdebconf-tetris/score.c
create mode 100644 packages/cdebconf-tetris/score.h
create mode 100644 packages/cdebconf-tetris/tetris.h
diff --git a/packages/cdebconf-tetris/Makefile.in b/packages/cdebconf-tetris/Makefile.in
new file mode 100644
index 0000000..e60f2d9
--- /dev/null
+++ b/packages/cdebconf-tetris/Makefile.in
@@ -0,0 +1,84 @@
+prefix = @prefix@
+etcdir = @sysconfdir@
+bindir = ${prefix}/bin
+sbindir = ${prefix}/sbin
+libdir = ${prefix}/lib
+moddir = ${libdir}/cdebconf/frontend
+sharedir = ${prefix}/share/debconf
+mandir = ${prefix}/share/man
+incdir = ${prefix}/include/cdebconf
+
+CC = @CC@
+CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -I.
+LDFLAGS = @LDFLAGS@ @LIBS@ @GTK_LIBS@
+
+# Export only strictly needed symbols
+LDFLAGS += "-Wl,--version-script=linker-script"
+
+# let the type char be unsigned by default
+CFLAGS += -funsigned-char
+# apply strict aliasing rules
+CFLAGS += -fstrict-aliasing
+# turn on all common warnings
+CFLAGS += -Wall
+# turn on extra warnings
+CFLAGS += -W
+# treat warnings as errors
+CFLAGS += -Werror
+# warn about undefined preprocessor identifiers
+CFLAGS += -Wundef
+# warn about casting of pointers to increased alignment requirements
+CFLAGS += -Wcast-align
+# make string constants const
+CFLAGS += -Wwrite-strings
+# warn about comparisons between signed and unsigned values
+CFLAGS += -Wsign-compare
+# warn about unused declared stuff
+CFLAGS += -Wno-unused-parameter
+# warn about variables which are initialized with themselves
+CFLAGS += -Winit-self
+# warn about pointer arithmetic on void* and function pointers
+CFLAGS += -Wpointer-arith
+# warn about multiple declarations
+CFLAGS += -Wredundant-decls
+# do not warn about zero-length formats.
+CFLAGS += -Wno-format-zero-length
+# missing prototypes
+CFLAGS += -Wmissing-prototypes
+# warn about functions without format attribute that should have one
+CFLAGS += -Wmissing-format-attribute
+
+PLUGIN_MODULES = gtk-plugin-tetris.so
+
+SOURCES = \
+ gtk-plugin-tetris.c tetris.h \
+ blocks.c blocks.h \
+ block_ops.c block_ops.h \
+ field.c field.h \
+ preview.c preview.h \
+ score.c score.h
+
+OBJS = $(filter %.opic,$(subst .c,.opic,$(SOURCES)))
+
+all: $(PLUGIN_MODULES)
+
+install: $(PLUGIN_MODULES)
+ for p in $(PLUGIN_MODULES); do \
+ install -m755 -d $(DESTDIR)/$(moddir)/$${p%%-*} ; \
+ install -m644 $$p $(DESTDIR)/$(moddir)/$${p%%-*}/$${p#*-} ; \
+ done
+
+clean:
+ rm -f $(PLUGIN_MODULES)
+ rm -f $(OBJS)
+
+distclean: clean
+ rm -f config.log config.status
+ rm -f Makefile
+
+gtk-plugin-tetris.so: $(OBJS)
+ $(CC) $(LDFLAGS) -shared -o $@ $(OBJS)
+
+%.opic: %.c
+ $(CC) $(CFLAGS) -fPIC -o $@ -c $<
+
diff --git a/packages/cdebconf-tetris/block_ops.c b/packages/cdebconf-tetris/block_ops.c
new file mode 100644
index 0000000..c7d0a9b
--- /dev/null
+++ b/packages/cdebconf-tetris/block_ops.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "block_ops.h"
+
+#include <glib.h>
+
+#include "tetris.h"
+#include "blocks.h"
+
+gboolean block_ok_here(struct tetris * tetris, int dx, int dy, int mr)
+{
+ int x = tetris->posx + dx;
+ int y = tetris->posy + dy;
+ int b = tetris->blocknr;
+ int r = -1 == mr ? tetris->rot : mr;
+ int x1;
+ int y1;
+
+ x -= 2;
+
+ for (x1 = 0; x1 < 4; ++x1) {
+ for (y1 = 0; y1 < 4; ++y1) {
+ if (BLOCK_TABLE[b][r][x1][y1] && (x1 + x < 0)) {
+ return FALSE;
+ }
+ if (BLOCK_TABLE[b][r][x1][y1] && (x1 + x >= COLUMNS)) {
+ return FALSE;
+ }
+ if (BLOCK_TABLE[b][r][x1][y1] && (y1 + y >= LINES)) {
+ return FALSE;
+ }
+ if (BLOCK_TABLE[b][r][x1][y1] &&
+ LAYING == tetris->blocks[x + x1][y1 + y].what) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+int get_lines_to_bottom(struct tetris * tetris)
+{
+ int lines = LINES;
+ int x;
+ int y;
+ int yy;
+ int tmp;
+
+ for (x = 0; x < 4; ++x) {
+ for (y = 3; y >= 0; --y) {
+ if (!BLOCK_TABLE[tetris->blocknr][tetris->rot][x][y]) {
+ continue;
+ }
+ for (yy = tetris->posy + y; yy < LINES; ++yy) {
+ if (LAYING == tetris->blocks[tetris->posx + x - 2][yy].what) {
+ break;
+ }
+ }
+ tmp = yy - tetris->posy - y;
+ if (lines > tmp) {
+ lines = tmp;
+ }
+ }
+ }
+
+ return lines;
+}
+
+gboolean move_block_left(struct tetris * tetris)
+{
+ if (!block_ok_here(tetris, -1, 0, -1)) {
+ return FALSE;
+ }
+ put_block_in_field(tetris, EMPTY);
+ --tetris->posx;
+ put_block_in_field(tetris, FALLING);
+ return TRUE;
+}
+
+gboolean move_block_right(struct tetris * tetris)
+{
+ if (!block_ok_here(tetris, 1, 0, -1)) {
+ return FALSE;
+ }
+ put_block_in_field(tetris, EMPTY);
+ ++tetris->posx;
+ put_block_in_field(tetris, FALLING);
+ return TRUE;
+}
+
+#define ROTATE_COUNTER_CLOCK_WISE TRUE
+#define ROTATE_CLOCK_WISE FALSE
+
+gboolean rotate_block(struct tetris * tetris, gboolean rotate_ccw)
+{
+ int r = tetris->rot;
+
+ if (rotate_ccw) {
+ if (--r < 0) {
+ r = 3;
+ }
+ } else {
+ if (++r >= 4) {
+ r = 0;
+ }
+ }
+
+ if (!block_ok_here(tetris, 0, 0, r)) {
+ return FALSE;
+ }
+ put_block_in_field(tetris, EMPTY);
+ tetris->rot = r;
+ put_block_in_field(tetris, FALLING);
+ return TRUE;
+}
+
+gboolean move_block_down(struct tetris * tetris)
+{
+ if (!block_ok_here(tetris, 0, 1, -1)) {
+ return TRUE;
+ }
+ put_block_in_field(tetris, EMPTY);
+ ++tetris->posy;
+ put_block_in_field(tetris, FALLING);
+ return FALSE;
+}
+
+int drop_block(struct tetris * tetris)
+{
+ int count = 0;
+
+ while (!move_block_down(tetris)) {
+ count++;
+ }
+
+ return count;
+}
+
+void falling_to_laying(struct tetris * tetris)
+{
+ int x;
+ int y;
+
+ for (x = 0; x < COLUMNS; ++x) {
+ for (y = 0; y < LINES; ++y) {
+ if (FALLING == tetris->blocks[x][y].what) {
+ tetris->blocks[x][y].what = LAYING;
+ }
+ }
+ }
+}
+
+void eliminate_line(struct tetris * tetris, int l)
+{
+ int y;
+ int x;
+
+ for (y = l; y > 0; --y) {
+ for (x = 0; x < COLUMNS; ++x) {
+ tetris->blocks[x][y] = tetris->blocks[x][y - 1];
+
+ tetris->blocks[x][y - 1].what = EMPTY;
+ tetris->blocks[x][y - 1].color = 0;
+ }
+ }
+}
+
+int check_full_lines(struct tetris * tetris)
+{
+ /* we can have at most 4 full lines (vertical block) */
+ int full_lines[4] = {0, 0, 0, 0};
+ int num_full_lines = 0;
+ int x;
+ int y;
+ int i;
+ gboolean f;
+
+ for (y = tetris->posy; y < MIN(tetris->posy + 4, LINES); ++y) {
+ f = TRUE;
+ for (x = 0; x < COLUMNS; ++x) {
+ if (tetris->blocks[x][y].what != LAYING) {
+ f = FALSE;
+ break;
+ }
+ }
+
+ if (f) {
+ full_lines[num_full_lines] = y;
+ ++num_full_lines;
+ }
+ }
+
+ if (num_full_lines > 0) {
+ for (i = 0; i < num_full_lines; ++i) {
+ eliminate_line(tetris, full_lines[i]);
+ }
+ }
+
+ return num_full_lines;
+}
+
+gboolean generate_falling_block(struct tetris * tetris)
+{
+ tetris->posx = COLUMNS / 2 + 1;
+ tetris->posy = 0;
+
+ tetris->blocknr = tetris->blocknr_next == -1 ?
+ g_random_int_range(0, BLOCK_TYPES) :
+ tetris->blocknr_next;
+ tetris->rot = tetris->rot_next == -1 ?
+ g_random_int_range(0, 4) :
+ tetris->rot_next;
+
+ tetris->blocknr_next = g_random_int_range(0, BLOCK_TYPES);
+ tetris->rot_next = g_random_int_range(0, 4);
+
+ if (!block_ok_here(tetris, 0, 0, -1)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void empty_field(struct tetris * tetris)
+{
+ int y;
+ int x;
+
+ for (y = 0; y < LINES; ++y) {
+ for (x = 0; x < COLUMNS; ++x) {
+ tetris->blocks[x][y].what = EMPTY;
+ tetris->blocks[x][y].color = 0;
+ }
+ }
+}
+
+void put_block_in_field(struct tetris * tetris, SlotType fill)
+{
+ int bx = tetris->posx;
+ int by = tetris->posy;
+ int x;
+ int y;
+ int i;
+ int j;
+
+ for (x = 0; x < 4; ++x) {
+ for (y = 0; y < 4; ++y) {
+ if (BLOCK_TABLE[tetris->blocknr][tetris->rot][x][y]) {
+ i = bx - 2 + x;
+ j = y + by;
+
+ tetris->blocks[i][j].what = fill;
+ if ((FALLING == fill) || (LAYING == fill)) {
+ tetris->blocks[i][j].color = tetris->blocknr % BLOCK_TYPES;
+ } else {
+ tetris->blocks[i][j].color = 0;
+ }
+ }
+ }
+ }
+}
+
+gboolean is_field_empty(struct tetris * tetris)
+{
+ int x;
+
+ for (x = 0; x < COLUMNS; x++) {
+ if (EMPTY != tetris->blocks[x][LINES - 1].what) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/block_ops.h b/packages/cdebconf-tetris/block_ops.h
new file mode 100644
index 0000000..2c219f9
--- /dev/null
+++ b/packages/cdebconf-tetris/block_ops.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _BLOCK_OPS_H_
+#define _BLOCK_OPS_H_
+
+#include <glib.h>
+
+#include "tetris.h"
+#include "blocks.h"
+
+gboolean block_ok_here(struct tetris * tetris, int dx, int dy, int mr);
+
+int get_lines_to_bottom(struct tetris * tetris);
+
+gboolean move_block_left(struct tetris * tetris);
+
+gboolean move_block_right(struct tetris * tetris);
+
+#define ROTATE_COUNTER_CLOCK_WISE TRUE
+#define ROTATE_CLOCK_WISE FALSE
+
+gboolean rotate_block(struct tetris * tetris, gboolean rotate_ccw);
+
+gboolean move_block_down(struct tetris * tetris);
+
+int drop_block(struct tetris * tetris);
+
+void falling_to_laying(struct tetris * tetris);
+
+void eliminate_line(struct tetris * tetris, int l);
+
+int check_full_lines(struct tetris * tetris);
+
+gboolean generate_falling_block(struct tetris * tetris);
+
+void empty_field(struct tetris * tetris);
+
+void put_block_in_field(struct tetris * tetris, SlotType fill);
+
+gboolean is_field_empty(struct tetris * tetris);
+
+#endif /* !_BLOCK_OPS_H_ */
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/blocks.c b/packages/cdebconf-tetris/blocks.c
new file mode 100644
index 0000000..570b5af
--- /dev/null
+++ b/packages/cdebconf-tetris/blocks.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "blocks.h"
+
+const int BLOCK_TABLE[BLOCK_TYPES][4][4][4] = {
+ {
+ {
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {1, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 1, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {1, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 1, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {1, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {1, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 1, 0},
+ {1, 1, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {1, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 1, 0},
+ {0, 1, 1, 0},
+ {0, 1, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {1, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {1, 1, 1, 1},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {1, 1, 1, 1},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ },
+ },
+
+ {
+ {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0},
+ },
+ }
+};
+
+const int SIZE_TABLE[BLOCK_TYPES][4][2] = {
+ {
+ {3, 2},
+ {2, 3},
+ {3, 2},
+ {2, 3},
+ },
+ {
+ {3, 2},
+ {2, 3},
+ {3, 2},
+ {2, 3},
+ },
+ {
+ {3, 2},
+ {2, 3},
+ {3, 2},
+ {2, 3},
+ },
+ {
+ {3, 2},
+ {2, 3},
+ {3, 2},
+ {2, 3},
+ },
+ {
+ {3, 2},
+ {2, 3},
+ {3, 2},
+ {2, 3},
+ },
+ {
+ {4, 1},
+ {1, 4},
+ {4, 1},
+ {1, 4},
+ },
+ {
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ },
+};
+
+const int OFFSET_TABLE[BLOCK_TYPES][4][2] = {
+ {
+ {0, 1},
+ {1, 0},
+ {0, 0},
+ {0, 0},
+
+ },
+ {
+ {0, 1},
+ {1, 0},
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 1},
+ {1, 0},
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 1},
+ {1, 0},
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 1},
+ {1, 0},
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 1},
+ {1, 0},
+ {0, 2},
+ {2, 0},
+ },
+ {
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ },
+};
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/blocks.h b/packages/cdebconf-tetris/blocks.h
new file mode 100644
index 0000000..9066492
--- /dev/null
+++ b/packages/cdebconf-tetris/blocks.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _BLOCKS_H_
+#define _BLOCKS_H_
+
+typedef enum {
+ EMPTY = 0,
+ FALLING,
+ LAYING
+} SlotType;
+
+struct block {
+ SlotType what;
+ int color;
+};
+
+#define BLOCK_TYPES 7
+
+extern const int BLOCK_TABLE[BLOCK_TYPES][4][4][4];
+extern const int SIZE_TABLE[BLOCK_TYPES][4][2];
+extern const int OFFSET_TABLE[BLOCK_TYPES][4][2];
+
+#endif /* !_BLOCKS_H_ */
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/configure.ac b/packages/cdebconf-tetris/configure.ac
new file mode 100644
index 0000000..d381c51
--- /dev/null
+++ b/packages/cdebconf-tetris/configure.ac
@@ -0,0 +1,16 @@
+AC_INIT
+PACKAGE=tetris
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+
+AC_PROG_MAKE_SET
+AC_PROG_CC
+
+dnl PKG_CHECK_MODULES(GTK, [gtk+-2.0])
+PKG_CHECK_MODULES(GTK, [gtk+-directfb-2.0])
+
+AC_CHECK_LIB(m, pow)
+
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LIBS)
+
+AC_OUTPUT(Makefile)
diff --git a/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.install b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.install
new file mode 100644
index 0000000..3a7472e
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.install
@@ -0,0 +1 @@
+usr/lib/cdebconf/frontend/gtk
diff --git a/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.postinst b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.postinst
new file mode 100644
index 0000000..8125948
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.postinst
@@ -0,0 +1,8 @@
+#! /bin/sh -e
+. /usr/share/debconf/confmodule
+
+db_capb
+
+db_fset cdebconf-gtk-tetris/tetris seen false
+db_input critical cdebconf-gtk-tetris/tetris || true
+db_go || true
diff --git a/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.templates b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.templates
new file mode 100644
index 0000000..29d9805
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/cdebconf-gtk-tetris.templates
@@ -0,0 +1,43 @@
+Template: cdebconf-gtk-tetris/tetris
+Type: tetris
+_Description: Play Tetris
+
+# The following keys are available:
+# Left/arrows: Move block left/right - Up arrow: Rotate block
+# Down arrow: Fast fall - Spacebar: Drop block - P: Pause
+
+Template: cdebconf-gtk-tetris/paused
+Type: text
+# Translators: this will appear in the play field
+_Description: Paused
+
+Template: cdebconf-gtk-tetris/game-over
+Type: text
+# Translators: this will appear on the play field
+_Description: Game Over
+
+Template: cdebconf-gtk-tetris/new-game
+Type: text
+# Translators: this will appear on a button
+_Description: New game
+
+Template: cdebconf-gtk-tetris/end-game
+Type: text
+# Translators: this will appear on a button
+_Description: End game
+
+Template: cdebconf-gtk-tetris/pause
+Type: text
+# Translators: this will appear on a button
+_Description: Pause
+
+Template: cdebconf-gtk-tetris/resume
+Type: text
+# Translators: this will appear on a button
+_Description: Resume
+
+Template: debian-installer/cdebconf-gtk-tetris/title
+Type: text
+# Main menu item
+# Translators: keep it under 65 columns
+_Description: Play Tetris
diff --git a/packages/cdebconf-tetris/debian/changelog b/packages/cdebconf-tetris/debian/changelog
new file mode 100644
index 0000000..939f18b
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/changelog
@@ -0,0 +1,5 @@
+cdebconf-tetris (1) UNRELEASED; urgency=low
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Jérémy Bobbio <lunar@debian.org> Thu, 09 Aug 2007 12:13:32 +0200
diff --git a/packages/cdebconf-tetris/debian/compat b/packages/cdebconf-tetris/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/packages/cdebconf-tetris/debian/control b/packages/cdebconf-tetris/debian/control
new file mode 100644
index 0000000..ec1178d
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/control
@@ -0,0 +1,17 @@
+Source: cdebconf-tetris
+Priority: extra
+Section: debian-installer
+Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
+Uploaders: Jérémy Bobbio <lunar@debian.org>
+Build-Depends: debhelper (>= 5), libgtk-directfb-2.0-dev,
+ libdebconfclient0-dev (>> 0.119)
+Standards-Version: 3.7.2
+XS-Vcs-Svn: svn://svn.debian.org/d-i/trunk/packages/cdebconf-tetris
+
+Package: cdebconf-gtk-tetris
+Architecture: any
+Section: debian-installer
+XC-Package-Type: udeb
+XB-Installer-Menu-Item: 95000
+Description: Play Tetris
+ This udeb will add a Tetris to the graphical version of the debian-installer.
diff --git a/packages/cdebconf-tetris/debian/copyright b/packages/cdebconf-tetris/debian/copyright
new file mode 100644
index 0000000..d402e02
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/copyright
@@ -0,0 +1,30 @@
+Tetris plugin for the GTK+ frontend of cdebconf
+
+Author:
+
+ Jérémy Bobbio <lunar@debian.org>
+
+Copyright:
+
+ © 2007 Jérémy Bobbio <lunar@debian.org>
+
+This work is based on Gnometris, written by:
+
+ J. Marcin Gorycki <marcin.gorycki@intel.com>
+
+License:
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 with
+ the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL;
+ if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
+ Floor, Boston, MA 02110-1301 USA
diff --git a/packages/cdebconf-tetris/debian/po/POTFILES.in b/packages/cdebconf-tetris/debian/po/POTFILES.in
new file mode 100644
index 0000000..f8ab290
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/po/POTFILES.in
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] cdebconf-gtk-tetris.templates
diff --git a/packages/cdebconf-tetris/debian/rules b/packages/cdebconf-tetris/debian/rules
new file mode 100755
index 0000000..9479f58
--- /dev/null
+++ b/packages/cdebconf-tetris/debian/rules
@@ -0,0 +1,71 @@
+#! /usr/bin/make -f
+
+#export DH_VERBOSE=1
+
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+ confflags += --build $(DEB_HOST_GNU_TYPE)
+else
+ confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
+endif
+
+config.status: configure
+ dh_testdir
+ CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,syms" \
+ ./configure $(confflags) --prefix=/usr
+
+build: build-stamp
+build-stamp: config.status
+ dh_testdir
+ $(MAKE)
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ -$(MAKE) distclean
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+ cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+ cp -f /usr/share/misc/config.guess config.guess
+endif
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+ $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
+
+binary-indep: build install
+ # We have nothing to do.
+
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_install --sourcedir=debian/tmp
+ dh_installdebconf
+ dh_strip
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
+
diff --git a/packages/cdebconf-tetris/field.c b/packages/cdebconf-tetris/field.c
new file mode 100644
index 0000000..7cd39a4
--- /dev/null
+++ b/packages/cdebconf-tetris/field.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "field.h"
+
+#include <gtk/gtk.h>
+#include <cairo/cairo.h>
+
+#include <cdebconf/cdebconf_gtk.h>
+
+#include "tetris.h"
+#include "blocks.h"
+
+#define FONT "Sans Bold"
+
+struct field {
+ struct tetris * tetris;
+ GtkWidget * drawing_area;
+ int pixel_width;
+ int pixel_height;
+ cairo_surface_t * buffer;
+ MessageType show_message;
+ struct block ** blocks;
+};
+
+void draw_cell(cairo_t * cr, struct block * block, int x, int y)
+{
+ const gdouble colours[7][3] = {
+ {1.0, 0.0, 0.0},
+ {0.0, 1.0, 0.0},
+ {0.0, 0.0, 1.0},
+ {1.0, 1.0, 1.0},
+ {1.0, 1.0, 0.0},
+ {1.0, 0.0, 1.0},
+ {0.0, 1.0, 1.0}
+ };
+ int i;
+
+ if (EMPTY == block->what) {
+ return;
+ }
+
+ i = block->color;
+ i = CLAMP(i, 0, 6);
+
+ cairo_set_source_rgb(cr, colours[i][0], colours[i][1], colours[i][2]);
+
+ cairo_rectangle(cr, x + 0.05, y + 0.05, 0.9, 0.9);
+ cairo_fill(cr);
+}
+
+void draw_background(cairo_t * cr)
+{
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_paint(cr);
+}
+
+static void draw_buffer(struct field * field)
+{
+ cairo_t * cr;
+ int x;
+ int y;
+
+ cr = cairo_create(field->buffer);
+
+ draw_background(cr);
+
+ cairo_scale(cr, 1.0 * field->pixel_width / COLUMNS, 1.0 * field->pixel_height / LINES);
+
+ for (y = 0; y < LINES; y++) {
+ for (x = 0; x < COLUMNS; x++) {
+ draw_cell(cr, &field->tetris->blocks[x][y], x, y);
+ }
+ }
+
+ cairo_destroy(cr);
+}
+
+static void draw_widget(struct field * field, gint x, gint y, gint wd, gint ht)
+{
+ cairo_t * cr;
+
+ cr = gdk_cairo_create(field->drawing_area->window);
+
+ cairo_set_source_surface(cr, field->buffer, 0, 0);
+ cairo_rectangle(cr, x, y, wd, ht);
+ cairo_fill(cr);
+
+ cairo_destroy(cr);
+}
+
+static void draw_message(struct field * field, cairo_t * cr, const char * msg)
+{
+ PangoLayout * dummy_layout;
+ PangoLayout * layout;
+ PangoFontDescription * desc;
+ int lw;
+ int lh;
+
+ cairo_save(cr);
+
+ // Center coordinates
+ cairo_translate(cr, field->pixel_width / 2, field->pixel_height / 2);
+
+ desc = pango_font_description_from_string(FONT);
+
+ layout = pango_cairo_create_layout(cr);
+ pango_layout_set_text(layout, msg, -1);
+
+ dummy_layout = pango_layout_copy(layout);
+ pango_layout_set_font_description(dummy_layout, desc);
+ pango_layout_get_size(dummy_layout, &lw, &lh);
+ g_object_unref(dummy_layout);
+
+ /* desired height : lh = widget width * 0.9 : lw */
+ pango_font_description_set_absolute_size(
+ desc, ((float) lh / lw) * PANGO_SCALE * field->pixel_width * 0.8);
+ pango_layout_set_font_description(layout, desc);
+ pango_font_description_free(desc);
+
+ pango_layout_get_size(layout, &lw, &lh);
+ cairo_move_to(cr, -((double)lw / PANGO_SCALE) / 2,
+ -((double)lh / PANGO_SCALE) / 2);
+ pango_cairo_layout_path(cr, layout);
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_fill_preserve(cr);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ /* A linewidth of 2 pixels at the default size. */
+ cairo_set_line_width(cr, field->pixel_width / 220.0);
+ cairo_stroke(cr);
+
+ g_object_unref(layout);
+
+ cairo_restore(cr);
+}
+
+static gboolean expose(GtkWidget * widget, GdkEventExpose * event,
+ struct field * field)
+{
+ draw_widget(field, event->area.x, event->area.y, event->area.width,
+ event->area.height);
+
+ return TRUE;
+}
+
+static gboolean configure(GtkWidget * widget, GdkEventConfigure * event,
+ struct field * field)
+{
+ cairo_t * cr;
+
+ field->pixel_width = widget->allocation.width;
+ field->pixel_height = widget->allocation.height;
+
+ cr = gdk_cairo_create(widget->window);
+
+ if (field->buffer) {
+ cairo_surface_destroy(field->buffer);
+ }
+ field->buffer = cairo_surface_create_similar(
+ cairo_get_target(cr), CAIRO_CONTENT_COLOR, widget->allocation.width,
+ widget->allocation.height);
+
+ cairo_destroy(cr);
+
+ return TRUE;
+}
+
+struct field * create_field(struct tetris * tetris, GtkWidget * container)
+{
+ struct field * field;
+ GtkWidget * aspect_frame;
+ GtkWidget * drawing_area;
+
+ if (NULL == (field = g_malloc0(sizeof (struct field)))) {
+ g_warning("g_malloc0 failed.");
+ return NULL;
+ }
+
+ field->tetris = tetris;
+ field->pixel_width = -1;
+ field->pixel_height = -1;
+ field->buffer = NULL;
+ field->show_message = MESSAGE_NONE;
+
+ aspect_frame = gtk_aspect_frame_new(
+ NULL /* no label */, 0.5 /* center */, 0.5 /* middle */,
+ (float) COLUMNS / (float) LINES, FALSE /* enforce ratio */);
+ if (NULL == aspect_frame) {
+ g_warning("gtk_aspect_frame_new failed.");
+ g_free(field);
+ return NULL;
+ }
+ gtk_frame_set_shadow_type(GTK_FRAME (aspect_frame), GTK_SHADOW_NONE);
+
+ if (NULL == (drawing_area = gtk_drawing_area_new())) {
+ g_warning("gtk_drawing_area_new failed.");
+ g_free(field);
+ return NULL;
+ }
+
+ g_signal_connect(drawing_area, "expose_event",
+ G_CALLBACK(expose), field);
+ g_signal_connect(drawing_area, "configure_event",
+ G_CALLBACK(configure), field);
+
+ gtk_widget_set_size_request(drawing_area, COLUMNS * 190 / LINES, 190);
+
+ g_object_ref(drawing_area);
+ field->drawing_area = drawing_area;
+
+ gtk_container_add(GTK_CONTAINER(aspect_frame), drawing_area);
+ gtk_box_pack_start_defaults(GTK_BOX(container), aspect_frame);
+
+ return field;
+}
+
+void destroy_field(struct field * field)
+{
+ if (NULL == field) {
+ return;
+ }
+ if (NULL != field->buffer) {
+ cairo_surface_destroy(field->buffer);
+ }
+ g_object_unref(field->drawing_area);
+ /* field->drawing_area will be destroyed by its parent. */
+ g_free(field);
+}
+
+static void redraw(struct field * field)
+{
+ cairo_t * cr;
+ gchar * message;
+
+ g_return_if_fail(field->buffer);
+ draw_buffer(field);
+ cr = cairo_create(field->buffer);
+ if (MESSAGE_PAUSED == field->show_message) {
+ message = cdebconf_gtk_get_text(
+ field->tetris->fe, "cdebconf-gtk-tetris/paused", "Paused");
+ draw_message(field, cr, message);
+ g_free(message);
+ } else if (MESSAGE_GAME_OVER == field->show_message) {
+ message = cdebconf_gtk_get_text(
+ field->tetris->fe, "cdebconf-gtk-tetris/game-over", "Game Over");
+ draw_message(field, cr, message);
+ g_free(message);
+ }
+ cairo_destroy(cr);
+ draw_widget(field, 0, 0, field->pixel_width, field->pixel_height);
+ gtk_widget_queue_draw(field->drawing_area);
+}
+
+void redraw_field(struct tetris * tetris)
+{
+ redraw(tetris->field);
+}
+
+void show_message(struct tetris * tetris, MessageType message_type)
+{
+ struct field * field = tetris->field;
+
+ field->show_message = message_type;
+ redraw(field);
+}
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/field.h b/packages/cdebconf-tetris/field.h
new file mode 100644
index 0000000..b688eba
--- /dev/null
+++ b/packages/cdebconf-tetris/field.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _FIELD_H_
+#define _FIELD_H_
+
+#include <gtk/gtk.h>
+#include <cairo/cairo.h>
+
+struct field;
+
+#include "tetris.h"
+
+typedef enum {
+ MESSAGE_NONE,
+ MESSAGE_PAUSED,
+ MESSAGE_GAME_OVER
+} MessageType;
+
+struct field * create_field(struct tetris * tetris, GtkWidget * container);
+
+void destroy_field(struct field * field);
+
+void draw_background(cairo_t * cr);
+void draw_cell(cairo_t * cr, struct block * block, int x, int y);
+
+void redraw_field(struct tetris * tetris);
+
+void show_message(struct tetris * tetris, MessageType message_type);
+
+#endif /* !_FIELD_H_ */
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/gtk-plugin-tetris.c b/packages/cdebconf-tetris/gtk-plugin-tetris.c
new file mode 100644
index 0000000..804b81b
--- /dev/null
+++ b/packages/cdebconf-tetris/gtk-plugin-tetris.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <math.h>
+
+#include <cdebconf/frontend.h>
+#include <cdebconf/question.h>
+#include <cdebconf/cdebconf_gtk.h>
+
+/* Plugin entry point. */
+int cdebconf_gtk_handler_tetris(struct frontend * fe,
+ struct question * question,
+ GtkWidget * question_box);
+
+#include "field.h"
+#include "block_ops.h"
+#include "preview.h"
+#include "score.h"
+
+/* XXX: remove?
+#define BLOCK_SIZE 40 */
+
+/* XXX: remove?
+#define TILE_THRESHOLD 65 */
+
+static void toggle_pause(struct tetris * tetris)
+{
+ int paused = !tetris->paused;
+ gchar * label;
+
+ tetris->paused = paused;
+
+ show_message(tetris, paused ? MESSAGE_PAUSED : MESSAGE_NONE);
+
+ if (paused) {
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/resume", "Resume");
+ } else {
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/pause", "Pause");
+ }
+ gtk_button_set_label(GTK_BUTTON(tetris->pause_button), label);
+ g_free(label);
+}
+
+static void end_game(struct tetris * tetris)
+{
+ gchar * label;
+
+ if (0 != tetris->timeout_id) {
+ g_source_remove(tetris->timeout_id);
+ tetris->timeout_id = 0;
+ }
+ if (tetris->paused) {
+ toggle_pause(tetris);
+ }
+ gtk_widget_set_sensitive(tetris->pause_button, FALSE);
+ gtk_widget_set_sensitive(tetris->continue_button, TRUE);
+
+ tetris->blocknr_next = -1;
+ tetris->rot_next = -1;
+ preview_block(tetris->preview);
+ show_message(tetris, MESSAGE_GAME_OVER);
+ tetris->in_play = FALSE;
+
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/new-game", "New game");
+ gtk_button_set_label(GTK_BUTTON(tetris->game_button), label);
+ g_free(label);
+}
+
+static void generate_new_block(struct tetris * tetris)
+{
+ if (generate_falling_block(tetris)) {
+ put_block_in_field(tetris, FALLING);
+ preview_block(tetris->preview);
+ tetris->one_pause = TRUE;
+ } else {
+ end_game(tetris);
+ }
+}
+
+static void manage_fallen(struct tetris * tetris);
+
+static gboolean handle_timeout(struct tetris * tetris)
+{
+ gboolean res;
+
+ if (tetris->paused) {
+ return TRUE;
+ }
+
+ if (tetris->one_pause) {
+ tetris->one_pause = FALSE;
+ redraw_field(tetris);
+ } else {
+ res = move_block_down(tetris);
+ redraw_field(tetris);
+ if (res) {
+ manage_fallen(tetris);
+ }
+ }
+ return TRUE;
+}
+
+static void generate_timer(struct tetris * tetris, int level)
+{
+ int intv;
+
+ g_assert(level > 0);
+
+ if (0 < tetris->timeout_id) {
+ g_source_remove(tetris->timeout_id);
+ }
+
+ intv = (int) (1000.0 * pow(0.8, level - 1));
+ if (10 >= intv) {
+ intv = 10;
+ }
+ tetris->timeout_id = g_timeout_add(intv, (GSourceFunc) handle_timeout,
+ tetris);
+}
+
+static void manage_fallen(struct tetris * tetris)
+{
+ int level_before;
+ int level_after;
+
+ falling_to_laying(tetris);
+
+ level_before = tetris->level;
+ level_after = score_lines(tetris, check_full_lines(tetris));
+ if (level_before != level_after) {
+ generate_timer(tetris, level_after);
+ }
+
+ if (is_field_empty(tetris)) {
+ score_last_line_bonus(tetris);
+ }
+
+ generate_new_block(tetris);
+}
+
+static void start_new_game(struct tetris * tetris)
+{
+ gchar * label;
+
+ if (tetris->timeout_id) {
+ g_source_remove(tetris->timeout_id);
+ tetris->timeout_id = 0;
+ }
+
+ tetris->in_play = TRUE;
+ tetris->paused = FALSE;
+
+ reset_score(tetris);
+
+ generate_timer(tetris, tetris->level);
+ empty_field(tetris);
+
+ generate_new_block(tetris);
+
+ gtk_widget_set_sensitive(tetris->pause_button, TRUE);
+ gtk_widget_set_sensitive(tetris->continue_button, FALSE);
+
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/end-game", "End game");
+ gtk_button_set_label(GTK_BUTTON(tetris->game_button), label);
+ g_free(label);
+
+ /* will redraw the field. */
+ show_message(tetris, MESSAGE_NONE);
+}
+
+static gboolean handle_key_press(GtkWidget * widget, GdkEvent * event,
+ struct tetris * tetris)
+{
+ gboolean res = FALSE;
+ int keyval = ((GdkEventKey *) event)->keyval;
+
+ if (tetris->in_play && KEY_PAUSE == keyval) {
+ toggle_pause(tetris);
+ return TRUE;
+ }
+
+ if (0 == tetris->timeout_id || tetris->paused) {
+ return FALSE;
+ }
+
+ if (KEY_DOWN == keyval) {
+ if (!tetris->fast_fall && !tetris->one_pause) {
+ tetris->fast_fall = TRUE;
+ g_source_remove(tetris->timeout_id);
+ tetris->timeout_id = g_timeout_add(
+ 10, (GSourceFunc) handle_timeout, tetris);
+ }
+ res = TRUE;
+ }
+
+ if (KEY_LEFT == keyval) {
+ res = move_block_left(tetris);
+ tetris->one_pause = FALSE;
+ res = TRUE;
+ } else if (KEY_RIGHT == keyval) {
+ res = move_block_right(tetris);
+ tetris->one_pause = FALSE;
+ res = TRUE;
+ } else if (KEY_UP == keyval) {
+ res = rotate_block(tetris, ROTATE_COUNTER_CLOCK_WISE);
+ tetris->one_pause = FALSE;
+ res = TRUE;
+ } else if (KEY_DROP == keyval) {
+ tetris->drop_block = TRUE;
+ drop_block(tetris);
+ manage_fallen(tetris);
+ res = TRUE;
+ }
+ if (res) {
+ redraw_field(tetris);
+ }
+ return res;
+}
+
+static gboolean handle_key_release(GtkWidget * widget, GdkEvent * event,
+ struct tetris * tetris)
+{
+ int keyval = ((GdkEventKey *) event)->keyval;
+
+ if (0 == tetris->timeout_id || tetris->paused) {
+ return FALSE;
+ }
+
+ if (KEY_DOWN == keyval) {
+ if (tetris->fast_fall) {
+ tetris->fast_fall = FALSE;
+ generate_timer(tetris, tetris->level);
+ }
+ return TRUE;
+ }
+ if (KEY_DROP == keyval) {
+ tetris->drop_block = FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void handle_game_button(struct tetris * tetris)
+{
+ if (tetris->in_play) {
+ end_game(tetris);
+ } else {
+ start_new_game(tetris);
+ }
+}
+
+static void create_buttons(struct tetris * tetris)
+{
+ gchar * label;
+ GtkWidget * pause_button;
+ GtkWidget * game_button;
+ GtkWidget * continue_button;
+
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/pause", "Pause");
+ pause_button = gtk_button_new_with_label(label);
+ g_free(label);
+ cdebconf_gtk_add_button(tetris->fe, pause_button);
+ cdebconf_gtk_set_button_secondary(tetris->fe, pause_button, TRUE);
+ gtk_widget_set_sensitive(pause_button, FALSE);
+ g_signal_connect_swapped(pause_button, "clicked",
+ (GCallback) toggle_pause, tetris);
+ g_object_ref(pause_button);
+ tetris->pause_button = pause_button;
+
+ label = cdebconf_gtk_get_text(
+ tetris->fe, "cdebconf-gtk-tetris/new-game", "New game");
+ game_button = gtk_button_new_with_label(label);
+ g_free(label);
+ cdebconf_gtk_add_button(tetris->fe, game_button);
+ g_signal_connect_swapped(game_button, "clicked",
+ (GCallback) handle_game_button, tetris);
+ g_object_ref(game_button);
+ tetris->game_button = game_button;
+
+ continue_button = cdebconf_gtk_create_continue_button(tetris->fe);
+ g_object_ref(continue_button);
+ tetris->continue_button = continue_button;
+}
+
+static GtkWidget * create_widget(struct tetris * tetris)
+{
+ GtkWidget * hb;
+ GtkWidget * vb1;
+ GtkWidget * vb2;
+
+ hb = gtk_hbox_new(FALSE, 0);
+
+ vb1 = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vb1), 10);
+ tetris->field = create_field(tetris, vb1);
+ gtk_box_pack_start_defaults(GTK_BOX(hb), vb1);
+
+ vb2 = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vb2), 10);
+ gtk_box_pack_end(GTK_BOX(hb), vb2, 0, 0, 0);
+
+ create_buttons(tetris);
+ tetris->preview = create_preview(tetris, vb2);
+ tetris->score_frame = create_score_frame(tetris, vb2);
+
+ return hb;
+}
+
+static void destroy_tetris(struct tetris * tetris)
+{
+ if (NULL == tetris) {
+ return;
+ }
+ destroy_field(tetris->field);
+ destroy_preview(tetris->preview);
+ destroy_score_frame(tetris->score_frame);
+ g_object_unref(tetris->widget);
+ g_free(tetris);
+}
+
+static void cleanup(struct question * question, struct tetris * tetris)
+{
+ GtkWidget * widget = tetris->widget;
+ GtkWidget * main_window = gtk_widget_get_toplevel(widget);
+
+ g_assert(!tetris->in_play);
+ g_signal_handlers_disconnect_by_func(
+ main_window, handle_key_press, tetris);
+ g_signal_handlers_disconnect_by_func(
+ main_window, handle_key_release, tetris);
+ destroy_tetris(tetris);
+}
+
+int cdebconf_gtk_handler_tetris(struct frontend * fe,
+ struct question * question,
+ GtkWidget * question_box)
+{
+ struct tetris * tetris;
+ GtkWidget * widget;
+ GtkWidget * main_window;
+
+ if (NULL == (tetris = g_malloc0(sizeof (struct tetris)))) {
+ g_warning("g_malloc0 failed.");
+ return DC_NOTOK;
+ }
+ tetris->fe = fe;
+ if (NULL == (widget = create_widget(tetris))) {
+ g_warning("create_widget failed.");
+ return DC_NOTOK;
+ }
+ g_object_ref(widget);
+ tetris->widget = widget;
+
+ cdebconf_gtk_add_common_layout(fe, question, question_box, widget);
+
+ main_window = gtk_widget_get_toplevel(widget);
+
+ g_signal_connect(main_window, "key_press_event",
+ G_CALLBACK(handle_key_press), tetris);
+ g_signal_connect(main_window, "key_release_event",
+ G_CALLBACK(handle_key_release), tetris);
+
+ gtk_widget_grab_focus(widget);
+ cdebconf_gtk_register_setter(fe, SETTER_FUNCTION(cleanup), question,
+ tetris);
+ return DC_OK;
+}
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/linker-script b/packages/cdebconf-tetris/linker-script
new file mode 100644
index 0000000..2877829
--- /dev/null
+++ b/packages/cdebconf-tetris/linker-script
@@ -0,0 +1,6 @@
+{
+ global:
+ cdebconf_gtk_handler_tetris;
+ local:
+ *;
+};
diff --git a/packages/cdebconf-tetris/preview.c b/packages/cdebconf-tetris/preview.c
new file mode 100644
index 0000000..b1d0d2c
--- /dev/null
+++ b/packages/cdebconf-tetris/preview.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <cairo/cairo.h>
+
+#include "preview.h"
+
+#include "blocks.h"
+#include "field.h"
+
+#define PREVIEW_WIDTH 6
+#define PREVIEW_HEIGHT 6
+#define PREVIEW_SIZE 5
+
+struct preview {
+ struct tetris * tetris;
+ GtkWidget * widget;
+ gint pixel_width;
+ gint pixel_height;
+ gboolean enabled;
+ struct block blocks[PREVIEW_WIDTH][PREVIEW_HEIGHT];
+};
+
+static gboolean configure(GtkWidget * widget, GdkEventConfigure * event,
+ struct preview * preview)
+{
+ preview->pixel_width = event->width;
+ preview->pixel_height = event->height;
+
+ return TRUE;
+}
+
+static gboolean expose(GtkWidget * widget, GdkEventExpose * event,
+ struct preview * preview)
+{
+ cairo_t * cr;
+ cairo_surface_t * dst;
+ int x;
+ int y;
+
+ cr = gdk_cairo_create(widget->window);
+
+ if (!preview->enabled) {
+ cairo_scale(cr, 1.0 * widget->allocation.width / PREVIEW_WIDTH,
+ 1.0 * widget->allocation.height / PREVIEW_HEIGHT);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
+
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_paint(cr);
+
+ cairo_set_source_rgb(cr, 0.8, 0.1, 0.1);
+ cairo_set_line_width(cr, 0.5);
+
+ cairo_move_to(cr, 1, 1);
+ cairo_line_to(cr, PREVIEW_WIDTH - 1, PREVIEW_HEIGHT - 1);
+ cairo_move_to(cr, PREVIEW_WIDTH - 1, 1);
+ cairo_line_to(cr, 1, PREVIEW_HEIGHT - 1);
+
+ cairo_stroke (cr);
+ } else {
+ dst = cairo_get_target(cr);
+ draw_background(cr);
+ cairo_scale(cr, 1.0 * preview->pixel_width / PREVIEW_WIDTH,
+ 1.0 * preview->pixel_height / PREVIEW_HEIGHT);
+ for (y = 0; y < PREVIEW_HEIGHT; y++) {
+ for (x = 0; x < PREVIEW_WIDTH; x++) {
+ draw_cell(cr, &preview->blocks[x][y], x, y);
+ }
+ }
+ }
+
+ cairo_destroy (cr);
+
+ return TRUE;
+}
+
+struct preview * create_preview(struct tetris * tetris, GtkWidget * container)
+{
+ struct preview * preview;
+ GtkWidget * widget;
+
+ if (NULL == (preview = g_malloc0(sizeof (struct preview)))) {
+ g_warning("g_malloc failed.");
+ return NULL;
+ }
+ preview->tetris = tetris;
+ preview->enabled = TRUE;
+
+ widget = gtk_drawing_area_new();
+
+ g_object_ref(widget);
+ preview->widget = widget;
+ /* FIXME: We should scale with the rest of the UI, but that requires
+ * changes to the widget layout - i.e. wrap the preview in an
+ * fixed-aspect box. */
+ gtk_widget_set_size_request(
+ widget, PREVIEW_SIZE * 20, PREVIEW_SIZE * 20);
+
+ g_signal_connect(widget, "expose_event", G_CALLBACK(expose), preview);
+ g_signal_connect(widget, "configure_event",
+ G_CALLBACK(configure), preview);
+
+ gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0);
+
+ return preview;
+}
+
+void destroy_preview(struct preview * preview)
+{
+ if (NULL == preview) {
+ return;
+ }
+ g_object_unref(preview->widget);
+ /* preview->widget will be destroyed by its parent. */
+ g_free(preview);
+}
+
+void enable_preview(struct preview * preview, gboolean enabled)
+{
+ preview->enabled = enabled;
+ gtk_widget_queue_draw(preview->widget);
+}
+
+void preview_block(struct preview * preview)
+{
+ struct tetris * tetris = preview->tetris;
+ int blocknr = tetris->blocknr_next;
+ int blockrot = tetris->rot_next;
+ int x;
+ int y;
+
+ for (x = 1; x < PREVIEW_WIDTH - 1; x++) {
+ for (y = 1; y < PREVIEW_HEIGHT - 1; y++) {
+ if ((blocknr != -1) &&
+ BLOCK_TABLE[blocknr][blockrot][x - 1][y - 1]) {
+ preview->blocks[x][y].what = LAYING;
+ preview->blocks[x][y].color = blocknr % BLOCK_TYPES;
+ } else {
+ preview->blocks[x][y].what = EMPTY;
+ }
+ }
+ }
+ gtk_widget_queue_draw(preview->widget);
+}
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/preview.h b/packages/cdebconf-tetris/preview.h
new file mode 100644
index 0000000..0b5f533
--- /dev/null
+++ b/packages/cdebconf-tetris/preview.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _PREVIEW_H_
+#define _PREVIEW_H_
+
+#include <gtk/gtk.h>
+
+struct preview;
+
+#include "tetris.h"
+
+struct preview * create_preview(struct tetris * tetris, GtkWidget * container);
+
+void destroy_preview(struct preview * preview);
+
+void enable_preview(struct preview * preview, gboolean enabled);
+
+void preview_block(struct preview * preview);
+
+#endif /* !_PREVIEW_H_ */
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/score.c b/packages/cdebconf-tetris/score.c
new file mode 100644
index 0000000..7039039
--- /dev/null
+++ b/packages/cdebconf-tetris/score.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "score.h"
+
+#include <gtk/gtk.h>
+
+struct score_frame {
+ GtkWidget * score_widget;
+ GtkWidget * lines_widget;
+ GtkWidget * level_widget;
+};
+
+struct score_frame * create_score_frame(struct tetris * tetris,
+ GtkWidget * container)
+{
+ struct score_frame * score_frame;
+ GtkWidget * table;
+ GtkWidget * score_label;
+ GtkWidget * score_widget;
+ GtkWidget * lines_label;
+ GtkWidget * lines_widget;
+ GtkWidget * level_label;
+ GtkWidget * level_widget;
+
+ if (NULL == (score_frame = g_malloc0(sizeof (struct score_frame)))) {
+ g_warning("g_malloc0 failed.");
+ return NULL;
+ }
+
+ table = gtk_table_new(3, 2, FALSE /* not homogeneous */);
+
+ score_label = gtk_label_new(_("Score:"));
+ gtk_misc_set_alignment(GTK_MISC(score_label), 0.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), score_label, 0, 1, 0, 1);
+
+ score_widget = gtk_label_new("0" /* XXX */);
+ gtk_misc_set_alignment(GTK_MISC(score_widget), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), score_widget, 1, 2, 0, 1);
+
+ g_object_ref(score_widget);
+ score_frame->score_widget = score_widget;
+
+ lines_label = gtk_label_new(_("Lines:"));
+ gtk_misc_set_alignment(GTK_MISC(lines_label), 0.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), lines_label, 0, 1, 1, 2);
+
+ lines_widget = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(lines_widget), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), lines_widget, 1, 2, 1, 2);
+
+ g_object_ref(lines_widget);
+ score_frame->lines_widget = lines_widget;
+
+ level_label = gtk_label_new(_("Level:"));
+ gtk_misc_set_alignment(GTK_MISC(level_label), 0.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), level_label, 0, 1, 2, 3);
+
+ level_widget = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(level_widget), 1.0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(table), level_widget, 1, 2, 2, 3);
+
+ g_object_ref(level_widget);
+ score_frame->level_widget = level_widget;
+
+ gtk_box_pack_end(GTK_BOX(container), table, TRUE, FALSE, 0);
+
+ return score_frame;
+}
+
+void destroy_score_frame(struct score_frame * score_frame)
+{
+ if (NULL == score_frame) {
+ return;
+ }
+ g_object_unref(score_frame->level_widget);
+ g_object_unref(score_frame->lines_widget);
+ g_object_unref(score_frame->score_widget);
+ /* widgets will be destroyed by their parents. */
+ g_free(score_frame);
+}
+
+static void set_score(struct tetris * tetris, int score)
+{
+ struct score_frame * score_frame = tetris->score_frame;
+ gchar * s;
+
+ tetris->score = score;
+ s = g_strdup_printf("%7d", tetris->score);
+ gtk_label_set_text(GTK_LABEL(score_frame->score_widget), s);
+ g_free(s);
+}
+
+static void inc_score(struct tetris * tetris, int increment)
+{
+ set_score(tetris, tetris->score + increment);
+}
+
+void score_last_line_bonus(struct tetris * tetris)
+{
+ inc_score(tetris, 10000 * tetris->level);
+}
+
+static void set_level(struct tetris * tetris, int level)
+{
+ struct score_frame * score_frame = tetris->score_frame;
+ gchar * s;
+
+ tetris->level = level;
+ s = g_strdup_printf("%7d", tetris->level);
+ gtk_label_set_text(GTK_LABEL(score_frame->level_widget), s);
+ g_free(s);
+}
+
+static void set_lines(struct tetris * tetris, int lines)
+{
+ struct score_frame * score_frame = tetris->score_frame;
+ gchar * s;
+
+ tetris->lines = lines;
+ s = g_strdup_printf("%7d", tetris->lines);
+ gtk_label_set_text(GTK_LABEL(score_frame->lines_widget), s);
+ g_free(s);
+}
+
+int score_lines(struct tetris * tetris, int newlines)
+{
+ int level = tetris->level;
+ int linescore = 0;
+
+ switch (newlines) {
+ case 0:
+ return level;
+ case 1:
+ linescore = 40;
+ break;
+ case 2:
+ linescore = 100;
+ break;
+ case 3:
+ linescore = 300;
+ break;
+ case 4:
+ linescore = 1200;
+ break;
+ }
+ inc_score(tetris, level * linescore);
+
+ /* check the level */
+ set_lines(tetris, tetris->lines + newlines);
+ set_level(tetris, STARTING_LEVEL + tetris->lines / 10);
+
+ return level;
+}
+
+void reset_score(struct tetris * tetris)
+{
+ set_lines(tetris, 0);
+ set_score(tetris, 0);
+ set_level(tetris, STARTING_LEVEL);
+}
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/score.h b/packages/cdebconf-tetris/score.h
new file mode 100644
index 0000000..cc3bcc0
--- /dev/null
+++ b/packages/cdebconf-tetris/score.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _SCORE_H_
+#define _SCORE_H_
+
+#include <gtk/gtk.h>
+
+struct score_frame;
+
+#include "tetris.h"
+
+struct score_frame * create_score_frame(struct tetris * tetris,
+ GtkWidget * container);
+
+void destroy_score_frame(struct score_frame * score_frame);
+
+int score_lines(struct tetris * tetris, int newlines);
+
+void score_last_line_bonus(struct tetris * tetris);
+
+void reset_score(struct tetris * tetris);
+
+#endif /* !_SCORE_H_ */
+
+/* vim: et sw=4 si
+ */
diff --git a/packages/cdebconf-tetris/tetris.h b/packages/cdebconf-tetris/tetris.h
new file mode 100644
index 0000000..d19d2d5
--- /dev/null
+++ b/packages/cdebconf-tetris/tetris.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2007 Jérémy Bobbio <lunar@debian.org>
+ *
+ * Based on Gnometris, written by J. Marcin Gorycki <marcin.gorycki@intel.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TETRIS_H_
+#define _TETRIS_H_
+
+#include <glib.h>
+
+#include <cdebconf/frontend.h>
+
+struct tetris;
+
+#include "blocks.h"
+#include "score.h"
+#include "preview.h"
+
+#define LINES 20
+#define COLUMNS 11
+
+#define STARTING_LEVEL 1
+
+#define KEY_PAUSE GDK_p
+#define KEY_DOWN GDK_Down
+#define KEY_LEFT GDK_Left
+#define KEY_RIGHT GDK_Right
+#define KEY_UP GDK_Up
+#define KEY_DROP GDK_space
+
+struct tetris {
+ struct frontend * fe;
+ struct field * field;
+ struct preview * preview;
+ GtkWidget * widget;
+ GtkWidget * pause_button;
+ GtkWidget * game_button;
+ GtkWidget * continue_button;
+ struct score_frame * score_frame;
+ gboolean paused;
+ int timeout_id;
+ gboolean one_pause;
+ gboolean in_play;
+ gboolean fast_fall;
+ gboolean drop_block;
+ int level;
+ int score;
+ int lines;
+ int blocknr_next;
+ int rot_next;
+ int rot;
+ int blocknr;
+ int posx;
+ int posy;
+ struct block blocks[COLUMNS][LINES];
+};
+
+#endif /* !_TETRIS_H_ */
+
+/* vim: et sw=4 si
+ */
--
Jérémy Bobbio .''`.
lunar@debian.org : :Ⓐ : # apt-get install anarchism
`. `'`
`-
Attachment:
signature.asc
Description: Digital signature