|
|
/****************************************************************************
|
|
|
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 <tqtimer.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(TQWidget *tqparent,const char *name)
|
|
|
: TQWidget(tqparent,name)
|
|
|
{
|
|
|
pixmap=0;
|
|
|
playfield=0;
|
|
|
beginHint=false;
|
|
|
lookForward=15;
|
|
|
|
|
|
random.setSeed(0);
|
|
|
|
|
|
setFocusPolicy(TQ_StrongFocus);
|
|
|
setBackgroundMode(NoBackground);
|
|
|
|
|
|
gameBlocked=false;
|
|
|
rectSize=10;
|
|
|
|
|
|
timer = new TQTimer(this,"timer");
|
|
|
loadSettings();
|
|
|
connect(timer, TQT_SIGNAL(timeout()), TQT_SLOT(doMove()));
|
|
|
TQTimer::singleShot(15000, this,TQT_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();
|
|
|
tqrepaint();
|
|
|
}
|
|
|
|
|
|
// Backgroundimage
|
|
|
setBackgroundPix(NULL);
|
|
|
if(Settings::backgroundImageChoice()){
|
|
|
KURL url ( Settings::backgroundImage() );
|
|
|
if(!url.isEmpty()){
|
|
|
TQString tmpFile;
|
|
|
KIO::NetAccess::download(url, tmpFile, this);
|
|
|
TQPixmap pix(tmpFile);
|
|
|
if(!pix.isNull()){
|
|
|
setBackgroundPix(pix);
|
|
|
} else {
|
|
|
TQString msg=i18n("Wasn't able to load wallpaper\n%1");
|
|
|
msg=msg.tqarg(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 TQMemArray<int>[fieldWidth];
|
|
|
for(int i=0;i<fieldWidth;i++)
|
|
|
playfield[i].resize(fieldHeight);
|
|
|
|
|
|
pixmap=new TQPixmap(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();
|
|
|
|
|
|
TQTimer::singleShot(15000,this,TQT_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();
|
|
|
}
|
|
|
|
|
|
tqrepaint();
|
|
|
|
|
|
emit gameEnds(player);
|
|
|
|
|
|
if(isComputer(Both))
|
|
|
{
|
|
|
TQTimer::singleShot(1000,this,TQT_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());
|
|
|
}
|
|
|
|
|
|
TQPainter p;
|
|
|
p.begin(pixmap);
|
|
|
|
|
|
// alle Pixel pr<70>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
|
|
|
TQColor light=tqparentWidget()->tqcolorGroup().midlight();
|
|
|
TQColor dark=tqparentWidget()->tqcolorGroup().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()
|
|
|
{
|
|
|
TQPainter 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(TQPainter & 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
|
|
|
TQColor 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(TQPixmap pix)
|
|
|
{
|
|
|
bgPix=pix;
|
|
|
|
|
|
if(pixmap!=0){
|
|
|
updatePixmap();
|
|
|
// most pictures have colors, that you can read white text
|
|
|
setPalette(TQColor("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))
|
|
|
TQTimer::singleShot(1000,this,TQT_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(TQPaintEvent *e)
|
|
|
{
|
|
|
bitBlt(this,e->rect().topLeft(),pixmap,e->rect());
|
|
|
|
|
|
// if game is paused, print message
|
|
|
if(gamePaused)
|
|
|
{
|
|
|
TQString message=i18n("Game paused");
|
|
|
TQPainter p(this);
|
|
|
TQFontMetrics 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)
|
|
|
{
|
|
|
TQString message=i18n("Crash!");
|
|
|
TQPainter 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)
|
|
|
{
|
|
|
TQString 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(TQResizeEvent *)
|
|
|
{
|
|
|
createNewPlayfield();
|
|
|
reset();
|
|
|
}
|
|
|
|
|
|
void Tron::keyPressEvent(TQKeyEvent *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(TQKeyEvent * 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(TQFocusEvent *)
|
|
|
{
|
|
|
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;
|
|
|
tqrepaint();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// doMove() is called from TQTimer
|
|
|
void Tron::doMove()
|
|
|
{
|
|
|
int i;
|
|
|
for(i=0;i<2;i++)
|
|
|
{
|
|
|
// <20>berpr<70>fen, ob Acceleratortaste gedr<64>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;
|
|
|
TQTimer::singleShot(1000,this,TQT_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;
|
|
|
TQTimer::singleShot(1000,this,TQT_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"
|
|
|
|