Skip to content

Commit 373d30d

Browse files
authored
Merge pull request #80 from JavaBWAPI/usebyteforcolor
Use byte for colorquad
2 parents 95b640d + 021dde6 commit 373d30d

File tree

4 files changed

+112
-48
lines changed

4 files changed

+112
-48
lines changed

src/main/java/bwapi/Color.java

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package bwapi;
22

3-
43
import java.util.HashMap;
54
import java.util.Map;
65
import java.util.Objects;
@@ -61,21 +60,7 @@ public final class Color {
6160
*/
6261
public final static Color Grey = new Color(74);
6362

64-
private final static Map<Integer, String> defaultColors = new HashMap<>();
65-
static {
66-
defaultColors.put(Color.Red.id, "Red");
67-
defaultColors.put(Color.Blue.id, "Blue");
68-
defaultColors.put(Color.Teal.id, "Teal");
69-
defaultColors.put(Color.Purple.id, "Purple");
70-
defaultColors.put(Color.Orange.id, "Orange");
71-
defaultColors.put(Color.Brown.id, "Brown");
72-
defaultColors.put(Color.White.id, "White");
73-
defaultColors.put(Color.Yellow.id, "Yellow");
74-
defaultColors.put(Color.Green.id, "Green");
75-
defaultColors.put(Color.Cyan.id, "Cyan");
76-
defaultColors.put(Color.Black.id, "Black");
77-
defaultColors.put(Color.Grey.id, "Grey");
78-
}
63+
private static Map<Integer, String> defaultColors = null;
7964

8065
private static final RGBQUAD RGBRESERVE = new RGBQUAD(0, 0, 0, 0xFF);
8166

@@ -114,8 +99,7 @@ public final class Color {
11499
RGBRESERVE, RGBRESERVE, RGBRESERVE, RGBRESERVE, RGBRESERVE, RGBRESERVE, RGBRESERVE, new RGBQUAD(255, 255, 255)
115100
};
116101

117-
private static boolean rgbInitialized;
118-
private static final int[][][] closestColor = new int[64][64][64];
102+
private static byte[][][] closestColor = null;
119103

120104
public final int id;
121105

@@ -139,7 +123,10 @@ public Color(final int red, final int green, final int blue) {
139123
* @param id The index of the color in the 256-color palette.
140124
*/
141125
public Color(final int id) {
142-
this.id = id;
126+
// The id is set to 255 if the id is invalid, as in the official BWAPI sources:
127+
// https://github.com/bwapi/bwapi/blob/3438abd8e0222f37934ba62b2130c3933b067678/bwapi/include/BWAPI/Color.h#L13
128+
// https://github.com/bwapi/bwapi/blob/3438abd8e0222f37934ba62b2130c3933b067678/bwapi/include/BWAPI/Type.h#L66
129+
this.id = id < 0 || id > 255 ? 255 : id;
143130
}
144131

145132
private static int getBestIdFor(final int red, final int green, final int blue) {
@@ -151,9 +138,9 @@ private static int getBestIdFor(final int red, final int green, final int blue)
151138
if (p.rgbReserved != 0) {
152139
continue;
153140
}
154-
final int r = red - p.rgbRed;
155-
final int g = green - p.rgbGreen;
156-
final int b = blue - p.rgbBlue;
141+
final int r = red - (p.rgbRed & 0xFF);
142+
final int g = green - (p.rgbGreen & 0xFF);
143+
final int b = blue - (p.rgbBlue & 0xFF);
157144

158145
final int distance = r * r + g * g + b * b;
159146
if (distance < min_dist) {
@@ -168,29 +155,29 @@ private static int getBestIdFor(final int red, final int green, final int blue)
168155
}
169156

170157
private static int getRGBIndex(final int red, final int green, final int blue) {
171-
if (!rgbInitialized) {
172-
rgbInitialized = true;
158+
if (closestColor == null) {
159+
closestColor = new byte[64][64][64];
173160
for (int r = 0; r < 64; ++r) {
174161
for (int g = 0; g < 64; ++g) {
175162
for (int b = 0; b < 64; ++b) {
176-
closestColor[r][g][b] = getBestIdFor(r << 2, g << 2, b << 2);
163+
closestColor[r][g][b] = (byte) getBestIdFor(r << 2, g << 2, b << 2);
177164
}
178165
}
179166
}
180167
}
181-
return closestColor[red >> 2][green >> 2][blue >> 2];
168+
return closestColor[red >> 2][green >> 2][blue >> 2] & 0xFF;
182169
}
183170

184171
public int red() {
185-
return id < 256 ? defaultPalette[id].rgbRed : 0;
172+
return defaultPalette[id].rgbRed & 0xFF;
186173
}
187174

188175
public int green() {
189-
return id < 256 ? defaultPalette[id].rgbGreen : 0;
176+
return defaultPalette[id].rgbGreen & 0xFF;
190177
}
191178

192179
public int blue() {
193-
return id < 256 ? defaultPalette[id].rgbBlue : 0;
180+
return defaultPalette[id].rgbBlue & 0xFF;
194181
}
195182

196183
@Override
@@ -208,8 +195,9 @@ public int hashCode() {
208195

209196
@Override
210197
public String toString() {
211-
if (defaultColors.containsKey(id)) {
212-
return "Color." + defaultColors.get(id);
198+
String defaultColor = getDefaultColor(id);
199+
if (defaultColor != null) {
200+
return "Color." + defaultColor;
213201
}
214202
return "Color{" +
215203
"red=" + red() +
@@ -219,20 +207,39 @@ public String toString() {
219207

220208
/// BROODWAR COLOR IMPLEMENTATION
221209
private static class RGBQUAD {
222-
final int rgbRed;
223-
final int rgbGreen;
224-
final int rgbBlue;
225-
final int rgbReserved;
210+
final byte rgbRed;
211+
final byte rgbGreen;
212+
final byte rgbBlue;
213+
final byte rgbReserved;
226214

227215
RGBQUAD(int rgbRed, int rgbGreen, int rgbBlue) {
228216
this(rgbRed, rgbGreen, rgbBlue, 0);
229217
}
230218

231219
RGBQUAD(int rgbRed, int rgbGreen, int rgbBlue, int rgbReserved) {
232-
this.rgbRed = rgbRed;
233-
this.rgbGreen = rgbGreen;
234-
this.rgbBlue = rgbBlue;
235-
this.rgbReserved = rgbReserved;
220+
this.rgbRed = (byte)rgbRed;
221+
this.rgbGreen = (byte) rgbGreen;
222+
this.rgbBlue = (byte)rgbBlue;
223+
this.rgbReserved = (byte)rgbReserved;
224+
}
225+
}
226+
227+
private static String getDefaultColor(final int id) {
228+
if (defaultColors == null) {
229+
defaultColors = new HashMap<>();
230+
defaultColors.put(Color.Red.id, "Red");
231+
defaultColors.put(Color.Blue.id, "Blue");
232+
defaultColors.put(Color.Teal.id, "Teal");
233+
defaultColors.put(Color.Purple.id, "Purple");
234+
defaultColors.put(Color.Orange.id, "Orange");
235+
defaultColors.put(Color.Brown.id, "Brown");
236+
defaultColors.put(Color.White.id, "White");
237+
defaultColors.put(Color.Yellow.id, "Yellow");
238+
defaultColors.put(Color.Green.id, "Green");
239+
defaultColors.put(Color.Cyan.id, "Cyan");
240+
defaultColors.put(Color.Black.id, "Black");
241+
defaultColors.put(Color.Grey.id, "Grey");
236242
}
243+
return defaultColors.getOrDefault(id,null);
237244
}
238245
}

src/main/java/bwapi/Player.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class Player implements Comparable<Player> {
2525
private final String name;
2626
private final PlayerType playerType;
2727
private final TilePosition startLocation;
28-
28+
private final Color color;
2929
private PlayerSelf self = null;
3030
PlayerSelf self() {
3131
if (self == null) {
@@ -41,6 +41,7 @@ PlayerSelf self() {
4141
this.name = playerData.getName();
4242
this.playerType = PlayerType.idToEnum[playerData.getType()];
4343
this.startLocation = new TilePosition(playerData.getStartLocationX(), playerData.getStartLocationY());
44+
this.color = new Color(playerData.getColor());
4445
}
4546

4647
/**
@@ -533,7 +534,7 @@ public boolean isUpgrading(final UpgradeType upgrade) {
533534
* @return {@link Color} object that represents the color of the current player.
534535
*/
535536
public Color getColor() {
536-
return new Color(playerData.getColor());
537+
return color;
537538
}
538539

539540
/**
@@ -543,7 +544,7 @@ public Color getColor() {
543544
* @return character code to use for text in Broodwar.
544545
*/
545546
public Text getTextColor() {
546-
switch (playerData.getColor()) {
547+
switch (color.id) {
547548
case 111: // red
548549
return Text.BrightRed;
549550
case 165: // blue

src/test/java/bwapi/ColorTest.java

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import org.junit.Test;
44

55
import static org.junit.Assert.assertEquals;
6-
6+
import static org.junit.Assert.assertArrayEquals;
77
public class ColorTest {
88

9-
private static int[][] colors = {
9+
private static final int[][] COLORS_ID_TO_RGB = {
1010
{0, 0, 0},
1111
{0, 0, 0},
1212
{0, 0, 0},
@@ -265,21 +265,73 @@ public class ColorTest {
265265
{255, 255, 255}
266266
};
267267

268+
// Amount of colors expected per ID for all colors generated by
269+
// R=0..256, G=0..256, B=0..256 . If the Color::getBestIdFor is not
270+
// correctly implemented, this will probably mismatch.
271+
static final int[] COLORS_RGB_TO_ID_BUCKETS = {
272+
1152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28608, 13184,
273+
14592, 30464, 17408, 33344, 13056, 57344, 27200, 16512, 47808,
274+
65152, 42176, 38080, 54784, 75584, 60352, 70016, 59200, 89792,
275+
36992, 42880, 50944, 72320, 2688, 16960, 27968, 24000, 21952,
276+
55104, 36992, 35392, 51712, 118016, 64320, 330624, 391424, 279040,
277+
70912, 133056, 128000, 134144, 77376, 18368, 31104, 56960, 53184,
278+
32000, 3584, 5312, 8448, 11712, 9728, 12416, 15168, 12608, 22720,
279+
20736, 26240, 47040, 31168, 54080, 41536, 60288, 58496, 97792,
280+
104896, 93312, 124352, 81152, 6976, 10048, 9920, 14592, 44224,
281+
8640, 24256, 6016, 13696, 38592, 22592, 73408, 41728, 15360,
282+
117696, 88704, 75776, 98752, 65216, 35840, 114304, 38912, 206464,
283+
179008, 80640, 25984, 94464, 268160, 255552, 58048, 80448, 381376,
284+
9856, 16576, 42304, 48640, 100736, 247808, 183040, 79616, 165120,
285+
47296, 227712, 85312, 55424, 67136, 108864, 135808, 194304, 35328,
286+
31680, 21632, 3072, 5120, 7040, 7936, 11392, 18048, 9984, 25536,
287+
19328, 38208, 31104, 36992, 65728, 81408, 108800, 139456, 304512,
288+
387648, 75264, 127360, 244608, 508160, 57344, 142464, 71936,
289+
294848, 1439616, 181632, 392832, 230848, 1664, 3264, 2304, 7552,
290+
24448, 38912, 128384, 281920, 53248, 84736, 42304, 65664, 42560,
291+
3072, 12672, 31744, 26624, 80000, 308480, 243328, 305792, 218752,
292+
220032, 253568, 11840, 31424, 45888, 62016, 82368, 70912, 100352,
293+
130560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
294+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
296+
};
297+
268298
@Test
269-
public void checkAllColors() {
299+
public void checkAllColorsIdToRGB() {
270300
for (int id=0; id < 256; id++) {
271301
Color c = new Color(id);
272-
assertEquals(colors[id][0], c.red());
273-
assertEquals(colors[id][1], c.green());
274-
assertEquals(colors[id][2], c.blue());
302+
assertEquals(COLORS_ID_TO_RGB[id][0], c.red());
303+
assertEquals(COLORS_ID_TO_RGB[id][1], c.green());
304+
assertEquals(COLORS_ID_TO_RGB[id][2], c.blue());
305+
}
306+
}
307+
308+
@Test
309+
public void checkAllColorsRGBToId() {
310+
final int[] buckets = new int[256];
311+
for (int r=0; r < 256; r++) {
312+
for (int g=0; g < 256; g++) {
313+
for (int b=0; b < 256; b++) {
314+
Color c = new Color(r, g, b);
315+
buckets[c.id] += 1;
316+
}
317+
}
275318
}
319+
assertArrayEquals(COLORS_RGB_TO_ID_BUCKETS, buckets);
320+
}
321+
322+
@Test
323+
public void checkColorWithInvalidId() {
324+
assertEquals(255, new Color(-1).id);
325+
assertEquals(255, new Color(256).id);
276326
}
277327

278328
@Test
279329
public void toStringTest() {
280330
assertEquals("Color.Black", Color.Black.toString());
281331
assertEquals("Color.Black", new Color(0, 0, 0).toString());
282332
assertEquals("Color.Black", new Color(Color.Black.id).toString());
333+
assertEquals("Color.Orange", Color.Orange.toString());
334+
assertEquals("Color.Purple", Color.Purple.toString());
283335
assertEquals("Color{red=16, green=16, blue=16}", new Color(16, 16, 16).toString());
284336
}
285337
}

src/test/java/game/DrawTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public void onFrame() {
2929
game.drawBoxScreen(200, 110, 350, 210, Color.Purple, true);
3030
game.drawTextScreen(50, 50, "%cHello %cWorld!", Text.Red, Text.Green);
3131

32+
Player self = game.self();
33+
Player enemy = game.enemy();
34+
String out = "%c"+ self.getName() + " (" + self.getRace() + ")%c vs %c" + enemy.getName() + " (" + enemy.getRace() + ")";
35+
game.drawTextScreen(20, 20, out, self.getTextColor(), Text.Default, enemy.getTextColor());
3236
}
3337

3438
public static void main(String[] args) {

0 commit comments

Comments
 (0)