Each module now includes its own header first. Removed sstream.h and the definition...
[crack-attack.git] / src / GarbageGenerator.cxx
blob874a0e3868c2d87317b008c4860013bd5b8f5039
1 /*
2 * GarbageGenerator.cxx
3 * Daniel Nelson - 8/25/0
5 * Copyright (C) 2000 Daniel Nelson
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Daniel Nelson - aluminumangel.org
22 * 174 W. 18th Ave.
23 * Columbus, OH 43210
25 * Displays and sends garbage to the opponent.
28 #include "GarbageGenerator.h"
30 #include <iostream>
32 #include "Game.h"
33 #include "Block.h"
34 #include "BlockManager.h"
35 #include "Garbage.h"
36 #include "GarbageManager.h"
37 #include "ComboTabulator.h"
38 #include "Communicator.h"
39 #include "SparkleManager.h"
40 #include "SignManager.h"
41 #include "ComputerPlayer.h"
43 GarbageQueueElement GarbageGenerator::garbage_queue[GC_GARBAGE_QUEUE_SIZE];
44 int GarbageGenerator::waiting_count;
46 void GarbageGenerator::gameStart ( )
48 waiting_count = 0;
49 for (int n = GC_GARBAGE_QUEUE_SIZE; n--; )
50 garbage_queue[n].active = false;
53 void GarbageGenerator::comboElimination ( ComboTabulator &combo )
55 int sibling = (combo.multiplier > 1 ? 1 : 0);
57 // used by blocks to determine death spark number
58 combo.latest_magnitude = combo.special_magnitude + combo.magnitude
59 + combo.multiplier - 1;
61 // send the special garbage
63 bool special_sign = true;
64 for (int n = BF_NUMBER_SPECIAL; n--; ) {
65 if (combo.special[n]) {
66 special_sign = false;
67 SignManager::createSign(combo.x, combo.y, ST_SPECIAL, n + 1);
69 if (BlockManager::isColorlessCode(n))
70 combo.special_magnitude -= combo.special[n];
72 while (combo.special[n]--) {
73 sendSpecialGarbage(GarbageManager::mapBlockCodeToGarbageFlavor(n));
74 SparkleManager::createRewardMote(combo.x, combo.y, n + 4, sibling++);
76 combo.special[n] = 0;
80 // send the gray garbage
82 if (combo.special_magnitude >= GC_MIN_PATTERN_LENGTH) {
83 if (special_sign)
84 SignManager::createSign(combo.x, combo.y, ST_SPECIAL, 0);
86 combo.special_magnitude -= GC_MIN_PATTERN_LENGTH - 2;
87 while (--combo.special_magnitude) {
89 sendSpecialGarbage(GF_GRAY);
90 SparkleManager::createRewardMote(combo.x, combo.y, 3, sibling++);
93 } else
94 combo.special_magnitude = 0;
96 // send the normal garbage
98 if (combo.magnitude > GC_MIN_PATTERN_LENGTH) {
99 SignManager::createSign(combo.x, combo.y, ST_MAGNITUDE,
100 combo.magnitude - 4);
102 if (combo.magnitude <= GC_PLAY_WIDTH) {
104 sendGarbage(1, combo.magnitude - 1, GF_NORMAL);
105 SparkleManager::createRewardMote(combo.x, combo.y,
106 combo.magnitude - 4, sibling++);
108 } else if (combo.magnitude < 2 * GC_PLAY_WIDTH - 1) {
110 sendGarbage(1, combo.magnitude - (combo.magnitude >> 1),
111 GF_NORMAL);
112 SparkleManager::createRewardMote(combo.x, combo.y,
113 combo.magnitude - (combo.magnitude >> 1) - 3, sibling++);
115 sendGarbage(1, combo.magnitude >> 1, GF_NORMAL);
116 SparkleManager::createRewardMote(combo.x, combo.y,
117 (combo.magnitude >> 1) - 3, sibling++);
119 } else {
120 combo.magnitude += GC_MIN_PATTERN_LENGTH;
121 while (combo.magnitude > GC_PLAY_WIDTH - 1) {
123 sendGarbage(1, GC_PLAY_WIDTH - 1, GF_NORMAL);
124 SparkleManager::createRewardMote(combo.x, combo.y,
125 GC_PLAY_WIDTH - 4, sibling++);
127 combo.magnitude -= GC_PLAY_WIDTH - 1;
130 if (combo.magnitude >= GC_MIN_PATTERN_LENGTH) {
132 sendGarbage(1, combo.magnitude, GF_NORMAL);
133 SparkleManager::createRewardMote(combo.x, combo.y,
134 combo.magnitude - 3, sibling);
139 combo.magnitude = 0;
142 void GarbageGenerator::comboComplete ( ComboTabulator &combo )
144 // send the multiplier garbage
145 if (combo.multiplier > 1)
146 sendGarbage(combo.multiplier - 1, GC_PLAY_WIDTH, GF_NORMAL);
149 void GarbageGenerator::addToQueue ( GarbageBuffer &buffer )
151 addToQueue(buffer.garbage, buffer.count);
154 void GarbageGenerator::addToQueue (uint32 height, uint32 width, uint32 flavor, uint32 stamp)
156 assert(height <= GC_PLAY_HEIGHT);
157 assert(width <= GC_PLAY_WIDTH);
158 if (!GarbageManager::isSpecialFlavor(flavor))
159 dealLocalGarbage(height, width, flavor, stamp);
160 else
161 dealSpecialLocalGarbage(flavor, stamp);
164 void GarbageGenerator::addToQueue ( GarbageQueueElement &element )
166 int stamp = Game::time_step;
167 GarbageQueueElement e = element;
168 addToQueue(e.height, e.width, e.flavor, stamp);
171 void GarbageGenerator::addToQueue ( BufferElement *garbage, size_t size ) {
172 for (size_t n = 0; n < size; n++) {
173 BufferElement e = garbage[n];
174 addToQueue(e.height, e.width, e.flavor, e.time_stamp);
178 void GarbageGenerator::dealLocalGarbage ( int height, int width, int flavor,
179 int time_stamp )
181 * Used for solo games.
184 if (waiting_count == GC_GARBAGE_QUEUE_SIZE) return;
186 int i = 0;
187 while (garbage_queue[i].active) i++;
189 garbage_queue[i].active = true;
190 garbage_queue[i].height = height;
191 garbage_queue[i].width = width;
192 garbage_queue[i].flavor = flavor;
193 garbage_queue[i].alarm = determineDropTime(time_stamp);
195 waiting_count++;
198 void GarbageGenerator::dealSpecialLocalGarbage ( int flavor, int time_stamp )
200 switch (flavor) {
201 case GF_GRAY: case GF_WHITE: case GF_COLOR_2:
202 dealLocalGarbage(1, GC_PLAY_WIDTH, flavor, time_stamp);
203 break;
205 case GF_BLACK:
206 dealLocalGarbage(1, 2, GF_BLACK, time_stamp);
207 break;
209 case GF_COLOR_1:
210 if (Random::chanceIn2(4)) {
211 dealLocalGarbage(2, 2, GF_COLOR_1, time_stamp);
212 for (int n = 1 + Random::number(3); n--; )
213 dealLocalGarbage(1, 1, GF_COLOR_1, time_stamp);
214 } else
215 for (int n = 5 + Random::number(3); n--; )
216 dealLocalGarbage(1, 1, GF_COLOR_1, time_stamp);
217 break;
219 case GF_COLOR_3:
220 dealLocalGarbage(1, 4, GF_COLOR_3, time_stamp);
221 break;
223 case GF_COLOR_4:
224 dealLocalGarbage(1, 3, GF_COLOR_4, time_stamp);
225 break;
227 case GF_COLOR_5:
228 dealLocalGarbage(3, 2, GF_COLOR_5, time_stamp);
229 break;
233 void GarbageGenerator::timeStep ( )
235 int c = waiting_count;
237 for (int n = 0; c; n++)
238 if (garbage_queue[n].active) {
239 GarbageQueueElement &e = garbage_queue[n];
240 c--;
242 // if this garbage's ready, let's try to drop it
243 if (e.alarm < Game::time_step) {
244 // if we successfully drop it, take it away
245 if (GarbageManager::newFallingGarbage(e.height, e.width, e.flavor)) {
246 waiting_count--;
247 e.active = false;
249 // otherwise, reset the alarm
250 } else
251 e.alarm = Game::time_step + GC_AVERAGE_GARBAGE_DROP_DELAY;
256 void GarbageGenerator::sendGarbage ( int height, int width, int flavor )
258 if (!(MetaState::mode & CM_SOLO))
259 Communicator::sendGarbage(height, width, flavor);
260 else
261 if (MetaState::mode & CM_AI)
262 ComputerPlayer::addGarbage(height, width, flavor);
263 else
264 dealLocalGarbage(height, width, flavor, Game::time_step);
267 void GarbageGenerator::sendSpecialGarbage ( int flavor )
269 if (!(MetaState::mode & CM_SOLO))
270 Communicator::sendGarbage(0, 0, flavor);
271 else
272 if (MetaState::mode & CM_AI)
273 ComputerPlayer::addGarbage(1, GC_PLAY_WIDTH, flavor);
274 else
275 dealSpecialLocalGarbage(flavor, Game::time_step);