summaryrefslogtreecommitdiffstats
path: root/kfouleggs/board.cpp
blob: 836c7e1ecfcff96f9626d0a5b604b209cfbd0206 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "board.h"
#include "board.moc"

#include <kglobal.h>

#include "common/misc_ui.h"
#include "piece.h"


using namespace KGrid2D;

FEBoard::FEBoard(bool graphic, QWidget *parent)
: Board(graphic, new GiftPool(parent), parent),
  _field(matrix().width(), matrix().height()), _chainedPuyos(4)
{
    init();
}

void FEBoard::init()
{
    _nbPuyos  = 0;
    _chained  = 0;
    _giftRest = 0;
    _lastChained = 0;
    for (uint i=0; i<4; i++) {
      _chainedPuyos[i] = 0;
      _lastChained += (2<<i); // update
    }
}

void FEBoard::copy(const GenericTetris &g)
{
    Board::copy(g);
    _nbPuyos = static_cast<const FEBoard &>(g)._nbPuyos;
}

void FEBoard::start(const GTInitData &data)
{
    init();
    Board::start(data);
}

void FEBoard::computeInfos()
{
    Board::computeInfos();
    if ( graphic() ) computeNeighbours();
}

bool FEBoard::afterGlue(bool doAll, bool first)
{
    return !doFall(doAll, first, false);
}

void FEBoard::removeBlock(const Coord &c)
{
    Board::removeBlock(c);

    // remove surrounding garbage
    CoordList list = matrix().neighbours(c, true, true);
    for (CoordList::const_iterator i = list.begin(); i!=list.end(); ++i)
		if ( matrix()[*i]!=0 && matrix()[*i]->isGarbage() )
            Board::removeBlock(*i);
}

bool FEBoard::toBeRemoved(const Coord &c) const
{
    return ( _field[c]>=4 );
}

bool FEBoard::toFall(const Coord &c) const
{
    Coord under = c - Coord(0, 1);
    return ( matrix()[under]==0 );
}

void FEBoard::remove()
{
    Board::remove();

    // score calculation from another game
	// not sure it is the "official" way
	uint nbPuyos = _groups.size(); // number of group detroyed
	uint nbEggs = 0;               // number of eggs destroyed
	for (uint k=0; k<_groups.size(); k++) nbEggs += _groups[k];

	uint bonus = nbEggs - 3; // more than 4 since we are here !
	if ( nbEggs==11   ) bonus += 2;
	if ( nbPuyos>=2   ) bonus += 3 * (1 << (nbPuyos-2)); // 3 * 2^(nb-2)
	if ( _chained>=1  ) bonus += 1 << (_chained+2);      // 2^(chained+2)
	uint dscore = 10 * nbPuyos * bonus;

    uint i = kMin(_chained, (uint)3);
    _chainedPuyos[i] += nbPuyos;
    _lastChained = 2 << i;
	_chained++;
	_giftRest += dscore;
	_nbPuyos += nbPuyos;
	updateRemoved(nbRemoved() + nbEggs);
	updateScore(score() + dscore);

    updateLevel();
}

Board::AfterRemoveResult FEBoard::afterRemove(bool doAll, bool first)
{
    Board::AfterRemoveResult res = Board::afterRemove(doAll, first);
	if ( res==Done && needRemoving() ) return NeedRemoving;
	return res;
}

bool FEBoard::needRemoving()
{
    _groups = findGroups(_field, 4);
    if ( _groups.size()==0 ) _chained = 0;
	return _groups.size();
}

/*****************************************************************************/
// Multiplayers methods
uint FEBoard::gift()
{
	uint n   = _giftRest / 60;
	_giftRest = _giftRest % 60;
	return n;
}

bool FEBoard::putGift(uint n)
{
	QMemArray<bool> free(matrix().width());

	// garbage blocks are put randomly on conlumns with more than 5 free lines.
	uint nbFree = 0;
	for (uint i=0; i<free.size(); i++) {
		int f = firstColumnBlock(i);
		if ( f==-1 || f>=(int)matrix().height()-5 ) free[i] = false;
		else {
			free[i] = true;
			nbFree++;
		}
	}
	uint nb = kMin(nbFree, n);
	while (nbFree && nb) {
		uint k = (uint)randomGarbage.getLong(nbFree);
		uint l = 0;
		for (uint i=0; i<free.size(); i++) {
			if ( free[i]==false ) continue;
			if ( k==l ) {
				Block *gb = currentPiece()->garbageBlock();
				gb->sprite()->show();
                Coord c(i, matrix().height()-1);
				setBlock(c, gb);
				free[i] = false;
				nbFree--;
				nb--;
				break;
			}
			l++;
		}
	}
	return true;
}