diff --git a/src/simulations/corewar/corewar/core.ts b/src/simulations/corewar/corewar/core.ts
new file mode 100644
index 0000000..627721b
--- /dev/null
+++ b/src/simulations/corewar/corewar/core.ts
@@ -0,0 +1,18 @@
+import { CoreMemory } from "./instruction"
+import { Dat } from "./instructions"
+
+export class Core {
+  public readonly core: CoreMemory[]
+
+  public constructor(
+    public readonly coreSize = 80,
+  ) {
+    this.core = new Array(coreSize).fill(Dat)
+  }
+
+  public write(memory: CoreMemory[], atIndex: number): void {
+    memory.forEach((memoryValue, index) => {
+      this.core[(atIndex + index) % this.coreSize] = memoryValue
+    })
+  }
+}
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/corewar.ts b/src/simulations/corewar/corewar/corewar.ts
new file mode 100644
index 0000000..4d1b620
--- /dev/null
+++ b/src/simulations/corewar/corewar/corewar.ts
@@ -0,0 +1,3 @@
+import * as Corewar from "./index"
+
+export { Corewar }
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/engine.ts b/src/simulations/corewar/corewar/engine.ts
new file mode 100644
index 0000000..435aa24
--- /dev/null
+++ b/src/simulations/corewar/corewar/engine.ts
@@ -0,0 +1,72 @@
+import { Core } from "./core"
+import { interpret } from "./interpreter"
+import { Warrior } from "./warrior"
+import { WarriorCode } from "./warrior_code"
+
+
+export class Engine {
+  public get tick(): number {
+    return this._tick
+  }
+
+  private _tick = 0
+
+  public constructor(
+    public readonly core: Core,
+    private readonly warriors: Warrior[],
+  ) {
+  }
+
+  public runTick(): void {
+    this.warriors.forEach(warrior => {
+      const pointerWrapper = warrior.getNextPointer()
+      if (pointerWrapper == null) {
+        return
+      }
+
+      const result = interpret(this.core, pointerWrapper.pointer)
+      pointerWrapper.tickFinished(result)
+    })
+
+    this._tick += 1
+  }
+}
+
+
+export class EngineSetup {
+  private readonly core: Core
+  private readonly warriorCode = new Map<string, WarriorCode>()
+
+  public constructor(
+    coreSize = 80,
+  ) {
+    this.core = new Core(coreSize)
+  }
+
+  public addWarriorCode(warriorCode: WarriorCode): void {
+    this.warriorCode.set(warriorCode.name, warriorCode)
+  }
+
+  public init(): Engine | string {
+    const initialCodeMemoryLength = Array.from(this.warriorCode.values()).reduce((result, current) => result + current.code.length, 0)
+    const bufferSize = this.core.coreSize - initialCodeMemoryLength
+    if (bufferSize < 0) {
+      return `Coresize too small (initial warriors requires ${initialCodeMemoryLength} but ${this.core.coreSize} coresize given)`
+    }
+
+    const warriors: Warrior[] = []
+    const addWarrior = (instructionPointer: number, warriorCode: WarriorCode): void => {
+      warriors.push(new Warrior(warriorCode, instructionPointer))
+    }
+
+    let instructionPointer = 0
+    const bufferForEachWarriors = Math.floor(bufferSize / this.warriorCode.size)
+    this.warriorCode.forEach(warriorCode => {
+      addWarrior(instructionPointer, warriorCode)
+      instructionPointer += warriorCode.code.length + bufferForEachWarriors
+    })
+
+    return new Engine(this.core, warriors)
+  }
+}
+
diff --git a/src/simulations/corewar/corewar/index.ts b/src/simulations/corewar/corewar/index.ts
new file mode 100644
index 0000000..9cb8389
--- /dev/null
+++ b/src/simulations/corewar/corewar/index.ts
@@ -0,0 +1 @@
+export * from "./engine"
diff --git a/src/simulations/corewar/corewar/instruction.ts b/src/simulations/corewar/corewar/instruction.ts
new file mode 100644
index 0000000..216e426
--- /dev/null
+++ b/src/simulations/corewar/corewar/instruction.ts
@@ -0,0 +1,94 @@
+const opecodes = [
+  "add",
+  "mov",
+  "jmp",
+  "jmz",
+  "dat",
+] as const
+export type RawOpecode = typeof opecodes[number]
+
+
+const modifiers = [
+  ".a",
+  ".b",
+  ".ab",
+  ".ba",
+] as const
+export type Modifier = typeof modifiers[number]
+
+export type OperandType = ".a" | ".b"
+
+
+export type Opecode = {
+  readonly opecode: RawOpecode
+  readonly modifier: Modifier
+}
+
+
+const addressingModes = [
+  "#", // Immediate
+  // "$", // Direct
+  // "*", // A Indirect
+  // "@", // B Indirect
+  // "{", // A Pre-decrement Indirect
+  // "}", // A Post-increment Indirect
+  // "<", // B Pre-decrement Indirect
+  // ">", // B Post-increment Indirect
+] as const
+export type AddressingMode = typeof addressingModes[number]
+
+export type Operand = {
+  operand: number
+  readonly addressingMode: AddressingMode
+}
+
+
+export type Instruction = {
+  readonly opecode: Opecode
+
+  readonly operandA: Operand
+  readonly operandB: Operand
+}
+export type Data = number
+
+export type CoreMemory = Instruction | Data
+
+export const cloneMemory = (memory: CoreMemory): CoreMemory => {
+  if (isInstruction(memory)) {
+    return {...memory}
+  }
+  return memory
+}
+
+export const isInstruction = (memory: CoreMemory): memory is Instruction => !(typeof memory === "string")
+
+export const isZeroValue = (memory: CoreMemory): boolean => {
+  if (isInstruction(memory)) {
+    return memory.operandA.operand === 0 && memory.operandB.operand === 0
+  }
+  return memory === 0
+}
+
+export const compute = (memory: CoreMemory, computation: (value: number) => number, operandType: OperandType): CoreMemory => {
+  if (!isInstruction(memory)) {
+    return computation(memory)
+  } 
+
+  switch (operandType) {
+  case ".a":
+    memory.operandA.operand = computation(memory.operandA.operand)
+    return memory
+  case ".b":
+    memory.operandB.operand = computation(memory.operandB.operand)
+    return memory
+  }
+}
+
+
+export type ExecutionResult = {
+  readonly result: "succeeded"
+  readonly newPointer: number
+} | {
+  readonly result: "failed"
+  readonly failureReason: "dat" | "raw data"
+}
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/instructions.ts b/src/simulations/corewar/corewar/instructions.ts
new file mode 100644
index 0000000..5f975f1
--- /dev/null
+++ b/src/simulations/corewar/corewar/instructions.ts
@@ -0,0 +1,16 @@
+import { Instruction } from "./instruction"
+
+export const Dat: Instruction = {
+  opecode: {
+    opecode: "dat",
+    modifier: ".a",
+  },
+  operandA: {
+    addressingMode: "#",
+    operand: 0,
+  },
+  operandB: {
+    addressingMode: "#",
+    operand: 0,
+  },
+}
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/interpreter.ts b/src/simulations/corewar/corewar/interpreter.ts
new file mode 100644
index 0000000..733c942
--- /dev/null
+++ b/src/simulations/corewar/corewar/interpreter.ts
@@ -0,0 +1,69 @@
+import { Core } from "./core"
+import { cloneMemory, compute, ExecutionResult, isInstruction, isZeroValue } from "./instruction"
+
+export const interpret = (core: Core, pointer: number): ExecutionResult => {
+  const instruction = core.core[pointer]
+  if (!isInstruction(instruction)) {
+    return {
+      result: "failed",
+      failureReason: "raw data",
+    }
+  }
+
+  const p = (relativePointer: number): number => (pointer + relativePointer) % core.coreSize
+
+  switch (instruction.opecode.opecode) {
+  case "add":
+    // .ab実装
+    core.core[p(instruction.operandA.operand)] = compute(core.core[p(instruction.operandA.operand)], value => value + instruction.operandB.operand, ".b")
+    return {
+      result: "succeeded",
+      newPointer: p(+1),
+    }
+      
+  case "mov":
+    core.core[p(instruction.operandB.operand)] = cloneMemory(core.core[p(instruction.operandA.operand)])
+    return {
+      result: "succeeded",
+      newPointer: p(+1),
+    }
+      
+  case "jmp":
+    return {
+      result: "succeeded",
+      newPointer: p(instruction.operandA.operand),
+    }
+      
+  case "jmz":
+    if (isZeroValue(core.core[p(instruction.operandB.operand)])) {
+      return {
+        result: "succeeded",
+        newPointer: p(instruction.operandA.operand),
+      }
+    }
+    return {
+      result: "succeeded",
+      newPointer: p(+1),
+    }
+
+  case "dat":
+    return {
+      result: "failed",
+      failureReason: "dat",
+    }
+  }
+}
+
+/*
+// Bomber
+start   add.ab  #4, bmb
+        mov.i   bmb, @bmb
+        jmp     start
+bmb     dat     #0, #0
+
+// Scanner
+scn add   #10, ptr
+ptr jmz.f scn, 5
+    mov.i 2, >ptr
+    jmp   -1
+*/
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/warrior.ts b/src/simulations/corewar/corewar/warrior.ts
new file mode 100644
index 0000000..15e525d
--- /dev/null
+++ b/src/simulations/corewar/corewar/warrior.ts
@@ -0,0 +1,69 @@
+import { ExecutionResult } from "./instruction"
+import { WarriorCode } from "./warrior_code"
+
+
+type PointerWrapper = {
+  readonly pointer: number
+  readonly tickFinished: (result: ExecutionResult) => void
+}
+
+
+class WarriorProcess {
+  public constructor(
+    public instructionPointer: number,
+  ) {
+  }
+}
+
+
+export class Warrior {
+  public get name(): string {
+    return this.code.name
+  }
+  private processPointer = 0
+  private aliveProcesses: WarriorProcess[] = []
+  private deadProcesses: WarriorProcess[] = []
+
+  public constructor(
+    public readonly code: WarriorCode,
+    instructionPointer: number,
+  ) {
+    this.aliveProcesses.push(new WarriorProcess(instructionPointer))
+  }
+
+  public getNextPointer(): PointerWrapper | null {
+    const process = this.getNextAliveProcess()
+    if (process == null) {
+      return null
+    }
+
+    return {
+      pointer: process.instructionPointer,
+      tickFinished: result => {
+        switch (result.result) {
+        case "succeeded":
+          process.instructionPointer = result.newPointer
+          this.processPointer = (this.processPointer + 1) % this.aliveProcesses.length
+          break
+        case "failed":
+          this.aliveProcesses.splice(this.processPointer, 1)
+          this.deadProcesses.push(process)
+          if (this.aliveProcesses.length > 0) {
+            this.processPointer = this.processPointer % this.aliveProcesses.length
+          }
+          break
+        default: {
+          // eslint-disable-next-line @typescript-eslint/no-unused-vars
+          const _: never = result
+          break
+        }
+        }
+      },
+    }
+  }
+
+  /** @throws */
+  private getNextAliveProcess(): WarriorProcess | null {
+    return this.aliveProcesses[this.processPointer]
+  }
+}
\ No newline at end of file
diff --git a/src/simulations/corewar/corewar/warrior_code.ts b/src/simulations/corewar/corewar/warrior_code.ts
new file mode 100644
index 0000000..1d9a838
--- /dev/null
+++ b/src/simulations/corewar/corewar/warrior_code.ts
@@ -0,0 +1,6 @@
+import { Instruction } from "./instruction"
+
+export type WarriorCode = {
+  readonly name: string
+  readonly code: Instruction[]
+}
\ No newline at end of file