/**************************************************************************** This file is part of the game 'KTron' Copyright (C) 1998-2000 by Matthias Kiefer 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 #include // Normal class #include #include #include #include #include #include #include #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[fieldWidth]; for(int i=0;ifill(Settings::color_Background()); //int min=(fieldWidthstart(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;ifill(Settings::color_Background()); } QPainter p; p.begin(pixmap); // alle Pixel prüfen und evt. zeichnen for(i=0;icolorGroup().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 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= 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= 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 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"