You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1028 lines
24 KiB
1028 lines
24 KiB
/* Implementation of class BoardWidget
|
|
*
|
|
* This class handles rendering of a Board to a KDE/QT widget,
|
|
* shows moves (with a timer) and manages input of moves
|
|
*
|
|
* Josef Weidendorfer, 9/97
|
|
*/
|
|
|
|
#include <qbitmap.h>
|
|
#include <qpainter.h>
|
|
#include <qcursor.h>
|
|
|
|
#include <klocale.h>
|
|
#include <kdebug.h>
|
|
|
|
#ifdef HAVE_KIR
|
|
#include <kimgrender.h>
|
|
#endif
|
|
|
|
#include "Board.h"
|
|
#include "BoardWidget.h"
|
|
|
|
/* Cursors */
|
|
#include "bitmaps/Arrow1"
|
|
#include "bitmaps/Arrow1Mask"
|
|
#include "bitmaps/Arrow2"
|
|
#include "bitmaps/Arrow2Mask"
|
|
#include "bitmaps/Arrow3"
|
|
#include "bitmaps/Arrow3Mask"
|
|
#include "bitmaps/Arrow4"
|
|
#include "bitmaps/Arrow4Mask"
|
|
#include "bitmaps/Arrow5"
|
|
#include "bitmaps/Arrow5Mask"
|
|
#include "bitmaps/Arrow6"
|
|
#include "bitmaps/Arrow6Mask"
|
|
|
|
BoardWidget::BoardWidget(Board& b, QWidget *parent, const char *name)
|
|
: BallWidget(10,9,parent, name), board(b)
|
|
{
|
|
pList =0;
|
|
gettingMove = false;
|
|
editMode = false;
|
|
renderMode = false;
|
|
|
|
#ifdef HAVE_KIR
|
|
m_backRenderer = KIRManager::attach( this, "Background" );
|
|
connect( m_backRenderer, SIGNAL(rendered()),
|
|
this, SLOT(drawBoard()) );
|
|
#endif
|
|
|
|
/* setup cursors */
|
|
|
|
#define createCursor(bitmap,name) \
|
|
static QBitmap bitmap(bitmap##_width, bitmap##_height, \
|
|
(unsigned char *) bitmap##_bits, TRUE); \
|
|
static QBitmap bitmap##Mask(bitmap##Mask_width, bitmap##Mask_height, \
|
|
(unsigned char *) bitmap##Mask_bits, TRUE); \
|
|
name = new QCursor(bitmap, bitmap##Mask, bitmap##_x_hot, bitmap##_y_hot);
|
|
|
|
createCursor(Arrow1, arrow[1]);
|
|
createCursor(Arrow2, arrow[2]);
|
|
createCursor(Arrow3, arrow[3]);
|
|
createCursor(Arrow4, arrow[4]);
|
|
createCursor(Arrow5, arrow[5]);
|
|
createCursor(Arrow6, arrow[6]);
|
|
|
|
setCursor(crossCursor);
|
|
|
|
// boardColor = new QColor("lightblue");
|
|
boardColor = new QColor(backgroundColor());
|
|
redColor = new QColor("red2");
|
|
yellowColor = new QColor("yellow2");
|
|
redHColor = new QColor("orange");
|
|
yellowHColor = new QColor("green");
|
|
|
|
initBalls();
|
|
|
|
updatePosition();
|
|
}
|
|
|
|
BoardWidget::~BoardWidget()
|
|
{
|
|
for(int i=1; i<7; i++)
|
|
if (arrow[i] != 0)
|
|
delete arrow[i];
|
|
|
|
#ifdef HAVE_KIR
|
|
if (m_backRenderer != 0)
|
|
delete m_backRenderer;
|
|
#endif
|
|
delete boardColor;
|
|
delete redColor;
|
|
delete yellowColor;
|
|
delete redHColor;
|
|
delete yellowHColor;
|
|
|
|
}
|
|
|
|
void BoardWidget::configure()
|
|
{
|
|
#ifdef HAVE_KIR
|
|
if (m_backRenderer != 0) {
|
|
m_backRenderer->setup();
|
|
m_backRenderer->manager()->saveModules();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void BoardWidget::createPos(int pos, int i, int j, Ball* b)
|
|
{
|
|
int x=(465*(2*(i)-(j))/9);
|
|
int y=(500*19*(j)/100);
|
|
createBallPosition(pos, x,y, b);
|
|
}
|
|
|
|
void BoardWidget::initBalls()
|
|
{
|
|
n2 = new Ball( *yellowColor );
|
|
h2 = new Ball( *yellowHColor );
|
|
d2 = new Ball( *yellowHColor, 3.14/2 );
|
|
|
|
n1 = new Ball( *redColor );
|
|
h1 = new Ball( *redHColor );
|
|
d1 = new Ball( *redHColor, 3.14/2 );
|
|
|
|
// e = new Ball( white,0,0 );
|
|
// e->setSpecials(.6,.85,.75);
|
|
|
|
createBlending(1,10,h1,n1);
|
|
createBlending(2,10,h1,d1);
|
|
createBlending(3,10,h2,n2);
|
|
createBlending(4,10,h2,d2);
|
|
|
|
int i,j,pos;
|
|
for(j=-4;j<5;j++)
|
|
for(i= ((j>0)?j-4:-4) ; i< ((j<0)?5+j:5) ;i++) {
|
|
pos=60+j*11+i;
|
|
createPos(pos, i,j, 0);
|
|
}
|
|
|
|
pos = 0;
|
|
/* the outer marks of color1 */
|
|
for(i=0;i<3;i++) createPos(pos++, -6, i-4, 0 );
|
|
for(i=0;i<3;i++) createPos(pos++, 2+i, i-4, 0 );
|
|
|
|
/* the outer marks of color2 */
|
|
for(i=0;i<3;i++) createPos(pos++, 6, 4-i, 0 );
|
|
for(i=0;i<3;i++) createPos(pos++, -2-i, 4-i, 0 );
|
|
}
|
|
|
|
void BoardWidget::resizeEvent(QResizeEvent *e)
|
|
{
|
|
drawBoard();
|
|
BallWidget::resizeEvent(e);
|
|
}
|
|
|
|
void BoardWidget::moveEvent(QMoveEvent*)
|
|
{
|
|
drawBoard();
|
|
}
|
|
|
|
void BoardWidget::paintEvent(QPaintEvent *)
|
|
{
|
|
if (renderMode) {
|
|
pm = boardPM;
|
|
BallWidget::paint(&pm);
|
|
}
|
|
else
|
|
draw();
|
|
bitBlt(this, 0, 0, &pm);
|
|
}
|
|
|
|
|
|
void drawShadedHexagon(QPainter *p, int x, int y, int r, int lineWidth,
|
|
const QColorGroup& g, bool sunken)
|
|
{
|
|
int dx=r/2, dy=(r*87)/100;
|
|
int y1=y-dy, y2=y+dy;
|
|
int i;
|
|
|
|
QPen oldPen = p->pen();
|
|
|
|
p->setPen(sunken ? g.midlight() : g.dark());
|
|
|
|
for(i=0; i<lineWidth; i++) {
|
|
p->drawLine( x-i+dx, y-dy, x+2*dx-i, y);
|
|
p->drawLine( x+2*dx-i, y, x-i+dx, y+dy);
|
|
p->drawLine( x-i+dx, y1+i, x+i-dx, y1+i);
|
|
}
|
|
|
|
p->setPen(sunken ? g.dark() : g.midlight());
|
|
|
|
for(i=0; i<lineWidth; i++) {
|
|
p->drawLine( x+i-dx, y-dy, x+i-2*dx, y);
|
|
p->drawLine( x+i-2*dx, y, x+i-dx, y+dy);
|
|
p->drawLine( x-i+dx, y2-i, x+i-dx, y2-i);
|
|
}
|
|
|
|
p->setPen(oldPen);
|
|
}
|
|
|
|
|
|
void drawColor(QPainter *p, int x, int y, int r, QColor* c)
|
|
{
|
|
QColor w("white");
|
|
QPalette pal(*c);
|
|
|
|
QPen oldPen = p->pen();
|
|
QBrush oldBrush = p->brush();
|
|
|
|
p->setBrush(pal.active().dark());
|
|
p->setPen(pal.active().dark());
|
|
p->drawEllipse( x-r - 10,y-r +5, 2*r,2*r);
|
|
|
|
p->setBrush(pal.active().mid());
|
|
p->setPen(pal.active().mid());
|
|
p->drawEllipse( x-r,y-r, 2*r,2*r);
|
|
|
|
p->setBrush(pal.active().light());
|
|
p->setPen(pal.active().light());
|
|
p->drawEllipse( x-r/3, y-r/3, 4*r/3,4*r/3);
|
|
|
|
p->setBrush(w);
|
|
p->setPen(w);
|
|
p->drawEllipse( x+r/3, y+r/3, r/3,r/3);
|
|
|
|
p->setPen(oldPen);
|
|
p->setBrush(oldBrush);
|
|
}
|
|
|
|
|
|
void BoardWidget::drawBoard()
|
|
{
|
|
boardPM.resize(width(), height());
|
|
boardPM.fill(this, 0,0);
|
|
|
|
#ifndef HAVE_KIR
|
|
QColorGroup g = QPalette( *boardColor ).active();
|
|
QColorGroup g2 = QWidget::colorGroup();
|
|
|
|
int boardSize = width() *10/12;
|
|
if (boardSize > height()) boardSize = height();
|
|
|
|
QPainter p;
|
|
p.begin(&boardPM);
|
|
p.setBrush(g2.brush(QColorGroup::Mid));
|
|
|
|
QWMatrix m;
|
|
QPoint cp = rect().center();
|
|
m.translate(cp.x(), cp.y());
|
|
m.scale(boardSize/1100.0, boardSize/1000.0);
|
|
|
|
m.rotate(0);
|
|
|
|
p.setWorldMatrix(m);
|
|
|
|
/* draw field */
|
|
|
|
int i,j;
|
|
|
|
QPointArray a;
|
|
int dx=520 /2, dy=(520 *87)/100;
|
|
a.setPoints(6, -dx,-dy, dx,-dy, 2*dx,0, dx,dy, -dx,dy, -2*dx,0 );
|
|
p.drawPolygon(a);
|
|
|
|
drawShadedHexagon(&p, 0,0, 505, 1, g, false);
|
|
drawShadedHexagon(&p, 0,0, 512, 3, g, true);
|
|
drawShadedHexagon(&p, 0,0, 525, 5, g2, true);
|
|
|
|
#define xpos(i,j) (495*(2*(i)-(j))/9)
|
|
#define ypos(j) (500*19*(j)/100)
|
|
|
|
for(j=-4;j<5;j++)
|
|
for(i= ((j>0)?j-4:-4) ; i< ((j<0)?5+j:5) ;i++) {
|
|
int x=xpos(i,j);
|
|
int y=ypos(j);
|
|
|
|
drawShadedHexagon(&p, x,y, 50, 2, g, true);
|
|
drawShadedHexagon(&p, x,y, 30, 1, g, false);
|
|
}
|
|
p.end();
|
|
#endif
|
|
draw();
|
|
}
|
|
|
|
void BoardWidget::renderBalls(bool r)
|
|
{
|
|
renderMode=r;
|
|
draw();
|
|
}
|
|
|
|
void BoardWidget::updateBalls()
|
|
{
|
|
int i,j;
|
|
|
|
for(j=-4;j<5;j++)
|
|
for(i= ((j>0)?j-4:-4) ; i< ((j<0)?5+j:5) ;i++) {
|
|
int pos = 60+j*11+i;
|
|
int w=field[60+j*11+i];
|
|
|
|
if (w==Board::color1) {
|
|
if (positions[pos]->def != n1) {
|
|
positions[pos]->def= n1;
|
|
startAnimation(pos,1, ANIMATION_FORWARD);
|
|
}
|
|
else {
|
|
stopAnimation(pos);
|
|
}
|
|
}
|
|
else if (w==Board::color1bright)
|
|
startAnimation(pos,2,ANIMATION_LOOP);
|
|
else if (w==Board::color2) {
|
|
if (positions[pos]->def != n2) {
|
|
positions[pos]->def= n2;
|
|
startAnimation(pos,3,ANIMATION_FORWARD);
|
|
}
|
|
else {
|
|
stopAnimation(pos);
|
|
}
|
|
}
|
|
else if (w==Board::color2bright)
|
|
startAnimation(pos,4,ANIMATION_LOOP);
|
|
else if (w==Board::free) {
|
|
positions[pos]->def= 0;
|
|
positions[pos]->actAnimation = 0;
|
|
// stopAnimation(pos);
|
|
}
|
|
}
|
|
|
|
for(i=0;i<6;i++)
|
|
positions[i]->def= ((14-color1Count)>i && color1Count>0) ? n1:0;
|
|
|
|
for(i=6;i<12;i++)
|
|
positions[i]->def= ((14-color2Count)>i-6 && color2Count>0) ? n2:0;
|
|
|
|
}
|
|
|
|
void BoardWidget::draw()
|
|
{
|
|
if (boardPM.isNull())
|
|
return;
|
|
|
|
pm = boardPM;
|
|
|
|
if (renderMode) {
|
|
updateBalls();
|
|
repaint(false);
|
|
return;
|
|
}
|
|
|
|
int boardSize = width() *10/12;
|
|
if (boardSize > height()) boardSize = height();
|
|
|
|
QPainter p;
|
|
p.begin(&pm);
|
|
p.setBrush(foregroundColor());
|
|
|
|
QWMatrix m;
|
|
QPoint cp = rect().center();
|
|
m.translate(cp.x(), cp.y());
|
|
m.scale(boardSize/1100.0, boardSize/1000.0);
|
|
|
|
m.rotate(0);
|
|
|
|
p.setWorldMatrix(m);
|
|
|
|
/* draw fields */
|
|
|
|
int i,j;
|
|
|
|
for(j=-4;j<5;j++)
|
|
for(i= ((j>0)?j-4:-4) ; i< ((j<0)?5+j:5) ;i++) {
|
|
int x=xpos(i,j);
|
|
int y=ypos(j);
|
|
int w=field[60+j*11+i];
|
|
|
|
if (w==Board::color1)
|
|
drawColor(&p, x,y, 35, redColor );
|
|
else if (w==Board::color1bright)
|
|
drawColor(&p, x,y, 35, redHColor );
|
|
else if (w==Board::color2)
|
|
drawColor(&p, x,y, 35, yellowColor );
|
|
else if (w==Board::color2bright)
|
|
drawColor(&p, x,y, 35, yellowHColor );
|
|
}
|
|
|
|
if (color1Count >0) {
|
|
/* the outer marks of color1 */
|
|
if (color1Count <12) {
|
|
for(i=11; i>8 && i>color1Count ;i--)
|
|
drawColor(&p, xpos(12-i,7-i)+55, ypos(7-i), 35, redColor );
|
|
}
|
|
for(i=14; i>11 && i>color1Count ;i--)
|
|
drawColor(&p, xpos(-6,10-i)+55, ypos(10-i), 35, redColor );
|
|
|
|
/* the outer marks of color2 */
|
|
if (color2Count <12) {
|
|
for(i=11; i>8 && i>color2Count ;i--)
|
|
drawColor(&p, xpos(i-12,i-7)-55, ypos(i-7), 35, yellowColor);
|
|
}
|
|
for(i=14; i>11 && i>color2Count ;i--)
|
|
drawColor(&p, xpos(6,i-10)-55, ypos(i-10), 35, yellowColor);
|
|
}
|
|
p.end();
|
|
bitBlt(this, 0, 0, &pm);
|
|
}
|
|
|
|
/** updatePosition
|
|
*
|
|
* Update my position with that of the <board> member.
|
|
* If <updateGUI> is true, draw widget
|
|
*/
|
|
void BoardWidget::updatePosition(bool updateGUI)
|
|
{
|
|
for(int i=0; i<Board::AllFields;i++)
|
|
field[i] = board[i];
|
|
color1Count = board.getColor1Count();
|
|
color2Count = board.getColor2Count();
|
|
color = board.actColor();
|
|
boardOK = true;
|
|
|
|
if (updateGUI) draw();
|
|
}
|
|
|
|
|
|
bool BoardWidget::setEditMode(bool mode)
|
|
{
|
|
if (editMode == false && mode==true) {
|
|
editMode = true;
|
|
}
|
|
else if (editMode == true && mode == false) {
|
|
editMode = false;
|
|
|
|
for(int i=0; i<Board::AllFields;i++)
|
|
board.setField( i, field[i]);
|
|
board.setColor1Count(color1Count);
|
|
board.setColor2Count(color2Count);
|
|
|
|
}
|
|
return editMode;
|
|
}
|
|
|
|
|
|
void BoardWidget::clearPosition()
|
|
{
|
|
for(int i=0; i<Board::AllFields;i++)
|
|
field[i] = 0;
|
|
color1Count = color2Count = 0;
|
|
}
|
|
|
|
void BoardWidget::showMove(const Move& mm, int step, bool updateGUI)
|
|
{
|
|
int f, dir, dir2;
|
|
int opponentNew, colorNew;
|
|
bool afterMove;
|
|
static Move lastMove;
|
|
Move m;
|
|
|
|
if (boardOK) {
|
|
/* board ok means: board has the normal state
|
|
* (e.g. no highlighting)
|
|
*/
|
|
if (step == 0)
|
|
return; /* nothing to be done */
|
|
}
|
|
boardOK = (step == 0) ? true:false;
|
|
|
|
if (step == 0)
|
|
m = lastMove;
|
|
else {
|
|
m = lastMove = mm;
|
|
}
|
|
|
|
if (color == Board::color1) {
|
|
colorNew = (step<2) ? Board::color1 :
|
|
(step>2) ? Board::color1bright:Board::free;
|
|
opponentNew = (step<2) ? Board::color2 : Board::color2bright;
|
|
}
|
|
else {
|
|
colorNew = (step<2) ? Board::color2 :
|
|
(step>2) ? Board::color2bright:Board::free;
|
|
opponentNew = (step<2) ? Board::color1 : Board::color1bright;
|
|
}
|
|
|
|
afterMove = (step == 1) || (step == 4);
|
|
|
|
f = m.field;
|
|
dir = Board::fieldDiffOfDir(m.direction);
|
|
|
|
/* first field */
|
|
field[f] = afterMove ? Board::free : colorNew;
|
|
|
|
switch(m.type) {
|
|
case Move::out2: /* (c c c o o |) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
field[f + 3*dir] = afterMove ? colorNew : opponentNew;
|
|
field[f + 4*dir] = opponentNew;
|
|
break;
|
|
case Move::out1with3: /* (c c c o |) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
field[f + 3*dir] = afterMove ? colorNew : opponentNew;
|
|
break;
|
|
case Move::move3: /* (c c c .) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
field[f + 3*dir] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::out1with2: /* (c c o |) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = afterMove ? colorNew : opponentNew;
|
|
break;
|
|
case Move::move2: /* (c c .) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::push2: /* (c c c o o .) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
field[f + 3*dir] = afterMove ? colorNew : opponentNew;
|
|
field[f + 4*dir] = opponentNew;
|
|
field[f + 5*dir] = afterMove ? opponentNew : Board::free;
|
|
break;
|
|
case Move::left3:
|
|
dir2 = Board::fieldDiffOfDir(m.direction-1);
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::right3:
|
|
dir2 = Board::fieldDiffOfDir(m.direction+1);
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::push1with3: /* (c c c o .) => (. c c c o) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
field[f + 3*dir] = afterMove ? colorNew : opponentNew;
|
|
field[f + 4*dir] = afterMove ? opponentNew : Board::free;
|
|
break;
|
|
case Move::push1with2: /* (c c o .) => (. c c o) */
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = afterMove ? colorNew : opponentNew;
|
|
field[f + 3*dir] = afterMove ? opponentNew : Board::free;
|
|
break;
|
|
case Move::left2:
|
|
dir2 = Board::fieldDiffOfDir(m.direction-1);
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::right2:
|
|
dir2 = Board::fieldDiffOfDir(m.direction+1);
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
field[f+=dir] = afterMove ? Board::free : colorNew;
|
|
field[f+dir2] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
case Move::move1: /* (c .) => (. c) */
|
|
field[f + dir] = afterMove ? colorNew : Board::free;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (updateGUI)
|
|
draw();
|
|
}
|
|
|
|
void BoardWidget::showStart(const Move& m, int step, bool updateGUI)
|
|
{
|
|
int f, dir;
|
|
int colorNew;
|
|
|
|
if (boardOK) {
|
|
/* board ok means: board has the normal state before move */
|
|
if (step == 0)
|
|
return; /* nothing to be done */
|
|
}
|
|
boardOK = (step == 0) ? true:false;
|
|
|
|
if (color == Board::color1)
|
|
colorNew = (step==0) ? Board::color1 : Board::color1bright;
|
|
else
|
|
colorNew = (step==0) ? Board::color2 : Board::color2bright;
|
|
|
|
f = m.field;
|
|
|
|
/* first field */
|
|
field[f] = colorNew;
|
|
|
|
switch(m.type) {
|
|
case Move::left3:
|
|
case Move::right3:
|
|
dir = Board::fieldDiffOfDir(m.direction);
|
|
field[f + dir] = colorNew;
|
|
field[f + 2*dir] = colorNew;
|
|
break;
|
|
case Move::left2:
|
|
case Move::right2:
|
|
dir = Board::fieldDiffOfDir(m.direction);
|
|
field[f + dir] = colorNew;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (updateGUI)
|
|
draw();
|
|
}
|
|
|
|
|
|
void BoardWidget::choseMove(MoveList *pl)
|
|
{
|
|
if (!gettingMove && pl != 0) {
|
|
pList = pl;
|
|
gettingMove = true;
|
|
mbDown = false;
|
|
actValue = - board.calcEvaluation();
|
|
kdDebug(12011) << "Chose Move..." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
/* returns position of point (xx,yy)
|
|
*/
|
|
int BoardWidget::positionOf(int xx, int yy)
|
|
{
|
|
int boardSize = QMIN( width()*10/12, height() );
|
|
int x = (1000 * (xx- (width()-boardSize)/2)) / boardSize;
|
|
int y = (1000 * (yy- (height()-boardSize)/2)) / boardSize;
|
|
|
|
/*
|
|
kdDebug(12011) << "(" << xx << "," << yy << ") -> ("
|
|
<< x << "," << y << ")" << endl;
|
|
*/
|
|
|
|
y = (y-2)/47;
|
|
if (y < 2 || y > 18) return 0;
|
|
x= ((x+25)/25+ (y-10) )/2;
|
|
if (y < 10 && ((x < 2) || (x > 8+y) )) return 0;
|
|
if (y >= 10 && ((x < y-8) || (x > 18) )) return 0;
|
|
|
|
return 22*y + x;
|
|
}
|
|
|
|
|
|
bool isBetweenFields(int pos)
|
|
{
|
|
bool res = ( ((pos%2) == 1) || ( ((pos/22)%2) == 1) );
|
|
// kdDebug(12011) << "Pos " << pos << " is between fields: " << res << endl;
|
|
return res;
|
|
}
|
|
|
|
int fieldOf(int pos)
|
|
{
|
|
int f = 11*(pos/44) + (pos%22)/2;
|
|
// kdDebug(12011) << "Field1 of pos " << pos << " is " << f << endl;
|
|
return f;
|
|
}
|
|
|
|
int field2Of(int pos)
|
|
{
|
|
int y = pos/22, x = pos%22;
|
|
int f2 = 0, f1 = 11*(y/2) + (x/2);
|
|
|
|
if ( (y%2) == 0) {
|
|
/* exact on row */
|
|
if ( (x%2) != 0) {
|
|
/* horizontial between fields */
|
|
f2 = f1+1;
|
|
}
|
|
}
|
|
else {
|
|
/* vertical between fields */
|
|
f2 = f1 + ( ((x%2)==0) ? 11:12 );
|
|
}
|
|
|
|
// kdDebug(12011) << "Field2 of pos " << pos << " is " << f2 << endl;
|
|
return f2;
|
|
}
|
|
|
|
|
|
/* get direction depending on difference of positions */
|
|
int directionOfPosDiff(int d)
|
|
{
|
|
if (d>0) {
|
|
return ((d<21) ? Move::Right :
|
|
((d%22) == 0) ? Move::LeftDown :
|
|
((d%23) == 0) ? Move::RightDown : 0);
|
|
}
|
|
else if (d<0) {
|
|
return ((d>-21) ? Move::Left :
|
|
((d%23) == 0) ? Move::LeftUp :
|
|
((d%22) == 0) ? Move::RightUp : 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int directionOfFieldDiff(int d)
|
|
{
|
|
if (d>0) {
|
|
return ((d<10) ? Move::Right :
|
|
((d%11) == 0) ? Move::LeftDown :
|
|
((d%12) == 0) ? Move::RightDown : 0);
|
|
}
|
|
else if (d<0) {
|
|
return ((d>-10) ? Move::Left :
|
|
((d%12) == 0) ? Move::LeftUp :
|
|
((d%11) == 0) ? Move::RightUp : 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Check if <pos> is a valid start position for a allowed move
|
|
* If yes, set
|
|
* <startField>, <actMove> and <startType>
|
|
*/
|
|
bool BoardWidget::isValidStart(int pos, bool midPressed)
|
|
{
|
|
bool res = false;
|
|
int f1 = fieldOf(pos);
|
|
|
|
startField = f1;
|
|
|
|
if (isBetweenFields(pos)) {
|
|
int f2 = field2Of(pos);
|
|
|
|
actMove = Move(f1, directionOfFieldDiff( f2-f1 ), Move::none);
|
|
res = pList->isElement(actMove, MoveList::start2);
|
|
if (!res) {
|
|
startField = f2;
|
|
actMove = Move(f2, directionOfFieldDiff( f1-f2 ), Move::none);
|
|
res = pList->isElement(actMove, MoveList::start2);
|
|
}
|
|
startType = MoveList::start2;
|
|
return res;
|
|
}
|
|
|
|
if (midPressed) {
|
|
startType = MoveList::start3;
|
|
|
|
/* Check all 6 directions */
|
|
for(int dir=1;dir<7;dir++) {
|
|
actMove = Move(f1 - Board::fieldDiffOfDir(dir), dir, Move::none );
|
|
if (pList->isElement(actMove, startType))
|
|
return true;
|
|
}
|
|
/* if we don't find a side move3 fall trough to normal moves... */
|
|
}
|
|
|
|
startType = MoveList::start1;
|
|
actMove = Move(f1, 0, Move::none);
|
|
res = pList->isElement(actMove, startType);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/* Check if <pos> is a valid end position for a move
|
|
* regarding <startPos>
|
|
* If yes, set <actMove>
|
|
*/
|
|
bool BoardWidget::isValidEnd(int pos)
|
|
{
|
|
int dir = directionOfPosDiff(pos - startPos);
|
|
Move m;
|
|
|
|
if (dir == 0) return false;
|
|
|
|
switch(startType) {
|
|
case MoveList::start1:
|
|
m = Move(startField, dir, Move::none);
|
|
if (!pList->isElement(m, startType))
|
|
return false;
|
|
break;
|
|
|
|
case MoveList::start2:
|
|
{
|
|
int f1 = fieldOf(startPos);
|
|
int f2 = field2Of(startPos);
|
|
int dir2 = directionOfFieldDiff( f2-f1 );
|
|
int dir3 = directionOfFieldDiff( f1-f2 );
|
|
|
|
switch((dir2-dir+6)%6) {
|
|
case 1:
|
|
m = Move(f1, dir2, Move::left2);
|
|
break;
|
|
case 2:
|
|
m = Move(f2, dir3, Move::right2);
|
|
break;
|
|
case 4:
|
|
m = Move(f2, dir3, Move::left2);
|
|
break;
|
|
case 5:
|
|
m = Move(f1, dir2, Move::right2);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
if (!pList->isElement(m, startType))
|
|
return false;
|
|
|
|
break;
|
|
}
|
|
case MoveList::start3:
|
|
{
|
|
int rightDir = (dir%6)+1;
|
|
m = Move( startField - Board::fieldDiffOfDir(rightDir), rightDir, Move::left3 );
|
|
if (!pList->isElement(m, startType)) {
|
|
int leftDir = ((dir-2)%6)+1;
|
|
m = Move( startField - Board::fieldDiffOfDir(leftDir), leftDir, Move::right3 );
|
|
if (!pList->isElement(m, startType))
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
actMove = m;
|
|
shownDirection = dir;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void BoardWidget::mousePressEvent( QMouseEvent* pEvent )
|
|
{
|
|
int pos = positionOf( pEvent->x(), pEvent->y() );
|
|
int f = fieldOf(pos);
|
|
|
|
if (pEvent->button() == RightButton) {
|
|
emit rightButtonPressed(f, pEvent->globalPos());
|
|
return;
|
|
}
|
|
|
|
if (!gettingMove && !editMode) {
|
|
return;
|
|
}
|
|
mbDown = true;
|
|
|
|
|
|
if (editMode) {
|
|
editColor = (pEvent->button() == MidButton) ?
|
|
Board::color2 : Board::color1;
|
|
int newColor = (pEvent->button() == MidButton) ?
|
|
Board::color2bright : Board::color1bright;
|
|
|
|
if (field[f] == Board::free) {
|
|
field[f] = newColor;
|
|
}
|
|
else if (field[f] == Board::color1) {
|
|
if (editColor == Board::color1) {
|
|
editColor = Board::free;
|
|
newColor = Board::color1bright;
|
|
}
|
|
field[f] = newColor;
|
|
}
|
|
else if (field[f] == Board::color2) {
|
|
if (editColor == Board::color2) {
|
|
editColor = Board::free;
|
|
newColor = Board::color2bright;
|
|
}
|
|
field[f] = newColor;
|
|
}
|
|
else {
|
|
editColor = Board::out;
|
|
}
|
|
|
|
oldPos = pos;
|
|
draw();
|
|
return;
|
|
}
|
|
|
|
startValid = isValidStart(pos, (pEvent->button() == MidButton));
|
|
kdDebug(12011) << "Start pos " << pos << " is valid: " << startValid << endl;
|
|
// actMove.print();
|
|
|
|
if (!startValid) return;
|
|
startPos = oldPos = pos;
|
|
|
|
showStart(actMove,1);
|
|
startShown = true;
|
|
|
|
QString tmp;
|
|
actValue = - board.calcEvaluation();
|
|
tmp = i18n("Board value: %1").arg(actValue);
|
|
emit updateSpy(tmp);
|
|
}
|
|
|
|
|
|
void BoardWidget::mouseMoveEvent( QMouseEvent* pEvent )
|
|
{
|
|
if ((!gettingMove && !editMode) || !mbDown) return;
|
|
|
|
int pos = positionOf( pEvent->x(), pEvent->y() );
|
|
if (pos == oldPos) return;
|
|
oldPos = pos;
|
|
|
|
if (editMode) {
|
|
int f = fieldOf(pos);
|
|
if (field[f] != Board::out && field[f] != editColor) {
|
|
int newColor = (editColor == Board::color1) ? Board::color1bright :
|
|
(editColor == Board::color2) ? Board::color2bright :
|
|
(field[f] == Board::color1) ? Board::color1bright :
|
|
(field[f] == Board::color2) ? Board::color2bright : field[f];
|
|
field[f] = newColor;
|
|
draw();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!startValid) {
|
|
/* We haven't a valid move yet. Check if we are over a valid start */
|
|
|
|
startValid = isValidStart(pos, (pEvent->button() == MidButton));
|
|
kdDebug(12011) << "Start pos " << pos << " is valid: " << startValid << endl;
|
|
// actMove.print();
|
|
|
|
if (!startValid) return;
|
|
startPos = oldPos = pos;
|
|
|
|
showStart(actMove,1);
|
|
startShown = true;
|
|
|
|
QString tmp;
|
|
actValue = - board.calcEvaluation();
|
|
tmp = i18n("Board value: %1").arg(actValue);
|
|
emit updateSpy(tmp);
|
|
return;
|
|
}
|
|
|
|
/* restore board */
|
|
updatePosition();
|
|
startShown = false;
|
|
|
|
if (isValidEnd(pos)) {
|
|
// actMove.print();
|
|
|
|
board.playMove(actMove);
|
|
int v = board.calcEvaluation();
|
|
board.takeBack();
|
|
|
|
QString tmp;
|
|
tmp.sprintf("%+d", v-actValue);
|
|
QString str = QString("%1 : %2").arg(actMove.name()).arg(tmp);
|
|
emit updateSpy(str);
|
|
|
|
showMove(actMove,3);
|
|
setCursor(*arrow[shownDirection]);
|
|
}
|
|
else {
|
|
QString tmp;
|
|
|
|
setCursor(crossCursor);
|
|
if (pos == startPos) {
|
|
showStart(actMove,1);
|
|
startShown = true;
|
|
tmp = i18n("Board value: %1").arg(actValue);
|
|
}
|
|
else
|
|
draw();
|
|
emit updateSpy(tmp);
|
|
}
|
|
}
|
|
|
|
|
|
void BoardWidget::mouseReleaseEvent( QMouseEvent* pEvent )
|
|
{
|
|
if (!gettingMove && !editMode) return;
|
|
mbDown = false;
|
|
|
|
if (editMode) {
|
|
int i;
|
|
|
|
// printf("Releasing...");
|
|
for(i=0; i<Board::AllFields;i++)
|
|
if (field[i] == Board::color1bright ||
|
|
field[i] == Board::color2bright) {
|
|
//printf(" Found %d\n",i);
|
|
field[i] = editColor;
|
|
}
|
|
|
|
for(i=0; i<Board::AllFields;i++)
|
|
board.setField( i, field[i]);
|
|
|
|
int vState = board.validState(); // set color1/2Count
|
|
color1Count = board.getColor1Count();
|
|
color2Count = board.getColor2Count();
|
|
|
|
draw();
|
|
|
|
emit edited(vState);
|
|
return;
|
|
}
|
|
|
|
if (!startValid) return;
|
|
|
|
int pos = positionOf( pEvent->x(), pEvent->y() );
|
|
if (isValidEnd(pos)) {
|
|
// actMove.print();
|
|
startValid = false;
|
|
setCursor(crossCursor);
|
|
gettingMove = false;
|
|
emit moveChoosen(actMove);
|
|
return;
|
|
}
|
|
|
|
updatePosition(true);
|
|
startValid = false;
|
|
setCursor(crossCursor);
|
|
|
|
QString tmp;
|
|
emit updateSpy(tmp);
|
|
}
|
|
|
|
QSize BoardWidget::sizeHint() const
|
|
{
|
|
return QSize(400, 350);
|
|
}
|
|
|
|
#include "BoardWidget.moc"
|