diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /ksnake/snake.cpp | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'ksnake/snake.cpp')
-rw-r--r-- | ksnake/snake.cpp | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/ksnake/snake.cpp b/ksnake/snake.cpp new file mode 100644 index 00000000..33b3f027 --- /dev/null +++ b/ksnake/snake.cpp @@ -0,0 +1,557 @@ +/** + * Copyright Michel Filippi <mfilippi@sade.rhein-main.de> + * Robert Williams + * Andrew Chant <andrew.chant@utoronto.ca> + * André Luiz dos Santos <andre@netvision.com.br> + * Benjamin Meyer <ben+ksnake@meyerhome.net> + * + * This file is part of the ksnake package + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <qwidget.h> + +#include "snake.h" + +int opposite[4] = { S, N , W, E }; + +int emptySq[4][4]={ + { N, E, W, N }, + { S, W, E, S }, + { E, N, S, E }, + { W, S, N, W } +}; + +Snake::Snake(Board *b, PixServer *p, Gate g, PixMap x) +{ + list.setAutoDelete( true ); + pixServer = p; + board = b; + gate = g; + pixmap = x; + random.setSeed(0); +} + +void Snake::updateSamy() +{ + int x = tail(); + while ( x > 0) { + *list.at(x) = *list.at(x-1); + --x; + } +} + +void Snake::zero() +{ + for ( Samy *sam = list.first(); sam != 0; sam = list.next() ) { + board->set(sam->index, empty); + pixServer->erase(sam->index); + } +} + +void Snake::appendSamy() +{ + Samy *sam = new Samy; + list.append(sam); + + updateSamy(); + grow--; +} + +void Snake::reset(int index, int border) +{ + Samy *sam = list.first(); + + switch (border) { + case N: + sam->pixmap = (tail() == 0 ? HtailUp : HeadUp); + break; + case S: + sam->pixmap = (tail() == 0 ? HtailDown : HeadDown); + break; + case E: + sam->pixmap = (tail() == 0 ? HtailRight : HeadRight); + break; + case W: + sam->pixmap = (tail() == 0 ? HtailLeft : HeadLeft); + break; + } + + sam->index = index; + sam->direction = border; + + if (tail() > 1) { + + sam = list.next(); + + if (sam->direction == border) { + if (border == N || border == S) + sam->pixmap = BodyVt; + else + sam->pixmap = BodyHz; + } + else { + if (border == W && sam->direction == S + || border == N && sam->direction == E) + sam->pixmap = AngleNw; + if (border == E && sam->direction == S + || border == N && sam->direction == W) + sam->pixmap = AngleNe; + if(border == W && sam->direction == N + || border == S && sam->direction == E) + sam->pixmap = AngleSw; + if(border == E && sam->direction == N + || border == S && sam->direction == W) + sam->pixmap = AngleSe; + } + + + } //end if (tail() > 1) + + if (tail() > 0) { + + sam = list.last(); + + switch (list.at(tail()-1)->direction) { + case N: + sam->pixmap = TailUp; + break; + case S: + sam->pixmap = TailDown; + break; + case E: + sam->pixmap = TailRight; + break; + case W: + sam->pixmap = TailLeft; + break; + } + } +} + +void Snake::repaint( bool dirty) +{ + int x = 0; + for ( Samy *sam = list.first(); sam != 0; sam = list.next(), x++) { + if (sam->index != OUT ) { + if(!dirty && x > 1 && x < tail()) + continue; + pixServer->draw(sam->index, pixmap, sam->pixmap); + } + } + if (!growing() && hold != OUT && hold != gate) { + pixServer->erase(hold); + } +} + + +CompuSnake::CompuSnake( Board *b, PixServer *p) + : Snake( b, p, NORTH_GATE, CompuSnakePix ) +{ + init(); +} + +bool CompuSnake::init() +{ + if( !list.isEmpty()) { + list.clear(); + } + + int index = NORTH_GATE; + int length = 12; + grow = 0; + hold = OUT; + + if ( !board->isBrick(gate) ) return false; + + Samy *sam; + for ( int x = 0; x < length; x++) { + board->set(index, snake); + sam = new Samy; + sam->direction = S; + sam->index = index; + sam->pixmap = (x == 0 ? HeadDown : BodyVt); + list.append(sam); + index = -1; + } + return true; +} + +bool CompuSnake::permission() +{ + if( list.isEmpty() ){ + + if ( hold != OUT) { + emit killed(); + hold = OUT; + } + + if(board->isBrick(gate)){ + static int skip = 12; + if (skip < 12) { + skip++; + return false; + } else { + skip = 0; + return init(); + } + } + else return false; + } + else return true; +} + +void CompuSnake::nextMove() +{ + if (!permission()) + return; + + Samy *sam = list.first(); + int index = sam->index; + int dir = sam->direction; + static bool varies = false; + + + bool found = false; + + for ( int x = 0; x < 4 ; x++) { + int next = board->getNext(x, sam->index); + if (board->isApple(next)){ + index = next; + dir = x; + found = true; + grow+=6; + emit score(false, index); + break; + } + } + + if(!found) + for ( int x = 0; x < 4 ; x++) { + int sq = emptySq[sam->direction][x]; + if (varies && (x > 0 && x < 3)) + sq = opposite[sq]; + int next = board->getNext(sq, sam->index); + if (findEmpty(next, x)) { + index = next; + dir = sq; + found = true; + break; + } + } + varies = !varies; + + if(!found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + removeSamy(); + } + else + if(growing()) + appendSamy(); + else + if (!growing() && found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + updateSamy(); + } + + if( !list.isEmpty()) { + board->set(index, snake); + reset(index, dir); + } + + if ( hold == gate) + out(); +} + +void KillerCompuSnake::nextMove() +{ + if (!permission()) return; + + Samy *sam = list.first(); + int index = sam->index; + int dir = sam->direction; + static bool varies = false; + + + bool found = false; + + if(!found) { + int sn = board->samyHeadIndex(); + if(sn != -1 && board->isHead(sn)) { + int nextSq = board->getNextCloseTo(index, sn, false, lastIndex); + if(nextSq != -1) { + dir = board->direction(index, nextSq); + index = nextSq; + found = true; + } + } + } + + if(!found) + for ( int x = 0; x < 4 ; x++) { + int sq = emptySq[sam->direction][x]; + if (varies && (x > 0 && x < 3)) + sq = opposite[sq]; + int next = board->getNext(sq, sam->index); + if (findEmpty(next, x)) { + index = next; + dir = sq; + found = true; + break; + } + } + varies = !varies; + + if(!found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + removeSamy(); + } + else { + lastIndex = index; + + if(growing()) + appendSamy(); + else + if (!growing() && found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + updateSamy(); + } + } + + if( !list.isEmpty()) { + board->set(index, snake); + reset(index, dir); + } + + if ( hold == gate) + out(); +} + +void EaterCompuSnake::nextMove() +{ + if (!permission()) return; + + Samy *sam = list.first(); + int index = sam->index; + int dir = sam->direction; + static bool varies = false; + + + bool found = false; + + for ( int x = 0; x < 4 ; x++) { + int next = board->getNext(x, sam->index); + if (board->isApple(next)){ + index = next; + dir = x; + found = true; + grow+=6; + emit score(false, index); + break; + } + } + + if(!found) { + int sn; + bool apple = false; + for(sn = board->count() - 1; sn > 0; sn --) { + if(board->isApple(sn)) { + apple = true; + int nextSq = board->getNextCloseTo(index, sn, false); + if(nextSq != -1) { + dir = board->direction(index, nextSq); + index = nextSq; + found = true; + break; + } + } + } + if(!found && !apple) { + // No more apples, move snake to gate. + int nextSq = board->getNextCloseTo(index, gate, false, lastIndex); + if(nextSq != -1) { + dir = board->direction(index, nextSq); + index = nextSq; + found = true; + } + } + } + + if(!found) + for ( int x = 0; x < 4 ; x++) { + int sq = emptySq[sam->direction][x]; + if (varies && (x > 0 && x < 3)) + sq = opposite[sq]; + int next = board->getNext(sq, sam->index); + if (findEmpty(next, x)) { + index = next; + dir = sq; + found = true; + break; + } + } + varies = !varies; + + if(!found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + removeSamy(); + } + else { + lastIndex = index; + + if(growing()) + appendSamy(); + else + if (!growing() && found) { + hold = list.last()->index; + if (board->isSnake(hold)) board->set(hold, empty); + updateSamy(); + } + } + + if( !list.isEmpty()) { + board->set(index, snake); + reset(index, dir); + } + + if ( hold == gate) + out(); +} + +bool CompuSnake::findEmpty(int i, int it) +{ + bool found = false; + bool change = false; + static int s_random = random.getLong(BoardWidth/2); + static int moves = 0; + + if (moves > s_random) { + s_random = random.getLong(BoardWidth/2); + moves = 0; + change = true; + } + + found = ( ( board->isEmpty(i) && it > 0) + || ( board->isEmpty(i) && !change && it == 0) ); + + moves++; + change = false; + return found; +} + +void CompuSnake::removeSamy() +{ + list.remove(); + grow = 0; +} + +void CompuSnake::out() +{ + emit closeGate( gate ); + + if( list.isEmpty() ) + return; + + if(list.first()->index == OUT) { + emit restartTimer(); + list.clear(); + } +} + +SamySnake::SamySnake( Board *b, PixServer *p) + : Snake( b, p, SOUTH_GATE, SamyPix ) +{ + +} + +void SamySnake::init() +{ + if( !list.isEmpty()) { + list.clear(); + } + Samy *sam; + + int index = SOUTH_GATE; + int length = 12; + grow = 0; + hold = 0; + + for ( int x = 0; x < length; x++) { + board->set(index, head); + sam = new Samy; + sam->direction = N; + sam->index = index; + sam->pixmap = (x == 0 ? HeadUp : BodyVt); + list.append(sam); + index = -1; + } +} + +samyState SamySnake::nextMove(int direction) +{ + Samy *sam = list.first(); + + if(!board->isHead(sam->index) && sam->index != OUT) + return ko; + + if ( direction == opposite[sam->direction]) + direction = sam->direction; + + if(sam->index == gate || sam->index == OUT ) + direction = N; + + if (sam->index == NORTH_GATE) { + emit goingOut(); + direction = N; + } + + int index = board->getNext(direction, sam->index); + + if (board->isApple(index)) { + grow+=6; + emit score(true, index); + } + else if (!board->isEmpty(index)) + return ko; + + if(growing()) + appendSamy(); + else { + hold = list.last()->index; + board->set(hold, empty); + updateSamy(); + } + + board->set(sam->index, snake); + reset(index, direction); + board->set(index, head); + + if ( hold == gate) + emit closeGate( gate ); + else if ( hold == NORTH_GATE) + return out; + + return ok; +} + +#include "snake.moc" + |