diff options
Diffstat (limited to 'ktron')
-rw-r--r-- | ktron/AUTHORS | 2 | ||||
-rw-r--r-- | ktron/ChangeLog | 21 | ||||
-rw-r--r-- | ktron/Makefile.am | 22 | ||||
-rw-r--r-- | ktron/README | 39 | ||||
-rw-r--r-- | ktron/TODO | 10 | ||||
-rw-r--r-- | ktron/ai.ui | 141 | ||||
-rw-r--r-- | ktron/appearance.ui | 302 | ||||
-rw-r--r-- | ktron/general.ui | 219 | ||||
-rw-r--r-- | ktron/ktron.cpp | 195 | ||||
-rw-r--r-- | ktron/ktron.desktop | 66 | ||||
-rw-r--r-- | ktron/ktron.h | 67 | ||||
-rw-r--r-- | ktron/ktron.kcfg | 84 | ||||
-rw-r--r-- | ktron/ktronui.rc | 3 | ||||
-rw-r--r-- | ktron/main.cpp | 59 | ||||
-rw-r--r-- | ktron/pics/Makefile.am | 15 | ||||
-rw-r--r-- | ktron/pics/hi128-app-ktron.png | bin | 0 -> 10435 bytes | |||
-rw-r--r-- | ktron/pics/hi16-app-ktron.png | bin | 0 -> 531 bytes | |||
-rw-r--r-- | ktron/pics/hi22-app-ktron.png | bin | 0 -> 973 bytes | |||
-rw-r--r-- | ktron/pics/hi32-app-ktron.png | bin | 0 -> 1490 bytes | |||
-rw-r--r-- | ktron/pics/hi48-app-ktron.png | bin | 0 -> 2733 bytes | |||
-rw-r--r-- | ktron/pics/hi64-app-ktron.png | bin | 0 -> 3971 bytes | |||
-rw-r--r-- | ktron/player.cpp | 57 | ||||
-rw-r--r-- | ktron/player.h | 56 | ||||
-rw-r--r-- | ktron/settings.kcfgc | 5 | ||||
-rw-r--r-- | ktron/tron.cpp | 1654 | ||||
-rw-r--r-- | ktron/tron.h | 178 | ||||
-rw-r--r-- | ktron/version.h | 1 |
27 files changed, 3196 insertions, 0 deletions
diff --git a/ktron/AUTHORS b/ktron/AUTHORS new file mode 100644 index 00000000..2dc6d21a --- /dev/null +++ b/ktron/AUTHORS @@ -0,0 +1,2 @@ +Matthias Kiefer <matthias.kiefer@gmx.de> +Benjamin Meyer <ben at meyerhome dot net> diff --git a/ktron/ChangeLog b/ktron/ChangeLog new file mode 100644 index 00000000..317f9ac4 --- /dev/null +++ b/ktron/ChangeLog @@ -0,0 +1,21 @@ +Changes 1.0: +- added possibility to load background images +- added possibility to give names to players + +Changes 0.5: +- new drawing style: 3d-line +- new improved computerplayer with possibility to change the skill + +Changes 0.4: +- worked over to compile with KDE 1.1.1 +- flickering fixed +- added some options + (block accelerator, disable changing color) +- some finetuning at drawing players and frame + +Changes 0.3.3: +- use of bitBlt(...) to get less flickering +- crashes are now shown by changing the color +- after a crash, the game is blocked for one second +- possiblity to change the size of the players +- possibility to change style of the players diff --git a/ktron/Makefile.am b/ktron/Makefile.am new file mode 100644 index 00000000..e7629bd2 --- /dev/null +++ b/ktron/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS=pics + +bin_PROGRAMS = ktron +INCLUDES = -I$(top_srcdir)/libkdegames $(all_includes) + +ktron_SOURCES = ai.ui appearance.ui general.ui tron.cpp player.cpp ktron.cpp main.cpp settings.kcfgc +ktron_LDFLAGS = $(all_libraries) $(KDE_RPATH) +ktron_LDADD = $(LIB_KIO) $(LIB_KDEGAMES) +ktron_DEPENDENCIES = $(LIB_KDEGAMES_DEP) + +EXTRA_DIST = ktron.desktop + +xdg_apps_DATA = ktron.desktop +kde_kcfg_DATA = ktron.kcfg + +METASOURCES = AUTO + +rcdir = $(kde_datadir)/ktron +rc_DATA = ktronui.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/ktron.pot diff --git a/ktron/README b/ktron/README new file mode 100644 index 00000000..3f48d78d --- /dev/null +++ b/ktron/README @@ -0,0 +1,39 @@ +Hello! + +KTron is a simple tron-clone for the K Desktop Environment. +I think it's just nothing to say about the game: +avoid running into walls, your own tail, and that of your opponent. + +Read the Online-Documentation for more details. + + +Notice: +Parts of the code, especially parts of the algorithm for the computerplayer +are from xtron-1.1 by Rhett D. Jacobs <rhett@hotel.canberra.edu.au> + + +Copyright: + +KTron + +Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + +KTron is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 or any later version. + +KTron is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +Hope you have a lot of fun :-) + +--------------- +Matthias Kiefer <matthias.kiefer@gmx.de> +27 February 2000 diff --git a/ktron/TODO b/ktron/TODO new file mode 100644 index 00000000..6ff85f99 --- /dev/null +++ b/ktron/TODO @@ -0,0 +1,10 @@ +KTron in general does everything I wanted it to do. :-) + +Plans for the future are: +- possibility to create, load, save playfield with walls +- real cool would be to play KTron over the internet + +------------------ +Matthias Kiefer +5/99 + diff --git a/ktron/ai.ui b/ktron/ai.ui new file mode 100644 index 00000000..3abcef57 --- /dev/null +++ b/ktron/ai.ui @@ -0,0 +1,141 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>Ai</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Ai</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>302</width> + <height>168</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>frame9</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Computer Controls</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_Computerplayer1</cstring> + </property> + <property name="text"> + <string>Player &1</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_Computerplayer2</cstring> + </property> + <property name="text"> + <string>Player &2</string> + </property> + </widget> + </hbox> + </widget> + <spacer row="1" column="2"> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>101</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel15</cstring> + </property> + <property name="text"> + <string>Intelligence:</string> + </property> + </widget> + <widget class="QComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>Beginner</string> + </property> + </item> + <item> + <property name="text"> + <string>Average</string> + </property> + </item> + <item> + <property name="text"> + <string>Expert</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_Skill</cstring> + </property> + <property name="currentItem"> + <number>1</number> + </property> + </widget> + <spacer row="2" column="1"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>60</height> + </size> + </property> + </spacer> + </grid> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/ktron/appearance.ui b/ktron/appearance.ui new file mode 100644 index 00000000..af50183f --- /dev/null +++ b/ktron/appearance.ui @@ -0,0 +1,302 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>Appearance</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Appearance</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>284</width> + <height>337</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>frame4</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel16</cstring> + </property> + <property name="text"> + <string>Line style:</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="2"> + <item> + <property name="text"> + <string>3D Line</string> + </property> + </item> + <item> + <property name="text"> + <string>3D Rectangles</string> + </property> + </item> + <item> + <property name="text"> + <string>Flat</string> + </property> + </item> + <item> + <property name="text"> + <string>Circles</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_Style</cstring> + </property> + </widget> + <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>Line Size</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel13</cstring> + </property> + <property name="text"> + <string>Large</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel11</cstring> + </property> + <property name="text"> + <string>Small</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabel12</cstring> + </property> + <property name="text"> + <string>Medium</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QSlider" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_RectSize</cstring> + </property> + <property name="minValue"> + <number>4</number> + </property> + <property name="maxValue"> + <number>16</number> + </property> + <property name="lineStep"> + <number>3</number> + </property> + <property name="pageStep"> + <number>3</number> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>Right</enum> + </property> + <property name="tickInterval"> + <number>1</number> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_BackgroundImageChoice</cstring> + </property> + <property name="title"> + <string>Background</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>BackgroundColorChoice</cstring> + </property> + <property name="text"> + <string>Color:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>kcfg_BackgroundImage</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>BackgroundImageChoice</cstring> + </property> + <property name="text"> + <string>Image:</string> + </property> + </widget> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>kcfg_Color_Background</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + </widget> + </grid> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel7</cstring> + </property> + <property name="text"> + <string>Player 1 color:</string> + </property> + </widget> + <widget class="KColorButton" row="3" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_Color_Player1</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel8</cstring> + </property> + <property name="text"> + <string>Player 2 color:</string> + </property> + </widget> + <widget class="KColorButton" row="4" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_Color_Player2</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </property> + </widget> + <spacer row="5" column="2"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </grid> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>BackgroundColorChoice</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_Color_Background</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>BackgroundImageChoice</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_BackgroundImage</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_Style</tabstop> + <tabstop>kcfg_RectSize</tabstop> + <tabstop>kcfg_Color_Player1</tabstop> + <tabstop>kcfg_Color_Player2</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/ktron/general.ui b/ktron/general.ui new file mode 100644 index 00000000..ca492b9e --- /dev/null +++ b/ktron/general.ui @@ -0,0 +1,219 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>General</class> +<widget class="QWidget"> + <property name="name"> + <cstring>General</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>379</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>frame4</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Behavior</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_ChangeWinnerColor</cstring> + </property> + <property name="text"> + <string>&Show winner by changing color</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_AcceleratorBlocked</cstring> + </property> + <property name="text"> + <string>&Disable acceleration</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_OppositeDirCrashes</cstring> + </property> + <property name="text"> + <string>&Crash when moving in the opposite direction</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Player Names</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_NamePlayer1</cstring> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_NamePlayer2</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Player 1:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Player 2:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Speed</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSlider"> + <property name="name"> + <cstring>kcfg_Velocity</cstring> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>9</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>5</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>Right</enum> + </property> + <property name="tickInterval"> + <number>1</number> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Slow</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Default</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Fast</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/ktron/ktron.cpp b/ktron/ktron.cpp new file mode 100644 index 00000000..67151ff0 --- /dev/null +++ b/ktron/ktron.cpp @@ -0,0 +1,195 @@ +/* **************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + *****************************************************************************/ + +#include "ktron.h" + +#include <kconfigdialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kaction.h> +#include <kstdgameaction.h> +#include <kapplication.h> +#include <kstatusbar.h> + +// Settings +#include "settings.h" +#include "general.h" +#include "ai.h" +#include "appearance.h" + +#define ID_STATUS_BASE 40 +#define MESSAGE_TIME 2000 +#define WINNING_DIFF 5 + +/** + * Constuctor + */ +KTron::KTron(QWidget *parent, const char *name) : KMainWindow(parent, name) { + playerPoints[0]=playerPoints[1]=0; + + tron=new Tron(this, "Tron"); + connect(tron,SIGNAL(gameEnds(Player)),SLOT(changeStatus(Player))); + setCentralWidget(tron); + tron->setMinimumSize(200,180); + + // create statusbar + statusBar()->insertItem("abcdefghijklmnopqrst: 0 ",ID_STATUS_BASE+1); + statusBar()->insertItem("abcdefghijklmnopqrst: 0 ",ID_STATUS_BASE+2); + + // We match up keyboard events ourselves in Tron::keyPressEvent() + // We must disable the actions, otherwise we don't get the keyPressEvent's + KAction *act; + act = new KAction(i18n("Player 1 Up"), Key_R, 0, 0, actionCollection(), "Pl1Up"); + act->setEnabled(false); + act = new KAction(i18n("Player 1 Down"), Key_F, 0, 0, actionCollection(), "Pl1Down"); + act->setEnabled(false); + act = new KAction(i18n("Player 1 Right"), Key_G, 0, 0, actionCollection(), "Pl1Right"); + act->setEnabled(false); + act = new KAction(i18n("Player 1 Left"), Key_D, 0, 0, actionCollection(), "Pl1Left"); + act->setEnabled(false); + act = new KAction(i18n("Player 1 Accelerator"), Key_A, 0, 0, actionCollection(), "Pl1Ac"); + act->setEnabled(false); + + act = new KAction(i18n("Player 2 Up"), Key_Up, 0, 0, actionCollection(), "Pl2Up"); + act->setEnabled(false); + act = new KAction(i18n("Player 2 Down"), Key_Down, 0, 0, actionCollection(), "Pl2Down"); + act->setEnabled(false); + act = new KAction(i18n("Player 2 Right"), Key_Right, 0, 0, actionCollection(), "Pl2Right"); + act->setEnabled(false); + act = new KAction(i18n("Player 2 Left"), Key_Left, 0, 0, actionCollection(), "Pl2Left"); + act->setEnabled(false); + act = new KAction(i18n("Player 2 Accelerator"), Key_0, 0, 0, actionCollection(), "Pl2Ac"); + act->setEnabled(false); + + tron->setActionCollection(actionCollection()); + + KStdGameAction::pause(tron, SLOT(togglePause()), actionCollection()); + KStdGameAction::gameNew( tron, SLOT( newGame() ), actionCollection() ); + KStdGameAction::quit(this, SLOT( close() ), actionCollection()); + KStdAction::preferences(this, SLOT(showSettings()), actionCollection()); + + setupGUI( KMainWindow::Keys | StatusBar | Save | Create); + loadSettings(); +} + +void KTron::loadSettings() { + playerName[0]=Settings::namePlayer1(); + if ( playerName[0].isEmpty() ) + playerName[0] = i18n("Player 1"); + playerName[1]=Settings::namePlayer2(); + if ( playerName[1].isEmpty() ) + playerName[1] = i18n("Player 2"); + + updateStatusbar(); +} + +void KTron::updateStatusbar(){ + for(int i=0;i<2;i++){ + Player player; + player=(i==0?One:Two); + + QString name; + if(tron->isComputer(Both)) + name=i18n("Computer(%1)").arg(i+1); + else if(tron->isComputer(player)) + name=i18n("Computer"); + else + name=playerName[i]; + QString string = QString("%1: %2").arg(name).arg(playerPoints[i]); + statusBar()->changeItem(string,ID_STATUS_BASE+i+1); + } +} + +void KTron::changeStatus(Player player) { + // if player=Nobody, then new game + if(player==Nobody){ + playerPoints[0]=playerPoints[1]=0; + updateStatusbar(); + return; + } + + if(player==One) + playerPoints[0]++; + else if(player==Two) + playerPoints[1]++; + else if(player==Both){ + playerPoints[0]++; + playerPoints[1]++; + } + + updateStatusbar(); + + if(playerPoints[0]>=WINNING_DIFF && playerPoints[1] < playerPoints[0]-1) + showWinner(One); + else if(playerPoints[1]>=WINNING_DIFF && playerPoints[0] < playerPoints[1]-1) + showWinner(Two); +} + +void KTron::showWinner(Player winner){ + if(tron->isComputer(Both) || (winner != One && winner != Two)) + return; + + QString loserName = i18n("KTron"); + int loser = Two; + if(winner == Two) + loser = One; + if(!tron->isComputer(((Player)loser))) + loserName = playerName[loser]; + + QString winnerName = i18n("KTron"); + if(!tron->isComputer(winner)) + winnerName = playerName[winner]; + + QString message=i18n("%1 has won!").arg(winnerName); + statusBar()->message(message,MESSAGE_TIME); + + message = i18n("%1 has won versus %2 with %3 : %4 points!"); + message=message.arg(winnerName).arg(loserName); + message=message.arg(playerPoints[winner]).arg(playerPoints[loser]); + + KMessageBox::information(this, message, i18n("Winner")); + tron->newGame(); +} + +void KTron::paletteChange(const QPalette &/*oldPalette*/){ + update(); + tron->updatePixmap(); + tron->update(); +} + +/** + * Show Settings dialog. + */ +void KTron::showSettings(){ + if(KConfigDialog::showDialog("settings")) + return; + + KConfigDialog *dialog = new KConfigDialog(this, "settings", Settings::self()); + dialog->addPage(new General(0, "General"), i18n("General"), "package_settings"); + dialog->addPage(new Ai(0, "Ai"), i18n("A.I."), "personal"); + dialog->addPage(new Appearance(0, "Appearance"), i18n("Appearance"), "style"); + connect(dialog, SIGNAL(settingsChanged()), tron, SLOT(loadSettings())); + connect(dialog, SIGNAL(settingsChanged()), this, SLOT(loadSettings())); + dialog->show(); +} + +#include "ktron.moc" + diff --git a/ktron/ktron.desktop b/ktron/ktron.desktop new file mode 100644 index 00000000..20930d16 --- /dev/null +++ b/ktron/ktron.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Type=Application +Exec=ktron -caption "%c" %i %m +Icon=ktron +DocPath=ktron/index.html +GenericName=Tron-like Game +GenericName[be]=ÑğÑ½Ñ ˘Ñ½ +GenericName[bg]=³¸ÑµÑş° ¸³Ñ° +GenericName[bn]=àĤà§àĤ°àĤ¨-àĤàĤàĤ¤à§à§ àĤà§àĤ²àĤ +GenericName[br]=C'hoari doare Tron +GenericName[bs]=Igra nalik na Tron +GenericName[ca]=Joc a l'estil Tron +GenericName[cs]=Hra podobnĦ Tronu +GenericName[cy]=GŞm sy'n debyg i Tron +GenericName[da]=Tron-lignende spil +GenericName[de]=Tron-¤hnliches Spiel +GenericName[el]=Î ÎħÎıÏÎ½ÎŻÎ´Îı ÏÎħÏÏÎĵÎżÎıÎż Îĵε ÏÎż Tron +GenericName[eo]="Tron"-simila ludo +GenericName[es]=Juego similar a Tron +GenericName[et]=Tron +GenericName[eu]=Tron-en antzeko jokoa +GenericName[fa]=Ĝ¨Ĝ§Ĝ²Û Ĝ´Ĝ¨ÛÙTron +GenericName[fi]=Tron-tyylinen peli +GenericName[fr]=Jeu dans le style de Tron +GenericName[he]=××İ×ק ××ק×× Tron +GenericName[hr]=Igra poput Trona +GenericName[hu]=Tron-szerĊħ +GenericName[is]=Leikur sem lkist Tron +GenericName[it]=Gioco simile a Tron +GenericName[ja]=³Ş²ĵ +GenericName[km]=áááááâááĵá
Tron +GenericName[lv]=Tron lÄĞdzÄĞga spÄle +GenericName[mk]=³Ñ° Ñğ¸Ñ½° ½° Tron +GenericName[nb]=Tron-lignende spill +GenericName[nds]=Tron-liek Speel +GenericName[ne]=à¤àरàन à¤à¤¸àतà à¤àल +GenericName[nl]=Tron-achtig spel +GenericName[nn]=Tron-liknande spel +GenericName[pl]=Gra typu Tron +GenericName[pt]=Jogo tipo Tron +GenericName[pt_BR]=Jogo parecido com Tron +GenericName[ru]=˘Ñ½ +GenericName[se]=Tron-lĦgan speallu +GenericName[sk]=Hra typu Tron +GenericName[sl]=Igra podobna Tronu +GenericName[sr]=³Ñ° ½°ğ¸ş ½° Tron +GenericName[sr@Latn]=Igra nalik na Tron +GenericName[sv]=Tron-liknande spel +GenericName[ta]=ààŻà°àŻàİàŻ àŞàŻàİàŻàħ àµàżà³àŻàŻàààŻààŻ +GenericName[uk]=Ñ° ÑÑ
ĥ° ½° ³ÑÑ "˘Ñ½" +GenericName[zh_TW]=éĦäĵĵ Tron éĉ² +Terminal=false +Name=KTron +Name[af]=Ktron +Name[be]=˘Ñ½ +Name[bn]=àĤà§-àĤà§àĤ°àĤ¨ +Name[hi]=à¤à-à¤àरà¤à¤¨ +Name[nb]=Tron +Name[ne]=à¤àà¤Ħàठà¤àरàन +Name[sv]=Ktron +Name[ta]=KààŻà°ààİàŻ +Name[tg]=K˘Ñ½ +Name[zu]=I-KTron +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Game;ArcadeGame; diff --git a/ktron/ktron.h b/ktron/ktron.h new file mode 100644 index 00000000..191f2b44 --- /dev/null +++ b/ktron/ktron.h @@ -0,0 +1,67 @@ +/* *************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + ****************************************************************************/ + +#ifndef KTRON_H +#define KTRON_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kmainwindow.h> +#include "tron.h" + +class KAccel; +class KSelectAction; +class Tron; + +/** + * @short The main window of KTron + */ +class KTron : public KMainWindow { + +Q_OBJECT + +public: + KTron(QWidget *parent=0, const char *name=0); + +private: + KAccel *accel; + Tron *tron; + QString playerName[2]; + int playerPoints[2]; + void updateStatusbar(); + +protected: + /** calls tron->updatePixmap to draw frame in the new colors */ + void paletteChange(const QPalette &oldPalette); + +private slots: + void loadSettings(); + /** updates players points in statusbar and checks if someone has won */ + void changeStatus(Player); + + void showWinner(Player winner); + void showSettings(); +}; + +#endif // KTRON_H + diff --git a/ktron/ktron.kcfg b/ktron/ktron.kcfg new file mode 100644 index 00000000..d46c2a76 --- /dev/null +++ b/ktron/ktron.kcfg @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="ktronrc"/> + <group name="Game"> + <entry name="Color_Background" type="Color"> + <label>The background color of the game.</label> + <default>black</default> + </entry> + <entry name="Color_Player1" type="Color"> + <label>The color of player 1</label> + <default>red</default> + </entry> + <entry name="Color_Player2" type="Color"> + <label>The color of player 2</label> + <default>blue</default> + </entry> + <entry name="ChangeWinnerColor" type="Bool"> + <label>Whether to show the winner by changing color.</label> + <default>true</default> + </entry> + <entry name="AcceleratorBlocked" type="Bool"> + <label>Whether to disable acceleration.</label> + <default>false</default> + </entry> + <entry name="OppositeDirCrashes" type="Bool"> + <label>Whether changing in the opposite direction causes a crash.</label> + <default>false</default> + </entry> + <entry name="RectSize" type="Int"> + <label>The width of the line.</label> + <default>10</default> + </entry> + <entry name="Velocity" type="Int"> + <label>The speed of the line.</label> + <default>5</default> + </entry> + + <entry name="Skill" type="Enum"> + <label>The skill of the computer player.</label> + <choices> + <choice name="Easy"/> + <choice name="Medium"/> + <choice name="Hard"/> + </choices> + <default>Medium</default> + </entry> + <entry name="Style" type="Enum"> + <label>The line style.</label> + <choices> + <choice name="OLine"/> + <choice name="ORect"/> + <choice name="Line"/> + <choice name="Circle"/> + </choices> + <default>OLine</default> + </entry> + + <entry name="BackgroundImageChoice" type="Bool"> + <label>Whether to use a custom background image.</label> + <default>false</default> + </entry> + <entry name="BackgroundImage" type="Path"> + <label>Custom background image to use.</label> + </entry> + + <entry name="Computerplayer1" type="Bool"> + <label>Whether player 1 is a computer player.</label> + <default>true</default> + </entry> + <entry name="Computerplayer2" type="Bool"> + <label>Whether player 2 is a computer player.</label> + <default>false</default> + </entry> + <entry name="NamePlayer1" type="String" key="Name_Pl1"> + <label>The name of player 1.</label> + </entry> + <entry name="NamePlayer2" type="String" key="Name_Pl2"> + <label>The name of player 2.</label> + </entry> + </group> +</kcfg> diff --git a/ktron/ktronui.rc b/ktron/ktronui.rc new file mode 100644 index 00000000..2d5a6c99 --- /dev/null +++ b/ktron/ktronui.rc @@ -0,0 +1,3 @@ +<!DOCTYPE kpartgui> +<kpartgui name="ktron" version="3"> +</kpartgui> diff --git a/ktron/main.cpp b/ktron/main.cpp new file mode 100644 index 00000000..17be8fe1 --- /dev/null +++ b/ktron/main.cpp @@ -0,0 +1,59 @@ +/****************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + ****************************************************************************/ +#include <kapplication.h> +#include <kimageio.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> + +#include "ktron.h" +#include "version.h" + +static const char description[] = I18N_NOOP("A race in hyperspace"); +static const char notice[] = I18N_NOOP("(c) 1998-2000, Matthias Kiefer\n\n" +"Parts of the algorithms for the computer player are from\n" +"xtron-1.1 by Rhett D. Jacobs <rhett@hotel.canberra.edu.au>"); + + +int main(int argc, char* argv[]) +{ + KAboutData aboutData( "ktron", I18N_NOOP("KTron"), + KTRON_VERSION, description, KAboutData::License_GPL, notice); + aboutData.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"), "matthias.kiefer@gmx.de"); + aboutData.addAuthor("Benjamin Meyer",I18N_NOOP("Various improvements"), "ben+ktron@meyerhome.net"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication a; + KGlobal::locale()->insertCatalogue("libkdegames"); + + // used for loading background pixmaps + KImageIO::registerFormats(); + + if(a.isRestored()){ + RESTORE(KTron) + } + else { + KTron *ktron = new KTron(); + a.setMainWidget(ktron); + ktron->show(); + } + return a.exec(); +} + diff --git a/ktron/pics/Makefile.am b/ktron/pics/Makefile.am new file mode 100644 index 00000000..751de516 --- /dev/null +++ b/ktron/pics/Makefile.am @@ -0,0 +1,15 @@ +KDE_ICON=AUTO + +generate: + @echo "Converting SVG files to PNG files. Sizes: 16x16; 22x22; 32x32; 48x48; 64x64; 128x128" + + @for file in *.svg*; do \ + echo "Processing: $$file..."; \ + ksvgtopng 16 16 $$file `basename $$file | sed -e 's/crsc/cr16/' | sed -e 's/svg\|svgz/png/'`; \ + ksvgtopng 22 22 $$file `basename $$file | sed -e 's/crsc/cr22/' | sed -e 's/svg\|svgz/png/'`; \ + ksvgtopng 32 32 $$file `basename $$file | sed -e 's/crsc/cr32/' | sed -e 's/svg\|svgz/png/'`; \ + ksvgtopng 48 48 $$file `basename $$file | sed -e 's/crsc/cr48/' | sed -e 's/svg\|svgz/png/'`; \ + ksvgtopng 64 64 $$file `basename $$file | sed -e 's/crsc/cr64/' | sed -e 's/svg\|svgz/png/'`; \ + ksvgtopng 128 128 $$file `basename $$file | sed -e 's/crsc/cr128/' | sed -e 's/svg\|svgz/png/'`; \ + done + diff --git a/ktron/pics/hi128-app-ktron.png b/ktron/pics/hi128-app-ktron.png Binary files differnew file mode 100644 index 00000000..a2433c02 --- /dev/null +++ b/ktron/pics/hi128-app-ktron.png diff --git a/ktron/pics/hi16-app-ktron.png b/ktron/pics/hi16-app-ktron.png Binary files differnew file mode 100644 index 00000000..c6ee2edf --- /dev/null +++ b/ktron/pics/hi16-app-ktron.png diff --git a/ktron/pics/hi22-app-ktron.png b/ktron/pics/hi22-app-ktron.png Binary files differnew file mode 100644 index 00000000..2058ee2e --- /dev/null +++ b/ktron/pics/hi22-app-ktron.png diff --git a/ktron/pics/hi32-app-ktron.png b/ktron/pics/hi32-app-ktron.png Binary files differnew file mode 100644 index 00000000..2d96ffec --- /dev/null +++ b/ktron/pics/hi32-app-ktron.png diff --git a/ktron/pics/hi48-app-ktron.png b/ktron/pics/hi48-app-ktron.png Binary files differnew file mode 100644 index 00000000..5cc088f1 --- /dev/null +++ b/ktron/pics/hi48-app-ktron.png diff --git a/ktron/pics/hi64-app-ktron.png b/ktron/pics/hi64-app-ktron.png Binary files differnew file mode 100644 index 00000000..8961e2d0 --- /dev/null +++ b/ktron/pics/hi64-app-ktron.png diff --git a/ktron/player.cpp b/ktron/player.cpp new file mode 100644 index 00000000..76cef9de --- /dev/null +++ b/ktron/player.cpp @@ -0,0 +1,57 @@ +/********************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + *******************************************************************************/ + +#include "player.h" + +player::player() +{ + computer=false; + score=0; + reset(); + dir=Directions::Up; + last_dir=Directions::None; +} + + +void player::reset() +{ + alive=true; + accelerated=false; + if(computer) + keyPressed=true; + else + keyPressed=false; +} + +void player::setCoordinates(int x, int y) +{ + xCoordinate=x; + yCoordinate=y; +} + +void player::setComputer(bool isComputer) +{ + computer=isComputer; + if(computer) + keyPressed=true; + else keyPressed=false; +} + diff --git a/ktron/player.h b/ktron/player.h new file mode 100644 index 00000000..eefad62c --- /dev/null +++ b/ktron/player.h @@ -0,0 +1,56 @@ +/* ******************************************************************************** + This file is part of the kde-game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + *******************************************************************************/ + +#ifndef PLAYER_H +#define PLAYER_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +namespace Directions +{ + enum Direction{ None, Up, Down, Left, Right}; +} + +/** +* @short This class represents a player with current position and several flags +*/ +class player +{ +public: + player(); + void reset(); + void setCoordinates(int x, int y); + void setComputer(bool computer); + + int xCoordinate,yCoordinate; + int score; + bool alive; + Directions::Direction dir; + Directions::Direction last_dir; + bool accelerated; + bool keyPressed; + bool computer; +}; + +#endif + diff --git a/ktron/settings.kcfgc b/ktron/settings.kcfgc new file mode 100644 index 00000000..de60e440 --- /dev/null +++ b/ktron/settings.kcfgc @@ -0,0 +1,5 @@ +# Code generation options for kconfig_compiler +File=ktron.kcfg +ClassName=Settings +Singleton=true +Mutators=false diff --git a/ktron/tron.cpp b/ktron/tron.cpp new file mode 100644 index 00000000..494d96bc --- /dev/null +++ b/ktron/tron.cpp @@ -0,0 +1,1654 @@ +/**************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + ***************************************************************************/ +// Background +#include <kio/netaccess.h> +#include <kmessagebox.h> + +// Normal class +#include <qtimer.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kcolordialog.h> +#include <kaction.h> + +#include "settings.h" +#include "tron.h" + +#define TRON_FRAMESIZE 2 + +/** + * init-functions + **/ + +Tron::Tron(QWidget *parent,const char *name) + : QWidget(parent,name) +{ + pixmap=0; + playfield=0; + beginHint=false; + lookForward=15; + + random.setSeed(0); + + setFocusPolicy(QWidget::StrongFocus); + setBackgroundMode(NoBackground); + + gameBlocked=false; + rectSize=10; + + timer = new QTimer(this,"timer"); + loadSettings(); + connect(timer, SIGNAL(timeout()), SLOT(doMove())); + QTimer::singleShot(15000, this,SLOT(showBeginHint())); +} + +void Tron::loadSettings(){ + setPalette(Settings::color_Background()); + + // Size + int newSize = Settings::rectSize(); + if(newSize!=rectSize){ + rectSize=newSize; + createNewPlayfield(); + } + + reset(); + + // Velocity + setVelocity( Settings::velocity() ); + + // Style + if(pixmap){ + updatePixmap(); + repaint(); + } + + // Backgroundimage + setBackgroundPix(NULL); + if(Settings::backgroundImageChoice()){ + KURL url ( Settings::backgroundImage() ); + if(!url.isEmpty()){ + QString tmpFile; + KIO::NetAccess::download(url, tmpFile, this); + QPixmap pix(tmpFile); + if(!pix.isNull()){ + setBackgroundPix(pix); + } else { + QString msg=i18n("Wasn't able to load wallpaper\n%1"); + msg=msg.arg(tmpFile); + KMessageBox::sorry(this, msg); + } + KIO::NetAccess::removeTempFile(tmpFile); + } + else setBackgroundPix(NULL); + } + setComputerplayer(One, Settings::computerplayer1()); + setComputerplayer(Two, Settings::computerplayer2()); +} + +Tron::~Tron() +{ + if(playfield) + { + delete [] playfield; + } + if(pixmap) + delete pixmap; + delete timer; + +} + +void Tron::createNewPlayfield() +{ + if(playfield) + delete [] playfield; + + if(pixmap) + delete pixmap; + + // field size + fieldWidth=(width()-2*TRON_FRAMESIZE)/rectSize; + fieldHeight=(height()-2*TRON_FRAMESIZE)/rectSize; + + // start positions + playfield=new QMemArray<int>[fieldWidth]; + for(int i=0;i<fieldWidth;i++) + playfield[i].resize(fieldHeight); + + pixmap=new QPixmap(size()); + pixmap->fill(Settings::color_Background()); + + //int min=(fieldWidth<fieldHeight) ? fieldWidth : fieldHeight; + //lookForward=min/4; +} + +void Tron::newGame() +{ + players[0].score=0; + players[1].score=0; + emit gameEnds(Nobody); + reset(); + + QTimer::singleShot(15000,this,SLOT(showBeginHint())); +} + +void Tron::reset() +{ + gamePaused=false; + stopGame(); + + players[0].reset(); + players[1].reset(); + + // If playfield exists, then clean it + // ans set start coordinates + if(playfield) + { + int i; + for(i=0;i<fieldWidth;i++) + playfield[i].fill(BACKGROUND); + + // set start coordinates + + players[0].setCoordinates(fieldWidth/3, fieldHeight/2); + players[1].setCoordinates(2*fieldWidth/3, fieldHeight/2); + + playfield[players[0].xCoordinate][players[0].yCoordinate]= + PLAYER1 | TOP | BOTTOM | LEFT | RIGHT; + playfield[players[1].xCoordinate][players[1].yCoordinate]= + PLAYER2 | TOP | BOTTOM | LEFT | RIGHT; + + updatePixmap(); + update(); + } + + setFocus(); + + emit gameReset(); +} + +void Tron::computerStart() +{ + if(isComputer(Both)) + { + reset(); + startGame(); + } +} + +/* *************************************************************** ** +** ??? functions ** +** *************************************************************** */ + +void Tron::startGame() +{ + gameEnded=false; + beginHint=false; + timer->start(velocity); +} + +void Tron::stopGame() +{ + timer->stop(); + gameEnded=true; + players[0].last_dir = Directions::None; + players[1].last_dir = Directions::None; +} + +void Tron::togglePause() // pause or continue game +{ + if(!gameEnded) + { + if(gamePaused) + { + gamePaused=false; + update(); + timer->start(velocity); + } + else + { + gamePaused=true; + timer->stop(); + update(); + } + } +} + +void Tron::showWinner(Player player) +{ + int i,j; + + if(player != Both && Settings::changeWinnerColor()) + { + int winner; + int loser; + if(player==One) + { + winner=PLAYER1; + loser=PLAYER2; + } + else + { + winner=PLAYER2; + loser=PLAYER1; + } + + for(i=0;i<fieldWidth;i++) + for(j=0;j<fieldHeight;j++) + { + if(playfield[i][j]!=BACKGROUND) + { + // change player + playfield[i][j] |= winner; + playfield[i][j] &= ~loser; + } + } + + updatePixmap(); + } + + repaint(); + + emit gameEnds(player); + + if(isComputer(Both)) + { + QTimer::singleShot(1000,this,SLOT(computerStart())); + } +} + +/* *************************************************************** ** +** paint functions ** +** *************************************************************** */ + +void Tron::updatePixmap() +{ + int i,j; + + if(!bgPix.isNull()) + { + int pw=bgPix.width(); + int ph=bgPix.height(); + for (int x = 0; x <= width(); x+=pw) + for (int y = 0; y <= height(); y+=ph) + bitBlt(pixmap, x, y, &bgPix); + } + else + { + pixmap->fill(Settings::color_Background()); + } + + QPainter p; + p.begin(pixmap); + + // alle Pixel prüfen und evt. zeichnen + for(i=0;i<fieldWidth;i++) + for(j=0;j<fieldHeight;j++) + { + if(playfield[i][j]!=BACKGROUND) + { + drawRect(p,i,j); + } + } + + // draw frame + QColor light=parentWidget()->colorGroup().midlight(); + QColor dark=parentWidget()->colorGroup().mid(); + + p.setPen(NoPen); + p.setBrush(light); + p.drawRect(width()-TRON_FRAMESIZE,0,TRON_FRAMESIZE,height()); + p.drawRect(0,height()-TRON_FRAMESIZE,width(),TRON_FRAMESIZE); + p.setBrush(dark); + p.drawRect(0,0,width(),TRON_FRAMESIZE); + p.drawRect(0,0,TRON_FRAMESIZE,height()); + + p.end(); +} + +// draw new player rects +void Tron::paintPlayers() +{ + QPainter p; + p.begin(this); + drawRect(p,players[0].xCoordinate,players[0].yCoordinate); + drawRect(p,players[1].xCoordinate,players[1].yCoordinate); + p.end(); + + p.begin(pixmap); + drawRect(p,players[0].xCoordinate,players[0].yCoordinate); + drawRect(p,players[1].xCoordinate,players[1].yCoordinate); + p.end(); +} + +void Tron::drawRect(QPainter & p, int x, int y) +{ + int xOffset=x*rectSize+(width()-fieldWidth*rectSize)/2; + int yOffset=y*rectSize+(height()-fieldHeight*rectSize)/2; + + int type=playfield[x][y]; + + // find out which color to draw + QColor toDraw; + int player; + if(type&PLAYER1) // check player bit + { + toDraw=Settings::color_Player1(); + player=0; + } + else if(type&PLAYER2) + { + toDraw=Settings::color_Player2(); + player=1; + } + else + { + kdDebug() << "No player defined in Tron::drawRect(...)" << endl; + return; + } + + switch(Settings::style()) + { + case Settings::EnumStyle::Line: + p.setBrush(toDraw); + p.setPen(toDraw); + p.drawRect(xOffset,yOffset,rectSize,rectSize); + break; + case Settings::EnumStyle::OLine: + { + p.setBrush(toDraw); + p.setPen(toDraw); + p.drawRect(xOffset,yOffset,rectSize,rectSize); + p.setPen(toDraw.light()); + if(type&TOP) + { + p.drawLine(xOffset,yOffset,xOffset+rectSize-1,yOffset); + } + if(type&LEFT) + { + p.drawLine(xOffset,yOffset,xOffset,yOffset+rectSize-1); + } + p.setPen(toDraw.dark()); + if(type&RIGHT) + { + p.drawLine(xOffset+rectSize-1,yOffset,xOffset+rectSize-1,yOffset+rectSize-1); + } + if(type&BOTTOM) + { + p.drawLine(xOffset,yOffset+rectSize-1,xOffset+rectSize-1,yOffset+rectSize-1); + } + + break; + } + case Settings::EnumStyle::Circle: + p.setBrush(toDraw); + p.setPen(toDraw); + p.drawEllipse(xOffset ,yOffset ,rectSize,rectSize); + break; + case Settings::EnumStyle::ORect: + p.setBrush(toDraw); + p.setPen(toDraw.light()); + p.drawRect(xOffset,yOffset,rectSize,rectSize); + p.setPen(toDraw.dark()); + p.drawLine(xOffset,yOffset+rectSize-1,xOffset+rectSize-1 + ,yOffset+rectSize-1); + p.drawLine(xOffset+rectSize-1,yOffset,xOffset+rectSize-1,yOffset+rectSize-1); + break; + } +} + +/* *************************************************************** ** +** config functions ** +** *************************************************************** */ + +void Tron::setActionCollection(KActionCollection *a) +{ + actionCollection = a; +} + +void Tron::setBackgroundPix(QPixmap pix) +{ + bgPix=pix; + + if(pixmap!=0){ + updatePixmap(); + // most pictures have colors, that you can read white text + setPalette(QColor("black")); + } +} + +void Tron::setVelocity(int newVel) // set new velocity +{ + velocity=(10-newVel)*15; + + if(!gameEnded && !gamePaused) + timer->changeInterval(velocity); +} + +void Tron::setComputerplayer(Player player, bool flag) { + if(player==One) + players[0].setComputer(flag); + else if(player==Two) + players[1].setComputer(flag); + + if(isComputer(Both)) + QTimer::singleShot(1000,this,SLOT(computerStart())); +} + +bool Tron::isComputer(Player player) +{ + if(player==One) + return players[0].computer; + else if(player==Two) + return players[1].computer; + else if(player==Both) + { + if(players[0].computer && players[1].computer) + return true; + } + + return false; +} + +/* *************************************************************** ** +** moving functions ** +** *************************************************************** */ + +bool Tron::crashed(int playerNr,int xInc, int yInc) const +{ + bool flag; + int newX=players[playerNr].xCoordinate+xInc; + int newY=players[playerNr].yCoordinate+yInc; + + if(newX<0 || newY <0 || newX>=fieldWidth || newY>=fieldHeight) + flag=true; + else if(playfield[newX][newY] != BACKGROUND) + flag=true; + else flag=false; + + return flag; +} + +void Tron::switchDir(int playerNr,Directions::Direction newDirection) +{ + if(playerNr!=0 && playerNr != 1) + { + kdDebug() << "wrong playerNr" << endl; + return; + } + + if (Settings::oppositeDirCrashes()==false) + { + if (newDirection==Directions::Up && players[playerNr].last_dir==Directions::Down) + return; + if (newDirection==Directions::Down && players[playerNr].last_dir==Directions::Up) + return; + if (newDirection==Directions::Left && players[playerNr].last_dir==Directions::Right) + return; + if (newDirection==Directions::Right && players[playerNr].last_dir==Directions::Left) + return; + } + + players[playerNr].dir=newDirection; +} + +void Tron::updateDirections(int playerNr) +{ + if(playerNr==-1 || playerNr==0) + { + int x=players[0].xCoordinate; + int y=players[0].yCoordinate; + + // necessary for drawing the 3d-line + switch(players[0].dir) + { + // unset drawing flags in the moving direction + case Directions::Up: + { + playfield[x][y] &= (~TOP); + break; + } + case Directions::Down: + playfield[x][y] &= (~BOTTOM); + break; + case Directions::Right: + playfield[x][y] &= (~RIGHT); + break; + case Directions::Left: + playfield[x][y] &= (~LEFT); + break; + default: + break; + } + players[0].last_dir = players[0].dir; + + } + if(playerNr==-1 || playerNr==1) + { + int x=players[1].xCoordinate; + int y=players[1].yCoordinate; + + // necessary for drawing the 3d-line + switch(players[1].dir) + { + // unset drawing flags in the moving direction + case Directions::Up: + { + playfield[x][y] &= (~TOP); + break; + } + case Directions::Down: + playfield[x][y] &= (~BOTTOM); + break; + case Directions::Right: + playfield[x][y] &= (~RIGHT); + break; + case Directions::Left: + playfield[x][y] &= (~LEFT); + break; + default: + break; + } + players[1].last_dir = players[1].dir; + + } + + paintPlayers(); +} + +/* *************************************************************** ** +** Events ** +** *************************************************************** */ + +void Tron::paintEvent(QPaintEvent *e) +{ + bitBlt(this,e->rect().topLeft(),pixmap,e->rect()); + + // if game is paused, print message + if(gamePaused) + { + QString message=i18n("Game paused"); + QPainter p(this); + QFontMetrics fm=p.fontMetrics(); + int w=fm.width(message); + p.drawText(width()/2-w/2,height()/2,message); + } + + // If game ended, print "Crash!" + else if(gameEnded) + { + QString message=i18n("Crash!"); + QPainter p(this); + int w=p.fontMetrics().width(message); + int h=p.fontMetrics().height(); + for(int i=0;i<2;i++) + { + if(!players[i].alive) + { + int x=players[i].xCoordinate*rectSize; + int y=players[i].yCoordinate*rectSize; + while(x<0) x+=rectSize; + while(x+w>width()) x-=rectSize; + while(y-h<0) y+=rectSize; + while(y>height()) y-=rectSize; + p.drawText(x,y,message); + } + } + + // draw begin hint + if(beginHint) + { + QString hint=i18n("Press any of your direction keys to start!"); + int x=p.fontMetrics().width(hint); + x=(width()-x)/2; + int y=height()/2; + + p.drawText(x,y,hint); + } + } +} + +void Tron::resizeEvent(QResizeEvent *) +{ + createNewPlayfield(); + reset(); +} + +void Tron::keyPressEvent(QKeyEvent *e) +{ + KKey key(e); + if(!players[1].computer) + { + if(actionCollection->action("Pl2Up")->shortcut().contains(key)) + { + switchDir(1,Directions::Up); + players[1].keyPressed=true; + } + else if(actionCollection->action("Pl2Left")->shortcut().contains(key)) + { + switchDir(1,Directions::Left); + players[1].keyPressed=true; + } + else if(actionCollection->action("Pl2Right")->shortcut().contains(key)) + { + switchDir(1,Directions::Right); + players[1].keyPressed=true; + } + else if(actionCollection->action("Pl2Down")->shortcut().contains(key)) + { + switchDir(1,Directions::Down); + players[1].keyPressed=true; + } + else if(actionCollection->action("Pl2Ac")->shortcut().contains(key)) + { + if(!Settings::acceleratorBlocked()) + players[1].accelerated=true; + + } + } + + if(!players[0].computer) + { + if(actionCollection->action("Pl1Left")->shortcut().contains(key)) + { + switchDir(0,Directions::Left); + players[0].keyPressed=true; + } + else if(actionCollection->action("Pl1Right")->shortcut().contains(key)) + { + switchDir(0,Directions::Right); + players[0].keyPressed=true; + } + else if(actionCollection->action("Pl1Up")->shortcut().contains(key)) + { + switchDir(0,Directions::Up); + players[0].keyPressed=true; + } + else if(actionCollection->action("Pl1Down")->shortcut().contains(key)) + { + switchDir(0,Directions::Down); + players[0].keyPressed=true; + } + else if(actionCollection->action("Pl1Ac")->shortcut().contains(key)) + { + if(!Settings::acceleratorBlocked()) + players[0].accelerated=true; + } + } + + e->ignore(); // if key is unknown: ignore + + // if both players press keys at the same time, start game... + if(gameEnded && !gameBlocked) + { + if(players[0].keyPressed && players[1].keyPressed) + { + reset(); + startGame(); + } + } + // ...or continue + else if(gamePaused) + { + if(players[0].keyPressed && players[1].keyPressed) + { + togglePause(); + } + } +} + +void Tron::keyReleaseEvent(QKeyEvent * e) +{ + KKey key(e); + + if(!players[1].computer) + { + if(actionCollection->action("Pl2Ac")->shortcut().contains(key)) + { + players[1].accelerated=false; + return; + } + else if(actionCollection->action("Pl2Left")->shortcut().contains(key)) + { + players[1].keyPressed=false; + return; + } + else if(actionCollection->action("Pl2Right")->shortcut().contains(key)) + { + players[1].keyPressed=false; + return; + } + else if(actionCollection->action("Pl2Up")->shortcut().contains(key)) + { + players[1].keyPressed=false; + return; + } + else if(actionCollection->action("Pl2Down")->shortcut().contains(key)) + { + players[1].keyPressed=false; + return; + } + } + + if(!players[0].computer) + { + if(actionCollection->action("Pl1Left")->shortcut().contains(key)) + { + players[0].keyPressed=false; + return; + } + else if(actionCollection->action("Pl1Right")->shortcut().contains(key)) + { + players[0].keyPressed=false; + return; + } + else if(actionCollection->action("Pl1Up")->shortcut().contains(key)) + { + players[0].keyPressed=false; + return; + } + else if(actionCollection->action("Pl1Down")->shortcut().contains(key)) + { + players[0].keyPressed=false; + return; + } + else if(actionCollection->action("Pl1Ac")->shortcut().contains(key)) + { + players[0].accelerated=false; + return; + } + } + + e->ignore(); // if pressed key is unknown, ignore it + +} + +// if playingfield loses keyboard focus, pause game +void Tron::focusOutEvent(QFocusEvent *) +{ + if(!gameEnded && !gamePaused) + { + togglePause(); + } +} + +/* *************************************************************** ** +** slots ** +** *************************************************************** */ + +void Tron::unblockGame() +{ + gameBlocked=false; +} + +void Tron::showBeginHint() +{ + if(gameEnded) + { + // show only at the beginning of a game + if(players[0].score==0 && players[1].score==0) + { + beginHint=true; + repaint(); + } + } +} + +// doMove() is called from QTimer +void Tron::doMove() +{ + int i; + for(i=0;i<2;i++) + { + // Überprüfen, ob Acceleratortaste gedrückt wurde... + if(players[i].accelerated) + { + updateDirections(i); + + int newType; // determine type of rect to set + if(i==0) + { + newType=PLAYER1; + } + else + { + newType=PLAYER2; + } + switch(players[i].dir) + { + case Directions::Up: + if(crashed(i,0,-1)) + players[i].alive=false; + else + { + players[i].yCoordinate--; + newType|=(TOP | LEFT | RIGHT); + } + break; + case Directions::Down: + if(crashed(i,0,1)) + players[i].alive=false; + else + { + players[i].yCoordinate++; + newType |= (BOTTOM | LEFT | RIGHT); + } + break; + case Directions::Left: + if(crashed(i,-1,0)) + players[i].alive=false; + else + { + players[i].xCoordinate--; + newType |= (LEFT | TOP | BOTTOM); + } + break; + case Directions::Right: + if(crashed(i,1,0)) + players[i].alive=false; + else + { + players[i].xCoordinate++; + newType |= (RIGHT | TOP | BOTTOM); + } + break; + default: + break; + } + if(players[i].alive) + playfield[players[i].xCoordinate][players[i].yCoordinate]=newType; + } + } + + if(players[0].accelerated || players[1].accelerated) + { + /* player collision check */ + if(!players[1].alive) + { + int xInc=0,yInc=0; + switch(players[1].dir) + { + case Directions::Left: + xInc = -1; + break; + case Directions::Right: + xInc = 1; + break; + case Directions::Up: + yInc = -1; + break; + case Directions::Down: + yInc = 1; + break; + default: + break; + } + if ((players[1].xCoordinate+xInc) == players[0].xCoordinate) + if ((players[1].yCoordinate+yInc) == players[0].yCoordinate) + { + players[0].alive=false; + } + } + + paintPlayers(); + + // crashtest + if(!players[0].alive && !players[1].alive) + { + stopGame(); + players[0].score++; + players[1].score++; + showWinner(Both); + } + else + { + for(i=0;i<2;i++) + { + if(!players[i].alive) + { + stopGame(); + showWinner((i==0)? Two:One); + players[i].score++; + } + } + } + + + if(gameEnded) + { + //this is for waiting 0,5s before starting next game + gameBlocked=true; + QTimer::singleShot(1000,this,SLOT(unblockGame())); + return; + } + } + + // neue Spielerstandorte festlegen + for(i=0;i<2;i++) + { + if(players[i].computer) + think(i); + } + + updateDirections(); + + for(i=0;i<2;i++) + { + int newType; + if(i==0) + newType=PLAYER1; + else + newType=PLAYER2; + + switch(players[i].dir) + { + case Directions::Up: + if(crashed(i,0,-1)) + players[i].alive=false; + else + { + players[i].yCoordinate--; + newType |= (TOP | RIGHT | LEFT); + } + break; + case Directions::Down: + if(crashed(i,0,1)) + players[i].alive=false; + else + { + players[i].yCoordinate++; + newType |= (BOTTOM | RIGHT | LEFT); + } + break; + case Directions::Left: + if(crashed(i,-1,0)) + players[i].alive=false; + else + { + players[i].xCoordinate--; + newType |= (LEFT | TOP | BOTTOM); + } + break; + case Directions::Right: + if(crashed(i,1,0)) + players[i].alive=false; + else + { + players[i].xCoordinate++; + newType |= (RIGHT | TOP | BOTTOM); + } + break; + default: + break; + + } + if(players[i].alive) + playfield[players[i].xCoordinate][players[i].yCoordinate]=newType; + } + + /* player collision check */ + if(!players[1].alive) + { + int xInc=0,yInc=0; + switch(players[1].dir) + { + case Directions::Left: + xInc = -1; break; + case Directions::Right: + xInc = 1; break; + case Directions::Up: + yInc = -1; break; + case Directions::Down: + yInc = 1; break; + default: + break; + } + if ((players[1].xCoordinate+xInc) == players[0].xCoordinate) + if ((players[1].yCoordinate+yInc) == players[0].yCoordinate) + { + players[0].alive=false; + } + } + + paintPlayers(); + + if(!players[0].alive && !players[1].alive) + { + stopGame(); + players[0].score++; + players[1].score++; + showWinner(Both); + } + else + for(i=0;i<2;i++) + { + // crashtests + if(!players[i].alive) + { + stopGame(); + showWinner((i==0)? Two:One); + players[i].score++; + } + } + + if(gameEnded) + { + //this is for waiting 1s before starting next game + gameBlocked=true; + QTimer::singleShot(1000,this,SLOT(unblockGame())); + } + +} + +/* *************************************************************** ** +** algoritm for the computerplayer ** +** *************************************************************** */ + +// This part is partly ported from +// xtron-1.1 by Rhett D. Jacobs <rhett@hotel.canberra.edu.au> +void Tron::think(int playerNr) +{ +if(Settings::skill() != Settings::EnumSkill::Easy) +{ + int opponent=(playerNr==1)? 0 : 1; + + // determines left and right side + Directions::Direction sides[2]; + // increments for moving to the different sides + int flags[6]={0,0,0,0,0,0}; + int index[2]; + // distances to barrier + int dis_forward, dis_left, dis_right; + + dis_forward = dis_left = dis_right = 1; + + + switch (players[playerNr].dir) + { + case Directions::Left: + //forward flags + flags[0] = -1; + flags[1] = 0; + + //left flags + flags[2] = 0; + flags[3] = 1; + + // right flags + flags[4] = 0; + flags[5] = -1; + + //turns to either side + sides[0] = Directions::Down; + sides[1] = Directions::Up; + break; + case Directions::Right: + flags[0] = 1; + flags[1] = 0; + flags[2] = 0; + flags[3] = -1; + flags[4] = 0; + flags[5] = 1; + sides[0] = Directions::Up; + sides[1] = Directions::Down; + break; + case Directions::Up: + flags[0] = 0; + flags[1] = -1; + flags[2] = -1; + flags[3] = 0; + flags[4] = 1; + flags[5] = 0; + sides[0] = Directions::Left; + sides[1] = Directions::Right; + break; + case Directions::Down: + flags[0] = 0; + flags[1] = 1; + flags[2] = 1; + flags[3] = 0; + flags[4] = -1; + flags[5] = 0; + sides[0] = Directions::Right; + sides[1] = Directions::Left; + break; + default: + break; + + } + + // check forward + index[0] = players[playerNr].xCoordinate+flags[0]; + index[1] = players[playerNr].yCoordinate+flags[1]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) + { + dis_forward++; + index[0] += flags[0]; + index[1] += flags[1]; + } + + // check left + index[0] = players[playerNr].xCoordinate+flags[2]; + index[1] = players[playerNr].yCoordinate+flags[3]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) { + dis_left++; + index[0] += flags[2]; + index[1] += flags[3]; + } + + // check right + index[0] = players[playerNr].xCoordinate+flags[4]; + index[1] = players[playerNr].yCoordinate+flags[5]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) { + dis_right++; + index[0] += flags[4]; + index[1] += flags[5]; + } + + // distances to opponent + int hor_dis=0; // negative is opponent to the right + int vert_dis=0; // negative is opponent to the bottom + hor_dis=players[playerNr].xCoordinate-players[opponent].xCoordinate; + vert_dis=players[playerNr].yCoordinate-players[opponent].yCoordinate; + + int opForwardDis=0; // negative is to the back + int opSideDis=0; // negative is to the left + bool opMovesOppositeDir=false; + bool opMovesSameDir=false; + bool opMovesRight=false; + bool opMovesLeft=false; + + switch(players[playerNr].dir) + { + case Directions::Up: + opForwardDis=vert_dis; + opSideDis=-hor_dis; + if(players[opponent].dir==Directions::Down) + opMovesOppositeDir=true; + else if(players[opponent].dir==Directions::Up) + opMovesSameDir=true; + else if(players[opponent].dir==Directions::Left) + opMovesLeft=true; + else if(players[opponent].dir==Directions::Right) + opMovesRight=true; + break; + case Directions::Down: + opForwardDis=-vert_dis; + opSideDis=hor_dis; + if(players[opponent].dir==Directions::Up) + opMovesOppositeDir=true; + else if(players[opponent].dir==Directions::Down) + opMovesSameDir=true; + else if(players[opponent].dir==Directions::Left) + opMovesRight=true; + else if(players[opponent].dir==Directions::Right) + opMovesLeft=true; + break; + case Directions::Left: + opForwardDis=hor_dis; + opSideDis=vert_dis; + if(players[opponent].dir==Directions::Right) + opMovesOppositeDir=true; + else if(players[opponent].dir==Directions::Left) + opMovesSameDir=true; + else if(players[opponent].dir==Directions::Down) + opMovesLeft=true; + else if(players[opponent].dir==Directions::Up) + opMovesRight=true; + break; + case Directions::Right: + opForwardDis=-hor_dis; + opSideDis=-vert_dis; + if(players[opponent].dir==Directions::Left) + opMovesOppositeDir=true; + else if(players[opponent].dir==Directions::Right) + opMovesSameDir=true; + else if(players[opponent].dir==Directions::Up) + opMovesLeft=true; + else if(players[opponent].dir==Directions::Down) + opMovesRight=true; + break; + default: + break; + + } + + int doPercentage = 100; + switch(Settings::skill()) + { + case Settings::EnumSkill::Easy: + // Never reached + break; + + case Settings::EnumSkill::Medium: + doPercentage=5; + break; + + case Settings::EnumSkill::Hard: + doPercentage=90; + break; + } + + // if opponent moves the opposite direction as we + if(opMovesOppositeDir) + { + // if opponent is in front + if(opForwardDis>0) + { + // opponent is to the right and we have the chance to block the way + if(opSideDis>0 && opSideDis < opForwardDis && opSideDis < dis_right && opForwardDis < lookForward) + { + if ((int)random.getLong(100) <= doPercentage || dis_forward==1) + switchDir(playerNr,sides[1]); // turn right + } + // opponent is to the left and we have the chance to block the way + else if(opSideDis<0 && -opSideDis < opForwardDis && -opSideDis < dis_left && opForwardDis < lookForward) + { + if ((int)random.getLong(100) <= doPercentage || dis_forward==1) + switchDir(playerNr,sides[0]); // turn left + } + // if we can do nothing, go forward + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // opponent is in back of us and moves away: do nothing + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } // end if(opMovesOppositeDir) + + else if(opMovesSameDir) + { + // if opponent is to the back + if(opForwardDis < 0) + { + // opponent is to the right and we have the chance to block the way + if(opSideDis>0 && opSideDis < -opForwardDis && opSideDis < dis_right) + { + if ((int)random.getLong(100) <= doPercentage || dis_forward==1) + switchDir(playerNr,sides[1]); // turn right + } + // opponent is to the left and we have the chance to block the way + else if(opSideDis<0 && -opSideDis < -opForwardDis && -opSideDis < dis_left) + { + if ((int)random.getLong(100) <= doPercentage || dis_forward==1) + switchDir(playerNr,sides[0]); // turn left + } + // if we can do nothing, go forward + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // opponent is in front of us and moves away + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } // end if(opMovesSameDir) + + else if(opMovesRight) + { + // opponent is in front of us + if(opForwardDis>0) + { + // opponent is to the left + if(opSideDis < 0 && -opSideDis < opForwardDis && -opSideDis < dis_left) + { + if(opForwardDis < lookForward && dis_left > lookForward) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + changeDirection(playerNr,dis_right,dis_left); + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // op is to the right and moves away, but maybe we can block him + else if(opSideDis>=0 && opSideDis < dis_right) + { + if(opForwardDis < lookForward && dis_right>lookForward) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + switchDir(playerNr,sides[1]); // turn right + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // opponent is in the back of us + else + { + // opponent is right from us and we already blocked him + if(opSideDis>0 && opForwardDis < lookForward && opSideDis < dis_right) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + changeDirection(playerNr,dis_right,dis_left); + } + else if(dis_forward<lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + } // end if(opMovesRight) + + else if(opMovesLeft) + { + // opponent is in front of us + if(opForwardDis>0) + { + // opponent is to the right, moves towards us and could block us + if(opSideDis > 0 && opSideDis < opForwardDis && opSideDis < dis_right) + { + if(opForwardDis < lookForward && dis_right>lookForward) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + changeDirection(playerNr,dis_right,dis_left); + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // op is to the left and moves away, but maybe we can block him + else if(opSideDis<=0 && opSideDis < dis_left) + { + if(opForwardDis < lookForward && dis_left>lookForward) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + switchDir(playerNr,sides[0]); // turn left + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + + } + else if(dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + // opponent is in the back of us + else //if(opForwardDis<=0) + { + // opponent is left from us and we already blocked him + if(opSideDis<0 && opForwardDis < lookForward && -opSideDis < dis_left) + { + if ((int)random.getLong(100) <= doPercentage/2 || dis_forward==1) + changeDirection(playerNr,dis_right,dis_left); + } + else if(dis_forward<lookForward) + { + dis_forward = 100 - 100/dis_forward; + + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 1) + changeDirection(playerNr,dis_right,dis_left); + } + } + } // end if(opMovesLeft) + +} +// This part is completely ported from +// xtron-1.1 by Rhett D. Jacobs <rhett@hotel.canberra.edu.au> +else // Settings::skill() == Settings::EnumSkill::Easy +{ + Directions::Direction sides[2]; + int flags[6] = {0,0,0,0,0,0}; + int index[2]; + int dis_forward, dis_left, dis_right; + + dis_forward = dis_left = dis_right = 1; + + switch (players[playerNr].dir) { + case Directions::Left: + + //forward flags + flags[0] = -1; + flags[1] = 0; + + //left flags + flags[2] = 0; + flags[3] = 1; + + // right flags + flags[4] = 0; + flags[5] = -1; + + //turns to either side + sides[0] = Directions::Down; + sides[1] = Directions::Up; + break; + case Directions::Right: + flags[0] = 1; + flags[1] = 0; + flags[2] = 0; + flags[3] = -1; + flags[4] = 0; + flags[5] = 1; + sides[0] = Directions::Up; + sides[1] = Directions::Down; + break; + case Directions::Up: + flags[0] = 0; + flags[1] = -1; + flags[2] = -1; + flags[3] = 0; + flags[4] = 1; + flags[5] = 0; + sides[0] = Directions::Left; + sides[1] = Directions::Right; + break; + case Directions::Down: + flags[0] = 0; + flags[1] = 1; + flags[2] = 1; + flags[3] = 0; + flags[4] = -1; + flags[5] = 0; + sides[0] = Directions::Right; + sides[1] = Directions::Left; + break; + default: + break; + } + + // check forward + index[0] = players[playerNr].xCoordinate+flags[0]; + index[1] = players[playerNr].yCoordinate+flags[1]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) { + dis_forward++; + index[0] += flags[0]; + index[1] += flags[1]; + } + + if (dis_forward < lookForward) + { + dis_forward = 100 - 100/dis_forward; + + // check left + index[0] = players[playerNr].xCoordinate+flags[2]; + index[1] = players[playerNr].yCoordinate+flags[3]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) { + dis_left++; + index[0] += flags[2]; + index[1] += flags[3]; + } + + // check right + index[0] = players[playerNr].xCoordinate+flags[4]; + index[1] = players[playerNr].yCoordinate+flags[5]; + while (index[0] < fieldWidth && index[0] >= 0 && + index[1] < fieldHeight && index[1] >= 0 && + playfield[index[0]][index[1]] == BACKGROUND) { + dis_right++; + index[0] += flags[4]; + index[1] += flags[5]; + } + if(!(dis_left == 1 && dis_right == 1)) + if ((int)random.getLong(100) >= dis_forward || dis_forward == 0) { + + // change direction + if ((int)random.getLong(100) <= (100*dis_left)/(dis_left+dis_right)) + if (dis_left != 1) + + // turn to the left + switchDir(playerNr,sides[0]); + else + + // turn to the right + switchDir(playerNr,sides[1]); + else + if (dis_right != 1) + + // turn to the right + switchDir(playerNr,sides[1]); + else + + // turn to the left + switchDir(playerNr,sides[0]); + } + } + } +} + +void Tron::changeDirection(int playerNr,int dis_right,int dis_left) +{ + Directions::Direction currentDir=players[playerNr].dir; + Directions::Direction sides[2]; + switch (currentDir) + { + case Directions::Left: + //turns to either side + sides[0] = Directions::Down; + sides[1] = Directions::Up; + break; + case Directions::Right: + sides[0] = Directions::Up; + sides[1] = Directions::Down; + break; + case Directions::Up: + sides[0] = Directions::Left; + sides[1] = Directions::Right; + break; + case Directions::Down: + sides[0] = Directions::Right; + sides[1] = Directions::Left; + break; + default: + break; + + } + + if(!(dis_left == 1 && dis_right == 1)) + { + // change direction + if ((int)random.getLong(100) <= (100*dis_left)/(dis_left+dis_right)) + { + if (dis_left != 1) + // turn to the left + switchDir(playerNr,sides[0]); + else + // turn to the right + switchDir(playerNr,sides[1]); + } + else + { + if (dis_right != 1) + // turn to the right + switchDir(playerNr,sides[1]); + else + // turn to the left + switchDir(playerNr,sides[0]); + } + } +} + +#include "tron.moc" + diff --git a/ktron/tron.h b/ktron/tron.h new file mode 100644 index 00000000..ebfc1d56 --- /dev/null +++ b/ktron/tron.h @@ -0,0 +1,178 @@ +/* ******************************************************************************** + This file is part of the game 'KTron' + + Copyright (C) 1998-2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + *******************************************************************************/ + +#ifndef TRON_H +#define TRON_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <math.h> +#include <krandomsequence.h> + +class KActionCollection; + +#include "player.h" + +enum Player{One,Two,Both,Nobody}; +// Bits that defines the rect and which sides to draw +enum {BACKGROUND=0, PLAYER1=1,PLAYER2=2,TOP=4,BOTTOM=8,LEFT=16,RIGHT=32}; + +/** +* @short The playingfield +*/ +class Tron : public QWidget +{ + Q_OBJECT + +public: + Tron(QWidget *parent=0, const char *name=0); + ~Tron(); + void setActionCollection(KActionCollection*); + void updatePixmap(); + void setBackgroundPix(QPixmap); + void setComputerplayer(Player player, bool); + bool isComputer(Player player); + void setVelocity(int); + void setRectSize(int newSize); + +public slots: + /** Starts a new game. The difference to reset is, that the players + * points are set to zero. Emits gameEnds(Nobody). + */ + void newGame(); + void togglePause(); + + /** + * checks if both players are computer and starts the game + */ + void computerStart(); + + void loadSettings(); + +signals: + void gameEnds(Player loser); + void gameReset(); + +protected: + /** bitBlt´s the rect that has to be updated from the + * bufferpixmap on the screen and writes eventually text + */ + void paintEvent(QPaintEvent *); + /** resets game and creates a new playingfield */ + void resizeEvent(QResizeEvent *); + void keyPressEvent(QKeyEvent *); + void keyReleaseEvent(QKeyEvent *); + /** pauses game */ + void focusOutEvent(QFocusEvent *); + +private: + /** Stores key shortcuts */ + KActionCollection* actionCollection; + /** Drawing buffer */ + QPixmap *pixmap; + /** The playingfield */ + QMemArray<int> *playfield; + /** game status flag */ + bool gamePaused; + /** game status flag */ + bool gameEnded; + /** used for waiting after game ended */ + bool gameBlocked; + /** flag, if a string should be drawn, how to start the game */ + bool beginHint; + /** Height of the playingfield in number of rects*/ + int fieldHeight; + /** Width of the playingfield in number of rects*/ + int fieldWidth; + QTimer *timer; + player players[2]; + + /** Backgroundpixmap **/ + QPixmap bgPix; + + /** time in ms between two moves */ + int velocity; + /** size of the rects */ + int rectSize; + + /** The random sequence generator **/ + KRandomSequence random; + + // Options + /** determines level of computerplayer */ + int lookForward; + + // Funktionen + /** resets the game */ + void reset(); + /** starts the game timer */ + void startGame(); + /** stops the game timer */ + void stopGame(); + /** creates a new playfield and a bufferpixmap */ + void createNewPlayfield(); + /** paints players at current player coordinates */ + void paintPlayers(); + /** draws a rect in current TronStyle at position x,y of the playingfield */ + void drawRect(QPainter & p, int x, int y); + /** emits gameEnds(Player) and displays the winner by changing color*/ + void showWinner(Player winner); + + /** calculates if player playerNr would crash + * if he moves xInc in x-direction and yInc in y-direction + */ + bool crashed(int playerNr,int xInc, int yInc) const; + /** calculates if player playerNr should change direction */ + void think(int playerNr); + void changeDirection(int playerNr,int dis_right,int dis_left); + + /** sets the direction of player playerNr to newDirection */ + void switchDir(int playerNr,Directions::Direction newDirection); + /** + * updates the the rect at current position to not draw a + * border in the direction of the next step. + * (only used in mode OLine) + * + * -1 means update both players + */ + void updateDirections(int playerNr=-1); + +private slots: + /** + * This is the main function of KTron. + * It checkes if an accelerator is pressed and than moves this player + * forward. Then it checkes if a crash occurred. + * If no crash happen it moves both players forward and checks again + * if someone crashed. + */ + void doMove(); + void unblockGame(); + void showBeginHint(); +}; + + +#endif // TRON_H + diff --git a/ktron/version.h b/ktron/version.h new file mode 100644 index 00000000..71fdda43 --- /dev/null +++ b/ktron/version.h @@ -0,0 +1 @@ +#define KTRON_VERSION "1.1" |