From 7d57601c5e429730213eb61033cb1b0096226001 Mon Sep 17 00:00:00 2001 From: phisn Date: Tue, 14 May 2024 12:52:37 +0200 Subject: [PATCH] Refactor and start improving server --- package.json | 2 +- packages-dev/eslint-config-custom/index.js | 13 ++ .../dreamerv3/dreamerv3/configs.yaml | 6 +- .../learning-gym/dreamerv3/polyburn_env.py | 12 +- .../learning-gym/dreamerv3/polyburn_runner.py | 6 +- packages/learning-gym/dreamerv3/run.sh | 2 +- packages/learning-gym/src/game-environment.ts | 39 ++++-- packages/learning-gym/src/main.ts | 4 +- .../src/model/replay/runtime-from-replay.ts | 15 ++- packages/server/package.json | 2 +- packages/server/src/do-lobby/do-lobby.ts | 30 +++++ packages/server/src/index.ts | 50 ++------ .../api/leaderboard/leaderboard-router.ts | 0 .../api/leaderboard/validate-replay.ts | 0 .../src/{ => worker}/api/user/user-router.ts | 0 .../{ => worker}/api/world/world-router.ts | 0 .../domain/auth/jwt-creation-token.ts | 0 .../src/{ => worker}/domain/auth/jwt-token.ts | 0 .../src/{ => worker}/domain/auth/user.ts | 0 .../server/src/{ => worker}/domain/replay.ts | 0 .../server/src/{ => worker}/domain/replays.ts | 0 .../server/src/{ => worker}/domain/world.ts | 0 .../server/src/{ => worker}/domain/worlds.ts | 2 +- packages/server/src/{ => worker}/env.ts | 0 packages/server/src/worker/fetch.ts | 40 ++++++ .../src/{ => worker}/framework/db-schema.ts | 0 .../helper/user-from-authorization-header.ts | 0 .../src/{ => worker}/framework/trpc-router.ts | 0 .../server/src/{ => worker}/framework/trpc.ts | 0 packages/server/wrangler.toml | 1 + .../module-particles/particles-simulation.ts | 5 +- .../game/reward/default-reward-normalized.ts | 116 ++++++++++++++++++ .../src/game/reward/default-reward.ts | 7 +- .../src/game/reward/replay-follow-tracker.ts | 16 ++- yarn.lock | 8 +- 35 files changed, 284 insertions(+), 92 deletions(-) create mode 100644 packages/server/src/do-lobby/do-lobby.ts rename packages/server/src/{ => worker}/api/leaderboard/leaderboard-router.ts (100%) rename packages/server/src/{ => worker}/api/leaderboard/validate-replay.ts (100%) rename packages/server/src/{ => worker}/api/user/user-router.ts (100%) rename packages/server/src/{ => worker}/api/world/world-router.ts (100%) rename packages/server/src/{ => worker}/domain/auth/jwt-creation-token.ts (100%) rename packages/server/src/{ => worker}/domain/auth/jwt-token.ts (100%) rename packages/server/src/{ => worker}/domain/auth/user.ts (100%) rename packages/server/src/{ => worker}/domain/replay.ts (100%) rename packages/server/src/{ => worker}/domain/replays.ts (100%) rename packages/server/src/{ => worker}/domain/world.ts (100%) rename packages/server/src/{ => worker}/domain/worlds.ts (66%) rename packages/server/src/{ => worker}/env.ts (100%) create mode 100644 packages/server/src/worker/fetch.ts rename packages/server/src/{ => worker}/framework/db-schema.ts (100%) rename packages/server/src/{ => worker}/framework/helper/user-from-authorization-header.ts (100%) rename packages/server/src/{ => worker}/framework/trpc-router.ts (100%) rename packages/server/src/{ => worker}/framework/trpc.ts (100%) create mode 100644 packages/web-game/src/game/reward/default-reward-normalized.ts diff --git a/package.json b/package.json index c68470c3..b3749e1e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "postinstall": "yarn workspace server postinstall", "build": "turbo run build --no-daemon", - "dev": "turbo run dev --no-daemon", + "dev": "turbo run dev --no-daemon --concurrency 20", "lint": "turbo run lint --no-daemon", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "preview": "turbo run preview --no-daemon" diff --git a/packages-dev/eslint-config-custom/index.js b/packages-dev/eslint-config-custom/index.js index 25d9d2fc..13908030 100644 --- a/packages-dev/eslint-config-custom/index.js +++ b/packages-dev/eslint-config-custom/index.js @@ -28,6 +28,19 @@ module.exports = { eqeqeq: "error", "no-var": "error", + + "@typescript-eslint/no-unused-vars": [ + "error", + { + "args": "all", + "argsIgnorePattern": "^_", + "caughtErrors": "all", + "caughtErrorsIgnorePattern": "^_", + "destructuredArrayIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "ignoreRestSiblings": true + } + ] }, ignorePatterns: ["*.cjs", "vite.config.ts", "rollup.config.mjs"], } diff --git a/packages/learning-gym/dreamerv3/dreamerv3/configs.yaml b/packages/learning-gym/dreamerv3/dreamerv3/configs.yaml index 48f5cbf9..531f809e 100644 --- a/packages/learning-gym/dreamerv3/dreamerv3/configs.yaml +++ b/packages/learning-gym/dreamerv3/dreamerv3/configs.yaml @@ -14,7 +14,7 @@ defaults: prio: { exponent: 0.8, maxfrac: 0.5, initial: inf, zero_on_sample: True } priosignal: model recexp: 1.0 - chunksize: 1024 + chunksize: 4096 save_wait: False jax: @@ -196,7 +196,7 @@ defaults: symlog: True, outer: True, kernel: 5, - minres: 6, + minres: 4, } dec: spaces: ".*" @@ -215,7 +215,7 @@ defaults: winit: normal, outer: True, kernel: 5, - minres: 6, + minres: 4, block_space: 8, block_fans: False, block_norm: False, diff --git a/packages/learning-gym/dreamerv3/polyburn_env.py b/packages/learning-gym/dreamerv3/polyburn_env.py index ac30f9a2..11165483 100644 --- a/packages/learning-gym/dreamerv3/polyburn_env.py +++ b/packages/learning-gym/dreamerv3/polyburn_env.py @@ -17,7 +17,7 @@ def __init__(self, script_path): self.observation_space = spaces.Dict({ "image": spaces.Box(low=0, high=255, shape=(size, size, 3), dtype=np.uint8), - "features": spaces.Box(low=-1000, high=1000, shape=(4,), dtype=np.float32) + "features": spaces.Box(low=-1000, high=1000, shape=(6,), dtype=np.float32) }) self.action_space = spaces.Discrete(6) @@ -35,10 +35,10 @@ def step(self, action): self.restart_process() return self.reset(), 0, True, {} - data = self.process.stdout.read(size*size*3 + 4*4 + 4 + 1) + data = self.process.stdout.read(size*size*3 + 6*4 + 4 + 1) image = np.frombuffer(data[:size*size*3], dtype=np.uint8).reshape(size, size, 3) - features = np.frombuffer(data[size*size*3:size*size*3+ 4*4], dtype=np.float32) - reward = np.frombuffer(data[size*size*3 + 4*4:size*size*3 + 4*4 + 4], dtype=np.float32)[0] + features = np.frombuffer(data[size*size*3:size*size*3+ 6*4], dtype=np.float32) + reward = np.frombuffer(data[size*size*3 + 6*4:size*size*3 + 6*4 + 4], dtype=np.float32)[0] done = data[-1] == 1 return { "image": image, "features": features }, reward, done, {} @@ -51,7 +51,7 @@ def reset(self): command = command.encode("utf-8") self.process.stdin.write(command) self.process.stdin.flush() - data = self.process.stdout.read(size*size*3 + 4 * 4) + data = self.process.stdout.read(size*size*3 + 6 * 4) image = np.frombuffer(data[:size*size*3], dtype=np.uint8).reshape(size, size, 3) features = np.frombuffer(data[size*size*3:], dtype=np.float32) @@ -106,6 +106,6 @@ def close(self): o, r, _, _ = env.step(0) print(o["features"]) - # plt.show() + plt.show() env.close() diff --git a/packages/learning-gym/dreamerv3/polyburn_runner.py b/packages/learning-gym/dreamerv3/polyburn_runner.py index 15f37fc3..d99df64b 100644 --- a/packages/learning-gym/dreamerv3/polyburn_runner.py +++ b/packages/learning-gym/dreamerv3/polyburn_runner.py @@ -10,9 +10,9 @@ def main(): config = embodied.Config(dreamerv3.Agent.configs['defaults']) config = config.update({ - **dreamerv3.Agent.configs['size100m'], - 'logdir': f'./logdir/polyburn-1', - 'run.train_ratio': 32, + **dreamerv3.Agent.configs['size50m'], + 'logdir': f'./logdir/polyburn-2', + 'run.train_ratio': 16, }) config = embodied.Flags(config).parse() diff --git a/packages/learning-gym/dreamerv3/run.sh b/packages/learning-gym/dreamerv3/run.sh index ee57490e..0cccbc16 100644 --- a/packages/learning-gym/dreamerv3/run.sh +++ b/packages/learning-gym/dreamerv3/run.sh @@ -1,6 +1,6 @@ #!/bin/bash while true do - rm -rf /mnt/c/Users/Phisn/Repos/rocket-game/packages/learning-gym/dreamerv3/logdir/polyburn-1/replay + rm -rf /mnt/c/Users/Phisn/Repos/rocket-game/packages/learning-gym/dreamerv3/logdir/polyburn-2/replay python polyburn_runner.py done diff --git a/packages/learning-gym/src/game-environment.ts b/packages/learning-gym/src/game-environment.ts index e0321bc7..e501f112 100644 --- a/packages/learning-gym/src/game-environment.ts +++ b/packages/learning-gym/src/game-environment.ts @@ -62,7 +62,7 @@ export class GameEnvironment { // - distance to flag x // - distance to flag y // - flag in capture - this.observationFeatureBuffer = Buffer.alloc(4 * 4) + this.observationFeatureBuffer = Buffer.alloc(4 * 6) // image (3 channels) this.observationImageBuffer = Buffer.alloc( @@ -122,16 +122,32 @@ export class GameEnvironment { this.runtime = newRuntime(RAPIER as any, this.world, this.previousGamemode) - if (this.replayProcessed === undefined) { - const replayToFollow = - "CuUmcggAAAAACGaizaTNpGaeZp5momemZqrNqACozaTNpGWeZp4AAAFmomeeZ54AAAVmnmaiZ54AAAFnngAAAWaeZ55mngAABGaeAAACZ54AAAdmIs0kMyuaKTMtZyozLZopzChnKgAozShlIgAAAmYeZx5mHgAAAWYeAAAFZp5momeiZqZnomaeZ6Jmos2kZp5momeiZqJmogAABGeeAAAFZh5mImciZiJnIs0kzCTNJGciZh4AAAFnHgAADM2kzaRmps2kzajMpGeiZp5nnmaeAAABZ54AAAFmngAAWWaiZ6YAqACoZZ5momeeZp5nomaeZqJnngAAAWaeZqJnomaiZ54AAAJmnmeiZp4AAAJmngAACmYeZx4AAANmHmceAAAMZ55mnmaiZ6JmomeiZp5mngAAAmaiZ6IAAAFmomeeZqJnomaiZ55mnmaiZ55nos2kzKRongAAGWaiZ6Jmps2kzagAqGamZ55mngAACGYeAAABZiJnHmceZh5nHgAAAWYeZh5nHmYeAAABZx5mHs0kZh5mImciZh7NJGYiZibNJM0kzSQAKGYmZiZnJs0kZibNJGYiZibNJGcmzCQAKGcmZiaaKWYmACjNJGYiZh4AAAJmHmceZh5mIgAAAWcezSTNKMwkAChnImYiZx5nHgAABmYeAAABZh5nHmYeAAABZx4AADJnnmaeZqJnnmeeAAAHZp5nngAAAWaeZp5nnmaiZ6IAAAJmngAAC2aeZqJnns2kZp5momeeZ55momeiAAAOZp5momeeZqIAAAFnngAAAmaeAAABZ54AAAFmnmaiZ6ZmomaiZ55mos2kzaRmomaezaRmngAAAWaeAAAXZh4AAAdnHgAAAmYeZx4AAAFmHgAAAWYeAABTzaTMpGieZ6JmomaizaTNqM2oZqrNqGaszajNqDOrAKjNqGemZqbNpACozaTNpACoZqbNpGaiAAABZp4AAApmHgAABmYeAAACZx5mHmceZh5mHmciZh5mHmYiZyJmImceZh4AAAFnHmYeZh5nHmYeAAABZx5mHmYezSRmHmYiZyJmImcizSRlHmYiZx5mImciZh5mHmciZiJmImcmZiJmJmceZiJnHmYmZyZmJjMrzSgzK2cmzShmImYeZh4AABJmomeeZqJnnmaeZ6JmnmaeZp4AAAJnnmaeAAABZ55mngAAAmaeZ55mngAA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" + const replayToFollow = + "CuUmcggAAAAACGaizaTNpGaeZp5momemZqrNqACozaTNpGWeZp4AAAFmomeeZ54AAAVmnmaiZ54AAAFnngAAAWaeZ55mngAABGaeAAACZ54AAAdmIs0kMyuaKTMtZyozLZopzChnKgAozShlIgAAAmYeZx5mHgAAAWYeAAAFZp5momeiZqZnomaeZ6Jmos2kZp5momeiZqJmogAABGeeAAAFZh5mImciZiJnIs0kzCTNJGciZh4AAAFnHgAADM2kzaRmps2kzajMpGeiZp5nnmaeAAABZ54AAAFmngAAWWaiZ6YAqACoZZ5momeeZp5nomaeZqJnngAAAWaeZqJnomaiZ54AAAJmnmeiZp4AAAJmngAACmYeZx4AAANmHmceAAAMZ55mnmaiZ6JmomeiZp5mngAAAmaiZ6IAAAFmomeeZqJnomaiZ55mnmaiZ55nos2kzKRongAAGWaiZ6Jmps2kzagAqGamZ55mngAACGYeAAABZiJnHmceZh5nHgAAAWYeZh5nHmYeAAABZx5mHs0kZh5mImciZh7NJGYiZibNJM0kzSQAKGYmZiZnJs0kZibNJGYiZibNJGcmzCQAKGcmZiaaKWYmACjNJGYiZh4AAAJmHmceZh5mIgAAAWcezSTNKMwkAChnImYiZx5nHgAABmYeAAABZh5nHmYeAAABZx4AADJnnmaeZqJnnmeeAAAHZp5nngAAAWaeZp5nnmaiZ6IAAAJmngAAC2aeZqJnns2kZp5momeeZ55momeiAAAOZp5momeeZqIAAAFnngAAAmaeAAABZ54AAAFmnmaiZ6ZmomaiZ55mos2kzaRmomaezaRmngAAAWaeAAAXZh4AAAdnHgAAAmYeZx4AAAFmHgAAAWYeAABTzaTMpGieZ6JmomaizaTNqM2oZqrNqGaszajNqDOrAKjNqGemZqbNpACozaTNpACoZqbNpGaiAAABZp4AAApmHgAABmYeAAACZx5mHmceZh5mHmciZh5mHmYiZyJmImceZh4AAAFnHmYeZh5nHmYeAAABZx5mHmYezSRmHmYiZyJmImcizSRlHmYiZx5mImciZh5mHmciZiJmImcmZiJmJmceZiJnHmYmZyZmJjMrzSgzK2cmzShmImYeZh4AABJmomeeZqJnnmaeZ6JmnmaeZp4AAAJnnmaeAAABZ55mngAAAmaeZ55mngAABGeeAAACZp5mnmeeZp4AAAFnngAAHGaeAAAOZp5nngAAAWaeAAAEZ54AAChnHgAABGYeAAAPZx4AAANmHgAAB2YeZx5mHgAAAWceZh5mImceZx5mHmYezSRmIs0kZiJmJmciZyJmImciZiJmJmcizSTNKMwkAChnImYeZx4AAAJmHmceAAABZh4AAAFmHgAAAWceAAABZh4AABNmngAAAWeeAAABZp4AAAJmnmeeZp4AAAFnnmaeZqJnnmeiZZ5nomaeZqJnomaizaRmos2kZqJmnmeeAAASZqIAAAFnomaeZqJnngAAAmaiZ54AAAFnnmaeAAABZp5nnmaeAAAUZiJnIs0kZR5mHmceAAABZh4AABRnHgAABGYeZh5nHgAAAWYiZx7NJGYizSTNJMwkzSRnHmceZh5mHmceZh5nHgAAEmeeZp5nnmaiZ6JmomaizaTNpACozaRmpmamzaQAqGemZqJmps2kzajMpACozaTNpM2kZqLNpGaizaRmomaeZ6LNpACozKTNpGeeZ54AABBmngAABGaeZ54AAANmnmaiAAABZ55nomaizaQAAAFmnmaeZqJnngAAAWeeZp5mngAABGeeAAABZqJnnmaeZ54AAANmngAAEmYeAAAEZx4AAAFmHgAAAWYeZx4AAAFmImciZibNJGYiZyJmHmYiZyLNJGYiZh7NJGYiZibNJGcmZiJmJs0kzSRmImYiZyJmHmceAABZZ6JmnmaeZp5nogCoZqZmqs2oAKzNqDOrzahnpmamzaTNpMykzaRnpmamZqbNpM2kZp5nnmaiZ55mngAAB2YiZx5mImciZiJmImcezSRmJmcq/ydmJgAozSQAKM0kZx5mHgAABWYiAAABZyJmImcezSRmHmYiZx7NJGYiZibNJGcmZSLNJM0omSk0K2YmzCTNJGcezSRmImciZh5mHmYeZx5mHgAAAWceAAAEZh4AAA9mngAAAWeeAAAEZp5nnmaizaRmpmieZqLNpM2kZqZnnmaeAAABZ54AAAfNpGWeZ6JlnmeiZqYAqM2kZqZnogCoZqbNpGieZp4AAAFmnmeeZp5momeeAAABZ54AAAdnHgAAAWYeAAABZh4AAAJnHgAABWYeAAABZx4AAANmHgAAAWYeAAAIZp7NpM2o/6cAqGeiAKjNpGamZ6JmomeeZqJnngAADmeeAAAFZx5mHmYeZx5mHmceZh5mHmciZh5mHgAAAWYeZx5mHgAAAWceAAABZh4AAAVmHgAABGceAAACZh4AAAtnHgAAAWYeZh7NJM0kzSjMJGYmAChnJmYqAChnKv8nzSRoHmYeZh5nImYizSQAAAFmImYeZyJmImYmZyJmJs0kzShmJgAoZyr/J2Yumi1mLpowMy2ZLzQrmikAAAVpngAAAWaiZ6Jmqs2oAKwAqJqpAKiZqTSrZqYAqMykZ6ZmomaeZ55mnmaeAAAKACgAKAAsmikALGUmZyZmJmcmAAABZR4AAAJmomeiAKgAqJqpZaZnomeiAAABZqbNpACoZ6JlngAAAWeeZqIAAApmHmYeZx4AAAFmHgAAB2aeZ54AAAJmnmeeZp5mnmeeZp5nns2kZqLNpGWeZ54AAARmngAAPmaeZ6JmnmaeZp5nngAADGceAAABZiJnIs0kZiLNJGYiZh4AAC5nngAABWaeAAAoZh4AAAlnHgAAAWYeZh4AAB9nHgAAAWYeZiJnIgAAA2eezaRmpmeiZp5mngAAAWaeAAAFZ54AAARmngAAC2YeAAAEZx4AAAFmHmYeAAABZx4AAAFmIgAAAc0kZh5mImciZiJnJmYmAChmJmcmzSRmJpop/yfNJGYmzSTNJGYiZx4AAA9mngAAAWeeZp7NpGaeZqIAAAJnns2kzahmpmamZ55mpmemmqllomWeZ55mos2kZqJnngAAFWaeZ55mnmeeZp5momeiZqJnngAAcmaeAAABZ55mnmaeZ55momeeAAACZp5nngAACWaeZqJnogCoZqJnos2kZqYAqM2oZqbNpAAAAWaeZp5momemZZ5mngAABWYezSRmImYmzSRnImYeZiJnHmYizSTNJM0kZR5mJmciAChmJmcmAChmIs0kZh5mImceZiLNJGceAAAEZh4AAAJmHgAAAmceAAACZh4AAANnHgAAB2YeAAADZh4AABBmnmaeAAAwZ6JmomaiAAADzaRmnmeeAAAVZx5mHmYmZyJnIgAAE2eiZqJnnmaeZ57NpGWeZ54AAAFmngAAAWaeZ54AAAFmnmeeAAALZx4AAAFmHgAAAWceZh4AAApmpmeiZ6IAAAJmnmaeZqJnnmaiAAACZ57NpGaeAAABZp5nnmaeAAAFZ55mnmaeAAACZ6JmomamAAABaJ4AABFmHgAAAWceAAAEZh4AAB9nHgAAEWYeZh5nHgAAAWYeAAABZx5mHmYiZyJmIs0kZiIAKM0kzSRmIs0kZiJmHs0kzSTMJGgeZiIAAAFnHgAAAWceZh5mHgAAAWceZh4AAAFnHgAAAWYeZh4AAAFnHgAAAWYeZx5mHmYeZx4AAAFmHgAAAWceAAAbZ55mnmaizaTNqACoAKhmps2kZqJmomeiAABtZx4AAARmHgAAAmYeAAABZyIAAAJmHmYeZh4AAAFnHmYiZx5mHmciZiLNJGYeZiIAAARnHmYeZx5mHmYeZx7NJAAAAWUeZx4AAAtmHmceZiJnHmYmZyJnHgAABWeizaQAqMykzahmps2ozaRmogAAVmaeZ55mnmeeZp5mns2kZp5mnmeiAAABZp4AABRmnmaiZ57NpJqpZaZnpmaizaRmns2kZZ4AAAZmHmYeZx5mImceZiJnHmceZh4AAAFmHgAAAWceAAAPzahmpgCoZ6JlngAABWeeZqJnomaiZ55mps2kzahmomaeZqJnngAAAmeeZqJnngAAAWaeZ57NpGaiZqIAAAJnos2kZqJmnmaeZp7NpGaizaRmngAAA2YeZyJmIs0kzSRmImYmZyJmIs0kZh5mImciZiZnJpkpziQAKMwkZyYAKM0kZiJmImceZh5nHmYiZx5mHmceAAACZh5mImceZiJnImYeZx5mHmYeAAABZx5mHgAAAWceAAACZh4AAAJmHgAAE2ceAAABZiJnHmYiZx7NJGYiZiJnImYiZyIAAAFmHmYeAAAhZqZnos2kZqJnnmaeAAACZp4AAAxmHgAAB2YeAAArZx4AAAFmHgAADGaeAAABzaRmomamzaTNqGamZ6bMpGeizaTNpGWeAAAEZiJnHmYiZx5mHmceAAABZh4AAAJmngAAAWeezaRmomaizaRmns2kZqJmps2kZ6JmomeeAAADZx5mHs0kZiJmJgAoZyZmImYiZx5mImcezSRmImYmZyJnJswkZyJnImYiZiJnImYeAAACZh5nHmYeAAABZiIAAAFnHmceZh5nHmYeZh4AAAJnHgAABWYeZx5mHmYeZx5mHmceZh4AAAFmHmceZh5mIgAAAWciZiZnImYiZyJmImcizSRmImYeZh5mIgAAAWceAAABZyJmHgAAFWeiZqJmos2kZqJnogCozaQAqGamAKhnomaezaRmos2kZqLNpGaizaRlns2kZqIAAAhmHgAAP2aezaTNqMykzaSaqf+nAKzNqM2o/6fNqM2kZqZnnmeeZp5mos2kzaRmps2kzajMpGemZqLNpM2kZqJmnmaiZ54AAAZmHmciZiJmHs0kZiJnImYmzSTNJGYeZiJnHmYiZyIAAAFmHmYeZx5mHs0kZiJmImciZiLNJGYezSQAAAFmHmYiZyJmHmYiZyJmIs0kZiLNJGYiZh5nHmYeZx4AAAFmHgAAAWYiAAABZx5nHmYeZh4AAAFnHgAAAWYiZx7NJGYeZiJnHmYeZiJnIs0kZiLNKGYmZioAKDQrZiYAKMwkZyYAKGYmAAABZx4AABJmos2kZqbNpGemzKSaqc2ozKhnqs2omakAqJqpZqbNpGamzaRmpmeiAAARZh4AAAJmHgAAImceAAAPZh4AABdmnmeizaRmomamZ6Jmns2kZqJmomeeZqJnos2kZqJmomeeZqJnnmaeAAAMZ57NpGWeZ6JmomaiZ55nngAAAc2kZZ7NpGaezaTNpDOrmqmZqQCsmqkzq2aiZ54AAA3NJAAoACxmKpopzSzMKDMrmikzK5opZioAKAAozSTNJM0kZh5nHgAAAWYeZx4AAA9mHmYeZyJmImYiZyJmImceZiIAAAFnImYeZh5mIgAAAWceAAAFzaTNpMykZ6Jmps2kzaTNpGaiZp7NpGaeZqIAAARmHs0kzShmJgAoZiLNJGYiAAABZiJnHmYiZx5mImceAAABZx5mHgAAAWYeAAAFZx4AAAFmHgAABWceZh4AAAFmHmceZh5nHmYeZh5nHmYeZx5mHmYiAAAKZx4AAAFnHmYeAAAFZh4AAANnHmYeAAABZx4AAAhnngAABWaeAAABZqJnnmeiAAABZp5mnmaizaRmomeeAAABZ54AAAFmns2kZp5mngAAF2aiZ55nngAAAmaeZp7NpGaeZqJnnmeeZp5mos2kZqJnpmaiZp7NpGWezaRmns2kZZ5nnmaiZ6JmomeeZp5momemZqZmpgCoZ6JnpsykzahmpmemmakAqACozqTMpJqpAKgzq82omalnps2kZ55mnmaizaRmpmeiZ54AAAFmHmciZiZnIs0kmSkAKJopzSQAKGYmACxnKmYsAChnJgAoZiaaKWYmAChmJmciZyLNJGYiZiLNJGYmaB5mJmcizSRmHs0kZR5mImcmZiJmJmciZiZnImceZh5mImceZiJnImYeZx5mHmYiZx5nHmYeZh5nHgAAAWYiAAABZyJmHgAAAWYeZiJnHmceZiIAAAFnIgAAAmYeAAABZiJnImYeZh5nHmYeZh5nHmYeZiJnHmceZiJnImYeZh4AAAtmnmeeZqJmpmeizaTNpACoZqZnomaeZp4AAAFnos2kZqJmomaiZ57NpM2kAKjMpACoZ6LNpM2kAKhmomaiAAADzaRmomeeAAAMZh4AADKTAAAAAAkBEgAGAQsABAEKAAgBDQAFAQsABAE8AEkBngAKAQkACAEHAA8BCAAFAQgABAE5AAIBTgBYAWMAFQEoAAgBeQAcASoAAwGyAAgBIAAFAS8ACQEXAEgBLQAJAQgACgEEAA8BPAAOASUABgFOAAgBEAAOAcAABwEIAAUBDAAFAQcABgEIAAgBBQAEAUsACgEIAAcBBwAHAQoADwEcAAkBKgBAAWcAHQHxAB8BGwAKAQoABwEMAAMBCwAEARUAOAFzABwBDQAIAQoABQEPAAgBCgADAXMAGQELAAwBCgAGAREACQEWAAQBIwAFAREABQFeABkBFAAJARoADAEXAD4BLQAUAQwACAETAAgBHAAOAasADQE5AAYBKwANAZUAKgE7AAcBFwAy" - this.replayProcessed = processReplayForAgent( - ReplayModel.decode(Buffer.from(replayToFollow, "base64")), - this.runtime, - ) + this.replayProcessed = processReplayForAgent( + ReplayModel.decode(Buffer.from(replayToFollow, "base64")), + this.runtime, + ) + + // skip randomly first levels. dont skip the last level + const skipUntilLevel = Math.floor( + Math.random() * (this.replayProcessed.inputsInLevels.length - 1), + ) + + for (let i = 0; i < skipUntilLevel; ++i) { + for (const input of this.replayProcessed.inputsInLevels[i]) { + this.runtime.step(input) + } } + this.replayProcessed.inputsInLevels = this.replayProcessed.inputsInLevels.slice( + skipUntilLevel - 1, + ) + this.replayProcessed.positionsInLevels = this.replayProcessed.positionsInLevels.slice( + skipUntilLevel - 1, + ) + this.replayTracker = new ReplayFollowTracker(this.runtime, this.replayProcessed) this.game = new GameAgentWrapper( @@ -241,7 +257,7 @@ export class GameEnvironment { } prepareFeatureBuffer() { - for (const message of this.capturedCollector) { + for (const _ of this.capturedCollector) { this.targetFlag = nextFlag(this.runtime, this.rocket) } @@ -271,7 +287,10 @@ export class GameEnvironment { 8, ) - this.observationFeatureBuffer.writeFloatLE(inCapture ? 1 : -1, 12) + this.observationFeatureBuffer.writeFloatLE(dxTarget / 8, 12) + this.observationFeatureBuffer.writeFloatLE(dyTarget / 8, 16) + + this.observationFeatureBuffer.writeFloatLE(inCapture ? 1 : -1, 20) } generatePng(): Buffer { diff --git a/packages/learning-gym/src/main.ts b/packages/learning-gym/src/main.ts index 50f3fb7a..6b845b88 100644 --- a/packages/learning-gym/src/main.ts +++ b/packages/learning-gym/src/main.ts @@ -18,12 +18,14 @@ const worldStr4 = const world = WorldModel.decode(Buffer.from(worldStr4, "base64")) +const size = 96 + const environment = new GameEnvironment( world, ["Normal"], { grayScale: false, - size: 96, + size, pixelsPerUnit: 2.0, stepsPerFrame: 4, }, diff --git a/packages/runtime/src/model/replay/runtime-from-replay.ts b/packages/runtime/src/model/replay/runtime-from-replay.ts index 34ae3e72..46f96c33 100644 --- a/packages/runtime/src/model/replay/runtime-from-replay.ts +++ b/packages/runtime/src/model/replay/runtime-from-replay.ts @@ -1,7 +1,7 @@ import RAPIER from "@dimforge/rapier2d" import { ReplayModel } from "../../../proto/replay" import { WorldModel } from "../../../proto/world" -import { RuntimeSystemStack } from "../../core/runtime-system-stack" +import { RuntimeSystemContext, RuntimeSystemStack } from "../../core/runtime-system-stack" import { newRuntime } from "../../runtime" import { replayFramesFromBytes } from "./replay" @@ -11,7 +11,11 @@ export function runtimeFromReplay( world: WorldModel, gamemode: string, initializer?: (stack: RuntimeSystemStack) => T, - handler?: (stack: RuntimeSystemStack, context: T | undefined) => void, + handler?: ( + stack: RuntimeSystemStack, + step: RuntimeSystemContext, + context: T | undefined, + ) => void, ) { const replayFrames = replayFramesFromBytes(replay.frames) const stack = newRuntime(rapier, world, gamemode) @@ -23,12 +27,13 @@ export function runtimeFromReplay( for (const frame of replayFrames) { accumulator += frame.diff - stack.step({ + const step = { rotation: accumulator, thrust: frame.thrust, - }) + } - handler?.(stack, context) + stack.step(step) + handler?.(stack, step, context) } return stack diff --git a/packages/server/package.json b/packages/server/package.json index d443ed7b..1096d849 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -13,7 +13,7 @@ "author": "", "license": "ISC", "devDependencies": { - "@cloudflare/workers-types": "^4.20230821.0", + "@cloudflare/workers-types": "^4.20240512.0", "@types/node": "^20.5.7", "dotenv-cli": "^7.3.0", "drizzle-kit": "^0.20.14", diff --git a/packages/server/src/do-lobby/do-lobby.ts b/packages/server/src/do-lobby/do-lobby.ts new file mode 100644 index 00000000..0c582381 --- /dev/null +++ b/packages/server/src/do-lobby/do-lobby.ts @@ -0,0 +1,30 @@ +import { DurableObject } from "cloudflare:workers" +import { z } from "zod" + +export class DurableObjectLobby extends DurableObject { + async fetch(request: Request): Promise { + const { 0: client, 1: server } = new WebSocketPair() + + // why does server not have accept when all examples use it??? + ;(server as any).accept() + + server.addEventListener("message", event => { + const parsed = z + .object({ + type: z.string(), + }) + .safeParse(event.data) + + if (parsed.success) { + const t = parsed.data.type + } + + return undefined + }) + + return new Response(null, { + status: 101, + webSocket: client, + }) + } +} diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index dbf54a62..11ea80af 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,48 +1,12 @@ -import { fetchRequestHandler } from "@trpc/server/adapters/fetch" -import { Env } from "./env" -import { createContext } from "./framework/trpc" -import { appRouter } from "./framework/trpc-router" - -export default { - async fetch(request: Request, env: Env): Promise { - if (env.CLIENT_URL === undefined) { - throw new Error("CLIENT_URL is not defined") - } - - const headers = { - "Access-Control-Allow-Origin": "", - "Access-Control-Allow-Methods": "GET, POST, OPTIONS", - "Access-Control-Allow-Headers": "Content-Type, Authorization", - "Access-Control-Allow-Credentials": "true", - } - - if (env.CLIENT_URL.split(",").includes(request.headers.get("Origin") || "")) { - headers["Access-Control-Allow-Origin"] = request.headers.get("Origin") || "" - } - - if (request.method === "OPTIONS") { - return new Response(null, { - headers, - }) - } - - const response = await fetchRequestHandler({ - endpoint: "/trpc", - req: request, - router: appRouter, - createContext: createContext(env), - }) - - Object.entries(headers).forEach(([key, value]) => { - response.headers.set(key, value) - }) - - return response - }, -} +import { fetch } from "./worker/fetch" // initialize rapier wasm special for cloudflare workers import * as imports from "@dimforge/rapier2d/rapier_wasm2d_bg" import _wasm from "../../../node_modules/@dimforge/rapier2d/rapier_wasm2d_bg.wasm" - imports.__setWasm(new WebAssembly.Instance(_wasm, { "./rapier_wasm2d_bg.js": imports }).exports) + +export default { + fetch: fetch, +} + +export * from "./do-lobby/do-lobby" diff --git a/packages/server/src/api/leaderboard/leaderboard-router.ts b/packages/server/src/worker/api/leaderboard/leaderboard-router.ts similarity index 100% rename from packages/server/src/api/leaderboard/leaderboard-router.ts rename to packages/server/src/worker/api/leaderboard/leaderboard-router.ts diff --git a/packages/server/src/api/leaderboard/validate-replay.ts b/packages/server/src/worker/api/leaderboard/validate-replay.ts similarity index 100% rename from packages/server/src/api/leaderboard/validate-replay.ts rename to packages/server/src/worker/api/leaderboard/validate-replay.ts diff --git a/packages/server/src/api/user/user-router.ts b/packages/server/src/worker/api/user/user-router.ts similarity index 100% rename from packages/server/src/api/user/user-router.ts rename to packages/server/src/worker/api/user/user-router.ts diff --git a/packages/server/src/api/world/world-router.ts b/packages/server/src/worker/api/world/world-router.ts similarity index 100% rename from packages/server/src/api/world/world-router.ts rename to packages/server/src/worker/api/world/world-router.ts diff --git a/packages/server/src/domain/auth/jwt-creation-token.ts b/packages/server/src/worker/domain/auth/jwt-creation-token.ts similarity index 100% rename from packages/server/src/domain/auth/jwt-creation-token.ts rename to packages/server/src/worker/domain/auth/jwt-creation-token.ts diff --git a/packages/server/src/domain/auth/jwt-token.ts b/packages/server/src/worker/domain/auth/jwt-token.ts similarity index 100% rename from packages/server/src/domain/auth/jwt-token.ts rename to packages/server/src/worker/domain/auth/jwt-token.ts diff --git a/packages/server/src/domain/auth/user.ts b/packages/server/src/worker/domain/auth/user.ts similarity index 100% rename from packages/server/src/domain/auth/user.ts rename to packages/server/src/worker/domain/auth/user.ts diff --git a/packages/server/src/domain/replay.ts b/packages/server/src/worker/domain/replay.ts similarity index 100% rename from packages/server/src/domain/replay.ts rename to packages/server/src/worker/domain/replay.ts diff --git a/packages/server/src/domain/replays.ts b/packages/server/src/worker/domain/replays.ts similarity index 100% rename from packages/server/src/domain/replays.ts rename to packages/server/src/worker/domain/replays.ts diff --git a/packages/server/src/domain/world.ts b/packages/server/src/worker/domain/world.ts similarity index 100% rename from packages/server/src/domain/world.ts rename to packages/server/src/worker/domain/world.ts diff --git a/packages/server/src/domain/worlds.ts b/packages/server/src/worker/domain/worlds.ts similarity index 66% rename from packages/server/src/domain/worlds.ts rename to packages/server/src/worker/domain/worlds.ts index 4c9f41f4..a63c0492 100644 --- a/packages/server/src/domain/worlds.ts +++ b/packages/server/src/worker/domain/worlds.ts @@ -30,7 +30,7 @@ export const worlds: World[] = [ name: "Red 4", version: 1, }, - model: "", + model: "CvYCCgZOb3JtYWwS6wIKCg0zM9XBFTMzY0ISLQ2fbbnBFQPnFkIdPE0MOCUAAADCLVK4iUI1rkf5QT0fhf9BRQAAAEBNAAAAQBIoDVK4wUEVmZEaQiWF61FBLc3MUkI1KVynQj3NzERBRQAAAEBNAAAAQBIoDQCARUIV8hugQSUAAChCLQrXz0E1pHDhQj2uR1nBRQAAAEBNAAAAQBIoDXvUwEIVy5sdwSWamblCLQrXz0E1j8IjQz2uR1nBRQAAAEBNAAAAQBItDWzI4UIVOjK2QR1Ua7M6JZqZuUItKVxlQjVcjyNDPc3MiEFFAAAAQE0AAABAEi0NH+UBQxWT1U1CHZ9QNrUlpHD1Qi17FGxCNYXrQUM9AACUQUUAAABATQAAAEASKA3DVTNDFWmqQUIl16MkQy0Fb3hCNdejQkM9BW8AQkUAAABATQAAAEASKA2amebBFWQ7YEIlPYoRwi1xvY1CNQAAQMA9AAAAQkUAAABATQAAAEAK7goKDU5vcm1hbCBTaGFwZXMS3Aoa3wYK3AY/hQDCzcw0QaAQQABmNgAA////AHU8ABT///8AXk8AFP///wDJS0/E////ADNKDcv///8AwEkByP///wATRSbN////AIxUCjn///8Ak1GkOv///wBUTRZU////APS+VksAAP8AQ8jsGf///wCFw+U4AAD/AAVBmsX///8ANL0Xx////wAkwi7B////ALnG+8X///8A6snWt////wBzyKRA////AEDF9EX///8AaTGLSf///wCPQvFCAAD/AHXFZj3///8An8dkCVBQ/gDNxQG9AAD/APBAXMT///8AMMZHvf///wCzx5k+iIjxAHHFZDesrP8AXDcsxAAA/wDCQ1G0////ALZEo7j///8ASEF7wQAA/wBLRY88////AB1JpLH///8AzD9RyP///wDswE3G////AObGcb3///8AQsIUuv///wDDxQ6h////AArEKDgAAP8AuDw4wNnZ+wDiP03A////AKTEH78AAPAAcbCuvnh4+ABURFzC////AA/BdsD///8A9bQfQQAA+ABIu2e/////AAszrsMlJf8AUkCkv////wBmPi7A////AFy74cBNTf8AhTv7wf///wBcwrwt////AHvCMz8AAPgAcMLHwP///wAUQfvA////AAC+e8T///8A5MYKEv///wDpudxE////AIBB10AAAPgAH8DEsf///wAgv1E9AAD4AJnCq8b///8A4sIuRAAA+AAhxOvA////AO3BA8f///8A4slurP///wAuxHpDAAD4AP7HzMD///8A+0X3STIy/wAfuZlAJyf/AI3Eejy1tf8AgMCIRMrK/wBcQCBKAAD4AKXICpL///8Af0QbSf///wBLTKlE////ADFIgrswNOgA2MF1R////wDnzKPE////AIHIPUQwNOgAjMJgy////wCcyrczMDToAL5B6cX///8A3MZPRP///wC0wVJH////AHNFvzmWmP8AUkAsRDA06ACowik+MDToACDKIIX///8AA8QTvv///wDNPgVKc3X/ADPFYUIwNOgADbc9wpeX/wAZwuZAMDToAMw9Scm7vv8AWsbGwv///wDVNEZKMDToAIrCKTwwNOgATcClyf///wCvxJrA////AGzKCo////8AEcjzPTA06AAAAFPO////ABr3Awr0A83Mk0KPwmVA////AGa2XLz///8AFraOyDY2/wA7RIQ3AAD4AKS+u0S8vP8AbS44Rf///wDhRoc+////AD5CVcUAAPgACkHYvgAA+AB4MtVE////ABNIccAAAPgAOEDcQ////wCzQwq8AADwAM4/EzgAAPgASMFNQP///wCuPlM/cHT4ALIrD0NobPgAubp4PP///wApPgxI////AOE/LkIAAP8A9L9cQv///wD4RXo/AAD/AB2xe0Gnp/8AbMSkQQAA/wCKx8S5////ANfBUkj///8AmkRpR////wCFR/FA////AHtEDcUAAP8A10FPNQAA/wALwL1G////AEZChUT///8A9EykPP///wDuRLfIAAD/AMtH0cH///8AUsc2xwAA/wBHQc3B////AOy+0sYAAP8AAETmQP///wAPQkhG////APRE0kD///8ARUWpwP///wDcRKnDAAD/AC7CC0n///8ABEGoSP///wAtR1tJ////ADTUeSz///8AeMIAvf///wAXyznH////ALi+U8////8AwTU7x////wCGwgA+AAD4AFzFlcLt7f8AisSlQwAA+ACNxsPFy8v/AF1AXMX///8ASMj7wQAA4ABDQZm9////AAY3vsAVFf8A+UVcPP///wCKQTPCSEj4ANxCajL///8ACs0CCgdSZXZlcnNlEsECCg8NHJ0uQxWTmUVCHbPtmTYSKA2kcLrBFZfjFkIlAAAAwi0AAExCNQAAQME9H4X/QUUAAABATQAAAEASKA1SuMFBFZmRGkIlH4UAwi1m5olCNQAA+kE9AAAAQkUAAABATQAAAEASKA0AgEVCFfIboEElAABQQS2F61FCNaRwp0I9UrhOQUUAAABATQAAAEASKA171MBCFcubHcElNDMoQi0K189BNR4F4kI9rkdZwUUAAABATQAAAEASLQ1syOFCFToytkEdVGuzOiWamblCLVK41EE1XI8jQz1mZlrBRQAAAEBNAAAAQBItDR/lAUMVk9VNQh2fUDa1JaTwuUItexRlQjWFKyRDPQAAhkFFAAAAQE0AAABAEigNw1UzQxVpqkFCJQCA9UItAABsQjUAAEJDPQAAlEFFAAAAQE0AAABAEiEKBk5vcm1hbBIXCg1Ob3JtYWwgU2hhcGVzCgZOb3JtYWwSIwoHUmV2ZXJzZRIYCg1Ob3JtYWwgU2hhcGVzCgdSZXZlcnNl", gamemodes: ["Normal", "Reverse"], }, ] diff --git a/packages/server/src/env.ts b/packages/server/src/worker/env.ts similarity index 100% rename from packages/server/src/env.ts rename to packages/server/src/worker/env.ts diff --git a/packages/server/src/worker/fetch.ts b/packages/server/src/worker/fetch.ts new file mode 100644 index 00000000..96421387 --- /dev/null +++ b/packages/server/src/worker/fetch.ts @@ -0,0 +1,40 @@ +import { fetchRequestHandler } from "@trpc/server/adapters/fetch" +import { Env } from "./env" +import { createContext } from "./framework/trpc" +import { appRouter } from "./framework/trpc-router" + +export async function fetch(request: Request, env: Env): Promise { + if (env.CLIENT_URL === undefined) { + throw new Error("CLIENT_URL is not defined") + } + + const headers = { + "Access-Control-Allow-Origin": "", + "Access-Control-Allow-Methods": "GET, POST, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization", + "Access-Control-Allow-Credentials": "true", + } + + if (env.CLIENT_URL.split(",").includes(request.headers.get("Origin") || "")) { + headers["Access-Control-Allow-Origin"] = request.headers.get("Origin") || "" + } + + if (request.method === "OPTIONS") { + return new Response(null, { + headers, + }) + } + + const response = await fetchRequestHandler({ + endpoint: "/trpc", + req: request, + router: appRouter, + createContext: createContext(env), + }) + + Object.entries(headers).forEach(([key, value]) => { + response.headers.set(key, value) + }) + + return response +} diff --git a/packages/server/src/framework/db-schema.ts b/packages/server/src/worker/framework/db-schema.ts similarity index 100% rename from packages/server/src/framework/db-schema.ts rename to packages/server/src/worker/framework/db-schema.ts diff --git a/packages/server/src/framework/helper/user-from-authorization-header.ts b/packages/server/src/worker/framework/helper/user-from-authorization-header.ts similarity index 100% rename from packages/server/src/framework/helper/user-from-authorization-header.ts rename to packages/server/src/worker/framework/helper/user-from-authorization-header.ts diff --git a/packages/server/src/framework/trpc-router.ts b/packages/server/src/worker/framework/trpc-router.ts similarity index 100% rename from packages/server/src/framework/trpc-router.ts rename to packages/server/src/worker/framework/trpc-router.ts diff --git a/packages/server/src/framework/trpc.ts b/packages/server/src/worker/framework/trpc.ts similarity index 100% rename from packages/server/src/framework/trpc.ts rename to packages/server/src/worker/framework/trpc.ts diff --git a/packages/server/wrangler.toml b/packages/server/wrangler.toml index 175b1053..ecfb1b5a 100644 --- a/packages/server/wrangler.toml +++ b/packages/server/wrangler.toml @@ -5,6 +5,7 @@ compatibility_date = "2024-03-04" compatibility_flags = [ "nodejs_compat" ] usage_model = "unbound" +upload_source_maps = true [dev] port = 3002 diff --git a/packages/web-game/src/game/modules/module-particles/particles-simulation.ts b/packages/web-game/src/game/modules/module-particles/particles-simulation.ts index 4014716b..aeae827a 100644 --- a/packages/web-game/src/game/modules/module-particles/particles-simulation.ts +++ b/packages/web-game/src/game/modules/module-particles/particles-simulation.ts @@ -1,8 +1,7 @@ +import { makeCCW, quickDecomp } from "poly-decomp-es" import { Point } from "runtime/src/model/point" import * as SAT from "sat" import * as THREE from "three" - -import { makeCCW, quickDecomp } from "poly-decomp-es" import { ExtendedRuntime } from "../../runtime-extension/new-extended-runtime" import { Environment, aabbFromCircle, newEnvironment } from "./particle-environment" import { @@ -59,7 +58,7 @@ export class ParticleSimulation { this.polygons.push( new SAT.Polygon( new SAT.Vector(0, 0), - decomp.map(([x, y]) => new SAT.Vector(x, y)), + decomp.map(([x, y]: any) => new SAT.Vector(x, y)), ), ) } diff --git a/packages/web-game/src/game/reward/default-reward-normalized.ts b/packages/web-game/src/game/reward/default-reward-normalized.ts new file mode 100644 index 00000000..49e3cf19 --- /dev/null +++ b/packages/web-game/src/game/reward/default-reward-normalized.ts @@ -0,0 +1,116 @@ +import { EntityWith, MessageCollector } from "runtime-framework" +import { LevelCapturedMessage } from "runtime/src/core/level-capture/level-captured-message" +import { RocketDeathMessage } from "runtime/src/core/rocket/rocket-death-message" +import { RuntimeComponents } from "runtime/src/core/runtime-components" +import { Runtime } from "runtime/src/runtime" +import { ReplayFollowTracker } from "./replay-follow-tracker" + +export interface Reward { + next: (steps: () => void) => [number, boolean] +} + +export type RewardFactory = (game: Runtime, replay: ReplayFollowTracker) => Reward + +export class DefaultGameReward implements Reward { + private captureCollector: MessageCollector + private deathCollector: MessageCollector + + private rocket: EntityWith + private nextLevel: EntityWith | undefined + + private steps: number + private maxSteps: number + + private beenInCaptureFor: number + + constructor( + private runtime: Runtime, + private tracker: ReplayFollowTracker, + ) { + this.captureCollector = runtime.factoryContext.messageStore.collect("levelCaptured") + this.deathCollector = runtime.factoryContext.messageStore.collect("rocketDeath") + + this.rocket = runtime.factoryContext.store.find("rocket", "rigidBody")[0] + + // next level is nearest level that is not captured + this.nextLevel = nextFlag(runtime, this.rocket) + + this.steps = 0 + this.maxSteps = 10000 // ~~ 5 min + this.beenInCaptureFor = 0 + } + + next(steps: () => void): [number, boolean] { + let reward = -0.01 + steps() + ++this.steps + + if (this.steps >= this.maxSteps) { + return [-1, true] + } + + // step will return acc reward of 1.0 for each level + // we scale it down to 0.5 so that we on average need 50 frames to reach the next level + reward += 0.5 * this.tracker.step() + + for (const _ of this.deathCollector) { + return [-0.5, true] + } + + if (this.nextLevel!.components.level.inCapture) { + if (this.beenInCaptureFor < 4) { + reward += 0.1 + this.beenInCaptureFor++ + } else { + reward += 0.01 + } + } + + for (const _ of this.captureCollector) { + this.nextLevel = nextFlag(this.runtime, this.rocket) + this.beenInCaptureFor = 0 + + const noNextLevel = this.nextLevel === undefined + + return [1, noNextLevel] + } + + return [reward, false] + } + + findDistanceToLevel(flagEntity: EntityWith | undefined) { + if (flagEntity === undefined) { + return 0 + } + + const dx = + this.rocket.components.rigidBody.translation().x - flagEntity.components.level.flag.x + const dy = + this.rocket.components.rigidBody.translation().y - flagEntity.components.level.flag.y + return Math.sqrt(dx * dx + dy * dy) + } +} + +function nextFlag(runtime: Runtime, rocket: EntityWith) { + const distanceToFlag = (flagEntity: EntityWith) => { + const dx = rocket.components.rigidBody.translation().x - flagEntity.components.level.flag.x + const dy = rocket.components.rigidBody.translation().y - flagEntity.components.level.flag.y + return Math.sqrt(dx * dx + dy * dy) + } + + const uncapturedLevels = runtime.factoryContext.store + .find("level") + .filter(level => !level.components.level.captured) + + if (uncapturedLevels.length === 0) { + return undefined + } + + const nextLevel = uncapturedLevels + .map(level => [level, distanceToFlag(level)] as const) + .reduce(([minLevel, minDistance], [level, distance]) => + distance < minDistance ? [level, distance] : [minLevel, minDistance], + )[0] + + return nextLevel +} diff --git a/packages/web-game/src/game/reward/default-reward.ts b/packages/web-game/src/game/reward/default-reward.ts index 9a3566af..10226a3a 100644 --- a/packages/web-game/src/game/reward/default-reward.ts +++ b/packages/web-game/src/game/reward/default-reward.ts @@ -54,10 +54,7 @@ export class DefaultGameReward implements Reward { reward += 16 * this.tracker.step() - for (const message of this.deathCollector) { - const velocity = this.rocket.components.rigidBody.linvel() - const speed = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y) - + for (const _ of this.deathCollector) { return [-1, true] } @@ -70,7 +67,7 @@ export class DefaultGameReward implements Reward { this.hasBeenInCapture = true } - for (const message of this.captureCollector) { + for (const _ of this.captureCollector) { reward += Math.max(0, (1 - this.steps / this.maxSteps) * 500) + Math.max(0, (1 - this.stepsSinceCapture / (15 * 60)) * 500) diff --git a/packages/web-game/src/game/reward/replay-follow-tracker.ts b/packages/web-game/src/game/reward/replay-follow-tracker.ts index 37f8ca67..1f233d48 100644 --- a/packages/web-game/src/game/reward/replay-follow-tracker.ts +++ b/packages/web-game/src/game/reward/replay-follow-tracker.ts @@ -2,17 +2,19 @@ import { EntityWith, MessageCollector } from "runtime-framework" import { ReplayModel } from "runtime/proto/replay" import { LevelCapturedMessage } from "runtime/src/core/level-capture/level-captured-message" import { RuntimeComponents } from "runtime/src/core/runtime-components" +import { RuntimeSystemContext } from "runtime/src/core/runtime-system-stack" import { Point } from "runtime/src/model/point" import { runtimeFromReplay } from "runtime/src/model/replay/runtime-from-replay" import { Runtime } from "runtime/src/runtime" export interface ReplayProcessed { positionsInLevels: Point[][] + inputsInLevels: RuntimeSystemContext[][] } export function processReplayForAgent(replay: ReplayModel, runtime: Runtime): ReplayProcessed { - const time = Date.now() const positionsInLevels: Point[][] = [[]] + const inputsInLevels: RuntimeSystemContext[][] = [[]] const resultStack = runtimeFromReplay( runtime.factoryContext.rapier, @@ -22,9 +24,10 @@ export function processReplayForAgent(replay: ReplayModel, runtime: Runtime): Re stack => { return stack.factoryContext.messageStore.collect("levelCaptured") }, - (stack, context) => { - for (const message of context!) { + (stack, input, context) => { + for (const _ of context!) { positionsInLevels.push([]) + inputsInLevels.push([]) } const vector = stack.factoryContext.store @@ -35,6 +38,8 @@ export function processReplayForAgent(replay: ReplayModel, runtime: Runtime): Re x: vector.x, y: vector.y, }) + + inputsInLevels.at(-1)?.push(input) }, ) @@ -42,6 +47,7 @@ export function processReplayForAgent(replay: ReplayModel, runtime: Runtime): Re return { positionsInLevels, + inputsInLevels, } } @@ -67,7 +73,7 @@ export class ReplayFollowTracker { // returns progress step(): number { - for (const message of this.captureCollector) { + for (const _ of this.captureCollector) { this.level++ this.i = 0 } @@ -79,7 +85,7 @@ export class ReplayFollowTracker { const rocketPosition = this.rocket.components.rigidBody.translation() const previousI = this.i - while (true) { + for (;;) { if (this.i + 1 >= this.replayProcessed.positionsInLevels[this.level].length) { break } diff --git a/yarn.lock b/yarn.lock index 43ee3fb5..09ca1c51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1468,10 +1468,10 @@ resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240419.0.tgz#a6ec1ad8386c13fc533bfc5d8a37695c2c5ec2a0" integrity sha512-YJjgaJN2yGTkV7Cr4K3i8N4dUwVQTclT3Pr3NpRZCcLjTszwlE53++XXDnHMKGXBbSguIizaVbmcU2EtmIXyeQ== -"@cloudflare/workers-types@^4.20230821.0": - version "4.20240502.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20240502.0.tgz#261ac668a5283e20e7be06d0e2ba98cf47a7d788" - integrity sha512-OB1jIyPOzyOcuZFHWhsQnkRLN6u8+jmU9X3T4KZlGgn3Ivw8pBiswhLOp+yFeChR3Y4/5+V0hPFRko5SReordg== +"@cloudflare/workers-types@^4.20240512.0": + version "4.20240512.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20240512.0.tgz#a98a895460156a21f892aa45ae97be9f66056679" + integrity sha512-o2yTEWg+YK/I1t/Me+dA0oarO0aCbjibp6wSeaw52DSE9tDyKJ7S+Qdyw/XsMrKn4t8kF6f/YOba+9O4MJfW9w== "@cspotcode/source-map-support@0.8.1": version "0.8.1"