-
Notifications
You must be signed in to change notification settings - Fork 0
/
NextPieceProvider.pde
155 lines (125 loc) · 4.34 KB
/
NextPieceProvider.pde
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
class NextPieceProvider {
public boolean canProvideInfiniteBlocks() { return false; }
public ArrayList<Shape> getNextShapes() { return null; }
public Shape takeNextShape() { return null; }
}
class StandardNextPieceProvider extends NextPieceProvider {
private ArrayList<Shape> nextShapes;
StandardNextPieceProvider() {
nextShapes = new ArrayList<Shape>();
update();
}
public boolean canProvideInfiniteBlocks() { return true; }
public ArrayList<Shape> getNextShapes() { return nextShapes; }
public Shape takeNextShape() {
Shape nextShape = nextShapes.remove(0);
update();
return nextShape;
}
private void update() {
while (nextShapes.size() < TETRIS_SHAPES.length) {
ArrayList<Shape> newShapes = new ArrayList<Shape>();
for (int i = 0; i < TETRIS_SHAPES.length; ++i) {
newShapes.add(new Shape(TETRIS_SHAPES[i]));
}
while (!newShapes.isEmpty()) {
nextShapes.add(newShapes.remove((int)(Math.random() * newShapes.size())));
}
}
}
}
class PresetNextPieceProvider extends NextPieceProvider {
private ArrayList<Shape> nextShapes;
PresetNextPieceProvider(ArrayList<Shape> nextShapes) {
this.nextShapes = nextShapes;
}
public boolean canProvideInfiniteBlocks() { return false; }
public ArrayList<Shape> getNextShapes() { return nextShapes; }
public Shape takeNextShape() {
if (nextShapes.size() > 0) return nextShapes.remove(0);
else return null;
}
}
class RandomNextPieceProvider extends NextPieceProvider {
RandomNextPieceProvider() {
}
public boolean canProvideInfiniteBlocks() { return true; }
public ArrayList<Shape> getNextShapes() { return new ArrayList<Shape>(); }
public Shape takeNextShape() {
return TETRIS_SHAPES[(int)(Math.random() * TETRIS_SHAPES.length)];
}
}
class CompositeNextPieceProvider extends NextPieceProvider {
public ArrayList<NextPieceProvider> providers;
CompositeNextPieceProvider() {
providers = new ArrayList<NextPieceProvider>();
}
// If any of the providers have infinite blocks, this provider can too
public boolean canProvideInfiniteBlocks() {
for (int i = 0; i < providers.size(); ++i) {
if (providers.get(i).canProvideInfiniteBlocks()) return true;
}
return false;
}
// As soon as we hit an infinite block provider, we need to return since the blocks
// of providers following it can never be reached.
public ArrayList<Shape> getNextShapes() {
ArrayList<Shape> nextShapes = new ArrayList<Shape>();
for (int i = 0; i < providers.size(); ++i) {
NextPieceProvider provider = providers.get(i);
nextShapes.addAll(provider.getNextShapes());
if (provider.canProvideInfiniteBlocks()) return nextShapes;
}
return nextShapes;
}
public Shape takeNextShape() {
Shape nextShape;
for (int i = 0; i < providers.size(); ++i) {
nextShape = providers.get(i).takeNextShape();
if (nextShape != null) return nextShape;
}
return null;
}
}
class ToughestNextPieceProvider extends NextPieceProvider {
private TetrisGame game;
ToughestNextPieceProvider(TetrisGame game) {
this.game = game;
}
public boolean canProvideInfiniteBlocks() { return true; }
public ArrayList<Shape> getNextShapes() { return new ArrayList<Shape>(); }
public Shape takeNextShape() {
Shape worstShape = null;
int worstScore = 0; // High score value is bad, find the highest
for (int i = 0; i < TETRIS_SHAPES.length; ++i) {
Shape s = TETRIS_SHAPES[i];
int bestScore = -1;
for (int orientation = 0; orientation < 4; ++orientation) {
for (int col = 0; col < game.grid.cols; ++col) {
s = s.rotated();
// Create a new grid, insert the shape and score it
Grid tested = new Grid(game.grid);
int row = 0;
for (; row < tested.rows; ++row) {
if (!tested.isLegal(s, col, row)) {
--row;
break;
}
}
if (tested.placeShape(s, col, row)) {
// Score only counts if the dropped location was valid
int score = tested.scoreGrid();
if (bestScore == -1 || score < bestScore) {
bestScore = score;
}
}
}
}
if (bestScore > worstScore) {
worstScore = bestScore;
worstShape = s;
}
}
return worstShape;
}
}