Game end works this way now:
[crack-attack.git] / src / BlockManager.h
blobd448e11536618e255d72e27bdb1d7bcd42611f73
1 /*
2 * BlockManager.h
3 * Daniel Nelson - 8/24/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
26 #ifndef BLOCKMANAGER_H
27 #define BLOCKMANAGER_H
29 #include <cassert>
31 using namespace std;
33 #include "Game.h"
34 #include "Block.h"
35 #include "Random.h"
36 #include "MetaState.h"
37 #include "X.h"
39 class ComboTabulator;
41 /* static */ class BlockManager {
42 public:
43 static void gameStart ( );
44 static void newAwakingBlock ( int x, int y, int pop_delay, int awake_delay,
45 ComboTabulator *combo, int pop_color );
47 static inline void newCreepRow ( )
49 if (!(MetaState::mode & CM_X))
50 if (Random::chanceIn(GC_NO_SPECIAL_BLOCK_CHANCE_IN))
51 special_block_location = -1;
52 else
53 special_block_location = Random::number(GC_PLAY_WIDTH);
54 else
55 if (Random::chanceIn(GC_X_NO_SPECIAL_BLOCK_CHANCE_IN))
56 special_block_location = -1;
57 else
58 special_block_location = Random::number(GC_PLAY_WIDTH);
60 for (int x = GC_PLAY_WIDTH; x--; )
61 newCreepBlock(x);
64 static inline void newBlock ( int x, int y, int flavor )
66 if (block_count == GC_BLOCK_STORE_SIZE) return;
68 int id = findFreeId();
69 allocateId(id);
70 Block &block = blockStore[id];
72 block.initializeStatic(x, y, flavor);
75 static inline void newBlock ( int x, int y, int flavor, int pop_delay,
76 int awake_delay, ComboTabulator *combo, int pop_color )
78 if (block_count == GC_BLOCK_STORE_SIZE) return;
80 int id = findFreeId();
81 allocateId(id);
82 Block &block = blockStore[id];
84 block.initializeAwaking(x, y, flavor, pop_delay, awake_delay, combo,
85 pop_color);
88 static inline void deleteBlock ( Block *block )
90 freeId(block->id);
93 static inline void shiftUp ( )
95 int c = block_count;
96 for (int n = 0; c; n++)
97 if (storeMap[n]) {
98 c--;
99 blockStore[n].y++;
103 static inline int generatePopDirection ( )
105 if (next_pop_direction & (1 << 3))
106 return next_pop_direction = (1 << 0);
107 else
108 return next_pop_direction <<= 1;
111 static inline int generatePopDirection ( int n )
113 int npd;
114 if (next_pop_direction & (1 << 3))
115 npd = next_pop_direction = (1 << 0);
116 else
117 npd = next_pop_direction <<= 1;
118 while (--n)
119 if (next_pop_direction & (1 << 3))
120 next_pop_direction = (1 << 0);
121 else
122 next_pop_direction <<= 1;
123 return npd;
126 static inline bool flavorMatch ( Block &block_1, Block &block_2 )
128 if (!X::wildActive())
129 return mapFlavorToBaseFlavor(block_1.flavor)
130 == mapFlavorToBaseFlavor(block_2.flavor);
131 else if (block_1.flavor != BF_WILD && block_2.flavor != BF_WILD)
132 return mapFlavorToBaseFlavor(block_1.flavor)
133 == mapFlavorToBaseFlavor(block_2.flavor);
134 else {
135 int f1;
136 if (block_1.flavor == BF_WILD)
137 f1 = X::wildFlavor(block_1);
138 else
139 f1 = mapFlavorToBaseFlavor(block_1.flavor);
140 if (block_2.flavor == BF_WILD)
141 return f1 == X::wildFlavor(block_2);
142 else
143 return f1 == mapFlavorToBaseFlavor(block_2.flavor);
147 static inline bool isNormalFlavor ( int flavor )
149 return flavor <= BF_NUMBER_NORMAL;
152 static inline bool isBaseFlavor ( int flavor )
154 return flavor <= BF_GRAY;
157 static inline bool isColorlessFlavor ( int flavor )
159 return flavor >= BF_GRAY && flavor <= BF_FINAL_GRAY_SPECIAL;
162 static inline bool isSpecialFlavor ( int flavor )
164 return flavor > BF_GRAY;
167 static inline bool isSpecialColorFlavor ( int flavor )
169 return flavor >= BF_SPECIAL_COLOR_1;
172 static inline int mapFlavorToBaseFlavor ( int flavor )
174 if (isBaseFlavor(flavor))
175 return flavor;
176 if (isSpecialColorFlavor(flavor))
177 return mapSpecialColorFlavorToColor(flavor);
178 return BF_GRAY;
181 // The following handle block flavor codes. Each special block flavor has
182 // a code which is distinct from it's flavor number. This code is used to
183 // dereference special flavor arrays.
185 static inline bool isColorlessCode ( int code )
187 return code <= mapSpecialFlavorToCode(BF_FINAL_GRAY_SPECIAL);
190 static inline int mapSpecialFlavorToCode ( int flavor )
192 return flavor - (BF_GRAY + 1);
195 static inline int mapSpecialColorFlavorToColor ( int flavor )
197 return flavor - BF_SPECIAL_COLOR_1;
200 static int block_count;
201 static Block blockStore[GC_BLOCK_STORE_SIZE];
202 static bool storeMap[GC_BLOCK_STORE_SIZE];
204 static int last_row_c[GC_PLAY_WIDTH], second_to_last_row_c[GC_PLAY_WIDTH];
206 private:
207 static void newCreepBlock ( int x );
209 static inline int findFreeId ( )
211 int n;
212 for (n = 0; storeMap[n]; n++);
213 return n;
216 static inline void allocateId ( int id )
218 assert(!storeMap[id]);
219 storeMap[id] = true;
220 block_count++;
223 static inline void freeId ( int id )
225 assert(storeMap[id]);
226 storeMap[id] = false;
227 block_count--;
230 static int next_pop_direction;
232 static int last_flavor_a, second_to_last_flavor_a;
233 static int last_flavor_c, second_to_last_flavor_c;
234 static int last_row_a[GC_PLAY_WIDTH], second_to_last_row_a[GC_PLAY_WIDTH];
235 static int special_block_location;
238 #endif