--- /dev/null
+#include "playfield.h"
+#include <stdio.h>
+PlayField::PlayField(const QString &_title, const QString &_board, const QString &_solution):title(_title),solution(_solution)
+{
+ for(int w=0;w<PF::FIELD_WIDTH;w++)
+ for(int h=0;h<PF::FIELD_HEIGHT;h++)
+ field[w][h]=PF::CELL_WALL;
+ QStringList rows=_board.split("/");
+ QListIterator<QString> rowI(rows);
+ int h=0;
+ while(rowI.hasNext())
+ {
+ QString row=rowI.next();
+ int w=0;
+ for(int i=0;i<row.size();i++)
+ {
+ char ch=row[i].toAscii();
+ int c=0;
+ while(ch>='0' && ch<='9')
+ {
+ c=c*10+ch-'0';
+ ch=row[++i].toAscii();
+ if(i>=row.size()) break;
+ }
+ w+=c;
+ if(ch=='~')
+ {
+ field[w++][h]=PF::CELL_EMPTY;
+ }
+ if(ch>='a' && ch <= 'h')
+ {
+ field[w++][h]=ch-'a'+2;
+ }
+ }
+ h++;
+ }
+}
+
+void PlayField::move(int w, int h, int w_new)
+{
+ if((w_new < 0) ||
+ (w_new >= PF::FIELD_WIDTH) || w == w_new)
+ {
+ return;
+ }
+ if(get(w,h)==PF::CELL_EMPTY ||
+ get(w,h)==PF::CELL_WALL)
+ {
+ return;
+ }
+ int d=w>w_new?-1:1;
+
+ Field temp;
+ int movesTemp=moves;
+ copy(field,temp);
+
+ bool moved=false;
+ bool cont;
+
+ int h_below=h+1;
+ do
+ {
+ cont=moveBlock(w,h,d,0);
+ w+=d;
+ if(cont){
+ moves++;
+ moved=true;
+ }//if coordination has changed, inc the moves
+ } while(cont && (w!=w_new) && ((h_below >= PF::FIELD_HEIGHT) || get(w,h_below)!=PF::CELL_EMPTY));
+ do
+ {
+ cont=false;
+ cont|=checkGlobalFall();
+ cont|=checkTouch();
+ } while(cont);
+ if(moved)
+ {
+ if(totalUndo<PF::MAX_UNDO) totalUndo++;
+ copy(temp,undos[currentUndo]);
+ undoMade[currentUndo]=movesTemp;
+ currentUndo=(currentUndo + 1) % PF::MAX_UNDO;
+ }
+}
+
+bool PlayField::moveBlock(int w, int h, int dw, int dh)
+{
+ int wn=w+dw;
+ int hn=h+dh;
+
+ if(wn<0 || wn >= PF::FIELD_WIDTH || hn < 0 || hn >= PF::FIELD_HEIGHT)
+ return false;
+
+ if(get(wn,hn)!=PF::CELL_EMPTY)
+ return false;
+ set(wn, hn, get(w,h));
+ set(w,h,PF::CELL_EMPTY);
+ emit cellMoved(w,h,wn,hn);
+ return true;
+}
+bool PlayField::checkGlobalFall()
+{
+ bool fall;
+ bool fallen=false;
+ do
+ {
+ fall=false;
+ for(int w=0;w<PF::FIELD_WIDTH;w++)
+ for(int h=0;h<PF::FIELD_HEIGHT;h++)
+ if(checkFall(w,h))
+ {
+ if(moveBlock(w,h,0,1))
+ {
+ fall=true;
+ fallen=true;
+ }
+ }
+ } while(fall);
+ return fallen;
+}
+
+bool PlayField::checkFall(int w, int h)
+{
+ int cell=get(w,h);
+ return (cell!=PF::CELL_EMPTY) &&
+ (cell!=PF::CELL_WALL) &&
+ (h!=(PF::FIELD_HEIGHT-1)) &&
+ (get(w,h+1)==PF::CELL_EMPTY);
+}
+bool PlayField::checkTouch()
+{
+ int toHide[PF::FIELD_WIDTH][PF::FIELD_HEIGHT];
+
+ for (int w = 0; w < PF::FIELD_WIDTH; w++) {
+ for (int h = 0; h < PF::FIELD_HEIGHT; h++) {
+ toHide[w][h] = PF::CELL_EMPTY;
+ if ((get(w,h) != PF::CELL_EMPTY) && (get(w,h)!=PF::CELL_WALL)) {
+ if (h != 0) {
+ toHide[w][h] |= (get(w,h-1) == get(w,h));
+ }
+ if (h != PF::FIELD_HEIGHT - 1) {
+ toHide[w][h] |= (get(w,h+1) == get(w,h));
+ }
+ if (w != 0) {
+ toHide[w][h] |= (get(w-1,h) == get(w,h));
+ }
+ if (w != PF::FIELD_WIDTH - 1) {
+ toHide[w][h] |= (get(w+1,h) == get(w,h));
+ }
+ }
+ }
+ }
+
+ bool touched=false;
+ for (int w = 0; w < PF::FIELD_WIDTH; w++) {
+ for (int h = 0; h < PF::FIELD_HEIGHT; h++) {
+ if(toHide[w][h])
+ {
+ set(w,h,PF::CELL_EMPTY);
+ emit cellGone(w,h);
+ touched=true;
+ }
+ }
+ }
+ return touched;
+}
+
+bool PlayField::checkSolved()
+{
+ for(int w=0;w<PF::FIELD_WIDTH-1;w++)
+ for(int h=0;h<PF::FIELD_HEIGHT-1;h++)
+ {
+ int cell=get(w,h);
+ if((cell!=PF::CELL_EMPTY) && (cell!=PF::CELL_WALL)) return false;
+ }
+ return true;
+}
+
+void PlayField::undo()
+{
+ if(totalUndo > 0)
+ {
+ totalUndo--;
+ currentUndo=(currentUndo - 1 + PF::MAX_UNDO) % PF::MAX_UNDO;
+ copy(undos[currentUndo],field);
+ moves=undoMade[currentUndo];
+ }
+}