summaryrefslogtreecommitdiff
path: root/noncore/games
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/games
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'noncore/games') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/chess/Makefile.in134
-rw-r--r--noncore/games/chess/boardview.cw23
-rw-r--r--noncore/games/chess/chess.cpp358
-rw-r--r--noncore/games/chess/chess.db2
-rw-r--r--noncore/games/chess/chess.h128
-rw-r--r--noncore/games/chess/chess.pro14
-rw-r--r--noncore/games/chess/main.cpp51
-rw-r--r--noncore/games/chess/mainwindow.ui220
-rw-r--r--noncore/games/chess/pieces.pngbin0 -> 5696 bytes
-rw-r--r--noncore/games/chess/qpe-chess.control9
-rw-r--r--noncore/games/chess/simple-l.pngbin0 -> 16143 bytes
-rw-r--r--noncore/games/fifteen/.cvsignore2
-rw-r--r--noncore/games/fifteen/Makefile.in118
-rw-r--r--noncore/games/fifteen/fifteen.cpp364
-rw-r--r--noncore/games/fifteen/fifteen.h83
-rw-r--r--noncore/games/fifteen/fifteen.pro10
-rw-r--r--noncore/games/fifteen/main.cpp33
-rw-r--r--noncore/games/fifteen/qpe-fifteen.control11
-rw-r--r--noncore/games/go/.cvsignore2
-rw-r--r--noncore/games/go/Makefile.in158
-rw-r--r--noncore/games/go/README3
-rw-r--r--noncore/games/go/README.AMIGO42
-rw-r--r--noncore/games/go/README.XAMIGO26
-rw-r--r--noncore/games/go/amigo.c656
-rw-r--r--noncore/games/go/amigo.h146
-rw-r--r--noncore/games/go/go.h81
-rw-r--r--noncore/games/go/go.pro19
-rw-r--r--noncore/games/go/goplayer.c1499
-rw-r--r--noncore/games/go/goplayutils.c1317
-rw-r--r--noncore/games/go/goplayutils.h85
-rw-r--r--noncore/games/go/gowidget.cpp449
-rw-r--r--noncore/games/go/gowidget.h111
-rw-r--r--noncore/games/go/killable.c373
-rw-r--r--noncore/games/go/main.cpp35
-rw-r--r--noncore/games/go/qpe-go.control9
-rw-r--r--noncore/games/mindbreaker/.cvsignore4
-rw-r--r--noncore/games/mindbreaker/Makefile.in117
-rw-r--r--noncore/games/mindbreaker/main.cpp35
-rw-r--r--noncore/games/mindbreaker/mindbreaker.cpp818
-rw-r--r--noncore/games/mindbreaker/mindbreaker.h122
-rw-r--r--noncore/games/mindbreaker/mindbreaker.pro12
-rw-r--r--noncore/games/mindbreaker/qpe-mindbreaker.control9
-rw-r--r--noncore/games/minesweep/.cvsignore2
-rw-r--r--noncore/games/minesweep/Makefile.in134
-rw-r--r--noncore/games/minesweep/main.cpp34
-rw-r--r--noncore/games/minesweep/minefield.cpp623
-rw-r--r--noncore/games/minesweep/minefield.h87
-rw-r--r--noncore/games/minesweep/minesweep.cpp390
-rw-r--r--noncore/games/minesweep/minesweep.h67
-rw-r--r--noncore/games/minesweep/minesweep.pro14
-rw-r--r--noncore/games/minesweep/qpe-minesweep.control9
-rw-r--r--noncore/games/parashoot/.cvsignore3
-rw-r--r--noncore/games/parashoot/Makefile.in203
-rw-r--r--noncore/games/parashoot/base.cpp71
-rw-r--r--noncore/games/parashoot/base.h38
-rw-r--r--noncore/games/parashoot/bullet.cpp142
-rw-r--r--noncore/games/parashoot/bullet.h51
-rw-r--r--noncore/games/parashoot/cannon.cpp140
-rw-r--r--noncore/games/parashoot/cannon.h58
-rw-r--r--noncore/games/parashoot/codes.h25
-rw-r--r--noncore/games/parashoot/helicopter.cpp114
-rw-r--r--noncore/games/parashoot/helicopter.h45
-rw-r--r--noncore/games/parashoot/interface.cpp247
-rw-r--r--noncore/games/parashoot/interface.h79
-rw-r--r--noncore/games/parashoot/main.cpp36
-rw-r--r--noncore/games/parashoot/man.cpp174
-rw-r--r--noncore/games/parashoot/man.h52
-rw-r--r--noncore/games/parashoot/parashoot.pro11
-rw-r--r--noncore/games/parashoot/qpe-parashoot.control9
-rw-r--r--noncore/games/qasteroids/.cvsignore2
-rw-r--r--noncore/games/qasteroids/Makefile.in155
-rw-r--r--noncore/games/qasteroids/ledmeter.cpp135
-rw-r--r--noncore/games/qasteroids/ledmeter.h72
-rw-r--r--noncore/games/qasteroids/main.cpp36
-rw-r--r--noncore/games/qasteroids/qasteroids.pro11
-rw-r--r--noncore/games/qasteroids/qpe-qasteroids.control9
-rw-r--r--noncore/games/qasteroids/sprites.h147
-rw-r--r--noncore/games/qasteroids/toplevel.cpp514
-rw-r--r--noncore/games/qasteroids/toplevel.h99
-rw-r--r--noncore/games/qasteroids/view.cpp884
-rw-r--r--noncore/games/qasteroids/view.h156
-rw-r--r--noncore/games/snake/.cvsignore3
-rw-r--r--noncore/games/snake/Makefile.in159
-rw-r--r--noncore/games/snake/codes.h20
-rw-r--r--noncore/games/snake/interface.cpp224
-rw-r--r--noncore/games/snake/interface.h69
-rw-r--r--noncore/games/snake/main.cpp35
-rw-r--r--noncore/games/snake/obstacle.cpp51
-rw-r--r--noncore/games/snake/obstacle.h30
-rw-r--r--noncore/games/snake/qpe-snake.control9
-rw-r--r--noncore/games/snake/snake.cpp246
-rw-r--r--noncore/games/snake/snake.h64
-rw-r--r--noncore/games/snake/snake.pro11
-rw-r--r--noncore/games/snake/target.cpp77
-rw-r--r--noncore/games/snake/target.h37
-rw-r--r--noncore/games/solitaire/.cvsignore3
-rw-r--r--noncore/games/solitaire/Makefile.in235
-rw-r--r--noncore/games/solitaire/canvascard.cpp282
-rw-r--r--noncore/games/solitaire/canvascard.h82
-rw-r--r--noncore/games/solitaire/canvascardgame.cpp380
-rw-r--r--noncore/games/solitaire/canvascardgame.h95
-rw-r--r--noncore/games/solitaire/canvascardwindow.cpp227
-rw-r--r--noncore/games/solitaire/canvascardwindow.h70
-rw-r--r--noncore/games/solitaire/canvasshapes.cpp92
-rw-r--r--noncore/games/solitaire/canvasshapes.h55
-rw-r--r--noncore/games/solitaire/card.cpp53
-rw-r--r--noncore/games/solitaire/card.h84
-rw-r--r--noncore/games/solitaire/carddeck.cpp81
-rw-r--r--noncore/games/solitaire/carddeck.h49
-rw-r--r--noncore/games/solitaire/cardgame.cpp35
-rw-r--r--noncore/games/solitaire/cardgame.h45
-rw-r--r--noncore/games/solitaire/cardgamelayout.cpp61
-rw-r--r--noncore/games/solitaire/cardgamelayout.h42
-rw-r--r--noncore/games/solitaire/cardpile.cpp114
-rw-r--r--noncore/games/solitaire/cardpile.h101
-rw-r--r--noncore/games/solitaire/freecellcardgame.cpp137
-rw-r--r--noncore/games/solitaire/freecellcardgame.h152
-rw-r--r--noncore/games/solitaire/main.cpp36
-rw-r--r--noncore/games/solitaire/patiencecardgame.cpp234
-rw-r--r--noncore/games/solitaire/patiencecardgame.h206
-rw-r--r--noncore/games/solitaire/qpe-solitaire.control9
-rwxr-xr-xnoncore/games/solitaire/solitaire.pro18
-rw-r--r--noncore/games/tetrix/.cvsignore3
-rw-r--r--noncore/games/tetrix/Makefile.in157
-rw-r--r--noncore/games/tetrix/gtetrix.cpp514
-rw-r--r--noncore/games/tetrix/gtetrix.h104
-rw-r--r--noncore/games/tetrix/main.cpp33
-rw-r--r--noncore/games/tetrix/qpe-tetrix.control10
-rw-r--r--noncore/games/tetrix/qtetrix.cpp170
-rw-r--r--noncore/games/tetrix/qtetrix.h78
-rw-r--r--noncore/games/tetrix/qtetrixb.cpp251
-rw-r--r--noncore/games/tetrix/qtetrixb.h80
-rw-r--r--noncore/games/tetrix/tetrix.pro17
-rw-r--r--noncore/games/tetrix/tpiece.cpp201
-rw-r--r--noncore/games/tetrix/tpiece.h62
-rw-r--r--noncore/games/wordgame/.cvsignore6
-rw-r--r--noncore/games/wordgame/Makefile.in168
-rwxr-xr-xnoncore/games/wordgame/calcdist27
-rw-r--r--noncore/games/wordgame/main.cpp34
-rw-r--r--noncore/games/wordgame/newgamebase.ui337
-rw-r--r--noncore/games/wordgame/qpe-wordgame.control10
-rw-r--r--noncore/games/wordgame/rulesbase.ui274
-rw-r--r--noncore/games/wordgame/wordgame.cpp1476
-rw-r--r--noncore/games/wordgame/wordgame.h376
-rw-r--r--noncore/games/wordgame/wordgame.pro13
145 files changed, 21180 insertions, 0 deletions
diff --git a/noncore/games/chess/Makefile.in b/noncore/games/chess/Makefile.in
new file mode 100644
index 0000000..7354d76
--- a/dev/null
+++ b/noncore/games/chess/Makefile.in
@@ -0,0 +1,134 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) -DQCONFIG=\"qpe\"
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS) -DQCONFIG=\"qpe\"
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = ../bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = chess
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = chess.h
+SOURCES = chess.cpp \
+ main.cpp
+OBJECTS = chess.o \
+ main.o \
+ mainwindow.o
+INTERFACES = mainwindow.ui
+UICDECLS = mainwindow.h
+UICIMPLS = mainwindow.cpp
+SRCMOC = moc_chess.cpp \
+ moc_mainwindow.cpp
+OBJMOC = moc_chess.o \
+ moc_mainwindow.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake chess.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+chess.o: chess.cpp \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ chess.h
+
+main.o: main.cpp \
+ mainwindow.h
+
+mainwindow.h: mainwindow.ui
+ $(UIC) mainwindow.ui -o $(INTERFACE_DECL_PATH)/mainwindow.h
+
+mainwindow.cpp: mainwindow.ui
+ $(UIC) mainwindow.ui -i mainwindow.h -o mainwindow.cpp
+
+mainwindow.o: mainwindow.cpp \
+ mainwindow.h \
+ mainwindow.ui
+
+moc_chess.o: moc_chess.cpp \
+ chess.h
+
+moc_mainwindow.o: moc_mainwindow.cpp \
+ mainwindow.h
+
+moc_chess.cpp: chess.h
+ $(MOC) chess.h -o moc_chess.cpp
+
+moc_mainwindow.cpp: mainwindow.h
+ $(MOC) mainwindow.h -o moc_mainwindow.cpp
+
+
diff --git a/noncore/games/chess/boardview.cw b/noncore/games/chess/boardview.cw
new file mode 100644
index 0000000..020af96
--- a/dev/null
+++ b/noncore/games/chess/boardview.cw
@@ -0,0 +1,23 @@
+<!DOCTYPE CW><CW>
+<customwidgets>
+ <customwidget>
+ <class>BoardView</class>
+ <header location="global">/home/luke/depot/qpe/chess/chess.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>
+ <data format="XPM.GZ" length="4605">789c6dd7d96ee33a1206e0fb7e8aa0ebae31a863c9966d613017d9e3ecce9e0ce6a228c94b6c67f192d83998771f9af517e10493b4daf89a25b258a428f75f7fb61e2ecfb6fefcf56b3697f9b0d82a0632ddfa532e2693d5bffff3afbf7ffd4ed3adf027d94a7fffe3d76ff7b9556c9dbfbe5401ef9bf8d8c464136f9b186ee27513cf9bd8dec47c13d30d74bfb52c3d28cdd322a9058fd6aee7f5a29e047f697bbd96b483573fe2173ffc82fbdbb87fb0762389fdcdd6ee859fe0716ccfd7e6def7fed8c5f1d5c5f77c58c2788959ea70230dfd3982dba9de7f6ff9693b757ee4dbb7f9a3fdf5473d7aea464dfb23fa3e3fdafe319f3d75a3a1edbc0fb7913f9991df8b19f7977081f1ae83c5da89cd8dd0bf34601bffceaced14facfd22c53f36db484f95570a9e3398ed6f1c27ec8c4e239877378d79c85bd4f477089f117d1219ee666c4d7d4cd04fddd98d1de5ebb995abc3ca863fb04467eb26746fc398c7ce5c0aced7c1dade3bfc2983f5766acf7be19f59f466b3d4b752bc1fd9a9f58ffd28311cf6d33f2b9323735ff17752bc17855b4f697c119f2cbcd884fe15cd757d6c711b5ea2dd48766708efd959871ffb319f53c86ad1e67d1fafc89ba9d60bcaf68edffca8ce7ab8033c4b7a2b57e3bc1ae95b7eac1db70091fa9db895a6e61ab472b3af4277730e6cb5d33e69bc3781e6865c6f31ce6d3f6f9b75c881738d3f5e2b119ed27708ef655b4aedf0d6cf5fc50e709f27d84510fb930e3f94a615bdf6bb3f627f7b0cd47f3f5f36d877a5103b67af6cddace23759e20fe00b6e77da016acb77370a6e71df5cc18bf1fadfb610c0bcef304ae6aeab619ef83f57b92f286e5c3cfd1a1de3c803378095bbd9bea98cf305af7430b16d47319adf53f34637daee00af9f7d52ed57c692f5acf7fbdbfc8f3bc113c834be43b35a37d185d84feeed482fd47e77086fdbf0b57d81f75b54b311f8ad6f95e9a319f1adc44fed3689ddf132c589f8e59e385a3b5fdcc8cf1bb30d697a2311eea53a07e1cce7b6948a2f52007676ad956bb14e7e53e6cebb382adff67339eb7a5dac6930f33ce87266cf5388dd6f50ccf83f87a8baed77bb4aed78edaa5c877085738ff3fcdd89f13b58d4f68b7f1e5d48cfd589a118ff10bd49b9ea235fe12aef0fc55669c6fe17c718d42701ececcfafea2118cfb3935e3bcf98cd6f18ecc785fbd99f1beabab4bab77c38cef2b613d5c5908ced357b8c2799aa9637c12ade32dcc787fedc04d7c1fb935e33c7b8cd6f509df578aac10acef02aef0bc76ccbade7caeb6fb656ec6fe1c98f1fc5ec2a82f9f9931bf5ab4e67b0263bf70d80f455956e8efc6acf9d185ba4a51bfb119e779789f97be7f9d1fbda9637b19adf73b33e21fe026ea7162c6f31ad6a7acaad4e9fe1fc1d6be1badf53b36a39e4fb0e5771f1dda257c7fa89a668a76657013b6f509eb5bf99f225bbb3b5fff32b1b0e3c25fffefb3d4288de78a7bdce7010ffdf5cca38dabef7fc73ce1177fcf6b8c77fcc6ef3cf56d6f3ce3392ff8833f79c92bfee26ddef1f1bbbcc785c6f3be8f3be0433ef2b11d3ee6133ee5333ee70bbee42e5ff135dff02ddff13d5388179fc5d4f7f4c08ffcc4354e38e53a3738f39f4d6e719b73ce898958d7a7c74312725450491537a9477d1ad0909e69e4e39b34a609bdf01dbdb2d6abf0fd3ff8e8377aa729cd684e8b704de8833e69e97f57f4e5fbdf8efd3fd30eed724a7bb44f733ff6fa3ae0aebf6be5a30f7d2f473ebe8378f1f1c77442a77416fb3ea70bba0c77f47c465dbaa2eb6ffddfd0adefddfabea37b7aa0477aa21a25beff25a5a17fcbff994a4ea88ebe1b9451d3d734a116b529f7d15df1cbefe71bfbe753ba145af72d224e7ca5f84c4aa9bc7b7edca5f4bfe72f03df3ea485f83b652463bf0a19d765e2df012febfcb9f53d7f79f5f16ff22e5399c95c16f2219f7ec512ffe9eb232bf9fa96ff48b67ddb8eecca9eef719fbb72208772b45ee175fda523c7dff2efcb899cfad57a973339478de672219721ba2b573fea3fe61db9f6792eb9292c37722b77d4926558dbaecfa62ff73eff4eec7fc2d7f2208f612dfde5ef3c44e493cfa523354924953af22fa5e1f7f7adaf9dff4f9d5fcb25aeae7468202d1fdd96dcb123ddcfe179d9f3fbef3a5c95131abbf54fc1fe0deb3771e9a32bd7e35e7cbefc4e757d377043f78c6be4af71f87be25edcab7b73ef6eaaf16eb67e92dddc2ddc87fbf4ff6e9f9ffe73e93f57eecb6dfb081ff7fbbffffcf53f54dd2532</data>
+ </pixmap>
+ <slot access="public">newGame()</slot>
+ <slot access="public">swapSides()</slot>
+ <slot access="public">setTheme(QString)</slot>
+ </customwidget>
+</customwidgets>
+</CW>
diff --git a/noncore/games/chess/chess.cpp b/noncore/games/chess/chess.cpp
new file mode 100644
index 0000000..96a838a
--- a/dev/null
+++ b/noncore/games/chess/chess.cpp
@@ -0,0 +1,358 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+// human is not offered a promotion yet
+
+#include <qcanvas.h>
+#include <qmainwindow.h>
+#include <qlist.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qmessagebox.h>
+#include <qregexp.h>
+
+#include <qpe/config.h>
+#include <qpe/resource.h>
+
+#include "chess.h"
+
+#define CHESS_DEBUG
+
+int pieceSize = 40;
+static QVector < QImage > imgList;
+int timeMoves, timeTime;
+
+int BoardView::convertToRank(int r)
+{
+ r = r / pieceSize;
+ if (humanSide == sideWhite)
+ r = 8 - r;
+ else
+ r++;
+ return r;
+}
+
+char BoardView::convertToFile(int f)
+{
+ f = f / pieceSize;
+ if (humanSide == sideWhite)
+ return f + 'a';
+ else
+ return 'h' - f;
+}
+
+int BoardView::convertFromFile(char f)
+{
+ if (humanSide == sideWhite)
+ f = f - 'a';
+ else
+ f = 'h' - f;
+ return f * pieceSize;
+}
+
+int BoardView::convertFromRank(int r)
+{
+ if (humanSide == sideWhite)
+ r = 8 - r;
+ else
+ r--;
+ return r * pieceSize;
+}
+
+// Pieces
+Piece::Piece(QCanvas * canvas, int t):QCanvasRectangle(canvas)
+{
+ type = t;
+ setSize(pieceSize, pieceSize);
+ show();
+}
+
+Piece *BoardView::newPiece(int t, char f, int r)
+{
+ Piece *tmpPiece = new Piece(canvas(), t);
+ tmpPiece->move(convertFromFile(f), convertFromRank(r));
+ list.append(tmpPiece);
+ return tmpPiece;
+}
+
+void BoardView::deletePiece(Piece * p)
+{
+ list.remove(p);
+ canvas()->update();
+}
+
+void Piece::drawShape(QPainter & p)
+{
+ p.drawImage(int (x()), int (y()), *(imgList[type]));
+}
+
+void BoardView::buildImages(QImage theme)
+{
+ imgList.resize(12);
+ int x;
+ int y = 0;
+
+ for (int j = 0; j < 2; j++) {
+ x = 0;
+ for (int i = 0; i < 6; i++) {
+ imgList.insert(i + (j * 6),
+ new QImage(theme.
+ copy(x, y, pieceSize, pieceSize)));
+ x += pieceSize;
+ }
+ y += pieceSize;
+ }
+}
+
+void BoardView::readStdout()
+{
+ QString input( crafty->readStdout() );
+#ifdef CHESS_DEBUG
+ qDebug("received this string from crafty->\n%s\n", input.latin1());
+#endif
+
+ int startPosition = input.find("setboard");
+ if (startPosition != -1)
+ decodePosition(input.remove(0, startPosition + 9));
+
+ if (input.contains("Black mates")) {
+ playingGame = FALSE;
+ emit(showMessage("Black mates"));
+ } else if (input.contains("White mates")) {
+ playingGame = FALSE;
+ emit(showMessage("White mates"));
+ } else if (input.contains(" resigns")) {
+ playingGame = FALSE;
+ emit(showMessage("Computer resigns"));
+ } else if (input.contains("Draw")) {
+ playingGame = FALSE;
+ emit(showMessage("Draw"));
+ }
+}
+
+// this is pretty close to getting done right
+// maybe dont use sprites and just draw a picture
+// there'll be lots of drawing done anyway
+// eg creating pictures for the webpages,
+// and presenting options for promotions
+void BoardView::decodePosition(const QString & t)
+{
+ qDebug("decode copped %s \n", t.latin1());
+
+ int count = 0;
+ int stringPos = 0;
+ for (int file = 0; file < 8; file++) {
+ for (int rank = 0; rank < 8; rank++) {
+ if (count)
+ count--;
+ else {
+ if (t.at(stringPos).isNumber())
+ count = t.at(stringPos).digitValue();
+ else {
+ newPiece(t.at(stringPos).latin1(), 'a' + file,
+ rank + 1);
+ }
+ }
+ }
+ }
+}
+
+void BoardView::undo()
+{
+ crafty->writeToStdin("undo\n");
+ crafty->writeToStdin("savepos\nclock\n");
+}
+
+void BoardView::emitErrorMessage()
+{
+ if (activeSide != humanSide)
+ emit(showMessage("Not your move"));
+ else
+ emit(showMessage("You are not playing a game"));
+}
+
+void BoardView::annotateGame()
+{
+ crafty->
+ writeToStdin
+ ("savegame game.save\nannotateh game.save bw 0 1.0 1\n");
+ emit(showMessage("Annotating game"));
+}
+
+Piece *BoardView::findPiece(char f, int r)
+{
+ QListIterator < Piece > it(list);
+ Piece *tmpPiece;
+ for (; it.current(); ++it) {
+ tmpPiece = it.current();
+ if (convertToRank(tmpPiece->x()) == r
+ && convertToFile(tmpPiece->y()) == f)
+ return tmpPiece;
+ }
+ return 0;
+}
+
+void BoardView::newGame()
+{
+ activeSide = sideWhite;
+ emit(showMessage("New game"));
+ crafty->writeToStdin("new\n");
+ crafty->writeToStdin("savepos\n");
+ crafty->writeToStdin("time " +
+ QString::number(timeMoves) +
+ "/" + QString::number(timeTime) + "\n");
+ activeSide = sideWhite;
+ if (humanSide == sideBlack)
+ crafty->writeToStdin("go\n");
+}
+
+void BoardView::setTheme(QString filename)
+{
+ QImage theme = Resource::loadImage(QString("chess/") + filename);
+ pieceSize = theme.height() / 2;
+ setFrameStyle(QFrame::Plain);
+ setFixedSize(8 * pieceSize, 8 * pieceSize);
+ canvas()->setBackgroundColor(Qt::red);
+ canvas()->resize(8 * pieceSize, 8 * pieceSize);
+ whiteSquare = theme.copy(6 * pieceSize, 0, pieceSize, pieceSize);
+ activeWhiteSquare = theme.copy(7 * pieceSize, 0, pieceSize, pieceSize);
+ blackSquare =
+ theme.copy(6 * pieceSize, pieceSize, pieceSize, pieceSize);
+ activeBlackSquare =
+ theme.copy(7 * pieceSize, pieceSize, pieceSize, pieceSize);
+ buildImages(theme);
+ drawBackgroundImage(QPoint(-1, -1));
+}
+
+
+// sets the bg to the default background image for the current theme
+// also resposible for drawing the "active" marker
+void BoardView::drawBackgroundImage(QPoint activeSquare)
+{
+ bg = QPixmap(8 * pieceSize, 8 * pieceSize);
+ QPainter p(&bg);
+ bool col = FALSE;
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ QPoint point(i * pieceSize, j * pieceSize);
+ if (col) {
+ if (point.x() == activeSquare.x()
+ && point.y() == activeSquare.y())
+ p.drawImage(point, activeBlackSquare);
+ else
+ p.drawImage(point, blackSquare);
+ col = FALSE;
+ } else {
+ if (point.x() == activeSquare.x()
+ && point.y() == activeSquare.y())
+ p.drawImage(point, activeWhiteSquare);
+ else
+ p.drawImage(point, whiteSquare);
+ col = TRUE;
+ }
+ }
+ col = !col;
+ }
+ canvas()->setBackgroundPixmap(bg);
+ canvas()->update();
+}
+
+
+// Board view widget
+void BoardView::contentsMousePressEvent(QMouseEvent * e)
+{
+ QCanvasItemList cList = canvas()->collisions(e->pos());
+ if (activeSide == humanSide && playingGame) {
+ if (!activePiece) {
+ if (cList.count()) {
+ activePiece = (Piece *) (*(cList.at(0)));
+ drawBackgroundImage(QPoint
+ (activePiece->x(), activePiece->y()));
+ }
+ } else {
+ if (!(activePiece == (Piece *) (*(cList.at(0))))) {
+ char fromFile = convertToFile(activePiece->x());
+ int fromRank = convertToRank(activePiece->y());
+ char toFile = convertToFile(e->pos().x());
+ int toRank = convertToRank(e->pos().y());
+ QString moveS;
+ moveS.append(fromFile);
+ moveS.append(moveS.number(fromRank));
+ moveS.append(toFile);
+ moveS.append(moveS.number(toRank));
+ if ((activePiece->type == wPawn
+ && fromRank == 7 && toRank == 8)
+ || (activePiece->type == bPawn
+ && fromRank == 2 && toRank == 1)) {
+ // offer a promotion
+ emit(showMessage
+ ("you are meant to be offered a promotion here"));
+ char promoteTo = wQueen; // doesnt matter for now
+ moveS.append(promoteTo);
+ moveS.append("\n");
+ crafty->writeToStdin(moveS.latin1());
+ }
+ }
+ activePiece = 0;
+ drawBackgroundImage(QPoint(-1, -1));
+ }
+ }
+
+ else {
+ emitErrorMessage();
+ }
+}
+
+void BoardView::swapSides()
+{
+ if (activeSide == humanSide && playingGame) {
+ humanSide = !humanSide;
+ crafty->writeToStdin("savepos\ngo\n");
+ } else
+ emitErrorMessage();
+}
+
+BoardView::BoardView(QCanvas *c, QWidget *w, const char *name)
+ : QCanvasView(c, w, name) {
+ humanSide = sideWhite;
+ activeSide = sideWhite;
+ playingGame = TRUE;
+ activePiece = 0;
+ list.setAutoDelete(TRUE);
+ setCanvas(new QCanvas());
+ Config c("Chess", Config::User);
+ c.setGroup("Theme");
+ QString theme = c.readEntry("imagefile", "simple-28");
+ setTheme(theme);
+ crafty = new CraftyProcess(this);
+ crafty->addArgument("crafty");
+ if (!crafty->start()) {
+ QMessageBox::critical(0,
+ tr("Could not find crafty chess engine"),
+ tr("Quit"));
+ exit(-1);
+ }
+
+ connect(crafty, SIGNAL(readyReadStdout()), this, SLOT(readStdout()));
+ connect(crafty, SIGNAL(processExited()), this, SLOT(craftyDied()));
+// crafty->writeToStdin("xboard\nics\nkibitz=2\n");
+ newGame();
+}
diff --git a/noncore/games/chess/chess.db b/noncore/games/chess/chess.db
new file mode 100644
index 0000000..b520b30
--- a/dev/null
+++ b/noncore/games/chess/chess.db
@@ -0,0 +1,2 @@
+<!DOCTYPE DB><DB version="1.0">
+</DB>
diff --git a/noncore/games/chess/chess.h b/noncore/games/chess/chess.h
new file mode 100644
index 0000000..067b2f8
--- a/dev/null
+++ b/noncore/games/chess/chess.h
@@ -0,0 +1,128 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+** $Id$
+**
+**********************************************************************/
+#ifndef CHESS_H
+#define CHESS_H
+
+#include <qwidget.h>
+#include <qcanvas.h>
+#include <qmainwindow.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qstack.h>
+#include <qvector.h>
+#include <qpe/process.h>
+
+#define wPawn 'P'
+#define wKnight 'N'
+#define wBishop 'B'
+#define wRook 'R'
+#define wQueen 'Q'
+#define wKing 'K'
+#define bPawn 'p'
+#define bKnight 'n'
+#define bBishop 'b'
+#define bRook 'r'
+#define bQueen 'q'
+#define bKing 'k'
+#define NONE N
+
+#define sideWhite 0
+#define sideBlack 1
+
+
+class Piece:public QCanvasRectangle {
+ public:
+ Piece(QCanvas *, int);
+ ~Piece() {
+ };
+
+ char type;
+
+ protected:
+ void drawShape(QPainter &);
+};
+
+
+class CraftyProcess : public Process {
+ public:
+ CraftyProcess(QObject *parent) : Process( parent ) { qDebug("CraftyProcess functions not implemented"); }
+ ~CraftyProcess() { }
+ bool start() { qDebug("CraftyProcess functions not implemented"); return FALSE; }
+ const char *readStdout() { qDebug("CraftyProcess functions not implemented"); return "Blah"; }
+ void writeToStdin(const char *) { qDebug("CraftyProcess functions not implemented"); }
+};
+
+
+class BoardView:public QCanvasView {
+ Q_OBJECT public:
+ BoardView(QCanvas *, QWidget *, const char *);
+ ~BoardView() {
+ };
+
+ protected:
+ void contentsMousePressEvent(QMouseEvent *);
+
+ signals:
+ void showMessage(const QString &);
+
+ public slots:void readStdout();
+ void craftyDied() {
+ qFatal("Crafty died unexpectedly\n");
+ };
+ void newGame();
+ void setTheme(QString);
+ void swapSides();
+ void undo();
+ void annotateGame();
+
+ private:
+ CraftyProcess * crafty;
+ QList < Piece > list;
+ Piece *activePiece;
+
+ void revertLastMove();
+ void emitErrorMessage();
+ void drawBackgroundImage(QPoint activeSquare);
+
+ void buildImages(QImage);
+
+ char convertToFile(int);
+ int convertToRank(int);
+ int convertFromFile(char);
+ int convertFromRank(int);
+
+ void decodePosition(const QString & t);
+
+ Piece *findPiece(char f, int r);
+ Piece *newPiece(int, char, int);
+ void deletePiece(Piece *);
+
+ int pieceSize;
+ QPixmap bg;
+ QImage whiteSquare, blackSquare, activeWhiteSquare, activeBlackSquare;
+
+ bool humanSide;
+ bool activeSide;
+ bool playingGame;
+};
+
+#endif
diff --git a/noncore/games/chess/chess.pro b/noncore/games/chess/chess.pro
new file mode 100644
index 0000000..f6650a0
--- a/dev/null
+++ b/noncore/games/chess/chess.pro
@@ -0,0 +1,14 @@
+SOURCES += chess.cpp main.cpp
+HEADERS += chess.h
+DESTDIR = ../bin
+TARGET = chess
+DEPENDPATH += $(QPEDIR)/include
+INTERFACES = mainwindow.ui
+IMAGES = images/new.png images/repeat.png images/txt.png images/back.png
+TEMPLATE =app
+CONFIG += qt warn_on release
+INCLUDEPATH += $(QPEDIR)/include
+LIBS += -lqpe
+DBFILE = chess.db
+LANGUAGE = C++
+CPP_ALWAYS_CREATE_SOURCE = TRUE
diff --git a/noncore/games/chess/main.cpp b/noncore/games/chess/main.cpp
new file mode 100644
index 0000000..a56913f
--- a/dev/null
+++ b/noncore/games/chess/main.cpp
@@ -0,0 +1,51 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+** $Id$
+**
+**********************************************************************/
+#include <qpe/qpeapplication.h>
+#include <qpe/qpetoolbar.h>
+#include <qmainwindow.h>
+#include <qcanvas.h>
+#include "chess.h"
+
+
+class CanvasMainWindow : public QMainWindow {
+public:
+ CanvasMainWindow(QWidget* parent=0, const char* name=0, WFlags f=0)
+ : QMainWindow(parent,name,f), canvas(232, 258) {
+ view = new BoardView(&canvas, this, 0);
+ setToolBarsMovable( FALSE );
+ QPEToolBar* toolbar = new QPEToolBar(this);
+ toolbar->setHorizontalStretchable( TRUE );
+ }
+
+private:
+ QCanvas canvas;
+ BoardView *view;
+};
+
+
+int main( int argc, char **argv ) {
+ QPEApplication a(argc,argv);
+ CanvasMainWindow *mw = new CanvasMainWindow();
+ a.showMainWidget( mw );
+ return a.exec();
+}
+
diff --git a/noncore/games/chess/mainwindow.ui b/noncore/games/chess/mainwindow.ui
new file mode 100644
index 0000000..dc3ae0f
--- a/dev/null
+++ b/noncore/games/chess/mainwindow.ui
@@ -0,0 +1,220 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>MainWindow</class>
+<widget class="QMainWindow">
+ <property name="name">
+ <cstring>MainWindow</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>256</width>
+ <height>338</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Chess</string>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>236</y>
+ <width>221</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>TextLabel1</string>
+ </property>
+ </widget>
+ <widget class="BoardView">
+ <property name="name">
+ <cstring>ChessBoard</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>224</width>
+ <height>224</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>224</width>
+ <height>224</height>
+ </size>
+ </property>
+ </widget>
+</widget>
+<menubar>
+ <property name="name">
+ <cstring>menubar</cstring>
+ </property>
+ <item text="Game" name="PopupMenu_2">
+ <action name="newGame"/>
+ <action name="annotateGame"/>
+ </item>
+ <item text="Position" name="PopupMenu_3">
+ <action name="swapSides"/>
+ <action name="undo"/>
+ </item>
+</menubar>
+<toolbars>
+</toolbars>
+<customwidgets>
+ <customwidget>
+ <class>BoardView</class>
+ <header location="global">/home/luke/depot/qpe/chess/chess.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>showMessage(const QString&amp;)</signal>
+ <slot access="public" specifier="">newGame()</slot>
+ <slot access="public" specifier="">swapSides()</slot>
+ <slot access="public" specifier="">setTheme(QString)</slot>
+ <slot access="public" specifier="">undo()</slot>
+ <slot access="public" specifier="">annotateGame()</slot>
+ </customwidget>
+</customwidgets>
+<actions>
+ <actiongroup>
+ <property name="name">
+ <cstring>gameActions</cstring>
+ </property>
+ <property name="text">
+ <string>ActionGroup</string>
+ </property>
+ <property name="usesDropDown">
+ <bool>false</bool>
+ </property>
+ <action>
+ <property name="name">
+ <cstring>newGame</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>new.png</iconset>
+ </property>
+ <property name="text">
+ <string>New Game</string>
+ </property>
+ <property name="menuText">
+ <string>New Game</string>
+ </property>
+ <property name="toolTip">
+ <string>New Game</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>swapSides</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>repeat.png</iconset>
+ </property>
+ <property name="text">
+ <string>Swap sides</string>
+ </property>
+ <property name="toolTip">
+ <string>Swap sides</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>annotateGame</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>txt.png</iconset>
+ </property>
+ <property name="text">
+ <string>Annotate game</string>
+ </property>
+ <property name="toolTip">
+ <string>Annotate game</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>undo</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>back.png</iconset>
+ </property>
+ <property name="text">
+ <string>Undo move</string>
+ </property>
+ <property name="toolTip">
+ <string>Undo move</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>saveGame</cstring>
+ </property>
+ <property name="text">
+ <string>Action</string>
+ </property>
+ </action>
+ </actiongroup>
+</actions>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="3456">789ce5d35d5313491406e07b7e458abea3b68e99cfccd4d65ee0079ac8a720a2d65ef474cf2424229004152dffbba7cf795941182a59bcd8aa6548524fbafb9d9ed3278fd63a47bb5b9db5472bb3b99d1fbb8e1bd96967cd5f9c9c5cbefffbaf6f2bab49dce1ff5eaf13affeb1b24aa6e33aa62b7f620fa7b01517ec423c850bb571b0c3f8bbe0a8db7591ae1fa9c3257e0aa7b0ac8f0ab6aeefc305bc073b783d38ee462ed6f5953a5ce20d38859f894b7629de820bb519c20ee3af829328764924be50275d7806a76a732c2ed9ba7e08176a33811d2cf548a3c4a59a97a9d3aedad4708af153b1655bf14bb880bfc00e3e0fcee2ac9be9f926629b65998eefc21e3e0acee3cce73affb33acfe037ff58e737629b97f026ece128b897e4be9788bfaa7b119cc319fc445cb12bf1215caa8d813d2cfd59243d5fe8faaeb82ab242d7d770097f803d2ce751a66554a6e28f70a636d24fa5633b191fc325fc1cf6f049b04d6d6435ef139cc16fc5ce5aabf3b7e11ade09ae525b573a7f5f5dc5f00bb1aff2ca8b07b0559b315c63fc20d86555ed32f15ced62f812ce61e95fe7d99a67610b3770ada65eb0e776f1bafe4c5cb36bf16bd8c245709dd7719d8b5371cddfc8b821d8aa290e6e78b4d1f9a5ba89e1c7e2a6b14d13bc37879b2bdf7f91b9fffadf65d8df90519123ffc08c9a1a1ad2a86d3ff767d0318d69421fe8843ed229a72c9d4167742ef79ed28ce69c7471f713b567d027beef675ea733bfd0257da5f5bb52da32e8313de18ca7f48c67add30657f539bde07df597c818d04bdae41a84593557654a5bb44d3bb44b7bbfeea53563c2ab467c1a61569f77123e5fd13e1d704a7533a535e3351dd21b3afa65dfeb9cf09677f86ec19a7679e64cea71f3daa788ebb45846cccf93dcaae1942bbb793be38e339ff2b34f28e5f7ab6f4e29e33a8c68f3f6dd5a320cdf29a7deb58c824aeeb31d434b64f48de1351b5736b6fd17d192e1a9321577d5cfe73e5c32c31ac79db16dfccf3e30f55219533e8b53634c73bd3bcc90e285332cf7f21177f51977d9f046775d2e9e6146fc8bbdabcab816c89872270f1e98e1f909c6b4c5cf7f71f5e2f7637e9fe9e742f5e8d3399feb3e0dcc9877744083f613693d174b23befbcc4ccc84b2f0fa1719d7d37c783d28a3b58affd18cef7faefc007d894af5</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>newGame</sender>
+ <signal>activated()</signal>
+ <receiver>ChessBoard</receiver>
+ <slot>newGame()</slot>
+ </connection>
+ <connection>
+ <sender>swapSides</sender>
+ <signal>activated()</signal>
+ <receiver>ChessBoard</receiver>
+ <slot>swapSides()</slot>
+ </connection>
+ <connection>
+ <sender>annotateGame</sender>
+ <signal>activated()</signal>
+ <receiver>ChessBoard</receiver>
+ <slot>annotateGame()</slot>
+ </connection>
+ <connection>
+ <sender>undo</sender>
+ <signal>activated()</signal>
+ <receiver>ChessBoard</receiver>
+ <slot>undo()</slot>
+ </connection>
+ <connection>
+ <sender>ChessBoard</sender>
+ <signal>showMessage(const QString&amp;)</signal>
+ <receiver>TextLabel1</receiver>
+ <slot>setText(const QString&amp;)</slot>
+ </connection>
+</connections>
+<pixmapinproject/>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/noncore/games/chess/pieces.png b/noncore/games/chess/pieces.png
new file mode 100644
index 0000000..4baeb4a
--- a/dev/null
+++ b/noncore/games/chess/pieces.png
Binary files differ
diff --git a/noncore/games/chess/qpe-chess.control b/noncore/games/chess/qpe-chess.control
new file mode 100644
index 0000000..2a7d2d2
--- a/dev/null
+++ b/noncore/games/chess/qpe-chess.control
@@ -0,0 +1,9 @@
+Files: bin/chess apps/Games/chess.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Luke Graham <luke@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Crafty GUI
+ A GUI for the crafty chess engine
diff --git a/noncore/games/chess/simple-l.png b/noncore/games/chess/simple-l.png
new file mode 100644
index 0000000..908e2e1
--- a/dev/null
+++ b/noncore/games/chess/simple-l.png
Binary files differ
diff --git a/noncore/games/fifteen/.cvsignore b/noncore/games/fifteen/.cvsignore
new file mode 100644
index 0000000..6fe2396
--- a/dev/null
+++ b/noncore/games/fifteen/.cvsignore
@@ -0,0 +1,2 @@
+moc_*
+Makefile
diff --git a/noncore/games/fifteen/Makefile.in b/noncore/games/fifteen/Makefile.in
new file mode 100644
index 0000000..23c7334
--- a/dev/null
+++ b/noncore/games/fifteen/Makefile.in
@@ -0,0 +1,118 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = ../bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = fifteen
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = fifteen.h
+SOURCES = fifteen.cpp \
+ main.cpp
+OBJECTS = fifteen.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_fifteen.cpp
+OBJMOC = moc_fifteen.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake fifteen.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+fifteen.o: fifteen.cpp \
+ fifteen.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+main.o: main.cpp \
+ fifteen.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_fifteen.o: moc_fifteen.cpp \
+ fifteen.h
+
+moc_fifteen.cpp: fifteen.h
+ $(MOC) fifteen.h -o moc_fifteen.cpp
+
+
diff --git a/noncore/games/fifteen/fifteen.cpp b/noncore/games/fifteen/fifteen.cpp
new file mode 100644
index 0000000..293cd65
--- a/dev/null
+++ b/noncore/games/fifteen/fifteen.cpp
@@ -0,0 +1,364 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "fifteen.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qvbox.h>
+#include <qaction.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qpopupmenu.h>
+#include <qmessagebox.h>
+#include <qpe/qpetoolbar.h>
+#include <qpe/qpemenubar.h>
+#include <qstringlist.h>
+#include <qapplication.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+FifteenMainWindow::FifteenMainWindow(QWidget *parent, const char* name)
+ : QMainWindow( parent, name )
+{
+ // random seed
+ srand(time(0));
+
+ setToolBarsMovable( FALSE );
+ QVBox *vbox = new QVBox( this );
+ PiecesTable *table = new PiecesTable( vbox );
+ setCentralWidget(vbox);
+
+ QPEToolBar *toolbar = new QPEToolBar(this);
+ toolbar->setHorizontalStretchable( TRUE );
+ addToolBar(toolbar);
+
+ QPEMenuBar *menubar = new QPEMenuBar( toolbar );
+ menubar->setMargin(0);
+
+ QPopupMenu *game = new QPopupMenu( this );
+
+ QWidget *spacer = new QWidget( toolbar );
+ spacer->setBackgroundMode( PaletteButton );
+ toolbar->setStretchableWidget( spacer );
+
+ QAction *a = new QAction( tr( "Randomize" ), Resource::loadPixmap( "new" ),
+ QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), table, SLOT( slotRandomize() ) );
+ a->addTo( game );
+ a->addTo( toolbar );
+
+ a = new QAction( tr( "Solve" ), Resource::loadPixmap( "repeat" ),
+ QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), table, SLOT( slotReset() ) );
+ a->addTo( game );
+ a->addTo( toolbar );
+
+ menubar->insertItem( tr( "Game" ), game );
+}
+
+PiecesTable::PiecesTable(QWidget* parent, const char* name )
+ : QTableView(parent, name), _menu(0), _randomized(false)
+{
+ // setup table view
+ setFrameStyle(StyledPanel | Sunken);
+ setBackgroundMode(NoBackground);
+ setMouseTracking(true);
+
+ setNumRows(4);
+ setNumCols(4);
+
+ // init arrays
+ initMap();
+ readConfig();
+ initColors();
+
+ // set font
+ QFont f = font();
+ f.setPixelSize(18);
+ f.setBold( TRUE );
+ setFont(f);
+}
+
+PiecesTable::~PiecesTable()
+{
+ writeConfig();
+}
+
+void PiecesTable::writeConfig()
+{
+ Config cfg("Fifteen");
+ cfg.setGroup("Game");
+ QStringList map;
+ for (unsigned int i = 0; i < 16; i++)
+ map.append( QString::number( _map[i] ) );
+ cfg.writeEntry("Map", map, '-');
+ cfg.writeEntry("Randomized", _randomized );
+}
+
+void PiecesTable::readConfig()
+{
+ Config cfg("Fifteen");
+ cfg.setGroup("Game");
+ QStringList map = cfg.readListEntry("Map", '-');
+ _randomized = cfg.readBoolEntry( "Randomized", FALSE );
+ unsigned int i = 0;
+ for ( QStringList::Iterator it = map.begin(); it != map.end(); ++it ) {
+ _map[i] = (*it).toInt();
+ i++;
+ if ( i > 15 ) break;
+ }
+}
+
+void PiecesTable::paintCell(QPainter *p, int row, int col)
+{
+ int w = cellWidth();
+ int h = cellHeight();
+ int x2 = w - 1;
+ int y2 = h - 1;
+
+ int number = _map[col + row * numCols()] + 1;
+
+ // draw cell background
+ if(number == 16)
+ p->setBrush(colorGroup().background());
+ else
+ p->setBrush(_colors[number-1]);
+ p->setPen(NoPen);
+ p->drawRect(0, 0, w, h);
+
+ // draw borders
+ if (height() > 40) {
+ p->setPen(colorGroup().text());
+ if(col < numCols()-1)
+ p->drawLine(x2, 0, x2, y2); // right border line
+
+ if(row < numRows()-1)
+ p->drawLine(0, y2, x2, y2); // bottom boder line
+ }
+
+ // draw number
+ if (number == 16) return;
+ p->setPen(black);
+ p->drawText(0, 0, x2, y2, AlignHCenter | AlignVCenter, QString::number(number));
+}
+
+void PiecesTable::resizeEvent(QResizeEvent *e)
+{
+ QTableView::resizeEvent(e);
+
+ setCellWidth(contentsRect().width()/ numRows());
+ setCellHeight(contentsRect().height() / numCols());
+}
+
+void PiecesTable::initColors()
+{
+ _colors.resize(numRows() * numCols());
+ for (int r = 0; r < numRows(); r++)
+ for (int c = 0; c < numCols(); c++)
+ _colors[c + r *numCols()] = QColor(255 - 70 * c,255 - 70 * r, 150);
+}
+
+void PiecesTable::initMap()
+{
+ _map.resize(16);
+ for (unsigned int i = 0; i < 16; i++)
+ _map[i] = i;
+
+ _randomized = false;
+}
+
+void PiecesTable::randomizeMap()
+{
+ initMap();
+ _randomized = true;
+ // find the free position
+ int pos = _map.find(15);
+
+ int move = 0;
+ while ( move < 333 ) {
+
+ int frow = pos / numCols();
+ int fcol = pos - frow * numCols();
+
+ // find click position
+ int row = rand()%4;
+ int col = rand()%4;
+
+ // sanity check
+ if ( row < 0 || row >= numRows() ) continue;
+ if ( col < 0 || col >= numCols() ) continue;
+ if ( row != frow && col != fcol ) continue;
+
+ move++;
+
+ // rows match -> shift pieces
+ if(row == frow) {
+
+ if (col < fcol) {
+ for(int c = fcol; c > col; c--) {
+ _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
+ }
+ }
+ else if (col > fcol) {
+ for(int c = fcol; c < col; c++) {
+ _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
+ }
+ }
+ }
+ // cols match -> shift pieces
+ else if (col == fcol) {
+
+ if (row < frow) {
+ for(int r = frow; r > row; r--) {
+ _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
+ }
+ }
+ else if (row > frow) {
+ for(int r = frow; r < row; r++) {
+ _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
+ }
+ }
+ }
+ // move free cell to click position
+ _map[pos=(col + row * numCols())] = 15;
+ repaint();
+ }
+}
+
+void PiecesTable::checkwin()
+{
+ if(!_randomized) return;
+
+ int i;
+ for (i = 0; i < 16; i++)
+ if(i != _map[i])
+ break;
+
+ if (i == 16) {
+ QMessageBox::information(this, tr("Fifteen Pieces"),
+ tr("Congratulations!\nYou win the game!"));
+ _randomized = FALSE;
+ }
+
+}
+
+void PiecesTable::slotRandomize()
+{
+ randomizeMap();
+}
+
+void PiecesTable::slotReset()
+{
+ initMap();
+ repaint();
+}
+
+void PiecesTable::mousePressEvent(QMouseEvent* e)
+{
+ QTableView::mousePressEvent(e);
+
+ if (e->button() == RightButton) {
+
+ // setup RMB pupup menu
+ if(!_menu) {
+ _menu = new QPopupMenu(this);
+ _menu->insertItem(tr("R&andomize Pieces"), mRandomize);
+ _menu->insertItem(tr("&Reset Pieces"), mReset);
+ _menu->adjustSize();
+ }
+
+ // execute RMB popup and check result
+ switch(_menu->exec(mapToGlobal(e->pos()))) {
+ case mRandomize:
+ randomizeMap();
+ break;
+ case mReset:
+ initMap();
+ repaint();
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ // GAME LOGIC
+
+ // find the free position
+ int pos = _map.find(15);
+ if(pos < 0) return;
+
+ int frow = pos / numCols();
+ int fcol = pos - frow * numCols();
+
+ // find click position
+ int row = findRow(e->y());
+ int col = findCol(e->x());
+
+ // sanity check
+ if (row < 0 || row >= numRows()) return;
+ if (col < 0 || col >= numCols()) return;
+ if ( row != frow && col != fcol ) return;
+
+ // valid move?
+ if(row != frow && col != fcol) return;
+
+ // rows match -> shift pieces
+ if(row == frow) {
+
+ if (col < fcol) {
+ for(int c = fcol; c > col; c--) {
+ _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
+ updateCell(row, c, false);
+ }
+ }
+ else if (col > fcol) {
+ for(int c = fcol; c < col; c++) {
+ _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
+ updateCell(row, c, false);
+ }
+ }
+ }
+ // cols match -> shift pieces
+ else if (col == fcol) {
+
+ if (row < frow) {
+ for(int r = frow; r > row; r--) {
+ _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
+ updateCell(r, col, false);
+ }
+ }
+ else if (row > frow) {
+ for(int r = frow; r < row; r++) {
+ _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
+ updateCell(r, col, false);
+ }
+ }
+ }
+ // move free cell to click position
+ _map[col + row * numCols()] = 15;
+ updateCell(row, col, false);
+
+ // check if the player wins with this move
+ checkwin();
+ }
+}
diff --git a/noncore/games/fifteen/fifteen.h b/noncore/games/fifteen/fifteen.h
new file mode 100644
index 0000000..703a8a7
--- a/dev/null
+++ b/noncore/games/fifteen/fifteen.h
@@ -0,0 +1,83 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef __fifteenapplet_h__
+#define __fifteenapplet_h__
+
+#include <qmainwindow.h>
+#include <qtableview.h>
+#include <qarray.h>
+
+class QPopupMenu;
+
+class PiecesTable : public QTableView
+{
+ Q_OBJECT
+
+ public:
+ PiecesTable(QWidget* parent = 0, const char* name = 0);
+ ~PiecesTable();
+
+ protected slots:
+ void slotRandomize();
+ void slotReset();
+
+ protected:
+ void resizeEvent(QResizeEvent*);
+ void mousePressEvent(QMouseEvent*);
+
+ void paintCell(QPainter *, int row, int col);
+
+ void initMap();
+ void initColors();
+ void randomizeMap();
+ void checkwin();
+ void readConfig();
+ void writeConfig();
+
+ private:
+ QArray<int> _map;
+ QArray<QColor> _colors;
+ QPopupMenu *_menu;
+ bool _randomized;
+
+ enum MenuOp { mRandomize = 1, mReset = 2 };
+};
+
+class FifteenWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ FifteenWidget(QWidget *parent = 0, const char *name = 0);
+
+private:
+ PiecesTable *_table;
+};
+
+class FifteenMainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ FifteenMainWindow(QWidget *parent=0, const char* name=0);
+};
+
+#endif
diff --git a/noncore/games/fifteen/fifteen.pro b/noncore/games/fifteen/fifteen.pro
new file mode 100644
index 0000000..167f4f8
--- a/dev/null
+++ b/noncore/games/fifteen/fifteen.pro
@@ -0,0 +1,10 @@
+DESTDIR = ../bin
+TEMPLATE = app
+CONFIG = qt warn_on release
+HEADERS = fifteen.h
+SOURCES = fifteen.cpp \
+ main.cpp
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+TARGET = fifteen
diff --git a/noncore/games/fifteen/main.cpp b/noncore/games/fifteen/main.cpp
new file mode 100644
index 0000000..4838a36
--- a/dev/null
+++ b/noncore/games/fifteen/main.cpp
@@ -0,0 +1,33 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "fifteen.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char ** argv)
+{
+ QPEApplication app( argc, argv );
+
+ FifteenMainWindow mw;
+ mw.setCaption( FifteenMainWindow::tr("Fifteen Pieces") );
+ app.showMainWidget( &mw );
+ return app.exec();
+}
diff --git a/noncore/games/fifteen/qpe-fifteen.control b/noncore/games/fifteen/qpe-fifteen.control
new file mode 100644
index 0000000..d77eb32
--- a/dev/null
+++ b/noncore/games/fifteen/qpe-fifteen.control
@@ -0,0 +1,11 @@
+Files: bin/fifteen apps/Games/fifteen.desktop pics/Fifteen.png
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Arch: iPAQ
+Version: $QPE_VERSION-4
+Depends: qpe-base ($QPE_VERSION)
+Description: Fifteen pieces game
+ A game for the Qtopia environment
+.
diff --git a/noncore/games/go/.cvsignore b/noncore/games/go/.cvsignore
new file mode 100644
index 0000000..6fe2396
--- a/dev/null
+++ b/noncore/games/go/.cvsignore
@@ -0,0 +1,2 @@
+moc_*
+Makefile
diff --git a/noncore/games/go/Makefile.in b/noncore/games/go/Makefile.in
new file mode 100644
index 0000000..27304f1
--- a/dev/null
+++ b/noncore/games/go/Makefile.in
@@ -0,0 +1,158 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = ../bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = go
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = amigo.h \
+ go.h \
+ goplayutils.h \
+ gowidget.h
+SOURCES = amigo.c \
+ goplayer.c \
+ goplayutils.c \
+ killable.c \
+ gowidget.cpp \
+ main.cpp
+OBJECTS = amigo.o \
+ goplayer.o \
+ goplayutils.o \
+ killable.o \
+ gowidget.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_gowidget.cpp
+OBJMOC = moc_gowidget.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake go.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+amigo.o: amigo.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+goplayer.o: goplayer.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+goplayutils.o: goplayutils.c \
+ goplayutils.h \
+ amigo.h \
+ go.h
+
+killable.o: killable.c \
+ go.h \
+ goplayutils.h \
+ amigo.h
+
+gowidget.o: gowidget.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+main.o: main.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_gowidget.o: moc_gowidget.cpp \
+ gowidget.h \
+ amigo.h \
+ go.h \
+ goplayutils.h
+
+moc_gowidget.cpp: gowidget.h
+ $(MOC) gowidget.h -o moc_gowidget.cpp
+
+
diff --git a/noncore/games/go/README b/noncore/games/go/README
new file mode 100644
index 0000000..c6fa1f5
--- a/dev/null
+++ b/noncore/games/go/README
@@ -0,0 +1,3 @@
+This Go player For Qtopia is based on Xamigo, which in turn was
+based on Amigo. The original README files are included as README.XAMIGO
+and README.AMIGO.
diff --git a/noncore/games/go/README.AMIGO b/noncore/games/go/README.AMIGO
new file mode 100644
index 0000000..03978e7
--- a/dev/null
+++ b/noncore/games/go/README.AMIGO
@@ -0,0 +1,42 @@
+ This is version 1.0 of AmiGo --- a Go board and player for the Amiga.
+The Amiga interface and board manager were written by Todd R. Johnson.
+The player is a C port of a Pascal player written by Stoney Ballard.
+The interface allows you to play human vs. human, human vs. Amiga, or
+Amiga vs. Amiga.
+
+ The board manager and player could both use some work. Currently,
+you cannot save/load games, take back a move, or automatically score a
+game. It is also limited to a 19 by 19 board. I'm releasing AmiGo
+now because 1) I'm in the final phases of my dissertation and probably
+won't have much time to do any further work on AmiGo, and 2) a lot of
+people have been asking for an Amiga Go player. I am also releasing
+all of the source code so that others can add to and modify AmiGo.
+Note that all of my code in this release is public domain, while the
+ported go player retains the original copyright.
+
+ If you distribute AmiGo, I urge you to include the source
+code. If anyone makes changes, I would appreciate a copy. In fact, I
+am willing to act as a clearinghouse for AmiGo changes.
+
+Todd R. Johnson
+tj@cis.ohio-state.edu
+8/8/89
+
+Here is the message attached to the original USENET posting of Stoney
+Ballard's Pascal code. Note that the board manager mentioned here is
+not included in this distribution.
+
+This go board manager and rudimentary go player was written by
+Stoney Ballard at Perq Systems in 1983-1984. It is written in
+Perq Pascal and utilizes some Perq libraries for I/O. The code
+is offered here if someone is interested to convert it to Unix.
+
+The wonderful part about it is that a game is recorded as a tree
+and can be played forward or backward, branching at any point
+where there were alternate moves.
+
+For some time, this program was also used to generate the go
+boards displayed in the American Go Journal. For this it used
+some large font digits which are now lost.
+
+Fred Hansen
diff --git a/noncore/games/go/README.XAMIGO b/noncore/games/go/README.XAMIGO
new file mode 100644
index 0000000..219b25f
--- a/dev/null
+++ b/noncore/games/go/README.XAMIGO
@@ -0,0 +1,26 @@
+
+ Xamigo 1.1
+
+This is an alpha release of xamigo --- a port (read: quick hack) of the
+Amiga Go program AmiGo. I don't have time to get it real nice now,
+but will spend some more time on it when my thesis is out of the way.
+Sadly this is the second time I've said that :-)
+
+The `readme' from the original distribution is included as README.AMIGO
+
+An Imakefile is included, so you should be able to type
+ xmkmf
+ make
+to build xamigo. Let me know if you have problems with the Imakefile,
+preferably with fixes :-)
+
+You *have* to install the app-defaults file (Xamigo.ad) before you use
+xamigo. This should either go in /usr/lib/X11/app-defaults,
+or in your own app-defaults directory, as file Xamigo (ie lose the '.ad')
+If you do the latter, you have to:
+ setenv XAPPLRESDIR <full path of your app-defaults directory>
+
+Feel free to mail me any comments and suggestions for improvements.
+
+Neil
+neilb@scs.leeds.ac.uk
diff --git a/noncore/games/go/amigo.c b/noncore/games/go/amigo.c
new file mode 100644
index 0000000..cd61013
--- a/dev/null
+++ b/noncore/games/go/amigo.c
@@ -0,0 +1,656 @@
+/* Go started 4/17/88 by Todd R. Johnson */
+/* 8/8/89 cleaned up for first release */
+/* Public Domain */
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+
+extern char *playReason;
+extern short playLevel, showTrees;
+
+struct bRec goboard[19][19]; /*-- The main go board --*/
+
+struct Group GroupList[MAXGROUPS]; /*-- The list of Groups --*/
+short DeletedGroups[4]; /*-- Codes of deleted groups --*/
+
+short GroupCount = 0; /*-- The total number of groups --*/
+short DeletedGroupCount; /*-- The total number of groups --*/
+ /*-- deleted on a move --*/
+short ko, koX, koY;
+short blackTerritory,whiteTerritory;
+short blackPrisoners, whitePrisoners;
+short showMoveReason = FALSE,
+ groupInfo = FALSE,
+ whitePassed = FALSE,
+ blackPassed = FALSE;
+
+
+/* Arrays for use when checking around a point */
+short xVec[4] = {0, 1, 0, -1};
+short yVec[4] = {-1, 0, 1, 0};
+
+short
+member(group, grouplist, cnt)
+ short group;
+ short grouplist[4];
+ short cnt;
+{
+ unsigned short i;
+
+
+ for (i = 0; i < cnt; i++)
+ if (grouplist[i] == group)
+ return TRUE;
+ return FALSE;
+}
+
+/* Does a stone at x, y connect to any groups of color? */
+short
+Connect( color, x, y, fGroups, fCnt, eGroups, eCnt)
+ enum bVal color;
+ short x, y;
+ short fGroups[4], eGroups[4];
+ short *fCnt, *eCnt;
+{
+ unsigned short point = 0;
+ short tx, ty, total = 0;
+ enum bVal opcolor = WHITE;
+
+
+ *fCnt = 0;
+ *eCnt = 0;
+ if (color == WHITE)
+ opcolor = BLACK;
+ for (point = 0; point <= 3; point++ )
+ {
+ tx = x + xVec[point];
+ ty = y + yVec[point];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val == color)
+ {
+ total++;
+ if (!member(goboard[tx][ty].GroupNum, fGroups, *fCnt))
+ fGroups[(*fCnt)++] = goboard[tx][ty].GroupNum;
+ }
+ else if (goboard[tx][ty].Val == opcolor)
+ {
+ total++;
+ if (!member(goboard[tx][ty].GroupNum, eGroups, *eCnt))
+ eGroups[(*eCnt)++] = goboard[tx][ty].GroupNum;
+ }
+ }
+ return total;
+}
+
+/* Returns the maximum number of liberties for a given intersection */
+short
+Maxlibs(x, y)
+ short x, y;
+{
+ short cnt = 4;
+
+
+ if (x == 0 || x == 18)
+ cnt--;
+ if (y == 0 || y == 18)
+ cnt--;
+ return cnt;
+}
+
+DeleteGroupFromStone(x,y)
+ short x,y;
+{
+ if (goboard[x][y].Val != EMPTY)
+ GroupCapture(goboard[x][y].GroupNum);
+}
+
+/* Determine whether x, y is suicide for color */
+short
+Suicide(color, x, y)
+ enum bVal color;
+ short x, y;
+{
+ enum bVal opcolor = BLACK;
+ short friendlycnt, friendlygroups[4],
+ enemycnt, enemygroups[4],
+ total;
+ short maxlibs, i, libcnt = 0;
+
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ maxlibs = Maxlibs( x, y);
+ total = Connect(color, x, y, friendlygroups, &friendlycnt,
+ enemygroups, &enemycnt);
+
+ if (total < maxlibs)
+ return FALSE;
+
+ /* Check for a capture */
+ for (i = 0; i < enemycnt; i++)
+ if (GroupList[enemygroups[i]].liberties == 1)
+ return FALSE;
+ for (i = 0; i < friendlycnt; i++)
+ libcnt += (GroupList[friendlygroups[i]].liberties - 1);
+ if (libcnt != 0)
+ return FALSE;
+ return TRUE;
+}
+
+/* Returns the number of liberties for x, y */
+short
+StoneLibs(x, y)
+ short x, y;
+{
+ short cnt = 0, tx, ty;
+ unsigned short point;
+
+
+ for (point = 0; point <= 3; point++)
+ {
+ tx = x + xVec[point];
+ ty = y + yVec[point];
+ if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY)
+ cnt++;
+ }
+ return cnt;
+}
+
+void
+EraseMarks()
+{
+ register short i;
+ register struct bRec *gpt = &goboard[0][0];
+
+
+ for (i=0; i<361; gpt++,i++)
+ gpt->marked = FALSE;
+}
+
+/* Place a stone of color at x, y */
+short
+GoPlaceStone(color, x, y)
+ enum bVal color;
+ short x, y;
+{
+ short fgroups[4], egroups[4]; /* group codes surrounding stone */
+ short fcnt, ecnt, i;
+ short lowest = GroupCount + 1;
+
+
+ DeletedGroupCount = 0;
+ if (goboard[x][y].Val != EMPTY || Suicide(color,x,y))
+ return FALSE;
+
+ if (ko && koX == x && koY == y)
+ return FALSE;
+
+ ko = FALSE;
+ placestone(color, x, y);
+ goboard[x][y].Val = color;
+ /* Does the new stone connect to any friendly stone(s)? */
+ Connect(color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (fcnt)
+ {
+ /* Find the connecting friendly group with the lowest code */
+ for (i = 0; i < fcnt; i++)
+ if (fgroups[i] <= lowest)
+ lowest = fgroups[i];
+ /*-- Renumber resulting group --*/
+ /*-- Raise the stone count of the lowest by one to account --*/
+ /*-- for new stone --*/
+ goboard[x][y].GroupNum = lowest;
+ GroupList[lowest].count++;
+ for (i = 0; i < fcnt; i++)
+ if (fgroups[i] != lowest)
+ MergeGroups(lowest, fgroups[i]);
+ /* Fix the liberties of the resulting group */
+ CountLiberties(lowest);
+ }
+ else
+ {
+ /* Isolated stone. Create new group. */
+ GroupCount++;
+ lowest = GroupCount;
+ GroupList[lowest].color = color;
+ GroupList[lowest].count = 1;
+ GroupList[lowest].internal = 0;
+ GroupList[lowest].external = StoneLibs( x, y);
+ GroupList[lowest].liberties = GroupList[lowest].external;
+ GroupList[lowest].eyes = 0;
+ GroupList[lowest].alive = 0;
+ GroupList[lowest].territory = 0;
+ goboard[x][y].GroupNum = lowest;
+ }
+ /* Now fix the liberties of enemy groups adjacent to played stone */
+ FixLibs(color, x, y, PLACED); /* Fix the liberties of opcolor */
+ ReEvalGroups(color, x, y, lowest);
+ RelabelGroups();
+ return TRUE;
+}
+
+/* Remove a stone from the board */
+void
+GoRemoveStone(x, y)
+ short x, y;
+{
+ goboard[x][y].Val = EMPTY;
+ goboard[x][y].GroupNum = 0;
+ removestone( x, y);
+}
+
+/* Merges two groups -- Renumbers stones and deletes second group from
+list. Fixes stone count of groups. This does not fix anything else.
+FixLibs must be called to fix liberties, etc. */
+void
+MergeGroups(g1, g2)
+ short g1, g2;
+{
+ short x, y;
+
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == g2)
+ goboard[x][y].GroupNum = g1;
+ GroupList[g1].count += GroupList[g2].count;
+ DeleteGroup( g2 ); /* Removes group from GroupList */
+}
+
+/* Stores a group code to be deleted */
+void
+DeleteGroup(code)
+ short code;
+{
+ DeletedGroups[DeletedGroupCount++] = code;
+}
+
+/* Re-evaluate the groups given the last move. This assumes that the
+last move has been merged into adjoining groups and all liberty counts
+are correct. Handles capture. Checks for Ko. Keeps track of captured
+stones. code is the group number of the stone just played. */
+void
+ReEvalGroups(color, x, y, code)
+ enum bVal color;
+ short x, y, code;
+{
+ short fgroups[4], egroups[4],
+ fcnt, ecnt, i, killcnt = 0, count = 0;
+ enum bVal opcolor = BLACK;
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ /* Check for capture */
+ Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (ecnt)
+ {
+ /* See if any of the groups have no liberties */
+ for (i = 0; i < ecnt; i++)
+ if (GroupList[egroups[i]].liberties == 0)
+ {
+ killcnt++;
+ count = GroupList[egroups[i]].count;
+ GroupCapture( egroups[i]);
+ }
+ }
+ /* Check for ko. koX and koY are set in GroupCapture above. */
+ if (killcnt == 1 && count == 1 && GroupList[ code ].count == 1
+ && GroupList[ code ].liberties == 1)
+ {
+ ko = TRUE;
+ }
+ if (killcnt)
+ intrPrisonerReport( blackPrisoners, whitePrisoners);
+ /* Set eye count for groups */
+ CountEyes();
+}
+
+/* Remove a captured group from the board and fix the liberties of any
+ adjacent groups. Fixes prisoner count. Sets KoX and KoY */
+/*-- update display of captured stones -neilb --*/
+void
+GroupCapture(code)
+ short code;
+{
+ short x, y;
+
+ if (GroupList[code].color == BLACK)
+ blackPrisoners += GroupList[code].count;
+ else
+ whitePrisoners += GroupList[code].count;
+ intrPrisonerReport(blackPrisoners, whitePrisoners);
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == code)
+ {
+ FixLibs(GroupList[code].color,x,y,REMOVED);
+ GoRemoveStone(x, y);
+ koX = x;
+ koY = y;
+ }
+ DeleteGroup( code);
+}
+
+/* Fix the liberties of groups adjacent to x, y. move indicates
+ whether a stone of color was placed or removed at x, y
+ This does not change liberty counts of friendly groups when a stone
+ is placed. Does not do captures. */
+void
+FixLibs( color, x, y, move)
+ enum bVal color;
+ short x, y, move;
+{
+ short fgroups[4], fcnt, egroups[4], ecnt, i;
+ enum bVal opcolor = BLACK;
+
+ if (color == BLACK)
+ opcolor = WHITE;
+ Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
+ if (move == PLACED)
+ for (i = 0; i < ecnt; i++)
+ GroupList[egroups[i]].liberties--;
+ else /* Stone removed so increment opcolor */
+ for (i = 0; i < ecnt; i++)
+ GroupList[egroups[i]].liberties++;
+}
+
+void
+goSetHandicap(handicap)
+ int handicap;
+{
+ if (handicap < 2)
+ return;
+
+ GoPlaceStone(BLACK,3,3);
+ GoPlaceStone(BLACK,15,15);
+
+ if (handicap >= 3)
+ GoPlaceStone(BLACK,15,3);
+ if (handicap >= 4)
+ GoPlaceStone(BLACK,3,15);
+ if (handicap == 5 || handicap == 7 || handicap == 9)
+ GoPlaceStone(BLACK,9,9);
+ if (handicap >= 6)
+ {
+ GoPlaceStone(BLACK,15,9);
+ GoPlaceStone(BLACK,3,9);
+ }
+ if (handicap >= 8)
+ {
+ GoPlaceStone(BLACK,9,15);
+ GoPlaceStone(BLACK,9,3);
+ }
+}
+
+void
+goRestart(handicap)
+ int handicap;
+{
+ register short i;
+ register struct bRec *gpt = &goboard[0][0];
+
+
+ GroupCount = 0;
+ ko = FALSE;
+ blackPrisoners = whitePrisoners = 0;
+ intrPrisonerReport(0, 0);
+ for (i=0; i<361; gpt++,i++)
+ {
+ gpt->Val = EMPTY;
+ gpt->GroupNum = 0;
+ }
+ goSetHandicap(handicap);
+}
+
+
+/* if any groups have been deleted as a result of the last move, this
+ routine will delete the old group numbers from GroupList and
+ reassign group numbers. */
+void
+RelabelGroups()
+{
+ unsigned short i, j, x, y;
+
+ for (i = 0; i < DeletedGroupCount; i++)
+ {
+ /* Relabel all higher groups */
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum > DeletedGroups[i])
+ goboard[x][y].GroupNum--;
+ /* Move the groups down */
+ for (y = DeletedGroups[i]; y < GroupCount; y++)
+ GroupList[y] = GroupList[y+1];
+ /* fix the group numbers stored in the deleted list */
+ for (j = i+1; j < DeletedGroupCount; j++)
+ if (DeletedGroups[j] > DeletedGroups[i])
+ DeletedGroups[j]--;
+ GroupCount--;
+ }
+}
+
+/* Returns liberty count for x, y intersection. Sets marked to true
+ for each liberty */
+short
+CountAndMarkLibs( x, y)
+ short x, y;
+{
+ short tx,ty,i;
+ short cnt = 0;
+
+
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY
+ && goboard[tx][ty].marked == FALSE)
+ {
+ cnt++;
+ goboard[tx][ty].marked = TRUE;
+ }
+ }
+ return cnt;
+}
+
+/* Determine the number of liberties for a group given the group code
+ num */
+void
+CountLiberties( code)
+ short code;
+{
+ short x, y, libcnt = 0;
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].GroupNum == code)
+ libcnt += CountAndMarkLibs( x, y);
+ EraseMarks();
+ GroupList[code].liberties = libcnt;
+}
+
+void
+CheckForEye( x, y, groups, cnt, recheck)
+ short x, y, groups[4], cnt, *recheck;
+{
+ short i;
+
+ for (i = 0; i < (cnt-1); i++)
+ if (groups[i] != groups[i+1])
+ {
+ /* Mark liberty for false eye check */
+ goboard[x][y].marked = TRUE;
+ (*recheck)++;
+ return;
+ }
+ /* It is an eye */
+ GroupList[groups[i]].eyes += 1;
+}
+
+/* Set the eye count for the groups */
+void CountEyes()
+{
+ short i, x, y,
+ wgroups[4], bgroups[4], wcnt, bcnt, max, cnt, recheck = 0, eye;
+
+ for (i = 1; i <= GroupCount; i++)
+ GroupList[i].eyes = 0;
+
+ ForeachPoint(y,x)
+ {
+ if (goboard[x][y].Val != EMPTY)
+ continue;
+ cnt = Connect(WHITE,x,y,wgroups,&wcnt,bgroups,&bcnt);
+ max = Maxlibs( x, y);
+ if (cnt == max && wcnt == 1 && bcnt == 0)
+ GroupList[wgroups[0]].eyes++;
+ else if (cnt == max && bcnt == 1 && wcnt == 0)
+ GroupList[bgroups[0]].eyes++;
+ else if (cnt == max && ( bcnt == 0 || wcnt == 0 ))
+ {
+ goboard[x][y].marked = TRUE;
+ recheck++;
+ }
+ }
+
+ /*-- Now recheck marked liberties to see if two or more one eye --*/
+ /*-- groups contribute to a false eye */
+ if (recheck == 0)
+ return;
+
+ ForeachPoint(y,x)
+ if (goboard[x][y].marked)
+ {
+ recheck--;
+ goboard[x][y].marked = FALSE;
+ Connect( WHITE, x, y, wgroups, &wcnt, bgroups, &bcnt);
+ /* If all the groups have at least one eye then all the
+ groups are safe from capture because of the common
+ liberty at x, y */
+ eye = TRUE;
+ for (i = 0; i < wcnt; i++)
+ if (GroupList[wgroups[i]].eyes == 0)
+ eye = FALSE;
+ if (eye)
+ for (i = 0; i < wcnt; i++)
+ GroupList[wgroups[i]].eyes++;
+ for (i = 0; i < bcnt; i++)
+ if (GroupList[bgroups[i]].eyes == 0)
+ eye = FALSE;
+ if (eye)
+ for (i = 0; i < bcnt; i++)
+ GroupList[bgroups[i]].eyes++;
+ if (recheck == 0)
+ return;
+ }
+}
+
+
+short foo[19][19];
+
+/*----------------------------------------------------------------
+-- CountUp() --
+-- Count up final scores at the end of the game. --
+----------------------------------------------------------------*/
+CountUp( wtotal, btotal )
+ int *wtotal, *btotal;
+{
+ short x,y;
+ short CountFromPoint();
+ short vv;
+ char buff[512];
+
+
+ blackTerritory = whiteTerritory = 0;
+ ForeachPoint(y,x)
+ {
+ goboard[x][y].marked = FALSE;
+ foo[x][y] = CNT_UNDECIDED;
+ }
+ ForeachPoint(y,x)
+ if (goboard[x][y].Val==EMPTY && foo[x][y]==CNT_UNDECIDED)
+ {
+ FillPoints(x,y,CountFromPoint(x,y));
+ }
+
+ *wtotal = whiteTerritory + blackPrisoners;
+ *btotal = blackTerritory + whitePrisoners;
+ /*
+ sprintf(buff,"White : %3d territory + %3d prisoners = %d\n\
+Black : %3d territory + %3d prisoners = %d\n\n%s.\n",
+ whiteTerritory,blackPrisoners,*wtotal,
+ blackTerritory,whitePrisoners,*btotal,
+ (*btotal>*wtotal?"Black wins":(*wtotal>*btotal?"White wins":
+ "A draw")));
+
+
+
+ XtVaSetValues(message,XtNstring,buff,0);
+ printf( "CountUp() %s", buff );
+ */
+}
+
+FillPoints(x,y,val)
+ short x,y,val;
+{
+ int i;
+ short tx,ty;
+
+
+ if ((foo[x][y] = val) == CNT_BLACK_TERR)
+ blackTerritory++;
+ else if (val == CNT_WHITE_TERR)
+ whiteTerritory++;
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val==EMPTY && foo[tx][ty]==CNT_UNDECIDED)
+ FillPoints(tx,ty,val);
+ }
+}
+
+short
+CountFromPoint(x,y)
+ short x,y;
+{
+ int i;
+ short tx,ty;
+ short blkcnt=0,whtcnt=0;
+ short baz;
+
+
+ goboard[x][y].marked = TRUE;
+ for (i=0;i<4;i++)
+ {
+ tx = x + xVec[i];
+ ty = y + yVec[i];
+ if (!LegalPoint(tx,ty))
+ continue;
+ if (goboard[tx][ty].Val == BLACK)
+ blkcnt++;
+ else if (goboard[tx][ty].Val == WHITE)
+ whtcnt++;
+ else
+ {
+ if (goboard[tx][ty].marked)
+ continue;
+ baz = CountFromPoint(tx,ty);
+ if (baz == CNT_NOONE)
+ return CNT_NOONE;
+ else if (baz == CNT_BLACK_TERR)
+ blkcnt++;
+ else if (baz == CNT_WHITE_TERR)
+ whtcnt++;
+ }
+ if (blkcnt && whtcnt)
+ return CNT_NOONE;
+ }
+ if (blkcnt && !whtcnt)
+ return CNT_BLACK_TERR;
+ else if (whtcnt && !blkcnt)
+ return CNT_WHITE_TERR;
+ else
+ return CNT_UNDECIDED;
+}
diff --git a/noncore/games/go/amigo.h b/noncore/games/go/amigo.h
new file mode 100644
index 0000000..5150ac0
--- a/dev/null
+++ b/noncore/games/go/amigo.h
@@ -0,0 +1,146 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+/*=========================================================================
+=== ===
+=== FILE amigo.h ===
+=== ===
+=== CONTENTS prototypes for the various AmiGo routines. ===
+=== added by neilb ===
+=== ===
+=========================================================================*/
+
+#ifndef __amigo_h
+#define __amigo_h
+
+#include "go.h"
+#include "goplayutils.h"
+
+#ifdef __STDC__
+#define PROTO(fp) fp
+#else
+#define PROTO(fp) ()
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* From goplayer.c */
+
+
+
+/* Procedures from amigo.c */
+
+short Connect PROTO((enum bVal, short, short, short[4], short[4], short *, short * ));
+short Maxlibs PROTO((short, short));
+short Suicide PROTO((enum bVal, short, short));
+short StoneLibs PROTO((short, short));
+void EraseMarks PROTO(());
+short GoPlaceStone PROTO((enum bVal, short, short));
+void GoRemoveStone PROTO((short, short));
+void MergeGroups PROTO((short, short));
+void DeleteGroup PROTO((short));
+void ReEvalGroups PROTO((enum bVal, short, short, short));
+void GroupCapture PROTO((short));
+void FixLibs PROTO((enum bVal, short, short, short));
+int CountUp PROTO((int*, int*));
+/*void main PROTO(());*/
+void goRestart PROTO((int));
+void RelabelGroups PROTO(());
+short CountAndMarkLibs PROTO((short, short));
+void CountLiberties PROTO((short));
+void CheckForEye PROTO((short, short, short[4], short, short *));
+void CountEyes PROTO(());
+void printGroupReport PROTO((short, short));
+
+
+/* killable.c */
+
+int tryPlay PROTO(( short, short, short ));
+int sSpanGroup PROTO(( short, short, sPointList * ));
+int spanGroup PROTO(( short, short, pointList *));
+int pause PROTO(());
+
+int genState PROTO(());
+int initGPUtils PROTO(());
+int genBord PROTO((enum bVal));
+
+short genMove PROTO(( enum bVal, short *, short * ));
+short checkPos PROTO(( short, short, short ));
+short takeCorner PROTO(( short *, short * ));
+short extend PROTO(( short *, short * ));
+short noNbrs PROTO(( short, short ));
+short extend2 PROTO(( short *, short * ));
+short lookForSave PROTO(( short *, short * ));
+short lookForSaveN PROTO(( short *, short * ));
+short lookForKill PROTO(( short *, short * ));
+short doubleAtari PROTO(( short *, short * ));
+short lookForAttack PROTO(( short *, short * ));
+short threaten PROTO(( short *, short * ));
+short connectCut PROTO(( short *, short * ));
+short heCanCut PROTO(( short, short ));
+short safeMove PROTO(( short, short ));
+short extendWall PROTO(( short *, short * ));
+short findAttack2 PROTO(( short *, short * ));
+short blockCut PROTO(( short *, short * ));
+short cutHim PROTO(( short *, short * ));
+short atariAnyway PROTO(( short *, short * ));
+short underCut PROTO(( short *, short * ));
+short dropToEdge PROTO(( short *, short * ));
+short pushWall PROTO(( short *, short * ));
+short reduceHisLiberties PROTO(( short *, short * ));
+short dropToEdge2 PROTO(( short *, short * ));
+
+
+/* goplayutils.c */
+
+short saveable PROTO((short, short, short *, short *));
+short killable PROTO((short, short, short *, short *));
+int initBoolBoard PROTO((boolBoard));
+int intersectPlist PROTO((pointList *, pointList *, pointList *));
+int initArray PROTO((intBoard));
+int initState PROTO(());
+int copyArray PROTO((intBoard, intBoard));
+int stake PROTO(());
+int spread PROTO(());
+int respreicen PROTO(());
+int tryPlay PROTO((short, short, short));
+int saveState PROTO(());
+int restoreState PROTO(());
+short tencen PROTO((short, short));
+int genConnects PROTO(());
+int sortLibs PROTO(());
+
+
+/*-- from xinterface.c --*/
+void removestone PROTO((short, short));
+void placestone PROTO((enum bVal, short, short));
+
+void intrMoveReport PROTO((enum bVal,char *,char *));
+void intrPrisonerReport PROTO(( short, short ));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/noncore/games/go/go.h b/noncore/games/go/go.h
new file mode 100644
index 0000000..9aa644b
--- a/dev/null
+++ b/noncore/games/go/go.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+/* AmiGo Include */
+/* MSG types for getinput() */
+
+#ifndef __go_h
+#define __go_h
+
+
+#define INTERSECTIONMSG 1 /* User buttoned an intersection */
+#define QUITMSG 2 /* User buttoned QUIT icon */
+#define PLAYMSG 3
+#define RESTARTMSG 4
+#define PASSMSG 5
+
+#define TRUE 1
+#define FALSE 0
+
+#define MAXGROUPS 100
+
+#define PLACED 0
+#define REMOVED 1
+
+#define numPoints 19
+#define maxPoint numPoints - 1
+
+/*-- definitions used when counting up --*/
+
+#define CNT_UNDECIDED 0
+#define CNT_BLACK_TERR 1
+#define CNT_WHITE_TERR 2
+#define CNT_NOONE 3
+
+/*-- macro functions --*/
+
+#define LegalPoint(x,y) (x>=0 && x<=18 && y>=0 && y<=18)
+#define ForeachPoint(a,b) for(a=0;a<19;a++) for (b=0;b<19;b++)
+
+enum bVal {BLACK, WHITE, EMPTY};
+typedef enum bVal sType;
+struct Group
+{
+ enum bVal color; /* The color of the group */
+ short code, /* The code used to mark stones in the group */
+ count, /* The number of stones in the group */
+ internal, /* The number of internal liberties */
+ external, /* The number of external liberties */
+ liberties, /* The total number of liberties */
+ eyes, /* The number of eyes */
+ alive, /* A judgement of how alive this group is */
+ territory; /* The territory this group controls */
+};
+
+struct bRec
+{
+ enum bVal Val; /* What is at this intersection */
+ short xOfs,
+ yOfs;
+ short mNum;
+ short GroupNum; /* What group the stone belongs to */
+ short marked; /* TRUE or FALSE */
+};
+
+#endif
diff --git a/noncore/games/go/go.pro b/noncore/games/go/go.pro
new file mode 100644
index 0000000..deb90c5
--- a/dev/null
+++ b/noncore/games/go/go.pro
@@ -0,0 +1,19 @@
+DESTDIR = ../bin
+TEMPLATE = app
+CONFIG = qt warn_on release
+HEADERS = amigo.h \
+ go.h \
+ goplayutils.h \
+ gowidget.h
+SOURCES = amigo.c \
+ goplayer.c \
+ goplayutils.c \
+ killable.c \
+ gowidget.cpp \
+ main.cpp
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+TARGET = go
+
+TRANSLATIONS = ../i18n/de/go.ts \ No newline at end of file
diff --git a/noncore/games/go/goplayer.c b/noncore/games/go/goplayer.c
new file mode 100644
index 0000000..88c0f61
--- a/dev/null
+++ b/noncore/games/go/goplayer.c
@@ -0,0 +1,1499 @@
+/* The go player */
+/* Ported from Pascal to C by Todd R. Johnson 4/17/88 */
+/* From the original pascal file:
+Go Move Generator
+Copyright (c) 1983 by Three Rivers Computer Corp.
+
+Written: January 17, 1983 by Stoney Ballard
+Edit History:
+*/
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+#define BIGGEST 32767 /* maximum value for short */
+
+/* From go.c */
+extern struct bRec goboard[19][19];
+extern short ko, koX, koY;
+
+/* From goplayutils.c */
+extern intBoard bord;
+extern intBoard ndbord;
+extern intBoard claim;
+extern intBoard legal;
+extern intBoard connectMap;
+extern intBoard threatBord;
+extern short maxGroupID;
+extern short treeLibLim;
+extern short killFlag;
+extern short depthLimit;
+extern short showTrees;
+extern short utilPlayLevel;
+extern groupRec gList[maxGroup];
+extern short sGlist[maxGroup + 1];
+extern pointList pList;
+extern pointList pList1;
+extern pointList plist2;
+extern pointList plist3;
+extern intBoard groupIDs;
+extern intBoard protPoints;
+extern sType mySType;
+
+
+short saveNLibs;
+pointList dapList1, dapList2, dapList3;
+char *playReason;
+short maxPlayLevel = 7;
+short playLevel = 7;
+
+genBord(color)
+ enum bVal color;
+{
+ short x, y, nomoves = TRUE;
+ char mv[8];
+
+ maxPlayLevel = 7;
+ utilPlayLevel = playLevel;
+ mySType = color;
+ if (playLevel < 2)
+ treeLibLim = 2;
+ else
+ treeLibLim = 3;
+ depthLimit = 100;
+ for (y = 0; y <= 18; y++)
+ for (x = 0; x <= 18; x++)
+ if (goboard[x][y].Val == color)
+ {
+ bord[x][y] = 1;
+ legal[x][y] = FALSE;
+ nomoves = FALSE;
+ }
+ else if (goboard[x][y].Val == EMPTY)
+ {
+ bord[x][y] = 0;
+ legal[x][y] = TRUE;
+ }
+ else
+ {
+ bord[x][y] = -1;
+ legal[x][y] = FALSE;
+ nomoves = FALSE;
+ }
+ if (ko)
+ {
+ legal[koX][koY] = FALSE;
+ }
+
+ if (! nomoves)
+ genState();
+ else
+ initGPUtils();
+}
+
+
+short getMove( x, y )
+short *x, *y;
+{
+ if (takeCorner(x, y)) return TRUE;
+ if (lookForSave(x, y)) return TRUE;
+ if (lookForSaveN(x, y)) return TRUE;
+ if (extend(x, y)) return TRUE;
+ if (lookForKill(x, y)) return TRUE;
+ if (doubleAtari(x, y)) return TRUE;
+ if (lookForAttack(x, y)) return TRUE;
+ if (threaten(x, y)) return TRUE;
+ if (extend2(x, y)) return TRUE;
+ if (connectCut(x, y)) return TRUE;
+ if (blockCut(x, y)) return TRUE;
+ if (cutHim(x, y)) return TRUE;
+ if (extendWall(x, y)) return TRUE;
+ if (findAttack2(x, y)) return TRUE;
+ if (atariAnyway(x, y)) return TRUE;
+ if (underCut(x, y)) return TRUE;
+ if (dropToEdge(x, y)) return TRUE;
+ if (pushWall(x, y)) return TRUE;
+ if (reduceHisLiberties(x, y)) return TRUE;
+ if (dropToEdge2(x, y)) return TRUE;
+ return FALSE;
+}
+
+short genMove( color, x, y )
+enum bVal color;
+short *x, *y;
+{
+ if (playLevel > 2)
+ saveNLibs = TRUE;
+ else
+ saveNLibs = FALSE;
+ genBord(color);
+ if (getMove(x, y))
+ return TRUE;
+ return FALSE;
+}
+
+short checkPos(x, y, field)
+short x, y, field;
+{
+ short ok;
+ ok = (((field == 0) && (claim[x][y] == 0)) ||
+ ((field > 0) &&
+ (claim[x][y] >= 0) && (claim[x][y] <= field)) ||
+ ((field < 0) &&
+ (claim[x][y] <= 0) && (claim[x][y] >= field))) &&
+ (bord[x-1][y] == 0) &&
+ (bord[x+1][y] == 0) &&
+ (bord[x][y-1] == 0) &&
+ (bord[x][y+1] == 0);
+ if (ok) return TRUE; else return FALSE;
+}
+
+short takeCorner( x, y )
+short *x, *y;
+{
+ short field = -1, i;
+ i = 18 - 3;
+ playReason = "takeCorner";
+ while (field != -4)
+ {
+ if (field == -1) field = 0;
+ else if (field == 0) field = 4;
+ else field = -4;
+ if (checkPos(2, 3, field)) { *x = 2; *y = 3; return TRUE; }
+ if (checkPos(3, 2, field)) { *x = 3; *y = 2; return TRUE; }
+ if (checkPos(2, i, field)) { *x = 2; *y = i; return TRUE; }
+ if (checkPos(3, i + 1, field)) { *x = 3; *y = i+1; return TRUE; }
+ if (checkPos(i, i + 1, field)) { *x = i; *y = i+1; return TRUE; }
+ if (checkPos(i + 1, i, field)) { *x = i+1; *y = i; return TRUE; }
+ if (checkPos(i, 2, field)) { *x = i; *y = 2; return TRUE; }
+ if (checkPos(i + 1, 3, field)) { *x = i+1; *y = 3; return TRUE; }
+ if (checkPos(2, 4, field)) { *x = 2; *y = 4; return TRUE; }
+ if (checkPos(4, 2, field)) { *x = 4; *y = 2; return TRUE; }
+ if (checkPos(2, i - 1, field)) { *x = 2; *y = i-1; return TRUE; }
+ if (checkPos(4, i + 1, field)) { *x = 4; *y = i+1; return TRUE; }
+ if (checkPos(i - 1, i + 1, field)) { *x = i-1; *y = i+1; return TRUE; }
+ if (checkPos(i + 1, i - 1, field)) { *x = i+1; *y = i-1; return TRUE; }
+ if (checkPos(i + 1, 4, field)) { *x = i+1; *y = 4; return TRUE; }
+ if (checkPos(i - 1, 2, field)) { *x = i-1; *y = 2; return TRUE; }
+ }
+ return FALSE;
+}
+
+printBoard(brd, name)
+intBoard brd;
+char *name;
+{
+ short x, y;
+ printf( "%s\n", name );
+ for (y = 0; y <= 18; y++)
+ {
+ for (x = 0; x <= 18; x++)
+ printf("%d ", brd[x][y]);
+ printf("\n");
+ }
+}
+
+short noNbrs( x, y )
+short x, y;
+{
+ if (x > 0 && bord[x-1][y] != 0) return FALSE;
+ if (x < 18 && bord[x+1][y] != 0) return FALSE;
+ if (y > 0 && bord[x][y-1] != 0) return FALSE;
+ if (y < 18 && bord[x][y+1] != 0) return FALSE;
+ return TRUE;
+}
+
+short extend(x, y)
+short *x, *y;
+{
+ short i;
+ playReason = "extend";
+ for (i = 2; i <= 18-2; i++)
+ if (claim[2][i] == 0 && noNbrs( 2, i ))
+ {
+ *x = 2;
+ *y = i;
+ return TRUE;
+ }
+ for (i = 2; i <= 18-2; i++)
+ if (claim[i][18-2] == 0 && noNbrs( 2, i ))
+ {
+ *x = i;
+ *y = 18-2;
+ return TRUE;
+ }
+ for (i = 18-2; i >= 2; i--)
+ if (claim[18-2][i] == 0 && noNbrs( 18-2, i ))
+ {
+ *x = 18-2;
+ *y = i;
+ return TRUE;
+ }
+ for (i = 18-2; i >= 2; i--)
+ if (claim[i][2] == 0 && noNbrs( i, 2 ))
+ {
+ *x = i;
+ *y = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+short extend2( x, y )
+short *x, *y;
+{
+ short i, lowest = BIGGEST, value;
+ playReason = "extend2";
+ for (i = 3; i <= 18-3; i++)
+ if (legal[2][i]) /* if there is nobody there */
+ {
+ value = claim[2][i]; /* get influence */
+ if ((value < 7) && /* a reasonable hole in my wall */
+ (value > -5) && /* or a reasonable gap in his */
+ (bord[2][i + 1] == 0) && /* not in contact with any stones */
+ (bord[2][i - 1] == 0))
+ if (value < lowest)
+ {
+ lowest = value; /* lowest gets the smallest value */
+ *x = 2; /* that was seen along all the 3-lines */
+ *y = i; /* x and y save that location */
+ }
+ }
+ for (i = 3; i <= 18-3; i++)
+ if (legal[i][2])
+ {
+ value = claim[i][2];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[i + 1][2] == 0) &&
+ (bord[i - 1][2] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = i;
+ *y = 2;
+ }
+ }
+ for (i = 18-3; i >= 3; i--)
+ if (legal[18 - 2][i])
+ {
+ value = claim[18 - 2][i];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[18 - 2][i + 1] == 0) &&
+ (bord[18 - 2][i - 1] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = 18 - 2;
+ *y = i;
+ }
+ }
+ for (i = 3; i <= 18-3; i++)
+ if (legal[i][18 - 2])
+ {
+ value = claim[i][18 - 2];
+ if ((value < 7) &&
+ (value > -5) &&
+ (bord[i + 1][18 - 2] == 0) &&
+ (bord[i - 1][18 - 2] == 0))
+ if (value < lowest)
+ {
+ lowest = value;
+ *x = i;
+ *y = 18 - 2;
+ }
+ }
+ if (lowest == BIGGEST) return FALSE;
+ return TRUE;
+}
+
+ /*
+ check to see if I can save anything in atari
+ */
+short lookForSave(x, y)
+short *x, *y;
+ { /* lookForSave */
+ short i;
+ playReason = "lookForSave";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 1) &&
+ (ndbord[gList[i].lx][gList[i].ly] == 1))
+ if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
+ return TRUE;
+ return FALSE;
+ } /* lookForSave */
+
+ /*
+ check to see if I can save anything with n libs
+ */
+short lookForSaveN(x, y)
+short *x, *y;
+ { /* lookForSaveN */
+ short i;
+ if (saveNLibs)
+ {
+ playReason = "lookForSaveN";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC > 1) &&
+ (gList[i].libC <= treeLibLim) &&
+ (ndbord[gList[i].lx][gList[i].ly] == 1))
+ {
+ if (killable(gList[i].lx, gList[i].ly, x, y))
+ if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* lookForSaveN */
+
+
+/*----------------------------------------------------------------
+-- lookForKill() --
+-- check to see if I can kill anything. --
+----------------------------------------------------------------*/
+short
+lookForKill(x, y)
+ short *x, *y;
+{
+ short i;
+ char mv[8];
+
+ playReason = "lookForKill";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 1) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ { /* we found a live enemy group with one liberty */
+ /* find the liberty */
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ *x = pList.p[1].px;
+ *y = pList.p[1].py;
+ if (legal[*x][*y])
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+short doubleAtari(x, y)
+short *x, *y;
+ { /* doubleAtari */
+ short i, j;
+ playReason = "doubleAtari";
+ for (i = 1; i <= maxGroupID - 1; i++)
+ if ((gList[i].libC == 2) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1)) /* found an atariable group of his */
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &dapList1);
+ for (j = i + 1; j <= maxGroupID; j++)
+ if ((gList[j].libC == 2) &&
+ (ndbord[gList[j].lx][gList[j].ly] == -1))
+ {
+ spanGroup(gList[j].lx, gList[j].ly, &dapList2);
+ intersectPlist(&dapList1, &dapList2, &dapList3);
+ if (dapList3.indx > 0)
+ if (legal[dapList3.p[1].px][dapList3.p[1].py])
+ {
+ tryPlay(dapList3.p[1].px, dapList3.p[1].py, 1);
+ if (gList[groupIDs[dapList3.p[1].px][
+ dapList3.p[1].py]].libC > 1)
+ {
+ *x = dapList3.p[1].px;
+ *y = dapList3.p[1].py;
+ restoreState();
+ return TRUE;
+ }
+ restoreState();
+ }
+ }
+ }
+ return FALSE;
+ } /* doubleAtari */
+
+short lookForAttack(x, y)
+short *x, *y;
+ { /* lookForAttack */
+ short tx, ty, i;
+ playReason = "lookForAttack";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((! gList[i].isLive) &&
+ (gList[i].libC > 1) &&
+ (gList[i].libC <= (treeLibLim + 1)) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
+ {
+ *x = tx; /* yep - do so */
+ *y = ty;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* lookForAttack */
+
+ /*
+ Plays a move that requires a response on the opponent's part
+ */
+short threaten(x, y)
+short *x, *y;
+ { /* threaten */
+ short i, j, gx, gy, tNum;
+ playReason = "threaten";
+ initArray(threatBord);
+ for (i = 1; i <= maxGroupID; i++)
+ if ((! gList[i].isLive) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ for (j = 1; j <= pList.indx; j++)
+ if (legal[pList.p[j].px][pList.p[j].py])
+ {
+ tryPlay(pList.p[j].px, pList.p[j].py, 1);
+ if (gList[groupIDs[pList.p[j].px][pList.p[j].py]].libC > 1)
+ if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
+ threatBord[pList.p[j].px][pList.p[j].py] += 1;
+ restoreState();
+ }
+ }
+ tNum = 0;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if ((threatBord[i][j] > tNum) &&
+ ((threatBord[i][j] > 1) ||
+ (connectMap[i][j] > 0)))
+ {
+ tNum = threatBord[i][j];
+ *x = i;
+ *y = j;
+ }
+ if (tNum > 0) return TRUE;
+ else return FALSE;
+ } /* threaten */
+
+ /*
+ connects against enemy cuts
+ */
+short connectCut(x, y)
+short *x, *y;
+ { /* connectCut */
+ short i, j, nap, gid, infl;
+ playReason = "connectCut";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j] &&
+ (protPoints[i][j] == 0)) /* not a protected point */
+ {
+ nap = 0; /* how many of my stones am I adjacent to? */
+ if ((i > 0) && (bord[i - 1][j] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i - 1;
+ pList.p[nap].py = j;
+ }
+ if ((j > 0) && (bord[i][j - 1] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j - 1;
+ }
+ if ((i < maxPoint) && (bord[i + 1][j] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i + 1;
+ pList.p[nap].py = j;
+ }
+ if ((j < maxPoint) && (bord[i][j + 1] == 1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j + 1;
+ }
+ if (nap == 1) /* possible knight's || 2-point extention */
+ {
+ gid = groupIDs[pList.p[1].px][pList.p[1].py];
+ if ((i > 0) && (i < maxPoint) &&
+ (ndbord[i - 1][j] == 1) &&
+ (ndbord[i + 1][j] == 0)) /* contact on left */
+ {
+ if (((j > 0) && (ndbord[i][j - 1] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
+ (i < (maxPoint - 1)) &&
+ (ndbord[i + 2][j] == 1) &&
+ (gid != groupIDs[i + 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((i < maxPoint) && (i > 0) &&
+ (ndbord[i + 1][j] == 1) &&
+ (ndbord[i - 1][j] == 0)) /* r */
+ {
+ if (((j > 0) && (ndbord[i][j - 1] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
+ (i > 1) &&
+ (ndbord[i - 2][j] == 1) &&
+ (gid != groupIDs[i - 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j - 1] == 1) &&
+ (ndbord[i][j + 1] == 0)) /* top */
+ {
+ if (((i > 0) && (ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
+ (j < (maxPoint - 1)) &&
+ (ndbord[i][j + 2] == 1) &&
+ (gid != groupIDs[i][j + 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j + 1] == 1) &&
+ (ndbord[i][j - 1] == 0)) /* bottom */
+ {
+ if (((i > 0) && (ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
+ (j > 1) &&
+ (ndbord[i][j - 2] == 1) &&
+ (gid != groupIDs[i][j - 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ else if (nap == 2) /* diagonal or 1-point extention */
+ {
+ if (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py])
+ {
+ if ((pList.p[1].px != pList.p[2].px) &&
+ (pList.p[1].py != pList.p[2].py)) /* diag */
+ {
+ spanGroup(pList.p[1].px,
+ pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px,
+ pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ if (plist3.indx == 1)
+ if ((i > 0) && (ndbord[i - 1][j] == -1) ||
+ (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
+ (j > 0) && (ndbord[i][j - 1] == -1) ||
+ (j < maxPoint) && (ndbord[i][j + 1] == -1))
+ { /* must make direct connection */
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ else if (heCanCut(i, j))
+ { /* protect point if possible */
+ infl = 1000;
+ if ((i > 0) && legal[i - 1][j] &&
+ ((i == 1) || (ndbord[i - 2][j] == 0)) &&
+ ((j == 0) || (ndbord[i - 1][j - 1] == 0)) &&
+ ((j == maxPoint) ||
+ (ndbord[i - 1][j + 1] == 0)))
+ if (safeMove(i - 1, j))
+ if (claim[i - 1][j] < infl)
+ {
+ *x = i - 1;
+ *y = j;
+ infl = claim[i - 1][j];
+ }
+ if ((j > 0) && legal[i][j - 1] &&
+ ((j == 1) || (ndbord[i][j - 2] == 0)) &&
+ ((i == 0) || (ndbord[i - 1][j - 1] == 0)) &&
+ ((i == maxPoint) ||
+ (ndbord[i + 1][j - 1] == 0)))
+ if (safeMove(i, j - 1))
+ if (claim[i][j - 1] < infl)
+ {
+ *x = i;
+ *y = j - 1;
+ infl = claim[i][j - 1];
+ }
+ if ((i < maxPoint) && legal[i + 1][j] &&
+ ((i == (maxPoint - 1)) ||
+ (ndbord[i + 2][j] == 0)) &&
+ ((j == 0) || (ndbord[i + 1][j - 1] == 0)) &&
+ ((j == maxPoint) ||
+ (ndbord[i + 1][j + 1] == 0)))
+ if (safeMove(i + 1, j))
+ if (claim[i + 1][j] < infl)
+ {
+ *x = i + 1;
+ *y = j;
+ infl = claim[i + 1][j];
+ }
+ if ((j < maxPoint) && legal[i][j + 1] &&
+ ((j == (maxPoint - 1)) ||
+ (ndbord[i][j + 2] == 0)) &&
+ ((i == 0) || (ndbord[i - 1][j + 1] == 0)) &&
+ ((i == maxPoint) ||
+ (ndbord[i + 1][j + 1] == 0)))
+ if (safeMove(i, j + 1))
+ if (claim[i][j + 1] < infl)
+ {
+ *x = i;
+ *y = j + 1;
+ infl = claim[i][j + 1];
+ }
+ if (infl < 1000)
+ return TRUE;
+ *x = i; /* direct connection */
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else /* 1-point extension, only protect if threatened */
+ {
+ if ((i > 0) && (ndbord[i - 1][j] == -1) ||
+ (j > 0) && (ndbord[i][j - 1] == -1) ||
+ (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
+ (j < maxPoint) && (ndbord[i][j + 1] == -1))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ }
+ else if (nap == 3) /* unprotected, but me on 3 sides */
+ {
+ if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]) ||
+ (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[3].px][pList.p[3].py]) ||
+ (groupIDs[pList.p[3].px][pList.p[3].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]))
+ {
+ spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
+ intersectPlist(&plist2, &plist3, &pList1);
+ if (pList1.indx == 1) /* a common connect point */
+ if (heCanCut(i, j))
+ if (safeMove(i, j))
+ {
+ *x = i;
+ *y = j;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+ } /* connectCut */
+
+short heCanCut(x, y)
+short x, y;
+ { /* heCanCut */
+ short gx, gy, result;
+ if (playLevel > 3)
+ {
+ tryPlay(x, y, -1); /* try his cut */
+ result = ! killable(x, y, &gx, &gy);
+ restoreState();
+ return result;
+ }
+ else
+ return FALSE;
+ } /* heCanCut */
+
+ /*
+ Checks out a move.
+ If my stone is not killable then true.
+ */
+short safeMove(x, y)
+short x, y;
+ { /* safeMove */
+ short gbx, gby, result;
+ tryPlay(x, y, 1); /* try playing at point */
+ if (killFlag) /* I shouldn't kill if lookForKill didn't */
+ result = FALSE;
+ else if (gList[groupIDs[x][y]].libC < 2)
+ { /* if it is in atari or dead */
+ result = FALSE; /* reject it */
+ }
+ else if (gList[groupIDs[x][y]].libC <= treeLibLim) /* see if killable */
+ if (playLevel > 0)
+ result = ! killable(x, y, &gbx, &gby);
+ else
+ result = TRUE;
+ else
+ result = TRUE;
+ restoreState();
+ return result;
+ } /* safeMove */
+
+ /*
+ Extends walls in a connected fashion.
+ Finds the lowest influence (mine) point that is connected to one
+ of my groups.
+ Only looks in the center of the board.
+ */
+short extendWall(x, y)
+short *x, *y;
+ { /* extendWall */
+ short infl, i, j;
+ playReason = "extendWall";
+ *x = iNil;
+ *y = iNil;
+ infl = 11;
+ for (i = 2; i <= maxPoint - 2; i++)
+ for (j = 2; j <= maxPoint - 2; j++)
+ if (legal[i][j])
+ if (connectMap[i][j] > 0)
+ if ((claim[i][j] < infl) &&
+ (ndbord[i - 1][j] < 1) &&
+ (ndbord[i + 1][j] < 1) &&
+ (ndbord[i][j - 1] < 1) &&
+ (ndbord[i][j + 1] < 1) &&
+ ((claim[i - 1][j] < 0) ||
+ (claim[i + 1][j] < 0) ||
+ (claim[i][j - 1] < 0) ||
+ (claim[i][j + 1] < 0)))
+ if (safeMove(i, j))
+ {
+ infl = claim[i][j];
+ *x = i;
+ *y = j;
+ }
+ if (*x != iNil) return TRUE;
+ return FALSE;
+ } /* extendWall */
+
+
+ /*
+ check to see if I can attack one of his groups
+ uses limited depth search so that it can work on larger lib counts
+ */
+short findAttack2(x, y)
+short *x, *y;
+ { /* findAttack2 */
+ short tx, ty, i, otll;
+ if (playLevel < 7)
+ return FALSE;
+ playReason = "findAttack2";
+ depthLimit = 8;
+ otll = treeLibLim;
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((! gList[i].isLive) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1) &&
+ (gList[i].libC > 1))
+ {
+ treeLibLim = 6;
+ if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
+ {
+ *x = tx; /* yep - do so */
+ *y = ty;
+ return TRUE;
+ }
+ treeLibLim = otll;
+ }
+ depthLimit = 100;
+ return FALSE;
+ } /* findAttack2 */
+
+
+ /*
+ blocks enemy cuts thru 1-point extensions
+ */
+short blockCut(x, y)
+short *x, *y;
+ { /* blockCut */
+ short i, j;
+ playReason = "blockCut";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ {
+ if ((i > 0) && (j > 0) && (j < maxPoint))
+ {
+ if ((ndbord[i - 1][j] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (groupIDs[i - 1][j - 1] != groupIDs[i - 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((i < maxPoint) && (j > 0) && (j < maxPoint))
+ {
+ if ((ndbord[i + 1][j] == -1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (groupIDs[i + 1][j - 1] != groupIDs[i + 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((j > 0) && (i > 0) && (i < maxPoint))
+ {
+ if ((ndbord[i][j - 1] == -1) &&
+ (ndbord[i - 1][j - 1] == 1) &&
+ (ndbord[i + 1][j - 1] == 1) &&
+ (groupIDs[i - 1][j - 1] != groupIDs[i + 1][j - 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if ((j < maxPoint) && (i > 0) && (i < maxPoint))
+ {
+ if ((ndbord[i][j + 1] == -1) &&
+ (ndbord[i - 1][j + 1] == 1) &&
+ (ndbord[i + 1][j + 1] == 1) &&
+ (groupIDs[i - 1][j + 1] != groupIDs[i + 1][j + 1]))
+ {
+ *x = i;
+ *y = j;
+ if (heCanCut(*x, *y))
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* blockCut */
+
+
+ /*
+ cuts the enemy
+ */
+short cutHim(x, y)
+short *x, *y;
+ { /* cutHim */
+ short i, j, nap, gid;
+ playReason = "cutHim";
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ {
+ nap = 0; /* how many of his stones am I adjacent to? */
+ if ((i > 0) && (ndbord[i - 1][j] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i - 1;
+ pList.p[nap].py = j;
+ }
+ if ((j > 0) && (ndbord[i][j - 1] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j - 1;
+ }
+ if ((i < maxPoint) && (ndbord[i + 1][j] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i + 1;
+ pList.p[nap].py = j;
+ }
+ if ((j < maxPoint) && (ndbord[i][j + 1] == -1))
+ {
+ nap = nap + 1;
+ pList.p[nap].px = i;
+ pList.p[nap].py = j + 1;
+ }
+ if (nap == 1) /* possible knight's or 2-point extention */
+ {
+ gid = groupIDs[pList.p[1].px][pList.p[1].py];
+ if ((i > 0) && (i < maxPoint) &&
+ (ndbord[i - 1][j] == -1) &&
+ (connectMap[i][j] > 0)) /* contact on left */
+ {
+ if (((j > 0) &&
+ (ndbord[i + 1][j - 1] == -1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j < maxPoint) &&
+ (ndbord[i + 1][j + 1] == -1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((i < (maxPoint - 1)) &&
+ (ndbord[i + 1][j] == 0) &&
+ (ndbord[i + 2][j] == -1) &&
+ (gid != groupIDs[i + 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((i < maxPoint) && (i > 0) &&
+ (ndbord[i + 1][j] == -1) &&
+ (connectMap[i][j] > 0)) /* r */
+ {
+ if (((j > 0) &&
+ (ndbord[i - 1][j - 1] == -1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((j < maxPoint) &&
+ (ndbord[i - 1][j + 1] == -1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i > 1) &&
+ (ndbord[i - 1][j] == 0) &&
+ (ndbord[i - 2][j] == -1) &&
+ (gid != groupIDs[i - 2][j])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j - 1] == -1) &&
+ (connectMap[i][j] > 0)) /* top */
+ {
+ if (((i > 0) &&
+ (ndbord[i - 1][j + 1] == -1) &&
+ (gid != groupIDs[i - 1][j + 1])) ||
+ ((i < maxPoint) &&
+ (ndbord[i + 1][j + 1] == -1) &&
+ (gid != groupIDs[i + 1][j + 1])) ||
+ ((j < (maxPoint - 1)) &&
+ (ndbord[i][j + 1] == 0) &&
+ (ndbord[i][j + 2] == -1) &&
+ (gid != groupIDs[i][j + 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else if ((j > 0) && (j < maxPoint) &&
+ (ndbord[i][j + 1] == -1) &&
+ (connectMap[i][j] > 0)) /* bottom */
+ {
+ if (((i > 0) &&
+ (ndbord[i - 1][j - 1] == -1) &&
+ (gid != groupIDs[i - 1][j - 1])) ||
+ ((i < maxPoint) &&
+ (ndbord[i + 1][j - 1] == -1) &&
+ (gid != groupIDs[i + 1][j - 1])) ||
+ ((j > 1) &&
+ (ndbord[i][j - 1] == 0) &&
+ (ndbord[i][j - 2] == -1) &&
+ (gid != groupIDs[i][j - 2])))
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ else if (nap == 2) /* diagonal or 1-point extention */
+ {
+ if (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py])
+ {
+ if ((pList.p[1].px != pList.p[2].px) &&
+ (pList.p[1].py != pList.p[2].py)) /* diag */
+ {
+ spanGroup(pList.p[1].px,
+ pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px,
+ pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ if (plist3.indx == 1)
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ else /* 1-point extension, only cut if connected */
+ {
+ if (connectMap[i][j] > 0)
+ {
+ *x = i;
+ *y = j;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ }
+ else if (nap == 3) /* unprotected, but him on 3 sides */
+ {
+ if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]) ||
+ (groupIDs[pList.p[1].px][pList.p[1].py] !=
+ groupIDs[pList.p[3].px][pList.p[3].py]) ||
+ (groupIDs[pList.p[3].px][pList.p[3].py] !=
+ groupIDs[pList.p[2].px][pList.p[2].py]))
+ {
+ spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
+ spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
+ intersectPlist(&pList1, &plist2, &plist3);
+ spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
+ intersectPlist(&plist2, &plist3, &pList1);
+ if (pList1.indx == 1) /* a common connect point */
+ if (safeMove(i, j))
+ {
+ *x = i;
+ *y = j;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+ } /* cutHim */
+
+
+ /*
+ ataris a group just for the hell of it
+ */
+short atariAnyway(x, y)
+short *x, *y;
+ { /* atariAnyway */
+ short i;
+ playReason = "atariAnyway";
+ for (i = 1; i <= maxGroupID; i++) /* scan the group list */
+ if ((gList[i].libC == 2) &&
+ (ndbord[gList[i].lx][gList[i].ly] == -1))
+ {
+ spanGroup(gList[i].lx, gList[i].ly, &pList);
+ if (legal[pList.p[1].px][pList.p[1].py] &&
+ ((connectMap[pList.p[1].px][pList.p[1].py] > 0) ||
+ ((pList.p[1].px > 0) &&
+ (connectMap[pList.p[1].px - 1][pList.p[1].py] > 0)) ||
+ ((pList.p[1].px < maxPoint) &&
+ (connectMap[pList.p[1].px + 1][pList.p[1].py] > 0)) ||
+ ((pList.p[1].py > 0) &&
+ (connectMap[pList.p[1].px][pList.p[1].py - 1] > 0)) ||
+ ((pList.p[1].py < maxPoint) &&
+ (connectMap[pList.p[1].px][pList.p[1].py + 1] > 0))))
+ if (safeMove(pList.p[1].px, pList.p[1].py))
+ {
+ *x = pList.p[1].px;
+ *y = pList.p[1].py;
+ return TRUE;
+ }
+ if (legal[pList.p[2].px][pList.p[2].py] &&
+ ((connectMap[pList.p[2].px][pList.p[2].py] > 0) ||
+ ((pList.p[2].px > 0) &&
+ (connectMap[pList.p[2].px - 1][pList.p[2].py] > 0)) ||
+ ((pList.p[2].px < maxPoint) &&
+ (connectMap[pList.p[2].px + 1][pList.p[2].py] > 0)) ||
+ ((pList.p[2].py > 0) &&
+ (connectMap[pList.p[2].px][pList.p[2].py - 1] > 0)) ||
+ ((pList.p[2].py < maxPoint) &&
+ (connectMap[pList.p[2].px][pList.p[2].py + 1] > 0))))
+ if (safeMove(pList.p[2].px, pList.p[2].py))
+ {
+ *x = pList.p[2].px;
+ *y = pList.p[2].py;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* atariAnyway */
+
+
+ /*
+ undercuts his groups
+ */
+short underCut(x, y)
+short *x, *y;
+ { /* underCut */
+ short i, j;
+ playReason = "underCut";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[0][i])
+ {
+ if (ndbord[1][i] == -1)
+ if (safeMove(0, i))
+ {
+ *x = 0;
+ *y = i;
+ return TRUE;
+ }
+ }
+ if (legal[maxPoint][i])
+ {
+ if (ndbord[maxPoint - 1][i] == -1)
+ if (safeMove(maxPoint, i))
+ {
+ *x = maxPoint;
+ *y = i;
+ return TRUE;
+ }
+ }
+ if (legal[i][0])
+ {
+ if (ndbord[i][1] == -1)
+ if (safeMove(i, 0))
+ {
+ *x = i;
+ *y = 0;
+ return TRUE;
+ }
+ }
+ if (legal[i][maxPoint])
+ {
+ if (ndbord[i][maxPoint - 1] == -1)
+ if (safeMove(i, maxPoint))
+ {
+ *x = i;
+ *y = maxPoint;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* underCut */
+
+ /*
+ drops to the edge of the board if threatened
+ */
+short dropToEdge(x, y)
+short *x, *y;
+ { /* dropToEdge */
+ short i;
+ playReason = "dropToEdge";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[1][i])
+ if ((ndbord[2][i] == 1) &&
+ (ndbord[0][i] == 0) &&
+ (ndbord[1][i - 1] < 1) &&
+ (ndbord[1][i + 1] < 1) &&
+ ((ndbord[2][i - 1] == -1) ||
+ (ndbord[2][i + 1] == -1) ||
+ (ndbord[1][i - 1] == -1) ||
+ (ndbord[1][i + 1] == -1)))
+ {
+ *x = 1;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[maxPoint - 1][i])
+ if ((ndbord[maxPoint - 2][i] == 1) &&
+ (ndbord[maxPoint][i] == 0) &&
+ (ndbord[maxPoint - 1][i - 1] < 1) &&
+ (ndbord[maxPoint - 1][i + 1] < 1) &&
+ ((ndbord[maxPoint - 2][i - 1] == -1) ||
+ (ndbord[maxPoint - 2][i + 1] == -1) ||
+ (ndbord[maxPoint - 1][i - 1] == -1) ||
+ (ndbord[maxPoint - 1][i + 1] == -1)))
+ {
+ *x = maxPoint - 1;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][1])
+ if ((ndbord[i][2] == 1) &&
+ (ndbord[i][0] == 0) &&
+ (ndbord[i - 1][1] < 1) &&
+ (ndbord[i + 1][1] < 1) &&
+ ((ndbord[i - 1][2] == -1) ||
+ (ndbord[i + 1][2] == -1) ||
+ (ndbord[i - 1][1] == -1) ||
+ (ndbord[i + 1][1] == -1)))
+ {
+ *x = i;
+ *y = 1;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][maxPoint - 1])
+ if ((ndbord[i][maxPoint - 2] == 1) &&
+ (ndbord[i][maxPoint] == 0) &&
+ (ndbord[i - 1][maxPoint - 1] < 1) &&
+ (ndbord[i + 1][maxPoint - 1] < 1) &&
+ ((ndbord[i - 1][maxPoint - 2] == -1) ||
+ (ndbord[i + 1][maxPoint - 2] == -1) ||
+ (ndbord[i - 1][maxPoint - 1] == -1) ||
+ (ndbord[i + 1][maxPoint - 1] == -1)))
+ {
+ *x = i;
+ *y = maxPoint - 1;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[0][i])
+ if ((ndbord[1][i] == 1) &&
+ (ndbord[0][i - 1] < 1) &&
+ (ndbord[0][i + 1] < 1) &&
+ (((ndbord[1][i - 1] == -1) &&
+ (ndbord[1][i + 1] == -1)) ||
+ (ndbord[0][i - 1] == -1) ||
+ (ndbord[0][i + 1] == -1)))
+ {
+ *x = 0;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[maxPoint][i])
+ if ((ndbord[maxPoint - 1][i] == 1) &&
+ (ndbord[maxPoint][i - 1] < 1) &&
+ (ndbord[maxPoint][i + 1] < 1) &&
+ (((ndbord[maxPoint - 1][i - 1] == -1) &&
+ (ndbord[maxPoint - 1][i + 1] == -1)) ||
+ (ndbord[maxPoint][i - 1] == -1) ||
+ (ndbord[maxPoint][i + 1] == -1)))
+ {
+ *x = maxPoint;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][0])
+ if ((ndbord[i][1] == 1) &&
+ (ndbord[i - 1][0] < 1) &&
+ (ndbord[i + 1][0] < 1) &&
+ (((ndbord[i - 1][1] == -1) &&
+ (ndbord[i + 1][1] == -1)) ||
+ (ndbord[i - 1][0] == -1) ||
+ (ndbord[i + 1][0] == -1)))
+ {
+ *x = i;
+ *y = 0;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ if (legal[i][maxPoint])
+ if ((ndbord[i][maxPoint - 1] == 1) &&
+ (ndbord[i - 1][maxPoint] < 1) &&
+ (ndbord[i + 1][maxPoint] < 1) &&
+ (((ndbord[i - 1][maxPoint - 1] == -1) &&
+ (ndbord[i + 1][maxPoint - 1] == -1)) ||
+ (ndbord[i - 1][maxPoint] == -1) ||
+ (ndbord[i + 1][maxPoint] == -1)))
+ {
+ *x = i;
+ *y = maxPoint;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* dropToEdge */
+
+ /*
+ Pushes walls in a tightly connected fashion.
+ Finds the lowest influence (mine) point that is connected to one
+ of my groups.
+ */
+short pushWall(x, y)
+short *x, *y;
+ { /* pushWall */
+ short infl, i, j, na;
+ playReason = "pushWall";
+ *x = iNil;
+ *y = iNil;
+ infl = 11;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (legal[i][j])
+ if (connectMap[i][j] > 0)
+ if ((claim[i][j] < infl) &&
+ (((i > 0) && (ndbord[i - 1][j] == 1)) ||
+ ((i < maxPoint) && (ndbord[i + 1][j] == 1)) ||
+ ((j > 0) && (ndbord[i][j - 1] == 1)) ||
+ ((j < maxPoint) && (ndbord[i][j + 1] == 1)) ||
+ ((i > 0) && (j > 0) && (ndbord[i - 1][j - 1] == 1)) ||
+ ((i < maxPoint) && (j > 0) && (ndbord[i + 1][j - 1] == 1)) ||
+ ((i > 0) && (j < maxPoint) && (ndbord[i - 1][j + 1] == 1)) ||
+ ((i < maxPoint) && (j < maxPoint) &&
+ (ndbord[i + 1][j + 1] == 1))) &&
+ (((i > 0) && (claim[i - 1][j] < 0)) ||
+ ((i < maxPoint) && (claim[i + 1][j] < 0)) ||
+ ((j > 0) && (claim[i][j - 1] < 0)) ||
+ ((j < maxPoint) && (claim[i][j + 1] < 0))))
+ {
+ na = 0;
+ if ((i > 0) && (ndbord[i - 1][j] != 0))
+ na = na + 1;
+ if ((i < maxPoint) && (ndbord[i + 1][j] != 0))
+ na = na + 1;
+ if ((j > 0) && (ndbord[i][j - 1] != 0))
+ na = na + 1;
+ if ((j < maxPoint) && (ndbord[i][j + 1] != 0))
+ na = na + 1;
+ if (na < 3)
+ if (safeMove(i, j))
+ {
+ infl = claim[i][j];
+ *x = i;
+ *y = j;
+ }
+ }
+ if (*x != iNil) return TRUE;
+ return FALSE;
+ } /* pushWall */
+
+
+ /*
+ reduces the liberty count of one of his groups
+ */
+short reduceHisLiberties(x, y)
+short *x, *y;
+ { /* reduceHisLiberties */
+ short i, j;
+ playReason = "reduceHisLiberties";
+ sortLibs();
+ for (i = 1; i <= maxGroupID; i++)
+ if ((! gList[sGlist[i]].isLive) &&
+ (gList[sGlist[i]].libC > 2) &&
+ (ndbord[gList[sGlist[i]].lx][gList[sGlist[i]].ly] == -1))
+ {
+ spanGroup(gList[sGlist[i]].lx, gList[sGlist[i]].ly, &pList);
+ for (j = 1; j <= pList.indx; j++)
+ if (legal[pList.p[j].px][pList.p[j].py] &&
+ (connectMap[pList.p[j].px][pList.p[j].py] > 0))
+ if (safeMove(pList.p[j].px, pList.p[j].py))
+ {
+ *x = pList.p[j].px;
+ *y = pList.p[j].py;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } /* reduceHisLiberties */
+
+
+ /*
+ connects a group to the edge
+ */
+short dropToEdge2(x, y)
+short *x, *y;
+ { /* dropToEdge2 */
+ short i;
+ playReason = "dropToEdge2";
+ for (i = 1; i <= maxPoint - 1; i++)
+ {
+ if (legal[i][0])
+ {
+ if ((ndbord[i][1] == 1) &&
+ ((ndbord[i - 1][0] < 1) ||
+ (groupIDs[i - 1][0] != groupIDs[i][1])) &&
+ ((ndbord[i + 1][0] < 1) ||
+ (groupIDs[i + 1][0] != groupIDs[i][1])) &&
+ ((ndbord[i - 1][1] == -1) ||
+ (ndbord[i + 1][1] == -1)))
+ {
+ *x = i;
+ *y = 0;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[0][i])
+ {
+ if ((ndbord[1][i] == 1) &&
+ ((ndbord[0][i - 1] < 1) ||
+ (groupIDs[0][i - 1] != groupIDs[1][i])) &&
+ ((ndbord[0][i + 1] < 1) ||
+ (groupIDs[0][i + 1] != groupIDs[1][i])) &&
+ ((ndbord[1][i - 1] == -1) ||
+ (ndbord[1][i + 1] == -1)))
+ {
+ *x = 0;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[i][maxPoint])
+ {
+ if ((ndbord[i][maxPoint - 1] == 1) &&
+ ((ndbord[i - 1][maxPoint] < 1) ||
+ (groupIDs[i - 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
+ ((ndbord[i + 1][maxPoint] < 1) ||
+ (groupIDs[i + 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
+ ((ndbord[i - 1][maxPoint - 1] == -1) ||
+ (ndbord[i + 1][maxPoint - 1] == -1)))
+ {
+ *x = i;
+ *y = maxPoint;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ if (legal[maxPoint][i])
+ {
+ if ((ndbord[maxPoint - 1][i] == 1) &&
+ ((ndbord[maxPoint][i - 1] < 1) ||
+ (groupIDs[maxPoint][i - 1] != groupIDs[maxPoint - 1][i])) &&
+ ((ndbord[maxPoint][i + 1] < 1) ||
+ (groupIDs[maxPoint][i + 1] != groupIDs[maxPoint - 1][i])) &&
+ ((ndbord[maxPoint - 1][i - 1] == -1) ||
+ (ndbord[maxPoint - 1][i + 1] == -1)))
+ {
+ *x = maxPoint;
+ *y = i;
+ if (safeMove(*x, *y))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ } /* dropToEdge2 */
+
diff --git a/noncore/games/go/goplayutils.c b/noncore/games/go/goplayutils.c
new file mode 100644
index 0000000..9e2ce4c
--- a/dev/null
+++ b/noncore/games/go/goplayutils.c
@@ -0,0 +1,1317 @@
+/* The go player utilities */
+/* Ported from Pascal to C by Todd R. Johnson */
+/* From the original Pascal file:
+Copyright (c) 1983 by Three Rivers Computer Corp.
+
+Written: January 17, 1983 by Stoney Ballard
+*/
+
+#include "goplayutils.h"
+#include "amigo.h"
+#include "go.h"
+
+extern struct bRec goboard[19][19];
+
+intBoard claim, extra, bord, ndbord, sGroups, threatBord,
+ groupIDs, connectMap, protPoints;
+boolBoard groupSeen, legal;
+short maxGroupID;
+pointList pList, pList1, plist2, plist3, pPlist;
+intList nlcGroup, aList;
+sgRec sList[401];
+groupRec gList[maxGroup];
+short killFlag,
+ numCapt,
+ utilPlayLevel,
+ treeLibLim;
+sType mySType;
+short showTrees;
+short sGlist[maxGroup+1];
+short depthLimit;
+intBoard markBoard;
+short marker;
+
+short adjInAtari, adj2Libs,
+ intersectNum, spanNum, libMark;
+playRec playStack[1025];
+short playMark,
+ newGID,
+ tryLevel,
+ grpMark,
+ gMap[maxGroup];
+short dbStop, inGenState;
+
+ pause()
+{ /* pause */
+/* if (dbStop and ! inGenState)
+ {
+ while ! tabswitch do;
+ repeat
+ if (tabYellow)
+ dbStop = false;
+ until ! tabswitch;
+ } */
+} /* pause */
+
+sstone(w, x, y, numb)
+short w, x, y, numb;
+{ /* sstone */
+ if (w == 1)
+ placestone(mySType, x, y);
+ else if (mySType == WHITE)
+ placestone(BLACK, x, y);
+ else
+ placestone(WHITE, x, y);
+} /* sstone */
+
+rstone(x, y)
+short x, y;
+{ /* rstone */
+ removestone(x, y);
+} /* rstone */
+
+initBoolBoard(bb)
+boolBoard bb;
+{ /* initBoolBoard */
+ short i, j;
+#ifdef DEBUG
+ printf( "initBoolBoard\n" );
+#endif
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ bb[i][j] = FALSE;
+} /* initBoolBoard */
+
+sortLibs()
+{ /* sortLibs */
+ short i, j, t;
+#ifdef DEBUG
+ printf( "sortLibs\n" );
+#endif
+ for (i = 1; i <= maxGroupID; i++)
+ sGlist[i] = i;
+ for (i = 1; i < maxGroupID; i++)
+ for (j = i + 1; j <= maxGroupID; j++)
+ if (gList[sGlist[i]].libC > gList[sGlist[j]].libC)
+ {
+ t = sGlist[i];
+ sGlist[i] = sGlist[j];
+ sGlist[j] = t;
+ }
+} /* sortLibs */
+
+spanGroupspan(x, y, libs, lookFor)
+short x, y, lookFor;
+pointList *libs;
+ { /* span */
+ markBoard[x][y] = marker;
+ if (bord[x][y] == 0)
+ {
+ libs->indx = libs->indx + 1;
+ libs->p[libs->indx].px = x;
+ libs->p[libs->indx].py = y;
+ }
+ else if (bord[x][y] == lookFor)
+ {
+ groupSeen[x][y] = TRUE;
+ if ((x > 0) && (markBoard[x - 1][y] != marker))
+ spanGroupspan(x - 1, y, libs, lookFor);
+ if ((y > 0) && (markBoard[x][y - 1] != marker))
+ spanGroupspan(x, y - 1, libs, lookFor);
+ if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
+ spanGroupspan(x + 1, y, libs, lookFor);
+ if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
+ spanGroupspan(x, y + 1, libs, lookFor);
+ }
+ else if (gList[gMap[groupIDs[x][y]]].libC == 1)
+ adjInAtari = TRUE;
+ else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
+ (! gList[gMap[groupIDs[x][y]]].isLive))
+ adj2Libs = TRUE;
+ } /* span */
+
+spanGroup(x, y, libs)
+short x, y;
+pointList *libs;
+{ /* spanGroup */
+ short lookFor;
+#ifdef DEBUG
+ printf( "spanGroup\n" );
+#endif
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ adjInAtari = FALSE;
+ adj2Libs = FALSE;
+ lookFor = bord[x][y];
+ libs->indx = 0;
+ spanGroupspan(x, y, libs, lookFor);
+} /* spanGroup */
+
+sSpanGroupspan(x, y, libs, lookFor)
+short x, y, lookFor;
+sPointList *libs;
+ { /* span */
+ markBoard[x][y] = marker;
+ if (bord[x][y] == 0)
+ {
+ libs->indx += 1;
+ if (libs->indx <= maxSPoint)
+ {
+ libs->p[libs->indx].px = x;
+ libs->p[libs->indx].py = y;
+ }
+ }
+ else if (bord[x][y] == lookFor)
+ {
+ groupSeen[x][y] = TRUE;
+ if ((x > 0) && (markBoard[x - 1][y] != marker))
+ sSpanGroupspan(x - 1, y, libs, lookFor);
+ if ((y > 0) && (markBoard[x][y - 1] != marker))
+ sSpanGroupspan(x, y - 1, libs, lookFor);
+ if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
+ sSpanGroupspan(x + 1, y, libs, lookFor);
+ if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
+ sSpanGroupspan(x, y + 1, libs, lookFor);
+ }
+ else if (gList[gMap[groupIDs[x][y]]].libC == 1)
+ adjInAtari = TRUE;
+ else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
+ (! gList[gMap[groupIDs[x][y]]].isLive))
+ adj2Libs = TRUE;
+ } /* span */
+
+sSpanGroup(x, y, libs)
+short x, y;
+sPointList *libs;
+{ /* sSpanGroup */
+ short lookFor;
+#ifdef DEBUG
+ printf( "sSpanGroup\n" );
+#endif
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ adjInAtari = FALSE;
+ adj2Libs = FALSE;
+ lookFor = bord[x][y];
+ libs->indx = 0;
+ sSpanGroupspan(x, y, libs, lookFor);
+} /* sSpanGroup */
+
+LAspan(x, y, me, him, iL)
+short x, y, me, him;
+intList *iL;
+ { /* span */
+#ifdef DEBUG
+ printf( "LAspan\n" );
+#endif
+ markBoard[x][y] = marker;
+ if (bord[x][y] == me)
+ {
+ if ((x > 0) && (markBoard[x - 1][y] != marker))
+ LAspan(x - 1, y, me, him, iL);
+ if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
+ LAspan(x + 1, y, me, him, iL);
+ if ((y > 0) && (markBoard[x][y - 1] != marker))
+ LAspan(x, y - 1, me, him, iL);
+ if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
+ LAspan(x, y + 1, me, him, iL);
+ }
+ else if (bord[x][y] == him)
+ if (gList[gMap[groupIDs[x][y]]].groupMark != grpMark)
+ {
+ gList[gMap[groupIDs[x][y]]].groupMark = grpMark;
+ iL->indx = iL->indx + 1;
+ iL->v[iL->indx] = gMap[groupIDs[x][y]];
+ }
+ } /* span */
+
+listAdjacents(x, y, iL)
+short x, y;
+intList *iL;
+{ /* listAdjacents */
+ short me, him;
+#ifdef DEBUG
+ printf( "listAdjacents\n" );
+#endif
+ grpMark = grpMark + 1;
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ iL->indx = 0;
+ me = bord[x][y];
+ him = -me;
+ LAspan(x, y, me , him, iL);
+} /* listAdjacents */
+
+LDspan(x, y, me, diags)
+short x, y, me;
+sPointList *diags;
+ { /* span */
+#ifdef DEBUG
+ printf( "LDspan\n" );
+#endif
+ markBoard[x][y] = marker;
+ if ((x > 0) && (y > 0) &&
+ (bord[x - 1][y - 1] == 0) &&
+ (bord[x][y - 1] != me) &&
+ (bord[x - 1][y] != me) &&
+ (markBoard[x - 1][y - 1] != marker))
+ {
+ markBoard[x - 1][y - 1] = marker;
+ diags->indx = diags->indx + 1;
+ if (diags->indx <= maxSPoint)
+ {
+ diags->p[diags->indx].px = x - 1;
+ diags->p[diags->indx].py = y - 1;
+ }
+ }
+ if ((x < maxPoint) && (y > 0) &&
+ (bord[x + 1][y - 1] == 0) &&
+ (bord[x][y - 1] != me) &&
+ (bord[x + 1][y] != me) &&
+ (markBoard[x + 1][y - 1] != marker))
+ {
+ markBoard[x + 1][y - 1] = marker;
+ diags->indx = diags->indx + 1;
+ if (diags->indx <= maxSPoint)
+ {
+ diags->p[diags->indx].px = x + 1;
+ diags->p[diags->indx].py = y - 1;
+ }
+ }
+ if ((x > 0) && (y < maxPoint) &&
+ (bord[x - 1][y + 1] == 0) &&
+ (bord[x][y + 1] != me) &&
+ (bord[x - 1][y] != me) &&
+ (markBoard[x - 1][y + 1] != marker))
+ {
+ markBoard[x - 1][y + 1] = marker;
+ diags->indx = diags->indx + 1;
+ if (diags->indx <= maxSPoint)
+ {
+ diags->p[diags->indx].px = x - 1;
+ diags->p[diags->indx].py = y + 1;
+ }
+ }
+ if ((x < maxPoint) && (y < maxPoint) &&
+ (bord[x + 1][y + 1] == 0) &&
+ (bord[x][y + 1] != me) &&
+ (bord[x + 1][y] != me) &&
+ (markBoard[x + 1][y + 1] != marker))
+ {
+ markBoard[x + 1][y + 1] = marker;
+ diags->indx = diags->indx + 1;
+ if (diags->indx <= maxSPoint)
+ {
+ diags->p[diags->indx].px = x + 1;
+ diags->p[diags->indx].py = y + 1;
+ }
+ }
+ if ((x > 0) && (bord[x - 1][y] == me) &&
+ (markBoard[x - 1][y] != marker))
+ LDspan(x - 1, y, me, diags);
+ if ((x < maxPoint) && (bord[x + 1][y] == me) &&
+ (markBoard[x + 1][y] != marker))
+ LDspan(x + 1, y, me, diags);
+ if ((y > 0) && (bord[x][y - 1] == me) &&
+ (markBoard[x][y - 1] != marker))
+ LDspan(x, y - 1, me, diags);
+ if ((y < maxPoint) && (bord[x][y + 1] == me) &&
+ (markBoard[x][y + 1] != marker))
+ LDspan(x, y + 1, me , diags);
+} /* span */
+
+listDiags(x, y, diags)
+short x, y;
+sPointList *diags;
+{ /* listDiags */
+ short me;
+#ifdef DEBUG
+ printf( "listDiags\n" );
+#endif
+ me = bord[x][y];
+ diags->indx = 0;
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ LDspan(x, y, me, diags);
+} /* listDiags */
+
+intersectPlist(p1, p2, pr)
+pointList *p1, *p2, *pr;
+{ /* intersectPlist */
+ short i, j, k;
+#ifdef DEBUG
+ printf( "intersectPlist\n" );
+#endif
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ pr->indx = 0;
+ for (i = 1; i <= p1->indx; i++)
+ markBoard[p1->p[i].px][p1->p[i].py] = marker;
+ j = 0;
+ for (i = 1; i <= p2->indx; i++)
+ if (markBoard[p2->p[i].px][p2->p[i].py] == marker)
+ {
+ j = j + 1;
+ pr->p[j] = p2->p[i];
+ }
+ pr->indx = j;
+} /* intersectPlist */
+
+initArray(ary)
+intBoard ary;
+{ /* initArray */
+ short i, j;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ ary[i][j] = 0;
+} /* initArray */
+
+initState()
+{ /* initState */
+ short i, j;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ {
+ extra[i][j] = 0;
+ claim[i][j] = 0;
+ groupIDs[i][j] = 0;
+ connectMap[i][j] = 0;
+ protPoints[i][j] = 0;
+ }
+} /* initState */
+
+copyArray( dest, src )
+intBoard dest, src;
+{
+ short x, y;
+ for (y = 0; y <= maxPoint; y++)
+ for (x = 0; x <= maxPoint; x++)
+ dest[x][y] = src[x][y];
+}
+
+/*
+ generates a one-point spread in the force field array (claim)
+
+ the spread from a single point after four calls is:
+
+ 1
+ 2 2 2
+ 2 4 6 4 2
+ 2 4 8 10 8 4 2
+ 1 2 6 10 62 10 6 2 1
+ 2 4 8 10 8 4 2
+ 2 4 6 4 2
+ 2 2 2
+ 1
+
+*/
+stake()
+{
+ short x, y;
+ initArray( extra );
+ for (y = 0; y <= maxPoint; y++)
+ for (x = 0; x <= maxPoint; x++)
+ {
+ extra[x][y] = extra[x][y] + claim[x][y];
+ if (claim[x][y] > 0)
+ {
+ if (x > 0) extra[x-1][y] += 1;
+ if (y > 0) extra[x][y-1] += 1;
+ if (x < maxPoint) extra[x+1][y] += 1;
+ if (y < maxPoint) extra[x][y+1] += 1;
+ }
+ else if (claim[x][y] < 0)
+ {
+ if (x > 0) extra[x-1][y] -= 1;
+ if (y > 0) extra[x][y-1] -= 1;
+ if (x < maxPoint) extra[x+1][y] -= 1;
+ if (y < maxPoint) extra[x][y+1] -= 1;
+ }
+ }
+ copyArray( claim, extra );
+} /* stake */
+
+/*
+ sets up claim from the current board position
+*/
+spread()
+{
+ short x, y;
+ for (y = 0; y <= maxPoint; y++)
+ for (x = 0; x <= maxPoint; x++)
+ claim[x][y] = ndbord[x][y] * 50;
+ stake();
+ stake();
+ stake();
+ stake();
+} /* spread */
+
+/*
+ gList is initialized with the size, loc, and libCount of each group
+ groupIDs contains the serial numbers of the groups.
+*/
+Resspan(x, y, gID, gSize, libCount, who)
+short x, y, gID, *gSize, *libCount, who;
+ { /* span */
+ if ((bord[x][y] == 0) &&
+ (markBoard[x][y] != marker)) /* a liberty */
+ {
+ markBoard[x][y] = marker;
+ *libCount = *libCount + 1;
+ }
+ else if ((bord[x][y] == who) &&
+ (groupIDs[x][y] == 0))
+ {
+ groupIDs[x][y] = gID;
+ *gSize = *gSize + 1;
+ if (x > 0)
+ Resspan(x - 1, y, gID, gSize, libCount, who);
+ if (x < maxPoint)
+ Resspan(x + 1, y, gID, gSize, libCount, who);
+ if (y > 0)
+ Resspan(x, y - 1, gID, gSize, libCount, who);
+ if (y < maxPoint)
+ Resspan(x, y + 1, gID, gSize, libCount, who);
+ }
+ } /* span */
+
+respreicen()
+{ /* respreicen */
+ short i, j, gID, libCount, gSize, who;
+ gID = 0;
+#ifdef DEBUG
+ printf( "respreicen\n" );
+#endif
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ groupIDs[i][j] = 0;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if ((bord[i][j] != 0) && /* a stone there */
+ (groupIDs[i][j] == 0)) /* not seen yet */
+ {
+ marker = marker + 1;
+ if (marker == 0)
+ {
+ initArray(markBoard);
+ marker = 1;
+ }
+ gID = gID + 1;
+ libCount = 0;
+ gSize = 0;
+ who = bord[i][j];
+ Resspan(i, j, gID, &gSize, &libCount, who); /* span the group, collecting info */
+ gList[gID].groupMark = 0;
+ gList[gID].atLevel = 0;
+ gList[gID].isLive = FALSE; /* we don't know yet */
+ gList[gID].isDead = FALSE;
+ gList[gID].numEyes = -1;
+ gList[gID].size = gSize;
+ gList[gID].libC = libCount;
+ gList[gID].lx = i;
+ gList[gID].ly = j;
+ gMap[gID] = gID; /* set up identity map */
+ }
+ maxGroupID = gID;
+ newGID = gID;
+ grpMark = 0;
+} /* respreicen */
+
+/*
+ play z at [x, y].
+ killFlag is set true if anything is killed.
+*/
+killGroup(x, y, me, him)
+short x, y, me, him;
+ { /* killGroup */
+#ifdef DEBUG
+ printf( "killGroup\n" );
+#endif
+ playMark = playMark + 1;
+ /* record this kill */
+ playStack[playMark].kind = rem;
+ playStack[playMark].uval.rem.who = him;
+ playStack[playMark].uval.rem.xl = x;
+ playStack[playMark].uval.rem.yl = y;
+ playStack[playMark].gID = groupIDs[x][y];
+ playStack[playMark].uval.rem.sNumber = goboard[x][y].mNum;
+ if (showTrees)
+ rstone(x, y);
+ numCapt = numCapt + 1;
+ bord[x][y] = 0;
+ groupIDs[x][y] = 0;
+ if (x > 0)
+ {
+ if (bord[x - 1][y] == me)
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
+ }
+ else if (bord[x - 1][y] == him)
+ killGroup(x - 1, y, me , him);
+ }
+ if (x < maxPoint)
+ {
+ if (bord[x + 1][y] == me)
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
+ }
+ else if (bord[x + 1][y] == him)
+ killGroup(x + 1, y, me, him);
+ }
+ if (y > 0)
+ {
+ if (bord[x][y - 1] == me)
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
+ }
+ else if (bord[x][y - 1] == him)
+ killGroup(x, y - 1, me, him);
+ }
+ if (y < maxPoint)
+ {
+ if (bord[x][y + 1] == me)
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
+ }
+ else if (bord[x][y + 1] == him)
+ killGroup(x, y + 1, me, him);
+ }
+ } /* killGroup */
+
+mergeGroup(sGID, myGID)
+short sGID, myGID;
+ { /* mergeGroup */
+ short i;
+#ifdef DEBUG
+ printf( "mergeGroup\n" );
+#endif
+ for (i = 1; i <= newGID; i++)
+ if (gMap[i] == sGID)
+ {
+ playMark = playMark + 1;
+ playStack[playMark].kind = reMap;
+ playStack[playMark].gID = i;
+ playStack[playMark].uval.reMap.oldGID = sGID;
+ gMap[i] = myGID;
+ }
+ } /* mergeGroup */
+
+tryPlay(x, y, z)
+short x, y, z;
+{ /* plei */
+ short i, me, him, myGID;
+ short isNew;
+#ifdef DEBUG
+ printf( "tryPlay\n" );
+#endif
+ me = z;
+ him = -me;
+ killFlag = FALSE; /* set true if something is killed */
+ numCapt = 0;
+ tryLevel = tryLevel + 1;
+ isNew = FALSE;
+ bord[x][y] = z; /* play the stone */
+ if ((x > 0) && (bord[x - 1][y] == me)) /* connect to adjacent group */
+ myGID = gMap[groupIDs[x - 1][y]];
+ else if ((x < maxPoint) && (bord[x + 1][y] == me))
+ myGID = gMap[groupIDs[x + 1][y]];
+ else if ((y > 0) && (bord[x][y - 1] == me))
+ myGID = gMap[groupIDs[x][y - 1]];
+ else if ((y < maxPoint) && (bord[x][y + 1] == me))
+ myGID = gMap[groupIDs[x][y + 1]];
+ else /* nobody to connect to */
+ {
+ newGID = newGID + 1;
+ isNew = TRUE;
+ myGID = newGID;
+ gList[myGID].groupMark = 0;
+ gList[myGID].atLevel = tryLevel;
+ gList[myGID].isLive = FALSE;
+ gList[myGID].numEyes = -1;
+ gList[myGID].size = -1;
+ gList[myGID].lx = x;
+ gList[myGID].ly = y;
+ gMap[myGID] = myGID;
+ }
+ groupIDs[x][y] = myGID;
+ playMark = playMark + 1;
+ /* record this move */
+ playStack[playMark].kind = add;
+ playStack[playMark].uval.add.who = me;
+ playStack[playMark].uval.add.xl = x;
+ playStack[playMark].uval.add.yl = y;
+ playStack[playMark].gID = myGID;
+ playStack[playMark].uval.add.sNumber = 0;
+ if (isNew)
+ playStack[playMark].uval.add.nextGID = newGID - 1;
+ else
+ playStack[playMark].uval.add.nextGID = newGID;
+ if (showTrees)
+ sstone(me, x, y, 0);
+ /* merge adjacent groups */
+ if ((x > 0) && (bord[x - 1][y] == me) &&
+ (gMap[groupIDs[x - 1][y]] != myGID))
+ mergeGroup(gMap[groupIDs[x - 1][y]], myGID);
+ if ((x < maxPoint) && (bord[x + 1][y] == me) &&
+ (gMap[groupIDs[x + 1][y]] != myGID))
+ mergeGroup(gMap[groupIDs[x + 1][y]], myGID);
+ if ((y > 0) && (bord[x][y - 1] == me) &&
+ (gMap[groupIDs[x][y - 1]] != myGID))
+ mergeGroup(gMap[groupIDs[x][y - 1]], myGID);
+ if ((y < maxPoint) && (bord[x][y + 1] == me) &&
+ (gMap[groupIDs[x][y + 1]] != myGID))
+ mergeGroup(gMap[groupIDs[x][y + 1]], myGID);
+ /* kill opposing groups, listing affected groups */
+ nlcGroup.indx = 1;
+ nlcGroup.v[1] = myGID; /* init list to include me */
+ if ((x > 0) && (bord[x - 1][y] == him) &&
+ (gList[gMap[groupIDs[x - 1][y]]].libC == 1))
+ {
+ killFlag = TRUE;
+ killGroup(x - 1, y, me, him);
+ }
+ if ((x < maxPoint) && (bord[x + 1][y] == him) &&
+ (gList[gMap[groupIDs[x + 1][y]]].libC == 1))
+ {
+ killFlag = TRUE;
+ killGroup(x + 1, y, me, him);
+ }
+ if ((y > 0) && (bord[x][y - 1] == him) &&
+ (gList[gMap[groupIDs[x][y - 1]]].libC == 1))
+ {
+ killFlag = TRUE;
+ killGroup(x, y - 1, me, him);
+ }
+ if ((y < maxPoint) && (bord[x][y + 1] == him) &&
+ (gList[gMap[groupIDs[x][y + 1]]].libC == 1))
+ {
+ killFlag = TRUE;
+ killGroup(x, y + 1, me, him);
+ }
+ /* list groups adjacent to me */
+ if ((x > 0) && (bord[x - 1][y] == him))
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
+ }
+ if ((x < maxPoint) && (bord[x + 1][y] == him))
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
+ }
+ if ((y > 0) && (bord[x][y - 1] == him))
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
+ }
+ if ((y < maxPoint) && (bord[x][y + 1] == him))
+ {
+ nlcGroup.indx = nlcGroup.indx + 1;
+ nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
+ }
+ /* fix liberty count for affected groups */
+ grpMark = grpMark + 1;
+ for (i = 1; i <= nlcGroup.indx; i++)
+ if (gList[nlcGroup.v[i]].groupMark != grpMark)
+ {
+ if (gList[nlcGroup.v[i]].atLevel != tryLevel)
+ {
+ playMark = playMark + 1;
+ playStack[playMark].kind = chLib;
+ playStack[playMark].gID = nlcGroup.v[i];
+ playStack[playMark].uval.chLib.oldLevel =
+ gList[nlcGroup.v[i]].atLevel;
+ playStack[playMark].uval.chLib.oldLC =
+ gList[nlcGroup.v[i]].libC;
+ }
+ gList[nlcGroup.v[i]].groupMark = grpMark;
+ gList[nlcGroup.v[i]].atLevel = tryLevel;
+ spanGroup(gList[nlcGroup.v[i]].lx, gList[nlcGroup.v[i]].ly, &pPlist);
+ gList[nlcGroup.v[i]].libC = pPlist.indx;
+ }
+} /* plei */
+
+saveState()
+{ /* saveState */
+ playMark = 0;
+ tryLevel = 0;
+ newGID = maxGroupID;
+} /* saveState */
+
+/*
+ undoes a move sequence back to uMark
+*/
+undoTo(uMark)
+short uMark;
+{ /* undoTo */
+ short i, xl, yl;
+#ifdef DEBUG
+ printf( "undoTo\n" );
+#endif
+ for (i = playMark; i >= uMark + 1; i--)
+ if (playStack[i].kind == rem)
+ {
+ xl = playStack[i].uval.rem.xl;
+ yl = playStack[i].uval.rem.yl;
+ bord[xl][yl] = playStack[i].uval.rem.who;
+ groupIDs[xl][yl] = playStack[i].gID;
+ if (showTrees)
+ sstone(playStack[i].uval.rem.who, xl, yl,
+ playStack[i].uval.rem.sNumber);
+ }
+ else if (playStack[i].kind == add)
+ {
+ xl = playStack[i].uval.add.xl;
+ yl = playStack[i].uval.add.yl;
+ bord[xl][yl] = 0;
+ groupIDs[xl][yl] = 0;
+ tryLevel = tryLevel - 1;
+ newGID = playStack[i].uval.add.nextGID;
+ if (showTrees)
+ rstone(xl, yl);
+ }
+ else if (playStack[i].kind == reMap)
+ gMap[playStack[i].gID] = playStack[i].uval.reMap.oldGID;
+ else /* change libs of group - gID is pre-mapped */
+ {
+ gList[playStack[i].gID].libC = playStack[i].uval.chLib.oldLC;
+ gList[playStack[i].gID].atLevel = playStack[i].uval.chLib.oldLevel;
+ }
+ playMark = uMark;
+} /* undoTo */
+
+/*
+ restores the state of the world after trying a move sequence
+*/
+restoreState()
+{ /* restoreState */
+#ifdef DEBUG
+ printf( "restoreState\n" );
+#endif
+ if (playMark > 0)
+ {
+ undoTo(0);
+ playMark = 0;
+ tryLevel = 0;
+ }
+} /* restoreState */
+
+/* exception bpt; */
+
+
+/*
+ returns true if (the group (at gx, gy) is saveable.
+ if so, returns the point to play at in savex, savey
+*/
+short saveable(gx, gy, savex, savey)
+short gx, gy, *savex, *savey;
+{ /* saveable */
+ short me, him, gx1, gx2, i, j, smark, mark2, tl, result;
+ char sChar;
+ sPointList dList;
+ point tp;
+ short libList[maxSPoint+1];
+#ifdef DEBUG
+ printf( "saveable\n" );
+#endif
+ dbStop = TRUE;
+ me = bord[gx][gy];
+ him = -me;
+ if (me == 1)
+ sChar = '|';
+ else
+ sChar = '>';
+/* write(sChar); */
+ spanGroup(gx, gy, &plist3); /* find my liberties */
+ if (adjInAtari) /* one of my options is to kill */
+ {
+ listAdjacents(gx, gy, &aList);
+ for (i = 1; i <= aList.indx; i++)
+ if (gList[aList.v[i]].libC == 1)
+ {
+ spanGroup(gList[aList.v[i]].lx, gList[aList.v[i]].ly,
+ &pList1); /* find it's liberty */
+ plist3.indx = plist3.indx + 1;
+ plist3.p[plist3.indx].px = pList1.p[1].px;
+ plist3.p[plist3.indx].py = pList1.p[1].py;
+ }
+ }
+ for (i = 1; i <= maxSPoint; i++)
+ libList[i] = -1;
+ if ((utilPlayLevel > 4) &&
+ (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* account for diags */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ i = plist3.indx;
+ while ((j < dList.indx) &&
+ (i < maxSPoint))
+ {
+ j = j + 1;
+ i = i + 1;
+ libList[i] = 100;
+ plist3.p[i].px = dList.p[j].px;
+ plist3.p[i].py = dList.p[j].py;
+ }
+ plist3.indx = i;
+ }
+ if (plist3.indx > 1) /* sort by decreasing lib count */
+ {
+ for (i = 1; i <= plist3.indx; i++)
+ if (libList[i] != 100)
+ {
+ mark2 = playMark;
+ tryPlay(plist3.p[i].px, plist3.p[i].py, me);
+ libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
+ if (libList[i] > treeLibLim) /* i'm safe */
+ {
+ *savex = plist3.p[i].px;
+ *savey = plist3.p[i].py;
+ result = TRUE;
+ goto one;
+ }
+ undoTo(mark2);
+ }
+ for (i = 1; i <= plist3.indx - 1; i++)
+ for (j = i + 1; j <= plist3.indx; j++)
+ if (libList[i] < libList[j])
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = plist3.p[i];
+ plist3.p[i] = plist3.p[j];
+ plist3.p[j] = tp;
+ }
+ }
+ for (i = 1; i <= plist3.indx; i++)
+ {
+ *savex = plist3.p[i].px;
+ *savey = plist3.p[i].py;
+ if (legal[*savex][*savey])
+ {
+ smark = playMark;
+ tryPlay(*savex, *savey, me);
+ pause();
+ if (gList[gMap[groupIDs[*savex][*savey]]].libC > 1)
+ if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
+ {
+ restoreState();
+/* sClearChar(sChar, rXor); */
+ return TRUE;
+ }
+ else if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
+ if (! killable(gx, gy, &gx1, &gx2))
+ {
+ restoreState();
+/* sClearChar(sChar, rXor); */
+ return TRUE;
+ }
+ undoTo(smark);
+ }
+ }
+ result = FALSE;
+one:
+ restoreState();
+/* sClearChar(sChar, rXor); */
+ return result;
+} /* saveable */
+
+/*
+ marks unsavable groups as dead
+*/
+markDead()
+{ /* markDead */
+ short i, j, gx, gy, result;
+#ifdef DEBUG
+ printf( "markDead\n" );
+#endif
+ for (i = 1; i <= maxGroupID; i++)
+ if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
+ result = ! saveable(gList[i].lx, gList[i].ly, &gx, &gy);
+ else
+ result = FALSE;
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if (bord[i][j] == 0)
+ ndbord[i][j] = 0;
+ else if (gList[groupIDs[i][j]].isDead)
+ ndbord[i][j] = 0;
+ else
+ ndbord[i][j] = bord[i][j];
+} /* markDead */
+
+/*
+ marks groups with two eyes as live
+*/
+MLspan(x, y, saw1, sawm1, size, sMark)
+short x, y, *saw1, *sawm1, *size, sMark;
+ { /* span */
+ if (ndbord[x][y] == 1)
+ *saw1 = TRUE;
+ else if (ndbord[x][y] == -1)
+ *sawm1 = TRUE;
+ else if (sGroups[x][y] == 0)
+ {
+ sGroups[x][y] = sMark;
+ *size = *size + 1;
+ if (x > 0)
+ MLspan(x - 1, y, saw1, sawm1, size, sMark);
+ if (x < maxPoint)
+ MLspan(x + 1, y, saw1, sawm1, size, sMark);
+ if (y > 0)
+ MLspan(x, y - 1, saw1, sawm1, size, sMark);
+ if (y < maxPoint)
+ MLspan(x, y + 1, saw1, sawm1, size, sMark);
+ }
+ } /* span */
+
+short CLspan(x, y, numEyes, who)
+short x, y, *numEyes, who;
+ { /* span */
+ markBoard[x][y] = marker;
+ if (ndbord[x][y] == 0)
+ {
+ if ((sList[sGroups[x][y]].sm != marker) &&
+ (sList[sGroups[x][y]].w == who))
+ {
+ sList[sGroups[x][y]].sm = marker;
+ if (sList[sGroups[x][y]].s > 6)
+ return TRUE;
+ *numEyes = *numEyes + 1;
+ if (*numEyes > 1)
+ return TRUE;
+ }
+ }
+ else if (bord[x][y] == who)
+ {
+ if ((x > 0) &&
+ (markBoard[x - 1][y] != marker))
+ if (CLspan(x - 1, y, numEyes, who)) return TRUE;
+ if ((x < maxPoint) &&
+ (markBoard[x + 1][y] != marker))
+ if (CLspan(x + 1, y, numEyes, who)) return TRUE;
+ if ((y > 0) &&
+ (markBoard[x][y - 1] != marker))
+ if (CLspan(x, y - 1, numEyes, who)) return TRUE;
+ if ((y < maxPoint) &&
+ (markBoard[x][y + 1] != marker))
+ if (CLspan(x, y + 1, numEyes, who)) return TRUE;
+ }
+ return FALSE;
+ } /* span */
+
+short checkLive(x, y)
+short x, y;
+ { /* checkLive */
+ short numEyes, who;
+#ifdef DEBUG
+ printf( "checkLive\n" );
+#endif
+ numEyes = 0;
+ who = bord[x][y];
+ marker = marker + 1;
+ return CLspan(x, y, &numEyes, who);
+ } /* checkLive */
+
+markLive()
+{ /* markLive */
+ short i, j, size, sMark = 0;
+ short saw1, sawm1;
+#ifdef DEBUG
+ printf( "markLive\n" );
+#endif
+ initArray(sGroups);
+ for (i = 0; i <= maxPoint; i++)
+ for (j = 0; j <= maxPoint; j++)
+ if ((sGroups[i][j] == 0) &&
+ (ndbord[i][j] == 0))
+ {
+ size = 0;
+ sMark = sMark + 1;
+ sawm1 = FALSE;
+ saw1 = FALSE;
+ MLspan(i, j, &saw1, &sawm1, &size, sMark);
+ sList[sMark].s = size;
+ sList[sMark].sm = 0;
+ if (sawm1)
+ if (saw1)
+ sList[sMark].w = 0;
+ else
+ sList[sMark].w = -1;
+ else if (saw1)
+ sList[sMark].w = 1;
+ else
+ sList[sMark].w = 0;
+ }
+ for (i = 1; i <= maxGroupID; i++)
+ if (! gList[i].isDead)
+ gList[i].isLive = checkLive(gList[i].lx, gList[i].ly);
+} /* markLive */
+
+/*
+ generates the connection map and the protected point map.
+*/
+genConnects()
+{ /* genConnects */
+ short x, y, numStones;
+#ifdef DEBUG
+ printf( "genConnects\n" );
+#endif
+ for (x = 0; x <= maxPoint; x++)
+ for (y = 0; y <= maxPoint; y++)
+ {
+ connectMap[x][y] = 0;
+ protPoints[x][y] = 0;
+ }
+ for (x = 0; x <= maxPoint; x++)
+ for (y = 0; y <= maxPoint; y++)
+ if (bord[x][y] == 1) /* map connections to this stone */
+ {
+ if (x > 0) /* direct connection */
+ connectMap[x - 1][y] += 1;
+ if (x < maxPoint)
+ connectMap[x + 1][y] += 1;
+ if (y > 0)
+ connectMap[x][y - 1] += 1;
+ if (y < maxPoint)
+ connectMap[x][y + 1] += 1;
+ if ((x > 0) && (y > 0) && /* diagonal connection */
+ (bord[x - 1][y] == 0) && (bord[x][y - 1] == 0))
+ connectMap[x - 1][y - 1] += 1;
+ if ((x < maxPoint) && (y > 0) &&
+ (bord[x + 1][y] == 0) && (bord[x][y - 1] == 0))
+ connectMap[x + 1][y - 1] += 1;
+ if ((x < maxPoint) && (y < maxPoint) &&
+ (bord[x + 1][y] == 0) && (bord[x][y + 1] == 0))
+ connectMap[x + 1][y + 1] += 1;
+ if ((x > 0) && (y < maxPoint) &&
+ (bord[x - 1][y] == 0) && (bord[x][y + 1] == 0))
+ connectMap[x - 1][y + 1] += 1;
+ if ((x > 1) && (claim[x - 1][y] > 3)) /* one point jump */
+ connectMap[x - 2][y] += 1;
+ if ((x < (maxPoint - 1)) && (claim[x + 1][y] > 3))
+ connectMap[x + 2][y] += 1;
+ if ((y > 1) && (claim[x][y - 1] > 3))
+ connectMap[x][y - 2] += 1;
+ if ((y < (maxPoint - 1)) && (claim[x][y + 1] > 3))
+ connectMap[x][y + 2] += 1;
+ if ((x > 1) && (y > 0) && /* knight's move */
+ (claim[x - 1][y] > 3) && (claim[x - 1][y - 1] > 3))
+ connectMap[x - 2][y - 1] += 1;
+ if ((x > 0) && (y > 1) &&
+ (claim[x][y - 1] > 3) && (claim[x - 1][y - 1] > 3))
+ connectMap[x - 1][y - 2] += 1;
+ if ((x < (maxPoint - 1)) && (y > 0) &&
+ (claim[x + 1][y] > 3) && (claim[x + 1][y - 1] > 3))
+ connectMap[x + 2][y - 1] += 1;
+ if ((x < maxPoint) && (y > 1) &&
+ (claim[x][y - 1] > 3) && (claim[x + 1][y - 1] > 3))
+ connectMap[x + 1][y - 2] += 1;
+ if ((x > 1) && (y < maxPoint) &&
+ (claim[x - 1][y] > 3) && (claim[x - 1][y + 1] > 3))
+ connectMap[x - 2][y + 1] += 1;
+ if ((x > 0) && (y < (maxPoint - 1)) &&
+ (claim[x][y + 1] > 3) && (claim[x - 1][y + 1] > 3))
+ connectMap[x - 1][y + 2] += 1;
+ if ((x < (maxPoint - 1)) && (y < maxPoint) &&
+ (claim[x + 1][y] > 3) && (claim[x + 1][y + 1] > 3))
+ connectMap[x + 2][y + 1] += 1;
+ if ((x < maxPoint) && (y < (maxPoint - 1)) &&
+ (claim[x][y + 1] > 3) && (claim[x + 1][y + 1] > 3))
+ connectMap[x + 1][y + 2] += 1;
+ }
+ else if (bord[x][y] == 0) /* see if protected point */
+ {
+ numStones = 0;
+ if (x == 0)
+ numStones = numStones + 1;
+ if (y == 0)
+ numStones = numStones + 1;
+ if (x == maxPoint)
+ numStones = numStones + 1;
+ if (y == maxPoint)
+ numStones = numStones + 1;
+ if ((x > 0) && (bord[x - 1][y] == 1))
+ numStones = numStones + 1;
+ if ((y > 0) && (bord[x][y - 1] == 1))
+ numStones = numStones + 1;
+ if ((x < maxPoint) && (bord[x + 1][y] == 1))
+ numStones = numStones + 1;
+ if ((y < maxPoint) && (bord[x][y + 1] == 1))
+ numStones = numStones + 1;
+ if (numStones == 4)
+ protPoints[x][y] = 1;
+ else if (numStones == 3)
+ {
+ if ((x > 0) &&
+ ((bord[x - 1][y] == 0) ||
+ ((bord[x - 1][y] == -1) &&
+ (gList[groupIDs[x - 1][y]].libC == 1))))
+ protPoints[x][y] = 1;
+ else if ((x < maxPoint) &&
+ ((bord[x + 1][y] == 0) ||
+ ((bord[x + 1][y] == -1) &&
+ (gList[groupIDs[x + 1][y]].libC == 1))))
+ protPoints[x][y] = 1;
+ else if ((y > 0) &&
+ ((bord[x][y - 1] == 0) ||
+ ((bord[x][y - 1] == -1) &&
+ (gList[groupIDs[x][y - 1]].libC == 1))))
+ protPoints[x][y] = 1;
+ else if ((y < maxPoint) &&
+ ((bord[x][y + 1] == 0) ||
+ ((bord[x][y + 1] == -1) &&
+ (gList[groupIDs[x][y + 1]].libC == 1))))
+ protPoints[x][y] = 1;
+ }
+ }
+ for (x = 0; x <= maxPoint; x++)
+ for (y = 0; y <= maxPoint; y++)
+ if (bord[x][y] != 0)
+ {
+ connectMap[x][y] = 0;
+ protPoints[x][y] = 0;
+ }
+} /* genConnects */
+
+/*
+ generates the whole state of the game.
+*/
+genState()
+{ /* genState */
+#ifdef DEBUG
+ printf( "genState\n" );
+#endif
+ inGenState = TRUE;
+ respreicen();
+ markDead();
+ markLive();
+ spread();
+ genConnects();
+#ifdef DEBUG
+/* printBoard( claim, "claim" ); */
+/* printBoard( bord, "bord" ); */
+/* printBoard( ndbord, "ndbord" );
+ printBoard( sGroups, "sGroups" );
+ printBoard( groupIDs, "groupIDs" );
+ printBoard( connectMap, "connectMap" );
+ printBoard( protPoints, "protPoints" ); */
+#endif
+ inGenState = FALSE;
+} /* genState */
+
+/*
+ generates a value for the [x, y] location that appears to get larger
+ for points that are saddle points in the influence graph (klein)
+*/
+short tencen(x, y)
+short x, y;
+{ /* tencen */
+ short a, b, c, d, w, z;
+#ifdef DEBUG
+ printf( "tencen\n" );
+#endif
+ if (claim[x][y] > -1) /* if (he does not influence this area, return 50 */
+ {
+ return 50;
+ }
+ w = claim[x][y]; /* w <= -1 */
+ a = iNil;
+ if (x > 0)
+ if (claim[x - 1][y] > -1) /* if (neighbor is not influenced by him */
+ a = claim[x - 1][y] - w; /* score is sum of his influence on central */
+ b = iNil; /* point and my influence on this neighbor */
+ if (y > 0)
+ if (claim[x][y - 1] > -1)
+ b = claim[x][y - 1] - w;
+ c = iNil;
+ if (x < maxPoint)
+ if (claim[x + 1][y] > -1)
+ c = claim[x + 1][y] - w;
+ d = iNil;
+ if (y < maxPoint)
+ if (claim[x][y + 1] > -1)
+ d = claim[x][y + 1] - w;
+ z = a; /* z = max(a, b, c, d) */
+ if (z != iNil)
+ {
+ if ((b != iNil) &&
+ (b > z))
+ z = b;
+ }
+ else
+ z = b;
+ if (z != iNil)
+ {
+ if ((c != iNil) &&
+ (c > z))
+ z = c;
+ }
+ else
+ z = c;
+ if (z != iNil)
+ {
+ if ((d != iNil) &&
+ (d > z))
+ z = d;
+ }
+ else
+ z = d;
+ if ((z != iNil) &&
+ ((x == 0) ||
+ (y == 0) ||
+ (x == maxPoint) ||
+ (y == maxPoint)))
+ z = z * 2; /* double z if (on the edge of the board ?? */
+ if (z != iNil)
+ return z;
+ else
+ return 50;
+} /* tencen */
+
+initGPUtils()
+{ /* initGPUtils */
+#ifdef DEBUG
+ printf( "initGPUtils\n" );
+#endif
+ initArray(markBoard);
+ initState();
+ marker = 0;
+ playMark = 0;
+ gList[0].isLive = FALSE;
+ gList[0].isDead = FALSE;
+ gList[0].libC = 0;
+ gList[0].size = 0;
+ gList[0].numEyes = 0;
+ gList[0].lx = -1;
+ gList[0].ly = -1;
+ gMap[0] = 0;
+ dbStop = FALSE;
+ inGenState = FALSE;
+} /* initGPUtils */
+
diff --git a/noncore/games/go/goplayutils.h b/noncore/games/go/goplayutils.h
new file mode 100644
index 0000000..11ab658
--- a/dev/null
+++ b/noncore/games/go/goplayutils.h
@@ -0,0 +1,85 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef __goplayutils_h
+#define __goplayutils_h
+
+#define iNil 32767 /* a distinguished value like nil */
+#define maxGroup 512
+#define maxSPoint 16
+#define tryLimit 300
+
+typedef short intBoard[19][19]; /* these were -2 to maxPoint + 2 */
+
+typedef short boolBoard[19][19];
+
+typedef struct
+{
+ short px, py;
+} point;
+
+typedef struct
+{
+ point p[401];
+ short indx;
+} pointList;
+
+typedef struct
+{
+ point p[maxSPoint+1];
+ short indx;
+} sPointList;
+
+typedef struct
+{
+ short indx,
+ v[401];
+} intList;
+
+typedef struct { short w, s, sm; } sgRec;
+
+typedef struct
+{
+ short groupMark,
+ atLevel,
+ isLive,
+ isDead,
+ libC,
+ numEyes,
+ size,
+ lx, ly;
+} groupRec;
+
+typedef enum {rem, add, chLib, reMap} playType;
+
+typedef struct { short who, xl, yl, nextGID, sNumber; } remAddRec;
+typedef struct { short oldLC, oldLevel; } chLibRec;
+typedef struct { short oldGID; } reMapRec;
+typedef struct
+{
+ short gID;
+ playType kind;
+ union {
+ remAddRec rem, add;
+ chLibRec chLib;
+ reMapRec reMap;
+ } uval;
+} playRec;
+
+#endif
diff --git a/noncore/games/go/gowidget.cpp b/noncore/games/go/gowidget.cpp
new file mode 100644
index 0000000..fca9797
--- a/dev/null
+++ b/noncore/games/go/gowidget.cpp
@@ -0,0 +1,449 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "gowidget.h"
+
+#include <qpe/config.h>
+#include <qpe/resource.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpe/qpetoolbar.h>
+#include <qpe/qpemenubar.h>
+#include <qpopupmenu.h>
+#include <qaction.h>
+#include <qapplication.h> //processEvents()
+#include <qlabel.h>
+
+//#include <stdio.h>
+
+#include "amigo.h"
+#include "goplayutils.h"
+
+static const enum bVal computer_color = BLACK;
+
+static int current_handicap = 1;
+
+static QBrush *goBrush;
+//static QImage *newBlackStone;
+//static QImage *blackStone;
+//static QImage *whiteStone;
+static QPixmap *newBlackStone;
+static QPixmap *blackStone;
+static QPixmap *whiteStone;
+
+GoMainWidget::GoMainWidget( QWidget *parent, const char* name) :
+ QMainWindow( parent, name )
+{
+ setToolBarsMovable( FALSE );
+ GoWidget *go = new GoWidget(this);
+
+ setCentralWidget(go);
+ toolbar = new QPEToolBar(this);
+ toolbar->setHorizontalStretchable( TRUE );
+ addToolBar(toolbar);
+
+ QPEMenuBar *mb = new QPEMenuBar( toolbar );
+ mb->setMargin(0);
+ QPopupMenu *file = new QPopupMenu( this );
+
+ QAction *a = new QAction( tr( "New Game" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( newGame() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Pass" ), Resource::loadPixmap( "pass" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( pass() ) );
+ a->addTo( file );
+ a->addTo( toolbar );
+
+
+ a = new QAction( tr( "Resign" ), Resource::loadPixmap( "reset" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), go, SLOT( resign() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Two player option" ), QString::null, 0, this, 0 );
+ a->setToggleAction( TRUE );
+ connect( a, SIGNAL( toggled(bool) ), go, SLOT( setTwoplayer(bool) ) );
+ a->addTo( file );
+
+ mb->insertItem( tr( "Game" ), file );
+
+ QLabel *turnLabel = new QLabel( toolbar );
+ turnLabel->setBackgroundMode( PaletteButton );
+ connect( go, SIGNAL(showTurn(const QPixmap&)),
+ turnLabel, SLOT(setPixmap(const QPixmap&)) );
+
+
+ QLabel * scoreLabel = new QLabel( toolbar );
+ scoreLabel->setBackgroundMode( PaletteButton );
+ connect( go, SIGNAL(showScore(const QString&)),
+ scoreLabel, SLOT(setText(const QString&)) );
+
+ toolbar->setStretchableWidget( scoreLabel );
+
+ go->readConfig();
+}
+
+void GoMainWidget::resizeEvent( QResizeEvent * )
+{
+ //### this won't work because of the text label...
+ /*
+ if ( width() > height() )
+ moveToolBar( toolbar, Left );
+ else
+ moveToolBar( toolbar, Top );
+ */
+}
+
+GoWidget *GoWidget::self = 0;
+
+GoWidget::GoWidget( QWidget *parent, const char* name) :
+ QWidget( parent, name )
+{
+ if ( self )
+ fatal( "Only one Go widget allowed" );
+ self = this;
+ twoplayer = FALSE;
+
+
+ d = bx = by = 1;
+
+ QPixmap pix = Resource::loadPixmap( "pine" );
+ goBrush = new QBrush( black, pix );
+ /*
+ QString fn = Resource::findPixmap("Go-black");
+ blackStone = new QImage( fn );
+ fn = Resource::findPixmap("Go-black-highlight");
+ newBlackStone = new QImage( fn );
+ fn = Resource::findPixmap("Go-white");
+ whiteStone = new QImage( fn );
+ */
+ blackStone = new QPixmap(Resource::loadPixmap( "Go-black" ));
+ whiteStone = new QPixmap(Resource::loadPixmap( "Go-white" ));
+ newBlackStone = new QPixmap(Resource::loadPixmap( "Go-black-highlight" ));
+
+ init();
+}
+
+GoWidget::~GoWidget()
+{
+ writeConfig();
+}
+
+void GoWidget::writeConfig()
+{
+ Config cfg("Go");
+ cfg.setGroup("Game");
+ cfg.writeEntry("TwoPlayer", twoplayer);
+ cfg.writeEntry("CurrentPlayer", currentPlayer);
+ cfg.writeEntry("NPassed", nPassed);
+ QString b;
+ for (int i=0; i<19; i++)
+ for (int j=0; j<19; j++)
+ b += board[i][j] == BLACK ? 'B' : board[i][j] == WHITE ? 'W' : '.';
+ cfg.writeEntry("Board", b);
+ cfg.writeEntry("LastX", lastX);
+ cfg.writeEntry("LastY", lastY);
+ extern int blackPrisoners, whitePrisoners;
+ cfg.writeEntry("BlackPrisoners", blackPrisoners);
+ cfg.writeEntry("WhitePrisoners", whitePrisoners);
+}
+
+void GoWidget::readConfig()
+{
+ init();
+ Config cfg("Go");
+ cfg.setGroup("Game");
+ twoplayer = cfg.readBoolEntry("TwoPlayer");
+ currentPlayer = (bVal)cfg.readNumEntry("CurrentPlayer",1);
+ nPassed = cfg.readNumEntry("NPassed",0);
+ QString b = cfg.readEntry("Board");
+ if ( b.length() == 19*19 )
+ for (int i=0; i<19; i++)
+ for (int j=0; j<19; j++) {
+ QChar ch = b[j+19*i];
+ if ( ch != '.' )
+ GoPlaceStone( ch == 'B' ? BLACK : WHITE, i, j );
+ }
+ lastX = cfg.readNumEntry("LastX");
+ lastY = cfg.readNumEntry("LastY");
+ extern int blackPrisoners, whitePrisoners;
+ blackPrisoners = cfg.readNumEntry("BlackPrisoners",0);
+ whitePrisoners = cfg.readNumEntry("WhitePrisoners",0);
+ reportPrisoners(blackPrisoners,whitePrisoners);
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+}
+
+void GoWidget::resizeEvent( QResizeEvent * )
+{
+ d = QMIN(width(),height())/19;
+ // int r = (d/2-1);
+ bx = (width() - 18*d)/2 ;
+ by = (height() - 18*d)/2 ;
+}
+
+void GoWidget::init()
+{
+ lastX = lastY = newX = newY = -1;
+ nPassed = 0;
+ for ( int i = 0; i < 19; i++ )
+ for ( int j = 0; j < 19; j++ )
+ board[i][j]=-1;
+ gameActive = TRUE;
+ goRestart(current_handicap);
+
+ if ( twoplayer ) {
+ currentPlayer = BLACK;
+ } else {
+ doComputerMove();
+ currentPlayer = WHITE;
+ }
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+}
+
+void GoWidget::paintEvent( QPaintEvent *e )
+{
+ int i,j;
+
+ int r = whiteStone->width()/2;
+
+ QPainter p(this);
+ p.fillRect( bx - d/2, by - d/2, 19*d, 19*d, *goBrush );
+
+ int xMin = QMAX( x2board(e->rect().left()), 0 );
+ int xMax = QMIN( x2board(e->rect().right()), 18 );
+ int yMin = QMAX( y2board(e->rect().top()), 0 );
+ int yMax = QMIN( y2board(e->rect().bottom()), 18 );
+
+ QColor pine( 255, 186, 89 );
+ p.setPen( pine.dark() );
+
+ for ( i = xMin; i < xMax+1 ; i ++ ) {
+ p.drawLine( bx+i*d, by, bx+i*d, by+18*d );
+ }
+ for ( j = yMin; j < yMax+1 ; j ++ ) {
+ p.drawLine( bx, by+j*d, bx+18*d, by+j*d);
+ }
+
+ // dots are at (3,3), (3,9), (3,15) and so on
+ p.setBrush( black );
+ for ( i = 3; i < xMax+1; i+=6 )
+ for ( j = 3; j < yMax+1; j+=6 )
+ p.drawEllipse( bx+i*d-2, by+j*d-2, 5, 5 );
+
+
+ for ( i = xMin; i < xMax+1; i++ )
+ for ( j = yMin; j < yMax+1; j++ ) {
+ if ( board[i][j] == WHITE ||
+ currentPlayer==WHITE && newX == i && newY == j )
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *whiteStone );
+ else if ( i == lastX && j == lastY )
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *newBlackStone );
+ else if ( board[i][j] == BLACK ||
+ currentPlayer==BLACK && newX == i && newY == j)
+ p.drawPixmap( bx+i*d - r, by+j*d - r, *blackStone );
+ }
+}
+
+void GoWidget::doMove( int x, int y )
+{
+
+ if ( !GoPlaceStone( currentPlayer, x, y ) ) {
+ //printf( "Illegal move (%d,%d)\n", x, y );
+ return;
+ }
+ //printf( "you do (%d,%d)\n", x, y );
+ nPassed = 0;
+ if ( twoplayer )
+ currentPlayer = (currentPlayer==WHITE) ? BLACK : WHITE;
+ else
+ doComputerMove();
+
+ emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
+
+}
+
+void GoWidget::pass()
+{
+ if ( !gameActive )
+ return;
+ nPassed++;
+ if ( nPassed >= 2 )
+ endGame();
+ else if ( !twoplayer )
+ doComputerMove();
+}
+
+void GoWidget::resign()
+{
+ if ( gameActive )
+ endGame();
+}
+
+
+void GoWidget::newGame()
+{
+ init();
+ update();
+}
+
+
+void GoWidget::endGame()
+{
+ gameActive = FALSE;
+
+ int w,b;
+ CountUp( &w, &b);
+ QString s = tr("White %1, Black %2. ").arg(w).arg(b);
+ if ( w > b )
+ s += tr("White wins.");
+ else if ( w < b )
+ s += tr("Black wins.");
+ else
+ s += tr("A draw.");
+ emit showScore( s );
+}
+
+void GoWidget::doComputerMove()
+{
+ int ox = lastX;
+ int oy = lastY;
+ lastX = lastY = -1;
+ emit showTurn( *blackStone );
+ refresh( ox, oy);
+ qApp->processEvents();
+ short int x,y;
+ if ( genMove( computer_color, &x, &y ) ) {
+ lastX = x;
+ lastY = y;
+ //printf( "I do (%d,%d)\n", x, y );
+ GoPlaceStone(computer_color,x,y);
+ nPassed = 0;
+ } else {
+ emit showScore( tr("I pass") );
+ nPassed++;
+ if ( nPassed >= 2 )
+ endGame();
+ }
+}
+
+void GoWidget::mousePressEvent( QMouseEvent *me )
+{
+ if ( !gameActive )
+ return;
+ int x = x2board(me->x());
+ int y = y2board(me->y());
+ showStone(x,y,currentPlayer);
+}
+
+void GoWidget::mouseMoveEvent( QMouseEvent *me )
+{
+ if ( !gameActive )
+ return;
+ int x = x2board(me->x());
+ int y = y2board(me->y());
+ if ( x != newX || y != newY )
+ showStone(x,y,currentPlayer);
+}
+
+void GoWidget::showStone( int x, int y, enum bVal c )
+{
+
+ if ( newX > -1 ) {
+ refresh( newX, newY );
+ newY = newX = -1;
+ }
+ if ( x < 0 || x > 18 || y < 0 || y > 18 ) {
+ newX = newY = -1;
+ return;
+ }
+ if ( board[x][y] == -1 && !Suicide( c, x, y ) ) {
+ newX = x;
+ newY = y;
+ refresh(x,y);
+ }
+
+}
+
+void GoWidget::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( gameActive && newX > -1 )
+ doMove( newX, newY );
+ newX = newY = -1;
+}
+
+void GoWidget::refresh( int x, int y )
+{
+ update( bx+d*x-d/2-1, by+d*y-d/2-1, d+2, d+2 );
+}
+
+void GoWidget::removeStone(short x, short y)
+{
+ board[x][y]=-1;
+ refresh( x, y );
+}
+
+void GoWidget::placeStone (enum bVal c, short x, short y )
+{
+ board[x][y]=c;
+ refresh( x, y );
+}
+
+void GoWidget::reportPrisoners( int blackcnt, int whitecnt )
+{
+ QString s = tr( "Prisoners: black %1, white %2" ).arg(blackcnt).arg(whitecnt);
+ emit showScore( s );
+}
+
+void GoWidget::setTwoplayer( bool b )
+{
+ twoplayer = b;
+}
+
+void GoWidget::setHandicap( int h )
+{
+ current_handicap = h;
+}
+
+
+extern "C" {
+
+void removestone(short x, short y)
+{
+ GoWidget::self->removeStone(x,y);
+}
+
+void placestone (enum bVal c, short x, short y )
+{
+ GoWidget::self->placeStone(c,x,y);
+}
+
+void intrMoveReport(enum bVal c ,char *coord ,char *reason )
+{
+ qDebug( "intrMoveReport colour %d, %s %s", c, coord, reason );
+}
+
+void intrPrisonerReport( short blackcnt, short whitecnt )
+{
+ GoWidget::self->reportPrisoners(blackcnt,whitecnt);
+}
+
+}
+
diff --git a/noncore/games/go/gowidget.h b/noncore/games/go/gowidget.h
new file mode 100644
index 0000000..94de2cc
--- a/dev/null
+++ b/noncore/games/go/gowidget.h
@@ -0,0 +1,111 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef GOWIDGET_H
+#define GOWIDGET_H
+
+#include <qmainwindow.h>
+#include "amigo.h"
+
+
+class QToolBar;
+
+class GoMainWidget : public QMainWindow
+{
+ Q_OBJECT
+public:
+ GoMainWidget( QWidget *parent=0, const char* name=0);
+protected:
+ void resizeEvent( QResizeEvent * );
+private:
+ QToolBar *toolbar;
+
+};
+
+
+class QLabel;
+class GoWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ GoWidget( QWidget *parent=0, const char* name=0);
+ ~GoWidget();
+
+ void doMove( int x, int y );
+ void doComputerMove();
+
+ void readConfig();
+ void writeConfig();
+
+public slots:
+ void pass();
+ void resign();
+ void newGame();
+ void setTwoplayer( bool );
+ void setHandicap( int );
+signals:
+ void showScore( const QString& );
+ void showTurn( const QPixmap& );
+
+protected:
+ void paintEvent( QPaintEvent * );
+ void mousePressEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void resizeEvent( QResizeEvent * );
+private:
+ void init();
+ void removeStone(short x, short y);
+ void placeStone (enum bVal c, short x, short y );
+
+ void refresh( int x, int y );
+ void showStone( int x, int y, enum bVal );
+ void reportPrisoners(int,int);
+
+ inline int x2board( int x ) { return (x-bx+d/2)/d; }
+ inline int y2board( int y ) { return (y-by+d/2)/d; }
+
+ void endGame();
+
+ bool twoplayer;
+ enum bVal currentPlayer;
+ bool gameActive;
+ int nPassed;
+ signed char board[19][19];
+
+ int d; //distance between lines
+ int bx; //vertical baseline
+ int by; //horizontal baseline
+
+ int lastX,lastY;
+ int newX,newY;
+
+ static GoWidget *self;
+
+ friend void removestone(short x, short y);
+ friend void intrPrisonerReport( short, short );
+ friend void placestone(enum bVal c, short x, short y );
+};
+
+
+
+
+
+#endif
diff --git a/noncore/games/go/killable.c b/noncore/games/go/killable.c
new file mode 100644
index 0000000..3ed2d2e
--- a/dev/null
+++ b/noncore/games/go/killable.c
@@ -0,0 +1,373 @@
+/* By Stoney Ballard */
+/* Ported from Pascal to C by Todd R. Johnson */
+
+#include "go.h"
+#include "goplayutils.h"
+#include "amigo.h"
+
+extern intBoard bord, groupIDs;
+extern boolBoard legal;
+extern groupRec gList[maxGroup];
+extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim,
+ utilPlayLevel, killFlag, depthLimit, dbStop, showTrees;
+extern pointList plist2;
+
+/*
+ returns true if the group (at x, y) is killable.
+ if so, returns the point to play at in killx, killy.
+*/
+
+ short me, him, depth, i, j, tryCount, tl, topMark, tkMark, mark2;
+ char sChar;
+ sPointList lList, dList;
+ point tp;
+ short libList[maxSPoint+1];
+ short esc;
+
+short mtNbrs(x, y)
+short x, y;
+ { /* mtNbrs */
+ short n = 0;
+ if ((x > 0) && (bord[x - 1][y] == 0))
+ n = n + 1;
+ if ((x < maxPoint) && (bord[x + 1][y] == 0))
+ n = n + 1;
+ if ((y > 0) && (bord[x][y - 1] == 0))
+ n = n + 1;
+ if ((y < maxPoint) && (bord[x][y + 1] == 0))
+ n = n + 1;
+ return n;
+ } /* mtNbrs */
+
+short killTree(tx, ty, gx, gy, escape, tkMark)
+short tx, ty, gx, gy, *escape, tkMark;
+ { /* killTree */
+ short curMark, mark2, mark3, i, j, k, tl, dStart, result;
+ sPointList lList1, lList2;
+ short libList[maxSPoint+1];
+ point tp;
+ short esc = FALSE;
+ tryCount = tryCount + 1;
+ if (tryCount > tryLimit)
+ {
+ undoTo(tkMark);
+/* for (i = 1; i <= depth - 1; i++)
+ {
+ sClearChar(sChar, rXor);
+ } */
+ depth = 1;
+ return FALSE;
+ }
+/* write(sChar); */
+ depth = depth + 1;
+ curMark = playMark;
+ tryPlay(tx, ty, me); /* try my move */
+ pause();
+ if (gList[gMap[groupIDs[tx][ty]]].libC == 0) /* I'm dead */
+ {
+ result = FALSE;
+ goto one;
+ }
+ else if (killFlag) /* I killed something of his */
+ {
+ result = TRUE;
+ goto one;
+ }
+ else if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) /* safe */
+ {
+ result = FALSE;
+ goto one;
+ }
+ else
+ {
+ sSpanGroup(gx, gy, &lList1); /* find his liberties */
+ if (gList[gMap[groupIDs[tx][ty]]].libC == 1) /* he can kill me */
+ {
+ if (lList1.indx < maxSPoint) /* add that option to his list */
+ {
+ lList1.indx = lList1.indx + 1;
+ spanGroup(tx, ty, &plist2); /* find my liberty */
+ lList1.p[lList1.indx].px = plist2.p[1].px;
+ lList1.p[lList1.indx].py = plist2.p[1].py;
+ }
+ else
+ {
+ result = FALSE;
+ goto one;
+ }
+ }
+ for (i = 1; i <= maxSPoint; i++) /* init liblist so diags can be marked */
+ libList[i] = -1;
+ if ((utilPlayLevel > 4) &&
+ (lList1.indx > 1) &&
+ (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* try diags */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ i = lList1.indx;
+ while ((j < dList.indx) &&
+ (i < maxSPoint))
+ {
+ j = j + 1;
+ i = i + 1;
+ libList[i] = 0; /* mark this as a diag */
+ lList1.p[i].px = dList.p[j].px;
+ lList1.p[i].py = dList.p[j].py;
+ }
+ lList1.indx = i;
+ }
+ if (lList1.indx > 1) /* sort by decreasing lib count */
+ {
+ for (i = 1; i <= lList1.indx; i++)
+ if (libList[i] != 0) /* diags are tried last */
+ {
+ mark2 = playMark;
+ tryPlay(lList1.p[i].px, lList1.p[i].py, him);
+ libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
+ if ((libList[i] > treeLibLim) ||
+ ((libList[i] > (depthLimit - depth)) &&
+ (libList[i] > 2)))
+ {
+ *escape = TRUE;
+ result = FALSE;
+ goto one;
+ }
+ undoTo(mark2);
+ }
+ for (i = 1; i <= lList1.indx - 1; i++)
+ for (j = i + 1; j <= lList1.indx; j++)
+ if (libList[i] < libList[j])
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList1.p[i];
+ lList1.p[i] = lList1.p[j];
+ lList1.p[j] = tp;
+ }
+ }
+ for (i = 1; i <= lList1.indx + 1; i++) /* try his responses */
+ {
+ mark2 = playMark;
+ if (i <= lList1.indx) /* try his move */
+ {
+ tryPlay(lList1.p[i].px, lList1.p[i].py, him); /* play his response */
+ pause();
+ if (gList[gMap[groupIDs[lList1.p[i].px]
+ [lList1.p[i].py]]].libC < 2)
+ goto two; /* a bogus move */
+ }
+ else if (gList[gMap[groupIDs[gx][gy]]].libC <= 1)
+ {
+ result = TRUE;
+ goto one;
+ }
+ if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
+ {
+ *escape = TRUE;
+ result = FALSE;
+ goto one;
+ }
+ if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
+ { /* look at my responses */
+ sSpanGroup(gx, gy, &lList2); /* list his liberties */
+ dStart = lList2.indx + 1;
+ if (adjInAtari) /* he wins */
+ {
+ result = FALSE;
+ goto one;
+ }
+ if ((lList2.indx > 2) && adj2Libs) /* he wins */
+ {
+ result = FALSE;
+ goto one;
+ }
+ for (k = 1; k <= maxSPoint; k++)
+ libList[k] = -1;
+ if (utilPlayLevel > 4) /* account for diagonal moves */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ k = lList2.indx;
+ while ((j < dList.indx) &&
+ (k < maxSPoint))
+ {
+ j = j + 1;
+ k = k + 1;
+ libList[k] = 100;
+ lList2.p[k].px = dList.p[j].px;
+ lList2.p[k].py = dList.p[j].py;
+ }
+ lList2.indx = k;
+ }
+ if (lList2.indx > 1) /* sort by increasing lib count */
+ {
+ for (k = 1; k <= lList2.indx; k++)
+ if (libList[k] != 100) /* diags go last */
+ {
+ mark3 = playMark;
+ tryPlay(lList2.p[k].px, lList2.p[k].py, me);
+ libList[k] = gList[gMap[groupIDs[gx][gy]]].libC;
+ undoTo(mark3);
+ }
+ for (k = 1; k <= lList2.indx - 1; k++)
+ for (j = k + 1; j <= lList2.indx; j++)
+ if (libList[k] > libList[j])
+ {
+ tl = libList[k];
+ libList[k] = libList[j];
+ libList[j] = tl;
+ tp = lList2.p[k];
+ lList2.p[k] = lList2.p[j];
+ lList2.p[j] = tp;
+ }
+ else if ((libList[k] == libList[j]) &&
+ (libList[k] == 1))
+ if (mtNbrs(lList2.p[k].px, lList2.p[k].py) <
+ mtNbrs(lList2.p[j].px, lList2.p[j].py))
+ {
+ tl = libList[k];
+ libList[k] = libList[j];
+ libList[j] = tl;
+ tp = lList2.p[k];
+ lList2.p[k] = lList2.p[j];
+ lList2.p[j] = tp;
+ }
+ }
+ for (j = 1; j <= lList2.indx; j++)
+ {
+ if (killTree(lList2.p[j].px, lList2.p[j].py, gx,
+ gy, &esc, tkMark))
+ goto two; /* this kills him */
+ if (esc && (j >= dStart))
+ {
+ result = FALSE;
+ goto one; /* don't bother with more diags if escapes */
+ }
+ }
+ result = FALSE; /* none of my responses kills him */
+ goto one;
+ }
+ two:
+ undoTo(mark2);
+ }
+ result = TRUE; /* none of his responses saves him */
+ }
+ one:
+ undoTo(curMark);
+/* sClearChar(sChar, rXor); */
+ depth = depth - 1;
+ return result;
+ } /* killTree */
+
+short tKillTree(tx, ty, gx, gy)
+short tx, ty, gx, gy;
+ { /* tKillTree */
+ short tkMark, escape;
+ tryCount = 0;
+ tkMark = playMark;
+ return killTree(tx, ty, gx, gy, &escape, tkMark);
+ } /* tKillTree */
+
+short killable(gx, gy, killx, killy)
+short gx, gy, *killx, *killy;
+{ /* killable */
+#ifdef DEBUG
+ printf( "killable\n" );
+ showTrees = TRUE;
+#endif
+ dbStop = TRUE;
+ him = bord[gx][gy]; /* find out who I am */
+ me = -him;
+/* if (me == 1)
+ sChar = '>';
+ else
+ sChar = '|'; */
+/* write(sChar); */
+ depth = 1;
+ topMark = playMark;
+ sSpanGroup(gx, gy, &lList); /* find his liberties */
+ if (lList.indx == 1)
+ {
+ *killx = lList.p[1].px;
+ *killy = lList.p[1].py;
+ return TRUE;
+ }
+ else if (lList.indx > treeLibLim)
+ return FALSE;
+ else if (adjInAtari)
+ return FALSE;
+ else if ((lList.indx > 2) && adj2Libs)
+ return FALSE;
+ else
+ {
+ for (i = 1; i <= maxSPoint; i++)
+ libList[i] = -1;
+ if (utilPlayLevel > 4) /* account for diagonal moves */
+ {
+ listDiags(gx, gy, &dList);
+ j = 0;
+ i = lList.indx;
+ while ((j < dList.indx) &&
+ (i < maxSPoint))
+ {
+ j = j + 1;
+ i = i + 1;
+ libList[i] = 100;
+ lList.p[i].px = dList.p[j].px;
+ lList.p[i].py = dList.p[j].py;
+ }
+ lList.indx = i;
+ }
+ if (lList.indx > 1) /* sort by increasing lib count */
+ {
+ for (i = 1; i <= lList.indx; i++)
+ if (libList[i] != 100) /* diags go last */
+ {
+ mark2 = playMark;
+ tryPlay(lList.p[i].px, lList.p[i].py, me);
+ libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
+ undoTo(mark2);
+ }
+ for (i = 1; i <= lList.indx - 1; i++)
+ for (j = i + 1; j <= lList.indx; j++)
+ if (libList[i] > libList[j])
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList.p[i];
+ lList.p[i] = lList.p[j];
+ lList.p[j] = tp;
+ }
+ else if ((libList[i] == libList[j]) &&
+ (libList[i] == 1))
+ if (mtNbrs(lList.p[i].px, lList.p[i].py) <
+ mtNbrs(lList.p[j].px, lList.p[j].py))
+ {
+ tl = libList[i];
+ libList[i] = libList[j];
+ libList[j] = tl;
+ tp = lList.p[i];
+ lList.p[i] = lList.p[j];
+ lList.p[j] = tp;
+ }
+ }
+ for (i = 1; i <= lList.indx; i++)
+ {
+ if (legal[lList.p[i].px][lList.p[i].py])
+ {
+ *killx = lList.p[i].px;
+ *killy = lList.p[i].py;
+ if (tKillTree(*killx, *killy, gx, gy))
+ {
+/* sClearChar(sChar, rXor); */
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+ }
+/* sClearChar(sChar, rXor); */
+} /* killable */
+
diff --git a/noncore/games/go/main.cpp b/noncore/games/go/main.cpp
new file mode 100644
index 0000000..c7e2669
--- a/dev/null
+++ b/noncore/games/go/main.cpp
@@ -0,0 +1,35 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "gowidget.h"
+
+#include <qpe/qpeapplication.h>
+
+#include <stdio.h>
+
+int main( int argc, char ** argv)
+{
+ QPEApplication app( argc, argv );
+
+ GoMainWidget m;
+ m.setCaption( GoWidget::tr("Go") );
+ app.showMainWidget( &m );
+ return app.exec();
+}
diff --git a/noncore/games/go/qpe-go.control b/noncore/games/go/qpe-go.control
new file mode 100644
index 0000000..edc106b
--- a/dev/null
+++ b/noncore/games/go/qpe-go.control
@@ -0,0 +1,9 @@
+Files: bin/go apps/Games/go.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: The game of Go
+ A game for the Qtopia environment.
diff --git a/noncore/games/mindbreaker/.cvsignore b/noncore/games/mindbreaker/.cvsignore
new file mode 100644
index 0000000..415ec09
--- a/dev/null
+++ b/noncore/games/mindbreaker/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+moc_*
+helpdialog.cpp
+helpdialog.h
diff --git a/noncore/games/mindbreaker/Makefile.in b/noncore/games/mindbreaker/Makefile.in
new file mode 100644
index 0000000..88f6fb1
--- a/dev/null
+++ b/noncore/games/mindbreaker/Makefile.in
@@ -0,0 +1,117 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = mindbreaker
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = mindbreaker.h
+SOURCES = main.cpp \
+ mindbreaker.cpp
+OBJECTS = main.o \
+ mindbreaker.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_mindbreaker.cpp
+OBJMOC = moc_mindbreaker.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake mindbreaker.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+main.o: main.cpp \
+ mindbreaker.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+mindbreaker.o: mindbreaker.cpp \
+ mindbreaker.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h
+
+moc_mindbreaker.o: moc_mindbreaker.cpp \
+ mindbreaker.h
+
+moc_mindbreaker.cpp: mindbreaker.h
+ $(MOC) mindbreaker.h -o moc_mindbreaker.cpp
+
+
diff --git a/noncore/games/mindbreaker/main.cpp b/noncore/games/mindbreaker/main.cpp
new file mode 100644
index 0000000..8ba0fde
--- a/dev/null
+++ b/noncore/games/mindbreaker/main.cpp
@@ -0,0 +1,35 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "mindbreaker.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char **argv )
+{
+ QPEApplication a( argc, argv );
+
+ MindBreaker w(0, "new window");
+ w.setCaption("Mind Breaker");
+ QPEApplication::setInputMethodHint( &w, QPEApplication::AlwaysOff );
+ a.showMainWidget(&w);
+
+ return a.exec();
+}
diff --git a/noncore/games/mindbreaker/mindbreaker.cpp b/noncore/games/mindbreaker/mindbreaker.cpp
new file mode 100644
index 0000000..b0e4d88
--- a/dev/null
+++ b/noncore/games/mindbreaker/mindbreaker.cpp
@@ -0,0 +1,818 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "mindbreaker.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qpe/qpetoolbar.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qmessagebox.h>
+#include <qlabel.h>
+#include <qstyle.h>
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static int pegRTTI = 3393393;
+
+/* helper class, */
+class Peg : public QCanvasRectangle
+{
+public:
+ Peg(QCanvas *canvas, int type, int go = -1, int pos = -1);
+ int rtti() const {return pegRTTI; }
+ void advance(int phase);
+
+ bool hit( const QPoint &) const;
+
+/* a placed peg is one that has been set down on the board correctly and
+ should not be moved, only copied */
+ bool placed() const;
+ void setPlaced(bool);
+
+ int pegGo() const;
+ int pegPos() const;
+ void setPegPos(int);
+
+ int type() const;
+
+ static void buildImages();
+ static QImage imageForType(int t);
+
+ static int eggLevel;
+
+protected:
+ void drawShape(QPainter &);
+private:
+ static QVector<QImage> normalPegs;
+ static QVector<QImage> specialPegs;
+
+ bool isplaced;
+ int pegtype;
+ int peg_go;
+ int peg_pos;
+
+ int aniStep;
+};
+
+int Peg::eggLevel = 0;
+QVector<QImage> Peg::normalPegs;
+QVector<QImage> Peg::specialPegs;
+
+void Peg::buildImages()
+{
+
+ QImage pegs = Resource::loadImage("mindbreaker/pegs");
+ int x = 0;
+ int y = 0;
+ int i;
+ eggLevel = 0;
+ normalPegs.resize(10);
+ for (i = 0; i < 6; i++) {
+ normalPegs.insert(i, new QImage(pegs.copy(x, y, peg_size, peg_size)));
+ x += peg_size;
+ }
+ specialPegs.resize(5);
+ for (i = 0; i < 5; i++) {
+ specialPegs.insert(i, new QImage(pegs.copy(x,y,peg_size, peg_size)));
+ x += peg_size;
+ }
+
+ QImage image = Resource::loadImage("mindbreaker/mindbreaker");
+ /* copy from master image to functional images */
+ x = 0;
+ y = panel_height;
+ normalPegs.insert(8,
+ new QImage(image.copy(x, y, panel_width, panel_height)));
+ y += panel_height;
+ y += title_height;
+ normalPegs.insert(9,
+ new QImage(image.copy(x, y, title_width, title_height)));
+ y += title_height;
+
+ x = 6 * peg_size;
+ normalPegs.insert(6,
+ new QImage(image.copy(x, y, answerpeg_size, answerpeg_size)));
+ x += answerpeg_size;
+ normalPegs.insert(7,
+ new QImage(image.copy(x, y, answerpeg_size, answerpeg_size)));
+}
+
+QImage Peg::imageForType(int t)
+{
+ if (eggLevel > t ) {
+ if( t < 5) {
+ return *specialPegs[t];
+ } else {
+ return *normalPegs[rand() % 6];
+ }
+ }
+ return *normalPegs[t];
+}
+
+Peg::Peg(QCanvas *canvas , int t, int g = -1, int p = -1)
+ : QCanvasRectangle(canvas)
+{
+ setSize(normalPegs[t]->width(), normalPegs[t]->height() );
+ pegtype = t;
+ isplaced = FALSE;
+ peg_pos = p;
+ peg_go = g;
+ aniStep = rand() % 6;
+ setAnimated(TRUE);
+}
+
+void Peg::advance(int phase) {
+ if (phase == 0)
+ aniStep = (++aniStep) % 6;
+ else {
+ hide();
+ show();
+ }
+}
+
+void Peg::drawShape(QPainter &p )
+{
+ if ((pegtype == 5) && eggLevel > 5) {
+ p.drawImage(x(), y(), *normalPegs[aniStep]);
+ } else
+ p.drawImage(x(), y(), imageForType(pegtype));
+}
+
+bool Peg::hit( const QPoint &p ) const
+{
+ int ix = p.x() - int(x());
+ int iy = p.y() - int(y());
+ if (!normalPegs[pegtype]->valid(ix, iy))
+ return FALSE;
+ QRgb pixel = normalPegs[pegtype]->pixel(ix, iy);
+ return (qAlpha(pixel ) != 0);
+}
+
+inline bool Peg::placed() const
+{
+ return isplaced;
+}
+
+inline int Peg::pegGo() const
+{
+ return peg_go;
+}
+
+inline int Peg::pegPos() const
+{
+ return peg_pos;
+}
+
+inline void Peg::setPegPos(int p)
+{
+ peg_pos = p;
+}
+
+inline void Peg::setPlaced(bool p)
+{
+ isplaced = p;
+}
+
+inline int Peg::type() const
+{
+ return pegtype;
+}
+
+/* Load the main image, copy from it the pegs, the board, and the answer image
+ * and use these to create the tray, answer and board
+ */
+MindBreaker::MindBreaker( QWidget *parent=0, const char *name=0, int wFlags=0 )
+: QMainWindow(parent, name, wFlags),
+ canvas(board_height, board_width)
+{
+ MindBreakerBoard *m = new MindBreakerBoard(canvas, this);
+ setCentralWidget(m);
+
+ setToolBarsMovable( FALSE );
+
+ QPEToolBar *tb = new QPEToolBar(this);
+ tb->setHorizontalStretchable( TRUE );
+
+ QPixmap newicon = Resource::loadPixmap("new");
+ new QToolButton(newicon, tr("New Game"), 0,
+ m, SLOT(clear()), tb, "NewGame");
+
+ score = new QToolButton(tb);
+ score->setText("");
+ score->setMaximumHeight(20);
+ score->setUsesTextLabel(TRUE);
+ tb->setStretchableWidget(score);
+
+ connect(m, SIGNAL(scoreChanged(int, int)), this, SLOT(setScore(int, int)));
+ connect(score, SIGNAL(clicked()), m, SLOT(resetScore()));
+
+ int a, b;
+ m->getScore(&a, &b);
+ setScore(a,b);
+}
+
+void MindBreaker::setScore(int turns, int games)
+{
+ double average;
+ double total_turns = turns;
+ double total_games = games;
+
+ if(total_games > 0)
+ average = total_turns / total_games;
+ else
+ average = 0.0;
+
+ score->setText(tr("win avg: %1 turns (%2 games)").arg(average).arg(games));
+}
+
+
+MindBreakerBoard::MindBreakerBoard( QCanvas &c, QWidget *parent=0,
+ const char *name=0, int wFlags=0 )
+ : QCanvasView(&c, parent, name, wFlags)
+{
+ int i, x, y;
+ struct timeval tv;
+
+ current_go = 0;
+ gettimeofday(&tv, 0);
+
+ srand(tv.tv_usec);
+
+ canvas()->setAdvancePeriod(500);
+
+ QImage image = Resource::loadImage("mindbreaker/mindbreaker");
+
+ /* copy from master image to functional images */
+ x = 0;
+ y = 0;
+ panelImage = image.copy(x,y, panel_width, panel_height);
+ y += panel_height;
+ y += panel_height;
+
+ titleImage = image.copy(x, y, title_width, title_height);
+
+ Peg::buildImages(); // must be done BEFORE any pegs are made
+
+ current_highlight = new Peg(canvas(), 8);
+ current_highlight->setPlaced(TRUE);
+ current_highlight->setX(0);
+ current_highlight->setY(board_height - ((current_go + 1) * panel_height));
+ current_highlight->setZ(0);
+ current_highlight->show();
+
+
+ /* set up the game */
+ Config c("MindBreaker", Config::User);
+ c.setGroup("Board");
+ game_over = FALSE;
+ if (c.readNumEntry("Answer0") < 0) {
+ for (i = 0; i < 4; i++) {
+ answer[i] = rand() % 6;
+ current_guess[i] = 6;
+ }
+ total_turns = 0;
+ total_games = 0;
+ } else {
+ int j;
+ c.setGroup("Score");
+ total_turns = c.readNumEntry("Turns");
+ total_games = c.readNumEntry("Games");
+ if(total_turns < 0)
+ total_turns = 0;
+ if(total_games < 0)
+ total_games = 0;
+
+
+ checkScores();
+ c.setGroup("Board");
+ for(i = 0; i < 4; i++)
+ answer[i] = c.readNumEntry(QString("Answer%1").arg(i));
+ /* read, and parse past guesses */
+ current_go = 0;
+ for(j=0; j < 9; j++) {
+ current_guess[0] = c.readNumEntry(QString("Go%1p0").arg(j));
+ if (current_guess[0] < 0)
+ break;
+ placeGuessPeg(0, current_guess[0]);
+ current_guess[1] = c.readNumEntry(QString("Go%1p1").arg(j));
+ placeGuessPeg(1, current_guess[1]);
+ current_guess[2] = c.readNumEntry(QString("Go%1p2").arg(j));
+ placeGuessPeg(2, current_guess[2]);
+ current_guess[3] = c.readNumEntry(QString("Go%1p3").arg(j));
+ placeGuessPeg(3, current_guess[3]);
+ checkGuess();
+ }
+ for(i = 0; i < 4; i++) {
+ current_guess[i] = c.readNumEntry(QString("CurrentGo%1").arg(i));
+ if (current_guess[i] != 6)
+ placeGuessPeg(i, current_guess[i]);
+ }
+ }
+
+ /* draw initial screen */
+ drawBackground();
+ canvas()->update();
+}
+
+MindBreakerBoard::~MindBreakerBoard()
+{
+ int i, j;
+ if (game_over) {
+ current_go = 0;
+ /* clear the answer, clear the guess */
+ for (i = 0; i < 4; i++) {
+ answer[i] = rand() % 6;
+ current_guess[i] = 6;
+ }
+ }
+
+ Config c("MindBreaker", Config::User);
+ c.setGroup("Board");
+ c.clearGroup();
+ /* write the board */
+ for (i = 0; i < current_go; i++) {
+ for(j = 0; j < 4; j++)
+ c.writeEntry(tr("Go%1p%2").arg(i).arg(j), past_guesses[4*i+j]);
+ }
+ for(j = 0; j < 4; j++)
+ c.writeEntry(tr("CurrentGo%1").arg(j), current_guess[j]);
+ for(j = 0; j < 4; j++)
+ c.writeEntry(tr("Answer%1").arg(j), answer[j]);
+
+ c.setGroup("Score");
+ /* write the score */
+
+ c.writeEntry("Turns", total_turns);
+ c.writeEntry("Games", total_games);
+}
+
+void MindBreakerBoard::getScore(int *a, int *b)
+{
+ *a = total_turns;
+ *b = total_games;
+ return;
+}
+
+void MindBreakerBoard::placeGuessPeg(int pos, int pegId)
+{
+ int x = first_peg_x_diff + (pos * peg_spacing);
+ int y = board_height - ((current_go + 1) * panel_height)
+ + first_peg_y_diff;
+
+ Peg *peg = new Peg(canvas(), pegId, current_go, pos);
+ peg->setPegPos(pos);
+ peg->setPlaced(TRUE);
+ peg->setX(x);
+ peg->setY(y);
+ peg->setZ(2);
+ peg->show();
+}
+
+void MindBreakerBoard::drawBackground()
+{
+ int i, j, x, y, x_gap, y_gap;
+ QPixmap background = QPixmap(canvas()->width(), canvas()->height());
+
+ QPainter painter(&background);
+
+ painter.fillRect(0, 0, canvas()->width(), canvas()->height(), QColor(0,0,0));
+ /* very first thing is to draw the bins, as everything else needs
+ * to be drawn over them */
+
+ QPen pen(QColor(85, 45, 27), 4);
+ painter.setPen(pen);
+ x_gap = canvas()->width() - (panel_width + (2 * bin_margin));
+ //x_gap += peg_size >> 1;
+ if (x_gap < 1)
+ x_gap = 1;
+
+ y_gap = board_height / 6;
+ y_gap -= (2 * bin_margin);
+ //y_gap += peg_size >> 1;
+ if (y_gap < 1)
+ y_gap = 1;
+ x = panel_width + bin_margin - (peg_size >> 1);
+ y = bin_margin - (peg_size >> 1) + 2;
+
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 10; j++) {
+ int rx = x + (rand() % x_gap);
+ int ry = y + (rand() % y_gap);
+ painter.drawImage(rx,ry, Peg::imageForType(i));
+ }
+ y += board_height / 6;
+ }
+ /* now draw the surrounding boxes */
+ x_gap = canvas()->width() - panel_width;
+ if (x_gap < 1) x_gap = 1;
+ y_gap = board_height / 6;
+ x = panel_width;
+ y = 1;
+
+ for (i = 0; i < 6; i++) {
+ painter.drawRect(x, y, x_gap, y_gap);
+ y += y_gap;
+ }
+
+ x = 0;
+ y = 0;
+
+ painter.drawImage(x,y, titleImage);
+ y = title_height;
+ /* now nine gues panels */
+ for (i = 0; i < 9; i ++) {
+ painter.drawImage(x, y, panelImage);
+ y += panel_height;
+ }
+
+ painter.flush();
+ canvas()->setBackgroundPixmap(background);
+}
+
+void MindBreakerBoard::checkGuess()
+{
+ int i,j;
+ int num_white = 0;
+ int num_black = 0;
+ int copy_answer[4];
+ int copy_guess[4];
+
+ for(i = 0; i < 4; i++) {
+ copy_answer[i] = answer[i];
+ copy_guess[i] = current_guess[i];
+ if (current_guess[i] == 6)
+ return;
+ if (answer[i] == current_guess[i]) {
+ num_black++;
+ copy_answer[i] = 6;
+ copy_guess[i] = 7;
+ }
+ }
+
+ /* now sure that user has completed a 'guess' */
+ for (i = 0; i < 4; i++) {
+ if (copy_guess[i] == 7)
+ continue; // already marked for a black
+ for (j = 0; j < 4; j++) {
+ if(copy_guess[i] == copy_answer[j]) {
+ copy_answer[j] = 6;
+ num_white++;
+ break;
+ }
+ }
+ }
+
+ int x = answerpegx;
+ int y = (board_height - ((current_go + 1) * panel_height)) + answerpegy;
+
+ if (num_black == 4)
+ game_over = TRUE;
+
+ while(num_black > 0) {
+ Peg *p = new Peg(canvas(), 7);
+ p->setPlaced(TRUE);
+ p->setX(x);
+ p->setY(y);
+ p->setZ(1);
+ p->show();
+ num_black--;
+
+ if (x == answerpegx)
+ x = answerpegx + answerpeg_diff;
+ else {
+ x = answerpegx;
+ y += answerpeg_diff;
+ }
+ }
+ while(num_white > 0){
+ Peg *p = new Peg(canvas(), 6);
+ p->setPlaced(TRUE);
+ p->setX(x);
+ p->setY(y);
+ p->setZ(1);
+ p->show();
+ num_white--;
+
+ if (x == answerpegx)
+ x = answerpegx + answerpeg_diff;
+ else {
+ x = answerpegx;
+ y += answerpeg_diff;
+ }
+ }
+ /* move to next go */
+ for(i = 0; i < 4; i++) {
+ past_guesses[4*current_go+i] = current_guess[i];
+ current_guess[i] = 6;
+ }
+
+ current_go++;
+ if((current_go > 8) || game_over) {
+ total_games++;
+ if(!game_over)
+ total_turns += 10;
+ else
+ total_turns += current_go;
+
+ emit scoreChanged(total_turns, total_games);
+ Peg *p = new Peg(canvas(), 9);
+ game_over = TRUE;
+ p->setPlaced(TRUE);
+ p->setX(0);
+ p->setY(0);
+ p->setZ(0);
+ p->show();
+
+ for (i = 0; i < 4; i++) {
+ p = new Peg(canvas(), answer[i], -1);
+ p->setX(first_peg_x_diff + (i * peg_spacing));
+ p->setY(5);
+ p->setZ(3);
+ p->show();
+ }
+ } else {
+ current_highlight->setY(board_height - ((current_go + 1) * panel_height));
+ }
+ canvas()->update();
+}
+
+void MindBreakerBoard::clear()
+{
+ if(!game_over) {
+ total_games++;
+ total_turns += 10;
+ emit scoreChanged(total_turns, total_games);
+ }
+ int i;
+ /* reset the game board */
+ game_over = FALSE;
+ /* clear the answer, clear the guess */
+ for (i = 0; i < 4; i++) {
+ answer[i] = rand() % 6;
+ current_guess[i] = 6;
+ }
+ current_go = 0;
+
+ QCanvasItemList list = canvas()->allItems();
+ QCanvasItemList::Iterator it = list.begin();
+ for (; it != list.end(); ++it) {
+ if (*it == current_highlight)
+ continue;
+ if (*it)
+ delete *it;
+ }
+
+ current_highlight->setY(board_height - ((current_go + 1) * panel_height));
+ checkScores();
+ drawBackground();
+ canvas()->update();
+}
+
+void MindBreakerBoard::resetScore()
+{
+ /* are u sure */
+
+ if (QMessageBox::information(this, tr( "Reset Statistics" ),
+ tr( "Reset the win ratio?" ),
+ tr( "OK" ), tr( "Cancel" ) ) == 0) {
+ total_turns = 0;
+ total_games = 0;
+ Peg::eggLevel = 0;
+ drawBackground();
+ canvas()->update();
+ emit scoreChanged(total_turns, total_games);
+ }
+}
+
+/* EVENTS */
+
+void MindBreakerBoard::contentsMousePressEvent(QMouseEvent *e)
+{
+ copy_press = FALSE;
+ null_press = FALSE;
+ /* ok, first work out if it is one of the bins that
+ got clicked */
+ if (e->x() > panel_width) {
+ /* its a bin, but which bin */
+ if(e->y() > board_height)
+ return; // missed everything
+ int bin = (e->y() + 2) / (board_height / 6);
+
+ /* make new peg... set it moving */
+ moving_pos = e->pos();
+ moving = new Peg(canvas(), bin, current_go);
+ moving->setX(e->x() - (peg_size >> 1));
+ moving->setY(e->y() - (peg_size >> 1));
+ moving->setZ(5);
+ moving->show();
+ canvas()->update();
+ return;
+ }
+
+ QCanvasItemList l = canvas()->collisions(e->pos());
+ for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
+ if ( (*it)->rtti() == pegRTTI ) {
+ Peg *item = (Peg *)(*it);
+ if (!item->hit(e->pos()))
+ continue;
+ if (item->type() > 5) {
+ null_press = TRUE;
+ null_point = e->pos();
+ continue; /* not a color peg */
+ }
+ if (item->placed()) {
+ /* copy */
+ if(item->pegGo() == -1)
+ return;
+ if(item->pegGo() == current_go) {
+ copy_press = TRUE;
+ copy_peg = item;
+ }
+ moving = new Peg(canvas(),
+ item->type(), current_go);
+ moving->setX(e->x() - (peg_size >> 1));
+ moving->setY(e->y() - (peg_size >> 1));
+ moving->setZ(5);
+ moving->show();
+ moving_pos = QPoint(e->x(), e->y());
+ canvas()->update();
+ return;
+ }
+ moving = (Peg *)*it;
+ moving_pos = e->pos();
+ canvas()->update();
+ return;
+ }
+ }
+ null_press = TRUE;
+ null_point = e->pos();
+ moving = 0;
+}
+
+void MindBreakerBoard::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ if (moving ) {
+ moving->moveBy(e->pos().x() - moving_pos.x(),
+ e->pos().y() - moving_pos.y());
+ moving_pos = e->pos();
+ canvas()->update();
+ return;
+ }
+}
+
+void MindBreakerBoard::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ /* time to put down the peg */
+ if(moving) {
+ if(copy_press) {
+ /* check if collided with original. if so, delete both */
+ copy_press = FALSE;
+ QCanvasItemList l = canvas()->collisions(e->pos());
+ for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
+ if (*it == copy_peg)
+ copy_press = TRUE;
+ }
+ if (copy_press) {
+ current_guess[copy_peg->pegPos()] = 6;
+ delete copy_peg;
+ delete moving;
+ copy_press = FALSE;
+ moving = 0;
+ copy_peg = 0;
+ canvas()->update();
+ return;
+ }
+ }
+
+ /* first work out if in y */
+ if (e->y() > (board_height - (current_go * panel_height))) {
+ delete moving;
+ moving = 0;
+ canvas()->update();
+ return;
+ }
+ if (e->y() < (board_height - ((current_go + 1) * panel_height))) {
+ delete moving;
+ moving = 0;
+ canvas()->update();
+ return;
+ }
+ /* ok, a valid go, but which peg */
+ int x_bar = first_peg_x_diff - (peg_size >> 1);
+ x_bar += peg_spacing;
+ int pos = 0;
+ if (e->x() > x_bar)
+ pos = 1;
+ x_bar += peg_spacing;
+ if (e->x() > x_bar)
+ pos = 2;
+ x_bar += peg_spacing;
+ if (e->x() > x_bar)
+ pos = 3;
+ x_bar += peg_spacing;
+
+ if (e->x() > x_bar) {
+ /* invalid x */
+ delete moving;
+ moving = 0;
+ canvas()->update();
+ return;
+ }
+
+ int x = first_peg_x_diff + (pos * peg_spacing);
+ int y = board_height - ((current_go + 1) * panel_height)
+ + first_peg_y_diff;
+ moving->setPegPos(pos);
+ moving->setX(x);
+ moving->setY(y);
+ moving->setZ(2);
+
+ /* remove all other pegs from this position */
+ QCanvasItemList l = canvas()->collisions(QPoint(x,y));
+ for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
+ if ( (*it)->rtti() == pegRTTI ) {
+ Peg *item = (Peg *)(*it);
+ if ((item != moving) && (item != current_highlight))
+ delete item;
+ }
+ }
+ current_guess[pos] = ((Peg *)moving)->type();
+
+ ((Peg *)moving)->setPlaced(true);
+ canvas()->update();
+ return;
+ }
+ moving = 0;
+ null_point -= e->pos();
+ if(null_point.manhattanLength() < 6) {
+ if (game_over)
+ clear();
+ else
+ checkGuess();
+ }
+}
+
+void MindBreakerBoard::resizeEvent(QResizeEvent *e)
+{
+ QSize s = e->size();
+ int fw = style().defaultFrameWidth();
+ s.setWidth(s.width() - fw);
+ s.setHeight(s.height() - fw);
+
+ /* min size is 200 x 260 */
+ if (s.width() < board_width)
+ s.setWidth(board_width);
+
+ if (s.height() < board_height)
+ s.setHeight(board_height);
+
+ canvas()->resize(s.width() - fw, s.height() - fw);
+ drawBackground();
+}
+
+
+/* Easter egg function... beat the clock */
+void MindBreakerBoard::checkScores()
+{
+ double games = total_games;
+ double turns = total_turns;
+ double g = games / 10.0;
+ Peg::eggLevel = 0;
+
+ double break_even = 5.0;
+ if (g < 1.0)
+ return;
+ double avg = turns / games;
+ g--;
+ while (break_even >= 0.0) {
+ if (avg >= (break_even + g))
+ return;
+ // score a peg.
+ break_even -= 1.0;
+ Peg::eggLevel = int(5.0 - break_even);
+ }
+}
diff --git a/noncore/games/mindbreaker/mindbreaker.h b/noncore/games/mindbreaker/mindbreaker.h
new file mode 100644
index 0000000..fca649a
--- a/dev/null
+++ b/noncore/games/mindbreaker/mindbreaker.h
@@ -0,0 +1,122 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef MINDBREAKER_H
+#define MINDBREAKER_H
+
+#include <qwidget.h>
+#include <qmainwindow.h>
+#include <qimage.h>
+#include <qvector.h>
+#include <qcanvas.h>
+#include <qlabel.h>
+
+static const int panel_height = 26;
+static const int panel_width = 180;
+
+static const int title_height = 25;
+static const int title_width = 180;
+
+static const int bin_margin = 10;
+static const int peg_size = 20;
+static const int answerpeg_size = 13;
+
+static const int first_peg_x_diff = 21;
+static const int first_peg_y_diff = ((panel_height - peg_size) >> 1);
+static const int peg_spacing = 30;
+
+static const int answerpegx = 152;
+static const int answerpegy = 2;
+static const int answerpeg_diff = 9;
+
+static const int board_height = (title_height + (panel_height * 9));
+static const int board_width = (panel_width + (bin_margin * 2) + peg_size);
+
+class Peg;
+class QToolButton;
+
+class MindBreakerBoard : public QCanvasView // QWidget
+{
+ Q_OBJECT
+public:
+ MindBreakerBoard(QCanvas &c, QWidget *parent=0, const char *name=0, int wFlags=0 );
+ ~MindBreakerBoard();
+
+ void getScore(int *, int *);
+signals:
+ void scoreChanged(int, int);
+
+public slots:
+ void clear();
+ void resetScore();
+
+protected:
+ void contentsMousePressEvent(QMouseEvent *);
+ void contentsMouseMoveEvent(QMouseEvent *);
+ void contentsMouseReleaseEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *);
+
+private:
+ void drawBackground();
+ void checkGuess();
+ void checkScores();
+ void placeGuessPeg(int pos, int pegId);
+
+ QImage panelImage;
+ QImage titleImage;
+
+ Peg *moving;
+ Peg *current_highlight;
+ QPoint moving_pos;
+
+ // the game stuff
+ int answer[4];
+ int current_guess[4];
+ int past_guesses[4*9];
+ int current_go;
+
+ int null_press;
+ QPoint null_point;
+ bool copy_press;
+ Peg *copy_peg;
+ bool game_over;
+
+ int total_turns;
+ int total_games;
+};
+
+class MindBreaker : public QMainWindow // QWidget
+{
+ Q_OBJECT
+public:
+ MindBreaker(QWidget *parent=0, const char *name=0, int wFlags=0 );
+
+public slots:
+ void setScore(int, int);
+
+private:
+ QCanvas canvas;
+ MindBreakerBoard *board;
+ QToolButton *score;
+
+};
+
+
+#endif
diff --git a/noncore/games/mindbreaker/mindbreaker.pro b/noncore/games/mindbreaker/mindbreaker.pro
new file mode 100644
index 0000000..12944d1
--- a/dev/null
+++ b/noncore/games/mindbreaker/mindbreaker.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = mindbreaker.h
+SOURCES = main.cpp \
+ mindbreaker.cpp
+TARGET = mindbreaker
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+TRANSLATIONS = ../i18n/de/mindbreaker.ts
diff --git a/noncore/games/mindbreaker/qpe-mindbreaker.control b/noncore/games/mindbreaker/qpe-mindbreaker.control
new file mode 100644
index 0000000..3bad93d
--- a/dev/null
+++ b/noncore/games/mindbreaker/qpe-mindbreaker.control
@@ -0,0 +1,9 @@
+Files: bin/mindbreaker apps/Games/mindbreaker.desktop pics/mindbreaker
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: crack the coloured code
+ A game for the Qtopia environment.
diff --git a/noncore/games/minesweep/.cvsignore b/noncore/games/minesweep/.cvsignore
new file mode 100644
index 0000000..6fe2396
--- a/dev/null
+++ b/noncore/games/minesweep/.cvsignore
@@ -0,0 +1,2 @@
+moc_*
+Makefile
diff --git a/noncore/games/minesweep/Makefile.in b/noncore/games/minesweep/Makefile.in
new file mode 100644
index 0000000..9ed6234
--- a/dev/null
+++ b/noncore/games/minesweep/Makefile.in
@@ -0,0 +1,134 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = minesweep
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = minefield.h \
+ minesweep.h
+SOURCES = main.cpp \
+ minefield.cpp \
+ minesweep.cpp
+OBJECTS = main.o \
+ minefield.o \
+ minesweep.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_minefield.cpp \
+ moc_minesweep.cpp
+OBJMOC = moc_minefield.o \
+ moc_minesweep.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake minesweep.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+main.o: main.cpp \
+ minesweep.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+minefield.o: minefield.cpp \
+ minefield.h \
+ $(QPEDIR)/include/qpe/config.h
+
+minesweep.o: minesweep.cpp \
+ minesweep.h \
+ minefield.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+moc_minefield.o: moc_minefield.cpp \
+ minefield.h
+
+moc_minesweep.o: moc_minesweep.cpp \
+ minesweep.h
+
+moc_minefield.cpp: minefield.h
+ $(MOC) minefield.h -o moc_minefield.cpp
+
+moc_minesweep.cpp: minesweep.h
+ $(MOC) minesweep.h -o moc_minesweep.cpp
+
+
diff --git a/noncore/games/minesweep/main.cpp b/noncore/games/minesweep/main.cpp
new file mode 100644
index 0000000..83de9a3
--- a/dev/null
+++ b/noncore/games/minesweep/main.cpp
@@ -0,0 +1,34 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "minesweep.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char** argv )
+{
+ QPEApplication a( argc, argv );
+
+ MineSweep ms;
+ QPEApplication::setInputMethodHint( &ms, QPEApplication::AlwaysOff );
+ a.showMainWidget( &ms );
+
+ return a.exec();
+}
diff --git a/noncore/games/minesweep/minefield.cpp b/noncore/games/minesweep/minefield.cpp
new file mode 100644
index 0000000..be2f9a3
--- a/dev/null
+++ b/noncore/games/minesweep/minefield.cpp
@@ -0,0 +1,623 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "minefield.h"
+
+#include <qpe/config.h>
+
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qtimer.h>
+
+#include <stdlib.h>
+
+static const char *pix_flag[]={
+"13 13 3 1",
+"# c #000000",
+"x c #ff0000",
+". c None",
+".............",
+".............",
+".....#xxxxxx.",
+".....#xxxxxx.",
+".....#xxxxxx.",
+".....#xxxxxx.",
+".....#.......",
+".....#.......",
+".....#.......",
+".....#.......",
+"...#####.....",
+"..#######....",
+"............."};
+
+static const char *pix_mine[]={
+"13 13 3 1",
+"# c #000000",
+". c None",
+"a c #ffffff",
+"......#......",
+"......#......",
+"..#.#####.#..",
+"...#######...",
+"..##aa#####..",
+"..##aa#####..",
+"#############",
+"..#########..",
+"..#########..",
+"...#######...",
+"..#.#####.#..",
+"......#......",
+"......#......"};
+
+class Mine : public QTableItem
+{
+public:
+ enum MineState {
+ Hidden = 0,
+ Empty,
+ Mined,
+ Flagged,
+#ifdef MARK_UNSURE
+ Unsure,
+#endif
+ Exploded,
+ Wrong
+ };
+
+ Mine( QTable* );
+ void paint( QPainter * p, const QColorGroup & cg, const QRect & cr, bool selected );
+ EditType editType() const { return Never; }
+ QSize sizeHint() const { return QSize( 12, 12 ); }
+
+ void activate( bool sure = TRUE );
+ void setHint( int );
+
+ void setState( MineState );
+ MineState state() const { return st; }
+
+ bool isMined() const { return mined; }
+ void setMined( bool m ) { mined = m; }
+
+ static void paletteChange();
+
+private:
+ bool mined;
+ int hint;
+
+ MineState st;
+
+ static QPixmap* knownField;
+ static QPixmap* unknownField;
+ static QPixmap* flag_pix;
+ static QPixmap* mine_pix;
+};
+
+QPixmap* Mine::knownField = 0;
+QPixmap* Mine::unknownField = 0;
+QPixmap* Mine::flag_pix = 0;
+QPixmap* Mine::mine_pix = 0;
+
+Mine::Mine( QTable *t )
+: QTableItem( t, Never, QString::null )
+{
+ mined = FALSE;
+ st = Hidden;
+ hint = 0;
+}
+
+void Mine::activate( bool sure )
+{
+ if ( !sure ) {
+ switch ( st ) {
+ case Hidden:
+ setState( Flagged );
+ break;
+ case Flagged:
+#ifdef MARK_UNSURE
+ setState( Unsure );
+ break;
+ case Unsure:
+#endif
+ setState( Hidden );
+ default:
+ break;
+ }
+ } else if ( st == Flagged ) {
+ return;
+ } else {
+ if ( mined ) {
+ setState( Exploded );
+ } else {
+ setState( Empty );
+ }
+ }
+}
+
+void Mine::setState( MineState s )
+{
+ st = s;
+}
+
+void Mine::setHint( int h )
+{
+ hint = h;
+}
+
+void Mine::paletteChange()
+{
+ delete knownField;
+ knownField = 0;
+ delete unknownField;
+ unknownField = 0;
+ delete mine_pix;
+ mine_pix = 0;
+ delete flag_pix;
+ flag_pix = 0;
+}
+
+void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool )
+{
+ if ( !knownField ) {
+ knownField = new QPixmap( cr.width(), cr.height() );
+ QPainter pp( knownField );
+ QBrush br( cg.button().dark(115) );
+ qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, TRUE, &br );
+ }
+
+ const int pmmarg=cr.width()/5;
+
+ if ( !unknownField ) {
+ unknownField = new QPixmap( cr.width(), cr.height() );
+ QPainter pp( unknownField );
+ QBrush br( cg.button() );
+ qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, FALSE, &br );
+ }
+
+ if ( !flag_pix ) {
+ flag_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
+ flag_pix->convertFromImage( QImage(pix_flag).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
+ }
+
+ if ( !mine_pix ) {
+ mine_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
+ mine_pix->convertFromImage( QImage(pix_mine).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
+ }
+
+ p->save();
+
+ switch(st) {
+ case Hidden:
+ p->drawPixmap( 0, 0, *unknownField );
+ break;
+ case Empty:
+ p->drawPixmap( 0, 0, *knownField );
+ if ( hint > 0 ) {
+ switch( hint ) {
+ case 1:
+ p->setPen( blue );
+ break;
+ case 2:
+ p->setPen( green );
+ case 3:
+ p->setPen( red );
+ break;
+ default:
+ p->setPen( darkMagenta );
+ break;
+ }
+ p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, QString().setNum( hint ) );
+ }
+ break;
+ case Mined:
+ p->drawPixmap( 0, 0, *knownField );
+ p->drawPixmap( pmmarg, pmmarg, *mine_pix );
+ break;
+ case Exploded:
+ p->drawPixmap( 0, 0, *knownField );
+ p->drawPixmap( pmmarg, pmmarg, *mine_pix );
+ p->setPen( red );
+ p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" );
+ break;
+ case Flagged:
+ p->drawPixmap( 0, 0, *unknownField );
+ p->drawPixmap( pmmarg, pmmarg, *flag_pix );
+ break;
+#ifdef MARK_UNSURE
+ case Unsure:
+ p->drawPixmap( 0, 0, *unknownField );
+ p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "?" );
+ break;
+#endif
+ case Wrong:
+ p->drawPixmap( 0, 0, *unknownField );
+ p->drawPixmap( pmmarg, pmmarg, *flag_pix );
+ p->setPen( red );
+ p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" );
+ break;
+ }
+
+ p->restore();
+}
+
+/*
+ MineField implementation
+*/
+
+MineField::MineField( QWidget* parent, const char* name )
+: QTable( parent, name )
+{
+ setState( GameOver );
+ setShowGrid( FALSE );
+ horizontalHeader()->hide();
+ verticalHeader()->hide();
+ setTopMargin( 0 );
+ setLeftMargin( 0 );
+
+ setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) );
+
+ setSelectionMode( QTable::NoSelection );
+ setFocusPolicy( QWidget::NoFocus );
+
+ setCurrentCell( -1, -1 );
+
+ connect( this, SIGNAL( pressed( int, int, int, const QPoint& ) ), this, SLOT( cellPressed( int, int ) ) );
+ connect( this, SIGNAL( clicked( int, int, int, const QPoint& ) ), this, SLOT( cellClicked( int, int ) ) );
+
+ holdTimer = new QTimer( this );
+ connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) );
+
+ flagAction = NoAction;
+ ignoreClick = FALSE;
+ currRow = currCol = 0;
+ minecount=0;
+ mineguess=0;
+ nonminecount=0;
+}
+
+MineField::~MineField()
+{
+}
+
+void MineField::setState( State st )
+{
+ stat = st;
+}
+
+
+void MineField::setup( int level )
+{
+ lev = level;
+ setState( Waiting );
+ viewport()->setUpdatesEnabled( FALSE );
+
+ int cellsize;
+
+ int x;
+ int y;
+ for ( x = 0; x < numCols(); x++ )
+ for ( y = 0; y < numRows(); y++ )
+ clearCell( y, x );
+
+ switch( lev ) {
+ case 1:
+ setNumRows( 9 );
+ setNumCols( 9 );
+ minecount = 12;
+ cellsize = 21;
+ break;
+ case 2:
+ setNumRows( 16 );
+ setNumCols( 16 );
+ minecount = 45;
+ cellsize = 14;
+ break;
+ case 3:
+ setNumRows( 18 );
+ setNumCols( 18 );
+ minecount = 66 ;
+ cellsize = 12;
+ break;
+ }
+ nonminecount = numRows()*numCols() - minecount;
+ mineguess = minecount;
+ emit mineCount( mineguess );
+ Mine::paletteChange();
+
+ for ( y = 0; y < numRows(); y++ )
+ setRowHeight( y, cellsize );
+ for ( x = 0; x < numCols(); x++ )
+ setColumnWidth( x, cellsize );
+ for ( x = 0; x < numCols(); x++ )
+ for ( y = 0; y < numRows(); y++ )
+ setItem( y, x, new Mine( this ) );
+
+ updateGeometry();
+ viewport()->setUpdatesEnabled( TRUE );
+ viewport()->repaint( TRUE );
+}
+
+
+void MineField::placeMines()
+{
+ int mines = minecount;
+ while ( mines ) {
+ int col = int((double(rand()) / double(RAND_MAX)) * numCols());
+ int row = int((double(rand()) / double(RAND_MAX)) * numRows());
+
+ Mine* mine = (Mine*)item( row, col );
+
+ if ( mine && !mine->isMined() && mine->state() == Mine::Hidden ) {
+ mine->setMined( TRUE );
+ mines--;
+ }
+ }
+}
+
+void MineField::paintFocus( QPainter*, const QRect& )
+{
+}
+
+void MineField::viewportMousePressEvent( QMouseEvent* e )
+{
+ QTable::viewportMousePressEvent( e );
+}
+
+void MineField::viewportMouseReleaseEvent( QMouseEvent* e )
+{
+ QTable::viewportMouseReleaseEvent( e );
+ if ( flagAction == FlagNext ) {
+ flagAction = NoAction;
+ }
+}
+
+void MineField::keyPressEvent( QKeyEvent* e )
+{
+#if defined(Q_WS_QWS) || defined(_WS_QWS_)
+ flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction;
+#else
+ flagAction = ( ( e->state() & ShiftButton ) == ShiftButton ) ? FlagOn : NoAction;
+#endif
+}
+
+void MineField::keyReleaseEvent( QKeyEvent* )
+{
+ flagAction = NoAction;
+}
+
+int MineField::getHint( int row, int col )
+{
+ int hint = 0;
+ for ( int c = col-1; c <= col+1; c++ )
+ for ( int r = row-1; r <= row+1; r++ ) {
+ Mine* mine = (Mine*)item( r, c );
+ if ( mine && mine->isMined() )
+ hint++;
+ }
+
+ return hint;
+}
+
+void MineField::setHint( Mine* mine )
+{
+ if ( !mine )
+ return;
+
+ int row = mine->row();
+ int col = mine->col();
+ int hint = getHint( row, col );
+
+ if ( !hint ) {
+ for ( int c = col-1; c <= col+1; c++ )
+ for ( int r = row-1; r <= row+1; r++ ) {
+ Mine* mine = (Mine*)item( r, c );
+ if ( mine && mine->state() == Mine::Hidden ) {
+ mine->activate( TRUE );
+ nonminecount--;
+ setHint( mine );
+ updateCell( r, c );
+ }
+ }
+ }
+
+ mine->setHint( hint );
+ updateCell( row, col );
+}
+
+/*
+ state == Waiting means no "hold"
+
+
+*/
+void MineField::cellPressed( int row, int col )
+{
+ if ( state() == GameOver )
+ return;
+ currRow = row;
+ currCol = col;
+ if ( state() == Playing )
+ holdTimer->start( 150, TRUE );
+}
+
+void MineField::held()
+{
+ flagAction = FlagNext;
+ updateMine( currRow, currCol );
+ ignoreClick = TRUE;
+}
+
+/*
+ Only place mines after first click, since it is pointless to
+ kill the player before the game has started.
+*/
+
+void MineField::cellClicked( int row, int col )
+{
+ if ( state() == GameOver )
+ return;
+ if ( state() == Waiting ) {
+ Mine* mine = (Mine*)item( row, col );
+ if ( !mine )
+ return;
+ mine->setState( Mine::Empty );
+ nonminecount--;
+ placeMines();
+ setState( Playing );
+ emit gameStarted();
+ updateMine( row, col );
+ } else { // state() == Playing
+ holdTimer->stop();
+ if ( ignoreClick )
+ ignoreClick = FALSE;
+ else
+ updateMine( row, col );
+ }
+}
+
+void MineField::updateMine( int row, int col )
+{
+ Mine* mine = (Mine*)item( row, col );
+ if ( !mine )
+ return;
+
+ bool wasFlagged = mine->state() == Mine::Flagged;
+ bool wasEmpty = mine->state() == Mine::Empty;
+
+ mine->activate( flagAction == NoAction );
+
+ if ( mine->state() == Mine::Exploded ) {
+ emit gameOver( FALSE );
+ setState( GameOver );
+ return;
+ } else if ( mine->state() == Mine::Empty ) {
+ setHint( mine );
+ if ( !wasEmpty )
+ nonminecount--;
+ }
+
+ if ( flagAction != NoAction ) {
+ if ( mine->state() == Mine::Flagged ) {
+ --mineguess;
+ emit mineCount( mineguess );
+ if ( mine->isMined() )
+ --minecount;
+ } else if ( wasFlagged ) {
+ ++mineguess;
+ emit mineCount( mineguess );
+ if ( mine->isMined() )
+ ++minecount;
+ }
+ }
+
+ updateCell( row, col );
+
+ if ( !minecount && !mineguess || !nonminecount ) {
+ emit gameOver( TRUE );
+ setState( GameOver );
+ }
+}
+
+void MineField::showMines()
+{
+ for ( int c = 0; c < numCols(); c++ )
+ for ( int r = 0; r < numRows(); r++ ) {
+ Mine* mine = (Mine*)item( r, c );
+ if ( !mine )
+ continue;
+ if ( mine->isMined() && mine->state() == Mine::Hidden )
+ mine->setState( Mine::Mined );
+ if ( !mine->isMined() && mine->state() == Mine::Flagged )
+ mine->setState( Mine::Wrong );
+
+ updateCell( r, c );
+ }
+}
+
+void MineField::paletteChange( const QPalette &o )
+{
+ Mine::paletteChange();
+ QTable::paletteChange( o );
+}
+
+void MineField::writeConfig(Config& cfg) const
+{
+ cfg.setGroup("Field");
+ cfg.writeEntry("Level",lev);
+ QString grid="";
+ if ( stat == Playing ) {
+ for ( int x = 0; x < numCols(); x++ )
+ for ( int y = 0; y < numRows(); y++ ) {
+ char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat
+ Mine* mine = (Mine*)item( y, x );
+ int st = (int)mine->state(); if ( mine->isMined() ) st+=5;
+ grid += code + st;
+ }
+ }
+ cfg.writeEntry("Grid",grid);
+}
+
+void MineField::readConfig(Config& cfg)
+{
+ cfg.setGroup("Field");
+ lev = cfg.readNumEntry("Level",1);
+ setup(lev);
+ flagAction = NoAction;
+ ignoreClick = FALSE;
+ currRow = currCol = 0;
+ QString grid = cfg.readEntry("Grid");
+ if ( !grid.isEmpty() ) {
+ int i=0;
+ minecount=0;
+ mineguess=0;
+ for ( int x = 0; x < numCols(); x++ ) {
+ for ( int y = 0; y < numRows(); y++ ) {
+ char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat
+ int st = (char)(QChar)grid[i++]-code;
+ Mine* mine = (Mine*)item( y, x );
+ if ( st >= 5 ) {
+ st-=5;
+ mine->setMined(TRUE);
+ minecount++;
+ mineguess++;
+ }
+ mine->setState((Mine::MineState)st);
+ switch ( mine->state() ) {
+ case Mine::Flagged:
+ if (mine->isMined())
+ minecount--;
+ mineguess--;
+ break;
+ case Mine::Empty:
+ --nonminecount;
+ }
+ }
+ }
+ for ( int x = 0; x < numCols(); x++ ) {
+ for ( int y = 0; y < numRows(); y++ ) {
+ Mine* mine = (Mine*)item( y, x );
+ if ( mine->state() == Mine::Empty )
+ mine->setHint(getHint(y,x));
+ }
+ }
+ }
+ setState( Playing );
+ emit mineCount( mineguess );
+}
+
diff --git a/noncore/games/minesweep/minefield.h b/noncore/games/minesweep/minefield.h
new file mode 100644
index 0000000..4ede435
--- a/dev/null
+++ b/noncore/games/minesweep/minefield.h
@@ -0,0 +1,87 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef MINEFIELD_H
+#define MINEFIELD_H
+
+#include <qtable.h>
+
+class Mine;
+class Config;
+
+class MineField : public QTable
+{
+ Q_OBJECT
+public:
+ MineField( QWidget* parent = 0, const char* name = 0 );
+ ~MineField();
+
+ enum State { Waiting, Playing, GameOver };
+
+ State state() const { return stat; }
+
+ void readConfig(Config&);
+ void writeConfig(Config&) const;
+
+ int level() const { return lev; }
+
+public slots:
+ void setup( int level );
+
+ void showMines();
+
+signals:
+ void gameOver( bool won );
+ void gameStarted();
+ void mineCount( int );
+
+protected:
+ void paintFocus( QPainter*, const QRect& );
+ void viewportMousePressEvent( QMouseEvent* );
+ void viewportMouseReleaseEvent( QMouseEvent* );
+ void keyPressEvent( QKeyEvent* );
+ void keyReleaseEvent( QKeyEvent* );
+
+ int getHint( int row, int col );
+ void setHint( Mine* );
+ void updateMine( int row, int col );
+ void paletteChange( const QPalette & );
+
+protected slots:
+ void cellPressed( int row, int col );
+ void cellClicked( int row, int col );
+ void held();
+
+private:
+ State stat;
+ void MineField::setState( State st );
+ void MineField::placeMines();
+ enum FlagAction { NoAction, FlagOn, FlagNext };
+ FlagAction flagAction;
+ bool ignoreClick;
+ int currRow;
+ int currCol;
+ int minecount;
+ int mineguess;
+ int nonminecount;
+ int lev;
+ QTimer *holdTimer;
+};
+
+#endif // MINEFIELD_H
diff --git a/noncore/games/minesweep/minesweep.cpp b/noncore/games/minesweep/minesweep.cpp
new file mode 100644
index 0000000..6492462
--- a/dev/null
+++ b/noncore/games/minesweep/minesweep.cpp
@@ -0,0 +1,390 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "minesweep.h"
+#include "minefield.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qpe/qpetoolbar.h>
+#include <qpe/qpemenubar.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qlcdnumber.h>
+#include <qmessagebox.h>
+#include <qtimer.h>
+#include <qpalette.h>
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+
+
+
+static const char *pix_new[]={
+"20 20 3 1",
+" c None",
+"# c #00FF00",
+". c #000000",
+" ",
+" ...... ",
+" ..######.. ",
+" .##########. ",
+" .############. ",
+" .##############. ",
+" .##############. ",
+" .################. ",
+" .################. ",
+" .################. ",
+" .################. ",
+" .################. ",
+" .################. ",
+" .##############. ",
+" .##############. ",
+" .############. ",
+" .##########. ",
+" ..######.. ",
+" ...... ",
+" "};
+
+
+/* XPM */
+static const char * happy_xpm[] = {
+"20 20 3 1",
+" c None",
+". c #ffff3f ",
+"# c #000000",
+" ",
+" ###### ",
+" ##......## ",
+" #..........# ",
+" #............# ",
+" #..............# ",
+" #..............# ",
+" #....##....##....# ",
+" #....##....##....# ",
+" #................# ",
+" #................# ",
+" #................# ",
+" #...#........#...# ",
+" #.##........##.# ",
+" #...########...# ",
+" #...######...# ",
+" #..........# ",
+" ##......## ",
+" ###### ",
+" "};
+
+
+/* XPM */
+static const char * worried_xpm[] = {
+"20 20 3 1",
+" c None",
+". c #ffff3f",
+"# c #000000",
+" ",
+" ###### ",
+" ##......## ",
+" #..........# ",
+" #............# ",
+" #..............# ",
+" #..............# ",
+" #....##....##....# ",
+" #....##....##....# ",
+" #................# ",
+" #................# ",
+" #................# ",
+" #................# ",
+" #....######....# ",
+" #..............# ",
+" #............# ",
+" #..........# ",
+" ##......## ",
+" ###### ",
+" "};
+
+
+/* XPM */
+static const char * dead_xpm[] = {
+"20 20 3 1",
+" c None",
+". c #ffff3f",
+"# c #000000",
+" ",
+" ###### ",
+" ##......## ",
+" #..........# ",
+" #............# ",
+" #..............# ",
+" #..#.#...#.#...# ",
+" #....#.....#.....# ",
+" #...#.#...#.#....# ",
+" #................# ",
+" #................# ",
+" #................# ",
+" #......####......# ",
+" #....# #....# ",
+" #...#......#...# ",
+" #............# ",
+" #..........# ",
+" ##......## ",
+" ###### ",
+" "};
+
+
+class ResultIndicator : private QLabel
+{
+public:
+ static void showResult( QWidget *ref, bool won );
+private:
+ ResultIndicator( QWidget *parent, const char *name, WFlags f)
+ :QLabel( parent, name, f ) {}
+
+ void timerEvent( QTimerEvent *);
+ void center();
+ bool twoStage;
+ int timerId;
+};
+
+void ResultIndicator::showResult( QWidget *ref, bool won )
+{
+ ResultIndicator *r = new ResultIndicator( ref, 0, WStyle_Customize | WStyle_Tool | WType_TopLevel );
+
+ r->setAlignment( AlignCenter );
+ r->setFrameStyle( Sunken|StyledPanel );
+ if ( won ) {
+ r->setText( MineSweep::tr("You won!") );
+ r->center();
+ r->show();
+ r->twoStage = FALSE;
+ r->timerId = r->startTimer(1500);
+ } else {
+ QPalette p( red );
+ r->setPalette( p );
+ r->setText( MineSweep::tr("You exploded!") );
+ r->resize( ref->size() );
+ r->move( ref->mapToGlobal(QPoint(0,0)) );
+ r->show();
+ r->twoStage = TRUE;
+ r->timerId =r->startTimer(200);
+ }
+}
+
+void ResultIndicator::center()
+{
+ QWidget *w = parentWidget();
+
+ QPoint pp = w->mapToGlobal( QPoint(0,0) );
+ QSize s = sizeHint()*3;
+ pp = QPoint( pp.x() + w->width()/2 - s.width()/2,
+ pp.y() + w->height()/ 2 - s.height()/2 );
+
+ setGeometry( QRect(pp, s) );
+
+}
+
+void ResultIndicator::timerEvent( QTimerEvent *te )
+{
+ if ( te->timerId() != timerId )
+ return;
+ killTimer( timerId );
+ if ( twoStage ) {
+ center();
+ twoStage = FALSE;
+ timerId = startTimer( 1000 );
+ } else {
+ delete this;
+ }
+}
+
+
+MineSweep::MineSweep( QWidget* parent, const char* name, WFlags f )
+: QMainWindow( parent, name, f )
+{
+ srand(::time(0));
+ setCaption( tr("Mine Hunt") );
+ setIcon( Resource::loadPixmap( "minesweep_icon" ) );
+
+ QPEToolBar *menuToolBar = new QPEToolBar( this );
+ QPEMenuBar *menuBar = new QPEMenuBar( menuToolBar );
+
+ QPopupMenu *gameMenu = new QPopupMenu( this );
+ gameMenu->insertItem( tr("Beginner"), this, SLOT( beginner() ) );
+ gameMenu->insertItem( tr("Advanced"), this, SLOT( advanced() ) );
+ gameMenu->insertItem( tr("Expert"), this, SLOT( expert() ) );
+
+ menuBar->insertItem( tr("Game"), gameMenu );
+
+ QPEToolBar *toolBar = new QPEToolBar( this );
+ toolBar->setHorizontalStretchable( TRUE );
+
+ guessLCD = new QLCDNumber( toolBar );
+ toolBar->setStretchableWidget( guessLCD );
+
+ QPalette lcdPal( red );
+ lcdPal.setColor( QColorGroup::Background, QApplication::palette().active().background() );
+ lcdPal.setColor( QColorGroup::Button, QApplication::palette().active().button() );
+
+// guessLCD->setPalette( lcdPal );
+ guessLCD->setSegmentStyle( QLCDNumber::Flat );
+ guessLCD->setFrameStyle( QFrame::NoFrame );
+ guessLCD->setNumDigits( 2 );
+ guessLCD->setBackgroundMode( PaletteButton );
+ newGameButton = new QPushButton( toolBar );
+ newGameButton->setPixmap( QPixmap( pix_new ) );
+ newGameButton->setFocusPolicy(QWidget::NoFocus);
+ connect( newGameButton, SIGNAL(clicked()), this, SLOT(newGame()) );
+
+ timeLCD = new QLCDNumber( toolBar );
+// timeLCD->setPalette( lcdPal );
+ timeLCD->setSegmentStyle( QLCDNumber::Flat );
+ timeLCD->setFrameStyle( QFrame::NoFrame );
+ timeLCD->setNumDigits( 5 ); // "mm:ss"
+ timeLCD->setBackgroundMode( PaletteButton );
+
+ setToolBarsMovable ( FALSE );
+
+ addToolBar( menuToolBar );
+ addToolBar( toolBar );
+
+ QFrame *mainframe = new QFrame( this );
+ mainframe->setFrameShape( QFrame::Box );
+ mainframe->setFrameShadow( QFrame::Raised );
+ mainframe->setMargin(5);
+ mainframe->setLineWidth(2);
+ QBoxLayout *box = new QVBoxLayout( mainframe );
+ field = new MineField( mainframe );
+ box->addWidget( field, 0, AlignCenter );
+ QFont fnt = field->font();
+ fnt.setBold( TRUE );
+ field->setFont( QFont( fnt ) );
+ field->setFocus();
+ setCentralWidget( mainframe );
+
+ connect( field, SIGNAL( gameOver( bool ) ), this, SLOT( gameOver( bool ) ) );
+ connect( field, SIGNAL( mineCount( int ) ), this, SLOT( setCounter( int ) ) );
+ connect( field, SIGNAL( gameStarted()), this, SLOT( startPlaying() ) );
+
+ timer = new QTimer( this );
+
+ connect( timer, SIGNAL( timeout() ), this, SLOT( updateTime() ) );
+
+ readConfig();
+}
+
+MineSweep::~MineSweep()
+{
+ writeConfig();
+}
+
+void MineSweep::gameOver( bool won )
+{
+ field->showMines();
+ if ( won ) {
+ newGameButton->setPixmap( QPixmap( happy_xpm ) );
+ } else {
+ newGameButton->setPixmap( QPixmap( dead_xpm ) );
+ }
+ ResultIndicator::showResult( this, won );
+ timer->stop();
+}
+
+void MineSweep::newGame()
+{
+ newGame(field->level());
+}
+
+void MineSweep::newGame(int level)
+{
+ timeLCD->display( "0:00" );
+ field->setup( level );
+ newGameButton->setPixmap( QPixmap( pix_new ) );
+ timer->stop();
+}
+
+void MineSweep::startPlaying()
+{
+ newGameButton->setPixmap( QPixmap( worried_xpm ) );
+ starttime = QDateTime::currentDateTime();
+ timer->start( 1000 );
+}
+
+void MineSweep::beginner()
+{
+ newGame(1);
+}
+
+void MineSweep::advanced()
+{
+ newGame(2);
+}
+
+void MineSweep::expert()
+{
+ newGame(3);
+}
+
+void MineSweep::setCounter( int c )
+{
+ if ( !guessLCD )
+ return;
+
+ guessLCD->display( c );
+}
+
+void MineSweep::updateTime()
+{
+ if ( !timeLCD )
+ return;
+
+ int s = starttime.secsTo(QDateTime::currentDateTime());
+ if ( s/60 > 99 )
+ timeLCD->display( "-----" );
+ else
+ timeLCD->display( QString().sprintf("%2d:%02d",s/60,s%60) );
+}
+
+void MineSweep::writeConfig() const
+{
+ Config cfg("MineSweep");
+ cfg.setGroup("Panel");
+ cfg.writeEntry("Time",
+ timer->isActive() ? starttime.secsTo(QDateTime::currentDateTime()) : -1);
+ field->writeConfig(cfg);
+}
+
+void MineSweep::readConfig()
+{
+ Config cfg("MineSweep");
+ field->readConfig(cfg);
+ cfg.setGroup("Panel");
+ int s = cfg.readNumEntry("Time",-1);
+ if ( s<0 ) {
+ newGame();
+ } else {
+ startPlaying();
+ starttime = QDateTime::currentDateTime().addSecs(-s);
+ updateTime();
+ }
+}
diff --git a/noncore/games/minesweep/minesweep.h b/noncore/games/minesweep/minesweep.h
new file mode 100644
index 0000000..e860573
--- a/dev/null
+++ b/noncore/games/minesweep/minesweep.h
@@ -0,0 +1,67 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef MINESWEEP_H
+#define MINESWEEP_H
+
+#include <qmainwindow.h>
+#include <qdatetime.h>
+
+class MineField;
+class QLCDNumber;
+class QPushButton;
+
+class MineSweep : public QMainWindow
+{
+ Q_OBJECT
+public:
+ MineSweep( QWidget* parent = 0, const char* name = 0, WFlags f = 0 );
+ ~MineSweep();
+
+public slots:
+ void gameOver( bool won );
+ void newGame();
+
+protected slots:
+ void setCounter( int );
+ void updateTime();
+
+ void beginner();
+ void advanced();
+ void expert();
+
+private slots:
+ void startPlaying();
+
+private:
+ void readConfig();
+ void writeConfig() const;
+
+ void newGame(int);
+ MineField* field;
+ QLCDNumber* guessLCD;
+ QLCDNumber* timeLCD;
+ QPushButton* newGameButton;
+
+ QDateTime starttime;
+ QTimer* timer;
+};
+
+#endif // MINESWEEP_H
+
diff --git a/noncore/games/minesweep/minesweep.pro b/noncore/games/minesweep/minesweep.pro
new file mode 100644
index 0000000..87484bc
--- a/dev/null
+++ b/noncore/games/minesweep/minesweep.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+CONFIG = qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = minefield.h \
+ minesweep.h
+SOURCES = main.cpp \
+ minefield.cpp \
+ minesweep.cpp
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+INTERFACES =
+
+TRANSLATIONS = ../i18n/de/minesweep.ts
diff --git a/noncore/games/minesweep/qpe-minesweep.control b/noncore/games/minesweep/qpe-minesweep.control
new file mode 100644
index 0000000..36bc221
--- a/dev/null
+++ b/noncore/games/minesweep/qpe-minesweep.control
@@ -0,0 +1,9 @@
+Files: bin/minesweep apps/Games/minesweep.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: find the mines
+ A game for the Qtopia environment.
diff --git a/noncore/games/parashoot/.cvsignore b/noncore/games/parashoot/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/noncore/games/parashoot/.cvsignore
@@ -0,0 +1,3 @@
+moc_*
+*.moc
+Makefile
diff --git a/noncore/games/parashoot/Makefile.in b/noncore/games/parashoot/Makefile.in
new file mode 100644
index 0000000..ff7397e
--- a/dev/null
+++ b/noncore/games/parashoot/Makefile.in
@@ -0,0 +1,203 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = parashoot
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = interface.h \
+ man.h \
+ cannon.h \
+ base.h \
+ bullet.h \
+ helicopter.h
+SOURCES = main.cpp \
+ interface.cpp \
+ man.cpp \
+ cannon.cpp \
+ base.cpp \
+ bullet.cpp \
+ helicopter.cpp
+OBJECTS = main.o \
+ interface.o \
+ man.o \
+ cannon.o \
+ base.o \
+ bullet.o \
+ helicopter.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_interface.cpp \
+ moc_cannon.cpp \
+ moc_bullet.cpp
+OBJMOC = moc_interface.o \
+ moc_cannon.o \
+ moc_bullet.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake parashoot.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+main.o: main.cpp \
+ interface.h \
+ cannon.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ base.h \
+ helicopter.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+interface.o: interface.cpp \
+ interface.h \
+ cannon.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ base.h \
+ helicopter.h \
+ man.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h
+
+man.o: man.cpp \
+ codes.h \
+ man.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ base.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+cannon.o: cannon.cpp \
+ $(QPEDIR)/include/qpe/resource.h \
+ codes.h \
+ cannon.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h
+
+base.o: base.cpp \
+ codes.h \
+ base.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ man.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+bullet.o: bullet.cpp \
+ codes.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ man.h \
+ helicopter.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/qmath.h
+
+helicopter.o: helicopter.cpp \
+ helicopter.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ man.h \
+ codes.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+moc_interface.o: moc_interface.cpp \
+ interface.h \
+ cannon.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h \
+ base.h \
+ helicopter.h
+
+moc_cannon.o: moc_cannon.cpp \
+ cannon.h \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h
+
+moc_bullet.o: moc_bullet.cpp \
+ bullet.h \
+ $(QPEDIR)/include/qpe/sound.h
+
+moc_interface.cpp: interface.h
+ $(MOC) interface.h -o moc_interface.cpp
+
+moc_cannon.cpp: cannon.h
+ $(MOC) cannon.h -o moc_cannon.cpp
+
+moc_bullet.cpp: bullet.h
+ $(MOC) bullet.h -o moc_bullet.cpp
+
+
diff --git a/noncore/games/parashoot/base.cpp b/noncore/games/parashoot/base.cpp
new file mode 100644
index 0000000..c03802f
--- a/dev/null
+++ b/noncore/games/parashoot/base.cpp
@@ -0,0 +1,71 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "codes.h"
+#include "base.h"
+#include "man.h"
+
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+int damage;
+
+Base::Base(QCanvas* canvas) :
+ QCanvasSprite(0, canvas),
+ kaboom("landmine"),
+ ohdear("crmble01")
+{
+ basearray = new QCanvasPixmapArray();
+ QString b0 = Resource::findPixmap("parashoot/b0001");
+ b0.replace(QRegExp("0001"),"%1");
+ basearray->readPixmaps(b0, 4);
+ setSequence(basearray);
+ setFrame(0);
+ move(2, canvas->height()-50);
+ setZ(10);
+ show();
+ damage = 0;
+}
+
+void Base::damageBase()
+{
+ damage++;
+
+ switch(damage) {
+ case 1: setFrame(1); ohdear.play(); break;
+ case 2: setFrame(2); ohdear.play(); break;
+ case 3: setFrame(3); kaboom.play(); break;
+ }
+ show();
+}
+
+bool Base::baseDestroyed()
+{
+ return (damage >= 3);
+}
+
+Base::~Base()
+{
+}
+
+int Base::rtti() const
+{
+ return base_rtti;
+}
diff --git a/noncore/games/parashoot/base.h b/noncore/games/parashoot/base.h
new file mode 100644
index 0000000..ee7f166
--- a/dev/null
+++ b/noncore/games/parashoot/base.h
@@ -0,0 +1,38 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qpe/sound.h>
+
+#include <qcanvas.h>
+
+class Base : public QCanvasSprite
+{
+
+public:
+ Base(QCanvas*);
+ ~Base();
+ void damageBase();
+ int rtti() const;
+ static bool baseDestroyed();
+
+private:
+ QCanvasPixmapArray* basearray;
+ Sound kaboom, ohdear;
+};
diff --git a/noncore/games/parashoot/bullet.cpp b/noncore/games/parashoot/bullet.cpp
new file mode 100644
index 0000000..584f564
--- a/dev/null
+++ b/noncore/games/parashoot/bullet.cpp
@@ -0,0 +1,142 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "codes.h"
+#include "bullet.h"
+#include "man.h"
+#include "helicopter.h"
+
+#include <qpe/resource.h>
+#include <qpe/qmath.h>
+
+
+int limit;
+int shotcount;
+int nobullets;
+
+Bullet::Bullet(QCanvas* canvas, double angle, int cannonx, int cannony) :
+ QCanvasSprite(0, canvas),
+ bang("collide01")
+{
+ QCanvasPixmapArray* bulletarray = new QCanvasPixmapArray(Resource::findPixmap("parashoot/bullet"));
+ setSequence(bulletarray);
+ if (nobullets < limit) {
+ nobullets++;
+ move(cannonx, cannony);
+ dy = 0;
+ dx = 0;
+ show();
+ setXY(angle);
+ setVelocity(-dx, -dy);
+ bang.play();
+ } else
+ return;
+}
+
+void Bullet::setXY(double angle)
+{
+ double ang = angle;
+ if ( (y() < 0) || (x() < 0) || (y() > canvas()->height()) ||
+ (x() > canvas()->width()) )
+ delete this;
+ else {
+ double radians = 0;
+ radians = ang * 3.14159265/180;
+ dx = (qCos(radians)) *7;
+ dy = (qSin(radians)) *7;
+ }
+}
+
+void Bullet::setLimit(int amount)
+{
+ limit = amount;
+}
+
+void Bullet::setNobullets(int amount)
+{
+ nobullets = amount;
+}
+
+void Bullet::checkCollision()
+{
+ QCanvasItem* item;
+ QCanvasItemList l=collisions(FALSE);
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ item = *it;
+ if ( (item->rtti()== 1500) && (item->collidesWith(this)) ) {
+ Man* deadman = (Man*)item;
+ if (deadman->frame() != 5) return;
+ deadman->done();
+ emit score(10);
+ setShotCount(shotcount+1);
+ setAnimated(false);
+ nobullets--;
+ delete this;
+ return;
+ }
+ else if ( (item->rtti()==1900) && (item->collidesWith(this)) ) {
+ Helicopter* deadchopper = (Helicopter*) item;
+ deadchopper->done();
+ emit score(50);
+ setAnimated(false);
+ nobullets--;
+ delete this;
+ return;
+ }
+ }
+ //check shot is not out of bounds
+ if ( (y() < 0) || (x() < 0) ||
+ (y() > canvas()->height()) ||
+ ( x() > canvas()->width())) {
+ setAnimated(false);
+ nobullets--;
+ delete this;
+ return;
+ }
+}
+
+void Bullet::advance(int phase)
+{
+ QCanvasSprite::advance(phase);
+
+ if (phase == 0)
+ checkCollision();
+
+}
+
+int Bullet::getShotCount()
+{
+ return shotcount;
+}
+
+void Bullet::setShotCount(int amount)
+{
+ shotcount = amount;
+}
+
+Bullet::~Bullet()
+{
+
+}
+
+int Bullet::rtti() const
+{
+ return bullet_rtti;
+}
diff --git a/noncore/games/parashoot/bullet.h b/noncore/games/parashoot/bullet.h
new file mode 100644
index 0000000..7d15899
--- a/dev/null
+++ b/noncore/games/parashoot/bullet.h
@@ -0,0 +1,51 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qpe/sound.h>
+
+#include <qtimer.h>
+#include <qcanvas.h>
+
+#include <math.h>
+
+class Bullet : public QObject, public QCanvasSprite
+{
+ Q_OBJECT
+public:
+ Bullet(QCanvas*, double angle, int cannonx, int cannony);
+ ~Bullet();
+ void setXY(double angle);
+ void checkCollision();
+ void advance(int phase);
+ int rtti() const;
+ static int getShotCount();
+ static void setShotCount(int amount);
+ static void setLimit(int amount);
+ static void setNobullets(int amount);
+
+signals:
+ void score(int);
+
+private:
+ double dx;
+ double dy;
+ int damage;
+ Sound bang;
+};
diff --git a/noncore/games/parashoot/cannon.cpp b/noncore/games/parashoot/cannon.cpp
new file mode 100644
index 0000000..3c0a5fe
--- a/dev/null
+++ b/noncore/games/parashoot/cannon.cpp
@@ -0,0 +1,140 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+#include "codes.h"
+#include "cannon.h"
+
+Cannon::Cannon(QCanvas* canvas) :
+ QCanvasSprite(0, canvas)
+{
+shotsfired=0;
+ index = 8;
+ cannonx = 0;
+ cannony = 0;
+ cannonarray = new QCanvasPixmapArray();
+ QString c0 = Resource::findPixmap("parashoot/can0001");
+ c0.replace(QRegExp("0001"),"%1");
+ cannonarray->readPixmaps(c0,17);
+ setSequence(cannonarray);
+ setFrame(index);
+ move(canvas->width()/2-20, canvas->height()-32);
+ // co ords for barrel of cannon when upright
+ barrelypos = canvas->height()-32;
+ barrelxpos = canvas->width()/2;
+ movedir = NoDir;
+ moveDelay = 0;
+ setAnimated(TRUE);
+ show();
+}
+
+void Cannon::advance(int stage)
+{
+ if ( stage == 1 && moveDelay-- == 0 ) {
+ if (movedir == Left) {
+ if (index > 0) {
+ setFrame(index-1);
+ index--;
+ }
+ }
+ if (movedir == Right) {
+ if (index < 16) {
+ setFrame(index+1);
+ index++;
+ }
+ }
+ moveDelay = 0;
+ }
+}
+
+void Cannon::pointCannon(Direction dir)
+{
+ movedir = dir;
+ moveDelay = 0;
+ advance(1);
+ moveDelay = 1;
+}
+
+void Cannon::setCoords()
+{
+ switch(index) {
+ case 0: cannonx = barrelxpos-29; cannony = barrelypos-8; break;
+ case 1: cannonx = barrelxpos-27; cannony = barrelypos-8; break;
+ case 2: cannonx = barrelxpos-25; cannony = barrelypos-6; break;
+ case 3: cannonx = barrelxpos-23; cannony = barrelypos-4; break;
+ case 4: cannonx = barrelxpos-21; cannony = barrelypos-2; break;
+ case 5: cannonx = barrelxpos-19; cannony = barrelypos; break;
+ case 6: cannonx = barrelxpos-15; cannony = barrelypos; break;
+ case 7: cannonx = barrelxpos-10; cannony = barrelypos; break;
+ case 8: cannonx = barrelxpos; cannony = barrelypos; break;
+ case 9: cannonx = barrelxpos+2; cannony = barrelypos; break;
+ case 10: cannonx = barrelxpos+6; cannony = barrelypos; break;
+ case 11: cannonx = barrelxpos+8; cannony = barrelypos; break;
+ case 12: cannonx = barrelxpos+12; cannony = barrelypos-2; break;
+ case 13: cannonx = barrelxpos+18; cannony = barrelypos-4; break;
+ case 14: cannonx = barrelxpos+22; cannony = barrelypos-6; break;
+ case 15: cannonx = barrelxpos+26; cannony = barrelypos-8; break;
+ case 16: cannonx = barrelxpos+28; cannony = barrelypos-8; break;
+ }
+}
+
+double Cannon::shootAngle()
+{
+ switch(index) {
+ case 0: return 30.0;
+ case 1: return 37.5;
+ case 2: return 45.0;
+ case 3: return 52.5;
+ case 4: return 60.0;
+ case 5: return 67.5;
+ case 6: return 75.0;
+ case 7: return 82.5;
+ case 8: return 90.0;
+ case 9: return 97.5;
+ case 10: return 105.0;
+ case 11: return 112.5;
+ case 12: return 120.0;
+ case 13: return 127.5;
+ case 14: return 135.0;
+ case 15: return 142.5;
+ case 16: return 150.0;
+ }
+ return 0;
+}
+
+void Cannon::shoot()
+{
+ setCoords();
+ Bullet* bullet = new Bullet(canvas(), shootAngle(), cannonx, cannony);
+ connect(bullet, SIGNAL(score(int)), this, SIGNAL(score(int)));
+ shotsfired++;
+}
+
+Cannon::~Cannon()
+{
+}
+
+int Cannon::rtti() const
+{
+ return cannon_rtti;
+}
diff --git a/noncore/games/parashoot/cannon.h b/noncore/games/parashoot/cannon.h
new file mode 100644
index 0000000..44d0c65
--- a/dev/null
+++ b/noncore/games/parashoot/cannon.h
@@ -0,0 +1,58 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qcanvas.h>
+
+#include "bullet.h"
+
+class Cannon : public QObject, public QCanvasSprite
+{
+ Q_OBJECT
+
+public:
+ Cannon(QCanvas*); //create cannon
+ ~Cannon(); //destroy cannon
+
+ enum Direction{ Left, Right, NoDir };
+
+ void pointCannon(Direction dir);
+ void setCoords();
+ double shootAngle();
+ void shoot();
+ int rtti() const;
+
+int shotsFired() { return shotsfired; };
+
+protected:
+ void advance(int stage);
+
+signals:
+ void score(int);
+
+private:
+ QCanvasPixmapArray* cannonarray;
+ int index;
+ int cannonx;
+ int cannony;
+ int barrelxpos;
+ int barrelypos;
+ int moveDelay;
+ Direction movedir;
+ int shotsfired;
+};
diff --git a/noncore/games/parashoot/codes.h b/noncore/games/parashoot/codes.h
new file mode 100644
index 0000000..68acb3f
--- a/dev/null
+++ b/noncore/games/parashoot/codes.h
@@ -0,0 +1,25 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+const int man_rtti = 1500;
+const int bullet_rtti = 1600;
+const int cannon_rtti = 1700;
+const int base_rtti = 1800;
+const int helicopter_rtti = 1900;
diff --git a/noncore/games/parashoot/helicopter.cpp b/noncore/games/parashoot/helicopter.cpp
new file mode 100644
index 0000000..0923124
--- a/dev/null
+++ b/noncore/games/parashoot/helicopter.cpp
@@ -0,0 +1,114 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "helicopter.h"
+#include "man.h"
+#include "codes.h"
+
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+static QList<Helicopter> all;
+
+Helicopter::Helicopter(QCanvas* canvas) :
+ QCanvasSprite(0, canvas),
+ chikachika("aland01")
+{
+ all.append(this);
+ hits = 0;
+ QCanvasPixmapArray* helicopterarray = new QCanvasPixmapArray();
+ QString h0 = Resource::findPixmap("parashoot/helicopter0001");
+ h0.replace(QRegExp("0001"),"%1");
+ helicopterarray->readPixmaps(h0,3 );
+ setSequence(helicopterarray);
+ setAnimated(true);
+ move(canvas->width(), 5);
+ setVelocity(-2, 0);
+ chikachika.playLoop();
+ show();
+}
+
+Helicopter::~Helicopter()
+{
+ all.remove(this);
+}
+
+int fr = 0;
+
+void Helicopter::advance(int phase)
+{
+ QCanvasSprite::advance(phase);
+ if (phase == 0) {
+ setFrame(fr%3);
+ fr++;
+ checkCollision();
+ }
+}
+
+void Helicopter::checkCollision()
+{
+ if (x() == 6) {
+ setAnimated(false); //setVelocity(0, 0);
+ dropman();
+ }
+ if (x() < 0)
+ done();
+}
+
+void Helicopter::dropman()
+{
+ (void)new Man(canvas(), 15, 25);
+ (void)new Man(canvas(), 35, 25);
+ takeOff();
+}
+
+void Helicopter::done()
+{
+ hits++;
+ if (hits >= 2) {
+ setAnimated(false);
+ delete this;
+ }
+}
+
+void Helicopter::takeOff()
+{
+ setVelocity(-1, 0);
+}
+
+int Helicopter::rtti() const
+{
+ return helicopter_rtti;
+}
+
+void Helicopter::silenceAll()
+{
+ for (Helicopter* h = all.first(); h; h = all.next())
+ h->chikachika.stop();
+}
+
+void Helicopter::deleteAll()
+{
+ Helicopter* h;
+ while ((h = all.first()))
+ delete h;
+}
+
diff --git a/noncore/games/parashoot/helicopter.h b/noncore/games/parashoot/helicopter.h
new file mode 100644
index 0000000..5cb92de
--- a/dev/null
+++ b/noncore/games/parashoot/helicopter.h
@@ -0,0 +1,45 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qpe/sound.h>
+
+#include <qcanvas.h>
+
+class Helicopter : public QCanvasSprite
+{
+
+public:
+ Helicopter(QCanvas*);
+ ~Helicopter();
+ void advance(int phase);
+ void checkCollision();
+ void dropman();
+ void takeOff();
+ void done();
+
+ static void silenceAll();
+ static void deleteAll();
+
+ int rtti() const;
+
+private:
+ int hits;
+ Sound chikachika;
+};
diff --git a/noncore/games/parashoot/interface.cpp b/noncore/games/parashoot/interface.cpp
new file mode 100644
index 0000000..84e5e60
--- a/dev/null
+++ b/noncore/games/parashoot/interface.cpp
@@ -0,0 +1,247 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "interface.h"
+#include "man.h"
+
+#include <qpe/resource.h>
+
+#include <qlabel.h>
+#include <qmessagebox.h>
+#include <qapplication.h>
+#include <qstyle.h>
+#include <qpe/qpetoolbar.h>
+#include <qtoolbutton.h>
+
+ParaShoot::ParaShoot(QWidget* parent, const char* name, WFlags f) :
+ QMainWindow(parent,name,f),
+ canvas(232, 258),
+ fanfare("level_up"),
+ score(0)
+{
+ canvas.setAdvancePeriod(80);
+ QPixmap bg = Resource::loadPixmap("parashoot/sky");
+ canvas.setBackgroundPixmap(bg);
+
+ pb = new QCanvasView(&canvas, this);
+ pb->setFocus();
+
+ setToolBarsMovable( FALSE );
+
+ QPEToolBar* toolbar = new QPEToolBar(this);
+ toolbar->setHorizontalStretchable( TRUE );
+
+ setCaption( tr("ParaShoot") );
+ QPixmap newicon = Resource::loadPixmap("parashoot/manicon");
+ setIcon(newicon);
+ new QToolButton(newicon, tr("New Game"), 0,
+ this, SLOT(newGame()), toolbar, "New Game");
+
+ levelscore = new QLabel(toolbar);
+ levelscore->setBackgroundMode( PaletteButton );
+ levelscore->setAlignment( AlignRight | AlignVCenter | ExpandTabs );
+ toolbar->setStretchableWidget( levelscore );
+ showScore(0,0);
+
+ setCentralWidget(pb);
+
+ autoDropTimer = new QTimer(this);
+ connect (autoDropTimer, SIGNAL(timeout()), this, SLOT(play()) );
+
+ pauseTimer = new QTimer(this);
+ connect(pauseTimer, SIGNAL(timeout()), this, SLOT(wait()) );
+
+ setFocusPolicy(StrongFocus);
+
+ newGame();
+}
+
+
+void ParaShoot::resizeEvent(QResizeEvent *)
+{
+ QSize s = centralWidget()->size();
+ int fw = style().defaultFrameWidth();
+ canvas.resize( s.width() - fw - 2, s.height() - fw - 2);
+}
+
+
+void ParaShoot::showScore( int score, int level )
+{
+ levelscore->setText(tr(" Level: %1 Score: %2 ").arg(score).arg(level) );
+}
+
+
+void ParaShoot::newGame()
+{
+ clear();
+ if (pauseTimer->isActive())
+ pauseTimer->stop();
+ clear();
+ Man::setManCount(0);
+ score = 0;
+ Bullet::setShotCount(0);
+ Bullet::setNobullets(0);
+ nomen = 2;
+ Bullet::setLimit(nomen);
+ level = 0;
+ updatespeed = 80;
+ showScore(0,0);
+ gamestopped = false;
+ Helicopter::deleteAll();
+ waitover = true;
+ base = new Base(&canvas);
+ cannon = new Cannon(&canvas);
+ connect( cannon, SIGNAL(score(int)), this, SLOT(increaseScore(int)));
+ autoDropTimer->start(100);
+}
+
+
+void ParaShoot::clear()
+{
+ autoDropTimer->stop();
+// QCanvasItem* item;
+ QCanvasItemList l = canvas.allItems();
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ delete *it;
+ }
+}
+
+void ParaShoot::gameOver()
+{
+ QCanvasItem* item;
+ QCanvasItemList l = canvas.allItems();
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ item = *it;
+ if ((item->rtti()==1500) || (item->rtti()==1600) || item->rtti()==1900)
+ item->setAnimated(false);
+ }
+ autoDropTimer->stop();
+ Helicopter::silenceAll();
+
+ int shots = Bullet::getShotCount();
+
+ int shotsFired = cannon->shotsFired();
+ if ( shotsFired == 0 )
+ shotsFired = 1;
+ QCanvasText* gameover = new QCanvasText(
+ tr( " GAME OVER!\n"
+ " Your Score: %1\n"
+ " Parachuters Killed: %2\n"
+ " Accuracy: %3% " ).arg(score).arg(shots).arg(shots * 100 / shotsFired ),
+ &canvas);
+ gameover->setColor(red);
+ gameover->setFont( QFont("times", 18, QFont::Bold) );
+ gameover->move(canvas.width()/2 -110, canvas.height()/2 -50);
+ gameover->setZ(500);
+ gameover->show();
+ gamestopped = true;
+ waitover = false;
+ pauseTimer->start(3000);
+}
+
+void ParaShoot::wait()
+{
+ waitover = true;
+ pauseTimer->stop();
+}
+
+void ParaShoot::play()
+{
+ if (Man::getManCount() < nomen ) {
+ new Man(&canvas);
+ }
+ if (Base::baseDestroyed()) {
+ gameOver();
+ return;
+ }
+}
+
+void ParaShoot::increaseScore(int x)
+{
+ score += x;
+ if ( score / 150 != (score-x) / 150 )
+ levelUp();
+ showScore(level,score);
+}
+
+void ParaShoot::levelUp()
+{
+ level++;
+ int stage = level % 3;
+ switch(stage) {
+ case 0:
+ nomen++;
+ Bullet::setLimit(nomen);
+ fanfare.play();
+ break;
+ case 1:
+ new Helicopter(&canvas);
+ break;
+ case 2:
+ moveFaster();
+ fanfare.play();
+ break;
+ default: return;
+ }
+}
+
+void ParaShoot::moveFaster()
+{
+ if (updatespeed > 50)
+ updatespeed = updatespeed-5;
+ else
+ updatespeed = updatespeed-3;
+ canvas.setAdvancePeriod(updatespeed);
+}
+
+void ParaShoot::keyPressEvent(QKeyEvent* event)
+{
+ if (gamestopped) {
+ if (waitover)
+ newGame();
+ else
+ return;
+ } else {
+ switch(event->key()) {
+ case Key_Up:
+ case Key_F1:
+ case Key_F9:
+ case Key_Space:
+ cannon->shoot();
+ break;
+ case Key_Left:
+ cannon->pointCannon(Cannon::Left);
+ lastcannonkey=Key_Left;
+ break;
+ case Key_Right:
+ cannon->pointCannon(Cannon::Right);
+ lastcannonkey=Key_Right;
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+void ParaShoot::keyReleaseEvent(QKeyEvent* event)
+{
+ if ( lastcannonkey == event->key() )
+ cannon->pointCannon(Cannon::NoDir);
+}
diff --git a/noncore/games/parashoot/interface.h b/noncore/games/parashoot/interface.h
new file mode 100644
index 0000000..3f36d0b
--- a/dev/null
+++ b/noncore/games/parashoot/interface.h
@@ -0,0 +1,79 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "cannon.h"
+#include "base.h"
+#include "helicopter.h"
+
+#include <qpe/sound.h>
+
+#include <qmainwindow.h>
+#include <qtimer.h>
+#include <qlabel.h>
+
+class QCanvas;
+class Helicopter;
+
+//enum Direction{
+// left, right, up, down };
+
+class ParaShoot : public QMainWindow {
+ Q_OBJECT
+
+public:
+ ParaShoot(QWidget* parent=0, const char* name=0, WFlags f=0);
+
+ void clear();
+ void gameOver();
+ int mancount;
+ void levelUp();
+ void moveFaster();
+
+protected:
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void keyReleaseEvent(QKeyEvent*);
+ virtual void resizeEvent(QResizeEvent *e);
+
+private slots:
+ void increaseScore(int);
+ void newGame();
+ void play();
+ void wait();
+
+private:
+ void showScore( int score, int level );
+ QCanvasView* pb;
+ QCanvas canvas;
+ Cannon* cannon;
+ Base* base;
+ QCanvasText* gameover;
+ QLabel* levelscore;
+ int nomen;
+ int level;
+ int oldscore;
+ int updatespeed;
+ QTimer* autoDropTimer;
+ QTimer* pauseTimer;
+ bool gamestopped;
+ bool waitover;
+ Sound fanfare;
+ int score;
+ int lastcannonkey;
+};
diff --git a/noncore/games/parashoot/main.cpp b/noncore/games/parashoot/main.cpp
new file mode 100644
index 0000000..60eea18
--- a/dev/null
+++ b/noncore/games/parashoot/main.cpp
@@ -0,0 +1,36 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "interface.h"
+
+#include <qpe/qpeapplication.h>
+
+int main(int argc, char **argv)
+{
+ QPEApplication app(argc,argv);
+
+ QPEApplication::grabKeyboard();
+
+ ParaShoot m;
+ QPEApplication::setInputMethodHint( &m, QPEApplication::AlwaysOff );
+ app.showMainWidget(&m);
+
+ return app.exec();
+}
diff --git a/noncore/games/parashoot/man.cpp b/noncore/games/parashoot/man.cpp
new file mode 100644
index 0000000..8435572
--- a/dev/null
+++ b/noncore/games/parashoot/man.cpp
@@ -0,0 +1,174 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "codes.h"
+#include "man.h"
+#include "base.h"
+
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+int mancount;
+
+Man::Man(QCanvas* canvas) :
+ QCanvasSprite(0, canvas),
+ splat("lose")
+{
+ manarray = new QCanvasPixmapArray();
+ QString m0 = Resource::findPixmap("parashoot/man0001");
+ m0.replace(QRegExp("0001"),"%1");
+ manarray->readPixmaps(m0, 7);
+ setSequence(manarray);
+ setAnimated(true);
+ mancount++;
+ dead = false;
+ start();
+}
+
+Man::Man(QCanvas* canvas, int x, int y) :
+ QCanvasSprite(0, canvas),
+ splat("bang")
+{
+ manarray = new QCanvasPixmapArray();
+ QString m0 = Resource::findPixmap("parashoot/man0001");
+ m0.replace(QString("0001"),"%1");
+ manarray->readPixmaps(m0, 7);
+ setSequence(manarray);
+ move(x, y);
+ setFrame(5);
+ setZ(300);
+ show();
+
+ static bool first_time = TRUE;
+ if (first_time) {
+ first_time = FALSE;
+ QTime midnight(0, 0, 0);
+ srand(midnight.secsTo(QTime::currentTime()) );
+ }
+ int yfallspeed = 0;
+ yfallspeed = (rand() % 3) + 1;
+ setVelocity(0, yfallspeed);
+
+ mancount++;
+ dead = false;
+}
+int f = 0;
+
+void Man::advance(int phase)
+{
+ QCanvasSprite::advance(phase);
+ if (phase == 0) {
+ checkCollision();
+ if (dead) {
+ if (count < 10) {
+ setFrame(6);
+ setVelocity(0,0);
+ count++;
+ } else {
+ delete this;
+ return;
+ }
+ }
+ if (y() > canvas()->height()-43) {
+ setFrame(f%5);
+ f++;
+ move(x(), canvas()->height()-26);
+ setVelocity(-2, 0);
+ }
+ }
+}
+
+void Man::setInitialCoords()
+{
+ static bool first_time = TRUE;
+ if (first_time) {
+ first_time = FALSE;
+ QTime midnight(0, 0, 0);
+ srand(midnight.secsTo(QTime::currentTime()) );
+ }
+ dx = rand() % (canvas()->width()-16);
+ dy = -43; //height of a man off the screen
+}
+
+//check if man has reached the base
+void Man::checkCollision()
+{
+ if ( (x() < 23) && (y() == canvas()->height()-26)) {
+ QCanvasItem* item;
+ QCanvasItemList l=collisions(FALSE);
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ item = *it;
+ if ( (item->rtti()== 1800) && (item->collidesWith(this)) ) {
+ Base* base = (Base*) item;
+ base->damageBase();
+ start();
+ }
+ }
+ }
+}
+
+void Man::start()
+{
+ setInitialCoords();
+ move(dx, dy);
+ setFrame(5);
+ setZ(300);
+ show();
+
+ static bool first_time = TRUE;
+ if (first_time) {
+ first_time = FALSE;
+ QTime midnight(0, 0, 0);
+ srand(midnight.secsTo(QTime::currentTime()) );
+ }
+ int yfallspeed = 0;
+ yfallspeed = (rand() % 3) + 1;
+ setVelocity(0, yfallspeed);
+}
+
+void Man::done()
+{
+ splat.play();
+ count = 0;
+ dead = true;
+ setFrame(6);
+}
+
+int Man::getManCount()
+{
+ return mancount;
+}
+
+void Man::setManCount(int count)
+{
+ mancount = count;
+}
+
+
+int Man::rtti() const
+{
+ return man_rtti;
+}
+
+Man::~Man()
+{
+ mancount--;
+}
diff --git a/noncore/games/parashoot/man.h b/noncore/games/parashoot/man.h
new file mode 100644
index 0000000..e48fc20
--- a/dev/null
+++ b/noncore/games/parashoot/man.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qpe/sound.h>
+
+#include <qcanvas.h>
+#include <qdatetime.h>
+
+#include <stdlib.h>
+
+class Man : public QCanvasSprite
+{
+
+public:
+ Man (QCanvas*);
+ Man (QCanvas*, int x, int y);
+ ~Man();
+ void advance(int phase);
+ void setInitialCoords();
+ void checkCollision();
+ void start();
+ void done();
+ static int getManCount();
+ static void setManCount(int count);
+ int rtti() const;
+// int mancount;
+
+private:
+ QCanvasPixmapArray* manarray;
+ int dx;
+ int dy;
+ bool dead;
+ int count;
+ Sound splat;
+};
diff --git a/noncore/games/parashoot/parashoot.pro b/noncore/games/parashoot/parashoot.pro
new file mode 100644
index 0000000..631560b
--- a/dev/null
+++ b/noncore/games/parashoot/parashoot.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = interface.h man.h cannon.h base.h bullet.h helicopter.h
+SOURCES = main.cpp interface.cpp man.cpp cannon.cpp base.cpp bullet.cpp helicopter.cpp
+TARGET = parashoot
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+TRANSLATIONS = ../i18n/de/parashoot.ts
diff --git a/noncore/games/parashoot/qpe-parashoot.control b/noncore/games/parashoot/qpe-parashoot.control
new file mode 100644
index 0000000..82e9421
--- a/dev/null
+++ b/noncore/games/parashoot/qpe-parashoot.control
@@ -0,0 +1,9 @@
+Files: bin/parashoot apps/Games/parashoot.desktop pics/parashoot
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: shoot the parachutists
+ A game for the Qtopia environment.
diff --git a/noncore/games/qasteroids/.cvsignore b/noncore/games/qasteroids/.cvsignore
new file mode 100644
index 0000000..c152c55
--- a/dev/null
+++ b/noncore/games/qasteroids/.cvsignore
@@ -0,0 +1,2 @@
+moc_*.cpp
+Makefile
diff --git a/noncore/games/qasteroids/Makefile.in b/noncore/games/qasteroids/Makefile.in
new file mode 100644
index 0000000..7312743
--- a/dev/null
+++ b/noncore/games/qasteroids/Makefile.in
@@ -0,0 +1,155 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = qasteroids
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = ledmeter.h \
+ sprites.h \
+ toplevel.h \
+ view.h
+SOURCES = ledmeter.cpp \
+ toplevel.cpp \
+ view.cpp \
+ main.cpp
+OBJECTS = ledmeter.o \
+ toplevel.o \
+ view.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_ledmeter.cpp \
+ moc_toplevel.cpp \
+ moc_view.cpp
+OBJMOC = moc_ledmeter.o \
+ moc_toplevel.o \
+ moc_view.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake qasteroids.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+ledmeter.o: ledmeter.cpp \
+ ledmeter.h
+
+toplevel.o: toplevel.cpp \
+ toplevel.h \
+ view.h \
+ sprites.h \
+ ledmeter.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+view.o: view.cpp \
+ view.h \
+ sprites.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+main.o: main.cpp \
+ toplevel.h \
+ view.h \
+ sprites.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_ledmeter.o: moc_ledmeter.cpp \
+ ledmeter.h
+
+moc_toplevel.o: moc_toplevel.cpp \
+ toplevel.h \
+ view.h \
+ sprites.h
+
+moc_view.o: moc_view.cpp \
+ view.h \
+ sprites.h
+
+moc_ledmeter.cpp: ledmeter.h
+ $(MOC) ledmeter.h -o moc_ledmeter.cpp
+
+moc_toplevel.cpp: toplevel.h
+ $(MOC) toplevel.h -o moc_toplevel.cpp
+
+moc_view.cpp: view.h
+ $(MOC) view.h -o moc_view.cpp
+
+
diff --git a/noncore/games/qasteroids/ledmeter.cpp b/noncore/games/qasteroids/ledmeter.cpp
new file mode 100644
index 0000000..f4d4d1a
--- a/dev/null
+++ b/noncore/games/qasteroids/ledmeter.cpp
@@ -0,0 +1,135 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#include <qpainter.h>
+#include "ledmeter.h"
+
+KALedMeter::KALedMeter( QWidget *parent ) : QFrame( parent )
+{
+ mCRanges.setAutoDelete( TRUE );
+ mRange = 100;
+ mCount = 20;
+ mCurrentCount = 0;
+ mValue = 0;
+ setMinimumWidth( mCount * 2 + frameWidth() );
+}
+
+void KALedMeter::setRange( int r )
+{
+ mRange = r;
+ if ( mRange < 1 )
+ mRange = 1;
+ setValue( mValue );
+ update();
+}
+
+void KALedMeter::setCount( int c )
+{
+ mCount = c;
+ if ( mCount < 1 )
+ mCount = 1;
+ setMinimumWidth( mCount * 2 + frameWidth() );
+ calcColorRanges();
+ setValue( mValue );
+ update();
+}
+
+void KALedMeter::setValue( int v )
+{
+ mValue = v;
+ if ( mValue > mRange )
+ mValue = mRange;
+ else if ( mValue < 0 )
+ mValue = 0;
+ int c = ( mValue + mRange / mCount - 1 ) * mCount / mRange;
+ if ( c != mCurrentCount )
+ {
+ mCurrentCount = c;
+ update();
+ }
+}
+
+void KALedMeter::addColorRange( int pc, const QColor &c )
+{
+ ColorRange *cr = new ColorRange;
+ cr->mPc = pc;
+ cr->mColor = c;
+ mCRanges.append( cr );
+ calcColorRanges();
+}
+
+void KALedMeter::resizeEvent( QResizeEvent *e )
+{
+ QFrame::resizeEvent( e );
+ int w = ( width() - frameWidth() - 2 ) / mCount * mCount;
+ w += frameWidth() + 2;
+ setFrameRect( QRect( 0, 0, w, height() ) );
+}
+
+void KALedMeter::drawContents( QPainter *p )
+{
+ QRect b = contentsRect();
+
+ unsigned cidx = 0;
+ int ncol = mCount;
+ QColor col = colorGroup().foreground();
+
+ if ( !mCRanges.isEmpty() )
+ {
+ col = mCRanges.at( cidx )->mColor;
+ ncol = mCRanges.at( cidx )->mValue;
+ }
+ p->setBrush( col );
+ p->setPen( col );
+
+ int lw = b.width() / mCount;
+ int lx = b.left() + 1;
+ for ( int i = 0; i < mCurrentCount; i++, lx += lw )
+ {
+ if ( i > ncol )
+ {
+ if ( ++cidx < mCRanges.count() )
+ {
+ col = mCRanges.at( cidx )->mColor;
+ ncol = mCRanges.at( cidx )->mValue;
+ p->setBrush( col );
+ p->setPen( col );
+ }
+ }
+
+ p->drawRect( lx, b.top() + 1, lw - 1, b.height() - 2 );
+ }
+}
+
+void KALedMeter::calcColorRanges()
+{
+ int prev = 0;
+ ColorRange *cr;
+ for ( cr = mCRanges.first(); cr; cr = mCRanges.next() )
+ {
+ cr->mValue = prev + cr->mPc * mCount / 100;
+ prev = cr->mValue;
+ }
+}
+
diff --git a/noncore/games/qasteroids/ledmeter.h b/noncore/games/qasteroids/ledmeter.h
new file mode 100644
index 0000000..b2f06c1
--- a/dev/null
+++ b/noncore/games/qasteroids/ledmeter.h
@@ -0,0 +1,72 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#ifndef __LEDMETER_H__
+#define __LEDMETER_H__
+
+#include <qframe.h>
+#include <qlist.h>
+
+#define QPtrList QList
+
+class KALedMeter : public QFrame
+{
+ Q_OBJECT
+public:
+ KALedMeter( QWidget *parent );
+
+ int range() const { return mRange; }
+ void setRange( int r );
+
+ int count() const { return mCount; }
+ void setCount( int c );
+
+ int value () const { return mValue; }
+
+ void addColorRange( int pc, const QColor &c );
+
+public slots:
+ void setValue( int v );
+
+protected:
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void drawContents( QPainter * );
+ void calcColorRanges();
+
+protected:
+ struct ColorRange
+ {
+ int mPc;
+ int mValue;
+ QColor mColor;
+ };
+
+ int mRange;
+ int mCount;
+ int mCurrentCount;
+ int mValue;
+ QPtrList<ColorRange> mCRanges;
+};
+
+#endif
diff --git a/noncore/games/qasteroids/main.cpp b/noncore/games/qasteroids/main.cpp
new file mode 100644
index 0000000..7d1682c
--- a/dev/null
+++ b/noncore/games/qasteroids/main.cpp
@@ -0,0 +1,36 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "toplevel.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char *argv[] )
+{
+ QPEApplication app( argc, argv );
+
+ QPEApplication::grabKeyboard();
+
+ KAstTopLevel *mainWidget = new KAstTopLevel();
+ app.showMainWidget( mainWidget );
+
+ app.exec();
+}
+
diff --git a/noncore/games/qasteroids/qasteroids.pro b/noncore/games/qasteroids/qasteroids.pro
new file mode 100644
index 0000000..14a0901
--- a/dev/null
+++ b/noncore/games/qasteroids/qasteroids.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = ledmeter.h sprites.h toplevel.h view.h
+SOURCES = ledmeter.cpp toplevel.cpp view.cpp main.cpp
+TARGET = qasteroids
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+TRANSLATIONS = ../i18n/de/qasteroids.ts
diff --git a/noncore/games/qasteroids/qpe-qasteroids.control b/noncore/games/qasteroids/qpe-qasteroids.control
new file mode 100644
index 0000000..c1b328e
--- a/dev/null
+++ b/noncore/games/qasteroids/qpe-qasteroids.control
@@ -0,0 +1,9 @@
+Files: bin/qasteroids apps/Games/qasteroids.desktop pics/qasteroids pics/Asteroids.png
+Priority: optional
+Section: qpe/games
+Maintainer: Martin Jones <mjones@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: shoot the asteroids
+ A game for the Qtopia environment.
diff --git a/noncore/games/qasteroids/sprites.h b/noncore/games/qasteroids/sprites.h
new file mode 100644
index 0000000..0827821
--- a/dev/null
+++ b/noncore/games/qasteroids/sprites.h
@@ -0,0 +1,147 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#ifndef __SPRITES_H__
+#define __SPRITES_H__
+
+#include <qcanvas.h>
+
+#define ID_ROCK_LARGE 1024
+#define ID_ROCK_MEDIUM 1025
+#define ID_ROCK_SMALL 1026
+
+#define ID_MISSILE 1030
+
+#define ID_BIT 1040
+#define ID_EXHAUST 1041
+
+#define ID_ENERGY_POWERUP 1310
+#define ID_TELEPORT_POWERUP 1311
+#define ID_BRAKE_POWERUP 1312
+#define ID_SHIELD_POWERUP 1313
+#define ID_SHOOT_POWERUP 1314
+
+#define ID_SHIP 1350
+#define ID_SHIELD 1351
+
+#define MAX_SHIELD_AGE 350
+#define MAX_POWERUP_AGE 500
+#define MAX_MISSILE_AGE 20
+
+class KMissile : public QCanvasSprite
+{
+public:
+ KMissile( QCanvasPixmapArray *s, QCanvas *c ) : QCanvasSprite( s, c )
+ { myAge = 0; }
+
+ virtual int rtti() const { return ID_MISSILE; }
+
+ void growOlder() { myAge++; }
+ bool expired() { return myAge > MAX_MISSILE_AGE; }
+
+private:
+ int myAge;
+};
+
+class KBit : public QCanvasSprite
+{
+public:
+ KBit( QCanvasPixmapArray *s, QCanvas *c ) : QCanvasSprite( s, c )
+ { death = 7; }
+
+ virtual int rtti() const { return ID_BIT; }
+
+ void setDeath( int d ) { death = d; }
+ void growOlder() { death--; }
+ bool expired() { return death <= 0; }
+
+private:
+ int death;
+};
+
+class KExhaust : public QCanvasSprite
+{
+public:
+ KExhaust( QCanvasPixmapArray *s, QCanvas *c ) : QCanvasSprite( s, c )
+ { death = 1; }
+
+ virtual int rtti() const { return ID_EXHAUST; }
+
+ void setDeath( int d ) { death = d; }
+ void growOlder() { death--; }
+ bool expired() { return death <= 0; }
+
+private:
+ int death;
+};
+
+class KPowerup : public QCanvasSprite
+{
+public:
+ KPowerup( QCanvasPixmapArray *s, QCanvas *c, int t ) : QCanvasSprite( s, c ),
+ myAge( 0 ), type(t) { }
+
+ virtual int rtti() const { return type; }
+
+ void growOlder() { myAge++; }
+ bool expired() const { return myAge > MAX_POWERUP_AGE; }
+
+protected:
+ int myAge;
+ int type;
+};
+
+class KRock : public QCanvasSprite
+{
+public:
+ KRock (QCanvasPixmapArray *s, QCanvas *c, int t, int sk, int st) : QCanvasSprite( s, c )
+ { type = t; skip = cskip = sk; step = st; }
+
+ void nextFrame()
+ {
+ if (cskip-- <= 0) {
+ setFrame( (frame()+step+frameCount())%frameCount() );
+ cskip = QABS(skip);
+ }
+ }
+
+ virtual int rtti() const { return type; }
+
+private:
+ int type;
+ int skip;
+ int cskip;
+ int step;
+};
+
+class KShield : public QCanvasSprite
+{
+public:
+ KShield( QCanvasPixmapArray *s, QCanvas *c )
+ : QCanvasSprite( s, c ) {}
+
+ virtual int rtti() const { return ID_SHIELD; }
+};
+
+#endif
diff --git a/noncore/games/qasteroids/toplevel.cpp b/noncore/games/qasteroids/toplevel.cpp
new file mode 100644
index 0000000..57242a0
--- a/dev/null
+++ b/noncore/games/qasteroids/toplevel.cpp
@@ -0,0 +1,514 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+// --- toplevel.cpp ---
+
+#include "toplevel.h"
+#include "ledmeter.h"
+
+#include <qpe/qpeapplication.h>
+#include <qpe/resource.h>
+
+#include <qaccel.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlcdnumber.h>
+#include <qpushbutton.h>
+
+
+#define SB_SCORE 1
+#define SB_LEVEL 2
+#define SB_SHIPS 3
+
+struct SLevel
+{
+ int nrocks;
+ double rockSpeed;
+};
+
+#define MAX_LEVELS 16
+
+SLevel levels[MAX_LEVELS] =
+{
+ { 1, 0.4 },
+ { 1, 0.6 },
+ { 2, 0.5 },
+ { 2, 0.7 },
+ { 2, 0.8 },
+ { 3, 0.6 },
+ { 3, 0.7 },
+ { 3, 0.8 },
+ { 4, 0.6 },
+ { 4, 0.7 },
+ { 4, 0.8 },
+ { 5, 0.7 },
+ { 5, 0.8 },
+ { 5, 0.9 },
+ { 5, 1.0 }
+};
+
+const char *soundEvents[] =
+{
+ "ShipDestroyed",
+ "RockDestroyed",
+ 0
+};
+
+const char *soundDefaults[] =
+{
+ "Explosion.wav",
+ "ploop.wav",
+ 0
+};
+
+
+KAstTopLevel::KAstTopLevel( QWidget *parent, const char *name )
+ : QMainWindow( parent, name )
+{
+ setCaption( tr("Asteroids") );
+ QWidget *border = new QWidget( this );
+ border->setBackgroundColor( black );
+ setCentralWidget( border );
+
+ QVBoxLayout *borderLayout = new QVBoxLayout( border );
+
+ QWidget *mainWin = new QWidget( border );
+ borderLayout->addWidget( mainWin, 2, AlignHCenter );
+
+ view = new KAsteroidsView( mainWin );
+ connect( view, SIGNAL( shipKilled() ), SLOT( slotShipKilled() ) );
+ connect( view, SIGNAL( rockHit(int) ), SLOT( slotRockHit(int) ) );
+ connect( view, SIGNAL( rocksRemoved() ), SLOT( slotRocksRemoved() ) );
+ connect( view, SIGNAL( updateVitals() ), SLOT( slotUpdateVitals() ) );
+
+ QVBoxLayout *vb = new QVBoxLayout( mainWin );
+ QHBoxLayout *hb = new QHBoxLayout;
+ QHBoxLayout *hbd = new QHBoxLayout;
+ vb->addLayout( hb );
+
+ QFont labelFont( "helvetica", 12 );
+ QColorGroup grp( darkGreen, black, QColor( 128, 128, 128 ),
+ QColor( 64, 64, 64 ), black, darkGreen, black );
+ QPalette pal( grp, grp, grp );
+
+ mainWin->setPalette( pal );
+
+ QLabel *label;
+ label = new QLabel( tr("Score"), mainWin );
+ label->setFont( labelFont );
+ label->setPalette( pal );
+// label->setFixedWidth( label->sizeHint().width() );
+ hb->addWidget( label );
+
+ scoreLCD = new QLCDNumber( 5, mainWin );
+ scoreLCD->setFrameStyle( QFrame::NoFrame );
+ scoreLCD->setSegmentStyle( QLCDNumber::Flat );
+ scoreLCD->setFixedHeight( 16 );
+ scoreLCD->setPalette( pal );
+ hb->addWidget( scoreLCD );
+ hb->addStretch( 1 );
+
+ label = new QLabel( tr("Level"), mainWin );
+ label->setFont( labelFont );
+ label->setPalette( pal );
+// label->setFixedWidth( label->sizeHint().width() );
+ hb->addWidget( label );
+
+ levelLCD = new QLCDNumber( 2, mainWin );
+ levelLCD->setFrameStyle( QFrame::NoFrame );
+ levelLCD->setSegmentStyle( QLCDNumber::Flat );
+ levelLCD->setFixedHeight( 16 );
+ levelLCD->setPalette( pal );
+ hb->addWidget( levelLCD );
+ hb->addStretch( 1 );
+
+ label = new QLabel( tr("Ships"), mainWin );
+ label->setFont( labelFont );
+// label->setFixedWidth( label->sizeHint().width() );
+ label->setPalette( pal );
+ hb->addWidget( label );
+
+ shipsLCD = new QLCDNumber( 1, mainWin );
+ shipsLCD->setFrameStyle( QFrame::NoFrame );
+ shipsLCD->setSegmentStyle( QLCDNumber::Flat );
+ shipsLCD->setFixedHeight( 16 );
+ shipsLCD->setPalette( pal );
+ hb->addWidget( shipsLCD );
+
+// hb->addStrut( 14 );
+
+ vb->addWidget( view, 10 );
+
+// -- bottom layout:
+ vb->addLayout( hbd );
+
+ QFont smallFont( "helvetica", 12 );
+ hbd->addSpacing( 5 );
+
+/*
+ label = new QLabel( tr( "T" ), mainWin );
+ label->setFont( smallFont );
+ label->setFixedWidth( label->sizeHint().width() );
+ label->setPalette( pal );
+ hbd->addWidget( label );
+
+ teleportsLCD = new QLCDNumber( 1, mainWin );
+ teleportsLCD->setFrameStyle( QFrame::NoFrame );
+ teleportsLCD->setSegmentStyle( QLCDNumber::Flat );
+ teleportsLCD->setPalette( pal );
+ teleportsLCD->setFixedHeight( 18 );
+ hbd->addWidget( teleportsLCD );
+
+ hbd->addSpacing( 10 );
+*/
+ label = new QLabel( mainWin );
+ label->setPixmap( Resource::loadPixmap("qasteroids/powerups/brake.png") );
+ label->setFixedWidth( 16 );
+ label->setPalette( pal );
+ hbd->addWidget( label );
+
+ brakesLCD = new QLCDNumber( 1, mainWin );
+ brakesLCD->setFrameStyle( QFrame::NoFrame );
+ brakesLCD->setSegmentStyle( QLCDNumber::Flat );
+ brakesLCD->setPalette( pal );
+ brakesLCD->setFixedHeight( 16 );
+ hbd->addWidget( brakesLCD );
+
+ hbd->addSpacing( 5 );
+
+ label = new QLabel( mainWin );
+ label->setPixmap( Resource::loadPixmap("qasteroids/powerups/shield.png") );
+ label->setFixedWidth( 16 );
+ label->setPalette( pal );
+ hbd->addWidget( label );
+
+ shieldLCD = new QLCDNumber( 1, mainWin );
+ shieldLCD->setFrameStyle( QFrame::NoFrame );
+ shieldLCD->setSegmentStyle( QLCDNumber::Flat );
+ shieldLCD->setPalette( pal );
+ shieldLCD->setFixedHeight( 16 );
+ hbd->addWidget( shieldLCD );
+
+ hbd->addSpacing( 5 );
+
+ label = new QLabel( mainWin );
+ label->setPixmap( Resource::loadPixmap("qasteroids/powerups/shoot.png") );
+ label->setFixedWidth( 16 );
+ label->setPalette( pal );
+ hbd->addWidget( label );
+
+ shootLCD = new QLCDNumber( 1, mainWin );
+ shootLCD->setFrameStyle( QFrame::NoFrame );
+ shootLCD->setSegmentStyle( QLCDNumber::Flat );
+ shootLCD->setPalette( pal );
+ shootLCD->setFixedHeight( 16 );
+ hbd->addWidget( shootLCD );
+
+ hbd->addStretch( 1 );
+
+ label = new QLabel( tr( "Fuel" ), mainWin );
+ label->setFont( smallFont );
+ label->setFixedWidth( label->sizeHint().width() + 5 );
+ label->setPalette( pal );
+ hbd->addWidget( label );
+
+ powerMeter = new KALedMeter( mainWin );
+ powerMeter->setFrameStyle( QFrame::Box | QFrame::Plain );
+ powerMeter->setRange( MAX_POWER_LEVEL );
+ powerMeter->addColorRange( 10, darkRed );
+ powerMeter->addColorRange( 20, QColor(160, 96, 0) );
+ powerMeter->addColorRange( 70, darkGreen );
+ powerMeter->setCount( 15 );
+ powerMeter->setPalette( pal );
+ powerMeter->setFixedSize( 60, 12 );
+ hbd->addWidget( powerMeter );
+
+ shipsRemain = 3;
+ showHiscores = FALSE;
+
+ actions.insert( Qt::Key_Up, Thrust );
+ actions.insert( Qt::Key_Left, RotateLeft );
+ actions.insert( Qt::Key_Right, RotateRight );
+ actions.insert( Qt::Key_Enter, Shoot );
+ actions.insert( Qt::Key_Z, Teleport );
+ actions.insert( Qt::Key_Down, Brake );
+ actions.insert( Qt::Key_P, Pause );
+ actions.insert( Key_F12, Launch );
+ actions.insert( Key_F11, Shield );
+ actions.insert( Key_F9, NewGame );
+
+// actions.insert( Qt::Key_S, Shield );
+// actions.insert( Qt::Key_X, Brake );
+// actions.insert( Qt::Key_L, Launch );
+ actions.insert( Qt::Key_Space, Shoot );
+
+ view->showText( tr( "Press Calendar to start playing" ), yellow );
+
+ setFocusPolicy( StrongFocus );
+
+ slotNewGame();
+}
+
+KAstTopLevel::~KAstTopLevel()
+{
+}
+
+void KAstTopLevel::playSound( const char * )
+{
+}
+
+void KAstTopLevel::keyPressEvent( QKeyEvent *event )
+{
+ if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
+ {
+ event->ignore();
+ return;
+ }
+
+ Action a = actions[ event->key() ];
+
+ switch ( a )
+ {
+ case RotateLeft:
+ view->rotateLeft( TRUE );
+ break;
+
+ case RotateRight:
+ view->rotateRight( TRUE );
+ break;
+
+ case Thrust:
+ view->thrust( TRUE );
+ break;
+
+ case Shoot:
+ view->shoot( TRUE );
+ break;
+
+ case Shield:
+ view->setShield( TRUE );
+ break;
+
+ case Teleport:
+ view->teleport( TRUE );
+ break;
+
+ case Brake:
+ view->brake( TRUE );
+ break;
+
+ default:
+ event->ignore();
+ return;
+ }
+ event->accept();
+}
+
+void KAstTopLevel::keyReleaseEvent( QKeyEvent *event )
+{
+ if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
+ {
+ event->ignore();
+ return;
+ }
+
+ Action a = actions[ event->key() ];
+
+ switch ( a )
+ {
+ case RotateLeft:
+ view->rotateLeft( FALSE );
+ break;
+
+ case RotateRight:
+ view->rotateRight( FALSE );
+ break;
+
+ case Thrust:
+ view->thrust( FALSE );
+ break;
+
+ case Shoot:
+ view->shoot( FALSE );
+ break;
+
+ case Brake:
+ view->brake( FALSE );
+ break;
+
+ case Shield:
+ view->setShield( FALSE );
+ break;
+
+ case Teleport:
+ view->teleport( FALSE );
+ break;
+
+ case Launch:
+ if ( waitShip )
+ {
+ view->newShip();
+ waitShip = FALSE;
+ view->hideText();
+ }
+ else
+ {
+ event->ignore();
+ return;
+ }
+ break;
+
+ case NewGame:
+ slotNewGame();
+ break;
+/*
+ case Pause:
+ {
+ view->pause( TRUE );
+ QMessageBox::information( this,
+ tr("KAsteroids is paused"),
+ tr("Paused") );
+ view->pause( FALSE );
+ }
+ break;
+*/
+ default:
+ event->ignore();
+ return;
+ }
+
+ event->accept();
+}
+
+void KAstTopLevel::showEvent( QShowEvent *e )
+{
+ QMainWindow::showEvent( e );
+ view->pause( FALSE );
+ setFocus();
+}
+
+void KAstTopLevel::hideEvent( QHideEvent *e )
+{
+ QMainWindow::hideEvent( e );
+ view->pause( TRUE );
+}
+
+void KAstTopLevel::focusInEvent( QFocusEvent * )
+{
+ view->pause( FALSE );
+ setFocus();
+}
+
+void KAstTopLevel::focusOutEvent( QFocusEvent * )
+{
+ view->pause( TRUE );
+}
+
+void KAstTopLevel::slotNewGame()
+{
+ shipsRemain = 3;
+ score = 0;
+ scoreLCD->display( 0 );
+ level = 0;
+ levelLCD->display( level+1 );
+ shipsLCD->display( shipsRemain-1 );
+ view->newGame();
+ view->setRockSpeed( levels[0].rockSpeed );
+ view->addRocks( levels[0].nrocks );
+ view->newShip();
+ waitShip = FALSE;
+ view->hideText();
+ isPaused = FALSE;
+}
+
+void KAstTopLevel::slotShipKilled()
+{
+ shipsRemain--;
+ shipsLCD->display( shipsRemain-1 );
+
+ playSound( "ShipDestroyed" );
+
+ if ( shipsRemain > 0 )
+ {
+ waitShip = TRUE;
+ view->showText( tr( "Ship Destroyed.\nPress Launch/Home key."), yellow );
+ }
+ else
+ {
+ view->endGame();
+ doStats();
+ }
+}
+
+void KAstTopLevel::slotRockHit( int size )
+{
+ switch ( size )
+ {
+ case 0:
+ score += 10;
+ break;
+
+ case 1:
+ score += 20;
+ break;
+
+ default:
+ score += 40;
+ }
+
+ playSound( "RockDestroyed" );
+
+ scoreLCD->display( score );
+}
+
+void KAstTopLevel::slotRocksRemoved()
+{
+ level++;
+
+ if ( level >= MAX_LEVELS )
+ level = MAX_LEVELS - 1;
+
+ view->setRockSpeed( levels[level-1].rockSpeed );
+ view->addRocks( levels[level-1].nrocks );
+
+ levelLCD->display( level+1 );
+}
+
+void KAstTopLevel::doStats()
+{
+ QString r( "0.00" );
+ if ( view->shots() )
+ r = QString::number( (double)view->hits() / view->shots() * 100.0,
+ 'g', 2 );
+
+ view->showText( tr( "Game Over.\nPress Calendar for a new game." ), yellow, FALSE );
+}
+
+void KAstTopLevel::slotUpdateVitals()
+{
+ brakesLCD->display( view->brakeCount() );
+ shieldLCD->display( view->shieldCount() );
+ shootLCD->display( view->shootCount() );
+// teleportsLCD->display( view->teleportCount() );
+ powerMeter->setValue( view->power() );
+}
diff --git a/noncore/games/qasteroids/toplevel.h b/noncore/games/qasteroids/toplevel.h
new file mode 100644
index 0000000..4e1ac9c
--- a/dev/null
+++ b/noncore/games/qasteroids/toplevel.h
@@ -0,0 +1,99 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#ifndef __KAST_TOPLEVEL_H__
+#define __KAST_TOPLEVEL_H__
+
+#include <qmainwindow.h>
+#include <qdict.h>
+#include <qmap.h>
+
+#include "view.h"
+
+
+class KALedMeter;
+class QLCDNumber;
+
+class KAstTopLevel : public QMainWindow
+{
+ Q_OBJECT
+public:
+ KAstTopLevel( QWidget *parent=0, const char *name=0 );
+ virtual ~KAstTopLevel();
+
+private:
+ void playSound( const char *snd );
+ void readSoundMapping();
+ void doStats();
+
+protected:
+ virtual void showEvent( QShowEvent * );
+ virtual void hideEvent( QHideEvent * );
+ virtual void keyPressEvent( QKeyEvent *event );
+ virtual void keyReleaseEvent( QKeyEvent *event );
+ virtual void focusInEvent( QFocusEvent *event );
+ virtual void focusOutEvent( QFocusEvent *event );
+
+private slots:
+ void slotNewGame();
+
+ void slotShipKilled();
+ void slotRockHit( int size );
+ void slotRocksRemoved();
+
+ void slotUpdateVitals();
+
+private:
+ KAsteroidsView *view;
+ QLCDNumber *scoreLCD;
+ QLCDNumber *levelLCD;
+ QLCDNumber *shipsLCD;
+
+ QLCDNumber *teleportsLCD;
+// QLCDNumber *bombsLCD;
+ QLCDNumber *brakesLCD;
+ QLCDNumber *shieldLCD;
+ QLCDNumber *shootLCD;
+ KALedMeter *powerMeter;
+
+ bool sound;
+ QDict<QString> soundDict;
+
+ // waiting for user to press Enter to launch a ship
+ bool waitShip;
+ bool isPaused;
+
+ int shipsRemain;
+ int score;
+ int level;
+ bool showHiscores;
+
+ enum Action { Launch, Thrust, RotateLeft, RotateRight, Shoot, Teleport,
+ Brake, Shield, Pause, NewGame };
+
+ QMap<int,Action> actions;
+};
+
+#endif
+
diff --git a/noncore/games/qasteroids/view.cpp b/noncore/games/qasteroids/view.cpp
new file mode 100644
index 0000000..ef08343
--- a/dev/null
+++ b/noncore/games/qasteroids/view.cpp
@@ -0,0 +1,884 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#include "view.h"
+
+#include <qpe/resource.h>
+
+#include <qapplication.h>
+#include <qkeycode.h>
+#include <qaccel.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+#define IMG_BACKGROUND "qasteroids/bg.png"
+
+#define REFRESH_DELAY 33
+#define SHIP_SPEED 0.3
+#define MISSILE_SPEED 10.0
+#define SHIP_STEPS 64
+#define ROTATE_RATE 2
+#define SHIELD_ON_COST 1
+#define SHIELD_HIT_COST 30
+#define BRAKE_ON_COST 4
+
+#define MAX_ROCK_SPEED 2.5
+#define MAX_POWERUP_SPEED 1.5
+#define MAX_SHIP_SPEED 8
+#define MAX_BRAKES 5
+#define MAX_SHIELDS 5
+#define MAX_FIREPOWER 5
+
+#define TEXT_SPEED 4
+
+#define PI_X_2 6.283185307
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+struct
+{
+ int id;
+ const char *path;
+ int frames;
+}
+kas_animations [] =
+{
+// { ID_ROCK_LARGE, "rock1/rock1\%1.png", 32 },
+ { ID_ROCK_MEDIUM, "rock2/rock2\%1.png", 32 },
+ { ID_ROCK_SMALL, "rock3/rock3\%1.png", 32 },
+ { ID_SHIP, "ship/ship\%1.png", 32 },
+ { ID_MISSILE, "missile/missile.png", 1 },
+ { ID_BIT, "bits/bits\%1.png", 16 },
+ { ID_EXHAUST, "exhaust/exhaust.png", 1 },
+ { ID_ENERGY_POWERUP, "powerups/energy.png", 1 },
+// { ID_TELEPORT_POWERUP, "powerups/teleport%1.png", 12 },
+ { ID_BRAKE_POWERUP, "powerups/brake.png", 1 },
+ { ID_SHIELD_POWERUP, "powerups/shield.png", 1 },
+ { ID_SHOOT_POWERUP, "powerups/shoot.png", 1 },
+ { ID_SHIELD, "shield/shield\%1.png", 6 },
+ { 0, 0, 0 }
+};
+
+
+
+KAsteroidsView::KAsteroidsView( QWidget *parent, const char *name )
+ : QWidget( parent, name ),
+ field(200, 200),
+ view(&field,this)
+{
+ view.setVScrollBarMode( QScrollView::AlwaysOff );
+ view.setHScrollBarMode( QScrollView::AlwaysOff );
+ rocks.setAutoDelete( TRUE );
+ missiles.setAutoDelete( TRUE );
+ bits.setAutoDelete( TRUE );
+ powerups.setAutoDelete( TRUE );
+ exhaust.setAutoDelete( TRUE );
+
+ QPixmap pm( Resource::loadPixmap(IMG_BACKGROUND) );
+ field.setBackgroundPixmap( pm );
+
+ textSprite = new QCanvasText( &field );
+ QFont font( "helvetica", 14 );
+ textSprite->setFont( font );
+
+ shield = 0;
+ shieldOn = FALSE;
+ refreshRate = REFRESH_DELAY;
+
+ readSprites();
+
+ shieldTimer = new QTimer( this );
+ connect( shieldTimer, SIGNAL(timeout()), this, SLOT(hideShield()) );
+ mTimerId = -1;
+
+ shipPower = MAX_POWER_LEVEL;
+ vitalsChanged = TRUE;
+ can_destroy_powerups = FALSE;
+
+ mPaused = TRUE;
+}
+
+// - - -
+
+KAsteroidsView::~KAsteroidsView()
+{
+}
+
+// - - -
+
+void KAsteroidsView::reset()
+{
+ rocks.clear();
+ missiles.clear();
+ bits.clear();
+ powerups.clear();
+ exhaust.clear();
+
+ shotsFired = 0;
+ shotsHit = 0;
+
+ rockSpeed = 1.0;
+ powerupSpeed = 1.0;
+ mFrameNum = 0;
+ mPaused = FALSE;
+
+ ship->hide();
+ shield->hide();
+/*
+ if ( mTimerId >= 0 ) {
+ killTimer( mTimerId );
+ mTimerId = -1;
+ }
+*/
+}
+
+// - --
+
+void KAsteroidsView::newGame()
+{
+ if ( shieldOn )
+ {
+ shield->hide();
+ shieldOn = FALSE;
+ }
+ reset();
+ if ( mTimerId < 0 )
+ mTimerId = startTimer( REFRESH_DELAY );
+ emit updateVitals();
+}
+
+// - - -
+
+void KAsteroidsView::endGame()
+{
+}
+
+void KAsteroidsView::pause( bool p )
+{
+ if ( !mPaused && p ) {
+ if ( mTimerId >= 0 ) {
+ killTimer( mTimerId );
+ mTimerId = -1;
+ }
+ } else if ( mPaused && !p )
+ mTimerId = startTimer( REFRESH_DELAY );
+ mPaused = p;
+}
+
+// - - -
+
+void KAsteroidsView::newShip()
+{
+ ship->move( field.width()/2, field.height()/2, 0 );
+ shield->move( field.width()/2, field.height()/2, 0 );
+ ship->setVelocity( 0.0, 0.0 );
+ shipDx = 0;
+ shipDy = 0;
+ shipAngle = 0;
+ rotateL = FALSE;
+ rotateR = FALSE;
+ thrustShip = FALSE;
+ shootShip = FALSE;
+ brakeShip = FALSE;
+ teleportShip = FALSE;
+ shieldOn = TRUE;
+ shootDelay = 0;
+ shipPower = MAX_POWER_LEVEL;
+ rotateRate = ROTATE_RATE;
+ rotateSlow = 0;
+
+ mBrakeCount = 0;
+ mTeleportCount = 0;
+ mShootCount = 0;
+
+ ship->show();
+ shield->show();
+ mShieldCount = 1; // just in case the ship appears on a rock.
+ shieldTimer->start( 1000, TRUE );
+}
+
+void KAsteroidsView::setShield( bool s )
+{
+ if ( shieldTimer->isActive() && !s ) {
+ shieldTimer->stop();
+ hideShield();
+ } else {
+ shieldOn = s && mShieldCount;
+ }
+}
+
+void KAsteroidsView::brake( bool b )
+{
+ if ( mBrakeCount )
+ {
+ if ( brakeShip && !b )
+ {
+ rotateL = FALSE;
+ rotateR = FALSE;
+ thrustShip = FALSE;
+ rotateRate = ROTATE_RATE;
+ }
+
+ brakeShip = b;
+ }
+}
+
+// - - -
+
+void KAsteroidsView::readSprites()
+{
+ QString sprites_prefix = Resource::findPixmap( IMG_BACKGROUND );
+ int sep = sprites_prefix.findRev( "/" );
+
+ sprites_prefix.truncate( sep );
+
+ int i = 0;
+ while ( kas_animations[i].id )
+ {
+ animation.insert( kas_animations[i].id,
+ new QCanvasPixmapArray( sprites_prefix + "/" + kas_animations[i].path,
+ kas_animations[i].frames ) );
+ i++;
+ }
+
+ ship = new QCanvasSprite( animation[ID_SHIP], &field );
+ ship->hide();
+
+ shield = new KShield( animation[ID_SHIELD], &field );
+ shield->hide();
+}
+
+// - - -
+
+void KAsteroidsView::addRocks( int num )
+{
+ for ( int i = 0; i < num; i++ )
+ {
+ KRock *rock = new KRock( animation[ID_ROCK_MEDIUM], &field,
+ ID_ROCK_MEDIUM, randInt(2), randInt(2) ? -1 : 1 );
+ double dx = (2.0 - randDouble()*4.0) * rockSpeed;
+ double dy = (2.0 - randDouble()*4.0) * rockSpeed;
+ rock->setVelocity( dx, dy );
+ rock->setFrame( randInt( rock->frameCount() ) );
+ if ( dx > 0 )
+ {
+ if ( dy > 0 )
+ rock->move( 5, 5, 0 );
+ else
+ rock->move( 5, field.height() - 25, 0 );
+ }
+ else
+ {
+ if ( dy > 0 )
+ rock->move( field.width() - 25, 5, 0 );
+ else
+ rock->move( field.width() - 25, field.height() - 25, 0 );
+ }
+ rock->show( );
+ rocks.append( rock );
+ }
+}
+
+// - - -
+
+void KAsteroidsView::showText( const QString &text, const QColor &color, bool scroll )
+{
+ textSprite->setTextFlags( AlignLeft | AlignVCenter );
+ textSprite->setText( text );
+ textSprite->setColor( color );
+
+ if ( scroll ) {
+ textSprite->move( (field.width()-textSprite->boundingRect().width()) / 2,
+ -textSprite->boundingRect().height() );
+ textDy = TEXT_SPEED;
+ } else {
+ textSprite->move( (field.width()-textSprite->boundingRect().width()) / 2,
+ (field.height()-textSprite->boundingRect().height()) / 2 );
+ textDy = 0;
+ }
+ textSprite->show();
+}
+
+// - - -
+
+void KAsteroidsView::hideText()
+{
+ textDy = -TEXT_SPEED;
+}
+
+// - - -
+
+void KAsteroidsView::resizeEvent(QResizeEvent* event)
+{
+ QWidget::resizeEvent(event);
+ field.resize(width()-4, height()-4);
+ view.resize(width(),height());
+}
+
+// - - -
+
+void KAsteroidsView::timerEvent( QTimerEvent * )
+{
+ field.advance();
+
+ QCanvasSprite *rock;
+
+ // move rocks forward
+ for ( rock = rocks.first(); rock; rock = rocks.next() ) {
+ ((KRock *)rock)->nextFrame();
+ wrapSprite( rock );
+ }
+
+ wrapSprite( ship );
+
+ // check for missile collision with rocks.
+ processMissiles();
+
+ // these are generated when a ship explodes
+ for ( KBit *bit = bits.first(); bit; bit = bits.next() )
+ {
+ if ( bit->expired() )
+ {
+ bits.removeRef( bit );
+ }
+ else
+ {
+ bit->growOlder();
+ bit->setFrame( ( bit->frame()+1 ) % bit->frameCount() );
+ }
+ }
+
+ for ( KExhaust *e = exhaust.first(); e; e = exhaust.next() )
+ exhaust.removeRef( e );
+
+ // move / rotate ship.
+ // check for collision with a rock.
+ processShip();
+
+ // move powerups and check for collision with player and missiles
+ processPowerups();
+
+ if ( textSprite->visible() )
+ {
+ if ( textDy < 0 &&
+ textSprite->boundingRect().y() <= -textSprite->boundingRect().height() ) {
+ textSprite->hide();
+ } else {
+ textSprite->moveBy( 0, textDy );
+ }
+ if ( textSprite->boundingRect().y() > (field.height()-textSprite->boundingRect().height())/2 )
+ textDy = 0;
+ }
+
+ if ( vitalsChanged && !(mFrameNum % 10) ) {
+ emit updateVitals();
+ vitalsChanged = FALSE;
+ }
+
+ mFrameNum++;
+}
+
+void KAsteroidsView::wrapSprite( QCanvasItem *s )
+{
+ int x = int(s->x() + s->boundingRect().width() / 2);
+ int y = int(s->y() + s->boundingRect().height() / 2);
+
+ if ( x > field.width() )
+ s->move( s->x() - field.width(), s->y() );
+ else if ( x < 0 )
+ s->move( field.width() + s->x(), s->y() );
+
+ if ( y > field.height() )
+ s->move( s->x(), s->y() - field.height() );
+ else if ( y < 0 )
+ s->move( s->x(), field.height() + s->y() );
+}
+
+// - - -
+
+void KAsteroidsView::rockHit( QCanvasItem *hit )
+{
+ KPowerup *nPup = 0;
+ int rnd = static_cast<int>(randDouble()*30.0) % 30;
+ switch( rnd )
+ {
+ case 4:
+ case 5:
+ nPup = new KPowerup( animation[ID_ENERGY_POWERUP], &field,
+ ID_ENERGY_POWERUP );
+ break;
+ case 10:
+// nPup = new KPowerup( animation[ID_TELEPORT_POWERUP], &field,
+// ID_TELEPORT_POWERUP );
+ break;
+ case 15:
+ nPup = new KPowerup( animation[ID_BRAKE_POWERUP], &field,
+ ID_BRAKE_POWERUP );
+ break;
+ case 20:
+ nPup = new KPowerup( animation[ID_SHIELD_POWERUP], &field,
+ ID_SHIELD_POWERUP );
+ break;
+ case 24:
+ case 25:
+ nPup = new KPowerup( animation[ID_SHOOT_POWERUP], &field,
+ ID_SHOOT_POWERUP );
+ break;
+ }
+ if ( nPup )
+ {
+ double r = 0.5 - randDouble();
+ nPup->move( hit->x(), hit->y(), 0 );
+ nPup->setVelocity( hit->xVelocity() + r, hit->yVelocity() + r );
+ nPup->show( );
+ powerups.append( nPup );
+ }
+
+ if ( hit->rtti() == ID_ROCK_LARGE || hit->rtti() == ID_ROCK_MEDIUM )
+ {
+ // break into smaller rocks
+ double addx[4] = { 1.0, 1.0, -1.0, -1.0 };
+ double addy[4] = { -1.0, 1.0, -1.0, 1.0 };
+
+ double dx = hit->xVelocity();
+ double dy = hit->yVelocity();
+
+ double maxRockSpeed = MAX_ROCK_SPEED * rockSpeed;
+ if ( dx > maxRockSpeed )
+ dx = maxRockSpeed;
+ else if ( dx < -maxRockSpeed )
+ dx = -maxRockSpeed;
+ if ( dy > maxRockSpeed )
+ dy = maxRockSpeed;
+ else if ( dy < -maxRockSpeed )
+ dy = -maxRockSpeed;
+
+ QCanvasSprite *nrock;
+
+ for ( int i = 0; i < 4; i++ )
+ {
+ double r = rockSpeed/2 - randDouble()*rockSpeed;
+ if ( hit->rtti() == ID_ROCK_LARGE )
+ {
+ nrock = new KRock( animation[ID_ROCK_MEDIUM], &field,
+ ID_ROCK_MEDIUM, randInt(2), randInt(2) ? -1 : 1 );
+ emit rockHit( 0 );
+ }
+ else
+ {
+ nrock = new KRock( animation[ID_ROCK_SMALL], &field,
+ ID_ROCK_SMALL, randInt(2), randInt(2) ? -1 : 1 );
+ emit rockHit( 1 );
+ }
+
+ nrock->move( hit->x(), hit->y(), 0 );
+ nrock->setVelocity( dx+addx[i]*rockSpeed+r, dy+addy[i]*rockSpeed+r );
+ nrock->setFrame( randInt( nrock->frameCount() ) );
+ nrock->show( );
+ rocks.append( nrock );
+ }
+ }
+ else if ( hit->rtti() == ID_ROCK_SMALL )
+ emit rockHit( 2 );
+ rocks.removeRef( (QCanvasSprite *)hit );
+ if ( rocks.count() == 0 )
+ emit rocksRemoved();
+}
+
+void KAsteroidsView::reducePower( int val )
+{
+ shipPower -= val;
+ if ( shipPower <= 0 )
+ {
+ shipPower = 0;
+ thrustShip = FALSE;
+ if ( shieldOn )
+ {
+ shieldOn = FALSE;
+ shield->hide();
+ }
+ }
+ vitalsChanged = TRUE;
+}
+
+void KAsteroidsView::addExhaust( double x, double y, double dx,
+ double dy, int count )
+{
+ for ( int i = 0; i < count; i++ )
+ {
+ KExhaust *e = new KExhaust( animation[ID_EXHAUST], &field );
+ e->move( x + 2 - randDouble()*4, y + 2 - randDouble()*4 );
+ e->setVelocity( dx, dy );
+ e->show( );
+ exhaust.append( e );
+ }
+}
+
+void KAsteroidsView::processMissiles()
+{
+ KMissile *missile;
+
+ // if a missile has hit a rock, remove missile and break rock into smaller
+ // rocks or remove completely.
+ QPtrListIterator<KMissile> it(missiles);
+
+ for ( ; it.current(); ++it )
+ {
+ missile = it.current();
+ missile->growOlder();
+
+ if ( missile->expired() )
+ {
+ missiles.removeRef( missile );
+ continue;
+ }
+
+ wrapSprite( missile );
+
+ QCanvasItemList hits = missile->collisions( TRUE );
+ QCanvasItemList::Iterator hit;
+ for ( hit = hits.begin(); hit != hits.end(); ++hit )
+ {
+ if ( (*hit)->rtti() >= ID_ROCK_LARGE &&
+ (*hit)->rtti() <= ID_ROCK_SMALL )
+ {
+ shotsHit++;
+ rockHit( *hit );
+ missiles.removeRef( missile );
+ break;
+ }
+ }
+ }
+}
+
+// - - -
+
+void KAsteroidsView::processShip()
+{
+ if ( ship->visible() )
+ {
+ if ( shieldOn )
+ {
+ shield->show();
+ reducePower( SHIELD_ON_COST );
+ static int sf = 0;
+ sf++;
+
+ if ( sf % 2 )
+ shield->setFrame( (shield->frame()+1) % shield->frameCount() );
+ shield->move( ship->x() - 5, ship->y() - 5 );
+
+ QCanvasItemList hits = shield->collisions( TRUE );
+ QCanvasItemList::Iterator it;
+ for ( it = hits.begin(); it != hits.end(); ++it )
+ {
+ if ( (*it)->rtti() >= ID_ROCK_LARGE &&
+ (*it)->rtti() <= ID_ROCK_SMALL )
+ {
+ int factor;
+ switch ( (*it)->rtti() )
+ {
+ case ID_ROCK_LARGE:
+ factor = 3;
+ break;
+
+ case ID_ROCK_MEDIUM:
+ factor = 2;
+ break;
+
+ default:
+ factor = 1;
+ }
+
+ if ( factor > mShieldCount )
+ {
+ // shield not strong enough
+ shieldOn = FALSE;
+ break;
+ }
+ rockHit( *it );
+ // the more shields we have the less costly
+ reducePower( factor * (SHIELD_HIT_COST - mShieldCount*2) );
+ }
+ }
+ }
+
+ if ( !shieldOn )
+ {
+ shield->hide();
+ QCanvasItemList hits = ship->collisions( TRUE );
+ QCanvasItemList::Iterator it;
+ for ( it = hits.begin(); it != hits.end(); ++it )
+ {
+ if ( (*it)->rtti() >= ID_ROCK_LARGE &&
+ (*it)->rtti() <= ID_ROCK_SMALL )
+ {
+ KBit *bit;
+ for ( int i = 0; i < 8; i++ )
+ {
+ bit = new KBit( animation[ID_BIT], &field );
+ bit->move( ship->x() + 5 - randDouble() * 10,
+ ship->y() + 5 - randDouble() * 10,
+ randInt(bit->frameCount()) );
+ bit->setVelocity( 1-randDouble()*2,
+ 1-randDouble()*2 );
+ bit->setDeath( 60 + randInt(60) );
+ bit->show( );
+ bits.append( bit );
+ }
+ ship->hide();
+ shield->hide();
+ emit shipKilled();
+ break;
+ }
+ }
+ }
+
+
+ if ( rotateSlow )
+ rotateSlow--;
+
+ if ( rotateL )
+ {
+ shipAngle -= rotateSlow ? 1 : rotateRate;
+ if ( shipAngle < 0 )
+ shipAngle += SHIP_STEPS;
+ }
+
+ if ( rotateR )
+ {
+ shipAngle += rotateSlow ? 1 : rotateRate;
+ if ( shipAngle >= SHIP_STEPS )
+ shipAngle -= SHIP_STEPS;
+ }
+
+ double angle = shipAngle * PI_X_2 / SHIP_STEPS;
+ double cosangle = cos( angle );
+ double sinangle = sin( angle );
+
+ if ( brakeShip )
+ {
+ thrustShip = FALSE;
+ rotateL = FALSE;
+ rotateR = FALSE;
+ rotateRate = ROTATE_RATE;
+ if ( fabs(shipDx) < 2.5 && fabs(shipDy) < 2.5 )
+ {
+ shipDx = 0.0;
+ shipDy = 0.0;
+ ship->setVelocity( shipDx, shipDy );
+ brakeShip = FALSE;
+ }
+ else
+ {
+ double motionAngle = atan2( -shipDy, -shipDx );
+ if ( angle > M_PI )
+ angle -= PI_X_2;
+ double angleDiff = angle - motionAngle;
+ if ( angleDiff > M_PI )
+ angleDiff = PI_X_2 - angleDiff;
+ else if ( angleDiff < -M_PI )
+ angleDiff = PI_X_2 + angleDiff;
+ double fdiff = fabs( angleDiff );
+ if ( fdiff > 0.08 )
+ {
+ if ( angleDiff > 0 )
+ rotateL = TRUE;
+ else if ( angleDiff < 0 )
+ rotateR = TRUE;
+ if ( fdiff > 0.6 )
+ rotateRate = mBrakeCount + 1;
+ else if ( fdiff > 0.4 )
+ rotateRate = 2;
+ else
+ rotateRate = 1;
+
+ if ( rotateRate > 5 )
+ rotateRate = 5;
+ }
+ else if ( fabs(shipDx) > 1 || fabs(shipDy) > 1 )
+ {
+ thrustShip = TRUE;
+ // we'll make braking a bit faster
+ shipDx += cosangle/6 * (mBrakeCount - 1);
+ shipDy += sinangle/6 * (mBrakeCount - 1);
+ reducePower( BRAKE_ON_COST );
+ addExhaust( ship->x() + 10 - cosangle*11,
+ ship->y() + 10 - sinangle*11,
+ shipDx-cosangle, shipDy-sinangle,
+ mBrakeCount+1 );
+ }
+ }
+ }
+
+ if ( thrustShip )
+ {
+ // The ship has a terminal velocity, but trying to go faster
+ // still uses fuel (can go faster diagonally - don't care).
+ double thrustx = cosangle/8;
+ double thrusty = sinangle/8;
+ if ( fabs(shipDx + thrustx) < MAX_SHIP_SPEED )
+ shipDx += thrustx;
+ if ( fabs(shipDy + thrusty) < MAX_SHIP_SPEED )
+ shipDy += thrusty;
+ ship->setVelocity( shipDx, shipDy );
+ reducePower( 1 );
+ addExhaust( ship->x() + 10 - cosangle*10,
+ ship->y() + 10 - sinangle*10,
+ shipDx-cosangle, shipDy-sinangle, 3 );
+ }
+
+ ship->setFrame( shipAngle >> 1 );
+
+ if ( shootShip )
+ {
+ if ( !shootDelay && (int)missiles.count() < mShootCount + 2 )
+ {
+ KMissile *missile = new KMissile( animation[ID_MISSILE], &field );
+ missile->move( 11+ship->x()+cosangle*11,
+ 11+ship->y()+sinangle*11, 0 );
+ missile->setVelocity( shipDx + cosangle*MISSILE_SPEED,
+ shipDy + sinangle*MISSILE_SPEED );
+ missile->show( );
+ missiles.append( missile );
+ shotsFired++;
+ reducePower( 1 );
+
+ shootDelay = 5;
+ }
+
+ if ( shootDelay )
+ shootDelay--;
+ }
+
+ if ( teleportShip )
+ {
+ int ra = rand() % 10;
+ if( ra == 0 )
+ ra += rand() % 20;
+ int xra = ra * 60 + ( (rand() % 20) * (rand() % 20) );
+ int yra = ra * 50 - ( (rand() % 20) * (rand() % 20) );
+ ship->move( xra, yra );
+ }
+
+ vitalsChanged = TRUE;
+ }
+}
+
+// - - -
+
+void KAsteroidsView::processPowerups()
+{
+ if ( !powerups.isEmpty() )
+ {
+ // if player gets the powerup remove it from the screen, if option
+ // "Can destroy powerups" is enabled and a missile hits the powerup
+ // destroy it
+
+ KPowerup *pup;
+ QPtrListIterator<KPowerup> it( powerups );
+
+ for( ; it.current(); ++it )
+ {
+ pup = it.current();
+ pup->growOlder();
+
+ if( pup->expired() )
+ {
+ powerups.removeRef( pup );
+ continue;
+ }
+
+ wrapSprite( pup );
+
+ QCanvasItemList hits = pup->collisions( TRUE );
+ QCanvasItemList::Iterator it;
+ for ( it = hits.begin(); it != hits.end(); ++it )
+ {
+ if ( (*it) == ship )
+ {
+ switch( pup->rtti() )
+ {
+ case ID_ENERGY_POWERUP:
+ shipPower += 150;
+ if ( shipPower > MAX_POWER_LEVEL )
+ shipPower = MAX_POWER_LEVEL;
+ break;
+ case ID_TELEPORT_POWERUP:
+ mTeleportCount++;
+ break;
+ case ID_BRAKE_POWERUP:
+ if ( mBrakeCount < MAX_BRAKES )
+ mBrakeCount++;
+ break;
+ case ID_SHIELD_POWERUP:
+ if ( mShieldCount < MAX_SHIELDS )
+ mShieldCount++;
+ break;
+ case ID_SHOOT_POWERUP:
+ if ( mShootCount < MAX_FIREPOWER )
+ mShootCount++;
+ break;
+ }
+
+ powerups.removeRef( pup );
+ vitalsChanged = TRUE;
+ }
+ else if ( (*it) == shield )
+ {
+ powerups.removeRef( pup );
+ }
+ else if ( (*it)->rtti() == ID_MISSILE )
+ {
+ if ( can_destroy_powerups )
+ {
+ powerups.removeRef( pup );
+ }
+ }
+ }
+ }
+ } // -- if( powerups.isEmpty() )
+}
+
+// - - -
+
+void KAsteroidsView::hideShield()
+{
+ shield->hide();
+ mShieldCount = 0;
+ shieldOn = FALSE;
+}
+
+double KAsteroidsView::randDouble()
+{
+ int v = rand();
+ return (double)v / (double)RAND_MAX;
+}
+
+int KAsteroidsView::randInt( int range )
+{
+ return rand() % range;
+}
diff --git a/noncore/games/qasteroids/view.h b/noncore/games/qasteroids/view.h
new file mode 100644
index 0000000..0a7902b
--- a/dev/null
+++ b/noncore/games/qasteroids/view.h
@@ -0,0 +1,156 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************//*
+ * KAsteroids - Copyright (c) Martin R. Jones 1997
+ *
+ * Part of the KDE project
+ */
+
+#ifndef __AST_VIEW_H__
+#define __AST_VIEW_H__
+
+#include <qwidget.h>
+#include <qlist.h>
+#include <qintdict.h>
+#include <qtimer.h>
+#include <qcanvas.h>
+#include "sprites.h"
+
+#define QPtrList QList
+#define QPtrListIterator QListIterator
+
+#define MAX_POWER_LEVEL 1000
+
+class KAsteroidsView : public QWidget
+{
+ Q_OBJECT
+public:
+ KAsteroidsView( QWidget *parent = 0, const char *name = 0 );
+ virtual ~KAsteroidsView();
+
+ int refreshRate;
+
+ void reset();
+ void setRockSpeed( double rs ) { rockSpeed = rs; }
+ void addRocks( int num );
+ void newGame();
+ void endGame();
+ void newShip();
+
+ void rotateLeft( bool r ) { rotateL = r; rotateSlow = 5; }
+ void rotateRight( bool r ) { rotateR = r; rotateSlow = 5; }
+ void thrust( bool t ) { thrustShip = t && shipPower > 0; }
+ void shoot( bool s ) { shootShip = s; shootDelay = 0; }
+ void setShield( bool s );
+ void teleport( bool te) { teleportShip = te && mTeleportCount; }
+ void brake( bool b );
+ void pause( bool p);
+
+ void showText( const QString &text, const QColor &color, bool scroll=TRUE );
+ void hideText();
+
+ int shots() const { return shotsFired; }
+ int hits() const { return shotsHit; }
+ int power() const { return shipPower; }
+
+ int teleportCount() const { return mTeleportCount; }
+ int brakeCount() const { return mBrakeCount; }
+ int shieldCount() const { return mShieldCount; }
+ int shootCount() const { return mShootCount; }
+
+signals:
+ void shipKilled();
+ void rockHit( int size );
+ void rocksRemoved();
+ void updateVitals();
+
+private slots:
+ void hideShield();
+
+protected:
+ void readSprites();
+ void wrapSprite( QCanvasItem * );
+ void rockHit( QCanvasItem * );
+ void reducePower( int val );
+ void addExhaust( double x, double y, double dx, double dy, int count );
+ void processMissiles();
+ void processShip();
+ void processPowerups();
+ void processShield();
+ double randDouble();
+ int randInt( int range );
+
+ virtual void resizeEvent( QResizeEvent *event );
+ virtual void timerEvent( QTimerEvent * );
+
+private:
+ QCanvas field;
+ QCanvasView view;
+ QIntDict<QCanvasPixmapArray> animation;
+ QPtrList<QCanvasSprite> rocks;
+ QPtrList<KMissile> missiles;
+ QPtrList<KBit> bits;
+ QPtrList<KExhaust> exhaust;
+ QPtrList<KPowerup> powerups;
+ KShield *shield;
+ QCanvasSprite *ship;
+ QCanvasText *textSprite;
+
+ bool rotateL;
+ bool rotateR;
+ bool thrustShip;
+ bool shootShip;
+ bool teleportShip;
+ bool brakeShip;
+ bool pauseShip;
+ bool shieldOn;
+
+ bool vitalsChanged;
+
+ int shipAngle;
+ int rotateSlow;
+ int rotateRate;
+ int shipPower;
+
+ int shotsFired;
+ int shotsHit;
+ int shootDelay;
+
+ int mBrakeCount;
+ int mShieldCount;
+ int mTeleportCount;
+ int mShootCount;
+
+ double shipDx;
+ double shipDy;
+
+ int textDy;
+ int mFrameNum;
+ bool mPaused;
+ int mTimerId;
+
+ double rockSpeed;
+ double powerupSpeed;
+
+ bool can_destroy_powerups;
+
+ QTimer *shieldTimer;
+};
+
+#endif
diff --git a/noncore/games/snake/.cvsignore b/noncore/games/snake/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/noncore/games/snake/.cvsignore
@@ -0,0 +1,3 @@
+moc_*
+*.moc
+Makefile
diff --git a/noncore/games/snake/Makefile.in b/noncore/games/snake/Makefile.in
new file mode 100644
index 0000000..8179b6f
--- a/dev/null
+++ b/noncore/games/snake/Makefile.in
@@ -0,0 +1,159 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = snake
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = snake.h \
+ target.h \
+ obstacle.h \
+ interface.h \
+ codes.h
+SOURCES = snake.cpp \
+ target.cpp \
+ obstacle.cpp \
+ interface.cpp \
+ main.cpp
+OBJECTS = snake.o \
+ target.o \
+ obstacle.o \
+ interface.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_snake.cpp \
+ moc_interface.cpp
+OBJMOC = moc_snake.o \
+ moc_interface.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake snake.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+snake.o: snake.cpp \
+ snake.h \
+ target.h \
+ codes.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+target.o: target.cpp \
+ target.h \
+ codes.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+obstacle.o: obstacle.cpp \
+ obstacle.h \
+ codes.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+interface.o: interface.cpp \
+ interface.h \
+ snake.h \
+ target.h \
+ obstacle.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h
+
+main.o: main.cpp \
+ interface.h \
+ snake.h \
+ target.h \
+ obstacle.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_snake.o: moc_snake.cpp \
+ snake.h
+
+moc_interface.o: moc_interface.cpp \
+ interface.h \
+ snake.h \
+ target.h \
+ obstacle.h
+
+moc_snake.cpp: snake.h
+ $(MOC) snake.h -o moc_snake.cpp
+
+moc_interface.cpp: interface.h
+ $(MOC) interface.h -o moc_interface.cpp
+
+
diff --git a/noncore/games/snake/codes.h b/noncore/games/snake/codes.h
new file mode 100644
index 0000000..3b5e4d0
--- a/dev/null
+++ b/noncore/games/snake/codes.h
@@ -0,0 +1,20 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/const int target_rtti = 1500;
+const int obstacle_rtti = 1600;
diff --git a/noncore/games/snake/interface.cpp b/noncore/games/snake/interface.cpp
new file mode 100644
index 0000000..c9b4931
--- a/dev/null
+++ b/noncore/games/snake/interface.cpp
@@ -0,0 +1,224 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "interface.h"
+
+#include <qpe/resource.h>
+
+#include <qpe/qpetoolbar.h>
+#include <qtoolbutton.h>
+#include <qstyle.h>
+#include <qapplication.h>
+#include <qmessagebox.h>
+
+SnakeGame::SnakeGame(QWidget* parent, const char* name, WFlags f) :
+ QMainWindow(parent,name,f),
+ canvas(232, 258)
+{
+ setCaption( tr("Snake") );
+ QPixmap bg = Resource::loadPixmap("grass");
+ canvas.setBackgroundPixmap(bg);
+ canvas.setUpdatePeriod(100);
+ snake = 0;
+
+ cv = new QCanvasView(&canvas, this);
+
+ pauseTimer = new QTimer(this);
+ connect(pauseTimer, SIGNAL(timeout()), this, SLOT(wait()) );
+
+ setToolBarsMovable( FALSE );
+
+ QPEToolBar* toolbar = new QPEToolBar( this);
+ toolbar->setHorizontalStretchable( TRUE );
+
+ QPixmap newicon = Resource::loadPixmap("ksnake");
+ setIcon(newicon);
+ (void)new QToolButton(newicon, tr("New Game"), 0,
+ this, SLOT(newGame()), toolbar, "New Game");
+
+ scorelabel = new QLabel(toolbar);
+ showScore(0);
+ scorelabel->setBackgroundMode( PaletteButton );
+ scorelabel->setAlignment( AlignRight | AlignVCenter | ExpandTabs );
+ toolbar->setStretchableWidget( scorelabel );
+
+ setFocusPolicy(StrongFocus);
+
+ setCentralWidget(cv);
+
+ welcomescreen();
+ gamestopped = true;
+ waitover = true;
+}
+
+SnakeGame::~SnakeGame()
+{
+ delete snake;
+}
+
+void SnakeGame::resizeEvent(QResizeEvent *)
+{
+ QSize s = centralWidget()->size();
+ int fw = style().defaultFrameWidth();
+ canvas.resize( s.width() - fw - 2, s.height() - fw - 2);
+}
+
+void SnakeGame::welcomescreen()
+{
+ QCanvasText* title = new QCanvasText(tr("SNAKE!"), &canvas);
+ title->setColor(yellow);
+ title->setFont( QFont("times", 18, QFont::Bold) );
+ int w = title->boundingRect().width();
+ title->move(canvas.width()/2 -w/2, canvas.height()/2-110);
+ title->show();
+ QCanvasPixmapArray* titlearray = new QCanvasPixmapArray(Resource::findPixmap("title"));
+ QCanvasSprite* titlepic = new QCanvasSprite(titlearray, &canvas);
+ titlepic->move(canvas.width()/2 - 33, canvas.height()/2-85);
+ titlepic->show();
+ QCanvasText* instr = new QCanvasText(tr("Use the arrow keys to guide the\n"
+ "snake to eat the mouse. You must not\n"
+ "crash into the walls, edges or its tail."),
+ &canvas);
+ w = instr->boundingRect().width();
+ instr->move(canvas.width()/2-w/2, canvas.height()/2-20);
+ instr->setColor(white);
+ instr->show();
+ QCanvasText* cont = new QCanvasText(tr("Press Any Key To Start"), &canvas);
+ w = cont->boundingRect().width();
+ cont->move(canvas.width()/2-w/2, canvas.height()/2+80);
+ cont->setColor(yellow);
+ cont->show();
+
+}
+
+void SnakeGame::newGame()
+{
+ clear();
+ snake = new Snake(&canvas);
+ connect(snake, SIGNAL(dead()), this, SLOT(gameOver()) );
+ connect(snake, SIGNAL(targethit()), this, SLOT(levelUp()) );
+ connect(snake, SIGNAL(scorechanged()), this, SLOT(scoreInc()) );
+ connect(this, SIGNAL(moveFaster()), snake, SLOT(increaseSpeed()) );
+ last = 0;
+ targetamount = 1;
+ notargets = 1;
+ level = 1;
+ stage = 1;
+ showScore(0);
+ gamestopped = false;
+ waitover = true;
+ int x = canvas.width()/2 - 70;
+ x = x - x % 16;
+ int y = canvas.height()-50;
+ y = y - y % 16;
+ (void)new Obstacle(&canvas, x, 32);
+ (void)new Obstacle(&canvas, x, y);
+ createTargets();
+}
+
+
+void SnakeGame::showScore(int score)
+{
+ scorelabel->setText(tr(" Score : %1 ").arg(score) );
+}
+
+
+void SnakeGame::scoreInc()
+{
+ showScore( snake->getScore() );
+}
+
+void SnakeGame::levelUp()
+{
+ notargets--;
+ if (notargets == 0) {
+ stage++;
+ if (stage == 3) {
+ level++;
+ emit moveFaster();
+ targetamount++;
+ stage = 0;
+ }
+ createTargets();
+ }
+}
+
+void SnakeGame::createTargets()
+{
+ for (int i = 0; i < targetamount; i++)
+ (void)new Target(&canvas);
+ notargets = targetamount;
+}
+
+void SnakeGame::clear()
+{
+ delete snake;
+ snake = 0;
+ QCanvasItemList l = canvas.allItems();
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ delete *it;
+ }
+}
+
+void SnakeGame::gameOver()
+{
+ int score = snake->getScore();
+ QString scoreoutput="";
+ scoreoutput.setNum(score);
+ QCanvasText* gameover = new QCanvasText(tr("GAME OVER!\n Your Score: %1").arg( scoreoutput), &canvas);
+
+ gameover->setZ(100);
+ gameover->setColor(yellow);
+ gameover->setFont( QFont("times", 18, QFont::Bold) );
+ int w = gameover->boundingRect().width();
+ gameover->move(canvas.width()/2 -w/2, canvas.height()/2 -50);
+ gameover->show();
+ gamestopped = true;
+ waitover = false;
+ pauseTimer->start(2500);
+}
+
+void SnakeGame::wait()
+{
+ waitover = true;
+ pauseTimer->stop();
+ QCanvasText* cont = new QCanvasText(tr("Press Any Key to Begin a New Game."),
+ &canvas);
+ cont->setZ(100);
+ cont->setColor(white);
+ int w = cont->boundingRect().width();
+ cont->move(canvas.width()/2 -w/2, canvas.height()/2);
+ cont->show();
+}
+
+void SnakeGame::keyPressEvent(QKeyEvent* event)
+{
+ if (gamestopped) {
+ if (waitover)
+ newGame();
+ else
+ return;
+ }
+ else {
+ int newkey = event->key();
+ snake->go(newkey);
+ }
+}
+
diff --git a/noncore/games/snake/interface.h b/noncore/games/snake/interface.h
new file mode 100644
index 0000000..30c7f84
--- a/dev/null
+++ b/noncore/games/snake/interface.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qmainwindow.h>
+#include <qcanvas.h>
+#include <qlabel.h>
+
+#include "snake.h"
+#include "target.h"
+#include "obstacle.h"
+
+// class QCanvas;
+
+class SnakeGame : public QMainWindow {
+ Q_OBJECT
+
+public:
+ SnakeGame(QWidget* parent=0, const char* name=0, WFlags f=0);
+ ~SnakeGame();
+
+ void clear();
+ void createTargets();
+ void welcomescreen();
+
+protected:
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void resizeEvent(QResizeEvent *e);
+
+signals:
+ void moveFaster();
+
+private slots:
+ void newGame();
+ void gameOver();
+ void wait();
+ void levelUp();
+ void scoreInc();
+
+private:
+ void showScore(int);
+ QCanvasView* cv;
+ QLabel* scorelabel;
+ QCanvas canvas;
+ QTimer* pauseTimer;
+ Snake* snake;
+ int last;
+ int level;
+ int stage;
+ int targetamount;
+ int notargets;
+ bool waitover;
+ bool gamestopped;
+};
diff --git a/noncore/games/snake/main.cpp b/noncore/games/snake/main.cpp
new file mode 100644
index 0000000..90a93b7
--- a/dev/null
+++ b/noncore/games/snake/main.cpp
@@ -0,0 +1,35 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "interface.h"
+
+#include <qpe/qpeapplication.h>
+
+
+int main(int argc, char **argv)
+{
+ QPEApplication app(argc,argv);
+
+ SnakeGame* m = new SnakeGame;
+ QPEApplication::setInputMethodHint( m, QPEApplication::AlwaysOff );
+ app.showMainWidget(m);
+
+ return app.exec();
+}
diff --git a/noncore/games/snake/obstacle.cpp b/noncore/games/snake/obstacle.cpp
new file mode 100644
index 0000000..2d07fe7
--- a/dev/null
+++ b/noncore/games/snake/obstacle.cpp
@@ -0,0 +1,51 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "obstacle.h"
+#include "codes.h"
+
+#include <qpe/resource.h>
+
+Obstacle::Obstacle(QCanvas* canvas, int x, int y)
+ : QCanvasSprite(0, canvas)
+{
+ newObstacle(x, y);
+}
+
+void Obstacle::newObstacle(int x, int y)
+{
+ QCanvasPixmapArray* obstaclearray = new QCanvasPixmapArray(Resource::findPixmap("snake/wall.png"));
+
+ setSequence(obstaclearray);
+
+ move(x, y);
+
+ show();
+ canvas()->update();
+}
+
+int Obstacle::rtti() const
+{
+ return obstacle_rtti;
+}
+
+Obstacle::~Obstacle()
+{
+}
diff --git a/noncore/games/snake/obstacle.h b/noncore/games/snake/obstacle.h
new file mode 100644
index 0000000..838917f
--- a/dev/null
+++ b/noncore/games/snake/obstacle.h
@@ -0,0 +1,30 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qcanvas.h>
+
+class Obstacle : public QCanvasSprite
+{
+
+public:
+ Obstacle(QCanvas*, int x, int y);
+ ~Obstacle();
+ void newObstacle(int x, int y);
+ int rtti() const;
+};
diff --git a/noncore/games/snake/qpe-snake.control b/noncore/games/snake/qpe-snake.control
new file mode 100644
index 0000000..489e642
--- a/dev/null
+++ b/noncore/games/snake/qpe-snake.control
@@ -0,0 +1,9 @@
+Files: bin/snake apps/Games/snake.desktop pics/snake
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: control the snake
+ A game for the Qtopia environment.
diff --git a/noncore/games/snake/snake.cpp b/noncore/games/snake/snake.cpp
new file mode 100644
index 0000000..9f19841
--- a/dev/null
+++ b/noncore/games/snake/snake.cpp
@@ -0,0 +1,246 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "snake.h"
+#include "target.h"
+#include "codes.h"
+
+#include <qpe/resource.h>
+
+#include <qregexp.h>
+
+static int Piecekey[4][4] = { {6, 0, 4, 3 }, {0, 6, 2, 1 }, { 1, 3, 5, 0 }, {2, 4, 0, 5 } };
+
+Snake::Snake(QCanvas* c)
+{
+ canvas = c;
+ score = 0;
+ snakelist.setAutoDelete(true);
+ autoMoveTimer = new QTimer(this);
+ connect( autoMoveTimer, SIGNAL(timeout()), this, SLOT(moveSnake()) );
+ createSnake();
+}
+
+void Snake::createSnake()
+{
+ snakeparts = new QCanvasPixmapArray();
+ QString s0 = Resource::findPixmap("snake/s0001");
+ s0.replace(QRegExp("0001"),"%1");
+ snakeparts->readPixmaps(s0, 15);
+
+ grow = 0;
+ last = Key_Right;
+
+ QCanvasSprite* head = new QCanvasSprite(snakeparts, canvas );
+ head->setFrame(7);
+ snakelist.insert(0, head);
+ head->show();
+ head->move(34, 16);
+
+ QCanvasSprite* body = new QCanvasSprite(snakeparts, canvas );
+ body->setFrame(6);
+ snakelist.append( body );
+ body->show();
+ body->move(18, 16);
+
+ QCanvasSprite* end = new QCanvasSprite(snakeparts, canvas );
+ end->setFrame(11);
+ snakelist.append( end );
+ end->show();
+ end->move(2, 16);
+
+ currentdir = right;
+ speed = 250;
+ autoMoveTimer->start(speed);
+ moveSnake();
+}
+
+void Snake::increaseSpeed()
+{
+ if (speed > 150)
+ speed = speed - 5;
+ autoMoveTimer->start(speed);
+}
+
+void Snake::go(int newkey)
+{
+ // check key is a direction
+ if (!( (newkey == Key_Up) || (newkey == Key_Left) ||
+ (newkey == Key_Right) || (newkey == Key_Down) ))
+ return;
+ // check move is possible
+ if ( ((currentdir == left) && ((newkey == Key_Right) || (newkey == Key_Left)) ) ||
+ ((currentdir == right) && ((newkey == Key_Left) || (newkey == Key_Right)) ) ||
+ ((currentdir == up) && ((newkey == Key_Down) || (newkey == Key_Up)) ) ||
+ ((currentdir == down) && ((newkey == Key_Up) || (newkey == Key_Down)) ) )
+ return;
+ else {
+ Snake::changeHead(newkey);
+ Snake::moveSnake();
+ }
+}
+
+void Snake::move(Direction dir)
+{
+ autoMoveTimer->start(speed);
+ int x = 0;
+ int y = 0;
+ newdir = dir;
+ switch (dir) {
+ case right: x = 16; break;
+ case left: x = -16; break;
+ case down: y = 16; break;
+ case up: y = -16; break;
+ }
+ int index = lookUpPiece(currentdir, newdir);
+ QCanvasSprite* sprite = new QCanvasSprite(snakeparts, canvas );
+ sprite->setFrame(index);
+ snakelist.insert(1, sprite);
+ sprite->move(snakelist.first()->x(), snakelist.first()->y() );
+
+ snakelist.first()->moveBy(x, y);
+ if (grow <= 0)
+ changeTail();
+ else
+ grow--;
+ sprite->show();
+
+ currentdir = dir;
+}
+
+void Snake::changeTail()
+{
+ snakelist.removeLast();
+
+ double lastx = snakelist.last()->x();
+ double prevx = snakelist.prev()->x();
+ int index = 0;
+
+ if ( prevx == lastx ) { //vertical
+ if ( snakelist.prev()->y() > snakelist.last()->y() )
+ index = 13;
+ else
+ index = 14;
+ } else { //horizontal
+ if (snakelist.prev()->x() > snakelist.last()->x() )
+ index = 11;
+ else
+ index = 12;
+ }
+
+ snakelist.last()->setFrame(index);
+}
+
+void Snake::changeHead(int lastkey)
+{
+ int index = 0;
+ last = lastkey;
+
+ switch (last)
+ {
+ case Key_Up: index = 10; break;
+ case Key_Left: index = 8; break;
+ case Key_Right: index = 7; break;
+ case Key_Down: index = 9; break;
+ }
+
+ if (index) {
+ snakelist.first()->setFrame(index);
+ }
+}
+
+// returns an integer corresponding to a particular type of snake piece
+int Snake::lookUpPiece(Direction currentdir, Direction newdir)
+{
+ return Piecekey[currentdir][newdir];
+}
+
+void Snake::extendSnake()
+{
+ grow++;
+}
+
+void Snake::moveSnake()
+{
+ switch (last)
+ {
+ case Key_Up: move(up); break;
+ case Key_Left: move(left); break;
+ case Key_Right: move(right); break;
+ case Key_Down: move(down); break;
+ }
+ detectCrash();
+}
+
+void Snake::detectCrash()
+{
+ QCanvasSprite* head = snakelist.first();
+ QCanvasItem* item;
+ QCanvasItemList l=head->collisions(FALSE);
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ item = *it;
+ // check if snake hit target
+ if ( (item->rtti()== 1500 ) && (item->collidesWith(head)) ) {
+ Target* target = (Target*) item;
+ target->done();
+ emit targethit();
+ extendSnake();
+ setScore(5);
+ return;
+ }
+ // check if snake hit obstacles
+ if ( (item->rtti()==1600) && (item->collidesWith(head)) ) {
+ emit dead();
+ autoMoveTimer->stop();
+ return;
+ }
+ }
+ //check if snake hit itself
+ for (uint i = 3; i < snakelist.count(); i++) {
+ if (head->collidesWith(snakelist.at(i)) ) {
+ emit dead();
+ autoMoveTimer->stop();
+ return;
+ }
+ }
+ //check if snake hit edge
+ if ( (head->x() > canvas->width()-5) || (head->y() > canvas->height()-10)
+ || (head->x() <2) || (head->y() <-5) ) {
+ emit dead();
+ autoMoveTimer->stop();
+ return;
+ }
+}
+
+void Snake::setScore(int amount)
+{
+ score = score + amount;
+ emit scorechanged();
+}
+
+int Snake::getScore()
+{
+ return score;
+}
+
+Snake::~Snake()
+{
+ autoMoveTimer->stop();
+}
diff --git a/noncore/games/snake/snake.h b/noncore/games/snake/snake.h
new file mode 100644
index 0000000..5725343
--- a/dev/null
+++ b/noncore/games/snake/snake.h
@@ -0,0 +1,64 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qcanvas.h>
+#include <qtimer.h>
+
+class Snake : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Direction{ left, right, up, down};
+
+ Snake(QCanvas*);
+ ~Snake();
+ void go(int newkey);
+ void move(Direction dir);
+ void changeHead(int last);
+ void changeTail();
+ void detectCrash();
+ void createSnake();
+ void extendSnake();
+ int lookUpPiece(Direction currentdir, Direction newdir);
+ void setScore(int amount);
+ int getScore();
+
+signals:
+ void dead();
+ void targethit();
+ void scorechanged();
+
+private slots:
+ void moveSnake();
+ void increaseSpeed();
+
+private:
+ QCanvasPixmapArray* snakeparts;
+ QList<QCanvasSprite>snakelist;
+ QTimer* autoMoveTimer;
+ QCanvas* canvas;
+ int grow;
+ int last;
+ int speed;
+ int score;
+ Direction currentdir;
+ Direction newdir;
+};
+
diff --git a/noncore/games/snake/snake.pro b/noncore/games/snake/snake.pro
new file mode 100644
index 0000000..6dacdbd
--- a/dev/null
+++ b/noncore/games/snake/snake.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = snake.h target.h obstacle.h interface.h codes.h
+SOURCES = snake.cpp target.cpp obstacle.cpp interface.cpp main.cpp
+TARGET = snake
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+TRANSLATIONS = ../i18n/de/snake.ts
diff --git a/noncore/games/snake/target.cpp b/noncore/games/snake/target.cpp
new file mode 100644
index 0000000..a09af69
--- a/dev/null
+++ b/noncore/games/snake/target.cpp
@@ -0,0 +1,77 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "target.h"
+#include "codes.h"
+
+#include <qpe/resource.h>
+
+#include <stdlib.h>
+
+Target::Target(QCanvas* canvas)
+ : QCanvasSprite(0, canvas)
+{
+ mouse = new QCanvasPixmapArray(Resource::findPixmap("snake/mouse"));
+ setSequence(mouse);
+ newTarget();
+}
+
+void Target::newTarget()
+{
+ static bool first_time = TRUE;
+ if (first_time) {
+ first_time = FALSE;
+ QTime midnight(0, 0, 0);
+ srand(midnight.secsTo(QTime::currentTime()) );
+ }
+ do {
+ int x = rand() % (canvas()->width()-10);
+ x = x - (x % 16) + 2;
+ int y = rand() % (canvas()->height()-10);
+ y = y - (y % 16) + 2;
+ move(x, y);
+ } while (onTop());
+ show();
+}
+
+bool Target::onTop()
+{
+ QCanvasItem* item;
+ QCanvasItemList l= canvas()->allItems(); //collisions(FALSE);
+ for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) {
+ item = *it;
+ if (item != this && item->collidesWith(this)) return true;
+ }
+ return false;
+}
+
+void Target::done()
+{
+ delete this;
+}
+
+int Target::rtti() const
+{
+ return target_rtti;
+}
+
+Target::~Target()
+{
+}
diff --git a/noncore/games/snake/target.h b/noncore/games/snake/target.h
new file mode 100644
index 0000000..a6da37c
--- a/dev/null
+++ b/noncore/games/snake/target.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qcanvas.h>
+#include <qdatetime.h>
+
+class Target : public QCanvasSprite
+{
+
+public:
+ Target(QCanvas*);
+ ~Target();
+ void newTarget();
+ void done();
+ void createMouse();
+ bool onTop();
+ int rtti() const;
+
+private:
+ QCanvasPixmapArray* mouse;
+};
diff --git a/noncore/games/solitaire/.cvsignore b/noncore/games/solitaire/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/noncore/games/solitaire/.cvsignore
@@ -0,0 +1,3 @@
+moc_*
+*.moc
+Makefile
diff --git a/noncore/games/solitaire/Makefile.in b/noncore/games/solitaire/Makefile.in
new file mode 100644
index 0000000..3c50345
--- a/dev/null
+++ b/noncore/games/solitaire/Makefile.in
@@ -0,0 +1,235 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = patience
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = canvascard.h \
+ canvasshapes.h \
+ cardgame.h \
+ cardgamelayout.h \
+ cardpile.h \
+ card.h \
+ carddeck.h \
+ canvascardgame.h \
+ freecellcardgame.h \
+ patiencecardgame.h \
+ canvascardwindow.h
+SOURCES = canvascard.cpp \
+ canvasshapes.cpp \
+ cardgame.cpp \
+ cardgamelayout.cpp \
+ cardpile.cpp \
+ card.cpp \
+ carddeck.cpp \
+ canvascardgame.cpp \
+ freecellcardgame.cpp \
+ patiencecardgame.cpp \
+ canvascardwindow.cpp \
+ main.cpp
+OBJECTS = canvascard.o \
+ canvasshapes.o \
+ cardgame.o \
+ cardgamelayout.o \
+ cardpile.o \
+ card.o \
+ carddeck.o \
+ canvascardgame.o \
+ freecellcardgame.o \
+ patiencecardgame.o \
+ canvascardwindow.o \
+ main.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_canvascardwindow.cpp
+OBJMOC = moc_canvascardwindow.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake solitaire.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=patience
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+canvascard.o: canvascard.cpp \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h \
+ canvascard.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+canvasshapes.o: canvasshapes.cpp \
+ canvasshapes.h
+
+cardgame.o: cardgame.cpp \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h
+
+cardgamelayout.o: cardgamelayout.cpp \
+ cardgamelayout.h \
+ cardpile.h
+
+cardpile.o: cardpile.cpp \
+ cardpile.h \
+ card.h \
+ $(QPEDIR)/include/qpe/config.h
+
+card.o: card.cpp \
+ card.h \
+ $(QPEDIR)/include/qpe/config.h
+
+carddeck.o: carddeck.cpp \
+ card.h \
+ carddeck.h
+
+canvascardgame.o: canvascardgame.cpp \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h \
+ canvasshapes.h \
+ canvascard.h \
+ canvascardgame.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+freecellcardgame.o: freecellcardgame.cpp \
+ freecellcardgame.h \
+ patiencecardgame.h \
+ canvascardgame.h \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h \
+ canvasshapes.h \
+ canvascard.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+patiencecardgame.o: patiencecardgame.cpp \
+ patiencecardgame.h \
+ canvascardgame.h \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h \
+ canvasshapes.h \
+ canvascard.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h
+
+canvascardwindow.o: canvascardwindow.cpp \
+ canvascardwindow.h \
+ patiencecardgame.h \
+ canvascardgame.h \
+ cardgame.h \
+ card.h \
+ cardpile.h \
+ carddeck.h \
+ cardgamelayout.h \
+ canvasshapes.h \
+ canvascard.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpemenubar.h \
+ freecellcardgame.h
+
+main.o: main.cpp \
+ canvascardwindow.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+moc_canvascardwindow.o: moc_canvascardwindow.cpp \
+ canvascardwindow.h
+
+moc_canvascardwindow.cpp: canvascardwindow.h
+ $(MOC) canvascardwindow.h -o moc_canvascardwindow.cpp
+
+
diff --git a/noncore/games/solitaire/canvascard.cpp b/noncore/games/solitaire/canvascard.cpp
new file mode 100644
index 0000000..ae3c859
--- a/dev/null
+++ b/noncore/games/solitaire/canvascard.cpp
@@ -0,0 +1,282 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "cardgame.h"
+#include "canvascard.h"
+
+#include <qpe/resource.h>
+
+#include <qpainter.h>
+#include <qimage.h>
+#include <qpaintdevice.h>
+#include <qbitmap.h>
+
+#include <math.h>
+
+#if defined( QT_QWS_CASSIOPEIA )
+#define SLOW_HARDWARE
+#endif
+
+// Seems to be fast enough to me even without Transformations in the library
+//#if defined( QT_NO_TRANSFORMATIONS ) && defined( QT_QWS_IPAQ )
+//#define SLOW_HARDWARE
+//#endif
+
+
+QBitmap *Create180RotatedBitmap(QBitmap *srcBitmap)
+{
+#ifdef QT_NO_TRANSFORMATIONS
+ int w = srcBitmap->width();
+ int h = srcBitmap->height();
+ QBitmap *dstBitmap = new QBitmap( w, h );
+ // ### this is very poorly implemented and probably could be much faster
+ for (int i = 0; i < w; i++)
+ for (int j = 0; j < h; j++)
+ bitBlt( dstBitmap, i, j, srcBitmap, w - i - 1, h - j - 1, 1, 1 );
+ return dstBitmap;
+#else
+ QWMatrix m;
+ m.rotate( 180.0 );
+ return new QBitmap( srcBitmap->xForm( m ) );
+#endif
+}
+
+
+QPixmap *CreateScaledPixmap(QPixmap *srcPixmap, double scaleX, double scaleY)
+{
+#ifdef QT_NO_TRANSFORMATIONS
+ int w = srcPixmap->width();
+ int h = srcPixmap->height();
+ int newW = (int)(w * scaleX);
+ int newH = (int)(h * scaleY);
+ QPixmap *dstPixmap = new QPixmap( newW, newH );
+ // ### this is very poorly implemented and probably could be much faster
+ for (int i = 0; i < newW; i++) {
+ int srcX = w * i / newW;
+ if (newH == h) {
+ // Optimise for scaleing in the X-axis only
+ bitBlt( dstPixmap, i, 0, srcPixmap, srcX, 0, 1, h );
+ } else {
+ for (int j = 0; j < newH; j++) {
+ int srcY = h * j / newH;
+ bitBlt( dstPixmap, i, j, srcPixmap, srcX, srcY, 1, 1 );
+ }
+ }
+ }
+ return dstPixmap;
+#else
+ QWMatrix s;
+ s.scale( scaleX, scaleY );
+ return new QPixmap( srcPixmap->xForm( s ) );
+#endif
+}
+
+
+// Initialise static member variables to NULL
+QPixmap *CanvasCard::cardsFaces = NULL;
+QPixmap *CanvasCard::cardsBacks = NULL;
+QBitmap *CanvasCard::cardsChars = NULL;
+QBitmap *CanvasCard::cardsSuits = NULL;
+QBitmap *CanvasCard::cardsCharsUpsideDown = NULL;
+QBitmap *CanvasCard::cardsSuitsUpsideDown = NULL;
+
+
+CanvasCard::CanvasCard( eValue v, eSuit s, bool f, QCanvas *canvas ) :
+ Card(v, s, f), QCanvasRectangle( 0, 0, 1, 1, canvas ), cardBack(1), scaleX(1.0), scaleY(1.0)
+{
+ if ( !cardsFaces ) {
+ cardsFaces = new QPixmap( Resource::loadPixmap( "cards/card_face" ) );
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0001" ) );
+ cardsChars = new QBitmap( Resource::loadBitmap( "cards/card_chars" ) );
+ cardsSuits = new QBitmap( Resource::loadBitmap( "cards/card_suits" ) );
+ cardsCharsUpsideDown = Create180RotatedBitmap( cardsChars );
+ cardsSuitsUpsideDown = Create180RotatedBitmap( cardsSuits );
+ }
+ xOff = cardsFaces->width() / 2;
+ yOff = cardsFaces->height() / 2;
+ setSize( cardsFaces->width(), cardsFaces->height() );
+ setPen( NoPen );
+ flipping = FALSE;
+}
+
+
+void CanvasCard::setCardBack(int b)
+{
+ if ( cardBack != b ) {
+
+ cardBack = b;
+
+ if ( cardsBacks )
+ delete cardsBacks;
+
+ switch (cardBack) {
+ case 0:
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0001" ) ); break;
+ case 1:
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0002" ) ); break;
+ case 2:
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0003" ) ); break;
+ case 3:
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0004" ) ); break;
+ case 4:
+ cardsBacks = new QPixmap( Resource::loadPixmap( "cards/card_back0005" ) ); break;
+ }
+
+ if ( !isFacing() )
+ redraw();
+ }
+}
+
+
+void CanvasCard::draw(QPainter &painter)
+{
+ int ix = (int)x(), iy = (int)y();
+
+ QPainter *p = &painter;
+ QPixmap *unscaledCard = NULL;
+
+ if ((scaleX <= 0.98) || (scaleY <= 0.98))
+ {
+ p = new QPainter();
+ unscaledCard = new QPixmap( cardsFaces->width(), cardsFaces->height() );
+ p->begin(unscaledCard);
+ ix = 0;
+ iy = 0;
+ }
+
+ if ( isFacing() ) {
+
+/*
+ // Now add the joker and card backs to the list of pixmaps
+ QPixmap *CardsBack = new QPixmap( Resource::loadPixmap( "cards/card_joker.png" ) );
+ QPoint *newBackHotspot = new QPoint( 0, 0 );
+ pixmaps->append((const QPixmap *)CardsBack);
+ hotspots->append((const QPoint *)newBackHotspot);
+*/
+
+ int w = cardsFaces->width(), h = cardsFaces->height();
+
+// p->setBrush( NoBrush );
+ p->setBrush( QColor( 0xFF, 0xFF, 0xFF ) );
+
+ if ( isRed() == TRUE )
+ p->setPen( QColor( 0xFF, 0, 0 ) );
+ else
+ p->setPen( QColor( 0, 0, 0 ) );
+
+ p->drawPixmap( ix + 0, iy + 0, *cardsFaces );
+ p->drawPixmap( ix + 4, iy + 4, *cardsChars, 7*(getValue()-1), 0, 7, 7 );
+ p->drawPixmap( ix + 12, iy + 4, *cardsSuits, 7*(getSuit()-1), 0, 7, 8 );
+ p->drawPixmap( ix + w-4-7, iy + h-4-7, *cardsCharsUpsideDown, 7*(12-getValue()+1), 0, 7, 7 );
+ p->drawPixmap( ix + w-12-7, iy + h-5-7, *cardsSuitsUpsideDown, 7*(3-getSuit()+1), 0, 7, 8 );
+
+ } else {
+
+ p->drawPixmap( ix, iy, *cardsBacks );
+
+ }
+
+ if (p != &painter)
+ {
+ p->end();
+ QPixmap *scaledCard = CreateScaledPixmap( unscaledCard, scaleX, scaleY );
+ int xoff = scaledCard->width() / 2;
+ int yoff = scaledCard->height() / 2;
+ painter.drawPixmap( (int)x() + xOff - xoff, (int)y() + yOff - yoff, *scaledCard );
+ delete p;
+ delete unscaledCard;
+ delete scaledCard;
+ }
+}
+
+
+static const double flipLift = 1.5;
+
+
+void CanvasCard::flipTo(int x2, int y2, int steps)
+{
+ flipSteps = steps;
+
+#ifdef SLOW_HARDWARE
+ move(x2,y2);
+ Card::flipTo(x2,y2,steps);
+#else
+ int x1 = (int)x();
+ int y1 = (int)y();
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+
+ flipping = TRUE;
+ destX = x2;
+ destY = y2;
+ animSteps = flipSteps;
+ setVelocity(dx/animSteps, dy/animSteps-flipLift);
+ setAnimated(TRUE);
+#endif
+}
+
+
+void CanvasCard::advance(int stage)
+{
+ if ( stage==1 ) {
+ if ( animSteps-- <= 0 ) {
+ scaleX = 1.0;
+ scaleY = 1.0;
+ flipping = FALSE;
+ setVelocity(0,0);
+ setAnimated(FALSE);
+ move(destX,destY); // exact
+ } else {
+ if ( flipping ) {
+ if ( animSteps > flipSteps / 2 ) {
+ // animSteps = flipSteps .. flipSteps/2 (flip up) -> 1..0
+ scaleX = ((double)animSteps/flipSteps-0.5)*2;
+ } else {
+ // animSteps = flipSteps/2 .. 0 (flip down) -> 0..1
+ scaleX = 1-((double)animSteps/flipSteps)*2;
+ }
+ if ( animSteps == flipSteps / 2-1 ) {
+ setYVelocity(yVelocity()+flipLift*2);
+ setFace( !isFacing() );
+ }
+ }
+ }
+ }
+ QCanvasRectangle::advance(stage);
+}
+
+
+void CanvasCard::animatedMove(int x2, int y2, int steps)
+{
+ destX = x2;
+ destY = y2;
+
+ double x1 = x(), y1 = y(), dx = x2 - x1, dy = y2 - y1;
+
+ // Ensure a good speed
+ while ( fabs(dx/steps)+fabs(dy/steps) < 5.0 && steps > 4 )
+ steps--;
+
+ setAnimated(TRUE);
+ setVelocity(dx/steps, dy/steps);
+
+ animSteps = steps;
+}
+
diff --git a/noncore/games/solitaire/canvascard.h b/noncore/games/solitaire/canvascard.h
new file mode 100644
index 0000000..cd9691f
--- a/dev/null
+++ b/noncore/games/solitaire/canvascard.h
@@ -0,0 +1,82 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CANVAS_CARD_H
+#define CANVAS_CARD_H
+
+
+#include <qpainter.h>
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qpoint.h>
+#include <qcanvas.h>
+#include "cardgame.h"
+
+
+// ### Just made the number up, is that what you do???
+static const int canvasCardId = 2434321;
+
+
+class CanvasCard : public Card, public QCanvasRectangle
+{
+public:
+ CanvasCard( eValue v, eSuit s, bool f, QCanvas *canvas );
+ virtual ~CanvasCard() { canvas()->removeItem(this); }
+
+ int rtti () const { return canvasCardId; }
+ void move(QPoint p) { QCanvasItem::move( p.x(), p.y() ); }
+ void move(int x, int y) { QCanvasItem::move( x, y ); }
+ void animatedMove(int x, int y, int steps = 10);
+ void animatedMove() { animatedMove(savedX, savedY); }
+ void savePos(void) { savedX = (int)x(); savedY = (int)y(); }
+ void moveToPile(int p) { Q_UNUSED(p); }
+ void setCardBack(int b);
+
+ /*virtual*/ void flipTo(int x, int y, int steps = 8);
+ /*virtual*/ void setPos( int x, int y, int z ) { setX( x ); setY( y ); setZ( z ); }
+ /*virtual*/ void showCard(void) { show(); }
+ /*virtual*/ void redraw(void) { hide(); show(); }
+ /*virtual*/ void draw(QPainter &p);
+
+ void advance(int stage);
+
+protected:
+ /*virtual*/ void flip(void) { redraw(); }
+
+private:
+ int destX, destY;
+ int animSteps;
+ int flipSteps;
+ bool flipping;
+ int savedX, savedY;
+ int cardBack;
+ int oldCardBack;
+ double scaleX, scaleY;
+ int xOff, yOff;
+ static QPixmap *cardsFaces;
+ static QPixmap *cardsBacks;
+ static QBitmap *cardsChars;
+ static QBitmap *cardsSuits;
+ static QBitmap *cardsCharsUpsideDown;
+ static QBitmap *cardsSuitsUpsideDown;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/canvascardgame.cpp b/noncore/games/solitaire/canvascardgame.cpp
new file mode 100644
index 0000000..32635a0
--- a/dev/null
+++ b/noncore/games/solitaire/canvascardgame.cpp
@@ -0,0 +1,380 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "cardgame.h"
+#include "canvasshapes.h"
+#include "canvascard.h"
+#include "canvascardgame.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qmainwindow.h>
+#include <qpe/qpemenubar.h>
+#include <qpainter.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+#include <math.h>
+
+
+extern int highestZ;
+
+
+class CanvasCardPile : public QCanvasRectangle
+{
+public:
+ CanvasCardPile( CanvasCardGame *ccg, QCanvas *canvas ) : QCanvasRectangle( canvas ), parent( ccg ) {
+ pile = new QPixmap( 0, 0 );
+ pileHeight = 0;
+ firstCard = NULL;
+ }
+
+ void addCard( CanvasCard *card );
+ void advance(int stage);
+ void animatedMove() { animatedMove(savedX, savedY); }
+ void savePos(void) { savedX = (int)x(); savedY = (int)y(); }
+ void animatedMove(int x2, int y2, int steps = 7 );
+
+protected:
+ virtual void draw( QPainter& p );
+
+private:
+ CanvasCardGame *parent;
+ QPixmap *pile;
+ QImage tempImage32;
+ CanvasCard *firstCard;
+ int pileHeight;
+ int destX, destY;
+ int savedX, savedY;
+ int animSteps;
+};
+
+
+void CanvasCardPile::addCard( CanvasCard *card )
+{
+ if ( !firstCard )
+ firstCard = card;
+
+ int height = 36 + pileHeight * 13;
+ setSize( 23, height );
+ pile->resize( 23, height );
+ QPainter p( pile );
+ p.translate( -card->x(), -card->y() + pileHeight * 13 );
+ card->draw( p );
+ pileHeight++;
+
+ QImage tempImage;
+ tempImage = *pile;
+ tempImage32 = tempImage.convertDepth( 32 );
+ tempImage32.setAlphaBuffer( TRUE );
+ for ( int i = 0; i < tempImage32.width(); i++ )
+ for ( int j = 0; j < tempImage32.height(); j++ ) {
+ QRgb col = tempImage32.pixel( i, j );
+ int a = 255-j*220/tempImage32.height();
+ QRgb alpha = qRgba( qRed( col ), qGreen( col ), qBlue( col ), a );
+ tempImage32.setPixel( i, j, alpha );
+ }
+
+ QRgb alpha = qRgba( 0, 0, 0, 0 );
+ tempImage32.setPixel( 1, 0, alpha );
+ tempImage32.setPixel( 0, 0, alpha );
+ tempImage32.setPixel( 0, 1, alpha );
+
+ tempImage32.setPixel( 21, 0, alpha );
+ tempImage32.setPixel( 22, 0, alpha );
+ tempImage32.setPixel( 22, 1, alpha );
+ height--;
+ tempImage32.setPixel( 1, height, alpha );
+ tempImage32.setPixel( 0, height - 1, alpha );
+ tempImage32.setPixel( 0, height, alpha );
+
+ tempImage32.setPixel( 21, height, alpha );
+ tempImage32.setPixel( 22, height, alpha );
+ tempImage32.setPixel( 22, height - 1, alpha );
+}
+
+
+void CanvasCardPile::advance(int stage)
+{
+ if ( stage==1 ) {
+ if ( animSteps-- <= 0 ) {
+ CanvasCard *item = firstCard;
+ while (item) {
+ item->show();
+ item = (CanvasCard *)item->getCardPile()->cardInfront(item);
+ }
+ setVelocity(0,0);
+ setAnimated(FALSE);
+ parent->cancelMoving();
+ hide();
+ move(destX,destY); // exact
+ }
+ }
+ QCanvasRectangle::advance(stage);
+}
+
+
+void CanvasCardPile::animatedMove(int x2, int y2, int steps = 7 )
+{
+ destX = x2;
+ destY = y2;
+
+ double x1 = x(), y1 = y(), dx = x2 - x1, dy = y2 - y1;
+
+ // Ensure a good speed
+ while ( fabs(dx/steps)+fabs(dy/steps) < 5.0 && steps > 4 )
+ steps--;
+
+ setAnimated(TRUE);
+ setVelocity(dx/steps, dy/steps);
+
+ animSteps = steps;
+}
+
+
+void CanvasCardPile::draw( QPainter& p )
+{
+ int ix = (int)x(), iy = (int)y();
+ p.drawImage( ix, iy, tempImage32 );
+}
+
+
+CanvasCardGame::~CanvasCardGame() {
+ // the deletion stuff should be fixed now and only deletes
+ // items created by this CardGame. I haven't verified there are zero
+ // memory leaks yet
+ if ( alphaCardPile )
+ delete alphaCardPile;
+}
+
+
+void CanvasCardGame::gameWon() {
+
+ srand(time(NULL));
+
+ QCanvasItemList list = canvas()->allItems();
+ QCanvasItemList::Iterator it = list.begin();
+
+ for (; it != list.end(); ++it) {
+ if ( (*it)->rtti() == canvasCardId ) {
+ // disperse the cards everywhere
+ int x = 300 - rand() % 1000;
+ int y = 300 + rand() % 200;
+ ((CanvasCard *)*it)->animatedMove( x, y, 50 );
+ }
+ }
+}
+
+
+void CanvasCardGame::contentsMousePressEvent(QMouseEvent *e) {
+
+ if ( moving )
+ return;
+
+ QCanvasItemList l = canvas()->collisions( e->pos() );
+
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+
+ if ( (*it)->rtti() == canvasCardId ) {
+
+ moving = (CanvasCard *)*it;
+
+ if ( moving->animated() )
+ return;
+
+ cardXOff = (int)(e->pos().x() - moving->x());
+ cardYOff = (int)(e->pos().y() - moving->y());
+
+ if ( !mousePressCard( moving, e->pos() ) ) {
+ CanvasCard *card = moving;
+
+ if ( alphaCardPile )
+ delete alphaCardPile;
+
+ alphaCardPile = new CanvasCardPile( this, canvas() );
+ alphaCardPile->move( card->x(), card->y() );
+ alphaCardPile->savePos();
+ alphaCardPile->show();
+
+ while (card) {
+ alphaCardPile->addCard( card );
+ card->hide();
+ card = (CanvasCard *)card->getCardPile()->cardInfront(card);
+ }
+
+ alphaCardPile->setZ( INT_MAX );
+
+ moved = TRUE;
+ } else {
+ if ( alphaCardPile )
+ alphaCardPile->hide();
+ }
+ return;
+ }
+ }
+
+ mousePress( e->pos() );
+}
+
+/*
+//
+// Should have some intelligent way to make double clicking on a
+// card send it to the most appropriate pile
+//
+void CanvasCardGame::contentsMouseDoubleClickEvent(QMouseEvent *e) {
+ QCanvasItemList l = canvas()->collisions( e->pos() );
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ( (*it)->rtti() == canvasCardId ) {
+ CanvasCard *card = (CanvasCard *)*it;
+
+ if ( card->animated() )
+ return;
+
+ if ( card->getCardPile()->isAllowedToBeMoved(card) ) {
+ if (card->getCardPile()->cardInfront(card) == NULL) {
+ CardPile *pile = first();
+ if (pile && pile->isAllowedOnTop(card)) {
+ // move card to this pile
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+*/
+
+void CanvasCardGame::contentsMouseMoveEvent(QMouseEvent *e) {
+
+ QPoint p = e->pos();
+
+ if ( moving ) {
+
+ moved = TRUE;
+
+ if (moving->isFacing() != TRUE)
+ return;
+
+ int tx = (int)p.x() - cardXOff;
+ int ty = (int)p.y() - cardYOff;
+
+ if (snapOn == TRUE) {
+ CardPile *pile = closestPile( tx, ty, 50 );
+ if ( pile && pile->isAllowedOnTop( moving ) ) {
+ QPoint p = pile->getHypertheticalNextCardPos();
+ if ( alphaCardPile )
+ alphaCardPile->move( p.x(), p.y() );
+ return;
+ }
+ }
+
+ if ( alphaCardPile )
+ alphaCardPile->move( tx, ty );
+ }
+
+}
+
+
+void CanvasCardGame::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+ QPoint p = e->pos();
+
+ Q_UNUSED(p);
+
+ if ( moving ) {
+
+ CanvasCard *item = moving;
+
+ if ( item->animated() )
+ return;
+
+ if ( alphaCardPile )
+ if ( moved ) {
+
+ CardPile *pile = closestPile((int)alphaCardPile->x(), (int)alphaCardPile->y(), 30);
+
+ if (pile && pile->isAllowedOnTop(item)) {
+ CardPile *oldPile = item->getCardPile();
+ Card *c = NULL;
+ if ( oldPile != pile) {
+ while ( item ) {
+ item->show();
+ if ( oldPile ) {
+ c = oldPile->cardInfront(item);
+ oldPile->removeCard(item);
+ }
+ pile->addCardToTop(item);
+ item->setCardPile(pile);
+ //item->move( pile->getCardPos(item) );
+ QPoint p = pile->getCardPos(item);
+ item->setPos( p.x(), p.y(), highestZ );
+ highestZ++;
+
+ if (item->getValue() == king && haveWeWon()) {
+ alphaCardPile->hide();
+ gameWon();
+ moving = NULL;
+ return;
+ }
+
+ if (oldPile) {
+ item = (CanvasCard *)c;
+ } else {
+ item = NULL;
+ }
+ }
+ alphaCardPile->hide();
+ moving = NULL;
+ return;
+ }
+ }
+
+ alphaCardPile->animatedMove();
+ }
+ }
+
+ moved = FALSE;
+}
+
+
+void CanvasCardGame::readPile( Config& cfg, CardPile *pile, QString name, int& highestZ )
+{
+ cfg.setGroup( name );
+ int numberOfCards = cfg.readNumEntry("NumberOfCards", 0);
+ Card *card = NULL;
+ for ( int i = 0; i < numberOfCards; i++ ) {
+ QString cardStr;
+ cardStr.sprintf( "%i", i );
+ int val = cfg.readNumEntry( "Card" + cardStr );
+ bool facing = cfg.readBoolEntry( "CardFacing" + cardStr );
+ card = cards[ val ];
+ card->setFace(facing);
+ pile->addCardToTop(card);
+ card->setCardPile(pile);
+ QPoint p = pile->getCardPos( card );
+ card->setPos( p.x(), p.y(), highestZ );
+ card->showCard();
+ highestZ++;
+ }
+}
+
+
diff --git a/noncore/games/solitaire/canvascardgame.h b/noncore/games/solitaire/canvascardgame.h
new file mode 100644
index 0000000..4d32014
--- a/dev/null
+++ b/noncore/games/solitaire/canvascardgame.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CANVAS_CARD_GAME_H
+#define CANVAS_CARD_GAME_H
+
+#include "cardgame.h"
+#include "canvasshapes.h"
+#include "canvascard.h"
+
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qmainwindow.h>
+#include <qpe/qpemenubar.h>
+#include <qpainter.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+
+class CanvasCardPile;
+
+
+class CanvasCardGame : public QCanvasView, public CardGame
+{
+public:
+ CanvasCardGame(QCanvas &c, bool snap, QWidget *parent = 0, const char *name = 0, WFlags f = 0) :
+ QCanvasView( &c, parent, name, f ),
+ moved(FALSE),
+ moving(NULL),
+ alphaCardPile( NULL ),
+ cardXOff(0), cardYOff(0),
+ snapOn(snap),
+ numberToDraw(1) { }
+
+ virtual ~CanvasCardGame();
+
+ virtual Card *newCard( eValue v, eSuit s, bool f ) {
+ return new CanvasCard( v, s, f, canvas() );
+ }
+
+ virtual void readConfig( Config& cfg ) { Q_UNUSED( cfg ); }
+ virtual void writeConfig( Config& cfg ) { Q_UNUSED( cfg ); }
+
+ virtual void gameWon();
+ virtual bool haveWeWon() { return FALSE; }
+
+ virtual bool mousePressCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); return FALSE; }
+ virtual void mouseReleaseCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); }
+
+ void cancelMoving() { moving = NULL; }
+ void toggleSnap() { snapOn = (snapOn == TRUE) ? FALSE : TRUE; }
+ void toggleCardsDrawn() { numberToDraw = (numberToDraw == 1) ? 3 : 1; }
+ int cardsDrawn() { return numberToDraw; }
+ void setNumberToDraw(int numToDraw) { this->numberToDraw = numToDraw; }
+
+ void readPile( Config& cfg, CardPile *pile, QString name, int& highestZ );
+
+protected:
+ void contentsMousePressEvent(QMouseEvent *e);
+ void contentsMouseReleaseEvent(QMouseEvent *e);
+ void contentsMouseMoveEvent(QMouseEvent *e);
+
+protected:
+ // Mouse event state variables
+ bool moved;
+ CanvasCard *moving;
+ CanvasCardPile *alphaCardPile;
+ int cardXOff, cardYOff;
+
+private:
+ bool snapOn;
+ int numberToDraw;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/canvascardwindow.cpp b/noncore/games/solitaire/canvascardwindow.cpp
new file mode 100644
index 0000000..4c365a5
--- a/dev/null
+++ b/noncore/games/solitaire/canvascardwindow.cpp
@@ -0,0 +1,227 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "canvascardwindow.h"
+#include "patiencecardgame.h"
+#include "freecellcardgame.h"
+
+#include <qpe/resource.h>
+
+#include <qmainwindow.h>
+#include <qpopupmenu.h>
+#include <qstyle.h>
+
+
+CanvasCardWindow::CanvasCardWindow(QWidget* parent, const char* name, WFlags f) :
+ QMainWindow(parent, name, f), canvas(230, 260), snapOn(TRUE), cardBack(4), gameType(0),
+ cardGame(NULL)
+{
+ setIcon( Resource::loadPixmap( "cards" ) );
+
+ // Create Playing Area for Games
+ if ( QPixmap::defaultDepth() < 12 ) {
+// canvas.setBackgroundColor(QColor(0x51, 0x74, 0x6B));
+// canvas.setBackgroundColor(QColor(0x20, 0xb0, 0x50));
+ canvas.setBackgroundColor(QColor(0x08, 0x98, 0x2D));
+ } else {
+ QPixmap bg;
+ bg.convertFromImage( Resource::loadImage( "table_pattern" ), ThresholdDither );
+ canvas.setBackgroundPixmap(bg);
+ }
+
+#if defined( QT_QWS_CASSIOPEIA )
+ canvas.setAdvancePeriod(70);
+#else
+ canvas.setAdvancePeriod(30);
+#endif
+
+
+#ifdef _PATIENCE_USE_ACCELS_
+ QPEMenuBar* menu = menuBar();
+
+ QPopupMenu* file = new QPopupMenu;
+ file->insertItem(tr("Patience"), this, SLOT(initPatience()), CTRL+Key_F);
+ file->insertItem(tr("Freecell"), this, SLOT(initFreecell()), CTRL+Key_F);
+ menu->insertItem(tr("&Game"), file);
+
+ menu->insertSeparator();
+
+ settings = new QPopupMenu;
+ settings->insertItem(tr("&Change Card Backs"), this, SLOT(changeCardBacks()), Key_F2);
+ snap_id = settings->insertItem(tr("&Snap To Position"), this, SLOT(snapToggle()), Key_F3);
+ settings->setCheckable(TRUE);
+ menu->insertItem(tr("&Settings"),settings);
+
+ menu->insertSeparator();
+
+ QPopupMenu* help = new QPopupMenu;
+ help->insertItem(tr("&About"), this, SLOT(help()), Key_F1);
+ help->setItemChecked(dbf_id, TRUE);
+ menu->insertItem(tr("&Help"),help);
+#else
+ QMenuBar* menu = menuBar();
+
+ QPopupMenu* file = new QPopupMenu;
+ file->insertItem(tr("Patience"), this, SLOT(initPatience()));
+ file->insertItem(tr("Freecell"), this, SLOT(initFreecell()));
+ menu->insertItem(tr("Play"), file);
+
+ menu->insertSeparator();
+
+ settings = new QPopupMenu;
+ settings->setCheckable(TRUE);
+ settings->insertItem(tr("Change Card Backs"), this, SLOT(changeCardBacks()));
+ snap_id = settings->insertItem(tr("Snap To Position"), this, SLOT(snapToggle()));
+ QString m;
+
+ drawId = settings->insertItem(tr("Turn One Card"), this, SLOT(drawnToggle()));
+ menu->insertItem(tr("Settings"),settings);
+
+#endif
+
+ menu->show();
+
+ Config cfg( "Patience" );
+ cfg.setGroup( "GlobalSettings" );
+ snapOn = cfg.readBoolEntry( "SnapOn", TRUE);
+ settings->setItemChecked(snap_id, snapOn);
+ gameType = cfg.readNumEntry( "GameType", -1 );
+ drawThree = cfg.readBoolEntry( "DrawThree", TRUE);
+ if ( gameType == 0 ) {
+ cardGame = new PatienceCardGame( &canvas, snapOn, this );
+ cardGame->setNumberToDraw(drawThree ? 3 : 1);
+ setCaption(tr("Patience"));
+ setCentralWidget(cardGame);
+ cardGame->readConfig( cfg );
+ setCardBacks();
+ } else if ( gameType == 1 ) {
+ cardGame = new FreecellCardGame( &canvas, snapOn, this );
+ setCaption(tr("Freecell"));
+ setCentralWidget(cardGame);
+ //cardGame->newGame(); // Until we know how to handle reading freecell config
+ cardGame->readConfig( cfg );
+ setCardBacks();
+ } else {
+ // Probably there isn't a config file or it is broken
+ // Start a new game
+ initPatience();
+ }
+
+ updateDraw();
+}
+
+
+CanvasCardWindow::~CanvasCardWindow()
+{
+ if (cardGame) {
+ Config cfg("Patience");
+ cfg.setGroup( "GlobalSettings" );
+ cfg.writeEntry( "GameType", gameType );
+ cfg.writeEntry( "SnapOn", snapOn );
+ cfg.writeEntry( "DrawThree", drawThree);
+ cardGame->writeConfig( cfg );
+ delete cardGame;
+ }
+}
+
+
+void CanvasCardWindow::resizeEvent(QResizeEvent *)
+{
+ QSize s = centralWidget()->size();
+ int fw = style().defaultFrameWidth();
+ canvas.resize( s.width() - fw - 2, s.height() - fw - 2);
+}
+
+
+void CanvasCardWindow::initPatience()
+{
+ // Create New Game
+ if ( cardGame )
+ delete cardGame;
+ cardGame = new PatienceCardGame( &canvas, snapOn, this );
+ cardGame->setNumberToDraw(drawThree ? 3 : 1);
+ gameType = 0;
+ setCaption(tr("Patience"));
+ setCentralWidget(cardGame);
+ cardGame->newGame();
+ setCardBacks();
+ updateDraw();
+}
+
+
+void CanvasCardWindow::initFreecell()
+{
+ // Create New Game
+ if ( cardGame ) {
+ delete cardGame;
+ }
+ cardGame = new FreecellCardGame( &canvas, snapOn, this );
+ gameType = 1;
+ setCaption(tr("Freecell"));
+ setCentralWidget(cardGame);
+ cardGame->newGame();
+ setCardBacks();
+}
+
+
+void CanvasCardWindow::snapToggle()
+{
+ snapOn = !snapOn;
+ settings->setItemChecked(snap_id, snapOn);
+ cardGame->toggleSnap();
+}
+
+
+void CanvasCardWindow::drawnToggle()
+{
+ cardGame->toggleCardsDrawn();
+ updateDraw();
+}
+
+void CanvasCardWindow::updateDraw() {
+ if(cardGame->cardsDrawn() == 3)
+ settings->changeItem(drawId, tr("Turn One Card"));
+ else
+ settings->changeItem(drawId, tr("Turn Three Cards"));
+}
+
+
+void CanvasCardWindow::setCardBacks()
+{
+ QCanvasItemList l = canvas.allItems();
+
+ for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) {
+ if ( (*it)->rtti() == canvasCardId )
+ ((CanvasCard *)(*it))->setCardBack( cardBack );
+ }
+}
+
+
+void CanvasCardWindow::changeCardBacks()
+{
+ cardBack++;
+
+ if (cardBack == 5)
+ cardBack = 0;
+
+ setCardBacks();
+}
+
+
diff --git a/noncore/games/solitaire/canvascardwindow.h b/noncore/games/solitaire/canvascardwindow.h
new file mode 100644
index 0000000..b75d40a
--- a/dev/null
+++ b/noncore/games/solitaire/canvascardwindow.h
@@ -0,0 +1,70 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CANVAS_CARD_WINDOW_H
+#define CANVAS_CARD_WINDOW_H
+
+
+#include <qmainwindow.h>
+#include <qcanvas.h>
+
+
+class CanvasCardGame;
+class QPopupMenu;
+
+
+class CanvasCardWindow : public QMainWindow {
+ Q_OBJECT
+
+public:
+ CanvasCardWindow(QWidget* parent=0, const char* name=0, WFlags f=0);
+ virtual ~CanvasCardWindow();
+
+public slots:
+ void setCardBacks();
+ void changeCardBacks();
+ void snapToggle();
+ void drawnToggle();
+
+private slots:
+ void initFreecell();
+ void initPatience();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *e);
+
+ void updateDraw();
+private:
+ QCanvas canvas;
+ bool snapOn;
+ bool drawThree;
+ int drawId;
+ int cardBack;
+ int gameType;
+ CanvasCardGame *cardGame;
+
+ QPopupMenu* options;
+ QPopupMenu* settings;
+ int dbf_id;
+ int snap_id;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/canvasshapes.cpp b/noncore/games/solitaire/canvasshapes.cpp
new file mode 100644
index 0000000..28d0b4e
--- a/dev/null
+++ b/noncore/games/solitaire/canvasshapes.cpp
@@ -0,0 +1,92 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <qpainter.h>
+#include <qcanvas.h>
+#include "canvasshapes.h"
+
+
+CanvasRoundRect::CanvasRoundRect(int x, int y, QCanvas *canvas) :
+ QCanvasRectangle( x, y, 23, 36, canvas)
+{
+ setZ(0);
+ show();
+}
+
+
+void CanvasRoundRect::redraw()
+{
+ hide();
+ show();
+}
+
+
+void CanvasRoundRect::drawShape(QPainter &p)
+{
+ p.drawRoundRect( (int)x(), (int)y(), 23, 36);
+}
+
+
+CanvasCircleOrCross::CanvasCircleOrCross(int x, int y, QCanvas *canvas) :
+ QCanvasRectangle( x, y, 21, 21, canvas), circleShape(TRUE)
+{
+ show();
+}
+
+
+void CanvasCircleOrCross::redraw()
+{
+ hide();
+ show();
+}
+
+
+void CanvasCircleOrCross::setCircle()
+{
+ circleShape = TRUE;
+ redraw();
+}
+
+
+void CanvasCircleOrCross::setCross()
+{
+ circleShape = FALSE;
+ redraw();
+}
+
+
+void CanvasCircleOrCross::drawShape(QPainter &p)
+{
+ int x1 = (int)x(), y1 = (int)y();
+ // Green circle
+ if (circleShape == TRUE) {
+ p.setPen( QPen( QColor(0x10, 0xE0, 0x10), 1 ) );
+ p.drawEllipse( x1 - 1, y1 - 1, 21, 21);
+ p.drawEllipse( x1 - 1, y1 - 0, 21, 19);
+ p.drawEllipse( x1 + 0, y1 + 0, 19, 19);
+ p.drawEllipse( x1 + 1, y1 + 0, 17, 19);
+ p.drawEllipse( x1 + 1, y1 + 1, 17, 17);
+ // Red cross
+ } else {
+ p.setPen( QPen( QColor(0xE0, 0x10, 0x10), 5 ) );
+ p.drawLine( x1, y1, x1 + 20, y1 + 20);
+ p.drawLine( x1 + 20, y1, x1, y1 + 20);
+ }
+}
+
diff --git a/noncore/games/solitaire/canvasshapes.h b/noncore/games/solitaire/canvasshapes.h
new file mode 100644
index 0000000..72acf6b
--- a/dev/null
+++ b/noncore/games/solitaire/canvasshapes.h
@@ -0,0 +1,55 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CANVAS_SHAPES_H
+#define CANVAS_SHAPES_H
+
+
+#include <qcanvas.h>
+
+
+class QPainter;
+
+
+class CanvasRoundRect : QCanvasRectangle
+{
+public:
+ CanvasRoundRect(int x, int y, QCanvas *canvas);
+ void redraw();
+protected:
+ void drawShape(QPainter &p);
+};
+
+
+class CanvasCircleOrCross : QCanvasRectangle
+{
+public:
+ CanvasCircleOrCross(int x, int y, QCanvas *canvas);
+ void redraw();
+ void setCircle();
+ void setCross();
+protected:
+ void drawShape(QPainter &p);
+private:
+ bool circleShape;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/card.cpp b/noncore/games/solitaire/card.cpp
new file mode 100644
index 0000000..609e280
--- a/dev/null
+++ b/noncore/games/solitaire/card.cpp
@@ -0,0 +1,53 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "card.h"
+
+#include <qpe/config.h>
+
+#include <qpoint.h>
+#include <qlist.h>
+
+/*
+Card( eValue v, eSuit s, bool f ) :
+ val(v), suit(s), faceUp(f), showing(FALSE), ix(0), iy(0), iz(0), cardPile(NULL) { }
+virtual ~Card() { }
+eValue getValue() { return val; }
+eSuit getSuit() { return suit; }
+CardPile *getCardPile() { return cardPile; }
+bool isFacing() { return faceUp; }
+bool isShowing() { return showing; }
+bool isRed() { return ((suit == diamonds) || (suit == hearts)); }
+int getX(void) { return ix; }
+int getY(void) { return iy; }
+int getZ(void) { return iz; }
+void setCardPile(CardPile *p) { cardPile = p; }
+void setFace(bool f) { faceUp = f; }
+void flip(void) { flipTo(getX(), getY()); }
+virtual void setPos(int x, int y, int z) { ix = x; iy = y; iz = z; }
+virtual void move(int x, int y) { ix = x; iy = y; }
+virtual void move(QPoint p) { ix = p.x(); iy = p.y(); }
+virtual void flipTo(int x, int y, int steps = 8) { ix = x; iy = y; faceUp = !faceUp; redraw(); Q_UNUSED(steps); }
+virtual void showCard(void) { showing = TRUE; }
+virtual void hideCard(void) { showing = FALSE; }
+virtual void redraw(void) { }
+*/
+
+
diff --git a/noncore/games/solitaire/card.h b/noncore/games/solitaire/card.h
new file mode 100644
index 0000000..eb30d30
--- a/dev/null
+++ b/noncore/games/solitaire/card.h
@@ -0,0 +1,84 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CARD_H
+#define CARD_H
+
+
+#include <qpoint.h>
+
+
+class CardPile;
+
+
+enum eSuit {
+ jokerSuit = 0, clubs, spades, diamonds, hearts
+};
+
+
+enum eValue {
+ jokerVal = 0, ace, two, three, four, five,
+ six, seven, eight, nine, ten, jack, queen, king
+};
+
+
+class Card
+{
+public:
+ Card( eValue v, eSuit s, bool f ) :
+ val(v), suit(s), faceUp(f), showing(FALSE), ix(0), iy(0), iz(0), cardPile(NULL) { }
+ virtual ~Card() { }
+
+ eValue getValue() { return val; }
+ eSuit getSuit() { return suit; }
+
+ void setCardPile(CardPile *p) { cardPile = p; }
+ CardPile *getCardPile() { return cardPile; }
+
+ void setFace(bool f) { faceUp = f; /* flip(); */ }
+ bool isFacing() { return faceUp; }
+
+ bool isShowing() { return showing; }
+ bool isRed() { return ((suit == diamonds) || (suit == hearts)); }
+
+ int getX(void) { return ix; }
+ int getY(void) { return iy; }
+ int getZ(void) { return iz; }
+ void flip(void) { flipTo(getX(), getY()); }
+
+ virtual void setPos(int x, int y, int z) { ix = x; iy = y; iz = z; }
+ virtual void move(int x, int y) { ix = x; iy = y; }
+ virtual void move(QPoint p) { ix = p.x(); iy = p.y(); }
+ virtual void flipTo(int x, int y, int steps = 8) { ix = x; iy = y; faceUp = !faceUp; redraw(); Q_UNUSED(steps); }
+ virtual void showCard(void) { showing = TRUE; }
+ virtual void hideCard(void) { showing = FALSE; }
+protected:
+ virtual void redraw(void) { }
+private:
+ eValue val;
+ eSuit suit;
+ bool faceUp;
+ bool showing;
+ int ix, iy, iz;
+ CardPile *cardPile;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/carddeck.cpp b/noncore/games/solitaire/carddeck.cpp
new file mode 100644
index 0000000..87c043a
--- a/dev/null
+++ b/noncore/games/solitaire/carddeck.cpp
@@ -0,0 +1,81 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include <stdlib.h>
+#include <time.h>
+#include "card.h"
+#include "carddeck.h"
+
+
+CardDeck::CardDeck(int jokers) : numberOfJokers(jokers), deckCreated(FALSE)
+{
+ cards = new (Card *)[getNumberOfCards()];
+}
+
+
+CardDeck::~CardDeck()
+{
+ for (int i = 0; i < getNumberOfCards(); i++)
+ delete cards[i];
+ delete cards;
+}
+
+
+void CardDeck::createDeck()
+{
+ if (!deckCreated) {
+ for (int i = 0; i < 52; i++)
+ cards[i] = newCard( (eValue)((i % 13) + 1), (eSuit)((i / 13) + 1), FALSE );
+ for (int i = 0; i < getNumberOfJokers(); i++)
+ cards[52 + i] = newCard( jokerVal, jokerSuit, FALSE );
+ deckCreated = TRUE;
+ }
+}
+
+
+void CardDeck::shuffle()
+{
+ srand(time(NULL));
+ for (int i = 0; i < getNumberOfCards(); i++) {
+ int index = rand() % getNumberOfCards();
+ Card *tmpCard = cards[i];
+ cards[i] = cards[index];
+ cards[index] = tmpCard;
+ }
+}
+
+
+int CardDeck::getNumberOfCards()
+{
+ return 52 + getNumberOfJokers();
+}
+
+
+int CardDeck::getNumberOfJokers()
+{
+ return numberOfJokers;
+}
+
+
+Card *CardDeck::newCard( eValue v, eSuit s, bool f )
+{
+ return new Card(v, s, f);
+}
+
+
diff --git a/noncore/games/solitaire/carddeck.h b/noncore/games/solitaire/carddeck.h
new file mode 100644
index 0000000..9ad35a9
--- a/dev/null
+++ b/noncore/games/solitaire/carddeck.h
@@ -0,0 +1,49 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CARD_DECK_H
+#define CARD_DECK_H
+
+
+class Card;
+
+
+class CardDeck
+{
+public:
+ CardDeck(int jokers = 0);
+ virtual ~CardDeck();
+
+ void createDeck();
+ void shuffle();
+ int getNumberOfCards();
+ int getNumberOfJokers();
+
+ virtual Card *newCard( eValue v, eSuit s, bool f );
+ virtual void deal() { }
+
+ Card **cards;
+private:
+ int numberOfJokers;
+ bool deckCreated;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/cardgame.cpp b/noncore/games/solitaire/cardgame.cpp
new file mode 100644
index 0000000..b19aeef
--- a/dev/null
+++ b/noncore/games/solitaire/cardgame.cpp
@@ -0,0 +1,35 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "cardgame.h"
+
+
+void CardGame::newGame()
+{
+ // Create Cards
+ createDeck();
+
+ // Shuffle Cards
+ shuffle();
+
+ // Deal Cards
+ deal();
+}
+
+
diff --git a/noncore/games/solitaire/cardgame.h b/noncore/games/solitaire/cardgame.h
new file mode 100644
index 0000000..dd7efab
--- a/dev/null
+++ b/noncore/games/solitaire/cardgame.h
@@ -0,0 +1,45 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CARD_GAME_H
+#define CARD_GAME_H
+
+
+#include <qpoint.h>
+#include "card.h"
+#include "cardpile.h"
+#include "carddeck.h"
+#include "cardgamelayout.h"
+
+
+class CardGame : public CardGameLayout, public CardDeck
+{
+public:
+ CardGame(int numOfJokers = 0) : CardGameLayout(), CardDeck(numOfJokers) { }
+ virtual ~CardGame() { }
+ virtual void newGame();
+ virtual void mousePress(QPoint p) { Q_UNUSED(p); }
+ virtual void mouseRelease(QPoint p) { Q_UNUSED(p); }
+ virtual void mouseMove(QPoint p) { Q_UNUSED(p); }
+private:
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/cardgamelayout.cpp b/noncore/games/solitaire/cardgamelayout.cpp
new file mode 100644
index 0000000..1ceee8d
--- a/dev/null
+++ b/noncore/games/solitaire/cardgamelayout.cpp
@@ -0,0 +1,61 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "cardgamelayout.h"
+
+
+CardGameLayout::~CardGameLayout()
+{
+ // Should I just do setAutoDelete( TRUE ); ?
+ for (CardPile *p = first(); p != NULL; p = next())
+ delete p;
+}
+
+
+CardPile *CardGameLayout::closestPile(int x, int y, int maxDistance)
+{
+ int closestDistance = maxDistance * maxDistance;
+ CardPile *closestPile = NULL;
+
+ for (CardPile *p = first(); p != NULL; p = next()) {
+ int d = p->distanceFromNextPos(x, y);
+ if (d < closestDistance) {
+ closestDistance = d;
+ closestPile = p;
+ }
+ }
+
+ return closestPile;
+}
+
+
+void CardGameLayout::beginDealing()
+{
+ for (CardPile *p = first(); p != NULL; p = next())
+ p->beginDealing();
+}
+
+
+void CardGameLayout::endDealing()
+{
+ for (CardPile *p = first(); p != NULL; p = next())
+ p->endDealing();
+}
+
+
diff --git a/noncore/games/solitaire/cardgamelayout.h b/noncore/games/solitaire/cardgamelayout.h
new file mode 100644
index 0000000..bb36e6b
--- a/dev/null
+++ b/noncore/games/solitaire/cardgamelayout.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CARD_GAME_LAYOUT_H
+#define CARD_GAME_LAYOUT_H
+
+
+#include <qlist.h>
+#include "cardpile.h"
+
+
+class CardGameLayout : public QList<CardPile>
+{
+public:
+ CardGameLayout() { }
+ virtual ~CardGameLayout();
+
+ void addCardPile(CardPile *pile) { append((const CardPile *)pile); }
+ CardPile *closestPile(int x, int y, int maxDistance);
+ void beginDealing();
+ void endDealing();
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/cardpile.cpp b/noncore/games/solitaire/cardpile.cpp
new file mode 100644
index 0000000..0b738d2
--- a/dev/null
+++ b/noncore/games/solitaire/cardpile.cpp
@@ -0,0 +1,114 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "cardpile.h"
+#include "card.h"
+
+#include <qpe/config.h>
+#include <qpoint.h>
+
+#include <qlist.h>
+
+
+CardPile::CardPile(int x, int y) : pileX(x), pileY(y), dealing(FALSE) {
+ pileWidth = 0;
+ pileHeight = 0;
+ pileNextX = pileX;
+ pileNextY = pileY;
+ pileCenterX = x + pileWidth / 2;
+ pileCenterY = y + pileHeight / 2;
+ pileRadius = (pileWidth > pileHeight) ? pileWidth : pileHeight;
+}
+
+
+int CardPile::distanceFromPile(int x, int y) {
+ return (pileCenterX-x)*(pileCenterX-x)+(pileCenterY-y)*(pileCenterY-y);
+}
+
+
+int CardPile::distanceFromNextPos(int x, int y) {
+ return (pileNextX-x)*(pileNextX-x)+(pileNextY-y)*(pileNextY-y);
+}
+
+
+Card *CardPile::cardInfront(Card *c) {
+ CardPile *p = c->getCardPile();
+ if (p) {
+ p->at(p->find(c));
+ return p->next();
+ } else {
+ return NULL;
+ }
+}
+
+
+bool CardPile::kingOnTop() {
+ Card *top = cardOnTop();
+ return top && top->getValue() == king;
+}
+
+
+bool CardPile::addCardToTop(Card *c) {
+ if (dealing || isAllowedOnTop(c)) {
+ append((const Card *)c);
+ cardAddedToTop(c);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+bool CardPile::addCardToBottom(Card *c) {
+ if (dealing || isAllowedOnBottom(c)) {
+ prepend((const Card *)c);
+ cardAddedToBottom(c);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+bool CardPile::removeCard(Card *c) {
+ if (dealing || isAllowedToBeMoved(c)) {
+ take(find(c));
+ cardRemoved(c);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void CardPile::writeConfig( Config& cfg, QString name ) {
+ int numberOfCards = 0;
+ cfg.setGroup( name );
+ Card *card = cardOnBottom();
+ while ( card ) {
+ QString cardStr;
+ cardStr.sprintf( "%i", numberOfCards );
+ int val = (int)card->getValue() - 1 + ( (int)card->getSuit() - 1 ) * 13;
+ cfg.writeEntry( "Card" + cardStr, val );
+ cfg.writeEntry( "CardFacing" + cardStr, card->isFacing() );
+ card = cardInfront( card );
+ numberOfCards++;
+ }
+ cfg.writeEntry("NumberOfCards", numberOfCards);
+}
+
+
diff --git a/noncore/games/solitaire/cardpile.h b/noncore/games/solitaire/cardpile.h
new file mode 100644
index 0000000..c515bbc
--- a/dev/null
+++ b/noncore/games/solitaire/cardpile.h
@@ -0,0 +1,101 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef CARD_PILE_H
+#define CARD_PILE_H
+
+
+#include <qpoint.h>
+#include <qlist.h>
+
+
+enum ePileStackingType {
+ pileCascades = 0, pileStacks, pileCascadesOrStacks
+};
+
+
+enum ePileFaceingType {
+ pileFaceUp = 0, pileFaceDown, pileFaceUpOrDown
+};
+
+
+class Card;
+class Config;
+
+
+class CardPile : public QList<Card>
+{
+public:
+ CardPile(int x, int y);
+ virtual ~CardPile() { }
+
+ int getX() { return pileX; }
+ int getY() { return pileY; }
+ int getNextX() { return pileNextX; }
+ int getNextY() { return pileNextY; }
+ int getWidth() { return pileWidth; }
+ int getHeight() { return pileHeight; }
+
+ void setX(int x) { pileX = x; }
+ void setY(int y) { pileY = y; }
+ void setNextX(int x) { pileNextX = x; }
+ void setNextY(int y) { pileNextY = y; }
+ void setWidth(int width) { pileWidth = width; }
+ void setHeight(int height) { pileHeight = height; }
+
+ void beginDealing() { dealing = TRUE; }
+ void endDealing() { dealing = FALSE; }
+ bool isDealing() { return dealing; }
+
+ int distanceFromPile(int x, int y);
+ int distanceFromNextPos(int x, int y);
+
+ Card *cardOnTop() { return getLast(); }
+ Card *cardOnBottom() { return getFirst(); }
+ Card *cardInfront(Card *c);
+ bool kingOnTop();
+
+ bool addCardToTop(Card *c);
+ bool addCardToBottom(Card *c);
+ bool removeCard(Card *c);
+
+ virtual void cardAddedToTop(Card *) { }
+ virtual void cardAddedToBottom(Card *) { }
+ virtual void cardRemoved(Card *) { }
+ virtual bool isAllowedOnTop(Card *) { return FALSE; }
+ virtual bool isAllowedOnBottom(Card *) { return FALSE; }
+ virtual bool isAllowedToBeMoved(Card *) { return FALSE; }
+ virtual QPoint getCardPos(Card *) { return QPoint(pileX, pileY); }
+ virtual QPoint getHypertheticalNextCardPos() { return QPoint(pileX, pileY); }
+
+ void writeConfig( Config& cfg, QString name );
+
+protected:
+ int pileX, pileY;
+ int pileNextX, pileNextY;
+ int pileWidth, pileHeight;
+ int pileCenterX, pileCenterY;
+ int pileRadius;
+private:
+ bool dealing;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/freecellcardgame.cpp b/noncore/games/solitaire/freecellcardgame.cpp
new file mode 100644
index 0000000..e82afd4
--- a/dev/null
+++ b/noncore/games/solitaire/freecellcardgame.cpp
@@ -0,0 +1,137 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "freecellcardgame.h"
+
+
+extern int highestZ;
+int numberOfFreeCells = 4;
+
+
+FreecellCardGame::FreecellCardGame(QCanvas *c, bool snap, QWidget *parent) : CanvasCardGame(*c, snap, parent)
+{
+ numberOfFreeCells = 4;
+ highestZ = 0;
+
+ for (int i = 0; i < 4; i++) {
+ freecellPiles[i] = new FreecellFreecellPile( 5 + i * 28, 10, canvas() );
+ addCardPile(freecellPiles[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ discardPiles[i] = new FreecellDiscardPile( 125 + i * 28, 10, canvas() );
+ addCardPile(discardPiles[i]);
+ }
+ for (int i = 0; i < 8; i++) {
+ workingPiles[i] = new FreecellWorkingPile( 10 + i * 28, 50, canvas() );
+ addCardPile(workingPiles[i]);
+ }
+}
+
+
+void FreecellCardGame::deal(void)
+{
+ highestZ = 1;
+
+ beginDealing();
+
+ for (int i = 0; i < 52; i++) {
+ Card *card = cards[i];
+ card->setFace( TRUE );
+ card->setPos( 0, 0, highestZ );
+ card->setCardPile( workingPiles[i%8] );
+ workingPiles[i%8]->addCardToTop( card );
+ card->move( workingPiles[i%8]->getCardPos( card ) );
+ card->showCard();
+ highestZ++;
+ }
+
+ endDealing();
+}
+
+
+bool FreecellCardGame::mousePressCard( Card *c, QPoint p )
+{
+ Q_UNUSED(p);
+
+ if ( !c->getCardPile()->isAllowedToBeMoved(c) ) {
+ moving = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void FreecellCardGame::readConfig( Config& cfg )
+{
+ cfg.setGroup("GameState");
+
+ // Create Cards, but don't shuffle or deal them yet
+ createDeck();
+
+ // Move the cards to their piles (deal them to their previous places)
+ beginDealing();
+
+ highestZ = 1;
+
+ for (int k = 0; k < 4; k++) {
+ QString pile;
+ pile.sprintf( "FreeCellPile%i", k );
+ readPile( cfg, freecellPiles[k], pile, highestZ );
+ }
+
+ for (int k = 0; k < 4; k++) {
+ QString pile;
+ pile.sprintf( "DiscardPile%i", k );
+ readPile( cfg, discardPiles[k], pile, highestZ );
+ }
+
+ for (int k = 0; k < 8; k++) {
+ QString pile;
+ pile.sprintf( "WorkingPile%i", k );
+ readPile( cfg, workingPiles[k], pile, highestZ );
+ }
+
+ highestZ++;
+
+ endDealing();
+}
+
+
+void FreecellCardGame::writeConfig( Config& cfg )
+{
+ cfg.setGroup("GameState");
+ for ( int i = 0; i < 4; i++ ) {
+ QString pile;
+ pile.sprintf( "FreeCellPile%i", i );
+ freecellPiles[i]->writeConfig( cfg, pile );
+ }
+ for ( int i = 0; i < 4; i++ ) {
+ QString pile;
+ pile.sprintf( "DiscardPile%i", i );
+ discardPiles[i]->writeConfig( cfg, pile );
+ }
+ for ( int i = 0; i < 8; i++ ) {
+ QString pile;
+ pile.sprintf( "WorkingPile%i", i );
+ workingPiles[i]->writeConfig( cfg, pile );
+ }
+}
+
+
diff --git a/noncore/games/solitaire/freecellcardgame.h b/noncore/games/solitaire/freecellcardgame.h
new file mode 100644
index 0000000..f1b09ab
--- a/dev/null
+++ b/noncore/games/solitaire/freecellcardgame.h
@@ -0,0 +1,152 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef FREECELL_CARD_GAME_H
+#define FREECELL_CARD_GAME_H
+
+
+#include "patiencecardgame.h"
+
+
+extern int numberOfFreeCells;
+
+
+class FreecellDiscardPile : public PatienceDiscardPile
+{
+public:
+ FreecellDiscardPile(int x, int y, QCanvas *canvas) :
+ PatienceDiscardPile(x, y, canvas) { }
+
+};
+
+
+class FreecellWorkingPile : public PatienceWorkingPile
+{
+public:
+ FreecellWorkingPile(int x, int y, QCanvas *canvas) :
+ PatienceWorkingPile(x, y, canvas) { }
+
+ virtual bool isAllowedOnTop(Card *card) {
+ if ( cardOnBottom() == NULL ) {
+ int numberOfCardsBeingMoved = 0;
+ Card *tempCard = card;
+
+ while ((tempCard != NULL)) {
+ numberOfCardsBeingMoved++;
+ tempCard = cardInfront(tempCard);
+ }
+
+ if (numberOfCardsBeingMoved > numberOfFreeCells)
+ return FALSE;
+ }
+
+ if ( card->isFacing() &&
+ cardOnTop() == NULL )
+ return TRUE;
+ return PatienceWorkingPile::isAllowedOnTop( card );
+ }
+
+ virtual bool isAllowedToBeMoved(Card *card) {
+ int nextExpectedValue = (int)card->getValue();
+ bool nextExpectedColor = card->isRed();
+ int numberOfCardsBeingMoved = 0;
+
+ while ((card != NULL)) {
+ numberOfCardsBeingMoved++;
+ if ( (int)card->getValue() != nextExpectedValue )
+ return FALSE;
+ if ( card->isRed() != nextExpectedColor )
+ return FALSE;
+ nextExpectedValue--;;
+ nextExpectedColor = !nextExpectedColor;
+ card = cardInfront(card);
+ }
+
+ if (numberOfCardsBeingMoved <= (numberOfFreeCells + 1))
+ return TRUE;
+
+ return FALSE;
+ }
+ virtual void cardRemoved(Card *card) {
+ if ( !isDealing() && !cardOnTop() )
+ numberOfFreeCells++;
+ PatienceWorkingPile::cardRemoved( card );
+ }
+ virtual void cardAddedToTop(Card *card) {
+ if ( !isDealing() && cardOnBottom() == card )
+ numberOfFreeCells--;
+ PatienceWorkingPile::cardAddedToTop( card );
+ }
+};
+
+
+class FreecellFreecellPile : public CardPile, public CanvasRoundRect
+{
+public:
+ FreecellFreecellPile(int x, int y, QCanvas *canvas)
+ : CardPile(x, y), CanvasRoundRect(x, y, canvas) { }
+ virtual bool isAllowedOnTop(Card *card) {
+ if ( ( cardOnTop() == NULL ) && ( card->getCardPile()->cardInfront(card) == NULL ) )
+ return TRUE;
+ return FALSE;
+ }
+ virtual bool isAllowedToBeMoved(Card *card) {
+ Q_UNUSED(card);
+ return TRUE;
+ }
+ virtual void cardAddedToTop(Card *card) {
+ Q_UNUSED(card);
+ numberOfFreeCells--;
+ }
+ virtual void cardRemoved(Card *card) {
+ Q_UNUSED(card);
+ numberOfFreeCells++;
+ }
+};
+
+
+class FreecellCardGame : public CanvasCardGame
+{
+public:
+ FreecellCardGame(QCanvas *c, bool snap, QWidget *parent = 0);
+ virtual void deal(void);
+ virtual bool haveWeWon() {
+ return ( discardPiles[0]->kingOnTop() &&
+ discardPiles[1]->kingOnTop() &&
+ discardPiles[2]->kingOnTop() &&
+ discardPiles[3]->kingOnTop() );
+ }
+ virtual void mousePress(QPoint p) { Q_UNUSED(p); }
+ virtual void mouseRelease(QPoint p) { Q_UNUSED(p); }
+// virtual void mouseMove(QPoint p);
+ virtual bool mousePressCard(Card *card, QPoint p);
+ virtual void mouseReleaseCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); }
+// virtual void mouseMoveCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); }
+ void readConfig( Config& cfg );
+ void writeConfig( Config& cfg );
+ bool snapOn;
+private:
+ FreecellFreecellPile *freecellPiles[8];
+ FreecellWorkingPile *workingPiles[8];
+ FreecellDiscardPile *discardPiles[4];
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/main.cpp b/noncore/games/solitaire/main.cpp
new file mode 100644
index 0000000..f81aa3c
--- a/dev/null
+++ b/noncore/games/solitaire/main.cpp
@@ -0,0 +1,36 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "canvascardwindow.h"
+
+#include <qpe/qpeapplication.h>
+
+
+int main( int argc, char ** argv )
+{
+ QPEApplication a( argc, argv );
+
+ CanvasCardWindow m;
+ m.setCaption( CanvasCardWindow::tr("Patience") );
+ a.showMainWidget( &m );
+
+ return a.exec();
+}
+
diff --git a/noncore/games/solitaire/patiencecardgame.cpp b/noncore/games/solitaire/patiencecardgame.cpp
new file mode 100644
index 0000000..5a9326a
--- a/dev/null
+++ b/noncore/games/solitaire/patiencecardgame.cpp
@@ -0,0 +1,234 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#include "patiencecardgame.h"
+
+
+int highestZ = 0;
+
+
+PatienceCardGame::PatienceCardGame(QCanvas *c, bool snap, QWidget *parent) : CanvasCardGame(*c, snap, parent)
+{
+ numberOfTimesThroughDeck = 0;
+ highestZ = 0;
+
+ circleCross = new CanvasCircleOrCross( 7, 18, canvas() );
+ rectangle = new CanvasRoundRect( 35, 10, canvas() );
+
+ for (int i = 0; i < 4; i++) {
+ discardPiles[i] = new PatienceDiscardPile( 110 + i * 30, 10, canvas() );
+ addCardPile(discardPiles[i]);
+ }
+ for (int i = 0; i < 7; i++) {
+ workingPiles[i] = new PatienceWorkingPile( 10 + i * 30, 50, canvas() );
+ addCardPile(workingPiles[i]);
+ }
+ faceDownDealingPile = new PatienceFaceDownDeck( 5, 10, canvas() );
+ faceUpDealingPile = new PatienceFaceUpDeck( 35, 10, canvas() );
+}
+
+
+PatienceCardGame::~PatienceCardGame()
+{
+ delete circleCross;
+ delete rectangle;
+ delete faceDownDealingPile;
+ delete faceUpDealingPile;
+}
+
+
+void PatienceCardGame::deal(void)
+{
+ highestZ = 1;
+ int t = 0;
+
+ beginDealing();
+
+ for (int i = 0; i < 7; i++) {
+ cards[t]->setFace(TRUE);
+ for (int k = i; k < 7; k++, t++) {
+ Card *card = cards[t];
+ workingPiles[k]->addCardToTop(card);
+ card->setCardPile( workingPiles[k] );
+ QPoint p = workingPiles[k]->getCardPos( card );
+ card->setPos( p.x(), p.y(), highestZ );
+ card->showCard();
+ highestZ++;
+ }
+ }
+
+ for ( ; t < 52; t++) {
+ Card *card = cards[t];
+ faceDownDealingPile->addCardToTop(card);
+ card->setCardPile( faceDownDealingPile );
+ QPoint p = faceDownDealingPile->getCardPos( card );
+ card->setPos( p.x(), p.y(), highestZ );
+ card->showCard();
+ highestZ++;
+ }
+
+ endDealing();
+}
+
+
+void PatienceCardGame::readConfig( Config& cfg )
+{
+ cfg.setGroup("GameState");
+
+ // Do we have a config file to read in?
+ if ( !cfg.hasKey("numberOfTimesThroughDeck") ) {
+ // if not, create a new game
+ newGame();
+ return;
+ }
+ // We have a config file, lets read it in and use it
+
+ // Create Cards, but don't shuffle or deal them yet
+ createDeck();
+
+ // How many times through the deck have we been
+ numberOfTimesThroughDeck = cfg.readNumEntry("NumberOfTimesThroughDeck");
+
+ // restore state to the circle/cross under the dealing pile
+ if ( canTurnOverDeck() )
+ circleCross->setCircle();
+ else
+ circleCross->setCross();
+
+ // Move the cards to their piles (deal them to their previous places)
+ beginDealing();
+
+ highestZ = 1;
+
+ for (int k = 0; k < 7; k++) {
+ QString pile;
+ pile.sprintf( "WorkingPile%i", k );
+ readPile( cfg, workingPiles[k], pile, highestZ );
+ }
+
+ for (int k = 0; k < 4; k++) {
+ QString pile;
+ pile.sprintf( "DiscardPile%i", k );
+ readPile( cfg, discardPiles[k], pile, highestZ );
+ }
+
+ readPile( cfg, faceDownDealingPile, "FaceDownDealingPile", highestZ );
+ readPile( cfg, faceUpDealingPile, "FaceUpDealingPile", highestZ );
+
+ highestZ++;
+
+ endDealing();
+}
+
+
+void PatienceCardGame::writeConfig( Config& cfg )
+{
+ cfg.setGroup("GameState");
+ cfg.writeEntry("numberOfTimesThroughDeck", numberOfTimesThroughDeck);
+
+ for ( int i = 0; i < 7; i++ ) {
+ QString pile;
+ pile.sprintf( "WorkingPile%i", i );
+ workingPiles[i]->writeConfig( cfg, pile );
+ }
+ for ( int i = 0; i < 4; i++ ) {
+ QString pile;
+ pile.sprintf( "DiscardPile%i", i );
+ discardPiles[i]->writeConfig( cfg, pile );
+ }
+ faceDownDealingPile->writeConfig( cfg, "FaceDownDealingPile" );
+ faceUpDealingPile->writeConfig( cfg, "FaceUpDealingPile" );
+}
+
+
+bool PatienceCardGame::mousePressCard( Card *card, QPoint p )
+{
+ Q_UNUSED(p);
+
+ CanvasCard *item = (CanvasCard *)card;
+ if (item->isFacing() != TRUE) {
+ // From facedown stack
+ if ((item->x() == 5) && ((int)item->y() == 10)) {
+ item->setZ(highestZ);
+ highestZ++;
+
+ // Added Code
+ faceDownDealingPile->removeCard(item);
+ faceUpDealingPile->addCardToTop(item);
+ item->setCardPile( faceUpDealingPile );
+
+ item->flipTo( 35, (int)item->y() );
+ }
+ moving = NULL;
+ moved = FALSE;
+
+ // move two other cards if we flip three at a time
+ int flipped = 1;
+ QCanvasItemList l = canvas()->collisions( p );
+ for (QCanvasItemList::Iterator it = l.begin(); (it != l.end()) && (flipped != cardsDrawn()); ++it) {
+ if ( (*it)->rtti() == canvasCardId ) {
+ CanvasCard *item = (CanvasCard *)*it;
+ if (item->animated())
+ continue;
+ item->setZ(highestZ);
+ highestZ++;
+ flipped++;
+
+ // Added Code
+ faceDownDealingPile->removeCard(item);
+ faceUpDealingPile->addCardToTop(item);
+ item->setCardPile( faceUpDealingPile );
+
+ item->flipTo( 35, (int)item->y(), 8 * flipped );
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void PatienceCardGame::mousePress(QPoint p)
+{
+ if ( canTurnOverDeck() &&
+ (p.x() > 5) && (p.x() < 28) &&
+ (p.y() > 10) && (p.y() < 46) ) {
+
+ beginDealing();
+ Card *card = faceUpDealingPile->cardOnTop();
+ while ( card ) {
+ card->setPos( 5, 10, highestZ );
+ card->setFace( FALSE );
+ faceUpDealingPile->removeCard( card );
+ faceDownDealingPile->addCardToTop( card );
+ card->setCardPile( faceDownDealingPile );
+ card = faceUpDealingPile->cardOnTop();
+ highestZ++;
+ }
+ endDealing();
+
+ throughDeck();
+
+ moved = TRUE;
+ }
+}
+
+
diff --git a/noncore/games/solitaire/patiencecardgame.h b/noncore/games/solitaire/patiencecardgame.h
new file mode 100644
index 0000000..c4f6c48
--- a/dev/null
+++ b/noncore/games/solitaire/patiencecardgame.h
@@ -0,0 +1,206 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef PATIENCE_CARD_GAME_H
+#define PATIENCE_CARD_GAME_H
+
+
+#include <qpopupmenu.h>
+#include <qmainwindow.h>
+#include <qintdict.h>
+#include <qcanvas.h>
+// #include "canvascardshapes.h"
+// #include "canvascard.h"
+#include "canvascardgame.h"
+
+
+class PatienceFaceDownDeck : public CardPile, public CanvasRoundRect
+{
+public:
+ PatienceFaceDownDeck(int x, int y, QCanvas *canvas)
+ : CardPile(x, y), CanvasRoundRect(x, y, canvas) { }
+ virtual bool isAllowedOnTop(Card *card) {
+ Q_UNUSED(card);
+ // Need to check it is from the faceUpDealingPile
+ return TRUE;
+ }
+ virtual bool isAllowedToBeMoved(Card *card) {
+ Q_UNUSED(card);
+ //if ( ( !card->isFacing() ) && ( card == cardOnTop() ) )
+ if ( card == cardOnTop() )
+ return TRUE;
+ return FALSE;
+ }
+};
+
+
+class PatienceFaceUpDeck : public CardPile, public CanvasRoundRect
+{
+public:
+ PatienceFaceUpDeck(int x, int y, QCanvas *canvas)
+ : CardPile(x, y), CanvasRoundRect(x, y, canvas) { }
+ virtual bool isAllowedOnTop(Card *card) {
+ Q_UNUSED(card);
+ // Need to check it is from the faceDownDealingPile
+ return TRUE;
+ }
+ virtual bool isAllowedToBeMoved(Card *card) {
+ Q_UNUSED(card);
+ //if ( ( card->isFacing() ) && ( card == cardOnTop() ) )
+ if ( card == cardOnTop() )
+ return TRUE;
+ return FALSE;
+ }
+};
+
+
+class PatienceDiscardPile : public CardPile, public CanvasRoundRect
+{
+public:
+ PatienceDiscardPile(int x, int y, QCanvas *canvas)
+ : CardPile(x, y), CanvasRoundRect(x, y, canvas) { }
+ virtual bool isAllowedOnTop(Card *card) {
+ if ( card->isFacing() && ( card->getCardPile()->cardInfront(card) == NULL ) &&
+ ( ( ( cardOnTop() == NULL ) && ( card->getValue() == ace ) ) ||
+ ( ( cardOnTop() != NULL ) &&
+ ( (int)card->getValue() == (int)cardOnTop()->getValue() + 1 ) &&
+ ( card->getSuit() == cardOnTop()->getSuit() ) ) ) )
+ return TRUE;
+ return FALSE;
+ }
+ virtual bool isAllowedToBeMoved(Card *card) {
+ if ( card->isFacing() && ( card == cardOnTop() ) )
+ return TRUE;
+ return FALSE;
+ }
+};
+
+
+class PatienceWorkingPile : public CardPile, public CanvasRoundRect
+{
+public:
+ PatienceWorkingPile(int x, int y, QCanvas *canvas)
+ : CardPile(x, y), CanvasRoundRect(x, y, canvas), top(x, y) { }
+ virtual bool isAllowedOnTop(Card *card) {
+ if ( card->isFacing() &&
+ ( ( ( cardOnTop() == NULL ) && (card->getValue() == king) ) ||
+ ( ( cardOnTop() != NULL ) &&
+ ( (int)card->getValue() + 1 == (int)cardOnTop()->getValue() ) &&
+ ( card->isRed() != cardOnTop()->isRed() ) ) ) )
+ return TRUE;
+ return FALSE;
+ }
+ virtual bool isAllowedToBeMoved(Card *card) {
+ if ( card->isFacing() )
+ return TRUE;
+ return FALSE;
+ }
+ virtual void cardAddedToTop(Card *card) {
+ Q_UNUSED(card);
+ top = getCardPos(NULL);
+ setNextX( top.x() );
+ setNextY( top.y() );
+ }
+ virtual void cardRemoved(Card *card) {
+ Q_UNUSED(card);
+
+ Card *newTopCard = cardOnTop();
+
+ if ( !newTopCard ) {
+ top = QPoint( pileX, pileY );
+ setNextX( pileX );
+ setNextY( pileY );
+ return;
+ } else {
+ top = getCardPos(NULL);
+ if ( newTopCard->isFacing() == FALSE ) {
+ // correct the position taking in to account the card is not
+ // yet flipped, but will become flipped
+ top = QPoint( top.x() - 1, top.y() - 3 );
+ newTopCard->flipTo( top.x(), top.y() );
+ top = QPoint( top.x(), top.y() + 13 );
+ }
+ setNextX( top.x() );
+ setNextY( top.y() );
+ }
+ }
+ virtual QPoint getCardPos(Card *c) {
+ int x = pileX, y = pileY;
+ Card *card = cardOnBottom();
+ while ((card != c) && (card != NULL)) {
+ if (card->isFacing()) {
+ y += 13;
+ } else {
+ x += 1;
+ y += 3;
+ }
+ card = cardInfront(card);
+ }
+ return QPoint( x, y );
+ }
+ virtual QPoint getHypertheticalNextCardPos(void) {
+ return top;
+ // return QPoint( getNextX(), getNextY() );
+ }
+private:
+ QPoint top;
+
+};
+
+
+class PatienceCardGame : public CanvasCardGame
+{
+public:
+ PatienceCardGame(QCanvas *c, bool snap, QWidget *parent = 0);
+ virtual ~PatienceCardGame();
+ virtual void deal(void);
+ virtual bool haveWeWon() {
+ return ( discardPiles[0]->kingOnTop() &&
+ discardPiles[1]->kingOnTop() &&
+ discardPiles[2]->kingOnTop() &&
+ discardPiles[3]->kingOnTop() );;
+ }
+ virtual void mousePress(QPoint p);
+ virtual void mouseRelease(QPoint p) { Q_UNUSED(p); }
+// virtual void mouseMove(QPoint p);
+ virtual bool mousePressCard(Card *card, QPoint p);
+ virtual void mouseReleaseCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); }
+// virtual void mouseMoveCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); }
+ bool canTurnOverDeck(void) { return (numberOfTimesThroughDeck != 3); }
+ void throughDeck(void) {
+ numberOfTimesThroughDeck++;
+ if (numberOfTimesThroughDeck == 3)
+ circleCross->setCross();
+ }
+ bool snapOn;
+ virtual void writeConfig( Config& cfg );
+ virtual void readConfig( Config& cfg );
+private:
+ CanvasCircleOrCross *circleCross;
+ CanvasRoundRect *rectangle;
+ PatienceWorkingPile *workingPiles[7];
+ PatienceDiscardPile *discardPiles[4];
+ PatienceFaceDownDeck *faceDownDealingPile;
+ PatienceFaceUpDeck *faceUpDealingPile;
+ int numberOfTimesThroughDeck;
+};
+
+
+#endif
+
diff --git a/noncore/games/solitaire/qpe-solitaire.control b/noncore/games/solitaire/qpe-solitaire.control
new file mode 100644
index 0000000..71abb0c
--- a/dev/null
+++ b/noncore/games/solitaire/qpe-solitaire.control
@@ -0,0 +1,9 @@
+Files: bin/patience apps/Games/patience.desktop pics/cards
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: solitaire card games
+ A solitaire game for the Qtopia environment.
diff --git a/noncore/games/solitaire/solitaire.pro b/noncore/games/solitaire/solitaire.pro
new file mode 100755
index 0000000..8617cab
--- a/dev/null
+++ b/noncore/games/solitaire/solitaire.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+
+CONFIG += qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+
+HEADERS = canvascard.h canvasshapes.h cardgame.h cardgamelayout.h cardpile.h card.h carddeck.h canvascardgame.h freecellcardgame.h patiencecardgame.h canvascardwindow.h
+
+SOURCES = canvascard.cpp canvasshapes.cpp cardgame.cpp cardgamelayout.cpp cardpile.cpp card.cpp carddeck.cpp canvascardgame.cpp freecellcardgame.cpp patiencecardgame.cpp canvascardwindow.cpp main.cpp
+
+TARGET = patience
+
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+REQUIRES = patience
+
+TRANSLATIONS = ../i18n/de/patience.ts
diff --git a/noncore/games/tetrix/.cvsignore b/noncore/games/tetrix/.cvsignore
new file mode 100644
index 0000000..edfa921
--- a/dev/null
+++ b/noncore/games/tetrix/.cvsignore
@@ -0,0 +1,3 @@
+moc_*
+*.moc
+Makefile
diff --git a/noncore/games/tetrix/Makefile.in b/noncore/games/tetrix/Makefile.in
new file mode 100644
index 0000000..3a74fdc
--- a/dev/null
+++ b/noncore/games/tetrix/Makefile.in
@@ -0,0 +1,157 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = ../bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = tetrix
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = minefield.h \
+ gtetrix.h \
+ qtetrix.h \
+ qtetrixb.h \
+ tpiece.h
+SOURCES = main.cpp \
+ gtetrix.cpp \
+ qtetrix.cpp \
+ qtetrixb.cpp \
+ tpiece.cpp
+OBJECTS = main.o \
+ gtetrix.o \
+ qtetrix.o \
+ qtetrixb.o \
+ tpiece.o
+INTERFACES =
+UICDECLS =
+UICIMPLS =
+SRCMOC = moc_qtetrix.cpp \
+ moc_qtetrixb.cpp
+OBJMOC = moc_qtetrix.o \
+ moc_qtetrixb.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake tetrix.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+main.o: main.cpp \
+ qtetrix.h \
+ qtetrixb.h \
+ gtetrix.h \
+ tpiece.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+gtetrix.o: gtetrix.cpp \
+ gtetrix.h \
+ tpiece.h
+
+qtetrix.o: qtetrix.cpp \
+ qtetrix.h \
+ qtetrixb.h \
+ gtetrix.h \
+ tpiece.h \
+ $(QPEDIR)/include/qpe/resource.h
+
+qtetrixb.o: qtetrixb.cpp \
+ qtetrixb.h \
+ gtetrix.h \
+ tpiece.h \
+ qtetrix.h
+
+tpiece.o: tpiece.cpp \
+ tpiece.h
+
+moc_qtetrix.o: moc_qtetrix.cpp \
+ qtetrix.h \
+ qtetrixb.h \
+ gtetrix.h \
+ tpiece.h
+
+moc_qtetrixb.o: moc_qtetrixb.cpp \
+ qtetrixb.h \
+ gtetrix.h \
+ tpiece.h
+
+moc_qtetrix.cpp: qtetrix.h
+ $(MOC) qtetrix.h -o moc_qtetrix.cpp
+
+moc_qtetrixb.cpp: qtetrixb.h
+ $(MOC) qtetrixb.h -o moc_qtetrixb.cpp
+
+
diff --git a/noncore/games/tetrix/gtetrix.cpp b/noncore/games/tetrix/gtetrix.cpp
new file mode 100644
index 0000000..d1f38b1
--- a/dev/null
+++ b/noncore/games/tetrix/gtetrix.cpp
@@ -0,0 +1,514 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include "gtetrix.h"
+
+#include <string.h>
+
+GenericTetrix::GenericTetrix(int boardWidth,int boardHeight)
+{
+ int i,j;
+
+ width = boardWidth;
+ height = boardHeight;
+ boardPtr = new int[height*width]; // Note the order, this makes it easier
+ // to remove full lines.
+ for(i = 0 ; i < height ; i++)
+ for(j = 0 ; j < width ; j++)
+ board(j,i) = 0;
+ currentLine = -1; // -1 if no falling piece.
+ currentPos = 0;
+ showNext = 0; // FALSE
+ nLinesRemoved = 0;
+ nPiecesDropped = 0;
+ score = 0;
+ level = 1;
+ gameID = 0;
+ nClearLines = height;
+}
+
+GenericTetrix::~GenericTetrix()
+{
+ delete[] boardPtr;
+}
+
+
+void GenericTetrix::clearBoard(int fillRandomLines)
+{
+ int i,j;
+
+ if (fillRandomLines >= height)
+ fillRandomLines = height - 1;
+
+ erasePiece();
+ for(i = height - nClearLines - 1 ; i >= fillRandomLines ; i--)
+ for(j = 0 ; j < width ; j++)
+ if (board(j,i) != 0) {
+ draw(j,i,0);
+ board(j,i) = 0;
+ }
+ if (fillRandomLines != 0)
+ for (i = 0 ; i < fillRandomLines ; i++) {
+ fillRandom(i);
+ }
+ nClearLines = height - fillRandomLines;
+}
+
+void GenericTetrix::showBoard()
+{
+ int i,j;
+
+ showPiece();
+ for(i = height - nClearLines - 1 ; i >= 0 ; i--)
+ for(j = 0 ; j < width ; j++)
+ if (board(j,i) != 0)
+ draw(j,i,board(j,i));
+}
+
+void GenericTetrix::hideBoard()
+{
+ int i,j;
+
+ erasePiece();
+ for(i = height - nClearLines - 1 ; i >= 0 ; i--)
+ for(j = 0 ; j < width ; j++)
+ if (board(j,i) != 0)
+ draw(j,i,0);
+}
+
+void GenericTetrix::startGame(int gameType,int fillRandomLines)
+{
+ gameID = gameType;
+ clearBoard(fillRandomLines);
+ nLinesRemoved = 0;
+ updateRemoved(nLinesRemoved);
+ nClearLines = height;
+ nPiecesDropped = 0;
+ score = 0;
+ updateScore(score);
+ level = 1;
+ updateLevel(level);
+ newPiece();
+}
+
+void GenericTetrix::revealNextPiece(int revealIt)
+{
+ if (showNext == revealIt)
+ return;
+ showNext = revealIt;
+ if (!showNext)
+ eraseNextPiece();
+ else
+ showNextPiece();
+}
+
+void GenericTetrix::updateBoard(int x1,int y1,int x2, int y2,
+ int dontUpdateBlanks)
+{
+ int i,j;
+ int tmp;
+
+ if (x1 > x2) {
+ tmp = x2;
+ x2 = x1;
+ x1 = tmp;
+ }
+ if (y1 > y2) {
+ tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ }
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 >= width)
+ x2 = width - 1;
+ if (y1 < 0)
+ y1 = 0;
+ if (y2 >= height)
+ y2 = height - 1;
+ for(i = y1 ; i <= y2 ; i++)
+ for(j = x1 ; j <= x2 ; j++)
+ if (!dontUpdateBlanks || board(j,height - i - 1) != 0)
+ draw(j,height - i - 1,board(j,height - i - 1));
+ showPiece(); // Remember to update piece correctly!!!!
+}
+
+
+void GenericTetrix::fillRandom(int line)
+{
+ int i,j;
+ int holes;
+
+ for(i = 0 ; i < width ; i++)
+ board(i,line) = TetrixPiece::randomValue(7);
+ holes = 0;
+ for(i = 0 ; i < width ; i++)
+ if (board(i,line) == 0) // Count holes in the line.
+ holes++;
+ if (holes == 0) // Full line, make a random hole:
+ board(TetrixPiece::randomValue(width),line) = 0;
+ if (holes == width) // Empty line, make a random square:
+ board(TetrixPiece::randomValue(width),line) =
+ TetrixPiece::randomValue(6) + 1;
+ for(j = 0 ; j < width ; j++)
+ draw(j,i,board(j,i));
+}
+
+void GenericTetrix::moveLeft(int steps)
+{
+ while(steps) {
+ if (!canMoveTo(currentPos - 1,currentLine))
+ return;
+ moveTo(currentPos - 1,currentLine);
+ steps--;
+ }
+}
+
+void GenericTetrix::moveRight(int steps)
+{
+ while(steps) {
+ if (!canMoveTo(currentPos + 1,currentLine))
+ return;
+ moveTo(currentPos + 1,currentLine);
+ steps--;
+ }
+}
+
+void GenericTetrix::rotateLeft()
+{
+ TetrixPiece tmp(currentPiece);
+
+ tmp.rotateLeft();
+ if (!canPosition(tmp))
+ return;
+ position(tmp);
+ currentPiece = tmp;
+}
+
+void GenericTetrix::rotateRight()
+{
+ TetrixPiece tmp(currentPiece);
+
+ tmp.rotateRight();
+ if (!canPosition(tmp))
+ return;
+ position(tmp);
+ currentPiece = tmp;
+}
+
+void GenericTetrix::dropDown()
+{
+ if (currentLine == -1)
+ return;
+
+ int dropHeight = 0;
+ int newLine = currentLine;
+ while(newLine) {
+ if (!canMoveTo(currentPos,newLine - 1))
+ break;
+ newLine--;
+ dropHeight++;
+ }
+ if (dropHeight != 0)
+ moveTo(currentPos,newLine);
+ internalPieceDropped(dropHeight);
+}
+
+void GenericTetrix::oneLineDown()
+{
+ if (currentLine == -1)
+ return;
+ if (canMoveTo(currentPos,currentLine - 1)) {
+ moveTo(currentPos,currentLine - 1);
+ } else {
+ internalPieceDropped(0);
+ }
+}
+
+void GenericTetrix::newPiece()
+{
+ currentPiece = nextPiece;
+ if (showNext)
+ eraseNextPiece();
+ nextPiece.setRandomType();
+ if (showNext)
+ showNextPiece();
+ currentLine = height - 1 + currentPiece.getMinY();
+ currentPos = width/2 + 1;
+ if (!canMoveTo(currentPos,currentLine)) {
+ currentLine = -1;
+ gameOver();
+ } else {
+ showPiece();
+ }
+}
+
+void GenericTetrix::removePiece()
+{
+ erasePiece();
+ currentLine = -1;
+}
+
+void GenericTetrix::drawNextSquare(int,int,int)
+{
+
+}
+
+void GenericTetrix::pieceDropped(int)
+{
+ newPiece();
+}
+
+void GenericTetrix::updateRemoved(int)
+{
+}
+
+void GenericTetrix::updateScore(int)
+{
+}
+
+void GenericTetrix::updateLevel(int)
+{
+}
+
+void GenericTetrix::removeFullLines()
+{
+ int i,j,k;
+ int nFullLines;
+
+ for(i = 0 ; i < height - nClearLines ; i++) {
+ for(j = 0 ; j < width ; j++)
+ if (board(j,i) == 0)
+ break;
+ if (j == width) {
+ nFullLines = 1;
+ for(k = i + 1 ; k < height - nClearLines ; k++) {
+ for(j = 0 ; j < width ; j++)
+ if (board(j,k) == 0)
+ break;
+ if (j == width) {
+ nFullLines++;
+ } else {
+ for(j = 0 ; j < width ; j++) {
+ if (board(j,k - nFullLines) != board(j,k)) {
+ board(j,k - nFullLines) = board(j,k);
+ draw( j,k - nFullLines,
+ board(j,k - nFullLines));
+ }
+ }
+ }
+ }
+ nClearLines = nClearLines + nFullLines;
+ nLinesRemoved = nLinesRemoved + nFullLines;
+ updateRemoved(nLinesRemoved);
+ score = score + 10*nFullLines; // updateScore must be
+ // called by caller!
+ for (i = height - nClearLines ;
+ i < height - nClearLines + nFullLines ;
+ i++)
+ for(j = 0 ; j < width ; j++)
+ if (board(j,i) != 0) {
+ draw(j,i,0);
+ board(j,i) = 0;
+ }
+ }
+ }
+}
+
+void GenericTetrix::showPiece()
+{
+ int x,y;
+
+ if (currentLine == -1)
+ return;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ currentPiece.getCoord(i,x,y);
+ draw(currentPos + x,currentLine - y,currentPiece.getType());
+ }
+}
+
+void GenericTetrix::erasePiece()
+{
+ int x,y;
+
+ if (currentLine == -1)
+ return;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ currentPiece.getCoord(i,x,y);
+ draw(currentPos + x,currentLine - y,0);
+ }
+}
+
+void GenericTetrix::internalPieceDropped(int dropHeight)
+{
+ gluePiece();
+ nPiecesDropped++;
+ if (nPiecesDropped % 25 == 0) {
+ level++;
+ updateLevel(level);
+ }
+ score = score + 7 + dropHeight;
+ removeFullLines();
+ updateScore(score);
+ pieceDropped(dropHeight);
+}
+
+void GenericTetrix::gluePiece()
+{
+ int x,y;
+ int min;
+
+ if (currentLine == -1)
+ return;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ currentPiece.getCoord(i,x,y);
+ board(currentPos + x,currentLine - y) = currentPiece.getType();
+ }
+ min = currentPiece.getMinY();
+ if (currentLine - min >= height - nClearLines)
+ nClearLines = height - currentLine + min - 1;
+}
+
+void GenericTetrix::showNextPiece(int erase)
+{
+ int x,y;
+ int minX = nextPiece.getMinX();
+ int minY = nextPiece.getMinY();
+ int maxX = nextPiece.getMaxX();
+ int maxY = nextPiece.getMaxY();
+
+ int xOffset = (3 - (maxX - minX))/2;
+ int yOffset = (3 - (maxY - minY))/2;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ nextPiece.getCoord(i,x,y);
+ if (erase)
+ drawNextSquare(x + xOffset - minX,
+ y + yOffset - minY,0);
+ else
+ drawNextSquare(x + xOffset - minX,
+ y + yOffset - minY,nextPiece.getType());
+ }
+}
+
+int GenericTetrix::canPosition(TetrixPiece &piece)
+{
+ if (currentLine == -1)
+ return 0;
+
+ int x,y;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ piece.getCoord(i,x,y);
+ x = currentPos + x;
+ y = currentLine - y; // Board and pieces have inverted y-coord. systems.
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ return 0; // Outside board, cannot put piece here.
+ if (board(x,y) != 0)
+ return 0; // Over a non-zero square, cannot put piece here.
+ }
+ return 1; // Inside board and no non-zero squares underneath.
+
+}
+
+int GenericTetrix::canMoveTo(int xPosition,int line)
+{
+ if (currentLine == -1)
+ return 0;
+
+ int x,y;
+
+ for(int i = 0 ; i < 4 ; i++) {
+ currentPiece.getCoord(i,x,y);
+ x = xPosition + x;
+ y = line - y; // Board and pieces have inverted y-coord. systems.
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ return 0; // Outside board, cannot put piece here.
+ if (board(x,y) != 0)
+ return 0; // Over a non-zero square, cannot put piece here.
+ }
+ return 1; // Inside board and no non-zero squares underneath.
+}
+
+void GenericTetrix::moveTo(int xPosition,int line)
+{
+ if (currentLine == -1)
+ return;
+ optimizedMove(xPosition,line,currentPiece);
+ currentPos = xPosition;
+ currentLine = line;
+}
+
+void GenericTetrix::position(TetrixPiece &piece)
+{
+ if (currentLine == -1)
+ return;
+
+ optimizedMove(currentPos,currentLine,piece);
+}
+
+void GenericTetrix::optimizedMove(int newPos, int newLine,
+ TetrixPiece &newPiece)
+{
+ int updates [8][3];
+ int nUpdates;
+ int value;
+ int x,y;
+ int i,j;
+
+ for(i = 0 ; i < 4 ; i++) { // Put the erasing coords into updates
+ currentPiece.getCoord(i,x,y);
+ updates[i][0] = currentPos + x;
+ updates[i][1] = currentLine - y;
+ updates[i][2] = 0;
+ }
+ nUpdates = 4;
+ for(i = 0 ; i < 4 ; i++) { // Any drawing coord same as an erasing one?
+ newPiece.getCoord(i,x,y);
+ x = newPos + x;
+ y = newLine - y;
+ for (j = 0 ; j < 4 ; j++)
+ if (updates[j][0] == x && updates[j][1] == y) { // Same coord,
+ // don't have to erase
+ if (currentPiece.getType() == newPiece.getType())
+ updates[j][2] = -1; // Correct on screen, no update!
+ else
+ updates[j][2] = newPiece.getType();
+ break;
+ }
+ if (j == 4) { // This coord does not overlap an erasing one
+ updates[nUpdates][0] = x;
+ updates[nUpdates][1] = y;
+ updates[nUpdates][2] = newPiece.getType();
+ nUpdates++;
+ }
+ }
+ for (i = 0 ; i < nUpdates ; i++) { // Do the updating
+ x = updates[i][0];
+ y = updates[i][1];
+ value = updates[i][2];
+ if (value != -1) // Only update if new value != current
+ draw(x,y,value);
+ }
+}
diff --git a/noncore/games/tetrix/gtetrix.h b/noncore/games/tetrix/gtetrix.h
new file mode 100644
index 0000000..520dd89
--- a/dev/null
+++ b/noncore/games/tetrix/gtetrix.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#ifndef GTETRIX_H
+#define GTETRIX_H
+
+#include "tpiece.h"
+
+
+class GenericTetrix
+{
+public:
+ GenericTetrix(int boardWidth = 10,int boardHeight = 22);
+ virtual ~GenericTetrix();
+
+ void clearBoard(int fillRandomLines = 0);
+ void revealNextPiece(int revealIt);
+ void updateBoard(int x1,int y1,int x2,int y2,int dontUpdateBlanks = 0);
+ void updateNext(){if (showNext) showNextPiece();}
+ void hideBoard();
+ void showBoard();
+ void fillRandom(int line);
+
+ void moveLeft(int steps = 1);
+ void moveRight(int steps = 1);
+ void rotateLeft();
+ void rotateRight();
+ void dropDown();
+ void oneLineDown();
+ void newPiece();
+ void removePiece();
+
+ int noOfClearLines() {return nClearLines;}
+ int getLinesRemoved() {return nLinesRemoved;}
+ int getPiecesDropped() {return nPiecesDropped;}
+ int getScore() {return score;}
+ int getLevel() {return level;}
+ int boardHeight() {return height;}
+ int boardWidth() {return width;}
+
+ virtual void drawSquare(int x,int y,int value) = 0;
+ virtual void gameOver() = 0;
+
+ virtual void startGame(int gameType = 0,int fillRandomLines = 0);
+ virtual void drawNextSquare(int x,int y,int value);
+ virtual void pieceDropped(int dropHeight);
+ virtual void updateRemoved(int noOfLines);
+ virtual void updateScore(int newScore);
+ virtual void updateLevel(int newLevel);
+
+private:
+ void draw(int x, int y, int value){drawSquare(x,height - y,value);}
+ void removeFullLines();
+ void removeLine(int line);
+ void showPiece();
+ void erasePiece();
+ void internalPieceDropped(int dropHeight);
+ void gluePiece();
+ void showNextPiece(int erase = 0);
+ void eraseNextPiece(){showNextPiece(1);};
+ int canPosition(TetrixPiece &piece); // Returns a boolean value.
+ int canMoveTo(int xPosition, int line); // Returns a boolean value.
+ void moveTo(int xPosition,int line);
+ void position(TetrixPiece &piece);
+ void optimizedMove(int newPos, int newLine,TetrixPiece &newPiece);
+
+ int &board(int x,int y){return boardPtr[width*y + x];}
+
+ TetrixPiece currentPiece;
+ TetrixPiece nextPiece;
+ int currentLine;
+ int currentPos;
+ int showNext; // Boolean variable.
+ int nLinesRemoved;
+ int nPiecesDropped;
+ int score;
+ int level;
+ int gameID;
+ int nClearLines;
+ int width;
+ int height;
+ int *boardPtr;
+};
+
+
+#endif
diff --git a/noncore/games/tetrix/main.cpp b/noncore/games/tetrix/main.cpp
new file mode 100644
index 0000000..e36d52d
--- a/dev/null
+++ b/noncore/games/tetrix/main.cpp
@@ -0,0 +1,33 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "qtetrix.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char **argv )
+{
+ QPEApplication a(argc,argv);
+
+ QTetrix *tetrix = new QTetrix;
+ a.showMainWidget(tetrix);
+
+ return a.exec();
+}
diff --git a/noncore/games/tetrix/qpe-tetrix.control b/noncore/games/tetrix/qpe-tetrix.control
new file mode 100644
index 0000000..46dfdf5
--- a/dev/null
+++ b/noncore/games/tetrix/qpe-tetrix.control
@@ -0,0 +1,10 @@
+Files: bin/tetrix apps/Games/tetrix.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Arch: iPAQ
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Game: control falling blocks
+ A game for the Qtopia environment.
diff --git a/noncore/games/tetrix/qtetrix.cpp b/noncore/games/tetrix/qtetrix.cpp
new file mode 100644
index 0000000..f649894
--- a/dev/null
+++ b/noncore/games/tetrix/qtetrix.cpp
@@ -0,0 +1,170 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include "qtetrix.h"
+
+#include <qpe/resource.h>
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qdatetime.h>
+#include <qlayout.h>
+
+
+
+void drawTetrixButton( QPainter *p, int x, int y, int w, int h,
+ const QColor *color )
+{
+ QColor fc;
+ if ( color ) {
+ QPointArray a;
+ a.setPoints( 3, x,y+h-1, x,y, x+w-1,y );
+ p->setPen( color->light() );
+ p->drawPolyline( a );
+ a.setPoints( 3, x+1,y+h-1, x+w-1,y+h-1, x+w-1,y+1 );
+ p->setPen( color->dark() );
+ p->drawPolyline( a );
+ x++;
+ y++;
+ w -= 2;
+ h -= 2;
+ fc = *color;
+ }
+ else
+ fc = p->backgroundColor();
+ p->fillRect( x, y, w, h, fc );
+}
+
+
+ShowNextPiece::ShowNextPiece( QWidget *parent, const char *name )
+ : QFrame( parent, name )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ xOffset = -1; // -1 until first resizeEvent.
+}
+
+void ShowNextPiece::resizeEvent( QResizeEvent *e )
+{
+ QSize sz = e->size();
+ blockWidth = (sz.width() - 3)/5;
+ blockHeight = (sz.height() - 3)/6;
+ xOffset = (sz.width() - 3)/5;
+ yOffset = (sz.height() - 3)/6;
+}
+
+
+void ShowNextPiece::paintEvent( QPaintEvent * )
+{
+ QPainter p( this );
+ drawFrame( &p );
+ p.end(); // explicit end() so any slots can paint too
+ emit update();
+}
+
+
+void ShowNextPiece::drawNextSquare(int x, int y,QColor *color)
+{
+ if (xOffset == -1) // Before first resizeEvent?
+ return;
+
+ QPainter paint;
+ paint.begin(this);
+ drawTetrixButton( &paint, xOffset+x*blockWidth, yOffset+y*blockHeight,
+ blockWidth, blockHeight, color );
+ paint.end();
+}
+
+
+QTetrix::QTetrix( QWidget *parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f )
+{
+ setIcon( Resource::loadPixmap( "tetrix_icon" ) );
+ setCaption( tr("Tetrix" ) );
+
+ QTime t = QTime::currentTime();
+ TetrixPiece::setRandomSeed( (((double)t.hour())+t.minute()+t.second())/
+ (24+60+60) );
+
+ QWidget *gameArea = new QWidget( this );
+ setCentralWidget( gameArea );
+
+ QGridLayout *gl = new QGridLayout( gameArea, 5, 3, 8 );
+
+ QLabel *l;
+ l = new QLabel( tr("Next"), gameArea );
+ gl->addWidget( l, 0, 0 );
+ showNext = new ShowNextPiece(gameArea);
+ showNext->setBackgroundColor(QColor(0,0,0));
+ gl->addWidget( showNext, 0, 1 );
+
+ l = new QLabel( tr("Score"), gameArea );
+ gl->addWidget( l, 1, 0 );
+ showScore = new QLabel(gameArea);
+ gl->addWidget( showScore, 1, 1 );
+ l = new QLabel( tr("Level"), gameArea );
+ gl->addWidget( l, 2, 0 );
+ showLevel = new QLabel(gameArea);
+ gl->addWidget( showLevel, 2, 1 );
+ l = new QLabel( tr("Removed"), gameArea );
+ gl->addWidget( l, 3, 0 );
+ showLines = new QLabel(gameArea);
+ gl->addWidget( showLines, 3, 1 );
+
+ board = new QTetrixBoard(gameArea);
+ board->setBackgroundColor(QColor(0,0,0));
+ board->setFixedWidth( 124 );
+ gl->addMultiCellWidget( board, 0, 4, 2, 2 );
+ gl->addColSpacing( 2, 100 );
+ gl->addColSpacing( 1, 35 );
+ gl->addRowSpacing( 0, 35 );
+
+ QPushButton *pb = new QPushButton( tr("Start"), gameArea );
+ pb->setFocusPolicy( NoFocus );
+ connect( pb, SIGNAL( clicked() ), board, SLOT( start() ) );
+ gl->addMultiCellWidget( pb, 4, 4, 0, 1 );
+
+ connect( board, SIGNAL(gameOverSignal()), SLOT(gameOver()) );
+ connect( board, SIGNAL(drawNextSquareSignal(int,int,QColor*)), showNext,
+ SLOT(drawNextSquare(int,int,QColor*)) );
+ connect( showNext, SIGNAL(update()), board, SLOT(updateNext()) );
+ connect( board, SIGNAL(updateScoreSignal(int)), showScore,
+ SLOT(setNum(int)) );
+ connect( board, SIGNAL(updateLevelSignal(int)), showLevel,
+ SLOT(setNum(int)));
+ connect( board, SIGNAL(updateRemovedSignal(int)), showLines,
+ SLOT(setNum(int)));
+
+ showScore->setNum( 0 );
+ showLevel->setNum( 0 );
+ showLines->setNum( 0 );
+ board->revealNextPiece(TRUE);
+ board->setFocusPolicy( StrongFocus );
+}
+
+void QTetrix::gameOver()
+{
+}
+
+
+void QTetrix::quit()
+{
+ close();
+}
diff --git a/noncore/games/tetrix/qtetrix.h b/noncore/games/tetrix/qtetrix.h
new file mode 100644
index 0000000..b6e058a
--- a/dev/null
+++ b/noncore/games/tetrix/qtetrix.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#ifndef QTETRIX_H
+#define QTETRIX_H
+
+#include "qtetrixb.h"
+#include <qframe.h>
+#include <qlcdnumber.h>
+#include <qpushbutton.h>
+#include <qpainter.h>
+#include <qmainwindow.h>
+
+class QLabel;
+
+class ShowNextPiece : public QFrame
+{
+ Q_OBJECT
+ friend class QTetrix;
+public:
+ ShowNextPiece( QWidget *parent=0, const char *name=0 );
+public slots:
+ void drawNextSquare( int x, int y,QColor *color );
+signals:
+ void update();
+private:
+ void paintEvent( QPaintEvent * );
+ void resizeEvent( QResizeEvent * );
+
+ int blockWidth,blockHeight;
+ int xOffset,yOffset;
+};
+
+
+class QTetrix : public QMainWindow
+{
+ Q_OBJECT
+public:
+ QTetrix( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ void startGame() { board->startGame(); }
+
+public slots:
+ void gameOver();
+ void quit();
+private:
+ void keyPressEvent( QKeyEvent *e ) { board->keyPressEvent(e); }
+
+ QTetrixBoard *board;
+ ShowNextPiece *showNext;
+ QLabel *showScore;
+ QLabel *showLevel;
+ QLabel *showLines;
+};
+
+
+void drawTetrixButton( QPainter *, int x, int y, int w, int h,
+ const QColor *color );
+
+
+#endif
diff --git a/noncore/games/tetrix/qtetrixb.cpp b/noncore/games/tetrix/qtetrixb.cpp
new file mode 100644
index 0000000..521f171
--- a/dev/null
+++ b/noncore/games/tetrix/qtetrixb.cpp
@@ -0,0 +1,251 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include "qtetrixb.h"
+#include "qtetrix.h"
+#include <qtimer.h>
+#include <qkeycode.h>
+#include <qpainter.h>
+
+const int waitAfterLineTime = 500;
+
+QTetrixBoard::QTetrixBoard( QWidget *p, const char *name )
+ : QFrame( p, name )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ paint = 0;
+ timer = new QTimer(this);
+ connect( timer, SIGNAL(timeout()), SLOT(timeout()) );
+
+ colors[0].setRgb(200,100,100);
+ colors[1].setRgb(100,200,100);
+ colors[2].setRgb(100,100,200);
+ colors[3].setRgb(200,200,100);
+ colors[4].setRgb(200,100,200);
+ colors[5].setRgb(100,200,200);
+ colors[6].setRgb(218,170, 0);
+
+ xOffset = -1; // -1 until a resizeEvent is received.
+ blockWidth = 20;
+ yOffset = 30;
+ blockHeight = 20;
+ noGame = TRUE;
+ isPaused = FALSE;
+ waitingAfterLine = FALSE;
+ updateTimeoutTime(); // Sets timeoutTime
+}
+
+void QTetrixBoard::startGame(int gameType,int fillRandomLines)
+{
+ if ( isPaused )
+ return; // ignore if game is paused
+ noGame = FALSE;
+ GenericTetrix::startGame( gameType, fillRandomLines );
+ // Note that the timer is started by updateLevel!
+}
+
+
+void QTetrixBoard::pause()
+{
+ if ( noGame ) // game not active
+ return;
+ isPaused = !isPaused;
+ if ( isPaused ) {
+ timer->stop();
+ hideBoard();
+ }
+ else
+ timer->start(timeoutTime);
+ update();
+}
+
+
+void QTetrixBoard::drawSquare(int x,int y,int value)
+{
+ if (xOffset == -1) // Before first resizeEvent?
+ return;
+
+ const int X = xOffset + x*blockWidth;
+ const int Y = yOffset + (y - 1)*blockHeight;
+
+ bool localPainter = paint == 0;
+ QPainter *p;
+ if ( localPainter )
+ p = new QPainter( this );
+ else
+ p = paint;
+ drawTetrixButton( p, X, Y, blockWidth, blockHeight,
+ value == 0 ? 0 : &colors[value-1] );
+ /*
+ if ( value != 0 ) {
+ QColor tc, bc;
+ tc = colors[value-1].light();
+ bc = colors[value-1].dark();
+ p->drawShadePanel( X, Y, blockWidth, blockHeight,
+ tc, bc, 1, colors[value-1], TRUE );
+ }
+ else
+ p->fillRect( X, Y, blockWidth, blockHeight, backgroundColor() );
+ */
+ if ( localPainter )
+ delete p;
+}
+
+void QTetrixBoard::drawNextSquare( int x, int y, int value )
+{
+ if ( value == 0 )
+ emit drawNextSquareSignal (x, y, 0 );
+ else
+ emit drawNextSquareSignal( x, y, &colors[value-1] );
+}
+
+void QTetrixBoard::updateRemoved( int noOfLines )
+{
+ if ( noOfLines > 0 ) {
+ timer->stop();
+ timer->start( waitAfterLineTime );
+ waitingAfterLine = TRUE;
+ }
+ emit updateRemovedSignal( noOfLines );
+}
+
+void QTetrixBoard::updateScore( int newScore )
+{
+ emit updateScoreSignal( newScore );
+}
+
+void QTetrixBoard::updateLevel( int newLevel )
+{
+ timer->stop();
+ updateTimeoutTime();
+ timer->start( timeoutTime );
+ emit updateLevelSignal( newLevel );
+}
+
+void QTetrixBoard::pieceDropped(int)
+{
+ if ( waitingAfterLine ) // give player a break if a line has been removed
+ return;
+ newPiece();
+}
+
+void QTetrixBoard::gameOver()
+{
+ timer->stop();
+ noGame = TRUE;
+ emit gameOverSignal();
+}
+
+void QTetrixBoard::timeout()
+{
+ if ( waitingAfterLine ) {
+ timer->stop();
+ waitingAfterLine = FALSE;
+ newPiece();
+ timer->start( timeoutTime );
+ } else {
+ oneLineDown();
+ }
+}
+
+void QTetrixBoard::drawContents( QPainter *p )
+{
+ const char *text = "Press \"Pause\"";
+ QRect r = contentsRect();
+ paint = p; // set widget painter
+ if ( isPaused ) {
+ p->drawText( r, AlignCenter | AlignVCenter, text );
+ return;
+ }
+ int x1,y1,x2,y2;
+ x1 = (r.left() - xOffset) / blockWidth;
+ if (x1 < 0)
+ x1 = 0;
+ if (x1 >= boardWidth())
+ x1 = boardWidth() - 1;
+
+ x2 = (r.right() - xOffset) / blockWidth;
+ if (x2 < 0)
+ x2 = 0;
+ if (x2 >= boardWidth())
+ x2 = boardWidth() - 1;
+
+ y1 = (r.top() - yOffset) / blockHeight;
+ if (y1 < 0)
+ y1 = 0;
+ if (y1 >= boardHeight())
+ y1 = boardHeight() - 1;
+
+ y2 = (r.bottom() - yOffset) / blockHeight;
+ if (y2 < 0)
+ y2 = 0;
+ if (y2 >= boardHeight())
+ y2 = boardHeight() - 1;
+
+ updateBoard( x1, y1, x2, y2, TRUE );
+ paint = 0; // reset widget painter
+ return;
+}
+
+void QTetrixBoard::resizeEvent(QResizeEvent *e)
+{
+ QSize sz = e->size();
+ blockWidth = (sz.width() - 2)/10;
+ blockHeight = (sz.height() - 2)/22;
+ xOffset = 1;
+ //yOffset = 1;
+ yOffset = (sz.height() - 2) - (blockHeight *22);
+}
+
+void QTetrixBoard::keyPressEvent( QKeyEvent *e )
+{
+ if ( noGame || isPaused || waitingAfterLine )
+ return;
+ switch( e->key() ) {
+ case Key_Left :
+ moveLeft();
+ break;
+ case Key_Right :
+ moveRight();
+ break;
+ case Key_Down :
+// rotateRight();
+ dropDown();
+ break;
+ case Key_Up :
+ rotateLeft();
+ break;
+ case Key_Space :
+ dropDown();
+ break;
+ case Key_D :
+ oneLineDown();
+ break;
+ default:
+ return;
+ }
+ e->accept();
+}
+
+void QTetrixBoard::updateTimeoutTime()
+{
+ timeoutTime = 1000/(1 + getLevel());
+}
diff --git a/noncore/games/tetrix/qtetrixb.h b/noncore/games/tetrix/qtetrixb.h
new file mode 100644
index 0000000..4134a84
--- a/dev/null
+++ b/noncore/games/tetrix/qtetrixb.h
@@ -0,0 +1,80 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#ifndef QTETRIXB_H
+#define QTETRIXB_H
+
+#include "gtetrix.h"
+#include <qframe.h>
+
+class QTimer;
+
+class QTetrixBoard : public QFrame, public GenericTetrix
+{
+ Q_OBJECT
+public:
+ QTetrixBoard( QWidget *parent=0, const char *name=0 );
+
+ void gameOver();
+ void startGame(int gameType = 0,int fillRandomLines = 0);
+
+public slots:
+ void timeout();
+ void updateNext() { GenericTetrix::updateNext(); }
+ void key(QKeyEvent *e) { keyPressEvent(e); }
+ void start() { startGame(); }
+ void pause();
+
+signals:
+ void gameOverSignal();
+ void drawNextSquareSignal(int x,int y,QColor *color1);
+ void updateRemovedSignal(int noOfLines);
+ void updateScoreSignal(int score);
+ void updateLevelSignal(int level);
+
+public: // until we have keyboard focus, should be protected
+ void keyPressEvent( QKeyEvent * );
+
+private:
+ void drawContents( QPainter * );
+ void resizeEvent( QResizeEvent * );
+ void drawSquare(int x,int y,int value);
+ void drawNextSquare(int x,int y,int value);
+ void updateRemoved(int noOfLines);
+ void updateScore(int newScore);
+ void updateLevel(int newLlevel);
+ void pieceDropped(int dropHeight);
+ void updateTimeoutTime();
+
+ QTimer *timer;
+
+ int xOffset,yOffset;
+ int blockWidth,blockHeight;
+ int timeoutTime;
+ bool noGame;
+ bool isPaused;
+ bool waitingAfterLine;
+
+ QColor colors[7];
+ QPainter *paint;
+};
+
+#endif
diff --git a/noncore/games/tetrix/tetrix.pro b/noncore/games/tetrix/tetrix.pro
new file mode 100644
index 0000000..1160585
--- a/dev/null
+++ b/noncore/games/tetrix/tetrix.pro
@@ -0,0 +1,17 @@
+TEMPLATE = app
+CONFIG = qt warn_on release
+DESTDIR = ../bin
+HEADERS = minefield.h \
+ gtetrix.h \
+ qtetrix.h \
+ qtetrixb.h \
+ tpiece.h
+SOURCES = main.cpp \
+ gtetrix.cpp \
+ qtetrix.cpp \
+ qtetrixb.cpp \
+ tpiece.cpp
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+INTERFACES =
diff --git a/noncore/games/tetrix/tpiece.cpp b/noncore/games/tetrix/tpiece.cpp
new file mode 100644
index 0000000..fe8b766
--- a/dev/null
+++ b/noncore/games/tetrix/tpiece.cpp
@@ -0,0 +1,201 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include "tpiece.h"
+#include "qstring.h"
+#include <stdlib.h>
+#include <time.h>
+
+void TetrixPiece::rotateLeft()
+{
+ if ( pieceType == 5 ) // don't rotate square piece type
+ return;
+ int tmp;
+ for (int i = 0 ; i < 4 ; i++) {
+ tmp = getXCoord(i);
+ setXCoord(i,getYCoord(i));
+ setYCoord(i,-tmp);
+ }
+}
+
+void TetrixPiece::rotateRight()
+{
+ if ( pieceType == 5 ) // don't rotate square piece type
+ return;
+ int tmp;
+ for (int i = 0 ; i < 4 ; i++) {
+ tmp = getXCoord(i);
+ setXCoord(i,-getYCoord(i));
+ setYCoord(i,tmp);
+ }
+}
+
+int TetrixPiece::getMinX()
+{
+ int tmp = coordinates[0][0];
+ for(int i = 1 ; i < 4 ; i++)
+ if (tmp > coordinates[i][0])
+ tmp = coordinates[i][0];
+ return tmp;
+}
+
+int TetrixPiece::getMaxX()
+{
+ int tmp = coordinates[0][0];
+ for(int i = 1 ; i < 4 ; i++)
+ if (tmp < coordinates[i][0])
+ tmp = coordinates[i][0];
+ return tmp;
+
+}
+
+int TetrixPiece::getMinY()
+{
+ int tmp = coordinates[0][1];
+ for(int i = 1 ; i < 4 ; i++)
+ if (tmp > coordinates[i][1])
+ tmp = coordinates[i][1];
+ return tmp;
+}
+
+int TetrixPiece::getMaxY()
+{
+ int tmp = coordinates[0][1];
+ for(int i = 1 ; i < 4 ; i++)
+ if (tmp < coordinates[i][1])
+ tmp = coordinates[i][1];
+ return tmp;
+}
+
+void TetrixPiece::initialize(int type)
+{
+ static int pieceTypes[7][4][2] = {{{ 0,-1},
+ { 0, 0},
+ {-1, 0},
+ {-1, 1}},
+
+ {{ 0,-1},
+ { 0, 0},
+ { 1, 0},
+ { 1, 1}},
+
+ {{ 0,-1},
+ { 0, 0},
+ { 0, 1},
+ { 0, 2}},
+
+ {{-1, 0},
+ { 0, 0},
+ { 1, 0},
+ { 0, 1}},
+
+ {{ 0, 0},
+ { 1, 0},
+ { 0, 1},
+ { 1, 1}},
+
+ {{-1,-1},
+ { 0,-1},
+ { 0, 0},
+ { 0, 1}},
+
+ {{ 1,-1},
+ { 0,-1},
+ { 0, 0},
+ { 0, 1}}};
+ if (type < 1 || type > 7)
+ type = 1;
+ pieceType = type;
+ for(int i = 0 ; i < 4 ; i++) {
+ coordinates[i][0] = pieceTypes[type - 1][i][0];
+ coordinates[i][1] = pieceTypes[type - 1][i][1];
+ }
+}
+
+
+/*
+ * Sigh, oh beautiful nostalgia! This random algorithm has
+ * been taken from the book "Adventures with your pocket calculator"
+ * and I used it in my first implemented and machine-
+ * run program of any size to speak of. Imagine how hungry I
+ * was after having programmed BASIC on paper for
+ * half a year?!!?!?!?!?!? The first program I typed in was a
+ * slot machine game and was made in BASIC on a SHARP
+ * PC-1211 with 1,47 KB RAM (one point four seven kilobytes) and
+ * a one-line LCD-display (I think it had 32 characters) in the
+ * year of our lord 1981. The man I had bought the machine from worked
+ * as a COBOL programmer and was amazed and impressed
+ * when I demonstrated the program 2 days after I had
+ * bought the machine, quote: "Gees, I have been looking so long
+ * for a "random" command in that BASIC, what is it called?"
+ * Oh, how I still get a thrill out of the thought of the
+ * explanation I then gave him...
+ */
+
+/*
+ * Sukk, aa vakre nostalgi! Denne random algoritmen er
+ * tatt fra boka "Adventures with your pocket calculator"
+ * og den brukte jeg i mitt foerste implementerte og maskin-
+ * kjoerte program av nevneverdig stoerrelse. Tror du jeg var
+ * noe sulten etter aa ha programmert BASIC paa papir i et
+ * halvt aar?!!?!?!?!?!? Programmet jeg tasta inn foerst var et
+ * "enarmet banditt" spill og ble laget i BASIC paa en SHARP
+ * PC-1211 med 1,47 KB RAM (en komma foertisju kilobyte) og
+ * et en-linjers LCD-display (tror det hadde 32 karakterer) i det
+ * herrens aar 1981. Mannen jeg kjoepte maskinen av jobbet til
+ * daglig med COBOL programmering og var forbloeffet og imponert
+ * da jeg demonstrerte programmet 2 dager etter at jeg hadde
+ * kjoept maskinen, sitat: "Joess, jeg som har leita saa lenge
+ * etter en random kommando i den BASICen, hva var det den
+ * het?" Aa, jeg frydes ennaa ved tanken paa forklaringen jeg
+ * deretter ga ham...
+ */
+
+double TetrixPiece::randomSeed = 0.33333;
+
+void TetrixPiece::setRandomSeed(double seed)
+{
+#ifdef __MIPSEL__
+ srand( clock() );
+#else
+ QCString buffer;
+ if (seed < 0)
+ seed = - seed;
+ if (seed >= 1)
+ seed = seed - (double) ((int) seed);
+ buffer.sprintf("%1.5f",(float) seed);
+ for (int i = 0 ; i < 5 ; i++)
+ if ((buffer[i + 2] - '0') % 2 == 0)
+ buffer[i + 2]++;
+ randomSeed = atof(buffer);
+#endif
+}
+
+int TetrixPiece::randomValue(int maxPlusOne)
+{
+#ifdef __MIPSEL__
+ return rand() % maxPlusOne;
+#else
+ randomSeed = randomSeed*147;
+ randomSeed = randomSeed - (double) ((int) randomSeed);
+ return (int) (randomSeed*maxPlusOne);
+#endif
+}
diff --git a/noncore/games/tetrix/tpiece.h b/noncore/games/tetrix/tpiece.h
new file mode 100644
index 0000000..9c1c629
--- a/dev/null
+++ b/noncore/games/tetrix/tpiece.h
@@ -0,0 +1,62 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#ifndef TPIECE_H
+#define TPIECE_H
+
+class TetrixPiece
+{
+public:
+ TetrixPiece() {setRandomType();}
+ TetrixPiece(int type) {initialize(type % 7 + 1);}
+
+ void setRandomType() {initialize(randomValue(7) + 1);}
+
+ void rotateLeft();
+ void rotateRight();
+
+ int getType() {return pieceType;}
+ int getXCoord(int index) {return coordinates[index][0];}
+ int getYCoord(int index) {return coordinates[index][1];}
+ void getCoord(int index,int &x,int&y){x = coordinates[index][0];
+ y = coordinates[index][1];}
+ int getMinX();
+ int getMaxX();
+ int getMinY();
+ int getMaxY();
+
+ static void setRandomSeed(double seed);
+ static int randomValue(int maxPlusOne);
+
+private:
+ void setXCoord(int index,int value) {coordinates[index][0] = value;}
+ void setYCoord(int index,int value) {coordinates[index][1] = value;}
+ void setCoords(int index,int x,int y){coordinates[index][0] = x;
+ coordinates[index][1] = y;}
+ void initialize(int type);
+
+ int pieceType;
+ int coordinates[4][2];
+
+ static double randomSeed;
+};
+
+#endif
diff --git a/noncore/games/wordgame/.cvsignore b/noncore/games/wordgame/.cvsignore
new file mode 100644
index 0000000..d498858
--- a/dev/null
+++ b/noncore/games/wordgame/.cvsignore
@@ -0,0 +1,6 @@
+moc_*
+Makefile
+newgamebase.h
+rulesbase.h
+newgamebase.cpp
+rulesbase.cpp
diff --git a/noncore/games/wordgame/Makefile.in b/noncore/games/wordgame/Makefile.in
new file mode 100644
index 0000000..5627414
--- a/dev/null
+++ b/noncore/games/wordgame/Makefile.in
@@ -0,0 +1,168 @@
+#############################################################################
+
+####### Compiler, tools and options
+
+CXX = $(SYSCONF_CXX) $(QT_CXX_MT)
+CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS)
+CC = $(SYSCONF_CC) $(QT_C_MT)
+CFLAGS = $(SYSCONF_CFLAGS)
+INCPATH = -I$(QPEDIR)/include
+LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT)
+LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP)
+MOC = $(SYSCONF_MOC)
+UIC = $(SYSCONF_UIC)
+
+####### Target
+
+DESTDIR = $(QPEDIR)/bin/
+VER_MAJ = 1
+VER_MIN = 0
+VER_PATCH = 0
+TARGET = wordgame
+TARGET1 = lib$(TARGET).so.$(VER_MAJ)
+
+####### Files
+
+HEADERS = wordgame.h
+SOURCES = main.cpp \
+ wordgame.cpp
+OBJECTS = main.o \
+ wordgame.o \
+ newgamebase.o \
+ rulesbase.o
+INTERFACES = newgamebase.ui \
+ rulesbase.ui
+UICDECLS = newgamebase.h \
+ rulesbase.h
+UICIMPLS = newgamebase.cpp \
+ rulesbase.cpp
+SRCMOC = moc_wordgame.cpp \
+ moc_newgamebase.cpp \
+ moc_rulesbase.cpp
+OBJMOC = moc_wordgame.o \
+ moc_newgamebase.o \
+ moc_rulesbase.o
+
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+
+all: $(DESTDIR)$(TARGET)
+
+$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
+ $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake wordgame.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
+ -rm -f *~ core
+ -rm -f allmoc.cpp
+
+####### Extension Modules
+
+listpromodules:
+ @echo
+
+listallmodules:
+ @echo
+
+listaddonpromodules:
+ @echo
+
+listaddonentmodules:
+ @echo
+
+
+REQUIRES=
+
+####### Sub-libraries
+
+
+###### Combined headers
+
+
+
+####### Compile
+
+main.o: main.cpp \
+ wordgame.h \
+ newgamebase.h \
+ rulesbase.h \
+ $(QPEDIR)/include/qpe/qdawg.h \
+ $(QPEDIR)/include/qpe/applnk.h \
+ $(QPEDIR)/include/qpe/qpeapplication.h
+
+wordgame.o: wordgame.cpp \
+ wordgame.h \
+ newgamebase.h \
+ rulesbase.h \
+ $(QPEDIR)/include/qpe/qdawg.h \
+ $(QPEDIR)/include/qpe/applnk.h \
+ $(QPEDIR)/include/qpe/global.h \
+ $(QPEDIR)/include/qpe/filemanager.h \
+ $(QPEDIR)/include/qpe/resource.h \
+ $(QPEDIR)/include/qpe/config.h \
+ $(QPEDIR)/include/qpe/qpetoolbar.h
+
+newgamebase.h: newgamebase.ui
+ $(UIC) newgamebase.ui -o $(INTERFACE_DECL_PATH)/newgamebase.h
+
+newgamebase.cpp: newgamebase.ui
+ $(UIC) newgamebase.ui -i newgamebase.h -o newgamebase.cpp
+
+rulesbase.h: rulesbase.ui
+ $(UIC) rulesbase.ui -o $(INTERFACE_DECL_PATH)/rulesbase.h
+
+rulesbase.cpp: rulesbase.ui
+ $(UIC) rulesbase.ui -i rulesbase.h -o rulesbase.cpp
+
+newgamebase.o: newgamebase.cpp
+
+rulesbase.o: rulesbase.cpp
+
+moc_wordgame.o: moc_wordgame.cpp \
+ wordgame.h \
+ newgamebase.h \
+ rulesbase.h \
+ $(QPEDIR)/include/qpe/qdawg.h \
+ $(QPEDIR)/include/qpe/applnk.h
+
+moc_newgamebase.o: moc_newgamebase.cpp \
+ newgamebase.h
+
+moc_rulesbase.o: moc_rulesbase.cpp \
+ rulesbase.h
+
+moc_wordgame.cpp: wordgame.h
+ $(MOC) wordgame.h -o moc_wordgame.cpp
+
+moc_newgamebase.cpp: newgamebase.h
+ $(MOC) newgamebase.h -o moc_newgamebase.cpp
+
+moc_rulesbase.cpp: rulesbase.h
+ $(MOC) rulesbase.h -o moc_rulesbase.cpp
+
+
diff --git a/noncore/games/wordgame/calcdist b/noncore/games/wordgame/calcdist
new file mode 100755
index 0000000..faf31f1
--- a/dev/null
+++ b/noncore/games/wordgame/calcdist
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+# Usage: cat dictionaries | grep -v '[^a-z]' | calcdist n score
+#
+# Given a lot of words, find an appropriate distribution
+# into n tiles with tile values proportional to the square root
+# of the ratio of score to the tile's frequency.
+
+$n = shift;
+$score = shift;
+
+while (<>) {
+ chomp;
+ for $c ( split "", $_ ) {
+ $freq{$c}++;
+ $t++;
+ }
+}
+
+for $c ( sort { $freq{$a} <=> $freq{$b} } keys %freq ) {
+ #print "$c: $freq{$c}\n";
+ $need = int($freq{$c}*$n/$t+0.5) || 1;
+ $value = int(sqrt($score/($freq{$c}*$n/$t))+0.5) || 1;
+ $t -= $freq{$c};
+ $n -= $need;
+ print "$need $c $value\n";
+}
diff --git a/noncore/games/wordgame/main.cpp b/noncore/games/wordgame/main.cpp
new file mode 100644
index 0000000..cd4600e
--- a/dev/null
+++ b/noncore/games/wordgame/main.cpp
@@ -0,0 +1,34 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "wordgame.h"
+
+#include <qpe/qpeapplication.h>
+
+int main( int argc, char ** argv )
+{
+ QPEApplication a( argc, argv );
+
+ WordGame mw;
+ //QPEApplication::setInputMethodHint( &mw, QPEApplication::AlwaysOff );
+ a.showMainWidget(&mw);
+
+ return a.exec();
+}
diff --git a/noncore/games/wordgame/newgamebase.ui b/noncore/games/wordgame/newgamebase.ui
new file mode 100644
index 0000000..3b6570b
--- a/dev/null
+++ b/noncore/games/wordgame/newgamebase.ui
@@ -0,0 +1,337 @@
+<!DOCTYPE UI><UI>
+<class>NewGameBase</class>
+<widget>
+ <class>QWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Form1</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>290</width>
+ <height>443</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Form1</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>8</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>3</number>
+ </property>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Players</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>7</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>2</number>
+ </property>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player0</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player1</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player2</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player3</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player4</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <item>
+ <property>
+ <name>text</name>
+ <string></string>
+ </property>
+ </item>
+ <item>
+ <property>
+ <name>text</name>
+ <string>AI3: Smart AI player</string>
+ </property>
+ </item>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>player5</cstring>
+ </property>
+ <property stdset="1">
+ <name>editable</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Rules</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>7</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>2</number>
+ </property>
+ <widget>
+ <class>QComboBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>rules</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer1</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>buttonOk</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Start</string>
+ </property>
+ <property stdset="1">
+ <name>autoDefault</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>default</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+</UI>
diff --git a/noncore/games/wordgame/qpe-wordgame.control b/noncore/games/wordgame/qpe-wordgame.control
new file mode 100644
index 0000000..2293f52
--- a/dev/null
+++ b/noncore/games/wordgame/qpe-wordgame.control
@@ -0,0 +1,10 @@
+Files: bin/wordgame apps/Games/wordgame.desktop
+Priority: optional
+Section: qpe/games
+Maintainer: Warwick Allison <warwick@trolltech.com>
+Architecture: arm
+Version: $QPE_VERSION-3
+Depends: qpe-base ($QPE_VERSION)
+Description: Crossword game
+ A crossword game for the Qtopia environment.
+ Play against the computer or human opponents.
diff --git a/noncore/games/wordgame/rulesbase.ui b/noncore/games/wordgame/rulesbase.ui
new file mode 100644
index 0000000..31cc402
--- a/dev/null
+++ b/noncore/games/wordgame/rulesbase.ui
@@ -0,0 +1,274 @@
+<!DOCTYPE UI><UI>
+<class>RulesBase</class>
+<widget>
+ <class>QDialog</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>RulesBase</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>283</width>
+ <height>264</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Game Rules</string>
+ </property>
+ <property stdset="1">
+ <name>sizeGripEnabled</name>
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout3</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QLineEdit</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>gamename</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Board</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>4</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ </sizepolicy>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Size:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QSpinBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>width</cstring>
+ </property>
+ <property stdset="1">
+ <name>maxValue</name>
+ <number>15</number>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>3</number>
+ </property>
+ <property stdset="1">
+ <name>value</name>
+ <number>15</number>
+ </property>
+ </widget>
+ <widget>
+ <class>QSpinBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>height</cstring>
+ </property>
+ <property stdset="1">
+ <name>maxValue</name>
+ <number>15</number>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>3</number>
+ </property>
+ <property stdset="1">
+ <name>value</name>
+ <number>15</number>
+ </property>
+ </widget>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>editboard</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Edit...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QTable</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>tiletable</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout3</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>buttonDelete</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Delete</string>
+ </property>
+ <property stdset="1">
+ <name>autoDefault</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>buttonOk</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;OK</string>
+ </property>
+ <property stdset="1">
+ <name>autoDefault</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>default</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget>
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Cancel</string>
+ </property>
+ <property stdset="1">
+ <name>autoDefault</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>RulesBase</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>RulesBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+</UI>
diff --git a/noncore/games/wordgame/wordgame.cpp b/noncore/games/wordgame/wordgame.cpp
new file mode 100644
index 0000000..ca4352d
--- a/dev/null
+++ b/noncore/games/wordgame/wordgame.cpp
@@ -0,0 +1,1476 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+#include "wordgame.h"
+
+#include <qpe/applnk.h>
+#include <qpe/global.h>
+#include <qpe/filemanager.h>
+#include <qpe/resource.h>
+#include <qpe/config.h>
+
+#include <qapplication.h>
+#include <qmessagebox.h>
+#include <qcombobox.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qiconset.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qpe/qpetoolbar.h>
+#include <qtoolbutton.h>
+#include <qvbox.h>
+#include <qwidgetstack.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+enum RuleEffects {
+ Multiplier=15,
+ MultiplyAll=64,
+ Start=128
+};
+
+static const int rack_tiles=7;
+
+const char* sampleWGR=
+ "wordgame_shapes\n"
+ "15 15\n"
+ "400001040100004\n"
+ "030000000000030\n"
+ "002002000200200\n"
+ "000300020003000\n"
+ "000020000020000\n"
+ "102001000100201\n"
+ "000000202000000\n"
+ "400200050002004\n"
+ "000000202000000\n"
+ "102001000100201\n"
+ "000020000020000\n"
+ "000300020003000\n"
+ "002002000200200\n"
+ "030000000000030\n"
+ "400001040100004\n"
+ "1 2 3 66 67 194 100 0\n"
+ "1 j 8\n"
+ "1 q 7\n"
+ "1 x 6\n"
+ "1 z 6\n"
+ "1 w 4\n"
+ "1 k 4\n"
+ "1 v 3\n"
+ "1 f 3\n"
+ "2 y 3\n"
+ "2 h 2\n"
+ "2 b 2\n"
+ "2 m 2\n"
+ "3 p 2\n"
+ "3 g 2\n"
+ "3 u 2\n"
+ "4 d 2\n"
+ "4 c 2\n"
+ "5 l 1\n"
+ "5 o 1\n"
+ "7 t 1\n"
+ "7 n 1\n"
+ "7 a 1\n"
+ "7 r 1\n"
+ "8 s 1\n"
+ "8 i 1\n"
+ "11 e 1\n"
+ "0\n";
+
+WordGame::WordGame( QWidget* parent, const char* name, WFlags fl ) :
+ QMainWindow(parent, name, fl)
+{
+ setIcon( Resource::loadPixmap( "wordgame" ) );
+ setCaption( tr("Word Game") );
+
+ setToolBarsMovable( FALSE );
+ vbox = new QVBox(this);
+
+ setCentralWidget(vbox);
+ toolbar = new QPEToolBar(this);
+ addToolBar(toolbar, Bottom);
+ reset = new QToolButton(Resource::loadPixmap("back"), tr("Back"), "", this, SLOT(resetTurn()), toolbar);
+ done = new QToolButton(Resource::loadPixmap("done"), tr("Done"), "", this, SLOT(endTurn()), toolbar);
+ scoreinfo = new ScoreInfo(toolbar);
+ scoreinfo->setFont(QFont("Helvetica",10));
+ new QToolButton(Resource::loadPixmap("finish"), tr("Close"), "", this, SLOT(endGame()), toolbar);
+ toolbar->setStretchableWidget(scoreinfo);
+
+ cpu = 0;
+ board = 0;
+ bag = 0;
+ racks = 0;
+
+ aiheart = new QTimer(this);
+ connect(aiheart, SIGNAL(timeout()), this, SLOT(think()));
+
+ readConfig();
+}
+
+WordGame::~WordGame()
+{
+ writeConfig();
+}
+
+void WordGame::writeConfig()
+{
+ Config cfg("WordGame");
+ cfg.setGroup("Game");
+ cfg.writeEntry("NameList",namelist,';');
+ cfg.writeEntry("CurrentPlayer",gameover ? 0 : player+1);
+ if ( !gameover ) {
+ cfg.writeEntry("Rules",rules);
+ bag->writeConfig(cfg);
+ board->writeConfig(cfg);
+ scoreinfo->writeConfig(cfg);
+ }
+ for (int p=0; p<nplayers; p++) {
+ cfg.setGroup("Player"+QString::number(p+1));
+ if ( gameover ) cfg.clearGroup(); else rack(p)->writeConfig(cfg);
+ }
+}
+
+void WordGame::readConfig()
+{
+ Config cfg("WordGame");
+ cfg.setGroup("Game");
+ int currentplayer = cfg.readNumEntry("CurrentPlayer",0);
+ QStringList pnames = cfg.readListEntry("NameList",';');
+ if ( currentplayer ) {
+ gameover = FALSE;
+ rules = cfg.readEntry("Rules");
+ if ( rules.find("x-wordgamerules") >= 0 ) {
+ // rules files moved
+ rules = "Sample.rules";
+ }
+ if ( loadRules(rules) ) {
+ startGame(pnames);
+ bag->readConfig(cfg);
+ board->readConfig(cfg);
+ scoreinfo->readConfig(cfg);
+ for (int p=0; p<nplayers; p++) {
+ cfg.setGroup("Player"+QString::number(p+1));
+ rack(p)->readConfig(cfg);
+ }
+ player=currentplayer-1;
+ readyRack(player);
+ return;
+ }
+ }
+ // fall-back
+ openGameSelector(pnames);
+}
+
+void WordGame::openGameSelector(const QStringList& initnames)
+{
+ toolbar->hide();
+ gameover = FALSE;
+
+ delete board;
+ board = 0;
+ delete racks;
+ racks = 0;
+
+ delete cpu;
+ cpu = 0;
+
+ newgame = new NewGame(vbox);
+
+ //Rules rules(this);
+ //connect(game.editrules, SIGNAL(clicked()), &rules, SLOT(editRules()));
+ //connect(&rules, SIGNAL(rulesChanged()), &game, SLOT(updateRuleSets()));
+ struct passwd* n = getpwuid(getuid());
+ QString playername = n ? n->pw_name : "";
+ if ( playername.isEmpty() ) {
+ playername = "Player";
+ }
+ newgame->player0->changeItem(playername,0);
+ newgame->player1->setCurrentItem(1);
+ newgame->updateRuleSets();
+ newgame->show();
+
+ connect(newgame->buttonOk, SIGNAL(clicked()), this, SLOT(startGame()));
+}
+
+void WordGame::startGame()
+{
+ rules = newgame->ruleslist[newgame->rules->currentItem()];
+ if ( loadRules(rules) ) {
+ QStringList names;
+ names.append(newgame->player0->currentText());
+ names.append(newgame->player1->currentText());
+ names.append(newgame->player2->currentText());
+ names.append(newgame->player3->currentText());
+ names.append(newgame->player4->currentText());
+ names.append(newgame->player5->currentText());
+ delete newgame;
+ startGame(names);
+ } else {
+ // error...
+ delete newgame;
+ close();
+ }
+}
+
+void WordGame::startGame(const QStringList& playerlist)
+{
+ toolbar->show();
+ racks = new QWidgetStack(vbox);
+ namelist.clear();
+ nplayers=0;
+ for (QStringList::ConstIterator it=playerlist.begin(); it!=playerlist.end(); ++it)
+ addPlayer(*it);
+ scoreinfo->init(namelist);
+
+ if ( nplayers ) {
+ player=0;
+ readyRack(player);
+ }
+
+ board->show();
+ racks->show();
+}
+
+bool WordGame::loadRules(const QString &name)
+{
+ QString filename = Global::applicationFileName( "wordgame", name );
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ return FALSE;
+
+ QTextStream ts( &file );
+
+ QString title = name;
+ title.truncate( title.length() - 6 );
+ setCaption( title );
+
+ QString shapepixmap;
+ ts >> shapepixmap;
+ int htiles,vtiles;
+ ts >> htiles >> vtiles;
+
+ if ( htiles < 3 || vtiles < 3 )
+ return FALSE;
+
+ QPixmap bgshapes = Resource::loadPixmap(shapepixmap);
+ QString rule_shapes;
+ for (int i=0; i<vtiles; i++) {
+ QString line;
+ ts >> line;
+ rule_shapes += line;
+ }
+ static int rule_effects[12];
+ int re=0,e;
+ ts >> e;
+ while ( e && re < 10 ) {
+ rule_effects[re] = e;
+ if ( re++ < 10 ) ts >> e;
+ }
+ rule_effects[re++] = 100; // default bonus
+ board = new Board(bgshapes, htiles, vtiles, vbox);
+ board->setRules(rule_shapes, rule_effects);
+ connect(board, SIGNAL(temporaryScore(int)), scoreinfo, SLOT(showTemporaryScore(int)));
+
+ bag = new Bag;
+
+ int count;
+ ts >> count;
+ while ( count ) {
+ QString text;
+ int value;
+ ts >> text >> value;
+ if ( text == "_" )
+ text = "";
+
+ Tile t(text, value);
+ for (int n=count; n--; )
+ bag->add(t);
+
+ ts >> count;
+ }
+
+ return TRUE;
+}
+
+
+NewGame::NewGame(QWidget* parent) :
+ NewGameBase(parent)
+{
+}
+
+void NewGame::updateRuleSets()
+{
+ rules->clear();
+
+ QString rulesDir = Global::applicationFileName( "wordgame", "" );
+ QDir dir( rulesDir, "*.rules" );
+ ruleslist = dir.entryList();
+ if ( ruleslist.isEmpty() ) {
+ // Provide a sample
+ QFile file( rulesDir + "Sample.rules" );
+ if ( file.open( IO_WriteOnly ) ) {
+ file.writeBlock( sampleWGR, strlen(sampleWGR) );
+ file.close();
+ updateRuleSets();
+ }
+ return;
+ }
+ int newest=0;
+ int newest_age=INT_MAX;
+ QDateTime now = QDateTime::currentDateTime();
+ QStringList::Iterator it;
+ for ( it = ruleslist.begin(); it != ruleslist.end(); ++it ) {
+ QFileInfo fi((*it));
+ int age = fi.lastModified().secsTo(now);
+ QString name = *it;
+ name.truncate( name.length()-6 ); // remove extension
+ rules->insertItem( name );
+ if ( age < newest_age ) {
+ newest_age = age;
+ newest = rules->count()-1;
+ }
+ }
+ rules->setCurrentItem(newest);
+}
+
+Rules::Rules(QWidget* parent) :
+ RulesBase(parent,0,TRUE)
+{
+}
+
+void Rules::editRules()
+{
+ if ( exec() ) {
+ // ### create a new set of rules
+ emit rulesChanged();
+ }
+}
+
+void Rules::deleteRuleSet()
+{
+ // ### delete existing rule set
+ emit rulesChanged();
+}
+
+void WordGame::addPlayer(const QString& name)
+{
+ if ( !name.isEmpty() ) {
+ int colon = name.find(':');
+ int cpu = (colon >=0 && name.left(2) == "AI") ? name.mid(2,1).toInt() : 0;
+ addPlayer(name,cpu);
+ }
+}
+
+void WordGame::addPlayer(const QString& name, int cpu)
+{
+ Rack* r = new Rack(rack_tiles,racks);
+ r->setPlayerName(name);
+ r->setComputerization(cpu);
+ racks->addWidget(r, nplayers);
+ refillRack(nplayers);
+ namelist.append(name);
+
+ ++nplayers;
+}
+
+void WordGame::nextPlayer()
+{
+ if ( !refillRack(player) ) {
+ endGame();
+ } else {
+ player = (player+1)%nplayers;
+ scoreinfo->setBoldOne(player);
+ readyRack(player);
+ }
+}
+
+bool WordGame::mayEndGame()
+{
+ int out=-1;
+ int i;
+ for (i=0; i<nplayers; i++)
+ if ( !rack(i)->count() )
+ out = i;
+ if ( out<0 ) {
+ if ( QMessageBox::warning(this,tr("End game"),
+ tr("Do you want to end the game early?"),
+ tr("Yes"), tr("No") )!=0 )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void WordGame::endGame()
+{
+ if ( gameover ) {
+ close();
+ return;
+ }
+
+ if ( !mayEndGame() )
+ return;
+ int out=-1;
+ int totalleft=0;
+ int i;
+ for (i=0; i<nplayers; i++) {
+ Rack* r = rack(i);
+ int c = r->count();
+ if ( c ) {
+ int lose=0;
+ for ( int j=0; j<c; j++ )
+ lose += r->tileRef(j)->value();
+ totalleft += lose;
+ scoreinfo->addScore(i,-lose);
+ } else {
+ out = i;
+ }
+ }
+ int highest=0;
+ int winner=0;
+ for (i=0; i<nplayers; i++) {
+ int s = scoreinfo->playerScore(i);
+ if ( s > highest ) {
+ highest = s;
+ winner = i;
+ }
+ }
+ if ( out >= 0 )
+ scoreinfo->addScore(out,totalleft);
+ scoreinfo->setBoldOne(winner);
+ gameover = TRUE;
+ done->setEnabled(TRUE);
+ reset->setEnabled(FALSE);
+}
+
+void WordGame::endTurn()
+{
+ if ( gameover ) {
+ openGameSelector(namelist);
+ } else {
+ if ( board->checkTurn() ) {
+ if ( board->turnScore() >= 0 ) {
+ scoreinfo->addScore(player,board->turnScore());
+ board->finalizeTurn();
+ } else {
+ QApplication::beep();
+ }
+ nextPlayer();
+ }
+ }
+}
+
+void WordGame::resetTurn()
+{
+ board->resetRack();
+}
+
+void WordGame::passTurn()
+{
+ // ######## trade?
+ nextPlayer();
+}
+
+bool WordGame::refillRack(int i)
+{
+ Rack* r = rack(i);
+ while ( !bag->isEmpty() && !r->isFull() ) {
+ r->addTile(bag->takeRandom());
+ }
+ return r->count() != 0;
+}
+
+void WordGame::readyRack(int i)
+{
+ Rack* r = rack(i);
+ racks->raiseWidget(i);
+ board->setCurrentRack(r);
+
+ done->setEnabled( !r->computerized() );
+ reset->setEnabled( !r->computerized() );
+
+ if ( r->computerized() ) {
+ cpu = new ComputerPlayer(board, r);
+ aiheart->start(0);
+ }
+}
+
+Rack* WordGame::rack(int i) const
+{
+ return (Rack*)racks->widget(i);
+}
+
+void WordGame::think()
+{
+ if ( !cpu->step() ) {
+ delete cpu;
+ cpu = 0;
+ aiheart->stop();
+ if ( board->turnScore() < 0 )
+ passTurn();
+ else
+ endTurn();
+ }
+}
+
+ComputerPlayer::ComputerPlayer(Board* b, Rack* r) :
+ board(b), rack(r), best(new const Tile*[rack_tiles]),
+ best_blankvalues(new Tile[rack_tiles])
+{
+ best_score = -1;
+ across=FALSE;
+ dict=0;
+}
+
+ComputerPlayer::~ComputerPlayer()
+{
+ delete [] best;
+ delete [] best_blankvalues;
+}
+
+bool ComputerPlayer::step()
+{
+ const QDawg::Node* root = dict ? Global::dawg("WordGame").root()
+ : Global::fixedDawg().root();
+ QPoint d = across ? QPoint(1,0) : QPoint(0,1);
+ const Tile* tiles[99]; // ### max board size
+ uchar nletter[4095]; // QDawg only handles 0..4095
+ memset(nletter,0,4096);
+ for (int i=0; i<rack->count(); i++) {
+ const Tile* r = rack->tileRef(i);
+ if ( r->isBlank() )
+ nletter[0]++;
+ else
+ nletter[r->text()[0].unicode()]++;
+ }
+ Tile blankvalues[99]; // ### max blanks
+ findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0);
+ if ( ++current.rx() == board->xTiles() ) {
+ current.rx() = 0;
+ if ( ++current.ry() == board->yTiles() ) {
+ if ( across ) {
+ if ( dict == 1 ) {
+ if ( best_score >= 0 ) {
+ rack->arrangeTiles(best,best_n);
+ rack->setBlanks(best_blankvalues);
+ board->scoreTurn(best_start, best_n, best_dir);
+ board->showTurn();
+ }
+ return FALSE;
+ }
+ dict++;
+ across = FALSE;
+ current = QPoint(0,0);
+ } else {
+ across = TRUE;
+ current = QPoint(0,0);
+ }
+ }
+ }
+ return TRUE;
+}
+
+void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused)
+{
+ if ( !node )
+ return;
+ QChar l = node->letter();
+ const Tile* cur = board->tile(at);
+ if ( cur ) {
+ if ( cur->text()[0] == l ) {
+ bool nextok = board->contains(at+d);
+ if ( node->isWord() && n && (!nextok || !board->tile(at+d)) )
+ noteChoice(tiles,n,d,blankvalues,blused);
+ if ( nextok )
+ findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
+ // #### text()[1]...
+ }
+ } else {
+ if ( nletter[l.unicode()] || nletter[0] ) {
+ int rc = rack->count();
+ ulong msk = 1;
+ for ( int x=0; x<rc; x++ ) {
+ if ( !(used&msk) ) {
+ const Tile* t = rack->tileRef(x);
+ if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s
+ bool nextok = board->contains(at+d);
+ tiles[n++] = t;
+ if ( t->isBlank() )
+ blankvalues[blused++] = Tile(l,0);
+ if ( node->isWord() && (!nextok || !board->tile(at+d)) )
+ noteChoice(tiles,n,d,blankvalues,blused);
+ used |= msk; // mark
+ nletter[t->text()[0].unicode()]--;
+ if ( nextok )
+ findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
+ n--;
+ nletter[t->text()[0].unicode()]++;
+ if ( t->isBlank() ) {
+ // keep looking
+ blused--;
+ used &= ~msk; // unmark
+ } else {
+ break;
+ }
+ }
+ }
+ msk <<= 1;
+ }
+ }
+ // #### text()[1]...
+ }
+ findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused);
+}
+
+void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused)
+{
+ int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0);
+/*
+if (s>0 || current==QPoint(5,1)){
+QString st;
+for ( int i=0; i<n; i++ )
+ st += tiles[i]->text();
+qDebug("%d,%d: %s (%d) for %d",current.x(),current.y(),st.latin1(),n,s);
+}
+*/
+ if ( s > best_score ) {
+ int i;
+ for ( i=0; i<n; i++ )
+ best[i] = tiles[i];
+ for ( i=0; i<blused; i++ )
+ best_blankvalues[i] = blankvalues[i];
+ best_n = n;
+ best_blused = blused;
+ best_score = s;
+ best_dir = d;
+ best_start = current;
+ }
+}
+
+int TileItem::smallWidth()
+{
+ return 16;
+}
+
+int TileItem::smallHeight()
+{
+ return 16;
+}
+
+int TileItem::bigWidth()
+{
+ return 22;
+}
+
+int TileItem::bigHeight()
+{
+ return 22;
+}
+
+void TileItem::setState( State state )
+{
+ hide();
+ s = state;
+ show(); // ### use update() in Qt 3.0
+}
+
+void TileItem::setTile(const Tile& tile)
+{
+ hide();
+ t = tile;
+ show(); // ### use update() in Qt 3.0
+}
+
+void TileItem::setBig(bool b)
+{
+ big = b;
+}
+
+void TileItem::drawShape(QPainter& p)
+{
+ static QFont value_font("heletica",8);
+ static QFont big_font("smoothtimes",17);
+ static QFont small_font("smoothtimes",10);
+
+ QRect area(x(),y(),width(),height());
+ p.setBrush(s == Floating ? yellow/*lightGray*/ : white);
+ p.drawRect(area);
+ if ( big ) {
+ p.setFont(value_font);
+ QString n = QString::number(t.value());
+ int w = p.fontMetrics().width('1');
+ int h = p.fontMetrics().height();
+ w *= n.length();
+ QRect valuearea(x()+width()-w-2,y()+height()-h+1,w,h);
+ p.drawText(valuearea,AlignCenter,n);
+ p.setFont(big_font);
+ area = QRect(x(),y(),width()-2,height()-1);
+ } else {
+ p.setFont(small_font);
+ area = QRect(x(),y()+2,width(),height()-2);
+ }
+ if ( t.value() == 0 )
+ p.setPen(darkGray);
+ p.drawText(area,AlignCenter,t.text().upper());
+}
+
+Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) :
+ QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()),
+ parent)
+{
+ grid = new TileItem*[w*h];
+ memset(grid,0,w*h*sizeof(TileItem*));
+ setFrameStyle(0);
+ setHScrollBarMode(AlwaysOff);
+ setVScrollBarMode(AlwaysOff);
+ current_rack = 0;
+ shown_n = 0;
+}
+
+Board::~Board()
+{
+ delete canvas();
+}
+
+void Board::writeConfig(Config& cfg)
+{
+ QStringList t;
+ int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
+ for (int i=0; i<n; i++)
+ t.append( grid[i] ? grid[i]->tile().key() : QString(".") );
+ cfg.writeEntry("Board",t,';');
+}
+
+void Board::readConfig(Config& cfg)
+{
+ clear();
+ QStringList t = cfg.readListEntry("Board",';');
+ int i=0;
+ int h=canvas()->tilesHorizontally();
+ for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) {
+ if ( *it != "." ) {
+ QPoint p(i%h,i/h);
+ setTile(p,Tile(*it));
+ }
+ i++;
+ }
+ canvas()->update();
+}
+
+void Board::clear()
+{
+ int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
+ for (int i=0; i<n; i++) {
+ delete grid[i];
+ grid[i]=0;
+ }
+}
+
+
+void Board::setCurrentRack(Rack* r)
+{
+ turn_score = -1;
+ current_rack = r;
+}
+
+void Board::resetRack()
+{
+ unshowTurn();
+ canvas()->update();
+}
+
+void Board::contentsMousePressEvent(QMouseEvent* e)
+{
+ dragstart = e->pos();
+}
+
+void Board::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ if ( current_rack && !current_rack->computerized() ) {
+ QPoint d = e->pos() - dragstart;
+ if ( d.x() <= 0 && d.y() <= 0 ) {
+ // None
+ resetRack();
+ } else {
+ int n;
+ QPoint start=boardPos(dragstart);
+ QPoint end=boardPos(e->pos());
+ QPoint diff=end-start;
+ QPoint dir;
+ if ( d.x() > d.y() ) {
+ n = diff.x()+1;
+ dir = QPoint(1,0);
+ } else {
+ n = diff.y()+1;
+ dir = QPoint(0,1);
+ }
+
+ unshowTurn();
+
+ // Subtract existing tiles from n
+ QPoint t = start;
+ for ( int i=n; i--; ) {
+ if ( contains(t) && tile(t) )
+ n--;
+ t += dir;
+ }
+
+ // Move start back to real start
+ while (contains(start-dir) && tile(start-dir))
+ start -= dir;
+
+ scoreTurn(start, n, dir);
+ showTurn();
+ }
+ }
+}
+
+void Board::finalizeTurn()
+{
+ int i=0;
+ QPoint at = shown_at;
+ while ( i<shown_n && contains(at) ) {
+ if ( item(at) && item(at)->state() == TileItem::Floating ) {
+ current_rack->remove(item(at)->tile());
+ setTileState(at,TileItem::Firm);
+ i++;
+ }
+ at += shown_step;
+ }
+ canvas()->update();
+}
+
+void Board::unshowTurn()
+{
+ int i=0;
+ QPoint at = shown_at;
+ while ( i<shown_n && i<current_rack->count() && contains(at) ) {
+ if ( item(at) && item(at)->state() == TileItem::Floating ) {
+ unsetTile(at);
+ i++;
+ }
+ at += shown_step;
+ }
+}
+
+void Board::showTurn()
+{
+ unshowTurn();
+ QPoint at = shown_at;
+ int i=0;
+ while ( i<shown_n && i<current_rack->count() && contains(at) ) {
+ if ( !tile(at) ) {
+ Tile t = current_rack->tile(i);
+ setTile(at,t);
+ setTileState(at,TileItem::Floating);
+ i++;
+ }
+ at += shown_step;
+ }
+ canvas()->update();
+}
+
+int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const
+{
+ int rule = rule_shape[idx(at)]-'0';
+ int effect = rule_effect[rule];
+ int mult = effect&Multiplier;
+ if ( effect & MultiplyAll ) {
+ all_mult *= mult;
+ return base;
+ } else {
+ return base * mult;
+ }
+}
+
+bool Board::isStart(const QPoint& at) const
+{
+ int rule = rule_shape[idx(at)]-'0';
+ int effect = rule_effect[rule];
+ return effect&Start;
+}
+
+bool Board::checkTurn()
+{
+ if ( current_rack->computerized() )
+ return TRUE; // computer doesn't cheat, and has already set blanks.
+
+ QPoint at = shown_at;
+ int n = shown_n;
+ QPoint d = shown_step;
+ const Tile* tiles[99];
+ Tile blankvalues[99];
+ if ( n > current_rack->count() )
+ n = current_rack->count();
+
+ QDialog check(this,0,TRUE);
+ (new QVBoxLayout(&check))->setAutoAdd(TRUE);
+
+ QHBox mw(&check);
+ new QLabel(tr("Blanks: "),&mw);
+
+ int bl=0;
+ QLineEdit* le[99];
+ for (int i=0; i<n; i++) {
+ tiles[i] = current_rack->tileRef(i);
+ if ( tiles[i]->isBlank() ) {
+ QLineEdit *l = new QLineEdit(&mw);
+ le[bl++] = l;
+ l->setMaxLength(1);
+ l->setFixedSize(l->minimumSizeHint());
+ }
+ }
+
+ QHBox btns(&check);
+ connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept()));
+ connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject()));
+
+ if ( bl ) {
+retry:
+ if ( !check.exec() ) {
+ unshowTurn();
+ canvas()->update();
+ return FALSE;
+ }
+
+ for (int b=0; b<bl; b++) {
+ QString v = le[b]->text();
+ blankvalues[b]=Tile(v,0);
+ if ( v.length() != 1 )
+ goto retry;
+ }
+ }
+
+ QStringList words;
+ unshowTurn();
+ turn_score = score(at,tiles,n,blankvalues,d,FALSE,&words);
+ showTurn();
+ QStringList to_add;
+ for (QStringList::Iterator it=words.begin(); it!=words.end(); ++it) {
+ if ( !Global::fixedDawg().contains(*it)
+ && !Global::dawg("WordGame").contains(*it) ) {
+ switch (QMessageBox::warning(this, tr("Unknown word"),
+ tr("<p>The word \"%1\" is not in the dictionary.").arg(*it),
+ tr("Add"), tr("Ignore"), tr("Cancel")))
+ {
+ case 0:
+ // ####### add to wordgame dictionary
+ to_add.append(*it);
+ break;
+ case 1:
+ break;
+ case 2:
+ unshowTurn();
+ canvas()->update();
+ return FALSE;
+ }
+ }
+ }
+ if ( to_add.count() )
+ Global::addWords("WordGame",to_add);
+ return TRUE;
+}
+
+void Board::scoreTurn(const QPoint& at, int n, const QPoint& d)
+{
+ unshowTurn();
+ shown_at = at;
+ shown_n = n;
+ shown_step = d;
+ const Tile* tiles[99];
+ if ( n > current_rack->count() )
+ n = current_rack->count();
+ for (int i=0; i<n; i++)
+ tiles[i] = current_rack->tileRef(i);
+ turn_score = score(at,tiles,n,0,d,FALSE,0);
+ emit temporaryScore(turn_score);
+}
+
+int Board::score(QPoint at, const Tile** tiles, int n, const Tile* blankvalue, const QPoint& d, bool checkdict, QStringList* words) const
+{
+ int total=0;
+ int totalsidetotal=0;
+
+ // words gets filled with words made
+
+ // mainword==0 ->
+ // Checks side words, but not main word
+
+ // -1 means words not in dict, or illegally positioned (eg. not connected)
+
+ // text is assumed to fit on board.
+
+ if ( words ) *words=QStringList();
+
+ QPoint otherd(d.y(), d.x());
+
+ int all_mult = 1;
+ int bl=0;
+
+ bool connected = FALSE;
+
+ QString mainword="";
+
+ if ( contains(at-d) && tile(at-d) ) {
+ return -1; // preceeding tiles
+ }
+
+ const Tile* t;
+ for (int i=0; contains(at) && ((t=tile(at)) || i<n); ) {
+ if ( t ) {
+ if ( checkdict || words ) mainword += t->text();
+ total += t->value();
+ connected = TRUE;
+ } else {
+ QString sideword;
+ QString tt;
+ if ( tiles[i]->isBlank() ) {
+ if ( blankvalue )
+ tt = blankvalue[bl++].text();
+ } else {
+ tt = tiles[i]->text();
+ }
+ sideword=tt;
+ if ( checkdict || words ) mainword += tt;
+ int side_mult = 1;
+ int tilevalue = bonussedValue(at,tiles[i]->value(),side_mult);
+ all_mult *= side_mult;
+ if ( !connected && isStart(at) )
+ connected = TRUE;
+ total += tilevalue;
+ int sidetotal = tilevalue;
+ {
+ QPoint side = at-otherd;
+
+ while ( contains(side) && (t=tile(side)) ) {
+ sidetotal += t->value();
+ sideword.prepend(t->text());
+ side -= otherd;
+ }
+ }
+ {
+ QPoint side = at+otherd;
+ while ( contains(side) && (t=tile(side)) ) {
+ sidetotal += t->value();
+ sideword.append(t->text());
+ side += otherd;
+ }
+ }
+ if ( sideword.length() > 1 ) {
+ if ( words )
+ words->append(sideword);
+ if ( checkdict && !Global::fixedDawg().contains(sideword)
+ && !Global::dawg("WordGame").contains(sideword) )
+ return -1;
+ totalsidetotal += sidetotal * side_mult;
+ connected = TRUE;
+ }
+ i++;
+ }
+ at += d;
+ }
+
+ if ( words )
+ words->append(mainword);
+ if ( checkdict && !Global::fixedDawg().contains(mainword)
+ && !Global::dawg("WordGame").contains(mainword) )
+ return -1;
+
+ if ( n == rack_tiles )
+ totalsidetotal += rack_tiles_bonus;
+
+ return connected ? totalsidetotal + total * all_mult : -1;
+}
+
+QPoint Board::boardPos(const QPoint& p) const
+{
+ return QPoint(p.x()/canvas()->tileWidth(), p.y()/canvas()->tileHeight());
+}
+
+void Board::contentsMouseReleaseEvent(QMouseEvent*)
+{
+ if ( current_rack ) {
+ }
+}
+
+
+void Board::setRules(const QString& shapes, const int* effects)
+{
+ rule_shape=shapes; rule_effect=effects;
+ int i=0;
+ int maxre=0;
+ for (int y=0; y<yTiles(); y++) {
+ for (int x=0; x<xTiles(); x++) {
+ int re = shapes[i++]-'0';
+ if ( re > maxre ) maxre = re;
+ canvas()->setTile(x,y,re);
+ }
+ }
+ rack_tiles_bonus=effects[maxre+1];
+}
+
+void Board::unsetTile(const QPoint& p)
+{
+ delete item(p);
+ grid[idx(p)] = 0;
+}
+
+void Board::setTile(const QPoint& p, const Tile& t)
+{
+ TileItem* it=item(p);
+ if ( !it ) {
+ it = grid[idx(p)] = new TileItem(t,FALSE,canvas());
+ it->move(p.x()*canvas()->tileWidth(), p.y()*canvas()->tileHeight());
+ it->show();
+ } else {
+ it->setTile(t);
+ }
+}
+
+Rack::Rack(int ntiles, QWidget* parent) : QCanvasView(
+ new QCanvas(ntiles*TileItem::bigWidth(),TileItem::bigHeight()),
+ parent),
+ item(ntiles)
+{
+ setLineWidth(1);
+ setFixedHeight(sizeHint().height());
+ n = 0;
+ for (int i=0; i<ntiles; i++)
+ item[i]=0;
+ setHScrollBarMode(AlwaysOff);
+ setVScrollBarMode(AlwaysOff);
+ canvas()->setBackgroundColor(gray);
+ dragging = 0;
+}
+
+Rack::~Rack()
+{
+ clear();
+ delete canvas();
+}
+
+void Rack::clear()
+{
+ for (int i=0; i<n; i++)
+ delete item[i];
+ n=0;
+}
+
+void Rack::writeConfig(Config& cfg)
+{
+ QStringList l;
+ for (int i=0; i<n; i++)
+ l.append(tile(i).key());
+ cfg.writeEntry("Tiles",l,';');
+}
+
+void Rack::readConfig(Config& cfg)
+{
+ clear();
+ int x=0;
+ QStringList l = cfg.readListEntry("Tiles",';');
+ for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) {
+ TileItem *i = new TileItem(Tile(*it),TRUE,canvas());
+ i->move(x++,0);
+ i->show();
+ item[n++] = i;
+ }
+ layoutTiles();
+}
+
+static int cmp_tileitem(const void *a, const void *b)
+{
+ const TileItem* ia = *(TileItem**)a;
+ const TileItem* ib = *(TileItem**)b;
+ return int(ia->x() - ib->x());
+}
+
+void Rack::layoutTiles()
+{
+ int w = TileItem::bigWidth()+2;
+
+ if ( dragging ) dragging->moveBy(dragging_adj,0);
+ qsort(item.data(), n, sizeof(TileItem*), cmp_tileitem);
+ if ( dragging ) dragging->moveBy(-dragging_adj,0);
+
+ for (int i=0; i<n ;i++)
+ if ( item[i] == dragging ) {
+ item[i]->setZ(1);
+ } else {
+ item[i]->move(i*w, 0);
+ item[i]->setZ(0);
+ }
+ canvas()->update();
+}
+
+void Rack::setBlanks(const Tile* bv)
+{
+ for (int j=0; j<n; j++) {
+ Tile tt = item[j]->tile();
+ if ( tt.isBlank() ) {
+ tt.setText(bv->text());
+ item[j]->setTile(tt);
+ bv++;
+ }
+ }
+}
+
+bool Rack::arrangeTiles(const Tile** s, int sn)
+{
+ bool could = TRUE;
+ for (int j=0; j<n; j++) {
+ Tile tt = item[j]->tile();
+ int f=-1;
+ for (int i=0; i<sn && f<0; i++) {
+ if (s[i] && *s[i] == tt ) {
+ s[i]=0;
+ f=i;
+ }
+ }
+ if ( f >= 0 ) {
+ item[j]->move(f-999,0);
+ } else {
+ could = FALSE;
+ }
+ }
+ layoutTiles();
+ return could;
+}
+
+void Rack::addTile(const Tile& t)
+{
+ TileItem *i = new TileItem(t,TRUE,canvas());
+ i->show();
+ item[n++] = i;
+ layoutTiles();
+}
+
+void Rack::remove(Tile t)
+{
+ for (int i=0; i<n ;i++)
+ if ( item[i]->tile() == t ) {
+ remove(i);
+ return;
+ }
+}
+
+void Rack::remove(int i)
+{
+ delete item[i];
+ n--;
+ for (;i<n;i++)
+ item[i]=item[i+1];
+ layoutTiles();
+}
+
+void Rack::resizeEvent(QResizeEvent* e)
+{
+ canvas()->resize(width()-frameWidth()*2,height()-frameWidth()*2);
+ QCanvasView::resizeEvent(e);
+}
+
+void Rack::contentsMousePressEvent(QMouseEvent* e)
+{
+ if ( computerized() )
+ return;
+ QCanvasItemList list = canvas()->collisions(e->pos());
+ if (list.count()) {
+ dragging = list.first();
+ dragstart = e->pos()-QPoint(int(dragging->x()),int(dragging->y()));
+ } else {
+ dragging = 0;
+ }
+}
+
+void Rack::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ if ( computerized() )
+ return;
+ //int w = TileItem::bigWidth()+2;
+ if ( dragging ) {
+ dragging_adj = TileItem::bigWidth()/2;
+ if ( dragging->x() > e->x()-dragstart.x() )
+ dragging_adj = -dragging_adj;
+ dragging->move(e->x()-dragstart.x(),0);
+ layoutTiles();
+ }
+}
+
+void Rack::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ if ( computerized() )
+ return;
+ if ( dragging ) {
+ dragging=0;
+ layoutTiles();
+ }
+}
+
+Tile::Tile(const QString& key)
+{
+ int a=key.find('@');
+ txt = key.left(a);
+ val = key.mid(a+1).toInt();
+ blank = txt.isEmpty();
+}
+
+QString Tile::key() const
+{
+ return txt+"@"+QString::number(val);
+}
+
+Bag::Bag()
+{
+ tiles.setAutoDelete(TRUE);
+}
+
+void Bag::writeConfig(Config& cfg)
+{
+ QStringList t;
+ for (QListIterator<Tile> it(tiles); it; ++it)
+ t.append((*it)->key());
+ cfg.writeEntry("Tiles",t,';');
+}
+
+void Bag::readConfig(Config& cfg)
+{
+ tiles.clear();
+ QStringList t = cfg.readListEntry("Tiles",';');
+ for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it )
+ add(Tile(*it));
+}
+
+void Bag::add(const Tile& t)
+{
+ tiles.append(new Tile(t));
+}
+
+Tile Bag::takeRandom()
+{
+ Tile* rp = tiles.take(random()%tiles.count());
+ Tile r=*rp;
+ return r;
+}
+
+ScoreInfo::ScoreInfo( QWidget* parent, const char* name, WFlags fl ) :
+ QLabel("<P>",parent,name,fl)
+{
+ score=0;
+ msgtimer = new QTimer(this);
+ connect(msgtimer, SIGNAL(timeout()), this, SLOT(showScores()));
+ setBackgroundMode( PaletteButton );
+}
+
+ScoreInfo::~ScoreInfo()
+{
+ if ( score ) delete [] score;
+}
+
+void ScoreInfo::writeConfig(Config& cfg)
+{
+ QStringList l;
+ for (int i=0; i<(int)names.count(); i++)
+ l.append(QString::number(score[i]));
+ cfg.writeEntry("Scores",l,';');
+}
+
+void ScoreInfo::readConfig(Config& cfg)
+{
+ QStringList l = cfg.readListEntry("Scores",';');
+ int i=0;
+ for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it )
+ score[i++]=(*it).toInt();
+ showScores();
+}
+
+
+QSize ScoreInfo::sizeHint() const
+{
+ return QSize(QLabel::sizeHint().width(),fontMetrics().height());
+}
+
+void ScoreInfo::init(const QStringList& namelist)
+{
+ names = namelist;
+ if ( score ) delete [] score;
+ score = new int[names.count()];
+ memset(score,0,sizeof(int)*names.count());
+ boldone = -1;
+ showScores();
+}
+
+void ScoreInfo::addScore(int player, int change)
+{
+ score[player] += change;
+ showScores();
+}
+
+void ScoreInfo::setBoldOne(int b)
+{
+ boldone=b;
+ showScores();
+}
+
+void ScoreInfo::showScores()
+{
+ QString r="<p>";
+ int i=0;
+ //int spl=(names.count()+1)/2; // 2 lines
+ for (QStringList::ConstIterator it=names.begin(); it!=names.end(); ) {
+ if ( i==boldone ) r += "<b>";
+ QString n = *it;
+ n.replace(QRegExp(":.*"),"");
+ r += n;
+ r += ":";
+ r += QString::number(score[i]);
+ if ( i==boldone ) r += "</b>";
+
+ ++i;
+ ++it;
+ if ( it != names.end() )
+ r += " ";
+ }
+ setText(r);
+}
+
+void ScoreInfo::showTemporaryScore(int amount)
+{
+ if ( amount < 0 )
+ setText(tr("<P>Invalid move"));
+ else
+ setText(tr("<P>Score: ")+QString::number(amount));
+ msgtimer->start(3000,TRUE);
+}
+
diff --git a/noncore/games/wordgame/wordgame.h b/noncore/games/wordgame/wordgame.h
new file mode 100644
index 0000000..0ffa56a
--- a/dev/null
+++ b/noncore/games/wordgame/wordgame.h
@@ -0,0 +1,376 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef WORDGAME_H
+#define WORDGAME_H
+
+#include "newgamebase.h"
+#include "rulesbase.h"
+
+#include <qpe/qdawg.h>
+#include <qpe/applnk.h>
+
+#include <qmainwindow.h>
+#include <qcanvas.h>
+#include <qlabel.h>
+
+class QVBox;
+class QLabel;
+class QWidgetStack;
+class QToolButton;
+class Config;
+
+class Tile {
+public:
+ Tile() {}
+
+ Tile(const Tile& t)
+ {
+ txt = t.txt;
+ val = t.val;
+ blank = t.blank;
+ }
+
+ Tile(QString text, int value)
+ {
+ txt = text;
+ val = value;
+ blank = txt.isEmpty();
+ }
+
+ Tile(const QString& key);
+
+ int value() const { return val; }
+ bool isBlank() const { return blank; }
+ QString text() const { return txt; }
+ void setText(const QString& t)
+ {
+ txt = t;
+ }
+
+ int operator==(const Tile& o) const
+ { return o.txt == txt && o.val == val && o.blank == blank; }
+ int operator!=(const Tile& o) const
+ { return !operator==(o); }
+ Tile& operator=(const Tile& o)
+ { txt=o.txt; val=o.val; blank=o.blank; return *this; }
+
+ QString key() const;
+
+private:
+ QString txt;
+ int val;
+ bool blank;
+};
+
+class Bag {
+public:
+ Bag();
+
+ void readConfig(Config&);
+ void writeConfig(Config&);
+
+ void add(const Tile&);
+ bool isEmpty() const { return tiles.isEmpty(); }
+ Tile takeRandom();
+private:
+ QList<Tile> tiles;
+};
+
+class TileItem : public QCanvasRectangle {
+public:
+ TileItem(const Tile& tile, bool b, QCanvas* c) :
+ QCanvasRectangle(0,0,
+ b?bigWidth():smallWidth(),
+ b?bigHeight():smallHeight(),c),
+ t(tile), big(b), s(Firm)
+ {
+ }
+
+ static int smallWidth();
+ static int smallHeight();
+ static int bigWidth();
+ static int bigHeight();
+
+ enum State { Firm, Floating };
+ void setState( State state );
+ State state() const { return s; }
+ const Tile& tile() const { return t; }
+ void setTile(const Tile&);
+ void setBig(bool);
+
+protected:
+ void drawShape(QPainter&);
+
+private:
+ Tile t;
+ bool big;
+ State s;
+};
+
+class Rack : public QCanvasView {
+public:
+ Rack(int ntiles, QWidget* parent);
+ ~Rack();
+
+ void readConfig(Config&);
+ void writeConfig(Config&);
+
+ bool isFull() const { return count()==max(); }
+ int max() const { return item.count(); }
+ int count() const { return n; }
+ void addTile(const Tile& t);
+ Tile tile(int i) const { return item[i]->tile(); }
+ const Tile* tileRef(int i) const { return &item[i]->tile(); }
+ void remove(int i);
+ void remove(Tile);
+ bool arrangeTiles(const Tile** s, int sn);
+ void setBlanks(const Tile*);
+
+ void setPlayerName(const QString& name) { nm = name; }
+ QString playerName() const { return nm; }
+ void setComputerization(int level) { cpu=level; }
+ bool computerized() const { return cpu>0; }
+
+protected:
+ void resizeEvent(QResizeEvent*e);
+ void contentsMousePressEvent(QMouseEvent*);
+ void contentsMouseMoveEvent(QMouseEvent*);
+ void contentsMouseReleaseEvent(QMouseEvent*);
+
+private:
+ void clear();
+ void layoutTiles();
+ int n;
+ QArray<TileItem*> item;
+ int dragging_adj;
+ QPoint dragstart;
+ QCanvasItem* dragging;
+ QString nm;
+ int cpu;
+};
+
+class Board : public QCanvasView {
+ Q_OBJECT
+public:
+ Board(QPixmap bgshapes, int w, int h, QWidget* parent);
+ ~Board();
+
+ void readConfig(Config&);
+ void writeConfig(Config&);
+
+ int xTiles() const { return canvas()->tilesHorizontally(); }
+ int yTiles() const { return canvas()->tilesVertically(); }
+
+ bool contains(const QPoint& p) const
+ { return p.x() >= 0 && p.y() >= 0
+ && p.x() < canvas()->tilesHorizontally()
+ && p.y() < canvas()->tilesVertically(); }
+ const Tile* tile(const QPoint& p) const
+ { TileItem* it=item(p); return it ? &it->tile() : 0; }
+
+ void setRules(const QString& shapes, const int* effects);
+
+ void clear();
+ void unsetTile(const QPoint& p);
+ void setTile(const QPoint& p, const Tile& t);
+
+ void setTileState(const QPoint& p, TileItem::State s)
+ {
+ TileItem* it=item(p);
+ if (it) it->setState(s);
+ }
+
+ void setCurrentRack(Rack*);
+ void resetRack();
+ void finalizeTurn();
+ void showTurn();
+ void scoreTurn(const QPoint& at, int n, const QPoint& d);
+ bool checkTurn();
+ int score(QPoint at, const Tile** tiles, int n,
+ const Tile* blankvalue,
+ const QPoint& d, bool ignoredict, QStringList* words) const;
+ int bonussedValue(const QPoint& at, int base, int& all_mult) const;
+ bool isStart(const QPoint& at) const;
+
+ int turnScore() const { return turn_score; }
+
+signals:
+ void temporaryScore(int);
+
+protected:
+ void contentsMousePressEvent(QMouseEvent*);
+ void contentsMouseMoveEvent(QMouseEvent*);
+ void contentsMouseReleaseEvent(QMouseEvent*);
+
+private:
+ int idx(const QPoint& p) const
+ { return p.x()+p.y()*canvas()->tilesHorizontally(); }
+ TileItem*& item(const QPoint& p) const
+ { return grid[idx(p)]; }
+ TileItem **grid;
+ QString rule_shape;
+ const int* rule_effect;
+ int rack_tiles_bonus;
+ Rack* current_rack;
+ QPoint boardPos(const QPoint&) const;
+ QPoint dragstart;
+ QPoint shown_at;
+ int shown_n;
+ QPoint shown_step;
+ void unshowTurn();
+ int turn_score;
+};
+
+class ComputerPlayer
+{
+ Board* board;
+ Rack* rack;
+
+ bool across;
+ int dict;
+ QPoint current;
+
+ const Tile** best;
+ int best_n;
+ Tile* best_blankvalues;
+ int best_blused;
+ int best_score;
+ QPoint best_dir;
+ QPoint best_start;
+
+public:
+ ComputerPlayer(Board* b, Rack* r);
+ ~ComputerPlayer();
+
+ bool step();
+
+private:
+ void findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar *nletter, const Tile** tiles, int n, Tile* blankvalues, int blused);
+ void noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused);
+};
+
+class ScoreInfo : public QLabel {
+ Q_OBJECT
+public:
+ ScoreInfo( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~ScoreInfo();
+
+ void init(const QStringList&);
+ void addScore(int player, int change);
+ int playerScore(int player) const { return score[player]; }
+ void setShowWinner(bool);
+ void setBoldOne(int);
+
+ void readConfig(Config&);
+ void writeConfig(Config&);
+
+protected:
+ QSize sizeHint() const;
+
+public slots:
+ void showTemporaryScore(int amount);
+
+private slots:
+ void showScores();
+
+private:
+ QStringList names;
+ int *score;
+ QTimer* msgtimer;
+ bool showwinner;
+ int boldone;
+};
+
+class NewGame;
+
+class WordGame : public QMainWindow {
+ Q_OBJECT
+public:
+ WordGame( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~WordGame();
+
+private slots:
+ void endTurn();
+ void resetTurn();
+ void passTurn();
+ void think();
+ void endGame();
+ void startGame();
+
+private:
+ void writeConfig();
+ void readConfig();
+
+ void startGame(const QStringList& pnames);
+ bool mayEndGame();
+ void openGameSelector(const QStringList& initnames);
+ bool loadRules(const QString& filename);
+ void addPlayer(const QString& name);
+ void addPlayer(const QString& name, int cpu);
+ void nextPlayer();
+ bool refillRack(int i);
+ void readyRack(int i);
+ Rack* rack(int i) const;
+
+ QWidgetStack *racks;
+ QToolBar* toolbar;
+ QVBox *vbox;
+ Board *board;
+ Bag *bag;
+ ScoreInfo *scoreinfo;
+ QToolButton *done;
+ QToolButton *reset;
+ QTimer* aiheart;
+ ComputerPlayer *cpu;
+ int player;
+ int nplayers;
+ QStringList namelist;
+ bool gameover;
+ QString rules;
+ NewGame* newgame;
+};
+
+class NewGame : public NewGameBase {
+ Q_OBJECT
+public:
+ NewGame(QWidget* parent);
+ QStringList ruleslist;
+
+public slots:
+ void updateRuleSets();
+};
+
+class Rules : public RulesBase {
+ Q_OBJECT
+
+public:
+ Rules(QWidget* parent);
+
+signals:
+ void rulesChanged();
+
+public slots:
+ void editRules();
+
+private:
+ void deleteRuleSet();
+};
+
+#endif // WORDGAME_H
diff --git a/noncore/games/wordgame/wordgame.pro b/noncore/games/wordgame/wordgame.pro
new file mode 100644
index 0000000..7feacf9
--- a/dev/null
+++ b/noncore/games/wordgame/wordgame.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+CONFIG = qt warn_on release
+DESTDIR = $(QPEDIR)/bin
+HEADERS = wordgame.h
+SOURCES = main.cpp \
+ wordgame.cpp
+INTERFACES = newgamebase.ui rulesbase.ui
+TARGET = wordgame
+INCLUDEPATH += $(QPEDIR)/include
+DEPENDPATH += $(QPEDIR)/include
+LIBS += -lqpe
+
+TRANSLATIONS = ../i18n/de/wordgame.ts