Skip to content

Commit 6c7f358

Browse files
Merge branch 'master' into public-release
2 parents 9dcdf59 + d836ec1 commit 6c7f358

File tree

9 files changed

+98
-16
lines changed

9 files changed

+98
-16
lines changed

client/src/client-config.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const DEFAULT_CONFIG = {
1414
showAllRobotRadii: false,
1515
showTimelineMarkers: true,
1616
showHealthBars: true,
17+
showPaintBars: false,
1718
showPaintMarkers: true,
1819
showMapXY: true,
1920
enableFancyPaint: true,
@@ -28,6 +29,7 @@ const configDescription: Record<keyof ClientConfig, string> = {
2829
showAllRobotRadii: 'Show all robot view and attack radii',
2930
showTimelineMarkers: 'Show user-generated markers on the timeline',
3031
showHealthBars: 'Show health bars below all robots',
32+
showPaintBars: 'Show paint bars below all robots',
3133
showPaintMarkers: 'Show paint markers created using mark()',
3234
showMapXY: 'Show X,Y when hovering a tile',
3335
enableFancyPaint: 'Enable fancy paint rendering',

client/src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const CLIENT_VERSION = '1.1.1'
1+
export const CLIENT_VERSION = '1.2.0'
22
export const SPEC_VERSION = '1'
33
export const BATTLECODE_YEAR: number = 2025
44
export const MAP_SIZE_RANGE = {

client/src/playback/Bodies.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ export class Body {
274274
if (focused || config.showHealthBars) {
275275
this.drawHealthBar(match, overlayCtx)
276276
}
277+
if (focused || config.showPaintBars) {
278+
this.drawPaintBar(match, overlayCtx, config.showHealthBars)
279+
}
277280
}
278281
}
279282

@@ -435,6 +438,21 @@ export class Body {
435438
ctx.fillRect(hpBarX, hpBarY, hpBarWidth * (this.hp / this.maxHp), hpBarHeight)
436439
}
437440

441+
private drawPaintBar(match: Match, ctx: CanvasRenderingContext2D, healthVisible: boolean): void {
442+
const dimension = match.currentRound.map.staticMap.dimension
443+
const interpCoords = this.getInterpolatedCoords(match)
444+
const renderCoords = renderUtils.getRenderCoords(interpCoords.x, interpCoords.y, dimension)
445+
const paintBarWidth = 0.8
446+
const paintBarHeight = 0.1
447+
const paintBarYOffset = 0.4 + (healthVisible ? 0.11 : 0)
448+
const paintBarX = renderCoords.x + 0.5 - paintBarWidth / 2
449+
const paintBarY = renderCoords.y + 0.5 + paintBarYOffset
450+
ctx.fillStyle = 'rgba(0,0,0,.3)'
451+
ctx.fillRect(paintBarX, paintBarY, paintBarWidth, paintBarHeight)
452+
ctx.fillStyle = '#c515ed'
453+
ctx.fillRect(paintBarX, paintBarY, paintBarWidth * (this.paint / this.maxPaint), paintBarHeight)
454+
}
455+
438456
protected drawLevel(match: Match, ctx: CanvasRenderingContext2D) {
439457
if (this.level <= 1) return
440458

engine/src/main/battlecode/common/RobotController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ public interface RobotController {
123123
*/
124124
int getMoney();
125125

126+
/**
127+
* Alias for getMoney
128+
*
129+
* @return the amount of money this robot's team has
130+
*
131+
* @battlecode.doc.costlymethod
132+
*/
133+
int getChips();
134+
126135
/**
127136
* Returns what UnitType this robot is.
128137
*

engine/src/main/battlecode/common/UnitType.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
package battlecode.common;
22

33
public enum UnitType {
4-
SOLDIER(200, 250, 5, 250, -1, 200, 10, 20, 20, -1, 0, 0),
5-
SPLASHER(300, 400, 50, 150, -1, 300, 50, 9, -1, 50, 0, 0),
4+
SOLDIER(200, 250, 5, 250, -1, 200, 10, 9, 20, -1, 0, 0),
5+
SPLASHER(300, 400, 50, 150, -1, 300, 50, 8, -1, 50, 0, 0),
66
MOPPER(100, 300, 0, 50, -1, 100, 30, 2, -1, -1, 0, 0),
77

8-
LEVEL_ONE_PAINT_TOWER(0, 25, 0, 1000, 1, 1000, 10, 9, 20, 10, 5, 0),
8+
LEVEL_ONE_PAINT_TOWER(0, 100, 0, 1000, 1, 1000, 10, 9, 20, 10, 5, 0),
99
LEVEL_TWO_PAINT_TOWER(0, 250, 0, 1500, 2, 1000, 10, 9, 20, 10, 10, 0),
1010
LEVEL_THREE_PAINT_TOWER(0, 500, 0, 2000, 3, 1000, 10, 9, 20, 10, 15, 0),
1111

12-
LEVEL_ONE_MONEY_TOWER(0, 25, 0, 1000, 1, 1000, 10, 9, 20, 10, 0, 10),
12+
LEVEL_ONE_MONEY_TOWER(0, 100, 0, 1000, 1, 1000, 10, 9, 20, 10, 0, 10),
1313
LEVEL_TWO_MONEY_TOWER(0, 250, 0, 1500, 2, 1000, 10, 9, 20, 10, 0, 15),
1414
LEVEL_THREE_MONEY_TOWER(0, 500, 0, 2000, 3, 1000, 10, 9, 20, 10, 0, 20),
1515

16-
LEVEL_ONE_DEFENSE_TOWER(0, 25, 0, 2500, 1, 1000, 10, 20, 60, 30, 0, 0),
16+
LEVEL_ONE_DEFENSE_TOWER(0, 100, 0, 2500, 1, 1000, 10, 20, 60, 30, 0, 0),
1717
LEVEL_TWO_DEFENSE_TOWER(0, 250, 0, 3000, 2, 1000, 10, 20, 65, 35, 0, 0),
1818
LEVEL_THREE_DEFENSE_TOWER(0, 500, 0, 3500, 3, 1000, 10, 20, 70, 40, 0, 0);
1919

engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ battlecode/common/RobotController/getAllLocationsWithinRadiusSquared 100 tru
4343
battlecode/common/RobotController/getHealth 1 true
4444
battlecode/common/RobotController/getID 1 true
4545
battlecode/common/RobotController/getPaint 1 true
46+
battlecode/common/RobotController/getChips 1 true
4647
battlecode/common/RobotController/getMoney 1 true
4748
battlecode/common/RobotController/getType 1 true
4849
battlecode/common/RobotController/getLocation 1 true

engine/src/main/battlecode/world/GameMapIO.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ public static LiveMap deserialize(battlecode.schema.GameMap raw, boolean teamsRe
236236
int[] patternArray = new int[4];
237237
for (int i = 0; i < wallArray.length; i++) {
238238
wallArray[i] = raw.walls(i);
239-
paintArray[i] = raw.paint(i);
239+
paintArray[i] = possiblyReversePaint(raw.paint(i), teamsReversed);
240240
}
241241
for (int i = 0; i < patternArray.length; i++){
242242
patternArray[i] = raw.paintPatterns(i);
@@ -294,6 +294,7 @@ public static int serialize(FlatBufferBuilder builder, LiveMap gameMap) {
294294
bodyTypes.add(FlatHelpers.getRobotTypeFromUnitType(robot.type));
295295
bodyLocsXs.add(robot.location.x);
296296
bodyLocsYs.add(robot.location.y);
297+
ruinArray[gameMap.locationToIndex(robot.location)] = true;
297298
}
298299

299300
for (int i = 0; i < gameMap.getWidth() * gameMap.getHeight(); i++) {
@@ -365,6 +366,19 @@ private static void initInitialBodiesFromSchemaBodyTable(InitialBodyTable bodyTa
365366
}
366367
}
367368

369+
// No color = 0, Team A color 1 = 1, Team A color 2 = 2, Team B color 1 = 3, Team B color 2 = 4
370+
private static byte possiblyReversePaint(byte originalPaint, boolean teamsReversed){
371+
if (!teamsReversed)
372+
return originalPaint;
373+
switch (originalPaint){
374+
case 1: return 3;
375+
case 2: return 4;
376+
case 3: return 1;
377+
case 4: return 2;
378+
default: return originalPaint;
379+
}
380+
}
381+
368382
private static int createSpawnActionsVector(FlatBufferBuilder builder, ArrayList<Integer> ids, ArrayList<Integer> xs, ArrayList<Integer> ys, ArrayList<Byte> teams, ArrayList<Byte> types){
369383
InitialBodyTable.startSpawnActionsVector(builder, ids.size());
370384
for (int i = 0; i < ids.size(); i++){

engine/src/main/battlecode/world/GameWorld.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,24 @@ public int getTowerPattern(UnitType towerType) {
576576
return this.patternArray[towerTypeToPatternIndex(towerType)];
577577
}
578578

579-
public boolean isValidPatternCenter(MapLocation loc) {
580-
return !(loc.x < GameConstants.PATTERN_SIZE / 2
579+
public boolean isValidPatternCenter(MapLocation loc, boolean isTower) {
580+
return (!(loc.x < GameConstants.PATTERN_SIZE / 2
581581
|| loc.y < GameConstants.PATTERN_SIZE / 2
582582
|| loc.x >= gameMap.getWidth() - (GameConstants.PATTERN_SIZE - 1) / 2
583583
|| loc.y >= gameMap.getHeight() - (GameConstants.PATTERN_SIZE - 1) / 2
584-
);
584+
)) && (isTower || areaIsPaintable(loc)) ;
585+
}
586+
587+
// checks that location has no walls/ruins in the surrounding 5x5 area
588+
public boolean areaIsPaintable(MapLocation loc){
589+
for (int dx = -GameConstants.PATTERN_SIZE / 2; dx < (GameConstants.PATTERN_SIZE + 1) / 2; dx++) {
590+
for (int dy = -GameConstants.PATTERN_SIZE / 2; dy < (GameConstants.PATTERN_SIZE + 1) / 2; dy++) {
591+
MapLocation newLoc = loc.translate(dx, dy);
592+
if (!isPaintable(newLoc))
593+
return false;
594+
}
595+
}
596+
return true;
585597
}
586598

587599
public boolean isPassable(MapLocation loc) {

engine/src/main/battlecode/world/RobotControllerImpl.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ public int getMoney() {
151151
return this.gameWorld.getTeamInfo().getMoney(getTeam());
152152
}
153153

154+
@Override
155+
public int getChips() {
156+
return this.getMoney();
157+
}
158+
154159
@Override
155160
public UnitType getType(){
156161
return this.robot.getType();
@@ -578,7 +583,7 @@ private void assertCanMarkTowerPattern(UnitType type, MapLocation loc) throws Ga
578583
+ ") because the center is not a ruin");
579584
}
580585

581-
if (!this.gameWorld.isValidPatternCenter(loc)) {
586+
if (!this.gameWorld.isValidPatternCenter(loc, true)) {
582587
throw new GameActionException(CANT_DO_THAT,
583588
"Cannot mark tower pattern centered at (" + loc.x + ", " + loc.y
584589
+ ") because it is too close to the edge of the map");
@@ -673,10 +678,10 @@ private void assertCanMarkResourcePattern(MapLocation loc) throws GameActionExce
673678
assertIsRobotType(this.robot.getType());
674679
assertCanActLocation(loc, GameConstants.RESOURCE_PATTERN_RADIUS_SQUARED);
675680

676-
if (!this.gameWorld.isValidPatternCenter(loc)) {
681+
if (!this.gameWorld.isValidPatternCenter(loc, false)) {
677682
throw new GameActionException(CANT_DO_THAT,
678683
"Cannot mark resource pattern centered at (" + loc.x + ", " + loc.y
679-
+ ") because it is too close to the edge of the map");
684+
+ ") because it is blocked or too close to the edge of the map");
680685
}
681686

682687
if (this.robot.getPaint() < GameConstants.MARK_PATTERN_PAINT_COST){
@@ -708,6 +713,20 @@ public void markResourcePattern(MapLocation loc, int rotationAngle, boolean refl
708713
this.gameWorld.markResourcePattern(getTeam(), loc, rotationAngle, reflect);
709714
}
710715

716+
private UnitType getBaseUnitType(UnitType type){
717+
UnitType baseType;
718+
switch (type){
719+
case LEVEL_TWO_DEFENSE_TOWER: baseType = UnitType.LEVEL_ONE_DEFENSE_TOWER; break;
720+
case LEVEL_THREE_DEFENSE_TOWER: baseType = UnitType.LEVEL_ONE_DEFENSE_TOWER; break;
721+
case LEVEL_TWO_MONEY_TOWER: baseType = UnitType.LEVEL_ONE_MONEY_TOWER; break;
722+
case LEVEL_THREE_MONEY_TOWER: baseType = UnitType.LEVEL_ONE_MONEY_TOWER; break;
723+
case LEVEL_TWO_PAINT_TOWER: baseType = UnitType.LEVEL_ONE_PAINT_TOWER; break;
724+
case LEVEL_THREE_PAINT_TOWER: baseType = UnitType.LEVEL_ONE_PAINT_TOWER; break;
725+
default: baseType = type;
726+
}
727+
return baseType;
728+
}
729+
711730
private void assertCanCompleteTowerPattern(UnitType type, MapLocation loc) throws GameActionException {
712731
assertIsRobotType(this.robot.getType());
713732
assertIsTowerType(type);
@@ -725,7 +744,13 @@ private void assertCanCompleteTowerPattern(UnitType type, MapLocation loc) throw
725744
+ ") because the center is not a ruin");
726745
}
727746

728-
if (!this.gameWorld.isValidPatternCenter(loc)) {
747+
if (getMoney() < getBaseUnitType(type).moneyCost){
748+
throw new GameActionException(CANT_DO_THAT,
749+
"Cannot complete tower pattern centered at (" + loc.x + ", " + loc.y
750+
+ ") because the team does not have enough money!");
751+
}
752+
753+
if (!this.gameWorld.isValidPatternCenter(loc, true)) {
729754
throw new GameActionException(CANT_DO_THAT,
730755
"Cannot complete tower pattern centered at (" + loc.x + ", " + loc.y
731756
+ ") because it is too close to the edge of the map");
@@ -768,6 +793,7 @@ public void completeTowerPattern(UnitType type, MapLocation loc) throws GameActi
768793
assertCanCompleteTowerPattern(type, loc);
769794
this.gameWorld.completeTowerPattern(getTeam(), type, loc);
770795
InternalRobot tower = this.gameWorld.getRobot(loc);
796+
this.gameWorld.getTeamInfo().addMoney(getTeam(), -getBaseUnitType(type).moneyCost);
771797
this.gameWorld.getMatchMaker().addSpawnAction(tower.getID(), loc, tower.getTeam(), type);
772798
this.gameWorld.getMatchMaker().addBuildAction(tower.getID());
773799
}
@@ -776,10 +802,10 @@ private void assertCanCompleteResourcePattern(MapLocation loc) throws GameAction
776802
assertIsRobotType(this.robot.getType());
777803
assertCanActLocation(loc, GameConstants.RESOURCE_PATTERN_RADIUS_SQUARED);
778804

779-
if (!this.gameWorld.isValidPatternCenter(loc)) {
805+
if (!this.gameWorld.isValidPatternCenter(loc, false)) {
780806
throw new GameActionException(CANT_DO_THAT,
781807
"Cannot complete resource pattern centered at (" + loc.x + ", " + loc.y
782-
+ ") because it is too close to the edge of the map");
808+
+ ") because it is blocked or too close to the edge of the map");
783809
}
784810

785811
boolean valid = this.gameWorld.checkResourcePattern(this.robot.getTeam(), loc);

0 commit comments

Comments
 (0)