Skip to content

Commit 6d00399

Browse files
Merge branch 'master' into public-release
2 parents d24cb4f + d4b4666 commit 6d00399

37 files changed

+329
-64
lines changed

client/src/client-config.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ const DEFAULT_CONFIG = {
2727
showAllRobotRadii: false,
2828
showTimelineMarkers: true,
2929
showHealthBars: true,
30-
showPaintBars: false,
30+
showPaintBars: true,
3131
showPaintMarkers: true,
32+
showSRPOutlines: true,
33+
showSRPText: false,
34+
showExceededBytecode: false,
3235
showMapXY: true,
3336
focusRobotTurn: true,
3437
enableFancyPaint: true,
@@ -58,6 +61,9 @@ const configDescription: Record<keyof ClientConfig, string> = {
5861
showHealthBars: 'Show health bars below all robots',
5962
showPaintBars: 'Show paint bars below all robots',
6063
showPaintMarkers: 'Show paint markers created using mark()',
64+
showSRPOutlines: 'Show outlines around active SRPs',
65+
showSRPText: 'Show remaining rounds in the center of inactive SRPs',
66+
showExceededBytecode: 'Show a red highlight over bots that exceeded their bytecode limit',
6167
showMapXY: 'Show X,Y when hovering a tile',
6268
focusRobotTurn: 'Focus the robot when performing their turn during turn-stepping mode',
6369
enableFancyPaint: 'Enable fancy paint rendering',

client/src/components/game/tournament-renderer/tournament-renderer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const TournamentRenderer: React.FC = () => {
1919
return (
2020
<div className="w-full h-screen relative">
2121
<Space ref={spaceRef} treatTwoFingerTrackPadGesturesLikeTouch={false}>
22-
{tournament && spaceRef.current ? (
22+
{tournament ? (
2323
<TournamentTree
2424
tournament={tournament}
2525
tournamentState={tournamentState}
@@ -38,7 +38,7 @@ export const TournamentRenderer: React.FC = () => {
3838
interface TournamentTreeProps {
3939
tournament: Tournament
4040
tournamentState: TournamentState
41-
spaceRef: Space
41+
spaceRef: Space | null
4242
winnerStart: number
4343
loserStart: number
4444
}
@@ -85,7 +85,7 @@ const TournamentTree: React.FC<TournamentTreeProps> = (props) => {
8585
interface TournamentGameWrapperProps {
8686
game: TournamentGame
8787
tournamentState: TournamentState
88-
spaceRef: Space
88+
spaceRef: Space | null
8989
winnerStart: number
9090
loserStart: number
9191
}
@@ -106,7 +106,7 @@ const TournamentGameWrapper: React.FC<TournamentGameWrapperProps> = (props) => {
106106
if (!wrapperRef.current) return
107107

108108
const wrapperRect = wrapperRef.current.getBoundingClientRect()
109-
const scale = props.spaceRef.viewPort?.zoomFactor ?? 1
109+
const scale = props.spaceRef?.viewPort?.zoomFactor ?? 1
110110
const startX = wrapperRect.x + wrapperRect.width / 2
111111
const startY = wrapperRect.y + wrapperRect.height - 17.45
112112

client/src/components/sidebar/sidebar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ export const Sidebar: React.FC = () => {
7474
React.useEffect(() => {
7575
if (localTournament) {
7676
setPage(PageType.TOURNAMENT)
77+
context.setState((prevState) => ({
78+
...prevState,
79+
tournament: new Tournament([])
80+
}))
7781
}
7882
}, [localTournament])
7983

client/src/components/sidebar/tournament/tournament.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ export const TournamentPage: React.FC<TournamentPageProps> = ({ open }) => {
8181
if (!tournament) return
8282

8383
// Reset state if it was not overridden
84-
console.log(tournamentShowLosers)
8584
context.setState((prevState) => ({
8685
...prevState,
8786
tournamentState: {

client/src/constants.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const CLIENT_VERSION = '1.4.3'
1+
export const CLIENT_VERSION = '2.0.0'
22
export const SPEC_VERSION = '1'
33
export const BATTLECODE_YEAR: number = 2025
44
export const MAP_SIZE_RANGE = {
@@ -21,7 +21,32 @@ export const DIRECTIONS: Record<number, Array<number>> = {
2121
8: [-1, 1]
2222
}
2323

24-
export const ENGINE_BUILTIN_MAP_NAMES: string[] = ['DefaultSmall', 'DefaultMedium', 'DefaultLarge', 'DefaultHuge']
24+
export const ENGINE_BUILTIN_MAP_NAMES: string[] = [
25+
// Default
26+
'DefaultSmall',
27+
'DefaultMedium',
28+
'DefaultLarge',
29+
'DefaultHuge',
30+
31+
// Sprint 1
32+
'Justice',
33+
'memstore',
34+
'Mirage',
35+
'MoneyTower',
36+
'Restart',
37+
'Thirds',
38+
'catface',
39+
'Fossil',
40+
'gardenworld',
41+
'Gears',
42+
'Money',
43+
'Racetrack',
44+
'SaltyPepper',
45+
'SMILE',
46+
'TargetPractice',
47+
'UglySweater',
48+
'UnderTheSea'
49+
]
2550

2651
export const TEAM_COLOR_NAMES = ['Silver', 'Gold']
2752

client/src/playback/Actions.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,18 +341,27 @@ export const ACTION_DEFINITIONS: Record<schema.Action, typeof Action<ActionUnion
341341
},
342342
[schema.Action.TransferAction]: class TransferAction extends Action<schema.TransferAction> {
343343
apply(round: Round): void {
344+
const src = round.bodies.getById(this.robotId)
344345
const amount = this.actionData.amount()
345346

346347
if (amount === 0) {
347348
/* ! SCUFFED SPECIAL CASE: Resource pattern completed ! */
349+
const center = round.map.indexToLocation(this.actionData.id())
350+
if (!round.map.resourcePatterns.find((srp) => srp.center.x === center.x && srp.center.y === center.y)) {
351+
round.map.resourcePatterns.push({
352+
center,
353+
teamId: src.team.id,
354+
createRound: round.roundNumber
355+
})
356+
}
357+
348358
return
349359
}
350360

351-
const src = round.bodies.getById(this.robotId)
352361
const dst = round.bodies.getById(this.actionData.id())
353362

354-
src.paint -= amount
355-
dst.paint += amount
363+
src.paint = Math.max(src.paint - amount, 0)
364+
dst.paint = Math.min(dst.paint + amount, dst.maxPaint)
356365
}
357366
draw(match: Match, ctx: CanvasRenderingContext2D): void {
358367
if (this.actionData.amount() === 0) {

client/src/playback/Bodies.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ export class Body {
272272
if (focused || config.showPaintBars) {
273273
this.drawPaintBar(match, ctx, focused || config.showHealthBars)
274274
}
275+
276+
// Draw bytecode overage indicator
277+
if (config.showExceededBytecode && this.bytecodesUsed >= this.metadata.bytecodeLimit()) {
278+
const pos = this.getInterpolatedCoords(match)
279+
const renderCoords = renderUtils.getRenderCoords(pos.x, pos.y, match.currentRound.map.staticMap.dimension)
280+
ctx.globalAlpha = 0.5
281+
ctx.fillStyle = 'red'
282+
ctx.fillRect(renderCoords.x, renderCoords.y, 1, 1)
283+
ctx.globalAlpha = 1.0
284+
}
275285
}
276286

277287
public draw(match: Match, ctx: CanvasRenderingContext2D): void {
@@ -494,7 +504,9 @@ export class Body {
494504
`Location: (${this.pos.x}, ${this.pos.y})`,
495505
`Move Cooldown: ${this.moveCooldown}`,
496506
`Action Cooldown: ${this.actionCooldown}`,
497-
`Bytecodes Used: ${this.bytecodesUsed}`
507+
`Bytecodes Used: ${this.bytecodesUsed}${
508+
this.bytecodesUsed >= this.metadata.bytecodeLimit() ? ' <EXCEEDED!>' : ''
509+
}`
498510
]
499511
if (this.indicatorString != '') {
500512
defaultInfo.push(`Indicator: ${this.indicatorString}`)

client/src/playback/Brushes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ export class PaintBrush extends SymmetricMapEditorBrush<CurrentMap> {
212212
const pos = this.map.indexToLocation(idx)
213213
const ruin = this.map.staticMap.ruins.find((r) => r.x === pos.x && r.y === pos.y)
214214
const wall = this.map.staticMap.walls[idx]
215-
if (ruin || wall) return true
215+
const body = this.bodies.getBodyAtLocation(pos.x, pos.y)
216+
if (body || ruin || wall) return true
216217
this.map.paint[idx] = value
217218
this.map.staticMap.initialPaint[idx] = this.map.paint[idx]
218219
}

client/src/playback/Map.ts

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ type SchemaPacket = {
2525
ruinsOffset: number
2626
}
2727

28+
type ResourcePatternData = {
29+
teamId: number
30+
center: Vector
31+
createRound: number
32+
}
33+
2834
export class CurrentMap {
2935
public readonly staticMap: StaticMap
3036
public readonly paint: Int8Array
3137
public readonly markers: [Int8Array, Int8Array] // Each team has markers
38+
public readonly resourcePatterns: ResourcePatternData[]
3239

3340
get width(): number {
3441
return this.dimension.width
@@ -48,12 +55,16 @@ export class CurrentMap {
4855
this.staticMap = from
4956
this.paint = new Int8Array(from.initialPaint)
5057
this.markers = [new Int8Array(this.width * this.height), new Int8Array(this.width * this.height)]
58+
this.resourcePatterns = []
5159
} else {
5260
// Create current map from current map (copy)
5361

5462
this.staticMap = from.staticMap
5563
this.paint = new Int8Array(from.paint)
5664
this.markers = [new Int8Array(from.markers[0]), new Int8Array(from.markers[1])]
65+
66+
// Assumes ResourcePatternData is immutable
67+
this.resourcePatterns = [...from.resourcePatterns]
5768
}
5869
}
5970

@@ -78,9 +89,34 @@ export class CurrentMap {
7889
}
7990

8091
/**
81-
* Mutates this currentMap to reflect the given turn.
92+
* Mutates this currentMap to reflect the given round.
8293
*/
83-
applyTurnDelta(turn: schema.Turn): void {}
94+
applyRoundDelta(round: Round, delta: schema.Round | null): void {
95+
// Update resource patterns and remove if they have been broken
96+
const patternMask = 28873275
97+
for (let i = 0; i < this.resourcePatterns.length; i++) {
98+
const srp = this.resourcePatterns[i]
99+
let patternIdx = 0
100+
let patternFailed = false
101+
for (let y = srp.center.y + 2; y >= srp.center.y - 2; y--) {
102+
for (let x = srp.center.x - 2; x <= srp.center.x + 2; x++) {
103+
const idx = this.locationToIndex(x, y)
104+
const expectedPaint = ((patternMask >> patternIdx) & 1) + (srp.teamId - 1) * 2 + 1
105+
const actualPaint = this.paint[idx]
106+
if (actualPaint !== expectedPaint) {
107+
this.resourcePatterns[i] = this.resourcePatterns[this.resourcePatterns.length - 1]
108+
this.resourcePatterns.pop()
109+
i--
110+
patternFailed = true
111+
break
112+
}
113+
patternIdx++
114+
}
115+
116+
if (patternFailed) break
117+
}
118+
}
119+
}
84120

85121
draw(
86122
match: Match,
@@ -152,6 +188,32 @@ export class CurrentMap {
152188
}
153189
}
154190
}
191+
192+
if (config.showSRPOutlines || config.showSRPText) {
193+
ctx.globalAlpha = 1
194+
ctx.lineWidth = 0.03
195+
this.resourcePatterns.forEach((srp) => {
196+
const topLeftCoords = renderUtils.getRenderCoords(srp.center.x - 2, srp.center.y + 2, this.dimension)
197+
const roundsRemaining = Math.max(srp.createRound + 50 - match.currentRound.roundNumber, -1)
198+
if (roundsRemaining >= 0 && config.showSRPText) {
199+
const label = roundsRemaining.toString()
200+
ctx.fillStyle = 'white'
201+
ctx.textAlign = 'right'
202+
ctx.font = '1px monospace'
203+
ctx.shadowColor = 'black'
204+
ctx.shadowBlur = 4
205+
ctx.scale(0.4, 0.4)
206+
ctx.fillText(label, (topLeftCoords.x + 3) * 2.5, (topLeftCoords.y + 2.5) * 2.5)
207+
ctx.scale(2.5, 2.5)
208+
ctx.shadowColor = ''
209+
ctx.shadowBlur = 0
210+
ctx.textAlign = 'start'
211+
} else if (roundsRemaining === -1 && config.showSRPOutlines) {
212+
ctx.strokeStyle = teamColors[srp.teamId - 1]
213+
ctx.strokeRect(topLeftCoords.x, topLeftCoords.y, 5, 5)
214+
}
215+
})
216+
}
155217
}
156218

157219
getTooltipInfo(square: Vector, match: Match): string[] {
@@ -163,6 +225,7 @@ export class CurrentMap {
163225
const paint = this.paint[schemaIdx]
164226
const wall = this.staticMap.walls[schemaIdx]
165227
const ruin = this.staticMap.ruins.find((r) => r.x === square.x && r.y === square.y)
228+
const srp = this.resourcePatterns.find((r) => r.center.x === square.x && r.center.y === square.y)
166229
const markerA = this.markers[0][schemaIdx]
167230
const markerB = this.markers[1][schemaIdx]
168231

@@ -186,6 +249,14 @@ export class CurrentMap {
186249
if (ruin) {
187250
info.push('Ruin')
188251
}
252+
if (srp) {
253+
const roundsRemaining = Math.max(srp.createRound + 50 - match.currentRound.roundNumber, 0)
254+
if (roundsRemaining === 0) {
255+
info.push(`${TEAM_COLOR_NAMES[srp.teamId - 1]} SRP Center (Active)`)
256+
} else {
257+
info.push(`${TEAM_COLOR_NAMES[srp.teamId - 1]} SRP Center (${roundsRemaining} Rounds Left)`)
258+
}
259+
}
189260

190261
return info
191262
}

client/src/playback/Round.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export default class Round {
5959

6060
this.roundNumber += 1
6161

62+
this.map.applyRoundDelta(this, this.currentDelta)
6263
this.stat.applyRoundDelta(this, this.currentDelta)
6364

6465
this.initialRoundState = null
@@ -125,7 +126,6 @@ export default class Round {
125126

126127
this.bodies.clearIndicators(turn.robotId())
127128

128-
this.map.applyTurnDelta(turn)
129129
this.actions.applyTurnDelta(this, turn)
130130
this.bodies.applyTurnDelta(this, turn)
131131

0 commit comments

Comments
 (0)