From 4c59a5ddfbdbcbcf8733fd18ea68b910218d0134 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Mon, 27 Feb 2023 23:47:06 +0900 Subject: [PATCH 01/15] =?UTF-8?q?=E5=90=84=E3=83=A2=E3=82=B8=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E5=AE=9F=E8=A3=85=E3=82=92=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=82=92=E5=90=AB=E3=81=BE=E3=81=AA=E3=81=84type=E3=81=A7?= =?UTF-8?q?=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/module/any_module.ts | 5 -- .../modular_life_v2/module/assemble.ts | 54 ------------------- .../modular_life_v2/module/compute.ts | 24 --------- .../modular_life_v2/module/hull.ts | 44 --------------- .../modular_life_v2/module/index.ts | 5 -- .../modular_life_v2/module/module.ts | 46 +++++++++++++++- .../modular_life_v2/module/module_spec.ts | 52 ------------------ .../modular_life_v2/module/types.ts | 31 ----------- .../modular_life_v2/physics/scope.ts | 13 +++-- src/simulations/modular_life_v2/system.ts | 2 +- 10 files changed, 53 insertions(+), 223 deletions(-) delete mode 100644 src/simulations/modular_life_v2/module/any_module.ts delete mode 100644 src/simulations/modular_life_v2/module/assemble.ts delete mode 100644 src/simulations/modular_life_v2/module/compute.ts delete mode 100644 src/simulations/modular_life_v2/module/hull.ts delete mode 100644 src/simulations/modular_life_v2/module/index.ts delete mode 100644 src/simulations/modular_life_v2/module/module_spec.ts delete mode 100644 src/simulations/modular_life_v2/module/types.ts diff --git a/src/simulations/modular_life_v2/module/any_module.ts b/src/simulations/modular_life_v2/module/any_module.ts deleted file mode 100644 index 219de5a..0000000 --- a/src/simulations/modular_life_v2/module/any_module.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Assemble } from "./assemble" -import { Compute } from "./compute" -import { Hull } from "./hull" - -export type AnyModule = Assemble | Compute | Hull \ No newline at end of file diff --git a/src/simulations/modular_life_v2/module/assemble.ts b/src/simulations/modular_life_v2/module/assemble.ts deleted file mode 100644 index 83d756b..0000000 --- a/src/simulations/modular_life_v2/module/assemble.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Module } from "./types" -import { Result } from "../../../classes/result" -import { Hull, InternalModule } from "./hull" -import { Compute } from "./compute" -import { AnyModule } from "./any_module" -import { LifeSpec } from "./module_spec" - -export const isAssemble = (module: AnyModule): module is Assemble => { - return module.type === "assemble" -} - -export class Assemble extends Module<"assemble"> { - public readonly name = "Assembler" - public readonly type = "assemble" - - public get assembling(): Hull | null { - return this._assembling - } - - private _assembling: Hull | null = null - - public constructor( - hits: number, - hitsMax: number, - ) { - super(hits, hitsMax) - } - - public assemble(spec: LifeSpec): Result { - if (this.assembling != null) { - return Result.Failed("already assembling") - } - - const internalModules: InternalModule[] = spec.internalModuleSpecs.map(moduleSpec => { - switch (moduleSpec.case) { - case "assemble": - return new Assemble(moduleSpec.hits, moduleSpec.hitsMax) - case "compute": - return new Compute(moduleSpec.code, moduleSpec.hits, moduleSpec.hitsMax) - } - }) - this._assembling = new Hull(internalModules, spec.hullSpec.energyAmount, spec.hullSpec.hits, spec.hullSpec.hitsMax) - return Result.Succeeded(undefined) - } - - public release(): Hull | null { - if (this.assembling == null) { - return null - } - const assembling = this.assembling - this._assembling = null - return assembling - } -} \ No newline at end of file diff --git a/src/simulations/modular_life_v2/module/compute.ts b/src/simulations/modular_life_v2/module/compute.ts deleted file mode 100644 index a0b115f..0000000 --- a/src/simulations/modular_life_v2/module/compute.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { AnyModule } from "./any_module" -import { ComputeArgument, SourceCode } from "./source_code" -import { Module } from "./types" - -export const isCompute = (module: AnyModule): module is Compute => { - return module.type === "compute" -} - -export class Compute extends Module<"compute"> { - readonly name = "Computer" - readonly type = "compute" - - public constructor( - public readonly code: SourceCode, - hits: number, - hitsMax: number, - ) { - super(hits, hitsMax) - } - - public run(args: ComputeArgument): void { - this.code(args) - } -} \ No newline at end of file diff --git a/src/simulations/modular_life_v2/module/hull.ts b/src/simulations/modular_life_v2/module/hull.ts deleted file mode 100644 index 18e57bb..0000000 --- a/src/simulations/modular_life_v2/module/hull.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Result } from "../../../classes/result" -import { EnergyTransferable, EnergyWithdrawable } from "../physics/energy_transaction" -import type { AnyModule } from "./any_module" -import { Module } from "./types" - -export type InternalModule = Exclude - -export const isHull = (module: AnyModule): module is Hull => { - return module.type === "hull" -} - -// 最初はここに各機能を集約しておく -// Moduleに分割していく -export class Hull extends Module<"hull"> implements EnergyTransferable, EnergyWithdrawable { - public readonly name = "Hull" - public readonly type = "hull" - - public get energyAmount(): number { - return this._energyAmount - } - - public constructor( - public readonly internalModules: InternalModule[], - private _energyAmount: number, - hits: number, - hitsMax: number, - ) { - super(hits, hitsMax) - } - - public transferEnergy(amount: number): Result { - this._energyAmount += amount - return Result.Succeeded(undefined) - } - - public withdrawEnergy(amount: number): Result { - if (this.energyAmount < amount) { - return Result.Failed(`${this} lack of energy (${this.energyAmount} < ${amount})`) - } - - this._energyAmount -= amount - return Result.Succeeded(undefined) - } -} \ No newline at end of file diff --git a/src/simulations/modular_life_v2/module/index.ts b/src/simulations/modular_life_v2/module/index.ts deleted file mode 100644 index a45165c..0000000 --- a/src/simulations/modular_life_v2/module/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./any_module" -export * from "./assemble" -export * from "./compute" -export * from "./hull" -export * from "./types" diff --git a/src/simulations/modular_life_v2/module/module.ts b/src/simulations/modular_life_v2/module/module.ts index 4f6dd05..71e2f1a 100644 --- a/src/simulations/modular_life_v2/module/module.ts +++ b/src/simulations/modular_life_v2/module/module.ts @@ -1,3 +1,45 @@ -import * as Module from "./index" +import type { Scope } from "../physics/scope" +import type { SourceCode } from "./source_code" -export { Module } +export type ModuleType = "computer" | "assembler" | "hull" +export const getShortModuleName = (moduleType: ModuleType): string => { + switch (moduleType) { + case "assembler": + return "A" + case "computer": + return "C" + case "hull": + return "H" + default: { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const _: never = moduleType + throw new Error() + } + } +} + +export type Module = { + readonly case: T +} + +export type AnyModule = Assembler | Computer | Hull +export type GenericModule = T extends "computer" ? Computer : + T extends "assembler" ? Assembler : + T extends "hull" ? Hull : + never + +export type InternalModuleType = Exclude + +export type Hull = Module<"hull"> & Scope & { + hits: number + readonly hitsMax: number + readonly internalModules: { [M in InternalModuleType]: GenericModule[] } // HullはScope.hullに入っている + readonly size: number +} + +export type Computer = Module<"computer"> & { + readonly code: SourceCode +} + +export type Assembler = Module<"assembler"> & { +} diff --git a/src/simulations/modular_life_v2/module/module_spec.ts b/src/simulations/modular_life_v2/module/module_spec.ts deleted file mode 100644 index 90f1865..0000000 --- a/src/simulations/modular_life_v2/module/module_spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { SourceCode } from "./source_code" -import { getShortModuleName, ModuleType } from "./types" - -type ModuleSpecBase = { - readonly case: T - readonly hits: number - readonly hitsMax: number -} -export type AssembleSpec = { -} & ModuleSpecBase<"assemble"> - -export type ComputeSpec = { - readonly code: SourceCode -} & ModuleSpecBase<"compute"> - -export type HullSpec = { - readonly energyAmount: number -} & ModuleSpecBase<"hull"> - -export type ModuleSpec = AssembleSpec | ComputeSpec | HullSpec - -export type LifeSpec = { - readonly hullSpec: HullSpec - readonly internalModuleSpecs: (Exclude)[] -} - -export const describeLifeSpec = (spec: LifeSpec): string => { - const internalModules = new Map() - spec.internalModuleSpecs.forEach(module => { - const moduleCount = internalModules.get(module.case) ?? 0 - internalModules.set(module.case, moduleCount + 1) - }) - - const internalModuleDescriptions = Array.from(internalModules.entries()).map(([moduleType, count]): string => { - return `${count}${getShortModuleName(moduleType)}` - }) - - return `H(${internalModuleDescriptions.join("")})` -} - -const calculateModuleEnergyConsumption = (spec: ModuleSpec): number => { - return Math.ceil(spec.hits + spec.hitsMax * 0.3) -} - -export const calculateAssembleEnergyConsumption = (spec: LifeSpec): number => { - const hullGeneration = calculateModuleEnergyConsumption(spec.hullSpec) - const internalModuleGeneration = spec.internalModuleSpecs.reduce((result, moduleSpec) => { - return result + calculateModuleEnergyConsumption(moduleSpec) - }, 0) - - return spec.hullSpec.energyAmount + hullGeneration + internalModuleGeneration -} diff --git a/src/simulations/modular_life_v2/module/types.ts b/src/simulations/modular_life_v2/module/types.ts deleted file mode 100644 index 6b1206a..0000000 --- a/src/simulations/modular_life_v2/module/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type ModuleType = "compute" | "assemble" | "hull" -export const getShortModuleName = (moduleType: ModuleType): string => { - switch (moduleType) { - case "assemble": - return "A" - case "compute": - return "C" - case "hull": - return "H" - default: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const _: never = moduleType - throw new Error() - } - } -} - -export abstract class Module { - public abstract readonly name: string - public abstract readonly type: T - - public constructor( - public hits: number, - public readonly hitsMax: number, - ) { - } - - public toString(): string { - return `${this.constructor.name}` - } -} diff --git a/src/simulations/modular_life_v2/physics/scope.ts b/src/simulations/modular_life_v2/physics/scope.ts index 91ecbe0..b24c1d6 100644 --- a/src/simulations/modular_life_v2/physics/scope.ts +++ b/src/simulations/modular_life_v2/physics/scope.ts @@ -1,9 +1,12 @@ -export type Scope = { - energy: number - energyMax: number +import { Hull } from "../module/module" +import { MaterialType, Energy } from "../physics/material" + +type MaterialStore = { [Material in (MaterialType | Energy)]: number } +export type Scope = { + readonly amount: MaterialStore + capacity: number heat: number - material: number - materialMax: number + hull: Hull[] } \ No newline at end of file diff --git a/src/simulations/modular_life_v2/system.ts b/src/simulations/modular_life_v2/system.ts index 12f914b..b5a9a8d 100644 --- a/src/simulations/modular_life_v2/system.ts +++ b/src/simulations/modular_life_v2/system.ts @@ -1,3 +1,3 @@ export const System = { - version: "2.0.3" + version: "2.0.4" } as const \ No newline at end of file From 37e42bbc46ddb0ebc19af9c3fcb07af0bcd428b6 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Mon, 27 Feb 2023 23:47:27 +0900 Subject: [PATCH 02/15] =?UTF-8?q?=E7=89=A9=E7=90=86=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=82=92Engine=E3=81=A7=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/engine.ts | 17 +++++++++++++++++ src/simulations/modular_life_v2/world.ts | 13 +++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 src/simulations/modular_life_v2/engine.ts diff --git a/src/simulations/modular_life_v2/engine.ts b/src/simulations/modular_life_v2/engine.ts new file mode 100644 index 0000000..237ad22 --- /dev/null +++ b/src/simulations/modular_life_v2/engine.ts @@ -0,0 +1,17 @@ +import { PhysicalConstant } from "./physics/physical_constant" +import { TerrainCell } from "./terrain" + +export class Engine { + public constructor( + public readonly physicalConstant: PhysicalConstant, + ) { + } + + public calculateCell(cell: TerrainCell): void { + const energyLoss = Math.floor(cell.energy * this.physicalConstant.energyHeatConversionRate) + cell.energy = cell.energy - energyLoss + cell.energyProduction + cell.heat += energyLoss + + cell.heat = Math.floor(cell.heat * (1 - this.physicalConstant.heatLossRate)) + } +} \ No newline at end of file diff --git a/src/simulations/modular_life_v2/world.ts b/src/simulations/modular_life_v2/world.ts index ad70552..34fc53a 100644 --- a/src/simulations/modular_life_v2/world.ts +++ b/src/simulations/modular_life_v2/world.ts @@ -5,6 +5,7 @@ import type { ComputerApi } from "./module/api" import { Logger } from "./logger" import { Terrain, TerrainCell } from "./terrain" import { PhysicalConstant } from "./physics/physical_constant" +import { Engine } from "./engine" type Life = unknown // FixMe: @@ -18,13 +19,15 @@ export class World { private _t = 0 private _terrain: Terrain + private engine: Engine public constructor( public readonly size: Vector, public readonly logger: Logger, - public readonly physicalConstant: PhysicalConstant, + physicalConstant: PhysicalConstant, ) { this._terrain = new Terrain(size) + this.engine = new Engine(physicalConstant) } public addAncestor(life: Life, atPosition: Vector): Result { @@ -46,15 +49,9 @@ export class World { } private step(): void { - const {energyHeatConversionRate, heatLossRate} = this.physicalConstant - this.terrain.cells.forEach(row => { row.forEach(cell => { - const energyLoss = Math.floor(cell.energy * energyHeatConversionRate) - cell.energy = cell.energy - energyLoss + cell.energyProduction - cell.heat += energyLoss - - cell.heat = Math.floor(cell.heat * (1 - heatLossRate)) + this.engine.calculateCell(cell) }) }) From fab4fe38e2338de5c8bfa4d29958f0a215e73620 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Mon, 27 Feb 2023 23:57:46 +0900 Subject: [PATCH 03/15] =?UTF-8?q?=E6=9C=80=E3=82=82=E5=8D=98=E7=B4=94?= =?UTF-8?q?=E3=81=AA=E7=A5=96=E5=85=88=E7=A8=AE=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/ancestor/ancestor.ts | 28 +++++++++++++++---- .../modular_life_v2/ancestor/source_code.ts | 8 ++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/simulations/modular_life_v2/ancestor/ancestor.ts b/src/simulations/modular_life_v2/ancestor/ancestor.ts index 00b9eab..5cc895f 100644 --- a/src/simulations/modular_life_v2/ancestor/ancestor.ts +++ b/src/simulations/modular_life_v2/ancestor/ancestor.ts @@ -1,17 +1,35 @@ +import { Computer, Hull } from "../module/module" import { SourceCode } from "../module/source_code" +import { createScopeData } from "../physics/scope" /// 生命として成立する最小の祖先種 -export const createMinimumAncestor = (code: SourceCode): unknown => { // TODO: +export const createMinimumAncestor = (code: SourceCode): Hull => { // TODO: /* - 計算機 x 1 - 外殻 x 1 - - 推進器 x 1 + - 推進器 x 1 // TODO: */ - throw "not implemented" + + const computer: Computer = { + case: "computer", + code, + } + + return { + case: "hull", + hits: 0, + hitsMax: 1000, + size: 4, + internalModules: { + computer: [computer], + assembler: [], + }, + ...createScopeData(1000), + } } /// 自己複製できる最小の祖先種 -export const createMinimumSelfReproductionAncestor = (code: SourceCode): unknown => { // TODO: +export const createMinimumSelfReproductionAncestor = (code: SourceCode): Hull => { // TODO: /* - 計算機 x 1 - 物質輸送口 x 1 @@ -24,6 +42,6 @@ export const createMinimumSelfReproductionAncestor = (code: SourceCode): unknown } /// 自身より複雑な子孫を組み立てられる祖先種 -export const createGeneralAssemblerAncestor = (code: SourceCode): unknown => { // TODO: +export const createGeneralAssemblerAncestor = (code: SourceCode): Hull => { // TODO: throw "not implemented" } diff --git a/src/simulations/modular_life_v2/ancestor/source_code.ts b/src/simulations/modular_life_v2/ancestor/source_code.ts index 79877fe..174c7b3 100644 --- a/src/simulations/modular_life_v2/ancestor/source_code.ts +++ b/src/simulations/modular_life_v2/ancestor/source_code.ts @@ -1,8 +1,10 @@ -import { SourceCode } from "../module/source_code" +import { ComputeArgument, SourceCode } from "../module/source_code" /// ゲーム世界上で何も行わない export const createStillCode = (): SourceCode => { - return () => { - console.log("still code") + return ([, environment]: ComputeArgument) => { + if (environment.time % 100 === 0) { + console.log(`[still code] t: ${environment.time}`) + } } } From f642fb6c1cc850407ea6d664bffba90b2b32b899 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Mon, 27 Feb 2023 23:58:03 +0900 Subject: [PATCH 04/15] =?UTF-8?q?TerrainCell=E3=82=92Scope=E3=82=92?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=A6=E5=86=8D=E5=AE=9A=E7=BE=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/engine.ts | 4 ++-- src/simulations/modular_life_v2/physics/scope.ts | 14 ++++++++++++++ src/simulations/modular_life_v2/terrain.ts | 14 +++++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/simulations/modular_life_v2/engine.ts b/src/simulations/modular_life_v2/engine.ts index 237ad22..59dcfed 100644 --- a/src/simulations/modular_life_v2/engine.ts +++ b/src/simulations/modular_life_v2/engine.ts @@ -8,8 +8,8 @@ export class Engine { } public calculateCell(cell: TerrainCell): void { - const energyLoss = Math.floor(cell.energy * this.physicalConstant.energyHeatConversionRate) - cell.energy = cell.energy - energyLoss + cell.energyProduction + const energyLoss = Math.floor(cell.amount.energy * this.physicalConstant.energyHeatConversionRate) + cell.amount.energy = cell.amount.energy - energyLoss + cell.energyProduction cell.heat += energyLoss cell.heat = Math.floor(cell.heat * (1 - this.physicalConstant.heatLossRate)) diff --git a/src/simulations/modular_life_v2/physics/scope.ts b/src/simulations/modular_life_v2/physics/scope.ts index b24c1d6..1f068b2 100644 --- a/src/simulations/modular_life_v2/physics/scope.ts +++ b/src/simulations/modular_life_v2/physics/scope.ts @@ -9,4 +9,18 @@ export type Scope = { heat: number hull: Hull[] +} + +export const createScopeData = (capacity: number): Scope => { + return { + amount: { + energy: 0, + red: 0, + green: 0, + blue: 0, + }, + capacity, + heat: 0, + hull: [], + } } \ No newline at end of file diff --git a/src/simulations/modular_life_v2/terrain.ts b/src/simulations/modular_life_v2/terrain.ts index 9fb65e0..2506926 100644 --- a/src/simulations/modular_life_v2/terrain.ts +++ b/src/simulations/modular_life_v2/terrain.ts @@ -1,9 +1,8 @@ import { Vector } from "../../classes/physics" +import { createScopeData, Scope } from "./physics/scope" -export class TerrainCell { - energy = 0 - energyProduction = 0 - heat = 0 +export type TerrainCell = Scope & { + energyProduction: number } export class Terrain { @@ -16,6 +15,11 @@ export class Terrain { public constructor( public readonly size: Vector, ) { - this._cells = (new Array(size.y)).fill(0).map(() => (new Array(size.x)).fill(0).map(() => new TerrainCell())) + this._cells = (new Array(size.y)).fill(0).map(() => (new Array(size.x)).fill(0).map((): TerrainCell => { + return { + energyProduction: 0, + ...createScopeData(Infinity) + } + })) } } \ No newline at end of file From 125a9132c7aef6648efe31352354b196a64bf50f Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 00:24:02 +0900 Subject: [PATCH 05/15] =?UTF-8?q?=E7=A5=96=E5=85=88=E7=A8=AE=E3=82=92?= =?UTF-8?q?=E4=B8=96=E7=95=8C=E3=81=AB=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/ancestor/ancestor.ts | 79 ++++++++++--------- .../modular_life_v2/ancestor/source_code.ts | 14 ++-- src/simulations/modular_life_v2/source.ts | 19 ++++- src/simulations/modular_life_v2/system.ts | 2 +- src/simulations/modular_life_v2/world.ts | 10 +-- 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/simulations/modular_life_v2/ancestor/ancestor.ts b/src/simulations/modular_life_v2/ancestor/ancestor.ts index 5cc895f..d083dfc 100644 --- a/src/simulations/modular_life_v2/ancestor/ancestor.ts +++ b/src/simulations/modular_life_v2/ancestor/ancestor.ts @@ -2,46 +2,49 @@ import { Computer, Hull } from "../module/module" import { SourceCode } from "../module/source_code" import { createScopeData } from "../physics/scope" -/// 生命として成立する最小の祖先種 -export const createMinimumAncestor = (code: SourceCode): Hull => { // TODO: - /* - - 計算機 x 1 - - 外殻 x 1 - - 推進器 x 1 // TODO: - */ +export const Ancestor = { + /// 生命として成立する最小の祖先種 + minimum(code: SourceCode): Hull { // TODO: + /* + - 計算機 x 1 + - 外殻 x 1 + - 推進器 x 1 // TODO: + */ - const computer: Computer = { - case: "computer", - code, - } + const computer: Computer = { + case: "computer", + code, + } - return { - case: "hull", - hits: 0, - hitsMax: 1000, - size: 4, - internalModules: { - computer: [computer], - assembler: [], - }, - ...createScopeData(1000), - } -} + return { + case: "hull", + hits: 0, + hitsMax: 1000, + size: 4, + internalModules: { + computer: [computer], + assembler: [], + }, + ...createScopeData(1000), + } + }, -/// 自己複製できる最小の祖先種 -export const createMinimumSelfReproductionAncestor = (code: SourceCode): Hull => { // TODO: - /* - - 計算機 x 1 - - 物質輸送口 x 1 - - 外殻 x n - - 推進器 x 1 - - 物質変換器 x n - - 組み立て機 x 1 - */ - throw "not implemented" -} + /// 自己複製できる最小の祖先種 + minimumSelfReproduction(code: SourceCode): Hull { // TODO: + /* + - 計算機 x 1 + - 物質輸送口 x 1 + - 外殻 x n + - 推進器 x 1 + - 物質変換器 x n + - 組み立て機 x 1 + */ + throw "not implemented" + }, -/// 自身より複雑な子孫を組み立てられる祖先種 -export const createGeneralAssemblerAncestor = (code: SourceCode): Hull => { // TODO: - throw "not implemented" + /// 自身より複雑な子孫を組み立てられる祖先種 + generalAssembler(code: SourceCode): Hull { // TODO: + throw "not implemented" + }, + } diff --git a/src/simulations/modular_life_v2/ancestor/source_code.ts b/src/simulations/modular_life_v2/ancestor/source_code.ts index 174c7b3..0aca301 100644 --- a/src/simulations/modular_life_v2/ancestor/source_code.ts +++ b/src/simulations/modular_life_v2/ancestor/source_code.ts @@ -1,10 +1,12 @@ import { ComputeArgument, SourceCode } from "../module/source_code" -/// ゲーム世界上で何も行わない -export const createStillCode = (): SourceCode => { - return ([, environment]: ComputeArgument) => { - if (environment.time % 100 === 0) { - console.log(`[still code] t: ${environment.time}`) +export const AncestorCode = { + /// ゲーム世界上で何も行わない + stillCode(): SourceCode { + return ([, environment]: ComputeArgument) => { + if (environment.time % 100 === 0) { + console.log(`[still code] t: ${environment.time}`) + } } - } + }, } diff --git a/src/simulations/modular_life_v2/source.ts b/src/simulations/modular_life_v2/source.ts index 021d3ee..b7bdf21 100644 --- a/src/simulations/modular_life_v2/source.ts +++ b/src/simulations/modular_life_v2/source.ts @@ -1,6 +1,8 @@ import p5 from "p5" import { Vector } from "../../classes/physics" import { defaultCanvasParentId } from "../../react-components/common/default_canvas_parent_id" +import { Ancestor } from "./ancestor/ancestor" +import { AncestorCode } from "./ancestor/source_code" import { constants } from "./constants" import { Logger } from "./logger" import { P5Drawer } from "./p5_drawer" @@ -40,11 +42,11 @@ const canvasSize = worldSize.mult(cellSize) const world = new World(worldSize, logger, constants.physicalConstant) initializeEnergySources(world) +initializeAncestors(world) const drawer = new P5Drawer(cellSize) -drawer.setDrawMode({ - case: "material", -}) +drawer.setDrawMode({ case: "material" }) +drawer.setDrawMode({ case: "life" }) export const main = (): ReactConnector => { let isRunning = true @@ -55,6 +57,9 @@ export const main = (): ReactConnector => { const canvas = p.createCanvas(canvasSize.x, canvasSize.y) canvas.id("canvas") canvas.parent(defaultCanvasParentId) + + p.ellipseMode(p.CORNER) + p.rectMode(p.CORNER) } p.draw = () => { @@ -125,4 +130,10 @@ function initializeEnergySources(world: World): void { world.setEnergyProductionAt(x, y, energyProduction) } } -} \ No newline at end of file +} + +function initializeAncestors(world: World): void { + world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).floor()) + world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(2).floor()) + world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).mult(2).floor()) +} diff --git a/src/simulations/modular_life_v2/system.ts b/src/simulations/modular_life_v2/system.ts index b5a9a8d..d65f11f 100644 --- a/src/simulations/modular_life_v2/system.ts +++ b/src/simulations/modular_life_v2/system.ts @@ -1,3 +1,3 @@ export const System = { - version: "2.0.4" + version: "2.0.5" } as const \ No newline at end of file diff --git a/src/simulations/modular_life_v2/world.ts b/src/simulations/modular_life_v2/world.ts index 34fc53a..fde3b67 100644 --- a/src/simulations/modular_life_v2/world.ts +++ b/src/simulations/modular_life_v2/world.ts @@ -6,6 +6,7 @@ import { Logger } from "./logger" import { Terrain, TerrainCell } from "./terrain" import { PhysicalConstant } from "./physics/physical_constant" import { Engine } from "./engine" +import { Hull } from "./module/module" type Life = unknown // FixMe: @@ -30,12 +31,9 @@ export class World { this.engine = new Engine(physicalConstant) } - public addAncestor(life: Life, atPosition: Vector): Result { - return Result.Failed("not implemented") - } - - private addLife(hull: Life, atPosition: Vector, parent: Life): Result { - return Result.Failed("not implemented") + public addAncestor(life: Hull, atPosition: Vector): void { + const cell = this.getTerrainCellAt(atPosition) + cell.hull.push(life) } public setEnergyProductionAt(x: number, y: number, energyProduction: number): void { From 9c05095f238657fb64fdc97b473a773dcab06a62 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 00:24:21 +0900 Subject: [PATCH 06/15] =?UTF-8?q?=E7=94=9F=E5=91=BD=E3=81=AE=E6=8F=8F?= =?UTF-8?q?=E7=94=BB=E5=87=A6=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/p5_drawer.ts | 82 +++++++++++--------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/simulations/modular_life_v2/p5_drawer.ts b/src/simulations/modular_life_v2/p5_drawer.ts index 6ca7927..cc38c20 100644 --- a/src/simulations/modular_life_v2/p5_drawer.ts +++ b/src/simulations/modular_life_v2/p5_drawer.ts @@ -1,11 +1,14 @@ import p5 from "p5" import { strictEntries } from "../../classes/utilities" -import { Terrain } from "./terrain" +import { Terrain, TerrainCell } from "./terrain" import { World } from "./world" type DrawModeMaterial = { readonly case: "material" } +type DrawModeLife = { + readonly case: "life" +} type DrawModeEnergy = { readonly case: "energy" } @@ -16,10 +19,12 @@ type DrawModeStatus = { readonly case: "status" readonly text: string } -type DrawMode = DrawModeMaterial | DrawModeEnergy | DrawModeHeat | DrawModeStatus +type DrawMode = DrawModeMaterial | DrawModeLife | DrawModeEnergy | DrawModeHeat | DrawModeStatus type DrawModes = DrawMode["case"] +type InnerCellDrawModes = DrawModeMaterial["case"] | DrawModeLife["case"] | DrawModeEnergy["case"] | DrawModeHeat["case"] type GenericDrawMode = T extends "material" ? DrawModeMaterial : T extends "energy" ? DrawModeEnergy : + T extends "life" ? DrawModeLife : T extends "heat" ? DrawModeHeat : T extends "status" ? DrawModeStatus : never @@ -47,50 +52,57 @@ export class P5Drawer { public drawWorld(p: p5, world: World): void { p.background(0x00) - if (this.drawMode["energy"] != null) { - this.drawEnergy(p, world.terrain) - } - if (this.drawMode["material"] != null) { - this.drawMaterial(p, world) - } - if (this.drawMode["heat"] != null) { - this.drawHeat(p, world.terrain) + const drawModes = this.drawModes + const drawTargets: { [Draw in InnerCellDrawModes]: boolean } = { + material: drawModes.includes("material"), + life: drawModes.includes("life"), + energy: drawModes.includes("energy"), + heat: drawModes.includes("heat"), } + + world.terrain.cells.forEach((row, y) => { + row.forEach((cell, x) => { + this.drawTerrainCell(p, cell, x, y, drawTargets) + }) + }) + if (this.drawMode["status"] != null) { this.drawStatus(p, world, this.drawMode["status"]) } } - private drawMaterial(p: p5, world: World): void { - p.noStroke() - p.fill(0xFF) - p.circle(100, 100, 100) // TODO: - } - - private drawEnergy(p: p5, terrain: Terrain): void { + private drawTerrainCell(p: p5, cell: TerrainCell, x: number, y: number, drawTargets: { [Draw in InnerCellDrawModes]: boolean }): void { const cellSize = this.cellSize - const energyMeanAmount = 10 // FixMe: - terrain.cells.forEach((row, y) => { - row.forEach((cell, x) => { - const alpha = Math.floor((cell.energy / energyMeanAmount) * 0x80) - p.fill(0xFF, 0xFF, 0x00, alpha) - p.square(x * cellSize, y * cellSize, cellSize) + if (drawTargets.material === true) { + // TODO: + } + + if (drawTargets.life === true) { + cell.hull.forEach(hull => { + p.noStroke() + p.fill(0xFF, 0xC0) + p.ellipse(x * cellSize, y * cellSize, cellSize, cellSize) }) - }) - } + } - private drawHeat(p: p5, terrain: Terrain): void { - const cellSize = this.cellSize - const heatMeanAmount = 10 // FixMe: + if (drawTargets.energy === true) { + const energyMeanAmount = 10 // FixMe: - terrain.cells.forEach((row, y) => { - row.forEach((cell, x) => { - const alpha = Math.floor((cell.heat / heatMeanAmount) * 0x80) - p.fill(0xFF, 0x00, 0x00, alpha) - p.square(x * cellSize, y * cellSize, cellSize) - }) - }) + p.noStroke() + const alpha = Math.floor((cell.amount.energy / energyMeanAmount) * 0x80) + p.fill(0xFF, 0xFF, 0x00, alpha) + p.rect(x * cellSize, y * cellSize, cellSize, cellSize) + } + + if (drawTargets.heat === true) { + const heatMeanAmount = 10 // FixMe: + + p.noStroke() + const alpha = Math.floor((cell.heat / heatMeanAmount) * 0x80) + p.fill(0xFF, 0x00, 0x00, alpha) + p.rect(x * cellSize, y * cellSize, cellSize, cellSize) + } } private drawStatus(p: p5, world: World, status: DrawModeStatus): void { From 9e93c77bb4b66fadffcb900c4edd18a0978904d2 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 00:59:01 +0900 Subject: [PATCH 07/15] =?UTF-8?q?=E4=B8=8D=E8=B6=B3=E5=88=86=E3=81=AEModul?= =?UTF-8?q?e=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/ancestor/ancestor.ts | 8 ++- .../modular_life_v2/module/module.ts | 72 ++++++++++++------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/simulations/modular_life_v2/ancestor/ancestor.ts b/src/simulations/modular_life_v2/ancestor/ancestor.ts index d083dfc..57f3ad6 100644 --- a/src/simulations/modular_life_v2/ancestor/ancestor.ts +++ b/src/simulations/modular_life_v2/ancestor/ancestor.ts @@ -1,4 +1,4 @@ -import { Computer, Hull } from "../module/module" +import { Computer, Hull, Mover } from "../module/module" import { SourceCode } from "../module/source_code" import { createScopeData } from "../physics/scope" @@ -15,6 +15,9 @@ export const Ancestor = { case: "computer", code, } + const mover: Mover = { + case: "mover", + } return { case: "hull", @@ -24,6 +27,9 @@ export const Ancestor = { internalModules: { computer: [computer], assembler: [], + channel: [], + mover: [mover], + materialSynthesizer: [], }, ...createScopeData(1000), } diff --git a/src/simulations/modular_life_v2/module/module.ts b/src/simulations/modular_life_v2/module/module.ts index 71e2f1a..2c63c78 100644 --- a/src/simulations/modular_life_v2/module/module.ts +++ b/src/simulations/modular_life_v2/module/module.ts @@ -1,15 +1,59 @@ import type { Scope } from "../physics/scope" import type { SourceCode } from "./source_code" -export type ModuleType = "computer" | "assembler" | "hull" +export type Hull = Scope & { + readonly case: "hull" + hits: number + readonly hitsMax: number + readonly internalModules: { [M in InternalModuleType]: Module[] } // HullはScope.hullに入っている + readonly size: number +} + +export type Computer = { + readonly case: "computer" + readonly code: SourceCode +} + +export type Assembler = { + readonly case: "assembler" +} + +export type Channel = { + readonly case: "channel" +} + +export type Mover = { + readonly case: "mover" +} + +export type MaterialSynthesizer = { + readonly case: "materialSynthesizer" +} + +export type AnyModule = Assembler | Computer | Hull | Channel | Mover | MaterialSynthesizer +export type Module = T extends "computer" ? Computer : + T extends "assembler" ? Assembler : + T extends "hull" ? Hull : + T extends "channel" ? Channel : + T extends "mover" ? Mover : + T extends "materialSynthesizer" ? MaterialSynthesizer : + never + +export type ModuleType = AnyModule["case"] export const getShortModuleName = (moduleType: ModuleType): string => { switch (moduleType) { case "assembler": return "A" case "computer": - return "C" + return "Co" case "hull": return "H" + case "channel": + return "Ch" + case "mover": + return "M" + case "materialSynthesizer": + return "S" default: { // eslint-disable-next-line @typescript-eslint/no-unused-vars const _: never = moduleType @@ -18,28 +62,4 @@ export const getShortModuleName = (moduleType: ModuleType): string => { } } -export type Module = { - readonly case: T -} - -export type AnyModule = Assembler | Computer | Hull -export type GenericModule = T extends "computer" ? Computer : - T extends "assembler" ? Assembler : - T extends "hull" ? Hull : - never - export type InternalModuleType = Exclude - -export type Hull = Module<"hull"> & Scope & { - hits: number - readonly hitsMax: number - readonly internalModules: { [M in InternalModuleType]: GenericModule[] } // HullはScope.hullに入っている - readonly size: number -} - -export type Computer = Module<"computer"> & { - readonly code: SourceCode -} - -export type Assembler = Module<"assembler"> & { -} From 68fda3af78b12044307bb294ae1c6b60f5e0834a Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 01:17:24 +0900 Subject: [PATCH 08/15] =?UTF-8?q?=E5=86=85=E9=83=A8=E3=83=A2=E3=82=B8?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E3=83=AB=E3=81=AE=E6=8F=8F=E7=94=BB=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/ancestor/ancestor.ts | 23 ++++++++++- src/simulations/modular_life_v2/constants.ts | 2 +- src/simulations/modular_life_v2/p5_drawer.ts | 41 +++++++++++++++++-- src/simulations/modular_life_v2/source.ts | 5 +-- src/simulations/modular_life_v2/system.ts | 2 +- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/simulations/modular_life_v2/ancestor/ancestor.ts b/src/simulations/modular_life_v2/ancestor/ancestor.ts index 57f3ad6..acb5eb9 100644 --- a/src/simulations/modular_life_v2/ancestor/ancestor.ts +++ b/src/simulations/modular_life_v2/ancestor/ancestor.ts @@ -4,11 +4,11 @@ import { createScopeData } from "../physics/scope" export const Ancestor = { /// 生命として成立する最小の祖先種 - minimum(code: SourceCode): Hull { // TODO: + minimum(code: SourceCode): Hull { /* - 計算機 x 1 - 外殻 x 1 - - 推進器 x 1 // TODO: + - 推進器 x 1 */ const computer: Computer = { @@ -35,6 +35,25 @@ export const Ancestor = { } }, + /// 試験用 + test(code: SourceCode): Hull { + return { + case: "hull", + hits: 0, + hitsMax: 1000, + size: 3, + internalModules: { + computer: [], + assembler: [], + channel: [{ case: "channel" }, { case: "channel" }, { case: "channel" }, { case: "channel" }], + mover: [{ case: "mover" }, { case: "mover" }, { case: "mover" }, { case: "mover" }], + materialSynthesizer: [], + }, + ...createScopeData(1000), + } + }, + + /// 自己複製できる最小の祖先種 minimumSelfReproduction(code: SourceCode): Hull { // TODO: /* diff --git a/src/simulations/modular_life_v2/constants.ts b/src/simulations/modular_life_v2/constants.ts index 4c5d6aa..c3df6cd 100644 --- a/src/simulations/modular_life_v2/constants.ts +++ b/src/simulations/modular_life_v2/constants.ts @@ -20,7 +20,7 @@ export const constants = { logLevel, }, simulation: { - cellSize: parameters.parseInt("cell_size", { alternativeKey: "si.c", min: 1 }) ?? 8, + cellSize: parameters.parseInt("cell_size", { alternativeKey: "si.c", min: 1 }) ?? 16, worldSize: parameters.parseInt("world_size", { alternativeKey: "si.w", min: 4 }) ?? 50, frameSkip: parameters.parseInt("frame_skip", { alternativeKey: "si.f", min: 1 }) ?? 2, }, diff --git a/src/simulations/modular_life_v2/p5_drawer.ts b/src/simulations/modular_life_v2/p5_drawer.ts index cc38c20..c3e3f3a 100644 --- a/src/simulations/modular_life_v2/p5_drawer.ts +++ b/src/simulations/modular_life_v2/p5_drawer.ts @@ -1,6 +1,8 @@ import p5 from "p5" +import { Color } from "../../classes/color" import { strictEntries } from "../../classes/utilities" -import { Terrain, TerrainCell } from "./terrain" +import { ModuleType } from "./module/module" +import { TerrainCell } from "./terrain" import { World } from "./world" type DrawModeMaterial = { @@ -29,6 +31,15 @@ type GenericDrawMode = T extends "material" ? DrawModeMater T extends "status" ? DrawModeStatus : never +const moduleColor: { [M in ModuleType]: Color } = { + hull: new Color(0xFF, 0xFF, 0xFF), + computer: new Color(0xFF, 0xFF, 0xFF), + assembler: new Color(0xFF, 0xFF, 0xFF), + channel: new Color(0xFF, 0xFF, 0xFF), + mover: new Color(0x22, 0x22, 0x22), + materialSynthesizer: new Color(0xFF, 0xFF, 0xFF), +} + export class P5Drawer { public get drawModes(): DrawModes[] { return strictEntries(this.drawMode).map(([key]) => key) @@ -73,6 +84,10 @@ export class P5Drawer { private drawTerrainCell(p: p5, cell: TerrainCell, x: number, y: number, drawTargets: { [Draw in InnerCellDrawModes]: boolean }): void { const cellSize = this.cellSize + const cellRadius = cellSize / 2 + + p.ellipseMode(p.CENTER) + p.rectMode(p.CORNER) if (drawTargets.material === true) { // TODO: @@ -80,9 +95,27 @@ export class P5Drawer { if (drawTargets.life === true) { cell.hull.forEach(hull => { - p.noStroke() - p.fill(0xFF, 0xC0) - p.ellipse(x * cellSize, y * cellSize, cellSize, cellSize) + const size = (hull.size / 5) * cellSize + const centerX = x * cellSize + cellRadius + const centerY = y * cellSize + cellRadius + + const hullColor = moduleColor.hull.p5(p) + p.stroke(hullColor) + p.strokeCap(p.SQUARE) + p.strokeWeight(size / 4) + p.fill(hullColor) + p.ellipse(centerX, centerY, size, size) + + const moverCount = hull.internalModules.mover.length + if (moverCount > 0) { + const drawSize = p.PI * 2 * (moverCount / ((hull.size - 1) * 4)) + const fromAngle = (p.PI / 2) - (drawSize / 2) + const toAngle = fromAngle + drawSize + + p.stroke(moduleColor.mover.p5(p)) + p.noFill() + p.arc(centerX, centerY, size, size, fromAngle, toAngle) + } }) } diff --git a/src/simulations/modular_life_v2/source.ts b/src/simulations/modular_life_v2/source.ts index b7bdf21..bf97117 100644 --- a/src/simulations/modular_life_v2/source.ts +++ b/src/simulations/modular_life_v2/source.ts @@ -57,9 +57,6 @@ export const main = (): ReactConnector => { const canvas = p.createCanvas(canvasSize.x, canvasSize.y) canvas.id("canvas") canvas.parent(defaultCanvasParentId) - - p.ellipseMode(p.CORNER) - p.rectMode(p.CORNER) } p.draw = () => { @@ -134,6 +131,6 @@ function initializeEnergySources(world: World): void { function initializeAncestors(world: World): void { world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).floor()) - world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(2).floor()) + world.addAncestor(Ancestor.test(AncestorCode.stillCode()), world.size.div(2).floor()) world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).mult(2).floor()) } diff --git a/src/simulations/modular_life_v2/system.ts b/src/simulations/modular_life_v2/system.ts index d65f11f..67045ae 100644 --- a/src/simulations/modular_life_v2/system.ts +++ b/src/simulations/modular_life_v2/system.ts @@ -1,3 +1,3 @@ export const System = { - version: "2.0.5" + version: "2.0.6" } as const \ No newline at end of file From 966e071339ff5205c4ee1c2eacf45ddf121ab882 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 01:27:28 +0900 Subject: [PATCH 09/15] =?UTF-8?q?Channel=E3=81=AE=E6=8F=8F=E7=94=BB?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/p5_drawer.ts | 25 +++++++++++++++----- src/simulations/modular_life_v2/system.ts | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/simulations/modular_life_v2/p5_drawer.ts b/src/simulations/modular_life_v2/p5_drawer.ts index c3e3f3a..52e7dfd 100644 --- a/src/simulations/modular_life_v2/p5_drawer.ts +++ b/src/simulations/modular_life_v2/p5_drawer.ts @@ -35,8 +35,8 @@ const moduleColor: { [M in ModuleType]: Color } = { hull: new Color(0xFF, 0xFF, 0xFF), computer: new Color(0xFF, 0xFF, 0xFF), assembler: new Color(0xFF, 0xFF, 0xFF), - channel: new Color(0xFF, 0xFF, 0xFF), - mover: new Color(0x22, 0x22, 0x22), + channel: new Color(0xFF, 0xFF, 0x00), + mover: new Color(0x60, 0x60, 0x60), materialSynthesizer: new Color(0xFF, 0xFF, 0xFF), } @@ -61,7 +61,7 @@ export class P5Drawer { } public drawWorld(p: p5, world: World): void { - p.background(0x00) + p.background(0x22) const drawModes = this.drawModes const drawTargets: { [Draw in InnerCellDrawModes]: boolean } = { @@ -99,13 +99,15 @@ export class P5Drawer { const centerX = x * cellSize + cellRadius const centerY = y * cellSize + cellRadius + const hullWeight = size / 4 const hullColor = moduleColor.hull.p5(p) - p.stroke(hullColor) - p.strokeCap(p.SQUARE) - p.strokeWeight(size / 4) + p.noStroke() p.fill(hullColor) p.ellipse(centerX, centerY, size, size) + p.strokeWeight(hullWeight) + p.strokeCap(p.SQUARE) + const moverCount = hull.internalModules.mover.length if (moverCount > 0) { const drawSize = p.PI * 2 * (moverCount / ((hull.size - 1) * 4)) @@ -116,6 +118,17 @@ export class P5Drawer { p.noFill() p.arc(centerX, centerY, size, size, fromAngle, toAngle) } + + const channelCount = hull.internalModules.channel.length + if (channelCount > 0) { + const drawSize = p.PI * 2 * (channelCount / ((hull.size - 1) * 4)) + const fromAngle = (p.PI / 2) * 3 - (drawSize / 2) + const toAngle = fromAngle + drawSize + + p.stroke(moduleColor.channel.p5(p)) + p.noFill() + p.arc(centerX, centerY, size, size, fromAngle, toAngle) + } }) } diff --git a/src/simulations/modular_life_v2/system.ts b/src/simulations/modular_life_v2/system.ts index 67045ae..f5d0001 100644 --- a/src/simulations/modular_life_v2/system.ts +++ b/src/simulations/modular_life_v2/system.ts @@ -1,3 +1,3 @@ export const System = { - version: "2.0.6" + version: "2.0.7" } as const \ No newline at end of file From 3ba45619bbc36f8055601b00aa840d7734234f63 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Tue, 28 Feb 2023 23:23:56 +0900 Subject: [PATCH 10/15] =?UTF-8?q?=E7=89=A9=E8=B3=AA=E3=81=AE=E5=AE=9A?= =?UTF-8?q?=E7=BE=A9=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/constants.ts | 4 +- .../modular_life_v2/physics/material.ts | 63 +++++++++++-------- .../physics/physical_constant.ts | 4 +- .../modular_life_v2/physics/scope.ts | 7 ++- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/simulations/modular_life_v2/constants.ts b/src/simulations/modular_life_v2/constants.ts index c3df6cd..ce8779f 100644 --- a/src/simulations/modular_life_v2/constants.ts +++ b/src/simulations/modular_life_v2/constants.ts @@ -1,6 +1,6 @@ import { URLParameterParser } from "../../classes/url_parameter_parser_v3" import { isLogLevel, LogLevel } from "./logger" -import { defaultMaterialProductionSpec } from "./physics/material" +import { materialProductionRecipes } from "./physics/material" import type { PhysicalConstant } from "./physics/physical_constant" const parameters = new URLParameterParser(document.location.search) @@ -11,7 +11,7 @@ const physicalConstant: PhysicalConstant = { heatLossRate: parameters.parseFloat("heat_loss", { alternativeKey: "ph.h", min: 0 }) ?? 0.25, energyHeatConversionRate: parameters.parseFloat("energy_heat_conversion", { alternativeKey: "ph.e", min: 0 }) ?? 0.5, - materialProduction: defaultMaterialProductionSpec, + materialProductionRecipe: materialProductionRecipes, } export const constants = { diff --git a/src/simulations/modular_life_v2/physics/material.ts b/src/simulations/modular_life_v2/physics/material.ts index 882c398..c534e17 100644 --- a/src/simulations/modular_life_v2/physics/material.ts +++ b/src/simulations/modular_life_v2/physics/material.ts @@ -1,43 +1,54 @@ -export type RedMaterial = "red" -export type GreenMaterial = "green" -export type BlueMaterial = "blue" -export type MaterialType = RedMaterial | GreenMaterial | BlueMaterial +export type Nitrogen = "nitrogen" +export type Carbon = "carbon" + +/// エネルギーを安定して保存できる +export type Fuel = "fuel" + +/// すべてのModuleの原料 +export type Substance = "substance" +export type MaterialType = Nitrogen | Carbon | Fuel | Substance export type Energy = "energy" export type Heat = "heat" -export type IngredientType = MaterialType | Energy +export type SynthesizeType = MaterialType | Energy type Amount = number -type ProductionSpec = { - readonly amount: Amount - /// 生産に必要な1tick当たりの必要量 - readonly ingredients: {[Ingredient in IngredientType]?: Amount} +export type ProductionRecipe = { + readonly name: string readonly time: number + readonly heatProduction: number + readonly ingredients: { [Ingredient in SynthesizeType]?: Amount } + readonly productions: { [Production in SynthesizeType]?: Amount } } -export type MaterialProductionSpec = { [Material in MaterialType]: ProductionSpec } - -export const defaultMaterialProductionSpec: MaterialProductionSpec = { - red: { - amount: 100, - ingredients: { - energy: 100, - }, +const recipes: ProductionRecipe[] = [ + { + name: "compose-fuel", time: 1, - }, - green: { - amount: 50, + heatProduction: 1, ingredients: { - energy: 50, + nitrogen: 1, + carbon: 1, + energy: 12, + }, + productions: { + fuel: 1, }, - time: 1, }, - blue: { - amount: 10, + { + name: "decompose-fuel", + time: 1, + heatProduction: 1, ingredients: { + fuel: 1, + }, + productions: { + nitrogen: 1, + carbon: 1, energy: 10, }, - time: 1, }, -} \ No newline at end of file +] + +export const materialProductionRecipes = new Map(recipes.map(x => [x.name, x])) diff --git a/src/simulations/modular_life_v2/physics/physical_constant.ts b/src/simulations/modular_life_v2/physics/physical_constant.ts index 97200da..2e64f63 100644 --- a/src/simulations/modular_life_v2/physics/physical_constant.ts +++ b/src/simulations/modular_life_v2/physics/physical_constant.ts @@ -1,8 +1,8 @@ -import type { MaterialProductionSpec } from "./material" +import { ProductionRecipe } from "./material" export type PhysicalConstant = { readonly heatLossRate: number readonly energyHeatConversionRate: number - readonly materialProduction: MaterialProductionSpec + readonly materialProductionRecipe: Map } \ No newline at end of file diff --git a/src/simulations/modular_life_v2/physics/scope.ts b/src/simulations/modular_life_v2/physics/scope.ts index 1f068b2..432a101 100644 --- a/src/simulations/modular_life_v2/physics/scope.ts +++ b/src/simulations/modular_life_v2/physics/scope.ts @@ -14,10 +14,11 @@ export type Scope = { export const createScopeData = (capacity: number): Scope => { return { amount: { + nitrogen: 0, + carbon: 0, + fuel: 0, + substance: 0, energy: 0, - red: 0, - green: 0, - blue: 0, }, capacity, heat: 0, From aa0dd14cc093d1526eb8fed669eda3032811749a Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Fri, 3 Mar 2023 00:01:03 +0900 Subject: [PATCH 11/15] =?UTF-8?q?ValuedArrayMap=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/utilities.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/classes/utilities.ts b/src/classes/utilities.ts index dce8aab..01647f8 100644 --- a/src/classes/utilities.ts +++ b/src/classes/utilities.ts @@ -49,3 +49,15 @@ export function toggleFullscreen(elementId: string): void { export const strictEntries = >(object: T): [keyof T, T[keyof T]][] => { return Object.entries(object) } + +export class ValuedArrayMap extends Map> { + public getValueFor(key: Key): Element[] { + const stored = this.get(key) + if (stored != null) { + return stored + } + const newArray: Element[] = [] + this.set(key, newArray) + return newArray + } +} From b7da3a30e00d0dd19fa1b70c93048d7cdf563d92 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Fri, 3 Mar 2023 00:01:22 +0900 Subject: [PATCH 12/15] =?UTF-8?q?API=E3=82=92=E5=AE=9A=E7=BE=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/api_request.ts | 45 +++++++++++++++++++ src/simulations/modular_life_v2/module/api.ts | 15 +++++++ 2 files changed, 60 insertions(+) create mode 100644 src/simulations/modular_life_v2/api_request.ts diff --git a/src/simulations/modular_life_v2/api_request.ts b/src/simulations/modular_life_v2/api_request.ts new file mode 100644 index 0000000..18801be --- /dev/null +++ b/src/simulations/modular_life_v2/api_request.ts @@ -0,0 +1,45 @@ +import type { Hull, ModuleType } from "./module/module" +import type { MaterialRecipeName, TransferrableMaterialType } from "./physics/material" +import type { NeighbourDirection } from "./physics/direction" + +export type Life = Hull + +// リクエストが関係するのはScopeの中だけなのでローカルに処理できるか? +export type ComputeRequestMove = { + readonly case: "move" + readonly direction: NeighbourDirection +} +export type ComputeRequestUptake = { + readonly case: "uptake" + readonly materialType: TransferrableMaterialType + readonly amount: number +} +export type ComputeRequestExcretion = { + readonly case: "excretion" + readonly materialType: TransferrableMaterialType + readonly amount: number +} +export type ComputeRequestSynthesize = { + readonly case: "synthesize" + readonly recipe: MaterialRecipeName +} +export type ComputeRequestAssemble = { + readonly case: "assemble" + readonly moduleType: ModuleType +} + +export type IntraScopeMaterialTransferRequest = ComputeRequestSynthesize + | ComputeRequestAssemble +export type IntraScopeMaterialTransferRequestType = IntraScopeMaterialTransferRequest["case"] + +export type InterScopeMaterialTransferRequest = ComputeRequestUptake + | ComputeRequestExcretion +export type InterScopeMaterialTransferRequestType = InterScopeMaterialTransferRequest["case"] + +export type MaterialTransferRequest = IntraScopeMaterialTransferRequest + | InterScopeMaterialTransferRequest +export type MaterialTransferRequestType = MaterialTransferRequest["case"] + +export type ComputeRequest = ComputeRequestMove + | MaterialTransferRequest +export type ComputeRequestType = ComputeRequest["case"] diff --git a/src/simulations/modular_life_v2/module/api.ts b/src/simulations/modular_life_v2/module/api.ts index 6a26e0a..2a33245 100644 --- a/src/simulations/modular_life_v2/module/api.ts +++ b/src/simulations/modular_life_v2/module/api.ts @@ -1,2 +1,17 @@ +import type { NeighbourDirection } from "../physics/direction" +import type { MaterialRecipeName, MaterialType, TransferrableMaterialType } from "../physics/material" +import type { AnyModule, ModuleType } from "./module" + export type ComputerApi = { + getStoredAmount(materialType: MaterialType): number + getEnergyAmount(): number + getHeat(): number + + modules(): AnyModule[] + + move(direction: NeighbourDirection): void + uptake(materialType: TransferrableMaterialType, amount: number): void + excretion(materialType: TransferrableMaterialType, amount: number): void + synthesize(recipe: MaterialRecipeName): void + assemble(moduleType: ModuleType): void } From 48c8324835008519e9d13d330048be0138165688 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Fri, 3 Mar 2023 00:02:24 +0900 Subject: [PATCH 13/15] =?UTF-8?q?Material=20Synthesize=E3=81=AFRecipe=20Na?= =?UTF-8?q?me=E3=81=A7=E5=AF=BE=E8=B1=A1=E3=82=92=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/module/module.ts | 2 ++ .../modular_life_v2/physics/material.ts | 19 +++++++------------ .../physics/physical_constant.ts | 4 ++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/simulations/modular_life_v2/module/module.ts b/src/simulations/modular_life_v2/module/module.ts index 2c63c78..06729fe 100644 --- a/src/simulations/modular_life_v2/module/module.ts +++ b/src/simulations/modular_life_v2/module/module.ts @@ -1,3 +1,4 @@ +import type { MaterialRecipeName } from "../physics/material" import type { Scope } from "../physics/scope" import type { SourceCode } from "./source_code" @@ -28,6 +29,7 @@ export type Mover = { export type MaterialSynthesizer = { readonly case: "materialSynthesizer" + readonly recipeName: MaterialRecipeName } export type AnyModule = Assembler | Computer | Hull | Channel | Mover | MaterialSynthesizer diff --git a/src/simulations/modular_life_v2/physics/material.ts b/src/simulations/modular_life_v2/physics/material.ts index c534e17..26a7404 100644 --- a/src/simulations/modular_life_v2/physics/material.ts +++ b/src/simulations/modular_life_v2/physics/material.ts @@ -11,21 +11,20 @@ export type MaterialType = Nitrogen | Carbon | Fuel | Substance export type Energy = "energy" export type Heat = "heat" +export type TransferrableMaterialType = MaterialType | Energy export type SynthesizeType = MaterialType | Energy type Amount = number export type ProductionRecipe = { - readonly name: string - readonly time: number + // readonly time: number // 時間がかかると中間状態を保存する必要が出るためこのバージョンでは1tickで完了とする readonly heatProduction: number readonly ingredients: { [Ingredient in SynthesizeType]?: Amount } readonly productions: { [Production in SynthesizeType]?: Amount } } -const recipes: ProductionRecipe[] = [ - { - name: "compose-fuel", - time: 1, +export type MaterialRecipeName = "composeFuel" | "decomposeFuel" +export const materialProductionRecipes: { [RecipeName in MaterialRecipeName]: ProductionRecipe } = { + composeFuel: { heatProduction: 1, ingredients: { nitrogen: 1, @@ -36,9 +35,7 @@ const recipes: ProductionRecipe[] = [ fuel: 1, }, }, - { - name: "decompose-fuel", - time: 1, + decomposeFuel: { heatProduction: 1, ingredients: { fuel: 1, @@ -49,6 +46,4 @@ const recipes: ProductionRecipe[] = [ energy: 10, }, }, -] - -export const materialProductionRecipes = new Map(recipes.map(x => [x.name, x])) +} diff --git a/src/simulations/modular_life_v2/physics/physical_constant.ts b/src/simulations/modular_life_v2/physics/physical_constant.ts index 2e64f63..d69c5c3 100644 --- a/src/simulations/modular_life_v2/physics/physical_constant.ts +++ b/src/simulations/modular_life_v2/physics/physical_constant.ts @@ -1,8 +1,8 @@ -import { ProductionRecipe } from "./material" +import type { MaterialRecipeName, ProductionRecipe } from "./material" export type PhysicalConstant = { readonly heatLossRate: number readonly energyHeatConversionRate: number - readonly materialProductionRecipe: Map + readonly materialProductionRecipe: { [RecipeName in MaterialRecipeName]: ProductionRecipe } } \ No newline at end of file From 9a65a3ede4f5e5f6c5e6fd3cac0d296ab775ce50 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Fri, 3 Mar 2023 00:02:53 +0900 Subject: [PATCH 14/15] =?UTF-8?q?MoveRequest=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/simulations/modular_life_v2/engine.ts | 12 ++ src/simulations/modular_life_v2/system.ts | 2 +- src/simulations/modular_life_v2/world.ts | 163 ++++++++++++++++++++-- 3 files changed, 162 insertions(+), 15 deletions(-) diff --git a/src/simulations/modular_life_v2/engine.ts b/src/simulations/modular_life_v2/engine.ts index 59dcfed..f7fb92f 100644 --- a/src/simulations/modular_life_v2/engine.ts +++ b/src/simulations/modular_life_v2/engine.ts @@ -1,12 +1,24 @@ +import { Life, MaterialTransferRequest, MaterialTransferRequestType } from "./api_request" import { PhysicalConstant } from "./physics/physical_constant" +import { Scope } from "./physics/scope" import { TerrainCell } from "./terrain" +export type ScopeOperation = { + readonly life: Life + readonly requests: Map +} + export class Engine { public constructor( public readonly physicalConstant: PhysicalConstant, ) { } + public celculateScope(scope: Scope, operations: ScopeOperation[]): void { + + } + + // TODO: celculateScopeに統合する? public calculateCell(cell: TerrainCell): void { const energyLoss = Math.floor(cell.amount.energy * this.physicalConstant.energyHeatConversionRate) cell.amount.energy = cell.amount.energy - energyLoss + cell.energyProduction diff --git a/src/simulations/modular_life_v2/system.ts b/src/simulations/modular_life_v2/system.ts index f5d0001..409801b 100644 --- a/src/simulations/modular_life_v2/system.ts +++ b/src/simulations/modular_life_v2/system.ts @@ -1,3 +1,3 @@ export const System = { - version: "2.0.7" + version: "2.1.0" } as const \ No newline at end of file diff --git a/src/simulations/modular_life_v2/world.ts b/src/simulations/modular_life_v2/world.ts index fde3b67..cc150b5 100644 --- a/src/simulations/modular_life_v2/world.ts +++ b/src/simulations/modular_life_v2/world.ts @@ -1,14 +1,21 @@ -import { Result } from "../../classes/result" import { guardPositionArgument, Vector } from "../../classes/physics" -import { Direction, getDirectionVector } from "./physics/direction" +import { Direction, getDirectionVector, NeighbourDirection } from "./physics/direction" import type { ComputerApi } from "./module/api" import { Logger } from "./logger" import { Terrain, TerrainCell } from "./terrain" import { PhysicalConstant } from "./physics/physical_constant" -import { Engine } from "./engine" -import { Hull } from "./module/module" +import { Engine, ScopeOperation } from "./engine" +import { Scope } from "./physics/scope" +import type { ComputeRequestMove, Life, MaterialTransferRequest, MaterialTransferRequestType } from "./api_request" +import type { AnyModule, Computer, ModuleType } from "./module/module" +import type { MaterialRecipeName, MaterialType, TransferrableMaterialType } from "./physics/material" +import { ValuedArrayMap } from "../../classes/utilities" +import { Environment } from "./physics/environment" -type Life = unknown // FixMe: +type LifeRequests = { + moveRequest: ComputeRequestMove | null + readonly materialTransferRequests: ValuedArrayMap +} export class World { public get t(): number { @@ -31,7 +38,7 @@ export class World { this.engine = new Engine(physicalConstant) } - public addAncestor(life: Hull, atPosition: Vector): void { + public addAncestor(life: Life, atPosition: Vector): void { const cell = this.getTerrainCellAt(atPosition) cell.hull.push(life) } @@ -47,12 +54,81 @@ export class World { } private step(): void { - this.terrain.cells.forEach(row => { - row.forEach(cell => { - this.engine.calculateCell(cell) + const environment: Environment = { + time: this.t, + } + + const calculateScope = (scope: Scope): { movedLifes: { life: Life, moveRequest: ComputeRequestMove }[] } => { + const results: { movedLifes: { life: Life, moveRequest: ComputeRequestMove }[] } = { + movedLifes: [], + } + const operations: ScopeOperation[] = [] + + const lifeIndicesToRemove: number[] = [] + const livesToAdd: Life[] = [] + + scope.hull.forEach((life, index) => { + const computer = life.internalModules.computer[0] // 複数のComputerを実行できるようにはなっていない + if (computer != null) { + const requests = this.runLifeCode(computer, life, scope, environment) + + if (requests.moveRequest != null) { + lifeIndicesToRemove.push(index) + results.movedLifes.push({ + life, + moveRequest: requests.moveRequest, + }) + } + + operations.push({ + life, + requests: requests.materialTransferRequests, + }) + } else { + operations.push({ + life, + requests: new Map(), + }) + } + + const childResults = calculateScope(life) + livesToAdd.push(...childResults.movedLifes.map(x => x.life)) + }) + + lifeIndicesToRemove.reverse() + lifeIndicesToRemove.forEach(index => { + scope.hull.splice(index, 1) + }) + + scope.hull.push(...livesToAdd) + + this.engine.celculateScope(scope, operations) + + return results + } + + const movedLives: {life: Life, destinationPosition: Vector}[] = [] + + this.terrain.cells.forEach((row, y) => { + row.forEach((cell, x) => { + const result = calculateScope(cell) + + result.movedLifes.forEach(({ life, moveRequest }) => { + const destinationPosition = this.getNewPosition(new Vector(x, y), moveRequest.direction) + + movedLives.push({ + life, + destinationPosition, + }) + }) }) }) + movedLives.forEach(({ life, destinationPosition }) => { + const destinationCell = this.getTerrainCellAt(destinationPosition) + destinationCell.hull.push(life) + }) + this._t += 1 } @@ -82,13 +158,72 @@ export class World { } // ---- API ---- // - private createApiFor(life: Life): ComputerApi { - return { + private runLifeCode(computer: Computer, life: Life, scope: Scope, environment: Environment): LifeRequests { + const lifeRequests: LifeRequests = { + moveRequest: null, + materialTransferRequests: new ValuedArrayMap(), } + const api = this.createApiFor(life, scope, lifeRequests) + computer.code([api, environment]) + + return lifeRequests } - /// 世界に対して働きかけるAPI呼び出しのログ出力 - private logActiveApiCall(life: Life, message: string): void { - // this.logger.debug(`Life[${life.hull.id}] at ${life.position} ${message}`) + private createApiFor(life: Life, scope: Scope, requests: LifeRequests): ComputerApi { + const addMaterialTransferRequest = (request: MaterialTransferRequest): void => { + requests.materialTransferRequests.getValueFor(request.case).push(request) + } + + return { + getStoredAmount(materialType: MaterialType): number { + return life.amount[materialType] + }, + getEnergyAmount(): number { + return life.amount.energy + }, + getHeat(): number { + return life.heat + }, + modules(): AnyModule[] { + const internalModules = Array.from(Object.values(life.internalModules)).flatMap((x): AnyModule[] => x) + + return [ + life, + ...internalModules, + ] + }, + move(direction: NeighbourDirection): void { + requests.moveRequest = { + case: "move", + direction, + } + }, + uptake(materialType: TransferrableMaterialType, amount: number): void { + addMaterialTransferRequest({ + case: "uptake", + materialType, + amount, + }) + }, + excretion(materialType: TransferrableMaterialType, amount: number): void { + addMaterialTransferRequest({ + case: "excretion", + materialType, + amount, + }) + }, + synthesize(recipe: MaterialRecipeName): void { + addMaterialTransferRequest({ + case: "synthesize", + recipe, + }) + }, + assemble(moduleType: ModuleType): void { + addMaterialTransferRequest({ + case: "assemble", + moduleType, + }) + }, + } } } From f1fc8dd0c3946f57124616a13cf64715030b5cf9 Mon Sep 17 00:00:00 2001 From: Yamazaki Mitsuyoshi Date: Fri, 3 Mar 2023 00:03:00 +0900 Subject: [PATCH 15/15] =?UTF-8?q?=E7=A7=BB=E5=8B=95=E3=81=99=E3=82=8B?= =?UTF-8?q?=E7=94=9F=E5=91=BD=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modular_life_v2/ancestor/source_code.ts | 12 +++++++++++- src/simulations/modular_life_v2/source.ts | 5 +++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/simulations/modular_life_v2/ancestor/source_code.ts b/src/simulations/modular_life_v2/ancestor/source_code.ts index 0aca301..abe02a0 100644 --- a/src/simulations/modular_life_v2/ancestor/source_code.ts +++ b/src/simulations/modular_life_v2/ancestor/source_code.ts @@ -1,4 +1,5 @@ -import { ComputeArgument, SourceCode } from "../module/source_code" +import type { ComputeArgument, SourceCode } from "../module/source_code" +import type { NeighbourDirection } from "../physics/direction" export const AncestorCode = { /// ゲーム世界上で何も行わない @@ -9,4 +10,13 @@ export const AncestorCode = { } } }, + + /// 一定方向へ移動するのみ + moveCode(direction: NeighbourDirection, moveInterval: number): SourceCode { + return ([api, environment]: ComputeArgument) => { + if (environment.time % moveInterval === 0) { + api.move(direction) + } + } + } } diff --git a/src/simulations/modular_life_v2/source.ts b/src/simulations/modular_life_v2/source.ts index bf97117..53e891b 100644 --- a/src/simulations/modular_life_v2/source.ts +++ b/src/simulations/modular_life_v2/source.ts @@ -6,6 +6,7 @@ import { AncestorCode } from "./ancestor/source_code" import { constants } from "./constants" import { Logger } from "./logger" import { P5Drawer } from "./p5_drawer" +import { NeighbourDirections } from "./physics/direction" import { System } from "./system" import { World } from "./world" @@ -130,7 +131,7 @@ function initializeEnergySources(world: World): void { } function initializeAncestors(world: World): void { - world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).floor()) + world.addAncestor(Ancestor.minimum(AncestorCode.moveCode(NeighbourDirections.right, 10)), world.size.div(3).floor()) world.addAncestor(Ancestor.test(AncestorCode.stillCode()), world.size.div(2).floor()) - world.addAncestor(Ancestor.minimum(AncestorCode.stillCode()), world.size.div(3).mult(2).floor()) + world.addAncestor(Ancestor.minimum(AncestorCode.moveCode(NeighbourDirections.bottom, 11)), world.size.div(3).mult(2).floor()) }