Skip to content
This repository was archived by the owner on Jan 12, 2023. It is now read-only.

Commit 00f124e

Browse files
committed
feat: predecessors
1 parent 6b393de commit 00f124e

File tree

5 files changed

+67
-37
lines changed

5 files changed

+67
-37
lines changed

ui/src/logic/game/game.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export type GameSettings = {
1414
},
1515
game: {
1616
playerSize: number,
17-
maxGameLength: number,
17+
// maxGameLength: number,
1818
},
1919
map: {
2020
size: number,
@@ -77,7 +77,7 @@ export type GameState = {
7777
bullets: GameStateBullet[],
7878
/** index of game winner, if -1 game isn't over yet -2 if game is draw */
7979
winner: number,
80-
timeRemaining: number,
80+
// timeRemaining: number,
8181
};
8282

8383
export type SensorPoint = { point: Vector, type: "none" | "unknown" | EGameStateObjectType };
@@ -125,7 +125,7 @@ export class Game {
125125
},
126126
game: {
127127
playerSize: 10,
128-
maxGameLength: 10_000,
128+
// maxGameLength: 10_000,
129129
},
130130
simulation: {
131131
delta: 32,
@@ -142,11 +142,14 @@ export class Game {
142142
this.applyInput(userInput);
143143

144144
const delta = deltaOveride || deltaSettings;
145-
this.gameState.timeRemaining -= delta;
145+
// this.gameState.timeRemaining -= delta;
146+
147+
// if (this.gameState.timeRemaining <= 0) {
148+
// players.forEach(x => x.health = 0);
149+
// }
150+
151+
players.forEach(x => { x.health -= .002; });
146152

147-
if (this.gameState.timeRemaining <= 0) {
148-
players.forEach(x => x.health = 0);
149-
}
150153

151154
Engine.update(engine, delta);
152155

@@ -176,11 +179,9 @@ export class Game {
176179
let vec = Vector.rotate(Vector.create(1, 0), body.angle);
177180
vec = Vector.mult(vec, 5);
178181
Body.setVelocity(body, vec);
179-
player.health -= .0005;
180182
}
181183
if (x.rotate !== 0) {
182184
Body.setAngularVelocity(body, x.rotate * .3);
183-
player.health -= Math.abs(x.rotate) * .005;
184185
}
185186
if (x.use) {
186187
this.use(player);
@@ -206,9 +207,10 @@ export class Game {
206207
World.remove(world, x.p.body);
207208
});
208209

209-
if (alivePlayers.length === 1) {
210+
if (alivePlayers.length === 1 && alivePlayers[0].p.health >= .05) {
210211
this.gameState.winner = alivePlayers[0].i;
211212
} else if (alivePlayers.length === 0) {
213+
deadPlayers.forEach(x => x.p.health = 0);
212214
this.gameState.winner = -2;
213215
}
214216
}
@@ -237,8 +239,8 @@ export class Game {
237239
const { body: { position, angle }, item } = player;
238240
const { gameState: { bullets }, settings: { game: { playerSize } } } = this;
239241

240-
if (item.cooldown !== 0){
241-
player.health -= .2;
242+
if (item.cooldown !== 0) {
243+
// player.health -= .2;
242244
return;
243245
}
244246
item.cooldown = itemCooldown;
@@ -260,6 +262,7 @@ export class Game {
260262
health: 1,
261263
body,
262264
});
265+
// player.health -= .1;
263266
}
264267

265268
// todo: move all sensor related things into GameAI folder
@@ -331,7 +334,7 @@ export class Game {
331334
World.add(world, players);
332335

333336
this.gameState = {
334-
walls: walls.map(x=>({body:x, health:Infinity, type:EGameStateObjectType.wall})),
337+
walls: walls.map(x => ({ body: x, health: Infinity, type: EGameStateObjectType.wall })),
335338
players: players.map((body) =>
336339
({
337340
type: EGameStateObjectType.player,
@@ -342,7 +345,7 @@ export class Game {
342345
),
343346
bullets: [],
344347
winner: -1,
345-
timeRemaining: settings.game.maxGameLength,
348+
// timeRemaining: settings.game.maxGameLength,
346349
};
347350

348351
Events.on(this.engine, "collisionStart", this.onCollision.bind(this));

ui/src/logic/gameAi/GameAiEval.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Vector } from "matter-js";
22
import { IANNInitParams, NeuralNet } from "../ai/nn/nn";
3-
import { EGameStateObjectType, Game, GameInputPlayer, GameSettings, SensorPoint } from "../game/game";
3+
import { EGameStateObjectType, Game, GameInputPlayer, GameSettings, GameState, SensorPoint } from "../game/game";
44

55

66
export type InitializeRandomBotParams = {
@@ -53,7 +53,9 @@ export class GameAiEval {
5353
public static NN_OUTPUTS = 4;
5454
/** returns number of nn inputs for given sensors array */
5555
public static NN_INPUTS_GET({ sensors }: { sensors: number[] | { length: number } }) {
56-
return (sensors.length * 2 + 1) * 2;
56+
return (sensors.length * 2 + 1) * 2
57+
// health + cooldown
58+
+ 2;
5759
}
5860

5961
public static initializeRandomBot(params: InitializeRandomBotParams): NeuralNet {
@@ -65,9 +67,9 @@ export class GameAiEval {
6567
});
6668
}
6769

68-
private sensorAsNumbers(playerIndex: number, points: SensorPoint[]): number[] {
70+
private botInputs(playerIndex: number, points: SensorPoint[]): number[] {
6971
const { gameState: { players } } = this.game;
70-
const { body: { position } } = players[playerIndex];
72+
const { body: { position }, health, item: { cooldown } } = players[playerIndex];
7173

7274
const numbers: number[] = [];
7375

@@ -76,6 +78,8 @@ export class GameAiEval {
7678
numbers.push(dist(point, position), numFromType(type));
7779
}
7880

81+
numbers.push(health, cooldown);
82+
7983
return numbers;
8084
}
8185

@@ -100,7 +104,7 @@ export class GameAiEval {
100104
public calculateBotResponse() {
101105
const { game } = this;
102106
const { gameState: { players } } = this.game;
103-
const sensorsResults = players.map((_, i) => this.sensorAsNumbers(i, game.sensor(i)));
107+
const sensorsResults = players.map((_, i) => this.botInputs(i, game.sensor(i)));
104108
const botsNNResults = sensorsResults.map((x, i) => this.playerNNs[i].predict(x));
105109
const botsActions = botsNNResults.map(x => this.inputFromNN(x));
106110

ui/src/logic/gameAi/GameAiLiveTrain.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export type Bot = {
1616
wins: number,
1717
lastGame: number,
1818
nn: NeuralNet,
19+
children: number,
20+
predecessors: number[],
1921
};
2022

2123

@@ -26,7 +28,7 @@ export class GameAiLiveTrain {
2628
/** for how many games has bot healths */
2729
healthMultiplier: 4,
2830
/** how many hp will player get after game when survives */
29-
healthGrowAfterGame: .2,
31+
healthGrowAfterGame: 1.4,
3032
sensors: [Math.PI * 1 / 4, Math.PI * 1 / 8, Math.PI * 1 / 32],
3133
};
3234

@@ -36,7 +38,9 @@ export class GameAiLiveTrain {
3638
const bots = this.bots;
3739

3840
const selectedIndex: number[] = math.pickRandom(
39-
range(bots.length), 2, bots.map(x => Math.max(1, (x.lastGame - 1000) ** 3 - x.games + x.bonus + x.wins ** 2))
41+
range(bots.length), 2, bots.map(x => Math.max(1,
42+
((1 - x.health) * 10) ** 2 + x.lastGame - x.games - x.bonus + (x.wins) ** 2
43+
))
4044
) as any;
4145

4246
const selected = selectedIndex.map(x => bots[x]);
@@ -75,10 +79,9 @@ export class GameAiLiveTrain {
7579
const resHealth = evaler.game.gameState.players.map(x => x.health);
7680
resHealth.forEach((x, i) => {
7781
const bot = selected[i];
78-
bot.health += x / healthMultiplier;
79-
if (x > 0) bot.health += healthGrowAfterGame/healthMultiplier;
82+
bot.health += healthGrowAfterGame * x / healthMultiplier;
8083

81-
const exceedingHealth = (bot.health - healthMultiplier)*healthMultiplier;
84+
const exceedingHealth = (bot.health - healthMultiplier) * healthMultiplier;
8285
if (exceedingHealth > 0) {
8386
bot.health = this.params.healthMultiplier;
8487
const bonusMultiplier =
@@ -101,8 +104,14 @@ export class GameAiLiveTrain {
101104

102105
selected.forEach(x => { x.lastGame = 0; x.games++; });
103106

104-
if (populationToMaxFrac > .9) {
105-
bots.map(x => x.bonus += .05);
107+
if (populationToMaxFrac > .75) {
108+
bots.forEach(x => {
109+
x.bonus = Math.min(x.bonus * 5 + populationToMaxFrac, 2)
110+
});
111+
};
112+
113+
if (populationToMaxFrac > .8) {
114+
bots.map(x => x.bonus += .01 * populationToMaxFrac);
106115
}
107116

108117
if (bots.length < 10)
@@ -124,9 +133,11 @@ export class GameAiLiveTrain {
124133
const bot = bots[i];
125134
if (bot.bonus < 1) continue;
126135

136+
const ci = bot.children++;
137+
const predecessors = bot.predecessors.concat(ci);
127138
console.log("new bot created");
128139
bot.bonus--;
129-
bots.push({ bonus: 0, games: 0, wins: 0, health: this.params.healthMultiplier, lastGame: 0, nn: bot.nn.mutate(.01) });
140+
bots.push({ bonus: 0, games: 0, wins: 0, health: 1, lastGame: 0, nn: bot.nn.mutate(.01), children: 0, predecessors });
130141
}
131142
}
132143

@@ -136,13 +147,15 @@ export class GameAiLiveTrain {
136147
const { hiddens } = constructorParams;
137148
const { sensors } = params;
138149

139-
this.bots = range(params.maxPop).map(() => ({
150+
this.bots = range(params.maxPop).map((i) => ({
140151
bonus: 0,
141-
health: params.healthMultiplier,
152+
health: 1,
142153
games: 0,
143154
wins: 0,
144155
lastGame: 0,
145156
nn: GameAiEval.initializeRandomBot({ hiddens, sensors }),
157+
children: 0,
158+
predecessors: [i],
146159
}));
147160
}
148161
}

ui/src/views/MainPage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Card, Row, Col } from "antd";
2-
import React, { useState } from "react";
2+
import React, { useCallback, useState } from "react";
33
import { PlayPage } from "./Play";
44
import { RunAI } from "./RunAI";
55
import { NeuralNet } from "../logic/ai/nn/nn";
@@ -19,6 +19,8 @@ export const MainPage: React.FC<TMainPageProps> = () => {
1919
// const [aiSettings, setAiSettings] = useState<TSettingState>(defaultInitParams as any);
2020
const [snapshot, setSnapshot] = useState<NeuralNet[] | undefined>(undefined);
2121

22+
const callback = useCallback((e: NeuralNet[]) => setSnapshot(e), []);
23+
2224
return <>
2325
<Card>
2426
<Row gutter={[8, 0]}>
@@ -29,7 +31,7 @@ export const MainPage: React.FC<TMainPageProps> = () => {
2931
{/* <Col sm={8}> */}
3032
<Row gutter={[8, 8]}>
3133
<Col sm={8}>
32-
<RunAI onSnapshot={(e) => setSnapshot(e)} />
34+
<RunAI onSnapshot={callback} />
3335
</Col>
3436
<Col sm={16}>
3537
<PlayPage snapshot={snapshot} />

ui/src/views/RunAI.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const targetDeltaTime = 1_000 / fps;
1616

1717
type BotSnapshot = { bots: Bot[], popsize: number };
1818
const createBotSnapshot = (bots: Bot[], samples: number): BotSnapshot => {
19-
return { bots: bots.slice(0, samples).map(x => ({ ...x })), popsize: bots.length };
19+
return { bots: bots.slice(0, samples).map(x => ({ ...x, predecessors: x.predecessors.slice() })), popsize: bots.length };
2020
};
2121

2222

@@ -28,11 +28,14 @@ const BotData = ({ popsize, bots, calculations }: BotSnapshot & { calculations:
2828
</Row>
2929
<Row gutter={[0, 12]}>
3030
{
31-
bots.map(({ bonus, games, health, lastGame, wins }) => {
31+
bots.map(({ bonus, games, health, lastGame, wins, children, predecessors }) => {
3232
return <Col sm={24}>
3333
<Card>
3434
<Row>
3535
<Col sm={18}>
36+
<Row>
37+
{predecessors.map(x => x.toString(16).padStart(4, "0")).join("-")}
38+
</Row>
3639
<Row>
3740
<Progress percent={bonus * 100} status={"active"} strokeColor={"#f4f711"} format={() => ""}></Progress>
3841
</Row>
@@ -43,13 +46,16 @@ const BotData = ({ popsize, bots, calculations }: BotSnapshot & { calculations:
4346
<Col sm={6}>
4447
<Row>
4548
{games.toLocaleString().padStart(5, " ")} : Games
46-
</Row>
49+
</Row>
4750
<Row>
4851
{wins.toLocaleString().padStart(5, " ")} : Wins
49-
</Row>
52+
</Row>
53+
<Row>
54+
{children.toLocaleString().padStart(5, " ")} : children
55+
</Row>
5056
<Row>
5157
{lastGame.toLocaleString().padStart(5, " ")} : last
52-
</Row>
58+
</Row>
5359
</Col>
5460
</Row>
5561
</Card>
@@ -68,6 +74,8 @@ const fakeSnapshot: BotSnapshot = {
6874
games: randInt(1000),
6975
lastGame: randInt(1000),
7076
nn: undefined as any,
77+
children: randInt(1000),
78+
predecessors: range(randInt(1, 5)).map(() => randInt(100)),
7179
})), popsize: 100,
7280
};
7381

@@ -108,7 +116,7 @@ export const RunAI: React.FC<TRunProps> = ({ onSnapshot }) => {
108116

109117
setTimeout(() => {
110118
setLastUpdate(Date.now());
111-
});
119+
}, 15);
112120
}, [lastUpdate, setLastUpdate, running, onSnapshot]);
113121

114122

0 commit comments

Comments
 (0)